@c8y/ngx-components 1023.63.1 → 1023.64.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/datapoints-export-selector/index.d.ts +213 -48
- package/datapoints-export-selector/index.d.ts.map +1 -1
- package/echart/index.d.ts +1 -0
- package/echart/index.d.ts.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs +568 -138
- package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-echart.mjs +6 -3
- package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-global-context.mjs +36 -1
- package/fesm2022/c8y-ngx-components-global-context.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-list.mjs +80 -0
- package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-list.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-widgets-definitions.mjs +1 -0
- package/fesm2022/c8y-ngx-components-widgets-definitions.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-exports.mjs +8 -1
- package/fesm2022/c8y-ngx-components-widgets-exports.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-list.mjs +702 -0
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-list.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs +3 -110
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components.mjs +116 -6
- package/fesm2022/c8y-ngx-components.mjs.map +1 -1
- package/global-context/index.d.ts +2 -0
- package/global-context/index.d.ts.map +1 -1
- package/index.d.ts +59 -2
- package/index.d.ts.map +1 -1
- package/locales/de.po +94 -23
- package/locales/es.po +96 -23
- package/locales/fr.po +95 -23
- package/locales/ja_JP.po +82 -23
- package/locales/ko.po +97 -23
- package/locales/locales.pot +62 -11
- package/locales/nl.po +94 -23
- package/locales/pl.po +98 -23
- package/locales/pt_BR.po +97 -23
- package/locales/zh_CN.po +98 -23
- package/locales/zh_TW.po +98 -23
- package/package.json +1 -1
- package/widgets/cockpit-exports/index.d.ts +6 -0
- package/widgets/cockpit-exports/index.d.ts.map +1 -1
- package/widgets/definitions/datapoints-list/index.d.ts +51 -0
- package/widgets/definitions/datapoints-list/index.d.ts.map +1 -0
- package/widgets/definitions/index.d.ts +1 -0
- package/widgets/definitions/index.d.ts.map +1 -1
- package/widgets/device-management-exports/index.d.ts +6 -0
- package/widgets/device-management-exports/index.d.ts.map +1 -1
- package/widgets/exports/index.d.ts +8 -1
- package/widgets/exports/index.d.ts.map +1 -1
- package/widgets/implementations/alarms/index.d.ts +2 -0
- package/widgets/implementations/alarms/index.d.ts.map +1 -1
- package/widgets/implementations/datapoints-list/index.d.ts +286 -0
- package/widgets/implementations/datapoints-list/index.d.ts.map +1 -0
- package/widgets/implementations/datapoints-table/index.d.ts +5 -66
- package/widgets/implementations/datapoints-table/index.d.ts.map +1 -1
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable,
|
|
2
|
+
import { Injectable, input, output, ChangeDetectionStrategy, Component, InjectionToken, Inject, computed, viewChild } from '@angular/core';
|
|
3
3
|
import * as i2 from '@c8y/client';
|
|
4
|
-
import { gettext } from '@c8y/ngx-components/gettext';
|
|
5
4
|
import * as i1 from '@c8y/ngx-components';
|
|
6
|
-
import { AGGREGATION_VALUES, CoreModule,
|
|
5
|
+
import { AGGREGATION_VALUES, CoreModule, ModalModule, IconDirective, C8yTranslatePipe, CommonModule } from '@c8y/ngx-components';
|
|
6
|
+
import { gettext } from '@c8y/ngx-components/gettext';
|
|
7
7
|
import * as i3 from '@ngx-translate/core';
|
|
8
8
|
import JSZip from 'jszip';
|
|
9
9
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
10
|
-
import * as
|
|
10
|
+
import * as i2$1 from '@angular/forms';
|
|
11
11
|
import { FormsModule, FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
12
12
|
import saveAs from 'file-saver';
|
|
13
13
|
import { Subject, debounceTime, merge, takeUntil as takeUntil$1 } from 'rxjs';
|
|
14
|
-
import {
|
|
14
|
+
import { AGGREGATION_LABELS, AGGREGATION_VALUES_ARR } from '@c8y/ngx-components/global-context';
|
|
15
15
|
import * as i3$1 from 'ngx-bootstrap/popover';
|
|
16
16
|
import { PopoverModule } from 'ngx-bootstrap/popover';
|
|
17
|
-
import * as
|
|
18
|
-
import { AGGREGATION_LABELS, AGGREGATION_VALUES_ARR } from '@c8y/ngx-components/global-context';
|
|
17
|
+
import * as i3$2 from '@angular/common';
|
|
19
18
|
import { skip, takeUntil } from 'rxjs/operators';
|
|
20
19
|
import { isNil, isEmpty, isNumber } from 'lodash-es';
|
|
20
|
+
import { A11yModule } from '@angular/cdk/a11y';
|
|
21
21
|
import * as i1$1 from 'ngx-bootstrap/modal';
|
|
22
|
-
import * as
|
|
22
|
+
import * as i3$3 from 'ngx-bootstrap/tooltip';
|
|
23
23
|
import { TooltipModule } from 'ngx-bootstrap/tooltip';
|
|
24
24
|
|
|
25
25
|
const HAS_ERROR = 'has-error';
|
|
@@ -464,6 +464,68 @@ class DataFetchingService {
|
|
|
464
464
|
}
|
|
465
465
|
return seriesData;
|
|
466
466
|
}
|
|
467
|
+
/**
|
|
468
|
+
* Fetches snapshot data for list-type exports
|
|
469
|
+
* Gets the latest measurement for each datapoint within the date range
|
|
470
|
+
* @param exportConfig - The export configuration with list type
|
|
471
|
+
* @returns Promise with array of ListExportDatapoint objects
|
|
472
|
+
*/
|
|
473
|
+
async fetchAndPrepareListExportData(exportConfig) {
|
|
474
|
+
const { datapointDetails, dateFrom, dateTo } = exportConfig;
|
|
475
|
+
const dataPromises = datapointDetails.map(async (detail) => {
|
|
476
|
+
try {
|
|
477
|
+
// Fetch the latest measurement within the date range
|
|
478
|
+
const filter = {
|
|
479
|
+
dateFrom,
|
|
480
|
+
dateTo,
|
|
481
|
+
source: detail.source,
|
|
482
|
+
valueFragmentSeries: detail.valueFragmentSeries,
|
|
483
|
+
valueFragmentType: detail.valueFragmentType,
|
|
484
|
+
pageSize: 1, // Only get the most recent measurement
|
|
485
|
+
revert: true // Sort by newest first
|
|
486
|
+
};
|
|
487
|
+
const { data } = await this.measurementService.list(filter);
|
|
488
|
+
const measurement = data && data.length > 0 ? data[0] : null;
|
|
489
|
+
// Extract value and unit from measurement
|
|
490
|
+
let current = null;
|
|
491
|
+
let unit;
|
|
492
|
+
if (measurement) {
|
|
493
|
+
const fragment = measurement[detail.valueFragmentType];
|
|
494
|
+
if (fragment && fragment[detail.valueFragmentSeries]) {
|
|
495
|
+
const seriesData = fragment[detail.valueFragmentSeries];
|
|
496
|
+
current = seriesData.value != null ? Number(seriesData.value) : null;
|
|
497
|
+
unit = seriesData.unit;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
// Calculate derived values using target from detail
|
|
501
|
+
const target = detail.target;
|
|
502
|
+
const diff = current !== null && current !== undefined && target !== null && target !== undefined
|
|
503
|
+
? current - target
|
|
504
|
+
: null;
|
|
505
|
+
const diffPercent = target !== null && target !== undefined && diff !== null ? (diff / target) * 100 : null;
|
|
506
|
+
return {
|
|
507
|
+
...detail,
|
|
508
|
+
label: detail.label || `${detail.valueFragmentType}.${detail.valueFragmentSeries}`,
|
|
509
|
+
target: target ?? null,
|
|
510
|
+
current,
|
|
511
|
+
diff,
|
|
512
|
+
diffPercent,
|
|
513
|
+
unit
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
catch (error) {
|
|
517
|
+
return {
|
|
518
|
+
...detail,
|
|
519
|
+
label: detail.label || `${detail.valueFragmentType}.${detail.valueFragmentSeries}`,
|
|
520
|
+
target: detail.target ?? null,
|
|
521
|
+
current: null,
|
|
522
|
+
diff: null,
|
|
523
|
+
diffPercent: null
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
return Promise.all(dataPromises);
|
|
528
|
+
}
|
|
467
529
|
/**
|
|
468
530
|
* Fetches and prepares measurement data for preview.
|
|
469
531
|
*
|
|
@@ -570,6 +632,24 @@ class DatapointsExportSelectorFileExporterService {
|
|
|
570
632
|
this.cachedRawExportSeriesData = null;
|
|
571
633
|
this.cachedFlatteredAndSortedSeriesExportData = null;
|
|
572
634
|
}
|
|
635
|
+
/**
|
|
636
|
+
* Generates a blob for list-type exports (snapshot data)
|
|
637
|
+
* @param fileType - The type of file to generate (csv or excel)
|
|
638
|
+
* @param listData - Array of datapoints with current values
|
|
639
|
+
* @param columns - Column configuration for export
|
|
640
|
+
* @param dateRange - Date range for the export header
|
|
641
|
+
* @returns Promise with Blob or null on error
|
|
642
|
+
*/
|
|
643
|
+
async getListExportedDataBlob(fileType, listData, columns, dateRange) {
|
|
644
|
+
try {
|
|
645
|
+
const blob = await this.datapointsExportSelectorDataProcessingService.generateListExport(fileType, listData, columns, dateRange);
|
|
646
|
+
return blob;
|
|
647
|
+
}
|
|
648
|
+
catch (error) {
|
|
649
|
+
this.showZipCreationErrorAlert();
|
|
650
|
+
return null;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
573
653
|
showZipCreationErrorAlert() {
|
|
574
654
|
const alertMessage = this.translateService.instant(gettext('Could not create zip file.'));
|
|
575
655
|
this.alertService.danger(alertMessage);
|
|
@@ -631,28 +711,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
631
711
|
}]
|
|
632
712
|
}], ctorParameters: () => [{ type: i1.AlertService }, { type: DataProcessingService }, { type: i3.TranslateService }] });
|
|
633
713
|
|
|
634
|
-
class DataPointsExportSelectorPreviewComponent {
|
|
635
|
-
constructor() {
|
|
636
|
-
this.MEASUREMENTS_PREVIEW_ITEMS_LIMIT = MEASUREMENTS_PREVIEW_ITEMS_LIMIT;
|
|
637
|
-
}
|
|
638
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DataPointsExportSelectorPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
639
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: DataPointsExportSelectorPreviewComponent, isStandalone: true, selector: "c8y-datapoints-export-selector-preview", inputs: { hasFetchedDataAnyValuesToExport: "hasFetchedDataAnyValuesToExport", isPreviewLoading: "isPreviewLoading", previewTableData: "previewTableData" }, ngImport: i0, template: "<div class=\"p-t-16 p-l-16 p-r-16 m-b-0\">\n <div class=\"d-flex a-i-center\">\n <label\n class=\"m-b-0 d-flex a-i-center gap-4\"\n [title]=\"'Preview`of exported file`' | translate\"\n >\n {{ 'Preview`of exported file`' | translate }}\n <button\n class=\"btn-help\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"popoverPreviewTemplate\"\n placement=\"right\"\n triggers=\"focus\"\n data-cy=\"preview--help\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n <ng-template #popoverPreviewTemplate>\n <span translate>\n <p>The preview shows the structure of the raw file from a single source.</p>\n <p>If no data is available, only the column headers are visible.</p>\n <p>\n The preview is limited to\n <b>{{ MEASUREMENTS_PREVIEW_ITEMS_LIMIT }}</b>\n records.\n </p>\n </span>\n </ng-template>\n </label>\n </div>\n <div\n class=\"table-responsive\"\n style=\"min-height: 275px\"\n >\n <table class=\"table\">\n <thead>\n <tr>\n <th>{{ 'Time' | translate }}</th>\n <th>{{ 'Source' | translate }}</th>\n <th>{{ 'Device name' | translate }}</th>\n <th>\n {{ 'Fragment and series' | translate }}\n </th>\n <th>{{ 'Value' | translate }}</th>\n <th>{{ 'Unit' | translate }}</th>\n </tr>\n </thead>\n <ng-container *ngIf=\"hasFetchedDataAnyValuesToExport || isPreviewLoading; else emptyState\">\n <ng-container *ngIf=\"!isPreviewLoading; else loading\">\n <tbody>\n <tr *ngFor=\"let row of previewTableData\">\n <td>{{ row.time }}</td>\n <td>{{ row.source }}</td>\n <td>{{ row.device_name }}</td>\n <td>\n {{ row.fragment_series }}\n </td>\n <td>{{ row.value }}</td>\n <td>{{ row.unit }}</td>\n </tr>\n </tbody>\n </ng-container>\n </ng-container>\n <ng-template #emptyState>\n <tbody>\n <tr>\n <td colspan=\"8\">\n <div class=\"d-col a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No data available.' | translate\"\n [horizontal]=\"true\"\n data-cy=\"datapoints-table-list--empty-state\"\n ></c8y-ui-empty-state>\n </div>\n </td>\n </tr>\n </tbody>\n </ng-template>\n <ng-template #loading>\n <tbody>\n <tr>\n <td colspan=\"8\">\n <c8y-loading></c8y-loading>\n </td>\n </tr>\n </tbody>\n </ng-template>\n </table>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i1.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i3$1.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }] }); }
|
|
640
|
-
}
|
|
641
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DataPointsExportSelectorPreviewComponent, decorators: [{
|
|
642
|
-
type: Component,
|
|
643
|
-
args: [{ selector: 'c8y-datapoints-export-selector-preview', standalone: true, imports: [A11yModule, CoreModule, PopoverModule], template: "<div class=\"p-t-16 p-l-16 p-r-16 m-b-0\">\n <div class=\"d-flex a-i-center\">\n <label\n class=\"m-b-0 d-flex a-i-center gap-4\"\n [title]=\"'Preview`of exported file`' | translate\"\n >\n {{ 'Preview`of exported file`' | translate }}\n <button\n class=\"btn-help\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"popoverPreviewTemplate\"\n placement=\"right\"\n triggers=\"focus\"\n data-cy=\"preview--help\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n <ng-template #popoverPreviewTemplate>\n <span translate>\n <p>The preview shows the structure of the raw file from a single source.</p>\n <p>If no data is available, only the column headers are visible.</p>\n <p>\n The preview is limited to\n <b>{{ MEASUREMENTS_PREVIEW_ITEMS_LIMIT }}</b>\n records.\n </p>\n </span>\n </ng-template>\n </label>\n </div>\n <div\n class=\"table-responsive\"\n style=\"min-height: 275px\"\n >\n <table class=\"table\">\n <thead>\n <tr>\n <th>{{ 'Time' | translate }}</th>\n <th>{{ 'Source' | translate }}</th>\n <th>{{ 'Device name' | translate }}</th>\n <th>\n {{ 'Fragment and series' | translate }}\n </th>\n <th>{{ 'Value' | translate }}</th>\n <th>{{ 'Unit' | translate }}</th>\n </tr>\n </thead>\n <ng-container *ngIf=\"hasFetchedDataAnyValuesToExport || isPreviewLoading; else emptyState\">\n <ng-container *ngIf=\"!isPreviewLoading; else loading\">\n <tbody>\n <tr *ngFor=\"let row of previewTableData\">\n <td>{{ row.time }}</td>\n <td>{{ row.source }}</td>\n <td>{{ row.device_name }}</td>\n <td>\n {{ row.fragment_series }}\n </td>\n <td>{{ row.value }}</td>\n <td>{{ row.unit }}</td>\n </tr>\n </tbody>\n </ng-container>\n </ng-container>\n <ng-template #emptyState>\n <tbody>\n <tr>\n <td colspan=\"8\">\n <div class=\"d-col a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No data available.' | translate\"\n [horizontal]=\"true\"\n data-cy=\"datapoints-table-list--empty-state\"\n ></c8y-ui-empty-state>\n </div>\n </td>\n </tr>\n </tbody>\n </ng-template>\n <ng-template #loading>\n <tbody>\n <tr>\n <td colspan=\"8\">\n <c8y-loading></c8y-loading>\n </td>\n </tr>\n </tbody>\n </ng-template>\n </table>\n </div>\n</div>\n" }]
|
|
644
|
-
}], propDecorators: { hasFetchedDataAnyValuesToExport: [{
|
|
645
|
-
type: Input
|
|
646
|
-
}], isPreviewLoading: [{
|
|
647
|
-
type: Input
|
|
648
|
-
}], previewTableData: [{
|
|
649
|
-
type: Input
|
|
650
|
-
}] } });
|
|
651
|
-
|
|
652
714
|
class DataPointsExportSelectorDataScopeComponent {
|
|
653
715
|
constructor() {
|
|
654
|
-
this.
|
|
655
|
-
this.
|
|
716
|
+
this.disabledAggregationOptions = input.required(...(ngDevMode ? [{ debugName: "disabledAggregationOptions" }] : []));
|
|
717
|
+
this.formGroup = input.required(...(ngDevMode ? [{ debugName: "formGroup" }] : []));
|
|
718
|
+
this.onAggregationChange = output();
|
|
719
|
+
this.onExportTypeChange = output();
|
|
656
720
|
this.AGGREGATION_LABELS = AGGREGATION_LABELS;
|
|
657
721
|
this.AGGREGATION_VALUES_ARR = AGGREGATION_VALUES_ARR;
|
|
658
722
|
this.EXPORT_MODE_LABELS = EXPORT_MODE_LABELS;
|
|
@@ -665,41 +729,31 @@ class DataPointsExportSelectorDataScopeComponent {
|
|
|
665
729
|
this.onExportTypeChange.emit(exportType);
|
|
666
730
|
}
|
|
667
731
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DataPointsExportSelectorDataScopeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
668
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
732
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: DataPointsExportSelectorDataScopeComponent, isStandalone: true, selector: "c8y-datapoints-export-selector-data-scope", inputs: { disabledAggregationOptions: { classPropertyName: "disabledAggregationOptions", publicName: "disabledAggregationOptions", isSignal: true, isRequired: true, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onAggregationChange: "onAggregationChange", onExportTypeChange: "onExportTypeChange" }, ngImport: i0, template: "<fieldset class=\"c8y-fieldset\">\n <legend class=\"d-flex a-i-center\">\n {{ 'Data scope' | translate }}\n <button\n class=\"btn-help\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"popoverDataScopeTemplate\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n data-cy=\"data-scope--help\"\n [adaptivePosition]=\"true\"\n ></button>\n <ng-template #popoverDataScopeTemplate>\n <p\n class=\"m-b-8\"\n translate\n >\n Choose export type from available options:\n </p>\n <p><strong translate>Compact</strong></p>\n <ul class=\"p-l-16\">\n <li translate>Up to 5,000 records per data point or data retention limit</li>\n <li translate>Single merged file for all data</li>\n <li translate>No preview available</li>\n <li translate>Optional data aggregation supported</li>\n </ul>\n <p><strong translate>Full</strong></p>\n <ul class=\"p-l-16\">\n <li translate>Up to 1,000,000 records per data point or data retention limit</li>\n <li translate>Email delivery if exceeds 50,000 records</li>\n <li translate>Separate files for each data point in ZIP format</li>\n <li translate>Preview available</li>\n <li translate>No data aggregation</li>\n </ul>\n </ng-template>\n </legend>\n <c8y-form-group class=\"m-b-8\">\n <label>\n {{ 'Export mode' | translate }}\n </label>\n <div\n class=\"c8y-select-wrapper\"\n [formGroup]=\"formGroup()\"\n data-cy=\"data-scope--export-selector\"\n >\n <select\n class=\"form-control text-12\"\n [title]=\"'Export mode' | translate\"\n id=\"exportMode\"\n formControlName=\"exportMode\"\n (ngModelChange)=\"emitExportTypeChange($event)\"\n >\n @for (exportModeValue of EXPORT_MODE_VALUES_ARR; track exportModeValue) {\n <option [ngValue]=\"exportModeValue\">\n {{ EXPORT_MODE_LABELS[exportModeValue] | translate }}\n </option>\n }\n </select>\n </div>\n </c8y-form-group>\n <c8y-form-group class=\"m-b-8\">\n <label>\n {{ 'Aggregation' | translate }}\n </label>\n <div\n class=\"c8y-select-wrapper\"\n [formGroup]=\"formGroup()\"\n data-cy=\"data-scope--aggregation-selector\"\n >\n <select\n class=\"form-control text-12\"\n [title]=\"'Aggregation' | translate\"\n id=\"aggregation\"\n formControlName=\"aggregation\"\n (ngModelChange)=\"emitAggregationChange($event)\"\n >\n @for (aggregationValue of AGGREGATION_VALUES_ARR; track aggregationValue) {\n <option\n [ngValue]=\"aggregationValue\"\n [disabled]=\"disabledAggregationOptions()[aggregationValue]\"\n >\n {{ AGGREGATION_LABELS[aggregationValue] | translate }}\n </option>\n }\n </select>\n </div>\n </c8y-form-group>\n</fieldset>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i1.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i3$1.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
669
733
|
}
|
|
670
734
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DataPointsExportSelectorDataScopeComponent, decorators: [{
|
|
671
735
|
type: Component,
|
|
672
|
-
args: [{ selector: 'c8y-datapoints-export-selector-data-scope',
|
|
673
|
-
}], propDecorators: { disabledAggregationOptions: [{
|
|
674
|
-
type: Input
|
|
675
|
-
}], formGroup: [{
|
|
676
|
-
type: Input
|
|
677
|
-
}], onAggregationChange: [{
|
|
678
|
-
type: Output
|
|
679
|
-
}], onExportTypeChange: [{
|
|
680
|
-
type: Output
|
|
681
|
-
}] } });
|
|
736
|
+
args: [{ selector: 'c8y-datapoints-export-selector-data-scope', imports: [CoreModule, FormsModule, PopoverModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<fieldset class=\"c8y-fieldset\">\n <legend class=\"d-flex a-i-center\">\n {{ 'Data scope' | translate }}\n <button\n class=\"btn-help\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"popoverDataScopeTemplate\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n data-cy=\"data-scope--help\"\n [adaptivePosition]=\"true\"\n ></button>\n <ng-template #popoverDataScopeTemplate>\n <p\n class=\"m-b-8\"\n translate\n >\n Choose export type from available options:\n </p>\n <p><strong translate>Compact</strong></p>\n <ul class=\"p-l-16\">\n <li translate>Up to 5,000 records per data point or data retention limit</li>\n <li translate>Single merged file for all data</li>\n <li translate>No preview available</li>\n <li translate>Optional data aggregation supported</li>\n </ul>\n <p><strong translate>Full</strong></p>\n <ul class=\"p-l-16\">\n <li translate>Up to 1,000,000 records per data point or data retention limit</li>\n <li translate>Email delivery if exceeds 50,000 records</li>\n <li translate>Separate files for each data point in ZIP format</li>\n <li translate>Preview available</li>\n <li translate>No data aggregation</li>\n </ul>\n </ng-template>\n </legend>\n <c8y-form-group class=\"m-b-8\">\n <label>\n {{ 'Export mode' | translate }}\n </label>\n <div\n class=\"c8y-select-wrapper\"\n [formGroup]=\"formGroup()\"\n data-cy=\"data-scope--export-selector\"\n >\n <select\n class=\"form-control text-12\"\n [title]=\"'Export mode' | translate\"\n id=\"exportMode\"\n formControlName=\"exportMode\"\n (ngModelChange)=\"emitExportTypeChange($event)\"\n >\n @for (exportModeValue of EXPORT_MODE_VALUES_ARR; track exportModeValue) {\n <option [ngValue]=\"exportModeValue\">\n {{ EXPORT_MODE_LABELS[exportModeValue] | translate }}\n </option>\n }\n </select>\n </div>\n </c8y-form-group>\n <c8y-form-group class=\"m-b-8\">\n <label>\n {{ 'Aggregation' | translate }}\n </label>\n <div\n class=\"c8y-select-wrapper\"\n [formGroup]=\"formGroup()\"\n data-cy=\"data-scope--aggregation-selector\"\n >\n <select\n class=\"form-control text-12\"\n [title]=\"'Aggregation' | translate\"\n id=\"aggregation\"\n formControlName=\"aggregation\"\n (ngModelChange)=\"emitAggregationChange($event)\"\n >\n @for (aggregationValue of AGGREGATION_VALUES_ARR; track aggregationValue) {\n <option\n [ngValue]=\"aggregationValue\"\n [disabled]=\"disabledAggregationOptions()[aggregationValue]\"\n >\n {{ AGGREGATION_LABELS[aggregationValue] | translate }}\n </option>\n }\n </select>\n </div>\n </c8y-form-group>\n</fieldset>\n" }]
|
|
737
|
+
}], propDecorators: { disabledAggregationOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledAggregationOptions", required: true }] }], formGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "formGroup", required: true }] }], onAggregationChange: [{ type: i0.Output, args: ["onAggregationChange"] }], onExportTypeChange: [{ type: i0.Output, args: ["onExportTypeChange"] }] } });
|
|
682
738
|
|
|
683
739
|
class DataPointsExportSelectorFileTypesComponent {
|
|
684
740
|
constructor() {
|
|
685
|
-
this.dynamicFilesTypeMetadata = {};
|
|
741
|
+
this.dynamicFilesTypeMetadata = input({}, ...(ngDevMode ? [{ debugName: "dynamicFilesTypeMetadata" }] : []));
|
|
742
|
+
this.formGroup = input.required(...(ngDevMode ? [{ debugName: "formGroup" }] : []));
|
|
686
743
|
}
|
|
687
744
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DataPointsExportSelectorFileTypesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
688
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
745
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: DataPointsExportSelectorFileTypesComponent, isStandalone: true, selector: "c8y-datapoints-export-selector-file-types", inputs: { dynamicFilesTypeMetadata: { classPropertyName: "dynamicFilesTypeMetadata", publicName: "dynamicFilesTypeMetadata", isSignal: true, isRequired: false, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<fieldset class=\"c8y-fieldset\">\n <legend class=\"d-flex a-i-center\">{{ 'File types' | translate }}</legend>\n <div [formGroup]=\"formGroup()\">\n <div formGroupName=\"fileTypes\">\n @for (item of dynamicFilesTypeMetadata() | keyvalue; track item.key) {\n <c8y-form-group class=\"m-b-8\">\n <label\n class=\"c8y-checkbox m-t-0\"\n title=\"{{ item.value.title }}\"\n >\n <input\n type=\"checkbox\"\n formControlName=\"{{ item.key }}\"\n />\n <span></span>\n <i\n class=\"m-l-8 m-r-4\"\n c8yIcon=\"{{ item.value.icon }}\"\n ></i>\n <span>{{ item.value.label | translate }}</span>\n </label>\n </c8y-form-group>\n }\n </div>\n </div>\n</fieldset>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i1.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i1.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3$2.KeyValuePipe, name: "keyvalue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
689
746
|
}
|
|
690
747
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DataPointsExportSelectorFileTypesComponent, decorators: [{
|
|
691
748
|
type: Component,
|
|
692
|
-
args: [{ selector: 'c8y-datapoints-export-selector-file-types',
|
|
693
|
-
}], propDecorators: { dynamicFilesTypeMetadata: [{
|
|
694
|
-
type: Input
|
|
695
|
-
}], formGroup: [{
|
|
696
|
-
type: Input
|
|
697
|
-
}] } });
|
|
749
|
+
args: [{ selector: 'c8y-datapoints-export-selector-file-types', imports: [CoreModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<fieldset class=\"c8y-fieldset\">\n <legend class=\"d-flex a-i-center\">{{ 'File types' | translate }}</legend>\n <div [formGroup]=\"formGroup()\">\n <div formGroupName=\"fileTypes\">\n @for (item of dynamicFilesTypeMetadata() | keyvalue; track item.key) {\n <c8y-form-group class=\"m-b-8\">\n <label\n class=\"c8y-checkbox m-t-0\"\n title=\"{{ item.value.title }}\"\n >\n <input\n type=\"checkbox\"\n formControlName=\"{{ item.key }}\"\n />\n <span></span>\n <i\n class=\"m-l-8 m-r-4\"\n c8yIcon=\"{{ item.value.icon }}\"\n ></i>\n <span>{{ item.value.label | translate }}</span>\n </label>\n </c8y-form-group>\n }\n </div>\n </div>\n</fieldset>\n" }]
|
|
750
|
+
}], propDecorators: { dynamicFilesTypeMetadata: [{ type: i0.Input, args: [{ isSignal: true, alias: "dynamicFilesTypeMetadata", required: false }] }], formGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "formGroup", required: true }] }] } });
|
|
698
751
|
|
|
699
752
|
class DataPointsExportSelectorTimeRangeComponent {
|
|
700
753
|
constructor() {
|
|
701
|
-
this.
|
|
702
|
-
this.
|
|
754
|
+
this.formGroup = input.required(...(ngDevMode ? [{ debugName: "formGroup" }] : []));
|
|
755
|
+
this.onDateFromChange = output();
|
|
756
|
+
this.onDateToChange = output();
|
|
703
757
|
this.destroy$ = new Subject();
|
|
704
758
|
this.DATE_FROM = 'dateFrom';
|
|
705
759
|
this.DATE_TO = 'dateTo';
|
|
@@ -712,14 +766,15 @@ class DataPointsExportSelectorTimeRangeComponent {
|
|
|
712
766
|
this.TO_DATE = gettext('To`date`');
|
|
713
767
|
}
|
|
714
768
|
ngOnInit() {
|
|
715
|
-
|
|
716
|
-
|
|
769
|
+
const fg = this.formGroup();
|
|
770
|
+
if (fg?.controls?.dateFrom) {
|
|
771
|
+
fg.controls.dateFrom.valueChanges
|
|
717
772
|
// Skip the first value emitted by the observable to avoid overriding the initial value while form is being created
|
|
718
773
|
.pipe(skip(1), takeUntil(this.destroy$))
|
|
719
774
|
.subscribe((updatedDate) => this.onDateFromChange.emit(updatedDate));
|
|
720
775
|
}
|
|
721
|
-
if (
|
|
722
|
-
|
|
776
|
+
if (fg?.controls?.dateTo) {
|
|
777
|
+
fg.controls.dateTo.valueChanges
|
|
723
778
|
// Skip the first value emitted by the observable to avoid overriding the initial value while form is being created
|
|
724
779
|
.pipe(skip(1), takeUntil(this.destroy$))
|
|
725
780
|
.subscribe((updatedDate) => this.onDateToChange.emit(updatedDate));
|
|
@@ -730,18 +785,12 @@ class DataPointsExportSelectorTimeRangeComponent {
|
|
|
730
785
|
this.destroy$.complete();
|
|
731
786
|
}
|
|
732
787
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DataPointsExportSelectorTimeRangeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
733
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
788
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: DataPointsExportSelectorTimeRangeComponent, isStandalone: true, selector: "c8y-datapoints-export-selector-time-range", inputs: { formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onDateFromChange: "onDateFromChange", onDateToChange: "onDateToChange" }, ngImport: i0, template: "<fieldset class=\"c8y-fieldset\">\n <legend>{{ 'Time range' | translate }}</legend>\n <c8y-form-group\n class=\"m-b-8 d-flex gap-4 a-i-center\"\n [class]=\"formGroup().controls.dateFrom.errors ? HAS_ERROR : ''\"\n >\n <label\n class=\"m-b-0\"\n style=\"min-width: 120px\"\n [title]=\"FROM_DATE | translate\"\n [for]=\"DATE_FROM\"\n >\n {{ FROM_DATE | translate }}\n </label>\n <div>\n <c8y-date-time-picker\n [class]=\"formGroup().controls.dateFrom.errors ? HAS_ERROR : ''\"\n id=\"DATE_FROM\"\n [maxDate]=\"formGroup().controls.dateTo.value ?? ''\"\n [placeholder]=\"FROM_DATE | translate\"\n [formControl]=\"formGroup().controls.dateFrom\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"formGroup().controls.dateFrom.errors ?? {}\">\n <c8y-message\n name=\"dateAfterRangeMax\"\n [text]=\"THIS_DATE_IS_AFTER_THE_LAST_ALLOWED_DATE | translate\"\n ></c8y-message>\n <c8y-message\n name=\"INVALID_DATE_TIME\"\n [text]=\"THIS_DATE_IS_INVALID | translate\"\n ></c8y-message>\n </c8y-messages>\n </div>\n </c8y-form-group>\n <c8y-form-group\n class=\"m-b-8 d-flex gap-4 a-i-center\"\n [class]=\"formGroup().controls.dateTo.errors ? HAS_ERROR : ''\"\n >\n <label\n class=\"m-b-0\"\n style=\"min-width: 120px\"\n [title]=\"TO_DATE | translate\"\n [for]=\"DATE_TO\"\n >\n {{ TO_DATE | translate }}\n </label>\n <div>\n <c8y-date-time-picker\n [class]=\"formGroup().controls.dateTo.errors ? HAS_ERROR : ''\"\n id=\"DATE_TO\"\n [minDate]=\"formGroup().controls.dateFrom.value ?? ''\"\n [placeholder]=\"TO_DATE | translate\"\n [formControl]=\"formGroup().controls.dateTo\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"formGroup().controls.dateTo.errors ?? {}\">\n <c8y-message\n name=\"dateBeforeRangeMin\"\n [text]=\"THIS_DATE_IS_BEFORE_THE_EARLIEST_ALLOWED_DATE | translate\"\n ></c8y-message>\n <c8y-message\n name=\"INVALID_DATE_TIME\"\n [text]=\"THIS_DATE_IS_INVALID | translate\"\n ></c8y-message>\n </c8y-messages>\n </div>\n </c8y-form-group>\n</fieldset>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: i1.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i1.MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "component", type: i1.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i1.DateTimePickerComponent, selector: "c8y-date-time-picker", inputs: ["minDate", "maxDate", "placeholder", "dateInputFormat", "adaptivePosition", "size", "dateType", "config"], outputs: ["onDateSelected"] }, { kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
734
789
|
}
|
|
735
790
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DataPointsExportSelectorTimeRangeComponent, decorators: [{
|
|
736
791
|
type: Component,
|
|
737
|
-
args: [{ selector: 'c8y-datapoints-export-selector-time-range',
|
|
738
|
-
}], propDecorators: { formGroup: [{
|
|
739
|
-
type: Input
|
|
740
|
-
}], onDateFromChange: [{
|
|
741
|
-
type: Output
|
|
742
|
-
}], onDateToChange: [{
|
|
743
|
-
type: Output
|
|
744
|
-
}] } });
|
|
792
|
+
args: [{ selector: 'c8y-datapoints-export-selector-time-range', imports: [CoreModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<fieldset class=\"c8y-fieldset\">\n <legend>{{ 'Time range' | translate }}</legend>\n <c8y-form-group\n class=\"m-b-8 d-flex gap-4 a-i-center\"\n [class]=\"formGroup().controls.dateFrom.errors ? HAS_ERROR : ''\"\n >\n <label\n class=\"m-b-0\"\n style=\"min-width: 120px\"\n [title]=\"FROM_DATE | translate\"\n [for]=\"DATE_FROM\"\n >\n {{ FROM_DATE | translate }}\n </label>\n <div>\n <c8y-date-time-picker\n [class]=\"formGroup().controls.dateFrom.errors ? HAS_ERROR : ''\"\n id=\"DATE_FROM\"\n [maxDate]=\"formGroup().controls.dateTo.value ?? ''\"\n [placeholder]=\"FROM_DATE | translate\"\n [formControl]=\"formGroup().controls.dateFrom\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"formGroup().controls.dateFrom.errors ?? {}\">\n <c8y-message\n name=\"dateAfterRangeMax\"\n [text]=\"THIS_DATE_IS_AFTER_THE_LAST_ALLOWED_DATE | translate\"\n ></c8y-message>\n <c8y-message\n name=\"INVALID_DATE_TIME\"\n [text]=\"THIS_DATE_IS_INVALID | translate\"\n ></c8y-message>\n </c8y-messages>\n </div>\n </c8y-form-group>\n <c8y-form-group\n class=\"m-b-8 d-flex gap-4 a-i-center\"\n [class]=\"formGroup().controls.dateTo.errors ? HAS_ERROR : ''\"\n >\n <label\n class=\"m-b-0\"\n style=\"min-width: 120px\"\n [title]=\"TO_DATE | translate\"\n [for]=\"DATE_TO\"\n >\n {{ TO_DATE | translate }}\n </label>\n <div>\n <c8y-date-time-picker\n [class]=\"formGroup().controls.dateTo.errors ? HAS_ERROR : ''\"\n id=\"DATE_TO\"\n [minDate]=\"formGroup().controls.dateFrom.value ?? ''\"\n [placeholder]=\"TO_DATE | translate\"\n [formControl]=\"formGroup().controls.dateTo\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"formGroup().controls.dateTo.errors ?? {}\">\n <c8y-message\n name=\"dateBeforeRangeMin\"\n [text]=\"THIS_DATE_IS_BEFORE_THE_EARLIEST_ALLOWED_DATE | translate\"\n ></c8y-message>\n <c8y-message\n name=\"INVALID_DATE_TIME\"\n [text]=\"THIS_DATE_IS_INVALID | translate\"\n ></c8y-message>\n </c8y-messages>\n </div>\n </c8y-form-group>\n</fieldset>\n" }]
|
|
793
|
+
}], propDecorators: { formGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "formGroup", required: true }] }], onDateFromChange: [{ type: i0.Output, args: ["onDateFromChange"] }], onDateToChange: [{ type: i0.Output, args: ["onDateToChange"] }] } });
|
|
745
794
|
|
|
746
795
|
class CSVDataTransformer {
|
|
747
796
|
transformToMergedFormat(exportData) {
|
|
@@ -819,6 +868,41 @@ class CSVGenerator {
|
|
|
819
868
|
const csvContent = rows.map(row => row.join(',')).join('\n');
|
|
820
869
|
return instance.fileCreator.createFile(csvContent, CSVGenerator.getMimeType());
|
|
821
870
|
}
|
|
871
|
+
/**
|
|
872
|
+
* Converts list-type datapoints to CSV format
|
|
873
|
+
* @param listData - Array of datapoints with current values
|
|
874
|
+
* @param columns - Column configuration specifying which columns to include and their order
|
|
875
|
+
* @returns Promise with CSV Blob
|
|
876
|
+
*/
|
|
877
|
+
static async convertToListCSV(listData, columns) {
|
|
878
|
+
const instance = CSVGenerator.getInstance();
|
|
879
|
+
const sortedColumns = columns.sort((a, b) => a.order - b.order);
|
|
880
|
+
const headers = sortedColumns.map(col => col.label);
|
|
881
|
+
const columnMapping = {
|
|
882
|
+
kpi: 'label',
|
|
883
|
+
target: 'target',
|
|
884
|
+
current: 'current',
|
|
885
|
+
diff: 'diff',
|
|
886
|
+
diffPercentage: 'diffPercent',
|
|
887
|
+
asset: 'deviceName'
|
|
888
|
+
};
|
|
889
|
+
const dataRows = listData.map(datapoint => {
|
|
890
|
+
return sortedColumns.map(col => {
|
|
891
|
+
const propKey = columnMapping[col.id];
|
|
892
|
+
const value = datapoint[propKey];
|
|
893
|
+
if (value === null || value === undefined) {
|
|
894
|
+
return '';
|
|
895
|
+
}
|
|
896
|
+
if (typeof value === 'number') {
|
|
897
|
+
return value.toFixed(2);
|
|
898
|
+
}
|
|
899
|
+
return String(value);
|
|
900
|
+
});
|
|
901
|
+
});
|
|
902
|
+
const allRows = [headers, ...dataRows];
|
|
903
|
+
const csvContent = allRows.map(row => row.join(',')).join('\n');
|
|
904
|
+
return instance.fileCreator.createFile(csvContent, CSVGenerator.getMimeType());
|
|
905
|
+
}
|
|
822
906
|
static getInstance() {
|
|
823
907
|
if (!CSVGenerator.instance) {
|
|
824
908
|
CSVGenerator.instance = new CSVGenerator();
|
|
@@ -856,12 +940,18 @@ const CSVGeneratorAdapter = {
|
|
|
856
940
|
getFileExtension: CSVGenerator.getFileExtension.bind(CSVGenerator),
|
|
857
941
|
getMimeType: CSVGenerator.getMimeType.bind(CSVGenerator),
|
|
858
942
|
generateMerged: CSVGenerator.convertToMergedCSV.bind(CSVGenerator),
|
|
943
|
+
generateList: CSVGenerator.convertToListCSV.bind(CSVGenerator),
|
|
859
944
|
getType: CSVGenerator.getType.bind(CSVGenerator),
|
|
860
945
|
getTitle: CSVGenerator.getTitle.bind(CSVGenerator),
|
|
861
946
|
getZipName: CSVGenerator.getZipName.bind(CSVGenerator),
|
|
862
947
|
getAcceptType: CSVGenerator.getAcceptType.bind(CSVGenerator)
|
|
863
948
|
};
|
|
864
949
|
|
|
950
|
+
var csvGenerator = /*#__PURE__*/Object.freeze({
|
|
951
|
+
__proto__: null,
|
|
952
|
+
CSVGeneratorAdapter: CSVGeneratorAdapter
|
|
953
|
+
});
|
|
954
|
+
|
|
865
955
|
// Utility functions
|
|
866
956
|
class XmlUtils {
|
|
867
957
|
static escapeXml(unsafe) {
|
|
@@ -1080,6 +1170,40 @@ class ExcelGenerator {
|
|
|
1080
1170
|
];
|
|
1081
1171
|
return instance.createExcelFile(rows, mergedExportDetails);
|
|
1082
1172
|
}
|
|
1173
|
+
/**
|
|
1174
|
+
* Converts list-type datapoints to Excel format
|
|
1175
|
+
* @param listData - Array of datapoints with current values
|
|
1176
|
+
* @param columns - Column configuration specifying which columns to include and their order
|
|
1177
|
+
* @returns Promise with Excel Blob
|
|
1178
|
+
*/
|
|
1179
|
+
static async convertToListExcel(listData, columns) {
|
|
1180
|
+
const instance = ExcelGenerator.getInstance();
|
|
1181
|
+
const sortedColumns = columns.sort((a, b) => a.order - b.order);
|
|
1182
|
+
const headers = sortedColumns.map(col => col.label);
|
|
1183
|
+
const columnMapping = {
|
|
1184
|
+
kpi: 'label',
|
|
1185
|
+
target: 'target',
|
|
1186
|
+
current: 'current',
|
|
1187
|
+
diff: 'diff',
|
|
1188
|
+
diffPercentage: 'diffPercent',
|
|
1189
|
+
asset: 'deviceName'
|
|
1190
|
+
};
|
|
1191
|
+
const dataRows = listData.map(datapoint => {
|
|
1192
|
+
return sortedColumns.map(col => {
|
|
1193
|
+
const propKey = columnMapping[col.id];
|
|
1194
|
+
const value = datapoint[propKey];
|
|
1195
|
+
if (value === null || value === undefined) {
|
|
1196
|
+
return '';
|
|
1197
|
+
}
|
|
1198
|
+
if (typeof value === 'number') {
|
|
1199
|
+
return value.toFixed(2);
|
|
1200
|
+
}
|
|
1201
|
+
return String(value);
|
|
1202
|
+
});
|
|
1203
|
+
});
|
|
1204
|
+
const allRows = [headers, ...dataRows];
|
|
1205
|
+
return instance.createExcelFile(allRows);
|
|
1206
|
+
}
|
|
1083
1207
|
static getInstance() {
|
|
1084
1208
|
if (!ExcelGenerator.instance) {
|
|
1085
1209
|
ExcelGenerator.instance = new ExcelGenerator();
|
|
@@ -1134,12 +1258,19 @@ const ExcelGeneratorAdapter = {
|
|
|
1134
1258
|
getFileExtension: ExcelGenerator.getFileExtension.bind(ExcelGenerator),
|
|
1135
1259
|
getMimeType: ExcelGenerator.getMimeType.bind(ExcelGenerator),
|
|
1136
1260
|
generateMerged: ExcelGenerator.convertToMergedExcel.bind(ExcelGenerator),
|
|
1261
|
+
generateList: ExcelGenerator.convertToListExcel.bind(ExcelGenerator),
|
|
1137
1262
|
getType: ExcelGenerator.getType.bind(ExcelGenerator),
|
|
1138
1263
|
getTitle: ExcelGenerator.getTitle.bind(ExcelGenerator),
|
|
1139
1264
|
getZipName: ExcelGenerator.getZipName.bind(ExcelGenerator),
|
|
1140
1265
|
getAcceptType: ExcelGenerator.getAcceptType.bind(ExcelGenerator)
|
|
1141
1266
|
};
|
|
1142
1267
|
|
|
1268
|
+
var excelGenerator = /*#__PURE__*/Object.freeze({
|
|
1269
|
+
__proto__: null,
|
|
1270
|
+
ExcelDataTransformer: ExcelDataTransformer,
|
|
1271
|
+
ExcelGeneratorAdapter: ExcelGeneratorAdapter
|
|
1272
|
+
});
|
|
1273
|
+
|
|
1143
1274
|
const FILE_GENERATORS = new InjectionToken('FILE_GENERATORS', {
|
|
1144
1275
|
providedIn: 'root',
|
|
1145
1276
|
factory: () => [ExcelGeneratorAdapter, CSVGeneratorAdapter]
|
|
@@ -1165,15 +1296,28 @@ const dateRangeValidator = (control) => {
|
|
|
1165
1296
|
return null;
|
|
1166
1297
|
};
|
|
1167
1298
|
class DatapointsExportSelectorFileExporterComponent {
|
|
1168
|
-
|
|
1299
|
+
get isPreviewLoading() {
|
|
1300
|
+
return this._isPreviewLoading;
|
|
1301
|
+
}
|
|
1302
|
+
set isPreviewLoading(value) {
|
|
1303
|
+
if (this._isPreviewLoading !== value) {
|
|
1304
|
+
this._isPreviewLoading = value;
|
|
1305
|
+
this.previewLoadingChange.emit(value);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
constructor(aggregationService, cdr, datapointsExportModalService, datapointsExportSelectorFileExporterService, dataFetchingService, formBuilder, generators, gainsightService) {
|
|
1169
1309
|
this.aggregationService = aggregationService;
|
|
1310
|
+
this.cdr = cdr;
|
|
1170
1311
|
this.datapointsExportModalService = datapointsExportModalService;
|
|
1171
1312
|
this.datapointsExportSelectorFileExporterService = datapointsExportSelectorFileExporterService;
|
|
1172
1313
|
this.dataFetchingService = dataFetchingService;
|
|
1173
1314
|
this.formBuilder = formBuilder;
|
|
1174
1315
|
this.generators = generators;
|
|
1175
1316
|
this.gainsightService = gainsightService;
|
|
1176
|
-
this.
|
|
1317
|
+
this.exportConfig = input.required(...(ngDevMode ? [{ debugName: "exportConfig" }] : []));
|
|
1318
|
+
this.onDownloadButtonStateChange = output();
|
|
1319
|
+
this.previewAvailabilityChange = output();
|
|
1320
|
+
this.previewLoadingChange = output();
|
|
1177
1321
|
/**
|
|
1178
1322
|
* Represents aggregation selector options that are disabled.
|
|
1179
1323
|
* This state is determined based on the current date range.
|
|
@@ -1190,13 +1334,24 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1190
1334
|
*/
|
|
1191
1335
|
this.hasFetchedDataAnyValuesToExport = false;
|
|
1192
1336
|
this.hasPermissionToReadAnyMeasurements = false;
|
|
1193
|
-
this.
|
|
1337
|
+
this.isCheckingPermissions = true;
|
|
1338
|
+
this._isPreviewLoading = true;
|
|
1194
1339
|
/**
|
|
1195
1340
|
* Indicates whether the full or compact type of export is selected.
|
|
1196
1341
|
* Full type of export is based on measurement API data.
|
|
1197
1342
|
* Compact type of export is based on series API data.
|
|
1198
1343
|
*/
|
|
1199
1344
|
this.isFullTypeOfExport = false;
|
|
1345
|
+
/**
|
|
1346
|
+
* Indicates whether list-type export is selected.
|
|
1347
|
+
* List type of export is a snapshot of current datapoints values.
|
|
1348
|
+
*/
|
|
1349
|
+
this.isListTypeOfExport = false;
|
|
1350
|
+
/**
|
|
1351
|
+
* Indicates whether the Data Scope component should be visible.
|
|
1352
|
+
* Hidden for list-type exports, visible for table-type exports.
|
|
1353
|
+
*/
|
|
1354
|
+
this.isDataScopeVisible = true;
|
|
1200
1355
|
/**
|
|
1201
1356
|
* Indicates whether the aggregation value was changed programmatically.
|
|
1202
1357
|
* It prevents a case where fetching may be triggered twice when export type is changed.
|
|
@@ -1236,25 +1391,36 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1236
1391
|
});
|
|
1237
1392
|
}
|
|
1238
1393
|
async ngOnInit() {
|
|
1239
|
-
|
|
1394
|
+
this.isListTypeOfExport = this.exportConfig().exportType === 'latestWithDetails';
|
|
1395
|
+
this.isDataScopeVisible = !this.isListTypeOfExport;
|
|
1396
|
+
this.emitPreviewAvailability();
|
|
1397
|
+
const sourcesPermittedToRead = await this.dataFetchingService.getSourcesWithPermissionsToRead(this.exportConfig().datapointDetails);
|
|
1398
|
+
this.isCheckingPermissions = false;
|
|
1399
|
+
this.cdr.markForCheck();
|
|
1240
1400
|
if (sourcesPermittedToRead.length === 0) {
|
|
1241
1401
|
return;
|
|
1242
1402
|
}
|
|
1243
|
-
if (sourcesPermittedToRead.length !== this.exportConfig.datapointDetails.length) {
|
|
1244
|
-
this.exportConfig.datapointDetails = this.exportConfig.datapointDetails.filter(dataPoint => sourcesPermittedToRead.includes(String(dataPoint.source)));
|
|
1403
|
+
if (sourcesPermittedToRead.length !== this.exportConfig().datapointDetails.length) {
|
|
1404
|
+
this.exportConfig().datapointDetails = this.exportConfig().datapointDetails.filter(dataPoint => sourcesPermittedToRead.includes(String(dataPoint.source)));
|
|
1245
1405
|
}
|
|
1246
1406
|
this.hasPermissionToReadAnyMeasurements = true;
|
|
1247
1407
|
this.storeInitialChangeableConfig();
|
|
1248
1408
|
this.fileTypeSelectionState = this.getInitialSelection(this.dynamicFilesTypeMetadata, [0]);
|
|
1249
1409
|
this.formGroup = this.createForm();
|
|
1250
|
-
this.
|
|
1410
|
+
this.isPreviewLoading = true;
|
|
1411
|
+
if (this.isListTypeOfExport) {
|
|
1412
|
+
await this.loadListExportData();
|
|
1413
|
+
}
|
|
1414
|
+
else {
|
|
1415
|
+
await this.loadTableExportData();
|
|
1416
|
+
this.handleExportModeChanges();
|
|
1417
|
+
}
|
|
1251
1418
|
this.handleDateSelectorChanges();
|
|
1252
|
-
this.determineShowingPreviewOrEmptyState();
|
|
1253
|
-
this.handleExportModeChanges();
|
|
1254
1419
|
this.handleFileTypeSelectionChanges();
|
|
1255
1420
|
this.handleFormValidationChanges();
|
|
1256
1421
|
this.updateFileTypeControl();
|
|
1257
1422
|
this.updateDisabledAggregationOptions();
|
|
1423
|
+
this.cdr.markForCheck();
|
|
1258
1424
|
}
|
|
1259
1425
|
ngOnDestroy() {
|
|
1260
1426
|
this.destroy$.next();
|
|
@@ -1278,6 +1444,9 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1278
1444
|
return fileExports.filter(f => this.fileTypeSelectionState[f.fileType] === true);
|
|
1279
1445
|
}
|
|
1280
1446
|
async exportFile(fileType) {
|
|
1447
|
+
if (this.isListTypeOfExport) {
|
|
1448
|
+
return await this.exportListFile(fileType);
|
|
1449
|
+
}
|
|
1281
1450
|
return this.isFullTypeOfExport
|
|
1282
1451
|
? await this.exportMeasurementFile(fileType)
|
|
1283
1452
|
: await this.exportSeriesFile(fileType);
|
|
@@ -1296,9 +1465,13 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1296
1465
|
if (shouldShowAlert) {
|
|
1297
1466
|
this.dataFetchingService.showSendViaEmailInfoAlert(fileType, this.datapointsExceedingBrowserDownloadLimit);
|
|
1298
1467
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1468
|
+
// Full export uses zip filename, compact and list exports use blob's attached filename
|
|
1469
|
+
if (this.isFullTypeOfExport) {
|
|
1470
|
+
saveAs(blob, measurementsZipFileName);
|
|
1471
|
+
}
|
|
1472
|
+
else {
|
|
1473
|
+
saveAs(blob, blob[SERIES_DATA_MERGED_FILE_NAME]);
|
|
1474
|
+
}
|
|
1302
1475
|
}
|
|
1303
1476
|
}
|
|
1304
1477
|
/**
|
|
@@ -1315,7 +1488,7 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1315
1488
|
*/
|
|
1316
1489
|
async exportMeasurementFile(fileType) {
|
|
1317
1490
|
const { acceptType, extension } = this.datapointsExportModalService.fileTypesConfigs[fileType];
|
|
1318
|
-
const updatedExportConfig = this.excludeDatapointsThatExceedsApiLimit(this.exportConfig);
|
|
1491
|
+
const updatedExportConfig = this.excludeDatapointsThatExceedsApiLimit(this.exportConfig());
|
|
1319
1492
|
const dataToExport = await this.dataFetchingService.fetchMeasurementDataFilesAndPairWithSourceDetails(acceptType, updatedExportConfig);
|
|
1320
1493
|
const isAllUndefined = dataToExport.every(data => data === undefined);
|
|
1321
1494
|
if (isAllUndefined) {
|
|
@@ -1342,32 +1515,47 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1342
1515
|
*/
|
|
1343
1516
|
async exportSeriesFile(fileType) {
|
|
1344
1517
|
const mergedExportDetails = {
|
|
1345
|
-
aggregation: this.exportConfig.aggregation,
|
|
1346
|
-
dateFrom: this.exportConfig.dateFrom,
|
|
1347
|
-
dateTo: this.exportConfig.dateTo
|
|
1518
|
+
aggregation: this.exportConfig().aggregation,
|
|
1519
|
+
dateFrom: this.exportConfig().dateFrom,
|
|
1520
|
+
dateTo: this.exportConfig().dateTo
|
|
1348
1521
|
};
|
|
1349
1522
|
return this.datapointsExportSelectorFileExporterService.getSeriesExportedDataBlob(fileType, this.dataToExport, mergedExportDetails);
|
|
1350
1523
|
}
|
|
1524
|
+
/**
|
|
1525
|
+
* Exports list-type data (snapshot of datapoints with current values)
|
|
1526
|
+
* @param fileType - The type of file to export (csv or excel)
|
|
1527
|
+
* @returns Promise resolving to a Blob with the exported file
|
|
1528
|
+
*/
|
|
1529
|
+
async exportListFile(fileType) {
|
|
1530
|
+
const listData = await this.dataFetchingService.fetchAndPrepareListExportData(this.exportConfig());
|
|
1531
|
+
const columns = this.exportConfig().columns || [];
|
|
1532
|
+
const dateRange = {
|
|
1533
|
+
dateFrom: this.exportConfig().dateFrom,
|
|
1534
|
+
dateTo: this.exportConfig().dateTo
|
|
1535
|
+
};
|
|
1536
|
+
return this.datapointsExportSelectorFileExporterService.getListExportedDataBlob(fileType, listData, columns, dateRange);
|
|
1537
|
+
}
|
|
1351
1538
|
async onAggregationChange(newAggregation) {
|
|
1352
|
-
const currentAggregation = this.exportConfig.aggregation ?? AGGREGATION_VALUES.none;
|
|
1539
|
+
const currentAggregation = this.exportConfig().aggregation ?? AGGREGATION_VALUES.none;
|
|
1353
1540
|
if (currentAggregation === newAggregation) {
|
|
1354
1541
|
return;
|
|
1355
1542
|
}
|
|
1356
|
-
this.exportConfig.aggregation = newAggregation;
|
|
1543
|
+
this.exportConfig().aggregation = newAggregation;
|
|
1357
1544
|
if (this.isAggregationChangedProgrammatically) {
|
|
1358
1545
|
return;
|
|
1359
1546
|
}
|
|
1360
1547
|
await this.loadExportData();
|
|
1361
1548
|
this.updateDownloadButtonState();
|
|
1549
|
+
this.cdr.markForCheck();
|
|
1362
1550
|
}
|
|
1363
1551
|
onDateFromChange(updatedDate) {
|
|
1364
|
-
this.update(updatedDate, this.exportConfig.dateTo);
|
|
1552
|
+
this.update(updatedDate, this.exportConfig().dateTo);
|
|
1365
1553
|
}
|
|
1366
1554
|
onDateToChange(updatedDate) {
|
|
1367
|
-
this.update(this.exportConfig.dateFrom, updatedDate);
|
|
1555
|
+
this.update(this.exportConfig().dateFrom, updatedDate);
|
|
1368
1556
|
}
|
|
1369
1557
|
async updateDateAndFetchData(dateType, dateInfo) {
|
|
1370
|
-
this.exportConfig[dateType] = dateInfo.date;
|
|
1558
|
+
this.exportConfig()[dateType] = dateInfo.date;
|
|
1371
1559
|
if (!dateInfo.shouldFetchData) {
|
|
1372
1560
|
return;
|
|
1373
1561
|
}
|
|
@@ -1378,6 +1566,7 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1378
1566
|
else {
|
|
1379
1567
|
this.updateDownloadButtonState();
|
|
1380
1568
|
}
|
|
1569
|
+
this.cdr.markForCheck();
|
|
1381
1570
|
}
|
|
1382
1571
|
async onExportTypeChange(exportType) {
|
|
1383
1572
|
if (exportType === EXPORT_MODE_VALUES.full) {
|
|
@@ -1385,24 +1574,39 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1385
1574
|
this.formGroup.controls.aggregation.setValue(AGGREGATION_VALUES.none);
|
|
1386
1575
|
this.isAggregationChangedProgrammatically = false;
|
|
1387
1576
|
this.isFullTypeOfExport = true;
|
|
1577
|
+
this.emitPreviewAvailability();
|
|
1388
1578
|
await this.loadExportData();
|
|
1389
1579
|
await this.determineIfMeasurementResponseWillBeProcessedByBackend();
|
|
1580
|
+
this.cdr.markForCheck();
|
|
1390
1581
|
return;
|
|
1391
1582
|
}
|
|
1392
1583
|
this.resetFullExportRelatedProperties();
|
|
1393
1584
|
this.isFullTypeOfExport = false;
|
|
1585
|
+
this.emitPreviewAvailability();
|
|
1394
1586
|
await this.loadExportData();
|
|
1395
1587
|
this.updateDisabledAggregationOptions();
|
|
1396
1588
|
this.updateDownloadButtonState();
|
|
1589
|
+
this.cdr.markForCheck();
|
|
1590
|
+
}
|
|
1591
|
+
/**
|
|
1592
|
+
* Prepares preview for list-type exports
|
|
1593
|
+
* @param listData - Array of list datapoints
|
|
1594
|
+
*/
|
|
1595
|
+
prepareListPreview(listData) {
|
|
1596
|
+
const columns = this.exportConfig().columns || [];
|
|
1597
|
+
this.previewTableData = this.datapointsExportModalService.transformListDataToPreview(listData, columns);
|
|
1598
|
+
this.isPreviewLoading = false;
|
|
1397
1599
|
}
|
|
1398
1600
|
updateDisabledAggregationOptions() {
|
|
1399
1601
|
this.disabledAggregationOptions = this.aggregationService.getDisabledAggregationOptions(this.formGroup.controls.dateFrom.value, this.formGroup.controls.dateTo.value);
|
|
1400
1602
|
}
|
|
1401
1603
|
createForm() {
|
|
1402
1604
|
return this.formBuilder.group({
|
|
1403
|
-
dateFrom: new FormControl(this.exportConfig.dateFrom),
|
|
1404
|
-
dateTo: new FormControl(this.exportConfig.dateTo),
|
|
1405
|
-
aggregation: new FormControl(this.exportConfig.aggregation
|
|
1605
|
+
dateFrom: new FormControl(this.exportConfig().dateFrom),
|
|
1606
|
+
dateTo: new FormControl(this.exportConfig().dateTo),
|
|
1607
|
+
aggregation: new FormControl(this.exportConfig().aggregation
|
|
1608
|
+
? this.exportConfig().aggregation
|
|
1609
|
+
: AGGREGATION_VALUES.none),
|
|
1406
1610
|
exportMode: new FormControl(EXPORT_MODE_VALUES.compact),
|
|
1407
1611
|
fileTypes: this.formBuilder.group(this.generators.reduce((a, c) => {
|
|
1408
1612
|
a[c.getType()] = false;
|
|
@@ -1493,12 +1697,12 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1493
1697
|
async determineIfMeasurementResponseWillBeProcessedByBackend() {
|
|
1494
1698
|
this.isPreviewLoading = true;
|
|
1495
1699
|
this.datapointsExceedingBrowserDownloadLimit =
|
|
1496
|
-
await this.dataFetchingService.getDatapointsExceedingLimit(this.exportConfig);
|
|
1700
|
+
await this.dataFetchingService.getDatapointsExceedingLimit(this.exportConfig());
|
|
1497
1701
|
const { browserDownloadableCount, emailDeliverableCount, nonRetrievableCount } = this.calculateDatapointCounts();
|
|
1498
1702
|
this.hasNoExportableData =
|
|
1499
1703
|
browserDownloadableCount === 0 && emailDeliverableCount === 0 && nonRetrievableCount > 0;
|
|
1500
1704
|
if (this.datapointsExceedingBrowserDownloadLimit.length > 0 && !this.hasNoExportableData) {
|
|
1501
|
-
this.limitExceededMessage = this.dataFetchingService.getLimitExceededMessage(this.hasNoExportableData, emailDeliverableCount, browserDownloadableCount, nonRetrievableCount, this.exportConfig.datapointDetails.length);
|
|
1705
|
+
this.limitExceededMessage = this.dataFetchingService.getLimitExceededMessage(this.hasNoExportableData, emailDeliverableCount, browserDownloadableCount, nonRetrievableCount, this.exportConfig().datapointDetails.length);
|
|
1502
1706
|
}
|
|
1503
1707
|
if (this.datapointsExceedingBrowserDownloadLimit.length > 0 && this.hasNoExportableData) {
|
|
1504
1708
|
this.limitExceededMessage = this.dataFetchingService.getLimitExceededMessage(this.hasNoExportableData);
|
|
@@ -1511,7 +1715,7 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1511
1715
|
this.dataPointsExceedingOneMillionLimit = this.datapointsExceedingBrowserDownloadLimit.filter(datapointsExceedingBrowserDownloadLimit => datapointsExceedingBrowserDownloadLimit.totalElements > RECORD_API_LIMIT);
|
|
1512
1716
|
const nonRetrievableCount = this.dataPointsExceedingOneMillionLimit.length;
|
|
1513
1717
|
const emailDeliverableCount = this.datapointsExceedingBrowserDownloadLimit.length - nonRetrievableCount;
|
|
1514
|
-
const browserDownloadableCount = this.exportConfig.datapointDetails.length - emailDeliverableCount - nonRetrievableCount;
|
|
1718
|
+
const browserDownloadableCount = this.exportConfig().datapointDetails.length - emailDeliverableCount - nonRetrievableCount;
|
|
1515
1719
|
return {
|
|
1516
1720
|
browserDownloadableCount,
|
|
1517
1721
|
emailDeliverableCount,
|
|
@@ -1519,19 +1723,19 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1519
1723
|
};
|
|
1520
1724
|
}
|
|
1521
1725
|
storeInitialChangeableConfig() {
|
|
1522
|
-
this.initialDateFrom = this.exportConfig.dateFrom;
|
|
1523
|
-
this.initialDateTo = this.exportConfig.dateTo;
|
|
1524
|
-
this.initialDatapointDetails = this.exportConfig.datapointDetails;
|
|
1726
|
+
this.initialDateFrom = this.exportConfig().dateFrom;
|
|
1727
|
+
this.initialDateTo = this.exportConfig().dateTo;
|
|
1728
|
+
this.initialDatapointDetails = this.exportConfig().datapointDetails;
|
|
1525
1729
|
if (!this.isFullTypeOfExport) {
|
|
1526
|
-
this.initialAggregation = this.exportConfig.aggregation;
|
|
1730
|
+
this.initialAggregation = this.exportConfig().aggregation;
|
|
1527
1731
|
}
|
|
1528
1732
|
}
|
|
1529
1733
|
loadInitialChangeableConfig() {
|
|
1530
|
-
this.exportConfig.dateFrom = this.initialDateFrom;
|
|
1531
|
-
this.exportConfig.dateTo = this.initialDateTo;
|
|
1532
|
-
this.exportConfig.datapointDetails = this.initialDatapointDetails;
|
|
1734
|
+
this.exportConfig().dateFrom = this.initialDateFrom;
|
|
1735
|
+
this.exportConfig().dateTo = this.initialDateTo;
|
|
1736
|
+
this.exportConfig().datapointDetails = this.initialDatapointDetails;
|
|
1533
1737
|
if (!this.isFullTypeOfExport) {
|
|
1534
|
-
this.exportConfig.aggregation = this.initialAggregation;
|
|
1738
|
+
this.exportConfig().aggregation = this.initialAggregation;
|
|
1535
1739
|
}
|
|
1536
1740
|
}
|
|
1537
1741
|
async loadExportData() {
|
|
@@ -1540,7 +1744,25 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1540
1744
|
}
|
|
1541
1745
|
this.isPreviewLoading = true;
|
|
1542
1746
|
this.onDownloadButtonStateChange.emit(false);
|
|
1543
|
-
|
|
1747
|
+
if (this.isListTypeOfExport) {
|
|
1748
|
+
await this.loadListExportData();
|
|
1749
|
+
}
|
|
1750
|
+
else {
|
|
1751
|
+
await this.loadTableExportData();
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
async loadListExportData() {
|
|
1755
|
+
const listData = await this.dataFetchingService.fetchAndPrepareListExportData(this.exportConfig());
|
|
1756
|
+
this.hasFetchedDataAnyValuesToExport = listData.length > 0;
|
|
1757
|
+
if (this.hasFetchedDataAnyValuesToExport) {
|
|
1758
|
+
this.prepareListPreview(listData);
|
|
1759
|
+
}
|
|
1760
|
+
else {
|
|
1761
|
+
this.isPreviewLoading = false;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
async loadTableExportData() {
|
|
1765
|
+
this.dataToExport = await this.dataFetchingService.fetchAndPrepareDataToExport(this.exportConfig(), this.isFullTypeOfExport);
|
|
1544
1766
|
this.determineShowingPreviewOrEmptyState();
|
|
1545
1767
|
}
|
|
1546
1768
|
updateDownloadButtonState() {
|
|
@@ -1550,6 +1772,9 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1550
1772
|
!this.hasNoExportableData;
|
|
1551
1773
|
this.onDownloadButtonStateChange.emit(canEnableDownloadButton);
|
|
1552
1774
|
}
|
|
1775
|
+
emitPreviewAvailability() {
|
|
1776
|
+
this.previewAvailabilityChange.emit(this.isFullTypeOfExport || this.isListTypeOfExport);
|
|
1777
|
+
}
|
|
1553
1778
|
resetFullExportRelatedProperties() {
|
|
1554
1779
|
this.hasNoExportableData = false;
|
|
1555
1780
|
this.datapointsExceedingBrowserDownloadLimit = [];
|
|
@@ -1615,31 +1840,26 @@ class DatapointsExportSelectorFileExporterComponent {
|
|
|
1615
1840
|
this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_DATAPOINTS_EXPORT_SELECTOR.EVENTS.EXPORT_SELECTOR, {
|
|
1616
1841
|
...commonEventData,
|
|
1617
1842
|
selectedExportType: PRODUCT_EXPERIENCE_DATAPOINTS_EXPORT_SELECTOR.EXPORT_CONFIG.COMPACT_EXPORT_TYPE,
|
|
1618
|
-
selectedAggregation: this.exportConfig.aggregation ?? AGGREGATION_VALUES.none
|
|
1843
|
+
selectedAggregation: this.exportConfig().aggregation ?? AGGREGATION_VALUES.none
|
|
1619
1844
|
});
|
|
1620
1845
|
}
|
|
1621
1846
|
}
|
|
1622
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatapointsExportSelectorFileExporterComponent, deps: [{ token: i1.AggregationService }, { token: DataProcessingService }, { token: DatapointsExportSelectorFileExporterService }, { token: DataFetchingService }, { token:
|
|
1623
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1847
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatapointsExportSelectorFileExporterComponent, deps: [{ token: i1.AggregationService }, { token: i0.ChangeDetectorRef }, { token: DataProcessingService }, { token: DatapointsExportSelectorFileExporterService }, { token: DataFetchingService }, { token: i2$1.FormBuilder }, { token: FILE_GENERATORS }, { token: i1.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1848
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: DatapointsExportSelectorFileExporterComponent, isStandalone: true, selector: "c8y-datapoints-export-selector-file-exporter", inputs: { exportConfig: { classPropertyName: "exportConfig", publicName: "exportConfig", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onDownloadButtonStateChange: "onDownloadButtonStateChange", previewAvailabilityChange: "previewAvailabilityChange", previewLoadingChange: "previewLoadingChange" }, ngImport: i0, template: "<div class=\"p-b-16\">\n @if (isCheckingPermissions) {\n <div class=\"p-t-24 p-r-16 p-l-16 p-b-16 d-flex j-c-center\">\n <c8y-loading></c8y-loading>\n </div>\n } @else if (hasPermissionToReadAnyMeasurements) {\n <div class=\"p-16 text-center separator-bottom sticky-top bg-component\">\n <p class=\"text-medium text-16\">\n {{ 'Configure export' | translate }}\n </p>\n </div>\n <div\n class=\"p-r-24 p-l-24 gap-8 p-b-16\"\n [class.separator-bottom]=\"isFullTypeOfExport\"\n >\n <c8y-datapoints-export-selector-time-range\n [formGroup]=\"formGroup\"\n (onDateFromChange)=\"onDateFromChange($event)\"\n (onDateToChange)=\"onDateToChange($event)\"\n ></c8y-datapoints-export-selector-time-range>\n @if (isDataScopeVisible) {\n <c8y-datapoints-export-selector-data-scope\n [disabledAggregationOptions]=\"disabledAggregationOptions\"\n [formGroup]=\"formGroup\"\n (onAggregationChange)=\"onAggregationChange($event)\"\n (onExportTypeChange)=\"onExportTypeChange($event)\"\n ></c8y-datapoints-export-selector-data-scope>\n }\n <c8y-datapoints-export-selector-file-types\n [dynamicFilesTypeMetadata]=\"dynamicFilesTypeMetadata\"\n [formGroup]=\"formGroup\"\n ></c8y-datapoints-export-selector-file-types>\n </div>\n @if (\n !isFullTypeOfExport &&\n !hasFetchedDataAnyValuesToExport &&\n !isPreviewLoading &&\n !isListTypeOfExport\n ) {\n <div class=\"p-t-24 p-r-16 p-l-16 p-b-16 d-flex\">\n <div\n class=\"alert alert-warning center-block\"\n role=\"alert\"\n data-cy=\"file-exporter--no-data-available\"\n translate\n >\n No data available.\n </div>\n </div>\n }\n @if (datapointsExceedingBrowserDownloadLimit.length > 0) {\n <div class=\"p-t-24 p-r-16 p-l-16 p-b-16 separator-bottom d-flex\">\n <div\n [class]=\"\n hasNoExportableData\n ? 'alert alert-warning center-block'\n : 'alert alert-info center-block'\n \"\n role=\"alert\"\n [attr.data-cy]=\"\n hasNoExportableData\n ? 'file-exporter--over-one-million-message'\n : 'file-exporter--over-50k-message'\n \"\n [innerHTML]=\"limitExceededMessage\"\n ></div>\n </div>\n }\n } @else {\n <div class=\"p-t-24 p-r-16 p-l-16 p-b-16 d-flex\">\n <div\n class=\"alert alert-info center-block\"\n role=\"alert\"\n translate\n >\n <p>To export data, you must meet at least one of these criteria:</p>\n <ul>\n <li>\n Have\n <b>READ permission for \"Measurements\" permission type</b>\n (either as a global role or for the specific source)\n </li>\n <li>\n Be the\n <b>owner of the source</b>\n you want to export data from\n </li>\n </ul>\n <p>Don't meet these requirements? Contact your system administrator for assistance.</p>\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: i1.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: DataPointsExportSelectorDataScopeComponent, selector: "c8y-datapoints-export-selector-data-scope", inputs: ["disabledAggregationOptions", "formGroup"], outputs: ["onAggregationChange", "onExportTypeChange"] }, { kind: "component", type: DataPointsExportSelectorFileTypesComponent, selector: "c8y-datapoints-export-selector-file-types", inputs: ["dynamicFilesTypeMetadata", "formGroup"] }, { kind: "component", type: DataPointsExportSelectorTimeRangeComponent, selector: "c8y-datapoints-export-selector-time-range", inputs: ["formGroup"], outputs: ["onDateFromChange", "onDateToChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1624
1849
|
}
|
|
1625
1850
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatapointsExportSelectorFileExporterComponent, decorators: [{
|
|
1626
1851
|
type: Component,
|
|
1627
|
-
args: [{ selector: 'c8y-datapoints-export-selector-file-exporter',
|
|
1852
|
+
args: [{ selector: 'c8y-datapoints-export-selector-file-exporter', imports: [
|
|
1628
1853
|
CoreModule,
|
|
1629
1854
|
DataPointsExportSelectorDataScopeComponent,
|
|
1630
1855
|
DataPointsExportSelectorFileTypesComponent,
|
|
1631
|
-
DataPointsExportSelectorPreviewComponent,
|
|
1632
1856
|
DataPointsExportSelectorTimeRangeComponent,
|
|
1633
1857
|
ReactiveFormsModule
|
|
1634
|
-
], template: "<div class=\"p-b-16\">\n <
|
|
1635
|
-
}], ctorParameters: () => [{ type: i1.AggregationService }, { type: DataProcessingService }, { type: DatapointsExportSelectorFileExporterService }, { type: DataFetchingService }, { type:
|
|
1858
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"p-b-16\">\n @if (isCheckingPermissions) {\n <div class=\"p-t-24 p-r-16 p-l-16 p-b-16 d-flex j-c-center\">\n <c8y-loading></c8y-loading>\n </div>\n } @else if (hasPermissionToReadAnyMeasurements) {\n <div class=\"p-16 text-center separator-bottom sticky-top bg-component\">\n <p class=\"text-medium text-16\">\n {{ 'Configure export' | translate }}\n </p>\n </div>\n <div\n class=\"p-r-24 p-l-24 gap-8 p-b-16\"\n [class.separator-bottom]=\"isFullTypeOfExport\"\n >\n <c8y-datapoints-export-selector-time-range\n [formGroup]=\"formGroup\"\n (onDateFromChange)=\"onDateFromChange($event)\"\n (onDateToChange)=\"onDateToChange($event)\"\n ></c8y-datapoints-export-selector-time-range>\n @if (isDataScopeVisible) {\n <c8y-datapoints-export-selector-data-scope\n [disabledAggregationOptions]=\"disabledAggregationOptions\"\n [formGroup]=\"formGroup\"\n (onAggregationChange)=\"onAggregationChange($event)\"\n (onExportTypeChange)=\"onExportTypeChange($event)\"\n ></c8y-datapoints-export-selector-data-scope>\n }\n <c8y-datapoints-export-selector-file-types\n [dynamicFilesTypeMetadata]=\"dynamicFilesTypeMetadata\"\n [formGroup]=\"formGroup\"\n ></c8y-datapoints-export-selector-file-types>\n </div>\n @if (\n !isFullTypeOfExport &&\n !hasFetchedDataAnyValuesToExport &&\n !isPreviewLoading &&\n !isListTypeOfExport\n ) {\n <div class=\"p-t-24 p-r-16 p-l-16 p-b-16 d-flex\">\n <div\n class=\"alert alert-warning center-block\"\n role=\"alert\"\n data-cy=\"file-exporter--no-data-available\"\n translate\n >\n No data available.\n </div>\n </div>\n }\n @if (datapointsExceedingBrowserDownloadLimit.length > 0) {\n <div class=\"p-t-24 p-r-16 p-l-16 p-b-16 separator-bottom d-flex\">\n <div\n [class]=\"\n hasNoExportableData\n ? 'alert alert-warning center-block'\n : 'alert alert-info center-block'\n \"\n role=\"alert\"\n [attr.data-cy]=\"\n hasNoExportableData\n ? 'file-exporter--over-one-million-message'\n : 'file-exporter--over-50k-message'\n \"\n [innerHTML]=\"limitExceededMessage\"\n ></div>\n </div>\n }\n } @else {\n <div class=\"p-t-24 p-r-16 p-l-16 p-b-16 d-flex\">\n <div\n class=\"alert alert-info center-block\"\n role=\"alert\"\n translate\n >\n <p>To export data, you must meet at least one of these criteria:</p>\n <ul>\n <li>\n Have\n <b>READ permission for \"Measurements\" permission type</b>\n (either as a global role or for the specific source)\n </li>\n <li>\n Be the\n <b>owner of the source</b>\n you want to export data from\n </li>\n </ul>\n <p>Don't meet these requirements? Contact your system administrator for assistance.</p>\n </div>\n </div>\n }\n</div>\n" }]
|
|
1859
|
+
}], ctorParameters: () => [{ type: i1.AggregationService }, { type: i0.ChangeDetectorRef }, { type: DataProcessingService }, { type: DatapointsExportSelectorFileExporterService }, { type: DataFetchingService }, { type: i2$1.FormBuilder }, { type: undefined, decorators: [{
|
|
1636
1860
|
type: Inject,
|
|
1637
1861
|
args: [FILE_GENERATORS]
|
|
1638
|
-
}] }, { type: i1.GainsightService }], propDecorators: { exportConfig: [{
|
|
1639
|
-
type: Input
|
|
1640
|
-
}], onDownloadButtonStateChange: [{
|
|
1641
|
-
type: Output
|
|
1642
|
-
}] } });
|
|
1862
|
+
}] }, { type: i1.GainsightService }], propDecorators: { exportConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportConfig", required: true }] }], onDownloadButtonStateChange: [{ type: i0.Output, args: ["onDownloadButtonStateChange"] }], previewAvailabilityChange: [{ type: i0.Output, args: ["previewAvailabilityChange"] }], previewLoadingChange: [{ type: i0.Output, args: ["previewLoadingChange"] }] } });
|
|
1643
1863
|
|
|
1644
1864
|
class DataProcessingService {
|
|
1645
1865
|
constructor(fileGenerators, utils) {
|
|
@@ -1692,6 +1912,17 @@ class DataProcessingService {
|
|
|
1692
1912
|
const exportData = this.processDataToExport(data);
|
|
1693
1913
|
return exportData.slice(0, MEASUREMENTS_PREVIEW_ITEMS_LIMIT);
|
|
1694
1914
|
}
|
|
1915
|
+
/**
|
|
1916
|
+
* Transforms list export data into a structured format for preview.
|
|
1917
|
+
*
|
|
1918
|
+
* @param listData - Array of list datapoints with snapshot values
|
|
1919
|
+
* @param columns - Column configuration for ordering
|
|
1920
|
+
* @returns Provides an array of up to 5 ExportData elements for preview
|
|
1921
|
+
*/
|
|
1922
|
+
transformListDataToPreview(listData, columns) {
|
|
1923
|
+
const exportData = this.processListDataToExport(listData, columns);
|
|
1924
|
+
return exportData.slice(0, MEASUREMENTS_PREVIEW_ITEMS_LIMIT);
|
|
1925
|
+
}
|
|
1695
1926
|
/**
|
|
1696
1927
|
* Processes a single dataToExport and transforms it into an array of ExportData.
|
|
1697
1928
|
*
|
|
@@ -1806,6 +2037,77 @@ class DataProcessingService {
|
|
|
1806
2037
|
createFileName(source, fragmentSeries, fileExtension) {
|
|
1807
2038
|
return `${source}_${fragmentSeries}.${fileExtension}`;
|
|
1808
2039
|
}
|
|
2040
|
+
/**
|
|
2041
|
+
* Generates list export blob (CSV or Excel) for snapshot data
|
|
2042
|
+
* @param fileType - Type of file (csv or excel)
|
|
2043
|
+
* @param listData - Array of datapoints with current values
|
|
2044
|
+
* @param columns - Column configuration
|
|
2045
|
+
* @param dateRange - Date range for filename generation
|
|
2046
|
+
* @returns Promise with Blob containing the exported file
|
|
2047
|
+
*/
|
|
2048
|
+
async generateListExport(fileType, listData, columns, dateRange) {
|
|
2049
|
+
const fileTypeConfig = this.fileTypesConfigs[fileType];
|
|
2050
|
+
let blobContent;
|
|
2051
|
+
if (fileType === 'csv') {
|
|
2052
|
+
const module = await Promise.resolve().then(function () { return csvGenerator; });
|
|
2053
|
+
blobContent = await module.CSVGeneratorAdapter.generateList(listData, columns);
|
|
2054
|
+
}
|
|
2055
|
+
else if (fileType === 'excel') {
|
|
2056
|
+
const module = await Promise.resolve().then(function () { return excelGenerator; });
|
|
2057
|
+
blobContent = await module.ExcelGeneratorAdapter.generateList(listData, columns);
|
|
2058
|
+
}
|
|
2059
|
+
else {
|
|
2060
|
+
throw new Error(`Unsupported file type for list export: ${fileType}`);
|
|
2061
|
+
}
|
|
2062
|
+
const fileName = `${this.utils.getFormattedDateRange(dateRange.dateFrom, dateRange.dateTo)}.${fileTypeConfig.extension}`;
|
|
2063
|
+
const blob = new Blob([blobContent], { type: fileTypeConfig.mimeType });
|
|
2064
|
+
Object.defineProperty(blob, SERIES_DATA_MERGED_FILE_NAME, {
|
|
2065
|
+
value: fileName,
|
|
2066
|
+
writable: false,
|
|
2067
|
+
enumerable: false,
|
|
2068
|
+
configurable: true
|
|
2069
|
+
});
|
|
2070
|
+
return blob;
|
|
2071
|
+
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Processes list datapoints and transforms them into an array of ExportData.
|
|
2074
|
+
*
|
|
2075
|
+
* @param listData - Array of list datapoints with snapshot values
|
|
2076
|
+
* @param columns - Column configuration for ordering
|
|
2077
|
+
* @returns An array of ExportData representing the processed list datapoints
|
|
2078
|
+
*/
|
|
2079
|
+
processListDataToExport(listData, columns) {
|
|
2080
|
+
const sortedColumns = columns.sort((a, b) => a.order - b.order);
|
|
2081
|
+
const columnMapping = {
|
|
2082
|
+
kpi: 'label',
|
|
2083
|
+
target: 'target',
|
|
2084
|
+
current: 'current',
|
|
2085
|
+
diff: 'diff',
|
|
2086
|
+
diffPercentage: 'diffPercent',
|
|
2087
|
+
asset: 'deviceName'
|
|
2088
|
+
};
|
|
2089
|
+
return listData.map(datapoint => {
|
|
2090
|
+
const values = sortedColumns.map(col => {
|
|
2091
|
+
const propKey = columnMapping[col.id];
|
|
2092
|
+
const value = datapoint[propKey];
|
|
2093
|
+
if (value === null || value === undefined) {
|
|
2094
|
+
return '';
|
|
2095
|
+
}
|
|
2096
|
+
if (typeof value === 'number') {
|
|
2097
|
+
return value.toFixed(2);
|
|
2098
|
+
}
|
|
2099
|
+
return String(value);
|
|
2100
|
+
});
|
|
2101
|
+
return {
|
|
2102
|
+
device_name: datapoint.deviceName || '',
|
|
2103
|
+
source: datapoint.source,
|
|
2104
|
+
fragment_series: values.join(' | '),
|
|
2105
|
+
value: datapoint.current,
|
|
2106
|
+
unit: datapoint.unit || null,
|
|
2107
|
+
time: null
|
|
2108
|
+
};
|
|
2109
|
+
});
|
|
2110
|
+
}
|
|
1809
2111
|
/**
|
|
1810
2112
|
* Generates a zip blob using the provided zip object.
|
|
1811
2113
|
*
|
|
@@ -1841,17 +2143,110 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1841
2143
|
args: [FILE_GENERATORS]
|
|
1842
2144
|
}] }, { type: UtilsService }] });
|
|
1843
2145
|
|
|
1844
|
-
class
|
|
2146
|
+
class DataPointsExportSelectorPreviewComponent {
|
|
2147
|
+
constructor() {
|
|
2148
|
+
this.columns = input(...(ngDevMode ? [undefined, { debugName: "columns" }] : []));
|
|
2149
|
+
this.hasFetchedDataAnyValuesToExport = input(...(ngDevMode ? [undefined, { debugName: "hasFetchedDataAnyValuesToExport" }] : []));
|
|
2150
|
+
this.isPreviewLoading = input(...(ngDevMode ? [undefined, { debugName: "isPreviewLoading" }] : []));
|
|
2151
|
+
this.previewTableData = input(...(ngDevMode ? [undefined, { debugName: "previewTableData" }] : []));
|
|
2152
|
+
this.MEASUREMENTS_PREVIEW_ITEMS_LIMIT = MEASUREMENTS_PREVIEW_ITEMS_LIMIT;
|
|
2153
|
+
this.isListPreview = computed(() => {
|
|
2154
|
+
const cols = this.columns();
|
|
2155
|
+
return !!cols && cols.length > 0;
|
|
2156
|
+
}, ...(ngDevMode ? [{ debugName: "isListPreview" }] : []));
|
|
2157
|
+
this.listHeaders = computed(() => {
|
|
2158
|
+
if (!this.isListPreview()) {
|
|
2159
|
+
return [];
|
|
2160
|
+
}
|
|
2161
|
+
return [...this.columns()].sort((a, b) => a.order - b.order).map(col => col.label);
|
|
2162
|
+
}, ...(ngDevMode ? [{ debugName: "listHeaders" }] : []));
|
|
2163
|
+
this.previewRows = computed(() => {
|
|
2164
|
+
const data = this.previewTableData();
|
|
2165
|
+
if (!data) {
|
|
2166
|
+
return [];
|
|
2167
|
+
}
|
|
2168
|
+
return data.map(row => ({
|
|
2169
|
+
...row,
|
|
2170
|
+
rowValues: row.fragment_series ? row.fragment_series.split(' | ') : []
|
|
2171
|
+
}));
|
|
2172
|
+
}, ...(ngDevMode ? [{ debugName: "previewRows" }] : []));
|
|
2173
|
+
}
|
|
2174
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DataPointsExportSelectorPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2175
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: DataPointsExportSelectorPreviewComponent, isStandalone: true, selector: "c8y-datapoints-export-selector-preview", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, hasFetchedDataAnyValuesToExport: { classPropertyName: "hasFetchedDataAnyValuesToExport", publicName: "hasFetchedDataAnyValuesToExport", isSignal: true, isRequired: false, transformFunction: null }, isPreviewLoading: { classPropertyName: "isPreviewLoading", publicName: "isPreviewLoading", isSignal: true, isRequired: false, transformFunction: null }, previewTableData: { classPropertyName: "previewTableData", publicName: "previewTableData", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"p-t-16 p-l-16 p-r-16 m-b-0\">\n <div class=\"d-flex a-i-center\">\n <label\n class=\"m-b-0 d-flex a-i-center gap-4\"\n [title]=\"'Preview`of exported file`' | translate\"\n >\n {{ 'Preview`of exported file`' | translate }}\n <button\n class=\"btn-help\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"isListPreview() ? popoverListPreviewTemplate : popoverTablePreviewTemplate\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n data-cy=\"preview--help\"\n [adaptivePosition]=\"true\"\n ></button>\n <ng-template #popoverTablePreviewTemplate>\n <p translate>The preview shows the structure of the raw file from a single source.</p>\n <p translate>If no data is available, only the column headers are visible.</p>\n <p>\n {{ 'The preview is limited to' | translate }}\n <b>{{ MEASUREMENTS_PREVIEW_ITEMS_LIMIT }}</b>\n {{ 'records.' | translate }}\n </p>\n </ng-template>\n <ng-template #popoverListPreviewTemplate>\n <p translate>The preview shows the structure of the raw file from all sources.</p>\n <p>\n {{ 'The preview is limited to' | translate }}\n <b>{{ MEASUREMENTS_PREVIEW_ITEMS_LIMIT }}</b>\n {{ 'records.' | translate }}\n </p>\n </ng-template>\n </label>\n </div>\n <div\n class=\"table-responsive\"\n style=\"min-height: 275px\"\n >\n @if (isListPreview()) {\n <table class=\"table\">\n <thead>\n <tr>\n @for (header of listHeaders(); track header) {\n <th>{{ header | translate }}</th>\n }\n </tr>\n </thead>\n @if (hasFetchedDataAnyValuesToExport() || isPreviewLoading()) {\n @if (!isPreviewLoading()) {\n <tbody>\n @for (row of previewRows(); track row.source) {\n <tr>\n @for (value of row.rowValues; track $index) {\n <td>{{ value }}</td>\n }\n </tr>\n }\n </tbody>\n } @else {\n <tbody>\n <tr>\n <td [attr.colspan]=\"listHeaders().length\">\n <c8y-loading></c8y-loading>\n </td>\n </tr>\n </tbody>\n }\n } @else {\n <tbody>\n <tr>\n <td [attr.colspan]=\"listHeaders().length\">\n <div class=\"d-col a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No data available.' | translate\"\n [horizontal]=\"true\"\n data-cy=\"datapoints-table-list--empty-state\"\n ></c8y-ui-empty-state>\n </div>\n </td>\n </tr>\n </tbody>\n }\n </table>\n } @else {\n <table class=\"table\">\n <thead>\n <tr>\n <th>{{ 'Time' | translate }}</th>\n <th>{{ 'Source' | translate }}</th>\n <th>{{ 'Device name' | translate }}</th>\n <th>\n {{ 'Fragment and series' | translate }}\n </th>\n <th>{{ 'Value' | translate }}</th>\n <th>{{ 'Unit' | translate }}</th>\n </tr>\n </thead>\n @if (hasFetchedDataAnyValuesToExport() || isPreviewLoading()) {\n @if (!isPreviewLoading()) {\n <tbody>\n @for (row of previewTableData(); track row.source) {\n <tr>\n <td>{{ row.time }}</td>\n <td>{{ row.source }}</td>\n <td>{{ row.device_name }}</td>\n <td>\n {{ row.fragment_series }}\n </td>\n <td>{{ row.value }}</td>\n <td>{{ row.unit }}</td>\n </tr>\n }\n </tbody>\n } @else {\n <tbody>\n <tr>\n <td colspan=\"8\">\n <c8y-loading></c8y-loading>\n </td>\n </tr>\n </tbody>\n }\n } @else {\n <tbody>\n <tr>\n <td colspan=\"8\">\n <div class=\"d-col a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No data available.' | translate\"\n [horizontal]=\"true\"\n data-cy=\"datapoints-table-list--empty-state\"\n ></c8y-ui-empty-state>\n </div>\n </td>\n </tr>\n </tbody>\n }\n </table>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: i1.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i3$1.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2176
|
+
}
|
|
2177
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DataPointsExportSelectorPreviewComponent, decorators: [{
|
|
2178
|
+
type: Component,
|
|
2179
|
+
args: [{ selector: 'c8y-datapoints-export-selector-preview', imports: [A11yModule, CoreModule, PopoverModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"p-t-16 p-l-16 p-r-16 m-b-0\">\n <div class=\"d-flex a-i-center\">\n <label\n class=\"m-b-0 d-flex a-i-center gap-4\"\n [title]=\"'Preview`of exported file`' | translate\"\n >\n {{ 'Preview`of exported file`' | translate }}\n <button\n class=\"btn-help\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"isListPreview() ? popoverListPreviewTemplate : popoverTablePreviewTemplate\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n data-cy=\"preview--help\"\n [adaptivePosition]=\"true\"\n ></button>\n <ng-template #popoverTablePreviewTemplate>\n <p translate>The preview shows the structure of the raw file from a single source.</p>\n <p translate>If no data is available, only the column headers are visible.</p>\n <p>\n {{ 'The preview is limited to' | translate }}\n <b>{{ MEASUREMENTS_PREVIEW_ITEMS_LIMIT }}</b>\n {{ 'records.' | translate }}\n </p>\n </ng-template>\n <ng-template #popoverListPreviewTemplate>\n <p translate>The preview shows the structure of the raw file from all sources.</p>\n <p>\n {{ 'The preview is limited to' | translate }}\n <b>{{ MEASUREMENTS_PREVIEW_ITEMS_LIMIT }}</b>\n {{ 'records.' | translate }}\n </p>\n </ng-template>\n </label>\n </div>\n <div\n class=\"table-responsive\"\n style=\"min-height: 275px\"\n >\n @if (isListPreview()) {\n <table class=\"table\">\n <thead>\n <tr>\n @for (header of listHeaders(); track header) {\n <th>{{ header | translate }}</th>\n }\n </tr>\n </thead>\n @if (hasFetchedDataAnyValuesToExport() || isPreviewLoading()) {\n @if (!isPreviewLoading()) {\n <tbody>\n @for (row of previewRows(); track row.source) {\n <tr>\n @for (value of row.rowValues; track $index) {\n <td>{{ value }}</td>\n }\n </tr>\n }\n </tbody>\n } @else {\n <tbody>\n <tr>\n <td [attr.colspan]=\"listHeaders().length\">\n <c8y-loading></c8y-loading>\n </td>\n </tr>\n </tbody>\n }\n } @else {\n <tbody>\n <tr>\n <td [attr.colspan]=\"listHeaders().length\">\n <div class=\"d-col a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No data available.' | translate\"\n [horizontal]=\"true\"\n data-cy=\"datapoints-table-list--empty-state\"\n ></c8y-ui-empty-state>\n </div>\n </td>\n </tr>\n </tbody>\n }\n </table>\n } @else {\n <table class=\"table\">\n <thead>\n <tr>\n <th>{{ 'Time' | translate }}</th>\n <th>{{ 'Source' | translate }}</th>\n <th>{{ 'Device name' | translate }}</th>\n <th>\n {{ 'Fragment and series' | translate }}\n </th>\n <th>{{ 'Value' | translate }}</th>\n <th>{{ 'Unit' | translate }}</th>\n </tr>\n </thead>\n @if (hasFetchedDataAnyValuesToExport() || isPreviewLoading()) {\n @if (!isPreviewLoading()) {\n <tbody>\n @for (row of previewTableData(); track row.source) {\n <tr>\n <td>{{ row.time }}</td>\n <td>{{ row.source }}</td>\n <td>{{ row.device_name }}</td>\n <td>\n {{ row.fragment_series }}\n </td>\n <td>{{ row.value }}</td>\n <td>{{ row.unit }}</td>\n </tr>\n }\n </tbody>\n } @else {\n <tbody>\n <tr>\n <td colspan=\"8\">\n <c8y-loading></c8y-loading>\n </td>\n </tr>\n </tbody>\n }\n } @else {\n <tbody>\n <tr>\n <td colspan=\"8\">\n <div class=\"d-col a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No data available.' | translate\"\n [horizontal]=\"true\"\n data-cy=\"datapoints-table-list--empty-state\"\n ></c8y-ui-empty-state>\n </div>\n </td>\n </tr>\n </tbody>\n }\n </table>\n }\n </div>\n</div>\n" }]
|
|
2180
|
+
}], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], hasFetchedDataAnyValuesToExport: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasFetchedDataAnyValuesToExport", required: false }] }], isPreviewLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPreviewLoading", required: false }] }], previewTableData: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewTableData", required: false }] }] } });
|
|
2181
|
+
|
|
2182
|
+
class DatapointsExportSelectorPreviewModalComponent {
|
|
1845
2183
|
constructor(bsModalRef) {
|
|
1846
2184
|
this.bsModalRef = bsModalRef;
|
|
2185
|
+
this.labels = { cancel: gettext('Close') };
|
|
2186
|
+
}
|
|
2187
|
+
close() {
|
|
2188
|
+
this.bsModalRef.hide();
|
|
2189
|
+
}
|
|
2190
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatapointsExportSelectorPreviewModalComponent, deps: [{ token: i1$1.BsModalRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2191
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: DatapointsExportSelectorPreviewModalComponent, isStandalone: true, selector: "c8y-datapoints-export-selector-preview-modal", host: { listeners: { "document:keydown.escape": "close()" } }, ngImport: i0, template: `
|
|
2192
|
+
<c8y-modal
|
|
2193
|
+
[title]="'Export preview' | translate"
|
|
2194
|
+
[labels]="labels"
|
|
2195
|
+
[headerClasses]="'dialog-header'"
|
|
2196
|
+
(onDismiss)="close()"
|
|
2197
|
+
>
|
|
2198
|
+
<c8y-datapoints-export-selector-preview
|
|
2199
|
+
[hasFetchedDataAnyValuesToExport]="hasFetchedDataAnyValuesToExport"
|
|
2200
|
+
[isPreviewLoading]="isPreviewLoading"
|
|
2201
|
+
[previewTableData]="previewTableData"
|
|
2202
|
+
[columns]="columns"
|
|
2203
|
+
></c8y-datapoints-export-selector-preview>
|
|
2204
|
+
</c8y-modal>
|
|
2205
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "component", type: DataPointsExportSelectorPreviewComponent, selector: "c8y-datapoints-export-selector-preview", inputs: ["columns", "hasFetchedDataAnyValuesToExport", "isPreviewLoading", "previewTableData"] }, { kind: "ngmodule", type: ModalModule }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2206
|
+
}
|
|
2207
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatapointsExportSelectorPreviewModalComponent, decorators: [{
|
|
2208
|
+
type: Component,
|
|
2209
|
+
args: [{
|
|
2210
|
+
selector: 'c8y-datapoints-export-selector-preview-modal',
|
|
2211
|
+
template: `
|
|
2212
|
+
<c8y-modal
|
|
2213
|
+
[title]="'Export preview' | translate"
|
|
2214
|
+
[labels]="labels"
|
|
2215
|
+
[headerClasses]="'dialog-header'"
|
|
2216
|
+
(onDismiss)="close()"
|
|
2217
|
+
>
|
|
2218
|
+
<c8y-datapoints-export-selector-preview
|
|
2219
|
+
[hasFetchedDataAnyValuesToExport]="hasFetchedDataAnyValuesToExport"
|
|
2220
|
+
[isPreviewLoading]="isPreviewLoading"
|
|
2221
|
+
[previewTableData]="previewTableData"
|
|
2222
|
+
[columns]="columns"
|
|
2223
|
+
></c8y-datapoints-export-selector-preview>
|
|
2224
|
+
</c8y-modal>
|
|
2225
|
+
`,
|
|
2226
|
+
imports: [CoreModule, DataPointsExportSelectorPreviewComponent, ModalModule],
|
|
2227
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2228
|
+
host: {
|
|
2229
|
+
'(document:keydown.escape)': 'close()'
|
|
2230
|
+
}
|
|
2231
|
+
}]
|
|
2232
|
+
}], ctorParameters: () => [{ type: i1$1.BsModalRef }] });
|
|
2233
|
+
|
|
2234
|
+
class DatapointsExportSelectorModalComponent {
|
|
2235
|
+
constructor(bsModalRef, bsModalService) {
|
|
2236
|
+
this.bsModalRef = bsModalRef;
|
|
2237
|
+
this.bsModalService = bsModalService;
|
|
2238
|
+
this.fileExporter = viewChild(DatapointsExportSelectorFileExporterComponent, ...(ngDevMode ? [{ debugName: "fileExporter" }] : []));
|
|
1847
2239
|
this.isDownloadEnabled = false;
|
|
2240
|
+
this.isPreviewAvailable = false;
|
|
2241
|
+
this.isPreviewLoading = true;
|
|
1848
2242
|
this.labels = { ok: gettext('Download'), cancel: gettext('Cancel') };
|
|
1849
2243
|
this.result = new Promise(resolve => {
|
|
1850
2244
|
this._close = resolve;
|
|
1851
2245
|
});
|
|
2246
|
+
this.isPreviewModalOpen = false;
|
|
1852
2247
|
}
|
|
1853
2248
|
handleKeyboardEvent(event) {
|
|
1854
|
-
if (event.key === 'Escape') {
|
|
2249
|
+
if (event.key === 'Escape' && !this.isPreviewModalOpen) {
|
|
1855
2250
|
this.dismiss();
|
|
1856
2251
|
}
|
|
1857
2252
|
}
|
|
@@ -1860,46 +2255,89 @@ class DatapointsExportSelectorModalComponent {
|
|
|
1860
2255
|
this.bsModalRef.hide();
|
|
1861
2256
|
}
|
|
1862
2257
|
async exportAndDownload() {
|
|
1863
|
-
await this.
|
|
2258
|
+
await this.fileExporter().exportAndDownload();
|
|
1864
2259
|
this.dismiss();
|
|
1865
2260
|
}
|
|
2261
|
+
openPreviewModal() {
|
|
2262
|
+
const exporter = this.fileExporter();
|
|
2263
|
+
const initialState = {
|
|
2264
|
+
columns: this.exportConfig.columns,
|
|
2265
|
+
hasFetchedDataAnyValuesToExport: exporter.hasFetchedDataAnyValuesToExport,
|
|
2266
|
+
isPreviewLoading: exporter.isPreviewLoading,
|
|
2267
|
+
previewTableData: exporter.previewTableData
|
|
2268
|
+
};
|
|
2269
|
+
const previewModalRef = this.bsModalService.show(DatapointsExportSelectorPreviewModalComponent, {
|
|
2270
|
+
class: 'modal-lg',
|
|
2271
|
+
ariaDescribedby: 'modal-body',
|
|
2272
|
+
ariaLabelledBy: 'modal-title',
|
|
2273
|
+
initialState
|
|
2274
|
+
});
|
|
2275
|
+
this.isPreviewModalOpen = true;
|
|
2276
|
+
previewModalRef.onHidden.subscribe(() => {
|
|
2277
|
+
this.isPreviewModalOpen = false;
|
|
2278
|
+
});
|
|
2279
|
+
}
|
|
1866
2280
|
changeDownloadButtonState(isEnabled) {
|
|
1867
2281
|
this.isDownloadEnabled = isEnabled;
|
|
1868
2282
|
}
|
|
1869
|
-
|
|
1870
|
-
|
|
2283
|
+
changePreviewAvailability(isAvailable) {
|
|
2284
|
+
this.isPreviewAvailable = isAvailable;
|
|
2285
|
+
}
|
|
2286
|
+
changePreviewLoading(isLoading) {
|
|
2287
|
+
this.isPreviewLoading = isLoading;
|
|
2288
|
+
}
|
|
2289
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatapointsExportSelectorModalComponent, deps: [{ token: i1$1.BsModalRef }, { token: i1$1.BsModalService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2290
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: DatapointsExportSelectorModalComponent, isStandalone: true, selector: "c8y-datapoints-export-selector-modal", host: { listeners: { "document:keydown": "handleKeyboardEvent($event)" } }, viewQueries: [{ propertyName: "fileExporter", first: true, predicate: DatapointsExportSelectorFileExporterComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<c8y-modal\n [title]=\"'Generate export' | translate\"\n [labels]=\"labels\"\n [disabled]=\"!isDownloadEnabled\"\n [headerClasses]=\"'dialog-header'\"\n (onDismiss)=\"dismiss()\"\n (onClose)=\"exportAndDownload()\"\n>\n <ng-container c8y-modal-title>\n <span [c8yIcon]=\"'data-export'\"></span>\n </ng-container>\n <c8y-datapoints-export-selector-file-exporter\n [exportConfig]=\"exportConfig\"\n (onDownloadButtonStateChange)=\"changeDownloadButtonState($event)\"\n (previewAvailabilityChange)=\"changePreviewAvailability($event)\"\n (previewLoadingChange)=\"changePreviewLoading($event)\"\n ></c8y-datapoints-export-selector-file-exporter>\n @if (isPreviewAvailable) {\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Show preview' | translate }}\"\n type=\"button\"\n c8y-modal-footer\n [disabled]=\"isPreviewLoading || !isDownloadEnabled\"\n (click)=\"openPreviewModal()\"\n >\n <i [c8yIcon]=\"'eye'\"></i>\n {{ 'Show preview' | translate }}\n </button>\n }\n</c8y-modal>\n", dependencies: [{ kind: "component", type: DatapointsExportSelectorFileExporterComponent, selector: "c8y-datapoints-export-selector-file-exporter", inputs: ["exportConfig"], outputs: ["onDownloadButtonStateChange", "previewAvailabilityChange", "previewLoadingChange"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: ModalModule }, { kind: "component", type: i1.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1871
2291
|
}
|
|
1872
2292
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatapointsExportSelectorModalComponent, decorators: [{
|
|
1873
2293
|
type: Component,
|
|
1874
|
-
args: [{ selector: 'c8y-datapoints-export-selector-modal',
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
2294
|
+
args: [{ selector: 'c8y-datapoints-export-selector-modal', imports: [
|
|
2295
|
+
C8yTranslatePipe,
|
|
2296
|
+
DatapointsExportSelectorFileExporterComponent,
|
|
2297
|
+
IconDirective,
|
|
2298
|
+
ModalModule
|
|
2299
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2300
|
+
'(document:keydown)': 'handleKeyboardEvent($event)'
|
|
2301
|
+
}, template: "<c8y-modal\n [title]=\"'Generate export' | translate\"\n [labels]=\"labels\"\n [disabled]=\"!isDownloadEnabled\"\n [headerClasses]=\"'dialog-header'\"\n (onDismiss)=\"dismiss()\"\n (onClose)=\"exportAndDownload()\"\n>\n <ng-container c8y-modal-title>\n <span [c8yIcon]=\"'data-export'\"></span>\n </ng-container>\n <c8y-datapoints-export-selector-file-exporter\n [exportConfig]=\"exportConfig\"\n (onDownloadButtonStateChange)=\"changeDownloadButtonState($event)\"\n (previewAvailabilityChange)=\"changePreviewAvailability($event)\"\n (previewLoadingChange)=\"changePreviewLoading($event)\"\n ></c8y-datapoints-export-selector-file-exporter>\n @if (isPreviewAvailable) {\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Show preview' | translate }}\"\n type=\"button\"\n c8y-modal-footer\n [disabled]=\"isPreviewLoading || !isDownloadEnabled\"\n (click)=\"openPreviewModal()\"\n >\n <i [c8yIcon]=\"'eye'\"></i>\n {{ 'Show preview' | translate }}\n </button>\n }\n</c8y-modal>\n" }]
|
|
2302
|
+
}], ctorParameters: () => [{ type: i1$1.BsModalRef }, { type: i1$1.BsModalService }], propDecorators: { fileExporter: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DatapointsExportSelectorFileExporterComponent), { isSignal: true }] }] } });
|
|
1882
2303
|
|
|
1883
2304
|
class DatapointsExportSelectorComponent {
|
|
1884
2305
|
constructor(bsModalService, gainsightService) {
|
|
1885
2306
|
this.bsModalService = bsModalService;
|
|
1886
2307
|
this.gainsightService = gainsightService;
|
|
1887
|
-
this.displayMode = 'default';
|
|
1888
|
-
|
|
2308
|
+
this.displayMode = input('default', ...(ngDevMode ? [{ debugName: "displayMode" }] : []));
|
|
2309
|
+
/**
|
|
2310
|
+
* CSS class for the container element.
|
|
2311
|
+
* Defaults to 'd-flex p-t-4 p-b-4' if not provided.
|
|
2312
|
+
*/
|
|
2313
|
+
this.containerClass = input(...(ngDevMode ? [undefined, { debugName: "containerClass" }] : []));
|
|
2314
|
+
/**
|
|
2315
|
+
* Configuration for the export selector modal.
|
|
2316
|
+
*/
|
|
2317
|
+
this.exportConfig = input(...(ngDevMode ? [undefined, { debugName: "exportConfig" }] : []));
|
|
2318
|
+
this.isOpen = output();
|
|
1889
2319
|
this.DEFAULT_CSS_STYLE = 'd-flex';
|
|
2320
|
+
/**
|
|
2321
|
+
* Check if export button should be disabled
|
|
2322
|
+
* Disabled when: no config provided or no datapoints configured
|
|
2323
|
+
*/
|
|
2324
|
+
this.isExportDisabled = computed(() => {
|
|
2325
|
+
const config = this.exportConfig();
|
|
2326
|
+
return !config?.datapointDetails || config.datapointDetails.length === 0;
|
|
2327
|
+
}, ...(ngDevMode ? [{ debugName: "isExportDisabled" }] : []));
|
|
1890
2328
|
}
|
|
1891
2329
|
async openExportModal() {
|
|
1892
2330
|
this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_DATAPOINTS_EXPORT_SELECTOR.EVENTS.EXPORT_SELECTOR, {
|
|
1893
2331
|
action: PRODUCT_EXPERIENCE_DATAPOINTS_EXPORT_SELECTOR.ACTIONS.OPEN_MODAL,
|
|
1894
2332
|
component: PRODUCT_EXPERIENCE_DATAPOINTS_EXPORT_SELECTOR.COMPONENTS.DATAPOINTS_EXPORT_SELECTOR
|
|
1895
2333
|
});
|
|
1896
|
-
const exportConfig = this.exportConfig;
|
|
2334
|
+
const exportConfig = this.exportConfig();
|
|
1897
2335
|
const initialState = {
|
|
1898
2336
|
exportConfig
|
|
1899
2337
|
};
|
|
1900
2338
|
this.isOpen.emit(true);
|
|
1901
2339
|
const modalRef = this.bsModalService.show(DatapointsExportSelectorModalComponent, {
|
|
1902
|
-
class: 'modal-
|
|
2340
|
+
class: 'modal-sm',
|
|
1903
2341
|
ariaDescribedby: 'modal-body',
|
|
1904
2342
|
ariaLabelledBy: 'modal-title',
|
|
1905
2343
|
initialState,
|
|
@@ -1909,20 +2347,12 @@ class DatapointsExportSelectorComponent {
|
|
|
1909
2347
|
this.isOpen.emit(await modalRef.result);
|
|
1910
2348
|
}
|
|
1911
2349
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatapointsExportSelectorComponent, deps: [{ token: i1$1.BsModalService }, { token: i1.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1912
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: DatapointsExportSelectorComponent, isStandalone: true, selector: "c8y-datapoints-export-selector", inputs: { displayMode: "displayMode", containerClass: "containerClass", exportConfig: "exportConfig" }, outputs: { isOpen: "isOpen" }, ngImport: i0, template: "@switch (displayMode) {\n @case ('default') {\n @if (containerClass
|
|
2350
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: DatapointsExportSelectorComponent, isStandalone: true, selector: "c8y-datapoints-export-selector", inputs: { displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: false, transformFunction: null }, containerClass: { classPropertyName: "containerClass", publicName: "containerClass", isSignal: true, isRequired: false, transformFunction: null }, exportConfig: { classPropertyName: "exportConfig", publicName: "exportConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpen" }, ngImport: i0, template: "@switch (displayMode()) {\n @case ('default') {\n @if (containerClass() !== 'd-contents') {\n <div [class]=\"containerClass() || DEFAULT_CSS_STYLE\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Generate export' | translate\"\n tooltip=\"{{ 'Generate export' | translate }}\"\n container=\"body\"\n type=\"button\"\n data-cy=\"datapoints-export-selector--open-export-button\"\n (click)=\"openExportModal()\"\n [adaptivePosition]=\"false\"\n [disabled]=\"isExportDisabled()\"\n [delay]=\"500\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"data-export\"\n ></i>\n </button>\n </div>\n } @else {\n <button\n class=\"btn btn-link\"\n type=\"button\"\n (click)=\"openExportModal()\"\n [disabled]=\"isExportDisabled()\"\n >\n <i c8yIcon=\"data-export\"></i>\n {{ 'Generate export' | translate }}\n </button>\n }\n }\n @case ('icon-only') {\n <button\n class=\"btn btn-icon\"\n [attr.aria-label]=\"'Generate export' | translate\"\n tooltip=\"{{ 'Generate export' | translate }}\"\n container=\"body\"\n type=\"button\"\n data-cy=\"datapoints-export-selector--open-export-button\"\n (click)=\"openExportModal()\"\n [adaptivePosition]=\"false\"\n [disabled]=\"!exportConfig()\"\n [delay]=\"500\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"data-export\"\n ></i>\n </button>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3$3.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1913
2351
|
}
|
|
1914
2352
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatapointsExportSelectorComponent, decorators: [{
|
|
1915
2353
|
type: Component,
|
|
1916
|
-
args: [{ selector: 'c8y-datapoints-export-selector',
|
|
1917
|
-
}], ctorParameters: () => [{ type: i1$1.BsModalService }, { type: i1.GainsightService }], propDecorators: { displayMode: [{
|
|
1918
|
-
type: Input
|
|
1919
|
-
}], containerClass: [{
|
|
1920
|
-
type: Input
|
|
1921
|
-
}], exportConfig: [{
|
|
1922
|
-
type: Input
|
|
1923
|
-
}], isOpen: [{
|
|
1924
|
-
type: Output
|
|
1925
|
-
}] } });
|
|
2354
|
+
args: [{ selector: 'c8y-datapoints-export-selector', imports: [CommonModule, TooltipModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (displayMode()) {\n @case ('default') {\n @if (containerClass() !== 'd-contents') {\n <div [class]=\"containerClass() || DEFAULT_CSS_STYLE\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Generate export' | translate\"\n tooltip=\"{{ 'Generate export' | translate }}\"\n container=\"body\"\n type=\"button\"\n data-cy=\"datapoints-export-selector--open-export-button\"\n (click)=\"openExportModal()\"\n [adaptivePosition]=\"false\"\n [disabled]=\"isExportDisabled()\"\n [delay]=\"500\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"data-export\"\n ></i>\n </button>\n </div>\n } @else {\n <button\n class=\"btn btn-link\"\n type=\"button\"\n (click)=\"openExportModal()\"\n [disabled]=\"isExportDisabled()\"\n >\n <i c8yIcon=\"data-export\"></i>\n {{ 'Generate export' | translate }}\n </button>\n }\n }\n @case ('icon-only') {\n <button\n class=\"btn btn-icon\"\n [attr.aria-label]=\"'Generate export' | translate\"\n tooltip=\"{{ 'Generate export' | translate }}\"\n container=\"body\"\n type=\"button\"\n data-cy=\"datapoints-export-selector--open-export-button\"\n (click)=\"openExportModal()\"\n [adaptivePosition]=\"false\"\n [disabled]=\"!exportConfig()\"\n [delay]=\"500\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"data-export\"\n ></i>\n </button>\n }\n}\n" }]
|
|
2355
|
+
}], ctorParameters: () => [{ type: i1$1.BsModalService }, { type: i1.GainsightService }], propDecorators: { displayMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayMode", required: false }] }], containerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "containerClass", required: false }] }], exportConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportConfig", required: false }] }], isOpen: [{ type: i0.Output, args: ["isOpen"] }] } });
|
|
1926
2356
|
|
|
1927
2357
|
/**
|
|
1928
2358
|
* Generated bundle index. Do not edit.
|