@esfaenza/admin-module 20.3.21 → 20.3.23

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.
@@ -923,11 +923,11 @@ class AdmProfilerComponent {
923
923
  });
924
924
  }
925
925
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: AdmProfilerComponent, deps: [{ token: i1.LocalizationService }, { token: i3.PreferencesService }, { token: i5.Location }, { token: i1$1.InterComService }, { token: i4.ActivatedRoute }, { token: AdminModuleBaseService }, { token: i4.Router }, { token: ADM_MODULE_PATH }, { token: ADM_WORKLOAD_V2, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
926
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.34", type: AdmProfilerComponent, isStandalone: false, selector: "adm_profiler", providers: [{ provide: LocalizationService, useClass: AdmProfilerComponentLoc }], ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-12\">\n <div class=\"card app-overflow-visible\" widget>\n <div class=\"card-header\">\n <span class=\"text-uppercase\">{{'Profiler del Server' | localize: lc}}</span>&nbsp;\n </div>\n <div class=\"card-body widget-body\">\n <div class=\"col-md-12 bottom-15\">\n <form role=\"form\">\n <div class=\"row app-first-filter-line\">\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\">\n <form-date [FormLayout]=\"false\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterfrom\" name=\"filterfrom\" [Placeholder]=\"'Da' | localize: lc\"></form-date>\n </div>\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\">\n <form-date [FormLayout]=\"false\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterto\" name=\"filterto\" [Placeholder]=\"'A' | localize: lc\"></form-date>\n </div>\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\" style=\"display: flex; height: 38px;\">\n <form-checkbox [FormLayout]=\"false\" [SliderMode]=\"true\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterglobal\" name=\"filterglobal\"></form-checkbox>&nbsp;\n <span class=\"app-pointer app-padding-top-5 app-padding-left-5\" (click)=\"searchView.filterglobal = !searchView.filterglobal\">{{'Globale' | localize: lc}}</span>\n </div>\n\n <button [disabled]=\"searchView.searchinprogress\" class=\"input-group-addon btn app-btn-search app-margin-top-20 app-margin-right-5\" (click)=\"sendSearch()\" type=\"submit\"><i class=\"fa fa-search\"></i></button>\n <button class=\"input-group-addon btn app-btn-search app-margin-top-20\" (click)=\"downloadWorkloadReport()\" type=\"submit\" [title]=\"workloadV2 ? 'Workload report' : ''\"><i class=\"fa\" [class.fa-download]=\"!workloadV2\" [class.fa-file-text-o]=\"workloadV2\"></i></button>\n </div>\n </form>\n </div>\n <div class=\"row\">\n <div class=\"col-md-12\">\n @if (!searchView) {\n <p><em>{{'Carico i Dati' | localize: lc}}</em></p>\n }\n @if (searchView) {\n <div>\n <es-table [(ngModel)]=\"searchView\" [Hierarchy]=\"true\" [OrderByColumn]=\"false\" [ParentKey]=\"'parentid'\"\n [OwnKey]=\"'id'\" [StartsExpanded]=\"false\" [ExportFunction]=\"prepareExport.bind(this)\" [Export]=\"true\"\n [ExportFileName]=\"'Profiler Export.csv'\" [HidePaging]=\"true\" (onSearchRequest)=\"sendSearch($event);\">\n <span *th=\"'1'\">{{'ID' | localize : lc}}</span>\n <span *th=\"'2'\">{{'Descrizione' | localize: lc}}</span>\n <span *th=\"'3'\">{{'Chiamate' | localize: lc}}</span>\n <span *th=\"'4'\">{{'Tempo' | localize: lc}}</span>\n <span *th=\"'5'\">{{'Tempo Max' | localize: lc}}</span>\n <span *th=\"'6'\">{{'Tempo Min' | localize: lc}}</span>\n <span *th=\"'7'\">{{'Tempo Medio' | localize: lc}}</span>\n <span *th=\"'8'\">{{'Tempo Specifico' | localize: lc}}</span>\n <span *th=\"'9'\">{{'Percentuale' | localize: lc}}</span>\n <span *th=\"'10'\">{{'Chiamate Periodo' | localize: lc}}</span>\n <span *th=\"'11'\">{{'Tempo Periodo' | localize: lc}}</span>\n <span *th=\"'12'\">{{'Tempo Max Periodo' | localize: lc}}</span>\n <span *th=\"'13'\">{{'Tempo Min Periodo' | localize: lc}}</span>\n <span *th=\"'14'\">{{'Tempo Medio Periodo' | localize: lc}}</span>\n <span *th=\"'15'\">{{'Tempo Specifico Periodo' | localize: lc}}</span>\n <span *th=\"'16'\">{{'Percentuale Periodo' | localize: lc}}</span>\n <span *th=\"'17'\">{{'Nome Tipologia Evento' | localize: lc}}</span>\n <span *th=\"'18'\">{{'Nome Classe Attesa' | localize: lc}}</span>\n <span *th=\"'19'\">{{'Numero Istanze' | localize: lc}}</span>\n <span *td=\"'1'; let item\"><span class=\"app-link app-inline\" (click)=\"loadNodeDetails(item.id); dlgNodeDetails.show();\">{{item.id}}</span></span>\n <span *td=\"'2'; let item\" title=\"{{item.description}}\">{{item.description.length <= 50 ? item.description : item.description.substr(0,50) + \"[...]\" }}</span>\n <span *td=\"'3'; let item\">{{item.calls}}</span>\n <span *td=\"'4'; let item\">{{item.time}}</span>\n <span *td=\"'5'; let item\">{{item.peaktime}}</span>\n <span *td=\"'6'; let item\">{{item.mintime}}</span>\n <span *td=\"'7'; let item\">{{item.avgtime}}</span>\n <span *td=\"'8'; let item\">{{item.timewithoutchildren }}</span>\n <span *td=\"'9'; let item\">{{item.percentage}}</span>\n <span *td=\"'10' let item\">{{item.snapdeltacalls}}</span>\n <span *td=\"'11' let item\">{{item.snapdeltatime}}</span>\n <span *td=\"'12' let item\">{{item.snappeaktime}}</span>\n <span *td=\"'13' let item\">{{item.snapmintime}}</span>\n <span *td=\"'14' let item\">{{item.snapavgtime}}</span>\n <span *td=\"'15' let item\">{{item.snaptimewithoutchildren}}</span>\n <span *td=\"'16' let item\">{{item.snappercentage}}</span>\n <span *td=\"'17' let item\">{{item.eventtypename}}</span>\n <span *td=\"'18' let item\">{{item.waitclassname}}</span>\n <span *td=\"'19' let item\">{{item.numinstances}}</span>\n </es-table>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<div bsModal #dlgNodeDetails=\"bs-modal\" class=\"modal fade\" role=\"dialog\" aria-hidden=\"true\">\n @if (NodeDetails) {\n <node-detail [NodeDetails]=\"NodeDetails\" (onClose)=\"dlgNodeDetails.hide()\"></node-detail>\n }\n</div>", dependencies: [{ kind: "directive", type: i7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i7.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i8$1.ModalDirective, selector: "[bsModal]", inputs: ["config", "closeInterceptor"], outputs: ["onShow", "onShown", "onHide", "onHidden"], exportAs: ["bs-modal"] }, { kind: "directive", type: i8.EsTdDirective, selector: "[td]", inputs: ["tdVisible", "td", "tdForProperty", "tdIf", "tdClass", "tdPropertyAccessor", "tdAlignment", "tdFormat", "tdIconClass", "tdConditionField", "tdConditionValue", "tdTitle", "tdContent"] }, { kind: "directive", type: i8.EsThDirective, selector: "[th]", inputs: ["th", "thPinned", "thPinnedRight", "thPinnable", "thPinnedWidth", "thVisible", "thFixed", "thParent", "thOrder", "thOrderable", "thWrap", "thResizable", "thClass", "thShrink", "thGroupClass", "thIf", "thEmpty", "thGroup", "thAggregation", "thProperty", "thType", "thSource", "thMulti", "thStaticContent", "thBackgroundColor", "thAlignment", "thFormat", "thEditorName", "thEditorOptions", "thRendererName", "thRoutePath", "thRouteParameterProperties"] }, { kind: "component", type: i8.EsTableComponent, selector: "es-table", inputs: ["globalCheck", "autoUpdate", "seconds", "researchInProgress", "globalColVisCheck", "EsThTdProvider", "CornerMenuOptions", "ColumnsResizable", "ColumnsPinnable", "AutoUpdate", "Height", "EmptySpaceBackgroundColor", "EsTableHandledSearch", "MaxHeight", "ContainerClass", "XLSXExport", "CSVExport", "AllSearch", "HighCellDensity", "Selection", "ShowLoadingOnBootstrap", "Removal", "RemovalCondition", "Export", "ShiftClick", "CountLabel", "HidePaging", "HidePagingCount", "HidePagingButtons", "ContextMenu", "ExportFileName", "TableClass", "ExportFunction", "ExportOnlyVisibleColumns", "HasHeaderGroup", "HasSecondaryHeaderGroup", "HeaderHidden", "BodyHidden", "SelectionDisabled", "SingleSelection", "RowClassAssigner", "OrderByColumn", "MultipleOrderingDirectives", "HiddenColumns", "ColumnsOrdering", "SearchView", "SelectAll", "UseArrayModePaging", "DynamicRowColumnsDefinition", "DynamicOperations", "Hierarchy", "ParentKey", "OwnKey", "AutoSortHierarchy", "StartsExpanded", "SavePreferences", "DefaultAlignment", "PagingStyle", "RowGroupingPagingStyle", "ItemSourceProperty", "UseSelectionCache", "ShowItemGroupsColumns", "Editable", "RangeSelection", "SearchThrottle", "ArraymodeItemsPerPage"], outputs: ["globalCheckChange", "autoUpdateChange", "secondsChange", "researchInProgressChange", "globalColVisCheckChange", "onOrderChanged", "onSearchRequest", "onSelectionChanged", "onRemoval", "onAbortRemoval", "onModelChange", "onOpenContextMenu", "onCornerAction", "onDynamicOperation"] }, { kind: "component", type: i9.EsFormDateComponent, selector: "form-date", inputs: ["InOutFormat", "FloatingLabel", "DateFormat"] }, { kind: "component", type: i9.EsFormCheckboxComponent, selector: "form-checkbox", inputs: ["SliderMode"] }, { kind: "directive", type: i10.Widget, selector: "[widget]" }, { kind: "component", type: NodeDetailComponent, selector: "node-detail", inputs: ["NodeDetails"], outputs: ["onClose"] }, { kind: "pipe", type: i1.LocalizePipe, name: "localize" }] }); }
926
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.34", type: AdmProfilerComponent, isStandalone: false, selector: "adm_profiler", providers: [{ provide: LocalizationService, useClass: AdmProfilerComponentLoc }], ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-12\">\n <div class=\"card app-overflow-visible\" widget>\n <div class=\"card-header\">\n <span class=\"text-uppercase\">{{'Profiler del Server' | localize: lc}}</span>&nbsp;\n </div>\n <div class=\"card-body widget-body\">\n <div class=\"col-md-12 bottom-15\">\n <form role=\"form\">\n <div class=\"row app-first-filter-line\">\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\">\n <form-date [FormLayout]=\"false\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterfrom\" name=\"filterfrom\" [Placeholder]=\"'Da' | localize: lc\"></form-date>\n </div>\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\">\n <form-date [FormLayout]=\"false\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterto\" name=\"filterto\" [Placeholder]=\"'A' | localize: lc\"></form-date>\n </div>\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\" style=\"display: flex; height: 38px;\">\n <form-checkbox [FormLayout]=\"false\" [SliderMode]=\"true\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterglobal\" name=\"filterglobal\"></form-checkbox>&nbsp;\n <span class=\"app-pointer app-padding-top-5 app-padding-left-5\" (click)=\"searchView.filterglobal = !searchView.filterglobal\">{{'Globale' | localize: lc}}</span>\n </div>\n\n <button [disabled]=\"searchView.searchinprogress\" class=\"input-group-addon btn app-btn-search app-margin-top-20 app-margin-right-5\" (click)=\"sendSearch()\" type=\"submit\"><i class=\"fa fa-search\"></i></button>\n <button class=\"input-group-addon btn app-btn-search app-margin-top-20\" (click)=\"downloadWorkloadReport()\" type=\"submit\" [title]=\"workloadV2 ? 'Workload report' : ''\"><i class=\"fa\" [class.fa-download]=\"!workloadV2\" [class.fa-file-text]=\"workloadV2\"></i></button>\n </div>\n </form>\n </div>\n <div class=\"row\">\n <div class=\"col-md-12\">\n @if (!searchView) {\n <p><em>{{'Carico i Dati' | localize: lc}}</em></p>\n }\n @if (searchView) {\n <div>\n <es-table [(ngModel)]=\"searchView\" [Hierarchy]=\"true\" [OrderByColumn]=\"false\" [ParentKey]=\"'parentid'\"\n [OwnKey]=\"'id'\" [StartsExpanded]=\"false\" [ExportFunction]=\"prepareExport.bind(this)\" [Export]=\"true\"\n [ExportFileName]=\"'Profiler Export.csv'\" [HidePaging]=\"true\" (onSearchRequest)=\"sendSearch($event);\">\n <span *th=\"'1'\">{{'ID' | localize : lc}}</span>\n <span *th=\"'2'\">{{'Descrizione' | localize: lc}}</span>\n <span *th=\"'3'\">{{'Chiamate' | localize: lc}}</span>\n <span *th=\"'4'\">{{'Tempo' | localize: lc}}</span>\n <span *th=\"'5'\">{{'Tempo Max' | localize: lc}}</span>\n <span *th=\"'6'\">{{'Tempo Min' | localize: lc}}</span>\n <span *th=\"'7'\">{{'Tempo Medio' | localize: lc}}</span>\n <span *th=\"'8'\">{{'Tempo Specifico' | localize: lc}}</span>\n <span *th=\"'9'\">{{'Percentuale' | localize: lc}}</span>\n <span *th=\"'10'\">{{'Chiamate Periodo' | localize: lc}}</span>\n <span *th=\"'11'\">{{'Tempo Periodo' | localize: lc}}</span>\n <span *th=\"'12'\">{{'Tempo Max Periodo' | localize: lc}}</span>\n <span *th=\"'13'\">{{'Tempo Min Periodo' | localize: lc}}</span>\n <span *th=\"'14'\">{{'Tempo Medio Periodo' | localize: lc}}</span>\n <span *th=\"'15'\">{{'Tempo Specifico Periodo' | localize: lc}}</span>\n <span *th=\"'16'\">{{'Percentuale Periodo' | localize: lc}}</span>\n <span *th=\"'17'\">{{'Nome Tipologia Evento' | localize: lc}}</span>\n <span *th=\"'18'\">{{'Nome Classe Attesa' | localize: lc}}</span>\n <span *th=\"'19'\">{{'Numero Istanze' | localize: lc}}</span>\n <span *td=\"'1'; let item\"><span class=\"app-link app-inline\" (click)=\"loadNodeDetails(item.id); dlgNodeDetails.show();\">{{item.id}}</span></span>\n <span *td=\"'2'; let item\" title=\"{{item.description}}\">{{item.description.length <= 50 ? item.description : item.description.substr(0,50) + \"[...]\" }}</span>\n <span *td=\"'3'; let item\">{{item.calls}}</span>\n <span *td=\"'4'; let item\">{{item.time}}</span>\n <span *td=\"'5'; let item\">{{item.peaktime}}</span>\n <span *td=\"'6'; let item\">{{item.mintime}}</span>\n <span *td=\"'7'; let item\">{{item.avgtime}}</span>\n <span *td=\"'8'; let item\">{{item.timewithoutchildren }}</span>\n <span *td=\"'9'; let item\">{{item.percentage}}</span>\n <span *td=\"'10' let item\">{{item.snapdeltacalls}}</span>\n <span *td=\"'11' let item\">{{item.snapdeltatime}}</span>\n <span *td=\"'12' let item\">{{item.snappeaktime}}</span>\n <span *td=\"'13' let item\">{{item.snapmintime}}</span>\n <span *td=\"'14' let item\">{{item.snapavgtime}}</span>\n <span *td=\"'15' let item\">{{item.snaptimewithoutchildren}}</span>\n <span *td=\"'16' let item\">{{item.snappercentage}}</span>\n <span *td=\"'17' let item\">{{item.eventtypename}}</span>\n <span *td=\"'18' let item\">{{item.waitclassname}}</span>\n <span *td=\"'19' let item\">{{item.numinstances}}</span>\n </es-table>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<div bsModal #dlgNodeDetails=\"bs-modal\" class=\"modal fade\" role=\"dialog\" aria-hidden=\"true\">\n @if (NodeDetails) {\n <node-detail [NodeDetails]=\"NodeDetails\" (onClose)=\"dlgNodeDetails.hide()\"></node-detail>\n }\n</div>", dependencies: [{ kind: "directive", type: i7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i7.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i8$1.ModalDirective, selector: "[bsModal]", inputs: ["config", "closeInterceptor"], outputs: ["onShow", "onShown", "onHide", "onHidden"], exportAs: ["bs-modal"] }, { kind: "directive", type: i8.EsTdDirective, selector: "[td]", inputs: ["tdVisible", "td", "tdForProperty", "tdIf", "tdClass", "tdPropertyAccessor", "tdAlignment", "tdFormat", "tdIconClass", "tdConditionField", "tdConditionValue", "tdTitle", "tdContent"] }, { kind: "directive", type: i8.EsThDirective, selector: "[th]", inputs: ["th", "thPinned", "thPinnedRight", "thPinnable", "thPinnedWidth", "thVisible", "thFixed", "thParent", "thOrder", "thOrderable", "thWrap", "thResizable", "thClass", "thShrink", "thGroupClass", "thIf", "thEmpty", "thGroup", "thAggregation", "thProperty", "thType", "thSource", "thMulti", "thStaticContent", "thBackgroundColor", "thAlignment", "thFormat", "thEditorName", "thEditorOptions", "thRendererName", "thRoutePath", "thRouteParameterProperties"] }, { kind: "component", type: i8.EsTableComponent, selector: "es-table", inputs: ["globalCheck", "autoUpdate", "seconds", "researchInProgress", "globalColVisCheck", "EsThTdProvider", "CornerMenuOptions", "ColumnsResizable", "ColumnsPinnable", "AutoUpdate", "Height", "EmptySpaceBackgroundColor", "EsTableHandledSearch", "MaxHeight", "ContainerClass", "XLSXExport", "CSVExport", "AllSearch", "HighCellDensity", "Selection", "ShowLoadingOnBootstrap", "Removal", "RemovalCondition", "Export", "ShiftClick", "CountLabel", "HidePaging", "HidePagingCount", "HidePagingButtons", "ContextMenu", "ExportFileName", "TableClass", "ExportFunction", "ExportOnlyVisibleColumns", "HasHeaderGroup", "HasSecondaryHeaderGroup", "HeaderHidden", "BodyHidden", "SelectionDisabled", "SingleSelection", "RowClassAssigner", "OrderByColumn", "MultipleOrderingDirectives", "HiddenColumns", "ColumnsOrdering", "SearchView", "SelectAll", "UseArrayModePaging", "DynamicRowColumnsDefinition", "DynamicOperations", "Hierarchy", "ParentKey", "OwnKey", "AutoSortHierarchy", "StartsExpanded", "SavePreferences", "DefaultAlignment", "PagingStyle", "RowGroupingPagingStyle", "ItemSourceProperty", "UseSelectionCache", "ShowItemGroupsColumns", "Editable", "RangeSelection", "SearchThrottle", "ArraymodeItemsPerPage"], outputs: ["globalCheckChange", "autoUpdateChange", "secondsChange", "researchInProgressChange", "globalColVisCheckChange", "onOrderChanged", "onSearchRequest", "onSelectionChanged", "onRemoval", "onAbortRemoval", "onModelChange", "onOpenContextMenu", "onCornerAction", "onDynamicOperation"] }, { kind: "component", type: i9.EsFormDateComponent, selector: "form-date", inputs: ["InOutFormat", "FloatingLabel", "DateFormat"] }, { kind: "component", type: i9.EsFormCheckboxComponent, selector: "form-checkbox", inputs: ["SliderMode"] }, { kind: "directive", type: i10.Widget, selector: "[widget]" }, { kind: "component", type: NodeDetailComponent, selector: "node-detail", inputs: ["NodeDetails"], outputs: ["onClose"] }, { kind: "pipe", type: i1.LocalizePipe, name: "localize" }] }); }
927
927
  }
928
928
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: AdmProfilerComponent, decorators: [{
929
929
  type: Component,
930
- args: [{ selector: "adm_profiler", providers: [{ provide: LocalizationService, useClass: AdmProfilerComponentLoc }], standalone: false, template: "<div class=\"row\">\n <div class=\"col-12\">\n <div class=\"card app-overflow-visible\" widget>\n <div class=\"card-header\">\n <span class=\"text-uppercase\">{{'Profiler del Server' | localize: lc}}</span>&nbsp;\n </div>\n <div class=\"card-body widget-body\">\n <div class=\"col-md-12 bottom-15\">\n <form role=\"form\">\n <div class=\"row app-first-filter-line\">\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\">\n <form-date [FormLayout]=\"false\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterfrom\" name=\"filterfrom\" [Placeholder]=\"'Da' | localize: lc\"></form-date>\n </div>\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\">\n <form-date [FormLayout]=\"false\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterto\" name=\"filterto\" [Placeholder]=\"'A' | localize: lc\"></form-date>\n </div>\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\" style=\"display: flex; height: 38px;\">\n <form-checkbox [FormLayout]=\"false\" [SliderMode]=\"true\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterglobal\" name=\"filterglobal\"></form-checkbox>&nbsp;\n <span class=\"app-pointer app-padding-top-5 app-padding-left-5\" (click)=\"searchView.filterglobal = !searchView.filterglobal\">{{'Globale' | localize: lc}}</span>\n </div>\n\n <button [disabled]=\"searchView.searchinprogress\" class=\"input-group-addon btn app-btn-search app-margin-top-20 app-margin-right-5\" (click)=\"sendSearch()\" type=\"submit\"><i class=\"fa fa-search\"></i></button>\n <button class=\"input-group-addon btn app-btn-search app-margin-top-20\" (click)=\"downloadWorkloadReport()\" type=\"submit\" [title]=\"workloadV2 ? 'Workload report' : ''\"><i class=\"fa\" [class.fa-download]=\"!workloadV2\" [class.fa-file-text-o]=\"workloadV2\"></i></button>\n </div>\n </form>\n </div>\n <div class=\"row\">\n <div class=\"col-md-12\">\n @if (!searchView) {\n <p><em>{{'Carico i Dati' | localize: lc}}</em></p>\n }\n @if (searchView) {\n <div>\n <es-table [(ngModel)]=\"searchView\" [Hierarchy]=\"true\" [OrderByColumn]=\"false\" [ParentKey]=\"'parentid'\"\n [OwnKey]=\"'id'\" [StartsExpanded]=\"false\" [ExportFunction]=\"prepareExport.bind(this)\" [Export]=\"true\"\n [ExportFileName]=\"'Profiler Export.csv'\" [HidePaging]=\"true\" (onSearchRequest)=\"sendSearch($event);\">\n <span *th=\"'1'\">{{'ID' | localize : lc}}</span>\n <span *th=\"'2'\">{{'Descrizione' | localize: lc}}</span>\n <span *th=\"'3'\">{{'Chiamate' | localize: lc}}</span>\n <span *th=\"'4'\">{{'Tempo' | localize: lc}}</span>\n <span *th=\"'5'\">{{'Tempo Max' | localize: lc}}</span>\n <span *th=\"'6'\">{{'Tempo Min' | localize: lc}}</span>\n <span *th=\"'7'\">{{'Tempo Medio' | localize: lc}}</span>\n <span *th=\"'8'\">{{'Tempo Specifico' | localize: lc}}</span>\n <span *th=\"'9'\">{{'Percentuale' | localize: lc}}</span>\n <span *th=\"'10'\">{{'Chiamate Periodo' | localize: lc}}</span>\n <span *th=\"'11'\">{{'Tempo Periodo' | localize: lc}}</span>\n <span *th=\"'12'\">{{'Tempo Max Periodo' | localize: lc}}</span>\n <span *th=\"'13'\">{{'Tempo Min Periodo' | localize: lc}}</span>\n <span *th=\"'14'\">{{'Tempo Medio Periodo' | localize: lc}}</span>\n <span *th=\"'15'\">{{'Tempo Specifico Periodo' | localize: lc}}</span>\n <span *th=\"'16'\">{{'Percentuale Periodo' | localize: lc}}</span>\n <span *th=\"'17'\">{{'Nome Tipologia Evento' | localize: lc}}</span>\n <span *th=\"'18'\">{{'Nome Classe Attesa' | localize: lc}}</span>\n <span *th=\"'19'\">{{'Numero Istanze' | localize: lc}}</span>\n <span *td=\"'1'; let item\"><span class=\"app-link app-inline\" (click)=\"loadNodeDetails(item.id); dlgNodeDetails.show();\">{{item.id}}</span></span>\n <span *td=\"'2'; let item\" title=\"{{item.description}}\">{{item.description.length <= 50 ? item.description : item.description.substr(0,50) + \"[...]\" }}</span>\n <span *td=\"'3'; let item\">{{item.calls}}</span>\n <span *td=\"'4'; let item\">{{item.time}}</span>\n <span *td=\"'5'; let item\">{{item.peaktime}}</span>\n <span *td=\"'6'; let item\">{{item.mintime}}</span>\n <span *td=\"'7'; let item\">{{item.avgtime}}</span>\n <span *td=\"'8'; let item\">{{item.timewithoutchildren }}</span>\n <span *td=\"'9'; let item\">{{item.percentage}}</span>\n <span *td=\"'10' let item\">{{item.snapdeltacalls}}</span>\n <span *td=\"'11' let item\">{{item.snapdeltatime}}</span>\n <span *td=\"'12' let item\">{{item.snappeaktime}}</span>\n <span *td=\"'13' let item\">{{item.snapmintime}}</span>\n <span *td=\"'14' let item\">{{item.snapavgtime}}</span>\n <span *td=\"'15' let item\">{{item.snaptimewithoutchildren}}</span>\n <span *td=\"'16' let item\">{{item.snappercentage}}</span>\n <span *td=\"'17' let item\">{{item.eventtypename}}</span>\n <span *td=\"'18' let item\">{{item.waitclassname}}</span>\n <span *td=\"'19' let item\">{{item.numinstances}}</span>\n </es-table>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<div bsModal #dlgNodeDetails=\"bs-modal\" class=\"modal fade\" role=\"dialog\" aria-hidden=\"true\">\n @if (NodeDetails) {\n <node-detail [NodeDetails]=\"NodeDetails\" (onClose)=\"dlgNodeDetails.hide()\"></node-detail>\n }\n</div>" }]
930
+ args: [{ selector: "adm_profiler", providers: [{ provide: LocalizationService, useClass: AdmProfilerComponentLoc }], standalone: false, template: "<div class=\"row\">\n <div class=\"col-12\">\n <div class=\"card app-overflow-visible\" widget>\n <div class=\"card-header\">\n <span class=\"text-uppercase\">{{'Profiler del Server' | localize: lc}}</span>&nbsp;\n </div>\n <div class=\"card-body widget-body\">\n <div class=\"col-md-12 bottom-15\">\n <form role=\"form\">\n <div class=\"row app-first-filter-line\">\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\">\n <form-date [FormLayout]=\"false\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterfrom\" name=\"filterfrom\" [Placeholder]=\"'Da' | localize: lc\"></form-date>\n </div>\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\">\n <form-date [FormLayout]=\"false\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterto\" name=\"filterto\" [Placeholder]=\"'A' | localize: lc\"></form-date>\n </div>\n <div class=\"col-xl-2 col-lg-2 col-md-12 app-filter-wrapper\" style=\"display: flex; height: 38px;\">\n <form-checkbox [FormLayout]=\"false\" [SliderMode]=\"true\" [Validation]=\"false\" [(ngModel)]=\"searchView.filterglobal\" name=\"filterglobal\"></form-checkbox>&nbsp;\n <span class=\"app-pointer app-padding-top-5 app-padding-left-5\" (click)=\"searchView.filterglobal = !searchView.filterglobal\">{{'Globale' | localize: lc}}</span>\n </div>\n\n <button [disabled]=\"searchView.searchinprogress\" class=\"input-group-addon btn app-btn-search app-margin-top-20 app-margin-right-5\" (click)=\"sendSearch()\" type=\"submit\"><i class=\"fa fa-search\"></i></button>\n <button class=\"input-group-addon btn app-btn-search app-margin-top-20\" (click)=\"downloadWorkloadReport()\" type=\"submit\" [title]=\"workloadV2 ? 'Workload report' : ''\"><i class=\"fa\" [class.fa-download]=\"!workloadV2\" [class.fa-file-text]=\"workloadV2\"></i></button>\n </div>\n </form>\n </div>\n <div class=\"row\">\n <div class=\"col-md-12\">\n @if (!searchView) {\n <p><em>{{'Carico i Dati' | localize: lc}}</em></p>\n }\n @if (searchView) {\n <div>\n <es-table [(ngModel)]=\"searchView\" [Hierarchy]=\"true\" [OrderByColumn]=\"false\" [ParentKey]=\"'parentid'\"\n [OwnKey]=\"'id'\" [StartsExpanded]=\"false\" [ExportFunction]=\"prepareExport.bind(this)\" [Export]=\"true\"\n [ExportFileName]=\"'Profiler Export.csv'\" [HidePaging]=\"true\" (onSearchRequest)=\"sendSearch($event);\">\n <span *th=\"'1'\">{{'ID' | localize : lc}}</span>\n <span *th=\"'2'\">{{'Descrizione' | localize: lc}}</span>\n <span *th=\"'3'\">{{'Chiamate' | localize: lc}}</span>\n <span *th=\"'4'\">{{'Tempo' | localize: lc}}</span>\n <span *th=\"'5'\">{{'Tempo Max' | localize: lc}}</span>\n <span *th=\"'6'\">{{'Tempo Min' | localize: lc}}</span>\n <span *th=\"'7'\">{{'Tempo Medio' | localize: lc}}</span>\n <span *th=\"'8'\">{{'Tempo Specifico' | localize: lc}}</span>\n <span *th=\"'9'\">{{'Percentuale' | localize: lc}}</span>\n <span *th=\"'10'\">{{'Chiamate Periodo' | localize: lc}}</span>\n <span *th=\"'11'\">{{'Tempo Periodo' | localize: lc}}</span>\n <span *th=\"'12'\">{{'Tempo Max Periodo' | localize: lc}}</span>\n <span *th=\"'13'\">{{'Tempo Min Periodo' | localize: lc}}</span>\n <span *th=\"'14'\">{{'Tempo Medio Periodo' | localize: lc}}</span>\n <span *th=\"'15'\">{{'Tempo Specifico Periodo' | localize: lc}}</span>\n <span *th=\"'16'\">{{'Percentuale Periodo' | localize: lc}}</span>\n <span *th=\"'17'\">{{'Nome Tipologia Evento' | localize: lc}}</span>\n <span *th=\"'18'\">{{'Nome Classe Attesa' | localize: lc}}</span>\n <span *th=\"'19'\">{{'Numero Istanze' | localize: lc}}</span>\n <span *td=\"'1'; let item\"><span class=\"app-link app-inline\" (click)=\"loadNodeDetails(item.id); dlgNodeDetails.show();\">{{item.id}}</span></span>\n <span *td=\"'2'; let item\" title=\"{{item.description}}\">{{item.description.length <= 50 ? item.description : item.description.substr(0,50) + \"[...]\" }}</span>\n <span *td=\"'3'; let item\">{{item.calls}}</span>\n <span *td=\"'4'; let item\">{{item.time}}</span>\n <span *td=\"'5'; let item\">{{item.peaktime}}</span>\n <span *td=\"'6'; let item\">{{item.mintime}}</span>\n <span *td=\"'7'; let item\">{{item.avgtime}}</span>\n <span *td=\"'8'; let item\">{{item.timewithoutchildren }}</span>\n <span *td=\"'9'; let item\">{{item.percentage}}</span>\n <span *td=\"'10' let item\">{{item.snapdeltacalls}}</span>\n <span *td=\"'11' let item\">{{item.snapdeltatime}}</span>\n <span *td=\"'12' let item\">{{item.snappeaktime}}</span>\n <span *td=\"'13' let item\">{{item.snapmintime}}</span>\n <span *td=\"'14' let item\">{{item.snapavgtime}}</span>\n <span *td=\"'15' let item\">{{item.snaptimewithoutchildren}}</span>\n <span *td=\"'16' let item\">{{item.snappercentage}}</span>\n <span *td=\"'17' let item\">{{item.eventtypename}}</span>\n <span *td=\"'18' let item\">{{item.waitclassname}}</span>\n <span *td=\"'19' let item\">{{item.numinstances}}</span>\n </es-table>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<div bsModal #dlgNodeDetails=\"bs-modal\" class=\"modal fade\" role=\"dialog\" aria-hidden=\"true\">\n @if (NodeDetails) {\n <node-detail [NodeDetails]=\"NodeDetails\" (onClose)=\"dlgNodeDetails.hide()\"></node-detail>\n }\n</div>" }]
931
931
  }], ctorParameters: () => [{ type: i1.LocalizationService }, { type: i3.PreferencesService }, { type: i5.Location }, { type: i1$1.InterComService }, { type: i4.ActivatedRoute }, { type: AdminModuleBaseService }, { type: i4.Router }, { type: undefined, decorators: [{
932
932
  type: Inject,
933
933
  args: [ADM_MODULE_PATH]
@@ -1020,6 +1020,7 @@ class AdmProfilerV2Loc extends LocalizationService {
1020
1020
  super.set("it->en", "Questa istanza", ["This instance"]);
1021
1021
  super.set("it->en", "Tutto il cluster", ["Whole cluster"]);
1022
1022
  super.set("it->en", "istanze", ["instances"]);
1023
+ super.set("it->en", "istanza", ["instance"]);
1023
1024
  super.set("it->en", "Solo", ["Only"]);
1024
1025
  super.set("it->en", "Dal", ["From"]);
1025
1026
  super.set("it->en", "Al", ["To"]);
@@ -1211,7 +1212,8 @@ class AdmProfilerV2Component {
1211
1212
  this.matchCount = 0;
1212
1213
  // Eventi per nome
1213
1214
  this.flatSearch = "";
1214
- this.flatType = "";
1215
+ // "*" = tutti i tipi (con un id vuoto la select mostrerebbe il segnaposto invece di "Tutti")
1216
+ this.flatType = "*";
1215
1217
  this.flatOrderBy = String(ProfilerOrderBy.TimeLessChildren);
1216
1218
  this.flatTop = "100";
1217
1219
  this.flatIncludeIdle = false;
@@ -1685,7 +1687,7 @@ class AdmProfilerV2Component {
1685
1687
  let search = (this.flatSearch ?? "").trim();
1686
1688
  if (search)
1687
1689
  req.search = search;
1688
- if (this.flatType)
1690
+ if (this.flatType && this.flatType != "*")
1689
1691
  req.eventType = this.flatType;
1690
1692
  if (this.flatIncludeIdle)
1691
1693
  req.includeIdle = true;
@@ -1899,7 +1901,7 @@ class AdmProfilerV2Component {
1899
1901
  this.FlatOrders = [1, 0, 2, 3, 4, 6, 7, 8].map(t => this.TreeOrders.find(k => k.id == String(t)));
1900
1902
  this.ChildrenOptions = ["10", "25", "50", "100"].map(t => new KeyValue(t, t)).concat([new KeyValue("0", this.lc.loc("Tutti"))]);
1901
1903
  this.ThresholdOptions = [new KeyValue("0", this.lc.loc("Nessuna")), new KeyValue("0.1", "≥ 0,1%"), new KeyValue("1", "≥ 1%"), new KeyValue("5", "≥ 5%")];
1902
- this.FlatTypes = [new KeyValue("", this.lc.loc("Tutti"))].concat(EVENT_TYPES.map(t => new KeyValue(t, t)));
1904
+ this.FlatTypes = [new KeyValue("*", this.lc.loc("Tutti"))].concat(EVENT_TYPES.map(t => new KeyValue(t, t)));
1903
1905
  this.FlatRows = [new KeyValue("100", "100"), new KeyValue("500", "500"), new KeyValue("1000", "1.000")];
1904
1906
  this.updateOrderOptions();
1905
1907
  this.buildInstances();
@@ -1923,7 +1925,7 @@ class AdmProfilerV2Component {
1923
1925
  buildInstances() {
1924
1926
  this.Instances = [
1925
1927
  new KeyValue(INSTANCE_THIS, this.instanceId ? `${this.lc.loc("Questa istanza")} (${this.instanceId})` : this.lc.loc("Questa istanza")),
1926
- new KeyValue(INSTANCE_ALL$1, this.instanceIds.length ? `${this.lc.loc("Tutto il cluster")} (${this.instanceIds.length} ${this.lc.loc("istanze")})` : this.lc.loc("Tutto il cluster")),
1928
+ new KeyValue(INSTANCE_ALL$1, this.instanceIds.length ? `${this.lc.loc("Tutto il cluster")} (${this.instanceIds.length} ${this.instanceIds.length == 1 ? this.lc.loc("istanza") : this.lc.loc("istanze")})` : this.lc.loc("Tutto il cluster")),
1927
1929
  ...this.instanceIds.map(t => new KeyValue(t, `${this.lc.loc("Solo")} ${t}`))
1928
1930
  ];
1929
1931
  }
@@ -1967,11 +1969,11 @@ class AdmProfilerV2Component {
1967
1969
  return ret;
1968
1970
  }
1969
1971
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: AdmProfilerV2Component, deps: [{ token: i1$1.DateService }, { token: i1.LocalizationService }, { token: i3.PreferencesService }, { token: i1$1.InterComService }, { token: i4.ActivatedRoute }, { token: i4.Router }, { token: i5.Location }, { token: AdminModuleBaseService }, { token: ADM_MODULE_PATH }, { token: ADM_WORKLOAD_V2, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
1970
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.34", type: AdmProfilerV2Component, isStandalone: false, selector: "profiler_v2", providers: [{ provide: LocalizationService, useClass: AdmProfilerV2Loc }], ngImport: i0, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Profiler del Server' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body pv2-body\">\r\n <!-- Barra dei comandi: quali dati caricare. Ogni cambio ricarica la vista e il dettaglio aperto -->\r\n <div class=\"pv2-toolbar\">\r\n <div class=\"pv2-cluster\">\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Sorgente' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"live\" (click)=\"setLive(true)\"><span class=\"pv2-live-dot\"></span>Live</button>\r\n <button type=\"button\" [class.pv2-on]=\"!live\" (click)=\"setLive(false)\">{{'Storico' | localize: lc}}</button>\r\n </div>\r\n </div>\r\n <div class=\"pv2-field pv2-field-wide pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instance\" (ngModelChange)=\"setInstance($event)\" name=\"instance\" [Source]=\"Instances\" [Placeholder]=\"'Istanze' | localize: lc\"></form-select>\r\n </div>\r\n </div>\r\n\r\n @if (!live) {\r\n <div class=\"pv2-cluster\">\r\n <div class=\"pv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterfrom\" (ngModelChange)=\"filterfrom = $event; datesChanged()\" name=\"filterfrom\" [Placeholder]=\"'Dal' | localize: lc\"></form-datetime>\r\n </div>\r\n <div class=\"pv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterto\" (ngModelChange)=\"filterto = $event; datesChanged()\" name=\"filterto\" [Placeholder]=\"'Al' | localize: lc\"></form-datetime>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Valori' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"!snapValues\" (click)=\"setSnapValues(false)\">{{\"Dall'avvio\" | localize: lc}}</button>\r\n <button type=\"button\" [class.pv2-on]=\"snapValues\" (click)=\"setSnapValues(true)\">{{\"Dall'ultimo snapshot\" | localize: lc}}</button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"pv2-cluster pv2-cluster-end\">\r\n <button type=\"button\" class=\"btn app-btn-search\" [disabled]=\"loading\" (click)=\"reloadAll()\" [title]=\"'Aggiorna' | localize: lc\">\r\n <i class=\"fa fa-refresh\" [class.fa-spin]=\"loading\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn app-btn-search\" (click)=\"downloadWorkloadReport()\" [title]=\"(workloadV2 ? 'Workload report' : 'Scarica il workload report') | localize: lc\">\r\n <i class=\"fa\" [class.fa-download]=\"!workloadV2\" [class.fa-file-text-o]=\"workloadV2\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Riga della finestra: sempre visibile sopra la vista -->\r\n <div class=\"pv2-window\">\r\n <span><strong>{{live ? 'Live' : ('Storico' | localize: lc)}}</strong> &middot; {{instanceLabel}}</span>\r\n @if (current?.snapFrom; as snapFrom) {\r\n @if (live) {\r\n <span>{{\"Delta dall'ultimo snapshot delle\" | localize: lc}} {{hhmm(snapFrom)}} ({{minutesAgo(snapFrom)}} {{'min fa' | localize: lc}})</span>\r\n } @else {\r\n <span>{{'Snapshot dalle' | localize: lc}} {{ddmmhhmm(snapFrom)}} {{'alle' | localize: lc}} {{ddmmhhmm(current?.snapTo)}}</span>\r\n }\r\n } @else if (current && !live) {\r\n <span class=\"pv2-warn-text\">{{'Nessuno snapshot termina nella finestra scelta' | localize: lc}}</span>\r\n }\r\n @if (view == 'tree' && tree?.idleNode) {\r\n <span>{{tree.numNodes | pv2fmt: 'int'}} {{\"nodi nell'albero\" | localize: lc}} &middot; {{tree.numReturnedNodes | pv2fmt: 'int'}} {{'nella risposta' | localize: lc}}</span>\r\n }\r\n @if (view == 'flat' && flat) {\r\n <span>{{flat.numItems | pv2fmt: 'int'}} {{'eventi distinti' | localize: lc}}</span>\r\n }\r\n @if (loading) {\r\n <span class=\"pv2-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n </div>\r\n\r\n <div class=\"pv2-main\">\r\n <!-- Vista: albero o eventi per nome -->\r\n <div class=\"pv2-panel pv2-view\">\r\n <div class=\"pv2-view-bar\">\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"view == 'tree'\" (click)=\"setView('tree')\"><i class=\"fa fa-sitemap\"></i> {{'Albero' | localize: lc}}</button>\r\n <button type=\"button\" [class.pv2-on]=\"view == 'flat'\" (click)=\"setView('flat')\"><i class=\"fa fa-list\"></i> {{'Per nome' | localize: lc}}</button>\r\n </div>\r\n\r\n @if (view == 'tree') {\r\n <div class=\"pv2-field pv2-field-search\" [title]=\"'Per esempio MRD_METERREADINGS, ENQUEUE, ProfilesMgr' | localize: lc\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"searchText\" (ngModelChange)=\"searchText = $event; searchChanged()\" name=\"search\" [Placeholder]=\"'Cerca nei nomi o per id' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"pv2-field pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"orderBy\" (ngModelChange)=\"setOrderBy($event)\" name=\"orderBy\" [Source]=\"TreeOrderOptions\" [Placeholder]=\"'Ordina per' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-group\" [class.pv2-disabled]=\"!!activeSearch\">\r\n <span class=\"pv2-group-label\">{{'Figli per nodo' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of ChildrenOptions; track o.id) {\r\n <button type=\"button\" [disabled]=\"!!activeSearch\" [class.pv2-on]=\"maxChildren == o.id\" (click)=\"setMaxChildren(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"pv2-group\" [class.pv2-disabled]=\"!!activeSearch\">\r\n <span class=\"pv2-group-label\">{{'Soglia' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of ThresholdOptions; track o.id) {\r\n <button type=\"button\" [disabled]=\"!!activeSearch\" [class.pv2-on]=\"minPercentage == o.id\" (click)=\"setMinPercentage(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"pv2-field pv2-field-search\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatSearch\" (ngModelChange)=\"flatSearch = $event; flatSearchChanged()\" name=\"flatSearch\" [Placeholder]=\"'Cerca nei nomi' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"pv2-field pv2-field-narrow pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatType\" (ngModelChange)=\"flatType = $event; flatChanged()\" name=\"flatType\" [Source]=\"FlatTypes\" [Placeholder]=\"'Tipo' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-field pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatOrderBy\" (ngModelChange)=\"flatOrderBy = $event; flatChanged()\" name=\"flatOrderBy\" [Source]=\"FlatOrderOptions\" [Placeholder]=\"'Ordina per' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Righe' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of FlatRows; track o.id) {\r\n <button type=\"button\" [class.pv2-on]=\"flatTop == o.id\" (click)=\"setFlatTop(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"pv2-toggle\">\r\n <form-checkbox [FormLayout]=\"false\" [SliderMode]=\"true\" [Validation]=\"false\" [ngModel]=\"flatIncludeIdle\" (ngModelChange)=\"flatIncludeIdle = $event; flatChanged()\" name=\"flatIncludeIdle\"></form-checkbox>\r\n <span class=\"pv2-pointer\" (click)=\"flatIncludeIdle = !flatIncludeIdle; flatChanged()\">{{'Anche gli eventi idle' | localize: lc}}</span>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (view == 'tree') {\r\n <!-- Percorso della radice: ogni antenato riporta l'albero a quel nodo -->\r\n @if (tree?.idleNode && tree?.rootPath?.length) {\r\n <nav class=\"pv2-crumbs\">\r\n @for (item of tree.rootPath; track item.nodeId) {\r\n <button type=\"button\" class=\"pv2-crumb\" [title]=\"item.nodeName\" (click)=\"setRoot(item.nodeId)\">{{item.nodeName}}</button>\r\n <span class=\"pv2-crumb-sep\">&rsaquo;</span>\r\n }\r\n <span class=\"pv2-crumb pv2-crumb-current\" [title]=\"tree.idleNode.nodeName\">{{tree.idleNode.nodeName}}</span>\r\n </nav>\r\n }\r\n\r\n @if (treeNotice) {\r\n <div class=\"pv2-alert pv2-alert-warn\">\r\n {{treeNotice}}\r\n <button type=\"button\" class=\"pv2-alert-close\" [title]=\"'Chiudi' | localize: lc\" (click)=\"treeNotice = null\">&times;</button>\r\n </div>\r\n }\r\n @if (activeSearch && tree) {\r\n @if (matchCount > 0) {\r\n <div class=\"pv2-alert\" [class.pv2-alert-warn]=\"tree.truncated\">\r\n {{matchCount | pv2fmt: 'int'}} {{'nodi trovati, con i loro antenati.' | localize: lc}}\r\n @if (tree.truncated) {\r\n <strong>{{'I nodi trovati sono pi\u00F9 di 1.000: sono mostrati i primi per l\\'ordinamento scelto.' | localize: lc}}</strong>\r\n }\r\n </div>\r\n } @else if (!treeLoading) {\r\n <div class=\"pv2-alert\">{{'Nessun nodo contiene' | localize: lc}} &laquo;{{activeSearch}}&raquo;.</div>\r\n }\r\n }\r\n @if (treeError) {\r\n <div class=\"pv2-alert pv2-alert-error\">{{treeError}}</div>\r\n }\r\n\r\n <div class=\"pv2-table-wrap\" tabindex=\"0\" (keydown)=\"treeKeydown($event)\">\r\n <table class=\"pv2-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"pv2-col-node\">{{'Nodo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Chiamate' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Tempo' | localize: lc}}</th>\r\n <th>{{snapMode ? '\u0394 ' : ''}}{{'% del padre' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? '\u0394 Proprio' : 'Tempo proprio') | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Medio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Picco' | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread ora' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of rows; track row.key) {\r\n @if (row.kind == 'node') {\r\n <tr [id]=\"'pv2-row-' + row.node.nodeId\" class=\"pv2-row\"\r\n [class.pv2-selected]=\"row.node.nodeId == selectedId\"\r\n [class.pv2-idle]=\"isIdle(row.node.eventTypeName, row.node.waitClassName)\"\r\n (click)=\"rowClicked(row.node)\" (dblclick)=\"toggle(row.node)\">\r\n <td class=\"pv2-col-node\">\r\n <div class=\"pv2-node\" [style.padding-left.px]=\"row.depth * 16\">\r\n @if (hasChildren(row.node)) {\r\n <button type=\"button\" class=\"pv2-caret\" tabindex=\"-1\" [attr.aria-expanded]=\"isExpanded(row.node)\" (click)=\"toggle(row.node, $event)\">\r\n <i class=\"fa\" [class.fa-caret-down]=\"isExpanded(row.node)\" [class.fa-caret-right]=\"!isExpanded(row.node)\"></i>\r\n </button>\r\n } @else {\r\n <span class=\"pv2-caret\"></span>\r\n }\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(row.node.eventTypeName, row.node.waitClassName)\"></span>{{typeLabel(row.node.eventTypeName, row.node.waitClassName)}}</span>\r\n <span class=\"pv2-name\" [title]=\"row.node.nodeName\">@if (row.node.searchMatch && activeSearch) {@for (part of nameParts(row.node.nodeName, activeSearch); track $index) {@if (part.hit) {<mark>{{part.text}}</mark>} @else {<span>{{part.text}}</span>}}} @else {<span>{{row.node.nodeName}}</span>}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{calls(row.node) | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{time(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-perc\" [title]=\"(parentPerc(row.node) | pv2fmt: 'pct') + ' ' + ('del padre' | localize: lc) + ' \u00B7 ' + (firstLevelPerc(row.node) | pv2fmt: 'pct') + ' ' + ('del nodo di primo livello' | localize: lc)\">\r\n <div class=\"pv2-perc-cell\">\r\n <div class=\"pv2-bar\"><div [style.width.%]=\"parentPerc(row.node)\" [style.background]=\"typeColor(row.node.eventTypeName, row.node.waitClassName)\"></div></div>\r\n <span>{{parentPerc(row.node) | pv2fmt: 'pct'}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{self(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{avg(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{peak(row.node) | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num pv2-threads\">\r\n @if (isLongRunning(row.node.eventTypeName, row.node.waitClassName, row.node.activeMaxTime)) {\r\n <span class=\"pv2-long\" [title]=\"('Esecuzione in corso da' | localize: lc) + ' ' + duration(row.node.activeMaxTime) + ': ' + ('forse bloccata' | localize: lc)\"><i class=\"fa fa-clock-o\"></i> {{duration(row.node.activeMaxTime)}}</span>\r\n }\r\n @if (row.node.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{row.node.activeThreads}}</span>\r\n } @else {\r\n <span class=\"pv2-muted\">{{row.node.activeThreads ?? '\u2014'}}</span>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n } @else if (row.kind == 'loading') {\r\n <tr class=\"pv2-service\">\r\n <td [attr.colspan]=\"live ? 8 : 7\">\r\n <div [style.padding-left.px]=\"row.depth * 16 + 24\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento dei figli\u2026' | localize: lc}}</div>\r\n </td>\r\n </tr>\r\n } @else {\r\n <tr class=\"pv2-service\">\r\n <td [attr.colspan]=\"live ? 8 : 7\">\r\n <div [style.padding-left.px]=\"row.depth * 16 + 24\">\r\n {{row.node.omittedChildren | pv2fmt: 'int'}} {{'figli non mostrati' | localize: lc}} &middot; {{omittedTime(row.node) | pv2fmt: 'dur'}}\r\n @if (!snapMode) {\r\n &middot; {{row.node.omittedCalls | pv2fmt: 'int'}} {{'chiamate' | localize: lc}}\r\n }\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"showAll(row.node, $event)\">{{'Mostra tutti' | localize: lc}}</button>\r\n </div>\r\n </td>\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n </table>\r\n @if (rows.length == 0 && !treeError) {\r\n <div class=\"pv2-empty\">\r\n @if (!tree) {\r\n {{'Caricamento\u2026' | localize: lc}}\r\n } @else if (!tree.snapFrom && !live) {\r\n {{'Nessuno snapshot termina nella finestra scelta: allargala o spostala indietro.' | localize: lc}}\r\n } @else {\r\n {{\"Il nodo non c'\u00E8 nelle istanze scelte.\" | localize: lc}}\r\n }\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n @if (flatError) {\r\n <div class=\"pv2-alert pv2-alert-error\">{{flatError}}</div>\r\n }\r\n <div class=\"pv2-table-wrap\">\r\n <table class=\"pv2-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"pv2-col-node\">{{'Evento' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Percorsi' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Chiamate' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? '\u0394 Proprio' : 'Tempo proprio') | localize: lc}}</th>\r\n <th>{{snapMode ? '\u0394 ' : ''}}{{'% proprio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Tempo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Medio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? \"Picco dall'avvio\" : 'Picco') | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (item of flat?.items ?? []; track flatKey(item)) {\r\n <tr class=\"pv2-row\" [class.pv2-idle]=\"isIdle(item.eventTypeName, item.waitClassName)\" [class.pv2-selected]=\"openFlat.has(flatKey(item))\" (click)=\"toggleFlat(item)\">\r\n <td class=\"pv2-col-node\">\r\n <div class=\"pv2-node\">\r\n <span class=\"pv2-caret\"><i class=\"fa\" [class.fa-caret-down]=\"openFlat.has(flatKey(item))\" [class.fa-caret-right]=\"!openFlat.has(flatKey(item))\"></i></span>\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></span>{{typeLabel(item.eventTypeName, item.waitClassName)}}</span>\r\n <span class=\"pv2-name\" [title]=\"item.nodeName\">@for (part of nameParts(item.nodeName, (flatSearch ?? '').trim()); track $index) {@if (part.hit) {<mark>{{part.text}}</mark>} @else {<span>{{part.text}}</span>}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{item.numPaths | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{flatCalls(item) | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{flatSelf(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-perc\">\r\n <div class=\"pv2-perc-cell\">\r\n <div class=\"pv2-bar\"><div [style.width.%]=\"flatPerc(item)\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></div></div>\r\n <span>{{flatPerc(item) | pv2fmt: 'pct'}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{flatTime(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{flatAvg(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{item.peakTime | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num pv2-threads\">\r\n @if (item.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{item.activeThreads}}</span>\r\n } @else {\r\n <span class=\"pv2-muted\">{{item.activeThreads ?? '\u2014'}}</span>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n @if (openFlat.has(flatKey(item))) {\r\n <tr class=\"pv2-sub\">\r\n <td [attr.colspan]=\"live ? 9 : 8\">\r\n <div class=\"pv2-sub-title\">{{'Nodi con pi\u00F9 tempo' | localize: lc}}</div>\r\n @for (id of item.nodeIds ?? []; track id) {\r\n <div class=\"pv2-sub-item\">\r\n <code>{{id}}</code>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"showDetail(id, $event)\">{{'Dettaglio' | localize: lc}}</button>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"openInTree(id, $event)\">{{\"Apri nell'albero\" | localize: lc}}</button>\r\n </div>\r\n }\r\n @if (item.numPaths > (item.nodeIds?.length ?? 0)) {\r\n <div class=\"pv2-muted\">+{{item.numPaths - (item.nodeIds?.length ?? 0) | pv2fmt: 'int'}} {{'altri' | localize: lc}}</div>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n </table>\r\n @if (!flatError && (!flat || !flat.items?.length)) {\r\n <div class=\"pv2-empty\">{{(flat ? 'Nessun evento con questi filtri.' : 'Caricamento\u2026') | localize: lc}}</div>\r\n }\r\n </div>\r\n @if (flat?.items?.length) {\r\n <div class=\"pv2-footer\">\r\n {{flat.numItems | pv2fmt: 'int'}} {{'eventi distinti' | localize: lc}}@if (flat.numItems > flat.items.length) {, {{'mostrati i primi' | localize: lc}} {{flat.items.length | pv2fmt: 'int'}}}.\r\n {{'La percentuale \u00E8 sul tempo proprio di tutti gli eventi non idle.' | localize: lc}}\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Dettaglio del nodo selezionato, lo stesso per le due viste -->\r\n <aside class=\"pv2-panel pv2-detail\" [class.pv2-stale]=\"detailStale\">\r\n @if (!selectedId) {\r\n <div class=\"pv2-placeholder\">{{'Seleziona un nodo per vederne il dettaglio.' | localize: lc}}</div>\r\n } @else if (detailMissing && !detailLoading) {\r\n <div class=\"pv2-placeholder\">{{\"Il nodo non c'\u00E8 nelle istanze o nella finestra scelte.\" | localize: lc}}</div>\r\n } @else if (detailError && !detailLoading) {\r\n <div class=\"pv2-placeholder pv2-error-text\">{{detailError}}</div>\r\n } @else if (!detail) {\r\n <div class=\"pv2-placeholder\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</div>\r\n } @else {\r\n <div class=\"pv2-d-head\">\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(detail.eventTypeName, detail.waitClassName)\"></span>{{typeLabel(detail.eventTypeName, detail.waitClassName)}}</span>\r\n @if (detailLoading) {\r\n <i class=\"fa fa-spinner fa-spin pv2-muted\"></i>\r\n }\r\n </div>\r\n <div class=\"pv2-fullname\">{{detail.nodeName}}</div>\r\n <div class=\"pv2-id\">\r\n Id <code #idText>{{detail.nodeId}}</code>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"copyId(idText)\">{{(copied ? 'Copiato' : 'Copia') | localize: lc}}</button>\r\n </div>\r\n\r\n <div class=\"pv2-d-title\">{{'Percorso' | localize: lc}}</div>\r\n <div class=\"pv2-path\">\r\n @for (item of detail.fullWaitStack ?? []; track item.nodeId; let i = $index) {\r\n <button type=\"button\" class=\"pv2-path-item\" [style.padding-left.px]=\"i * 10\" [title]=\"item.nodeName\" (click)=\"select(item.nodeId)\">\r\n <span class=\"pv2-dot\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></span>{{item.nodeName}}\r\n </button>\r\n }\r\n <div class=\"pv2-path-item pv2-path-current\" [style.padding-left.px]=\"(detail.fullWaitStack?.length ?? 0) * 10\" [title]=\"detail.nodeName\">\r\n <span class=\"pv2-dot\" [style.background]=\"typeColor(detail.eventTypeName, detail.waitClassName)\"></span>{{detail.nodeName}}\r\n </div>\r\n </div>\r\n\r\n <div class=\"pv2-d-title\">{{(live ? \"Dall'avvio\" : 'Nella finestra') | localize: lc}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Esecuzioni' | localize: lc}}</dt><dd>{{detail.executions | pv2fmt: 'int'}}</dd>\r\n <dt>{{'Tempo totale' | localize: lc}}</dt><dd>{{detail.elapsedTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Tempo proprio' | localize: lc}}</dt><dd>{{detail.elapsedTimeLessChildren | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Medio' | localize: lc}}</dt><dd>{{detail.avgTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Picco' | localize: lc}}</dt><dd>{{detail.peakTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Minimo' | localize: lc}}</dt><dd>{{detail.minTime ? (detail.minTime | pv2fmt: 'dur') : '\u2014'}}</dd>\r\n </dl>\r\n\r\n @if (live) {\r\n <div class=\"pv2-d-title\">{{\"Dall'ultimo snapshot\" | localize: lc}}, {{hhmm(detail.snapFrom)}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Esecuzioni' | localize: lc}}</dt><dd>{{detail.snapDeltaExecutions | pv2fmt: 'int'}}</dd>\r\n <dt>{{'Tempo totale' | localize: lc}}</dt><dd>{{detail.snapDeltaElapsedTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Tempo proprio' | localize: lc}}</dt><dd>{{detail.snapDeltaElapsedTimeLessChildren | pv2fmt: 'dur'}}</dd>\r\n </dl>\r\n\r\n <div class=\"pv2-d-title\">{{'Adesso' | localize: lc}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Thread dentro' | localize: lc}}</dt>\r\n <dd>\r\n @if (detail.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{detail.activeThreads}}</span>\r\n } @else {\r\n {{detail.activeThreads ?? '\u2014'}}\r\n }\r\n </dd>\r\n <dt>{{'Esecuzione pi\u00F9 lunga' | localize: lc}}</dt>\r\n <dd>\r\n @if (detail.activeThreads > 0) {\r\n {{detail.activeMaxTime | pv2fmt: 'dur'}}\r\n @if (isLongRunning(detail.eventTypeName, detail.waitClassName, detail.activeMaxTime)) {\r\n <span class=\"pv2-long\"><i class=\"fa fa-clock-o\"></i> {{'forse bloccata' | localize: lc}}</span>\r\n }\r\n } @else {\r\n \u2014\r\n }\r\n </dd>\r\n <dt>{{'Ultima uscita' | localize: lc}}</dt><dd>{{relative(detail.lastExitTime)}}</dd>\r\n </dl>\r\n }\r\n\r\n @if (typeParts.length > 0) {\r\n <div class=\"pv2-d-title\">{{'Tempo proprio del sottoalbero per tipo' | localize: lc}}</div>\r\n <div class=\"pv2-stack\">\r\n @for (part of typeParts; track part.type) {\r\n <div [style.width.%]=\"part.percentage\" [style.background]=\"part.color\" [title]=\"part.label + ' ' + (part.percentage | pv2fmt: 'pct')\"></div>\r\n }\r\n </div>\r\n <div class=\"pv2-legend\">\r\n @for (part of typeParts; track part.type) {\r\n <span class=\"pv2-legend-item\"><span class=\"pv2-swatch\" [style.background]=\"part.color\"></span>{{part.label}} <strong>{{part.percentage | pv2fmt: 'pct'}}</strong></span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pv2-d-title\">{{'Sessioni attive sul nodo e sui discendenti' | localize: lc}}</div>\r\n @if (chart) {\r\n <div class=\"pv2-chart\">\r\n <div class=\"pv2-chart-y\">\r\n <span>{{axisValue(chart.max)}}</span>\r\n <span>{{axisValue(chart.max / 2)}}</span>\r\n <span>0</span>\r\n </div>\r\n <div class=\"pv2-chart-plot\">\r\n <svg viewBox=\"0 0 100 100\" preserveAspectRatio=\"none\" aria-hidden=\"true\">\r\n <line x1=\"0\" y1=\"50\" x2=\"100\" y2=\"50\" class=\"pv2-chart-grid\" vector-effect=\"non-scaling-stroke\" />\r\n <path [attr.d]=\"chart.area\" [attr.fill]=\"chart.color\" fill-opacity=\"0.25\" />\r\n <path [attr.d]=\"chart.line\" [attr.stroke]=\"chart.color\" fill=\"none\" stroke-width=\"1.5\" vector-effect=\"non-scaling-stroke\" />\r\n </svg>\r\n <span class=\"pv2-chart-last\" [style.left.%]=\"chart.lastX\" [style.top.%]=\"chart.lastY\" [style.background]=\"chart.color\"></span>\r\n </div>\r\n <span></span>\r\n <div class=\"pv2-chart-x\">\r\n <span>{{chart.start}}</span>\r\n <span>{{chart.middle}}</span>\r\n <span>{{chart.end}}</span>\r\n </div>\r\n </div>\r\n <div class=\"pv2-caption\">\r\n {{'Media' | localize: lc}} {{axisValue(chart.average)}} &middot; {{'picco' | localize: lc}} {{axisValue(chart.peak)}} {{'sessioni' | localize: lc}}.\r\n {{chart.points | pv2fmt: 'int'}} {{\"punti dell'API\" | localize: lc}},\r\n @if (chart.interval == 1) {\r\n {{'uno al secondo' | localize: lc}},\r\n } @else {\r\n {{'uno ogni' | localize: lc}} {{chart.interval}} s,\r\n }\r\n {{'raggruppati a' | localize: lc}} {{chart.group}} s\r\n </div>\r\n } @else {\r\n <div class=\"pv2-muted pv2-small\">{{'Nessun campione in memoria per questa finestra: il grafico copre solo le ultime due ore circa.' | localize: lc}}</div>\r\n }\r\n\r\n @if (detail.instances?.length) {\r\n <div class=\"pv2-d-title\">{{'Per istanza' | localize: lc}}</div>\r\n <table class=\"pv2-mini\">\r\n <thead>\r\n <tr>\r\n <th>{{'Istanza' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Esecuzioni' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Tempo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Proprio' | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (inst of detail.instances; track inst.instanceId) {\r\n <tr>\r\n <td><span class=\"pv2-ellipsis\" [title]=\"inst.instanceId\">{{inst.instanceId}}</span></td>\r\n <td class=\"pv2-num\">{{inst.executions | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{inst.elapsedTime | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{inst.elapsedTimeLessChildren | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num\">{{inst.activeThreads ?? '\u2014'}}</td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <div class=\"pv2-d-foot\">\r\n <span class=\"pv2-muted\">{{detail.numChildren | pv2fmt: 'int'}} {{'figli diretti' | localize: lc}} &middot; {{detail.numDescendants | pv2fmt: 'int'}} {{'discendenti' | localize: lc}}</span>\r\n <button type=\"button\" class=\"pv2-btn\" (click)=\"setRoot(detail.nodeId)\"><i class=\"fa fa-sitemap\"></i> {{'Apri come radice' | localize: lc}}</button>\r\n </div>\r\n }\r\n </aside>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";:host{display:block}:host ::ng-deep .pv2-noclear .p-select-clear-icon{display:none}.pv2-body{container-type:inline-size}.pv2-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 22px;padding-top:6px}.pv2-cluster{display:flex;flex-wrap:nowrap;align-items:center;gap:10px}.pv2-cluster-end{margin-left:auto}.pv2-field{width:190px}.pv2-field-wide{width:290px}.pv2-field-narrow{width:140px}.pv2-field-search{flex:1 1 220px;min-width:200px;max-width:340px}.pv2-toggle{display:flex;align-items:center;gap:8px;height:39px;white-space:nowrap}.pv2-pointer{cursor:pointer}.pv2-group{position:relative;display:inline-flex}.pv2-group.pv2-disabled{opacity:.5}.pv2-group-label{position:absolute;top:-8px;left:8px;z-index:1;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.pv2-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.pv2-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 12px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.pv2-seg button:first-child{border-left:0}.pv2-seg button:hover:not(.pv2-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.pv2-seg button:disabled{cursor:default}.pv2-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.pv2-seg button.pv2-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.pv2-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.pv2-window{display:flex;flex-wrap:wrap;align-items:center;row-gap:4px;margin-top:12px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.pv2-window>span+span:before{content:\"\\b7\";margin:0 10px;color:var(--p-text-muted-color, #64748b)}.pv2-warn-text{color:#92400e}.pv2-main{display:grid;grid-template-columns:minmax(0,1fr) 420px;gap:14px;align-items:start;margin-top:14px}@container (max-width: 1150px){.pv2-main{grid-template-columns:minmax(0,1fr)}.pv2-detail{position:static;max-height:none}}.pv2-panel{padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.pv2-view-bar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 10px;padding-top:6px;margin-bottom:10px}.pv2-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;margin-bottom:8px;font-size:12px}.pv2-crumb{max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:2px 6px;border:0;border-radius:4px;background:transparent;color:var(--p-primary-color, #6366f1);cursor:pointer}.pv2-crumb:hover{background:var(--p-highlight-background, #eef2ff)}.pv2-crumb-current{color:var(--p-text-color, #334155);font-weight:500;cursor:default}.pv2-crumb-current:hover{background:transparent}.pv2-crumb-sep{color:var(--p-text-muted-color, #64748b)}.pv2-alert{position:relative;margin-bottom:8px;padding:6px 30px 6px 10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);font-size:13px}.pv2-alert.pv2-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.pv2-alert.pv2-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.pv2-alert-close{position:absolute;top:3px;right:6px;border:0;background:transparent;color:inherit;font-size:16px;cursor:pointer}.pv2-table-wrap{max-height:68vh;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.pv2-table-wrap:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:1px}.pv2-table{width:100%;min-width:860px;border-collapse:separate;border-spacing:0;font-size:13px;color:var(--p-text-color, #334155)}.pv2-table th{position:sticky;top:0;z-index:1;padding:7px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-size:12px;font-weight:500;white-space:nowrap;text-align:left}.pv2-table td{padding:4px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap;vertical-align:middle}.pv2-col-node{width:100%;max-width:0}.pv2-num{text-align:right!important;font-variant-numeric:tabular-nums}.pv2-row{cursor:pointer}.pv2-row:hover td{background:var(--p-content-hover-background, #f8fafc)}.pv2-row.pv2-selected td{background:var(--p-highlight-background, #eef2ff)}.pv2-row.pv2-idle td{color:var(--p-text-muted-color, #64748b)}.pv2-row.pv2-idle td .pv2-name{opacity:.75}.pv2-node{display:flex;align-items:center;gap:6px;min-width:0}.pv2-caret{flex:none;width:18px;height:20px;padding:0;border:0;background:transparent;color:var(--p-text-muted-color, #64748b);text-align:center;cursor:pointer}.pv2-type{flex:none;display:inline-flex;align-items:center;gap:5px;padding:0 6px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px;white-space:nowrap}.pv2-dot{flex:none;display:inline-block;width:8px;height:8px;border-radius:50%}.pv2-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pv2-name mark{padding:0 1px;border-radius:2px;background:#fde68a;color:#1f2937}.pv2-perc{width:1%}.pv2-perc-cell{display:flex;align-items:center;gap:8px}.pv2-bar{flex:none;width:64px;height:7px;border-radius:2px;overflow:hidden;background:var(--p-content-hover-background, #f8fafc);box-shadow:inset 0 0 0 1px var(--p-content-border-color, #e2e8f0)}.pv2-bar>div{height:100%}.pv2-threads>*+*{margin-left:8px}.pv2-active{display:inline-flex;align-items:center;gap:5px;font-weight:500}.pv2-active-dot{width:7px;height:7px;border-radius:50%;background:#16a34a;box-shadow:0 0 0 3px #16a34a2e}.pv2-long{display:inline-flex;align-items:center;gap:4px;padding:0 6px;border:1px solid #fcd34d;border-radius:10px;background:#fffbeb;color:#92400e;font-size:11px;line-height:18px;white-space:nowrap}.pv2-service td{padding:5px 10px;color:var(--p-text-muted-color, #64748b);font-size:12px;background:var(--p-content-background, #fff)}.pv2-sub td{padding:8px 10px 10px 34px;background:var(--p-content-hover-background, #f8fafc);white-space:normal}.pv2-sub-title{margin-bottom:4px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-sub-item{display:flex;align-items:center;gap:10px;padding:2px 0}.pv2-sub-item code{font-size:12px}.pv2-link{margin-left:6px;padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.pv2-link:hover{text-decoration:underline}.pv2-empty{padding:28px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.pv2-footer{margin-top:8px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-muted{color:var(--p-text-muted-color, #64748b)}.pv2-small{font-size:12px}.pv2-detail{position:sticky;top:10px;max-height:calc(100vh - 20px);overflow:auto;font-size:13px;color:var(--p-text-color, #334155);transition:opacity .15s}.pv2-detail.pv2-stale{opacity:.55}.pv2-placeholder{padding:36px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.pv2-error-text{color:#dc2626}.pv2-d-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.pv2-fullname{max-height:140px;overflow:auto;padding:8px 10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);font-family:ui-monospace,Cascadia Mono,Consolas,monospace;font-size:12px;white-space:pre-wrap;word-break:break-word}.pv2-id{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-id code{font-size:12px}.pv2-d-title{margin:16px 0 6px;padding-top:10px;border-top:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.pv2-path{display:flex;flex-direction:column}.pv2-path-item{display:flex;align-items:center;gap:6px;max-width:100%;padding:2px 0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.pv2-path-item:hover{text-decoration:underline}.pv2-path-current{color:var(--p-text-color, #334155);font-weight:600;cursor:default}.pv2-path-current:hover{text-decoration:none}.pv2-kv{display:grid;grid-template-columns:auto 1fr;gap:3px 14px;margin:0}.pv2-kv dt{color:var(--p-text-muted-color, #64748b);font-weight:400}.pv2-kv dd{margin:0;text-align:right;font-variant-numeric:tabular-nums}.pv2-stack{display:flex;height:12px;border-radius:3px;overflow:hidden;background:var(--p-content-hover-background, #f8fafc)}.pv2-legend{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:6px;font-size:12px}.pv2-legend-item{display:inline-flex;align-items:center;gap:5px}.pv2-swatch{width:10px;height:10px;border-radius:2px}.pv2-chart{display:grid;grid-template-columns:auto 1fr;gap:2px 6px}.pv2-chart-y{display:flex;flex-direction:column;justify-content:space-between;height:110px;color:var(--p-text-muted-color, #64748b);font-size:11px;text-align:right;line-height:1}.pv2-chart-plot{position:relative;height:110px;border-left:1px solid var(--p-content-border-color, #e2e8f0);border-bottom:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-chart-plot svg{display:block;width:100%;height:100%}.pv2-chart-grid{stroke:var(--p-content-border-color, #e2e8f0);stroke-dasharray:3 3}.pv2-chart-last{position:absolute;width:8px;height:8px;border:2px solid var(--p-content-background, #fff);border-radius:50%;transform:translate(-50%,-50%)}.pv2-chart-x{display:flex;justify-content:space-between;color:var(--p-text-muted-color, #64748b);font-size:11px}.pv2-caption{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-mini{width:100%;font-size:12px}.pv2-mini th{padding:3px 6px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-weight:500}.pv2-mini td{padding:3px 6px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-ellipsis{display:inline-block;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.pv2-d-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;margin-top:16px;padding-top:10px;border-top:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;cursor:pointer}.pv2-btn:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}\n"], dependencies: [{ kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i9.EsFormInputComponent, selector: "form-input", inputs: ["minlength", "maxlength", "pattern", "Password", "Type"] }, { kind: "component", type: i9.EsFormSelectComponent, selector: "form-select", inputs: ["OptionsTemplate"] }, { kind: "component", type: i9.EsFormDateTimeComponent, selector: "form-datetime" }, { kind: "component", type: i9.EsFormCheckboxComponent, selector: "form-checkbox", inputs: ["SliderMode"] }, { kind: "directive", type: i10.Widget, selector: "[widget]" }, { kind: "pipe", type: i1.LocalizePipe, name: "localize" }, { kind: "pipe", type: ProfilerFormatPipe, name: "pv2fmt" }] }); }
1972
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.34", type: AdmProfilerV2Component, isStandalone: false, selector: "profiler_v2", providers: [{ provide: LocalizationService, useClass: AdmProfilerV2Loc }], ngImport: i0, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Profiler del Server' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body pv2-body\">\r\n <!-- Barra dei comandi: quali dati caricare. Ogni cambio ricarica la vista e il dettaglio aperto -->\r\n <div class=\"pv2-toolbar\">\r\n <div class=\"pv2-cluster\">\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Sorgente' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"live\" (click)=\"setLive(true)\"><span class=\"pv2-live-dot\"></span>Live</button>\r\n <button type=\"button\" [class.pv2-on]=\"!live\" (click)=\"setLive(false)\">{{'Storico' | localize: lc}}</button>\r\n </div>\r\n </div>\r\n <div class=\"pv2-field pv2-field-wide pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instance\" (ngModelChange)=\"setInstance($event)\" name=\"instance\" [Source]=\"Instances\" [Placeholder]=\"'Istanze' | localize: lc\"></form-select>\r\n </div>\r\n </div>\r\n\r\n @if (!live) {\r\n <div class=\"pv2-cluster\">\r\n <div class=\"pv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterfrom\" (ngModelChange)=\"filterfrom = $event; datesChanged()\" name=\"filterfrom\" [Placeholder]=\"'Dal' | localize: lc\"></form-datetime>\r\n </div>\r\n <div class=\"pv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterto\" (ngModelChange)=\"filterto = $event; datesChanged()\" name=\"filterto\" [Placeholder]=\"'Al' | localize: lc\"></form-datetime>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Valori' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"!snapValues\" (click)=\"setSnapValues(false)\">{{\"Dall'avvio\" | localize: lc}}</button>\r\n <button type=\"button\" [class.pv2-on]=\"snapValues\" (click)=\"setSnapValues(true)\">{{\"Dall'ultimo snapshot\" | localize: lc}}</button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"pv2-cluster pv2-cluster-end\">\r\n <button type=\"button\" class=\"btn app-btn-search\" [disabled]=\"loading\" (click)=\"reloadAll()\" [title]=\"'Aggiorna' | localize: lc\">\r\n <i class=\"fa fa-refresh\" [class.fa-spin]=\"loading\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn app-btn-search\" (click)=\"downloadWorkloadReport()\" [title]=\"(workloadV2 ? 'Workload report' : 'Scarica il workload report') | localize: lc\">\r\n <i class=\"fa\" [class.fa-download]=\"!workloadV2\" [class.fa-file-text]=\"workloadV2\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Riga della finestra: sempre visibile sopra la vista -->\r\n <div class=\"pv2-window\">\r\n <span><strong>{{live ? 'Live' : ('Storico' | localize: lc)}}</strong> &middot; {{instanceLabel}}</span>\r\n @if (current?.snapFrom; as snapFrom) {\r\n @if (live) {\r\n <span>{{\"Delta dall'ultimo snapshot delle\" | localize: lc}} {{hhmm(snapFrom)}} ({{minutesAgo(snapFrom)}} {{'min fa' | localize: lc}})</span>\r\n } @else {\r\n <span>{{'Snapshot dalle' | localize: lc}} {{ddmmhhmm(snapFrom)}} {{'alle' | localize: lc}} {{ddmmhhmm(current?.snapTo)}}</span>\r\n }\r\n } @else if (current && !live) {\r\n <span class=\"pv2-warn-text\">{{'Nessuno snapshot termina nella finestra scelta' | localize: lc}}</span>\r\n }\r\n @if (view == 'tree' && tree?.idleNode) {\r\n <span>{{tree.numNodes | pv2fmt: 'int'}} {{\"nodi nell'albero\" | localize: lc}} &middot; {{tree.numReturnedNodes | pv2fmt: 'int'}} {{'nella risposta' | localize: lc}}</span>\r\n }\r\n @if (view == 'flat' && flat) {\r\n <span>{{flat.numItems | pv2fmt: 'int'}} {{'eventi distinti' | localize: lc}}</span>\r\n }\r\n @if (loading) {\r\n <span class=\"pv2-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n </div>\r\n\r\n <div class=\"pv2-main\">\r\n <!-- Vista: albero o eventi per nome -->\r\n <div class=\"pv2-panel pv2-view\">\r\n <div class=\"pv2-view-bar\">\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"view == 'tree'\" (click)=\"setView('tree')\"><i class=\"fa fa-sitemap\"></i> {{'Albero' | localize: lc}}</button>\r\n <button type=\"button\" [class.pv2-on]=\"view == 'flat'\" (click)=\"setView('flat')\"><i class=\"fa fa-list\"></i> {{'Per nome' | localize: lc}}</button>\r\n </div>\r\n\r\n @if (view == 'tree') {\r\n <div class=\"pv2-field pv2-field-search\" [title]=\"'Per esempio MRD_METERREADINGS, ENQUEUE, ProfilesMgr' | localize: lc\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"searchText\" (ngModelChange)=\"searchText = $event; searchChanged()\" name=\"search\" [Placeholder]=\"'Cerca nei nomi o per id' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"pv2-field pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"orderBy\" (ngModelChange)=\"setOrderBy($event)\" name=\"orderBy\" [Source]=\"TreeOrderOptions\" [Placeholder]=\"'Ordina per' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-group\" [class.pv2-disabled]=\"!!activeSearch\">\r\n <span class=\"pv2-group-label\">{{'Figli per nodo' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of ChildrenOptions; track o.id) {\r\n <button type=\"button\" [disabled]=\"!!activeSearch\" [class.pv2-on]=\"maxChildren == o.id\" (click)=\"setMaxChildren(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"pv2-group\" [class.pv2-disabled]=\"!!activeSearch\">\r\n <span class=\"pv2-group-label\">{{'Soglia' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of ThresholdOptions; track o.id) {\r\n <button type=\"button\" [disabled]=\"!!activeSearch\" [class.pv2-on]=\"minPercentage == o.id\" (click)=\"setMinPercentage(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"pv2-field pv2-field-search\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatSearch\" (ngModelChange)=\"flatSearch = $event; flatSearchChanged()\" name=\"flatSearch\" [Placeholder]=\"'Cerca nei nomi' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"pv2-field pv2-field-narrow pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatType\" (ngModelChange)=\"flatType = $event; flatChanged()\" name=\"flatType\" [Source]=\"FlatTypes\" [Placeholder]=\"'Tipo' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-field pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatOrderBy\" (ngModelChange)=\"flatOrderBy = $event; flatChanged()\" name=\"flatOrderBy\" [Source]=\"FlatOrderOptions\" [Placeholder]=\"'Ordina per' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Righe' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of FlatRows; track o.id) {\r\n <button type=\"button\" [class.pv2-on]=\"flatTop == o.id\" (click)=\"setFlatTop(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"pv2-toggle\">\r\n <form-checkbox [FormLayout]=\"false\" [SliderMode]=\"true\" [Validation]=\"false\" [ngModel]=\"flatIncludeIdle\" (ngModelChange)=\"flatIncludeIdle = $event; flatChanged()\" name=\"flatIncludeIdle\"></form-checkbox>\r\n <span class=\"pv2-pointer\" (click)=\"flatIncludeIdle = !flatIncludeIdle; flatChanged()\">{{'Anche gli eventi idle' | localize: lc}}</span>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (view == 'tree') {\r\n <!-- Percorso della radice: ogni antenato riporta l'albero a quel nodo -->\r\n @if (tree?.idleNode && tree?.rootPath?.length) {\r\n <nav class=\"pv2-crumbs\">\r\n @for (item of tree.rootPath; track item.nodeId) {\r\n <button type=\"button\" class=\"pv2-crumb\" [title]=\"item.nodeName\" (click)=\"setRoot(item.nodeId)\">{{item.nodeName}}</button>\r\n <span class=\"pv2-crumb-sep\">&rsaquo;</span>\r\n }\r\n <span class=\"pv2-crumb pv2-crumb-current\" [title]=\"tree.idleNode.nodeName\">{{tree.idleNode.nodeName}}</span>\r\n </nav>\r\n }\r\n\r\n @if (treeNotice) {\r\n <div class=\"pv2-alert pv2-alert-warn\">\r\n {{treeNotice}}\r\n <button type=\"button\" class=\"pv2-alert-close\" [title]=\"'Chiudi' | localize: lc\" (click)=\"treeNotice = null\">&times;</button>\r\n </div>\r\n }\r\n @if (activeSearch && tree) {\r\n @if (matchCount > 0) {\r\n <div class=\"pv2-alert\" [class.pv2-alert-warn]=\"tree.truncated\">\r\n {{matchCount | pv2fmt: 'int'}} {{'nodi trovati, con i loro antenati.' | localize: lc}}\r\n @if (tree.truncated) {\r\n <strong>{{'I nodi trovati sono pi\u00F9 di 1.000: sono mostrati i primi per l\\'ordinamento scelto.' | localize: lc}}</strong>\r\n }\r\n </div>\r\n } @else if (!treeLoading) {\r\n <div class=\"pv2-alert\">{{'Nessun nodo contiene' | localize: lc}} &laquo;{{activeSearch}}&raquo;.</div>\r\n }\r\n }\r\n @if (treeError) {\r\n <div class=\"pv2-alert pv2-alert-error\">{{treeError}}</div>\r\n }\r\n\r\n <div class=\"pv2-table-wrap\" tabindex=\"0\" (keydown)=\"treeKeydown($event)\">\r\n <table class=\"pv2-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"pv2-col-node\">{{'Nodo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Chiamate' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Tempo' | localize: lc}}</th>\r\n <th>{{snapMode ? '\u0394 ' : ''}}{{'% del padre' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? '\u0394 Proprio' : 'Tempo proprio') | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Medio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Picco' | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread ora' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of rows; track row.key) {\r\n @if (row.kind == 'node') {\r\n <tr [id]=\"'pv2-row-' + row.node.nodeId\" class=\"pv2-row\"\r\n [class.pv2-selected]=\"row.node.nodeId == selectedId\"\r\n [class.pv2-idle]=\"isIdle(row.node.eventTypeName, row.node.waitClassName)\"\r\n (click)=\"rowClicked(row.node)\" (dblclick)=\"toggle(row.node)\">\r\n <td class=\"pv2-col-node\">\r\n <div class=\"pv2-node\" [style.padding-left.px]=\"row.depth * 16\">\r\n @if (hasChildren(row.node)) {\r\n <button type=\"button\" class=\"pv2-caret\" tabindex=\"-1\" [attr.aria-expanded]=\"isExpanded(row.node)\" (click)=\"toggle(row.node, $event)\">\r\n <i class=\"fa\" [class.fa-caret-down]=\"isExpanded(row.node)\" [class.fa-caret-right]=\"!isExpanded(row.node)\"></i>\r\n </button>\r\n } @else {\r\n <span class=\"pv2-caret\"></span>\r\n }\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(row.node.eventTypeName, row.node.waitClassName)\"></span>{{typeLabel(row.node.eventTypeName, row.node.waitClassName)}}</span>\r\n <span class=\"pv2-name\" [title]=\"row.node.nodeName\">@if (row.node.searchMatch && activeSearch) {@for (part of nameParts(row.node.nodeName, activeSearch); track $index) {@if (part.hit) {<mark>{{part.text}}</mark>} @else {<span>{{part.text}}</span>}}} @else {<span>{{row.node.nodeName}}</span>}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{calls(row.node) | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{time(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-perc\" [title]=\"(parentPerc(row.node) | pv2fmt: 'pct') + ' ' + ('del padre' | localize: lc) + ' \u00B7 ' + (firstLevelPerc(row.node) | pv2fmt: 'pct') + ' ' + ('del nodo di primo livello' | localize: lc)\">\r\n <div class=\"pv2-perc-cell\">\r\n <div class=\"pv2-bar\"><div [style.width.%]=\"parentPerc(row.node)\" [style.background]=\"typeColor(row.node.eventTypeName, row.node.waitClassName)\"></div></div>\r\n <span>{{parentPerc(row.node) | pv2fmt: 'pct'}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{self(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{avg(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{peak(row.node) | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num pv2-threads\">\r\n @if (isLongRunning(row.node.eventTypeName, row.node.waitClassName, row.node.activeMaxTime)) {\r\n <span class=\"pv2-long\" [title]=\"('Esecuzione in corso da' | localize: lc) + ' ' + duration(row.node.activeMaxTime) + ': ' + ('forse bloccata' | localize: lc)\"><i class=\"fa fa-clock\"></i> {{duration(row.node.activeMaxTime)}}</span>\r\n }\r\n @if (row.node.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{row.node.activeThreads}}</span>\r\n } @else {\r\n <span class=\"pv2-muted\">{{row.node.activeThreads ?? '\u2014'}}</span>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n } @else if (row.kind == 'loading') {\r\n <tr class=\"pv2-service\">\r\n <td [attr.colspan]=\"live ? 8 : 7\">\r\n <div [style.padding-left.px]=\"row.depth * 16 + 24\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento dei figli\u2026' | localize: lc}}</div>\r\n </td>\r\n </tr>\r\n } @else {\r\n <tr class=\"pv2-service\">\r\n <td [attr.colspan]=\"live ? 8 : 7\">\r\n <div [style.padding-left.px]=\"row.depth * 16 + 24\">\r\n {{row.node.omittedChildren | pv2fmt: 'int'}} {{'figli non mostrati' | localize: lc}} &middot; {{omittedTime(row.node) | pv2fmt: 'dur'}}\r\n @if (!snapMode) {\r\n &middot; {{row.node.omittedCalls | pv2fmt: 'int'}} {{'chiamate' | localize: lc}}\r\n }\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"showAll(row.node, $event)\">{{'Mostra tutti' | localize: lc}}</button>\r\n </div>\r\n </td>\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n </table>\r\n @if (rows.length == 0 && !treeError) {\r\n <div class=\"pv2-empty\">\r\n @if (!tree) {\r\n {{'Caricamento\u2026' | localize: lc}}\r\n } @else if (!tree.snapFrom && !live) {\r\n {{'Nessuno snapshot termina nella finestra scelta: allargala o spostala indietro.' | localize: lc}}\r\n } @else {\r\n {{\"Il nodo non c'\u00E8 nelle istanze scelte.\" | localize: lc}}\r\n }\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n @if (flatError) {\r\n <div class=\"pv2-alert pv2-alert-error\">{{flatError}}</div>\r\n }\r\n <div class=\"pv2-table-wrap\">\r\n <table class=\"pv2-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"pv2-col-node\">{{'Evento' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Percorsi' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Chiamate' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? '\u0394 Proprio' : 'Tempo proprio') | localize: lc}}</th>\r\n <th>{{snapMode ? '\u0394 ' : ''}}{{'% proprio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Tempo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Medio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? \"Picco dall'avvio\" : 'Picco') | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (item of flat?.items ?? []; track flatKey(item)) {\r\n <tr class=\"pv2-row\" [class.pv2-idle]=\"isIdle(item.eventTypeName, item.waitClassName)\" [class.pv2-selected]=\"openFlat.has(flatKey(item))\" (click)=\"toggleFlat(item)\">\r\n <td class=\"pv2-col-node\">\r\n <div class=\"pv2-node\">\r\n <span class=\"pv2-caret\"><i class=\"fa\" [class.fa-caret-down]=\"openFlat.has(flatKey(item))\" [class.fa-caret-right]=\"!openFlat.has(flatKey(item))\"></i></span>\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></span>{{typeLabel(item.eventTypeName, item.waitClassName)}}</span>\r\n <span class=\"pv2-name\" [title]=\"item.nodeName\">@for (part of nameParts(item.nodeName, (flatSearch ?? '').trim()); track $index) {@if (part.hit) {<mark>{{part.text}}</mark>} @else {<span>{{part.text}}</span>}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{item.numPaths | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{flatCalls(item) | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{flatSelf(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-perc\">\r\n <div class=\"pv2-perc-cell\">\r\n <div class=\"pv2-bar\"><div [style.width.%]=\"flatPerc(item)\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></div></div>\r\n <span>{{flatPerc(item) | pv2fmt: 'pct'}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{flatTime(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{flatAvg(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{item.peakTime | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num pv2-threads\">\r\n @if (item.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{item.activeThreads}}</span>\r\n } @else {\r\n <span class=\"pv2-muted\">{{item.activeThreads ?? '\u2014'}}</span>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n @if (openFlat.has(flatKey(item))) {\r\n <tr class=\"pv2-sub\">\r\n <td [attr.colspan]=\"live ? 9 : 8\">\r\n <div class=\"pv2-sub-title\">{{'Nodi con pi\u00F9 tempo' | localize: lc}}</div>\r\n @for (id of item.nodeIds ?? []; track id) {\r\n <div class=\"pv2-sub-item\">\r\n <code>{{id}}</code>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"showDetail(id, $event)\">{{'Dettaglio' | localize: lc}}</button>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"openInTree(id, $event)\">{{\"Apri nell'albero\" | localize: lc}}</button>\r\n </div>\r\n }\r\n @if (item.numPaths > (item.nodeIds?.length ?? 0)) {\r\n <div class=\"pv2-muted\">+{{item.numPaths - (item.nodeIds?.length ?? 0) | pv2fmt: 'int'}} {{'altri' | localize: lc}}</div>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n </table>\r\n @if (!flatError && (!flat || !flat.items?.length)) {\r\n <div class=\"pv2-empty\">{{(flat ? 'Nessun evento con questi filtri.' : 'Caricamento\u2026') | localize: lc}}</div>\r\n }\r\n </div>\r\n @if (flat?.items?.length) {\r\n <div class=\"pv2-footer\">\r\n {{flat.numItems | pv2fmt: 'int'}} {{'eventi distinti' | localize: lc}}@if (flat.numItems > flat.items.length) {, {{'mostrati i primi' | localize: lc}} {{flat.items.length | pv2fmt: 'int'}}}.\r\n {{'La percentuale \u00E8 sul tempo proprio di tutti gli eventi non idle.' | localize: lc}}\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Dettaglio del nodo selezionato, lo stesso per le due viste -->\r\n <aside class=\"pv2-panel pv2-detail\" [class.pv2-stale]=\"detailStale\">\r\n @if (!selectedId) {\r\n <div class=\"pv2-placeholder\">{{'Seleziona un nodo per vederne il dettaglio.' | localize: lc}}</div>\r\n } @else if (detailMissing && !detailLoading) {\r\n <div class=\"pv2-placeholder\">{{\"Il nodo non c'\u00E8 nelle istanze o nella finestra scelte.\" | localize: lc}}</div>\r\n } @else if (detailError && !detailLoading) {\r\n <div class=\"pv2-placeholder pv2-error-text\">{{detailError}}</div>\r\n } @else if (!detail) {\r\n <div class=\"pv2-placeholder\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</div>\r\n } @else {\r\n <div class=\"pv2-d-head\">\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(detail.eventTypeName, detail.waitClassName)\"></span>{{typeLabel(detail.eventTypeName, detail.waitClassName)}}</span>\r\n @if (detailLoading) {\r\n <i class=\"fa fa-spinner fa-spin pv2-muted\"></i>\r\n }\r\n </div>\r\n <div class=\"pv2-fullname\">{{detail.nodeName}}</div>\r\n <div class=\"pv2-id\">\r\n Id <code #idText>{{detail.nodeId}}</code>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"copyId(idText)\">{{(copied ? 'Copiato' : 'Copia') | localize: lc}}</button>\r\n </div>\r\n\r\n <div class=\"pv2-d-title\">{{'Percorso' | localize: lc}}</div>\r\n <div class=\"pv2-path\">\r\n @for (item of detail.fullWaitStack ?? []; track item.nodeId; let i = $index) {\r\n <button type=\"button\" class=\"pv2-path-item\" [style.padding-left.px]=\"i * 10\" [title]=\"item.nodeName\" (click)=\"select(item.nodeId)\">\r\n <span class=\"pv2-dot\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></span>{{item.nodeName}}\r\n </button>\r\n }\r\n <div class=\"pv2-path-item pv2-path-current\" [style.padding-left.px]=\"(detail.fullWaitStack?.length ?? 0) * 10\" [title]=\"detail.nodeName\">\r\n <span class=\"pv2-dot\" [style.background]=\"typeColor(detail.eventTypeName, detail.waitClassName)\"></span>{{detail.nodeName}}\r\n </div>\r\n </div>\r\n\r\n <div class=\"pv2-d-title\">{{(live ? \"Dall'avvio\" : 'Nella finestra') | localize: lc}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Esecuzioni' | localize: lc}}</dt><dd>{{detail.executions | pv2fmt: 'int'}}</dd>\r\n <dt>{{'Tempo totale' | localize: lc}}</dt><dd>{{detail.elapsedTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Tempo proprio' | localize: lc}}</dt><dd>{{detail.elapsedTimeLessChildren | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Medio' | localize: lc}}</dt><dd>{{detail.avgTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Picco' | localize: lc}}</dt><dd>{{detail.peakTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Minimo' | localize: lc}}</dt><dd>{{detail.minTime ? (detail.minTime | pv2fmt: 'dur') : '\u2014'}}</dd>\r\n </dl>\r\n\r\n @if (live) {\r\n <div class=\"pv2-d-title\">{{\"Dall'ultimo snapshot\" | localize: lc}}, {{hhmm(detail.snapFrom)}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Esecuzioni' | localize: lc}}</dt><dd>{{detail.snapDeltaExecutions | pv2fmt: 'int'}}</dd>\r\n <dt>{{'Tempo totale' | localize: lc}}</dt><dd>{{detail.snapDeltaElapsedTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Tempo proprio' | localize: lc}}</dt><dd>{{detail.snapDeltaElapsedTimeLessChildren | pv2fmt: 'dur'}}</dd>\r\n </dl>\r\n\r\n <div class=\"pv2-d-title\">{{'Adesso' | localize: lc}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Thread dentro' | localize: lc}}</dt>\r\n <dd>\r\n @if (detail.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{detail.activeThreads}}</span>\r\n } @else {\r\n {{detail.activeThreads ?? '\u2014'}}\r\n }\r\n </dd>\r\n <dt>{{'Esecuzione pi\u00F9 lunga' | localize: lc}}</dt>\r\n <dd>\r\n @if (detail.activeThreads > 0) {\r\n {{detail.activeMaxTime | pv2fmt: 'dur'}}\r\n @if (isLongRunning(detail.eventTypeName, detail.waitClassName, detail.activeMaxTime)) {\r\n <span class=\"pv2-long\"><i class=\"fa fa-clock\"></i> {{'forse bloccata' | localize: lc}}</span>\r\n }\r\n } @else {\r\n \u2014\r\n }\r\n </dd>\r\n <dt>{{'Ultima uscita' | localize: lc}}</dt><dd>{{relative(detail.lastExitTime)}}</dd>\r\n </dl>\r\n }\r\n\r\n @if (typeParts.length > 0) {\r\n <div class=\"pv2-d-title\">{{'Tempo proprio del sottoalbero per tipo' | localize: lc}}</div>\r\n <div class=\"pv2-stack\">\r\n @for (part of typeParts; track part.type) {\r\n <div [style.width.%]=\"part.percentage\" [style.background]=\"part.color\" [title]=\"part.label + ' ' + (part.percentage | pv2fmt: 'pct')\"></div>\r\n }\r\n </div>\r\n <div class=\"pv2-legend\">\r\n @for (part of typeParts; track part.type) {\r\n <span class=\"pv2-legend-item\"><span class=\"pv2-swatch\" [style.background]=\"part.color\"></span>{{part.label}} <strong>{{part.percentage | pv2fmt: 'pct'}}</strong></span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pv2-d-title\">{{'Sessioni attive sul nodo e sui discendenti' | localize: lc}}</div>\r\n @if (chart) {\r\n <div class=\"pv2-chart\">\r\n <div class=\"pv2-chart-y\">\r\n <span>{{axisValue(chart.max)}}</span>\r\n <span>{{axisValue(chart.max / 2)}}</span>\r\n <span>0</span>\r\n </div>\r\n <div class=\"pv2-chart-plot\">\r\n <svg viewBox=\"0 0 100 100\" preserveAspectRatio=\"none\" aria-hidden=\"true\">\r\n <line x1=\"0\" y1=\"50\" x2=\"100\" y2=\"50\" class=\"pv2-chart-grid\" vector-effect=\"non-scaling-stroke\" />\r\n <path [attr.d]=\"chart.area\" [attr.fill]=\"chart.color\" fill-opacity=\"0.25\" />\r\n <path [attr.d]=\"chart.line\" [attr.stroke]=\"chart.color\" fill=\"none\" stroke-width=\"1.5\" vector-effect=\"non-scaling-stroke\" />\r\n </svg>\r\n <span class=\"pv2-chart-last\" [style.left.%]=\"chart.lastX\" [style.top.%]=\"chart.lastY\" [style.background]=\"chart.color\"></span>\r\n </div>\r\n <span></span>\r\n <div class=\"pv2-chart-x\">\r\n <span>{{chart.start}}</span>\r\n <span>{{chart.middle}}</span>\r\n <span>{{chart.end}}</span>\r\n </div>\r\n </div>\r\n <div class=\"pv2-caption\">\r\n {{'Media' | localize: lc}} {{axisValue(chart.average)}} &middot; {{'picco' | localize: lc}} {{axisValue(chart.peak)}} {{'sessioni' | localize: lc}}.\r\n {{chart.points | pv2fmt: 'int'}} {{\"punti dell'API\" | localize: lc}},\r\n @if (chart.interval == 1) {\r\n {{'uno al secondo' | localize: lc}},\r\n } @else {\r\n {{'uno ogni' | localize: lc}} {{chart.interval}} s,\r\n }\r\n {{'raggruppati a' | localize: lc}} {{chart.group}} s\r\n </div>\r\n } @else {\r\n <div class=\"pv2-muted pv2-small\">{{'Nessun campione in memoria per questa finestra: il grafico copre solo le ultime due ore circa.' | localize: lc}}</div>\r\n }\r\n\r\n @if (detail.instances?.length) {\r\n <div class=\"pv2-d-title\">{{'Per istanza' | localize: lc}}</div>\r\n <table class=\"pv2-mini\">\r\n <thead>\r\n <tr>\r\n <th>{{'Istanza' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Esecuzioni' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Tempo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Proprio' | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (inst of detail.instances; track inst.instanceId) {\r\n <tr>\r\n <td><span class=\"pv2-ellipsis\" [title]=\"inst.instanceId\">{{inst.instanceId}}</span></td>\r\n <td class=\"pv2-num\">{{inst.executions | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{inst.elapsedTime | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{inst.elapsedTimeLessChildren | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num\">{{inst.activeThreads ?? '\u2014'}}</td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <div class=\"pv2-d-foot\">\r\n <span class=\"pv2-muted\">{{detail.numChildren | pv2fmt: 'int'}} {{'figli diretti' | localize: lc}} &middot; {{detail.numDescendants | pv2fmt: 'int'}} {{'discendenti' | localize: lc}}</span>\r\n <button type=\"button\" class=\"pv2-btn\" (click)=\"setRoot(detail.nodeId)\"><i class=\"fa fa-sitemap\"></i> {{'Apri come radice' | localize: lc}}</button>\r\n </div>\r\n }\r\n </aside>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";:host{display:block}:host ::ng-deep .pv2-noclear .p-select-clear-icon{display:none}.pv2-body{container-type:inline-size}.pv2-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 22px;padding-top:6px}.pv2-cluster{display:flex;flex-wrap:nowrap;align-items:center;gap:10px}.pv2-cluster-end{margin-left:auto}.pv2-field{width:190px}.pv2-field-wide{width:290px}.pv2-field-narrow{width:140px}.pv2-field-search{flex:1 1 220px;min-width:200px;max-width:340px}.pv2-toggle{display:flex;align-items:center;gap:8px;height:39px;white-space:nowrap}.pv2-pointer{cursor:pointer}.pv2-group{position:relative;display:inline-flex}.pv2-group.pv2-disabled{opacity:.5}.pv2-group-label{position:absolute;top:-8px;left:8px;z-index:1;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.pv2-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.pv2-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 12px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.pv2-seg button:first-child{border-left:0}.pv2-seg button:hover:not(.pv2-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.pv2-seg button:disabled{cursor:default}.pv2-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.pv2-seg button.pv2-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.pv2-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.pv2-window{display:flex;flex-wrap:wrap;align-items:center;row-gap:4px;margin-top:12px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.pv2-window>span+span:before{content:\"\\b7\";margin:0 10px;color:var(--p-text-muted-color, #64748b)}.pv2-warn-text{color:#92400e}.pv2-main{display:grid;grid-template-columns:minmax(0,1fr) 380px;gap:14px;align-items:start;margin-top:14px}@container (max-width: 1350px){.pv2-main{grid-template-columns:minmax(0,1fr)}.pv2-detail{position:static;max-height:none}}.pv2-panel{padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.pv2-view-bar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 10px;padding-top:6px;margin-bottom:10px}.pv2-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;margin-bottom:8px;font-size:12px}.pv2-crumb{max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:2px 6px;border:0;border-radius:4px;background:transparent;color:var(--p-primary-color, #6366f1);cursor:pointer}.pv2-crumb:hover{background:var(--p-highlight-background, #eef2ff)}.pv2-crumb-current{color:var(--p-text-color, #334155);font-weight:500;cursor:default}.pv2-crumb-current:hover{background:transparent}.pv2-crumb-sep{color:var(--p-text-muted-color, #64748b)}.pv2-alert{position:relative;margin-bottom:8px;padding:6px 30px 6px 10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);font-size:13px}.pv2-alert.pv2-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.pv2-alert.pv2-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.pv2-alert-close{position:absolute;top:3px;right:6px;border:0;background:transparent;color:inherit;font-size:16px;cursor:pointer}.pv2-table-wrap{max-height:68vh;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.pv2-table-wrap:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:1px}.pv2-table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;color:var(--p-text-color, #334155)}.pv2-table th{position:sticky;top:0;z-index:1;padding:7px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-size:12px;font-weight:500;white-space:nowrap;text-align:left}.pv2-table td{padding:4px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap;vertical-align:middle}.pv2-col-node{width:100%;max-width:0}.pv2-col-node .pv2-node{min-width:260px}.pv2-num{text-align:right!important;font-variant-numeric:tabular-nums}.pv2-row{cursor:pointer}.pv2-row:hover td{background:var(--p-content-hover-background, #f8fafc)}.pv2-row.pv2-selected td{background:var(--p-highlight-background, #eef2ff)}.pv2-row.pv2-idle td{color:var(--p-text-muted-color, #64748b)}.pv2-row.pv2-idle td .pv2-name{opacity:.75}.pv2-node{display:flex;align-items:center;gap:6px;min-width:0}.pv2-caret{flex:none;width:18px;height:20px;padding:0;border:0;background:transparent;color:var(--p-text-muted-color, #64748b);text-align:center;cursor:pointer}.pv2-type{flex:none;display:inline-flex;align-items:center;gap:5px;padding:0 6px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px;white-space:nowrap}.pv2-dot{flex:none;display:inline-block;width:8px;height:8px;border-radius:50%}.pv2-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pv2-name mark{padding:0 1px;border-radius:2px;background:#fde68a;color:#1f2937}.pv2-perc{width:1%}.pv2-perc-cell{display:flex;align-items:center;gap:8px}.pv2-bar{flex:none;width:64px;height:7px;border-radius:2px;overflow:hidden;background:var(--p-content-hover-background, #f8fafc);box-shadow:inset 0 0 0 1px var(--p-content-border-color, #e2e8f0)}.pv2-bar>div{height:100%}.pv2-threads>*+*{margin-left:8px}.pv2-active{display:inline-flex;align-items:center;gap:5px;font-weight:500}.pv2-active-dot{width:7px;height:7px;border-radius:50%;background:#16a34a;box-shadow:0 0 0 3px #16a34a2e}.pv2-long{display:inline-flex;align-items:center;gap:4px;padding:0 6px;border:1px solid #fcd34d;border-radius:10px;background:#fffbeb;color:#92400e;font-size:11px;line-height:18px;white-space:nowrap}.pv2-service td{padding:5px 10px;color:var(--p-text-muted-color, #64748b);font-size:12px;background:var(--p-content-background, #fff)}.pv2-sub td{padding:8px 10px 10px 34px;background:var(--p-content-hover-background, #f8fafc);white-space:normal}.pv2-sub-title{margin-bottom:4px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-sub-item{display:flex;align-items:center;gap:10px;padding:2px 0}.pv2-sub-item code{font-size:12px}.pv2-link{margin-left:6px;padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.pv2-link:hover{text-decoration:underline}.pv2-empty{padding:28px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.pv2-footer{margin-top:8px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-muted{color:var(--p-text-muted-color, #64748b)}.pv2-small{font-size:12px}.pv2-detail{position:sticky;top:10px;max-height:calc(100vh - 20px);overflow:auto;font-size:13px;color:var(--p-text-color, #334155);transition:opacity .15s}.pv2-detail.pv2-stale{opacity:.55}.pv2-placeholder{padding:36px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.pv2-error-text{color:#dc2626}.pv2-d-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.pv2-fullname{max-height:140px;overflow:auto;padding:8px 10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);font-family:ui-monospace,Cascadia Mono,Consolas,monospace;font-size:12px;white-space:pre-wrap;word-break:break-word}.pv2-id{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-id code{font-size:12px}.pv2-d-title{margin:16px 0 6px;padding-top:10px;border-top:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.pv2-path{display:flex;flex-direction:column}.pv2-path-item{display:flex;align-items:center;gap:6px;max-width:100%;padding:2px 0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.pv2-path-item:hover{text-decoration:underline}.pv2-path-current{color:var(--p-text-color, #334155);font-weight:600;cursor:default}.pv2-path-current:hover{text-decoration:none}.pv2-kv{display:grid;grid-template-columns:auto 1fr;gap:3px 14px;margin:0}.pv2-kv dt{color:var(--p-text-muted-color, #64748b);font-weight:400}.pv2-kv dd{margin:0;text-align:right;font-variant-numeric:tabular-nums}.pv2-stack{display:flex;height:12px;border-radius:3px;overflow:hidden;background:var(--p-content-hover-background, #f8fafc)}.pv2-legend{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:6px;font-size:12px}.pv2-legend-item{display:inline-flex;align-items:center;gap:5px}.pv2-swatch{width:10px;height:10px;border-radius:2px}.pv2-chart{display:grid;grid-template-columns:auto 1fr;gap:2px 6px}.pv2-chart-y{display:flex;flex-direction:column;justify-content:space-between;height:110px;color:var(--p-text-muted-color, #64748b);font-size:11px;text-align:right;line-height:1}.pv2-chart-plot{position:relative;height:110px;border-left:1px solid var(--p-content-border-color, #e2e8f0);border-bottom:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-chart-plot svg{display:block;width:100%;height:100%}.pv2-chart-grid{stroke:var(--p-content-border-color, #e2e8f0);stroke-dasharray:3 3}.pv2-chart-last{position:absolute;width:8px;height:8px;border:2px solid var(--p-content-background, #fff);border-radius:50%;transform:translate(-50%,-50%)}.pv2-chart-x{display:flex;justify-content:space-between;color:var(--p-text-muted-color, #64748b);font-size:11px}.pv2-caption{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-mini{width:100%;font-size:12px}.pv2-mini th{padding:3px 6px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-weight:500}.pv2-mini td{padding:3px 6px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-ellipsis{display:inline-block;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.pv2-d-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;margin-top:16px;padding-top:10px;border-top:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;cursor:pointer}.pv2-btn:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}\n"], dependencies: [{ kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i9.EsFormInputComponent, selector: "form-input", inputs: ["minlength", "maxlength", "pattern", "Password", "Type"] }, { kind: "component", type: i9.EsFormSelectComponent, selector: "form-select", inputs: ["OptionsTemplate"] }, { kind: "component", type: i9.EsFormDateTimeComponent, selector: "form-datetime" }, { kind: "component", type: i9.EsFormCheckboxComponent, selector: "form-checkbox", inputs: ["SliderMode"] }, { kind: "directive", type: i10.Widget, selector: "[widget]" }, { kind: "pipe", type: i1.LocalizePipe, name: "localize" }, { kind: "pipe", type: ProfilerFormatPipe, name: "pv2fmt" }] }); }
1971
1973
  }
1972
1974
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: AdmProfilerV2Component, decorators: [{
1973
1975
  type: Component,
1974
- args: [{ selector: "profiler_v2", providers: [{ provide: LocalizationService, useClass: AdmProfilerV2Loc }], standalone: false, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Profiler del Server' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body pv2-body\">\r\n <!-- Barra dei comandi: quali dati caricare. Ogni cambio ricarica la vista e il dettaglio aperto -->\r\n <div class=\"pv2-toolbar\">\r\n <div class=\"pv2-cluster\">\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Sorgente' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"live\" (click)=\"setLive(true)\"><span class=\"pv2-live-dot\"></span>Live</button>\r\n <button type=\"button\" [class.pv2-on]=\"!live\" (click)=\"setLive(false)\">{{'Storico' | localize: lc}}</button>\r\n </div>\r\n </div>\r\n <div class=\"pv2-field pv2-field-wide pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instance\" (ngModelChange)=\"setInstance($event)\" name=\"instance\" [Source]=\"Instances\" [Placeholder]=\"'Istanze' | localize: lc\"></form-select>\r\n </div>\r\n </div>\r\n\r\n @if (!live) {\r\n <div class=\"pv2-cluster\">\r\n <div class=\"pv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterfrom\" (ngModelChange)=\"filterfrom = $event; datesChanged()\" name=\"filterfrom\" [Placeholder]=\"'Dal' | localize: lc\"></form-datetime>\r\n </div>\r\n <div class=\"pv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterto\" (ngModelChange)=\"filterto = $event; datesChanged()\" name=\"filterto\" [Placeholder]=\"'Al' | localize: lc\"></form-datetime>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Valori' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"!snapValues\" (click)=\"setSnapValues(false)\">{{\"Dall'avvio\" | localize: lc}}</button>\r\n <button type=\"button\" [class.pv2-on]=\"snapValues\" (click)=\"setSnapValues(true)\">{{\"Dall'ultimo snapshot\" | localize: lc}}</button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"pv2-cluster pv2-cluster-end\">\r\n <button type=\"button\" class=\"btn app-btn-search\" [disabled]=\"loading\" (click)=\"reloadAll()\" [title]=\"'Aggiorna' | localize: lc\">\r\n <i class=\"fa fa-refresh\" [class.fa-spin]=\"loading\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn app-btn-search\" (click)=\"downloadWorkloadReport()\" [title]=\"(workloadV2 ? 'Workload report' : 'Scarica il workload report') | localize: lc\">\r\n <i class=\"fa\" [class.fa-download]=\"!workloadV2\" [class.fa-file-text-o]=\"workloadV2\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Riga della finestra: sempre visibile sopra la vista -->\r\n <div class=\"pv2-window\">\r\n <span><strong>{{live ? 'Live' : ('Storico' | localize: lc)}}</strong> &middot; {{instanceLabel}}</span>\r\n @if (current?.snapFrom; as snapFrom) {\r\n @if (live) {\r\n <span>{{\"Delta dall'ultimo snapshot delle\" | localize: lc}} {{hhmm(snapFrom)}} ({{minutesAgo(snapFrom)}} {{'min fa' | localize: lc}})</span>\r\n } @else {\r\n <span>{{'Snapshot dalle' | localize: lc}} {{ddmmhhmm(snapFrom)}} {{'alle' | localize: lc}} {{ddmmhhmm(current?.snapTo)}}</span>\r\n }\r\n } @else if (current && !live) {\r\n <span class=\"pv2-warn-text\">{{'Nessuno snapshot termina nella finestra scelta' | localize: lc}}</span>\r\n }\r\n @if (view == 'tree' && tree?.idleNode) {\r\n <span>{{tree.numNodes | pv2fmt: 'int'}} {{\"nodi nell'albero\" | localize: lc}} &middot; {{tree.numReturnedNodes | pv2fmt: 'int'}} {{'nella risposta' | localize: lc}}</span>\r\n }\r\n @if (view == 'flat' && flat) {\r\n <span>{{flat.numItems | pv2fmt: 'int'}} {{'eventi distinti' | localize: lc}}</span>\r\n }\r\n @if (loading) {\r\n <span class=\"pv2-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n </div>\r\n\r\n <div class=\"pv2-main\">\r\n <!-- Vista: albero o eventi per nome -->\r\n <div class=\"pv2-panel pv2-view\">\r\n <div class=\"pv2-view-bar\">\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"view == 'tree'\" (click)=\"setView('tree')\"><i class=\"fa fa-sitemap\"></i> {{'Albero' | localize: lc}}</button>\r\n <button type=\"button\" [class.pv2-on]=\"view == 'flat'\" (click)=\"setView('flat')\"><i class=\"fa fa-list\"></i> {{'Per nome' | localize: lc}}</button>\r\n </div>\r\n\r\n @if (view == 'tree') {\r\n <div class=\"pv2-field pv2-field-search\" [title]=\"'Per esempio MRD_METERREADINGS, ENQUEUE, ProfilesMgr' | localize: lc\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"searchText\" (ngModelChange)=\"searchText = $event; searchChanged()\" name=\"search\" [Placeholder]=\"'Cerca nei nomi o per id' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"pv2-field pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"orderBy\" (ngModelChange)=\"setOrderBy($event)\" name=\"orderBy\" [Source]=\"TreeOrderOptions\" [Placeholder]=\"'Ordina per' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-group\" [class.pv2-disabled]=\"!!activeSearch\">\r\n <span class=\"pv2-group-label\">{{'Figli per nodo' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of ChildrenOptions; track o.id) {\r\n <button type=\"button\" [disabled]=\"!!activeSearch\" [class.pv2-on]=\"maxChildren == o.id\" (click)=\"setMaxChildren(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"pv2-group\" [class.pv2-disabled]=\"!!activeSearch\">\r\n <span class=\"pv2-group-label\">{{'Soglia' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of ThresholdOptions; track o.id) {\r\n <button type=\"button\" [disabled]=\"!!activeSearch\" [class.pv2-on]=\"minPercentage == o.id\" (click)=\"setMinPercentage(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"pv2-field pv2-field-search\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatSearch\" (ngModelChange)=\"flatSearch = $event; flatSearchChanged()\" name=\"flatSearch\" [Placeholder]=\"'Cerca nei nomi' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"pv2-field pv2-field-narrow pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatType\" (ngModelChange)=\"flatType = $event; flatChanged()\" name=\"flatType\" [Source]=\"FlatTypes\" [Placeholder]=\"'Tipo' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-field pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatOrderBy\" (ngModelChange)=\"flatOrderBy = $event; flatChanged()\" name=\"flatOrderBy\" [Source]=\"FlatOrderOptions\" [Placeholder]=\"'Ordina per' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Righe' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of FlatRows; track o.id) {\r\n <button type=\"button\" [class.pv2-on]=\"flatTop == o.id\" (click)=\"setFlatTop(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"pv2-toggle\">\r\n <form-checkbox [FormLayout]=\"false\" [SliderMode]=\"true\" [Validation]=\"false\" [ngModel]=\"flatIncludeIdle\" (ngModelChange)=\"flatIncludeIdle = $event; flatChanged()\" name=\"flatIncludeIdle\"></form-checkbox>\r\n <span class=\"pv2-pointer\" (click)=\"flatIncludeIdle = !flatIncludeIdle; flatChanged()\">{{'Anche gli eventi idle' | localize: lc}}</span>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (view == 'tree') {\r\n <!-- Percorso della radice: ogni antenato riporta l'albero a quel nodo -->\r\n @if (tree?.idleNode && tree?.rootPath?.length) {\r\n <nav class=\"pv2-crumbs\">\r\n @for (item of tree.rootPath; track item.nodeId) {\r\n <button type=\"button\" class=\"pv2-crumb\" [title]=\"item.nodeName\" (click)=\"setRoot(item.nodeId)\">{{item.nodeName}}</button>\r\n <span class=\"pv2-crumb-sep\">&rsaquo;</span>\r\n }\r\n <span class=\"pv2-crumb pv2-crumb-current\" [title]=\"tree.idleNode.nodeName\">{{tree.idleNode.nodeName}}</span>\r\n </nav>\r\n }\r\n\r\n @if (treeNotice) {\r\n <div class=\"pv2-alert pv2-alert-warn\">\r\n {{treeNotice}}\r\n <button type=\"button\" class=\"pv2-alert-close\" [title]=\"'Chiudi' | localize: lc\" (click)=\"treeNotice = null\">&times;</button>\r\n </div>\r\n }\r\n @if (activeSearch && tree) {\r\n @if (matchCount > 0) {\r\n <div class=\"pv2-alert\" [class.pv2-alert-warn]=\"tree.truncated\">\r\n {{matchCount | pv2fmt: 'int'}} {{'nodi trovati, con i loro antenati.' | localize: lc}}\r\n @if (tree.truncated) {\r\n <strong>{{'I nodi trovati sono pi\u00F9 di 1.000: sono mostrati i primi per l\\'ordinamento scelto.' | localize: lc}}</strong>\r\n }\r\n </div>\r\n } @else if (!treeLoading) {\r\n <div class=\"pv2-alert\">{{'Nessun nodo contiene' | localize: lc}} &laquo;{{activeSearch}}&raquo;.</div>\r\n }\r\n }\r\n @if (treeError) {\r\n <div class=\"pv2-alert pv2-alert-error\">{{treeError}}</div>\r\n }\r\n\r\n <div class=\"pv2-table-wrap\" tabindex=\"0\" (keydown)=\"treeKeydown($event)\">\r\n <table class=\"pv2-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"pv2-col-node\">{{'Nodo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Chiamate' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Tempo' | localize: lc}}</th>\r\n <th>{{snapMode ? '\u0394 ' : ''}}{{'% del padre' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? '\u0394 Proprio' : 'Tempo proprio') | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Medio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Picco' | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread ora' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of rows; track row.key) {\r\n @if (row.kind == 'node') {\r\n <tr [id]=\"'pv2-row-' + row.node.nodeId\" class=\"pv2-row\"\r\n [class.pv2-selected]=\"row.node.nodeId == selectedId\"\r\n [class.pv2-idle]=\"isIdle(row.node.eventTypeName, row.node.waitClassName)\"\r\n (click)=\"rowClicked(row.node)\" (dblclick)=\"toggle(row.node)\">\r\n <td class=\"pv2-col-node\">\r\n <div class=\"pv2-node\" [style.padding-left.px]=\"row.depth * 16\">\r\n @if (hasChildren(row.node)) {\r\n <button type=\"button\" class=\"pv2-caret\" tabindex=\"-1\" [attr.aria-expanded]=\"isExpanded(row.node)\" (click)=\"toggle(row.node, $event)\">\r\n <i class=\"fa\" [class.fa-caret-down]=\"isExpanded(row.node)\" [class.fa-caret-right]=\"!isExpanded(row.node)\"></i>\r\n </button>\r\n } @else {\r\n <span class=\"pv2-caret\"></span>\r\n }\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(row.node.eventTypeName, row.node.waitClassName)\"></span>{{typeLabel(row.node.eventTypeName, row.node.waitClassName)}}</span>\r\n <span class=\"pv2-name\" [title]=\"row.node.nodeName\">@if (row.node.searchMatch && activeSearch) {@for (part of nameParts(row.node.nodeName, activeSearch); track $index) {@if (part.hit) {<mark>{{part.text}}</mark>} @else {<span>{{part.text}}</span>}}} @else {<span>{{row.node.nodeName}}</span>}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{calls(row.node) | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{time(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-perc\" [title]=\"(parentPerc(row.node) | pv2fmt: 'pct') + ' ' + ('del padre' | localize: lc) + ' \u00B7 ' + (firstLevelPerc(row.node) | pv2fmt: 'pct') + ' ' + ('del nodo di primo livello' | localize: lc)\">\r\n <div class=\"pv2-perc-cell\">\r\n <div class=\"pv2-bar\"><div [style.width.%]=\"parentPerc(row.node)\" [style.background]=\"typeColor(row.node.eventTypeName, row.node.waitClassName)\"></div></div>\r\n <span>{{parentPerc(row.node) | pv2fmt: 'pct'}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{self(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{avg(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{peak(row.node) | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num pv2-threads\">\r\n @if (isLongRunning(row.node.eventTypeName, row.node.waitClassName, row.node.activeMaxTime)) {\r\n <span class=\"pv2-long\" [title]=\"('Esecuzione in corso da' | localize: lc) + ' ' + duration(row.node.activeMaxTime) + ': ' + ('forse bloccata' | localize: lc)\"><i class=\"fa fa-clock-o\"></i> {{duration(row.node.activeMaxTime)}}</span>\r\n }\r\n @if (row.node.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{row.node.activeThreads}}</span>\r\n } @else {\r\n <span class=\"pv2-muted\">{{row.node.activeThreads ?? '\u2014'}}</span>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n } @else if (row.kind == 'loading') {\r\n <tr class=\"pv2-service\">\r\n <td [attr.colspan]=\"live ? 8 : 7\">\r\n <div [style.padding-left.px]=\"row.depth * 16 + 24\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento dei figli\u2026' | localize: lc}}</div>\r\n </td>\r\n </tr>\r\n } @else {\r\n <tr class=\"pv2-service\">\r\n <td [attr.colspan]=\"live ? 8 : 7\">\r\n <div [style.padding-left.px]=\"row.depth * 16 + 24\">\r\n {{row.node.omittedChildren | pv2fmt: 'int'}} {{'figli non mostrati' | localize: lc}} &middot; {{omittedTime(row.node) | pv2fmt: 'dur'}}\r\n @if (!snapMode) {\r\n &middot; {{row.node.omittedCalls | pv2fmt: 'int'}} {{'chiamate' | localize: lc}}\r\n }\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"showAll(row.node, $event)\">{{'Mostra tutti' | localize: lc}}</button>\r\n </div>\r\n </td>\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n </table>\r\n @if (rows.length == 0 && !treeError) {\r\n <div class=\"pv2-empty\">\r\n @if (!tree) {\r\n {{'Caricamento\u2026' | localize: lc}}\r\n } @else if (!tree.snapFrom && !live) {\r\n {{'Nessuno snapshot termina nella finestra scelta: allargala o spostala indietro.' | localize: lc}}\r\n } @else {\r\n {{\"Il nodo non c'\u00E8 nelle istanze scelte.\" | localize: lc}}\r\n }\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n @if (flatError) {\r\n <div class=\"pv2-alert pv2-alert-error\">{{flatError}}</div>\r\n }\r\n <div class=\"pv2-table-wrap\">\r\n <table class=\"pv2-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"pv2-col-node\">{{'Evento' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Percorsi' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Chiamate' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? '\u0394 Proprio' : 'Tempo proprio') | localize: lc}}</th>\r\n <th>{{snapMode ? '\u0394 ' : ''}}{{'% proprio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Tempo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Medio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? \"Picco dall'avvio\" : 'Picco') | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (item of flat?.items ?? []; track flatKey(item)) {\r\n <tr class=\"pv2-row\" [class.pv2-idle]=\"isIdle(item.eventTypeName, item.waitClassName)\" [class.pv2-selected]=\"openFlat.has(flatKey(item))\" (click)=\"toggleFlat(item)\">\r\n <td class=\"pv2-col-node\">\r\n <div class=\"pv2-node\">\r\n <span class=\"pv2-caret\"><i class=\"fa\" [class.fa-caret-down]=\"openFlat.has(flatKey(item))\" [class.fa-caret-right]=\"!openFlat.has(flatKey(item))\"></i></span>\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></span>{{typeLabel(item.eventTypeName, item.waitClassName)}}</span>\r\n <span class=\"pv2-name\" [title]=\"item.nodeName\">@for (part of nameParts(item.nodeName, (flatSearch ?? '').trim()); track $index) {@if (part.hit) {<mark>{{part.text}}</mark>} @else {<span>{{part.text}}</span>}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{item.numPaths | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{flatCalls(item) | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{flatSelf(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-perc\">\r\n <div class=\"pv2-perc-cell\">\r\n <div class=\"pv2-bar\"><div [style.width.%]=\"flatPerc(item)\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></div></div>\r\n <span>{{flatPerc(item) | pv2fmt: 'pct'}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{flatTime(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{flatAvg(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{item.peakTime | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num pv2-threads\">\r\n @if (item.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{item.activeThreads}}</span>\r\n } @else {\r\n <span class=\"pv2-muted\">{{item.activeThreads ?? '\u2014'}}</span>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n @if (openFlat.has(flatKey(item))) {\r\n <tr class=\"pv2-sub\">\r\n <td [attr.colspan]=\"live ? 9 : 8\">\r\n <div class=\"pv2-sub-title\">{{'Nodi con pi\u00F9 tempo' | localize: lc}}</div>\r\n @for (id of item.nodeIds ?? []; track id) {\r\n <div class=\"pv2-sub-item\">\r\n <code>{{id}}</code>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"showDetail(id, $event)\">{{'Dettaglio' | localize: lc}}</button>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"openInTree(id, $event)\">{{\"Apri nell'albero\" | localize: lc}}</button>\r\n </div>\r\n }\r\n @if (item.numPaths > (item.nodeIds?.length ?? 0)) {\r\n <div class=\"pv2-muted\">+{{item.numPaths - (item.nodeIds?.length ?? 0) | pv2fmt: 'int'}} {{'altri' | localize: lc}}</div>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n </table>\r\n @if (!flatError && (!flat || !flat.items?.length)) {\r\n <div class=\"pv2-empty\">{{(flat ? 'Nessun evento con questi filtri.' : 'Caricamento\u2026') | localize: lc}}</div>\r\n }\r\n </div>\r\n @if (flat?.items?.length) {\r\n <div class=\"pv2-footer\">\r\n {{flat.numItems | pv2fmt: 'int'}} {{'eventi distinti' | localize: lc}}@if (flat.numItems > flat.items.length) {, {{'mostrati i primi' | localize: lc}} {{flat.items.length | pv2fmt: 'int'}}}.\r\n {{'La percentuale \u00E8 sul tempo proprio di tutti gli eventi non idle.' | localize: lc}}\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Dettaglio del nodo selezionato, lo stesso per le due viste -->\r\n <aside class=\"pv2-panel pv2-detail\" [class.pv2-stale]=\"detailStale\">\r\n @if (!selectedId) {\r\n <div class=\"pv2-placeholder\">{{'Seleziona un nodo per vederne il dettaglio.' | localize: lc}}</div>\r\n } @else if (detailMissing && !detailLoading) {\r\n <div class=\"pv2-placeholder\">{{\"Il nodo non c'\u00E8 nelle istanze o nella finestra scelte.\" | localize: lc}}</div>\r\n } @else if (detailError && !detailLoading) {\r\n <div class=\"pv2-placeholder pv2-error-text\">{{detailError}}</div>\r\n } @else if (!detail) {\r\n <div class=\"pv2-placeholder\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</div>\r\n } @else {\r\n <div class=\"pv2-d-head\">\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(detail.eventTypeName, detail.waitClassName)\"></span>{{typeLabel(detail.eventTypeName, detail.waitClassName)}}</span>\r\n @if (detailLoading) {\r\n <i class=\"fa fa-spinner fa-spin pv2-muted\"></i>\r\n }\r\n </div>\r\n <div class=\"pv2-fullname\">{{detail.nodeName}}</div>\r\n <div class=\"pv2-id\">\r\n Id <code #idText>{{detail.nodeId}}</code>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"copyId(idText)\">{{(copied ? 'Copiato' : 'Copia') | localize: lc}}</button>\r\n </div>\r\n\r\n <div class=\"pv2-d-title\">{{'Percorso' | localize: lc}}</div>\r\n <div class=\"pv2-path\">\r\n @for (item of detail.fullWaitStack ?? []; track item.nodeId; let i = $index) {\r\n <button type=\"button\" class=\"pv2-path-item\" [style.padding-left.px]=\"i * 10\" [title]=\"item.nodeName\" (click)=\"select(item.nodeId)\">\r\n <span class=\"pv2-dot\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></span>{{item.nodeName}}\r\n </button>\r\n }\r\n <div class=\"pv2-path-item pv2-path-current\" [style.padding-left.px]=\"(detail.fullWaitStack?.length ?? 0) * 10\" [title]=\"detail.nodeName\">\r\n <span class=\"pv2-dot\" [style.background]=\"typeColor(detail.eventTypeName, detail.waitClassName)\"></span>{{detail.nodeName}}\r\n </div>\r\n </div>\r\n\r\n <div class=\"pv2-d-title\">{{(live ? \"Dall'avvio\" : 'Nella finestra') | localize: lc}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Esecuzioni' | localize: lc}}</dt><dd>{{detail.executions | pv2fmt: 'int'}}</dd>\r\n <dt>{{'Tempo totale' | localize: lc}}</dt><dd>{{detail.elapsedTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Tempo proprio' | localize: lc}}</dt><dd>{{detail.elapsedTimeLessChildren | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Medio' | localize: lc}}</dt><dd>{{detail.avgTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Picco' | localize: lc}}</dt><dd>{{detail.peakTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Minimo' | localize: lc}}</dt><dd>{{detail.minTime ? (detail.minTime | pv2fmt: 'dur') : '\u2014'}}</dd>\r\n </dl>\r\n\r\n @if (live) {\r\n <div class=\"pv2-d-title\">{{\"Dall'ultimo snapshot\" | localize: lc}}, {{hhmm(detail.snapFrom)}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Esecuzioni' | localize: lc}}</dt><dd>{{detail.snapDeltaExecutions | pv2fmt: 'int'}}</dd>\r\n <dt>{{'Tempo totale' | localize: lc}}</dt><dd>{{detail.snapDeltaElapsedTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Tempo proprio' | localize: lc}}</dt><dd>{{detail.snapDeltaElapsedTimeLessChildren | pv2fmt: 'dur'}}</dd>\r\n </dl>\r\n\r\n <div class=\"pv2-d-title\">{{'Adesso' | localize: lc}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Thread dentro' | localize: lc}}</dt>\r\n <dd>\r\n @if (detail.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{detail.activeThreads}}</span>\r\n } @else {\r\n {{detail.activeThreads ?? '\u2014'}}\r\n }\r\n </dd>\r\n <dt>{{'Esecuzione pi\u00F9 lunga' | localize: lc}}</dt>\r\n <dd>\r\n @if (detail.activeThreads > 0) {\r\n {{detail.activeMaxTime | pv2fmt: 'dur'}}\r\n @if (isLongRunning(detail.eventTypeName, detail.waitClassName, detail.activeMaxTime)) {\r\n <span class=\"pv2-long\"><i class=\"fa fa-clock-o\"></i> {{'forse bloccata' | localize: lc}}</span>\r\n }\r\n } @else {\r\n \u2014\r\n }\r\n </dd>\r\n <dt>{{'Ultima uscita' | localize: lc}}</dt><dd>{{relative(detail.lastExitTime)}}</dd>\r\n </dl>\r\n }\r\n\r\n @if (typeParts.length > 0) {\r\n <div class=\"pv2-d-title\">{{'Tempo proprio del sottoalbero per tipo' | localize: lc}}</div>\r\n <div class=\"pv2-stack\">\r\n @for (part of typeParts; track part.type) {\r\n <div [style.width.%]=\"part.percentage\" [style.background]=\"part.color\" [title]=\"part.label + ' ' + (part.percentage | pv2fmt: 'pct')\"></div>\r\n }\r\n </div>\r\n <div class=\"pv2-legend\">\r\n @for (part of typeParts; track part.type) {\r\n <span class=\"pv2-legend-item\"><span class=\"pv2-swatch\" [style.background]=\"part.color\"></span>{{part.label}} <strong>{{part.percentage | pv2fmt: 'pct'}}</strong></span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pv2-d-title\">{{'Sessioni attive sul nodo e sui discendenti' | localize: lc}}</div>\r\n @if (chart) {\r\n <div class=\"pv2-chart\">\r\n <div class=\"pv2-chart-y\">\r\n <span>{{axisValue(chart.max)}}</span>\r\n <span>{{axisValue(chart.max / 2)}}</span>\r\n <span>0</span>\r\n </div>\r\n <div class=\"pv2-chart-plot\">\r\n <svg viewBox=\"0 0 100 100\" preserveAspectRatio=\"none\" aria-hidden=\"true\">\r\n <line x1=\"0\" y1=\"50\" x2=\"100\" y2=\"50\" class=\"pv2-chart-grid\" vector-effect=\"non-scaling-stroke\" />\r\n <path [attr.d]=\"chart.area\" [attr.fill]=\"chart.color\" fill-opacity=\"0.25\" />\r\n <path [attr.d]=\"chart.line\" [attr.stroke]=\"chart.color\" fill=\"none\" stroke-width=\"1.5\" vector-effect=\"non-scaling-stroke\" />\r\n </svg>\r\n <span class=\"pv2-chart-last\" [style.left.%]=\"chart.lastX\" [style.top.%]=\"chart.lastY\" [style.background]=\"chart.color\"></span>\r\n </div>\r\n <span></span>\r\n <div class=\"pv2-chart-x\">\r\n <span>{{chart.start}}</span>\r\n <span>{{chart.middle}}</span>\r\n <span>{{chart.end}}</span>\r\n </div>\r\n </div>\r\n <div class=\"pv2-caption\">\r\n {{'Media' | localize: lc}} {{axisValue(chart.average)}} &middot; {{'picco' | localize: lc}} {{axisValue(chart.peak)}} {{'sessioni' | localize: lc}}.\r\n {{chart.points | pv2fmt: 'int'}} {{\"punti dell'API\" | localize: lc}},\r\n @if (chart.interval == 1) {\r\n {{'uno al secondo' | localize: lc}},\r\n } @else {\r\n {{'uno ogni' | localize: lc}} {{chart.interval}} s,\r\n }\r\n {{'raggruppati a' | localize: lc}} {{chart.group}} s\r\n </div>\r\n } @else {\r\n <div class=\"pv2-muted pv2-small\">{{'Nessun campione in memoria per questa finestra: il grafico copre solo le ultime due ore circa.' | localize: lc}}</div>\r\n }\r\n\r\n @if (detail.instances?.length) {\r\n <div class=\"pv2-d-title\">{{'Per istanza' | localize: lc}}</div>\r\n <table class=\"pv2-mini\">\r\n <thead>\r\n <tr>\r\n <th>{{'Istanza' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Esecuzioni' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Tempo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Proprio' | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (inst of detail.instances; track inst.instanceId) {\r\n <tr>\r\n <td><span class=\"pv2-ellipsis\" [title]=\"inst.instanceId\">{{inst.instanceId}}</span></td>\r\n <td class=\"pv2-num\">{{inst.executions | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{inst.elapsedTime | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{inst.elapsedTimeLessChildren | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num\">{{inst.activeThreads ?? '\u2014'}}</td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <div class=\"pv2-d-foot\">\r\n <span class=\"pv2-muted\">{{detail.numChildren | pv2fmt: 'int'}} {{'figli diretti' | localize: lc}} &middot; {{detail.numDescendants | pv2fmt: 'int'}} {{'discendenti' | localize: lc}}</span>\r\n <button type=\"button\" class=\"pv2-btn\" (click)=\"setRoot(detail.nodeId)\"><i class=\"fa fa-sitemap\"></i> {{'Apri come radice' | localize: lc}}</button>\r\n </div>\r\n }\r\n </aside>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";:host{display:block}:host ::ng-deep .pv2-noclear .p-select-clear-icon{display:none}.pv2-body{container-type:inline-size}.pv2-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 22px;padding-top:6px}.pv2-cluster{display:flex;flex-wrap:nowrap;align-items:center;gap:10px}.pv2-cluster-end{margin-left:auto}.pv2-field{width:190px}.pv2-field-wide{width:290px}.pv2-field-narrow{width:140px}.pv2-field-search{flex:1 1 220px;min-width:200px;max-width:340px}.pv2-toggle{display:flex;align-items:center;gap:8px;height:39px;white-space:nowrap}.pv2-pointer{cursor:pointer}.pv2-group{position:relative;display:inline-flex}.pv2-group.pv2-disabled{opacity:.5}.pv2-group-label{position:absolute;top:-8px;left:8px;z-index:1;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.pv2-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.pv2-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 12px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.pv2-seg button:first-child{border-left:0}.pv2-seg button:hover:not(.pv2-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.pv2-seg button:disabled{cursor:default}.pv2-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.pv2-seg button.pv2-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.pv2-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.pv2-window{display:flex;flex-wrap:wrap;align-items:center;row-gap:4px;margin-top:12px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.pv2-window>span+span:before{content:\"\\b7\";margin:0 10px;color:var(--p-text-muted-color, #64748b)}.pv2-warn-text{color:#92400e}.pv2-main{display:grid;grid-template-columns:minmax(0,1fr) 420px;gap:14px;align-items:start;margin-top:14px}@container (max-width: 1150px){.pv2-main{grid-template-columns:minmax(0,1fr)}.pv2-detail{position:static;max-height:none}}.pv2-panel{padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.pv2-view-bar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 10px;padding-top:6px;margin-bottom:10px}.pv2-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;margin-bottom:8px;font-size:12px}.pv2-crumb{max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:2px 6px;border:0;border-radius:4px;background:transparent;color:var(--p-primary-color, #6366f1);cursor:pointer}.pv2-crumb:hover{background:var(--p-highlight-background, #eef2ff)}.pv2-crumb-current{color:var(--p-text-color, #334155);font-weight:500;cursor:default}.pv2-crumb-current:hover{background:transparent}.pv2-crumb-sep{color:var(--p-text-muted-color, #64748b)}.pv2-alert{position:relative;margin-bottom:8px;padding:6px 30px 6px 10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);font-size:13px}.pv2-alert.pv2-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.pv2-alert.pv2-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.pv2-alert-close{position:absolute;top:3px;right:6px;border:0;background:transparent;color:inherit;font-size:16px;cursor:pointer}.pv2-table-wrap{max-height:68vh;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.pv2-table-wrap:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:1px}.pv2-table{width:100%;min-width:860px;border-collapse:separate;border-spacing:0;font-size:13px;color:var(--p-text-color, #334155)}.pv2-table th{position:sticky;top:0;z-index:1;padding:7px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-size:12px;font-weight:500;white-space:nowrap;text-align:left}.pv2-table td{padding:4px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap;vertical-align:middle}.pv2-col-node{width:100%;max-width:0}.pv2-num{text-align:right!important;font-variant-numeric:tabular-nums}.pv2-row{cursor:pointer}.pv2-row:hover td{background:var(--p-content-hover-background, #f8fafc)}.pv2-row.pv2-selected td{background:var(--p-highlight-background, #eef2ff)}.pv2-row.pv2-idle td{color:var(--p-text-muted-color, #64748b)}.pv2-row.pv2-idle td .pv2-name{opacity:.75}.pv2-node{display:flex;align-items:center;gap:6px;min-width:0}.pv2-caret{flex:none;width:18px;height:20px;padding:0;border:0;background:transparent;color:var(--p-text-muted-color, #64748b);text-align:center;cursor:pointer}.pv2-type{flex:none;display:inline-flex;align-items:center;gap:5px;padding:0 6px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px;white-space:nowrap}.pv2-dot{flex:none;display:inline-block;width:8px;height:8px;border-radius:50%}.pv2-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pv2-name mark{padding:0 1px;border-radius:2px;background:#fde68a;color:#1f2937}.pv2-perc{width:1%}.pv2-perc-cell{display:flex;align-items:center;gap:8px}.pv2-bar{flex:none;width:64px;height:7px;border-radius:2px;overflow:hidden;background:var(--p-content-hover-background, #f8fafc);box-shadow:inset 0 0 0 1px var(--p-content-border-color, #e2e8f0)}.pv2-bar>div{height:100%}.pv2-threads>*+*{margin-left:8px}.pv2-active{display:inline-flex;align-items:center;gap:5px;font-weight:500}.pv2-active-dot{width:7px;height:7px;border-radius:50%;background:#16a34a;box-shadow:0 0 0 3px #16a34a2e}.pv2-long{display:inline-flex;align-items:center;gap:4px;padding:0 6px;border:1px solid #fcd34d;border-radius:10px;background:#fffbeb;color:#92400e;font-size:11px;line-height:18px;white-space:nowrap}.pv2-service td{padding:5px 10px;color:var(--p-text-muted-color, #64748b);font-size:12px;background:var(--p-content-background, #fff)}.pv2-sub td{padding:8px 10px 10px 34px;background:var(--p-content-hover-background, #f8fafc);white-space:normal}.pv2-sub-title{margin-bottom:4px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-sub-item{display:flex;align-items:center;gap:10px;padding:2px 0}.pv2-sub-item code{font-size:12px}.pv2-link{margin-left:6px;padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.pv2-link:hover{text-decoration:underline}.pv2-empty{padding:28px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.pv2-footer{margin-top:8px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-muted{color:var(--p-text-muted-color, #64748b)}.pv2-small{font-size:12px}.pv2-detail{position:sticky;top:10px;max-height:calc(100vh - 20px);overflow:auto;font-size:13px;color:var(--p-text-color, #334155);transition:opacity .15s}.pv2-detail.pv2-stale{opacity:.55}.pv2-placeholder{padding:36px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.pv2-error-text{color:#dc2626}.pv2-d-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.pv2-fullname{max-height:140px;overflow:auto;padding:8px 10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);font-family:ui-monospace,Cascadia Mono,Consolas,monospace;font-size:12px;white-space:pre-wrap;word-break:break-word}.pv2-id{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-id code{font-size:12px}.pv2-d-title{margin:16px 0 6px;padding-top:10px;border-top:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.pv2-path{display:flex;flex-direction:column}.pv2-path-item{display:flex;align-items:center;gap:6px;max-width:100%;padding:2px 0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.pv2-path-item:hover{text-decoration:underline}.pv2-path-current{color:var(--p-text-color, #334155);font-weight:600;cursor:default}.pv2-path-current:hover{text-decoration:none}.pv2-kv{display:grid;grid-template-columns:auto 1fr;gap:3px 14px;margin:0}.pv2-kv dt{color:var(--p-text-muted-color, #64748b);font-weight:400}.pv2-kv dd{margin:0;text-align:right;font-variant-numeric:tabular-nums}.pv2-stack{display:flex;height:12px;border-radius:3px;overflow:hidden;background:var(--p-content-hover-background, #f8fafc)}.pv2-legend{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:6px;font-size:12px}.pv2-legend-item{display:inline-flex;align-items:center;gap:5px}.pv2-swatch{width:10px;height:10px;border-radius:2px}.pv2-chart{display:grid;grid-template-columns:auto 1fr;gap:2px 6px}.pv2-chart-y{display:flex;flex-direction:column;justify-content:space-between;height:110px;color:var(--p-text-muted-color, #64748b);font-size:11px;text-align:right;line-height:1}.pv2-chart-plot{position:relative;height:110px;border-left:1px solid var(--p-content-border-color, #e2e8f0);border-bottom:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-chart-plot svg{display:block;width:100%;height:100%}.pv2-chart-grid{stroke:var(--p-content-border-color, #e2e8f0);stroke-dasharray:3 3}.pv2-chart-last{position:absolute;width:8px;height:8px;border:2px solid var(--p-content-background, #fff);border-radius:50%;transform:translate(-50%,-50%)}.pv2-chart-x{display:flex;justify-content:space-between;color:var(--p-text-muted-color, #64748b);font-size:11px}.pv2-caption{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-mini{width:100%;font-size:12px}.pv2-mini th{padding:3px 6px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-weight:500}.pv2-mini td{padding:3px 6px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-ellipsis{display:inline-block;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.pv2-d-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;margin-top:16px;padding-top:10px;border-top:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;cursor:pointer}.pv2-btn:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}\n"] }]
1976
+ args: [{ selector: "profiler_v2", providers: [{ provide: LocalizationService, useClass: AdmProfilerV2Loc }], standalone: false, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Profiler del Server' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body pv2-body\">\r\n <!-- Barra dei comandi: quali dati caricare. Ogni cambio ricarica la vista e il dettaglio aperto -->\r\n <div class=\"pv2-toolbar\">\r\n <div class=\"pv2-cluster\">\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Sorgente' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"live\" (click)=\"setLive(true)\"><span class=\"pv2-live-dot\"></span>Live</button>\r\n <button type=\"button\" [class.pv2-on]=\"!live\" (click)=\"setLive(false)\">{{'Storico' | localize: lc}}</button>\r\n </div>\r\n </div>\r\n <div class=\"pv2-field pv2-field-wide pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instance\" (ngModelChange)=\"setInstance($event)\" name=\"instance\" [Source]=\"Instances\" [Placeholder]=\"'Istanze' | localize: lc\"></form-select>\r\n </div>\r\n </div>\r\n\r\n @if (!live) {\r\n <div class=\"pv2-cluster\">\r\n <div class=\"pv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterfrom\" (ngModelChange)=\"filterfrom = $event; datesChanged()\" name=\"filterfrom\" [Placeholder]=\"'Dal' | localize: lc\"></form-datetime>\r\n </div>\r\n <div class=\"pv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterto\" (ngModelChange)=\"filterto = $event; datesChanged()\" name=\"filterto\" [Placeholder]=\"'Al' | localize: lc\"></form-datetime>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Valori' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"!snapValues\" (click)=\"setSnapValues(false)\">{{\"Dall'avvio\" | localize: lc}}</button>\r\n <button type=\"button\" [class.pv2-on]=\"snapValues\" (click)=\"setSnapValues(true)\">{{\"Dall'ultimo snapshot\" | localize: lc}}</button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"pv2-cluster pv2-cluster-end\">\r\n <button type=\"button\" class=\"btn app-btn-search\" [disabled]=\"loading\" (click)=\"reloadAll()\" [title]=\"'Aggiorna' | localize: lc\">\r\n <i class=\"fa fa-refresh\" [class.fa-spin]=\"loading\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn app-btn-search\" (click)=\"downloadWorkloadReport()\" [title]=\"(workloadV2 ? 'Workload report' : 'Scarica il workload report') | localize: lc\">\r\n <i class=\"fa\" [class.fa-download]=\"!workloadV2\" [class.fa-file-text]=\"workloadV2\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Riga della finestra: sempre visibile sopra la vista -->\r\n <div class=\"pv2-window\">\r\n <span><strong>{{live ? 'Live' : ('Storico' | localize: lc)}}</strong> &middot; {{instanceLabel}}</span>\r\n @if (current?.snapFrom; as snapFrom) {\r\n @if (live) {\r\n <span>{{\"Delta dall'ultimo snapshot delle\" | localize: lc}} {{hhmm(snapFrom)}} ({{minutesAgo(snapFrom)}} {{'min fa' | localize: lc}})</span>\r\n } @else {\r\n <span>{{'Snapshot dalle' | localize: lc}} {{ddmmhhmm(snapFrom)}} {{'alle' | localize: lc}} {{ddmmhhmm(current?.snapTo)}}</span>\r\n }\r\n } @else if (current && !live) {\r\n <span class=\"pv2-warn-text\">{{'Nessuno snapshot termina nella finestra scelta' | localize: lc}}</span>\r\n }\r\n @if (view == 'tree' && tree?.idleNode) {\r\n <span>{{tree.numNodes | pv2fmt: 'int'}} {{\"nodi nell'albero\" | localize: lc}} &middot; {{tree.numReturnedNodes | pv2fmt: 'int'}} {{'nella risposta' | localize: lc}}</span>\r\n }\r\n @if (view == 'flat' && flat) {\r\n <span>{{flat.numItems | pv2fmt: 'int'}} {{'eventi distinti' | localize: lc}}</span>\r\n }\r\n @if (loading) {\r\n <span class=\"pv2-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n </div>\r\n\r\n <div class=\"pv2-main\">\r\n <!-- Vista: albero o eventi per nome -->\r\n <div class=\"pv2-panel pv2-view\">\r\n <div class=\"pv2-view-bar\">\r\n <div class=\"pv2-seg\">\r\n <button type=\"button\" [class.pv2-on]=\"view == 'tree'\" (click)=\"setView('tree')\"><i class=\"fa fa-sitemap\"></i> {{'Albero' | localize: lc}}</button>\r\n <button type=\"button\" [class.pv2-on]=\"view == 'flat'\" (click)=\"setView('flat')\"><i class=\"fa fa-list\"></i> {{'Per nome' | localize: lc}}</button>\r\n </div>\r\n\r\n @if (view == 'tree') {\r\n <div class=\"pv2-field pv2-field-search\" [title]=\"'Per esempio MRD_METERREADINGS, ENQUEUE, ProfilesMgr' | localize: lc\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"searchText\" (ngModelChange)=\"searchText = $event; searchChanged()\" name=\"search\" [Placeholder]=\"'Cerca nei nomi o per id' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"pv2-field pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"orderBy\" (ngModelChange)=\"setOrderBy($event)\" name=\"orderBy\" [Source]=\"TreeOrderOptions\" [Placeholder]=\"'Ordina per' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-group\" [class.pv2-disabled]=\"!!activeSearch\">\r\n <span class=\"pv2-group-label\">{{'Figli per nodo' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of ChildrenOptions; track o.id) {\r\n <button type=\"button\" [disabled]=\"!!activeSearch\" [class.pv2-on]=\"maxChildren == o.id\" (click)=\"setMaxChildren(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"pv2-group\" [class.pv2-disabled]=\"!!activeSearch\">\r\n <span class=\"pv2-group-label\">{{'Soglia' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of ThresholdOptions; track o.id) {\r\n <button type=\"button\" [disabled]=\"!!activeSearch\" [class.pv2-on]=\"minPercentage == o.id\" (click)=\"setMinPercentage(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"pv2-field pv2-field-search\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatSearch\" (ngModelChange)=\"flatSearch = $event; flatSearchChanged()\" name=\"flatSearch\" [Placeholder]=\"'Cerca nei nomi' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"pv2-field pv2-field-narrow pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatType\" (ngModelChange)=\"flatType = $event; flatChanged()\" name=\"flatType\" [Source]=\"FlatTypes\" [Placeholder]=\"'Tipo' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-field pv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"flatOrderBy\" (ngModelChange)=\"flatOrderBy = $event; flatChanged()\" name=\"flatOrderBy\" [Source]=\"FlatOrderOptions\" [Placeholder]=\"'Ordina per' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"pv2-group\">\r\n <span class=\"pv2-group-label\">{{'Righe' | localize: lc}}</span>\r\n <div class=\"pv2-seg\">\r\n @for (o of FlatRows; track o.id) {\r\n <button type=\"button\" [class.pv2-on]=\"flatTop == o.id\" (click)=\"setFlatTop(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"pv2-toggle\">\r\n <form-checkbox [FormLayout]=\"false\" [SliderMode]=\"true\" [Validation]=\"false\" [ngModel]=\"flatIncludeIdle\" (ngModelChange)=\"flatIncludeIdle = $event; flatChanged()\" name=\"flatIncludeIdle\"></form-checkbox>\r\n <span class=\"pv2-pointer\" (click)=\"flatIncludeIdle = !flatIncludeIdle; flatChanged()\">{{'Anche gli eventi idle' | localize: lc}}</span>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (view == 'tree') {\r\n <!-- Percorso della radice: ogni antenato riporta l'albero a quel nodo -->\r\n @if (tree?.idleNode && tree?.rootPath?.length) {\r\n <nav class=\"pv2-crumbs\">\r\n @for (item of tree.rootPath; track item.nodeId) {\r\n <button type=\"button\" class=\"pv2-crumb\" [title]=\"item.nodeName\" (click)=\"setRoot(item.nodeId)\">{{item.nodeName}}</button>\r\n <span class=\"pv2-crumb-sep\">&rsaquo;</span>\r\n }\r\n <span class=\"pv2-crumb pv2-crumb-current\" [title]=\"tree.idleNode.nodeName\">{{tree.idleNode.nodeName}}</span>\r\n </nav>\r\n }\r\n\r\n @if (treeNotice) {\r\n <div class=\"pv2-alert pv2-alert-warn\">\r\n {{treeNotice}}\r\n <button type=\"button\" class=\"pv2-alert-close\" [title]=\"'Chiudi' | localize: lc\" (click)=\"treeNotice = null\">&times;</button>\r\n </div>\r\n }\r\n @if (activeSearch && tree) {\r\n @if (matchCount > 0) {\r\n <div class=\"pv2-alert\" [class.pv2-alert-warn]=\"tree.truncated\">\r\n {{matchCount | pv2fmt: 'int'}} {{'nodi trovati, con i loro antenati.' | localize: lc}}\r\n @if (tree.truncated) {\r\n <strong>{{'I nodi trovati sono pi\u00F9 di 1.000: sono mostrati i primi per l\\'ordinamento scelto.' | localize: lc}}</strong>\r\n }\r\n </div>\r\n } @else if (!treeLoading) {\r\n <div class=\"pv2-alert\">{{'Nessun nodo contiene' | localize: lc}} &laquo;{{activeSearch}}&raquo;.</div>\r\n }\r\n }\r\n @if (treeError) {\r\n <div class=\"pv2-alert pv2-alert-error\">{{treeError}}</div>\r\n }\r\n\r\n <div class=\"pv2-table-wrap\" tabindex=\"0\" (keydown)=\"treeKeydown($event)\">\r\n <table class=\"pv2-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"pv2-col-node\">{{'Nodo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Chiamate' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Tempo' | localize: lc}}</th>\r\n <th>{{snapMode ? '\u0394 ' : ''}}{{'% del padre' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? '\u0394 Proprio' : 'Tempo proprio') | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Medio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Picco' | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread ora' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of rows; track row.key) {\r\n @if (row.kind == 'node') {\r\n <tr [id]=\"'pv2-row-' + row.node.nodeId\" class=\"pv2-row\"\r\n [class.pv2-selected]=\"row.node.nodeId == selectedId\"\r\n [class.pv2-idle]=\"isIdle(row.node.eventTypeName, row.node.waitClassName)\"\r\n (click)=\"rowClicked(row.node)\" (dblclick)=\"toggle(row.node)\">\r\n <td class=\"pv2-col-node\">\r\n <div class=\"pv2-node\" [style.padding-left.px]=\"row.depth * 16\">\r\n @if (hasChildren(row.node)) {\r\n <button type=\"button\" class=\"pv2-caret\" tabindex=\"-1\" [attr.aria-expanded]=\"isExpanded(row.node)\" (click)=\"toggle(row.node, $event)\">\r\n <i class=\"fa\" [class.fa-caret-down]=\"isExpanded(row.node)\" [class.fa-caret-right]=\"!isExpanded(row.node)\"></i>\r\n </button>\r\n } @else {\r\n <span class=\"pv2-caret\"></span>\r\n }\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(row.node.eventTypeName, row.node.waitClassName)\"></span>{{typeLabel(row.node.eventTypeName, row.node.waitClassName)}}</span>\r\n <span class=\"pv2-name\" [title]=\"row.node.nodeName\">@if (row.node.searchMatch && activeSearch) {@for (part of nameParts(row.node.nodeName, activeSearch); track $index) {@if (part.hit) {<mark>{{part.text}}</mark>} @else {<span>{{part.text}}</span>}}} @else {<span>{{row.node.nodeName}}</span>}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{calls(row.node) | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{time(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-perc\" [title]=\"(parentPerc(row.node) | pv2fmt: 'pct') + ' ' + ('del padre' | localize: lc) + ' \u00B7 ' + (firstLevelPerc(row.node) | pv2fmt: 'pct') + ' ' + ('del nodo di primo livello' | localize: lc)\">\r\n <div class=\"pv2-perc-cell\">\r\n <div class=\"pv2-bar\"><div [style.width.%]=\"parentPerc(row.node)\" [style.background]=\"typeColor(row.node.eventTypeName, row.node.waitClassName)\"></div></div>\r\n <span>{{parentPerc(row.node) | pv2fmt: 'pct'}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{self(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{avg(row.node) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{peak(row.node) | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num pv2-threads\">\r\n @if (isLongRunning(row.node.eventTypeName, row.node.waitClassName, row.node.activeMaxTime)) {\r\n <span class=\"pv2-long\" [title]=\"('Esecuzione in corso da' | localize: lc) + ' ' + duration(row.node.activeMaxTime) + ': ' + ('forse bloccata' | localize: lc)\"><i class=\"fa fa-clock\"></i> {{duration(row.node.activeMaxTime)}}</span>\r\n }\r\n @if (row.node.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{row.node.activeThreads}}</span>\r\n } @else {\r\n <span class=\"pv2-muted\">{{row.node.activeThreads ?? '\u2014'}}</span>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n } @else if (row.kind == 'loading') {\r\n <tr class=\"pv2-service\">\r\n <td [attr.colspan]=\"live ? 8 : 7\">\r\n <div [style.padding-left.px]=\"row.depth * 16 + 24\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento dei figli\u2026' | localize: lc}}</div>\r\n </td>\r\n </tr>\r\n } @else {\r\n <tr class=\"pv2-service\">\r\n <td [attr.colspan]=\"live ? 8 : 7\">\r\n <div [style.padding-left.px]=\"row.depth * 16 + 24\">\r\n {{row.node.omittedChildren | pv2fmt: 'int'}} {{'figli non mostrati' | localize: lc}} &middot; {{omittedTime(row.node) | pv2fmt: 'dur'}}\r\n @if (!snapMode) {\r\n &middot; {{row.node.omittedCalls | pv2fmt: 'int'}} {{'chiamate' | localize: lc}}\r\n }\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"showAll(row.node, $event)\">{{'Mostra tutti' | localize: lc}}</button>\r\n </div>\r\n </td>\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n </table>\r\n @if (rows.length == 0 && !treeError) {\r\n <div class=\"pv2-empty\">\r\n @if (!tree) {\r\n {{'Caricamento\u2026' | localize: lc}}\r\n } @else if (!tree.snapFrom && !live) {\r\n {{'Nessuno snapshot termina nella finestra scelta: allargala o spostala indietro.' | localize: lc}}\r\n } @else {\r\n {{\"Il nodo non c'\u00E8 nelle istanze scelte.\" | localize: lc}}\r\n }\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n @if (flatError) {\r\n <div class=\"pv2-alert pv2-alert-error\">{{flatError}}</div>\r\n }\r\n <div class=\"pv2-table-wrap\">\r\n <table class=\"pv2-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"pv2-col-node\">{{'Evento' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Percorsi' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Chiamate' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? '\u0394 Proprio' : 'Tempo proprio') | localize: lc}}</th>\r\n <th>{{snapMode ? '\u0394 ' : ''}}{{'% proprio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Tempo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{snapMode ? '\u0394 ' : ''}}{{'Medio' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{(snapMode ? \"Picco dall'avvio\" : 'Picco') | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (item of flat?.items ?? []; track flatKey(item)) {\r\n <tr class=\"pv2-row\" [class.pv2-idle]=\"isIdle(item.eventTypeName, item.waitClassName)\" [class.pv2-selected]=\"openFlat.has(flatKey(item))\" (click)=\"toggleFlat(item)\">\r\n <td class=\"pv2-col-node\">\r\n <div class=\"pv2-node\">\r\n <span class=\"pv2-caret\"><i class=\"fa\" [class.fa-caret-down]=\"openFlat.has(flatKey(item))\" [class.fa-caret-right]=\"!openFlat.has(flatKey(item))\"></i></span>\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></span>{{typeLabel(item.eventTypeName, item.waitClassName)}}</span>\r\n <span class=\"pv2-name\" [title]=\"item.nodeName\">@for (part of nameParts(item.nodeName, (flatSearch ?? '').trim()); track $index) {@if (part.hit) {<mark>{{part.text}}</mark>} @else {<span>{{part.text}}</span>}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{item.numPaths | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{flatCalls(item) | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{flatSelf(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-perc\">\r\n <div class=\"pv2-perc-cell\">\r\n <div class=\"pv2-bar\"><div [style.width.%]=\"flatPerc(item)\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></div></div>\r\n <span>{{flatPerc(item) | pv2fmt: 'pct'}}</span>\r\n </div>\r\n </td>\r\n <td class=\"pv2-num\">{{flatTime(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{flatAvg(item) | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{item.peakTime | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num pv2-threads\">\r\n @if (item.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{item.activeThreads}}</span>\r\n } @else {\r\n <span class=\"pv2-muted\">{{item.activeThreads ?? '\u2014'}}</span>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n @if (openFlat.has(flatKey(item))) {\r\n <tr class=\"pv2-sub\">\r\n <td [attr.colspan]=\"live ? 9 : 8\">\r\n <div class=\"pv2-sub-title\">{{'Nodi con pi\u00F9 tempo' | localize: lc}}</div>\r\n @for (id of item.nodeIds ?? []; track id) {\r\n <div class=\"pv2-sub-item\">\r\n <code>{{id}}</code>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"showDetail(id, $event)\">{{'Dettaglio' | localize: lc}}</button>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"openInTree(id, $event)\">{{\"Apri nell'albero\" | localize: lc}}</button>\r\n </div>\r\n }\r\n @if (item.numPaths > (item.nodeIds?.length ?? 0)) {\r\n <div class=\"pv2-muted\">+{{item.numPaths - (item.nodeIds?.length ?? 0) | pv2fmt: 'int'}} {{'altri' | localize: lc}}</div>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n </table>\r\n @if (!flatError && (!flat || !flat.items?.length)) {\r\n <div class=\"pv2-empty\">{{(flat ? 'Nessun evento con questi filtri.' : 'Caricamento\u2026') | localize: lc}}</div>\r\n }\r\n </div>\r\n @if (flat?.items?.length) {\r\n <div class=\"pv2-footer\">\r\n {{flat.numItems | pv2fmt: 'int'}} {{'eventi distinti' | localize: lc}}@if (flat.numItems > flat.items.length) {, {{'mostrati i primi' | localize: lc}} {{flat.items.length | pv2fmt: 'int'}}}.\r\n {{'La percentuale \u00E8 sul tempo proprio di tutti gli eventi non idle.' | localize: lc}}\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Dettaglio del nodo selezionato, lo stesso per le due viste -->\r\n <aside class=\"pv2-panel pv2-detail\" [class.pv2-stale]=\"detailStale\">\r\n @if (!selectedId) {\r\n <div class=\"pv2-placeholder\">{{'Seleziona un nodo per vederne il dettaglio.' | localize: lc}}</div>\r\n } @else if (detailMissing && !detailLoading) {\r\n <div class=\"pv2-placeholder\">{{\"Il nodo non c'\u00E8 nelle istanze o nella finestra scelte.\" | localize: lc}}</div>\r\n } @else if (detailError && !detailLoading) {\r\n <div class=\"pv2-placeholder pv2-error-text\">{{detailError}}</div>\r\n } @else if (!detail) {\r\n <div class=\"pv2-placeholder\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</div>\r\n } @else {\r\n <div class=\"pv2-d-head\">\r\n <span class=\"pv2-type\"><span class=\"pv2-dot\" [style.background]=\"typeColor(detail.eventTypeName, detail.waitClassName)\"></span>{{typeLabel(detail.eventTypeName, detail.waitClassName)}}</span>\r\n @if (detailLoading) {\r\n <i class=\"fa fa-spinner fa-spin pv2-muted\"></i>\r\n }\r\n </div>\r\n <div class=\"pv2-fullname\">{{detail.nodeName}}</div>\r\n <div class=\"pv2-id\">\r\n Id <code #idText>{{detail.nodeId}}</code>\r\n <button type=\"button\" class=\"pv2-link\" (click)=\"copyId(idText)\">{{(copied ? 'Copiato' : 'Copia') | localize: lc}}</button>\r\n </div>\r\n\r\n <div class=\"pv2-d-title\">{{'Percorso' | localize: lc}}</div>\r\n <div class=\"pv2-path\">\r\n @for (item of detail.fullWaitStack ?? []; track item.nodeId; let i = $index) {\r\n <button type=\"button\" class=\"pv2-path-item\" [style.padding-left.px]=\"i * 10\" [title]=\"item.nodeName\" (click)=\"select(item.nodeId)\">\r\n <span class=\"pv2-dot\" [style.background]=\"typeColor(item.eventTypeName, item.waitClassName)\"></span>{{item.nodeName}}\r\n </button>\r\n }\r\n <div class=\"pv2-path-item pv2-path-current\" [style.padding-left.px]=\"(detail.fullWaitStack?.length ?? 0) * 10\" [title]=\"detail.nodeName\">\r\n <span class=\"pv2-dot\" [style.background]=\"typeColor(detail.eventTypeName, detail.waitClassName)\"></span>{{detail.nodeName}}\r\n </div>\r\n </div>\r\n\r\n <div class=\"pv2-d-title\">{{(live ? \"Dall'avvio\" : 'Nella finestra') | localize: lc}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Esecuzioni' | localize: lc}}</dt><dd>{{detail.executions | pv2fmt: 'int'}}</dd>\r\n <dt>{{'Tempo totale' | localize: lc}}</dt><dd>{{detail.elapsedTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Tempo proprio' | localize: lc}}</dt><dd>{{detail.elapsedTimeLessChildren | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Medio' | localize: lc}}</dt><dd>{{detail.avgTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Picco' | localize: lc}}</dt><dd>{{detail.peakTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Minimo' | localize: lc}}</dt><dd>{{detail.minTime ? (detail.minTime | pv2fmt: 'dur') : '\u2014'}}</dd>\r\n </dl>\r\n\r\n @if (live) {\r\n <div class=\"pv2-d-title\">{{\"Dall'ultimo snapshot\" | localize: lc}}, {{hhmm(detail.snapFrom)}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Esecuzioni' | localize: lc}}</dt><dd>{{detail.snapDeltaExecutions | pv2fmt: 'int'}}</dd>\r\n <dt>{{'Tempo totale' | localize: lc}}</dt><dd>{{detail.snapDeltaElapsedTime | pv2fmt: 'dur'}}</dd>\r\n <dt>{{'Tempo proprio' | localize: lc}}</dt><dd>{{detail.snapDeltaElapsedTimeLessChildren | pv2fmt: 'dur'}}</dd>\r\n </dl>\r\n\r\n <div class=\"pv2-d-title\">{{'Adesso' | localize: lc}}</div>\r\n <dl class=\"pv2-kv\">\r\n <dt>{{'Thread dentro' | localize: lc}}</dt>\r\n <dd>\r\n @if (detail.activeThreads > 0) {\r\n <span class=\"pv2-active\"><span class=\"pv2-active-dot\"></span>{{detail.activeThreads}}</span>\r\n } @else {\r\n {{detail.activeThreads ?? '\u2014'}}\r\n }\r\n </dd>\r\n <dt>{{'Esecuzione pi\u00F9 lunga' | localize: lc}}</dt>\r\n <dd>\r\n @if (detail.activeThreads > 0) {\r\n {{detail.activeMaxTime | pv2fmt: 'dur'}}\r\n @if (isLongRunning(detail.eventTypeName, detail.waitClassName, detail.activeMaxTime)) {\r\n <span class=\"pv2-long\"><i class=\"fa fa-clock\"></i> {{'forse bloccata' | localize: lc}}</span>\r\n }\r\n } @else {\r\n \u2014\r\n }\r\n </dd>\r\n <dt>{{'Ultima uscita' | localize: lc}}</dt><dd>{{relative(detail.lastExitTime)}}</dd>\r\n </dl>\r\n }\r\n\r\n @if (typeParts.length > 0) {\r\n <div class=\"pv2-d-title\">{{'Tempo proprio del sottoalbero per tipo' | localize: lc}}</div>\r\n <div class=\"pv2-stack\">\r\n @for (part of typeParts; track part.type) {\r\n <div [style.width.%]=\"part.percentage\" [style.background]=\"part.color\" [title]=\"part.label + ' ' + (part.percentage | pv2fmt: 'pct')\"></div>\r\n }\r\n </div>\r\n <div class=\"pv2-legend\">\r\n @for (part of typeParts; track part.type) {\r\n <span class=\"pv2-legend-item\"><span class=\"pv2-swatch\" [style.background]=\"part.color\"></span>{{part.label}} <strong>{{part.percentage | pv2fmt: 'pct'}}</strong></span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pv2-d-title\">{{'Sessioni attive sul nodo e sui discendenti' | localize: lc}}</div>\r\n @if (chart) {\r\n <div class=\"pv2-chart\">\r\n <div class=\"pv2-chart-y\">\r\n <span>{{axisValue(chart.max)}}</span>\r\n <span>{{axisValue(chart.max / 2)}}</span>\r\n <span>0</span>\r\n </div>\r\n <div class=\"pv2-chart-plot\">\r\n <svg viewBox=\"0 0 100 100\" preserveAspectRatio=\"none\" aria-hidden=\"true\">\r\n <line x1=\"0\" y1=\"50\" x2=\"100\" y2=\"50\" class=\"pv2-chart-grid\" vector-effect=\"non-scaling-stroke\" />\r\n <path [attr.d]=\"chart.area\" [attr.fill]=\"chart.color\" fill-opacity=\"0.25\" />\r\n <path [attr.d]=\"chart.line\" [attr.stroke]=\"chart.color\" fill=\"none\" stroke-width=\"1.5\" vector-effect=\"non-scaling-stroke\" />\r\n </svg>\r\n <span class=\"pv2-chart-last\" [style.left.%]=\"chart.lastX\" [style.top.%]=\"chart.lastY\" [style.background]=\"chart.color\"></span>\r\n </div>\r\n <span></span>\r\n <div class=\"pv2-chart-x\">\r\n <span>{{chart.start}}</span>\r\n <span>{{chart.middle}}</span>\r\n <span>{{chart.end}}</span>\r\n </div>\r\n </div>\r\n <div class=\"pv2-caption\">\r\n {{'Media' | localize: lc}} {{axisValue(chart.average)}} &middot; {{'picco' | localize: lc}} {{axisValue(chart.peak)}} {{'sessioni' | localize: lc}}.\r\n {{chart.points | pv2fmt: 'int'}} {{\"punti dell'API\" | localize: lc}},\r\n @if (chart.interval == 1) {\r\n {{'uno al secondo' | localize: lc}},\r\n } @else {\r\n {{'uno ogni' | localize: lc}} {{chart.interval}} s,\r\n }\r\n {{'raggruppati a' | localize: lc}} {{chart.group}} s\r\n </div>\r\n } @else {\r\n <div class=\"pv2-muted pv2-small\">{{'Nessun campione in memoria per questa finestra: il grafico copre solo le ultime due ore circa.' | localize: lc}}</div>\r\n }\r\n\r\n @if (detail.instances?.length) {\r\n <div class=\"pv2-d-title\">{{'Per istanza' | localize: lc}}</div>\r\n <table class=\"pv2-mini\">\r\n <thead>\r\n <tr>\r\n <th>{{'Istanza' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Esecuzioni' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Tempo' | localize: lc}}</th>\r\n <th class=\"pv2-num\">{{'Proprio' | localize: lc}}</th>\r\n @if (live) {\r\n <th class=\"pv2-num\">{{'Thread' | localize: lc}}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (inst of detail.instances; track inst.instanceId) {\r\n <tr>\r\n <td><span class=\"pv2-ellipsis\" [title]=\"inst.instanceId\">{{inst.instanceId}}</span></td>\r\n <td class=\"pv2-num\">{{inst.executions | pv2fmt: 'int'}}</td>\r\n <td class=\"pv2-num\">{{inst.elapsedTime | pv2fmt: 'dur'}}</td>\r\n <td class=\"pv2-num\">{{inst.elapsedTimeLessChildren | pv2fmt: 'dur'}}</td>\r\n @if (live) {\r\n <td class=\"pv2-num\">{{inst.activeThreads ?? '\u2014'}}</td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <div class=\"pv2-d-foot\">\r\n <span class=\"pv2-muted\">{{detail.numChildren | pv2fmt: 'int'}} {{'figli diretti' | localize: lc}} &middot; {{detail.numDescendants | pv2fmt: 'int'}} {{'discendenti' | localize: lc}}</span>\r\n <button type=\"button\" class=\"pv2-btn\" (click)=\"setRoot(detail.nodeId)\"><i class=\"fa fa-sitemap\"></i> {{'Apri come radice' | localize: lc}}</button>\r\n </div>\r\n }\r\n </aside>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";:host{display:block}:host ::ng-deep .pv2-noclear .p-select-clear-icon{display:none}.pv2-body{container-type:inline-size}.pv2-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 22px;padding-top:6px}.pv2-cluster{display:flex;flex-wrap:nowrap;align-items:center;gap:10px}.pv2-cluster-end{margin-left:auto}.pv2-field{width:190px}.pv2-field-wide{width:290px}.pv2-field-narrow{width:140px}.pv2-field-search{flex:1 1 220px;min-width:200px;max-width:340px}.pv2-toggle{display:flex;align-items:center;gap:8px;height:39px;white-space:nowrap}.pv2-pointer{cursor:pointer}.pv2-group{position:relative;display:inline-flex}.pv2-group.pv2-disabled{opacity:.5}.pv2-group-label{position:absolute;top:-8px;left:8px;z-index:1;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.pv2-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.pv2-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 12px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.pv2-seg button:first-child{border-left:0}.pv2-seg button:hover:not(.pv2-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.pv2-seg button:disabled{cursor:default}.pv2-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.pv2-seg button.pv2-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.pv2-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.pv2-window{display:flex;flex-wrap:wrap;align-items:center;row-gap:4px;margin-top:12px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.pv2-window>span+span:before{content:\"\\b7\";margin:0 10px;color:var(--p-text-muted-color, #64748b)}.pv2-warn-text{color:#92400e}.pv2-main{display:grid;grid-template-columns:minmax(0,1fr) 380px;gap:14px;align-items:start;margin-top:14px}@container (max-width: 1350px){.pv2-main{grid-template-columns:minmax(0,1fr)}.pv2-detail{position:static;max-height:none}}.pv2-panel{padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.pv2-view-bar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 10px;padding-top:6px;margin-bottom:10px}.pv2-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;margin-bottom:8px;font-size:12px}.pv2-crumb{max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:2px 6px;border:0;border-radius:4px;background:transparent;color:var(--p-primary-color, #6366f1);cursor:pointer}.pv2-crumb:hover{background:var(--p-highlight-background, #eef2ff)}.pv2-crumb-current{color:var(--p-text-color, #334155);font-weight:500;cursor:default}.pv2-crumb-current:hover{background:transparent}.pv2-crumb-sep{color:var(--p-text-muted-color, #64748b)}.pv2-alert{position:relative;margin-bottom:8px;padding:6px 30px 6px 10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);font-size:13px}.pv2-alert.pv2-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.pv2-alert.pv2-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.pv2-alert-close{position:absolute;top:3px;right:6px;border:0;background:transparent;color:inherit;font-size:16px;cursor:pointer}.pv2-table-wrap{max-height:68vh;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.pv2-table-wrap:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:1px}.pv2-table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;color:var(--p-text-color, #334155)}.pv2-table th{position:sticky;top:0;z-index:1;padding:7px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-size:12px;font-weight:500;white-space:nowrap;text-align:left}.pv2-table td{padding:4px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap;vertical-align:middle}.pv2-col-node{width:100%;max-width:0}.pv2-col-node .pv2-node{min-width:260px}.pv2-num{text-align:right!important;font-variant-numeric:tabular-nums}.pv2-row{cursor:pointer}.pv2-row:hover td{background:var(--p-content-hover-background, #f8fafc)}.pv2-row.pv2-selected td{background:var(--p-highlight-background, #eef2ff)}.pv2-row.pv2-idle td{color:var(--p-text-muted-color, #64748b)}.pv2-row.pv2-idle td .pv2-name{opacity:.75}.pv2-node{display:flex;align-items:center;gap:6px;min-width:0}.pv2-caret{flex:none;width:18px;height:20px;padding:0;border:0;background:transparent;color:var(--p-text-muted-color, #64748b);text-align:center;cursor:pointer}.pv2-type{flex:none;display:inline-flex;align-items:center;gap:5px;padding:0 6px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px;white-space:nowrap}.pv2-dot{flex:none;display:inline-block;width:8px;height:8px;border-radius:50%}.pv2-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pv2-name mark{padding:0 1px;border-radius:2px;background:#fde68a;color:#1f2937}.pv2-perc{width:1%}.pv2-perc-cell{display:flex;align-items:center;gap:8px}.pv2-bar{flex:none;width:64px;height:7px;border-radius:2px;overflow:hidden;background:var(--p-content-hover-background, #f8fafc);box-shadow:inset 0 0 0 1px var(--p-content-border-color, #e2e8f0)}.pv2-bar>div{height:100%}.pv2-threads>*+*{margin-left:8px}.pv2-active{display:inline-flex;align-items:center;gap:5px;font-weight:500}.pv2-active-dot{width:7px;height:7px;border-radius:50%;background:#16a34a;box-shadow:0 0 0 3px #16a34a2e}.pv2-long{display:inline-flex;align-items:center;gap:4px;padding:0 6px;border:1px solid #fcd34d;border-radius:10px;background:#fffbeb;color:#92400e;font-size:11px;line-height:18px;white-space:nowrap}.pv2-service td{padding:5px 10px;color:var(--p-text-muted-color, #64748b);font-size:12px;background:var(--p-content-background, #fff)}.pv2-sub td{padding:8px 10px 10px 34px;background:var(--p-content-hover-background, #f8fafc);white-space:normal}.pv2-sub-title{margin-bottom:4px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-sub-item{display:flex;align-items:center;gap:10px;padding:2px 0}.pv2-sub-item code{font-size:12px}.pv2-link{margin-left:6px;padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.pv2-link:hover{text-decoration:underline}.pv2-empty{padding:28px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.pv2-footer{margin-top:8px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-muted{color:var(--p-text-muted-color, #64748b)}.pv2-small{font-size:12px}.pv2-detail{position:sticky;top:10px;max-height:calc(100vh - 20px);overflow:auto;font-size:13px;color:var(--p-text-color, #334155);transition:opacity .15s}.pv2-detail.pv2-stale{opacity:.55}.pv2-placeholder{padding:36px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.pv2-error-text{color:#dc2626}.pv2-d-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.pv2-fullname{max-height:140px;overflow:auto;padding:8px 10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);font-family:ui-monospace,Cascadia Mono,Consolas,monospace;font-size:12px;white-space:pre-wrap;word-break:break-word}.pv2-id{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-id code{font-size:12px}.pv2-d-title{margin:16px 0 6px;padding-top:10px;border-top:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.pv2-path{display:flex;flex-direction:column}.pv2-path-item{display:flex;align-items:center;gap:6px;max-width:100%;padding:2px 0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.pv2-path-item:hover{text-decoration:underline}.pv2-path-current{color:var(--p-text-color, #334155);font-weight:600;cursor:default}.pv2-path-current:hover{text-decoration:none}.pv2-kv{display:grid;grid-template-columns:auto 1fr;gap:3px 14px;margin:0}.pv2-kv dt{color:var(--p-text-muted-color, #64748b);font-weight:400}.pv2-kv dd{margin:0;text-align:right;font-variant-numeric:tabular-nums}.pv2-stack{display:flex;height:12px;border-radius:3px;overflow:hidden;background:var(--p-content-hover-background, #f8fafc)}.pv2-legend{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:6px;font-size:12px}.pv2-legend-item{display:inline-flex;align-items:center;gap:5px}.pv2-swatch{width:10px;height:10px;border-radius:2px}.pv2-chart{display:grid;grid-template-columns:auto 1fr;gap:2px 6px}.pv2-chart-y{display:flex;flex-direction:column;justify-content:space-between;height:110px;color:var(--p-text-muted-color, #64748b);font-size:11px;text-align:right;line-height:1}.pv2-chart-plot{position:relative;height:110px;border-left:1px solid var(--p-content-border-color, #e2e8f0);border-bottom:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-chart-plot svg{display:block;width:100%;height:100%}.pv2-chart-grid{stroke:var(--p-content-border-color, #e2e8f0);stroke-dasharray:3 3}.pv2-chart-last{position:absolute;width:8px;height:8px;border:2px solid var(--p-content-background, #fff);border-radius:50%;transform:translate(-50%,-50%)}.pv2-chart-x{display:flex;justify-content:space-between;color:var(--p-text-muted-color, #64748b);font-size:11px}.pv2-caption{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.pv2-mini{width:100%;font-size:12px}.pv2-mini th{padding:3px 6px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-weight:500}.pv2-mini td{padding:3px 6px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-ellipsis{display:inline-block;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.pv2-d-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;margin-top:16px;padding-top:10px;border-top:1px solid var(--p-content-border-color, #e2e8f0)}.pv2-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;cursor:pointer}.pv2-btn:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}\n"] }]
1975
1977
  }], ctorParameters: () => [{ type: i1$1.DateService }, { type: i1.LocalizationService }, { type: i3.PreferencesService }, { type: i1$1.InterComService }, { type: i4.ActivatedRoute }, { type: i4.Router }, { type: i5.Location }, { type: AdminModuleBaseService }, { type: undefined, decorators: [{
1976
1978
  type: Inject,
1977
1979
  args: [ADM_MODULE_PATH]
@@ -2009,6 +2011,7 @@ class AdmWorkloadV2Loc extends LocalizationService {
2009
2011
  super.set("it->en", "Tutto il cluster", ["Whole cluster"]);
2010
2012
  super.set("it->en", "tutto il cluster", ["whole cluster"]);
2011
2013
  super.set("it->en", "istanze", ["instances"]);
2014
+ super.set("it->en", "istanza", ["instance"]);
2012
2015
  super.set("it->en", "Genera report", ["Generate report"]);
2013
2016
  super.set("it->en", "Annulla", ["Cancel"]);
2014
2017
  super.set("it->en", "Scegli il primo e l'ultimo snapshot", ["Choose the first and last snapshot"]);
@@ -2126,7 +2129,7 @@ class AdmWorkloadV2Component {
2126
2129
  }
2127
2130
  // #region Comandi
2128
2131
  get clusterLabel() {
2129
- return this.Instances.length ? `${this.lc.loc("Tutto il cluster")} (${this.Instances.length} ${this.lc.loc("istanze")})` : this.lc.loc("Tutto il cluster");
2132
+ return this.Instances.length ? `${this.lc.loc("Tutto il cluster")} (${this.Instances.length} ${this.Instances.length == 1 ? this.lc.loc("istanza") : this.lc.loc("istanze")})` : this.lc.loc("Tutto il cluster");
2130
2133
  }
2131
2134
  setLive(live) {
2132
2135
  if (!live && !this.historyAvailable)
@@ -2394,11 +2397,11 @@ class AdmWorkloadV2Component {
2394
2397
  this.localStorage.setItem(STORAGE_KEY$2, settings).subscribe();
2395
2398
  }
2396
2399
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: AdmWorkloadV2Component, deps: [{ token: i1.LocalizationService }, { token: i3.PreferencesService }, { token: i1$1.InterComService }, { token: i4.ActivatedRoute }, { token: i5$1.DomSanitizer }, { token: AdminModuleBaseService }], target: i0.ɵɵFactoryTarget.Component }); }
2397
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.34", type: AdmWorkloadV2Component, isStandalone: false, selector: "workload_v2", providers: [{ provide: LocalizationService, useClass: AdmWorkloadV2Loc }], viewQueries: [{ propertyName: "reportFrame", first: true, predicate: ["reportFrame"], descendants: true }], ngImport: i0, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Workload report' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body\">\r\n <!-- Barra dei comandi: tipo, istanze, genera. Il report si chiede solo con il comando -->\r\n <div class=\"wr-toolbar\">\r\n <div class=\"wr-group\">\r\n <span class=\"wr-group-label\">{{'Tipo' | localize: lc}}</span>\r\n <div class=\"wr-seg\">\r\n <button type=\"button\" [class.wr-on]=\"live\" (click)=\"setLive(true)\"><span class=\"wr-live-dot\"></span>Live</button>\r\n <button type=\"button\" [class.wr-on]=\"!live\" [disabled]=\"!historyAvailable\" (click)=\"setLive(false)\"\r\n [title]=\"historyAvailable ? '' : ('Lo storico non \u00E8 attivo su questo ambiente: il report si pu\u00F2 produrre solo live.' | localize: lc)\">\r\n {{'Fra snapshot' | localize: lc}}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"wr-group wr-field-wide\">\r\n <span class=\"wr-group-label\">{{'Istanze' | localize: lc}}</span>\r\n <form-multiselect class=\"wr-fill\" [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instances\" (ngModelChange)=\"instancesChanged($event)\" name=\"instances\" [Source]=\"Instances\" [Placeholder]=\"clusterLabel\" [MaxShownElements]=\"2\"></form-multiselect>\r\n </div>\r\n <div class=\"wr-toolbar-end\">\r\n <button type=\"button\" class=\"wr-btn wr-btn-primary\" [disabled]=\"!generating && !canGenerate\" (click)=\"generateOrCancel()\"\r\n [title]=\"!generating && !canGenerate ? ('Scegli il primo e l\\'ultimo snapshot' | localize: lc) : ''\">\r\n @if (generating) {\r\n <i class=\"fa fa-times\"></i> {{'Annulla' | localize: lc}}\r\n } @else {\r\n <i class=\"fa fa-file-text-o\"></i> {{'Genera report' | localize: lc}}\r\n }\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Avvisi sulla finestra (W4): non bloccano la generazione -->\r\n @for (warning of warnings; track $index) {\r\n <div class=\"wr-alert wr-alert-warn\"><i class=\"fa fa-exclamation-triangle\"></i> {{warning}}</div>\r\n }\r\n @if (snapshotsLoaded && !historyAvailable) {\r\n <div class=\"wr-alert\"><i class=\"fa fa-info-circle\"></i> {{'Lo storico non \u00E8 attivo su questo ambiente: il report si pu\u00F2 produrre solo live.' | localize: lc}}</div>\r\n }\r\n\r\n <!-- Elenco degli snapshot, solo per il report fra snapshot -->\r\n @if (!live) {\r\n <div class=\"wr-panel\">\r\n <div class=\"wr-panel-header\">\r\n <span class=\"wr-title\">{{'Snapshot' | localize: lc}}</span>\r\n <div class=\"wr-seg wr-seg-small\">\r\n @for (p of Periods; track p.id) {\r\n <button type=\"button\" [class.wr-on]=\"period == p.id\" (click)=\"setPeriod(p.id)\">{{p.description}}</button>\r\n }\r\n </div>\r\n @if (snapshotsLoading) {\r\n <span class=\"wr-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n <span class=\"wr-spacer\"></span>\r\n @if (selectionWindow; as w) {\r\n <span class=\"wr-window\">\r\n {{'Dalle' | localize: lc}} <strong>{{local(w.from)}}</strong> {{'alle' | localize: lc}} <strong>{{local(w.to)}}</strong>\r\n ({{span(w.from, w.to)}})\r\n @if (selTo == null) {\r\n <span class=\"wr-muted\">&middot; {{\"scegli l'ultimo snapshot\" | localize: lc}}</span>\r\n }\r\n </span>\r\n <button type=\"button\" class=\"wr-link\" (click)=\"clearSelection()\">{{'Azzera' | localize: lc}}</button>\r\n } @else {\r\n <span class=\"wr-muted\">{{\"Un clic sceglie il primo snapshot, un secondo clic l'ultimo.\" | localize: lc}}</span>\r\n }\r\n </div>\r\n\r\n @if (snapshotsError) {\r\n <div class=\"wr-alert wr-alert-error\">{{snapshotsError}}</div>\r\n }\r\n\r\n <div class=\"wr-table-wrap\">\r\n <table class=\"wr-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"wr-num\">{{'Snapshot' | localize: lc}}</th>\r\n <th>{{'Inizio' | localize: lc}}</th>\r\n <th>{{'Fine' | localize: lc}}</th>\r\n <th class=\"wr-num\">{{'Durata' | localize: lc}}</th>\r\n <th class=\"wr-num\">{{'Istanze' | localize: lc}}</th>\r\n <th>{{'Manuale' | localize: lc}}</th>\r\n <th>{{'Riavvio' | localize: lc}}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (s of snapshots; track s.snapId) {\r\n <tr class=\"wr-row\" [class.wr-in-range]=\"inRange(s)\" [class.wr-edge]=\"isEdge(s)\" [class.wr-restart]=\"s.restart\" (click)=\"pick(s)\">\r\n <td class=\"wr-num\"><strong>{{s.snapId}}</strong></td>\r\n <td>{{local(s.beginIntervalTime)}}</td>\r\n <td>{{local(s.endIntervalTime)}}</td>\r\n <td class=\"wr-num\">{{span(s.beginIntervalTime, s.endIntervalTime)}}</td>\r\n <td class=\"wr-num\" [title]=\"instancesTitle(s)\">{{s.instances?.length ?? 0}}</td>\r\n <td>\r\n @if (s.manual) {\r\n <span class=\"wr-badge\"><i class=\"fa fa-hand-pointer-o\"></i> {{'Manuale' | localize: lc}}</span>\r\n }\r\n </td>\r\n <td>\r\n @if (s.restart) {\r\n <span class=\"wr-badge wr-badge-warn\" [title]=\"'Un\\'istanza \u00E8 ripartita: counter e meter non sono attendibili' | localize: lc\"><i class=\"fa fa-power-off\"></i> {{'Riavvio' | localize: lc}}</span>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (snapshotsLoaded && !snapshotsLoading && !snapshotsError && snapshots.length == 0 && historyAvailable) {\r\n <div class=\"wr-empty\">{{'Nessuno snapshot nel periodo scelto: prova con un periodo pi\u00F9 lungo.' | localize: lc}}</div>\r\n }\r\n </div>\r\n <div class=\"wr-footnote\">{{'Orari in ora locale' | localize: lc}} ({{zone}})</div>\r\n </div>\r\n }\r\n\r\n <!-- Report -->\r\n <div class=\"wr-panel wr-report\">\r\n @if (generating) {\r\n <div class=\"wr-alert wr-alert-busy\">\r\n <i class=\"fa fa-spinner fa-spin\"></i> {{'Generazione del report\u2026' | localize: lc}}\r\n <button type=\"button\" class=\"wr-link\" (click)=\"cancel()\">{{'Annulla' | localize: lc}}</button>\r\n </div>\r\n }\r\n @if (reportError) {\r\n <div class=\"wr-alert wr-alert-error\">{{'Il report non si pu\u00F2 produrre' | localize: lc}}: {{reportError}}</div>\r\n }\r\n\r\n @if (report) {\r\n <div class=\"wr-report-bar\">\r\n <div class=\"wr-summary\">\r\n @if (report.live) {\r\n <strong>Live</strong>\r\n } @else {\r\n <strong>{{'Snapshot' | localize: lc}} {{report.snapFrom}}\u2013{{report.snapTo}}</strong>\r\n }\r\n &middot; {{scopeLabel(report.instances)}}\r\n @if (!report.live && report.windowFrom) {\r\n &middot; {{'dalle' | localize: lc}} {{local(report.windowFrom)}} {{'alle' | localize: lc}} {{local(report.windowTo)}}\r\n }\r\n &middot; {{'generato alle' | localize: lc}} {{hhmm(report.generatedAt)}} ({{kilobytes(report.size)}})\r\n </div>\r\n <div class=\"wr-actions\">\r\n @if (report.sections.length > 0) {\r\n <div class=\"wr-field wr-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"section\" (ngModelChange)=\"goToSection($event)\" name=\"section\" [Source]=\"report.sections\" [Placeholder]=\"'Vai a\u2026' | localize: lc\"></form-select>\r\n </div>\r\n }\r\n <button type=\"button\" class=\"wr-btn\" (click)=\"download()\"><i class=\"fa fa-download\"></i> {{'Scarica' | localize: lc}}</button>\r\n <button type=\"button\" class=\"wr-btn\" (click)=\"openInTab()\"><i class=\"fa fa-external-link\"></i> {{'Apri in una scheda' | localize: lc}}</button>\r\n </div>\r\n </div>\r\n <div class=\"wr-footnote\"><i class=\"fa fa-clock-o\"></i> {{'Gli orari del report sono in UTC.' | localize: lc}}</div>\r\n <!-- Riquadro isolato e senza script: gli stili del report non toccano la pagina e le ancore dell'indice restano dentro (W8) -->\r\n <iframe #reportFrame class=\"wr-frame\" [class.wr-stale]=\"generating\" [srcdoc]=\"report.doc\" sandbox=\"allow-same-origin allow-popups\" title=\"Workload report\"></iframe>\r\n } @else if (!generating && !reportError) {\r\n <div class=\"wr-placeholder\">\r\n <i class=\"fa fa-file-text-o\"></i>\r\n {{'Scegli tipo e istanze, poi genera il report.' | localize: lc}}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}:host ::ng-deep .wr-noclear .p-select-clear-icon{display:none}:host ::ng-deep .wr-fill{display:block;width:100%}.wr-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px;padding-top:6px}.wr-toolbar-end{margin-left:auto}.wr-field{width:240px}.wr-field-wide{width:380px;max-width:100%}.wr-group{position:relative;display:inline-flex}.wr-group-label{position:absolute;top:-8px;left:8px;z-index:2;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.wr-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.wr-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 14px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.wr-seg button:first-child{border-left:0}.wr-seg button:hover:not(.wr-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.wr-seg button:disabled{color:var(--p-text-muted-color, #64748b);opacity:.6;cursor:not-allowed}.wr-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.wr-seg button.wr-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.wr-seg.wr-seg-small{height:30px}.wr-seg.wr-seg-small button{padding:0 10px;font-size:12px}.wr-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.wr-btn{display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 14px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.wr-btn:hover:not(:disabled){background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.wr-btn:disabled{opacity:.55;cursor:not-allowed}.wr-btn.wr-btn-primary{height:39px;padding:0 18px;border-color:var(--p-primary-color, #6366f1);background:var(--p-primary-color, #6366f1);color:var(--p-primary-contrast-color, #fff);font-weight:500}.wr-btn.wr-btn-primary:hover:not(:disabled){background:var(--p-primary-color, #6366f1);color:var(--p-primary-contrast-color, #fff);filter:brightness(1.08)}.wr-link{margin-left:8px;padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.wr-link:hover{text-decoration:underline}.wr-alert{margin-top:10px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.wr-alert.wr-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.wr-alert.wr-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.wr-alert.wr-alert-busy{margin-top:0;margin-bottom:10px;border-color:var(--p-primary-color, #6366f1);background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.wr-panel{margin-top:14px;padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.wr-panel-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;margin-bottom:10px}.wr-title{font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--p-text-muted-color, #64748b)}.wr-spacer{flex:1 1 auto}.wr-window{color:var(--p-text-color, #334155);font-size:13px}.wr-muted{color:var(--p-text-muted-color, #64748b);font-size:12px}.wr-table-wrap{max-height:320px;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.wr-table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;color:var(--p-text-color, #334155)}.wr-table th{position:sticky;top:0;z-index:1;padding:6px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-size:12px;font-weight:500;white-space:nowrap;text-align:left}.wr-table td{padding:4px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap}.wr-num{text-align:right!important;font-variant-numeric:tabular-nums}.wr-row{cursor:pointer}.wr-row:hover td{background:var(--p-content-hover-background, #f8fafc)}.wr-row.wr-restart td:first-child{box-shadow:inset 3px 0 #f59e0b}.wr-row.wr-in-range td{background:var(--p-highlight-background, #eef2ff)}.wr-row.wr-edge td{color:var(--p-highlight-color, #4338ca);font-weight:600}.wr-badge{display:inline-flex;align-items:center;gap:4px;padding:0 7px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px}.wr-badge.wr-badge-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.wr-empty{padding:22px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.wr-footnote{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.wr-report-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 14px;padding-top:6px}.wr-summary{color:var(--p-text-color, #334155);font-size:13px}.wr-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.wr-frame{display:block;width:100%;height:calc(100vh - 240px);min-height:520px;margin-top:8px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:#fff;transition:opacity .15s}.wr-frame.wr-stale{opacity:.5}.wr-placeholder{display:flex;flex-direction:column;align-items:center;gap:10px;padding:70px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.wr-placeholder .fa{font-size:28px;opacity:.5}\n"], dependencies: [{ kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i9.EsFormSelectComponent, selector: "form-select", inputs: ["OptionsTemplate"] }, { kind: "component", type: i9.EsFormMultiselectComponent, selector: "form-multiselect", inputs: ["display", "InOutFormat", "FloatingLabel", "MaxShownElements"] }, { kind: "directive", type: i10.Widget, selector: "[widget]" }, { kind: "pipe", type: i1.LocalizePipe, name: "localize" }] }); }
2400
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.34", type: AdmWorkloadV2Component, isStandalone: false, selector: "workload_v2", providers: [{ provide: LocalizationService, useClass: AdmWorkloadV2Loc }], viewQueries: [{ propertyName: "reportFrame", first: true, predicate: ["reportFrame"], descendants: true }], ngImport: i0, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Workload report' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body\">\r\n <!-- Barra dei comandi: tipo, istanze, genera. Il report si chiede solo con il comando -->\r\n <div class=\"wr-toolbar\">\r\n <div class=\"wr-group\">\r\n <span class=\"wr-group-label\">{{'Tipo' | localize: lc}}</span>\r\n <div class=\"wr-seg\">\r\n <button type=\"button\" [class.wr-on]=\"live\" (click)=\"setLive(true)\"><span class=\"wr-live-dot\"></span>Live</button>\r\n <button type=\"button\" [class.wr-on]=\"!live\" [disabled]=\"!historyAvailable\" (click)=\"setLive(false)\"\r\n [title]=\"historyAvailable ? '' : ('Lo storico non \u00E8 attivo su questo ambiente: il report si pu\u00F2 produrre solo live.' | localize: lc)\">\r\n {{'Fra snapshot' | localize: lc}}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"wr-group wr-field-wide\">\r\n <span class=\"wr-group-label\">{{'Istanze' | localize: lc}}</span>\r\n <form-multiselect class=\"wr-fill\" [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instances\" (ngModelChange)=\"instancesChanged($event)\" name=\"instances\" [Source]=\"Instances\" [Placeholder]=\"clusterLabel\" [MaxShownElements]=\"2\"></form-multiselect>\r\n </div>\r\n <div class=\"wr-toolbar-end\">\r\n <button type=\"button\" class=\"wr-btn wr-btn-primary\" [disabled]=\"!generating && !canGenerate\" (click)=\"generateOrCancel()\"\r\n [title]=\"!generating && !canGenerate ? ('Scegli il primo e l\\'ultimo snapshot' | localize: lc) : ''\">\r\n @if (generating) {\r\n <i class=\"fa fa-times\"></i> {{'Annulla' | localize: lc}}\r\n } @else {\r\n <i class=\"fa fa-file-text\"></i> {{'Genera report' | localize: lc}}\r\n }\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Avvisi sulla finestra (W4): non bloccano la generazione -->\r\n @for (warning of warnings; track $index) {\r\n <div class=\"wr-alert wr-alert-warn\"><i class=\"fa fa-exclamation-triangle\"></i> {{warning}}</div>\r\n }\r\n @if (snapshotsLoaded && !historyAvailable) {\r\n <div class=\"wr-alert\"><i class=\"fa fa-info-circle\"></i> {{'Lo storico non \u00E8 attivo su questo ambiente: il report si pu\u00F2 produrre solo live.' | localize: lc}}</div>\r\n }\r\n\r\n <!-- Elenco degli snapshot, solo per il report fra snapshot -->\r\n @if (!live) {\r\n <div class=\"wr-panel\">\r\n <div class=\"wr-panel-header\">\r\n <span class=\"wr-title\">{{'Snapshot' | localize: lc}}</span>\r\n <div class=\"wr-seg wr-seg-small\">\r\n @for (p of Periods; track p.id) {\r\n <button type=\"button\" [class.wr-on]=\"period == p.id\" (click)=\"setPeriod(p.id)\">{{p.description}}</button>\r\n }\r\n </div>\r\n @if (snapshotsLoading) {\r\n <span class=\"wr-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n <span class=\"wr-spacer\"></span>\r\n @if (selectionWindow; as w) {\r\n <span class=\"wr-window\">\r\n {{'Dalle' | localize: lc}} <strong>{{local(w.from)}}</strong> {{'alle' | localize: lc}} <strong>{{local(w.to)}}</strong>\r\n ({{span(w.from, w.to)}})\r\n @if (selTo == null) {\r\n <span class=\"wr-muted\">&middot; {{\"scegli l'ultimo snapshot\" | localize: lc}}</span>\r\n }\r\n </span>\r\n <button type=\"button\" class=\"wr-link\" (click)=\"clearSelection()\">{{'Azzera' | localize: lc}}</button>\r\n } @else {\r\n <span class=\"wr-muted\">{{\"Un clic sceglie il primo snapshot, un secondo clic l'ultimo.\" | localize: lc}}</span>\r\n }\r\n </div>\r\n\r\n @if (snapshotsError) {\r\n <div class=\"wr-alert wr-alert-error\">{{snapshotsError}}</div>\r\n }\r\n\r\n <div class=\"wr-table-wrap\">\r\n <table class=\"wr-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"wr-num\">{{'Snapshot' | localize: lc}}</th>\r\n <th>{{'Inizio' | localize: lc}}</th>\r\n <th>{{'Fine' | localize: lc}}</th>\r\n <th class=\"wr-num\">{{'Durata' | localize: lc}}</th>\r\n <th class=\"wr-num\">{{'Istanze' | localize: lc}}</th>\r\n <th>{{'Manuale' | localize: lc}}</th>\r\n <th>{{'Riavvio' | localize: lc}}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (s of snapshots; track s.snapId) {\r\n <tr class=\"wr-row\" [class.wr-in-range]=\"inRange(s)\" [class.wr-edge]=\"isEdge(s)\" [class.wr-restart]=\"s.restart\" (click)=\"pick(s)\">\r\n <td class=\"wr-num\"><strong>{{s.snapId}}</strong></td>\r\n <td>{{local(s.beginIntervalTime)}}</td>\r\n <td>{{local(s.endIntervalTime)}}</td>\r\n <td class=\"wr-num\">{{span(s.beginIntervalTime, s.endIntervalTime)}}</td>\r\n <td class=\"wr-num\" [title]=\"instancesTitle(s)\">{{s.instances?.length ?? 0}}</td>\r\n <td>\r\n @if (s.manual) {\r\n <span class=\"wr-badge\"><i class=\"fa fa-hand-pointer\"></i> {{'Manuale' | localize: lc}}</span>\r\n }\r\n </td>\r\n <td>\r\n @if (s.restart) {\r\n <span class=\"wr-badge wr-badge-warn\" [title]=\"'Un\\'istanza \u00E8 ripartita: counter e meter non sono attendibili' | localize: lc\"><i class=\"fa fa-power-off\"></i> {{'Riavvio' | localize: lc}}</span>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (snapshotsLoaded && !snapshotsLoading && !snapshotsError && snapshots.length == 0 && historyAvailable) {\r\n <div class=\"wr-empty\">{{'Nessuno snapshot nel periodo scelto: prova con un periodo pi\u00F9 lungo.' | localize: lc}}</div>\r\n }\r\n </div>\r\n <div class=\"wr-footnote\">{{'Orari in ora locale' | localize: lc}} ({{zone}})</div>\r\n </div>\r\n }\r\n\r\n <!-- Report -->\r\n <div class=\"wr-panel wr-report\">\r\n @if (generating) {\r\n <div class=\"wr-alert wr-alert-busy\">\r\n <i class=\"fa fa-spinner fa-spin\"></i> {{'Generazione del report\u2026' | localize: lc}}\r\n <button type=\"button\" class=\"wr-link\" (click)=\"cancel()\">{{'Annulla' | localize: lc}}</button>\r\n </div>\r\n }\r\n @if (reportError) {\r\n <div class=\"wr-alert wr-alert-error\">{{'Il report non si pu\u00F2 produrre' | localize: lc}}: {{reportError}}</div>\r\n }\r\n\r\n @if (report) {\r\n <div class=\"wr-report-bar\">\r\n <div class=\"wr-summary\">\r\n @if (report.live) {\r\n <strong>Live</strong>\r\n } @else {\r\n <strong>{{'Snapshot' | localize: lc}} {{report.snapFrom}}\u2013{{report.snapTo}}</strong>\r\n }\r\n &middot; {{scopeLabel(report.instances)}}\r\n @if (!report.live && report.windowFrom) {\r\n &middot; {{'dalle' | localize: lc}} {{local(report.windowFrom)}} {{'alle' | localize: lc}} {{local(report.windowTo)}}\r\n }\r\n &middot; {{'generato alle' | localize: lc}} {{hhmm(report.generatedAt)}} ({{kilobytes(report.size)}})\r\n </div>\r\n <div class=\"wr-actions\">\r\n @if (report.sections.length > 0) {\r\n <div class=\"wr-field wr-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"section\" (ngModelChange)=\"goToSection($event)\" name=\"section\" [Source]=\"report.sections\" [Placeholder]=\"'Vai a\u2026' | localize: lc\"></form-select>\r\n </div>\r\n }\r\n <button type=\"button\" class=\"wr-btn\" (click)=\"download()\"><i class=\"fa fa-download\"></i> {{'Scarica' | localize: lc}}</button>\r\n <button type=\"button\" class=\"wr-btn\" (click)=\"openInTab()\"><i class=\"fa fa-external-link\"></i> {{'Apri in una scheda' | localize: lc}}</button>\r\n </div>\r\n </div>\r\n <div class=\"wr-footnote\"><i class=\"fa fa-clock\"></i> {{'Gli orari del report sono in UTC.' | localize: lc}}</div>\r\n <!-- Riquadro isolato e senza script: gli stili del report non toccano la pagina e le ancore dell'indice restano dentro (W8) -->\r\n <iframe #reportFrame class=\"wr-frame\" [class.wr-stale]=\"generating\" [srcdoc]=\"report.doc\" sandbox=\"allow-same-origin allow-popups\" title=\"Workload report\"></iframe>\r\n } @else if (!generating && !reportError) {\r\n <div class=\"wr-placeholder\">\r\n <i class=\"fa fa-file-text\"></i>\r\n {{'Scegli tipo e istanze, poi genera il report.' | localize: lc}}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}:host ::ng-deep .wr-noclear .p-select-clear-icon{display:none}:host ::ng-deep .wr-fill{display:block;width:100%}.wr-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px;padding-top:6px}.wr-toolbar-end{margin-left:auto}.wr-field{width:240px}.wr-field-wide{width:380px;max-width:100%}.wr-group{position:relative;display:inline-flex}.wr-group-label{position:absolute;top:-8px;left:8px;z-index:2;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.wr-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.wr-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 14px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.wr-seg button:first-child{border-left:0}.wr-seg button:hover:not(.wr-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.wr-seg button:disabled{color:var(--p-text-muted-color, #64748b);opacity:.6;cursor:not-allowed}.wr-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.wr-seg button.wr-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.wr-seg.wr-seg-small{height:30px}.wr-seg.wr-seg-small button{padding:0 10px;font-size:12px}.wr-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.wr-btn{display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 14px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.wr-btn:hover:not(:disabled){background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.wr-btn:disabled{opacity:.55;cursor:not-allowed}.wr-btn.wr-btn-primary{height:39px;padding:0 18px;border-color:var(--p-primary-color, #6366f1);background:var(--p-primary-color, #6366f1);color:var(--p-primary-contrast-color, #fff);font-weight:500}.wr-btn.wr-btn-primary:hover:not(:disabled){background:var(--p-primary-color, #6366f1);color:var(--p-primary-contrast-color, #fff);filter:brightness(1.08)}.wr-link{margin-left:8px;padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.wr-link:hover{text-decoration:underline}.wr-alert{margin-top:10px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.wr-alert.wr-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.wr-alert.wr-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.wr-alert.wr-alert-busy{margin-top:0;margin-bottom:10px;border-color:var(--p-primary-color, #6366f1);background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.wr-panel{margin-top:14px;padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.wr-panel-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;margin-bottom:10px}.wr-title{font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--p-text-muted-color, #64748b)}.wr-spacer{flex:1 1 auto}.wr-window{color:var(--p-text-color, #334155);font-size:13px}.wr-muted{color:var(--p-text-muted-color, #64748b);font-size:12px}.wr-table-wrap{max-height:320px;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.wr-table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;color:var(--p-text-color, #334155)}.wr-table th{position:sticky;top:0;z-index:1;padding:6px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-size:12px;font-weight:500;white-space:nowrap;text-align:left}.wr-table td{padding:4px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap}.wr-num{text-align:right!important;font-variant-numeric:tabular-nums}.wr-row{cursor:pointer}.wr-row:hover td{background:var(--p-content-hover-background, #f8fafc)}.wr-row.wr-restart td:first-child{box-shadow:inset 3px 0 #f59e0b}.wr-row.wr-in-range td{background:var(--p-highlight-background, #eef2ff)}.wr-row.wr-edge td{color:var(--p-highlight-color, #4338ca);font-weight:600}.wr-badge{display:inline-flex;align-items:center;gap:4px;padding:0 7px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px}.wr-badge.wr-badge-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.wr-empty{padding:22px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.wr-footnote{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.wr-report-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 14px;padding-top:6px}.wr-summary{color:var(--p-text-color, #334155);font-size:13px}.wr-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.wr-frame{display:block;width:100%;height:calc(100vh - 240px);min-height:520px;margin-top:8px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:#fff;transition:opacity .15s}.wr-frame.wr-stale{opacity:.5}.wr-placeholder{display:flex;flex-direction:column;align-items:center;gap:10px;padding:70px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.wr-placeholder .fa{font-size:28px;opacity:.5}\n"], dependencies: [{ kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i9.EsFormSelectComponent, selector: "form-select", inputs: ["OptionsTemplate"] }, { kind: "component", type: i9.EsFormMultiselectComponent, selector: "form-multiselect", inputs: ["display", "InOutFormat", "FloatingLabel", "MaxShownElements"] }, { kind: "directive", type: i10.Widget, selector: "[widget]" }, { kind: "pipe", type: i1.LocalizePipe, name: "localize" }] }); }
2398
2401
  }
2399
2402
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: AdmWorkloadV2Component, decorators: [{
2400
2403
  type: Component,
2401
- args: [{ selector: "workload_v2", providers: [{ provide: LocalizationService, useClass: AdmWorkloadV2Loc }], standalone: false, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Workload report' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body\">\r\n <!-- Barra dei comandi: tipo, istanze, genera. Il report si chiede solo con il comando -->\r\n <div class=\"wr-toolbar\">\r\n <div class=\"wr-group\">\r\n <span class=\"wr-group-label\">{{'Tipo' | localize: lc}}</span>\r\n <div class=\"wr-seg\">\r\n <button type=\"button\" [class.wr-on]=\"live\" (click)=\"setLive(true)\"><span class=\"wr-live-dot\"></span>Live</button>\r\n <button type=\"button\" [class.wr-on]=\"!live\" [disabled]=\"!historyAvailable\" (click)=\"setLive(false)\"\r\n [title]=\"historyAvailable ? '' : ('Lo storico non \u00E8 attivo su questo ambiente: il report si pu\u00F2 produrre solo live.' | localize: lc)\">\r\n {{'Fra snapshot' | localize: lc}}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"wr-group wr-field-wide\">\r\n <span class=\"wr-group-label\">{{'Istanze' | localize: lc}}</span>\r\n <form-multiselect class=\"wr-fill\" [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instances\" (ngModelChange)=\"instancesChanged($event)\" name=\"instances\" [Source]=\"Instances\" [Placeholder]=\"clusterLabel\" [MaxShownElements]=\"2\"></form-multiselect>\r\n </div>\r\n <div class=\"wr-toolbar-end\">\r\n <button type=\"button\" class=\"wr-btn wr-btn-primary\" [disabled]=\"!generating && !canGenerate\" (click)=\"generateOrCancel()\"\r\n [title]=\"!generating && !canGenerate ? ('Scegli il primo e l\\'ultimo snapshot' | localize: lc) : ''\">\r\n @if (generating) {\r\n <i class=\"fa fa-times\"></i> {{'Annulla' | localize: lc}}\r\n } @else {\r\n <i class=\"fa fa-file-text-o\"></i> {{'Genera report' | localize: lc}}\r\n }\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Avvisi sulla finestra (W4): non bloccano la generazione -->\r\n @for (warning of warnings; track $index) {\r\n <div class=\"wr-alert wr-alert-warn\"><i class=\"fa fa-exclamation-triangle\"></i> {{warning}}</div>\r\n }\r\n @if (snapshotsLoaded && !historyAvailable) {\r\n <div class=\"wr-alert\"><i class=\"fa fa-info-circle\"></i> {{'Lo storico non \u00E8 attivo su questo ambiente: il report si pu\u00F2 produrre solo live.' | localize: lc}}</div>\r\n }\r\n\r\n <!-- Elenco degli snapshot, solo per il report fra snapshot -->\r\n @if (!live) {\r\n <div class=\"wr-panel\">\r\n <div class=\"wr-panel-header\">\r\n <span class=\"wr-title\">{{'Snapshot' | localize: lc}}</span>\r\n <div class=\"wr-seg wr-seg-small\">\r\n @for (p of Periods; track p.id) {\r\n <button type=\"button\" [class.wr-on]=\"period == p.id\" (click)=\"setPeriod(p.id)\">{{p.description}}</button>\r\n }\r\n </div>\r\n @if (snapshotsLoading) {\r\n <span class=\"wr-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n <span class=\"wr-spacer\"></span>\r\n @if (selectionWindow; as w) {\r\n <span class=\"wr-window\">\r\n {{'Dalle' | localize: lc}} <strong>{{local(w.from)}}</strong> {{'alle' | localize: lc}} <strong>{{local(w.to)}}</strong>\r\n ({{span(w.from, w.to)}})\r\n @if (selTo == null) {\r\n <span class=\"wr-muted\">&middot; {{\"scegli l'ultimo snapshot\" | localize: lc}}</span>\r\n }\r\n </span>\r\n <button type=\"button\" class=\"wr-link\" (click)=\"clearSelection()\">{{'Azzera' | localize: lc}}</button>\r\n } @else {\r\n <span class=\"wr-muted\">{{\"Un clic sceglie il primo snapshot, un secondo clic l'ultimo.\" | localize: lc}}</span>\r\n }\r\n </div>\r\n\r\n @if (snapshotsError) {\r\n <div class=\"wr-alert wr-alert-error\">{{snapshotsError}}</div>\r\n }\r\n\r\n <div class=\"wr-table-wrap\">\r\n <table class=\"wr-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"wr-num\">{{'Snapshot' | localize: lc}}</th>\r\n <th>{{'Inizio' | localize: lc}}</th>\r\n <th>{{'Fine' | localize: lc}}</th>\r\n <th class=\"wr-num\">{{'Durata' | localize: lc}}</th>\r\n <th class=\"wr-num\">{{'Istanze' | localize: lc}}</th>\r\n <th>{{'Manuale' | localize: lc}}</th>\r\n <th>{{'Riavvio' | localize: lc}}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (s of snapshots; track s.snapId) {\r\n <tr class=\"wr-row\" [class.wr-in-range]=\"inRange(s)\" [class.wr-edge]=\"isEdge(s)\" [class.wr-restart]=\"s.restart\" (click)=\"pick(s)\">\r\n <td class=\"wr-num\"><strong>{{s.snapId}}</strong></td>\r\n <td>{{local(s.beginIntervalTime)}}</td>\r\n <td>{{local(s.endIntervalTime)}}</td>\r\n <td class=\"wr-num\">{{span(s.beginIntervalTime, s.endIntervalTime)}}</td>\r\n <td class=\"wr-num\" [title]=\"instancesTitle(s)\">{{s.instances?.length ?? 0}}</td>\r\n <td>\r\n @if (s.manual) {\r\n <span class=\"wr-badge\"><i class=\"fa fa-hand-pointer-o\"></i> {{'Manuale' | localize: lc}}</span>\r\n }\r\n </td>\r\n <td>\r\n @if (s.restart) {\r\n <span class=\"wr-badge wr-badge-warn\" [title]=\"'Un\\'istanza \u00E8 ripartita: counter e meter non sono attendibili' | localize: lc\"><i class=\"fa fa-power-off\"></i> {{'Riavvio' | localize: lc}}</span>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (snapshotsLoaded && !snapshotsLoading && !snapshotsError && snapshots.length == 0 && historyAvailable) {\r\n <div class=\"wr-empty\">{{'Nessuno snapshot nel periodo scelto: prova con un periodo pi\u00F9 lungo.' | localize: lc}}</div>\r\n }\r\n </div>\r\n <div class=\"wr-footnote\">{{'Orari in ora locale' | localize: lc}} ({{zone}})</div>\r\n </div>\r\n }\r\n\r\n <!-- Report -->\r\n <div class=\"wr-panel wr-report\">\r\n @if (generating) {\r\n <div class=\"wr-alert wr-alert-busy\">\r\n <i class=\"fa fa-spinner fa-spin\"></i> {{'Generazione del report\u2026' | localize: lc}}\r\n <button type=\"button\" class=\"wr-link\" (click)=\"cancel()\">{{'Annulla' | localize: lc}}</button>\r\n </div>\r\n }\r\n @if (reportError) {\r\n <div class=\"wr-alert wr-alert-error\">{{'Il report non si pu\u00F2 produrre' | localize: lc}}: {{reportError}}</div>\r\n }\r\n\r\n @if (report) {\r\n <div class=\"wr-report-bar\">\r\n <div class=\"wr-summary\">\r\n @if (report.live) {\r\n <strong>Live</strong>\r\n } @else {\r\n <strong>{{'Snapshot' | localize: lc}} {{report.snapFrom}}\u2013{{report.snapTo}}</strong>\r\n }\r\n &middot; {{scopeLabel(report.instances)}}\r\n @if (!report.live && report.windowFrom) {\r\n &middot; {{'dalle' | localize: lc}} {{local(report.windowFrom)}} {{'alle' | localize: lc}} {{local(report.windowTo)}}\r\n }\r\n &middot; {{'generato alle' | localize: lc}} {{hhmm(report.generatedAt)}} ({{kilobytes(report.size)}})\r\n </div>\r\n <div class=\"wr-actions\">\r\n @if (report.sections.length > 0) {\r\n <div class=\"wr-field wr-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"section\" (ngModelChange)=\"goToSection($event)\" name=\"section\" [Source]=\"report.sections\" [Placeholder]=\"'Vai a\u2026' | localize: lc\"></form-select>\r\n </div>\r\n }\r\n <button type=\"button\" class=\"wr-btn\" (click)=\"download()\"><i class=\"fa fa-download\"></i> {{'Scarica' | localize: lc}}</button>\r\n <button type=\"button\" class=\"wr-btn\" (click)=\"openInTab()\"><i class=\"fa fa-external-link\"></i> {{'Apri in una scheda' | localize: lc}}</button>\r\n </div>\r\n </div>\r\n <div class=\"wr-footnote\"><i class=\"fa fa-clock-o\"></i> {{'Gli orari del report sono in UTC.' | localize: lc}}</div>\r\n <!-- Riquadro isolato e senza script: gli stili del report non toccano la pagina e le ancore dell'indice restano dentro (W8) -->\r\n <iframe #reportFrame class=\"wr-frame\" [class.wr-stale]=\"generating\" [srcdoc]=\"report.doc\" sandbox=\"allow-same-origin allow-popups\" title=\"Workload report\"></iframe>\r\n } @else if (!generating && !reportError) {\r\n <div class=\"wr-placeholder\">\r\n <i class=\"fa fa-file-text-o\"></i>\r\n {{'Scegli tipo e istanze, poi genera il report.' | localize: lc}}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}:host ::ng-deep .wr-noclear .p-select-clear-icon{display:none}:host ::ng-deep .wr-fill{display:block;width:100%}.wr-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px;padding-top:6px}.wr-toolbar-end{margin-left:auto}.wr-field{width:240px}.wr-field-wide{width:380px;max-width:100%}.wr-group{position:relative;display:inline-flex}.wr-group-label{position:absolute;top:-8px;left:8px;z-index:2;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.wr-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.wr-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 14px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.wr-seg button:first-child{border-left:0}.wr-seg button:hover:not(.wr-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.wr-seg button:disabled{color:var(--p-text-muted-color, #64748b);opacity:.6;cursor:not-allowed}.wr-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.wr-seg button.wr-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.wr-seg.wr-seg-small{height:30px}.wr-seg.wr-seg-small button{padding:0 10px;font-size:12px}.wr-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.wr-btn{display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 14px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.wr-btn:hover:not(:disabled){background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.wr-btn:disabled{opacity:.55;cursor:not-allowed}.wr-btn.wr-btn-primary{height:39px;padding:0 18px;border-color:var(--p-primary-color, #6366f1);background:var(--p-primary-color, #6366f1);color:var(--p-primary-contrast-color, #fff);font-weight:500}.wr-btn.wr-btn-primary:hover:not(:disabled){background:var(--p-primary-color, #6366f1);color:var(--p-primary-contrast-color, #fff);filter:brightness(1.08)}.wr-link{margin-left:8px;padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.wr-link:hover{text-decoration:underline}.wr-alert{margin-top:10px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.wr-alert.wr-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.wr-alert.wr-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.wr-alert.wr-alert-busy{margin-top:0;margin-bottom:10px;border-color:var(--p-primary-color, #6366f1);background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.wr-panel{margin-top:14px;padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.wr-panel-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;margin-bottom:10px}.wr-title{font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--p-text-muted-color, #64748b)}.wr-spacer{flex:1 1 auto}.wr-window{color:var(--p-text-color, #334155);font-size:13px}.wr-muted{color:var(--p-text-muted-color, #64748b);font-size:12px}.wr-table-wrap{max-height:320px;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.wr-table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;color:var(--p-text-color, #334155)}.wr-table th{position:sticky;top:0;z-index:1;padding:6px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-size:12px;font-weight:500;white-space:nowrap;text-align:left}.wr-table td{padding:4px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap}.wr-num{text-align:right!important;font-variant-numeric:tabular-nums}.wr-row{cursor:pointer}.wr-row:hover td{background:var(--p-content-hover-background, #f8fafc)}.wr-row.wr-restart td:first-child{box-shadow:inset 3px 0 #f59e0b}.wr-row.wr-in-range td{background:var(--p-highlight-background, #eef2ff)}.wr-row.wr-edge td{color:var(--p-highlight-color, #4338ca);font-weight:600}.wr-badge{display:inline-flex;align-items:center;gap:4px;padding:0 7px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px}.wr-badge.wr-badge-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.wr-empty{padding:22px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.wr-footnote{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.wr-report-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 14px;padding-top:6px}.wr-summary{color:var(--p-text-color, #334155);font-size:13px}.wr-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.wr-frame{display:block;width:100%;height:calc(100vh - 240px);min-height:520px;margin-top:8px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:#fff;transition:opacity .15s}.wr-frame.wr-stale{opacity:.5}.wr-placeholder{display:flex;flex-direction:column;align-items:center;gap:10px;padding:70px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.wr-placeholder .fa{font-size:28px;opacity:.5}\n"] }]
2404
+ args: [{ selector: "workload_v2", providers: [{ provide: LocalizationService, useClass: AdmWorkloadV2Loc }], standalone: false, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Workload report' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body\">\r\n <!-- Barra dei comandi: tipo, istanze, genera. Il report si chiede solo con il comando -->\r\n <div class=\"wr-toolbar\">\r\n <div class=\"wr-group\">\r\n <span class=\"wr-group-label\">{{'Tipo' | localize: lc}}</span>\r\n <div class=\"wr-seg\">\r\n <button type=\"button\" [class.wr-on]=\"live\" (click)=\"setLive(true)\"><span class=\"wr-live-dot\"></span>Live</button>\r\n <button type=\"button\" [class.wr-on]=\"!live\" [disabled]=\"!historyAvailable\" (click)=\"setLive(false)\"\r\n [title]=\"historyAvailable ? '' : ('Lo storico non \u00E8 attivo su questo ambiente: il report si pu\u00F2 produrre solo live.' | localize: lc)\">\r\n {{'Fra snapshot' | localize: lc}}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"wr-group wr-field-wide\">\r\n <span class=\"wr-group-label\">{{'Istanze' | localize: lc}}</span>\r\n <form-multiselect class=\"wr-fill\" [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instances\" (ngModelChange)=\"instancesChanged($event)\" name=\"instances\" [Source]=\"Instances\" [Placeholder]=\"clusterLabel\" [MaxShownElements]=\"2\"></form-multiselect>\r\n </div>\r\n <div class=\"wr-toolbar-end\">\r\n <button type=\"button\" class=\"wr-btn wr-btn-primary\" [disabled]=\"!generating && !canGenerate\" (click)=\"generateOrCancel()\"\r\n [title]=\"!generating && !canGenerate ? ('Scegli il primo e l\\'ultimo snapshot' | localize: lc) : ''\">\r\n @if (generating) {\r\n <i class=\"fa fa-times\"></i> {{'Annulla' | localize: lc}}\r\n } @else {\r\n <i class=\"fa fa-file-text\"></i> {{'Genera report' | localize: lc}}\r\n }\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Avvisi sulla finestra (W4): non bloccano la generazione -->\r\n @for (warning of warnings; track $index) {\r\n <div class=\"wr-alert wr-alert-warn\"><i class=\"fa fa-exclamation-triangle\"></i> {{warning}}</div>\r\n }\r\n @if (snapshotsLoaded && !historyAvailable) {\r\n <div class=\"wr-alert\"><i class=\"fa fa-info-circle\"></i> {{'Lo storico non \u00E8 attivo su questo ambiente: il report si pu\u00F2 produrre solo live.' | localize: lc}}</div>\r\n }\r\n\r\n <!-- Elenco degli snapshot, solo per il report fra snapshot -->\r\n @if (!live) {\r\n <div class=\"wr-panel\">\r\n <div class=\"wr-panel-header\">\r\n <span class=\"wr-title\">{{'Snapshot' | localize: lc}}</span>\r\n <div class=\"wr-seg wr-seg-small\">\r\n @for (p of Periods; track p.id) {\r\n <button type=\"button\" [class.wr-on]=\"period == p.id\" (click)=\"setPeriod(p.id)\">{{p.description}}</button>\r\n }\r\n </div>\r\n @if (snapshotsLoading) {\r\n <span class=\"wr-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n <span class=\"wr-spacer\"></span>\r\n @if (selectionWindow; as w) {\r\n <span class=\"wr-window\">\r\n {{'Dalle' | localize: lc}} <strong>{{local(w.from)}}</strong> {{'alle' | localize: lc}} <strong>{{local(w.to)}}</strong>\r\n ({{span(w.from, w.to)}})\r\n @if (selTo == null) {\r\n <span class=\"wr-muted\">&middot; {{\"scegli l'ultimo snapshot\" | localize: lc}}</span>\r\n }\r\n </span>\r\n <button type=\"button\" class=\"wr-link\" (click)=\"clearSelection()\">{{'Azzera' | localize: lc}}</button>\r\n } @else {\r\n <span class=\"wr-muted\">{{\"Un clic sceglie il primo snapshot, un secondo clic l'ultimo.\" | localize: lc}}</span>\r\n }\r\n </div>\r\n\r\n @if (snapshotsError) {\r\n <div class=\"wr-alert wr-alert-error\">{{snapshotsError}}</div>\r\n }\r\n\r\n <div class=\"wr-table-wrap\">\r\n <table class=\"wr-table\">\r\n <thead>\r\n <tr>\r\n <th class=\"wr-num\">{{'Snapshot' | localize: lc}}</th>\r\n <th>{{'Inizio' | localize: lc}}</th>\r\n <th>{{'Fine' | localize: lc}}</th>\r\n <th class=\"wr-num\">{{'Durata' | localize: lc}}</th>\r\n <th class=\"wr-num\">{{'Istanze' | localize: lc}}</th>\r\n <th>{{'Manuale' | localize: lc}}</th>\r\n <th>{{'Riavvio' | localize: lc}}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (s of snapshots; track s.snapId) {\r\n <tr class=\"wr-row\" [class.wr-in-range]=\"inRange(s)\" [class.wr-edge]=\"isEdge(s)\" [class.wr-restart]=\"s.restart\" (click)=\"pick(s)\">\r\n <td class=\"wr-num\"><strong>{{s.snapId}}</strong></td>\r\n <td>{{local(s.beginIntervalTime)}}</td>\r\n <td>{{local(s.endIntervalTime)}}</td>\r\n <td class=\"wr-num\">{{span(s.beginIntervalTime, s.endIntervalTime)}}</td>\r\n <td class=\"wr-num\" [title]=\"instancesTitle(s)\">{{s.instances?.length ?? 0}}</td>\r\n <td>\r\n @if (s.manual) {\r\n <span class=\"wr-badge\"><i class=\"fa fa-hand-pointer\"></i> {{'Manuale' | localize: lc}}</span>\r\n }\r\n </td>\r\n <td>\r\n @if (s.restart) {\r\n <span class=\"wr-badge wr-badge-warn\" [title]=\"'Un\\'istanza \u00E8 ripartita: counter e meter non sono attendibili' | localize: lc\"><i class=\"fa fa-power-off\"></i> {{'Riavvio' | localize: lc}}</span>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (snapshotsLoaded && !snapshotsLoading && !snapshotsError && snapshots.length == 0 && historyAvailable) {\r\n <div class=\"wr-empty\">{{'Nessuno snapshot nel periodo scelto: prova con un periodo pi\u00F9 lungo.' | localize: lc}}</div>\r\n }\r\n </div>\r\n <div class=\"wr-footnote\">{{'Orari in ora locale' | localize: lc}} ({{zone}})</div>\r\n </div>\r\n }\r\n\r\n <!-- Report -->\r\n <div class=\"wr-panel wr-report\">\r\n @if (generating) {\r\n <div class=\"wr-alert wr-alert-busy\">\r\n <i class=\"fa fa-spinner fa-spin\"></i> {{'Generazione del report\u2026' | localize: lc}}\r\n <button type=\"button\" class=\"wr-link\" (click)=\"cancel()\">{{'Annulla' | localize: lc}}</button>\r\n </div>\r\n }\r\n @if (reportError) {\r\n <div class=\"wr-alert wr-alert-error\">{{'Il report non si pu\u00F2 produrre' | localize: lc}}: {{reportError}}</div>\r\n }\r\n\r\n @if (report) {\r\n <div class=\"wr-report-bar\">\r\n <div class=\"wr-summary\">\r\n @if (report.live) {\r\n <strong>Live</strong>\r\n } @else {\r\n <strong>{{'Snapshot' | localize: lc}} {{report.snapFrom}}\u2013{{report.snapTo}}</strong>\r\n }\r\n &middot; {{scopeLabel(report.instances)}}\r\n @if (!report.live && report.windowFrom) {\r\n &middot; {{'dalle' | localize: lc}} {{local(report.windowFrom)}} {{'alle' | localize: lc}} {{local(report.windowTo)}}\r\n }\r\n &middot; {{'generato alle' | localize: lc}} {{hhmm(report.generatedAt)}} ({{kilobytes(report.size)}})\r\n </div>\r\n <div class=\"wr-actions\">\r\n @if (report.sections.length > 0) {\r\n <div class=\"wr-field wr-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"section\" (ngModelChange)=\"goToSection($event)\" name=\"section\" [Source]=\"report.sections\" [Placeholder]=\"'Vai a\u2026' | localize: lc\"></form-select>\r\n </div>\r\n }\r\n <button type=\"button\" class=\"wr-btn\" (click)=\"download()\"><i class=\"fa fa-download\"></i> {{'Scarica' | localize: lc}}</button>\r\n <button type=\"button\" class=\"wr-btn\" (click)=\"openInTab()\"><i class=\"fa fa-external-link\"></i> {{'Apri in una scheda' | localize: lc}}</button>\r\n </div>\r\n </div>\r\n <div class=\"wr-footnote\"><i class=\"fa fa-clock\"></i> {{'Gli orari del report sono in UTC.' | localize: lc}}</div>\r\n <!-- Riquadro isolato e senza script: gli stili del report non toccano la pagina e le ancore dell'indice restano dentro (W8) -->\r\n <iframe #reportFrame class=\"wr-frame\" [class.wr-stale]=\"generating\" [srcdoc]=\"report.doc\" sandbox=\"allow-same-origin allow-popups\" title=\"Workload report\"></iframe>\r\n } @else if (!generating && !reportError) {\r\n <div class=\"wr-placeholder\">\r\n <i class=\"fa fa-file-text\"></i>\r\n {{'Scegli tipo e istanze, poi genera il report.' | localize: lc}}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}:host ::ng-deep .wr-noclear .p-select-clear-icon{display:none}:host ::ng-deep .wr-fill{display:block;width:100%}.wr-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px;padding-top:6px}.wr-toolbar-end{margin-left:auto}.wr-field{width:240px}.wr-field-wide{width:380px;max-width:100%}.wr-group{position:relative;display:inline-flex}.wr-group-label{position:absolute;top:-8px;left:8px;z-index:2;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.wr-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.wr-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 14px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.wr-seg button:first-child{border-left:0}.wr-seg button:hover:not(.wr-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.wr-seg button:disabled{color:var(--p-text-muted-color, #64748b);opacity:.6;cursor:not-allowed}.wr-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.wr-seg button.wr-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.wr-seg.wr-seg-small{height:30px}.wr-seg.wr-seg-small button{padding:0 10px;font-size:12px}.wr-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.wr-btn{display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 14px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.wr-btn:hover:not(:disabled){background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.wr-btn:disabled{opacity:.55;cursor:not-allowed}.wr-btn.wr-btn-primary{height:39px;padding:0 18px;border-color:var(--p-primary-color, #6366f1);background:var(--p-primary-color, #6366f1);color:var(--p-primary-contrast-color, #fff);font-weight:500}.wr-btn.wr-btn-primary:hover:not(:disabled){background:var(--p-primary-color, #6366f1);color:var(--p-primary-contrast-color, #fff);filter:brightness(1.08)}.wr-link{margin-left:8px;padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.wr-link:hover{text-decoration:underline}.wr-alert{margin-top:10px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.wr-alert.wr-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.wr-alert.wr-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.wr-alert.wr-alert-busy{margin-top:0;margin-bottom:10px;border-color:var(--p-primary-color, #6366f1);background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.wr-panel{margin-top:14px;padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.wr-panel-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;margin-bottom:10px}.wr-title{font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--p-text-muted-color, #64748b)}.wr-spacer{flex:1 1 auto}.wr-window{color:var(--p-text-color, #334155);font-size:13px}.wr-muted{color:var(--p-text-muted-color, #64748b);font-size:12px}.wr-table-wrap{max-height:320px;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.wr-table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;color:var(--p-text-color, #334155)}.wr-table th{position:sticky;top:0;z-index:1;padding:6px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-size:12px;font-weight:500;white-space:nowrap;text-align:left}.wr-table td{padding:4px 10px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap}.wr-num{text-align:right!important;font-variant-numeric:tabular-nums}.wr-row{cursor:pointer}.wr-row:hover td{background:var(--p-content-hover-background, #f8fafc)}.wr-row.wr-restart td:first-child{box-shadow:inset 3px 0 #f59e0b}.wr-row.wr-in-range td{background:var(--p-highlight-background, #eef2ff)}.wr-row.wr-edge td{color:var(--p-highlight-color, #4338ca);font-weight:600}.wr-badge{display:inline-flex;align-items:center;gap:4px;padding:0 7px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px}.wr-badge.wr-badge-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.wr-empty{padding:22px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.wr-footnote{margin-top:6px;color:var(--p-text-muted-color, #64748b);font-size:12px}.wr-report-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 14px;padding-top:6px}.wr-summary{color:var(--p-text-color, #334155);font-size:13px}.wr-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.wr-frame{display:block;width:100%;height:calc(100vh - 240px);min-height:520px;margin-top:8px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:#fff;transition:opacity .15s}.wr-frame.wr-stale{opacity:.5}.wr-placeholder{display:flex;flex-direction:column;align-items:center;gap:10px;padding:70px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.wr-placeholder .fa{font-size:28px;opacity:.5}\n"] }]
2402
2405
  }], ctorParameters: () => [{ type: i1.LocalizationService }, { type: i3.PreferencesService }, { type: i1$1.InterComService }, { type: i4.ActivatedRoute }, { type: i5$1.DomSanitizer }, { type: AdminModuleBaseService }], propDecorators: { reportFrame: [{
2403
2406
  type: ViewChild,
2404
2407
  args: ["reportFrame"]
@@ -2447,6 +2450,7 @@ class AdmMetricsV2Loc extends LocalizationService {
2447
2450
  super.set("it->en", "Istanze", ["Instances"]);
2448
2451
  super.set("it->en", "Tutto il cluster", ["Whole cluster"]);
2449
2452
  super.set("it->en", "istanze", ["instances"]);
2453
+ super.set("it->en", "istanza", ["instance"]);
2450
2454
  super.set("it->en", "Aggiornato alle", ["Updated at"]);
2451
2455
  super.set("it->en", "Pausa", ["Pause"]);
2452
2456
  super.set("it->en", "Riprendi", ["Resume"]);
@@ -2532,7 +2536,8 @@ class Mv2TipRow {
2532
2536
  }
2533
2537
  const LEFT = 56;
2534
2538
  const RIGHT = 10;
2535
- const TOP = 8;
2539
+ // Spazio in alto per l'unità, che sta sopra la prima tacca
2540
+ const TOP = 20;
2536
2541
  const BOTTOM = 20;
2537
2542
  const STEPS_MS = [60, 120, 300, 600, 900, 1800, 3600, 7200, 10800, 21600, 43200, 86400, 172800, 604800].map(t => t * 1000);
2538
2543
  // Grafico SVG delle metriche v2: lo stesso asse dei tempi per tutti i pannelli, cursore e zoom condivisi tramite la pagina.
@@ -2652,6 +2657,12 @@ class MetricsV2ChartComponent {
2652
2657
  case "line":
2653
2658
  case "step":
2654
2659
  paths.push({ key: s.key, d: this.linePath(points, s.kind == "step"), color: s.color, fill: false, dash: s.dash ?? null, opacity: s.opacity ?? 1 });
2660
+ // Un punto senza vicini (per esempio la durata di un timer con poche chiamate) come linea non si vedrebbe: diventa un pallino
2661
+ if ((s.opacity ?? 1) > 0)
2662
+ points.forEach((p, i) => {
2663
+ if ((i == 0 || p.gap) && (i == points.length - 1 || points[i + 1].gap))
2664
+ dots.push({ key: `${s.key}~${i}`, x: this.x(p.t), y: this.y(p.v), color: s.color });
2665
+ });
2655
2666
  break;
2656
2667
  case "band":
2657
2668
  paths.push({ key: s.key, d: this.bandPath(points), color: s.color, fill: true, dash: null, opacity: s.opacity ?? 0.2 });
@@ -2787,7 +2798,7 @@ class MetricsV2ChartComponent {
2787
2798
  <text class="mv2c-xlabel" [attr.x]="tick.pos" [attr.y]="height - 5">{{tick.label}}</text>
2788
2799
  }
2789
2800
  @if (unit) {
2790
- <text class="mv2c-unit" [attr.x]="4" [attr.y]="10">{{unit}}</text>
2801
+ <text class="mv2c-unit" [attr.x]="4" [attr.y]="11">{{unit}}</text>
2791
2802
  }
2792
2803
  @for (mark of markTicks; track mark.key) {
2793
2804
  <line class="mv2c-mark" [class.mv2c-mark-restart]="mark.kind == 'restart'" [class.mv2c-mark-snapshot]="mark.kind == 'snapshot'" [attr.x1]="mark.pos" [attr.x2]="mark.pos" [attr.y1]="top" [attr.y2]="height - bottom" />
@@ -2835,7 +2846,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImpo
2835
2846
  <text class="mv2c-xlabel" [attr.x]="tick.pos" [attr.y]="height - 5">{{tick.label}}</text>
2836
2847
  }
2837
2848
  @if (unit) {
2838
- <text class="mv2c-unit" [attr.x]="4" [attr.y]="10">{{unit}}</text>
2849
+ <text class="mv2c-unit" [attr.x]="4" [attr.y]="11">{{unit}}</text>
2839
2850
  }
2840
2851
  @for (mark of markTicks; track mark.key) {
2841
2852
  <line class="mv2c-mark" [class.mv2c-mark-restart]="mark.kind == 'restart'" [class.mv2c-mark-snapshot]="mark.kind == 'snapshot'" [attr.x1]="mark.pos" [attr.x2]="mark.pos" [attr.y1]="top" [attr.y2]="height - bottom" />
@@ -3021,7 +3032,7 @@ class AdmMetricsV2Component {
3021
3032
  }
3022
3033
  // #region Comandi
3023
3034
  get clusterLabel() {
3024
- return this.Instances.length ? `${this.lc.loc("Tutto il cluster")} (${this.Instances.length} ${this.lc.loc("istanze")})` : this.lc.loc("Tutto il cluster");
3035
+ return this.Instances.length ? `${this.lc.loc("Tutto il cluster")} (${this.Instances.length} ${this.Instances.length == 1 ? this.lc.loc("istanza") : this.lc.loc("istanze")})` : this.lc.loc("Tutto il cluster");
3025
3036
  }
3026
3037
  get zone() {
3027
3038
  return `UTC${dayjs().format("Z")}`;
@@ -3792,11 +3803,11 @@ class AdmMetricsV2Component {
3792
3803
  this.localStorage.setItem(STORAGE_KEY$1, settings).subscribe();
3793
3804
  }
3794
3805
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: AdmMetricsV2Component, deps: [{ token: i1$1.DateService }, { token: i1.LocalizationService }, { token: i3.PreferencesService }, { token: i1$1.InterComService }, { token: i4.ActivatedRoute }, { token: AdminModuleBaseService }], target: i0.ɵɵFactoryTarget.Component }); }
3795
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.34", type: AdmMetricsV2Component, isStandalone: false, selector: "metrics_v2", providers: [{ provide: LocalizationService, useClass: AdmMetricsV2Loc }], ngImport: i0, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Metriche di Sistema' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body mv2-body\">\r\n <!-- Barra dei comandi: sorgente, finestra, istanze, vista, aggiornamento -->\r\n <div class=\"mv2-toolbar\">\r\n <div class=\"mv2-group\">\r\n <span class=\"mv2-group-label\">{{'Sorgente' | localize: lc}}</span>\r\n <div class=\"mv2-seg\">\r\n @for (o of Sources; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"source == o.id\" [disabled]=\"o.id != 'live' && !historyAvailable\" (click)=\"setSource(o.id)\"\r\n [title]=\"o.id != 'live' && !historyAvailable ? ('Lo storico non \u00E8 attivo su questo ambiente: ci sono solo i dati live.' | localize: lc) : ''\">\r\n @if (o.id == 'live') {\r\n <span class=\"mv2-live-dot\" [class.mv2-live-paused]=\"paused\"></span>\r\n }\r\n {{o.description}}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (source == 'live') {\r\n <div class=\"mv2-group\">\r\n <span class=\"mv2-group-label\">{{'Finestra' | localize: lc}}</span>\r\n <div class=\"mv2-seg\">\r\n @for (o of LiveWindows; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"liveMinutes == o.id\" (click)=\"setLiveMinutes(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n } @else if (source == 'period') {\r\n <div class=\"mv2-cluster\">\r\n <div class=\"mv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterfrom\" (ngModelChange)=\"filterfrom = $event; datesChanged()\" name=\"filterfrom\" [Placeholder]=\"'Dal' | localize: lc\"></form-datetime>\r\n </div>\r\n <div class=\"mv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterto\" (ngModelChange)=\"filterto = $event; datesChanged()\" name=\"filterto\" [Placeholder]=\"'Al' | localize: lc\"></form-datetime>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"mv2-cluster\">\r\n <div class=\"mv2-field mv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"snapFromId\" (ngModelChange)=\"snapFromId = $event; snapshotsChanged()\" name=\"snapFrom\" [Source]=\"SnapshotOptions\" [Placeholder]=\"'Dallo snapshot' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"mv2-field mv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"snapToId\" (ngModelChange)=\"snapToId = $event; snapshotsChanged()\" name=\"snapTo\" [Source]=\"SnapshotOptions\" [Placeholder]=\"'Allo snapshot' | localize: lc\"></form-select>\r\n </div>\r\n @if (snapshotWindow; as w) {\r\n <span class=\"mv2-muted\">{{'Dalle' | localize: lc}} {{local(w.from)}} {{'alle' | localize: lc}} {{local(w.to)}}</span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"mv2-group mv2-field-wide\">\r\n <span class=\"mv2-group-label\">{{'Istanze' | localize: lc}}</span>\r\n <form-multiselect class=\"mv2-fill\" [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instances\" (ngModelChange)=\"instancesChanged($event)\" name=\"instances\" [Source]=\"Instances\" [Placeholder]=\"clusterLabel\" [MaxShownElements]=\"2\"></form-multiselect>\r\n </div>\r\n\r\n <div class=\"mv2-cluster mv2-cluster-end\">\r\n @if (source == 'live') {\r\n <span class=\"mv2-muted\">\r\n @if (dataLoading) {\r\n <i class=\"fa fa-spinner fa-spin\"></i>\r\n }\r\n @if (lastUpdate) {\r\n {{'Aggiornato alle' | localize: lc}} {{hhmmss(lastUpdate)}}\r\n }\r\n </span>\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"togglePause()\">\r\n <i class=\"fa\" [class.fa-pause]=\"!paused\" [class.fa-play]=\"paused\"></i> {{(paused ? 'Riprendi' : 'Pausa') | localize: lc}}\r\n </button>\r\n } @else if (dataLoading) {\r\n <span class=\"mv2-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n <div class=\"mv2-seg\">\r\n @for (o of Views; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"view == o.id\" (click)=\"setView(o.id)\">\r\n <i class=\"fa\" [class.fa-line-chart]=\"o.id == 'charts'\" [class.fa-table]=\"o.id == 'table'\"></i> {{o.description}}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Avvisi -->\r\n @for (warning of warnings; track $index) {\r\n <div class=\"mv2-alert mv2-alert-warn\"><i class=\"fa fa-exclamation-triangle\"></i> {{warning}}</div>\r\n }\r\n @if (snapshotsLoaded && !historyAvailable) {\r\n <div class=\"mv2-alert\"><i class=\"fa fa-info-circle\"></i> {{'Lo storico non \u00E8 attivo su questo ambiente: ci sono solo i dati live.' | localize: lc}}</div>\r\n }\r\n @if (dataError) {\r\n <div class=\"mv2-alert mv2-alert-error\">{{dataError}}</div>\r\n }\r\n\r\n <div class=\"mv2-main\">\r\n <!-- Catalogo -->\r\n <aside class=\"mv2-panel mv2-catalog\">\r\n <div class=\"mv2-field-full\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"search\" (ngModelChange)=\"search = $event; buildGroups()\" name=\"search\" [Placeholder]=\"'Cerca una metrica\u2026' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"mv2-presets\">\r\n @for (p of Presets; track p) {\r\n <button type=\"button\" class=\"mv2-chip\" (click)=\"applyPreset(p)\">{{p | localize: lc}}</button>\r\n }\r\n </div>\r\n <div class=\"mv2-counter\">\r\n <span>{{selected.length}} {{'di' | localize: lc}} {{Max}} {{'metriche scelte' | localize: lc}}</span>\r\n @if (selected.length > 0) {\r\n <button type=\"button\" class=\"mv2-link\" (click)=\"clearSelection()\">{{'Togli tutte' | localize: lc}}</button>\r\n }\r\n </div>\r\n\r\n @if (catalogLoading) {\r\n <div class=\"mv2-muted mv2-pad\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</div>\r\n }\r\n @if (catalogError) {\r\n <div class=\"mv2-alert mv2-alert-error\">{{catalogError}}</div>\r\n }\r\n @for (group of groups; track group.type) {\r\n <div class=\"mv2-cat-group\">\r\n <div class=\"mv2-cat-title\">{{group.label}} <span class=\"mv2-muted\">{{group.count}}</span></div>\r\n @for (entry of group.entries; track entry.info.name) {\r\n <div class=\"mv2-cat-item\" [class.mv2-cat-disabled]=\"!canSelect(entry.info.name)\">\r\n <label class=\"mv2-check\">\r\n <input type=\"checkbox\" [checked]=\"isSelected(entry.info.name)\" [disabled]=\"!canSelect(entry.info.name)\" (change)=\"toggleMetric(entry.info.name)\" />\r\n <span class=\"mv2-cat-name\" [title]=\"entry.info.name\">{{entry.info.name}}</span>\r\n </label>\r\n <span class=\"mv2-cat-meta\">\r\n {{catalogUnit(entry.info)}}\r\n @if (instancesLabel(entry.info)) {\r\n <span class=\"mv2-cat-inst\" [title]=\"entry.info.instances.join('\\n')\">{{instancesLabel(entry.info)}}</span>\r\n }\r\n </span>\r\n @if (entry.items.length > 0) {\r\n <button type=\"button\" class=\"mv2-caret\" (click)=\"entry.open = !entry.open\" [title]=\"'Voci' | localize: lc\">\r\n <i class=\"fa\" [class.fa-caret-down]=\"entry.open\" [class.fa-caret-right]=\"!entry.open\"></i> {{entry.items.length}}\r\n </button>\r\n }\r\n </div>\r\n @if (entry.open && entry.items.length > 0) {\r\n <div class=\"mv2-cat-items\">\r\n <button type=\"button\" class=\"mv2-link\" (click)=\"addItems(entry)\">{{addItemsLabel(entry)}}</button>\r\n @for (item of entry.items; track item.name) {\r\n <div class=\"mv2-cat-item mv2-cat-sub\" [class.mv2-cat-disabled]=\"!canSelect(item.name)\">\r\n <label class=\"mv2-check\">\r\n <input type=\"checkbox\" [checked]=\"isSelected(item.name)\" [disabled]=\"!canSelect(item.name)\" (change)=\"toggleMetric(item.name)\" />\r\n <span class=\"mv2-cat-name\" [title]=\"item.name\">{{item.name.substring(entry.info.name.length + 3)}}</span>\r\n </label>\r\n @if (instancesLabel(item)) {\r\n <span class=\"mv2-cat-inst\" [title]=\"item.instances.join('\\n')\">{{instancesLabel(item)}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n </aside>\r\n\r\n <!-- Grafici, tessere e tabella -->\r\n <section class=\"mv2-area\">\r\n @if (selected.length == 0) {\r\n <div class=\"mv2-panel mv2-placeholder\">\r\n <i class=\"fa fa-line-chart\"></i>\r\n {{'Scegli una o pi\u00F9 metriche dal catalogo.' | localize: lc}}\r\n </div>\r\n } @else {\r\n <!-- Tessere dei valori correnti -->\r\n <div class=\"mv2-tiles\">\r\n @for (tile of tiles; track tile.info.name) {\r\n <div class=\"mv2-tile\">\r\n <div class=\"mv2-tile-name\" [title]=\"tile.info.name\">{{tile.info.name}}</div>\r\n @for (row of tile.rows; track row.instance) {\r\n <div class=\"mv2-tile-row\">\r\n <span class=\"mv2-dot\" [style.background]=\"row.color\" [title]=\"row.instance\"></span>\r\n <strong>{{row.value}}</strong>\r\n @if (row.extra) {\r\n <span class=\"mv2-muted\">{{row.extra}}</span>\r\n }\r\n </div>\r\n } @empty {\r\n <div class=\"mv2-muted\">\u2014</div>\r\n }\r\n <svg class=\"mv2-spark\" viewBox=\"0 0 120 28\" preserveAspectRatio=\"none\" aria-hidden=\"true\">\r\n @for (spark of tile.sparks; track $index) {\r\n <path [attr.d]=\"spark.d\" [attr.stroke]=\"spark.color\" fill=\"none\" stroke-width=\"1.3\" vector-effect=\"non-scaling-stroke\" />\r\n }\r\n </svg>\r\n @if (tile.time) {\r\n <div class=\"mv2-muted mv2-small\">{{'alle' | localize: lc}} {{tile.time}}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Legenda comune: un clic nasconde o mostra l'istanza ovunque -->\r\n <div class=\"mv2-legend-bar\">\r\n <div class=\"mv2-legend\">\r\n @for (item of legend; track item.instance) {\r\n <button type=\"button\" class=\"mv2-legend-item\" [class.mv2-legend-off]=\"item.hidden\" (click)=\"toggleInstance(item.instance)\">\r\n <span class=\"mv2-dot\" [style.background]=\"item.color\"></span>{{item.instance}}\r\n </button>\r\n }\r\n </div>\r\n <span class=\"mv2-muted mv2-small\">{{'Orari in ora locale' | localize: lc}} ({{zone}}) &middot; {{'trascina su un grafico per lo zoom' | localize: lc}}</span>\r\n @if (viewFrom != null) {\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"resetZoom()\"><i class=\"fa fa-arrows-h\"></i> {{'Finestra intera' | localize: lc}}</button>\r\n }\r\n </div>\r\n\r\n @if (view == 'charts') {\r\n @for (panel of panels; track panel.info.name) {\r\n <div class=\"mv2-panel mv2-chart-panel\">\r\n <div class=\"mv2-panel-header\">\r\n <span class=\"mv2-panel-title\">{{panel.info.name}}</span>\r\n <span class=\"mv2-type\">{{Type[panel.info.metricType]}}</span>\r\n <span class=\"mv2-muted\">{{mainUnit(panel.info)}}</span>\r\n <span class=\"mv2-spacer\"></span>\r\n @if (panel.alts.length > 1) {\r\n <div class=\"mv2-seg mv2-seg-small\">\r\n @for (o of panel.alts; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"panel.alt == o.id\" (click)=\"setAlt(panel, o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n }\r\n <button type=\"button\" class=\"mv2-icon-btn\" [title]=\"'Togli' | localize: lc\" (click)=\"removeMetric(panel.info.name)\">&times;</button>\r\n </div>\r\n @if (panel.empty) {\r\n <div class=\"mv2-empty\">\r\n @if (dataLoading) {\r\n <i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}\r\n } @else {\r\n {{emptyLabel(panel.info.name)}}\r\n }\r\n </div>\r\n } @else {\r\n @for (chart of panel.charts; track chart.key) {\r\n <mv2-chart [series]=\"chart.series\" [from]=\"chartFrom\" [to]=\"chartTo\" [height]=\"chart.height\" [unit]=\"chart.unit\" [marks]=\"marks\"\r\n [cursor]=\"cursor\" [format]=\"format\" (cursorChange)=\"cursor = $event\" (zoom)=\"zoomTo($event)\"></mv2-chart>\r\n }\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @for (section of tables; track section.info.name) {\r\n <div class=\"mv2-panel\">\r\n <div class=\"mv2-panel-header\">\r\n <span class=\"mv2-panel-title\">{{section.info.name}}</span>\r\n <span class=\"mv2-type\">{{Type[section.info.metricType]}}</span>\r\n <span class=\"mv2-spacer\"></span>\r\n @if (section.total > 0) {\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"exportCsv(section)\"><i class=\"fa fa-download\"></i> {{'Esporta CSV' | localize: lc}}</button>\r\n }\r\n </div>\r\n @if (section.total == 0) {\r\n <div class=\"mv2-empty\">{{emptyLabel(section.info.name)}}</div>\r\n } @else {\r\n <div class=\"mv2-table-wrap\">\r\n <table class=\"mv2-table\">\r\n <thead>\r\n <tr>\r\n @for (column of section.columns; track column.key) {\r\n <th [class.mv2-num]=\"column.num\" (click)=\"sortBy(section, column)\">\r\n {{column.label}}\r\n @if (section.sortKey == column.key) {\r\n <i class=\"fa\" [class.fa-caret-down]=\"section.sortDesc\" [class.fa-caret-up]=\"!section.sortDesc\"></i>\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of shownRows(section); track $index) {\r\n <tr>\r\n @for (column of section.columns; track column.key) {\r\n <td [class.mv2-num]=\"column.num\">\r\n @if (column.key == 'instance') {\r\n <span class=\"mv2-dot\" [style.background]=\"color(row['instance'])\"></span>\r\n }\r\n {{cell(row, column)}}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n @if (section.total > section.rows.length || section.total > 300) {\r\n <div class=\"mv2-muted mv2-small mv2-pad\">{{'Mostrate le prime 300 righe di' | localize: lc}} {{section.total}}; {{\"l'esportazione le comprende tutte.\" | localize: lc}}</div>\r\n }\r\n }\r\n </div>\r\n }\r\n }\r\n }\r\n </section>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}:host ::ng-deep .mv2-noclear .p-select-clear-icon{display:none}:host ::ng-deep .mv2-fill{display:block;width:100%}.mv2-body{container-type:inline-size}.mv2-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px;padding-top:6px}.mv2-cluster{display:flex;flex-wrap:wrap;align-items:center;gap:10px}.mv2-cluster-end{margin-left:auto}.mv2-field{width:200px}.mv2-field-wide{width:340px;max-width:100%}.mv2-field-full{width:100%}.mv2-group{position:relative;display:inline-flex}.mv2-group-label{position:absolute;top:-8px;left:8px;z-index:2;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.mv2-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.mv2-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 12px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.mv2-seg button:first-child{border-left:0}.mv2-seg button:hover:not(.mv2-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.mv2-seg button:disabled{color:var(--p-text-muted-color, #64748b);opacity:.6;cursor:not-allowed}.mv2-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.mv2-seg button.mv2-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.mv2-seg.mv2-seg-small{height:28px}.mv2-seg.mv2-seg-small button{padding:0 9px;font-size:12px}.mv2-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.mv2-live-dot.mv2-live-paused{background:var(--p-text-muted-color, #64748b)}.mv2-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.mv2-btn:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.mv2-icon-btn{width:26px;height:26px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--p-text-muted-color, #64748b);font-size:18px;line-height:1;cursor:pointer}.mv2-icon-btn:hover{background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155)}.mv2-link{padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.mv2-link:hover{text-decoration:underline}.mv2-muted{color:var(--p-text-muted-color, #64748b);font-size:12px}.mv2-small{font-size:11px}.mv2-pad{padding:6px 2px}.mv2-spacer{flex:1 1 auto}.mv2-alert{margin-top:10px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.mv2-alert.mv2-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.mv2-alert.mv2-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.mv2-main{display:grid;grid-template-columns:300px minmax(0,1fr);gap:14px;align-items:start;margin-top:14px}@container (max-width: 1000px){.mv2-main{grid-template-columns:minmax(0,1fr)}.mv2-catalog{position:static;max-height:360px}}.mv2-panel{padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.mv2-catalog{position:sticky;top:10px;max-height:calc(100vh - 20px);overflow:auto;font-size:13px;color:var(--p-text-color, #334155)}.mv2-presets{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 8px}.mv2-chip{padding:3px 10px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:12px;background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:12px;cursor:pointer}.mv2-chip:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.mv2-counter{display:flex;align-items:center;justify-content:space-between;padding:6px 0;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-size:12px}.mv2-cat-group{margin-top:10px}.mv2-cat-title{margin-bottom:4px;color:var(--p-text-muted-color, #64748b);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.mv2-cat-item{display:flex;align-items:center;gap:6px;padding:2px 0;min-width:0}.mv2-cat-item.mv2-cat-disabled{opacity:.5}.mv2-cat-sub{padding-left:18px}.mv2-check{display:flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;margin:0;cursor:pointer}.mv2-check input{flex:none;accent-color:var(--p-primary-color, #6366f1)}.mv2-cat-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mv2-cat-meta{flex:none;color:var(--p-text-muted-color, #64748b);font-size:11px;white-space:nowrap}.mv2-cat-inst{margin-left:4px;padding:0 5px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:8px;color:var(--p-text-muted-color, #64748b);font-size:10px;cursor:help}.mv2-caret{flex:none;padding:0 4px;border:0;background:transparent;color:var(--p-text-muted-color, #64748b);font-size:11px;cursor:pointer}.mv2-cat-items{padding:2px 0 4px 18px}.mv2-area{display:flex;flex-direction:column;gap:12px;min-width:0}.mv2-placeholder{display:flex;flex-direction:column;align-items:center;gap:10px;padding:70px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.mv2-placeholder .fa{font-size:28px;opacity:.5}.mv2-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}.mv2-tile{display:flex;flex-direction:column;gap:3px;padding:10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0;font-size:13px}.mv2-tile-name{overflow:hidden;color:var(--p-text-muted-color, #64748b);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.mv2-tile-row{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}.mv2-spark{display:block;width:100%;height:28px;margin-top:2px}.mv2-dot{display:inline-block;flex:none;width:9px;height:9px;margin-right:4px;border-radius:50%}.mv2-legend-bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px}.mv2-legend{display:flex;flex-wrap:wrap;gap:4px 6px}.mv2-legend-item{display:inline-flex;align-items:center;padding:2px 8px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:12px;background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:12px;cursor:pointer}.mv2-legend-item.mv2-legend-off{opacity:.45;text-decoration:line-through}.mv2-chart-panel{padding-bottom:6px}.mv2-panel-header{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin-bottom:6px}.mv2-panel-title{font-size:13px;font-weight:600;color:var(--p-text-color, #334155)}.mv2-type{padding:0 7px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px}.mv2-empty{padding:26px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.mv2-table-wrap{max-height:420px;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.mv2-table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px;color:var(--p-text-color, #334155)}.mv2-table th{position:sticky;top:0;z-index:1;padding:6px 8px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-weight:500;white-space:nowrap;cursor:pointer}.mv2-table td{padding:3px 8px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap}.mv2-num{text-align:right!important;font-variant-numeric:tabular-nums}\n"], dependencies: [{ kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i9.EsFormInputComponent, selector: "form-input", inputs: ["minlength", "maxlength", "pattern", "Password", "Type"] }, { kind: "component", type: i9.EsFormSelectComponent, selector: "form-select", inputs: ["OptionsTemplate"] }, { kind: "component", type: i9.EsFormDateTimeComponent, selector: "form-datetime" }, { kind: "component", type: i9.EsFormMultiselectComponent, selector: "form-multiselect", inputs: ["display", "InOutFormat", "FloatingLabel", "MaxShownElements"] }, { kind: "directive", type: i10.Widget, selector: "[widget]" }, { kind: "component", type: MetricsV2ChartComponent, selector: "mv2-chart", inputs: ["series", "from", "to", "height", "unit", "marks", "cursor", "format"], outputs: ["cursorChange", "zoom"] }, { kind: "pipe", type: i1.LocalizePipe, name: "localize" }] }); }
3806
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.34", type: AdmMetricsV2Component, isStandalone: false, selector: "metrics_v2", providers: [{ provide: LocalizationService, useClass: AdmMetricsV2Loc }], ngImport: i0, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Metriche di Sistema' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body mv2-body\">\r\n <!-- Barra dei comandi: sorgente, finestra, istanze, vista, aggiornamento -->\r\n <div class=\"mv2-toolbar\">\r\n <div class=\"mv2-group\">\r\n <span class=\"mv2-group-label\">{{'Sorgente' | localize: lc}}</span>\r\n <div class=\"mv2-seg\">\r\n @for (o of Sources; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"source == o.id\" [disabled]=\"o.id != 'live' && !historyAvailable\" (click)=\"setSource(o.id)\"\r\n [title]=\"o.id != 'live' && !historyAvailable ? ('Lo storico non \u00E8 attivo su questo ambiente: ci sono solo i dati live.' | localize: lc) : ''\">\r\n @if (o.id == 'live') {\r\n <span class=\"mv2-live-dot\" [class.mv2-live-paused]=\"paused\"></span>\r\n }\r\n {{o.description}}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (source == 'live') {\r\n <div class=\"mv2-group\">\r\n <span class=\"mv2-group-label\">{{'Finestra' | localize: lc}}</span>\r\n <div class=\"mv2-seg\">\r\n @for (o of LiveWindows; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"liveMinutes == o.id\" (click)=\"setLiveMinutes(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n } @else if (source == 'period') {\r\n <div class=\"mv2-cluster\">\r\n <div class=\"mv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterfrom\" (ngModelChange)=\"filterfrom = $event; datesChanged()\" name=\"filterfrom\" [Placeholder]=\"'Dal' | localize: lc\"></form-datetime>\r\n </div>\r\n <div class=\"mv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterto\" (ngModelChange)=\"filterto = $event; datesChanged()\" name=\"filterto\" [Placeholder]=\"'Al' | localize: lc\"></form-datetime>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"mv2-cluster\">\r\n <div class=\"mv2-field mv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"snapFromId\" (ngModelChange)=\"snapFromId = $event; snapshotsChanged()\" name=\"snapFrom\" [Source]=\"SnapshotOptions\" [Placeholder]=\"'Dallo snapshot' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"mv2-field mv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"snapToId\" (ngModelChange)=\"snapToId = $event; snapshotsChanged()\" name=\"snapTo\" [Source]=\"SnapshotOptions\" [Placeholder]=\"'Allo snapshot' | localize: lc\"></form-select>\r\n </div>\r\n @if (snapshotWindow; as w) {\r\n <span class=\"mv2-muted\">{{'Dalle' | localize: lc}} {{local(w.from)}} {{'alle' | localize: lc}} {{local(w.to)}}</span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"mv2-group mv2-field-wide\">\r\n <span class=\"mv2-group-label\">{{'Istanze' | localize: lc}}</span>\r\n <form-multiselect class=\"mv2-fill\" [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instances\" (ngModelChange)=\"instancesChanged($event)\" name=\"instances\" [Source]=\"Instances\" [Placeholder]=\"clusterLabel\" [MaxShownElements]=\"2\"></form-multiselect>\r\n </div>\r\n\r\n <div class=\"mv2-cluster mv2-cluster-end\">\r\n @if (source == 'live') {\r\n <span class=\"mv2-muted\">\r\n @if (dataLoading) {\r\n <i class=\"fa fa-spinner fa-spin\"></i>\r\n }\r\n @if (lastUpdate) {\r\n {{'Aggiornato alle' | localize: lc}} {{hhmmss(lastUpdate)}}\r\n }\r\n </span>\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"togglePause()\">\r\n <i class=\"fa\" [class.fa-pause]=\"!paused\" [class.fa-play]=\"paused\"></i> {{(paused ? 'Riprendi' : 'Pausa') | localize: lc}}\r\n </button>\r\n } @else if (dataLoading) {\r\n <span class=\"mv2-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n <div class=\"mv2-seg\">\r\n @for (o of Views; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"view == o.id\" (click)=\"setView(o.id)\">\r\n <i class=\"fa\" [class.fa-line-chart]=\"o.id == 'charts'\" [class.fa-table]=\"o.id == 'table'\"></i> {{o.description}}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Avvisi -->\r\n @for (warning of warnings; track $index) {\r\n <div class=\"mv2-alert mv2-alert-warn\"><i class=\"fa fa-exclamation-triangle\"></i> {{warning}}</div>\r\n }\r\n @if (snapshotsLoaded && !historyAvailable) {\r\n <div class=\"mv2-alert\"><i class=\"fa fa-info-circle\"></i> {{'Lo storico non \u00E8 attivo su questo ambiente: ci sono solo i dati live.' | localize: lc}}</div>\r\n }\r\n @if (dataError) {\r\n <div class=\"mv2-alert mv2-alert-error\">{{dataError}}</div>\r\n }\r\n\r\n <div class=\"mv2-main\">\r\n <!-- Catalogo -->\r\n <aside class=\"mv2-panel mv2-catalog\">\r\n <div class=\"mv2-field-full\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"search\" (ngModelChange)=\"search = $event; buildGroups()\" name=\"search\" [Placeholder]=\"'Cerca una metrica\u2026' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"mv2-presets\">\r\n @for (p of Presets; track p) {\r\n <button type=\"button\" class=\"mv2-chip\" (click)=\"applyPreset(p)\">{{p | localize: lc}}</button>\r\n }\r\n </div>\r\n <div class=\"mv2-counter\">\r\n <span>{{selected.length}} {{'di' | localize: lc}} {{Max}} {{'metriche scelte' | localize: lc}}</span>\r\n @if (selected.length > 0) {\r\n <button type=\"button\" class=\"mv2-link\" (click)=\"clearSelection()\">{{'Togli tutte' | localize: lc}}</button>\r\n }\r\n </div>\r\n\r\n @if (catalogLoading) {\r\n <div class=\"mv2-muted mv2-pad\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</div>\r\n }\r\n @if (catalogError) {\r\n <div class=\"mv2-alert mv2-alert-error\">{{catalogError}}</div>\r\n }\r\n @for (group of groups; track group.type) {\r\n <div class=\"mv2-cat-group\">\r\n <div class=\"mv2-cat-title\">{{group.label}} <span class=\"mv2-muted\">{{group.count}}</span></div>\r\n @for (entry of group.entries; track entry.info.name) {\r\n <div class=\"mv2-cat-item\" [class.mv2-cat-disabled]=\"!canSelect(entry.info.name)\">\r\n <label class=\"mv2-check\">\r\n <input type=\"checkbox\" [checked]=\"isSelected(entry.info.name)\" [disabled]=\"!canSelect(entry.info.name)\" (change)=\"toggleMetric(entry.info.name)\" />\r\n <span class=\"mv2-cat-name\" [title]=\"entry.info.name\">{{entry.info.name}}</span>\r\n </label>\r\n <span class=\"mv2-cat-meta\">\r\n {{catalogUnit(entry.info)}}\r\n @if (instancesLabel(entry.info)) {\r\n <span class=\"mv2-cat-inst\" [title]=\"entry.info.instances.join('\\n')\">{{instancesLabel(entry.info)}}</span>\r\n }\r\n </span>\r\n @if (entry.items.length > 0) {\r\n <button type=\"button\" class=\"mv2-caret\" (click)=\"entry.open = !entry.open\" [title]=\"'Voci' | localize: lc\">\r\n <i class=\"fa\" [class.fa-caret-down]=\"entry.open\" [class.fa-caret-right]=\"!entry.open\"></i> {{entry.items.length}}\r\n </button>\r\n }\r\n </div>\r\n @if (entry.open && entry.items.length > 0) {\r\n <div class=\"mv2-cat-items\">\r\n <button type=\"button\" class=\"mv2-link\" (click)=\"addItems(entry)\">{{addItemsLabel(entry)}}</button>\r\n @for (item of entry.items; track item.name) {\r\n <div class=\"mv2-cat-item mv2-cat-sub\" [class.mv2-cat-disabled]=\"!canSelect(item.name)\">\r\n <label class=\"mv2-check\">\r\n <input type=\"checkbox\" [checked]=\"isSelected(item.name)\" [disabled]=\"!canSelect(item.name)\" (change)=\"toggleMetric(item.name)\" />\r\n <span class=\"mv2-cat-name\" [title]=\"item.name\">{{item.name.substring(entry.info.name.length + 3)}}</span>\r\n </label>\r\n @if (instancesLabel(item)) {\r\n <span class=\"mv2-cat-inst\" [title]=\"item.instances.join('\\n')\">{{instancesLabel(item)}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n </aside>\r\n\r\n <!-- Grafici, tessere e tabella -->\r\n <section class=\"mv2-area\">\r\n @if (selected.length == 0) {\r\n <div class=\"mv2-panel mv2-placeholder\">\r\n <i class=\"fa fa-line-chart\"></i>\r\n {{'Scegli una o pi\u00F9 metriche dal catalogo.' | localize: lc}}\r\n </div>\r\n } @else {\r\n <!-- Tessere dei valori correnti -->\r\n <div class=\"mv2-tiles\">\r\n @for (tile of tiles; track tile.info.name) {\r\n <div class=\"mv2-tile\">\r\n <div class=\"mv2-tile-name\" [title]=\"tile.info.name\">{{tile.info.name}}</div>\r\n @for (row of tile.rows; track row.instance) {\r\n <div class=\"mv2-tile-row\">\r\n <span class=\"mv2-dot\" [style.background]=\"row.color\" [title]=\"row.instance\"></span>\r\n <strong>{{row.value}}</strong>\r\n @if (row.extra) {\r\n <span class=\"mv2-muted\">{{row.extra}}</span>\r\n }\r\n </div>\r\n } @empty {\r\n <div class=\"mv2-muted\">\u2014</div>\r\n }\r\n <svg class=\"mv2-spark\" viewBox=\"0 0 120 28\" preserveAspectRatio=\"none\" aria-hidden=\"true\">\r\n @for (spark of tile.sparks; track $index) {\r\n <path [attr.d]=\"spark.d\" [attr.stroke]=\"spark.color\" fill=\"none\" stroke-width=\"1.3\" vector-effect=\"non-scaling-stroke\" />\r\n }\r\n </svg>\r\n @if (tile.time) {\r\n <div class=\"mv2-muted mv2-small\">{{'alle' | localize: lc}} {{tile.time}}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Legenda comune: un clic nasconde o mostra l'istanza ovunque -->\r\n <div class=\"mv2-legend-bar\">\r\n <div class=\"mv2-legend\">\r\n @for (item of legend; track item.instance) {\r\n <button type=\"button\" class=\"mv2-legend-item\" [class.mv2-legend-off]=\"item.hidden\" (click)=\"toggleInstance(item.instance)\">\r\n <span class=\"mv2-dot\" [style.background]=\"item.color\"></span>{{item.instance}}\r\n </button>\r\n }\r\n </div>\r\n <span class=\"mv2-muted mv2-small\">{{'Orari in ora locale' | localize: lc}} ({{zone}}) &middot; {{'trascina su un grafico per lo zoom' | localize: lc}}</span>\r\n @if (viewFrom != null) {\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"resetZoom()\"><i class=\"fa fa-arrows-h\"></i> {{'Finestra intera' | localize: lc}}</button>\r\n }\r\n </div>\r\n\r\n @if (view == 'charts') {\r\n @for (panel of panels; track panel.info.name) {\r\n <div class=\"mv2-panel mv2-chart-panel\">\r\n <div class=\"mv2-panel-header\">\r\n <span class=\"mv2-panel-title\">{{panel.info.name}}</span>\r\n <span class=\"mv2-type\">{{Type[panel.info.metricType]}}</span>\r\n <span class=\"mv2-muted\">{{mainUnit(panel.info)}}</span>\r\n <span class=\"mv2-spacer\"></span>\r\n @if (panel.alts.length > 1) {\r\n <div class=\"mv2-seg mv2-seg-small\">\r\n @for (o of panel.alts; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"panel.alt == o.id\" (click)=\"setAlt(panel, o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n }\r\n <button type=\"button\" class=\"mv2-icon-btn\" [title]=\"'Togli' | localize: lc\" (click)=\"removeMetric(panel.info.name)\">&times;</button>\r\n </div>\r\n @if (panel.empty) {\r\n <div class=\"mv2-empty\">\r\n @if (dataLoading) {\r\n <i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}\r\n } @else {\r\n {{emptyLabel(panel.info.name)}}\r\n }\r\n </div>\r\n } @else {\r\n @for (chart of panel.charts; track chart.key) {\r\n <mv2-chart [series]=\"chart.series\" [from]=\"chartFrom\" [to]=\"chartTo\" [height]=\"chart.height\" [unit]=\"chart.unit\" [marks]=\"marks\"\r\n [cursor]=\"cursor\" [format]=\"format\" (cursorChange)=\"cursor = $event\" (zoom)=\"zoomTo($event)\"></mv2-chart>\r\n }\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @for (section of tables; track section.info.name) {\r\n <div class=\"mv2-panel\">\r\n <div class=\"mv2-panel-header\">\r\n <span class=\"mv2-panel-title\">{{section.info.name}}</span>\r\n <span class=\"mv2-type\">{{Type[section.info.metricType]}}</span>\r\n <span class=\"mv2-spacer\"></span>\r\n @if (section.total > 0) {\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"exportCsv(section)\"><i class=\"fa fa-download\"></i> {{'Esporta CSV' | localize: lc}}</button>\r\n }\r\n </div>\r\n @if (section.total == 0) {\r\n <div class=\"mv2-empty\">{{emptyLabel(section.info.name)}}</div>\r\n } @else {\r\n <div class=\"mv2-table-wrap\">\r\n <table class=\"mv2-table\">\r\n <thead>\r\n <tr>\r\n @for (column of section.columns; track column.key) {\r\n <th [class.mv2-num]=\"column.num\" (click)=\"sortBy(section, column)\">\r\n {{column.label}}\r\n @if (section.sortKey == column.key) {\r\n <i class=\"fa\" [class.fa-caret-down]=\"section.sortDesc\" [class.fa-caret-up]=\"!section.sortDesc\"></i>\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of shownRows(section); track $index) {\r\n <tr>\r\n @for (column of section.columns; track column.key) {\r\n <td [class.mv2-num]=\"column.num\">\r\n @if (column.key == 'instance') {\r\n <span class=\"mv2-dot\" [style.background]=\"color(row['instance'])\"></span>\r\n }\r\n {{cell(row, column)}}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n @if (section.total > section.rows.length || section.total > 300) {\r\n <div class=\"mv2-muted mv2-small mv2-pad\">{{'Mostrate le prime 300 righe di' | localize: lc}} {{section.total}}; {{\"l'esportazione le comprende tutte.\" | localize: lc}}</div>\r\n }\r\n }\r\n </div>\r\n }\r\n }\r\n }\r\n </section>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}:host ::ng-deep .mv2-noclear .p-select-clear-icon{display:none}:host ::ng-deep .mv2-fill{display:block;width:100%}.mv2-body{container-type:inline-size}.mv2-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px;padding-top:6px}.mv2-cluster{display:flex;flex-wrap:wrap;align-items:center;gap:10px}.mv2-cluster-end{margin-left:auto}.mv2-field{width:200px}.mv2-field-wide{width:340px;max-width:100%}.mv2-field-full{width:100%}.mv2-group{position:relative;display:inline-flex}.mv2-group-label{position:absolute;top:-8px;left:8px;z-index:2;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.mv2-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.mv2-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 12px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.mv2-seg button:first-child{border-left:0}.mv2-seg button:hover:not(.mv2-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.mv2-seg button:disabled{color:var(--p-text-muted-color, #64748b);opacity:.6;cursor:not-allowed}.mv2-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.mv2-seg button.mv2-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.mv2-seg.mv2-seg-small{height:28px}.mv2-seg.mv2-seg-small button{padding:0 9px;font-size:12px}.mv2-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.mv2-live-dot.mv2-live-paused{background:var(--p-text-muted-color, #64748b)}.mv2-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.mv2-btn:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.mv2-icon-btn{width:26px;height:26px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--p-text-muted-color, #64748b);font-size:18px;line-height:1;cursor:pointer}.mv2-icon-btn:hover{background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155)}.mv2-link{padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.mv2-link:hover{text-decoration:underline}.mv2-muted{color:var(--p-text-muted-color, #64748b);font-size:12px}.mv2-small{font-size:11px}.mv2-pad{padding:6px 2px}.mv2-spacer{flex:1 1 auto}.mv2-alert{margin-top:10px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.mv2-alert.mv2-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.mv2-alert.mv2-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.mv2-main{display:grid;grid-template-columns:300px minmax(0,1fr);gap:14px;align-items:start;margin-top:14px}@container (max-width: 1000px){.mv2-main{grid-template-columns:minmax(0,1fr)}.mv2-catalog{position:static;max-height:360px}}.mv2-panel{padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.mv2-catalog{position:sticky;top:10px;max-height:calc(100vh - 20px);overflow:auto;font-size:13px;color:var(--p-text-color, #334155)}.mv2-presets{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 8px}.mv2-chip{padding:3px 10px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:12px;background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:12px;cursor:pointer}.mv2-chip:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.mv2-counter{display:flex;align-items:center;justify-content:space-between;padding:6px 0;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-size:12px}.mv2-cat-group{margin-top:10px}.mv2-cat-title{margin-bottom:4px;color:var(--p-text-muted-color, #64748b);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.mv2-cat-item{display:flex;align-items:center;gap:6px;padding:2px 0;min-width:0}.mv2-cat-item.mv2-cat-disabled{opacity:.5}.mv2-cat-sub{padding-left:18px}.mv2-check{display:flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;margin:0;cursor:pointer}.mv2-check input{flex:none;display:inline-block;width:auto;height:auto;margin:0;accent-color:var(--p-primary-color, #6366f1)}.mv2-cat-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mv2-cat-meta{flex:none;color:var(--p-text-muted-color, #64748b);font-size:11px;white-space:nowrap}.mv2-cat-inst{margin-left:4px;padding:0 5px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:8px;color:var(--p-text-muted-color, #64748b);font-size:10px;cursor:help}.mv2-caret{flex:none;padding:0 4px;border:0;background:transparent;color:var(--p-text-muted-color, #64748b);font-size:11px;cursor:pointer}.mv2-cat-items{padding:2px 0 4px 18px}.mv2-area{display:flex;flex-direction:column;gap:12px;min-width:0}.mv2-placeholder{display:flex;flex-direction:column;align-items:center;gap:10px;padding:70px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.mv2-placeholder .fa{font-size:28px;opacity:.5}.mv2-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}.mv2-tile{display:flex;flex-direction:column;gap:3px;padding:10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0;font-size:13px}.mv2-tile-name{overflow:hidden;color:var(--p-text-muted-color, #64748b);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.mv2-tile-row{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}.mv2-spark{display:block;width:100%;height:28px;margin-top:2px}.mv2-dot{display:inline-block;flex:none;width:9px;height:9px;margin-right:4px;border-radius:50%}.mv2-legend-bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px}.mv2-legend{display:flex;flex-wrap:wrap;gap:4px 6px}.mv2-legend-item{display:inline-flex;align-items:center;padding:2px 8px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:12px;background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:12px;cursor:pointer}.mv2-legend-item.mv2-legend-off{opacity:.45;text-decoration:line-through}.mv2-chart-panel{padding-bottom:6px}.mv2-panel-header{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin-bottom:6px}.mv2-panel-title{font-size:13px;font-weight:600;color:var(--p-text-color, #334155)}.mv2-type{padding:0 7px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px}.mv2-empty{padding:26px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.mv2-table-wrap{max-height:420px;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.mv2-table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px;color:var(--p-text-color, #334155)}.mv2-table th{position:sticky;top:0;z-index:1;padding:6px 8px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-weight:500;white-space:nowrap;cursor:pointer}.mv2-table td{padding:3px 8px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap}.mv2-num{text-align:right!important;font-variant-numeric:tabular-nums}\n"], dependencies: [{ kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i9.EsFormInputComponent, selector: "form-input", inputs: ["minlength", "maxlength", "pattern", "Password", "Type"] }, { kind: "component", type: i9.EsFormSelectComponent, selector: "form-select", inputs: ["OptionsTemplate"] }, { kind: "component", type: i9.EsFormDateTimeComponent, selector: "form-datetime" }, { kind: "component", type: i9.EsFormMultiselectComponent, selector: "form-multiselect", inputs: ["display", "InOutFormat", "FloatingLabel", "MaxShownElements"] }, { kind: "directive", type: i10.Widget, selector: "[widget]" }, { kind: "component", type: MetricsV2ChartComponent, selector: "mv2-chart", inputs: ["series", "from", "to", "height", "unit", "marks", "cursor", "format"], outputs: ["cursorChange", "zoom"] }, { kind: "pipe", type: i1.LocalizePipe, name: "localize" }] }); }
3796
3807
  }
3797
3808
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: AdmMetricsV2Component, decorators: [{
3798
3809
  type: Component,
3799
- args: [{ selector: "metrics_v2", providers: [{ provide: LocalizationService, useClass: AdmMetricsV2Loc }], standalone: false, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Metriche di Sistema' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body mv2-body\">\r\n <!-- Barra dei comandi: sorgente, finestra, istanze, vista, aggiornamento -->\r\n <div class=\"mv2-toolbar\">\r\n <div class=\"mv2-group\">\r\n <span class=\"mv2-group-label\">{{'Sorgente' | localize: lc}}</span>\r\n <div class=\"mv2-seg\">\r\n @for (o of Sources; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"source == o.id\" [disabled]=\"o.id != 'live' && !historyAvailable\" (click)=\"setSource(o.id)\"\r\n [title]=\"o.id != 'live' && !historyAvailable ? ('Lo storico non \u00E8 attivo su questo ambiente: ci sono solo i dati live.' | localize: lc) : ''\">\r\n @if (o.id == 'live') {\r\n <span class=\"mv2-live-dot\" [class.mv2-live-paused]=\"paused\"></span>\r\n }\r\n {{o.description}}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (source == 'live') {\r\n <div class=\"mv2-group\">\r\n <span class=\"mv2-group-label\">{{'Finestra' | localize: lc}}</span>\r\n <div class=\"mv2-seg\">\r\n @for (o of LiveWindows; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"liveMinutes == o.id\" (click)=\"setLiveMinutes(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n } @else if (source == 'period') {\r\n <div class=\"mv2-cluster\">\r\n <div class=\"mv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterfrom\" (ngModelChange)=\"filterfrom = $event; datesChanged()\" name=\"filterfrom\" [Placeholder]=\"'Dal' | localize: lc\"></form-datetime>\r\n </div>\r\n <div class=\"mv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterto\" (ngModelChange)=\"filterto = $event; datesChanged()\" name=\"filterto\" [Placeholder]=\"'Al' | localize: lc\"></form-datetime>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"mv2-cluster\">\r\n <div class=\"mv2-field mv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"snapFromId\" (ngModelChange)=\"snapFromId = $event; snapshotsChanged()\" name=\"snapFrom\" [Source]=\"SnapshotOptions\" [Placeholder]=\"'Dallo snapshot' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"mv2-field mv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"snapToId\" (ngModelChange)=\"snapToId = $event; snapshotsChanged()\" name=\"snapTo\" [Source]=\"SnapshotOptions\" [Placeholder]=\"'Allo snapshot' | localize: lc\"></form-select>\r\n </div>\r\n @if (snapshotWindow; as w) {\r\n <span class=\"mv2-muted\">{{'Dalle' | localize: lc}} {{local(w.from)}} {{'alle' | localize: lc}} {{local(w.to)}}</span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"mv2-group mv2-field-wide\">\r\n <span class=\"mv2-group-label\">{{'Istanze' | localize: lc}}</span>\r\n <form-multiselect class=\"mv2-fill\" [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instances\" (ngModelChange)=\"instancesChanged($event)\" name=\"instances\" [Source]=\"Instances\" [Placeholder]=\"clusterLabel\" [MaxShownElements]=\"2\"></form-multiselect>\r\n </div>\r\n\r\n <div class=\"mv2-cluster mv2-cluster-end\">\r\n @if (source == 'live') {\r\n <span class=\"mv2-muted\">\r\n @if (dataLoading) {\r\n <i class=\"fa fa-spinner fa-spin\"></i>\r\n }\r\n @if (lastUpdate) {\r\n {{'Aggiornato alle' | localize: lc}} {{hhmmss(lastUpdate)}}\r\n }\r\n </span>\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"togglePause()\">\r\n <i class=\"fa\" [class.fa-pause]=\"!paused\" [class.fa-play]=\"paused\"></i> {{(paused ? 'Riprendi' : 'Pausa') | localize: lc}}\r\n </button>\r\n } @else if (dataLoading) {\r\n <span class=\"mv2-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n <div class=\"mv2-seg\">\r\n @for (o of Views; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"view == o.id\" (click)=\"setView(o.id)\">\r\n <i class=\"fa\" [class.fa-line-chart]=\"o.id == 'charts'\" [class.fa-table]=\"o.id == 'table'\"></i> {{o.description}}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Avvisi -->\r\n @for (warning of warnings; track $index) {\r\n <div class=\"mv2-alert mv2-alert-warn\"><i class=\"fa fa-exclamation-triangle\"></i> {{warning}}</div>\r\n }\r\n @if (snapshotsLoaded && !historyAvailable) {\r\n <div class=\"mv2-alert\"><i class=\"fa fa-info-circle\"></i> {{'Lo storico non \u00E8 attivo su questo ambiente: ci sono solo i dati live.' | localize: lc}}</div>\r\n }\r\n @if (dataError) {\r\n <div class=\"mv2-alert mv2-alert-error\">{{dataError}}</div>\r\n }\r\n\r\n <div class=\"mv2-main\">\r\n <!-- Catalogo -->\r\n <aside class=\"mv2-panel mv2-catalog\">\r\n <div class=\"mv2-field-full\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"search\" (ngModelChange)=\"search = $event; buildGroups()\" name=\"search\" [Placeholder]=\"'Cerca una metrica\u2026' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"mv2-presets\">\r\n @for (p of Presets; track p) {\r\n <button type=\"button\" class=\"mv2-chip\" (click)=\"applyPreset(p)\">{{p | localize: lc}}</button>\r\n }\r\n </div>\r\n <div class=\"mv2-counter\">\r\n <span>{{selected.length}} {{'di' | localize: lc}} {{Max}} {{'metriche scelte' | localize: lc}}</span>\r\n @if (selected.length > 0) {\r\n <button type=\"button\" class=\"mv2-link\" (click)=\"clearSelection()\">{{'Togli tutte' | localize: lc}}</button>\r\n }\r\n </div>\r\n\r\n @if (catalogLoading) {\r\n <div class=\"mv2-muted mv2-pad\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</div>\r\n }\r\n @if (catalogError) {\r\n <div class=\"mv2-alert mv2-alert-error\">{{catalogError}}</div>\r\n }\r\n @for (group of groups; track group.type) {\r\n <div class=\"mv2-cat-group\">\r\n <div class=\"mv2-cat-title\">{{group.label}} <span class=\"mv2-muted\">{{group.count}}</span></div>\r\n @for (entry of group.entries; track entry.info.name) {\r\n <div class=\"mv2-cat-item\" [class.mv2-cat-disabled]=\"!canSelect(entry.info.name)\">\r\n <label class=\"mv2-check\">\r\n <input type=\"checkbox\" [checked]=\"isSelected(entry.info.name)\" [disabled]=\"!canSelect(entry.info.name)\" (change)=\"toggleMetric(entry.info.name)\" />\r\n <span class=\"mv2-cat-name\" [title]=\"entry.info.name\">{{entry.info.name}}</span>\r\n </label>\r\n <span class=\"mv2-cat-meta\">\r\n {{catalogUnit(entry.info)}}\r\n @if (instancesLabel(entry.info)) {\r\n <span class=\"mv2-cat-inst\" [title]=\"entry.info.instances.join('\\n')\">{{instancesLabel(entry.info)}}</span>\r\n }\r\n </span>\r\n @if (entry.items.length > 0) {\r\n <button type=\"button\" class=\"mv2-caret\" (click)=\"entry.open = !entry.open\" [title]=\"'Voci' | localize: lc\">\r\n <i class=\"fa\" [class.fa-caret-down]=\"entry.open\" [class.fa-caret-right]=\"!entry.open\"></i> {{entry.items.length}}\r\n </button>\r\n }\r\n </div>\r\n @if (entry.open && entry.items.length > 0) {\r\n <div class=\"mv2-cat-items\">\r\n <button type=\"button\" class=\"mv2-link\" (click)=\"addItems(entry)\">{{addItemsLabel(entry)}}</button>\r\n @for (item of entry.items; track item.name) {\r\n <div class=\"mv2-cat-item mv2-cat-sub\" [class.mv2-cat-disabled]=\"!canSelect(item.name)\">\r\n <label class=\"mv2-check\">\r\n <input type=\"checkbox\" [checked]=\"isSelected(item.name)\" [disabled]=\"!canSelect(item.name)\" (change)=\"toggleMetric(item.name)\" />\r\n <span class=\"mv2-cat-name\" [title]=\"item.name\">{{item.name.substring(entry.info.name.length + 3)}}</span>\r\n </label>\r\n @if (instancesLabel(item)) {\r\n <span class=\"mv2-cat-inst\" [title]=\"item.instances.join('\\n')\">{{instancesLabel(item)}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n </aside>\r\n\r\n <!-- Grafici, tessere e tabella -->\r\n <section class=\"mv2-area\">\r\n @if (selected.length == 0) {\r\n <div class=\"mv2-panel mv2-placeholder\">\r\n <i class=\"fa fa-line-chart\"></i>\r\n {{'Scegli una o pi\u00F9 metriche dal catalogo.' | localize: lc}}\r\n </div>\r\n } @else {\r\n <!-- Tessere dei valori correnti -->\r\n <div class=\"mv2-tiles\">\r\n @for (tile of tiles; track tile.info.name) {\r\n <div class=\"mv2-tile\">\r\n <div class=\"mv2-tile-name\" [title]=\"tile.info.name\">{{tile.info.name}}</div>\r\n @for (row of tile.rows; track row.instance) {\r\n <div class=\"mv2-tile-row\">\r\n <span class=\"mv2-dot\" [style.background]=\"row.color\" [title]=\"row.instance\"></span>\r\n <strong>{{row.value}}</strong>\r\n @if (row.extra) {\r\n <span class=\"mv2-muted\">{{row.extra}}</span>\r\n }\r\n </div>\r\n } @empty {\r\n <div class=\"mv2-muted\">\u2014</div>\r\n }\r\n <svg class=\"mv2-spark\" viewBox=\"0 0 120 28\" preserveAspectRatio=\"none\" aria-hidden=\"true\">\r\n @for (spark of tile.sparks; track $index) {\r\n <path [attr.d]=\"spark.d\" [attr.stroke]=\"spark.color\" fill=\"none\" stroke-width=\"1.3\" vector-effect=\"non-scaling-stroke\" />\r\n }\r\n </svg>\r\n @if (tile.time) {\r\n <div class=\"mv2-muted mv2-small\">{{'alle' | localize: lc}} {{tile.time}}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Legenda comune: un clic nasconde o mostra l'istanza ovunque -->\r\n <div class=\"mv2-legend-bar\">\r\n <div class=\"mv2-legend\">\r\n @for (item of legend; track item.instance) {\r\n <button type=\"button\" class=\"mv2-legend-item\" [class.mv2-legend-off]=\"item.hidden\" (click)=\"toggleInstance(item.instance)\">\r\n <span class=\"mv2-dot\" [style.background]=\"item.color\"></span>{{item.instance}}\r\n </button>\r\n }\r\n </div>\r\n <span class=\"mv2-muted mv2-small\">{{'Orari in ora locale' | localize: lc}} ({{zone}}) &middot; {{'trascina su un grafico per lo zoom' | localize: lc}}</span>\r\n @if (viewFrom != null) {\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"resetZoom()\"><i class=\"fa fa-arrows-h\"></i> {{'Finestra intera' | localize: lc}}</button>\r\n }\r\n </div>\r\n\r\n @if (view == 'charts') {\r\n @for (panel of panels; track panel.info.name) {\r\n <div class=\"mv2-panel mv2-chart-panel\">\r\n <div class=\"mv2-panel-header\">\r\n <span class=\"mv2-panel-title\">{{panel.info.name}}</span>\r\n <span class=\"mv2-type\">{{Type[panel.info.metricType]}}</span>\r\n <span class=\"mv2-muted\">{{mainUnit(panel.info)}}</span>\r\n <span class=\"mv2-spacer\"></span>\r\n @if (panel.alts.length > 1) {\r\n <div class=\"mv2-seg mv2-seg-small\">\r\n @for (o of panel.alts; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"panel.alt == o.id\" (click)=\"setAlt(panel, o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n }\r\n <button type=\"button\" class=\"mv2-icon-btn\" [title]=\"'Togli' | localize: lc\" (click)=\"removeMetric(panel.info.name)\">&times;</button>\r\n </div>\r\n @if (panel.empty) {\r\n <div class=\"mv2-empty\">\r\n @if (dataLoading) {\r\n <i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}\r\n } @else {\r\n {{emptyLabel(panel.info.name)}}\r\n }\r\n </div>\r\n } @else {\r\n @for (chart of panel.charts; track chart.key) {\r\n <mv2-chart [series]=\"chart.series\" [from]=\"chartFrom\" [to]=\"chartTo\" [height]=\"chart.height\" [unit]=\"chart.unit\" [marks]=\"marks\"\r\n [cursor]=\"cursor\" [format]=\"format\" (cursorChange)=\"cursor = $event\" (zoom)=\"zoomTo($event)\"></mv2-chart>\r\n }\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @for (section of tables; track section.info.name) {\r\n <div class=\"mv2-panel\">\r\n <div class=\"mv2-panel-header\">\r\n <span class=\"mv2-panel-title\">{{section.info.name}}</span>\r\n <span class=\"mv2-type\">{{Type[section.info.metricType]}}</span>\r\n <span class=\"mv2-spacer\"></span>\r\n @if (section.total > 0) {\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"exportCsv(section)\"><i class=\"fa fa-download\"></i> {{'Esporta CSV' | localize: lc}}</button>\r\n }\r\n </div>\r\n @if (section.total == 0) {\r\n <div class=\"mv2-empty\">{{emptyLabel(section.info.name)}}</div>\r\n } @else {\r\n <div class=\"mv2-table-wrap\">\r\n <table class=\"mv2-table\">\r\n <thead>\r\n <tr>\r\n @for (column of section.columns; track column.key) {\r\n <th [class.mv2-num]=\"column.num\" (click)=\"sortBy(section, column)\">\r\n {{column.label}}\r\n @if (section.sortKey == column.key) {\r\n <i class=\"fa\" [class.fa-caret-down]=\"section.sortDesc\" [class.fa-caret-up]=\"!section.sortDesc\"></i>\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of shownRows(section); track $index) {\r\n <tr>\r\n @for (column of section.columns; track column.key) {\r\n <td [class.mv2-num]=\"column.num\">\r\n @if (column.key == 'instance') {\r\n <span class=\"mv2-dot\" [style.background]=\"color(row['instance'])\"></span>\r\n }\r\n {{cell(row, column)}}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n @if (section.total > section.rows.length || section.total > 300) {\r\n <div class=\"mv2-muted mv2-small mv2-pad\">{{'Mostrate le prime 300 righe di' | localize: lc}} {{section.total}}; {{\"l'esportazione le comprende tutte.\" | localize: lc}}</div>\r\n }\r\n }\r\n </div>\r\n }\r\n }\r\n }\r\n </section>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}:host ::ng-deep .mv2-noclear .p-select-clear-icon{display:none}:host ::ng-deep .mv2-fill{display:block;width:100%}.mv2-body{container-type:inline-size}.mv2-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px;padding-top:6px}.mv2-cluster{display:flex;flex-wrap:wrap;align-items:center;gap:10px}.mv2-cluster-end{margin-left:auto}.mv2-field{width:200px}.mv2-field-wide{width:340px;max-width:100%}.mv2-field-full{width:100%}.mv2-group{position:relative;display:inline-flex}.mv2-group-label{position:absolute;top:-8px;left:8px;z-index:2;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.mv2-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.mv2-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 12px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.mv2-seg button:first-child{border-left:0}.mv2-seg button:hover:not(.mv2-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.mv2-seg button:disabled{color:var(--p-text-muted-color, #64748b);opacity:.6;cursor:not-allowed}.mv2-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.mv2-seg button.mv2-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.mv2-seg.mv2-seg-small{height:28px}.mv2-seg.mv2-seg-small button{padding:0 9px;font-size:12px}.mv2-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.mv2-live-dot.mv2-live-paused{background:var(--p-text-muted-color, #64748b)}.mv2-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.mv2-btn:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.mv2-icon-btn{width:26px;height:26px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--p-text-muted-color, #64748b);font-size:18px;line-height:1;cursor:pointer}.mv2-icon-btn:hover{background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155)}.mv2-link{padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.mv2-link:hover{text-decoration:underline}.mv2-muted{color:var(--p-text-muted-color, #64748b);font-size:12px}.mv2-small{font-size:11px}.mv2-pad{padding:6px 2px}.mv2-spacer{flex:1 1 auto}.mv2-alert{margin-top:10px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.mv2-alert.mv2-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.mv2-alert.mv2-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.mv2-main{display:grid;grid-template-columns:300px minmax(0,1fr);gap:14px;align-items:start;margin-top:14px}@container (max-width: 1000px){.mv2-main{grid-template-columns:minmax(0,1fr)}.mv2-catalog{position:static;max-height:360px}}.mv2-panel{padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.mv2-catalog{position:sticky;top:10px;max-height:calc(100vh - 20px);overflow:auto;font-size:13px;color:var(--p-text-color, #334155)}.mv2-presets{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 8px}.mv2-chip{padding:3px 10px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:12px;background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:12px;cursor:pointer}.mv2-chip:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.mv2-counter{display:flex;align-items:center;justify-content:space-between;padding:6px 0;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-size:12px}.mv2-cat-group{margin-top:10px}.mv2-cat-title{margin-bottom:4px;color:var(--p-text-muted-color, #64748b);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.mv2-cat-item{display:flex;align-items:center;gap:6px;padding:2px 0;min-width:0}.mv2-cat-item.mv2-cat-disabled{opacity:.5}.mv2-cat-sub{padding-left:18px}.mv2-check{display:flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;margin:0;cursor:pointer}.mv2-check input{flex:none;accent-color:var(--p-primary-color, #6366f1)}.mv2-cat-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mv2-cat-meta{flex:none;color:var(--p-text-muted-color, #64748b);font-size:11px;white-space:nowrap}.mv2-cat-inst{margin-left:4px;padding:0 5px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:8px;color:var(--p-text-muted-color, #64748b);font-size:10px;cursor:help}.mv2-caret{flex:none;padding:0 4px;border:0;background:transparent;color:var(--p-text-muted-color, #64748b);font-size:11px;cursor:pointer}.mv2-cat-items{padding:2px 0 4px 18px}.mv2-area{display:flex;flex-direction:column;gap:12px;min-width:0}.mv2-placeholder{display:flex;flex-direction:column;align-items:center;gap:10px;padding:70px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.mv2-placeholder .fa{font-size:28px;opacity:.5}.mv2-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}.mv2-tile{display:flex;flex-direction:column;gap:3px;padding:10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0;font-size:13px}.mv2-tile-name{overflow:hidden;color:var(--p-text-muted-color, #64748b);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.mv2-tile-row{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}.mv2-spark{display:block;width:100%;height:28px;margin-top:2px}.mv2-dot{display:inline-block;flex:none;width:9px;height:9px;margin-right:4px;border-radius:50%}.mv2-legend-bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px}.mv2-legend{display:flex;flex-wrap:wrap;gap:4px 6px}.mv2-legend-item{display:inline-flex;align-items:center;padding:2px 8px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:12px;background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:12px;cursor:pointer}.mv2-legend-item.mv2-legend-off{opacity:.45;text-decoration:line-through}.mv2-chart-panel{padding-bottom:6px}.mv2-panel-header{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin-bottom:6px}.mv2-panel-title{font-size:13px;font-weight:600;color:var(--p-text-color, #334155)}.mv2-type{padding:0 7px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px}.mv2-empty{padding:26px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.mv2-table-wrap{max-height:420px;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.mv2-table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px;color:var(--p-text-color, #334155)}.mv2-table th{position:sticky;top:0;z-index:1;padding:6px 8px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-weight:500;white-space:nowrap;cursor:pointer}.mv2-table td{padding:3px 8px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap}.mv2-num{text-align:right!important;font-variant-numeric:tabular-nums}\n"] }]
3810
+ args: [{ selector: "metrics_v2", providers: [{ provide: LocalizationService, useClass: AdmMetricsV2Loc }], standalone: false, template: "<div class=\"row\">\r\n <div class=\"col-12\">\r\n <div class=\"card app-overflow-visible\" widget>\r\n <div class=\"card-header\">\r\n <span class=\"text-uppercase\">{{'Metriche di Sistema' | localize: lc}}</span>\r\n </div>\r\n <div class=\"card-body widget-body mv2-body\">\r\n <!-- Barra dei comandi: sorgente, finestra, istanze, vista, aggiornamento -->\r\n <div class=\"mv2-toolbar\">\r\n <div class=\"mv2-group\">\r\n <span class=\"mv2-group-label\">{{'Sorgente' | localize: lc}}</span>\r\n <div class=\"mv2-seg\">\r\n @for (o of Sources; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"source == o.id\" [disabled]=\"o.id != 'live' && !historyAvailable\" (click)=\"setSource(o.id)\"\r\n [title]=\"o.id != 'live' && !historyAvailable ? ('Lo storico non \u00E8 attivo su questo ambiente: ci sono solo i dati live.' | localize: lc) : ''\">\r\n @if (o.id == 'live') {\r\n <span class=\"mv2-live-dot\" [class.mv2-live-paused]=\"paused\"></span>\r\n }\r\n {{o.description}}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (source == 'live') {\r\n <div class=\"mv2-group\">\r\n <span class=\"mv2-group-label\">{{'Finestra' | localize: lc}}</span>\r\n <div class=\"mv2-seg\">\r\n @for (o of LiveWindows; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"liveMinutes == o.id\" (click)=\"setLiveMinutes(o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n </div>\r\n } @else if (source == 'period') {\r\n <div class=\"mv2-cluster\">\r\n <div class=\"mv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterfrom\" (ngModelChange)=\"filterfrom = $event; datesChanged()\" name=\"filterfrom\" [Placeholder]=\"'Dal' | localize: lc\"></form-datetime>\r\n </div>\r\n <div class=\"mv2-field\">\r\n <form-datetime [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"filterto\" (ngModelChange)=\"filterto = $event; datesChanged()\" name=\"filterto\" [Placeholder]=\"'Al' | localize: lc\"></form-datetime>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"mv2-cluster\">\r\n <div class=\"mv2-field mv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"snapFromId\" (ngModelChange)=\"snapFromId = $event; snapshotsChanged()\" name=\"snapFrom\" [Source]=\"SnapshotOptions\" [Placeholder]=\"'Dallo snapshot' | localize: lc\"></form-select>\r\n </div>\r\n <div class=\"mv2-field mv2-noclear\">\r\n <form-select [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"snapToId\" (ngModelChange)=\"snapToId = $event; snapshotsChanged()\" name=\"snapTo\" [Source]=\"SnapshotOptions\" [Placeholder]=\"'Allo snapshot' | localize: lc\"></form-select>\r\n </div>\r\n @if (snapshotWindow; as w) {\r\n <span class=\"mv2-muted\">{{'Dalle' | localize: lc}} {{local(w.from)}} {{'alle' | localize: lc}} {{local(w.to)}}</span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"mv2-group mv2-field-wide\">\r\n <span class=\"mv2-group-label\">{{'Istanze' | localize: lc}}</span>\r\n <form-multiselect class=\"mv2-fill\" [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"instances\" (ngModelChange)=\"instancesChanged($event)\" name=\"instances\" [Source]=\"Instances\" [Placeholder]=\"clusterLabel\" [MaxShownElements]=\"2\"></form-multiselect>\r\n </div>\r\n\r\n <div class=\"mv2-cluster mv2-cluster-end\">\r\n @if (source == 'live') {\r\n <span class=\"mv2-muted\">\r\n @if (dataLoading) {\r\n <i class=\"fa fa-spinner fa-spin\"></i>\r\n }\r\n @if (lastUpdate) {\r\n {{'Aggiornato alle' | localize: lc}} {{hhmmss(lastUpdate)}}\r\n }\r\n </span>\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"togglePause()\">\r\n <i class=\"fa\" [class.fa-pause]=\"!paused\" [class.fa-play]=\"paused\"></i> {{(paused ? 'Riprendi' : 'Pausa') | localize: lc}}\r\n </button>\r\n } @else if (dataLoading) {\r\n <span class=\"mv2-muted\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</span>\r\n }\r\n <div class=\"mv2-seg\">\r\n @for (o of Views; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"view == o.id\" (click)=\"setView(o.id)\">\r\n <i class=\"fa\" [class.fa-line-chart]=\"o.id == 'charts'\" [class.fa-table]=\"o.id == 'table'\"></i> {{o.description}}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Avvisi -->\r\n @for (warning of warnings; track $index) {\r\n <div class=\"mv2-alert mv2-alert-warn\"><i class=\"fa fa-exclamation-triangle\"></i> {{warning}}</div>\r\n }\r\n @if (snapshotsLoaded && !historyAvailable) {\r\n <div class=\"mv2-alert\"><i class=\"fa fa-info-circle\"></i> {{'Lo storico non \u00E8 attivo su questo ambiente: ci sono solo i dati live.' | localize: lc}}</div>\r\n }\r\n @if (dataError) {\r\n <div class=\"mv2-alert mv2-alert-error\">{{dataError}}</div>\r\n }\r\n\r\n <div class=\"mv2-main\">\r\n <!-- Catalogo -->\r\n <aside class=\"mv2-panel mv2-catalog\">\r\n <div class=\"mv2-field-full\">\r\n <form-input [FormLayout]=\"false\" [Validation]=\"false\" [ngModel]=\"search\" (ngModelChange)=\"search = $event; buildGroups()\" name=\"search\" [Placeholder]=\"'Cerca una metrica\u2026' | localize: lc\"></form-input>\r\n </div>\r\n <div class=\"mv2-presets\">\r\n @for (p of Presets; track p) {\r\n <button type=\"button\" class=\"mv2-chip\" (click)=\"applyPreset(p)\">{{p | localize: lc}}</button>\r\n }\r\n </div>\r\n <div class=\"mv2-counter\">\r\n <span>{{selected.length}} {{'di' | localize: lc}} {{Max}} {{'metriche scelte' | localize: lc}}</span>\r\n @if (selected.length > 0) {\r\n <button type=\"button\" class=\"mv2-link\" (click)=\"clearSelection()\">{{'Togli tutte' | localize: lc}}</button>\r\n }\r\n </div>\r\n\r\n @if (catalogLoading) {\r\n <div class=\"mv2-muted mv2-pad\"><i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}</div>\r\n }\r\n @if (catalogError) {\r\n <div class=\"mv2-alert mv2-alert-error\">{{catalogError}}</div>\r\n }\r\n @for (group of groups; track group.type) {\r\n <div class=\"mv2-cat-group\">\r\n <div class=\"mv2-cat-title\">{{group.label}} <span class=\"mv2-muted\">{{group.count}}</span></div>\r\n @for (entry of group.entries; track entry.info.name) {\r\n <div class=\"mv2-cat-item\" [class.mv2-cat-disabled]=\"!canSelect(entry.info.name)\">\r\n <label class=\"mv2-check\">\r\n <input type=\"checkbox\" [checked]=\"isSelected(entry.info.name)\" [disabled]=\"!canSelect(entry.info.name)\" (change)=\"toggleMetric(entry.info.name)\" />\r\n <span class=\"mv2-cat-name\" [title]=\"entry.info.name\">{{entry.info.name}}</span>\r\n </label>\r\n <span class=\"mv2-cat-meta\">\r\n {{catalogUnit(entry.info)}}\r\n @if (instancesLabel(entry.info)) {\r\n <span class=\"mv2-cat-inst\" [title]=\"entry.info.instances.join('\\n')\">{{instancesLabel(entry.info)}}</span>\r\n }\r\n </span>\r\n @if (entry.items.length > 0) {\r\n <button type=\"button\" class=\"mv2-caret\" (click)=\"entry.open = !entry.open\" [title]=\"'Voci' | localize: lc\">\r\n <i class=\"fa\" [class.fa-caret-down]=\"entry.open\" [class.fa-caret-right]=\"!entry.open\"></i> {{entry.items.length}}\r\n </button>\r\n }\r\n </div>\r\n @if (entry.open && entry.items.length > 0) {\r\n <div class=\"mv2-cat-items\">\r\n <button type=\"button\" class=\"mv2-link\" (click)=\"addItems(entry)\">{{addItemsLabel(entry)}}</button>\r\n @for (item of entry.items; track item.name) {\r\n <div class=\"mv2-cat-item mv2-cat-sub\" [class.mv2-cat-disabled]=\"!canSelect(item.name)\">\r\n <label class=\"mv2-check\">\r\n <input type=\"checkbox\" [checked]=\"isSelected(item.name)\" [disabled]=\"!canSelect(item.name)\" (change)=\"toggleMetric(item.name)\" />\r\n <span class=\"mv2-cat-name\" [title]=\"item.name\">{{item.name.substring(entry.info.name.length + 3)}}</span>\r\n </label>\r\n @if (instancesLabel(item)) {\r\n <span class=\"mv2-cat-inst\" [title]=\"item.instances.join('\\n')\">{{instancesLabel(item)}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n </aside>\r\n\r\n <!-- Grafici, tessere e tabella -->\r\n <section class=\"mv2-area\">\r\n @if (selected.length == 0) {\r\n <div class=\"mv2-panel mv2-placeholder\">\r\n <i class=\"fa fa-line-chart\"></i>\r\n {{'Scegli una o pi\u00F9 metriche dal catalogo.' | localize: lc}}\r\n </div>\r\n } @else {\r\n <!-- Tessere dei valori correnti -->\r\n <div class=\"mv2-tiles\">\r\n @for (tile of tiles; track tile.info.name) {\r\n <div class=\"mv2-tile\">\r\n <div class=\"mv2-tile-name\" [title]=\"tile.info.name\">{{tile.info.name}}</div>\r\n @for (row of tile.rows; track row.instance) {\r\n <div class=\"mv2-tile-row\">\r\n <span class=\"mv2-dot\" [style.background]=\"row.color\" [title]=\"row.instance\"></span>\r\n <strong>{{row.value}}</strong>\r\n @if (row.extra) {\r\n <span class=\"mv2-muted\">{{row.extra}}</span>\r\n }\r\n </div>\r\n } @empty {\r\n <div class=\"mv2-muted\">\u2014</div>\r\n }\r\n <svg class=\"mv2-spark\" viewBox=\"0 0 120 28\" preserveAspectRatio=\"none\" aria-hidden=\"true\">\r\n @for (spark of tile.sparks; track $index) {\r\n <path [attr.d]=\"spark.d\" [attr.stroke]=\"spark.color\" fill=\"none\" stroke-width=\"1.3\" vector-effect=\"non-scaling-stroke\" />\r\n }\r\n </svg>\r\n @if (tile.time) {\r\n <div class=\"mv2-muted mv2-small\">{{'alle' | localize: lc}} {{tile.time}}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Legenda comune: un clic nasconde o mostra l'istanza ovunque -->\r\n <div class=\"mv2-legend-bar\">\r\n <div class=\"mv2-legend\">\r\n @for (item of legend; track item.instance) {\r\n <button type=\"button\" class=\"mv2-legend-item\" [class.mv2-legend-off]=\"item.hidden\" (click)=\"toggleInstance(item.instance)\">\r\n <span class=\"mv2-dot\" [style.background]=\"item.color\"></span>{{item.instance}}\r\n </button>\r\n }\r\n </div>\r\n <span class=\"mv2-muted mv2-small\">{{'Orari in ora locale' | localize: lc}} ({{zone}}) &middot; {{'trascina su un grafico per lo zoom' | localize: lc}}</span>\r\n @if (viewFrom != null) {\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"resetZoom()\"><i class=\"fa fa-arrows-h\"></i> {{'Finestra intera' | localize: lc}}</button>\r\n }\r\n </div>\r\n\r\n @if (view == 'charts') {\r\n @for (panel of panels; track panel.info.name) {\r\n <div class=\"mv2-panel mv2-chart-panel\">\r\n <div class=\"mv2-panel-header\">\r\n <span class=\"mv2-panel-title\">{{panel.info.name}}</span>\r\n <span class=\"mv2-type\">{{Type[panel.info.metricType]}}</span>\r\n <span class=\"mv2-muted\">{{mainUnit(panel.info)}}</span>\r\n <span class=\"mv2-spacer\"></span>\r\n @if (panel.alts.length > 1) {\r\n <div class=\"mv2-seg mv2-seg-small\">\r\n @for (o of panel.alts; track o.id) {\r\n <button type=\"button\" [class.mv2-on]=\"panel.alt == o.id\" (click)=\"setAlt(panel, o.id)\">{{o.description}}</button>\r\n }\r\n </div>\r\n }\r\n <button type=\"button\" class=\"mv2-icon-btn\" [title]=\"'Togli' | localize: lc\" (click)=\"removeMetric(panel.info.name)\">&times;</button>\r\n </div>\r\n @if (panel.empty) {\r\n <div class=\"mv2-empty\">\r\n @if (dataLoading) {\r\n <i class=\"fa fa-spinner fa-spin\"></i> {{'Caricamento\u2026' | localize: lc}}\r\n } @else {\r\n {{emptyLabel(panel.info.name)}}\r\n }\r\n </div>\r\n } @else {\r\n @for (chart of panel.charts; track chart.key) {\r\n <mv2-chart [series]=\"chart.series\" [from]=\"chartFrom\" [to]=\"chartTo\" [height]=\"chart.height\" [unit]=\"chart.unit\" [marks]=\"marks\"\r\n [cursor]=\"cursor\" [format]=\"format\" (cursorChange)=\"cursor = $event\" (zoom)=\"zoomTo($event)\"></mv2-chart>\r\n }\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @for (section of tables; track section.info.name) {\r\n <div class=\"mv2-panel\">\r\n <div class=\"mv2-panel-header\">\r\n <span class=\"mv2-panel-title\">{{section.info.name}}</span>\r\n <span class=\"mv2-type\">{{Type[section.info.metricType]}}</span>\r\n <span class=\"mv2-spacer\"></span>\r\n @if (section.total > 0) {\r\n <button type=\"button\" class=\"mv2-btn\" (click)=\"exportCsv(section)\"><i class=\"fa fa-download\"></i> {{'Esporta CSV' | localize: lc}}</button>\r\n }\r\n </div>\r\n @if (section.total == 0) {\r\n <div class=\"mv2-empty\">{{emptyLabel(section.info.name)}}</div>\r\n } @else {\r\n <div class=\"mv2-table-wrap\">\r\n <table class=\"mv2-table\">\r\n <thead>\r\n <tr>\r\n @for (column of section.columns; track column.key) {\r\n <th [class.mv2-num]=\"column.num\" (click)=\"sortBy(section, column)\">\r\n {{column.label}}\r\n @if (section.sortKey == column.key) {\r\n <i class=\"fa\" [class.fa-caret-down]=\"section.sortDesc\" [class.fa-caret-up]=\"!section.sortDesc\"></i>\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of shownRows(section); track $index) {\r\n <tr>\r\n @for (column of section.columns; track column.key) {\r\n <td [class.mv2-num]=\"column.num\">\r\n @if (column.key == 'instance') {\r\n <span class=\"mv2-dot\" [style.background]=\"color(row['instance'])\"></span>\r\n }\r\n {{cell(row, column)}}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n @if (section.total > section.rows.length || section.total > 300) {\r\n <div class=\"mv2-muted mv2-small mv2-pad\">{{'Mostrate le prime 300 righe di' | localize: lc}} {{section.total}}; {{\"l'esportazione le comprende tutte.\" | localize: lc}}</div>\r\n }\r\n }\r\n </div>\r\n }\r\n }\r\n }\r\n </section>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}:host ::ng-deep .mv2-noclear .p-select-clear-icon{display:none}:host ::ng-deep .mv2-fill{display:block;width:100%}.mv2-body{container-type:inline-size}.mv2-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px;padding-top:6px}.mv2-cluster{display:flex;flex-wrap:wrap;align-items:center;gap:10px}.mv2-cluster-end{margin-left:auto}.mv2-field{width:200px}.mv2-field-wide{width:340px;max-width:100%}.mv2-field-full{width:100%}.mv2-group{position:relative;display:inline-flex}.mv2-group-label{position:absolute;top:-8px;left:8px;z-index:2;padding:0 4px;background:var(--p-content-background, #fff);color:var(--p-text-muted-color, #64748b);font-size:12px;line-height:15px;white-space:nowrap;pointer-events:none}.mv2-seg{display:inline-flex;height:39px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);overflow:hidden;background:var(--p-content-background, #fff)}.mv2-seg button{display:inline-flex;align-items:center;gap:6px;padding:0 12px;border:0;border-left:1px solid var(--p-form-field-border-color, #cbd5e1);background:transparent;color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.mv2-seg button:first-child{border-left:0}.mv2-seg button:hover:not(.mv2-on):not(:disabled){background:var(--p-content-hover-background, #f8fafc)}.mv2-seg button:disabled{color:var(--p-text-muted-color, #64748b);opacity:.6;cursor:not-allowed}.mv2-seg button:focus-visible{outline:2px solid var(--p-primary-color, #6366f1);outline-offset:-2px}.mv2-seg button.mv2-on{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca);font-weight:500;box-shadow:inset 0 -2px 0 var(--p-primary-color, #6366f1)}.mv2-seg.mv2-seg-small{height:28px}.mv2-seg.mv2-seg-small button{padding:0 9px;font-size:12px}.mv2-live-dot{width:8px;height:8px;border-radius:50%;background:#16a34a}.mv2-live-dot.mv2-live-paused{background:var(--p-text-muted-color, #64748b)}.mv2-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:13px;white-space:nowrap;cursor:pointer}.mv2-btn:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.mv2-icon-btn{width:26px;height:26px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--p-text-muted-color, #64748b);font-size:18px;line-height:1;cursor:pointer}.mv2-icon-btn:hover{background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155)}.mv2-link{padding:0;border:0;background:transparent;color:var(--p-primary-color, #6366f1);font-size:12px;cursor:pointer}.mv2-link:hover{text-decoration:underline}.mv2-muted{color:var(--p-text-muted-color, #64748b);font-size:12px}.mv2-small{font-size:11px}.mv2-pad{padding:6px 2px}.mv2-spacer{flex:1 1 auto}.mv2-alert{margin-top:10px;padding:7px 12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-color, #334155);font-size:13px}.mv2-alert.mv2-alert-warn{border-color:#fcd34d;background:#fffbeb;color:#92400e}.mv2-alert.mv2-alert-error{border-color:#fca5a5;background:#fef2f2;color:#991b1b}.mv2-main{display:grid;grid-template-columns:300px minmax(0,1fr);gap:14px;align-items:start;margin-top:14px}@container (max-width: 1000px){.mv2-main{grid-template-columns:minmax(0,1fr)}.mv2-catalog{position:static;max-height:360px}}.mv2-panel{padding:12px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0}.mv2-catalog{position:sticky;top:10px;max-height:calc(100vh - 20px);overflow:auto;font-size:13px;color:var(--p-text-color, #334155)}.mv2-presets{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 8px}.mv2-chip{padding:3px 10px;border:1px solid var(--p-form-field-border-color, #cbd5e1);border-radius:12px;background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:12px;cursor:pointer}.mv2-chip:hover{background:var(--p-highlight-background, #eef2ff);color:var(--p-highlight-color, #4338ca)}.mv2-counter{display:flex;align-items:center;justify-content:space-between;padding:6px 0;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);color:var(--p-text-muted-color, #64748b);font-size:12px}.mv2-cat-group{margin-top:10px}.mv2-cat-title{margin-bottom:4px;color:var(--p-text-muted-color, #64748b);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.mv2-cat-item{display:flex;align-items:center;gap:6px;padding:2px 0;min-width:0}.mv2-cat-item.mv2-cat-disabled{opacity:.5}.mv2-cat-sub{padding-left:18px}.mv2-check{display:flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;margin:0;cursor:pointer}.mv2-check input{flex:none;display:inline-block;width:auto;height:auto;margin:0;accent-color:var(--p-primary-color, #6366f1)}.mv2-cat-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mv2-cat-meta{flex:none;color:var(--p-text-muted-color, #64748b);font-size:11px;white-space:nowrap}.mv2-cat-inst{margin-left:4px;padding:0 5px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:8px;color:var(--p-text-muted-color, #64748b);font-size:10px;cursor:help}.mv2-caret{flex:none;padding:0 4px;border:0;background:transparent;color:var(--p-text-muted-color, #64748b);font-size:11px;cursor:pointer}.mv2-cat-items{padding:2px 0 4px 18px}.mv2-area{display:flex;flex-direction:column;gap:12px;min-width:0}.mv2-placeholder{display:flex;flex-direction:column;align-items:center;gap:10px;padding:70px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.mv2-placeholder .fa{font-size:28px;opacity:.5}.mv2-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}.mv2-tile{display:flex;flex-direction:column;gap:3px;padding:10px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px);background:var(--p-content-background, #fff);min-width:0;font-size:13px}.mv2-tile-name{overflow:hidden;color:var(--p-text-muted-color, #64748b);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.mv2-tile-row{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}.mv2-spark{display:block;width:100%;height:28px;margin-top:2px}.mv2-dot{display:inline-block;flex:none;width:9px;height:9px;margin-right:4px;border-radius:50%}.mv2-legend-bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px}.mv2-legend{display:flex;flex-wrap:wrap;gap:4px 6px}.mv2-legend-item{display:inline-flex;align-items:center;padding:2px 8px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:12px;background:var(--p-content-background, #fff);color:var(--p-text-color, #334155);font-size:12px;cursor:pointer}.mv2-legend-item.mv2-legend-off{opacity:.45;text-decoration:line-through}.mv2-chart-panel{padding-bottom:6px}.mv2-panel-header{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin-bottom:6px}.mv2-panel-title{font-size:13px;font-weight:600;color:var(--p-text-color, #334155)}.mv2-type{padding:0 7px;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:10px;color:var(--p-text-muted-color, #64748b);font-size:11px;line-height:18px}.mv2-empty{padding:26px 12px;color:var(--p-text-muted-color, #64748b);text-align:center}.mv2-table-wrap{max-height:420px;overflow:auto;border:1px solid var(--p-content-border-color, #e2e8f0);border-radius:var(--p-form-field-border-radius, 6px)}.mv2-table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px;color:var(--p-text-color, #334155)}.mv2-table th{position:sticky;top:0;z-index:1;padding:6px 8px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);background:var(--p-content-hover-background, #f8fafc);color:var(--p-text-muted-color, #64748b);font-weight:500;white-space:nowrap;cursor:pointer}.mv2-table td{padding:3px 8px;border-bottom:1px solid var(--p-content-border-color, #e2e8f0);white-space:nowrap}.mv2-num{text-align:right!important;font-variant-numeric:tabular-nums}\n"] }]
3800
3811
  }], ctorParameters: () => [{ type: i1$1.DateService }, { type: i1.LocalizationService }, { type: i3.PreferencesService }, { type: i1$1.InterComService }, { type: i4.ActivatedRoute }, { type: AdminModuleBaseService }] });
3801
3812
 
3802
3813
  class TopActivitiesDataView extends AppSearch {