@c8y/ngx-components 1023.12.0 → 1023.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/datapoint-explorer/index.d.ts +78 -1
- package/datapoint-explorer/index.d.ts.map +1 -1
- package/datapoint-explorer/view/index.d.ts +150 -14
- package/datapoint-explorer/view/index.d.ts.map +1 -1
- package/echart/index.d.ts +12 -2
- package/echart/index.d.ts.map +1 -1
- package/echart/models/index.d.ts +12 -2
- package/echart/models/index.d.ts.map +1 -1
- package/fesm2022/c8y-ngx-components-alarms.mjs +2 -2
- package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +388 -64
- package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-explorer.mjs +329 -4
- package/fesm2022/c8y-ngx-components-datapoint-explorer.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-echart-models.mjs +6 -1
- package/fesm2022/c8y-ngx-components-echart-models.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-echart.mjs +6 -1
- package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-global-context.mjs +4 -3
- package/fesm2022/c8y-ngx-components-global-context.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +129 -17
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-info-gauge.mjs +4 -4
- package/fesm2022/c8y-ngx-components-widgets-implementations-info-gauge.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components.mjs +16037 -15943
- package/fesm2022/c8y-ngx-components.mjs.map +1 -1
- package/global-context/index.d.ts.map +1 -1
- package/index.d.ts +9677 -9621
- package/index.d.ts.map +1 -1
- package/locales/de.po +26 -11
- package/locales/es.po +25 -10
- package/locales/fr.po +25 -10
- package/locales/ja_JP.po +22 -7
- package/locales/ko.po +24 -11
- package/locales/locales.pot +23 -8
- package/locales/nl.po +26 -10
- package/locales/pl.po +25 -10
- package/locales/pt_BR.po +25 -10
- package/locales/zh_CN.po +24 -9
- package/locales/zh_TW.po +26 -10
- package/package.json +1 -1
- package/widgets/implementations/datapoints-graph/index.d.ts +19 -5
- package/widgets/implementations/datapoints-graph/index.d.ts.map +1 -1
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, signal,
|
|
2
|
+
import { Injectable, signal, inject, EventEmitter, Output, Input, Component, DestroyRef, ViewChild } from '@angular/core';
|
|
3
|
+
import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from 'lz-string';
|
|
4
|
+
import * as i2 from '@c8y/ngx-components';
|
|
5
|
+
import { AlertService, MOChunkLoaderService, DatapointSyncService, ContextRouteService, ClipboardService, ViewContext, CoreModule, Permissions, GainsightService, CommonModule, FormsModule as FormsModule$1, WidgetTimeContextDateRangeService, IconDirective } from '@c8y/ngx-components';
|
|
6
|
+
import { gettext } from '@c8y/ngx-components/gettext';
|
|
3
7
|
import * as i5 from '@angular/cdk/a11y';
|
|
4
8
|
import { A11yModule } from '@angular/cdk/a11y';
|
|
5
9
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
6
|
-
import * as
|
|
10
|
+
import * as i2$1 from '@angular/forms';
|
|
7
11
|
import { FormBuilder, FormsModule, ReactiveFormsModule, FormControl, FormGroup, Validators } from '@angular/forms';
|
|
8
|
-
import { ActivatedRoute,
|
|
9
|
-
import * as
|
|
10
|
-
import { ContextRouteService, ClipboardService, ViewContext, CoreModule, AlertService, Permissions, GainsightService, WidgetTimeContextDateRangeService, CommonModule, FormsModule as FormsModule$1, IconDirective } from '@c8y/ngx-components';
|
|
11
|
-
import * as i5$1 from '@c8y/ngx-components/alarm-event-selector';
|
|
12
|
+
import { Router, ActivatedRoute, NavigationStart } from '@angular/router';
|
|
13
|
+
import * as i4$1 from '@c8y/ngx-components/alarm-event-selector';
|
|
12
14
|
import { AlarmEventSelectorModule } from '@c8y/ngx-components/alarm-event-selector';
|
|
13
15
|
import * as i1 from '@c8y/ngx-components/context-dashboard';
|
|
14
16
|
import { ContextDashboardService, ContextDashboardType, ContextDashboardModule } from '@c8y/ngx-components/context-dashboard';
|
|
15
|
-
import * as
|
|
17
|
+
import * as i3$1 from '@c8y/ngx-components/datapoint-selector';
|
|
16
18
|
import { DatapointSelectorModule } from '@c8y/ngx-components/datapoint-selector';
|
|
17
19
|
import { DatapointsExportSelectorComponent } from '@c8y/ngx-components/datapoints-export-selector';
|
|
18
|
-
import { gettext } from '@c8y/ngx-components/gettext';
|
|
19
20
|
import { CHART_VIEW_CONTEXT, PRODUCT_EXPERIENCE_DATA_EXPLORER_AND_GRAPH } from '@c8y/ngx-components/echart/models';
|
|
20
21
|
import { ChartHelpersService, ChartsComponent, ChartEventsService, ChartAlarmsService } from '@c8y/ngx-components/echart';
|
|
21
22
|
import * as i4 from 'ngx-bootstrap/dropdown';
|
|
@@ -27,9 +28,9 @@ import { INTERVALS } from '@c8y/ngx-components/interval-picker';
|
|
|
27
28
|
import { TimeContextComponent } from '@c8y/ngx-components/time-context';
|
|
28
29
|
import { BsModalService } from 'ngx-bootstrap/modal';
|
|
29
30
|
import { firstValueFrom, merge, of, map as map$1 } from 'rxjs';
|
|
31
|
+
import { InventoryService } from '@c8y/client';
|
|
30
32
|
import * as i3 from '@angular/common';
|
|
31
33
|
import { ReportDashboardModule, ReportDashboardService } from '@c8y/ngx-components/report-dashboard';
|
|
32
|
-
import { InventoryService } from '@c8y/client';
|
|
33
34
|
import { map } from 'rxjs/operators';
|
|
34
35
|
|
|
35
36
|
const adjectives = [
|
|
@@ -114,11 +115,52 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
114
115
|
}]
|
|
115
116
|
}] });
|
|
116
117
|
|
|
118
|
+
const DATA_EXPLORER_BASE_CONFIG = {
|
|
119
|
+
datapoints: [],
|
|
120
|
+
alarmsEventsConfigs: [],
|
|
121
|
+
dateFrom: null,
|
|
122
|
+
dateTo: null,
|
|
123
|
+
interval: 'hours',
|
|
124
|
+
aggregation: null,
|
|
125
|
+
realtime: false,
|
|
126
|
+
isAutoRefreshEnabled: false,
|
|
127
|
+
refreshInterval: 0,
|
|
128
|
+
displayMarkedLine: true,
|
|
129
|
+
displayMarkedPoint: true,
|
|
130
|
+
mergeMatchingDatapoints: false,
|
|
131
|
+
forceMergeDatapoints: false,
|
|
132
|
+
showLabelAndUnit: true,
|
|
133
|
+
showSlider: true,
|
|
134
|
+
displayDateSelection: false,
|
|
135
|
+
yAxisSplitLines: false,
|
|
136
|
+
xAxisSplitLines: false,
|
|
137
|
+
numberOfDecimalPlaces: 2
|
|
138
|
+
};
|
|
139
|
+
const REVERSE_KEY_MAP = {
|
|
140
|
+
d: 'datapoints',
|
|
141
|
+
a: 'alarmsEventsConfigs',
|
|
142
|
+
f: 'fragment',
|
|
143
|
+
s: 'series',
|
|
144
|
+
t: '__target',
|
|
145
|
+
m: '__template',
|
|
146
|
+
l: 'label',
|
|
147
|
+
r: 'filters',
|
|
148
|
+
y: 'timelineType',
|
|
149
|
+
df: 'dateFrom',
|
|
150
|
+
dt: 'dateTo',
|
|
151
|
+
ac: '__active',
|
|
152
|
+
c: 'color',
|
|
153
|
+
i: 'id',
|
|
154
|
+
tp: 'type'
|
|
155
|
+
};
|
|
156
|
+
const KEY_MAP = Object.fromEntries(Object.entries(REVERSE_KEY_MAP).map(([shortKey, longKey]) => [longKey, shortKey]));
|
|
157
|
+
|
|
117
158
|
class WorkspaceConfigurationService {
|
|
118
159
|
constructor() {
|
|
119
160
|
this.baseKey = 'c8y-configs';
|
|
120
161
|
this.baseDefaultKey = 'c8y-default-config-id';
|
|
121
162
|
this.contextIdSignal = signal(null, ...(ngDevMode ? [{ debugName: "contextIdSignal" }] : []));
|
|
163
|
+
this.alertService = inject(AlertService);
|
|
122
164
|
}
|
|
123
165
|
get LOCAL_STORAGE_KEY() {
|
|
124
166
|
const id = this.contextIdSignal();
|
|
@@ -128,17 +170,159 @@ class WorkspaceConfigurationService {
|
|
|
128
170
|
const id = this.contextIdSignal();
|
|
129
171
|
return id !== null ? `${this.baseDefaultKey}-${id}` : this.baseDefaultKey;
|
|
130
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Generates a full datapoint explorer link from a bare config
|
|
175
|
+
*/
|
|
176
|
+
generateExplorerLink(config, label, id) {
|
|
177
|
+
const diffed = this.removeDefaults(config);
|
|
178
|
+
const minified = this.minifyKeys(diffed);
|
|
179
|
+
const compressed = compressToEncodedURIComponent(JSON.stringify(minified));
|
|
180
|
+
const url = `/datapointexplorer-v2?id=${id}&label=${encodeURIComponent(label)}&config=${compressed}`;
|
|
181
|
+
return url;
|
|
182
|
+
}
|
|
183
|
+
/** Load workspace configs from localStorage */
|
|
131
184
|
getConfigurations() {
|
|
132
185
|
const configurations = localStorage.getItem(this.LOCAL_STORAGE_KEY);
|
|
133
|
-
|
|
186
|
+
if (configurations) {
|
|
187
|
+
const parsedConfigs = JSON.parse(configurations);
|
|
188
|
+
return parsedConfigs.map(workspaceConfig => {
|
|
189
|
+
if (typeof workspaceConfig.config === 'string') {
|
|
190
|
+
return {
|
|
191
|
+
...workspaceConfig,
|
|
192
|
+
config: this.decodeConfig(workspaceConfig.config)
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
return workspaceConfig;
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return [];
|
|
134
199
|
}
|
|
135
200
|
getDefaultConfigurationId() {
|
|
136
201
|
return localStorage.getItem(this.LOCAL_STORAGE_DEFAULT_ID_KEY);
|
|
137
202
|
}
|
|
203
|
+
/** Save workspace configs in localStorage */
|
|
138
204
|
saveConfigurations(configurations, id) {
|
|
139
205
|
localStorage.setItem(this.LOCAL_STORAGE_KEY, JSON.stringify(configurations));
|
|
140
206
|
localStorage.setItem(this.LOCAL_STORAGE_DEFAULT_ID_KEY, id);
|
|
141
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
*
|
|
210
|
+
* @param urlConfig - configuration from the URL, either compressed string or already decoded object
|
|
211
|
+
* @returns
|
|
212
|
+
*/
|
|
213
|
+
getConfigurationFromUrl(urlConfig) {
|
|
214
|
+
if (typeof urlConfig === 'string') {
|
|
215
|
+
const decodedConfig = this.decodeConfig(urlConfig);
|
|
216
|
+
const expandedConfig = this.expandKeys(decodedConfig);
|
|
217
|
+
return expandedConfig;
|
|
218
|
+
}
|
|
219
|
+
return this.expandKeys(urlConfig);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Encode a config for the URL:
|
|
223
|
+
* - Cleanup the __target objects to contain only name and id
|
|
224
|
+
* - Remove default values (diff from base)
|
|
225
|
+
* - Minify keys
|
|
226
|
+
* - Compress with lz-string
|
|
227
|
+
*/
|
|
228
|
+
encodeConfig(config) {
|
|
229
|
+
const normalized = this.cleanUpTargetObject(config);
|
|
230
|
+
const diffed = this.removeDefaults(normalized);
|
|
231
|
+
const minified = this.minifyKeys(diffed);
|
|
232
|
+
return compressToEncodedURIComponent(JSON.stringify(minified));
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Decode a config from the URL:
|
|
236
|
+
* - Decompress
|
|
237
|
+
* - Expand keys
|
|
238
|
+
* - Merge with base config
|
|
239
|
+
*/
|
|
240
|
+
decodeConfig(urlConfig) {
|
|
241
|
+
if (!urlConfig)
|
|
242
|
+
return null;
|
|
243
|
+
try {
|
|
244
|
+
const decompressed = decompressFromEncodedURIComponent(urlConfig);
|
|
245
|
+
if (!decompressed)
|
|
246
|
+
return null;
|
|
247
|
+
const parsed = JSON.parse(decompressed);
|
|
248
|
+
const expanded = this.expandKeys(parsed);
|
|
249
|
+
return { ...DATA_EXPLORER_BASE_CONFIG, ...expanded };
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
this.alertService.danger(gettext('The decoded configuration is invalid and could not be loaded.'));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/** Minify keys recursively using KEY_MAP */
|
|
256
|
+
minifyKeys(config) {
|
|
257
|
+
if (Array.isArray(config))
|
|
258
|
+
return config.map(object => this.minifyKeys(object));
|
|
259
|
+
if (config !== Object(config))
|
|
260
|
+
return config;
|
|
261
|
+
return Object.fromEntries(Object.entries(config).map(([originalKey, originalValue]) => [
|
|
262
|
+
KEY_MAP[originalKey] || originalKey,
|
|
263
|
+
this.minifyKeys(originalValue)
|
|
264
|
+
]));
|
|
265
|
+
}
|
|
266
|
+
/** Expand keys recursively using REVERSE_KEY_MAP */
|
|
267
|
+
expandKeys(config) {
|
|
268
|
+
if (Array.isArray(config))
|
|
269
|
+
return config.map(o => this.expandKeys(o));
|
|
270
|
+
if (config !== Object(config))
|
|
271
|
+
return config;
|
|
272
|
+
return Object.fromEntries(Object.entries(config).map(([originalKey, originalValue]) => [
|
|
273
|
+
REVERSE_KEY_MAP[originalKey] || originalKey,
|
|
274
|
+
this.expandKeys(originalValue)
|
|
275
|
+
]));
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Remove properties from `config` that match `base` so only changed values remain.
|
|
279
|
+
*/
|
|
280
|
+
removeDefaults(config) {
|
|
281
|
+
const result = {};
|
|
282
|
+
for (const key in config) {
|
|
283
|
+
if (!(key in DATA_EXPLORER_BASE_CONFIG) || DATA_EXPLORER_BASE_CONFIG[key] !== config[key]) {
|
|
284
|
+
result[key] = config[key];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Cleans up __target objects to only keep id and name and remove the rest.
|
|
291
|
+
*/
|
|
292
|
+
cleanUpTargetObject(config) {
|
|
293
|
+
const configCopy = { ...config };
|
|
294
|
+
// Cleanup the datapoints array
|
|
295
|
+
if (Array.isArray(configCopy.datapoints)) {
|
|
296
|
+
configCopy.datapoints = configCopy.datapoints.map((dp) => {
|
|
297
|
+
if (dp && typeof dp === 'object' && dp.__target && typeof dp.__target === 'object') {
|
|
298
|
+
const { id, name } = dp.__target;
|
|
299
|
+
const target = {};
|
|
300
|
+
if (id !== undefined)
|
|
301
|
+
target.id = id;
|
|
302
|
+
if (name !== undefined)
|
|
303
|
+
target.name = name;
|
|
304
|
+
return { ...dp, __target: target };
|
|
305
|
+
}
|
|
306
|
+
return dp;
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
// Cleanup the alarmEventsConfig array
|
|
310
|
+
if (Array.isArray(configCopy.alarmsEventsConfigs)) {
|
|
311
|
+
configCopy.alarmsEventsConfigs = configCopy.alarmsEventsConfigs.map((a) => {
|
|
312
|
+
if (a && typeof a === 'object' && a.__target && typeof a.__target === 'object') {
|
|
313
|
+
const { id, name } = a.__target;
|
|
314
|
+
const target = {};
|
|
315
|
+
if (id !== undefined)
|
|
316
|
+
target.id = id;
|
|
317
|
+
if (name !== undefined)
|
|
318
|
+
target.name = name;
|
|
319
|
+
return { ...a, __target: target };
|
|
320
|
+
}
|
|
321
|
+
return a;
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
return configCopy;
|
|
325
|
+
}
|
|
142
326
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: WorkspaceConfigurationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
143
327
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: WorkspaceConfigurationService, providedIn: 'root' }); }
|
|
144
328
|
}
|
|
@@ -149,11 +333,116 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
149
333
|
}]
|
|
150
334
|
}] });
|
|
151
335
|
|
|
336
|
+
class DataExplorerService {
|
|
337
|
+
constructor() {
|
|
338
|
+
this.inventory = inject(InventoryService);
|
|
339
|
+
this.contextDashboardService = inject(ContextDashboardService);
|
|
340
|
+
this.workspaceConfigurationService = inject(WorkspaceConfigurationService);
|
|
341
|
+
this.moChunkLoader = inject(MOChunkLoaderService);
|
|
342
|
+
this.datapointSyncService = inject(DatapointSyncService);
|
|
343
|
+
this.router = inject(Router);
|
|
344
|
+
this.maxNumberOfManagedObjectsPerRequest = 50;
|
|
345
|
+
}
|
|
346
|
+
async fetchReportDashboard(reportId) {
|
|
347
|
+
return (await this.inventory.list({
|
|
348
|
+
pageSize: 1,
|
|
349
|
+
query: `has('c8y_Dashboard!name!report_${reportId}')`
|
|
350
|
+
})).data[0];
|
|
351
|
+
}
|
|
352
|
+
async fetchContextDashboard(dashboardId, contextAsset) {
|
|
353
|
+
const context = contextAsset.c8y_isDevice
|
|
354
|
+
? ContextDashboardType.Device
|
|
355
|
+
: ContextDashboardType.Group;
|
|
356
|
+
return firstValueFrom(this.contextDashboardService.getDashboard$(dashboardId, [context]));
|
|
357
|
+
}
|
|
358
|
+
async loadManagedObjectsInChunks(uniqIds) {
|
|
359
|
+
const { results, errors } = await this.moChunkLoader.processInChunks(uniqIds, this.maxNumberOfManagedObjectsPerRequest, ids => this.loadAChunkOfManagedObjects(ids));
|
|
360
|
+
return { result: results, errors };
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Navigate to datapoint explorer with given config.
|
|
364
|
+
* The goal of this method is to navigate to the data explorer with a provided config from any other application.
|
|
365
|
+
* @param config Configuration to use
|
|
366
|
+
* @param label Label to be displayed for the configuration
|
|
367
|
+
* @param id ID for the configuration
|
|
368
|
+
*/
|
|
369
|
+
navigateToDataExplorer(config, label, id) {
|
|
370
|
+
const url = this.getUrlForConfig(config, label, id);
|
|
371
|
+
this.router.navigateByUrl(url);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Generate a URL for the datapoint explorer with the given config.
|
|
375
|
+
* The goal of this method is to generate a shareable link to the data explorer.
|
|
376
|
+
* @param config Configuration to use
|
|
377
|
+
* @param label Label to be displayed for the configuration
|
|
378
|
+
* @param id ID for the configuration
|
|
379
|
+
* @returns The generated URL
|
|
380
|
+
*/
|
|
381
|
+
getUrlForConfig(config, label, id) {
|
|
382
|
+
return this.workspaceConfigurationService.generateExplorerLink(config, label, id);
|
|
383
|
+
}
|
|
384
|
+
processAlarmEventConfigs(config) {
|
|
385
|
+
const firstTarget = config.alarmsEventsConfigs.find(ae => ae.__target)?.__target;
|
|
386
|
+
config.alarmsEventsConfigs = config.alarmsEventsConfigs.map((ae, index) => {
|
|
387
|
+
if (ae.__active === undefined)
|
|
388
|
+
ae.__active = true;
|
|
389
|
+
if (!ae.__target && firstTarget)
|
|
390
|
+
ae.__target = firstTarget;
|
|
391
|
+
if (!ae.color)
|
|
392
|
+
ae.color = this.generateColor(index);
|
|
393
|
+
return ae;
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
processDatapoints(config) {
|
|
397
|
+
const firstTarget = config.datapoints.find(dp => dp.__target)?.__target;
|
|
398
|
+
config.datapoints = config.datapoints.map((dp, index) => {
|
|
399
|
+
// Default __active
|
|
400
|
+
if (dp.__active === undefined)
|
|
401
|
+
dp.__active = true;
|
|
402
|
+
if (!dp.__target && firstTarget)
|
|
403
|
+
dp.__target = firstTarget;
|
|
404
|
+
if (!dp.color && !dp.__template)
|
|
405
|
+
dp.color = this.generateColor(index);
|
|
406
|
+
if (!dp.label)
|
|
407
|
+
dp.label = `${dp.fragment} -> ${dp.series}`;
|
|
408
|
+
return dp;
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Generates a color from a fixed palette based on the index.
|
|
413
|
+
* Used to assign colors to alarm/event configs in the UI.
|
|
414
|
+
*/
|
|
415
|
+
generateColor(index) {
|
|
416
|
+
// Simple palette, can expand
|
|
417
|
+
const palette = ['#c87d33', '#8c145f', '#8cd7fd', '#59a036', '#fb00ff', '#8d4c22', '#fbb2d7'];
|
|
418
|
+
return palette[index % palette.length];
|
|
419
|
+
}
|
|
420
|
+
async loadAndAssignManagedObjects(config, uniqueIds) {
|
|
421
|
+
const managedObjectsResult = await this.loadManagedObjectsInChunks([...uniqueIds]);
|
|
422
|
+
const managedObjects = managedObjectsResult.result;
|
|
423
|
+
const errors = managedObjectsResult.errors;
|
|
424
|
+
config.datapoints = this.datapointSyncService.assignUpdatedValues(config.datapoints, managedObjects, errors);
|
|
425
|
+
}
|
|
426
|
+
async loadAChunkOfManagedObjects(uniqIds) {
|
|
427
|
+
return this.moChunkLoader.loadAChunkOfManagedObjectsBase(uniqIds, this.inventory, this.maxNumberOfManagedObjectsPerRequest, id => this.moChunkLoader.getStatusDetails(id));
|
|
428
|
+
}
|
|
429
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataExplorerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
430
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataExplorerService, providedIn: 'root' }); }
|
|
431
|
+
}
|
|
432
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataExplorerService, decorators: [{
|
|
433
|
+
type: Injectable,
|
|
434
|
+
args: [{
|
|
435
|
+
providedIn: 'root'
|
|
436
|
+
}]
|
|
437
|
+
}] });
|
|
438
|
+
|
|
152
439
|
class WorkspaceConfigComponent {
|
|
153
440
|
constructor() {
|
|
154
441
|
this.silent = false;
|
|
155
442
|
this.onConfigurationChange = new EventEmitter();
|
|
156
443
|
this.configurations = [];
|
|
444
|
+
this.navigationSubscription = null;
|
|
445
|
+
this.shouldCleanParams = false;
|
|
157
446
|
this.activeConfigTooltip = gettext('Active configuration cannot be removed');
|
|
158
447
|
this.removeConfigTooltip = gettext('Remove configuration');
|
|
159
448
|
this.formBuilder = inject(FormBuilder);
|
|
@@ -163,22 +452,38 @@ class WorkspaceConfigComponent {
|
|
|
163
452
|
this.activatedRoute = inject(ActivatedRoute);
|
|
164
453
|
this.router = inject(Router);
|
|
165
454
|
this.nameGeneratorService = inject(NameGeneratorService);
|
|
455
|
+
this.datapointSyncService = inject(DatapointSyncService);
|
|
456
|
+
this.dataExplorerService = inject(DataExplorerService);
|
|
166
457
|
}
|
|
167
458
|
ngOnInit() {
|
|
168
459
|
this.initializeContextSourceId();
|
|
169
460
|
this.initializeConfigurations();
|
|
170
461
|
this.initWorkspaceForm();
|
|
462
|
+
this.subscribeToRouterEvents();
|
|
171
463
|
}
|
|
172
464
|
ngOnChanges(changes) {
|
|
173
465
|
if (changes.updatedConfig && !changes.updatedConfig.firstChange) {
|
|
174
466
|
this.updateConfigurations();
|
|
175
467
|
}
|
|
176
468
|
}
|
|
177
|
-
|
|
469
|
+
ngOnDestroy() {
|
|
470
|
+
if (this.shouldCleanParams) {
|
|
471
|
+
this.router.navigate([], {
|
|
472
|
+
queryParams: {
|
|
473
|
+
config: null,
|
|
474
|
+
id: null,
|
|
475
|
+
label: null
|
|
476
|
+
},
|
|
477
|
+
queryParamsHandling: 'merge'
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
this.navigationSubscription?.unsubscribe();
|
|
481
|
+
}
|
|
482
|
+
addConfig(duplicatedConfig, id, label) {
|
|
178
483
|
const name = this.nameGeneratorService.generateName();
|
|
179
484
|
const workspace = {
|
|
180
|
-
id: new Date().toISOString(),
|
|
181
|
-
label: name,
|
|
485
|
+
id: id || new Date().toISOString(),
|
|
486
|
+
label: label || name,
|
|
182
487
|
config: { datapoints: [], alarmsEventsConfigs: [] }
|
|
183
488
|
};
|
|
184
489
|
if (duplicatedConfig) {
|
|
@@ -192,6 +497,9 @@ class WorkspaceConfigComponent {
|
|
|
192
497
|
if (!selected) {
|
|
193
498
|
return;
|
|
194
499
|
}
|
|
500
|
+
if (this.currentConfiguration?.id === configuration.id) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
195
503
|
this.currentConfiguration = configuration;
|
|
196
504
|
localStorage.setItem(this.workspaceConfigurationService.LOCAL_STORAGE_DEFAULT_ID_KEY, this.currentConfiguration.id);
|
|
197
505
|
this.onConfigurationChange.emit(configuration.config);
|
|
@@ -216,20 +524,31 @@ class WorkspaceConfigComponent {
|
|
|
216
524
|
async shareConfig(configuration) {
|
|
217
525
|
await this.clipboardService.writeText(JSON.stringify(configuration.config));
|
|
218
526
|
}
|
|
219
|
-
addConfigFromUrl(queryParams) {
|
|
220
|
-
|
|
221
|
-
const
|
|
527
|
+
async addConfigFromUrl(queryParams) {
|
|
528
|
+
const id = queryParams.id || new Date().toISOString();
|
|
529
|
+
const label = queryParams.label || this.nameGeneratorService.generateName();
|
|
530
|
+
const config = this.workspaceConfigurationService.getConfigurationFromUrl(queryParams.config || {});
|
|
531
|
+
this.addConfig(config, id, label);
|
|
532
|
+
if (config.datapoints?.length) {
|
|
533
|
+
this.dataExplorerService.processDatapoints(config);
|
|
534
|
+
}
|
|
535
|
+
const uniqueIds = this.datapointSyncService.getManagedObjectIds(config.datapoints || []);
|
|
536
|
+
if (uniqueIds.length) {
|
|
537
|
+
await this.dataExplorerService.loadAndAssignManagedObjects(config, uniqueIds);
|
|
538
|
+
}
|
|
539
|
+
if (config.alarmsEventsConfigs?.length) {
|
|
540
|
+
this.dataExplorerService.processAlarmEventConfigs(config);
|
|
541
|
+
}
|
|
222
542
|
this.onConfigurationChange.emit(config);
|
|
223
543
|
}
|
|
224
544
|
updateConfigurations() {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
this.currentConfiguration.config = restConfig;
|
|
545
|
+
const config = { ...this.updatedConfig };
|
|
546
|
+
this.currentConfiguration.config = config;
|
|
228
547
|
this.configurations = this.configurations.map(currentConfig => currentConfig.id === this.currentConfiguration.id ? this.currentConfiguration : currentConfig);
|
|
229
548
|
const queryParams = {
|
|
230
|
-
|
|
549
|
+
id: this.currentConfiguration.id,
|
|
231
550
|
label: this.currentConfiguration.label,
|
|
232
|
-
config:
|
|
551
|
+
config: this.workspaceConfigurationService.encodeConfig(config)
|
|
233
552
|
};
|
|
234
553
|
this.workspaceConfigurationService.saveConfigurations(this.configurations, this.currentConfiguration.id);
|
|
235
554
|
const control = this.configurationsFormGroup.controls['configurations'];
|
|
@@ -255,13 +574,13 @@ class WorkspaceConfigComponent {
|
|
|
255
574
|
this.currentConfiguration =
|
|
256
575
|
this.configurations.find(c => c.id === defaultId) || this.configurations[0];
|
|
257
576
|
this.onConfigurationChange.emit(this.currentConfiguration.config);
|
|
258
|
-
if (queryParams?.
|
|
577
|
+
if (queryParams?.id && !this.configurations.find(c => c.id === queryParams.id)) {
|
|
259
578
|
this.addConfigFromUrl(queryParams);
|
|
260
579
|
}
|
|
261
|
-
else if (queryParams?.
|
|
262
|
-
this.configurations.find(c => c.id === queryParams.
|
|
263
|
-
this.currentConfiguration.id !== queryParams.
|
|
264
|
-
this.currentConfiguration = this.configurations.find(c => c.id === queryParams.
|
|
580
|
+
else if (queryParams?.id &&
|
|
581
|
+
this.configurations.find(c => c.id === queryParams.id) &&
|
|
582
|
+
this.currentConfiguration.id !== queryParams.id) {
|
|
583
|
+
this.currentConfiguration = this.configurations.find(c => c.id === queryParams.id);
|
|
265
584
|
this.changeConfiguration(true, this.currentConfiguration);
|
|
266
585
|
}
|
|
267
586
|
}
|
|
@@ -292,6 +611,25 @@ class WorkspaceConfigComponent {
|
|
|
292
611
|
id: [workspace.id]
|
|
293
612
|
});
|
|
294
613
|
}
|
|
614
|
+
/**
|
|
615
|
+
* Subscribe to router events to clean query params when navigating away, but only when navigating between group or device context
|
|
616
|
+
* Otherwise it breaks GC.
|
|
617
|
+
*/
|
|
618
|
+
subscribeToRouterEvents() {
|
|
619
|
+
this.navigationSubscription = this.router.events.subscribe(event => {
|
|
620
|
+
if (event instanceof NavigationStart) {
|
|
621
|
+
const urlTree = this.router.parseUrl(event.url);
|
|
622
|
+
if (urlTree.queryParams['config'] ||
|
|
623
|
+
urlTree.queryParams['id'] ||
|
|
624
|
+
urlTree.queryParams['label']) {
|
|
625
|
+
this.shouldCleanParams = true;
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
this.shouldCleanParams = false;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
}
|
|
295
633
|
initializeContextSourceId() {
|
|
296
634
|
const routeContext = this.contextRouteService.getContextData(this.activatedRoute);
|
|
297
635
|
if (!routeContext) {
|
|
@@ -304,11 +642,11 @@ class WorkspaceConfigComponent {
|
|
|
304
642
|
}
|
|
305
643
|
}
|
|
306
644
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: WorkspaceConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
307
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: WorkspaceConfigComponent, isStandalone: true, selector: "c8y-workspace-config", inputs: { updatedConfig: "updatedConfig", silent: "silent", defaultConfigurationId: "defaultConfigurationId" }, outputs: { onConfigurationChange: "onConfigurationChange" }, usesOnChanges: true, ngImport: i0, template: "@if (!silent) {\n <div\n class=\"dropdown\"\n #actionbar_dropdown=\"bs-dropdown\"\n [cdkTrapFocus]=\"actionbar_dropdown.isOpen\"\n dropdown\n [insideClick]=\"true\"\n >\n <button\n class=\"dropdown-toggle form-control l-h-tight d-flex a-i-center\"\n attr.aria-label=\"{{ currentConfiguration?.label }}\"\n tooltip=\"{{ 'Selected configuration' | translate }}\"\n placement=\"top\"\n container=\"body\"\n data-cy=\"current-configuration-dropdown-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"list\"\n ></i>\n <div class=\"d-col text-left fit-w\">\n <span class=\"text-12\">\n {{ 'Configuration' | translate }}\n </span>\n <span class=\"text-10 text-muted text-truncate\">\n {{ currentConfiguration?.label }}\n </span>\n </div>\n <span class=\"caret m-r-16 m-l-4\"></span>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-wide dropdown-menu-action-bar\"\n *dropdownMenu\n >\n <div class=\"sticky-top separator-bottom p-t-8 p-b-8 p-l-16 p-r-16\">\n <p>\n <strong>{{ 'Data explorer configurations' | translate }}</strong>\n </p>\n <p>\n <small>{{ 'Easily switch and manage configurations.' | translate }}</small>\n </p>\n </div>\n <c8y-list-group class=\"no-border-last\">\n <form [formGroup]=\"configurationsFormGroup\">\n <div formArrayName=\"configurations\">\n
|
|
645
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: WorkspaceConfigComponent, isStandalone: true, selector: "c8y-workspace-config", inputs: { updatedConfig: "updatedConfig", silent: "silent", defaultConfigurationId: "defaultConfigurationId" }, outputs: { onConfigurationChange: "onConfigurationChange" }, usesOnChanges: true, ngImport: i0, template: "@if (!silent) {\n <div\n class=\"dropdown\"\n #actionbar_dropdown=\"bs-dropdown\"\n [cdkTrapFocus]=\"actionbar_dropdown.isOpen\"\n dropdown\n [insideClick]=\"true\"\n >\n <button\n class=\"dropdown-toggle form-control l-h-tight d-flex a-i-center\"\n attr.aria-label=\"{{ currentConfiguration?.label }}\"\n tooltip=\"{{ 'Selected configuration' | translate }}\"\n placement=\"top\"\n container=\"body\"\n data-cy=\"current-configuration-dropdown-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"list\"\n ></i>\n <div class=\"d-col text-left fit-w\">\n <span class=\"text-12\">\n {{ 'Configuration' | translate }}\n </span>\n <span class=\"text-10 text-muted text-truncate\">\n {{ currentConfiguration?.label }}\n </span>\n </div>\n <span class=\"caret m-r-16 m-l-4\"></span>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-wide dropdown-menu-action-bar\"\n *dropdownMenu\n >\n <div class=\"sticky-top separator-bottom p-t-8 p-b-8 p-l-16 p-r-16\">\n <p>\n <strong>{{ 'Data explorer configurations' | translate }}</strong>\n </p>\n <p>\n <small>{{ 'Easily switch and manage configurations.' | translate }}</small>\n </p>\n </div>\n <c8y-list-group class=\"no-border-last\">\n <form [formGroup]=\"configurationsFormGroup\">\n <div formArrayName=\"configurations\">\n @for (\n configuration of configurationsFormGroup.controls.configurations['controls'];\n track $index\n ) {\n <c8y-li\n class=\"p-0\"\n [dense]=\"true\"\n >\n <c8y-li-radio\n style=\"min-height: 48px\"\n [selected]=\"configuration.value.id === currentConfiguration.id\"\n (onSelect)=\"changeConfiguration($event, configuration.value)\"\n ></c8y-li-radio>\n\n <div class=\"d-flex a-i-center gap-8\">\n <div\n class=\"min-width-0\"\n [formGroupName]=\"$index\"\n >\n <label\n class=\"editable\"\n [ngClass]=\"{\n updated:\n configuration.controls.label.touched && configuration.controls.label.dirty\n }\"\n >\n <input\n class=\"form-control\"\n [style.width.ch]=\"configuration.value.label || 25\"\n [attr.aria-label]=\"'Configuration label' | translate\"\n placeholder=\"{{ 'Configuration 1' | translate }}\"\n type=\"text\"\n autocomplete=\"off\"\n required\n formControlName=\"label\"\n (blur)=\"updateConfigurationLabel(configuration.value)\"\n (keydown.enter)=\"\n $event.preventDefault(); updateConfigurationLabel(configuration.value)\n \"\n />\n </label>\n </div>\n\n <div class=\"flex-nogrow d-flex gap-8\">\n <button\n class=\"btn-dot btn m-0\"\n [attr.aria-label]=\"'Duplicate configuration' | translate\"\n tooltip=\"{{ 'Duplicate configuration' | translate }}\"\n placement=\"left\"\n (click)=\"addConfig(configuration.value.config)\"\n [delay]=\"500\"\n >\n <i c8yIcon=\"copy\"></i>\n </button>\n\n <button\n class=\"btn-dot btn btn-dot--danger\"\n [attr.aria-label]=\"'Remove configurations' | translate\"\n tooltip=\"{{\n (configuration.value.id === currentConfiguration.id\n ? activeConfigTooltip\n : removeConfigTooltip\n ) | translate\n }}\"\n placement=\"left\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); deleteConfiguration(configuration.value)\"\n [disabled]=\"configuration.value.id === currentConfiguration.id\"\n >\n <i c8yIcon=\"minus-circle\"></i>\n </button>\n </div>\n </div>\n </c8y-li>\n }\n </div>\n </form>\n </c8y-list-group>\n <div class=\"sticky-bottom separator-top\">\n <div class=\"d-flex p-l-16 p-r-16 p-t-8 p-b-8\">\n <button\n class=\"btn btn-danger btn-sm flex-grow m-r-4\"\n (click)=\"clearAll()\"\n [disabled]=\"configurations.length < 2\"\n >\n <i [c8yIcon]=\"'delete'\"></i>\n {{ 'Delete all configurations' | translate }}\n </button>\n <button\n class=\"btn btn-default btn-sm flex-grow\"\n type=\"button\"\n (click)=\"addConfig()\"\n >\n <i [c8yIcon]=\"'add-circle-outline'\"></i>\n {{ 'Add configuration' | translate }}\n </button>\n </div>\n </div>\n </div>\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "component", type: i2.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i2.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i2.ListItemRadioComponent, selector: "c8y-list-item-radio, c8y-li-radio", inputs: ["selected", "name", "disabled", "value"], outputs: ["onSelect"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i4.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i4.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i4.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i5.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6.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: i2.C8yTranslatePipe, name: "translate" }] }); }
|
|
308
646
|
}
|
|
309
647
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: WorkspaceConfigComponent, decorators: [{
|
|
310
648
|
type: Component,
|
|
311
|
-
args: [{ selector: 'c8y-workspace-config', standalone: true, imports: [CoreModule, BsDropdownModule, FormsModule, A11yModule, TooltipModule], template: "@if (!silent) {\n <div\n class=\"dropdown\"\n #actionbar_dropdown=\"bs-dropdown\"\n [cdkTrapFocus]=\"actionbar_dropdown.isOpen\"\n dropdown\n [insideClick]=\"true\"\n >\n <button\n class=\"dropdown-toggle form-control l-h-tight d-flex a-i-center\"\n attr.aria-label=\"{{ currentConfiguration?.label }}\"\n tooltip=\"{{ 'Selected configuration' | translate }}\"\n placement=\"top\"\n container=\"body\"\n data-cy=\"current-configuration-dropdown-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"list\"\n ></i>\n <div class=\"d-col text-left fit-w\">\n <span class=\"text-12\">\n {{ 'Configuration' | translate }}\n </span>\n <span class=\"text-10 text-muted text-truncate\">\n {{ currentConfiguration?.label }}\n </span>\n </div>\n <span class=\"caret m-r-16 m-l-4\"></span>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-wide dropdown-menu-action-bar\"\n *dropdownMenu\n >\n <div class=\"sticky-top separator-bottom p-t-8 p-b-8 p-l-16 p-r-16\">\n <p>\n <strong>{{ 'Data explorer configurations' | translate }}</strong>\n </p>\n <p>\n <small>{{ 'Easily switch and manage configurations.' | translate }}</small>\n </p>\n </div>\n <c8y-list-group class=\"no-border-last\">\n <form [formGroup]=\"configurationsFormGroup\">\n <div formArrayName=\"configurations\">\n
|
|
649
|
+
args: [{ selector: 'c8y-workspace-config', standalone: true, imports: [CoreModule, BsDropdownModule, FormsModule, A11yModule, TooltipModule], template: "@if (!silent) {\n <div\n class=\"dropdown\"\n #actionbar_dropdown=\"bs-dropdown\"\n [cdkTrapFocus]=\"actionbar_dropdown.isOpen\"\n dropdown\n [insideClick]=\"true\"\n >\n <button\n class=\"dropdown-toggle form-control l-h-tight d-flex a-i-center\"\n attr.aria-label=\"{{ currentConfiguration?.label }}\"\n tooltip=\"{{ 'Selected configuration' | translate }}\"\n placement=\"top\"\n container=\"body\"\n data-cy=\"current-configuration-dropdown-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"list\"\n ></i>\n <div class=\"d-col text-left fit-w\">\n <span class=\"text-12\">\n {{ 'Configuration' | translate }}\n </span>\n <span class=\"text-10 text-muted text-truncate\">\n {{ currentConfiguration?.label }}\n </span>\n </div>\n <span class=\"caret m-r-16 m-l-4\"></span>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-wide dropdown-menu-action-bar\"\n *dropdownMenu\n >\n <div class=\"sticky-top separator-bottom p-t-8 p-b-8 p-l-16 p-r-16\">\n <p>\n <strong>{{ 'Data explorer configurations' | translate }}</strong>\n </p>\n <p>\n <small>{{ 'Easily switch and manage configurations.' | translate }}</small>\n </p>\n </div>\n <c8y-list-group class=\"no-border-last\">\n <form [formGroup]=\"configurationsFormGroup\">\n <div formArrayName=\"configurations\">\n @for (\n configuration of configurationsFormGroup.controls.configurations['controls'];\n track $index\n ) {\n <c8y-li\n class=\"p-0\"\n [dense]=\"true\"\n >\n <c8y-li-radio\n style=\"min-height: 48px\"\n [selected]=\"configuration.value.id === currentConfiguration.id\"\n (onSelect)=\"changeConfiguration($event, configuration.value)\"\n ></c8y-li-radio>\n\n <div class=\"d-flex a-i-center gap-8\">\n <div\n class=\"min-width-0\"\n [formGroupName]=\"$index\"\n >\n <label\n class=\"editable\"\n [ngClass]=\"{\n updated:\n configuration.controls.label.touched && configuration.controls.label.dirty\n }\"\n >\n <input\n class=\"form-control\"\n [style.width.ch]=\"configuration.value.label || 25\"\n [attr.aria-label]=\"'Configuration label' | translate\"\n placeholder=\"{{ 'Configuration 1' | translate }}\"\n type=\"text\"\n autocomplete=\"off\"\n required\n formControlName=\"label\"\n (blur)=\"updateConfigurationLabel(configuration.value)\"\n (keydown.enter)=\"\n $event.preventDefault(); updateConfigurationLabel(configuration.value)\n \"\n />\n </label>\n </div>\n\n <div class=\"flex-nogrow d-flex gap-8\">\n <button\n class=\"btn-dot btn m-0\"\n [attr.aria-label]=\"'Duplicate configuration' | translate\"\n tooltip=\"{{ 'Duplicate configuration' | translate }}\"\n placement=\"left\"\n (click)=\"addConfig(configuration.value.config)\"\n [delay]=\"500\"\n >\n <i c8yIcon=\"copy\"></i>\n </button>\n\n <button\n class=\"btn-dot btn btn-dot--danger\"\n [attr.aria-label]=\"'Remove configurations' | translate\"\n tooltip=\"{{\n (configuration.value.id === currentConfiguration.id\n ? activeConfigTooltip\n : removeConfigTooltip\n ) | translate\n }}\"\n placement=\"left\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); deleteConfiguration(configuration.value)\"\n [disabled]=\"configuration.value.id === currentConfiguration.id\"\n >\n <i c8yIcon=\"minus-circle\"></i>\n </button>\n </div>\n </div>\n </c8y-li>\n }\n </div>\n </form>\n </c8y-list-group>\n <div class=\"sticky-bottom separator-top\">\n <div class=\"d-flex p-l-16 p-r-16 p-t-8 p-b-8\">\n <button\n class=\"btn btn-danger btn-sm flex-grow m-r-4\"\n (click)=\"clearAll()\"\n [disabled]=\"configurations.length < 2\"\n >\n <i [c8yIcon]=\"'delete'\"></i>\n {{ 'Delete all configurations' | translate }}\n </button>\n <button\n class=\"btn btn-default btn-sm flex-grow\"\n type=\"button\"\n (click)=\"addConfig()\"\n >\n <i [c8yIcon]=\"'add-circle-outline'\"></i>\n {{ 'Add configuration' | translate }}\n </button>\n </div>\n </div>\n </div>\n </div>\n}\n" }]
|
|
312
650
|
}], propDecorators: { updatedConfig: [{
|
|
313
651
|
type: Input
|
|
314
652
|
}], silent: [{
|
|
@@ -369,40 +707,13 @@ class CreateNewReportModalComponent {
|
|
|
369
707
|
this._reject();
|
|
370
708
|
}
|
|
371
709
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CreateNewReportModalComponent, deps: [{ token: i1.ContextDashboardService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
372
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: CreateNewReportModalComponent, isStandalone: true, selector: "c8y-create-new-report-modal", ngImport: i0, template: "<c8y-modal\n [title]=\"'Create new report with widget' | translate\"\n [headerClasses]=\"'dialog-header'\"\n [disabled]=\"reportName === ''\"\n (onDismiss)=\"cancel()\"\n (onClose)=\"save()\"\n [labels]=\"labels\"\n>\n <ng-container c8y-modal-title>\n <span c8yIcon=\"c8y-reports\"></span>\n </ng-container>\n\n <p class=\"text-center bg-component text-balance sticky-top p-l-24 p-r-24 p-t-8 p-b-8 separator-bottom\">\n {{' Create a new report with the Data points graph widget using the current configuration.' | translate}}\n </p>\n <div class=\"p-24 p-t-8\">\n <c8y-form-group>\n <label\n for=\"reportName\"\n translate\n >\n Report name\n </label>\n <input\n class=\"form-control\"\n id=\"reportName\"\n placeholder=\"{{ 'e.g. My data point Report' }}\"\n name=\"name\"\n type=\"text\"\n autocomplete=\"off\"\n required\n [(ngModel)]=\"reportName\"\n />\n <c8y-messages></c8y-messages>\n </c8y-form-group>\n </div>\n</c8y-modal>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type:
|
|
710
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: CreateNewReportModalComponent, isStandalone: true, selector: "c8y-create-new-report-modal", ngImport: i0, template: "<c8y-modal\n [title]=\"'Create new report with widget' | translate\"\n [headerClasses]=\"'dialog-header'\"\n [disabled]=\"reportName === ''\"\n (onDismiss)=\"cancel()\"\n (onClose)=\"save()\"\n [labels]=\"labels\"\n>\n <ng-container c8y-modal-title>\n <span c8yIcon=\"c8y-reports\"></span>\n </ng-container>\n\n <p class=\"text-center bg-component text-balance sticky-top p-l-24 p-r-24 p-t-8 p-b-8 separator-bottom\">\n {{' Create a new report with the Data points graph widget using the current configuration.' | translate}}\n </p>\n <div class=\"p-24 p-t-8\">\n <c8y-form-group>\n <label\n for=\"reportName\"\n translate\n >\n Report name\n </label>\n <input\n class=\"form-control\"\n id=\"reportName\"\n placeholder=\"{{ 'e.g. My data point Report' }}\"\n name=\"name\"\n type=\"text\"\n autocomplete=\"off\"\n required\n [(ngModel)]=\"reportName\"\n />\n <c8y-messages></c8y-messages>\n </c8y-form-group>\n </div>\n</c8y-modal>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: i2.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: i2.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: i2.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "ngmodule", type: ReportDashboardModule }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
|
|
373
711
|
}
|
|
374
712
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CreateNewReportModalComponent, decorators: [{
|
|
375
713
|
type: Component,
|
|
376
714
|
args: [{ selector: 'c8y-create-new-report-modal', standalone: true, imports: [ReactiveFormsModule, CoreModule, ReportDashboardModule], template: "<c8y-modal\n [title]=\"'Create new report with widget' | translate\"\n [headerClasses]=\"'dialog-header'\"\n [disabled]=\"reportName === ''\"\n (onDismiss)=\"cancel()\"\n (onClose)=\"save()\"\n [labels]=\"labels\"\n>\n <ng-container c8y-modal-title>\n <span c8yIcon=\"c8y-reports\"></span>\n </ng-container>\n\n <p class=\"text-center bg-component text-balance sticky-top p-l-24 p-r-24 p-t-8 p-b-8 separator-bottom\">\n {{' Create a new report with the Data points graph widget using the current configuration.' | translate}}\n </p>\n <div class=\"p-24 p-t-8\">\n <c8y-form-group>\n <label\n for=\"reportName\"\n translate\n >\n Report name\n </label>\n <input\n class=\"form-control\"\n id=\"reportName\"\n placeholder=\"{{ 'e.g. My data point Report' }}\"\n name=\"name\"\n type=\"text\"\n autocomplete=\"off\"\n required\n [(ngModel)]=\"reportName\"\n />\n <c8y-messages></c8y-messages>\n </c8y-form-group>\n </div>\n</c8y-modal>\n" }]
|
|
377
715
|
}], ctorParameters: () => [{ type: i1.ContextDashboardService }] });
|
|
378
716
|
|
|
379
|
-
class DataExplorerService {
|
|
380
|
-
constructor() {
|
|
381
|
-
this.inventory = inject(InventoryService);
|
|
382
|
-
this.contextDashboardService = inject(ContextDashboardService);
|
|
383
|
-
}
|
|
384
|
-
async fetchReportDashboard(reportId) {
|
|
385
|
-
return (await this.inventory.list({
|
|
386
|
-
pageSize: 1,
|
|
387
|
-
query: `has('c8y_Dashboard!name!report_${reportId}')`
|
|
388
|
-
})).data[0];
|
|
389
|
-
}
|
|
390
|
-
async fetchContextDashboard(dashboardId, contextAsset) {
|
|
391
|
-
const context = contextAsset.c8y_isDevice
|
|
392
|
-
? ContextDashboardType.Device
|
|
393
|
-
: ContextDashboardType.Group;
|
|
394
|
-
return firstValueFrom(this.contextDashboardService.getDashboard$(dashboardId, [context]));
|
|
395
|
-
}
|
|
396
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataExplorerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
397
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataExplorerService, providedIn: 'root' }); }
|
|
398
|
-
}
|
|
399
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DataExplorerService, decorators: [{
|
|
400
|
-
type: Injectable,
|
|
401
|
-
args: [{
|
|
402
|
-
providedIn: 'root'
|
|
403
|
-
}]
|
|
404
|
-
}] });
|
|
405
|
-
|
|
406
717
|
class SendAsWidgetToDashboardModal {
|
|
407
718
|
constructor() {
|
|
408
719
|
this.dashboards = [];
|
|
@@ -439,7 +750,7 @@ class SendAsWidgetToDashboardModal {
|
|
|
439
750
|
return new FormGroup(controls);
|
|
440
751
|
}
|
|
441
752
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SendAsWidgetToDashboardModal, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
442
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SendAsWidgetToDashboardModal, isStandalone: true, selector: "c8y-send-as-widget-to-dashboard-modal", inputs: { contextAsset: "contextAsset" }, ngImport: i0, template: "<c8y-modal\n [title]=\"'Send as widget to dashboards' | translate\"\n [disabled]=\"!form || form.invalid\"\n [headerClasses]=\"'dialog-header'\"\n (onDismiss)=\"cancel()\"\n (onClose)=\"save()\"\n [labels]=\"labels\"\n>\n <ng-container c8y-modal-title>\n <span c8yIcon=\"th\"></span>\n </ng-container>\n\n <c8y-list-group\n class=\"m-b-0 no-border-last\"\n *ngIf=\"form\"\n [formGroup]=\"form\"\n >\n <c8y-li>\n <p\n class=\"text-center text-medium\"\n *ngIf=\"numberOfSelectedDashboards$ | async as numberOfDashboards; else noSelectedDashboards\"\n translate\n [translateParams]=\"{ numberOfDashboards: numberOfDashboards }\"\n ngNonBindable\n >\n {{ numberOfDashboards }} dashboards selected for widget\n </p>\n <ng-template #noSelectedDashboards>\n <p\n class=\"text-center text-medium\"\n translate\n >\n Select one or more dashboards to send the Data points graph widget with the current\n configuration\n </p>\n </ng-template>\n </c8y-li>\n <c8y-li *ngFor=\"let dashboard of dashboards\">\n <c8y-li-checkbox\n [attr.data-cy]=\"'branding-apply-branding-to-app-checkbox-' + dashboard.id\"\n [formControlName]=\"dashboard.id\"\n ></c8y-li-checkbox>\n <c8y-li-icon class=\"p-l-0\">\n <i c8yIcon=\"{{ dashboard.icon }}\"></i>\n </c8y-li-icon>\n <div\n class=\"text-truncate\"\n title=\"{{ dashboard.name }}\"\n >\n {{ dashboard.name }}\n </div>\n </c8y-li>\n </c8y-list-group>\n\n <c8y-ui-empty-state\n [icon]=\"'th'\"\n [title]=\"'There are no dashboards defined.' | translate\"\n [subtitle]=\"'Add a dashboard first.' | translate\"\n *ngIf=\"dashboards.length === 0\"\n ></c8y-ui-empty-state>\n</c8y-modal>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type:
|
|
753
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SendAsWidgetToDashboardModal, isStandalone: true, selector: "c8y-send-as-widget-to-dashboard-modal", inputs: { contextAsset: "contextAsset" }, ngImport: i0, template: "<c8y-modal\n [title]=\"'Send as widget to dashboards' | translate\"\n [disabled]=\"!form || form.invalid\"\n [headerClasses]=\"'dialog-header'\"\n (onDismiss)=\"cancel()\"\n (onClose)=\"save()\"\n [labels]=\"labels\"\n>\n <ng-container c8y-modal-title>\n <span c8yIcon=\"th\"></span>\n </ng-container>\n\n <c8y-list-group\n class=\"m-b-0 no-border-last\"\n *ngIf=\"form\"\n [formGroup]=\"form\"\n >\n <c8y-li>\n <p\n class=\"text-center text-medium\"\n *ngIf=\"numberOfSelectedDashboards$ | async as numberOfDashboards; else noSelectedDashboards\"\n translate\n [translateParams]=\"{ numberOfDashboards: numberOfDashboards }\"\n ngNonBindable\n >\n {{ numberOfDashboards }} dashboards selected for widget\n </p>\n <ng-template #noSelectedDashboards>\n <p\n class=\"text-center text-medium\"\n translate\n >\n Select one or more dashboards to send the Data points graph widget with the current\n configuration\n </p>\n </ng-template>\n </c8y-li>\n <c8y-li *ngFor=\"let dashboard of dashboards\">\n <c8y-li-checkbox\n [attr.data-cy]=\"'branding-apply-branding-to-app-checkbox-' + dashboard.id\"\n [formControlName]=\"dashboard.id\"\n ></c8y-li-checkbox>\n <c8y-li-icon class=\"p-l-0\">\n <i c8yIcon=\"{{ dashboard.icon }}\"></i>\n </c8y-li-icon>\n <div\n class=\"text-truncate\"\n title=\"{{ dashboard.name }}\"\n >\n {{ dashboard.name }}\n </div>\n </c8y-li>\n </c8y-list-group>\n\n <c8y-ui-empty-state\n [icon]=\"'th'\"\n [title]=\"'There are no dashboards defined.' | translate\"\n [subtitle]=\"'Add a dashboard first.' | translate\"\n *ngIf=\"dashboards.length === 0\"\n ></c8y-ui-empty-state>\n</c8y-modal>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "component", type: i2.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i2.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i2.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i2.ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "ngmodule", type: ContextDashboardModule }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
|
|
443
754
|
}
|
|
444
755
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SendAsWidgetToDashboardModal, decorators: [{
|
|
445
756
|
type: Component,
|
|
@@ -479,7 +790,7 @@ class SendAsWidgetToReportModal {
|
|
|
479
790
|
return new FormGroup(controls);
|
|
480
791
|
}
|
|
481
792
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SendAsWidgetToReportModal, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
482
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SendAsWidgetToReportModal, isStandalone: true, selector: "c8y-send-as-widget-to-report-modal", ngImport: i0, template: "<c8y-modal\n [title]=\"'Send as widget to reports' | translate\"\n [disabled]=\"!form || form.invalid\"\n [headerClasses]=\"'dialog-header'\"\n (onDismiss)=\"cancel()\"\n (onClose)=\"save()\"\n [labels]=\"labels\"\n>\n <ng-container c8y-modal-title>\n <span c8yIcon=\"c8y-reports\"></span>\n </ng-container>\n\n <c8y-list-group\n class=\"m-b-0 no-border-last\"\n *ngIf=\"form\"\n [formGroup]=\"form\"\n >\n <c8y-li>\n <p\n class=\"text-center text-medium\"\n *ngIf=\"numberOfSelectedReports$ | async as numberOfReports; else noSelectedReports\"\n translate\n [translateParams]=\"{ numberOfReports: numberOfReports }\"\n ngNonBindable\n >\n {{ numberOfReports }} reports selected for widget\n </p>\n <ng-template #noSelectedReports>\n <p\n class=\"text-center text-medium\"\n translate\n >\n Select one or more reports to send the Data points graph widget with the current configuration\n </p>\n </ng-template>\n </c8y-li>\n <c8y-li *ngFor=\"let report of reports\">\n <c8y-li-checkbox\n [attr.data-cy]=\"'branding-apply-branding-to-app-checkbox-' + report.id\"\n [formControlName]=\"report.id\"\n ></c8y-li-checkbox>\n <c8y-li-icon class=\"p-l-0\">\n <i c8yIcon=\"{{ report.icon }}\"></i>\n </c8y-li-icon>\n <div class=\"text-truncate\" title=\"{{report.name}}\">{{ report.name }}</div>\n </c8y-li>\n </c8y-list-group>\n\n <c8y-ui-empty-state\n [icon]=\"'c8y-reports'\"\n [title]=\"'There are no reports defined.' | translate\"\n [subtitle]=\"'Add a report first.' | translate\"\n *ngIf=\"reports.length === 0\"\n ></c8y-ui-empty-state>\n</c8y-modal>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type:
|
|
793
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SendAsWidgetToReportModal, isStandalone: true, selector: "c8y-send-as-widget-to-report-modal", ngImport: i0, template: "<c8y-modal\n [title]=\"'Send as widget to reports' | translate\"\n [disabled]=\"!form || form.invalid\"\n [headerClasses]=\"'dialog-header'\"\n (onDismiss)=\"cancel()\"\n (onClose)=\"save()\"\n [labels]=\"labels\"\n>\n <ng-container c8y-modal-title>\n <span c8yIcon=\"c8y-reports\"></span>\n </ng-container>\n\n <c8y-list-group\n class=\"m-b-0 no-border-last\"\n *ngIf=\"form\"\n [formGroup]=\"form\"\n >\n <c8y-li>\n <p\n class=\"text-center text-medium\"\n *ngIf=\"numberOfSelectedReports$ | async as numberOfReports; else noSelectedReports\"\n translate\n [translateParams]=\"{ numberOfReports: numberOfReports }\"\n ngNonBindable\n >\n {{ numberOfReports }} reports selected for widget\n </p>\n <ng-template #noSelectedReports>\n <p\n class=\"text-center text-medium\"\n translate\n >\n Select one or more reports to send the Data points graph widget with the current configuration\n </p>\n </ng-template>\n </c8y-li>\n <c8y-li *ngFor=\"let report of reports\">\n <c8y-li-checkbox\n [attr.data-cy]=\"'branding-apply-branding-to-app-checkbox-' + report.id\"\n [formControlName]=\"report.id\"\n ></c8y-li-checkbox>\n <c8y-li-icon class=\"p-l-0\">\n <i c8yIcon=\"{{ report.icon }}\"></i>\n </c8y-li-icon>\n <div class=\"text-truncate\" title=\"{{report.name}}\">{{ report.name }}</div>\n </c8y-li>\n </c8y-list-group>\n\n <c8y-ui-empty-state\n [icon]=\"'c8y-reports'\"\n [title]=\"'There are no reports defined.' | translate\"\n [subtitle]=\"'Add a report first.' | translate\"\n *ngIf=\"reports.length === 0\"\n ></c8y-ui-empty-state>\n</c8y-modal>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "component", type: i2.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i2.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i2.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i2.ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "ngmodule", type: ReportDashboardModule }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
|
|
483
794
|
}
|
|
484
795
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SendAsWidgetToReportModal, decorators: [{
|
|
485
796
|
type: Component,
|
|
@@ -514,7 +825,7 @@ class DatapointExplorerComponent {
|
|
|
514
825
|
this.contextRouteService = inject(ContextRouteService);
|
|
515
826
|
this.chartHelpersService = inject(ChartHelpersService);
|
|
516
827
|
this.gainsightService = inject(GainsightService);
|
|
517
|
-
this.
|
|
828
|
+
this.datapointSyncService = inject(DatapointSyncService);
|
|
518
829
|
this.formGroup = this.initForm();
|
|
519
830
|
this.settings$ = this.activatedRoute.data.pipe(map$1(data => data.settings));
|
|
520
831
|
}
|
|
@@ -596,9 +907,16 @@ class DatapointExplorerComponent {
|
|
|
596
907
|
aggregation: timeProps.aggregation
|
|
597
908
|
};
|
|
598
909
|
}
|
|
599
|
-
onConfigurationChange(config) {
|
|
910
|
+
async onConfigurationChange(config) {
|
|
911
|
+
const uniqueIds = this.datapointSyncService.getManagedObjectIds(config.datapoints || []);
|
|
912
|
+
if (uniqueIds.length) {
|
|
913
|
+
const managedObjectsResult = await this.dataExplorerService.loadManagedObjectsInChunks(uniqueIds);
|
|
914
|
+
const managedObjects = managedObjectsResult.result;
|
|
915
|
+
const errors = managedObjectsResult.errors;
|
|
916
|
+
config.datapoints = this.datapointSyncService.assignUpdatedValues(config.datapoints, managedObjects, errors);
|
|
917
|
+
}
|
|
600
918
|
// Calculate date range based on interval if not provided
|
|
601
|
-
const hasExplicitDates = config.dateFrom && config.dateTo;
|
|
919
|
+
const hasExplicitDates = this.isActualDate(config.dateFrom) && this.isActualDate(config.dateTo);
|
|
602
920
|
let dateFrom, dateTo;
|
|
603
921
|
if (hasExplicitDates) {
|
|
604
922
|
dateFrom = new Date(config.dateFrom);
|
|
@@ -793,6 +1111,12 @@ class DatapointExplorerComponent {
|
|
|
793
1111
|
// else: modal was closed
|
|
794
1112
|
}
|
|
795
1113
|
}
|
|
1114
|
+
isActualDate(val) {
|
|
1115
|
+
if (!val)
|
|
1116
|
+
return false;
|
|
1117
|
+
const date = new Date(val);
|
|
1118
|
+
return date instanceof Date && !isNaN(date.getTime());
|
|
1119
|
+
}
|
|
796
1120
|
isAlarm(item) {
|
|
797
1121
|
return item.timelineType === 'ALARM';
|
|
798
1122
|
}
|
|
@@ -879,7 +1203,7 @@ class DatapointExplorerComponent {
|
|
|
879
1203
|
ChartAlarmsService,
|
|
880
1204
|
ChartHelpersService,
|
|
881
1205
|
WidgetTimeContextDateRangeService
|
|
882
|
-
], viewQueries: [{ propertyName: "chart", first: true, predicate: ["chart"], descendants: true }, { propertyName: "timeContext", first: true, predicate: ["timeContext"], descendants: true }], ngImport: i0, template: "<c8y-title>{{ 'Data explorer' | translate }}</c8y-title>\n\n<c8y-time-context\n #timeContext\n (contextChange)=\"onTimeContextChange($event)\"\n [changedDateContext]=\"timeProps\"\n [timeContext]=\"(settings$ | async)?.timeContext\"\n></c8y-time-context>\n\n<c8y-action-bar-item [placement]=\"'left'\">\n <c8y-workspace-config\n [updatedConfig]=\"config\"\n [silent]=\"(settings$ | async)?.hideWorkspaceConfig\"\n (onConfigurationChange)=\"onConfigurationChange($event)\"\n ></c8y-workspace-config>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n *ngIf=\"!(settings$ | async)?.hideExportSelector\"\n [placement]=\"'right'\"\n>\n <c8y-datapoints-export-selector\n [exportConfig]=\"exportConfig\"\n [containerClass]=\"'d-contents'\"\n ></c8y-datapoints-export-selector>\n</c8y-action-bar-item>\n\n@if (!(settings$ | async)?.hideWidgetActions) {\n <ng-container *ngIf=\"contextAsset\">\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Send as widget to dashboard' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"sendAsWidgetToDashboard()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"th\"></i>\n <span>{{ 'Send as widget to dashboard' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n </ng-container>\n\n <ng-container *ngIf=\"!contextAsset\">\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n title=\"{{ 'Send as widget to report' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"sendAsWidgetToReport()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"c8y-reports\"></i>\n <span>{{ 'Send as widget to report' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n title=\"{{ 'Create a new report with widget' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"createNewReportWithWidget()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"c8y-reports\"></i>\n <span>{{ 'Create a new report with widget' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n </ng-container>\n}\n\n<div class=\"content-fullpage d-grid grid__col--auto-360 gap-24\">\n <div class=\"d-col gap-16\">\n <c8y-charts\n class=\"flex-grow data-point-explorer\"\n #chart\n [config]=\"config\"\n [alerts]=\"alerts\"\n [chartViewContext]=\"chartViewContext\"\n (updateAlarmsAndEvents)=\"updateAlarmsAndEvents($event)\"\n (configChangeOnZoomOut)=\"onSliderZoom($event)\"\n (datapointOutOfSync)=\"handleDatapointOutOfSync($event)\"\n (timeRangeChangeOnRealtime)=\"updateTimeRangeOnRealtime($event)\"\n (isMarkedAreaEnabled)=\"isMarkedAreaEnabled = $event\"\n (updateActiveDatapoints)=\"updateActiveDatapoints($event)\"\n (updateAggregatedSliderDatapoint)=\"updateAggregatedSliderDatapoint($event)\"\n ></c8y-charts>\n <form\n class=\"m-l-48 m-r-48\"\n [formGroup]=\"formGroup\"\n >\n <div class=\"d-grid-lg grid__col--4-4-4 gap-16\">\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Axis' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Y-axis helper lines' | translate\"\n >\n <input\n name=\"yAxisSplitLines\"\n type=\"checkbox\"\n formControlName=\"yAxisSplitLines\"\n />\n <span></span>\n <span translate>Y-axis helper lines</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'X-axis helper lines' | translate\"\n >\n <input\n name=\"xAxisSplitLines\"\n type=\"checkbox\"\n formControlName=\"xAxisSplitLines\"\n />\n <span></span>\n <span translate>X-axis helper lines</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Merge matching data points into single axis' | translate\"\n >\n <input\n name=\"mergeMatchingDatapoints\"\n type=\"checkbox\"\n formControlName=\"mergeMatchingDatapoints\"\n />\n <span></span>\n <span translate>Merge matching data points into single axis</span>\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'Data points with the same min and max values will be merged into a single axis. The values must be defined in the data point configuration.'\n | translate\n \"\n [tooltip]=\"\n 'Data points with the same min and max values will be merged into a single axis. The values must be defined in the data point configuration.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Force merge all data points into single axis' | translate\"\n >\n <input\n name=\"forceMergeDatapoints\"\n type=\"checkbox\"\n formControlName=\"forceMergeDatapoints\"\n />\n <span></span>\n <span translate>Force merge all data points into single axis</span>\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'All axes will be force merged to a single axis with the scale being set to the max and min value of all axes. It\\'s recommended to use this option for data points with similar values.'\n | translate\n \"\n [tooltip]=\"\n 'All axes will be force merged to a single axis with the scale being set to the max and min value of all axes. It\\'s recommended to use this option for data points with similar values.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n </label>\n </fieldset>\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Alarms & events' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show vertical line when alarm occurs' | translate\"\n >\n <input\n name=\"displayMarkedLine\"\n type=\"checkbox\"\n formControlName=\"displayMarkedLine\"\n />\n <span></span>\n <span translate>Show vertical line on every occurrence</span>\n </label>\n\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show icon when alarm or event occurs' | translate\"\n >\n <input\n name=\"displayMarkedPoint\"\n type=\"checkbox\"\n formControlName=\"displayMarkedPoint\"\n />\n <span></span>\n <span>\n {{\n 'Show icon when triggered`When alarms and events occur the icon will be shown`'\n | translate\n }}\n </span>\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'Some alarms or events have no matching data points. No icons will be shown for them.'\n | translate\n \"\n [tooltip]=\"\n 'Some alarms or events have no matching data points. No icons will be shown for them.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n *ngIf=\"alarmsOrEventsHaveNoMatchingDps\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n </label>\n </fieldset>\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Chart' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show labels and units' | translate\"\n >\n <input\n name=\"showLabelAndUnit\"\n type=\"checkbox\"\n formControlName=\"showLabelAndUnit\"\n />\n <span></span>\n <span translate>Display labels and units on Y-axis</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show slider' | translate\"\n >\n <input\n name=\"showSlider\"\n type=\"checkbox\"\n formControlName=\"showSlider\"\n />\n <span></span>\n <span translate>Show slider</span>\n </label>\n </fieldset>\n </div>\n </form>\n </div>\n <div class=\"card inner-scroll bg-level-1\">\n <form\n class=\"bg-inherit\"\n [formGroup]=\"formGroup\"\n >\n <c8y-datapoint-selection-list\n class=\"bg-inherit separator-top d-block\"\n name=\"datapoints\"\n [minActiveCount]=\"0\"\n [defaultFormOptions]=\"datapointSelectDefaultFormOptions\"\n [config]=\"{ contextAsset: contextAsset }\"\n formControlName=\"datapoints\"\n [allowDragAndDrop]=\"true\"\n ></c8y-datapoint-selection-list>\n\n <c8y-alarm-event-selection-list\n class=\"bg-inherit\"\n name=\"alarms\"\n formControlName=\"alarms\"\n [timelineType]=\"'ALARM'\"\n [datapoints]=\"config.datapoints\"\n ></c8y-alarm-event-selection-list>\n\n <c8y-alarm-event-selection-list\n class=\"bg-inherit\"\n name=\"events\"\n formControlName=\"events\"\n [timelineType]=\"'EVENT'\"\n [datapoints]=\"config.datapoints\"\n ></c8y-alarm-event-selection-list>\n\n <div class=\"p-l-16 p-r-16 form-group p-b-16\">\n <label\n [title]=\"'Number of decimal places' | translate\"\n translate\n >\n Number of decimal places\n </label>\n <input\n class=\"form-control\"\n name=\"numberOfDecimalPlaces\"\n type=\"number\"\n formControlName=\"numberOfDecimalPlaces\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n />\n <c8y-messages\n [show]=\"\n formGroup.controls?.numberOfDecimalPlaces?.touched &&\n formGroup?.controls?.numberOfDecimalPlaces?.errors\n \"\n ></c8y-messages>\n </div>\n </form>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "component", type: i2.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: i3$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i2.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: i2.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i3$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DatapointSelectorModule }, { kind: "component", type: i4$1.DatapointSelectionListComponent, selector: "c8y-datapoint-selection-list", inputs: ["actions", "allowDragAndDrop", "config", "defaultFormOptions", "maxActiveCount", "minActiveCount", "resolveContext", "listTitle"], outputs: ["isValid", "change"] }, { kind: "ngmodule", type: AlarmEventSelectorModule }, { kind: "component", type: i5$1.AlarmEventSelectionListComponent, selector: "c8y-alarm-event-selection-list", inputs: ["timelineType", "canRemove", "canEdit", "canDragAndDrop", "title", "addButtonLabel", "hideSource", "inline", "activeToggleAsSwitch", "omitProperties", "datapoints", "config"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6.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: PopoverModule }, { kind: "component", type: TimeContextComponent, selector: "c8y-time-context", inputs: ["changedDateContext", "controlsAvailable", "timeContext", "context"], outputs: ["contextChange"] }, { kind: "component", type: ChartsComponent, selector: "c8y-charts", inputs: ["config", "alerts", "chartViewContext"], outputs: ["configChangeOnZoomOut", "timeRangeChangeOnRealtime", "datapointOutOfSync", "updateAlarmsAndEvents", "isMarkedAreaEnabled", "finishLoading", "updateActiveDatapoints", "updateAggregatedSliderDatapoint"] }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "ngmodule", type: A11yModule }, { kind: "component", type: DatapointsExportSelectorComponent, selector: "c8y-datapoints-export-selector", inputs: ["containerClass", "exportConfig"], outputs: ["isOpen"] }, { kind: "component", type: WorkspaceConfigComponent, selector: "c8y-workspace-config", inputs: ["updatedConfig", "silent", "defaultConfigurationId"], outputs: ["onConfigurationChange"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
|
|
1206
|
+
], viewQueries: [{ propertyName: "chart", first: true, predicate: ["chart"], descendants: true }, { propertyName: "timeContext", first: true, predicate: ["timeContext"], descendants: true }], ngImport: i0, template: "<c8y-title>{{ 'Data explorer' | translate }}</c8y-title>\n\n<c8y-time-context\n #timeContext\n (contextChange)=\"onTimeContextChange($event)\"\n [changedDateContext]=\"timeProps\"\n [timeContext]=\"(settings$ | async)?.timeContext\"\n></c8y-time-context>\n\n<c8y-action-bar-item [placement]=\"'left'\">\n <c8y-workspace-config\n [updatedConfig]=\"config\"\n [silent]=\"(settings$ | async)?.hideWorkspaceConfig\"\n (onConfigurationChange)=\"onConfigurationChange($event)\"\n ></c8y-workspace-config>\n</c8y-action-bar-item>\n\n@if (!(settings$ | async)?.hideExportSelector) {\n <c8y-action-bar-item [placement]=\"'right'\">\n <c8y-datapoints-export-selector\n [exportConfig]=\"exportConfig\"\n [containerClass]=\"'d-contents'\"\n ></c8y-datapoints-export-selector>\n </c8y-action-bar-item>\n}\n\n@if (!(settings$ | async)?.hideWidgetActions) {\n @if (contextAsset) {\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Send as widget to dashboard' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"sendAsWidgetToDashboard()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"th\"></i>\n <span>{{ 'Send as widget to dashboard' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n } @else {\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n title=\"{{ 'Send as widget to report' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"sendAsWidgetToReport()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"c8y-reports\"></i>\n <span>{{ 'Send as widget to report' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n title=\"{{ 'Create a new report with widget' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"createNewReportWithWidget()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"c8y-reports\"></i>\n <span>{{ 'Create a new report with widget' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n }\n}\n\n<div class=\"content-fullpage d-grid grid__col--auto-360 gap-24\">\n <div class=\"d-col gap-16\">\n <c8y-charts\n class=\"flex-grow data-point-explorer\"\n #chart\n [config]=\"config\"\n [alerts]=\"alerts\"\n [chartViewContext]=\"chartViewContext\"\n (updateAlarmsAndEvents)=\"updateAlarmsAndEvents($event)\"\n (configChangeOnZoomOut)=\"onSliderZoom($event)\"\n (datapointOutOfSync)=\"handleDatapointOutOfSync($event)\"\n (timeRangeChangeOnRealtime)=\"updateTimeRangeOnRealtime($event)\"\n (isMarkedAreaEnabled)=\"isMarkedAreaEnabled = $event\"\n (updateActiveDatapoints)=\"updateActiveDatapoints($event)\"\n (updateAggregatedSliderDatapoint)=\"updateAggregatedSliderDatapoint($event)\"\n ></c8y-charts>\n <form\n class=\"m-l-48 m-r-48\"\n [formGroup]=\"formGroup\"\n >\n <div class=\"d-grid-lg grid__col--4-4-4 gap-16\">\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Axis' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Y-axis helper lines' | translate\"\n >\n <input\n name=\"yAxisSplitLines\"\n type=\"checkbox\"\n formControlName=\"yAxisSplitLines\"\n />\n <span></span>\n <span translate>Y-axis helper lines</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'X-axis helper lines' | translate\"\n >\n <input\n name=\"xAxisSplitLines\"\n type=\"checkbox\"\n formControlName=\"xAxisSplitLines\"\n />\n <span></span>\n <span translate>X-axis helper lines</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Merge matching data points into single axis' | translate\"\n >\n <input\n name=\"mergeMatchingDatapoints\"\n type=\"checkbox\"\n formControlName=\"mergeMatchingDatapoints\"\n />\n <span></span>\n <span translate>Merge matching data points into single axis</span>\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'Data points with the same min and max values will be merged into a single axis. The values must be defined in the data point configuration.'\n | translate\n \"\n [tooltip]=\"\n 'Data points with the same min and max values will be merged into a single axis. The values must be defined in the data point configuration.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Force merge all data points into single axis' | translate\"\n >\n <input\n name=\"forceMergeDatapoints\"\n type=\"checkbox\"\n formControlName=\"forceMergeDatapoints\"\n />\n <span></span>\n <span translate>Force merge all data points into single axis</span>\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'All axes will be force merged to a single axis with the scale being set to the max and min value of all axes. It\\'s recommended to use this option for data points with similar values.'\n | translate\n \"\n [tooltip]=\"\n 'All axes will be force merged to a single axis with the scale being set to the max and min value of all axes. It\\'s recommended to use this option for data points with similar values.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n </label>\n </fieldset>\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Alarms & events' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show vertical line when alarm occurs' | translate\"\n >\n <input\n name=\"displayMarkedLine\"\n type=\"checkbox\"\n formControlName=\"displayMarkedLine\"\n />\n <span></span>\n <span translate>Show vertical line on every occurrence</span>\n </label>\n\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show icon when alarm or event occurs' | translate\"\n >\n <input\n name=\"displayMarkedPoint\"\n type=\"checkbox\"\n formControlName=\"displayMarkedPoint\"\n />\n <span></span>\n <span>\n {{\n 'Show icon when triggered`When alarms and events occur the icon will be shown`'\n | translate\n }}\n </span>\n @if (alarmsOrEventsHaveNoMatchingDps) {\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'Some alarms or events have no matching data points. No icons will be shown for them.'\n | translate\n \"\n [tooltip]=\"\n 'Some alarms or events have no matching data points. No icons will be shown for them.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n }\n </label>\n </fieldset>\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Chart' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show labels and units' | translate\"\n >\n <input\n name=\"showLabelAndUnit\"\n type=\"checkbox\"\n formControlName=\"showLabelAndUnit\"\n />\n <span></span>\n <span translate>Display labels and units on Y-axis</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show slider' | translate\"\n >\n <input\n name=\"showSlider\"\n type=\"checkbox\"\n formControlName=\"showSlider\"\n />\n <span></span>\n <span translate>Show slider</span>\n </label>\n </fieldset>\n </div>\n </form>\n </div>\n <div class=\"card inner-scroll bg-level-1\">\n <form\n class=\"bg-inherit\"\n [formGroup]=\"formGroup\"\n >\n <c8y-datapoint-selection-list\n class=\"bg-inherit separator-top d-block\"\n name=\"datapoints\"\n [minActiveCount]=\"0\"\n [defaultFormOptions]=\"datapointSelectDefaultFormOptions\"\n [config]=\"{ contextAsset: contextAsset }\"\n formControlName=\"datapoints\"\n [allowDragAndDrop]=\"true\"\n ></c8y-datapoint-selection-list>\n\n <c8y-alarm-event-selection-list\n class=\"bg-inherit\"\n name=\"alarms\"\n formControlName=\"alarms\"\n [timelineType]=\"'ALARM'\"\n [datapoints]=\"config.datapoints\"\n ></c8y-alarm-event-selection-list>\n\n <c8y-alarm-event-selection-list\n class=\"bg-inherit\"\n name=\"events\"\n formControlName=\"events\"\n [timelineType]=\"'EVENT'\"\n [datapoints]=\"config.datapoints\"\n ></c8y-alarm-event-selection-list>\n\n <div class=\"p-l-16 p-r-16 form-group p-b-16\">\n <label\n [title]=\"'Number of decimal places' | translate\"\n translate\n >\n Number of decimal places\n </label>\n <input\n class=\"form-control\"\n name=\"numberOfDecimalPlaces\"\n type=\"number\"\n formControlName=\"numberOfDecimalPlaces\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n />\n <c8y-messages\n [show]=\"\n formGroup.controls?.numberOfDecimalPlaces?.touched &&\n formGroup?.controls?.numberOfDecimalPlaces?.errors\n \"\n ></c8y-messages>\n </div>\n </form>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "component", type: i2.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: i2.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i2.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: i2.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DatapointSelectorModule }, { kind: "component", type: i3$1.DatapointSelectionListComponent, selector: "c8y-datapoint-selection-list", inputs: ["actions", "allowDragAndDrop", "config", "defaultFormOptions", "maxActiveCount", "minActiveCount", "resolveContext", "listTitle"], outputs: ["isValid", "change"] }, { kind: "ngmodule", type: AlarmEventSelectorModule }, { kind: "component", type: i4$1.AlarmEventSelectionListComponent, selector: "c8y-alarm-event-selection-list", inputs: ["timelineType", "canRemove", "canEdit", "canDragAndDrop", "title", "addButtonLabel", "hideSource", "inline", "activeToggleAsSwitch", "omitProperties", "datapoints", "config"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6.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: PopoverModule }, { kind: "component", type: TimeContextComponent, selector: "c8y-time-context", inputs: ["changedDateContext", "controlsAvailable", "timeContext", "context"], outputs: ["contextChange"] }, { kind: "component", type: ChartsComponent, selector: "c8y-charts", inputs: ["config", "alerts", "chartViewContext"], outputs: ["configChangeOnZoomOut", "timeRangeChangeOnRealtime", "datapointOutOfSync", "updateAlarmsAndEvents", "isMarkedAreaEnabled", "finishLoading", "updateActiveDatapoints", "updateAggregatedSliderDatapoint"] }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "ngmodule", type: A11yModule }, { kind: "component", type: DatapointsExportSelectorComponent, selector: "c8y-datapoints-export-selector", inputs: ["containerClass", "exportConfig"], outputs: ["isOpen"] }, { kind: "component", type: WorkspaceConfigComponent, selector: "c8y-workspace-config", inputs: ["updatedConfig", "silent", "defaultConfigurationId"], outputs: ["onConfigurationChange"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
|
|
883
1207
|
}
|
|
884
1208
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatapointExplorerComponent, decorators: [{
|
|
885
1209
|
type: Component,
|
|
@@ -903,7 +1227,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
903
1227
|
ChartAlarmsService,
|
|
904
1228
|
ChartHelpersService,
|
|
905
1229
|
WidgetTimeContextDateRangeService
|
|
906
|
-
], template: "<c8y-title>{{ 'Data explorer' | translate }}</c8y-title>\n\n<c8y-time-context\n #timeContext\n (contextChange)=\"onTimeContextChange($event)\"\n [changedDateContext]=\"timeProps\"\n [timeContext]=\"(settings$ | async)?.timeContext\"\n></c8y-time-context>\n\n<c8y-action-bar-item [placement]=\"'left'\">\n <c8y-workspace-config\n [updatedConfig]=\"config\"\n [silent]=\"(settings$ | async)?.hideWorkspaceConfig\"\n (onConfigurationChange)=\"onConfigurationChange($event)\"\n ></c8y-workspace-config>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n *ngIf=\"!(settings$ | async)?.hideExportSelector\"\n [placement]=\"'right'\"\n>\n <c8y-datapoints-export-selector\n [exportConfig]=\"exportConfig\"\n [containerClass]=\"'d-contents'\"\n ></c8y-datapoints-export-selector>\n</c8y-action-bar-item>\n\n@if (!(settings$ | async)?.hideWidgetActions) {\n <ng-container *ngIf=\"contextAsset\">\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Send as widget to dashboard' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"sendAsWidgetToDashboard()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"th\"></i>\n <span>{{ 'Send as widget to dashboard' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n </ng-container>\n\n <ng-container *ngIf=\"!contextAsset\">\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n title=\"{{ 'Send as widget to report' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"sendAsWidgetToReport()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"c8y-reports\"></i>\n <span>{{ 'Send as widget to report' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n title=\"{{ 'Create a new report with widget' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"createNewReportWithWidget()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"c8y-reports\"></i>\n <span>{{ 'Create a new report with widget' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n </ng-container>\n}\n\n<div class=\"content-fullpage d-grid grid__col--auto-360 gap-24\">\n <div class=\"d-col gap-16\">\n <c8y-charts\n class=\"flex-grow data-point-explorer\"\n #chart\n [config]=\"config\"\n [alerts]=\"alerts\"\n [chartViewContext]=\"chartViewContext\"\n (updateAlarmsAndEvents)=\"updateAlarmsAndEvents($event)\"\n (configChangeOnZoomOut)=\"onSliderZoom($event)\"\n (datapointOutOfSync)=\"handleDatapointOutOfSync($event)\"\n (timeRangeChangeOnRealtime)=\"updateTimeRangeOnRealtime($event)\"\n (isMarkedAreaEnabled)=\"isMarkedAreaEnabled = $event\"\n (updateActiveDatapoints)=\"updateActiveDatapoints($event)\"\n (updateAggregatedSliderDatapoint)=\"updateAggregatedSliderDatapoint($event)\"\n ></c8y-charts>\n <form\n class=\"m-l-48 m-r-48\"\n [formGroup]=\"formGroup\"\n >\n <div class=\"d-grid-lg grid__col--4-4-4 gap-16\">\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Axis' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Y-axis helper lines' | translate\"\n >\n <input\n name=\"yAxisSplitLines\"\n type=\"checkbox\"\n formControlName=\"yAxisSplitLines\"\n />\n <span></span>\n <span translate>Y-axis helper lines</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'X-axis helper lines' | translate\"\n >\n <input\n name=\"xAxisSplitLines\"\n type=\"checkbox\"\n formControlName=\"xAxisSplitLines\"\n />\n <span></span>\n <span translate>X-axis helper lines</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Merge matching data points into single axis' | translate\"\n >\n <input\n name=\"mergeMatchingDatapoints\"\n type=\"checkbox\"\n formControlName=\"mergeMatchingDatapoints\"\n />\n <span></span>\n <span translate>Merge matching data points into single axis</span>\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'Data points with the same min and max values will be merged into a single axis. The values must be defined in the data point configuration.'\n | translate\n \"\n [tooltip]=\"\n 'Data points with the same min and max values will be merged into a single axis. The values must be defined in the data point configuration.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Force merge all data points into single axis' | translate\"\n >\n <input\n name=\"forceMergeDatapoints\"\n type=\"checkbox\"\n formControlName=\"forceMergeDatapoints\"\n />\n <span></span>\n <span translate>Force merge all data points into single axis</span>\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'All axes will be force merged to a single axis with the scale being set to the max and min value of all axes. It\\'s recommended to use this option for data points with similar values.'\n | translate\n \"\n [tooltip]=\"\n 'All axes will be force merged to a single axis with the scale being set to the max and min value of all axes. It\\'s recommended to use this option for data points with similar values.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n </label>\n </fieldset>\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Alarms & events' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show vertical line when alarm occurs' | translate\"\n >\n <input\n name=\"displayMarkedLine\"\n type=\"checkbox\"\n formControlName=\"displayMarkedLine\"\n />\n <span></span>\n <span translate>Show vertical line on every occurrence</span>\n </label>\n\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show icon when alarm or event occurs' | translate\"\n >\n <input\n name=\"displayMarkedPoint\"\n type=\"checkbox\"\n formControlName=\"displayMarkedPoint\"\n />\n <span></span>\n <span>\n {{\n 'Show icon when triggered`When alarms and events occur the icon will be shown`'\n | translate\n }}\n </span>\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'Some alarms or events have no matching data points. No icons will be shown for them.'\n | translate\n \"\n [tooltip]=\"\n 'Some alarms or events have no matching data points. No icons will be shown for them.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n *ngIf=\"alarmsOrEventsHaveNoMatchingDps\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n </label>\n </fieldset>\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Chart' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show labels and units' | translate\"\n >\n <input\n name=\"showLabelAndUnit\"\n type=\"checkbox\"\n formControlName=\"showLabelAndUnit\"\n />\n <span></span>\n <span translate>Display labels and units on Y-axis</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show slider' | translate\"\n >\n <input\n name=\"showSlider\"\n type=\"checkbox\"\n formControlName=\"showSlider\"\n />\n <span></span>\n <span translate>Show slider</span>\n </label>\n </fieldset>\n </div>\n </form>\n </div>\n <div class=\"card inner-scroll bg-level-1\">\n <form\n class=\"bg-inherit\"\n [formGroup]=\"formGroup\"\n >\n <c8y-datapoint-selection-list\n class=\"bg-inherit separator-top d-block\"\n name=\"datapoints\"\n [minActiveCount]=\"0\"\n [defaultFormOptions]=\"datapointSelectDefaultFormOptions\"\n [config]=\"{ contextAsset: contextAsset }\"\n formControlName=\"datapoints\"\n [allowDragAndDrop]=\"true\"\n ></c8y-datapoint-selection-list>\n\n <c8y-alarm-event-selection-list\n class=\"bg-inherit\"\n name=\"alarms\"\n formControlName=\"alarms\"\n [timelineType]=\"'ALARM'\"\n [datapoints]=\"config.datapoints\"\n ></c8y-alarm-event-selection-list>\n\n <c8y-alarm-event-selection-list\n class=\"bg-inherit\"\n name=\"events\"\n formControlName=\"events\"\n [timelineType]=\"'EVENT'\"\n [datapoints]=\"config.datapoints\"\n ></c8y-alarm-event-selection-list>\n\n <div class=\"p-l-16 p-r-16 form-group p-b-16\">\n <label\n [title]=\"'Number of decimal places' | translate\"\n translate\n >\n Number of decimal places\n </label>\n <input\n class=\"form-control\"\n name=\"numberOfDecimalPlaces\"\n type=\"number\"\n formControlName=\"numberOfDecimalPlaces\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n />\n <c8y-messages\n [show]=\"\n formGroup.controls?.numberOfDecimalPlaces?.touched &&\n formGroup?.controls?.numberOfDecimalPlaces?.errors\n \"\n ></c8y-messages>\n </div>\n </form>\n </div>\n</div>\n" }]
|
|
1230
|
+
], template: "<c8y-title>{{ 'Data explorer' | translate }}</c8y-title>\n\n<c8y-time-context\n #timeContext\n (contextChange)=\"onTimeContextChange($event)\"\n [changedDateContext]=\"timeProps\"\n [timeContext]=\"(settings$ | async)?.timeContext\"\n></c8y-time-context>\n\n<c8y-action-bar-item [placement]=\"'left'\">\n <c8y-workspace-config\n [updatedConfig]=\"config\"\n [silent]=\"(settings$ | async)?.hideWorkspaceConfig\"\n (onConfigurationChange)=\"onConfigurationChange($event)\"\n ></c8y-workspace-config>\n</c8y-action-bar-item>\n\n@if (!(settings$ | async)?.hideExportSelector) {\n <c8y-action-bar-item [placement]=\"'right'\">\n <c8y-datapoints-export-selector\n [exportConfig]=\"exportConfig\"\n [containerClass]=\"'d-contents'\"\n ></c8y-datapoints-export-selector>\n </c8y-action-bar-item>\n}\n\n@if (!(settings$ | async)?.hideWidgetActions) {\n @if (contextAsset) {\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Send as widget to dashboard' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"sendAsWidgetToDashboard()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"th\"></i>\n <span>{{ 'Send as widget to dashboard' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n } @else {\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n title=\"{{ 'Send as widget to report' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"sendAsWidgetToReport()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"c8y-reports\"></i>\n <span>{{ 'Send as widget to report' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <button\n title=\"{{ 'Create a new report with widget' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"createNewReportWithWidget()\"\n [disabled]=\"config?.datapoints?.length === 0 || !canAddReport\"\n >\n <i c8yIcon=\"c8y-reports\"></i>\n <span>{{ 'Create a new report with widget' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n }\n}\n\n<div class=\"content-fullpage d-grid grid__col--auto-360 gap-24\">\n <div class=\"d-col gap-16\">\n <c8y-charts\n class=\"flex-grow data-point-explorer\"\n #chart\n [config]=\"config\"\n [alerts]=\"alerts\"\n [chartViewContext]=\"chartViewContext\"\n (updateAlarmsAndEvents)=\"updateAlarmsAndEvents($event)\"\n (configChangeOnZoomOut)=\"onSliderZoom($event)\"\n (datapointOutOfSync)=\"handleDatapointOutOfSync($event)\"\n (timeRangeChangeOnRealtime)=\"updateTimeRangeOnRealtime($event)\"\n (isMarkedAreaEnabled)=\"isMarkedAreaEnabled = $event\"\n (updateActiveDatapoints)=\"updateActiveDatapoints($event)\"\n (updateAggregatedSliderDatapoint)=\"updateAggregatedSliderDatapoint($event)\"\n ></c8y-charts>\n <form\n class=\"m-l-48 m-r-48\"\n [formGroup]=\"formGroup\"\n >\n <div class=\"d-grid-lg grid__col--4-4-4 gap-16\">\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Axis' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Y-axis helper lines' | translate\"\n >\n <input\n name=\"yAxisSplitLines\"\n type=\"checkbox\"\n formControlName=\"yAxisSplitLines\"\n />\n <span></span>\n <span translate>Y-axis helper lines</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'X-axis helper lines' | translate\"\n >\n <input\n name=\"xAxisSplitLines\"\n type=\"checkbox\"\n formControlName=\"xAxisSplitLines\"\n />\n <span></span>\n <span translate>X-axis helper lines</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Merge matching data points into single axis' | translate\"\n >\n <input\n name=\"mergeMatchingDatapoints\"\n type=\"checkbox\"\n formControlName=\"mergeMatchingDatapoints\"\n />\n <span></span>\n <span translate>Merge matching data points into single axis</span>\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'Data points with the same min and max values will be merged into a single axis. The values must be defined in the data point configuration.'\n | translate\n \"\n [tooltip]=\"\n 'Data points with the same min and max values will be merged into a single axis. The values must be defined in the data point configuration.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Force merge all data points into single axis' | translate\"\n >\n <input\n name=\"forceMergeDatapoints\"\n type=\"checkbox\"\n formControlName=\"forceMergeDatapoints\"\n />\n <span></span>\n <span translate>Force merge all data points into single axis</span>\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'All axes will be force merged to a single axis with the scale being set to the max and min value of all axes. It\\'s recommended to use this option for data points with similar values.'\n | translate\n \"\n [tooltip]=\"\n 'All axes will be force merged to a single axis with the scale being set to the max and min value of all axes. It\\'s recommended to use this option for data points with similar values.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n </label>\n </fieldset>\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Alarms & events' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show vertical line when alarm occurs' | translate\"\n >\n <input\n name=\"displayMarkedLine\"\n type=\"checkbox\"\n formControlName=\"displayMarkedLine\"\n />\n <span></span>\n <span translate>Show vertical line on every occurrence</span>\n </label>\n\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show icon when alarm or event occurs' | translate\"\n >\n <input\n name=\"displayMarkedPoint\"\n type=\"checkbox\"\n formControlName=\"displayMarkedPoint\"\n />\n <span></span>\n <span>\n {{\n 'Show icon when triggered`When alarms and events occur the icon will be shown`'\n | translate\n }}\n </span>\n @if (alarmsOrEventsHaveNoMatchingDps) {\n <button\n class=\"btn-dot m-l-8\"\n [attr.aria-label]=\"\n 'Some alarms or events have no matching data points. No icons will be shown for them.'\n | translate\n \"\n [tooltip]=\"\n 'Some alarms or events have no matching data points. No icons will be shown for them.'\n | translate\n \"\n container=\"body\"\n type=\"button\"\n (click)=\"$event.stopPropagation()\"\n [adaptivePosition]=\"false\"\n >\n <i\n class=\"text-info\"\n c8yIcon=\"info\"\n ></i>\n </button>\n }\n </label>\n </fieldset>\n <fieldset class=\"c8y-fieldset form-group-sm m-t-md-0 p-b-8\">\n <legend>{{ 'Chart' | translate }}</legend>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show labels and units' | translate\"\n >\n <input\n name=\"showLabelAndUnit\"\n type=\"checkbox\"\n formControlName=\"showLabelAndUnit\"\n />\n <span></span>\n <span translate>Display labels and units on Y-axis</span>\n </label>\n <label\n class=\"c8y-checkbox\"\n [title]=\"'Show slider' | translate\"\n >\n <input\n name=\"showSlider\"\n type=\"checkbox\"\n formControlName=\"showSlider\"\n />\n <span></span>\n <span translate>Show slider</span>\n </label>\n </fieldset>\n </div>\n </form>\n </div>\n <div class=\"card inner-scroll bg-level-1\">\n <form\n class=\"bg-inherit\"\n [formGroup]=\"formGroup\"\n >\n <c8y-datapoint-selection-list\n class=\"bg-inherit separator-top d-block\"\n name=\"datapoints\"\n [minActiveCount]=\"0\"\n [defaultFormOptions]=\"datapointSelectDefaultFormOptions\"\n [config]=\"{ contextAsset: contextAsset }\"\n formControlName=\"datapoints\"\n [allowDragAndDrop]=\"true\"\n ></c8y-datapoint-selection-list>\n\n <c8y-alarm-event-selection-list\n class=\"bg-inherit\"\n name=\"alarms\"\n formControlName=\"alarms\"\n [timelineType]=\"'ALARM'\"\n [datapoints]=\"config.datapoints\"\n ></c8y-alarm-event-selection-list>\n\n <c8y-alarm-event-selection-list\n class=\"bg-inherit\"\n name=\"events\"\n formControlName=\"events\"\n [timelineType]=\"'EVENT'\"\n [datapoints]=\"config.datapoints\"\n ></c8y-alarm-event-selection-list>\n\n <div class=\"p-l-16 p-r-16 form-group p-b-16\">\n <label\n [title]=\"'Number of decimal places' | translate\"\n translate\n >\n Number of decimal places\n </label>\n <input\n class=\"form-control\"\n name=\"numberOfDecimalPlaces\"\n type=\"number\"\n formControlName=\"numberOfDecimalPlaces\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n />\n <c8y-messages\n [show]=\"\n formGroup.controls?.numberOfDecimalPlaces?.touched &&\n formGroup?.controls?.numberOfDecimalPlaces?.errors\n \"\n ></c8y-messages>\n </div>\n </form>\n </div>\n</div>\n" }]
|
|
907
1231
|
}], ctorParameters: () => [], propDecorators: { chart: [{
|
|
908
1232
|
type: ViewChild,
|
|
909
1233
|
args: ['chart']
|
|
@@ -916,5 +1240,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
916
1240
|
* Generated bundle index. Do not edit.
|
|
917
1241
|
*/
|
|
918
1242
|
|
|
919
|
-
export { DatapointExplorerComponent, NameGeneratorService, WorkspaceConfigurationService };
|
|
1243
|
+
export { DATA_EXPLORER_BASE_CONFIG, DataExplorerService, DatapointExplorerComponent, KEY_MAP, NameGeneratorService, REVERSE_KEY_MAP, WorkspaceConfigurationService };
|
|
920
1244
|
//# sourceMappingURL=c8y-ngx-components-datapoint-explorer-view.mjs.map
|