@c8y/ngx-components 1023.7.3 → 1023.10.1
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/branding/plain-branding-editor/index.d.ts +2 -1
- package/branding/plain-branding-editor/index.d.ts.map +1 -1
- package/branding/plain-branding-editor/lazy/index.d.ts +4 -0
- package/branding/plain-branding-editor/lazy/index.d.ts.map +1 -1
- package/branding/shared/data/index.d.ts +15 -10
- package/branding/shared/data/index.d.ts.map +1 -1
- package/context-dashboard/index.d.ts.map +1 -1
- package/context-dashboard-state/index.d.ts.map +1 -1
- package/fesm2022/c8y-ngx-components-branding-plain-branding-editor-lazy.mjs +21 -5
- package/fesm2022/c8y-ngx-components-branding-plain-branding-editor-lazy.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-branding-plain-branding-editor.mjs +11 -1
- package/fesm2022/c8y-ngx-components-branding-plain-branding-editor.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-branding-shared-data.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard-state.mjs +0 -1
- package/fesm2022/c8y-ngx-components-context-dashboard-state.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs +0 -6
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-global-context.mjs +296 -283
- package/fesm2022/c8y-ngx-components-global-context.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-map.mjs +11 -4
- package/fesm2022/c8y-ngx-components-map.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-alarms.mjs +2 -8
- package/fesm2022/c8y-ngx-components-widgets-implementations-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +2 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs +4 -16
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components.mjs +24 -28
- package/fesm2022/c8y-ngx-components.mjs.map +1 -1
- package/global-context/index.d.ts +68 -57
- package/global-context/index.d.ts.map +1 -1
- package/index.d.ts.map +1 -1
- package/locales/de.po +41 -32
- package/locales/es.po +41 -32
- package/locales/fr.po +41 -32
- package/locales/ja_JP.po +41 -32
- package/locales/ko.po +41 -32
- package/locales/locales.pot +40 -31
- package/locales/nl.po +41 -32
- package/locales/pl.po +41 -32
- package/locales/pt_BR.po +41 -32
- package/locales/zh_CN.po +41 -32
- package/locales/zh_TW.po +41 -32
- package/map/index.d.ts +8 -0
- package/map/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/widgets/implementations/alarms/index.d.ts.map +1 -1
- package/widgets/implementations/datapoints-graph/index.d.ts.map +1 -1
- package/widgets/implementations/datapoints-table/index.d.ts.map +1 -1
|
@@ -23,6 +23,7 @@ import * as i2 from 'ngx-bootstrap/dropdown';
|
|
|
23
23
|
import { BsDropdownModule, BsDropdownDirective } from 'ngx-bootstrap/dropdown';
|
|
24
24
|
import { A11yModule } from '@angular/cdk/a11y';
|
|
25
25
|
import { withLatestFrom, filter as filter$1, tap, distinctUntilChanged as distinctUntilChanged$1, map as map$1 } from 'rxjs/operators';
|
|
26
|
+
import { TranslateService } from '@ngx-translate/core';
|
|
26
27
|
|
|
27
28
|
const GLOBAL_CONTEXT_EVENTS = {
|
|
28
29
|
STATE_CHANGE: 'GLOBAL_CONTEXT_STATE_CHANGE',
|
|
@@ -127,8 +128,8 @@ const GLOBAL_CONTEXT_DEFAULTS = {
|
|
|
127
128
|
REFRESH_OPTION: REFRESH_OPTION.LIVE,
|
|
128
129
|
/** Default auto-refresh state */
|
|
129
130
|
IS_AUTO_REFRESH_ENABLED: true,
|
|
130
|
-
/** Default refresh interval in milliseconds (
|
|
131
|
-
REFRESH_INTERVAL:
|
|
131
|
+
/** Default refresh interval in milliseconds (5 seconds) */
|
|
132
|
+
REFRESH_INTERVAL: 5000,
|
|
132
133
|
/** Default aggregation type */
|
|
133
134
|
AGGREGATION: null,
|
|
134
135
|
/** Default display mode */
|
|
@@ -146,28 +147,22 @@ const LINK_BTNS_CONFIG = {
|
|
|
146
147
|
dateTimeContext: {
|
|
147
148
|
formControlName: 'dateTimeContext',
|
|
148
149
|
settingKey: 'showTimeContext',
|
|
149
|
-
label: 'time
|
|
150
|
+
label: gettext('date/time'),
|
|
150
151
|
cssClass: 'time-context',
|
|
151
|
-
linkTooltip: gettext('Link time context to global context'),
|
|
152
|
-
unlinkTooltip: gettext('Unlink time context from global context'),
|
|
153
152
|
icon: 'calendar'
|
|
154
153
|
},
|
|
155
154
|
isAutoRefreshEnabled: {
|
|
156
155
|
formControlName: 'isAutoRefreshEnabled',
|
|
157
156
|
settingKey: 'showAutoRefresh',
|
|
158
|
-
label: 'auto
|
|
157
|
+
label: gettext('auto refresh'),
|
|
159
158
|
cssClass: 'auto-refresh',
|
|
160
|
-
linkTooltip: gettext('Link auto-refresh to global context'),
|
|
161
|
-
unlinkTooltip: gettext('Unlink auto-refresh from global context'),
|
|
162
159
|
icon: 'refresh'
|
|
163
160
|
},
|
|
164
161
|
aggregation: {
|
|
165
162
|
formControlName: 'aggregation',
|
|
166
163
|
settingKey: 'showAggregation',
|
|
167
|
-
label: 'aggregation',
|
|
164
|
+
label: gettext('aggregation'),
|
|
168
165
|
cssClass: 'aggregation',
|
|
169
|
-
linkTooltip: gettext('Link aggregation to global context'),
|
|
170
|
-
unlinkTooltip: gettext('Unlink aggregation from global context'),
|
|
171
166
|
icon: 'input'
|
|
172
167
|
}
|
|
173
168
|
};
|
|
@@ -524,7 +519,10 @@ function fillMissingDefaults(state) {
|
|
|
524
519
|
return {
|
|
525
520
|
...defaults,
|
|
526
521
|
...state,
|
|
527
|
-
dateTimeContext
|
|
522
|
+
dateTimeContext,
|
|
523
|
+
// Always override refreshInterval to use the fixed 5s default
|
|
524
|
+
// This ensures old dashboards with custom intervals are migrated to the new fixed interval
|
|
525
|
+
refreshInterval: GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL
|
|
528
526
|
};
|
|
529
527
|
}
|
|
530
528
|
/**
|
|
@@ -893,7 +891,8 @@ class GlobalContextFormService {
|
|
|
893
891
|
dateTimeContext: formValue.dateTimeContext,
|
|
894
892
|
aggregation: formValue.aggregation,
|
|
895
893
|
isAutoRefreshEnabled: formValue.isAutoRefreshEnabled,
|
|
896
|
-
|
|
894
|
+
// Always use fixed 5s interval, ignore any form value
|
|
895
|
+
refreshInterval: GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL,
|
|
897
896
|
refreshOption: formValue.refreshOption
|
|
898
897
|
};
|
|
899
898
|
}
|
|
@@ -1515,7 +1514,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
1515
1514
|
class WidgetConfigMigrationService {
|
|
1516
1515
|
constructor(dateTimeContextPickerService) {
|
|
1517
1516
|
this.dateTimeContextPickerService = dateTimeContextPickerService;
|
|
1518
|
-
this.REALTIME_INTERVAL = 5000; // 5 seconds for realtime
|
|
1519
1517
|
}
|
|
1520
1518
|
/**
|
|
1521
1519
|
* Transforms legacy widget configurations into the standardized GlobalContextState format.
|
|
@@ -1686,16 +1684,9 @@ class WidgetConfigMigrationService {
|
|
|
1686
1684
|
if (config.isAutoRefreshEnabled === undefined) {
|
|
1687
1685
|
config.isAutoRefreshEnabled = this.resolveAutoRefreshEnabled(isRealtime, typeof legacyRefreshOption === 'string' ? legacyRefreshOption : undefined);
|
|
1688
1686
|
}
|
|
1689
|
-
// Refresh Interval - always use
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
typeof mergedSettings.refreshInterval === 'number'
|
|
1693
|
-
? mergedSettings.refreshInterval
|
|
1694
|
-
: GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL;
|
|
1695
|
-
}
|
|
1696
|
-
else if (config.refreshInterval === undefined) {
|
|
1697
|
-
config.refreshInterval = this.resolveRefreshInterval(isRealtime, mergedSettings);
|
|
1698
|
-
}
|
|
1687
|
+
// Refresh Interval - always use default 5s interval (ignore stored values)
|
|
1688
|
+
// This ensures old dashboards with custom intervals are migrated to the fixed 5s interval
|
|
1689
|
+
config.refreshInterval = GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL;
|
|
1699
1690
|
}
|
|
1700
1691
|
/**
|
|
1701
1692
|
* Determines the appropriate display mode based on legacy widget configuration.
|
|
@@ -1871,28 +1862,6 @@ class WidgetConfigMigrationService {
|
|
|
1871
1862
|
}
|
|
1872
1863
|
return true; // Default to enabled (including interval='none')
|
|
1873
1864
|
}
|
|
1874
|
-
/**
|
|
1875
|
-
* Resolves the refresh interval in milliseconds.
|
|
1876
|
-
*
|
|
1877
|
-
* Priority:
|
|
1878
|
-
* 1. Realtime widgets → 5000ms (5 seconds)
|
|
1879
|
-
* 2. Explicit refreshInterval in settings → use as-is
|
|
1880
|
-
* 3. Default → GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL
|
|
1881
|
-
*
|
|
1882
|
-
* @param isRealtime - Whether the widget is in realtime mode
|
|
1883
|
-
* @param settings - Widget settings potentially containing refreshInterval
|
|
1884
|
-
* @returns Refresh interval in milliseconds
|
|
1885
|
-
*
|
|
1886
|
-
*/
|
|
1887
|
-
resolveRefreshInterval(isRealtime, settings) {
|
|
1888
|
-
if (isRealtime) {
|
|
1889
|
-
return this.REALTIME_INTERVAL;
|
|
1890
|
-
}
|
|
1891
|
-
if (typeof settings.refreshInterval === 'number') {
|
|
1892
|
-
return settings.refreshInterval;
|
|
1893
|
-
}
|
|
1894
|
-
return GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL;
|
|
1895
|
-
}
|
|
1896
1865
|
/**
|
|
1897
1866
|
* Detects if a widget is configured for realtime operation.
|
|
1898
1867
|
*
|
|
@@ -2945,7 +2914,6 @@ class HistoryModeConfigurationControlsComponent {
|
|
|
2945
2914
|
}
|
|
2946
2915
|
}
|
|
2947
2916
|
constructor() {
|
|
2948
|
-
this.DEFAULT_INTERVAL_VALUES = DEFAULT_INTERVAL_VALUES;
|
|
2949
2917
|
this.AGGREGATION_TEXTS = AGGREGATION_TEXTS;
|
|
2950
2918
|
this.DATE_FORMAT = 'medium';
|
|
2951
2919
|
this.errorMessages = {
|
|
@@ -2955,7 +2923,7 @@ class HistoryModeConfigurationControlsComponent {
|
|
|
2955
2923
|
invalidDateRange: gettext('Start date must be before end date.')
|
|
2956
2924
|
};
|
|
2957
2925
|
// Popover messages for translation extraction
|
|
2958
|
-
this.TIME_RANGE_PICKER_POPOVER = gettext('
|
|
2926
|
+
this.TIME_RANGE_PICKER_POPOVER = gettext('Specify the exact start and end date/time of the time period to analyse. This provides a static view of historical data within the selected timeframe.');
|
|
2959
2927
|
this.AGGREGATION_POPOVER = gettext("Groups data points into larger time intervals to simplify visualization and improve performance. 'None' shows raw data, while other options combine data points into minute, hour, or day groupings.");
|
|
2960
2928
|
this.destroyRef = inject(DestroyRef);
|
|
2961
2929
|
this.formBuilder = inject(FormBuilder);
|
|
@@ -3130,7 +3098,7 @@ class HistoryModeConfigurationControlsComponent {
|
|
|
3130
3098
|
};
|
|
3131
3099
|
}
|
|
3132
3100
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: HistoryModeConfigurationControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3133
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: HistoryModeConfigurationControlsComponent, isStandalone: true, selector: "c8y-history-mode-configuration-controls", inputs: { settings: "settings", context: "context" }, outputs: { contextChange: "contextChange", validationStatus: "validationStatus" }, ngImport: i0, template: "@if (currentForm) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AGGREGATION = settings.showAggregation;\n\n <form [formGroup]=\"currentForm\">\n <div class=\"content-flex-100\">\n <div\n class=\"col-4\"\n [ngClass]=\"{ 'm-b-8': !SHOW_AGGREGATION }\"\n >\n @if (SHOW_TIME_CONTEXT) {\n @let dateTimeContext = currentForm.get('dateTimeContext');\n @let tempDateFromValue = dateTimeContext.get('dateFrom')?.value;\n @let tempDateToValue = dateTimeContext.get('dateTo')?.value;\n @let fromErrors = dateFromErrors();\n @let toErrors = dateToErrors();\n\n <fieldset class=\"c8y-fieldset\">\n <legend>\n <div class=\"btn-icon-
|
|
3101
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: HistoryModeConfigurationControlsComponent, isStandalone: true, selector: "c8y-history-mode-configuration-controls", inputs: { settings: "settings", context: "context" }, outputs: { contextChange: "contextChange", validationStatus: "validationStatus" }, ngImport: i0, template: "@if (currentForm) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AGGREGATION = settings.showAggregation;\n\n <form [formGroup]=\"currentForm\">\n <div class=\"content-flex-100\">\n <div\n class=\"col-4\"\n [ngClass]=\"{ 'm-b-8': !SHOW_AGGREGATION }\"\n >\n @if (SHOW_TIME_CONTEXT) {\n @let dateTimeContext = currentForm.get('dateTimeContext');\n @let tempDateFromValue = dateTimeContext.get('dateFrom')?.value;\n @let tempDateToValue = dateTimeContext.get('dateTo')?.value;\n @let fromErrors = dateFromErrors();\n @let toErrors = dateToErrors();\n\n <fieldset class=\"c8y-fieldset\">\n <legend>\n <div class=\"standalone btn-icon-dot__item time-context m-r-4\">\n <i\n class=\"\"\n [c8yIcon]=\"'calendar'\"\n ></i>\n </div>\n {{ 'Date & time range' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"TIME_RANGE_PICKER_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n </legend>\n <c8y-form-group class=\"content-flex-58 d-flex a-i-center m-b-0 p-t-16\">\n <c8y-form-group\n [class.has-error]=\"fromErrors\"\n class=\"form-group-sm d-flex a-i-center col-6 flex-wrap\"\n >\n <label\n class=\"m-b-sm-0 m-r-8 text-nowrap\"\n style=\"min-width: 30px\"\n [title]=\"'From`date`' | translate\"\n for=\"dateFrom\"\n translate\n >\n From`date`\n </label>\n <c8y-date-time-picker\n [class.has-error]=\"fromErrors\"\n id=\"dateFrom\"\n [maxDate]=\"tempDateToValue\"\n [placeholder]=\"'From`date`' | translate\"\n [formControl]=\"dateTimeContext.get('dateFrom')\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"fromErrors\">\n <c8y-message\n name=\"dateAfterRangeMax\"\n [text]=\"errorMessages.dateAfterRangeMax | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"errorMessages.invalidDateTime | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateRange\"\n [text]=\"errorMessages.invalidDateRange | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group\n [class.has-error]=\"toErrors\"\n class=\"form-group-sm d-flex flex-wrap col-6 a-i-center\"\n >\n <label\n class=\"m-b-sm-0 text-nowrap m-r-8\"\n style=\"min-width: 30px\"\n [title]=\"'To`date`' | translate\"\n for=\"dateTo\"\n translate\n >\n To`date`\n </label>\n <c8y-date-time-picker\n [class.has-error]=\"toErrors\"\n id=\"dateTo\"\n [minDate]=\"tempDateFromValue\"\n [placeholder]=\"'To`date`' | translate\"\n [formControl]=\"dateTimeContext.get('dateTo')\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"toErrors\">\n <c8y-message\n name=\"dateBeforeRangeMin\"\n [text]=\"errorMessages.dateBeforeRangeMin | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"errorMessages.invalidDateTime | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </c8y-form-group>\n </fieldset>\n }\n </div>\n <div class=\"col-\">\n @if (SHOW_AGGREGATION) {\n @let selectedAggregation = currentForm.get('aggregation')?.value;\n\n <fieldset class=\"c8y-fieldset\">\n <legend>\n <div class=\"standalone btn-icon-dot__item aggregation m-r-4\">\n <i [c8yIcon]=\"'input'\"></i>\n </div>\n {{ 'Aggregation' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"AGGREGATION_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n </legend>\n <c8y-form-group class=\"p-t-16 p-b-16 m-b-4\">\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [resetToDefault]=\"true\"\n [disabledAggregations]=\"disabledAggregations()\"\n [layout]=\"'radio'\"\n ></c8y-aggregation-picker>\n </c8y-form-group>\n </fieldset>\n }\n </div>\n </div>\n </form>\n}\n", dependencies: [{ kind: "ngmodule", type: I18nModule }, { kind: "directive", type: i4.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i2$1.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: AggregationPickerComponent, selector: "c8y-aggregation-picker", inputs: ["disabledAggregations", "resetToDefault", "layout"] }, { kind: "component", type: MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "ngmodule", type: DateTimePickerModule }, { kind: "component", type: i4.DateTimePickerComponent, selector: "c8y-date-time-picker", inputs: ["minDate", "maxDate", "placeholder", "dateInputFormat", "adaptivePosition", "size", "dateType", "config"], outputs: ["onDateSelected"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3134
3102
|
}
|
|
3135
3103
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: HistoryModeConfigurationControlsComponent, decorators: [{
|
|
3136
3104
|
type: Component,
|
|
@@ -3148,57 +3116,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
3148
3116
|
MessageDirective,
|
|
3149
3117
|
DateTimePickerModule,
|
|
3150
3118
|
NgClass
|
|
3151
|
-
], template: "@if (currentForm) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AGGREGATION = settings.showAggregation;\n\n <form [formGroup]=\"currentForm\">\n <div class=\"content-flex-100\">\n <div\n class=\"col-4\"\n [ngClass]=\"{ 'm-b-8': !SHOW_AGGREGATION }\"\n >\n @if (SHOW_TIME_CONTEXT) {\n @let dateTimeContext = currentForm.get('dateTimeContext');\n @let tempDateFromValue = dateTimeContext.get('dateFrom')?.value;\n @let tempDateToValue = dateTimeContext.get('dateTo')?.value;\n @let fromErrors = dateFromErrors();\n @let toErrors = dateToErrors();\n\n <fieldset class=\"c8y-fieldset\">\n <legend>\n <div class=\"btn-icon-
|
|
3119
|
+
], template: "@if (currentForm) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AGGREGATION = settings.showAggregation;\n\n <form [formGroup]=\"currentForm\">\n <div class=\"content-flex-100\">\n <div\n class=\"col-4\"\n [ngClass]=\"{ 'm-b-8': !SHOW_AGGREGATION }\"\n >\n @if (SHOW_TIME_CONTEXT) {\n @let dateTimeContext = currentForm.get('dateTimeContext');\n @let tempDateFromValue = dateTimeContext.get('dateFrom')?.value;\n @let tempDateToValue = dateTimeContext.get('dateTo')?.value;\n @let fromErrors = dateFromErrors();\n @let toErrors = dateToErrors();\n\n <fieldset class=\"c8y-fieldset\">\n <legend>\n <div class=\"standalone btn-icon-dot__item time-context m-r-4\">\n <i\n class=\"\"\n [c8yIcon]=\"'calendar'\"\n ></i>\n </div>\n {{ 'Date & time range' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"TIME_RANGE_PICKER_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n </legend>\n <c8y-form-group class=\"content-flex-58 d-flex a-i-center m-b-0 p-t-16\">\n <c8y-form-group\n [class.has-error]=\"fromErrors\"\n class=\"form-group-sm d-flex a-i-center col-6 flex-wrap\"\n >\n <label\n class=\"m-b-sm-0 m-r-8 text-nowrap\"\n style=\"min-width: 30px\"\n [title]=\"'From`date`' | translate\"\n for=\"dateFrom\"\n translate\n >\n From`date`\n </label>\n <c8y-date-time-picker\n [class.has-error]=\"fromErrors\"\n id=\"dateFrom\"\n [maxDate]=\"tempDateToValue\"\n [placeholder]=\"'From`date`' | translate\"\n [formControl]=\"dateTimeContext.get('dateFrom')\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"fromErrors\">\n <c8y-message\n name=\"dateAfterRangeMax\"\n [text]=\"errorMessages.dateAfterRangeMax | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"errorMessages.invalidDateTime | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateRange\"\n [text]=\"errorMessages.invalidDateRange | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group\n [class.has-error]=\"toErrors\"\n class=\"form-group-sm d-flex flex-wrap col-6 a-i-center\"\n >\n <label\n class=\"m-b-sm-0 text-nowrap m-r-8\"\n style=\"min-width: 30px\"\n [title]=\"'To`date`' | translate\"\n for=\"dateTo\"\n translate\n >\n To`date`\n </label>\n <c8y-date-time-picker\n [class.has-error]=\"toErrors\"\n id=\"dateTo\"\n [minDate]=\"tempDateFromValue\"\n [placeholder]=\"'To`date`' | translate\"\n [formControl]=\"dateTimeContext.get('dateTo')\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"toErrors\">\n <c8y-message\n name=\"dateBeforeRangeMin\"\n [text]=\"errorMessages.dateBeforeRangeMin | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"errorMessages.invalidDateTime | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </c8y-form-group>\n </fieldset>\n }\n </div>\n <div class=\"col-\">\n @if (SHOW_AGGREGATION) {\n @let selectedAggregation = currentForm.get('aggregation')?.value;\n\n <fieldset class=\"c8y-fieldset\">\n <legend>\n <div class=\"standalone btn-icon-dot__item aggregation m-r-4\">\n <i [c8yIcon]=\"'input'\"></i>\n </div>\n {{ 'Aggregation' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"AGGREGATION_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n </legend>\n <c8y-form-group class=\"p-t-16 p-b-16 m-b-4\">\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [resetToDefault]=\"true\"\n [disabledAggregations]=\"disabledAggregations()\"\n [layout]=\"'radio'\"\n ></c8y-aggregation-picker>\n </c8y-form-group>\n </fieldset>\n }\n </div>\n </div>\n </form>\n}\n" }]
|
|
3152
3120
|
}], ctorParameters: () => [], propDecorators: { settings: [{
|
|
3153
3121
|
type: Input
|
|
3154
3122
|
}], context: [{
|
|
3155
3123
|
type: Input
|
|
3156
3124
|
}], contextChange: [{ type: i0.Output, args: ["contextChange"] }], validationStatus: [{ type: i0.Output, args: ["validationStatus"] }] } });
|
|
3157
3125
|
|
|
3158
|
-
class AutoRefreshSelectControlComponent {
|
|
3159
|
-
constructor() {
|
|
3160
|
-
this.DEFAULT_INTERVAL_VALUES = DEFAULT_INTERVAL_VALUES;
|
|
3161
|
-
this.START_INTERVAL_VALUE = 30_000;
|
|
3162
|
-
this.SECONDS_UNTIL_REFRESH = gettext('{{ seconds }} s`until refresh`');
|
|
3163
|
-
this.intervalValueChange = output();
|
|
3164
|
-
this.autoRefreshSeconds = signal(undefined, ...(ngDevMode ? [{ debugName: "autoRefreshSeconds" }] : []));
|
|
3165
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
3166
|
-
this.onTouched = () => { };
|
|
3167
|
-
}
|
|
3168
|
-
registerOnChange(fn) {
|
|
3169
|
-
this.onChange = fn;
|
|
3170
|
-
}
|
|
3171
|
-
registerOnTouched(fn) {
|
|
3172
|
-
this.onTouched = fn;
|
|
3173
|
-
}
|
|
3174
|
-
writeValue(autoRefreshSeconds) {
|
|
3175
|
-
this.autoRefreshSeconds.set(autoRefreshSeconds);
|
|
3176
|
-
}
|
|
3177
|
-
onIntervalChange(autoRefreshSeconds) {
|
|
3178
|
-
this.onChange(autoRefreshSeconds);
|
|
3179
|
-
this.autoRefreshSeconds.set(autoRefreshSeconds);
|
|
3180
|
-
this.intervalValueChange.emit();
|
|
3181
|
-
}
|
|
3182
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AutoRefreshSelectControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3183
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: AutoRefreshSelectControlComponent, isStandalone: true, selector: "c8y-auto-refresh-select-control", outputs: { intervalValueChange: "intervalValueChange" }, providers: [
|
|
3184
|
-
{
|
|
3185
|
-
provide: NG_VALUE_ACCESSOR,
|
|
3186
|
-
useExisting: forwardRef(() => AutoRefreshSelectControlComponent),
|
|
3187
|
-
multi: true
|
|
3188
|
-
}
|
|
3189
|
-
], ngImport: i0, template: "@let refreshIntervalLabel = 'Refresh interval in seconds' | translate;\n@let secondsTranslation = SECONDS_UNTIL_REFRESH | translate;\n\n<div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control text-12\"\n [attr.aria-label]=\"refreshIntervalLabel\"\n [tooltip]=\"refreshIntervalLabel\"\n placement=\"bottom\"\n data-cy=\"global-context--refresh-interval-select\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n [container]=\"'body'\"\n mode\n [ngModel]=\"autoRefreshSeconds()\"\n (ngModelChange)=\"onIntervalChange($event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n @for (refreshInterval of DEFAULT_INTERVAL_VALUES; track refreshInterval) {\n @let isSelected = refreshInterval === START_INTERVAL_VALUE;\n @let secondsValue = refreshInterval / 1000;\n\n <option\n [ngValue]=\"refreshInterval\"\n [attr.selected]=\"isSelected ? '' : null\"\n >\n @if (secondsValue === 5) {\n {{ 'Auto' | translate }}\n } @else {\n {{ '{{ seconds }}s' | translate: { seconds: secondsValue } }}\n }\n </option>\n }\n </select>\n <span></span>\n</div>\n", dependencies: [{ kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1.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: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3190
|
-
}
|
|
3191
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AutoRefreshSelectControlComponent, decorators: [{
|
|
3192
|
-
type: Component,
|
|
3193
|
-
args: [{ selector: 'c8y-auto-refresh-select-control', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
3194
|
-
{
|
|
3195
|
-
provide: NG_VALUE_ACCESSOR,
|
|
3196
|
-
useExisting: forwardRef(() => AutoRefreshSelectControlComponent),
|
|
3197
|
-
multi: true
|
|
3198
|
-
}
|
|
3199
|
-
], standalone: true, imports: [C8yTranslatePipe, TooltipModule, FormsModule], template: "@let refreshIntervalLabel = 'Refresh interval in seconds' | translate;\n@let secondsTranslation = SECONDS_UNTIL_REFRESH | translate;\n\n<div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control text-12\"\n [attr.aria-label]=\"refreshIntervalLabel\"\n [tooltip]=\"refreshIntervalLabel\"\n placement=\"bottom\"\n data-cy=\"global-context--refresh-interval-select\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n [container]=\"'body'\"\n mode\n [ngModel]=\"autoRefreshSeconds()\"\n (ngModelChange)=\"onIntervalChange($event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n @for (refreshInterval of DEFAULT_INTERVAL_VALUES; track refreshInterval) {\n @let isSelected = refreshInterval === START_INTERVAL_VALUE;\n @let secondsValue = refreshInterval / 1000;\n\n <option\n [ngValue]=\"refreshInterval\"\n [attr.selected]=\"isSelected ? '' : null\"\n >\n @if (secondsValue === 5) {\n {{ 'Auto' | translate }}\n } @else {\n {{ '{{ seconds }}s' | translate: { seconds: secondsValue } }}\n }\n </option>\n }\n </select>\n <span></span>\n</div>\n" }]
|
|
3200
|
-
}], propDecorators: { intervalValueChange: [{ type: i0.Output, args: ["intervalValueChange"] }] } });
|
|
3201
|
-
|
|
3202
3126
|
class IntervalPickerComponent {
|
|
3203
3127
|
constructor() {
|
|
3204
3128
|
this.INTERVALS = [...INTERVALS];
|
|
@@ -3591,9 +3515,8 @@ class LiveModeConfigurationControlsComponent {
|
|
|
3591
3515
|
this.patchFormFromContext(cloned);
|
|
3592
3516
|
}
|
|
3593
3517
|
constructor() {
|
|
3594
|
-
this.DEFAULT_INTERVAL_VALUES = DEFAULT_INTERVAL_VALUES;
|
|
3595
3518
|
// Popover messages for translation extraction
|
|
3596
|
-
this.
|
|
3519
|
+
this.REFRESH_POPOVER_MESSAGE = gettext('The update method is determined by the widget type. Some widgets support real-time updates via WebSocket connection, while others use periodic refreshes.');
|
|
3597
3520
|
this.TIME_RANGE_PICKER_POPOVER = gettext('Sets a rolling time window relative to the current time. As time progresses, the window automatically shifts to maintain the selected duration, always showing the most recent data.');
|
|
3598
3521
|
this.destroyRef = inject(DestroyRef);
|
|
3599
3522
|
this.formBuilder = inject(FormBuilder);
|
|
@@ -3610,7 +3533,7 @@ class LiveModeConfigurationControlsComponent {
|
|
|
3610
3533
|
.subscribe(value => {
|
|
3611
3534
|
this.contextChange.emit({
|
|
3612
3535
|
dateTimeContext: value.dateTimeContext ?? null,
|
|
3613
|
-
refreshInterval:
|
|
3536
|
+
refreshInterval: GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL,
|
|
3614
3537
|
isAutoRefreshEnabled: value.isAutoRefreshEnabled ?? null,
|
|
3615
3538
|
aggregation: null
|
|
3616
3539
|
});
|
|
@@ -3620,8 +3543,8 @@ class LiveModeConfigurationControlsComponent {
|
|
|
3620
3543
|
createForm() {
|
|
3621
3544
|
return this.formBuilder.group({
|
|
3622
3545
|
dateTimeContext: this.formBuilder.control(null),
|
|
3623
|
-
refreshInterval: this.formBuilder.control(
|
|
3624
|
-
isAutoRefreshEnabled: this.formBuilder.control(
|
|
3546
|
+
refreshInterval: this.formBuilder.control(GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL),
|
|
3547
|
+
isAutoRefreshEnabled: this.formBuilder.control(true)
|
|
3625
3548
|
});
|
|
3626
3549
|
}
|
|
3627
3550
|
patchFormFromContext(context) {
|
|
@@ -3629,15 +3552,15 @@ class LiveModeConfigurationControlsComponent {
|
|
|
3629
3552
|
return;
|
|
3630
3553
|
}
|
|
3631
3554
|
const ctx = context ?? this.currentContext();
|
|
3632
|
-
const { dateTimeContext,
|
|
3555
|
+
const { dateTimeContext, isAutoRefreshEnabled } = ctx;
|
|
3633
3556
|
this.form.patchValue({
|
|
3634
3557
|
dateTimeContext: dateTimeContext ? structuredClone(dateTimeContext) : null,
|
|
3635
|
-
refreshInterval:
|
|
3558
|
+
refreshInterval: GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL,
|
|
3636
3559
|
isAutoRefreshEnabled: isAutoRefreshEnabled ?? null
|
|
3637
3560
|
}, { emitEvent: false });
|
|
3638
3561
|
}
|
|
3639
3562
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: LiveModeConfigurationControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3640
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: LiveModeConfigurationControlsComponent, isStandalone: true, selector: "c8y-live-mode-configuration-controls", inputs: { settings: "settings", context: "context" }, outputs: { contextChange: "contextChange" }, ngImport: i0, template: "@if (form) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AUTO_REFRESH = settings.showAutoRefresh;\n\n <form [formGroup]=\"form\">\n <div class=\"content-flex-82\">\n <div class=\"col-
|
|
3563
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: LiveModeConfigurationControlsComponent, isStandalone: true, selector: "c8y-live-mode-configuration-controls", inputs: { settings: "settings", context: "context" }, outputs: { contextChange: "contextChange" }, ngImport: i0, template: "@if (form) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AUTO_REFRESH = settings.showAutoRefresh;\n\n <form [formGroup]=\"form\">\n <div class=\"content-flex-82\">\n <div class=\"col-5\">\n @if (SHOW_TIME_CONTEXT) {\n <fieldset class=\"c8y-fieldset\">\n <legend>\n <div class=\"standalone btn-icon-dot__item time-context m-r-4\">\n <i [c8yIcon]=\"'calendar'\"></i>\n </div>\n {{ 'Date & time' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"TIME_RANGE_PICKER_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n </legend>\n <c8y-form-group class=\"m-b-4 p-t-16 p-b-16\">\n <c8y-date-time-context-picker\n formControlName=\"dateTimeContext\"\n [config]=\"{ showDateTo: false, showDateFrom: true }\"\n ></c8y-date-time-context-picker>\n </c8y-form-group>\n </fieldset>\n }\n </div>\n <div class=\"col-3\">\n @if (SHOW_AUTO_REFRESH) {\n <fieldset class=\"c8y-fieldset\">\n <legend class=\"d-flex\">\n <div class=\"standalone btn-icon-dot__item auto-refresh m-r-4\">\n <i [c8yIcon]=\"'refresh'\"></i>\n </div>\n {{ 'Auto refresh' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"REFRESH_POPOVER_MESSAGE | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n </legend>\n <c8y-form-group class=\"m-b-8 form-group-sm p-t-16 p-b-16\">\n <div class=\"d-flex gap-8 a-i-center\">\n <label class=\"c8y-switch c8y-switch--inline\">\n <input\n type=\"checkbox\"\n #arInput\n formControlName=\"isAutoRefreshEnabled\"\n />\n <span></span>\n <span>\n {{ 'Auto refresh enabled' | translate }}\n </span>\n </label>\n </div>\n </c8y-form-group>\n </fieldset>\n }\n </div>\n </div>\n </form>\n}\n", dependencies: [{ kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: DateTimeContextPickerComponent, selector: "c8y-date-time-context-picker", inputs: ["disabled", "shouldDisableInterval", "config"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i2$1.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3641
3564
|
}
|
|
3642
3565
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: LiveModeConfigurationControlsComponent, decorators: [{
|
|
3643
3566
|
type: Component,
|
|
@@ -3649,9 +3572,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
3649
3572
|
IconDirective,
|
|
3650
3573
|
FormsModule,
|
|
3651
3574
|
PopoverModule,
|
|
3652
|
-
FormGroupComponent
|
|
3653
|
-
|
|
3654
|
-
], template: "@if (form) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AUTO_REFRESH = settings.showAutoRefresh;\n\n <form [formGroup]=\"form\">\n <div class=\"content-flex-82\">\n <div class=\"col-3\">\n @if (SHOW_AUTO_REFRESH) {\n <fieldset class=\"c8y-fieldset\">\n <legend class=\"d-flex\">\n <div class=\"btn-icon-dot auto-refresh m-r-4\">\n <i [c8yIcon]=\"'refresh'\"></i>\n </div>\n {{ 'Refresh' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"REFRESH_INTERVAL_POPOVER_MESSAGE | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n </legend>\n <c8y-form-group class=\"m-b-8 form-group-sm p-t-16 p-b-16\">\n <div class=\"d-flex gap-8 a-i-center\">\n <ng-container>\n <label\n class=\"m-b-0 text-12 text-nowrap\"\n for=\"refreshInterval\"\n >\n {{ 'Refresh interval' | translate }}\n </label>\n <c8y-auto-refresh-select-control\n formControlName=\"refreshInterval\"\n ></c8y-auto-refresh-select-control>\n </ng-container>\n </div>\n </c8y-form-group>\n </fieldset>\n }\n </div>\n <div class=\"col-5\">\n @if (SHOW_TIME_CONTEXT) {\n <fieldset class=\"c8y-fieldset\">\n <legend>\n <div class=\"btn-icon-dot time-context m-r-4\">\n <i [c8yIcon]=\"'calendar'\"></i>\n </div>\n {{ 'Date filter' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"TIME_RANGE_PICKER_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n </legend>\n <c8y-form-group class=\"m-b-4 p-t-16 p-b-16\">\n <c8y-date-time-context-picker\n formControlName=\"dateTimeContext\"\n [config]=\"{ showDateTo: false, showDateFrom: true }\"\n ></c8y-date-time-context-picker>\n </c8y-form-group>\n </fieldset>\n }\n </div>\n </div>\n </form>\n}\n" }]
|
|
3575
|
+
FormGroupComponent
|
|
3576
|
+
], template: "@if (form) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AUTO_REFRESH = settings.showAutoRefresh;\n\n <form [formGroup]=\"form\">\n <div class=\"content-flex-82\">\n <div class=\"col-5\">\n @if (SHOW_TIME_CONTEXT) {\n <fieldset class=\"c8y-fieldset\">\n <legend>\n <div class=\"standalone btn-icon-dot__item time-context m-r-4\">\n <i [c8yIcon]=\"'calendar'\"></i>\n </div>\n {{ 'Date & time' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"TIME_RANGE_PICKER_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n </legend>\n <c8y-form-group class=\"m-b-4 p-t-16 p-b-16\">\n <c8y-date-time-context-picker\n formControlName=\"dateTimeContext\"\n [config]=\"{ showDateTo: false, showDateFrom: true }\"\n ></c8y-date-time-context-picker>\n </c8y-form-group>\n </fieldset>\n }\n </div>\n <div class=\"col-3\">\n @if (SHOW_AUTO_REFRESH) {\n <fieldset class=\"c8y-fieldset\">\n <legend class=\"d-flex\">\n <div class=\"standalone btn-icon-dot__item auto-refresh m-r-4\">\n <i [c8yIcon]=\"'refresh'\"></i>\n </div>\n {{ 'Auto refresh' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"REFRESH_POPOVER_MESSAGE | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"true\"\n ></button>\n </legend>\n <c8y-form-group class=\"m-b-8 form-group-sm p-t-16 p-b-16\">\n <div class=\"d-flex gap-8 a-i-center\">\n <label class=\"c8y-switch c8y-switch--inline\">\n <input\n type=\"checkbox\"\n #arInput\n formControlName=\"isAutoRefreshEnabled\"\n />\n <span></span>\n <span>\n {{ 'Auto refresh enabled' | translate }}\n </span>\n </label>\n </div>\n </c8y-form-group>\n </fieldset>\n }\n </div>\n </div>\n </form>\n}\n" }]
|
|
3655
3577
|
}], ctorParameters: () => [], propDecorators: { settings: [{
|
|
3656
3578
|
type: Input
|
|
3657
3579
|
}], context: [{
|
|
@@ -3795,7 +3717,7 @@ class ConfigurationControlsComponent {
|
|
|
3795
3717
|
<i [c8yIcon]="'process'"></i>
|
|
3796
3718
|
<div>
|
|
3797
3719
|
<p class="text-bold">{{ MODE_LABELS.LIVE | translate }}</p>
|
|
3798
|
-
<p class="text-12 l-h-tight">
|
|
3720
|
+
<p class="tab-description text-12 l-h-tight">
|
|
3799
3721
|
{{ MODE_DESCRIPTIONS.LIVE | translate }}
|
|
3800
3722
|
</p>
|
|
3801
3723
|
</div>
|
|
@@ -3804,7 +3726,7 @@ class ConfigurationControlsComponent {
|
|
|
3804
3726
|
<i [c8yIcon]="'schedule1'"></i>
|
|
3805
3727
|
<div>
|
|
3806
3728
|
<p class="text-bold">{{ MODE_LABELS.HISTORY | translate }}</p>
|
|
3807
|
-
<p class="text-12
|
|
3729
|
+
<p class="tab-description text-12 l-h-tight">
|
|
3808
3730
|
{{ MODE_DESCRIPTIONS.HISTORY | translate }}
|
|
3809
3731
|
</p>
|
|
3810
3732
|
</div>
|
|
@@ -3854,7 +3776,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
3854
3776
|
<i [c8yIcon]="'process'"></i>
|
|
3855
3777
|
<div>
|
|
3856
3778
|
<p class="text-bold">{{ MODE_LABELS.LIVE | translate }}</p>
|
|
3857
|
-
<p class="text-12 l-h-tight">
|
|
3779
|
+
<p class="tab-description text-12 l-h-tight">
|
|
3858
3780
|
{{ MODE_DESCRIPTIONS.LIVE | translate }}
|
|
3859
3781
|
</p>
|
|
3860
3782
|
</div>
|
|
@@ -3863,7 +3785,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
3863
3785
|
<i [c8yIcon]="'schedule1'"></i>
|
|
3864
3786
|
<div>
|
|
3865
3787
|
<p class="text-bold">{{ MODE_LABELS.HISTORY | translate }}</p>
|
|
3866
|
-
<p class="text-12
|
|
3788
|
+
<p class="tab-description text-12 l-h-tight">
|
|
3867
3789
|
{{ MODE_DESCRIPTIONS.HISTORY | translate }}
|
|
3868
3790
|
</p>
|
|
3869
3791
|
</div>
|
|
@@ -4650,9 +4572,9 @@ class AutoRefreshControlComponent {
|
|
|
4650
4572
|
};
|
|
4651
4573
|
this.isAutoRefreshConnected = false;
|
|
4652
4574
|
this.disableCounter = false;
|
|
4653
|
-
this.DISABLE_AUTO_REFRESH = gettext('
|
|
4654
|
-
this.ENABLE_AUTO_REFRESH = gettext('
|
|
4655
|
-
this.DEFAULT_INTERVAL_VALUE =
|
|
4575
|
+
this.DISABLE_AUTO_REFRESH = gettext('Auto refresh enabled');
|
|
4576
|
+
this.ENABLE_AUTO_REFRESH = gettext('Auto refresh paused');
|
|
4577
|
+
this.DEFAULT_INTERVAL_VALUE = GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL;
|
|
4656
4578
|
this.countdownComponentReady$ = new BehaviorSubject(null);
|
|
4657
4579
|
this.loading$ = new BehaviorSubject(false);
|
|
4658
4580
|
this.destroyRef = inject(DestroyRef);
|
|
@@ -4664,18 +4586,14 @@ class AutoRefreshControlComponent {
|
|
|
4664
4586
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
4665
4587
|
this.onTouched = () => { };
|
|
4666
4588
|
}
|
|
4667
|
-
set autoRefreshSeconds(
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
this.countdownIntervalConfig = {
|
|
4676
|
-
enforcePulseIcon: false
|
|
4677
|
-
};
|
|
4678
|
-
}
|
|
4589
|
+
set autoRefreshSeconds(_value) {
|
|
4590
|
+
// Value hardcoded to 5000ms for now, as per requirements
|
|
4591
|
+
// It will be adjusted later when dynamic intervals are supported (based on the request execution time)
|
|
4592
|
+
this.autoRefreshSeconds$ = new BehaviorSubject(GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL);
|
|
4593
|
+
// Always show pulse icon, never show countdown timer
|
|
4594
|
+
this.countdownIntervalConfig = {
|
|
4595
|
+
enforcePulseIcon: true
|
|
4596
|
+
};
|
|
4679
4597
|
}
|
|
4680
4598
|
set isLoading(value) {
|
|
4681
4599
|
const wasLoading = this._isLoading;
|
|
@@ -4850,7 +4768,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
4850
4768
|
class ContextControlsComponent {
|
|
4851
4769
|
constructor() {
|
|
4852
4770
|
// Static properties
|
|
4853
|
-
this.DEFAULT_INTERVAL_VALUES = DEFAULT_INTERVAL_VALUES;
|
|
4854
4771
|
this.REFRESH_OPTION = REFRESH_OPTION;
|
|
4855
4772
|
// Inputs
|
|
4856
4773
|
this.showDisplayModeLabel = false;
|
|
@@ -4931,7 +4848,7 @@ class ContextControlsComponent {
|
|
|
4931
4848
|
return pick(settings, requiredKeys);
|
|
4932
4849
|
}
|
|
4933
4850
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ContextControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4934
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ContextControlsComponent, isStandalone: true, selector: "c8y-context-controls", inputs: { showDisplayModeLabel: "showDisplayModeLabel", isLoading: "isLoading", settings: "settings", context: "context" }, outputs: { contextChange: "contextChange", refresh: "refresh", contextClick: "contextClick" }, ngImport: i0, template: "@if (form) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AGGREGATION = settings.showAggregation;\n @let SHOW_AUTO_REFRESH = settings.showAutoRefresh;\n @let refreshIntervalValue = form?.get('refreshInterval')?.value;\n @let isLiveMode = refreshOption === REFRESH_OPTION.LIVE;\n\n @if (isLiveMode) {\n <form\n class=\"input-group\"\n [formGroup]=\"form\"\n >\n <c8y-auto-refresh-control\n #autoRefreshControl\n [isLoading]=\"isLoading\"\n [isAutoRefreshConnected]=\"isAutoRefreshConnected\"\n formControlName=\"isAutoRefreshEnabled\"\n [autoRefreshSeconds]=\"refreshIntervalValue\"\n (refresh)=\"refresh.emit()\"\n ></c8y-auto-refresh-control>\n <button\n class=\"btn-clean d-flex p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n style=\"margin-left: -1px\"\n (click)=\"contextClick.emit($event); $event.stopPropagation()\"\n >\n <div class=\"d-col a-i-start form-control\">\n <p class=\"text-muted fit-w text-10 l-h-1\">\n {{ 'Time mode' | translate }}\n </p>\n <p\n class=\"text-bold text-12 fit-w l-h-1\"\n data-cy=\"global-time-context-controls--Display-mode\"\n >\n {{ refreshOption | translate | titlecase }}\n </p>\n </div>\n\n @let interval = form.get('dateTimeContext')?.value?.interval;\n @let isCustomInterval = interval === 'custom';\n\n <c8y-time-range-display\n style=\"margin-left: -1px\"\n [dateTimeContext]=\"form.get('dateTimeContext')?.value\"\n ></c8y-time-range-display>\n\n @if (!(isAnySettingsEnabled$ | async)) {\n <div\n class=\"d-col a-i-center form-control\"\n style=\"margin-left: -1px\"\n >\n <i\n class=\"dlt-c8y-icon-disconnected icon-20 text-danger\"\n [tooltip]=\"'No
|
|
4851
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ContextControlsComponent, isStandalone: true, selector: "c8y-context-controls", inputs: { showDisplayModeLabel: "showDisplayModeLabel", isLoading: "isLoading", settings: "settings", context: "context" }, outputs: { contextChange: "contextChange", refresh: "refresh", contextClick: "contextClick" }, ngImport: i0, template: "@if (form) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AGGREGATION = settings.showAggregation;\n @let SHOW_AUTO_REFRESH = settings.showAutoRefresh;\n @let refreshIntervalValue = form?.get('refreshInterval')?.value;\n @let isLiveMode = refreshOption === REFRESH_OPTION.LIVE;\n\n @if (isLiveMode) {\n <form\n class=\"input-group\"\n [formGroup]=\"form\"\n >\n <c8y-auto-refresh-control\n #autoRefreshControl\n [isLoading]=\"isLoading\"\n [isAutoRefreshConnected]=\"isAutoRefreshConnected\"\n formControlName=\"isAutoRefreshEnabled\"\n [autoRefreshSeconds]=\"refreshIntervalValue\"\n (refresh)=\"refresh.emit()\"\n ></c8y-auto-refresh-control>\n <button\n class=\"btn-clean d-flex p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n style=\"margin-left: -1px\"\n (click)=\"contextClick.emit($event); $event.stopPropagation()\"\n >\n <div class=\"d-col a-i-start form-control\">\n <p class=\"text-muted fit-w text-10 l-h-1\">\n {{ 'Time mode' | translate }}\n </p>\n <p\n class=\"text-bold text-12 fit-w l-h-1\"\n data-cy=\"global-time-context-controls--Display-mode\"\n >\n {{ refreshOption | translate | titlecase }}\n </p>\n </div>\n\n @let interval = form.get('dateTimeContext')?.value?.interval;\n @let isCustomInterval = interval === 'custom';\n\n <c8y-time-range-display\n style=\"margin-left: -1px\"\n [dateTimeContext]=\"form.get('dateTimeContext')?.value\"\n ></c8y-time-range-display>\n\n @if (!(isAnySettingsEnabled$ | async)) {\n <div\n class=\"d-col a-i-center form-control\"\n style=\"margin-left: -1px\"\n >\n <i\n class=\"dlt-c8y-icon-disconnected icon-20 text-danger\"\n [tooltip]=\"'No synced widgets' | translate\"\n placement=\"right\"\n container=\"body\"\n [delay]=\"500\"\n data-cy=\"global-time-context-controls--Widgets-disconnected\"\n ></i>\n </div>\n }\n </button>\n </form>\n } @else {\n <form [formGroup]=\"form\">\n <button\n class=\"btn-clean d-flex p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n (click)=\"contextClick.emit($event); $event.stopPropagation()\"\n >\n <div class=\"d-col a-i-center form-control\">\n <i class=\"dlt-c8y-icon-schedule1 icon-20 text-primary\"></i>\n </div>\n\n <div\n class=\"d-col a-i-start form-control\"\n style=\"margin-left: -1px\"\n >\n <p class=\"text-muted fit-w text-10 l-h-1\">\n {{ 'Time mode' | translate }}\n </p>\n <p\n class=\"text-bold text-12 fit-w l-h-1\"\n data-cy=\"global-time-context-controls--Display-mode\"\n >\n {{ refreshOption | translate | titlecase }}\n </p>\n </div>\n\n <c8y-time-range-display\n style=\"margin-left: -1px\"\n [dateTimeContext]=\"form.get('dateTimeContext')?.value\"\n ></c8y-time-range-display>\n <c8y-aggregation-display\n style=\"margin-left: -1px\"\n [aggregation]=\"form.get('aggregation')?.value\"\n ></c8y-aggregation-display>\n\n @if (!(isAnySettingsEnabled$ | async)) {\n <div\n class=\"d-col a-i-center form-control\"\n style=\"margin-left: -1px\"\n >\n <i\n class=\"dlt-c8y-icon-disconnected icon-20 text-danger\"\n [tooltip]=\"'No synced widgets' | translate\"\n placement=\"right\"\n container=\"body\"\n [delay]=\"500\"\n data-cy=\"global-time-context-controls--Widgets-disconnected\"\n ></i>\n </div>\n }\n </button>\n </form>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1.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: "ngmodule", type: CollapseModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: AutoRefreshControlComponent, selector: "c8y-auto-refresh-control", inputs: ["isAutoRefreshConnected", "autoRefreshSeconds", "disableCounter", "isEnabled", "isLoading"], outputs: ["loadingChange", "refresh"] }, { kind: "component", type: TimeRangeDisplayComponent, selector: "c8y-time-range-display", inputs: ["dateTimeContext", "mode"] }, { kind: "component", type: AggregationDisplayComponent, selector: "c8y-aggregation-display", inputs: ["aggregation"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4935
4852
|
}
|
|
4936
4853
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ContextControlsComponent, decorators: [{
|
|
4937
4854
|
type: Component,
|
|
@@ -4947,7 +4864,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
4947
4864
|
TimeRangeDisplayComponent,
|
|
4948
4865
|
AggregationDisplayComponent,
|
|
4949
4866
|
AsyncPipe
|
|
4950
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (form) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AGGREGATION = settings.showAggregation;\n @let SHOW_AUTO_REFRESH = settings.showAutoRefresh;\n @let refreshIntervalValue = form?.get('refreshInterval')?.value;\n @let isLiveMode = refreshOption === REFRESH_OPTION.LIVE;\n\n @if (isLiveMode) {\n <form\n class=\"input-group\"\n [formGroup]=\"form\"\n >\n <c8y-auto-refresh-control\n #autoRefreshControl\n [isLoading]=\"isLoading\"\n [isAutoRefreshConnected]=\"isAutoRefreshConnected\"\n formControlName=\"isAutoRefreshEnabled\"\n [autoRefreshSeconds]=\"refreshIntervalValue\"\n (refresh)=\"refresh.emit()\"\n ></c8y-auto-refresh-control>\n <button\n class=\"btn-clean d-flex p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n style=\"margin-left: -1px\"\n (click)=\"contextClick.emit($event); $event.stopPropagation()\"\n >\n <div class=\"d-col a-i-start form-control\">\n <p class=\"text-muted fit-w text-10 l-h-1\">\n {{ 'Time mode' | translate }}\n </p>\n <p\n class=\"text-bold text-12 fit-w l-h-1\"\n data-cy=\"global-time-context-controls--Display-mode\"\n >\n {{ refreshOption | translate | titlecase }}\n </p>\n </div>\n\n @let interval = form.get('dateTimeContext')?.value?.interval;\n @let isCustomInterval = interval === 'custom';\n\n <c8y-time-range-display\n style=\"margin-left: -1px\"\n [dateTimeContext]=\"form.get('dateTimeContext')?.value\"\n ></c8y-time-range-display>\n\n @if (!(isAnySettingsEnabled$ | async)) {\n <div\n class=\"d-col a-i-center form-control\"\n style=\"margin-left: -1px\"\n >\n <i\n class=\"dlt-c8y-icon-disconnected icon-20 text-danger\"\n [tooltip]=\"'No
|
|
4867
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (form) {\n @let SHOW_TIME_CONTEXT = settings.showTimeContext;\n @let SHOW_AGGREGATION = settings.showAggregation;\n @let SHOW_AUTO_REFRESH = settings.showAutoRefresh;\n @let refreshIntervalValue = form?.get('refreshInterval')?.value;\n @let isLiveMode = refreshOption === REFRESH_OPTION.LIVE;\n\n @if (isLiveMode) {\n <form\n class=\"input-group\"\n [formGroup]=\"form\"\n >\n <c8y-auto-refresh-control\n #autoRefreshControl\n [isLoading]=\"isLoading\"\n [isAutoRefreshConnected]=\"isAutoRefreshConnected\"\n formControlName=\"isAutoRefreshEnabled\"\n [autoRefreshSeconds]=\"refreshIntervalValue\"\n (refresh)=\"refresh.emit()\"\n ></c8y-auto-refresh-control>\n <button\n class=\"btn-clean d-flex p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n style=\"margin-left: -1px\"\n (click)=\"contextClick.emit($event); $event.stopPropagation()\"\n >\n <div class=\"d-col a-i-start form-control\">\n <p class=\"text-muted fit-w text-10 l-h-1\">\n {{ 'Time mode' | translate }}\n </p>\n <p\n class=\"text-bold text-12 fit-w l-h-1\"\n data-cy=\"global-time-context-controls--Display-mode\"\n >\n {{ refreshOption | translate | titlecase }}\n </p>\n </div>\n\n @let interval = form.get('dateTimeContext')?.value?.interval;\n @let isCustomInterval = interval === 'custom';\n\n <c8y-time-range-display\n style=\"margin-left: -1px\"\n [dateTimeContext]=\"form.get('dateTimeContext')?.value\"\n ></c8y-time-range-display>\n\n @if (!(isAnySettingsEnabled$ | async)) {\n <div\n class=\"d-col a-i-center form-control\"\n style=\"margin-left: -1px\"\n >\n <i\n class=\"dlt-c8y-icon-disconnected icon-20 text-danger\"\n [tooltip]=\"'No synced widgets' | translate\"\n placement=\"right\"\n container=\"body\"\n [delay]=\"500\"\n data-cy=\"global-time-context-controls--Widgets-disconnected\"\n ></i>\n </div>\n }\n </button>\n </form>\n } @else {\n <form [formGroup]=\"form\">\n <button\n class=\"btn-clean d-flex p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n (click)=\"contextClick.emit($event); $event.stopPropagation()\"\n >\n <div class=\"d-col a-i-center form-control\">\n <i class=\"dlt-c8y-icon-schedule1 icon-20 text-primary\"></i>\n </div>\n\n <div\n class=\"d-col a-i-start form-control\"\n style=\"margin-left: -1px\"\n >\n <p class=\"text-muted fit-w text-10 l-h-1\">\n {{ 'Time mode' | translate }}\n </p>\n <p\n class=\"text-bold text-12 fit-w l-h-1\"\n data-cy=\"global-time-context-controls--Display-mode\"\n >\n {{ refreshOption | translate | titlecase }}\n </p>\n </div>\n\n <c8y-time-range-display\n style=\"margin-left: -1px\"\n [dateTimeContext]=\"form.get('dateTimeContext')?.value\"\n ></c8y-time-range-display>\n <c8y-aggregation-display\n style=\"margin-left: -1px\"\n [aggregation]=\"form.get('aggregation')?.value\"\n ></c8y-aggregation-display>\n\n @if (!(isAnySettingsEnabled$ | async)) {\n <div\n class=\"d-col a-i-center form-control\"\n style=\"margin-left: -1px\"\n >\n <i\n class=\"dlt-c8y-icon-disconnected icon-20 text-danger\"\n [tooltip]=\"'No synced widgets' | translate\"\n placement=\"right\"\n container=\"body\"\n [delay]=\"500\"\n data-cy=\"global-time-context-controls--Widgets-disconnected\"\n ></i>\n </div>\n }\n </button>\n </form>\n }\n}\n" }]
|
|
4951
4868
|
}], propDecorators: { showDisplayModeLabel: [{
|
|
4952
4869
|
type: Input
|
|
4953
4870
|
}], isLoading: [{
|
|
@@ -5314,6 +5231,9 @@ class GlobalContextComponent {
|
|
|
5314
5231
|
dateTimeContext: normalized
|
|
5315
5232
|
};
|
|
5316
5233
|
}
|
|
5234
|
+
// Always enforce the fixed 5s refresh interval
|
|
5235
|
+
// This ensures old dashboards with custom intervals stored in dashboardState are migrated
|
|
5236
|
+
currentState.refreshInterval = GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL;
|
|
5317
5237
|
return currentState;
|
|
5318
5238
|
}
|
|
5319
5239
|
setupDashboardSubscription() {
|
|
@@ -5875,8 +5795,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
5875
5795
|
*/
|
|
5876
5796
|
class GlobalContextLinkControlsComponent {
|
|
5877
5797
|
constructor() {
|
|
5878
|
-
|
|
5798
|
+
// Single output event - all controls toggle together (v2 pattern)
|
|
5879
5799
|
this.allLinksToggled = new EventEmitter();
|
|
5800
|
+
this.translateService = inject(TranslateService);
|
|
5880
5801
|
this._linkStates = {};
|
|
5881
5802
|
this.linkStatesSignal = signal({}, ...(ngDevMode ? [{ debugName: "linkStatesSignal" }] : []));
|
|
5882
5803
|
this.controlConfigsSignal = signal({}, ...(ngDevMode ? [{ debugName: "controlConfigsSignal" }] : []));
|
|
@@ -5893,8 +5814,6 @@ class GlobalContextLinkControlsComponent {
|
|
|
5893
5814
|
key,
|
|
5894
5815
|
isLinked,
|
|
5895
5816
|
cssClass: (controlConfigs[key]?.cssClass || 'default').trim(),
|
|
5896
|
-
unlinkedTooltip: controlConfigs[key]?.unlinkTooltip || '',
|
|
5897
|
-
linkedTooltip: controlConfigs[key]?.linkTooltip || '',
|
|
5898
5817
|
icon: controlConfigs[key]?.icon || '',
|
|
5899
5818
|
disabled: !!controlConfigs[key]?.disabled,
|
|
5900
5819
|
disabledTooltip: controlConfigs[key]?.disabledTooltip,
|
|
@@ -5910,9 +5829,22 @@ class GlobalContextLinkControlsComponent {
|
|
|
5910
5829
|
return controls.length > 0 && controls.some(control => control.isLinked);
|
|
5911
5830
|
}, ...(ngDevMode ? [{ debugName: "someControlsLinked" }] : []));
|
|
5912
5831
|
this.masterTooltipText = computed(() => {
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5832
|
+
const controls = this.visibleControls();
|
|
5833
|
+
const linkedControls = controls.filter(control => control.isLinked);
|
|
5834
|
+
const controlConfigs = this.controlConfigsSignal();
|
|
5835
|
+
const clickToToggleLabel = this.translateService.instant(gettext('(click to toggle)'));
|
|
5836
|
+
if (linkedControls.length === 0) {
|
|
5837
|
+
const usingWidgetCustomTimeSettingsLabel = this.translateService.instant(gettext('Using widget custom time settings'));
|
|
5838
|
+
return `${usingWidgetCustomTimeSettingsLabel}\n${clickToToggleLabel}`;
|
|
5839
|
+
}
|
|
5840
|
+
const linkedNames = linkedControls.map(control => {
|
|
5841
|
+
const config = controlConfigs[control.key];
|
|
5842
|
+
return this.translateService.instant(config?.label);
|
|
5843
|
+
});
|
|
5844
|
+
const formatter = new Intl.ListFormat(this.translateService.getCurrentLang()?.replace('_', '-'), { type: 'conjunction' });
|
|
5845
|
+
const linkedNamesList = formatter.format(linkedNames);
|
|
5846
|
+
const linkedToDashboardLabel = this.translateService.instant(gettext('Synced to dashboard:'));
|
|
5847
|
+
return `${linkedToDashboardLabel}\n${linkedNamesList}\n${clickToToggleLabel}`;
|
|
5916
5848
|
}, ...(ngDevMode ? [{ debugName: "masterTooltipText" }] : []));
|
|
5917
5849
|
}
|
|
5918
5850
|
set linkStates(value) {
|
|
@@ -5928,18 +5860,6 @@ class GlobalContextLinkControlsComponent {
|
|
|
5928
5860
|
ngOnInit() {
|
|
5929
5861
|
this.linkStatesSignal.set(this._linkStates);
|
|
5930
5862
|
}
|
|
5931
|
-
toggle(key) {
|
|
5932
|
-
if (!(key in this._linkStates))
|
|
5933
|
-
return;
|
|
5934
|
-
const config = this.controlConfigsSignal();
|
|
5935
|
-
if (config[key]?.disabled) {
|
|
5936
|
-
return;
|
|
5937
|
-
}
|
|
5938
|
-
const newLinkState = !this._linkStates[key];
|
|
5939
|
-
this._linkStates = { ...this._linkStates, [key]: newLinkState };
|
|
5940
|
-
this.linkStatesSignal.set(this._linkStates);
|
|
5941
|
-
this.linkToggled.emit({ key, isLinked: newLinkState });
|
|
5942
|
-
}
|
|
5943
5863
|
toggleAll() {
|
|
5944
5864
|
const newLinkState = !this.allControlsLinked();
|
|
5945
5865
|
const updatedLinkStates = { ...this._linkStates };
|
|
@@ -5955,56 +5875,35 @@ class GlobalContextLinkControlsComponent {
|
|
|
5955
5875
|
this.allLinksToggled.emit(newLinkState);
|
|
5956
5876
|
}
|
|
5957
5877
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GlobalContextLinkControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5958
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: GlobalContextLinkControlsComponent, isStandalone: true, selector: "c8y-global-context-link-controls", inputs: { linkStates: "linkStates", controlConfigs: "controlConfigs" }, outputs: {
|
|
5878
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: GlobalContextLinkControlsComponent, isStandalone: true, selector: "c8y-global-context-link-controls", inputs: { linkStates: "linkStates", controlConfigs: "controlConfigs" }, outputs: { allLinksToggled: "allLinksToggled" }, ngImport: i0, template: `
|
|
5959
5879
|
@if (showLinks()) {
|
|
5960
|
-
<
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
(click)="toggleAll()"
|
|
5972
|
-
>
|
|
5880
|
+
<button
|
|
5881
|
+
class="btn-icon-dot-set"
|
|
5882
|
+
[class.active]="someControlsLinked()"
|
|
5883
|
+
[attr.aria-label]="'Global context sync controls' | translate"
|
|
5884
|
+
[tooltip]="masterTooltipTemplate"
|
|
5885
|
+
delay="500"
|
|
5886
|
+
container="body"
|
|
5887
|
+
(click)="toggleAll()"
|
|
5888
|
+
data-cy="global-context-link--all"
|
|
5889
|
+
>
|
|
5890
|
+
<span class="btn-icon-dot__item default" [class.active]="allControlsLinked()">
|
|
5973
5891
|
<i [c8yIcon]="someControlsLinked() ? 'link' : 'unlink'"></i>
|
|
5974
|
-
</
|
|
5975
|
-
|
|
5976
|
-
{{ masterTooltipText() | translate }}
|
|
5977
|
-
</ng-template>
|
|
5978
|
-
<!-- Individual Link Toggles -->
|
|
5892
|
+
</span>
|
|
5893
|
+
<!-- Individual Link icons -->
|
|
5979
5894
|
@for (control of visibleControls(); track control.key) {
|
|
5980
|
-
<
|
|
5981
|
-
[class]="control.cssClass + ' btn-icon-
|
|
5895
|
+
<span
|
|
5896
|
+
[class]="control.cssClass + ' btn-icon-dot__item'"
|
|
5982
5897
|
[class.active]="control.isLinked"
|
|
5983
5898
|
[class.link-disabled]="control.disabled"
|
|
5984
5899
|
[class.link-auto-unlinked]="control.autoUnlinked"
|
|
5985
|
-
[tooltip]="tooltipTemplate"
|
|
5986
5900
|
[attr.data-cy]="'global-context-link--' + control.key"
|
|
5987
|
-
[delay]="500"
|
|
5988
|
-
[container]="'body'"
|
|
5989
|
-
[placement]="'top'"
|
|
5990
|
-
[disabled]="control.disabled"
|
|
5991
|
-
(click)="toggle(control.key)"
|
|
5992
5901
|
>
|
|
5993
5902
|
<i [c8yIcon]="control.icon"></i>
|
|
5994
|
-
</
|
|
5995
|
-
|
|
5996
|
-
<ng-template #tooltipTemplate>
|
|
5997
|
-
{{
|
|
5998
|
-
(control.disabled
|
|
5999
|
-
? control.disabledTooltip
|
|
6000
|
-
: control.isLinked
|
|
6001
|
-
? control.unlinkedTooltip
|
|
6002
|
-
: control.linkedTooltip
|
|
6003
|
-
) | translate
|
|
6004
|
-
}}
|
|
6005
|
-
</ng-template>
|
|
5903
|
+
</span>
|
|
6006
5904
|
}
|
|
6007
|
-
</
|
|
5905
|
+
</button>
|
|
5906
|
+
<ng-template #masterTooltipTemplate>{{ masterTooltipText() | translate }}</ng-template>
|
|
6008
5907
|
}
|
|
6009
5908
|
`, isInline: true, styles: [".btn-icon-dot[disabled]{cursor:not-allowed;opacity:.75}.btn-icon-dot.link-auto-unlinked,.btn-icon-dot.link-auto-unlinked:focus{box-shadow:0 0 0 2px var(--c8y-palette-status-danger);border-color:var(--c8y-palette-status-danger)}\n"], dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1.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: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6010
5909
|
}
|
|
@@ -6012,59 +5911,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
6012
5911
|
type: Component,
|
|
6013
5912
|
args: [{ selector: 'c8y-global-context-link-controls', standalone: true, imports: [IconDirective, TooltipModule, C8yTranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
6014
5913
|
@if (showLinks()) {
|
|
6015
|
-
<
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
(click)="toggleAll()"
|
|
6027
|
-
>
|
|
5914
|
+
<button
|
|
5915
|
+
class="btn-icon-dot-set"
|
|
5916
|
+
[class.active]="someControlsLinked()"
|
|
5917
|
+
[attr.aria-label]="'Global context sync controls' | translate"
|
|
5918
|
+
[tooltip]="masterTooltipTemplate"
|
|
5919
|
+
delay="500"
|
|
5920
|
+
container="body"
|
|
5921
|
+
(click)="toggleAll()"
|
|
5922
|
+
data-cy="global-context-link--all"
|
|
5923
|
+
>
|
|
5924
|
+
<span class="btn-icon-dot__item default" [class.active]="allControlsLinked()">
|
|
6028
5925
|
<i [c8yIcon]="someControlsLinked() ? 'link' : 'unlink'"></i>
|
|
6029
|
-
</
|
|
6030
|
-
|
|
6031
|
-
{{ masterTooltipText() | translate }}
|
|
6032
|
-
</ng-template>
|
|
6033
|
-
<!-- Individual Link Toggles -->
|
|
5926
|
+
</span>
|
|
5927
|
+
<!-- Individual Link icons -->
|
|
6034
5928
|
@for (control of visibleControls(); track control.key) {
|
|
6035
|
-
<
|
|
6036
|
-
[class]="control.cssClass + ' btn-icon-
|
|
5929
|
+
<span
|
|
5930
|
+
[class]="control.cssClass + ' btn-icon-dot__item'"
|
|
6037
5931
|
[class.active]="control.isLinked"
|
|
6038
5932
|
[class.link-disabled]="control.disabled"
|
|
6039
5933
|
[class.link-auto-unlinked]="control.autoUnlinked"
|
|
6040
|
-
[tooltip]="tooltipTemplate"
|
|
6041
5934
|
[attr.data-cy]="'global-context-link--' + control.key"
|
|
6042
|
-
[delay]="500"
|
|
6043
|
-
[container]="'body'"
|
|
6044
|
-
[placement]="'top'"
|
|
6045
|
-
[disabled]="control.disabled"
|
|
6046
|
-
(click)="toggle(control.key)"
|
|
6047
5935
|
>
|
|
6048
5936
|
<i [c8yIcon]="control.icon"></i>
|
|
6049
|
-
</
|
|
6050
|
-
|
|
6051
|
-
<ng-template #tooltipTemplate>
|
|
6052
|
-
{{
|
|
6053
|
-
(control.disabled
|
|
6054
|
-
? control.disabledTooltip
|
|
6055
|
-
: control.isLinked
|
|
6056
|
-
? control.unlinkedTooltip
|
|
6057
|
-
: control.linkedTooltip
|
|
6058
|
-
) | translate
|
|
6059
|
-
}}
|
|
6060
|
-
</ng-template>
|
|
5937
|
+
</span>
|
|
6061
5938
|
}
|
|
6062
|
-
</
|
|
5939
|
+
</button>
|
|
5940
|
+
<ng-template #masterTooltipTemplate>{{ masterTooltipText() | translate }}</ng-template>
|
|
6063
5941
|
}
|
|
6064
5942
|
`, styles: [".btn-icon-dot[disabled]{cursor:not-allowed;opacity:.75}.btn-icon-dot.link-auto-unlinked,.btn-icon-dot.link-auto-unlinked:focus{box-shadow:0 0 0 2px var(--c8y-palette-status-danger);border-color:var(--c8y-palette-status-danger)}\n"] }]
|
|
6065
|
-
}], propDecorators: {
|
|
6066
|
-
type: Output
|
|
6067
|
-
}], allLinksToggled: [{
|
|
5943
|
+
}], propDecorators: { allLinksToggled: [{
|
|
6068
5944
|
type: Output
|
|
6069
5945
|
}], linkStates: [{
|
|
6070
5946
|
type: Input
|
|
@@ -6159,8 +6035,12 @@ function toggleAllLinks(ctx, args) {
|
|
|
6159
6035
|
if (outcome.recalcGlobalAggregation) {
|
|
6160
6036
|
ctx.recalcGlobalAggregation();
|
|
6161
6037
|
}
|
|
6162
|
-
|
|
6163
|
-
if (
|
|
6038
|
+
// Only emit configuration updates if not suppressed
|
|
6039
|
+
if (!args.suppressEmit) {
|
|
6040
|
+
ctx.emitBasedOnFieldSources();
|
|
6041
|
+
}
|
|
6042
|
+
// Only emit refresh if not suppressed (when unlinking, data is already loaded)
|
|
6043
|
+
if (outcome.shouldEmitRefresh && !args.suppressRefresh) {
|
|
6164
6044
|
ctx.emitRefresh(null);
|
|
6165
6045
|
}
|
|
6166
6046
|
syncWithEffectiveConfig(ctx, outcome.snapshotKeys);
|
|
@@ -6277,7 +6157,7 @@ function buildControlLinkConfig(ctx, settings, linkStates) {
|
|
|
6277
6157
|
...baseConfig,
|
|
6278
6158
|
cssClass: baseCssClass || 'default',
|
|
6279
6159
|
disabled: !!disableReason,
|
|
6280
|
-
disabledTooltip: disableReason ?? baseConfig.
|
|
6160
|
+
disabledTooltip: disableReason ?? baseConfig.label,
|
|
6281
6161
|
...(baseAutoUnlinked !== undefined ? { autoUnlinked: baseAutoUnlinked } : {})
|
|
6282
6162
|
};
|
|
6283
6163
|
filteredStates[key] = linkStates?.[key] ?? false;
|
|
@@ -6953,6 +6833,10 @@ function sanitizeLocalState(state, configSignal, ensureDateTimeContext) {
|
|
|
6953
6833
|
delete snapshot.dateTimeContext;
|
|
6954
6834
|
else if (snapshot.dateTimeContext !== undefined)
|
|
6955
6835
|
snapshot.dateTimeContext = ensureDateTimeContext(snapshot.dateTimeContext);
|
|
6836
|
+
// Always enforce the fixed 5s refresh interval
|
|
6837
|
+
if (snapshot.refreshInterval !== undefined) {
|
|
6838
|
+
snapshot.refreshInterval = GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL;
|
|
6839
|
+
}
|
|
6956
6840
|
return snapshot;
|
|
6957
6841
|
}
|
|
6958
6842
|
function sanitizeGlobalState(state, configSignal, normalizeRefreshOption, getDefaultRefreshOption, ensureDateTimeContext) {
|
|
@@ -6960,6 +6844,10 @@ function sanitizeGlobalState(state, configSignal, normalizeRefreshOption, getDef
|
|
|
6960
6844
|
if (snapshot.dateTimeContext !== undefined)
|
|
6961
6845
|
snapshot.dateTimeContext = ensureDateTimeContext(snapshot.dateTimeContext);
|
|
6962
6846
|
snapshot.refreshOption = normalizeRefreshOption(snapshot.refreshOption ?? getDefaultRefreshOption());
|
|
6847
|
+
// Always enforce the fixed 5s refresh interval
|
|
6848
|
+
if (snapshot.refreshInterval !== undefined) {
|
|
6849
|
+
snapshot.refreshInterval = GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL;
|
|
6850
|
+
}
|
|
6963
6851
|
return snapshot;
|
|
6964
6852
|
}
|
|
6965
6853
|
function ensureDateTimeContext(context, configSignal) {
|
|
@@ -7156,6 +7044,8 @@ class SharedModeOrchestrator {
|
|
|
7156
7044
|
}
|
|
7157
7045
|
initConfig(config) {
|
|
7158
7046
|
const cloned = structuredClone(config ?? createDefaultGlobalContextState());
|
|
7047
|
+
// Always enforce the fixed 5s refresh interval
|
|
7048
|
+
cloned.refreshInterval = GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL;
|
|
7159
7049
|
this.configSignal.set(cloned);
|
|
7160
7050
|
}
|
|
7161
7051
|
initWidgetControls(controls) {
|
|
@@ -7211,36 +7101,24 @@ class SharedModeOrchestrator {
|
|
|
7211
7101
|
this.setGlobalState(normalizedGlobalState);
|
|
7212
7102
|
this.initWidgetControls(widgetControls);
|
|
7213
7103
|
const widgetDisplayMode = resolveWidgetDisplayMode(initialConfig, normalizedGlobalState);
|
|
7214
|
-
const contextDisplayMode = mapToContextDisplayMode(widgetDisplayMode);
|
|
7215
7104
|
const controls = widgetControls ?? this.widgetControlsSignal();
|
|
7216
|
-
const refreshOption = forcedRefreshOption ??
|
|
7217
|
-
normalizedGlobalState.refreshOption ??
|
|
7218
|
-
initialConfig?.refreshOption ??
|
|
7219
|
-
this.getDefaultRefreshOption();
|
|
7220
|
-
const baseLinks = isDashboard && controls
|
|
7221
|
-
? (this.widgetControlService.getDefaultLinksFromControls(controls, contextDisplayMode, refreshOption) ?? {})
|
|
7222
|
-
: {};
|
|
7223
7105
|
const localState = initialConfig ? { ...initialConfig } : {};
|
|
7224
7106
|
const fieldSources = {};
|
|
7225
7107
|
const globalSnapshot = structuredClone(normalizedGlobalState ?? {});
|
|
7226
|
-
|
|
7108
|
+
// Simple rule: Dashboard mode → ALL sources global, Non-dashboard → ALL sources local
|
|
7109
|
+
const defaultSource = isDashboard ? FIELD_SOURCE_GLOBAL : FIELD_SOURCE_LOCAL;
|
|
7227
7110
|
Object.keys(localState).forEach(key => {
|
|
7228
|
-
fieldSources[key] =
|
|
7111
|
+
fieldSources[key] = defaultSource;
|
|
7229
7112
|
});
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7236
|
-
|
|
7237
|
-
if (!fieldSources.refreshOption) {
|
|
7238
|
-
fieldSources.refreshOption = FIELD_SOURCE_GLOBAL;
|
|
7239
|
-
}
|
|
7240
|
-
if (fieldSources.dateTimeContext === FIELD_SOURCE_LOCAL) {
|
|
7241
|
-
fieldSources.refreshOption = FIELD_SOURCE_LOCAL;
|
|
7113
|
+
// Ensure all supported controls have field sources
|
|
7114
|
+
if (controls?.supports) {
|
|
7115
|
+
controls.supports.forEach(field => {
|
|
7116
|
+
if (!fieldSources[field]) {
|
|
7117
|
+
fieldSources[field] = defaultSource;
|
|
7118
|
+
}
|
|
7119
|
+
});
|
|
7242
7120
|
}
|
|
7243
|
-
// ALWAYS
|
|
7121
|
+
// Source is ALWAYS global (tracks event origin)
|
|
7244
7122
|
fieldSources.source = FIELD_SOURCE_GLOBAL;
|
|
7245
7123
|
this.applyInitialModeAdjustments({
|
|
7246
7124
|
isDashboard,
|
|
@@ -7262,8 +7140,15 @@ class SharedModeOrchestrator {
|
|
|
7262
7140
|
const localState = this.localStateSignal();
|
|
7263
7141
|
const globalState = this.globalStateSignal();
|
|
7264
7142
|
const fieldSources = this.fieldSourcesSignal();
|
|
7143
|
+
// Normalize baseConfig to enforce fixed 5s refresh interval
|
|
7144
|
+
const normalizedBaseConfig = baseConfig
|
|
7145
|
+
? {
|
|
7146
|
+
...baseConfig,
|
|
7147
|
+
refreshInterval: GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL
|
|
7148
|
+
}
|
|
7149
|
+
: baseConfig;
|
|
7265
7150
|
const composed = composeEffectiveConfig({
|
|
7266
|
-
baseConfig,
|
|
7151
|
+
baseConfig: normalizedBaseConfig,
|
|
7267
7152
|
localState,
|
|
7268
7153
|
globalState,
|
|
7269
7154
|
fieldSources
|
|
@@ -7832,10 +7717,21 @@ class GlobalContextInlineOrchestratorService {
|
|
|
7832
7717
|
};
|
|
7833
7718
|
this.live.initializeStateAndSources(liveParams);
|
|
7834
7719
|
this.history.initializeStateAndSources(historyParams);
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7720
|
+
// After initialization, sync the fresh states back to snapshots
|
|
7721
|
+
// (applyInitialModeAdjustments may have generated fresh dates in local state)
|
|
7722
|
+
// Use computeEffectiveConfig to merge local+global states
|
|
7723
|
+
const liveEffective = this.live.computeEffectiveConfig(params.initialConfig);
|
|
7724
|
+
const historyEffective = this.history.computeEffectiveConfig(params.initialConfig);
|
|
7725
|
+
this.updateModeSnapshot(REFRESH_OPTION.LIVE, liveEffective);
|
|
7726
|
+
this.updateModeSnapshot(REFRESH_OPTION.HISTORY, historyEffective);
|
|
7727
|
+
// For standalone mode, use widget's refreshOption, not global state
|
|
7728
|
+
// For dashboard mode, use global state's refreshOption
|
|
7729
|
+
const desiredMode = params.isDashboard
|
|
7730
|
+
? (params.forcedRefreshOption ??
|
|
7731
|
+
baseGlobalState.refreshOption ??
|
|
7732
|
+
params.initialConfig?.refreshOption ??
|
|
7733
|
+
this.activeMode)
|
|
7734
|
+
: (params.forcedRefreshOption ?? params.initialConfig?.refreshOption ?? this.activeMode);
|
|
7839
7735
|
this.ensureMode(desiredMode);
|
|
7840
7736
|
}
|
|
7841
7737
|
handleFormChange(context) {
|
|
@@ -7861,6 +7757,15 @@ class GlobalContextInlineOrchestratorService {
|
|
|
7861
7757
|
this.getActive().executeHandler(context);
|
|
7862
7758
|
}
|
|
7863
7759
|
processRefresh(params) {
|
|
7760
|
+
// Choose orchestrator based on mode:
|
|
7761
|
+
// - Dashboard mode: use global state's refreshOption
|
|
7762
|
+
// - Standalone mode: use effective config's refreshOption (local state)
|
|
7763
|
+
const isDashboard = this.initSnapshot?.isDashboard ?? false;
|
|
7764
|
+
const effectiveRefreshOption = isDashboard
|
|
7765
|
+
? (this.getGlobalState().refreshOption ?? this.activeMode)
|
|
7766
|
+
: (this.getActive().computeEffectiveConfig(this.initSnapshot?.initialConfig ?? null)
|
|
7767
|
+
.refreshOption ?? this.activeMode);
|
|
7768
|
+
this.ensureMode(effectiveRefreshOption);
|
|
7864
7769
|
return this.getActive().processRefresh(params);
|
|
7865
7770
|
}
|
|
7866
7771
|
applyRefreshOptionChange(params) {
|
|
@@ -7942,10 +7847,17 @@ class GlobalContextInlineOrchestratorService {
|
|
|
7942
7847
|
if (!this.initSnapshot) {
|
|
7943
7848
|
return;
|
|
7944
7849
|
}
|
|
7850
|
+
const isDashboard = this.initSnapshot.isDashboard;
|
|
7851
|
+
const snapshot = this.modeSnapshots[this.activeMode] ?? {};
|
|
7852
|
+
// For standalone mode, use the snapshot as initialConfig so fresh dates are preserved
|
|
7853
|
+
// For dashboard mode, use original initialConfig and snapshot goes to globalState
|
|
7854
|
+
const effectiveInitialConfig = isDashboard
|
|
7855
|
+
? this.initSnapshot.initialConfig
|
|
7856
|
+
: snapshot;
|
|
7945
7857
|
const params = {
|
|
7946
|
-
initialConfig:
|
|
7947
|
-
globalState: structuredClone(
|
|
7948
|
-
isDashboard
|
|
7858
|
+
initialConfig: effectiveInitialConfig,
|
|
7859
|
+
globalState: structuredClone(snapshot),
|
|
7860
|
+
isDashboard,
|
|
7949
7861
|
widgetControls: this.initSnapshot.widgetControls,
|
|
7950
7862
|
generateFreshDateTime: this.initSnapshot.generateFreshDateTime,
|
|
7951
7863
|
forcedRefreshOption: this.activeMode
|
|
@@ -8136,16 +8048,59 @@ class GlobalContextInlineComponent {
|
|
|
8136
8048
|
handleLinkToggle(event, options) {
|
|
8137
8049
|
return handleLinkToggle(this.getLinkContext(), event, options);
|
|
8138
8050
|
}
|
|
8139
|
-
toggleAllLinks(isLinked) {
|
|
8051
|
+
toggleAllLinks(isLinked, suppressRefresh, suppressEmit) {
|
|
8140
8052
|
const supportedLinks = Object.keys(this.controlLinkStatus() || {});
|
|
8141
8053
|
if (!supportedLinks.length) {
|
|
8142
8054
|
return;
|
|
8143
8055
|
}
|
|
8056
|
+
// When unlinking: suppress both refresh and emit (data is already loaded)
|
|
8057
|
+
// When linking: allow both refresh and emit unless explicitly suppressed
|
|
8058
|
+
const shouldSuppressRefresh = suppressRefresh ?? !isLinked;
|
|
8059
|
+
const shouldSuppressEmit = suppressEmit ?? !isLinked;
|
|
8144
8060
|
toggleAllLinks(this.getLinkContext(), {
|
|
8145
8061
|
keys: supportedLinks,
|
|
8146
|
-
isLinked
|
|
8062
|
+
isLinked,
|
|
8063
|
+
suppressRefresh: shouldSuppressRefresh,
|
|
8064
|
+
suppressEmit: shouldSuppressEmit
|
|
8147
8065
|
});
|
|
8148
8066
|
}
|
|
8067
|
+
updateDateTimeContext(dateTimeContext) {
|
|
8068
|
+
this.orchestrator.updateLocalState(state => ({
|
|
8069
|
+
...state,
|
|
8070
|
+
dateTimeContext: structuredClone(dateTimeContext)
|
|
8071
|
+
}));
|
|
8072
|
+
const dateTimeControl = this.form?.get('dateTimeContext');
|
|
8073
|
+
if (dateTimeControl) {
|
|
8074
|
+
dateTimeControl.setValue(structuredClone(dateTimeContext), { emitEvent: false });
|
|
8075
|
+
}
|
|
8076
|
+
}
|
|
8077
|
+
/**
|
|
8078
|
+
* Pause auto-refresh: sets isAutoRefreshEnabled to false and unlinks all controls.
|
|
8079
|
+
* This stops the auto-refresh timer and prevents the widget from receiving
|
|
8080
|
+
* updates from the global context.
|
|
8081
|
+
*
|
|
8082
|
+
* NOTE: Does NOT trigger any refresh or emit - data is already loaded, no updates needed.
|
|
8083
|
+
*/
|
|
8084
|
+
pauseAutoRefresh() {
|
|
8085
|
+
// Step 1: Unlink all controls without any emissions (data already loaded)
|
|
8086
|
+
this.toggleAllLinks(false, // isLinked = false
|
|
8087
|
+
true, // suppressRefresh = true
|
|
8088
|
+
true // suppressEmit = true
|
|
8089
|
+
);
|
|
8090
|
+
// Step 2: Set isAutoRefreshEnabled to false without emitting events
|
|
8091
|
+
this.setAutoRefreshEnabled(false);
|
|
8092
|
+
}
|
|
8093
|
+
/**
|
|
8094
|
+
* Resume auto-refresh: sets isAutoRefreshEnabled to true and links all controls.
|
|
8095
|
+
* This starts the auto-refresh timer and allows the widget to receive
|
|
8096
|
+
* updates from the global context.
|
|
8097
|
+
*
|
|
8098
|
+
* NOTE: Triggers emissions and refresh to sync with the current global context state.
|
|
8099
|
+
*/
|
|
8100
|
+
resumeAutoRefresh() {
|
|
8101
|
+
this.toggleAllLinks(true, false, false);
|
|
8102
|
+
this.setAutoRefreshEnabled(true);
|
|
8103
|
+
}
|
|
8149
8104
|
triggerHandler(handlerName, configOverride) {
|
|
8150
8105
|
const handler = this.widgetControls()?.stateHandlers?.[handlerName];
|
|
8151
8106
|
const previousRefresh = this.effectiveConfig().refreshOption;
|
|
@@ -8173,6 +8128,12 @@ class GlobalContextInlineComponent {
|
|
|
8173
8128
|
this.refresh.emit(null);
|
|
8174
8129
|
}
|
|
8175
8130
|
}
|
|
8131
|
+
setAutoRefreshEnabled(enabled) {
|
|
8132
|
+
const autoRefreshControl = this.form?.get('isAutoRefreshEnabled');
|
|
8133
|
+
if (autoRefreshControl && autoRefreshControl.value !== enabled) {
|
|
8134
|
+
autoRefreshControl.setValue(enabled, { emitEvent: false });
|
|
8135
|
+
}
|
|
8136
|
+
}
|
|
8176
8137
|
mapToWidgetDisplayMode(mode) {
|
|
8177
8138
|
switch (mode) {
|
|
8178
8139
|
case GLOBAL_CONTEXT_DISPLAY_MODE.CONFIG:
|
|
@@ -8499,7 +8460,7 @@ class GlobalContextInlineComponent {
|
|
|
8499
8460
|
};
|
|
8500
8461
|
}
|
|
8501
8462
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GlobalContextInlineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8502
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: GlobalContextInlineComponent, isStandalone: true, selector: "c8y-global-context-inline", inputs: { widgetControls: { classPropertyName: "widgetControls", publicName: "widgetControls", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, dashboardChildForLegacy: { classPropertyName: "dashboardChildForLegacy", publicName: "dashboardChildForLegacy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { refresh: "refresh", globalContextChange: "globalContextChange" }, providers: [GlobalContextInlineOrchestratorService], viewQueries: [{ propertyName: "headerTemplateRef", first: true, predicate: ["headerContent"], descendants: true, read: TemplateRef, static: true }], exportAs: ["globalContextInline"], ngImport: i0, template: "<ng-template #headerContent>\n @let linkModel = linkDisplayModel();\n <ng-content select=\"#header\"></ng-content>\n\n @if (shouldShowHeaderLinks()) {\n <c8y-global-context-link-controls\n [linkStates]=\"linkModel.linkStates\"\n [controlConfigs]=\"linkModel.controlConfig\"\n (
|
|
8463
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: GlobalContextInlineComponent, isStandalone: true, selector: "c8y-global-context-inline", inputs: { widgetControls: { classPropertyName: "widgetControls", publicName: "widgetControls", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, dashboardChildForLegacy: { classPropertyName: "dashboardChildForLegacy", publicName: "dashboardChildForLegacy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { refresh: "refresh", globalContextChange: "globalContextChange" }, providers: [GlobalContextInlineOrchestratorService], viewQueries: [{ propertyName: "headerTemplateRef", first: true, predicate: ["headerContent"], descendants: true, read: TemplateRef, static: true }], exportAs: ["globalContextInline"], ngImport: i0, template: "<ng-template #headerContent>\n @let linkModel = linkDisplayModel();\n <ng-content select=\"#header\"></ng-content>\n\n @if (shouldShowHeaderLinks()) {\n <c8y-global-context-link-controls\n [linkStates]=\"linkModel.linkStates\"\n [controlConfigs]=\"linkModel.controlConfig\"\n (allLinksToggled)=\"toggleAllLinks($event)\"\n ></c8y-global-context-link-controls>\n }\n</ng-template>\n\n<ng-template #inlineContent>\n @let settings = inlineSettings();\n @let linkModel = linkDisplayModel();\n\n @if (form && settings) {\n <form\n class=\"d-flex gap-16 p-l-16 p-r-16 p-b-8 inner-scroll\"\n [formGroup]=\"form\"\n >\n <div class=\"input-group w-auto input-group-sm\">\n @if (settings.showAggregation) {\n <c8y-aggregation-picker\n data-cy=\"global-inline-date-context--Aggregation-display\"\n [disabledAggregations]=\"getDisabledAggregations()\"\n formControlName=\"aggregation\"\n [resetToDefault]=\"true\"\n ></c8y-aggregation-picker>\n }\n\n @if (settings.showAutoRefresh) {\n <c8y-auto-refresh-control\n [isLoading]=\"isLoading()\"\n [disableCounter]=\"shouldDisableCounter\"\n formControlName=\"isAutoRefreshEnabled\"\n [autoRefreshSeconds]=\"getAutoRefreshSeconds()\"\n [isAutoRefreshConnected]=\"linkModel.linkStates.isAutoRefreshEnabled ?? false\"\n (refresh)=\"onLocalRefreshTrigger()\"\n ></c8y-auto-refresh-control>\n }\n\n @if (settings.showTimeContext) {\n @let isHistoryMode = form.get('refreshOption')?.value === REFRESH_OPTION.HISTORY;\n <c8y-date-time-context-picker\n style=\"margin-left: -1px\"\n formControlName=\"dateTimeContext\"\n [shouldDisableInterval]=\"getIntervalDisableConfig()\"\n [config]=\"\n isHistoryMode\n ? { showDateTo: true, showDateFrom: true }\n : { showDateTo: false, showDateFrom: true }\n \"\n ></c8y-date-time-context-picker>\n }\n\n @if (settings.showRefresh) {\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Refresh' | translate\"\n [tooltip]=\"'Refresh' | translate\"\n placement=\"bottom\"\n container=\"body\"\n type=\"button\"\n data-cy=\"global-inline-date-context--reload-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n [disabled]=\"isLoading()\"\n (click)=\"refresh.emit(null)\"\n >\n <i\n [class.icon-spin]=\"isLoading()\"\n [c8yIcon]=\"'refresh'\"\n ></i>\n </button>\n </div>\n }\n </div>\n </form>\n }\n\n <ng-content select=\"#body\"></ng-content>\n</ng-template>\n\n@switch (effectiveConfig().displayMode) {\n @case (GLOBAL_CONTEXT_DISPLAY_MODE.CONFIG) {\n <ng-container [ngTemplateOutlet]=\"inlineContent\"></ng-container>\n }\n @case (GLOBAL_CONTEXT_DISPLAY_MODE.VIEW_AND_CONFIG) {\n <ng-container [ngTemplateOutlet]=\"headerContent\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"inlineContent\"></ng-container>\n }\n @default {\n @if (shouldRenderHeaderInline()) {\n <ng-container [ngTemplateOutlet]=\"headerContent\"></ng-container>\n }\n <ng-container [ngTemplateOutlet]=\"inlineContent\"></ng-container>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: GlobalContextLinkControlsComponent, selector: "c8y-global-context-link-controls", inputs: ["linkStates", "controlConfigs"], outputs: ["allLinksToggled"] }, { kind: "component", type: AggregationPickerComponent, selector: "c8y-aggregation-picker", inputs: ["disabledAggregations", "resetToDefault", "layout"] }, { kind: "component", type: AutoRefreshControlComponent, selector: "c8y-auto-refresh-control", inputs: ["isAutoRefreshConnected", "autoRefreshSeconds", "disableCounter", "isEnabled", "isLoading"], outputs: ["loadingChange", "refresh"] }, { kind: "component", type: DateTimeContextPickerComponent, selector: "c8y-date-time-context-picker", inputs: ["disabled", "shouldDisableInterval", "config"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1.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: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8503
8464
|
}
|
|
8504
8465
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GlobalContextInlineComponent, decorators: [{
|
|
8505
8466
|
type: Component,
|
|
@@ -8508,13 +8469,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
8508
8469
|
GlobalContextLinkControlsComponent,
|
|
8509
8470
|
AggregationPickerComponent,
|
|
8510
8471
|
AutoRefreshControlComponent,
|
|
8511
|
-
AutoRefreshSelectControlComponent,
|
|
8512
8472
|
DateTimeContextPickerComponent,
|
|
8513
8473
|
IconDirective,
|
|
8514
8474
|
C8yTranslatePipe,
|
|
8515
8475
|
TooltipModule,
|
|
8516
8476
|
NgTemplateOutlet
|
|
8517
|
-
], selector: 'c8y-global-context-inline', exportAs: 'globalContextInline', providers: [GlobalContextInlineOrchestratorService], template: "<ng-template #headerContent>\n @let linkModel = linkDisplayModel();\n <ng-content select=\"#header\"></ng-content>\n\n @if (shouldShowHeaderLinks()) {\n <c8y-global-context-link-controls\n [linkStates]=\"linkModel.linkStates\"\n [controlConfigs]=\"linkModel.controlConfig\"\n (
|
|
8477
|
+
], selector: 'c8y-global-context-inline', exportAs: 'globalContextInline', providers: [GlobalContextInlineOrchestratorService], template: "<ng-template #headerContent>\n @let linkModel = linkDisplayModel();\n <ng-content select=\"#header\"></ng-content>\n\n @if (shouldShowHeaderLinks()) {\n <c8y-global-context-link-controls\n [linkStates]=\"linkModel.linkStates\"\n [controlConfigs]=\"linkModel.controlConfig\"\n (allLinksToggled)=\"toggleAllLinks($event)\"\n ></c8y-global-context-link-controls>\n }\n</ng-template>\n\n<ng-template #inlineContent>\n @let settings = inlineSettings();\n @let linkModel = linkDisplayModel();\n\n @if (form && settings) {\n <form\n class=\"d-flex gap-16 p-l-16 p-r-16 p-b-8 inner-scroll\"\n [formGroup]=\"form\"\n >\n <div class=\"input-group w-auto input-group-sm\">\n @if (settings.showAggregation) {\n <c8y-aggregation-picker\n data-cy=\"global-inline-date-context--Aggregation-display\"\n [disabledAggregations]=\"getDisabledAggregations()\"\n formControlName=\"aggregation\"\n [resetToDefault]=\"true\"\n ></c8y-aggregation-picker>\n }\n\n @if (settings.showAutoRefresh) {\n <c8y-auto-refresh-control\n [isLoading]=\"isLoading()\"\n [disableCounter]=\"shouldDisableCounter\"\n formControlName=\"isAutoRefreshEnabled\"\n [autoRefreshSeconds]=\"getAutoRefreshSeconds()\"\n [isAutoRefreshConnected]=\"linkModel.linkStates.isAutoRefreshEnabled ?? false\"\n (refresh)=\"onLocalRefreshTrigger()\"\n ></c8y-auto-refresh-control>\n }\n\n @if (settings.showTimeContext) {\n @let isHistoryMode = form.get('refreshOption')?.value === REFRESH_OPTION.HISTORY;\n <c8y-date-time-context-picker\n style=\"margin-left: -1px\"\n formControlName=\"dateTimeContext\"\n [shouldDisableInterval]=\"getIntervalDisableConfig()\"\n [config]=\"\n isHistoryMode\n ? { showDateTo: true, showDateFrom: true }\n : { showDateTo: false, showDateFrom: true }\n \"\n ></c8y-date-time-context-picker>\n }\n\n @if (settings.showRefresh) {\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Refresh' | translate\"\n [tooltip]=\"'Refresh' | translate\"\n placement=\"bottom\"\n container=\"body\"\n type=\"button\"\n data-cy=\"global-inline-date-context--reload-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n [disabled]=\"isLoading()\"\n (click)=\"refresh.emit(null)\"\n >\n <i\n [class.icon-spin]=\"isLoading()\"\n [c8yIcon]=\"'refresh'\"\n ></i>\n </button>\n </div>\n }\n </div>\n </form>\n }\n\n <ng-content select=\"#body\"></ng-content>\n</ng-template>\n\n@switch (effectiveConfig().displayMode) {\n @case (GLOBAL_CONTEXT_DISPLAY_MODE.CONFIG) {\n <ng-container [ngTemplateOutlet]=\"inlineContent\"></ng-container>\n }\n @case (GLOBAL_CONTEXT_DISPLAY_MODE.VIEW_AND_CONFIG) {\n <ng-container [ngTemplateOutlet]=\"headerContent\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"inlineContent\"></ng-container>\n }\n @default {\n @if (shouldRenderHeaderInline()) {\n <ng-container [ngTemplateOutlet]=\"headerContent\"></ng-container>\n }\n <ng-container [ngTemplateOutlet]=\"inlineContent\"></ng-container>\n }\n}\n" }]
|
|
8518
8478
|
}], ctorParameters: () => [], propDecorators: { widgetControls: [{ type: i0.Input, args: [{ isSignal: true, alias: "widgetControls", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], dashboardChildForLegacy: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardChildForLegacy", required: false }] }], refresh: [{ type: i0.Output, args: ["refresh"] }], globalContextChange: [{ type: i0.Output, args: ["globalContextChange"] }], headerTemplateRef: [{
|
|
8519
8479
|
type: ViewChild,
|
|
8520
8480
|
args: ['headerContent', { static: true, read: TemplateRef }]
|
|
@@ -8715,7 +8675,9 @@ class GlobalContextConfigStoreService {
|
|
|
8715
8675
|
if (!prev) {
|
|
8716
8676
|
return;
|
|
8717
8677
|
}
|
|
8718
|
-
|
|
8678
|
+
// Filter out refreshInterval from changes - it's fixed at 5s and should not be user-modifiable
|
|
8679
|
+
const { refreshInterval: _, ...allowedChanges } = changes;
|
|
8680
|
+
let next = { ...prev, ...allowedChanges };
|
|
8719
8681
|
if (!isLive) {
|
|
8720
8682
|
next = this.enforceHistory(next);
|
|
8721
8683
|
}
|
|
@@ -8723,6 +8685,8 @@ class GlobalContextConfigStoreService {
|
|
|
8723
8685
|
// Live must not carry aggregation
|
|
8724
8686
|
next.aggregation = null;
|
|
8725
8687
|
}
|
|
8688
|
+
// Always enforce the fixed refresh interval
|
|
8689
|
+
next.refreshInterval = GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL;
|
|
8726
8690
|
this.setIfChanged(target, next);
|
|
8727
8691
|
}
|
|
8728
8692
|
/**
|
|
@@ -8798,6 +8762,8 @@ class GlobalContextConfigStoreService {
|
|
|
8798
8762
|
if (norm.refreshOption === REFRESH_OPTION.LIVE) {
|
|
8799
8763
|
norm.aggregation = null;
|
|
8800
8764
|
}
|
|
8765
|
+
// Always enforce the fixed 5s refresh interval
|
|
8766
|
+
norm.refreshInterval = GLOBAL_CONTEXT_DEFAULTS.REFRESH_INTERVAL;
|
|
8801
8767
|
if (norm.refreshOption === REFRESH_OPTION.HISTORY) {
|
|
8802
8768
|
return this.enforceHistory(norm);
|
|
8803
8769
|
}
|
|
@@ -9185,7 +9151,6 @@ class GlobalContextWidgetConfigComponent {
|
|
|
9185
9151
|
effect(() => {
|
|
9186
9152
|
const cfg = this.configInput();
|
|
9187
9153
|
// Always ensure auto-refresh is enabled in the widget config
|
|
9188
|
-
cfg.isAutoRefreshEnabled = true;
|
|
9189
9154
|
const next = cfg?.displayMode ?? GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD;
|
|
9190
9155
|
const current = this.form?.get('displayMode')?.value;
|
|
9191
9156
|
if (current !== next && this.form) {
|
|
@@ -9631,7 +9596,7 @@ class PreviewControlsComponent {
|
|
|
9631
9596
|
this.config.displayMode = GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD;
|
|
9632
9597
|
}
|
|
9633
9598
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PreviewControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9634
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PreviewControlsComponent, isStandalone: true, selector: "c8y-preview-controls", inputs: { widgetControls: "widgetControls", config: "config" }, ngImport: i0, template: "<!-- Main Controls -->\n@let isConfigMode = config?.displayMode === GLOBAL_CONTEXT_DISPLAY_MODE.CONFIG;\n@let settings = inlineControlsSettings$ | async;\n\n@if (form && settings) {\n <form\n class=\"d-flex gap-16 p-l-16 p-r-16 p-b-8 inner-scroll\"\n [formGroup]=\"form\"\n >\n <!-- Control Group Container -->\n <div class=\"input-group w-auto\">\n <!-- Aggregation Picker -->\n @if (settings.showAggregation) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [resetToDefault]=\"true\"\n ></c8y-aggregation-picker>\n }\n\n <!-- Auto Refresh Controls -->\n @if (settings.showAutoRefresh) {\n <!-- Auto Refresh Toggle -->\n <c8y-auto-refresh-control\n [isLoading]=\"isLoading\"\n [disableCounter]=\"shouldDisableCounter\"\n formControlName=\"isAutoRefreshEnabled\"\n [autoRefreshSeconds]=\"form.get('refreshInterval')?.value\"\n ></c8y-auto-refresh-control>\n
|
|
9599
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PreviewControlsComponent, isStandalone: true, selector: "c8y-preview-controls", inputs: { widgetControls: "widgetControls", config: "config" }, ngImport: i0, template: "<!-- Main Controls -->\n@let isConfigMode = config?.displayMode === GLOBAL_CONTEXT_DISPLAY_MODE.CONFIG;\n@let settings = inlineControlsSettings$ | async;\n\n@if (form && settings) {\n <form\n class=\"d-flex gap-16 p-l-16 p-r-16 p-b-8 inner-scroll\"\n [formGroup]=\"form\"\n >\n <!-- Control Group Container -->\n <div class=\"input-group w-auto\">\n <!-- Aggregation Picker -->\n @if (settings.showAggregation) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [resetToDefault]=\"true\"\n ></c8y-aggregation-picker>\n }\n\n <!-- Auto Refresh Controls -->\n @if (settings.showAutoRefresh) {\n <!-- Auto Refresh Toggle -->\n <c8y-auto-refresh-control\n [isLoading]=\"isLoading\"\n [disableCounter]=\"shouldDisableCounter\"\n formControlName=\"isAutoRefreshEnabled\"\n [autoRefreshSeconds]=\"form.get('refreshInterval')?.value\"\n ></c8y-auto-refresh-control>\n }\n\n @if (settings.showTimeContext) {\n @let isHistoryMode = form.get('refreshOption')?.value === REFRESH_OPTION.HISTORY;\n @let configValue =\n isHistoryMode\n ? {\n showDateTo: true,\n showDateFrom: true\n }\n : {\n showDateTo: false,\n showDateFrom: true\n };\n <c8y-date-time-context-picker\n style=\"margin-left: -1px\"\n formControlName=\"dateTimeContext\"\n [shouldDisableInterval]=\"shouldDisableCustomInterval\"\n [config]=\"configValue\"\n ></c8y-date-time-context-picker>\n }\n\n <!-- Manual Refresh Button -->\n @if (settings.showRefresh) {\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Refresh' | translate\"\n [tooltip]=\"'Refresh' | translate\"\n placement=\"bottom\"\n type=\"button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n [disabled]=\"isLoading\"\n >\n <i\n [class.icon-spin]=\"isLoading\"\n [c8yIcon]=\"'refresh'\"\n ></i>\n </button>\n </div>\n }\n </div>\n </form>\n}\n", styles: [":host{position:relative;display:block;cursor:not-allowed}:host form{position:relative;pointer-events:none;-webkit-user-select:none;user-select:none}:host form:after{content:\"\";position:absolute;inset:0;background:#ffffff0d;z-index:1;pointer-events:none}:host form button,:host form input,:host form select,:host form .dropdown-toggle,:host form .btn{cursor:not-allowed!important;opacity:.85}:host form *{pointer-events:none!important;-webkit-user-select:none!important;user-select:none!important}\n"], dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: DateTimeContextPickerComponent, selector: "c8y-date-time-context-picker", inputs: ["disabled", "shouldDisableInterval", "config"] }, { kind: "component", type: AggregationPickerComponent, selector: "c8y-aggregation-picker", inputs: ["disabledAggregations", "resetToDefault", "layout"] }, { kind: "component", type: AutoRefreshControlComponent, selector: "c8y-auto-refresh-control", inputs: ["isAutoRefreshConnected", "autoRefreshSeconds", "disableCounter", "isEnabled", "isLoading"], outputs: ["loadingChange", "refresh"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1.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: AsyncPipe, name: "async" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9635
9600
|
}
|
|
9636
9601
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PreviewControlsComponent, decorators: [{
|
|
9637
9602
|
type: Component,
|
|
@@ -9642,10 +9607,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
9642
9607
|
DateTimeContextPickerComponent,
|
|
9643
9608
|
AggregationPickerComponent,
|
|
9644
9609
|
AutoRefreshControlComponent,
|
|
9645
|
-
AutoRefreshSelectControlComponent,
|
|
9646
9610
|
TooltipModule,
|
|
9647
9611
|
C8yTranslatePipe
|
|
9648
|
-
], selector: 'c8y-preview-controls', template: "<!-- Main Controls -->\n@let isConfigMode = config?.displayMode === GLOBAL_CONTEXT_DISPLAY_MODE.CONFIG;\n@let settings = inlineControlsSettings$ | async;\n\n@if (form && settings) {\n <form\n class=\"d-flex gap-16 p-l-16 p-r-16 p-b-8 inner-scroll\"\n [formGroup]=\"form\"\n >\n <!-- Control Group Container -->\n <div class=\"input-group w-auto\">\n <!-- Aggregation Picker -->\n @if (settings.showAggregation) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [resetToDefault]=\"true\"\n ></c8y-aggregation-picker>\n }\n\n <!-- Auto Refresh Controls -->\n @if (settings.showAutoRefresh) {\n <!-- Auto Refresh Toggle -->\n <c8y-auto-refresh-control\n [isLoading]=\"isLoading\"\n [disableCounter]=\"shouldDisableCounter\"\n formControlName=\"isAutoRefreshEnabled\"\n [autoRefreshSeconds]=\"form.get('refreshInterval')?.value\"\n ></c8y-auto-refresh-control>\n
|
|
9612
|
+
], selector: 'c8y-preview-controls', template: "<!-- Main Controls -->\n@let isConfigMode = config?.displayMode === GLOBAL_CONTEXT_DISPLAY_MODE.CONFIG;\n@let settings = inlineControlsSettings$ | async;\n\n@if (form && settings) {\n <form\n class=\"d-flex gap-16 p-l-16 p-r-16 p-b-8 inner-scroll\"\n [formGroup]=\"form\"\n >\n <!-- Control Group Container -->\n <div class=\"input-group w-auto\">\n <!-- Aggregation Picker -->\n @if (settings.showAggregation) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [resetToDefault]=\"true\"\n ></c8y-aggregation-picker>\n }\n\n <!-- Auto Refresh Controls -->\n @if (settings.showAutoRefresh) {\n <!-- Auto Refresh Toggle -->\n <c8y-auto-refresh-control\n [isLoading]=\"isLoading\"\n [disableCounter]=\"shouldDisableCounter\"\n formControlName=\"isAutoRefreshEnabled\"\n [autoRefreshSeconds]=\"form.get('refreshInterval')?.value\"\n ></c8y-auto-refresh-control>\n }\n\n @if (settings.showTimeContext) {\n @let isHistoryMode = form.get('refreshOption')?.value === REFRESH_OPTION.HISTORY;\n @let configValue =\n isHistoryMode\n ? {\n showDateTo: true,\n showDateFrom: true\n }\n : {\n showDateTo: false,\n showDateFrom: true\n };\n <c8y-date-time-context-picker\n style=\"margin-left: -1px\"\n formControlName=\"dateTimeContext\"\n [shouldDisableInterval]=\"shouldDisableCustomInterval\"\n [config]=\"configValue\"\n ></c8y-date-time-context-picker>\n }\n\n <!-- Manual Refresh Button -->\n @if (settings.showRefresh) {\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Refresh' | translate\"\n [tooltip]=\"'Refresh' | translate\"\n placement=\"bottom\"\n type=\"button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n [disabled]=\"isLoading\"\n >\n <i\n [class.icon-spin]=\"isLoading\"\n [c8yIcon]=\"'refresh'\"\n ></i>\n </button>\n </div>\n }\n </div>\n </form>\n}\n", styles: [":host{position:relative;display:block;cursor:not-allowed}:host form{position:relative;pointer-events:none;-webkit-user-select:none;user-select:none}:host form:after{content:\"\";position:absolute;inset:0;background:#ffffff0d;z-index:1;pointer-events:none}:host form button,:host form input,:host form select,:host form .dropdown-toggle,:host form .btn{cursor:not-allowed!important;opacity:.85}:host form *{pointer-events:none!important;-webkit-user-select:none!important;user-select:none!important}\n"] }]
|
|
9649
9613
|
}], propDecorators: { widgetControls: [{
|
|
9650
9614
|
type: Input
|
|
9651
9615
|
}], config: [{
|
|
@@ -10461,6 +10425,8 @@ class GlobalContextWidgetWrapperComponent {
|
|
|
10461
10425
|
this.internalConfig = signal({}, ...(ngDevMode ? [{ debugName: "internalConfig" }] : []));
|
|
10462
10426
|
// Latest global snapshot cached for child config updates on mode change
|
|
10463
10427
|
this.widgetInitialConfig = null;
|
|
10428
|
+
// Last emitted state - used for diff calculation to avoid race conditions
|
|
10429
|
+
this.lastEmittedState = signal({}, ...(ngDevMode ? [{ debugName: "lastEmittedState" }] : []));
|
|
10464
10430
|
// --- Outputs ---
|
|
10465
10431
|
this.globalContextChange = new EventEmitter();
|
|
10466
10432
|
this.contextChangeSubject = new Subject();
|
|
@@ -10482,25 +10448,72 @@ class GlobalContextWidgetWrapperComponent {
|
|
|
10482
10448
|
this.globalContextChange.emit(structuredClone({ context, diff }));
|
|
10483
10449
|
});
|
|
10484
10450
|
}
|
|
10485
|
-
|
|
10486
|
-
|
|
10451
|
+
/**
|
|
10452
|
+
* Update dateTimeContext for internal widget interactions (e.g., slider drag).
|
|
10453
|
+
* This bypasses the config propagation logic and directly updates the inline component state.
|
|
10454
|
+
*/
|
|
10455
|
+
updateDateTimeContext(dateTimeContext) {
|
|
10456
|
+
this.globalContextInlineComponent?.updateDateTimeContext(dateTimeContext);
|
|
10457
|
+
}
|
|
10458
|
+
/**
|
|
10459
|
+
* Directly toggle all link controls to linked or unlinked state.
|
|
10460
|
+
* All controls are always toggled together as a unified group.
|
|
10461
|
+
*
|
|
10462
|
+
* @param isLinked - True to link all controls, false to unlink all controls
|
|
10463
|
+
* @param suppressRefresh - True to prevent refresh emission (data already loaded)
|
|
10464
|
+
* @param suppressEmit - True to prevent configuration change emission
|
|
10465
|
+
*/
|
|
10466
|
+
toggleAllLinks(isLinked, suppressRefresh, suppressEmit) {
|
|
10467
|
+
this.globalContextInlineComponent?.toggleAllLinks(isLinked, suppressRefresh, suppressEmit);
|
|
10468
|
+
}
|
|
10469
|
+
/**
|
|
10470
|
+
* Pause auto-refresh and unlink all controls from global context.
|
|
10471
|
+
* Useful when user is interacting with the widget (e.g., scrolling through a list)
|
|
10472
|
+
* and you want to prevent automatic updates.
|
|
10473
|
+
*
|
|
10474
|
+
* This does two things:
|
|
10475
|
+
* 1. Sets isAutoRefreshEnabled to false (stops the auto-refresh timer)
|
|
10476
|
+
* 2. Unlinks all controls (dateTimeContext, aggregation, isAutoRefreshEnabled)
|
|
10477
|
+
* from global context as they work as a unified group
|
|
10478
|
+
*/
|
|
10479
|
+
pauseAutoRefresh() {
|
|
10480
|
+
this.globalContextInlineComponent?.pauseAutoRefresh();
|
|
10481
|
+
}
|
|
10482
|
+
/**
|
|
10483
|
+
* Resume auto-refresh and re-link all controls to global context.
|
|
10484
|
+
* Useful when user has finished interacting with the widget (e.g., scrolled back to top)
|
|
10485
|
+
* and you want to re-enable automatic updates.
|
|
10486
|
+
*
|
|
10487
|
+
* This does two things:
|
|
10488
|
+
* 1. Sets isAutoRefreshEnabled to true (starts the auto-refresh timer)
|
|
10489
|
+
* 2. Links all controls (dateTimeContext, aggregation, isAutoRefreshEnabled)
|
|
10490
|
+
* to global context as they work as a unified group
|
|
10491
|
+
*/
|
|
10492
|
+
resumeAutoRefresh() {
|
|
10493
|
+
this.globalContextInlineComponent?.resumeAutoRefresh();
|
|
10487
10494
|
}
|
|
10488
10495
|
onGlobalContextChange(context) {
|
|
10489
|
-
const currentConfig = this.internalConfig();
|
|
10490
|
-
const diff = this.globalContextUtilsService.getChangedFields(currentConfig, context);
|
|
10491
10496
|
const template = this.widgetControls();
|
|
10492
|
-
const filteredContext = pick(context, template.supports);
|
|
10493
|
-
const filteredDiff = pick(diff, template.supports);
|
|
10494
|
-
const formattedContext = formatDateTimeContextForEmission(filteredContext, template.supports);
|
|
10495
10497
|
// OVERRIDE CONTROLS BASED ON WIDGET MODE
|
|
10496
|
-
// Ensure aggregation is null in live mode
|
|
10498
|
+
// Ensure aggregation is null in live mode BEFORE calculating diff
|
|
10497
10499
|
// TODO: consider updating inline component to handle this logic.
|
|
10498
10500
|
// Edge case: widget supports aggregation. In history mode, user selects aggregation different than null.
|
|
10499
10501
|
// Then switches to live mode.
|
|
10500
10502
|
// Second scenario: legacy widget migration where aggregation was set in config.
|
|
10501
|
-
|
|
10502
|
-
|
|
10503
|
-
|
|
10503
|
+
const normalizedContext = { ...context };
|
|
10504
|
+
if (normalizedContext.refreshOption === REFRESH_OPTION.LIVE) {
|
|
10505
|
+
normalizedContext.aggregation = null;
|
|
10506
|
+
}
|
|
10507
|
+
// Use lastEmittedState instead of internalConfig to avoid race conditions
|
|
10508
|
+
// where handleConfigChange updates internalConfig before the inline component emits
|
|
10509
|
+
const previousState = this.lastEmittedState();
|
|
10510
|
+
const diff = this.globalContextUtilsService.getChangedFields(previousState, normalizedContext);
|
|
10511
|
+
const filteredContext = pick(normalizedContext, template.supports);
|
|
10512
|
+
const filteredDiff = pick(diff, template.supports);
|
|
10513
|
+
const formattedContext = formatDateTimeContextForEmission(filteredContext, template.supports);
|
|
10514
|
+
// Update lastEmittedState to track what we just emitted
|
|
10515
|
+
this.lastEmittedState.set(formattedContext);
|
|
10516
|
+
// Also update internalConfig to keep it in sync (for backward compatibility)
|
|
10504
10517
|
this.internalConfig.update(cfg => ({ ...cfg, ...formattedContext }));
|
|
10505
10518
|
this.contextChangeSubject.next({ context: formattedContext, diff: filteredDiff });
|
|
10506
10519
|
}
|
|
@@ -10700,5 +10713,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
10700
10713
|
* Generated bundle index. Do not edit.
|
|
10701
10714
|
*/
|
|
10702
10715
|
|
|
10703
|
-
export { AGGREGATIONS, AGGREGATION_ICONS, AGGREGATION_ICON_TYPE, AGGREGATION_LABELS, AGGREGATION_LIMITS, AGGREGATION_TEXTS, AGGREGATION_VALUES, AGGREGATION_VALUES_ARR, AggregationDisplayComponent, AggregationPickerComponent, AggregationPickerService, AggregationValidationService, AutoRefreshControlComponent,
|
|
10716
|
+
export { AGGREGATIONS, AGGREGATION_ICONS, AGGREGATION_ICON_TYPE, AGGREGATION_LABELS, AGGREGATION_LIMITS, AGGREGATION_TEXTS, AGGREGATION_VALUES, AGGREGATION_VALUES_ARR, AggregationDisplayComponent, AggregationPickerComponent, AggregationPickerService, AggregationValidationService, AutoRefreshControlComponent, ConfigContextSelectorComponent, ConfigurationCollapseComponent, ConfigurationControlsComponent, ContextControlsComponent, DEFAULT_INTERVAL_VALUES, DEFAULT_WIDGET_TEMPLATE, DateContextQueryParamNames, DateTimeContextPickerComponent, DateTimeContextPickerService, GLOBAL_CONTEXT_DEFAULTS, GLOBAL_CONTEXT_DISPLAY_MODE, GLOBAL_CONTEXT_EVENTS, GLOBAL_CONTEXT_SOURCE, GlobalContextComponent, GlobalContextConfigComponent, GlobalContextEventService, GlobalContextFormService, GlobalContextInlineComponent, GlobalContextLinkControlsComponent, GlobalContextModule, GlobalContextNavigationService, GlobalContextQueryService, GlobalContextService, GlobalContextUtilsService, GlobalContextValidationService, GlobalContextWidgetConfigComponent, GlobalContextWidgetWrapperComponent, HistoryModeConfigurationControlsComponent, INTERVALS, INTERVAL_TITLES, IntervalPickerComponent, LINK_BTNS_CONFIG, LiveModeConfigurationControlsComponent, PreviewControlsComponent, REFRESH_OPTION, ROUTE_PATHS, RealtimeControlComponent, TIME_DURATION, TIME_INTERVAL, TIME_SPAN_MS, TIMING, TimeRangeDisplayComponent, UI_PRIORITIES, WIDGET_DISPLAY_MODE, WIDGET_FEATURE_MAP, WidgetConfigMigrationService, WidgetControlService, buildAggregationExtensions, buildBaselineControls, buildWidgetControlsFromPresets, createAutoRefreshHandlers, createResult, defineWidgetControls, guards, isAggregationLinked, isAggregationUnlinked, isAutoRefreshDisabled, isAutoRefreshEnabled, isConfig, isDashboard, isDateTimeContextLinked, isDateTimeContextUnlinked, isHistory, isLive, isViewAndConfig, mergePartialControls, resolveWidgetControlsInput, setAutoRefreshControlsVisibility, setAutoRefreshLinks, updateBothSettings };
|
|
10704
10717
|
//# sourceMappingURL=c8y-ngx-components-global-context.mjs.map
|