@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
1,459 lines • 80 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, Component, ElementRef, HostListener, ViewChild, EventEmitter, forwardRef, Output, Input, NgModule } from '@angular/core';
import * as i1$1 from '@c8y/ngx-components';
import { gettext, IconDirective, C8yTranslatePipe, BaseColumn, C8yTranslateDirective, getBasicInputArrayFormFieldConfig, DatePipe, DeviceStatusComponent, SendStatus, PushStatus, DataGridService, Status, alertOnError, FilteringActionType, DataGridComponent, ProductExperienceDirective, EmptyStateContextDirective, EmptyStateComponent, ColumnDirective, PRODUCT_EXPERIENCE_EVENT_SOURCE, CommonModule, FormsModule, DeviceStatusModule, DataGridModule, DynamicFormsModule, ProductExperienceModule } from '@c8y/ngx-components';
import * as i1 from '@ngx-translate/core';
import { map, sortBy, remove, cloneDeep } from 'lodash-es';
import { NgIf, NgFor } from '@angular/common';
import { FormGroup } from '@angular/forms';
import { PopoverDirective, PopoverModule } from 'ngx-bootstrap/popover';
import { AssetSelectorComponent, AssetSelectorModule } from '@c8y/ngx-components/assets-navigator';
import { gettext as gettext$1 } from '@c8y/ngx-components/gettext';
import { Subject } from 'rxjs';
import * as i1$2 from '@c8y/client';
import { RouterModule } from '@angular/router';
/**
* Service contains logic extracted from the device-grid service to avoid circular dependency MTM-40239.
*/
class ColumnUtilService {
constructor(translateService) {
this.translateService = translateService;
}
getAlarmsHref(device) {
return `${this.getHref(device)}/alarms`;
}
getHref(groupOrDevice, prefix = '#/') {
if (groupOrDevice.c8y_IsDeviceGroup || groupOrDevice.c8y_IsDynamicGroup) {
return `${prefix}group/${groupOrDevice.id}`;
}
return `${prefix}device/${groupOrDevice.id}`;
}
getParentsNames(device, featuredParentId) {
const assetParentsReferences = device.assetParents.references;
const assetParents = map(assetParentsReferences, 'managedObject');
const sortedByName = sortBy(assetParents, ['name']);
const featuredItems = remove(sortedByName, { id: featuredParentId });
const items = featuredItems.concat(sortedByName);
const names = map(items, 'name');
return names.join(', ');
}
getModel(device) {
const hardware = this.getHardware(device);
return hardware && hardware.model;
}
getProperName(device) {
const { id, name } = device;
return name ? name : this.translateService.instant('Device {{id}}', { id });
}
getSerialNumber(device) {
const hardware = this.getHardware(device);
return hardware && hardware['serialNumber'];
}
getHardware(device) {
return device && device['c8y_Hardware'];
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ColumnUtilService, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ColumnUtilService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ColumnUtilService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: i1.TranslateService }] });
class AlarmsCellRendererComponent {
constructor(context, columnUtilService) {
this.context = context;
this.columnUtilService = columnUtilService;
this.linkAriaLabel = gettext('See alarms for device "{{ name }}"');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AlarmsCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }, { token: ColumnUtilService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: AlarmsCellRendererComponent, isStandalone: true, selector: "c8y-alarms-cell-renderer", ngImport: i0, template: "<a\n class=\"d-flex a-i-center flex-wrap gap-4 no-decoration\"\n [href]=\"columnUtilService.getAlarmsHref(context.item)\"\n [attr.aria-label]=\"\n linkAriaLabel | translate: { name: columnUtilService.getProperName(context.item) }\n \"\n *ngIf=\"\n context.item.c8y_ActiveAlarmsStatus?.critical ||\n context.item.c8y_ActiveAlarmsStatus?.major ||\n context.item.c8y_ActiveAlarmsStatus?.minor ||\n context.item.c8y_ActiveAlarmsStatus?.warning\n \"\n>\n <span\n class=\"c8y-icon-badge\"\n data-cy=\"alarms.cell-renderer--critical-alarm-badge\"\n title=\"{{ context.item.c8y_ActiveAlarmsStatus?.critical }} {{ 'Critical alarms' | translate }}\"\n *ngIf=\"context.item.c8y_ActiveAlarmsStatus?.critical\"\n >\n <i [c8yIcon]=\"'exclamation-circle'\" class=\"status critical stroked-icon\" data-cy=\"alarms.cell-renderer--critical-alarm-icon\"></i>\n <span class=\"badge badge-info\">{{ context.item.c8y_ActiveAlarmsStatus?.critical }}</span>\n </span>\n <span\n class=\"c8y-icon-badge\"\n title=\"{{ context.item.c8y_ActiveAlarmsStatus?.major }} {{ 'Major alarms' | translate }}\"\n *ngIf=\"context.item.c8y_ActiveAlarmsStatus?.major\"\n >\n <i [c8yIcon]=\"'warning'\" class=\"status major stroked-icon\"></i>\n <span class=\"badge badge-info\">{{ context.item.c8y_ActiveAlarmsStatus?.major }}</span>\n </span>\n <span\n class=\"c8y-icon-badge\"\n title=\"{{ context.item.c8y_ActiveAlarmsStatus?.minor }} {{ 'Minor alarms' | translate }}\"\n *ngIf=\"context.item.c8y_ActiveAlarmsStatus?.minor\"\n >\n <i [c8yIcon]=\"'high-priority'\" class=\"status minor stroked-icon\"></i>\n <span class=\"badge badge-info\">{{ context.item.c8y_ActiveAlarmsStatus?.minor }}</span>\n </span>\n <span\n class=\"c8y-icon-badge\"\n title=\"{{ context.item.c8y_ActiveAlarmsStatus?.warning }} {{ 'Warning alarms' | translate }}\"\n *ngIf=\"context.item.c8y_ActiveAlarmsStatus?.warning\"\n >\n <i [c8yIcon]=\"'info-circle'\" class=\"status warning stroked-icon\"></i>\n <span class=\"badge badge-info\">{{ context.item.c8y_ActiveAlarmsStatus?.warning }}</span>\n </span>\n</a>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AlarmsCellRendererComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-alarms-cell-renderer', imports: [NgIf, IconDirective, C8yTranslatePipe], template: "<a\n class=\"d-flex a-i-center flex-wrap gap-4 no-decoration\"\n [href]=\"columnUtilService.getAlarmsHref(context.item)\"\n [attr.aria-label]=\"\n linkAriaLabel | translate: { name: columnUtilService.getProperName(context.item) }\n \"\n *ngIf=\"\n context.item.c8y_ActiveAlarmsStatus?.critical ||\n context.item.c8y_ActiveAlarmsStatus?.major ||\n context.item.c8y_ActiveAlarmsStatus?.minor ||\n context.item.c8y_ActiveAlarmsStatus?.warning\n \"\n>\n <span\n class=\"c8y-icon-badge\"\n data-cy=\"alarms.cell-renderer--critical-alarm-badge\"\n title=\"{{ context.item.c8y_ActiveAlarmsStatus?.critical }} {{ 'Critical alarms' | translate }}\"\n *ngIf=\"context.item.c8y_ActiveAlarmsStatus?.critical\"\n >\n <i [c8yIcon]=\"'exclamation-circle'\" class=\"status critical stroked-icon\" data-cy=\"alarms.cell-renderer--critical-alarm-icon\"></i>\n <span class=\"badge badge-info\">{{ context.item.c8y_ActiveAlarmsStatus?.critical }}</span>\n </span>\n <span\n class=\"c8y-icon-badge\"\n title=\"{{ context.item.c8y_ActiveAlarmsStatus?.major }} {{ 'Major alarms' | translate }}\"\n *ngIf=\"context.item.c8y_ActiveAlarmsStatus?.major\"\n >\n <i [c8yIcon]=\"'warning'\" class=\"status major stroked-icon\"></i>\n <span class=\"badge badge-info\">{{ context.item.c8y_ActiveAlarmsStatus?.major }}</span>\n </span>\n <span\n class=\"c8y-icon-badge\"\n title=\"{{ context.item.c8y_ActiveAlarmsStatus?.minor }} {{ 'Minor alarms' | translate }}\"\n *ngIf=\"context.item.c8y_ActiveAlarmsStatus?.minor\"\n >\n <i [c8yIcon]=\"'high-priority'\" class=\"status minor stroked-icon\"></i>\n <span class=\"badge badge-info\">{{ context.item.c8y_ActiveAlarmsStatus?.minor }}</span>\n </span>\n <span\n class=\"c8y-icon-badge\"\n title=\"{{ context.item.c8y_ActiveAlarmsStatus?.warning }} {{ 'Warning alarms' | translate }}\"\n *ngIf=\"context.item.c8y_ActiveAlarmsStatus?.warning\"\n >\n <i [c8yIcon]=\"'info-circle'\" class=\"status warning stroked-icon\"></i>\n <span class=\"badge badge-info\">{{ context.item.c8y_ActiveAlarmsStatus?.warning }}</span>\n </span>\n</a>\n" }]
}], ctorParameters: () => [{ type: i1$1.CellRendererContext }, { type: ColumnUtilService }] });
class AlarmsHeaderCellRendererComponent {
constructor(context) {
this.context = context;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AlarmsHeaderCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: AlarmsHeaderCellRendererComponent, isStandalone: true, selector: "c8y-alarms-header-cell-renderer", ngImport: i0, template: `
<div class="d-flex">
<span class="text-truncate" [title]="context.property.header | translate">
{{ context.property.header | translate }}
</span>
<button
class="btn-help btn-help--sm a-s-center"
[attr.aria-label]="'Help' | translate"
[popover]="'Only includes alarms for the parent device.' | translate"
placement="bottom"
triggers="focus"
container="body"
type="button"
(click)="$event.stopPropagation()"
>
<i c8yIcon="question-circle-o"></i>
</button>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AlarmsHeaderCellRendererComponent, decorators: [{
type: Component,
args: [{
template: `
<div class="d-flex">
<span class="text-truncate" [title]="context.property.header | translate">
{{ context.property.header | translate }}
</span>
<button
class="btn-help btn-help--sm a-s-center"
[attr.aria-label]="'Help' | translate"
[popover]="'Only includes alarms for the parent device.' | translate"
placement="bottom"
triggers="focus"
container="body"
type="button"
(click)="$event.stopPropagation()"
>
<i c8yIcon="question-circle-o"></i>
</button>
</div>
`,
selector: 'c8y-alarms-header-cell-renderer',
imports: [PopoverDirective, IconDirective, C8yTranslatePipe]
}]
}], ctorParameters: () => [{ type: i1$1.CellRendererContext }] });
class AlarmsDeviceGridColumn extends BaseColumn {
constructor(initialColumnConfig) {
super(initialColumnConfig);
this.name = 'alarms';
this.header = gettext('Alarms');
this.headerCellRendererComponent = AlarmsHeaderCellRendererComponent;
this.cellRendererComponent = AlarmsCellRendererComponent;
this.filterable = true;
this.filteringConfig = {
fields: [
{
type: 'object',
key: 'alarm',
templateOptions: {
label: 'Show items'
},
fieldGroup: [
{
key: 'critical',
type: 'switch',
props: {
label: gettext('With active critical alarms')
}
},
{
key: 'major',
type: 'switch',
props: {
label: gettext('With active major alarms')
}
},
{
key: 'minor',
type: 'switch',
props: {
label: gettext('With active minor alarms')
}
},
{
key: 'warning',
type: 'switch',
props: {
label: gettext('With active warnings')
}
},
{
key: 'none',
type: 'switch',
props: {
label: gettext('With no active alarms or warnings')
}
}
],
validators: {
atLeastOneSelected: {
expression: control => {
const alarmGroup = control.value;
return (alarmGroup.critical ||
alarmGroup.major ||
alarmGroup.minor ||
alarmGroup.warning ||
alarmGroup.none);
}
}
}
}
],
formGroup: new FormGroup({}),
getFilter: model => {
const filter = {};
const ors = [];
if (model.alarm.critical) {
ors.push({ 'c8y_ActiveAlarmsStatus.critical': { __gt: 0 } });
}
if (model.alarm.major) {
ors.push({ 'c8y_ActiveAlarmsStatus.major': { __gt: 0 } });
}
if (model.alarm.minor) {
ors.push({ 'c8y_ActiveAlarmsStatus.minor': { __gt: 0 } });
}
if (model.alarm.warning) {
ors.push({ 'c8y_ActiveAlarmsStatus.warning': { __gt: 0 } });
}
if (model.alarm.none) {
ors.push({ __not: { __has: 'c8y_ActiveAlarmsStatus' } });
ors.push({
__and: map(['critical', 'major', 'minor', 'warning'], sev => {
const zero = {};
const has = { __not: { __has: undefined } };
const key = `c8y_ActiveAlarmsStatus.${sev}`;
zero[key] = 0;
has.__not.__has = key;
return { __or: [zero, has] };
})
});
}
if (ors.length) {
filter.__or = ors;
}
return filter;
}
};
this.sortable = true;
this.sortingConfig = {
pathSortingConfigs: [
{ path: 'c8y_ActiveAlarmsStatus.critical' },
{ path: 'c8y_ActiveAlarmsStatus.major' },
{ path: 'c8y_ActiveAlarmsStatus.minor' },
{ path: 'c8y_ActiveAlarmsStatus.warning' }
]
};
}
}
class GroupCellRendererComponent {
constructor(context, columnUtilService) {
this.context = context;
this.columnUtilService = columnUtilService;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: GroupCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }, { token: ColumnUtilService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: GroupCellRendererComponent, isStandalone: true, selector: "c8y-group-cell-renderer", ngImport: i0, template: "<span\n title=\"{{\n columnUtilService.getParentsNames(\n context.item,\n context.property.externalFilterQuery?.deviceGroupId\n )\n }}\"\n>\n {{\n columnUtilService.getParentsNames(\n context.item,\n context.property.externalFilterQuery?.deviceGroupId\n )\n }}\n</span>\n" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: GroupCellRendererComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-group-cell-renderer', template: "<span\n title=\"{{\n columnUtilService.getParentsNames(\n context.item,\n context.property.externalFilterQuery?.deviceGroupId\n )\n }}\"\n>\n {{\n columnUtilService.getParentsNames(\n context.item,\n context.property.externalFilterQuery?.deviceGroupId\n )\n }}\n</span>\n" }]
}], ctorParameters: () => [{ type: i1$1.CellRendererContext }, { type: ColumnUtilService }] });
class GroupFilteringFormRendererComponent {
constructor(context) {
this.context = context;
this.preselected = [];
this.initialSelection = [];
this.isApplyDisabled = true;
}
onEnterKeyUp(event) {
event.stopPropagation();
this.applyFilter();
}
onEscapeKeyDown(event) {
event.stopPropagation();
this.resetFilter();
}
ngOnInit() {
const column = this.context.property;
this.model = cloneDeep(column.externalFilterQuery || {});
this.preselected = this.model.selectedNodes || [];
this.initialSelection = [...this.preselected];
}
ngAfterViewInit() {
setTimeout(() => {
try {
this.assetSelector.nativeElement.querySelector('input').focus();
}
catch (ex) {
// intended empty
}
}, 250);
}
applyFilter() {
this.context.applyFilter({
externalFilterQuery: this.model
});
this.isApplyDisabled = true; // Disable button after applying the filter
this.initialSelection = [...this.model.selectedNodes]; // Update initial selection
}
resetFilter() {
this.context.resetFilter();
this.model.selectedNodes = [];
this.preselected = [];
this.isApplyDisabled = true; // Disable button after resetting the filter
}
selectionChanged(nodes) {
this.model.selectedNodes = nodes.items;
this.isApplyDisabled = !this.isSelectionChanged();
}
isSelectionChanged() {
if (this.model.selectedNodes.length !== this.initialSelection.length) {
return true;
}
const currentSelectionSet = new Set(this.model.selectedNodes);
for (const item of this.initialSelection) {
if (!currentSelectionSet.has(item)) {
return true;
}
}
return false;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: GroupFilteringFormRendererComponent, deps: [{ token: i1$1.FilteringFormRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: GroupFilteringFormRendererComponent, isStandalone: true, selector: "ng-component", host: { listeners: { "keyup.enter": "onEnterKeyUp($event)", "keydown.escape": "onEscapeKeyDown($event)" } }, viewQueries: [{ propertyName: "assetSelector", first: true, predicate: ["assetSelector"], descendants: true, read: ElementRef }], ngImport: i0, template: "<c8y-asset-selector\n class=\"bg-component\"\n #assetSelector\n [config]=\"{\n groupsOnly: true,\n multi: true,\n groupsSelectable: true,\n search: true,\n label: ''\n }\"\n [selected]=\"preselected\"\n (onSelected)=\"selectionChanged($event)\"\n></c8y-asset-selector>\n\n<div class=\"data-grid__dropdown__footer d-flex separator-top\">\n <button\n class=\"btn btn-default btn-sm m-r-8 flex-grow\"\n title=\"{{ 'Reset' | translate }}\"\n (click)=\"resetFilter()\"\n translate\n >\n Reset\n </button>\n\n <button\n class=\"btn btn-primary btn-sm flex-grow\"\n title=\"{{ 'Apply' | translate }}\"\n (click)=\"applyFilter()\"\n [disabled]=\"isApplyDisabled\"\n translate\n >\n Apply\n </button>\n</div>\n", dependencies: [{ kind: "component", type: AssetSelectorComponent, selector: "c8y-asset-selector", inputs: ["config", "active", "index", "asset", "selectedDevice", "selected", "rootNode", "selectedItems", "container", "isNodeSelectable", "disabled"], outputs: ["onSelected", "onClearSelected", "onRowSelected", "onLoad"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: GroupFilteringFormRendererComponent, decorators: [{
type: Component,
args: [{ imports: [AssetSelectorComponent, C8yTranslateDirective, C8yTranslatePipe], template: "<c8y-asset-selector\n class=\"bg-component\"\n #assetSelector\n [config]=\"{\n groupsOnly: true,\n multi: true,\n groupsSelectable: true,\n search: true,\n label: ''\n }\"\n [selected]=\"preselected\"\n (onSelected)=\"selectionChanged($event)\"\n></c8y-asset-selector>\n\n<div class=\"data-grid__dropdown__footer d-flex separator-top\">\n <button\n class=\"btn btn-default btn-sm m-r-8 flex-grow\"\n title=\"{{ 'Reset' | translate }}\"\n (click)=\"resetFilter()\"\n translate\n >\n Reset\n </button>\n\n <button\n class=\"btn btn-primary btn-sm flex-grow\"\n title=\"{{ 'Apply' | translate }}\"\n (click)=\"applyFilter()\"\n [disabled]=\"isApplyDisabled\"\n translate\n >\n Apply\n </button>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1$1.FilteringFormRendererContext }], propDecorators: { assetSelector: [{
type: ViewChild,
args: ['assetSelector', { static: false, read: ElementRef }]
}], onEnterKeyUp: [{
type: HostListener,
args: ['keyup.enter', ['$event']]
}], onEscapeKeyDown: [{
type: HostListener,
args: ['keydown.escape', ['$event']]
}] } });
class GroupDeviceGridColumn extends BaseColumn {
constructor(initialColumnConfig) {
super(initialColumnConfig);
this.name = 'group';
this.header = gettext('Group');
this.cellRendererComponent = GroupCellRendererComponent;
this.filteringFormRendererComponent = GroupFilteringFormRendererComponent;
this.filterable = true;
this.filteringConfig = {
generateChips(model) {
if (model.selectedNodes) {
return model.selectedNodes.map(mo => ({
displayValue: mo.name,
value: mo,
remove() {
const { externalFilterQuery, columnName, value } = this;
const nodes = externalFilterQuery.selectedNodes.filter(node => node.id !== value.id);
return {
externalFilterQuery: { selectedNodes: nodes },
columnName: columnName
};
}
}));
}
},
getFilter(model) {
const filter = {};
if (model.selectedNodes) {
filter.__or = model.selectedNodes.map((mo) => {
if (mo.c8y_DeviceQueryString) {
return { __useFilterQueryString: mo.c8y_DeviceQueryString };
}
return { __bygroupid: mo.id };
});
}
return filter;
}
};
this.sortable = false;
}
}
class ImeiDeviceGridColumn extends BaseColumn {
constructor(initialColumnConfig) {
super(initialColumnConfig);
this.path = 'c8y_Mobile.imei';
this.name = 'imei';
this.header = gettext('IMEI');
this.filterable = true;
this.filteringConfig = {
fields: getBasicInputArrayFormFieldConfig({
key: 'imeis',
label: gettext('Show items with IMEI'),
addText: gettext('Add next`IMEI`'),
tooltip: gettext('Use * as a wildcard character'),
placeholder: '46543432321'
}),
getFilter: (model) => {
const filter = {};
if (model.imeis.length) {
filter[this.path] = { __in: model.imeis };
}
return filter;
}
};
this.sortable = true;
this.sortingConfig = {
pathSortingConfigs: [{ path: this.path }]
};
}
}
class ModelCellRendererComponent {
constructor(context, columnUtilService) {
this.context = context;
this.columnUtilService = columnUtilService;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ModelCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }, { token: ColumnUtilService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ModelCellRendererComponent, isStandalone: true, selector: "c8y-model-cell-renderer", ngImport: i0, template: ` {{ columnUtilService.getModel(context.item) }} `, isInline: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ModelCellRendererComponent, decorators: [{
type: Component,
args: [{
template: ` {{ columnUtilService.getModel(context.item) }} `,
selector: 'c8y-model-cell-renderer'
}]
}], ctorParameters: () => [{ type: i1$1.CellRendererContext }, { type: ColumnUtilService }] });
class ModelDeviceGridColumn extends BaseColumn {
constructor(initialColumnConfig) {
super(initialColumnConfig);
const hardwareModelPath = 'c8y_Hardware.model';
this.name = 'model';
this.header = gettext('Model');
this.cellRendererComponent = ModelCellRendererComponent;
this.filterable = true;
this.filteringConfig = {
fields: getBasicInputArrayFormFieldConfig({
key: 'models',
label: gettext('Show items with model'),
addText: gettext('Add next`model`'),
tooltip: gettext('Use * as a wildcard character'),
placeholder: 'NTC-220'
}),
getFilter(model) {
const filter = {};
if (model.models.length) {
filter.push = {
[hardwareModelPath]: { __in: model.models }
};
}
return filter;
}
};
this.sortable = true;
this.sortingConfig = {
pathSortingConfigs: [{ path: hardwareModelPath }]
};
}
}
class NameCellRendererComponent {
constructor(context, columnUtilService) {
this.context = context;
this.columnUtilService = columnUtilService;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NameCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }, { token: ColumnUtilService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: NameCellRendererComponent, isStandalone: true, selector: "c8y-name-cell-renderer", ngImport: i0, template: `
<a
class="interact"
title="{{ columnUtilService.getProperName(context.item) }}"
[href]="columnUtilService.getHref(context.item)"
>
{{ columnUtilService.getProperName(context.item) }}
</a>
`, isInline: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NameCellRendererComponent, decorators: [{
type: Component,
args: [{
template: `
<a
class="interact"
title="{{ columnUtilService.getProperName(context.item) }}"
[href]="columnUtilService.getHref(context.item)"
>
{{ columnUtilService.getProperName(context.item) }}
</a>
`,
selector: 'c8y-name-cell-renderer'
}]
}], ctorParameters: () => [{ type: i1$1.CellRendererContext }, { type: ColumnUtilService }] });
class NameDeviceGridColumn extends BaseColumn {
constructor(initialColumnConfig) {
super(initialColumnConfig);
this.name = 'name';
this.path = 'name';
this.header = gettext('Name');
this.cellCSSClassName = "data-record-header" /* ColumnDataRecordClassName.Header */;
this.cellRendererComponent = NameCellRendererComponent;
this.filterable = true;
this.filteringConfig = {
fields: getBasicInputArrayFormFieldConfig({
key: 'names',
label: gettext('Show items with name'),
addText: gettext('Add next`name`'),
tooltip: gettext('Use * as a wildcard character'),
placeholder: gettext('My device`DEVICE_NAME`')
}),
getFilter(model) {
const filter = {};
if (model.names.length) {
filter.name = { __in: model.names };
}
return filter;
}
};
this.sortable = true;
this.sortingConfig = {
pathSortingConfigs: [{ path: this.path }]
};
}
}
class RegistrationDateCellRendererComponent {
constructor(context) {
this.context = context;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: RegistrationDateCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: RegistrationDateCellRendererComponent, isStandalone: true, selector: "c8y-registration-date-cell-renderer", ngImport: i0, template: ` {{ context.value | c8yDate }} `, isInline: true, dependencies: [{ kind: "pipe", type: DatePipe, name: "c8yDate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: RegistrationDateCellRendererComponent, decorators: [{
type: Component,
args: [{
template: ` {{ context.value | c8yDate }} `,
selector: 'c8y-registration-date-cell-renderer',
imports: [DatePipe]
}]
}], ctorParameters: () => [{ type: i1$1.CellRendererContext }] });
class RegistrationDateDeviceGridColumn extends BaseColumn {
constructor(initialColumnConfig) {
super(initialColumnConfig);
this.path = 'creationTime';
this.name = 'registrationDate';
this.header = gettext('Registration date');
this.cellRendererComponent = RegistrationDateCellRendererComponent;
this.filterable = true;
this.filteringConfig = {
fields: [
{
type: 'object',
key: 'registrationDate',
templateOptions: {
label: gettext('Show items registered`between dates`')
},
fieldGroup: [
{
type: 'date-time',
key: 'after',
templateOptions: {
label: gettext('from`date`')
},
expressionProperties: {
'templateOptions.maxDate': (model) => model?.before
}
},
{
type: 'date-time',
key: 'before',
templateOptions: {
label: gettext('to`date`')
},
expressionProperties: {
'templateOptions.minDate': (model) => model?.after
}
}
],
validators: {
atLeastOneFilled: {
expression: (formGroup) => {
const after = formGroup.get('after').value;
const before = formGroup.get('before').value;
return after || before;
}
}
}
}
],
formGroup: new FormGroup({}),
getFilter: model => {
const filter = {};
const dates = model && model.registrationDate;
if (dates && (dates.after || dates.before)) {
filter.__and = [];
if (dates.after) {
const after = this.formatDate(dates.after);
filter.__and.push({
'creationTime.date': { __gt: after }
});
}
if (dates.before) {
const before = this.formatDate(dates.before);
filter.__and.push({
'creationTime.date': { __lt: before }
});
}
}
return filter;
}
};
this.sortable = true;
this.sortingConfig = {
pathSortingConfigs: [{ path: 'creationTime.date' }]
};
}
formatDate(dateToFormat) {
return new Date(dateToFormat).toISOString();
}
}
class SerialNumberCellRendererComponent {
constructor(context, columnUtilService) {
this.context = context;
this.columnUtilService = columnUtilService;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SerialNumberCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }, { token: ColumnUtilService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SerialNumberCellRendererComponent, isStandalone: true, selector: "c8y-serial-number-cell-renderer", ngImport: i0, template: ` {{ columnUtilService.getSerialNumber(context.item) }} `, isInline: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SerialNumberCellRendererComponent, decorators: [{
type: Component,
args: [{
template: ` {{ columnUtilService.getSerialNumber(context.item) }} `,
selector: 'c8y-serial-number-cell-renderer'
}]
}], ctorParameters: () => [{ type: i1$1.CellRendererContext }, { type: ColumnUtilService }] });
class SerialNumberDeviceGridColumn extends BaseColumn {
constructor(initialColumnConfig) {
super(initialColumnConfig);
const hardwareSerialNumberPath = 'c8y_Hardware.serialNumber';
this.name = 'serialNumber';
this.header = gettext('Serial number');
this.cellRendererComponent = SerialNumberCellRendererComponent;
this.filterable = true;
this.filteringConfig = {
fields: getBasicInputArrayFormFieldConfig({
key: 'serialNumbers',
label: gettext('Show items with serial number'),
addText: gettext('Add next`serial number`'),
tooltip: gettext('Use * as a wildcard character'),
placeholder: '54321-123'
}),
getFilter(model) {
const filter = {};
if (model.serialNumbers.length) {
filter.push = {
[hardwareSerialNumberPath]: { __in: model.serialNumbers }
};
}
return filter;
}
};
this.sortable = true;
this.sortingConfig = {
pathSortingConfigs: [{ path: hardwareSerialNumberPath }]
};
}
}
class DeviceStatusCellRendererComponent {
constructor(context) {
this.context = context;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceStatusCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DeviceStatusCellRendererComponent, isStandalone: true, selector: "c8y-device-status-cell-renderer", ngImport: i0, template: ` <device-status [mo]="context.item"></device-status> `, isInline: true, dependencies: [{ kind: "component", type: DeviceStatusComponent, selector: "device-status, c8y-device-status", inputs: ["mo", "size"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceStatusCellRendererComponent, decorators: [{
type: Component,
args: [{
template: ` <device-status [mo]="context.item"></device-status> `,
selector: 'c8y-device-status-cell-renderer',
imports: [DeviceStatusComponent]
}]
}], ctorParameters: () => [{ type: i1$1.CellRendererContext }] });
class StatusDeviceGridColumn extends BaseColumn {
constructor() {
super();
const responseIntervalPath = 'c8y_RequiredAvailability.responseInterval';
const responseIntervalLessThanOrEqualTo0 = { [responseIntervalPath]: { __le: 0 } };
const responseIntervalNotDefined = { __not: { __has: responseIntervalPath } };
const availabilityStatusPath = 'c8y_Availability.status';
const availabilityStatusAvailable = { [availabilityStatusPath]: SendStatus.AVAILABLE };
const availabilityStatusUnavailable = { [availabilityStatusPath]: SendStatus.UNAVAILABLE };
const availabilityStatusMaintenance = { [availabilityStatusPath]: SendStatus.MAINTENANCE };
const availabilityStatusNotDefined = { __not: { __has: availabilityStatusPath } };
const connectionStatusPath = 'c8y_Connection.status';
const connectionStatusConnected = { [connectionStatusPath]: PushStatus.CONNECTED };
const connectionStatusDisconnected = { [connectionStatusPath]: PushStatus.DISCONNECTED };
const connectionStatusMaintenance = { [connectionStatusPath]: PushStatus.MAINTENANCE };
const deviceUnderMaintenance = {
__or: [
responseIntervalLessThanOrEqualTo0,
availabilityStatusMaintenance,
connectionStatusMaintenance
]
};
const deviceNotUnderMaintenance = {
// using __and of __nots because backend does not support __not with __ors
__and: [
{ __not: responseIntervalLessThanOrEqualTo0 },
{ __not: availabilityStatusMaintenance },
{ __not: connectionStatusMaintenance }
]
};
this.name = 'status';
this.header = gettext('Status');
this.dataType = "icon" /* ColumnDataType.Icon */;
this.cellRendererComponent = DeviceStatusCellRendererComponent;
this.resizable = false;
this.filterable = true;
this.filteringConfig = {
fields: [
{
type: 'object',
templateOptions: {
label: 'Show items with status'
},
fieldGroup: [
{
key: 'sendStatus',
type: 'object',
props: {
label: gettext('Send status')
},
fieldGroup: [
{
key: 'sendOnline',
type: 'switch',
props: { label: gettext('Online') }
},
{
key: 'sendOffline',
type: 'switch',
props: { label: gettext('Offline') }
},
{
key: 'sendUnknown',
type: 'switch',
props: { label: gettext('Unknown') }
},
{
key: 'sendNotMonitored',
type: 'switch',
props: { label: gettext('Not monitored') }
}
]
},
{
key: 'pushStatus',
type: 'object',
props: {
label: gettext('Push status')
},
fieldGroup: [
{
key: 'pushOnline',
type: 'switch',
props: { label: gettext('Online') }
},
{
key: 'pushOffline',
type: 'switch',
props: { label: gettext('Offline') }
},
{
key: 'pushNotMonitored',
type: 'switch',
props: { label: gettext('Not monitored') }
}
]
},
{
key: 'maintenanceStatus',
type: 'object',
props: {
label: gettext('Maintenance status')
},
fieldGroup: [
{
key: 'maintenance',
type: 'switch',
props: { label: gettext('Device is under maintenance') }
}
]
}
],
validators: {
atLeastOneFilled: {
expression: (formGroup) => {
const sendStatus = formGroup.get('sendStatus').value || {};
const pushStatus = formGroup.get('pushStatus').value || {};
const maintenanceStatus = formGroup.get('maintenanceStatus').value || {};
return (sendStatus.sendOnline ||
sendStatus.sendOffline ||
sendStatus.sendUnknown ||
sendStatus.sendNotMonitored ||
pushStatus.pushOnline ||
pushStatus.pushOffline ||
pushStatus.pushNotMonitored ||
maintenanceStatus.maintenance);
}
}
}
}
],
formGroup: new FormGroup({}),
getFilter(model) {
const filter = {};
const ors = [];
if (model?.sendStatus?.sendOnline) {
ors.push({
__and: [deviceNotUnderMaintenance, availabilityStatusAvailable]
});
}
if (model?.sendStatus?.sendOffline) {
ors.push({
__and: [deviceNotUnderMaintenance, availabilityStatusUnavailable]
});
}
if (model?.sendStatus?.sendUnknown) {
ors.push({
__and: [deviceNotUnderMaintenance, availabilityStatusNotDefined]
});
}
if (model?.sendStatus?.sendNotMonitored || model?.pushStatus?.pushNotMonitored) {
ors.push(responseIntervalNotDefined);
}
if (model?.pushStatus?.pushOnline) {
ors.push({
__and: [deviceNotUnderMaintenance, connectionStatusConnected]
});
}
if (model?.pushStatus?.pushOffline) {
ors.push({
__and: [deviceNotUnderMaintenance, connectionStatusDisconnected]
});
}
if (model?.maintenanceStatus?.maintenance) {
ors.push(deviceUnderMaintenance);
}
if (ors.length) {
filter.__or = ors;
}
return filter;
}
};
this.sortable = true;
this.sortingConfig = {
pathSortingConfigs: [{ path: availabilityStatusPath }]
};
}
}
class SystemIdDeviceGridColumn extends BaseColumn {
constructor(initialColumnConfig) {
super(initialColumnConfig);
this.path = 'id';
this.name = 'systemId';
this.header = gettext('System ID');
this.filterable = true;
this.filteringConfig = {
fields: getBasicInputArrayFormFieldConfig({
key: 'ids',
label: gettext('Show items with system ID'),
addText: gettext('Add next`id`'),
tooltip: gettext('Use * as a wildcard character'),
placeholder: '10300'
}),
getFilter: (model) => {
const filter = {};
if (model.ids.length) {
filter[this.path] = { __in: model.ids };
}
return filter;
}
};
this.sortable = true;
this.sortingConfig = {
pathSortingConfigs: [{ path: this.path }]
};
}
}
class TypeDeviceGridColumn extends BaseColumn {
constructor(initialColumnConfig) {
super(initialColumnConfig);
this.name = 'type';
this.path = 'type';
this.header = gettext('Type');
this.filterable = true;
this.filteringConfig = {
fields: getBasicInputArrayFormFieldConfig({
key: 'types',
label: gettext('Show devices with type'),
addText: gettext('Add next`type`'),
tooltip: gettext('Use * as a wildcard character'),
placeholder: gettext('MyType`DEVICE_TYPE`')
}),
getFilter(model) {
const filter = {};
if (model.types.length) {
filter.type = { __in: model.types };
}
return filter;
}
};
this.sortable = true;
this.sortingConfig = { pathSortingConfigs: [{ path: 'type' }] };
}
}
class IconDeviceGridColumnComponent {
constructor(context) {
const propertyAsIconColumn = context.property;
if (propertyAsIconColumn && typeof propertyAsIconColumn.iconRetriever === 'function') {
this.icon = propertyAsIconColumn.iconRetriever(context);
}
else {
this.icon = context.value;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: IconDeviceGridColumnComponent, deps: [{ token: i1$1.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: IconDeviceGridColumnComponent, isStandalone: true, selector: "c8y-icon-device-grid-column", ngImport: i0, template: `<i [c8yIcon]="icon"></i>`, isInline: true, dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: IconDeviceGridColumnComponent, decorators: [{
type: Component,
args: [{
selector: 'c8y-icon-device-grid-column',
standalone: true,
imports: [IconDirective],
template: `<i [c8yIcon]="icon"></i>`
}]
}], ctorParameters: () => [{ type: i1$1.CellRendererContext }] });
class IconDeviceGridColumn extends BaseColumn {
constructor(options = {}, iconRetriever) {
super(options);
this.iconRetriever = iconRetriever;
this.dataType = "icon" /* ColumnDataType.Icon */;
this.name = 'icon';
this.path = 'icon';
this.filterable = false;
this.resizable = false;
this.header = gettext$1('Icon');
this.cellRendererComponent = IconDeviceGridColumnComponent;
Object.assign(this, options);
}
}
class DeviceGridService extends DataGridService {
constructor(inventoryService, userService, translateService, alertService, modal, columnUtilService, userPreferencesService) {
super(userPreferencesService);
this.inventoryService = inventoryService;
this.userService = userService;
this.translateService = translateService;
this.alertService = alertService;
this.modal = modal;
this.columnUtilService = columnUtilService;
this.userPreferencesService = userPreferencesService;
this.GRID_CONFIG_DEFAULT_STORAGE_KEY = 'device-grid-config';
}
getDefaultColumns() {
const defaultColumns = [
new StatusDeviceGridColumn(),
new NameDeviceGridColumn(),
new ModelDeviceGridColumn(),
new SerialNumberDeviceGridColumn(),
new GroupDeviceGridColumn(),
new RegistrationDateDeviceGridColumn(),
new SystemIdDeviceGridColumn(),
new ImeiDeviceGridColumn(),
new AlarmsDeviceGridColumn()
];
return defaultColumns;
}
getChildDeviceGridColumns() {
const childDeviceGridColumn = [
new StatusDeviceGridColumn(),
new NameDeviceGridColumn(),
new ModelDeviceGridColumn(),
new SerialNumberDeviceGridColumn(),
new RegistrationDateDeviceGridColumn(),
new SystemIdDeviceGridColumn(),
new ImeiDeviceGridColumn(),
new AlarmsDeviceGridColumn()
];
return childDeviceGridColumn;
}
getDefaultPagination() {
return {
pageSize: 25,
currentPage: 1
};
}
getInfiniteScrollPagination() {
return {
pageSize: 50,
currentPage: 1
};
}
getDefaultBulkActionControls() {
return [];
}
getDefaultHeaderActionControls() {
return [];
}
getProperName(device) {
return this.columnUtilService.getProperName(device);
}
getModel(device) {
return this.columnUtilService.getModel(device);
}
getSerialNumber(device) {
return this.columnUtilService.getSerialNumber(device);
}
getParentsNames(device, featuredParentId) {
return this.columnUtilService.getParentsNames(device, featuredParentId);
}
getHref(groupOrDevice, prefix = '#/') {
return this.columnUtilService.getHref(groupOrDevice, prefix);
}
getAlarmsHref(device) {
return this.columnUtilService.getAlarmsHref(device);
}
async delete(device) {
try {
const deviceWithChildren = await (await this.inventoryService.detail(device, { withChildren: true })).data;
const hasChildDevices = deviceWithChildren.childDevices?.references?.length > 0;
const hasChildAdditions = deviceWithChildren.childAdditions?.references?.length > 0;
const hasChildAssets = deviceWithChildren.childAssets?.references?.length > 0;
const showDeleteChildren = () => hasChildAdditions || hasChildDevices || hasChildAssets;
const modalResult = await this.modal.confirm(gettext('Delete device'), this.translateService.instant(gettext(`You are about to delete device "{{ name }}". Do you want to proceed?`), device), Status.DANGER, { ok: gettext('Delete'), cancel: gettext('Cancel') }, {
cascade: {
text: gettext('Also delete child hierarchy of this device.'),
checked: showDeleteChildren(),
showIf: showDeleteChildren,
disabledByKey: 'withDeviceUser'
},
withDeviceUser: {
text: this.translateService.instant(gettext('Also delete associated device owner "{{ owner }}".'), device),
checked: false,
showIf: () => {
const isRootDevice = device.c8y_IsDevice;
const hasDeviceUserAsOwner = device.owner &&
this.userService.isDeviceUser({ id: device.owner });
return Boolean(isRootDevice && hasDeviceUserAsOwner);
},
disabledByKey: 'cascade'
}
});
await this.inventoryService.delete(device, modalResult.confirmOptions);
this.alertService.success(gettext('Device deleted.'));
return Promise.resolve();
}
catch (ex) {
// only if not cancel from modal
if (ex) {
this.alertService.addServerFailure(ex);
}
return Promise.reject();
}
}
async getData(columns, pagination, query = {}, withChildren = false, text = null) {
const filters = {
...this.getDevicesFilters(columns, pagination, query, false, text),
withGroups: true,
withChildren,
withTotalElements: true
};
return this.inventoryService.list(filters);
}
async getChildDeviceData(columns, pagination, query = {}, withChildren = false, id) {
const childDeviceFilters = true;
const filters = {
...this.getDevicesFilters(columns, pagination, query, childDeviceFilters),
withGroups: true,
withChildren
};
return this.inventoryService.childDevicesList(id, filters);
}
async getCount(columns, pagination, query = {}, text = null) {
const filters = {
...this.getDevicesFilters(columns, pagination, query, false, text),
withTotalElements: true
};
return (await this.inventoryService.list(filters)).paging.totalElements;
}
async getCountChildDevices(columns, pagination, query = {}, id) {
const childDeviceFilters = true;
const filters = {
...this.getDevicesFilters(columns, pagination, query, childDeviceFilters),
withTotalElements: true
};
return (await this.inventoryService.childDevicesList(id, filters)).paging.totalElements;
}
async getTotalChildDevices(query = {}, id) {
const filters = {
q: this.queriesUtil.buildQuery(query),
withTotalElements: true
};
return (await this.inventoryService.childDevicesList(id, filters)).paging.totalElements;
}
async getTotal(query = {}) {
const filters = {
q: this.queriesUtil.buildQuery(query),
withTotalElements: true
};
return (await this.inventoryService.list(filters)).paging.totalElements;
}
getDeviceQueryString(columns, query) {
let fullQuery = this.getQueryObj(columns);
fullQuery = this.queriesUtil.addAndFilter(fullQuery, query);
return this.queriesUtil.buildQuery(fullQuery);
}
clearConfig(key = this.GRID_CONFIG_DEFAULT_STORAGE_KEY) {
super.clearConfig(key);
}
getConfig$(key = this.GRID_CONFIG_DEFAULT_STORAGE_KEY) {
return super.getConfig$(key);
}
saveConfig$(config, key = this.GRID_CONFIG_DEFAULT_STORAGE_KEY) {
return super.saveConfig$(config, key);
}
getDevicesFilters(columns, pagination, query, childDeviceFilters, text) {
return {
...(childDeviceFilters
? { query: this.getDeviceQueryString(columns, query) }
: { q: this.getDeviceQueryString(columns, query) }),
...(text && { text }),
pageSize: pagination.pageSize,
currentPage: pagination.currentPage,
withChildren: false,
withTotalPages: true
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceGridService, deps: [{ token: i1$2.InventoryService }, { token: i1$2.UserService }, { token: i1.TranslateService }, { token: i1$1.AlertService }, { token: i1$1.ModalService }, { token: ColumnUtilService }, { token: i1$1.UserPreferencesService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceGridService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceGridService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1$2.InventoryService }, { type: i1$2.UserService }, { type: i1.TranslateService }, { type: i1$1.AlertService }, { type: i1$1.ModalService }, { type: ColumnUtilService }, { type: i1$1.UserPreferencesService }] });
class DeviceGridComponent {
/** Pagination settings, e.g. allows for setting current page or page size. If not given, defaults to standard settings. */
set _pagination(value) {
if (value) {
this.pagination = value;
}
}
/** Sets load more mode. */
set _infiniteScroll(infiniteScroll) {
this.infiniteScroll = infiniteScroll;
if (infiniteScroll) {
this.pagination = this.deviceGridService.getInfiniteScrollPagination();
}
}
/** Sets action controls (actions available for individual items). If not given, it defaults to standard actions. */
set _actionControls(value) {
this.actionControls = value;
}
/** Sets bulk action controls (actions available for items selected by user). If not given, it defaults to standard bulk actions. */
set _bulkActionControls(value) {
if (value) {
this.bulkActionControls = value;
}
else {
this.bulkActionControls = this.deviceGridService.getDefaultBulkActionControls();
}
}
/** Sets header action controls (actions available from the grid header). If not given, it defaults to empty list of actions. */
set _headerActionControls(value) {
if (value) {
this.headerActionControls = value;
}
else {
this.headerActionControls = this.deviceGridService.getDefaultHeaderActionControls();
}
}
constructor(deviceGridService) {
this.deviceGridService = deviceGridService;
/** Takes an event emitter. When an event is emitted, the grid will be reloaded. */
this.refresh = new EventEmitter();
/** The title for the data grid, it's displayed in the grid's header. */
this.title = gettext('Devices');
/** The label for load more button. */
this.loadMoreItemsLabel = gettext('Load more devices');
/** The label for loading indicator. */
this.loadingItemsLabel = gettext('Loading devices…');
/** The list of columns to be displayed in the grid. If not given, it defaults to standard columns. */
this.columns = this.deviceGridService.getDefaultColumns();
/** Determines whether items can be selected by clicking a checkbox in the first column. */
this.selectable = false;
/** Restricts selection to a single row only. Selection column displays radio button instead of checkboxes */
this.singleSelection = false;
/** Sets the base query which is appended to the request for data. */
this.baseQuery = {};
this.childDeviceGrid = false;
/** Sets the withChildren query which is appended to the request. */
this.withChildren = false;
/**
* Enables the search for devices where any device propery is matched agains the search term.
* Enabled by default. This input does not take effect if the <code>childDeviceGrid</code> input is set to <code>true</code>
*/
this.showSearch = true;
/**
* Sets the class name used for active rows (last clicked).
* Set empty string to disable appending active class to grid rows.
*/
this.activeClassName = 'active';
/** Emits an event when columns configuration changes. */
this.onColumnsChange = new EventEmitter();
this.onFilterChange = new EventEmitter();
this.onDeviceQueryStringChange = new EventEmitter();
/** Emits an event when items selection changes. The array contains ids of selected items. */
this.itemsSelect = new EventEmitter();
this.actionControls = [];
this.appliedFilters = [];
this.pagination = this.deviceGridService.getDefaultPagination();
this.bulkActionControls = this.deviceGridService.getDefaultBulkActionControls();
this.headerActionControls = this.deviceGridService.getDefaultHeaderActionControls();
this.noResultsMessage = gettext('No matching devices.');
this.noDataMessage = gettext('No devices to display.');
this.noResultsSubtitle = gettext('Refine your search terms');
this.destroyed$ = new Subject();
this.serverSideDataCallback = this.onDataSourceModifier.bind(this);
}
ngOnDestroy() {
this.destroyed$.next();
this.destroyed$.complete();
}
trackByName(_index, column) {
return column.name;
}
async onDataSourceModifier(dataSourceModifier) {
let serverSideDataResult;
let filteredSize;
let size;
if (this.childDeviceGrid) {
const { res, data, paging } = await alertOnError(this.deviceGridService.getChildDeviceData(dataSourceModifier.columns, dataSourceModifier.pagination, this.baseQuery, this.withChildren, this.parentDeviceId));
filteredSize = await alertOnError(this.deviceGridService.getCountChildDevices(dataSourceModifier.columns, dataSourceModifier.pagination, this.baseQuery, this.parentDeviceId));
size = await alertOnError(this.deviceGridService.getTotalChildDevices(this.baseQuery, this.parentDeviceId));
serverSideDataResult = {
res,
data,
paging,
filteredSize,
size
};
}
else {
const { res, data, paging } = await alertOnError(this.deviceGridService.getData(dataSourceModifier.columns, dataSourceModifier.pagination, this.baseQuery, this.withChildren, dataSourceModifier.searchText));
filteredSize = await alertOnError(this.deviceGridService.getCount(dataSourceModifier.columns, dataSourceModifier.pagination, this.baseQuery, dataSourceModifier.searchText));
size = await alertOnError(this.deviceGridService.getTotal(this.baseQuery));
serverSideDataResult = {
res,
data,
paging,
filteredSize,
size
};
}
this.onColumnsChange.emit(dataSourceModifier.columns);
this.onDeviceQueryStringChange.emit(this.deviceGridService.getDeviceQueryString(dataSourceModifier.columns, this.baseQuery));
if (this.dataCallback) {
serverSideDataResult = this.dataCallback(serverSideDataResult);
}
return serverSideDataResult;
}
updateFiltering(columnNames, action) {
const { type } = action;
if (type === FilteringActionType.ResetFilter) {
this.dataGrid.clearFilters();
}
else {
this.dataGrid.updateFiltering(columnNames, action);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceGridComponent, deps: [{ token: DeviceGridService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DeviceGridComponent, isStandalone: true, selector: "c8y-device-grid", inputs: { dataCallback: "dataCallback", refresh: "refresh", title: "title", loadMoreItemsLabel: "loadMoreItemsLabel", loadingItemsLabel: "loadingItemsLabel", legacyConfigKey: "legacyConfigKey", legacyFilterKey: "legacyFilterKey", columns: "columns", _pagination: ["pagination", "_pagination"], _infiniteScroll: ["infiniteScroll", "_infiniteScroll"], _actionControls: ["actionControls", "_actionControls"], selectable: "selectable", singleSelection: "singleSelection", baseQuery: "baseQuery", _bulkActionControls: ["bulkActionControls", "_bulkActionControls"], _headerActionControls: ["headerActionControls", "_headerActionControls"], childDeviceGrid: "childDeviceGrid", parentDeviceId: "parentDeviceId", withChildren: "withChildren", showSearch: "showSearch", activeClassName: "activeClassName" }, outputs: { onColumnsChange: "onColumnsChange", onFilterChange: "onFilterChange", onDeviceQueryStringChange: "onDeviceQueryStringChange", itemsSelect: "itemsSelect" }, providers: [
{
provide: PRODUCT_EXPERIENCE_EVENT_SOURCE,
useExisting: forwardRef(() => DeviceGridComponent)
}
], viewQueries: [{ propertyName: "dataGrid", first: true, predicate: DataGridComponent, descendants: true, static: true }], ngImport: i0, template: "<c8y-data-grid\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [columns]=\"columns\"\n [pagination]=\"pagination\"\n [infiniteScroll]=\"infiniteScroll\"\n [actionControls]=\"actionControls\"\n [selectable]=\"selectable\"\n [singleSelection]=\"singleSelection\"\n [bulkActionControls]=\"bulkActionControls\"\n [serverSideDataCallback]=\"serverSideDataCallback\"\n (itemsSelect)=\"itemsSelect.emit($event)\"\n [refresh]=\"refresh\"\n [showSearch]=\"showSearch && !childDeviceGrid\"\n [headerActionControls]=\"headerActionControls\"\n [activeClassName]=\"activeClassName\"\n c8yProductExperience\n inherit\n>\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-device-management'\"\n [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : null\"\n *emptyStateContext=\"let stats\"\n [horizontal]=\"stats?.size > 0\"\n ></c8y-ui-empty-state>\n\n <ng-container *ngFor=\"let column of columns; trackBy: trackByName\">\n <c8y-column [name]=\"column.name\"></c8y-column>\n </ng-container>\n</c8y-data-grid>\n", dependencies: [{ kind: "component", type: DataGridComponent, selector: "c8y-data-grid", inputs: ["title", "loadMoreItemsLabel", "loadingItemsLabel", "showSearch", "refresh", "columns", "rows", "pagination", "childNodePagination", "infiniteScroll", "serverSideDataCallback", "selectable", "singleSelection", "selectionPrimaryKey", "displayOptions", "actionControls", "bulkActionControls", "headerActionControls", "searchText", "configureColumnsEnabled", "showCounterWarning", "activeClassName", "expandableRows", "treeGrid", "hideReload", "childNodesProperty", "parentNodeLabelProperty"], outputs: ["rowMouseOver", "rowMouseLeave", "rowClick", "onConfigChange", "onBeforeFilter", "onBeforeSearch", "onFilter", "itemsSelect", "onReload", "onAddCustomColumn", "onRemoveCustomColumn", "onColumnFilterReset", "onSort", "onPageSizeChange", "onColumnReordered", "onColumnVisibilityChange"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: EmptyStateContextDirective, selector: "[emptyStateContext]" }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: ColumnDirective, selector: "c8y-column", inputs: ["name"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceGridComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-device-grid', providers: [
{
provide: PRODUCT_EXPERIENCE_EVENT_SOURCE,
useExisting: forwardRef(() => DeviceGridComponent)
}
], imports: [
DataGridComponent,
ProductExperienceDirective,
EmptyStateContextDirective,
EmptyStateComponent,
NgFor,
ColumnDirective,
C8yTranslatePipe
], template: "<c8y-data-grid\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [columns]=\"columns\"\n [pagination]=\"pagination\"\n [infiniteScroll]=\"infiniteScroll\"\n [actionControls]=\"actionControls\"\n [selectable]=\"selectable\"\n [singleSelection]=\"singleSelection\"\n [bulkActionControls]=\"bulkActionControls\"\n [serverSideDataCallback]=\"serverSideDataCallback\"\n (itemsSelect)=\"itemsSelect.emit($event)\"\n [refresh]=\"refresh\"\n [showSearch]=\"showSearch && !childDeviceGrid\"\n [headerActionControls]=\"headerActionControls\"\n [activeClassName]=\"activeClassName\"\n c8yProductExperience\n inherit\n>\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-device-management'\"\n [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : null\"\n *emptyStateContext=\"let stats\"\n [horizontal]=\"stats?.size > 0\"\n ></c8y-ui-empty-state>\n\n <ng-container *ngFor=\"let column of columns; trackBy: trackByName\">\n <c8y-column [name]=\"column.name\"></c8y-column>\n </ng-container>\n</c8y-data-grid>\n" }]
}], ctorParameters: () => [{ type: DeviceGridService }], propDecorators: { dataCallback: [{
type: Input
}], refresh: [{
type: Input
}], title: [{
type: Input
}], loadMoreItemsLabel: [{
type: Input
}], loadingItemsLabel: [{
type: Input
}], legacyConfigKey: [{
type: Input
}], legacyFilterKey: [{
type: Input
}], columns: [{
type: Input,
args: ['columns']
}], _pagination: [{
type: Input,
args: ['pagination']
}], _infiniteScroll: [{
type: Input,
args: ['infiniteScroll']
}], _actionControls: [{
type: Input,
args: ['actionControls']
}], selectable: [{
type: Input
}], singleSelection: [{
type: Input
}], baseQuery: [{
type: Input
}], _bulkActionControls: [{
type: Input,
args: ['bulkActionControls']
}], _headerActionControls: [{
type: Input,
args: ['headerActionControls']
}], childDeviceGrid: [{
type: Input
}], parentDeviceId: [{
type: Input
}], withChildren: [{
type: Input
}], showSearch: [{
type: Input
}], activeClassName: [{
type: Input
}], onColumnsChange: [{
type: Output
}], onFilterChange: [{
type: Output
}], onDeviceQueryStringChange: [{
type: Output
}], itemsSelect: [{
type: Output
}], dataGrid: [{
type: ViewChild,
args: [DataGridComponent, { static: true }]
}] } });
class DeviceGridModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceGridModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: DeviceGridModule, imports: [CommonModule,
FormsModule,
DeviceStatusModule,
DataGridModule,
AssetSelectorModule,
DynamicFormsModule,
PopoverModule,
RouterModule,
ProductExperienceModule,
DeviceGridComponent,
GroupFilteringFormRendererComponent,
DeviceStatusCellRendererComponent,
NameCellRendererComponent,
ModelCellRendererComponent,
SerialNumberCellRendererComponent,
GroupCellRendererComponent,
RegistrationDateCellRendererComponent,
AlarmsCellRendererComponent,
AlarmsHeaderCellRendererComponent], exports: [DeviceGridComponent,
GroupFilteringFormRendererComponent,
DeviceStatusCellRendererComponent,
NameCellRendererComponent,
ModelCellRendererComponent,
SerialNumberCellRendererComponent,
GroupCellRendererComponent,
RegistrationDateCellRendererComponent,
AlarmsCellRendererComponent,
AlarmsHeaderCellRendererComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceGridModule, imports: [CommonModule,
FormsModule,
DeviceStatusModule,
DataGridModule,
AssetSelectorModule,
DynamicFormsModule,
PopoverModule,
RouterModule,
ProductExperienceModule,
DeviceGridComponent,
GroupFilteringFormRendererComponent,
DeviceStatusCellRendererComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceGridModule, decorators: [{
type: NgModule,
args: [{
imports: [
CommonModule,
FormsModule,
DeviceStatusModule,
DataGridModule,
AssetSelectorModule,
DynamicFormsModule,
PopoverModule,
RouterModule,
ProductExperienceModule,
DeviceGridComponent,
GroupFilteringFormRendererComponent,
DeviceStatusCellRendererComponent,
NameCellRendererComponent,
ModelCellRendererComponent,
SerialNumberCellRendererComponent,
GroupCellRendererComponent,
RegistrationDateCellRendererComponent,
AlarmsCellRendererComponent,
AlarmsHeaderCellRendererComponent
],
exports: [
DeviceGridComponent,
GroupFilteringFormRendererComponent,
DeviceStatusCellRendererComponent,
NameCellRendererComponent,
ModelCellRendererComponent,
SerialNumberCellRendererComponent,
GroupCellRendererComponent,
RegistrationDateCellRendererComponent,
AlarmsCellRendererComponent,
AlarmsHeaderCellRendererComponent
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { AlarmsCellRendererComponent, AlarmsDeviceGridColumn, AlarmsHeaderCellRendererComponent, ColumnUtilService, DeviceGridComponent, DeviceGridModule, DeviceGridService, DeviceStatusCellRendererComponent, GroupCellRendererComponent, GroupDeviceGridColumn, GroupFilteringFormRendererComponent, IconDeviceGridColumn, IconDeviceGridColumnComponent, ImeiDeviceGridColumn, ModelCellRendererComponent, ModelDeviceGridColumn, NameCellRendererComponent, NameDeviceGridColumn, RegistrationDateCellRendererComponent, RegistrationDateDeviceGridColumn, SerialNumberCellRendererComponent, SerialNumberDeviceGridColumn, StatusDeviceGridColumn, SystemIdDeviceGridColumn, TypeDeviceGridColumn };
//# sourceMappingURL=c8y-ngx-components-device-grid.mjs.map