@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
929 lines (908 loc) • 80.3 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, Component, ElementRef, HostListener, ViewChild, EventEmitter, forwardRef, Output, Input, NgModule } from '@angular/core';
import { gettext } from '@c8y/ngx-components/gettext';
import * as i1$1 from '@c8y/ngx-components';
import { IconDirective, C8yTranslatePipe, BaseColumn, C8yTranslateDirective, getBasicInputArrayFormFieldConfig, DatePipe, DeviceStatusComponent, SendStatus, PushStatus, DataGridService, Status, alertOnError, FilteringActionType, DataGridComponent, ProductExperienceDirective, EmptyStateContextDirective, EmptyStateComponent, 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 } 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 { 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: "20.3.19", ngImport: i0, type: ColumnUtilService, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ColumnUtilService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", ngImport: i0, type: AlarmsHeaderCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", 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: "20.3.19", 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 = 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", ngImport: i0, type: GroupFilteringFormRendererComponent, deps: [{ token: i1$1.FilteringFormRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", ngImport: i0, type: RegistrationDateCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", 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: "20.3.19", ngImport: i0, type: DeviceStatusCellRendererComponent, deps: [{ token: i1$1.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", 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: "20.3.19", 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: 'c8y_MQTTDevice'
}),
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: "20.3.19", ngImport: i0, type: IconDeviceGridColumnComponent, deps: [{ token: i1$1.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareCompon