@esfaenza/admin-module 20.3.21 → 20.3.22
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> \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> \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> \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> \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> \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> \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
|
|
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> \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> \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
|
-
|
|
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> · {{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}} · {{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\">›</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\">×</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}} «{{activeSearch}}».</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}} · {{omittedTime(row.node) | pv2fmt: 'dur'}}\r\n @if (!snapMode) {\r\n · {{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)}} · {{'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}} · {{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> · {{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}} · {{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\">›</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\">×</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}} «{{activeSearch}}».</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}} · {{omittedTime(row.node) | pv2fmt: 'dur'}}\r\n @if (!snapMode) {\r\n · {{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)}} · {{'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}} · {{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: 1000px){.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:740px;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" }] }); }
|
|
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> · {{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}} · {{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\">›</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\">×</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}} «{{activeSearch}}».</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}} · {{omittedTime(row.node) | pv2fmt: 'dur'}}\r\n @if (!snapMode) {\r\n · {{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)}} · {{'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}} · {{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> · {{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}} · {{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\">›</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\">×</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}} «{{activeSearch}}».</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}} · {{omittedTime(row.node) | pv2fmt: 'dur'}}\r\n @if (!snapMode) {\r\n · {{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)}} · {{'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}} · {{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: 1000px){.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:740px;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"] }]
|
|
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\">· {{\"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 · {{scopeLabel(report.instances)}}\r\n @if (!report.live && report.windowFrom) {\r\n · {{'dalle' | localize: lc}} {{local(report.windowFrom)}} {{'alle' | localize: lc}} {{local(report.windowTo)}}\r\n }\r\n · {{'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\">· {{\"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 · {{scopeLabel(report.instances)}}\r\n @if (!report.live && report.windowFrom) {\r\n · {{'dalle' | localize: lc}} {{local(report.windowFrom)}} {{'alle' | localize: lc}} {{local(report.windowTo)}}\r\n }\r\n · {{'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\">· {{\"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 · {{scopeLabel(report.instances)}}\r\n @if (!report.live && report.windowFrom) {\r\n · {{'dalle' | localize: lc}} {{local(report.windowFrom)}} {{'alle' | localize: lc}} {{local(report.windowTo)}}\r\n }\r\n · {{'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\">· {{\"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 · {{scopeLabel(report.instances)}}\r\n @if (!report.live && report.windowFrom) {\r\n · {{'dalle' | localize: lc}} {{local(report.windowFrom)}} {{'alle' | localize: lc}} {{local(report.windowTo)}}\r\n }\r\n · {{'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
|
-
|
|
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.
|
|
@@ -2787,7 +2792,7 @@ class MetricsV2ChartComponent {
|
|
|
2787
2792
|
<text class="mv2c-xlabel" [attr.x]="tick.pos" [attr.y]="height - 5">{{tick.label}}</text>
|
|
2788
2793
|
}
|
|
2789
2794
|
@if (unit) {
|
|
2790
|
-
<text class="mv2c-unit" [attr.x]="4" [attr.y]="
|
|
2795
|
+
<text class="mv2c-unit" [attr.x]="4" [attr.y]="11">{{unit}}</text>
|
|
2791
2796
|
}
|
|
2792
2797
|
@for (mark of markTicks; track mark.key) {
|
|
2793
2798
|
<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 +2840,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImpo
|
|
|
2835
2840
|
<text class="mv2c-xlabel" [attr.x]="tick.pos" [attr.y]="height - 5">{{tick.label}}</text>
|
|
2836
2841
|
}
|
|
2837
2842
|
@if (unit) {
|
|
2838
|
-
<text class="mv2c-unit" [attr.x]="4" [attr.y]="
|
|
2843
|
+
<text class="mv2c-unit" [attr.x]="4" [attr.y]="11">{{unit}}</text>
|
|
2839
2844
|
}
|
|
2840
2845
|
@for (mark of markTicks; track mark.key) {
|
|
2841
2846
|
<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 +3026,7 @@ class AdmMetricsV2Component {
|
|
|
3021
3026
|
}
|
|
3022
3027
|
// #region Comandi
|
|
3023
3028
|
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");
|
|
3029
|
+
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
3030
|
}
|
|
3026
3031
|
get zone() {
|
|
3027
3032
|
return `UTC${dayjs().format("Z")}`;
|
|
@@ -3792,11 +3797,11 @@ class AdmMetricsV2Component {
|
|
|
3792
3797
|
this.localStorage.setItem(STORAGE_KEY$1, settings).subscribe();
|
|
3793
3798
|
}
|
|
3794
3799
|
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}}) · {{'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)\">×</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" }] }); }
|
|
3800
|
+
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}}) · {{'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)\">×</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
3801
|
}
|
|
3797
3802
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: AdmMetricsV2Component, decorators: [{
|
|
3798
3803
|
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}}) · {{'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)\">×</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"] }]
|
|
3804
|
+
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}}) · {{'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)\">×</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
3805
|
}], ctorParameters: () => [{ type: i1$1.DateService }, { type: i1.LocalizationService }, { type: i3.PreferencesService }, { type: i1$1.InterComService }, { type: i4.ActivatedRoute }, { type: AdminModuleBaseService }] });
|
|
3801
3806
|
|
|
3802
3807
|
class TopActivitiesDataView extends AppSearch {
|