UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

2,408 lines 205 kB
import * as i0 from '@angular/core';
import { Injectable, ViewChild, Input, Component, Inject, Optional, EventEmitter, Output, HostListener, TemplateRef, NgModule, InjectionToken, signal } from '@angular/core';
import * as i3 from '@c8y/ngx-components';
import { DataGridService, Permissions, WILDCARD_SEARCH_FEATURE_KEY, GroupFragment, Status, ConfirmModalComponent, FormGroupComponent, ProductExperienceDirective, C8yTranslatePipe, AbstractConfigurationStrategy, DATA_GRID_CONFIGURATION_CONTEXT, DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER, BuiltInActionType, DataGridComponent, EmptyStateContextDirective, EmptyStateComponent, ColumnDirective, UserPreferencesConfigurationStrategy, DATA_GRID_CONFIGURATION_STRATEGY, C8yStepper, C8yTranslateDirective, RequiredInputPlaceholderDirective, C8yStepperButtons, CoreModule, DatePipe, IconDirective, LoadingComponent, CustomColumn, TextareaAutoresizeDirective, FilterMapperPipe, GroupedFilterChips, TitleComponent, BreadcrumbComponent, BreadcrumbItemComponent, ActionBarItemComponent, HelpComponent, FilterMapperModule, hookRoute, ViewContext } from '@c8y/ngx-components';
import { NameDeviceGridColumn, ModelDeviceGridColumn, SerialNumberDeviceGridColumn, RegistrationDateDeviceGridColumn, SystemIdDeviceGridColumn, ImeiDeviceGridColumn, AlarmsDeviceGridColumn, DeviceGridComponent, DeviceGridModule } from '@c8y/ngx-components/device-grid';
import * as i1$1 from '@angular/forms';
import { FormsModule, Validators, ReactiveFormsModule, FormGroup } from '@angular/forms';
import { gettext } from '@c8y/ngx-components/gettext';
import * as i2 from '@c8y/client';
import * as i4 from '@c8y/ngx-components/assets-navigator';
import { AssetTypeGridColumn, AssetTypeCellRendererComponent } from '@c8y/ngx-components/data-grid-columns/asset-type';
import * as i1 from '@ngx-translate/core';
import { firstValueFrom, catchError, of, Subject, delay, takeUntil as takeUntil$1, tap } from 'rxjs';
import { NgIf, NgFor, NgClass, NgTemplateOutlet, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, AsyncPipe } from '@angular/common';
import { CdkTrapFocus } from '@angular/cdk/a11y';
import { CdkStep } from '@angular/cdk/stepper';
import * as i4$1 from '@c8y/ngx-components/device-list';
import * as i2$1 from 'ngx-bootstrap/modal';
import { takeUntil } from 'rxjs/operators';
import { cloneDeep, clone, sortBy, isNumber, toPairs, fromPairs, find, pick } from 'lodash-es';
import { PopoverDirective, PopoverModule } from 'ngx-bootstrap/popover';
import { BsDropdownModule, BsDropdownDirective, BsDropdownToggleDirective, BsDropdownMenuDirective } from 'ngx-bootstrap/dropdown';
import { TooltipModule, TooltipDirective } from 'ngx-bootstrap/tooltip';
import * as i2$2 from '@ngx-formly/core';
import { FormlyModule } from '@ngx-formly/core';
import * as i2$3 from '@c8y/ngx-components/map';
import { defaultMapConfig, getC8yMarker, MapComponent, MapModule } from '@c8y/ngx-components/map';
import * as i1$2 from '@angular/router';

const PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED = {
    EVENT: 'subAssets',
    DELETE_ASSET: {
        COMPONENTS: { DELETE_ASSETS_MODAL: 'delete-assets-modal' },
        ACTIONS: { CASCADE_DELETE: 'cascadeDelete', DELETE_DEVICE_OWNER: 'deleteDeviceOwner' },
        RESULTS: { CANCELED: 'canceled', DELETED: 'deleted' }
    },
    ASSIGN_DEVICES: {
        COMPONENTS: { ASSIGN_DEVICES: 'assign-devices' },
        ACTIONS: { ASSIGN: 'assign', CANCEL: 'cancel', DISPLAY_CHILD_DEVICES: 'displayChildDevices' }
    },
    UNASSIGN_MODAL: {
        COMPONENTS: { UNASSIGN_MODAL: 'unassign-modal' },
        RESULTS: { ASSET_UNASSIGNED: 'asset-unassigned' },
        ACTIONS: { CANCEL: 'cancel' }
    },
    GROUP_INFO: {
        COMPONENTS: { GROUP_INFO: 'group-info' },
        ACTIONS: { EDIT: 'edit' },
        RESULTS: { EDIT_SAVED: 'edit-saved' },
        PROPERTIES: { NAME: 'name', DESCRIPTION: 'description' }
    },
    ADD_GROUP: {
        COMPONENTS: { ADD_GROUP: 'add-group' },
        ACTIONS: { ADD: 'add' },
        RESULTS: { ADD_SUCCESS: 'group-added' }
    }
};

class SubAssetsService extends DataGridService {
    constructor(translateService, inventoryService, appState, user, assetNodeService, smartGroupsService, smartRulesService, alertService, permissionsService, assetTypes, userPreferencesService, previewService) {
        super(userPreferencesService);
        this.translateService = translateService;
        this.inventoryService = inventoryService;
        this.appState = appState;
        this.user = user;
        this.assetNodeService = assetNodeService;
        this.smartGroupsService = smartGroupsService;
        this.smartRulesService = smartRulesService;
        this.alertService = alertService;
        this.permissionsService = permissionsService;
        this.assetTypes = assetTypes;
        this.userPreferencesService = userPreferencesService;
        this.previewService = previewService;
        this.GRID_CONFIG_DEFAULT_STORAGE_KEY = 'sub-assets-grid-config';
        this.IS_DEVICE_GROUP_FRAGMENT = 'c8y_IsDeviceGroup';
        this.IS_DYNAMIC_GROUP_FRAGMENT = 'c8y_IsDynamicGroup';
    }
    async getCustomProperties(group) {
        const assetType$ = this.assetTypes.getAssetTypeByName$(group.type);
        const assetType = await firstValueFrom(assetType$);
        if (assetType) {
            const { data } = await this.inventoryService.childAdditionsList(assetType, {
                pageSize: 2000,
                query: "$filter=(has('c8y_IsAssetProperty'))"
            });
            return data;
        }
        return [];
    }
    getDefaultColumns(_filterable = true, _sortable = true) {
        const defaultColumns = [
            new AssetTypeGridColumn({ sortOrder: 'desc' }),
            new NameDeviceGridColumn({ sortOrder: 'asc' }),
            new ModelDeviceGridColumn(),
            new SerialNumberDeviceGridColumn({ visible: false }),
            new RegistrationDateDeviceGridColumn({ visible: false }),
            new SystemIdDeviceGridColumn({ visible: false }),
            new ImeiDeviceGridColumn({ visible: false }),
            new AlarmsDeviceGridColumn()
        ];
        return defaultColumns;
    }
    getDefaultPagination() {
        return {
            pageSize: 25,
            currentPage: 1
        };
    }
    getDefaultActionControls() {
        return [];
    }
    async unassignAsset(asset, parentRef) {
        const { id: assetId } = asset;
        const { id: parentId } = parentRef;
        if (this.isDevice(asset)) {
            try {
                await this.inventoryService.childAssetsRemove(assetId, parentId);
                const alertMessage = this.translateService.instant(gettext('Device unassigned.'));
                this.alertService.success(alertMessage);
            }
            catch (error) {
                const alertMessage = this.translateService.instant(gettext('Could not unassign device.'));
                this.alertService.danger(alertMessage, error);
            }
            await this.deactivateSmartrulesForAsset(asset, parentRef);
        }
    }
    isDevice(asset) {
        return (!asset.hasOwnProperty(this.IS_DEVICE_GROUP_FRAGMENT) &&
            !asset.hasOwnProperty(this.IS_DYNAMIC_GROUP_FRAGMENT));
    }
    async deleteAsset(asset, parentRef, params = {}) {
        const isGroup = asset.hasOwnProperty(this.IS_DEVICE_GROUP_FRAGMENT) ||
            this.smartGroupsService.isSmartGroup(asset);
        if (isGroup) {
            await this.deleteGroup(asset, params);
        }
        else {
            await this.deleteDevice(asset, params);
        }
        if (parentRef && !this.smartGroupsService.isSmartGroup(asset)) {
            await this.deactivateSmartrulesForAsset(asset, parentRef);
        }
    }
    shouldShowWithDeviceUserCheckbox(asset) {
        const { owner, c8y_IsDevice: isRootDevice } = asset;
        const hasDeviceUserAsOwner = asset.owner && this.isDeviceUser(owner);
        return Boolean(isRootDevice && hasDeviceUserAsOwner);
    }
    getDefaultBulkActionControls() {
        return [];
    }
    async getData(columns, pagination, parentReference, baseQuery = {}, text = null) {
        const isRoot = !parentReference;
        const isWildcardSearchEnabled = await this.isWildcardSearchEnabled();
        if (isRoot) {
            const query = this.buildCombinedRootQueryFilter(columns, pagination, baseQuery, isWildcardSearchEnabled, text);
            return this.assetNodeService.getRootNodes({
                ...pagination,
                ...(text && !isWildcardSearchEnabled && { text }),
                query
            });
        }
        const filters = {
            ...this.getAssetsFilters(columns, pagination, baseQuery, text, isWildcardSearchEnabled),
            withParents: false
        };
        if (this.assetNodeService.isGroup(parentReference)) {
            return this.assetNodeService.getGroupItems(parentReference.id, filters);
        }
        if (this.assetNodeService.isDynamicGroup(parentReference)) {
            return this.assetNodeService.getDynamicGroupItems(parentReference.c8y_DeviceQueryString, filters);
        }
        if (this.assetNodeService.isDevice(parentReference)) {
            return this.assetNodeService.getDeviceChildren(parentReference.id, filters);
        }
    }
    async getCount(columns, pagination, parentReference, baseQuery = {}, text = null) {
        const defaultFilters = {
            pageSize: 1,
            withChildren: false
        };
        const isWildcardSearchEnabled = await this.isWildcardSearchEnabled();
        const filters = !parentReference
            ? {
                query: this.buildCombinedRootQueryFilter(columns, pagination, baseQuery, isWildcardSearchEnabled, text),
                ...defaultFilters
            }
            : {
                ...this.getAssetsFilters(columns, pagination, baseQuery, text, isWildcardSearchEnabled),
                ...defaultFilters
            };
        return this.getAssetsStatistics(parentReference, filters);
    }
    getTotal(parentReference, baseQuery = {}) {
        const queryFilter = this.assetNodeService.rootQueryFilter();
        const query = !parentReference
            ? this.queriesUtil.addAndFilter(queryFilter, baseQuery)
            : baseQuery;
        const filters = {
            query: this.queriesUtil.buildQuery(query),
            withChildren: false,
            withTotalPages: true,
            pageSize: 1
        };
        return this.getAssetsStatistics(parentReference, filters);
    }
    async canEditGroup(group) {
        return await this.permissionsService.canEdit([Permissions.ROLE_INVENTORY_ADMIN, Permissions.ROLE_MANAGED_OBJECT_ADMIN], group);
    }
    canCreateGroup() {
        const currentUser = this.appState.currentUser.value;
        const hasAdminRole = this.user.hasAnyRole(currentUser, [
            Permissions.ROLE_INVENTORY_ADMIN,
            Permissions.ROLE_INVENTORY_CREATE,
            Permissions.ROLE_MANAGED_OBJECT_ADMIN,
            Permissions.ROLE_MANAGED_OBJECT_CREATE
        ]);
        return hasAdminRole;
    }
    async canAssignDevice(group) {
        return await this.permissionsService.canEdit([Permissions.ROLE_INVENTORY_ADMIN, Permissions.ROLE_MANAGED_OBJECT_ADMIN], group);
    }
    canEditSmartGroup() {
        const SMART_GROUPS_ROLES_EDIT = [
            Permissions.ROLE_SMARTGROUP_UPDATE,
            Permissions.ROLE_SMARTGROUP_ADMIN
        ];
        return this.permissionsService.hasAnyRole(SMART_GROUPS_ROLES_EDIT);
    }
    canDeleteSmartGroup() {
        const SMART_GROUPS_ROLES_DELETE = [
            Permissions.ROLE_SMARTGROUP_ADMIN,
            Permissions.ROLE_INVENTORY_ADMIN,
            Permissions.ROLE_MANAGED_OBJECT_ADMIN
        ];
        return this.permissionsService.hasAnyRole(SMART_GROUPS_ROLES_DELETE);
    }
    isSmartGroup(group) {
        return this.smartGroupsService.isSmartGroup(group);
    }
    isUsingInventoryRoles() {
        const currentUser = this.appState.currentUser.value;
        const hasAnyInventoryRole = this.user.hasAnyRole(currentUser, [
            Permissions.ROLE_INVENTORY_ADMIN,
            Permissions.ROLE_INVENTORY_READ,
            Permissions.ROLE_INVENTORY_CREATE,
            Permissions.ROLE_MANAGED_OBJECT_ADMIN,
            Permissions.ROLE_MANAGED_OBJECT_CREATE,
            Permissions.ROLE_MANAGED_OBJECT_READ
        ]);
        return !hasAnyInventoryRole;
    }
    async getAssetsStatistics(parentReference, filters) {
        const isRoot = !parentReference;
        if (isRoot) {
            return (await this.assetNodeService.getRootNodes(filters)).paging.totalPages;
        }
        if (this.assetNodeService.isGroup(parentReference)) {
            return (await this.assetNodeService.getGroupItems(parentReference.id, filters)).paging
                .totalPages;
        }
        if (this.assetNodeService.isDynamicGroup(parentReference)) {
            return (await this.assetNodeService.getDynamicGroupItems(parentReference.c8y_DeviceQueryString, filters)).paging.totalPages;
        }
        if (this.assetNodeService.isDevice(parentReference)) {
            return (await this.assetNodeService.getDeviceChildren(parentReference.id, filters)).paging
                .totalPages;
        }
    }
    buildCombinedRootQueryFilter(columns, pagination, baseQuery = {}, isWildcardSearchEnabled = true, text) {
        const userQuery = this.getQueryObj(columns, pagination);
        const rootQuery = this.assetNodeService.rootQueryFilter();
        const orderedRootQuery = this.queriesUtil.addOrderbys(rootQuery, userQuery.__orderby, 'append');
        const rootAndUserQuery = this.queriesUtil.addAndFilter(orderedRootQuery, userQuery.__filter);
        let fullQuery = this.queriesUtil.addAndFilter(rootAndUserQuery, baseQuery);
        if (text && isWildcardSearchEnabled) {
            fullQuery = this.queriesUtil.addAndFilter(fullQuery, {
                name: `*${text.trim().replace(/\s+/g, '*')}*`
            });
        }
        return this.queriesUtil.buildQuery(fullQuery);
    }
    async deleteGroup(group, params = {}) {
        const { cascade } = params;
        try {
            this.smartGroupsService.isSmartGroup(group)
                ? await this.smartGroupsService.delete(group, { cascade })
                : await this.inventoryService.delete(group, { cascade });
            const alertMessage = this.translateService.instant(gettext('"{{ name }}" deleted.'), {
                name: group.name
            });
            this.alertService.success(alertMessage);
        }
        catch (error) {
            const alertMessage = this.translateService.instant(gettext('Could not delete "{{ name }}".'), {
                name: group.name
            });
            this.alertService.danger(alertMessage, error);
        }
    }
    async isWildcardSearchEnabled() {
        return firstValueFrom(this.previewService.getState$(WILDCARD_SEARCH_FEATURE_KEY).pipe(catchError(() => of(true))));
    }
    async deleteDevice(device, params = {}) {
        const { cascade, withDeviceUser } = params;
        try {
            const { owner } = device;
            const shouldRemoveOwner = withDeviceUser && owner && this.isDeviceUser(owner);
            shouldRemoveOwner
                ? await this.deleteDeviceWithUser(device, cascade)
                : await this.inventoryService.delete(device, { cascade });
            const alertMessage = this.translateService.instant(gettext('Device deleted.'));
            this.alertService.success(alertMessage);
        }
        catch (error) {
            const alertMessage = this.translateService.instant(gettext('Could not delete device.'));
            this.alertService.danger(alertMessage, error);
        }
    }
    async deactivateSmartrulesForAsset(asset, parentRef) {
        const { id: assetId } = asset;
        const { id: parentId } = parentRef;
        const rules = (await this.smartRulesService.listByContext(parentId)).data;
        const upateSmartrulesPromises = rules.map(rule => this.smartRulesService.bulkDeactivateEnabledSources(rule, [assetId]));
        try {
            await Promise.all(upateSmartrulesPromises);
        }
        catch (error) {
            const alertMessage = this.translateService.instant(gettext('Could not deactivate smart rules.'));
            this.alertService.danger(alertMessage);
        }
    }
    isDeviceUser(userId) {
        return userId.match(/^device_/);
    }
    async deleteDeviceWithUser(device, cascade) {
        const params = { cascade, withDeviceUser: true };
        try {
            return await this.inventoryService.delete(device, params);
        }
        catch (error) {
            return await this.inventoryService.delete(device, { cascade });
        }
    }
    getAssetsFilters(columns, pagination, baseQuery, text, isWildcardSearchEnabled = true) {
        let query = this.queriesUtil.addAndFilter(this.getQueryObj(columns), baseQuery);
        if (text && isWildcardSearchEnabled) {
            query = this.queriesUtil.addAndFilter(query, {
                name: `*${text.trim().replace(/\s+/g, '*')}*`
            });
        }
        return {
            ...(text && !isWildcardSearchEnabled && { text }),
            query: this.queriesUtil.buildQuery(query),
            pageSize: pagination.pageSize || this.DEFAULT_PAGE_SIZE,
            currentPage: pagination.currentPage,
            withTotalPages: true
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsService, deps: [{ token: i1.TranslateService }, { token: i2.InventoryService }, { token: i3.AppStateService }, { token: i2.UserService }, { token: i4.AssetNodeService }, { token: i2.SmartGroupsService }, { token: i2.SmartRulesService }, { token: i3.AlertService }, { token: i3.Permissions }, { token: i3.AssetTypesRealtimeService }, { token: i3.UserPreferencesService }, { token: i3.PreviewService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: i1.TranslateService }, { type: i2.InventoryService }, { type: i3.AppStateService }, { type: i2.UserService }, { type: i4.AssetNodeService }, { type: i2.SmartGroupsService }, { type: i2.SmartRulesService }, { type: i3.AlertService }, { type: i3.Permissions }, { type: i3.AssetTypesRealtimeService }, { type: i3.UserPreferencesService }, { type: i3.PreviewService }] });

class AddGroupService {
    constructor(inventoryService) {
        this.inventoryService = inventoryService;
        this.GROUP_FRAGMENT_TYPE = 'c8y_IsDeviceGroup';
    }
    async createGroupAndAssignDevices(groupForm, groupContextId, selectedDevices) {
        let group;
        const { name, description } = groupForm;
        const newGroupMO = this.getGroupMO(name, description, groupContextId);
        if (groupContextId) {
            group = (await this.inventoryService.childAssetsCreate(newGroupMO, groupContextId)).data;
        }
        else {
            group = (await this.inventoryService.create(newGroupMO)).data;
        }
        if (selectedDevices.length > 0) {
            await this.assignDevices(group.id, selectedDevices);
        }
        return group;
    }
    getGroupMO(name, description = '', groupContextId) {
        const group = {
            type: this.getGroupType(groupContextId),
            [this.GROUP_FRAGMENT_TYPE]: {},
            name,
            c8y_Notes: description
        };
        return group;
    }
    getGroupType(groupContextId) {
        return groupContextId ? GroupFragment.subGroupType : GroupFragment.groupType;
    }
    async assignDevices(id, selectedDevices) {
        const promises = [];
        selectedDevices.forEach(moId => {
            promises.push(this.inventoryService.childAssetsAdd(moId, id));
        });
        return await Promise.all(promises);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AddGroupService, deps: [{ token: i2.InventoryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AddGroupService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AddGroupService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i2.InventoryService }] });

class DeleteAssetsModalComponent {
    constructor(translateService, gainsightService) {
        this.translateService = translateService;
        this.gainsightService = gainsightService;
        this.CURRENT_LOCATION = location.href;
        this.PRODUCT_EXPERIENCE = PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED;
        this.showWithCascadeCheckbox = true;
        this.showWithDeviceUserCheckbox = false;
        this.closeSubject = new Subject();
        this.labels = { ok: gettext('Delete'), cancel: gettext('Cancel') };
        this.title = gettext('Delete');
        this.status = Status.DANGER;
        this.config = {
            cascade: false,
            withDeviceUser: false
        };
    }
    ngOnInit() {
        this.setModalTexts();
    }
    async ngAfterViewInit() {
        try {
            await this.modalRef.result;
            this.onClose();
        }
        catch (error) {
            this.onDismiss();
        }
    }
    onClose() {
        this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.EVENT, {
            component: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.DELETE_ASSET.COMPONENTS.DELETE_ASSETS_MODAL,
            result: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.DELETE_ASSET.RESULTS.DELETED,
            url: this.CURRENT_LOCATION
        });
        this.closeSubject.next(this.config);
        this.closeSubject.complete();
    }
    onDismiss() {
        this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.EVENT, {
            component: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.DELETE_ASSET.COMPONENTS.DELETE_ASSETS_MODAL,
            result: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.DELETE_ASSET.RESULTS.CANCELED,
            url: this.CURRENT_LOCATION
        });
        this.closeSubject.complete();
    }
    setModalTexts() {
        this.message = this.translateService.instant(gettext('You are about to delete: "{{name}}". This operation is irreversible. Do you want to proceed?'), { name: this.asset.name });
        this.deleteGroupSubAssetsMsg = this.translateService.instant(gettext('Also delete all devices inside "{{name}}" and its subassets.'), { name: this.asset.name });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DeleteAssetsModalComponent, deps: [{ token: i1.TranslateService }, { token: i3.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: DeleteAssetsModalComponent, isStandalone: true, selector: "c8y-delete-assets-modal", inputs: { showWithCascadeCheckbox: "showWithCascadeCheckbox", showWithDeviceUserCheckbox: "showWithDeviceUserCheckbox", asset: "asset" }, viewQueries: [{ propertyName: "modalRef", first: true, predicate: ["modalRef"], descendants: true }], ngImport: i0, template: "<c8y-confirm-modal [title]=\"title\" [status]=\"status\" [labels]=\"labels\" #modalRef>\n  <form #assetsForm=\"ngForm\">\n    <p class=\"text-wrap m-b-16\">\n      {{ message | translate }}\n    </p>\n    <c8y-form-group *ngIf=\"showWithCascadeCheckbox\" class=\"m-b-0\">\n      <label title=\"{{ 'Delete devices' | translate }}\" class=\"c8y-checkbox\">\n        <input\n          type=\"checkbox\"\n          name=\"cascade\"\n          [(ngModel)]=\"config.cascade\"\n          c8yProductExperience\n          [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n          [actionData]=\"{\n            component: PRODUCT_EXPERIENCE.DELETE_ASSET.COMPONENTS.DELETE_ASSETS_MODAL,\n            action: PRODUCT_EXPERIENCE.DELETE_ASSET.ACTIONS.CASCADE_DELETE\n          }\"\n          [disabled]=\"config?.withDeviceUser\"\n        />\n        <span></span>\n        <span class=\"text-break-word\">\n          {{ deleteGroupSubAssetsMsg | translate }}\n        </span>\n      </label>\n    </c8y-form-group>\n    <c8y-form-group *ngIf=\"showWithDeviceUserCheckbox\" class=\"m-b-0\">\n      <label title=\"{{ 'Delete associated device owner' | translate }}\" class=\"c8y-checkbox\">\n        <input\n          type=\"checkbox\"\n          name=\"withDeviceUser\"\n          [(ngModel)]=\"config.withDeviceUser\"\n          c8yProductExperience\n          [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n          [actionData]=\"{\n            component: PRODUCT_EXPERIENCE.DELETE_ASSET.COMPONENTS.DELETE_ASSETS_MODAL,\n            action: PRODUCT_EXPERIENCE.DELETE_ASSET.ACTIONS.DELETE_DEVICE_OWNER\n          }\"\n          [disabled]=\"config?.cascade\"\n        />\n        <span></span>\n        <span>\n          {{ 'Also delete associated device owner.' | translate }}\n        </span>\n      </label>\n    </c8y-form-group>\n  </form>\n</c8y-confirm-modal>\n", dependencies: [{ kind: "component", type: ConfirmModalComponent, selector: "c8y-confirm-modal", inputs: ["title", "body", "confirmOptions", "status", "labels"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DeleteAssetsModalComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-delete-assets-modal', imports: [
                        ConfirmModalComponent,
                        FormsModule,
                        NgIf,
                        FormGroupComponent,
                        ProductExperienceDirective,
                        C8yTranslatePipe
                    ], template: "<c8y-confirm-modal [title]=\"title\" [status]=\"status\" [labels]=\"labels\" #modalRef>\n  <form #assetsForm=\"ngForm\">\n    <p class=\"text-wrap m-b-16\">\n      {{ message | translate }}\n    </p>\n    <c8y-form-group *ngIf=\"showWithCascadeCheckbox\" class=\"m-b-0\">\n      <label title=\"{{ 'Delete devices' | translate }}\" class=\"c8y-checkbox\">\n        <input\n          type=\"checkbox\"\n          name=\"cascade\"\n          [(ngModel)]=\"config.cascade\"\n          c8yProductExperience\n          [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n          [actionData]=\"{\n            component: PRODUCT_EXPERIENCE.DELETE_ASSET.COMPONENTS.DELETE_ASSETS_MODAL,\n            action: PRODUCT_EXPERIENCE.DELETE_ASSET.ACTIONS.CASCADE_DELETE\n          }\"\n          [disabled]=\"config?.withDeviceUser\"\n        />\n        <span></span>\n        <span class=\"text-break-word\">\n          {{ deleteGroupSubAssetsMsg | translate }}\n        </span>\n      </label>\n    </c8y-form-group>\n    <c8y-form-group *ngIf=\"showWithDeviceUserCheckbox\" class=\"m-b-0\">\n      <label title=\"{{ 'Delete associated device owner' | translate }}\" class=\"c8y-checkbox\">\n        <input\n          type=\"checkbox\"\n          name=\"withDeviceUser\"\n          [(ngModel)]=\"config.withDeviceUser\"\n          c8yProductExperience\n          [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n          [actionData]=\"{\n            component: PRODUCT_EXPERIENCE.DELETE_ASSET.COMPONENTS.DELETE_ASSETS_MODAL,\n            action: PRODUCT_EXPERIENCE.DELETE_ASSET.ACTIONS.DELETE_DEVICE_OWNER\n          }\"\n          [disabled]=\"config?.cascade\"\n        />\n        <span></span>\n        <span>\n          {{ 'Also delete associated device owner.' | translate }}\n        </span>\n      </label>\n    </c8y-form-group>\n  </form>\n</c8y-confirm-modal>\n" }]
        }], ctorParameters: () => [{ type: i1.TranslateService }, { type: i3.GainsightService }], propDecorators: { showWithCascadeCheckbox: [{
                type: Input
            }], showWithDeviceUserCheckbox: [{
                type: Input
            }], asset: [{
                type: Input
            }], modalRef: [{
                type: ViewChild,
                args: ['modalRef', { static: false }]
            }] } });

class SmartGroupGridConfigurationStrategy extends AbstractConfigurationStrategy {
    constructor(userPreferencesConfigurationStrategy, context, contextProvider) {
        super(context, contextProvider);
        this.userPreferencesConfigurationStrategy = userPreferencesConfigurationStrategy;
        this.context = context;
        this.contextProvider = contextProvider;
    }
    getConfig$(context) {
        const group = cloneDeep(this.retrieveContext(context)?.group);
        if (group?.c8y_DeviceColumnsConfig?.columns?.length) {
            group.c8y_DeviceColumnsConfig.columns = group.c8y_DeviceColumnsConfig.columns.map(column => {
                delete column.filter;
                return column;
            });
        }
        return of(group?.c8y_DeviceColumnsConfig);
    }
    saveConfig$(config, _context) {
        return of(config);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartGroupGridConfigurationStrategy, deps: [{ token: i3.UserPreferencesConfigurationStrategy }, { token: DATA_GRID_CONFIGURATION_CONTEXT, optional: true }, { token: DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartGroupGridConfigurationStrategy, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartGroupGridConfigurationStrategy, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: i3.UserPreferencesConfigurationStrategy }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [DATA_GRID_CONFIGURATION_CONTEXT]
                }, {
                    type: Optional
                }] }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER]
                }, {
                    type: Optional
                }] }] });

class SubAssetsGridConfigurationStrategy extends AbstractConfigurationStrategy {
    constructor(userPreferencesConfigurationStrategy, smartGroupGridConfigurationStrategy, assetNodeService, context, contextProvider) {
        super(context, contextProvider);
        this.userPreferencesConfigurationStrategy = userPreferencesConfigurationStrategy;
        this.smartGroupGridConfigurationStrategy = smartGroupGridConfigurationStrategy;
        this.assetNodeService = assetNodeService;
        this.context = context;
        this.contextProvider = contextProvider;
    }
    getConfig$(context) {
        return this.getStrategy(context).getConfig$(context);
    }
    saveConfig$(config, context) {
        return this.getStrategy(context).saveConfig$(config, context);
    }
    getStrategy(ctx) {
        const context = this.retrieveContext(ctx);
        return !!context?.group &&
            this.assetNodeService.isDynamicGroup(context?.group) &&
            context?.group?.c8y_DeviceColumnsConfig
            ? this.smartGroupGridConfigurationStrategy
            : this.userPreferencesConfigurationStrategy;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsGridConfigurationStrategy, deps: [{ token: i3.UserPreferencesConfigurationStrategy }, { token: SmartGroupGridConfigurationStrategy }, { token: i4.AssetNodeService }, { token: DATA_GRID_CONFIGURATION_CONTEXT, optional: true }, { token: DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsGridConfigurationStrategy, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsGridConfigurationStrategy, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: i3.UserPreferencesConfigurationStrategy }, { type: SmartGroupGridConfigurationStrategy }, { type: i4.AssetNodeService }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [DATA_GRID_CONFIGURATION_CONTEXT]
                }, {
                    type: Optional
                }] }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER]
                }, {
                    type: Optional
                }] }] });

class UnassignModalComponent {
    constructor(translateService, gainsightService) {
        this.translateService = translateService;
        this.gainsightService = gainsightService;
        this.CURRENT_LOCATION = location.href;
        this.closeSubject = new Subject();
        this.labels = { ok: gettext('Unassign'), cancel: gettext('Cancel') };
        this.title = gettext('Unassign');
        this.status = Status.WARNING;
    }
    ngOnInit() {
        this.message = this.translateService.instant(gettext('You are about to unassign "{{name}}". Do you want to proceed?'), { name: this.asset.name });
    }
    async ngAfterViewInit() {
        try {
            await this.modalRef.result;
            this.onClose();
        }
        catch (error) {
            this.onDismiss();
        }
    }
    onClose() {
        this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.EVENT, {
            component: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.UNASSIGN_MODAL.COMPONENTS.UNASSIGN_MODAL,
            result: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.UNASSIGN_MODAL.RESULTS.ASSET_UNASSIGNED,
            url: this.CURRENT_LOCATION
        });
        this.closeSubject.next(true);
        this.closeSubject.complete();
    }
    onDismiss() {
        this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.EVENT, {
            component: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.UNASSIGN_MODAL.COMPONENTS.UNASSIGN_MODAL,
            action: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.UNASSIGN_MODAL.ACTIONS.CANCEL,
            url: this.CURRENT_LOCATION
        });
        this.closeSubject.complete();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: UnassignModalComponent, deps: [{ token: i1.TranslateService }, { token: i3.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: UnassignModalComponent, isStandalone: true, selector: "c8y-unassign-modal", inputs: { asset: "asset" }, viewQueries: [{ propertyName: "modalRef", first: true, predicate: ["modalRef"], descendants: true }], ngImport: i0, template: "<c8y-confirm-modal [title]=\"title\" [status]=\"status\" [labels]=\"labels\" #modalRef>\n  <span>{{ message | translate }}</span>\n</c8y-confirm-modal>\n", dependencies: [{ kind: "component", type: ConfirmModalComponent, selector: "c8y-confirm-modal", inputs: ["title", "body", "confirmOptions", "status", "labels"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: UnassignModalComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-unassign-modal', imports: [ConfirmModalComponent, C8yTranslatePipe], template: "<c8y-confirm-modal [title]=\"title\" [status]=\"status\" [labels]=\"labels\" #modalRef>\n  <span>{{ message | translate }}</span>\n</c8y-confirm-modal>\n" }]
        }], ctorParameters: () => [{ type: i1.TranslateService }, { type: i3.GainsightService }], propDecorators: { asset: [{
                type: Input
            }], modalRef: [{
                type: ViewChild,
                args: ['modalRef', { static: false }]
            }] } });

class SubAssetsGridComponent {
    get columns() {
        return this._columns;
    }
    set columns(value) {
        this._columns = value ?? this.subAssetsGridService.getDefaultColumns();
    }
    set _pagination(value) {
        if (value) {
            this.pagination = value;
        }
        else {
            this.pagination = this.subAssetsGridService.getDefaultPagination();
        }
    }
    set _actionControls(value) {
        if (value) {
            this.actionControls = value;
        }
        else {
            this.actionControls = this.subAssetsGridService.getDefaultActionControls();
        }
    }
    set _bulkActionControls(value) {
        if (value) {
            this.bulkActionControls = value;
        }
        else {
            this.bulkActionControls = this.subAssetsGridService.getDefaultBulkActionControls();
        }
    }
    get isRootGroup() {
        return !this.parentGroup;
    }
    get getInfiniteScrollMode() {
        return this.isRootGroup && this.subAssetsGridService.isUsingInventoryRoles()
            ? 'auto'
            : undefined;
    }
    set _displayOptions(displayOptions) {
        this.displayOptions = { ...this.displayOptions, ...displayOptions };
    }
    constructor(subAssetsGridService, bsModalService, smartGroupsService, deviceListExtensionService, assetNodeService) {
        this.subAssetsGridService = subAssetsGridService;
        this.bsModalService = bsModalService;
        this.smartGroupsService = smartGroupsService;
        this.deviceListExtensionService = deviceListExtensionService;
        this.assetNodeService = assetNodeService;
        this.PRODUCT_EXPERIENCE = PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED;
        this.title = gettext('Subassets');
        this.emptyStateText = gettext('Add your first group or assign devices using the buttons on the action bar.');
        this.loadingItemsLabel = gettext('Loading assets…');
        this.selectable = false;
        this.baseQuery = {};
        this.filterable = true;
        this.sortable = true;
        this.onColumnsChange = new EventEmitter();
        this.itemsSelect = new EventEmitter();
        this.pagination = this.subAssetsGridService.getDefaultPagination();
        this.showCounterWarning = false;
        this.bulkActionControls = this.subAssetsGridService.getDefaultBulkActionControls();
        this.displayOptions = {
            striped: true,
            bordered: false,
            gridHeader: true,
            filter: true,
            hover: true
        };
        this.showSearch = false;
        this.noResultsMessage = gettext('No matching items.');
        this.noDataMessage = gettext('No items to display.');
        this.noResultsSubtitle = gettext('Refine your search terms or check your spelling.');
        this.destroyed$ = new Subject();
        this.serverSideDataCallback = this.onDataSourceModifier.bind(this);
    }
    getGridConfigContext() {
        if (!!this.columnsConfigKey) {
            return { key: this.columnsConfigKey, group: this.parentGroup };
        }
    }
    ngOnInit() {
        const isDynamicGroup = !!this.parentGroup && this.assetNodeService.isDynamicGroup(this.parentGroup);
        if (!this.isRootGroup) {
            (isDynamicGroup
                ? this.deviceListExtensionService.items$
                : of(this.subAssetsGridService.getDefaultColumns(this.filterable, this.sortable)))
                .pipe(takeUntil(this.destroyed$))
                .subscribe(columns => (this.columns = columns));
        }
        if (!this.filterable || !this.sortable) {
            this.displayOptions.filter = this.filterable;
            this.columns.forEach(column => {
                column.filterable = this.filterable;
                column.sortable = this.sortable;
            });
        }
        this.setActionControls();
        this.showSearch = isDynamicGroup || !this.parentGroup;
    }
    setActionControls() {
        const actionControls = [];
        const unassignAction = {
            type: 'UNASSIGN',
            icon: 'unlink',
            text: gettext('Unassign'),
            priority: 1000,
            callback: (asset) => this.onUnassignAsset(asset, this.parentGroup),
            showIf: (asset) => this.subAssetsGridService.isDevice(asset) &&
                !this.subAssetsGridService.isSmartGroup(this.parentGroup)
        };
        actionControls.push(unassignAction);
        const deleteAction = {
            type: BuiltInActionType.Delete,
            priority: -Infinity,
            callback: (asset) => this.onDeleteAsset(asset, this.parentGroup),
            showIf: (asset) => {
                if (this.smartGroupsService.isSmartGroup(asset)) {
                    return this.subAssetsGridService.canDeleteSmartGroup();
                }
                return true;
            }
        };
        actionControls.push(deleteAction);
        if (!this.actionControls) {
            this.actionControls = actionControls;
        }
    }
    onUnassignAsset(asset, parentRef) {
        const initialState = {
            asset
        };
        const modalRef = this.bsModalService.show(UnassignModalComponent, { initialState });
        modalRef.content.closeSubject.subscribe(async (result) => {
            if (result) {
                await this.subAssetsGridService.unassignAsset(asset, parentRef);
                this.refresh.emit();
            }
        });
    }
    async onDeleteAsset(asset, parentRef) {
        const initialState = {
            showWithDeviceUserCheckbox: this.subAssetsGridService.shouldShowWithDeviceUserCheckbox(asset),
            asset,
            showWithCascadeCheckbox: !this.smartGroupsService.isSmartGroup(asset)
        };
        const modalRef = this.bsModalService.show(DeleteAssetsModalComponent, { initialState });
        modalRef.content.closeSubject.subscribe(async (result) => {
            if (result) {
                await this.subAssetsGridService.deleteAsset(asset, parentRef, result);
                if (result.cascade) {
                    this.showCounterWarning = true;
                }
                this.refresh.emit();
            }
        });
    }
    ngOnChanges(changes) {
        if (changes.parentGroup && !changes.parentGroup.firstChange) {
            this.dataGrid.reload();
        }
    }
    trackByName(_index, column) {
        return column.name;
    }
    onReload() {
        this.assetNodeService.rootNode.refresh();
    }
    async onDataSourceModifier(dataSourceModifier) {
        const promises = [];
        let counters;
        promises.push(this.subAssetsGridService.getData(dataSourceModifier.columns, dataSourceModifier.pagination, this.parentGroup, this.baseQuery, dataSourceModifier.searchText));
        promises.push(this.subAssetsGridService.getTotal(this.parentGroup, this.baseQuery));
        promises.push(this.subAssetsGridService.getCount(dataSourceModifier.columns, dataSourceModifier.pagination, this.parentGroup, this.baseQuery, dataSourceModifier.searchText));
        const [dataResponse, size, filteredSize] = await Promise.all(promises);
        if (!counters) {
            counters = {
                size,
                filteredSize
            };
        }
        this.onColumnsChange.emit(dataSourceModifier.columns);
        return {
            res: dataResponse.res,
            data: dataResponse.data,
            paging: dataResponse.paging,
            ...counters
        };
    }
    ngOnDestroy() {
        this.destroyed$.next();
        this.destroyed$.complete();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsGridComponent, deps: [{ token: SubAssetsService }, { token: i2$1.BsModalService }, { token: i2.SmartGroupsService }, { token: i4$1.DeviceListExtensionService }, { token: i4.AssetNodeService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SubAssetsGridComponent, isStandalone: true, selector: "c8y-sub-assets-grid", inputs: { parentGroup: ["parent-group", "parentGroup"], refresh: "refresh", title: "title", emptyStateText: "emptyStateText", loadingItemsLabel: "loadingItemsLabel", columnsConfigKey: "columnsConfigKey", columns: "columns", _pagination: ["pagination", "_pagination"], _actionControls: ["actionControls", "_actionControls"], selectable: "selectable", baseQuery: "baseQuery", _bulkActionControls: ["bulkActionControls", "_bulkActionControls"], filterable: "filterable", sortable: "sortable", _displayOptions: ["displayOptions", "_displayOptions"] }, outputs: { onColumnsChange: "onColumnsChange", itemsSelect: "itemsSelect" }, providers: [
            {
                provide: UserPreferencesConfigurationStrategy,
                useClass: UserPreferencesConfigurationStrategy
            },
            {
                provide: SmartGroupGridConfigurationStrategy,
                useClass: SmartGroupGridConfigurationStrategy
            },
            {
                provide: DATA_GRID_CONFIGURATION_STRATEGY,
                useClass: SubAssetsGridConfigurationStrategy
            },
            {
                provide: DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER,
                useExisting: SubAssetsGridComponent
            }
        ], viewQueries: [{ propertyName: "dataGrid", first: true, predicate: DataGridComponent, descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<c8y-data-grid\n  [title]=\"title\"\n  [loadingItemsLabel]=\"loadingItemsLabel\"\n  [columns]=\"columns\"\n  [pagination]=\"pagination\"\n  [actionControls]=\"actionControls\"\n  [selectable]=\"selectable\"\n  [bulkActionControls]=\"bulkActionControls\"\n  [serverSideDataCallback]=\"serverSideDataCallback\"\n  [infiniteScroll]=\"getInfiniteScrollMode\"\n  [showCounterWarning]=\"showCounterWarning\"\n  [refresh]=\"refresh\"\n  [showSearch]=\"showSearch\"\n  [displayOptions]=\"displayOptions\"\n  (itemsSelect)=\"itemsSelect.emit($event)\"\n  c8yProductExperience\n  [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n  (onReload)=\"onReload()\"\n>\n  <c8y-ui-empty-state\n    [icon]=\"'c8y-group-add'\"\n    [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n    [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : (emptyStateText | translate)\"\n    *emptyStateContext=\"let stats\"\n    [horizontal]=\"true\"\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: "20.3.15", ngImport: i0, type: SubAssetsGridComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-sub-assets-grid', providers: [
                        {
                            provide: UserPreferencesConfigurationStrategy,
                            useClass: UserPreferencesConfigurationStrategy
                        },
                        {
                            provide: SmartGroupGridConfigurationStrategy,
                            useClass: SmartGroupGridConfigurationStrategy
                        },
                        {
                            provide: DATA_GRID_CONFIGURATION_STRATEGY,
                            useClass: SubAssetsGridConfigurationStrategy
                        },
                        {
                            provide: DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER,
                            useExisting: SubAssetsGridComponent
                        }
                    ], imports: [
                        DataGridComponent,
                        ProductExperienceDirective,
                        EmptyStateContextDirective,
                        EmptyStateComponent,
                        NgFor,
                        ColumnDirective,
                        C8yTranslatePipe
                    ], template: "<c8y-data-grid\n  [title]=\"title\"\n  [loadingItemsLabel]=\"loadingItemsLabel\"\n  [columns]=\"columns\"\n  [pagination]=\"pagination\"\n  [actionControls]=\"actionControls\"\n  [selectable]=\"selectable\"\n  [bulkActionControls]=\"bulkActionControls\"\n  [serverSideDataCallback]=\"serverSideDataCallback\"\n  [infiniteScroll]=\"getInfiniteScrollMode\"\n  [showCounterWarning]=\"showCounterWarning\"\n  [refresh]=\"refresh\"\n  [showSearch]=\"showSearch\"\n  [displayOptions]=\"displayOptions\"\n  (itemsSelect)=\"itemsSelect.emit($event)\"\n  c8yProductExperience\n  [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n  (onReload)=\"onReload()\"\n>\n  <c8y-ui-empty-state\n    [icon]=\"'c8y-group-add'\"\n    [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n    [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : (emptyStateText | translate)\"\n    *emptyStateContext=\"let stats\"\n    [horizontal]=\"true\"\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: SubAssetsService }, { type: i2$1.BsModalService }, { type: i2.SmartGroupsService }, { type: i4$1.DeviceListExtensionService }, { type: i4.AssetNodeService }], propDecorators: { parentGroup: [{
                type: Input,
                args: ['parent-group']
            }], refresh: [{
                type: Input
            }], title: [{
                type: Input
            }], emptyStateText: [{
                type: Input
            }], loadingItemsLabel: [{
                type: Input
            }], columnsConfigKey: [{
                type: Input
            }], columns: [{
                type: Input
            }], _pagination: [{
                type: Input,
                args: ['pagination']
            }], _actionControls: [{
                type: Input,
                args: ['actionControls']
            }], selectable: [{
                type: Input
            }], baseQuery: [{
                type: Input
            }], _bulkActionControls: [{
                type: Input,
                args: ['bulkActionControls']
            }], filterable: [{
                type: Input
            }], sortable: [{
                type: Input
            }], onColumnsChange: [{
                type: Output
            }], itemsSelect: [{
                type: Output
            }], dataGrid: [{
                type: ViewChild,
                args: [DataGridComponent, { static: true }]
            }], _displayOptions: [{
                type: Input,
                args: ['displayOptions']
            }] } });

class AssignChildDevicesComponent {
    constructor(alert, subAssetsService, inventoryService) {
        this.alert = alert;
        this.subAssetsService = subAssetsService;
        this.inventoryService = inventoryService;
        this.onCancel = new EventEmitter();
        this.onSelectedDevices = new EventEmitter();
        this.refresh = new EventEmitter();
        this.onlySelect = false; // if true, devices are only selected, not assigned
        this.selected = [];
        this.canAssignDevice = false;
        this.pendingStatus = false;
    }
    onEnterKeyDown(_event) {
        if (this.selected.length > 0) {
            this.assignDevices();
        }
    }
    onEscapeKeyDown(_event) {
        this.onCancel.emit();
    }
    async ngOnInit() {
        this.setNotIncludedInGroupQuery();
        this.canAssignDevice = await this.subAssetsService.canAssignDevice({
            id: this.currentGroupId
        });
    }
    setNotIncludedInGroupQuery() {
        const notIncludedInGroupQuery = { __not: { __bygroupid: this.currentGroupId } };
        this.baseQuery = notIncludedInGroupQuery;
    }
    async assignDevices() {
        if (this.canAssignDevice === false) {
            return;
        }
        if (this.onlySelect) {
            this.onSelectedDevices.emit(this.selected);
            this.alert.success(gettext('Child devices selected.'));
            this.onCancel.emit();
            return;
        }
        this.pendingStatus = true;
        try {
            await this.inventoryService.childAssetsBulkAdd(this.selected, this.currentGroupId);
            this.refresh.emit();
            this.alert.success(gettext('Child devices assigned.'));
        }
        catch (error) {
            this.alert.danger(gettext('Could not assign child devices.'), error);
        }
        this.pendingStatus = false;
        this.selected = [];
        this.onCancel.emit();
    }
    onSelected(selectedDevicesIDs) {
        this.selected = selectedDevicesIDs;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AssignChildDevicesComponent, deps: [{ token: i3.AlertService }, { token: SubAssetsService }, { token: i2.InventoryService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: AssignChildDevicesComponent, isStandalone: true, selector: "c8y-assign-child-devices", inputs: { currentGroupId: "currentGroupId", parentDevice: "parentDevice", refresh: "refresh", onlySelect: "onlySelect" }, outputs: { onCancel: "onCancel", onSelectedDevices: "onSelectedDevices" }, host: { listeners: { "document:keydown.enter": "onEnterKeyDown($event)", "document:keydown.escape": "onEscapeKeyDown($event)" } }, ngImport: i0, template: "<div class=\"card-block flex-no-shrink separator-bottom col-xs-12 large-padding p-t-24 p-b-24\">\n  <div class=\"row\">\n    <div class=\"col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4\">\n      <h4 class=\"text-center text-medium\" id=\"childDevicesDrawerTitle\">\n        {{ 'Assign child devices' | translate }}\n      </h4>\n    </div>\n  </div>\n</div>\n\n<c8y-sub-assets-grid\n  [title]=\"''\"\n  [emptyStateText]=\"'All child devices are already assigned' | translate\"\n  [refresh]=\"refresh\"\n  [actionControls]=\"[]\"\n  [columnsConfigKey]=\"'assign-child-devices'\"\n  [selectable]=\"true\"\n  [parent-group]=\"parentDevice\"\n  [baseQuery]=\"baseQuery\"\n  (itemsSelect)=\"onSelected($event)\"\n  class=\"d-contents\"\n></c8y-sub-assets-grid>\n\n<div class=\"text-center card-footer p-24 separator\">\n  <button\n    (click)=\"onCancel.emit()\"\n    type=\"button\"\n    class=\"btn btn-default\"\n    title=\"{{ 'Cancel' | translate }}\"\n  >\n    <span>{{ 'Cancel' | translate }}</span>\n  </button>\n  <button\n    (click)=\"assignDevices()\"\n    type=\"button\"\n    class=\"btn btn-primary\"\n    [ngClass]=\"{ 'btn-pending': pendingStatus }\"\n    title=\"{{ 'Assign' | translate }}\"\n    [disabled]=\"selected.length === 0 || !canAssignDevice\"\n  >\n    <span>{{ 'Assign' | translate }}</span>\n  </button>\n</div>\n", dependencies: [{ kind: "component", type: SubAssetsGridComponent, selector: "c8y-sub-assets-grid", inputs: ["parent-group", "refresh", "title", "emptyStateText", "loadingItemsLabel", "columnsConfigKey", "columns", "pagination", "actionControls", "selectable", "baseQuery", "bulkActionControls", "filterable", "sortable", "displayOptions"], outputs: ["onColumnsChange", "itemsSelect"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AssignChildDevicesComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-assign-child-devices', imports: [SubAssetsGridComponent, NgClass, C8yTranslatePipe], template: "<div class=\"card-block flex-no-shrink separator-bottom col-xs-12 large-padding p-t-24 p-b-24\">\n  <div class=\"row\">\n    <div class=\"col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4\">\n      <h4 class=\"text-center text-medium\" id=\"childDevicesDrawerTitle\">\n        {{ 'Assign child devices' | translate }}\n      </h4>\n    </div>\n  </div>\n</div>\n\n<c8y-sub-assets-grid\n  [title]=\"''\"\n  [emptyStateText]=\"'All child devices are already assigned' | translate\"\n  [refresh]=\"refresh\"\n  [actionControls]=\"[]\"\n  [columnsConfigKey]=\"'assign-child-devices'\"\n  [selectable]=\"true\"\n  [parent-group]=\"parentDevice\"\n  [baseQuery]=\"baseQuery\"\n  (itemsSelect)=\"onSelected($event)\"\n  class=\"d-contents\"\n></c8y-sub-assets-grid>\n\n<div class=\"text-center card-footer p-24 separator\">\n  <button\n    (click)=\"onCancel.emit()\"\n    type=\"button\"\n    class=\"btn btn-default\"\n    title=\"{{ 'Cancel' | translate }}\"\n  >\n    <span>{{ 'Cancel' | translate }}</span>\n  </button>\n  <button\n    (click)=\"assignDevices()\"\n    type=\"button\"\n    class=\"btn btn-primary\"\n    [ngClass]=\"{ 'btn-pending': pendingStatus }\"\n    title=\"{{ 'Assign' | translate }}\"\n    [disabled]=\"selected.length === 0 || !canAssignDevice\"\n  >\n    <span>{{ 'Assign' | translate }}</span>\n  </button>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i3.AlertService }, { type: SubAssetsService }, { type: i2.InventoryService }], propDecorators: { currentGroupId: [{
                type: Input
            }], parentDevice: [{
                type: Input
            }], onCancel: [{
                type: Output
            }], onSelectedDevices: [{
                type: Output
            }], refresh: [{
                type: Input
            }], onlySelect: [{
                type: Input
            }], onEnterKeyDown: [{
                type: HostListener,
                args: ['document:keydown.enter', ['$event']]
            }], onEscapeKeyDown: [{
                type: HostListener,
                args: ['document:keydown.escape', ['$event']]
            }] } });

class AddGroupComponent {
    constructor(fb, addGroupService, alert, subAssetsService, gainsightService, permissionsService) {
        this.fb = fb;
        this.addGroupService = addGroupService;
        this.alert = alert;
        this.subAssetsService = subAssetsService;
        this.gainsightService = gainsightService;
        this.permissionsService = permissionsService;
        this.refresh = new EventEmitter();
        this.onDeviceQueryStringChange = new EventEmitter();
        this.onCancel = new EventEmitter();
        this.showAssignChildDevices = false;
        this.actionControls = [];
        this.pendingStatus = false;
        this.pagination = { pageSize: 20, currentPage: 1 };
        this.selected = [];
        this.selectedChildDevices = [];
        this.canCreateGroup = false;
        this.canAssignDevice = false;
        this.PRODUCT_EXPERIENCE = PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED;
        this.ITEMS_SELECT_LIMIT = 15;
        this.btnLabels = {
            next: gettext('Next'),
            cancel: gettext('Cancel'),
            create: gettext('Create')
        };
    }
    onEnterKeyDown(_event) {
        // Order matters! Needs to be placed before this.stepper.next
        if ((this.isGroupDetailsStep() && !this.canAssignDevice) || this.isAssignDeviceStep()) {
            this.createGroup();
            return;
        }
        this.stepper.next();
    }
    async ngOnInit() {
        this.formGroupStepOne = this.fb.group({
            name: ['', Validators.required],
            description: ['']
        });
        this.subscription = this.onCancel.subscribe(() => this.resetStepper());
        this.canCreateGroup =
            this.subAssetsService.canCreateGroup() ||
                (await this.permissionsService.canEdit([
                    Permissions.ROLE_INVENTORY_ADMIN,
                    Permissions.ROLE_INVENTORY_CREATE,
                    Permissions.ROLE_MANAGED_OBJECT_ADMIN,
                    Permissions.ROLE_MANAGED_OBJECT_CREATE
                ], {
                    id: this.currentGroupId
                }));
        this.canAssignDevice = await this.subAssetsService.canAssignDevice({
            id: this.currentGroupId
        });
        this.setActionControls();
    }
    setActionControls() {
        const actionControls = [];
        const selectChildrenAction = {
            type: 'SHOW_TARGET_CHILD_DEVICES',
            icon: 'enter-bottom',
            text: gettext('Select target child devices'),
            callback: (asset) => this.selectChildren(asset),
            showIf: (asset) => asset.childDevices.references.length > 0
        };
        actionControls.push(selectChildrenAction);
        this.actionControls = actionControls;
        this.refresh.emit();
    }
    ngAfterViewInit() {
        this.nameInput = this.nameInputRef.nativeElement;
        this.setFocusOnNameInput();
    }
    async createGroup() {
        if (this.canCreateGroup === false) {
            return;
        }
        this.pendingStatus = true;
        const combinedDevices = [...this.selected, ...this.selectedChildDevices];
        await this.addGroupService.createGroupAndAssignDevices(this.formGroupStepOne.value, this.currentGroupId, combinedDevices);
        this.pendingStatus = false;
        this.resetStepper();
        const alertMsg = gettext('Group created.');
        this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.EVENT, {
            component: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.ADD_GROUP.COMPONENTS.ADD_GROUP,
            url: window.location.href,
            result: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.ADD_GROUP.RESULTS.ADD_SUCCESS
        });
        this.alert.success(alertMsg);
        this.refresh.emit();
        this.onCancel.emit();
    }
    onSelected(selectedDevicesIDs) {
        this.selected = selectedDevicesIDs;
    }
    onSelectedChildDevices(selectedDevicesIDs) {
        this.selectedChildDevices = selectedDevicesIDs;
    }
    resetStepper() {
        this.stepper.reset();
        this.stepper.selectedIndex = 1;
        this.selected = [];
    }
    ngOnDestroy() {
        if (this.subscription) {
            this.subscription.unsubscribe();
        }
    }
    isGroupDetailsStep() {
        return this.stepper.selectedIndex === 0;
    }
    isAssignDeviceStep() {
        return this.stepper.selectedIndex === 1;
    }
    setFocusOnNameInput() {
        if (this.nameInput) {
            this.nameInput.focus();
            this.nameInput.select();
        }
    }
    selectChildren(asset) {
        this.showAssignChildDevices = true;
        this.showChildrenForDevice = asset;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AddGroupComponent, deps: [{ token: i1$1.FormBuilder }, { token: AddGroupService }, { token: i3.AlertService }, { token: SubAssetsService }, { token: i3.GainsightService }, { token: i3.Permissions }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: AddGroupComponent, isStandalone: true, selector: "c8y-add-group", inputs: { currentGroupId: "currentGroupId", refresh: "refresh" }, outputs: { onDeviceQueryStringChange: "onDeviceQueryStringChange", onCancel: "onCancel" }, host: { listeners: { "document:keydown.enter": "onEnterKeyDown($event)" } }, viewQueries: [{ propertyName: "stepper", first: true, predicate: C8yStepper, descendants: true }, { propertyName: "nameInputRef", first: true, predicate: ["nameRef"], descendants: true }], ngImport: i0, template: "<div\n  [ngClass]=\"{ drawerOpen: true }\"\n  *ngIf=\"!currentGroupId; else stepper\"\n>\n  <div class=\"bottom-drawer has-backdrop\"\n    role=\"dialog\" \n    [cdkTrapFocus]=\"!currentGroupId\" \n    aria-modal=\"true\" \n    aria-labelledby=\"drawerTitle\">\n    <div class=\"d-contents\">\n      <ng-container [ngTemplateOutlet]=\"stepper\"></ng-container>\n    </div>\n  </div>\n</div>\n\n<ng-template #stepper>\n  <c8y-stepper\n    class=\"d-col flex-nowrap no-align-items fit-h c8y-stepper--no-btns\"\n    [disableDefaultIcons]=\"{ edit: true, done: false }\"\n    [disableProgressButtons]=\"true\"\n    [customClasses]=\"['col-md-6', 'col-md-offset-3', 'm-t-24', 'm-b-40', 'p-0', 'flex-no-shrink']\"\n    linear\n    c8yProductExperience\n    inherit\n    [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n    [actionData]=\"{ component: PRODUCT_EXPERIENCE.ADD_GROUP.COMPONENTS.ADD_GROUP }\"\n  >\n    <cdk-step\n      [stepControl]=\"formGroupStepOne\"\n      [label]=\"'New group' | translate\"\n    >\n      <div class=\"p-16 p-t-0 flex-no-shrink separator-bottom col-xs-12\">\n        <div class=\"row\">\n          <div class=\"col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4\">\n            <div class=\"h4 text-center text-medium\" id=\"drawerTitle\">\n              {{ 'New group' | translate }}\n            </div>\n          </div>\n        </div>\n      </div>\n      <div class=\"col-xs-12 flex-grow no-gutter\">\n        <div class=\"card-inner-scroll fit-h\">\n          <div class=\"card-block p-b-0\">\n            <div class=\"row\">\n              <div class=\"col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4\">\n                <c8y-form-group [novalidation]=\"true\">\n                  <div [formGroup]=\"formGroupStepOne\">\n                    <c8y-form-group>\n                      <label translate>Name</label>\n                      <input\n                        class=\"form-control\"\n                        placeholder=\"{{ 'e.g. First floor' | translate }} \"\n                        type=\"text\"\n                        required\n                        formControlName=\"name\"\n                        maxlength=\"254\"\n                        #nameRef\n                      />\n                    </c8y-form-group>\n\n                    <c8y-form-group>\n                      <label translate>Description</label>\n                      <input\n                        class=\"form-control\"\n                        placeholder=\"{{ 'e.g. first floor devices' | translate }}\"\n                        type=\"text\"\n                        formControlName=\"description\"\n                      />\n                    </c8y-form-group>\n                  </div>\n                </c8y-form-group>\n                <c8y-form-group>\n                  <div [formGroup]=\"formGroupStepOne\"></div>\n                </c8y-form-group>\n                <div\n                  class=\"alert alert-info max-width-100\"\n                  translate\n                  *ngIf=\"!canAssignDevice\"\n                >\n                  You don't have permission to assign devices.\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      <c8y-stepper-buttons\n        class=\"d-block card-footer p-24 separator\"\n        (onCancel)=\"onCancel.emit()\"\n        (onCustom)=\"createGroup()\"\n        [disabled]=\"!canCreateGroup\"\n        [labels]=\"\n          canAssignDevice\n            ? { next: btnLabels.next, cancel: btnLabels.cancel }\n            : { custom: btnLabels.create, cancel: btnLabels.cancel }\n        \"\n        [showButtons]=\"\n          canAssignDevice ? { next: true, cancel: true } : { custom: true, cancel: true }\n        \"\n      ></c8y-stepper-buttons>\n    </cdk-step>\n    <cdk-step [label]=\"'Assign devices' | translate\">\n      <div class=\"p-16 p-t-0 flex-no-shrink separator-bottom col-xs-12\">\n        <div class=\"row\">\n          <div class=\"col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4\">\n            <div class=\"h4 text-center text-medium\">\n              {{ 'Assign devices' | translate }}\n            </div>\n          </div>\n        </div>\n      </div>\n      <div class=\"col-xs-12 no-gutter flex-grow\">\n        <c8y-device-grid\n          [title]=\"'Select target devices' | translate\"\n          [actionControls]=\"actionControls\"\n          [infiniteScroll]=\"'auto'\"\n          [selectable]=\"true\"\n          [withChildren]=\"true\"\n          [pagination]=\"pagination\"\n          (itemsSelect)=\"onSelected($event)\"\n          [refresh]=\"refresh\"\n          c8yProductExperience\n          [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n          [actionData]=\"{ component: PRODUCT_EXPERIENCE.ADD_GROUP.COMPONENTS.ADD_GROUP }\"\n        ></c8y-device-grid>\n      </div>\n      <c8y-stepper-buttons\n        class=\"d-block card-footer p-24 separator\"\n        (onCancel)=\"onCancel.emit()\"\n        (onCustom)=\"createGroup()\"\n        [labels]=\"{ custom: btnLabels.create }\"\n        [disabled]=\"!canAssignDevice\"\n        [pending]=\"pendingStatus\"\n      ></c8y-stepper-buttons>\n    </cdk-step>\n  </c8y-stepper>\n</ng-template>\n\n<div\n  *ngIf=\"showAssignChildDevices\"\n  [ngClass]=\"{ drawerOpen: showAssignChildDevices }\"\n>\n  <div\n    class=\"m-t-40 bottom-drawer has-backdrop\"\n    role=\"dialog\"\n    aria-modal=\"true\"\n    aria-labelledby=\"childDevicesDrawerTitle\"\n    [ngStyle]=\"!!currentGroupId && { right: '0px'  }\"\n  >\n    <div class=\"d-flex d-col no-align-items fit-h\">\n      <c8y-assign-child-devices\n        class=\"d-contents\"\n        (onCancel)=\"showAssignChildDevices = false\"\n        [refresh]=\"refresh\"\n        [currentGroupId]=\"currentGroupId\"\n        [parentDevice]=\"showChildrenForDevice\"\n        [onlySelect]=\"true\"\n        (onSelectedDevices)=\"onSelectedChildDevices($event)\"\n      ></c8y-assign-child-devices>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: C8yStepper, selector: "c8y-stepper", inputs: ["disableDefaultIcons", "disableProgressButtons", "customClasses", "hideStepProgress", "useStepLabelsAsTitlesOnly"], outputs: ["onStepChange"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "component", type: CdkStep, selector: "cdk-step", inputs: ["stepControl", "label", "errorMessage", "aria-label", "aria-labelledby", "state", "editable", "optional", "completed", "hasError"], outputs: ["interacted"], exportAs: ["cdkStep"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "component", type: C8yStepperButtons, selector: "c8y-stepper-buttons", inputs: ["labels", "pending", "disabled", "showButtons"], outputs: ["onCancel", "onNext", "onBack", "onCustom"] }, { kind: "component", type: DeviceGridComponent, selector: "c8y-device-grid", inputs: ["dataCallback", "refresh", "title", "loadMoreItemsLabel", "loadingItemsLabel", "legacyConfigKey", "legacyFilterKey", "columns", "pagination", "infiniteScroll", "actionControls", "selectable", "singleSelection", "baseQuery", "bulkActionControls", "headerActionControls", "childDeviceGrid", "parentDeviceId", "withChildren", "showSearch", "activeClassName"], outputs: ["onColumnsChange", "onFilterChange", "onDeviceQueryStringChange", "itemsSelect"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: AssignChildDevicesComponent, selector: "c8y-assign-child-devices", inputs: ["currentGroupId", "parentDevice", "refresh", "onlySelect"], outputs: ["onCancel", "onSelectedDevices"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AddGroupComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-add-group', imports: [
                        NgIf,
                        NgClass,
                        NgTemplateOutlet,
                        C8yStepper,
                        ProductExperienceDirective,
                        CdkStep,
                        CdkTrapFocus,
                        FormGroupComponent,
                        FormsModule,
                        ReactiveFormsModule,
                        C8yTranslateDirective,
                        RequiredInputPlaceholderDirective,
                        C8yStepperButtons,
                        DeviceGridComponent,
                        NgStyle,
                        AssignChildDevicesComponent,
                        C8yTranslatePipe
                    ], template: "<div\n  [ngClass]=\"{ drawerOpen: true }\"\n  *ngIf=\"!currentGroupId; else stepper\"\n>\n  <div class=\"bottom-drawer has-backdrop\"\n    role=\"dialog\" \n    [cdkTrapFocus]=\"!currentGroupId\" \n    aria-modal=\"true\" \n    aria-labelledby=\"drawerTitle\">\n    <div class=\"d-contents\">\n      <ng-container [ngTemplateOutlet]=\"stepper\"></ng-container>\n    </div>\n  </div>\n</div>\n\n<ng-template #stepper>\n  <c8y-stepper\n    class=\"d-col flex-nowrap no-align-items fit-h c8y-stepper--no-btns\"\n    [disableDefaultIcons]=\"{ edit: true, done: false }\"\n    [disableProgressButtons]=\"true\"\n    [customClasses]=\"['col-md-6', 'col-md-offset-3', 'm-t-24', 'm-b-40', 'p-0', 'flex-no-shrink']\"\n    linear\n    c8yProductExperience\n    inherit\n    [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n    [actionData]=\"{ component: PRODUCT_EXPERIENCE.ADD_GROUP.COMPONENTS.ADD_GROUP }\"\n  >\n    <cdk-step\n      [stepControl]=\"formGroupStepOne\"\n      [label]=\"'New group' | translate\"\n    >\n      <div class=\"p-16 p-t-0 flex-no-shrink separator-bottom col-xs-12\">\n        <div class=\"row\">\n          <div class=\"col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4\">\n            <div class=\"h4 text-center text-medium\" id=\"drawerTitle\">\n              {{ 'New group' | translate }}\n            </div>\n          </div>\n        </div>\n      </div>\n      <div class=\"col-xs-12 flex-grow no-gutter\">\n        <div class=\"card-inner-scroll fit-h\">\n          <div class=\"card-block p-b-0\">\n            <div class=\"row\">\n              <div class=\"col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4\">\n                <c8y-form-group [novalidation]=\"true\">\n                  <div [formGroup]=\"formGroupStepOne\">\n                    <c8y-form-group>\n                      <label translate>Name</label>\n                      <input\n                        class=\"form-control\"\n                        placeholder=\"{{ 'e.g. First floor' | translate }} \"\n                        type=\"text\"\n                        required\n                        formControlName=\"name\"\n                        maxlength=\"254\"\n                        #nameRef\n                      />\n                    </c8y-form-group>\n\n                    <c8y-form-group>\n                      <label translate>Description</label>\n                      <input\n                        class=\"form-control\"\n                        placeholder=\"{{ 'e.g. first floor devices' | translate }}\"\n                        type=\"text\"\n                        formControlName=\"description\"\n                      />\n                    </c8y-form-group>\n                  </div>\n                </c8y-form-group>\n                <c8y-form-group>\n                  <div [formGroup]=\"formGroupStepOne\"></div>\n                </c8y-form-group>\n                <div\n                  class=\"alert alert-info max-width-100\"\n                  translate\n                  *ngIf=\"!canAssignDevice\"\n                >\n                  You don't have permission to assign devices.\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      <c8y-stepper-buttons\n        class=\"d-block card-footer p-24 separator\"\n        (onCancel)=\"onCancel.emit()\"\n        (onCustom)=\"createGroup()\"\n        [disabled]=\"!canCreateGroup\"\n        [labels]=\"\n          canAssignDevice\n            ? { next: btnLabels.next, cancel: btnLabels.cancel }\n            : { custom: btnLabels.create, cancel: btnLabels.cancel }\n        \"\n        [showButtons]=\"\n          canAssignDevice ? { next: true, cancel: true } : { custom: true, cancel: true }\n        \"\n      ></c8y-stepper-buttons>\n    </cdk-step>\n    <cdk-step [label]=\"'Assign devices' | translate\">\n      <div class=\"p-16 p-t-0 flex-no-shrink separator-bottom col-xs-12\">\n        <div class=\"row\">\n          <div class=\"col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4\">\n            <div class=\"h4 text-center text-medium\">\n              {{ 'Assign devices' | translate }}\n            </div>\n          </div>\n        </div>\n      </div>\n      <div class=\"col-xs-12 no-gutter flex-grow\">\n        <c8y-device-grid\n          [title]=\"'Select target devices' | translate\"\n          [actionControls]=\"actionControls\"\n          [infiniteScroll]=\"'auto'\"\n          [selectable]=\"true\"\n          [withChildren]=\"true\"\n          [pagination]=\"pagination\"\n          (itemsSelect)=\"onSelected($event)\"\n          [refresh]=\"refresh\"\n          c8yProductExperience\n          [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n          [actionData]=\"{ component: PRODUCT_EXPERIENCE.ADD_GROUP.COMPONENTS.ADD_GROUP }\"\n        ></c8y-device-grid>\n      </div>\n      <c8y-stepper-buttons\n        class=\"d-block card-footer p-24 separator\"\n        (onCancel)=\"onCancel.emit()\"\n        (onCustom)=\"createGroup()\"\n        [labels]=\"{ custom: btnLabels.create }\"\n        [disabled]=\"!canAssignDevice\"\n        [pending]=\"pendingStatus\"\n      ></c8y-stepper-buttons>\n    </cdk-step>\n  </c8y-stepper>\n</ng-template>\n\n<div\n  *ngIf=\"showAssignChildDevices\"\n  [ngClass]=\"{ drawerOpen: showAssignChildDevices }\"\n>\n  <div\n    class=\"m-t-40 bottom-drawer has-backdrop\"\n    role=\"dialog\"\n    aria-modal=\"true\"\n    aria-labelledby=\"childDevicesDrawerTitle\"\n    [ngStyle]=\"!!currentGroupId && { right: '0px'  }\"\n  >\n    <div class=\"d-flex d-col no-align-items fit-h\">\n      <c8y-assign-child-devices\n        class=\"d-contents\"\n        (onCancel)=\"showAssignChildDevices = false\"\n        [refresh]=\"refresh\"\n        [currentGroupId]=\"currentGroupId\"\n        [parentDevice]=\"showChildrenForDevice\"\n        [onlySelect]=\"true\"\n        (onSelectedDevices)=\"onSelectedChildDevices($event)\"\n      ></c8y-assign-child-devices>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: AddGroupService }, { type: i3.AlertService }, { type: SubAssetsService }, { type: i3.GainsightService }, { type: i3.Permissions }], propDecorators: { currentGroupId: [{
                type: Input
            }], refresh: [{
                type: Input
            }], onDeviceQueryStringChange: [{
                type: Output
            }], onCancel: [{
                type: Output
            }], stepper: [{
                type: ViewChild,
                args: [C8yStepper, { static: false }]
            }], nameInputRef: [{
                type: ViewChild,
                args: ['nameRef', { static: false }]
            }], onEnterKeyDown: [{
                type: HostListener,
                args: ['document:keydown.enter', ['$event']]
            }] } });

class AssignDevicesComponent {
    static { this.GRID_CONFIG_CONTEXT = {
        key: 'assign-devices-grid',
        configFilter: {
            filter: false
        }
    }; }
    constructor(alert, subAssetsService, inventoryService, gainsightService) {
        this.alert = alert;
        this.subAssetsService = subAssetsService;
        this.inventoryService = inventoryService;
        this.gainsightService = gainsightService;
        this.CURRENT_LOCATION = location.href;
        this.PRODUCT_EXPERIENCE = PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED;
        this.refresh = new EventEmitter();
        this.onCancel = new EventEmitter();
        this.onShowChildDevices = new EventEmitter();
        this.selectedDevice = new EventEmitter();
        this.pendingStatus = false;
        this.pagination = { pageSize: 20, currentPage: 1 };
        this.selected = [];
        this.canAssignDevice = false;
        this.actionControls = [];
        this.headerActionControls = [];
        this.showChildren = false;
        this.isSelectable = true;
    }
    onEnterKeyDown(_event) {
        if (this.selected.length > 0) {
            this.assignDevices();
        }
    }
    async ngOnInit() {
        this.setNotIncludedInGroupQuery();
        this.canAssignDevice = await this.subAssetsService.canAssignDevice({
            id: this.currentGroupId
        });
        this.setHeaderActionControls();
    }
    setNotIncludedInGroupQuery() {
        const notIncludedInGroupQuery = { __not: { __bygroupid: this.currentGroupId } };
        this.baseQuery = notIncludedInGroupQuery;
    }
    setHeaderActionControls() {
        const headerActionControls = [];
        const showChildDevices = {
            type: 'DISPLAY_CHILD_DEVICES_BUTTON',
            text: gettext('Enable child devices selection'),
            template: this.showDevicesToggle,
            callback: () => {
                this.showChildren = !this.showChildren;
                this.setActionControls(this.showChildren);
                this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.EVENT, {
                    component: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.ASSIGN_DEVICES.COMPONENTS.ASSIGN_DEVICES,
                    action: PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED.ASSIGN_DEVICES.ACTIONS.DISPLAY_CHILD_DEVICES,
                    url: this.CURRENT_LOCATION
                });
            }
        };
        headerActionControls.push(showChildDevices);
        this.headerActionControls = headerActionControls;
    }
    setActionControls(showChildren) {
        const actionControls = [];
        const selectChildrenAction = {
            type: 'SHOW_TARGET_CHILD_DEVICES',
            icon: 'enter-bottom',
            text: gettext('Select target child devices'),
            callback: (asset) => this.selectChildren(asset),
            showIf: (asset) => asset.childDevices.references.length > 0
        };
        if (showChildren) {
            actionControls.push(selectChildrenAction);
        }
        this.actionControls = actionControls;
        this.refresh.emit();
    }
    async assignDevices() {
        if (this.canAssignDevice === false) {
            return;
        }
        this.pendingStatus = true;
        try {
            await this.inventoryService.childAssetsBulkAdd(this.selected, this.currentGroupId);
            this.refresh.emit();
            this.alert.success(gettext('Devices assigned.'));
        }
        catch (error) {
            this.alert.danger(gettext('Could not assign devices.'), error);
        }
        this.pendingStatus = false;
        this.selected = [];
        this.onCancel.emit();
    }
    onSelected(selectedDevicesIDs) {
        this.selected = selectedDevicesIDs;
    }
    selectChildren(asset) {
        this.onShowChildDevices.emit(true);
        this.selectedDevice.emit(asset);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AssignDevicesComponent, deps: [{ token: i3.AlertService }, { token: SubAssetsService }, { token: i2.InventoryService }, { token: i3.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: AssignDevicesComponent, isStandalone: true, selector: "c8y-assign-devices", inputs: { currentGroupId: "currentGroupId", refresh: "refresh" }, outputs: { onCancel: "onCancel", onShowChildDevices: "onShowChildDevices", selectedDevice: "selectedDevice" }, host: { listeners: { "document:keydown.enter": "onEnterKeyDown($event)" } }, providers: [
            {
                provide: DATA_GRID_CONFIGURATION_STRATEGY,
                useClass: UserPreferencesConfigurationStrategy
            },
            {
                provide: DATA_GRID_CONFIGURATION_CONTEXT,
                useValue: AssignDevicesComponent.GRID_CONFIG_CONTEXT
            }
        ], viewQueries: [{ propertyName: "showDevicesToggle", first: true, predicate: ["showDevicesToggle"], descendants: true, read: TemplateRef }], ngImport: i0, template: "<div class=\"card-block flex-no-shrink separator-bottom col-xs-12 large-padding p-t-24 p-b-24\">\n  <div class=\"row\">\n    <div class=\"col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4\">\n      <div\n        class=\"h4 text-center text-medium\"\n        id=\"drawerTitle\"\n      >\n        {{ 'Assign devices' | translate }}\n      </div>\n    </div>\n  </div>\n</div>\n<c8y-device-grid\n  class=\"flex-grow col-xs-12 no-gutter\"\n  [title]=\"''\"\n  [actionControls]=\"actionControls\"\n  [infiniteScroll]=\"'auto'\"\n  [selectable]=\"isSelectable\"\n  [pagination]=\"pagination\"\n  (itemsSelect)=\"onSelected($event)\"\n  [refresh]=\"refresh\"\n  [baseQuery]=\"baseQuery\"\n  [headerActionControls]=\"headerActionControls\"\n  [withChildren]=\"true\"\n  c8yProductExperience\n  [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n  [actionData]=\"{ component: PRODUCT_EXPERIENCE.ASSIGN_DEVICES.COMPONENTS.ASSIGN_DEVICES }\"\n></c8y-device-grid>\n\n<div class=\"text-center card-footer p-24 separator\">\n  <button\n    class=\"btn btn-default\"\n    title=\"{{ 'Cancel' | translate }}\"\n    type=\"button\"\n    (click)=\"onCancel.emit()\"\n    c8yProductExperience\n    [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n    [actionData]=\"{\n      component: PRODUCT_EXPERIENCE.ASSIGN_DEVICES.COMPONENTS.ASSIGN_DEVICES,\n      action: PRODUCT_EXPERIENCE.ASSIGN_DEVICES.ACTIONS.CANCEL\n    }\"\n  >\n    <span>{{ 'Cancel' | translate }}</span>\n  </button>\n  <button\n    class=\"btn btn-primary\"\n    title=\"{{ 'Assign' | translate }}\"\n    type=\"button\"\n    [ngClass]=\"{ 'btn-pending': pendingStatus }\"\n    (click)=\"assignDevices()\"\n    [disabled]=\"selected.length === 0 || !canAssignDevice\"\n    c8yProductExperience\n    [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n    [actionData]=\"{\n      component: PRODUCT_EXPERIENCE.ASSIGN_DEVICES.COMPONENTS.ASSIGN_DEVICES,\n      action: PRODUCT_EXPERIENCE.ASSIGN_DEVICES.ACTIONS.ASSIGN\n    }\"\n  >\n    <span>{{ 'Assign' | translate }}</span>\n  </button>\n</div>\n\n<ng-template\n  #showDevicesToggle\n  let-control=\"headerActionControl\"\n>\n  <label\n    class=\"c8y-switch a-s-center\"\n    title=\"{{ control.text | translate }}\"\n  >\n    <input\n      type=\"checkbox\"\n      [(ngModel)]=\"showChildren\"\n      (click)=\"control.callback()\"\n    />\n    <span></span>\n    <span>{{ control.text | translate }}</span>\n  </label>\n  <button\n    class=\"btn-help m-r-16 a-s-center\"\n    [attr.aria-label]=\"'Help' | translate\"\n    [popover]=\"childDevicesPop\"\n    placement=\"bottom\"\n    triggers=\"focus\"\n    type=\"button\"\n  ></button>\n  <ng-template #childDevicesPop>\n    <span\n      class=\"btn btn-dot btn-icon no-pointer\"\n      title=\"{{ 'Child devices icon' | translate }}\"\n    >\n      <i class=\"text-primary dlt-c8y-icon-enter-bottom\"></i>\n    </span>\n    <span translate>\n      Displays the button next to target devices with children. Clicking it displays a list with all\n      child devices of the selected target device.\n    </span>\n  </ng-template>\n</ng-template>\n", dependencies: [{ kind: "component", type: DeviceGridComponent, selector: "c8y-device-grid", inputs: ["dataCallback", "refresh", "title", "loadMoreItemsLabel", "loadingItemsLabel", "legacyConfigKey", "legacyFilterKey", "columns", "pagination", "infiniteScroll", "actionControls", "selectable", "singleSelection", "baseQuery", "bulkActionControls", "headerActionControls", "childDeviceGrid", "parentDeviceId", "withChildren", "showSearch", "activeClassName"], outputs: ["onColumnsChange", "onFilterChange", "onDeviceQueryStringChange", "itemsSelect"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AssignDevicesComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-assign-devices', providers: [
                        {
                            provide: DATA_GRID_CONFIGURATION_STRATEGY,
                            useClass: UserPreferencesConfigurationStrategy
                        },
                        {
                            provide: DATA_GRID_CONFIGURATION_CONTEXT,
                            useValue: AssignDevicesComponent.GRID_CONFIG_CONTEXT
                        }
                    ], imports: [
                        DeviceGridComponent,
                        ProductExperienceDirective,
                        NgClass,
                        FormsModule,
                        PopoverDirective,
                        C8yTranslateDirective,
                        C8yTranslatePipe
                    ], template: "<div class=\"card-block flex-no-shrink separator-bottom col-xs-12 large-padding p-t-24 p-b-24\">\n  <div class=\"row\">\n    <div class=\"col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4\">\n      <div\n        class=\"h4 text-center text-medium\"\n        id=\"drawerTitle\"\n      >\n        {{ 'Assign devices' | translate }}\n      </div>\n    </div>\n  </div>\n</div>\n<c8y-device-grid\n  class=\"flex-grow col-xs-12 no-gutter\"\n  [title]=\"''\"\n  [actionControls]=\"actionControls\"\n  [infiniteScroll]=\"'auto'\"\n  [selectable]=\"isSelectable\"\n  [pagination]=\"pagination\"\n  (itemsSelect)=\"onSelected($event)\"\n  [refresh]=\"refresh\"\n  [baseQuery]=\"baseQuery\"\n  [headerActionControls]=\"headerActionControls\"\n  [withChildren]=\"true\"\n  c8yProductExperience\n  [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n  [actionData]=\"{ component: PRODUCT_EXPERIENCE.ASSIGN_DEVICES.COMPONENTS.ASSIGN_DEVICES }\"\n></c8y-device-grid>\n\n<div class=\"text-center card-footer p-24 separator\">\n  <button\n    class=\"btn btn-default\"\n    title=\"{{ 'Cancel' | translate }}\"\n    type=\"button\"\n    (click)=\"onCancel.emit()\"\n    c8yProductExperience\n    [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n    [actionData]=\"{\n      component: PRODUCT_EXPERIENCE.ASSIGN_DEVICES.COMPONENTS.ASSIGN_DEVICES,\n      action: PRODUCT_EXPERIENCE.ASSIGN_DEVICES.ACTIONS.CANCEL\n    }\"\n  >\n    <span>{{ 'Cancel' | translate }}</span>\n  </button>\n  <button\n    class=\"btn btn-primary\"\n    title=\"{{ 'Assign' | translate }}\"\n    type=\"button\"\n    [ngClass]=\"{ 'btn-pending': pendingStatus }\"\n    (click)=\"assignDevices()\"\n    [disabled]=\"selected.length === 0 || !canAssignDevice\"\n    c8yProductExperience\n    [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n    [actionData]=\"{\n      component: PRODUCT_EXPERIENCE.ASSIGN_DEVICES.COMPONENTS.ASSIGN_DEVICES,\n      action: PRODUCT_EXPERIENCE.ASSIGN_DEVICES.ACTIONS.ASSIGN\n    }\"\n  >\n    <span>{{ 'Assign' | translate }}</span>\n  </button>\n</div>\n\n<ng-template\n  #showDevicesToggle\n  let-control=\"headerActionControl\"\n>\n  <label\n    class=\"c8y-switch a-s-center\"\n    title=\"{{ control.text | translate }}\"\n  >\n    <input\n      type=\"checkbox\"\n      [(ngModel)]=\"showChildren\"\n      (click)=\"control.callback()\"\n    />\n    <span></span>\n    <span>{{ control.text | translate }}</span>\n  </label>\n  <button\n    class=\"btn-help m-r-16 a-s-center\"\n    [attr.aria-label]=\"'Help' | translate\"\n    [popover]=\"childDevicesPop\"\n    placement=\"bottom\"\n    triggers=\"focus\"\n    type=\"button\"\n  ></button>\n  <ng-template #childDevicesPop>\n    <span\n      class=\"btn btn-dot btn-icon no-pointer\"\n      title=\"{{ 'Child devices icon' | translate }}\"\n    >\n      <i class=\"text-primary dlt-c8y-icon-enter-bottom\"></i>\n    </span>\n    <span translate>\n      Displays the button next to target devices with children. Clicking it displays a list with all\n      child devices of the selected target device.\n    </span>\n  </ng-template>\n</ng-template>\n" }]
        }], ctorParameters: () => [{ type: i3.AlertService }, { type: SubAssetsService }, { type: i2.InventoryService }, { type: i3.GainsightService }], propDecorators: { currentGroupId: [{
                type: Input
            }], refresh: [{
                type: Input
            }], onCancel: [{
                type: Output
            }], onShowChildDevices: [{
                type: Output
            }], selectedDevice: [{
                type: Output
            }], showDevicesToggle: [{
                type: ViewChild,
                args: ['showDevicesToggle', { read: TemplateRef }]
            }], onEnterKeyDown: [{
                type: HostListener,
                args: ['document:keydown.enter', ['$event']]
            }] } });

class SubAssetsGridsModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsGridsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsGridsModule, imports: [CoreModule,
            DeviceGridModule,
            PopoverModule,
            BsDropdownModule,
            TooltipModule,
            AssignDevicesComponent,
            AssignChildDevicesComponent,
            SubAssetsGridComponent], exports: [SubAssetsGridComponent, AssignDevicesComponent, AssignChildDevicesComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsGridsModule, imports: [CoreModule,
            DeviceGridModule,
            PopoverModule,
            BsDropdownModule,
            TooltipModule,
            AssignDevicesComponent,
            AssignChildDevicesComponent,
            SubAssetsGridComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsGridsModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CoreModule,
                        DeviceGridModule,
                        PopoverModule,
                        BsDropdownModule,
                        TooltipModule,
                        AssignDevicesComponent,
                        AssignChildDevicesComponent,
                        SubAssetsGridComponent
                    ],
                    exports: [SubAssetsGridComponent, AssignDevicesComponent, AssignChildDevicesComponent]
                }]
        }] });

class AddGroupModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AddGroupModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: AddGroupModule, imports: [CoreModule,
            DeviceGridModule,
            FormsModule,
            ReactiveFormsModule,
            PopoverModule,
            SubAssetsGridsModule,
            AddGroupComponent], exports: [AddGroupComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AddGroupModule, providers: [AddGroupService], imports: [CoreModule,
            DeviceGridModule,
            FormsModule,
            ReactiveFormsModule,
            PopoverModule,
            SubAssetsGridsModule,
            AddGroupComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AddGroupModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CoreModule,
                        DeviceGridModule,
                        FormsModule,
                        ReactiveFormsModule,
                        PopoverModule,
                        SubAssetsGridsModule,
                        AddGroupComponent
                    ],
                    exports: [AddGroupComponent],
                    providers: [AddGroupService]
                }]
        }] });

class AssetPropertiesItemComponent {
    constructor(alert, c8yJsonSchemaService, filesService) {
        this.alert = alert;
        this.c8yJsonSchemaService = c8yJsonSchemaService;
        this.filesService = filesService;
    }
    async ngOnChanges(changes) {
        if (changes.isEdit) {
            this.resolveJsonSchema();
            await this.resolveFile();
        }
    }
    async resolveFile() {
        if (this.file) {
            try {
                if (this.filesService.fileNamesHaveValidExtension(this.file.name, 'image')) {
                    const imageFile = await this.filesService.getFile(this.file);
                    this.previewImage = await this.getPreviewIfImage(imageFile);
                }
            }
            catch (ex) {
                this.alert.danger(gettext('File could not be loaded.'));
            }
        }
    }
    formComplexPropsValue() {
        const complexProps = {};
        this.complex.forEach(complexObj => {
            if (complexObj.file) {
                complexProps[complexObj.key] = complexObj.value;
            }
            else {
                complexProps[complexObj.key] = this.value[complexObj.key];
            }
        });
        return complexProps;
    }
    getModel() {
        if (this.complex && this.complex.length > 0) {
            return {
                [this.key]: this.formComplexPropsValue()
            };
        }
        return {
            [this.key]: clone(this.value)
        };
    }
    resolveJsonSchema() {
        if (this.jsonSchema) {
            const fieldConfig = this.c8yJsonSchemaService.toFieldConfig(this.jsonSchema, this.jsonSchema);
            if (this.complex && this.complex.length > 0) {
                const orderedFieldConfig = sortBy(fieldConfig.fieldGroup[0].fieldGroup, 'order');
                fieldConfig.fieldGroup[0].fieldGroup = orderedFieldConfig;
            }
            this.form = new FormGroup({});
            this.fields = [fieldConfig];
            this.model = this.getModel();
        }
    }
    async getPreviewIfImage(imageFile) {
        return this.filesService.toBase64(imageFile);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AssetPropertiesItemComponent, deps: [{ token: i3.AlertService }, { token: i3.C8yJSONSchema }, { token: i3.FilesService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: AssetPropertiesItemComponent, isStandalone: true, selector: "c8y-asset-properties-item", inputs: { key: "key", value: "value", label: "label", type: "type", file: "file", complex: "complex", isEdit: "isEdit", jsonSchema: "jsonSchema" }, usesOnChanges: true, ngImport: i0, template: "<ng-container [ngSwitch]=\"type\" *ngIf=\"!isEdit\">\n  <ng-container *ngSwitchCase=\"'date'\">\n    {{ (value | c8yDate: 'fullDate') || ('Undefined' | translate) }}\n  </ng-container>\n  <ng-container *ngSwitchCase=\"'file'\">\n    <ng-container *ngIf=\"file\">\n      <img *ngIf=\"previewImage\" [src]=\"previewImage\" class=\"img-responsive\" />\n      <button\n        *ngIf=\"!previewImage\"\n        (click)=\"filesService.download(file)\"\n        type=\"button\"\n        title=\"{{ 'Download' | translate }} {{ file.name }}\"\n        class=\"btn btn-clean text-truncate p-0\"\n      >\n        {{ file.name }}\n      </button>\n    </ng-container>\n    <ng-container *ngIf=\"!file\">\n      {{ 'No file attached.' | translate }}\n    </ng-container>\n  </ng-container>\n  <ng-container *ngSwitchCase=\"'object'\">\n    <ul class=\"list-unstyled c8y-custom-properties\">\n      <li\n        *ngFor=\"let prop of complex; let i = index\"\n        [ngClass]=\"{ 'separator-top-bottom': i === 0, 'separator-bottom': i > 0 }\"\n        class=\"p-t-4 p-b-4 d-flex text-nowrap\"\n      >\n        <label\n          class=\"small m-b-0 m-r-8 text-truncate\"\n          title=\"{{ prop.label | translate }}\"\n          [ngClass]=\"{ 'a-s-start': prop.file }\"\n        >\n          {{ prop.label | translate }}\n        </label>\n        <span class=\"m-l-auto\" style=\"max-width: {{ prop.file ? '50%' : '100%' }}; min-width:0;\">\n          <c8y-asset-properties-item\n            [file]=\"prop.file\"\n            [key]=\"prop.key\"\n            [type]=\"prop.type\"\n            [value]=\"prop.value\"\n          ></c8y-asset-properties-item>\n        </span>\n      </li>\n    </ul>\n  </ng-container>\n  <!--\n  <ng-container *ngSwitchCase=\"'boolean'\">\n      <input type=\"checkbox\" [checked]=\"value\" [disabled]=\"true\" />\n    </ng-container>\n  -->\n  <ng-container *ngSwitchCase=\"type === 'number' || type === 'boolean' ? type : ''\">\n    <p class=\"text-truncate\" title=\"{{ value != null ? value : ('Undefined' | translate) }}\">\n      {{ value != null ? value : ('Undefined' | translate) }}\n    </p>\n  </ng-container>\n  <ng-container *ngSwitchDefault>\n    <p class=\"text-truncate\" title=\"{{ (value | translate) || ('Undefined' | translate) }}\">\n      {{ (value | translate) || ('Undefined' | translate) }}\n    </p>\n  </ng-container>\n</ng-container>\n<formly-form *ngIf=\"isEdit\" [form]=\"form\" [fields]=\"fields\" [model]=\"model\"></formly-form>\n", dependencies: [{ kind: "component", type: AssetPropertiesItemComponent, selector: "c8y-asset-properties-item", inputs: ["key", "value", "label", "type", "file", "complex", "isEdit", "jsonSchema"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i2$2.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AssetPropertiesItemComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-asset-properties-item', imports: [
                        NgIf,
                        NgSwitch,
                        NgSwitchCase,
                        NgFor,
                        NgClass,
                        NgSwitchDefault,
                        FormlyModule,
                        C8yTranslatePipe,
                        DatePipe
                    ], template: "<ng-container [ngSwitch]=\"type\" *ngIf=\"!isEdit\">\n  <ng-container *ngSwitchCase=\"'date'\">\n    {{ (value | c8yDate: 'fullDate') || ('Undefined' | translate) }}\n  </ng-container>\n  <ng-container *ngSwitchCase=\"'file'\">\n    <ng-container *ngIf=\"file\">\n      <img *ngIf=\"previewImage\" [src]=\"previewImage\" class=\"img-responsive\" />\n      <button\n        *ngIf=\"!previewImage\"\n        (click)=\"filesService.download(file)\"\n        type=\"button\"\n        title=\"{{ 'Download' | translate }} {{ file.name }}\"\n        class=\"btn btn-clean text-truncate p-0\"\n      >\n        {{ file.name }}\n      </button>\n    </ng-container>\n    <ng-container *ngIf=\"!file\">\n      {{ 'No file attached.' | translate }}\n    </ng-container>\n  </ng-container>\n  <ng-container *ngSwitchCase=\"'object'\">\n    <ul class=\"list-unstyled c8y-custom-properties\">\n      <li\n        *ngFor=\"let prop of complex; let i = index\"\n        [ngClass]=\"{ 'separator-top-bottom': i === 0, 'separator-bottom': i > 0 }\"\n        class=\"p-t-4 p-b-4 d-flex text-nowrap\"\n      >\n        <label\n          class=\"small m-b-0 m-r-8 text-truncate\"\n          title=\"{{ prop.label | translate }}\"\n          [ngClass]=\"{ 'a-s-start': prop.file }\"\n        >\n          {{ prop.label | translate }}\n        </label>\n        <span class=\"m-l-auto\" style=\"max-width: {{ prop.file ? '50%' : '100%' }}; min-width:0;\">\n          <c8y-asset-properties-item\n            [file]=\"prop.file\"\n            [key]=\"prop.key\"\n            [type]=\"prop.type\"\n            [value]=\"prop.value\"\n          ></c8y-asset-properties-item>\n        </span>\n      </li>\n    </ul>\n  </ng-container>\n  <!--\n  <ng-container *ngSwitchCase=\"'boolean'\">\n      <input type=\"checkbox\" [checked]=\"value\" [disabled]=\"true\" />\n    </ng-container>\n  -->\n  <ng-container *ngSwitchCase=\"type === 'number' || type === 'boolean' ? type : ''\">\n    <p class=\"text-truncate\" title=\"{{ value != null ? value : ('Undefined' | translate) }}\">\n      {{ value != null ? value : ('Undefined' | translate) }}\n    </p>\n  </ng-container>\n  <ng-container *ngSwitchDefault>\n    <p class=\"text-truncate\" title=\"{{ (value | translate) || ('Undefined' | translate) }}\">\n      {{ (value | translate) || ('Undefined' | translate) }}\n    </p>\n  </ng-container>\n</ng-container>\n<formly-form *ngIf=\"isEdit\" [form]=\"form\" [fields]=\"fields\" [model]=\"model\"></formly-form>\n" }]
        }], ctorParameters: () => [{ type: i3.AlertService }, { type: i3.C8yJSONSchema }, { type: i3.FilesService }], propDecorators: { key: [{
                type: Input
            }], value: [{
                type: Input
            }], label: [{
                type: Input
            }], type: [{
                type: Input
            }], file: [{
                type: Input
            }], complex: [{
                type: Input
            }], isEdit: [{
                type: Input
            }], jsonSchema: [{
                type: Input
            }] } });

function isFullScreenEnabled(element) {
    const doc = element;
    return !!(doc.fullscreenElement ||
        doc.mozFullScreenElement ||
        doc.webkitFullscreenElement ||
        doc.msFullscreenElement);
}
function toggleFullscreen(element) {
    const elem = element;
    const doc = element;
    if (!isFullScreenEnabled(element)) {
        if (elem.requestFullscreen) {
            elem.requestFullscreen();
        }
        else if (elem.msRequestFullscreen) {
            elem.msRequestFullscreen();
        }
        else if (elem.mozRequestFullScreen) {
            elem.mozRequestFullScreen();
        }
        else if (elem.webkitRequestFullscreen) {
            elem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
        }
    }
    else if (doc.exitFullscreen) {
        doc.exitFullscreen();
    }
    else if (doc.msExitFullscreen) {
        doc.msExitFullscreen();
    }
    else if (doc.mozCancelFullScreen) {
        doc.mozCancelFullScreen();
    }
    else if (doc.webkitExitFullscreen) {
        doc.webkitExitFullscreen();
    }
}

// Düsseldorf
const defaultMapLocation = {
    lat: defaultMapConfig.center[0],
    lng: defaultMapConfig.center[1]
};
class AssetLocationComponent {
    constructor(activatedRouter, mapService) {
        this.activatedRouter = activatedRouter;
        this.mapService = mapService;
        this.config = {
            center: defaultMapConfig.center,
            zoomLevel: 13,
            color: 'green',
            icon: 'c8y-icon-location'
        };
        this.isMarkerDraggable = false;
        this.isMapClickable = false;
        this.showMap = true;
    }
    async ngOnInit() {
        const leaflet = await this.mapService.getLeaflet();
        if (leaflet) {
            const { contextData } = !this.activatedRouter.parent || this.activatedRouter.snapshot.data.context
                ? this.activatedRouter.snapshot.data
                : this.activatedRouter.parent.snapshot.data;
            this.assets = contextData ? contextData : this.locationMO;
            if (this.assets.c8y_Position.lat && this.assets.c8y_Position.lng)
                this.config.center = [this.assets.c8y_Position.lat, this.assets.c8y_Position.lng];
            this.setView(this.assets.c8y_Position.lat, this.assets.c8y_Position.lng);
        }
    }
    ngOnChanges(changes) {
        if (changes.isEdit?.currentValue) {
            this.showMap = true;
            this.isMarkerDraggable = true;
            this.isMapClickable = true;
            queueMicrotask(() => this.mapView?.map.invalidateSize());
            this.mapView?.map.on('click', event => {
                this.onClickOfMap(event);
                this.updateMarker(event.latlng.lat, event.latlng.lng);
            });
            this.formSubscription = this.form?.valueChanges.subscribe(value => {
                this.updateMarker(value.c8y_Position.lat, value.c8y_Position.lng);
                this.setView(value.c8y_Position.lat, value.c8y_Position.lng);
            });
            return;
        }
        if (!changes.isEdit?.currentValue) {
            const isAnyValueMissing = this.checkIfAnyValueIsMissing(this.locationMO?.c8y_Position.lat, this.locationMO?.c8y_Position.lng);
            if (isAnyValueMissing) {
                this.showMap = false;
                return;
            }
            this.isMarkerDraggable = false;
            this.isMapClickable = false;
            this.updateMarker(this.locationMO?.c8y_Position.lat, this.locationMO?.c8y_Position.lng);
            this.setView(this.locationMO?.c8y_Position.lat, this.locationMO?.c8y_Position.lng);
        }
    }
    ngOnDestroy() {
        this.formSubscription?.unsubscribe();
        if (this.mapView?.markers && this.dragListener) {
            this.mapView?.markers.forEach(marker => {
                marker.off('drag', this.dragListener);
            });
        }
    }
    /**
     * This command is used to prefill the latitude and longitude values in the form when the marker is dragged.
     */
    onMarkerDrag(event) {
        if (this.form) {
            const properties = this.form.get('c8y_Position');
            properties?.get('lat').patchValue(event.target._latlng.lat);
            properties?.get('lng').patchValue(event.target._latlng.lng);
        }
    }
    /**
     * This method is used to update the marker with the specified values and if any one of the values is not availble, sets
     * showWarning to true.
     * @param latitude - The latitude of the marker
     * @param longitude - The longitude of the marker
     */
    updateMarker(latitude, longitude) {
        const isAnyValueMissing = this.checkIfAnyValueIsMissing(latitude, longitude);
        if (!isAnyValueMissing) {
            [latitude, longitude] = this.setLatLngValues(latitude, longitude);
            const asset = {
                c8y_Position: {
                    latitude,
                    longitude
                }
            };
            if (this.mapView) {
                const icon = this.mapView.getAssetIcon(this.assets);
                const leafletMarker = this.mapView.leaflet.marker([latitude, longitude], {
                    icon: icon,
                    draggable: this.isMarkerDraggable
                });
                if (this.isMarkerDraggable) {
                    this.dragListener = event => {
                        this.onMarkerDrag(event);
                    };
                    leafletMarker.on('dragend', this.dragListener);
                }
                this.mapView.clearMarkers();
                const marker = getC8yMarker(leafletMarker, asset);
                this.mapView.addMarkerToMap(marker);
                this.setView(latitude, longitude);
            }
            return;
        }
        this.mapView.clearMarkers();
    }
    /**
     * This command is used to prefill the latitude and longitude values in the form on click of map.
     */
    onClickOfMap(event) {
        if (this.form) {
            const properties = this.form.get('c8y_Position');
            properties?.get('lat').patchValue(event.latlng.lat);
            properties?.get('lng').patchValue(event.latlng.lng);
            this.form.markAsDirty();
        }
    }
    /**
     * Used to enable full screen of the map.
     */
    enableFullscreen() {
        toggleFullscreen(this.mapView.mapElement.nativeElement);
    }
    /**
     * Checks if any one of the values i.e., latitude/longitude is undefined or null.
     * @param latitude Latitude value of the position
     * @param longitude Longitude value of the position
     * @returns returns true if any one of the values are both the values are missing else it returns false.
     */
    checkIfAnyValueIsMissing(latitude, longitude) {
        return this.isNullOrUndefined(latitude) || this.isNullOrUndefined(longitude);
    }
    /**
     * Sets the view of the map based on the position of marker.
     * @param latitude - Latitude of the marker
     * @param longitude Longitude of the marker
     */
    setView(latitude, longitude) {
        if (isNumber(latitude) && isNumber(longitude) && this.mapView) {
            [latitude, longitude] = this.setLatLngValues(latitude, longitude);
            this.config.center = [latitude, longitude];
            this.mapView.center();
        }
    }
    setLatLngValues(latitude, longitude) {
        latitude = this.isNullOrUndefined(latitude) ? defaultMapLocation.lat : latitude;
        longitude = this.isNullOrUndefined(longitude) ? defaultMapLocation.lng : longitude;
        return [latitude, longitude];
    }
    isNullOrUndefined(value) {
        return value === null || value === undefined;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AssetLocationComponent, deps: [{ token: i1$2.ActivatedRoute }, { token: i2$3.MapService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: AssetLocationComponent, isStandalone: true, selector: "c8y-asset-location", inputs: { isEdit: "isEdit", locationMO: "locationMO", form: "form" }, viewQueries: [{ propertyName: "mapView", first: true, predicate: MapComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div [hidden]=\"!showMap\">\n  <div class=\"row\">\n    <button\n      class=\"btn btn-link pull-right\"\n      style=\"margin-right: 12px\"\n      title=\"Full screen\"\n      type=\"button\"\n      data-cy=\"asset-location-full-screen\"\n      (click)=\"enableFullscreen()\"\n    >\n    <i c8yIcon=\"expand\"></i>\n    </button>\n  </div>\n  <div style=\"width: 100%; height: 400px\">\n    <c8y-map\n      #map\n      [assets]=\"assets\"\n      [config]=\"config\"\n    ></c8y-map>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: MapComponent, selector: "c8y-map", inputs: ["config", "assets", "polyline$", "polylineOptions"], outputs: ["onRealtimeUpdate", "onMove", "onMoveEnd", "onZoomStart", "onZoomEnd", "onMap", "onInit"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AssetLocationComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-asset-location', imports: [IconDirective, MapComponent], template: "<div [hidden]=\"!showMap\">\n  <div class=\"row\">\n    <button\n      class=\"btn btn-link pull-right\"\n      style=\"margin-right: 12px\"\n      title=\"Full screen\"\n      type=\"button\"\n      data-cy=\"asset-location-full-screen\"\n      (click)=\"enableFullscreen()\"\n    >\n    <i c8yIcon=\"expand\"></i>\n    </button>\n  </div>\n  <div style=\"width: 100%; height: 400px\">\n    <c8y-map\n      #map\n      [assets]=\"assets\"\n      [config]=\"config\"\n    ></c8y-map>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1$2.ActivatedRoute }, { type: i2$3.MapService }], propDecorators: { mapView: [{
                type: ViewChild,
                args: [MapComponent]
            }], isEdit: [{
                type: Input
            }], locationMO: [{
                type: Input
            }], form: [{
                type: Input
            }] } });

class AssetPropertiesComponent {
    constructor(assetTypes, inventory, inventoryBinary, alert) {
        this.assetTypes = assetTypes;
        this.inventory = inventory;
        this.inventoryBinary = inventoryBinary;
        this.alert = alert;
        this.assetChange = new EventEmitter();
        this.properties = [];
        this.customProperties = [];
        this.isEdit = false;
        this.isLoading = false;
        this.POSITION_PROPERTY_KEY = 'c8y_Position';
    }
    ngOnChanges(changes) {
        if (changes.asset) {
            // Back button handling, as component is not destroyed
            this.assetType = undefined;
            this.customProperties = [];
            this.loadAsset();
        }
    }
    async loadAsset() {
        this.isLoading = true;
        const assetType$ = this.assetTypes.getAssetTypeByName$(this.asset.type);
        this.assetType = await firstValueFrom(assetType$);
        try {
            this.properties = this.keepOrder(this.assetType?.c8y_IsAssetType?.properties, this.properties);
        }
        catch (ex) {
            console.warn(ex);
        }
        this.customProperties = await this.resolveCustomProperties(this.properties);
        this.isLoading = false;
    }
    async resolveCustomProperties(managedObjects) {
        const properties = [];
        for (const mo of managedObjects) {
            if (mo.c8y_JsonSchema) {
                const [item] = await this.parseItem(mo, mo.c8y_JsonSchema.properties, this.asset);
                this.setItemRequired(item, mo);
                this.updatePositionKeyLabel(item);
                properties.push(item);
            }
        }
        return properties;
    }
    deleteTitleFromMOJsonSchema(mo) {
        const schemaProperties = mo?.c8y_JsonSchema?.properties;
        const property = Object.keys(schemaProperties || {})[0];
        delete (mo?.c8y_JsonSchema?.properties[property] || {}).title;
    }
    /**
     * This method is used to order the complex properties in the order specified by the user in asset properties screen.
     * @param mo - Managed object of the complex property associated with the asset.
     */
    orderComplexProperties(mo) {
        const complexProperties = mo.c8y_JsonSchema.properties[mo.name]?.['properties'];
        const keyValuesArray = toPairs(complexProperties);
        const orderedProperties = sortBy(keyValuesArray, ([, value]) => value.order);
        mo.c8y_JsonSchema.properties[mo.name]['properties'] = fromPairs(orderedProperties);
    }
    async parseItem(mo, properties, asset) {
        if (!asset) {
            return [];
        }
        const keys = Object.keys(properties);
        const items = [];
        for (const key of keys) {
            const type = properties[key].type;
            const title = properties[key].title;
            let value = this.getTypeValue(type, asset[key]);
            let file;
            if (type === 'file' && value) {
                const fileId = typeof value === 'object' ? value[0]?.file?.id : value;
                const fileData = await this.getFileManagedObject(fileId);
                file = fileData;
                value = [fileData];
            }
            else if (type === 'date') {
                const valueDate = new Date(value);
                value = !isNaN(valueDate.getTime()) ? valueDate : '';
            }
            if (type === 'object') {
                // remove title to avoid excessive property name on asset complex properties form
                this.deleteTitleFromMOJsonSchema(mo);
                this.orderComplexProperties(mo);
                if (!value) {
                    value = {};
                    for (const prop in properties[key].properties) {
                        value[prop] = this.getTypeValue(properties[key].properties[prop].type, null);
                    }
                }
            }
            items.push({
                key,
                value,
                label: title || mo.label,
                type,
                description: mo.description,
                file,
                complex: type === 'object'
                    ? await this.parseItem(mo, properties[key].properties, value)
                    : undefined,
                isEdit: false,
                jsonSchema: mo.c8y_JsonSchema
            });
        }
        return items;
    }
    toggleEdit(prop) {
        prop.isEdit = !prop.isEdit;
    }
    async getFileManagedObject(id) {
        try {
            const { data } = await this.inventory.detail(id);
            return data;
        }
        catch (ex) {
            this.alert.addServerFailure(ex);
        }
    }
    async save(propertyValue, prop) {
        try {
            if (prop.type === 'object') {
                this.updateUndefinedToPropTypeValue(prop, propertyValue[prop.key]);
            }
            else {
                this.updateUndefinedToPropTypeValue(prop, propertyValue);
            }
            propertyValue = await this.uploadFiles(propertyValue, prop.value);
            // Avoid making a PUT request containing just the id, as response body might be incomplete
            const hasValues = Object.values(propertyValue).some(value => value !== undefined);
            if (!hasValues) {
                this.toggleEdit(prop);
                return;
            }
            const updatedAsset = { id: this.asset.id, ...propertyValue };
            const { data } = await this.inventory.update(updatedAsset);
            this.toggleEdit(prop);
            this.asset = data;
            this.assetChange.emit(this.asset);
            await this.loadAsset();
            this.alert.success(gettext('Asset properties updated.'));
        }
        catch (ex) {
            this.alert.addServerFailure(ex);
            this.toggleEdit(prop);
        }
    }
    updateUndefinedToPropTypeValue(prop, propertyValue) {
        for (const [key, value] of Object.entries(propertyValue)) {
            const property = prop.complex ? find(prop.complex, { key: key }) : prop;
            propertyValue[key] = this.getTypeValue(property.type, value);
        }
    }
    getTypeValue(propType, value) {
        if (value || (propType === 'boolean' && value !== undefined))
            return value;
        switch (propType) {
            case 'number':
            case 'boolean':
                return value || value === 0 ? value : null;
            default:
                return '';
        }
    }
    keepOrder(correctOrderedIds, properties) {
        const orderedProperties = correctOrderedIds.map(({ id }) => {
            const foundProperty = properties.find(property => property.id === id);
            if (!foundProperty) {
                throw new Error('Custom property mismatch');
            }
            return foundProperty;
        });
        return orderedProperties;
    }
    async uploadFiles(model, moId) {
        const keys = Object.keys(model);
        for (const key of keys) {
            if (Array.isArray(model[key]) && model[key][0]?.file instanceof File) {
                try {
                    const upload = await this.inventoryBinary.create(model[key][0].file);
                    try {
                        if (moId && moId[0]) {
                            await this.inventory.childAdditionsRemove(moId[0], this.asset.id);
                        }
                    }
                    catch (ex) {
                        throw ex;
                    }
                    model[key] = upload.data.id;
                    await this.inventory.childAdditionsAdd(upload.data.id, this.asset.id);
                }
                catch (ex) {
                    throw ex;
                }
            }
        }
        return model;
    }
    updatePositionKeyLabel(item) {
        if (item.label === this.POSITION_PROPERTY_KEY) {
            item.label = gettext('Location');
        }
    }
    setItemRequired(item, mo) {
        const isAssetPropertyRequired = !!this.assetType?.c8y_IsAssetType?.properties.find(p => p.id === mo.id)?.isRequired;
        if (!isAssetPropertyRequired) {
            return;
        }
        const isComplexProperty = !!item?.complex?.length;
        if (isComplexProperty) {
            const complexProperty = item.jsonSchema?.properties?.[mo.c8y_JsonSchema.key];
            complexProperty.required = item.complex.map(({ key }) => key);
        }
        else {
            item.jsonSchema.required = [mo.c8y_JsonSchema.key];
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AssetPropertiesComponent, deps: [{ token: i3.AssetTypesRealtimeService }, { token: i2.InventoryService }, { token: i2.InventoryBinaryService }, { token: i3.AlertService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: AssetPropertiesComponent, isStandalone: true, selector: "c8y-asset-properties", inputs: { asset: "asset", properties: "properties" }, outputs: { assetChange: "assetChange" }, usesOnChanges: true, ngImport: i0, template: "<ng-container>\n  <div class=\"card-header bg-inherit separator sticky-top\">\n    <h1\n      class=\"card-title p-t-4 p-b-4\"\n      ngNonBindable\n      translate\n      [translateParams]=\"{ label: assetType?.label || '' | translate }\"\n    >\n      {{ label }} properties\n    </h1>\n  </div>\n  <div class=\"card-block\">\n    <div\n      class=\"text-center\"\n      *ngIf=\"isLoading\"\n    >\n      <c8y-loading></c8y-loading>\n    </div>\n\n    <ng-container *ngIf=\"!isLoading\">\n      <div\n        class=\"card m-b-8\"\n        title=\"{{ prop.description | translate }}\"\n        *ngFor=\"let prop of customProperties\"\n        [ngClass]=\"{ 'card-highlight': prop.isEdit }\"\n      >\n        <div\n          class=\"card-block\"\n          [ngClass]=\"{ 'p-b-0': prop.isEdit }\"\n        >\n          <div\n            class=\"d-flex p-b-8 a-i-center\"\n            *ngIf=\"!prop.isEdit\"\n          >\n            <p\n              class=\"text-medium text-truncate\"\n              title=\"{{ prop?.label | translate }}\"\n            >\n              {{ prop?.label | translate }}\n            </p>\n            <button\n              class=\"btn btn-dot m-l-auto text-12\"\n              [attr.aria-label]=\"'Edit' | translate\"\n              tooltip=\"{{ 'Edit' | translate }}\"\n              type=\"button\"\n              [delay]=\"500\"\n              (click)=\"toggleEdit(prop)\"\n            >\n              <i c8yIcon=\"pencil\"></i>\n            </button>\n          </div>\n          <c8y-asset-properties-item\n            #assetProps\n            [file]=\"prop.file\"\n            [key]=\"prop.key\"\n            [type]=\"prop.type\"\n            [value]=\"prop.value\"\n            [complex]=\"prop.complex\"\n            [isEdit]=\"prop.isEdit\"\n            [jsonSchema]=\"prop.jsonSchema\"\n          ></c8y-asset-properties-item>\n          <div *ngIf=\"prop.key === POSITION_PROPERTY_KEY\">\n            <c8y-asset-location\n              [locationMO]=\"asset\"\n              [isEdit]=\"prop.isEdit\"\n              [form]=\"assetProps.form\"\n            ></c8y-asset-location>\n          </div>\n        </div>\n        <div\n          class=\"card-footer p-t-0\"\n          *ngIf=\"prop.isEdit\"\n        >\n          <button\n            class=\"btn btn-default btn-sm\"\n            title=\"{{ 'Cancel' | translate }}\"\n            type=\"button\"\n            (click)=\"toggleEdit(prop)\"\n          >\n            {{ 'Cancel' | translate }}\n          </button>\n          <button\n            class=\"btn btn-primary btn-sm\"\n            title=\"{{ 'Save' | translate }}\"\n            type=\"button\"\n            [disabled]=\"!assetProps?.form?.valid || !assetProps?.form?.dirty\"\n            (click)=\"save(assetProps.form.value, prop)\"\n          >\n            {{ 'Save' | translate }}\n          </button>\n        </div>\n      </div>\n    </ng-container>\n  </div>\n</ng-container>\n", dependencies: [{ kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: AssetPropertiesItemComponent, selector: "c8y-asset-properties-item", inputs: ["key", "value", "label", "type", "file", "complex", "isEdit", "jsonSchema"] }, { kind: "component", type: AssetLocationComponent, selector: "c8y-asset-location", inputs: ["isEdit", "locationMO", "form"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AssetPropertiesComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-asset-properties', imports: [
                        C8yTranslateDirective,
                        NgIf,
                        LoadingComponent,
                        NgFor,
                        NgClass,
                        TooltipDirective,
                        IconDirective,
                        AssetPropertiesItemComponent,
                        AssetLocationComponent,
                        C8yTranslatePipe
                    ], template: "<ng-container>\n  <div class=\"card-header bg-inherit separator sticky-top\">\n    <h1\n      class=\"card-title p-t-4 p-b-4\"\n      ngNonBindable\n      translate\n      [translateParams]=\"{ label: assetType?.label || '' | translate }\"\n    >\n      {{ label }} properties\n    </h1>\n  </div>\n  <div class=\"card-block\">\n    <div\n      class=\"text-center\"\n      *ngIf=\"isLoading\"\n    >\n      <c8y-loading></c8y-loading>\n    </div>\n\n    <ng-container *ngIf=\"!isLoading\">\n      <div\n        class=\"card m-b-8\"\n        title=\"{{ prop.description | translate }}\"\n        *ngFor=\"let prop of customProperties\"\n        [ngClass]=\"{ 'card-highlight': prop.isEdit }\"\n      >\n        <div\n          class=\"card-block\"\n          [ngClass]=\"{ 'p-b-0': prop.isEdit }\"\n        >\n          <div\n            class=\"d-flex p-b-8 a-i-center\"\n            *ngIf=\"!prop.isEdit\"\n          >\n            <p\n              class=\"text-medium text-truncate\"\n              title=\"{{ prop?.label | translate }}\"\n            >\n              {{ prop?.label | translate }}\n            </p>\n            <button\n              class=\"btn btn-dot m-l-auto text-12\"\n              [attr.aria-label]=\"'Edit' | translate\"\n              tooltip=\"{{ 'Edit' | translate }}\"\n              type=\"button\"\n              [delay]=\"500\"\n              (click)=\"toggleEdit(prop)\"\n            >\n              <i c8yIcon=\"pencil\"></i>\n            </button>\n          </div>\n          <c8y-asset-properties-item\n            #assetProps\n            [file]=\"prop.file\"\n            [key]=\"prop.key\"\n            [type]=\"prop.type\"\n            [value]=\"prop.value\"\n            [complex]=\"prop.complex\"\n            [isEdit]=\"prop.isEdit\"\n            [jsonSchema]=\"prop.jsonSchema\"\n          ></c8y-asset-properties-item>\n          <div *ngIf=\"prop.key === POSITION_PROPERTY_KEY\">\n            <c8y-asset-location\n              [locationMO]=\"asset\"\n              [isEdit]=\"prop.isEdit\"\n              [form]=\"assetProps.form\"\n            ></c8y-asset-location>\n          </div>\n        </div>\n        <div\n          class=\"card-footer p-t-0\"\n          *ngIf=\"prop.isEdit\"\n        >\n          <button\n            class=\"btn btn-default btn-sm\"\n            title=\"{{ 'Cancel' | translate }}\"\n            type=\"button\"\n            (click)=\"toggleEdit(prop)\"\n          >\n            {{ 'Cancel' | translate }}\n          </button>\n          <button\n            class=\"btn btn-primary btn-sm\"\n            title=\"{{ 'Save' | translate }}\"\n            type=\"button\"\n            [disabled]=\"!assetProps?.form?.valid || !assetProps?.form?.dirty\"\n            (click)=\"save(assetProps.form.value, prop)\"\n          >\n            {{ 'Save' | translate }}\n          </button>\n        </div>\n      </div>\n    </ng-container>\n  </div>\n</ng-container>\n" }]
        }], ctorParameters: () => [{ type: i3.AssetTypesRealtimeService }, { type: i2.InventoryService }, { type: i2.InventoryBinaryService }, { type: i3.AlertService }], propDecorators: { asset: [{
                type: Input
            }], assetChange: [{
                type: Output
            }], properties: [{
                type: Input
            }] } });

const SUB_ASSETS_CONFIG = new InjectionToken('SubAssetsConfig');
const defaultModuleConfig = {
    showAddGroupBtn: true,
    showAssignDeviceBtn: true,
    name: gettext('Groups'),
    baseQuery: {},
    showDetails: true,
    showProperties: true,
    showGroupsContextHelp: true
};

class GroupInfoComponent {
    constructor(inventory, subAssetsService, smartGroupsService, alertService, modalService, assetNodeService, assetType, deviceListExtensionService, moduleConfig) {
        this.inventory = inventory;
        this.subAssetsService = subAssetsService;
        this.smartGroupsService = smartGroupsService;
        this.alertService = alertService;
        this.modalService = modalService;
        this.assetNodeService = assetNodeService;
        this.assetType = assetType;
        this.deviceListExtensionService = deviceListExtensionService;
        this.moduleConfig = moduleConfig;
        this.PRODUCT_EXPERIENCE = PRODUCT_EXPERIENCE_SUB_ASSETS_SHARED;
        this.groupChange = new EventEmitter();
        this.groupInfoModel = {
            name: '',
            c8y_Notes: ''
        };
        this.filterMsg = gettext('Smart groups are groups dynamically constructed based on filtering criteria.');
        this.GROUP_UPDATED_MSG = gettext('Group updated.');
        this.destroyed$ = new Subject();
        this.deviceListExtensionService.items$.pipe(takeUntil(this.destroyed$)).subscribe(columns => {
            this.allDevicesGridColumns = columns;
        });
    }
    async ngOnChanges(changes) {
        if (changes.group) {
            const { name, c8y_Notes } = this.group;
            this.groupInfoModel = { name, c8y_Notes };
            this.canEdit = await this.subAssetsService.canEditGroup(this.group);
            this.groupIcon = await this.assetNodeService.icon(this.group);
            this.smartGroupFilter = this.group.c8y_DeviceQueryString;
            this.columnsWithFilter = this.group.c8y_DeviceColumnsConfig?.columns
                ?.filter(col => !!col.filter)
                .map(col => ({
                ...col,
                externalFilterQuery: col.filter.externalFilterQuery,
                ...this.withPropsFromGridColumn(col)
            }));
            this.label = this.assetNodeService.isAsset(this.group)
                ? (await firstValueFrom(this.assetType.getAssetTypeByName$(this.group.type))).label
                : gettext('Group');
        }
    }
    isSmartGroup() {
        return this.subAssetsService.isSmartGroup(this.group);
    }
    async update(partialGroup) {
        try {
            const isSmartGroup = this.subAssetsService.isSmartGroup(this.group);
            const updatedGroup = isSmartGroup
                ? await this.updateSmartGroup(partialGroup)
                : await this.updateGroup(partialGroup);
            this.group = updatedGroup;
            this.groupChange.emit(this.group);
            this.alertService.success(this.GROUP_UPDATED_MSG);
        }
        catch (error) {
            this.alertService.addServerFailure(error);
        }
    }
    ngOnDestroy() {
        this.destroyed$.next();
        this.destroyed$.complete();
    }
    withPropsFromGridColumn(column) {
        if (column.custom) {
            const col = new CustomColumn();
            return {
                filteringConfig: col.filteringConfig
            };
        }
        else {
            return pick(this.allDevicesGridColumns.find(col => col.name === column.name), 'filteringConfig', 'header');
        }
    }
    async updateGroup(partialGroup) {
        const { id } = this.group;
        const group = { id, ...partialGroup };
        return (await this.inventory.update(group)).data;
    }
    async updateSmartGroup(partialGroup) {
        const { id } = this.group;
        const { c8y_DeviceQueryString } = partialGroup;
        const group = { id, ...partialGroup };
        if (!c8y_DeviceQueryString) {
            return (await this.smartGroupsService.update(group)).data;
        }
        try {
            const modalBody = gettext('You are about to change the smart group filter. Do you want to proceed?');
            const title = gettext('Smart group filter');
            await this.modalService.confirm(title, modalBody, Status.WARNING, {
                ok: gettext('Save'),
                cancel: gettext('Cancel')
            });
            await this.isQueryExecutable(c8y_DeviceQueryString);
        }
        catch (error) {
            throw Error(error);
        }
        return (await this.smartGroupsService.update(group)).data;
    }
    async isQueryExecutable(query) {
        try {
            const filter = { q: query };
            await this.inventory.list(filter);
        }
        catch (error) {
            throw Error(error);
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GroupInfoComponent, deps: [{ token: i2.InventoryService }, { token: SubAssetsService }, { token: i2.SmartGroupsService }, { token: i3.AlertService }, { token: i3.ModalService }, { token: i4.AssetNodeService }, { token: i3.AssetTypesRealtimeService }, { token: i4$1.DeviceListExtensionService }, { token: SUB_ASSETS_CONFIG }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: GroupInfoComponent, isStandalone: true, selector: "c8y-group-info", inputs: { group: "group" }, outputs: { groupChange: "groupChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"bg-level-1 separator-bottom\">\n  <div class=\"card-block p-t-24 p-b-24 large-padding\">\n    <div class=\"content-flex-70\">\n      <div class=\"text-center col-1\">\n        <i\n          class=\"c8y-icon-duocolor icon-48\"\n          [c8yIcon]=\"groupIcon\"\n        ></i>\n        <p>\n          <small\n            class=\"label label-info\"\n            *ngIf=\"group.c8y_IsDynamicGroup\"\n          >\n            {{ 'Smart group' | translate }}\n          </small>\n          <small\n            class=\"label label-info text-truncate d-inline-block\"\n            title=\"{{ label | translate }}\"\n            *ngIf=\"!group.c8y_IsDynamicGroup && !group.com_cumulocity_model_Agent\"\n          >\n            {{ label | translate }}\n          </small>\n          <small\n            class=\"label label-info\"\n            *ngIf=\"group.com_cumulocity_model_Agent\"\n          >\n            {{ 'Remote group' | translate }}\n          </small>\n        </p>\n      </div>\n\n      <div class=\"flex-grow col-10\">\n        <div class=\"content-flex-80\">\n          <div class=\"col-9\">\n            <form #groupNameForm=\"ngForm\">\n              <c8y-form-group class=\"form-group-lg m-b-0\">\n                <label\n                  class=\"sr-only\"\n                  for=\"groupName\"\n                  translate\n                >\n                  Name\n                </label>\n                <p\n                  class=\"form-control-static\"\n                  *ngIf=\"!canEdit\"\n                >\n                  {{ groupInfoModel.name }}\n                </p>\n                <div\n                  class=\"input-group input-group-lg input-group-editable\"\n                  *ngIf=\"canEdit\"\n                >\n                  <input\n                    class=\"form-control\"\n                    title=\"{{ groupInfoModel.name }}\"\n                    id=\"groupName\"\n                    placeholder=\"{{ 'e.g. My group' | translate }}\"\n                    name=\"name\"\n                    type=\"text\"\n                    required\n                    [(ngModel)]=\"groupInfoModel.name\"\n                    size=\"{{ groupInfoModel.name.length + 2 }}\"\n                    maxlength=\"254\"\n                    c8yProductExperience\n                    [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n                    [actionData]=\"{\n                      component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n                      action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n                      property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n                    }\"\n                  />\n                  <span></span>\n                  <div class=\"input-group-btn\">\n                    <button\n                      class=\"btn btn-primary\"\n                      title=\"{{ 'Save' | translate }}\"\n                      type=\"submit\"\n                      [disabled]=\"groupNameForm.form.invalid\"\n                      (click)=\"\n                        update({ name: groupInfoModel.name }); groupNameForm.form.markAsPristine()\n                      \"\n                      [actionName]=\"'groupInfo:EditedNameSaved'\"\n                      c8yProductExperience\n                      [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n                      [actionData]=\"{\n                        component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n                        result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n                        property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n                      }\"\n                    >\n                      {{ 'Save' | translate }}\n                    </button>\n                  </div>\n                </div>\n              </c8y-form-group>\n            </form>\n            <form #groupDescriptionForm=\"ngForm\">\n              <label\n                class=\"sr-only\"\n                for=\"description\"\n                translate\n              >\n                Description\n              </label>\n              <p\n                class=\"form-control-static\"\n                *ngIf=\"!canEdit\"\n              >\n                {{ groupInfoModel.c8y_Notes }}\n              </p>\n              <div\n                class=\"input-group input-group-editable\"\n                *ngIf=\"canEdit\"\n              >\n                <textarea\n                  class=\"form-control no-resize\"\n                  title=\"{{\n                    groupInfoModel.c8y_Notes\n                      ? groupInfoModel.c8y_Notes\n                      : ('e.g. My description' | translate)\n                  }}\"\n                  id=\"description\"\n                  placeholder=\"{{ 'e.g. My description' | translate }}\"\n                  name=\"description\"\n                  c8y-textarea-autoresize\n                  [(ngModel)]=\"groupInfoModel.c8y_Notes\"\n                  cols=\"{{ groupInfoModel.c8y_Notes ? groupInfoModel.c8y_Notes.length : 25 }}\"\n                  c8yProductExperience\n                  [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n                  [actionData]=\"{\n                    component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n                    action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n                    property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n                  }\"\n                ></textarea>\n                <span></span>\n                <div class=\"input-group-btn\">\n                  <button\n                    class=\"btn btn-primary\"\n                    title=\"{{ 'Save' | translate }}\"\n                    type=\"submit\"\n                    [disabled]=\"groupDescriptionForm.form.invalid\"\n                    (click)=\"\n                      update({ c8y_Notes: groupInfoModel.c8y_Notes });\n                      groupDescriptionForm.form.markAsPristine()\n                    \"\n                    c8yProductExperience\n                    [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n                    [actionData]=\"{\n                      component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n                      result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n                      property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n                    }\"\n                  >\n                    {{ 'Save' | translate }}\n                  </button>\n                </div>\n              </div>\n            </form>\n\n            <div\n              class=\"dropdown m-t-8\"\n              placement=\"bottom left\"\n              container=\"body\"\n              type=\"button\"\n              dropdown\n              *ngIf=\"isSmartGroup()\"\n              #ddFilters=\"bs-dropdown\"\n              [insideClick]=\"true\"\n            >\n              <button\n                class=\"btn btn-default btn-sm\"\n                title=\"{{ 'Smart group filters' | translate }}\"\n                aria-haspopup=\"true\"\n                dropdownToggle\n                data-cy=\"c8y-data-grid--filters\"\n                [disabled]=\"columnsWithFilter?.length === 0\"\n              >\n                <i\n                  class=\"m-r-4\"\n                  c8yIcon=\"filter\"\n                ></i>\n                <span>{{ 'Smart group filters' | translate }}</span>\n                <span\n                  class=\"p-relative p-l-4 p-r-16\"\n                  *ngIf=\"columnsWithFilter?.length > 0\"\n                >\n                  <span class=\"badge badge-system p-absolute\" data-cy=\"group-info--filter-number\">\n                    {{ columnsWithFilter?.length }}\n                  </span>\n                </span>\n              </button>\n              <button\n                class=\"btn-help btn-help--sm m-r-4\"\n                [attr.aria-label]=\"'Help' | translate\"\n                popover=\"{{ filterMsg | translate }}\"\n                placement=\"right\"\n                triggers=\"focus\"\n                data-cy=\"group-info--help-button\"\n                container=\"body\"\n                type=\"button\"\n              ></button>\n              <div\n                class=\"dropdown-menu\"\n                *dropdownMenu\n                (click)=\"$event.stopPropagation()\"\n              >\n                <div class=\"data-grid__dropdown bg-level-0\">\n                  <ul class=\"list-unstyled m-0\">\n                    <li\n                      *ngFor=\"let column of columnsWithFilter; let last = last\"\n                      [ngClass]=\"{ 'separator-bottom': !last }\"\n                    >\n                      <ng-container>\n                        <div\n                          class=\"dropdown-header sticky-top text-truncate no-border-top p-b-0\"\n                          title=\"{{ (column.header | translate) || column.name }}\"\n                        >\n                          <label>\n                            {{ (column.header | translate) || column.name }}\n                          </label>\n                        </div>\n                        <div\n                          class=\"list-group-item borderless d-flex d-col\"\n                          *ngFor=\"\n                            let groupedFilterChips of column\n                              | mapToFilterChips\n                              | async\n                              | groupedFilterChips;\n                            let first = first\n                          \"\n                          [ngClass]=\"{ 'p-t-0': first }\"\n                        >\n                          <p\n                            class=\"small p-b-4\"\n                            *ngIf=\"groupedFilterChips.label\"\n                          >\n                            {{ groupedFilterChips.label | translate }}\n                          </p>\n                          <div class=\"d-flex a-i-center gap-4 flex-wrap\">\n                            <span\n                              class=\"tag tag--info chip\"\n                              data-cy=\"group-info--grouped-filter-chip\"\n                              *ngFor=\"let chip of groupedFilterChips.chips\"\n                            >\n                              {{ chip.displayValue | translate }}\n                            </span>\n                          </div>\n                        </div>\n                      </ng-container>\n                    </li>\n                  </ul>\n                </div>\n              </div>\n            </div>\n          </div>\n          <div class=\"flex-grow\">\n            <ul class=\"list-unstyled small\">\n              <li class=\"p-t-4 p-b-4 d-flex separator-top-bottom text-nowrap\">\n                <label class=\"small m-b-0 m-r-8\">{{ 'Created' | translate }}</label>\n                <span class=\"m-l-auto\">{{ group.creationTime | c8yDate }}</span>\n              </li>\n              <li class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\">\n                <label class=\"small m-b-0 m-r-8\">{{ 'Last updated' | translate }}</label>\n                <span class=\"m-l-auto\">{{ group.lastUpdated | c8yDate }}</span>\n              </li>\n              <li\n                class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\"\n                *ngIf=\"group.com_cumulocity_model_Agent\"\n              >\n                <label class=\"small m-b-0 m-r-8\">{{ 'Status' | translate }}</label>\n                <span\n                  class=\"m-l-auto\"\n                  *ngIf=\"group.c8y_BrokerSource\"\n                >\n                  {{ group.c8y_BrokerSource.status }}\n                </span>\n                <span\n                  class=\"m-l-auto\"\n                  *ngIf=\"!group.c8y_BrokerSource\"\n                >\n                  {{ 'Offline' | translate }}\n                </span>\n              </li>\n            </ul>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: TextareaAutoresizeDirective, selector: "[c8y-textarea-autoresize]" }, { kind: "directive", type: BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { 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: BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }, { kind: "pipe", type: FilterMapperPipe, name: "mapToFilterChips" }, { kind: "pipe", type: GroupedFilterChips, name: "groupedFilterChips" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GroupInfoComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-group-info', imports: [
                        IconDirective,
                        NgIf,
                        FormsModule,
                        FormGroupComponent,
                        C8yTranslateDirective,
                        RequiredInputPlaceholderDirective,
                        ProductExperienceDirective,
                        TextareaAutoresizeDirective,
                        BsDropdownDirective,
                        BsDropdownToggleDirective,
                        PopoverDirective,
                        BsDropdownMenuDirective,
                        NgFor,
                        NgClass,
                        C8yTranslatePipe,
                        AsyncPipe,
                        DatePipe,
                        FilterMapperPipe,
                        GroupedFilterChips
                    ], template: "<div class=\"bg-level-1 separator-bottom\">\n  <div class=\"card-block p-t-24 p-b-24 large-padding\">\n    <div class=\"content-flex-70\">\n      <div class=\"text-center col-1\">\n        <i\n          class=\"c8y-icon-duocolor icon-48\"\n          [c8yIcon]=\"groupIcon\"\n        ></i>\n        <p>\n          <small\n            class=\"label label-info\"\n            *ngIf=\"group.c8y_IsDynamicGroup\"\n          >\n            {{ 'Smart group' | translate }}\n          </small>\n          <small\n            class=\"label label-info text-truncate d-inline-block\"\n            title=\"{{ label | translate }}\"\n            *ngIf=\"!group.c8y_IsDynamicGroup && !group.com_cumulocity_model_Agent\"\n          >\n            {{ label | translate }}\n          </small>\n          <small\n            class=\"label label-info\"\n            *ngIf=\"group.com_cumulocity_model_Agent\"\n          >\n            {{ 'Remote group' | translate }}\n          </small>\n        </p>\n      </div>\n\n      <div class=\"flex-grow col-10\">\n        <div class=\"content-flex-80\">\n          <div class=\"col-9\">\n            <form #groupNameForm=\"ngForm\">\n              <c8y-form-group class=\"form-group-lg m-b-0\">\n                <label\n                  class=\"sr-only\"\n                  for=\"groupName\"\n                  translate\n                >\n                  Name\n                </label>\n                <p\n                  class=\"form-control-static\"\n                  *ngIf=\"!canEdit\"\n                >\n                  {{ groupInfoModel.name }}\n                </p>\n                <div\n                  class=\"input-group input-group-lg input-group-editable\"\n                  *ngIf=\"canEdit\"\n                >\n                  <input\n                    class=\"form-control\"\n                    title=\"{{ groupInfoModel.name }}\"\n                    id=\"groupName\"\n                    placeholder=\"{{ 'e.g. My group' | translate }}\"\n                    name=\"name\"\n                    type=\"text\"\n                    required\n                    [(ngModel)]=\"groupInfoModel.name\"\n                    size=\"{{ groupInfoModel.name.length + 2 }}\"\n                    maxlength=\"254\"\n                    c8yProductExperience\n                    [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n                    [actionData]=\"{\n                      component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n                      action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n                      property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n                    }\"\n                  />\n                  <span></span>\n                  <div class=\"input-group-btn\">\n                    <button\n                      class=\"btn btn-primary\"\n                      title=\"{{ 'Save' | translate }}\"\n                      type=\"submit\"\n                      [disabled]=\"groupNameForm.form.invalid\"\n                      (click)=\"\n                        update({ name: groupInfoModel.name }); groupNameForm.form.markAsPristine()\n                      \"\n                      [actionName]=\"'groupInfo:EditedNameSaved'\"\n                      c8yProductExperience\n                      [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n                      [actionData]=\"{\n                        component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n                        result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n                        property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n                      }\"\n                    >\n                      {{ 'Save' | translate }}\n                    </button>\n                  </div>\n                </div>\n              </c8y-form-group>\n            </form>\n            <form #groupDescriptionForm=\"ngForm\">\n              <label\n                class=\"sr-only\"\n                for=\"description\"\n                translate\n              >\n                Description\n              </label>\n              <p\n                class=\"form-control-static\"\n                *ngIf=\"!canEdit\"\n              >\n                {{ groupInfoModel.c8y_Notes }}\n              </p>\n              <div\n                class=\"input-group input-group-editable\"\n                *ngIf=\"canEdit\"\n              >\n                <textarea\n                  class=\"form-control no-resize\"\n                  title=\"{{\n                    groupInfoModel.c8y_Notes\n                      ? groupInfoModel.c8y_Notes\n                      : ('e.g. My description' | translate)\n                  }}\"\n                  id=\"description\"\n                  placeholder=\"{{ 'e.g. My description' | translate }}\"\n                  name=\"description\"\n                  c8y-textarea-autoresize\n                  [(ngModel)]=\"groupInfoModel.c8y_Notes\"\n                  cols=\"{{ groupInfoModel.c8y_Notes ? groupInfoModel.c8y_Notes.length : 25 }}\"\n                  c8yProductExperience\n                  [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n                  [actionData]=\"{\n                    component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n                    action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n                    property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n                  }\"\n                ></textarea>\n                <span></span>\n                <div class=\"input-group-btn\">\n                  <button\n                    class=\"btn btn-primary\"\n                    title=\"{{ 'Save' | translate }}\"\n                    type=\"submit\"\n                    [disabled]=\"groupDescriptionForm.form.invalid\"\n                    (click)=\"\n                      update({ c8y_Notes: groupInfoModel.c8y_Notes });\n                      groupDescriptionForm.form.markAsPristine()\n                    \"\n                    c8yProductExperience\n                    [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n                    [actionData]=\"{\n                      component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n                      result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n                      property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n                    }\"\n                  >\n                    {{ 'Save' | translate }}\n                  </button>\n                </div>\n              </div>\n            </form>\n\n            <div\n              class=\"dropdown m-t-8\"\n              placement=\"bottom left\"\n              container=\"body\"\n              type=\"button\"\n              dropdown\n              *ngIf=\"isSmartGroup()\"\n              #ddFilters=\"bs-dropdown\"\n              [insideClick]=\"true\"\n            >\n              <button\n                class=\"btn btn-default btn-sm\"\n                title=\"{{ 'Smart group filters' | translate }}\"\n                aria-haspopup=\"true\"\n                dropdownToggle\n                data-cy=\"c8y-data-grid--filters\"\n                [disabled]=\"columnsWithFilter?.length === 0\"\n              >\n                <i\n                  class=\"m-r-4\"\n                  c8yIcon=\"filter\"\n                ></i>\n                <span>{{ 'Smart group filters' | translate }}</span>\n                <span\n                  class=\"p-relative p-l-4 p-r-16\"\n                  *ngIf=\"columnsWithFilter?.length > 0\"\n                >\n                  <span class=\"badge badge-system p-absolute\" data-cy=\"group-info--filter-number\">\n                    {{ columnsWithFilter?.length }}\n                  </span>\n                </span>\n              </button>\n              <button\n                class=\"btn-help btn-help--sm m-r-4\"\n                [attr.aria-label]=\"'Help' | translate\"\n                popover=\"{{ filterMsg | translate }}\"\n                placement=\"right\"\n                triggers=\"focus\"\n                data-cy=\"group-info--help-button\"\n                container=\"body\"\n                type=\"button\"\n              ></button>\n              <div\n                class=\"dropdown-menu\"\n                *dropdownMenu\n                (click)=\"$event.stopPropagation()\"\n              >\n                <div class=\"data-grid__dropdown bg-level-0\">\n                  <ul class=\"list-unstyled m-0\">\n                    <li\n                      *ngFor=\"let column of columnsWithFilter; let last = last\"\n                      [ngClass]=\"{ 'separator-bottom': !last }\"\n                    >\n                      <ng-container>\n                        <div\n                          class=\"dropdown-header sticky-top text-truncate no-border-top p-b-0\"\n                          title=\"{{ (column.header | translate) || column.name }}\"\n                        >\n                          <label>\n                            {{ (column.header | translate) || column.name }}\n                          </label>\n                        </div>\n                        <div\n                          class=\"list-group-item borderless d-flex d-col\"\n                          *ngFor=\"\n                            let groupedFilterChips of column\n                              | mapToFilterChips\n                              | async\n                              | groupedFilterChips;\n                            let first = first\n                          \"\n                          [ngClass]=\"{ 'p-t-0': first }\"\n                        >\n                          <p\n                            class=\"small p-b-4\"\n                            *ngIf=\"groupedFilterChips.label\"\n                          >\n                            {{ groupedFilterChips.label | translate }}\n                          </p>\n                          <div class=\"d-flex a-i-center gap-4 flex-wrap\">\n                            <span\n                              class=\"tag tag--info chip\"\n                              data-cy=\"group-info--grouped-filter-chip\"\n                              *ngFor=\"let chip of groupedFilterChips.chips\"\n                            >\n                              {{ chip.displayValue | translate }}\n                            </span>\n                          </div>\n                        </div>\n                      </ng-container>\n                    </li>\n                  </ul>\n                </div>\n              </div>\n            </div>\n          </div>\n          <div class=\"flex-grow\">\n            <ul class=\"list-unstyled small\">\n              <li class=\"p-t-4 p-b-4 d-flex separator-top-bottom text-nowrap\">\n                <label class=\"small m-b-0 m-r-8\">{{ 'Created' | translate }}</label>\n                <span class=\"m-l-auto\">{{ group.creationTime | c8yDate }}</span>\n              </li>\n              <li class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\">\n                <label class=\"small m-b-0 m-r-8\">{{ 'Last updated' | translate }}</label>\n                <span class=\"m-l-auto\">{{ group.lastUpdated | c8yDate }}</span>\n              </li>\n              <li\n                class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\"\n                *ngIf=\"group.com_cumulocity_model_Agent\"\n              >\n                <label class=\"small m-b-0 m-r-8\">{{ 'Status' | translate }}</label>\n                <span\n                  class=\"m-l-auto\"\n                  *ngIf=\"group.c8y_BrokerSource\"\n                >\n                  {{ group.c8y_BrokerSource.status }}\n                </span>\n                <span\n                  class=\"m-l-auto\"\n                  *ngIf=\"!group.c8y_BrokerSource\"\n                >\n                  {{ 'Offline' | translate }}\n                </span>\n              </li>\n            </ul>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i2.InventoryService }, { type: SubAssetsService }, { type: i2.SmartGroupsService }, { type: i3.AlertService }, { type: i3.ModalService }, { type: i4.AssetNodeService }, { type: i3.AssetTypesRealtimeService }, { type: i4$1.DeviceListExtensionService }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [SUB_ASSETS_CONFIG]
                }] }], propDecorators: { group: [{
                type: Input
            }], groupChange: [{
                type: Output
            }] } });

class GroupsComponent {
    constructor(permissions, subAssetsService, moduleConfig, activeRoute, router) {
        this.permissions = permissions;
        this.subAssetsService = subAssetsService;
        this.moduleConfig = moduleConfig;
        this.activeRoute = activeRoute;
        this.router = router;
        this.SHOW_ADD_GROUP = 'showAddGroup';
        this.showAddGroup = signal(false, ...(ngDevMode ? [{ debugName: "showAddGroup" }] : []));
        this.refresh = new EventEmitter();
        this.filterable = true;
        this.sortable = true;
        this.shouldDisableAddGroup = false;
        this.columns = [];
        this.destroyed = new Subject();
    }
    ngOnInit() {
        if (!this.permissions.hasAnyRole([
            Permissions.ROLE_INVENTORY_READ,
            Permissions.ROLE_MANAGED_OBJECT_READ
        ])) {
            this.sortable = false;
        }
        this.shouldDisableAddGroup = !this.subAssetsService.canCreateGroup();
        this.columns = this.subAssetsService
            .getDefaultColumns()
            .filter(column => column.name !== 'alarms');
        this.activeRoute.queryParamMap
            .pipe(delay(50), // It allows seeing drawer animation.
        takeUntil$1(this.destroyed), tap(params => this.showAddGroup.set(params.has(this.SHOW_ADD_GROUP))))
            .subscribe();
    }
    onAddGroupClick() {
        this.showAddGroup.set(!this.showAddGroup());
        this.handleShowAddGroupQueryParam();
    }
    ngOnDestroy() {
        this.destroyed.next();
        this.destroyed.complete();
    }
    /**
     * Updates the query parameter `showAddGroup` based on the value of `showAddGroup` property.
     * - If `showAddGroup` is `true`, adds `showAddGroup=true` to the query parameters.
     * - If `showAddGroup` is `false`, removes `showAddGroup` from the query parameters.
     */
    handleShowAddGroupQueryParam() {
        const currentParams = { ...this.activeRoute.snapshot.queryParams };
        if (this.showAddGroup()) {
            currentParams[this.SHOW_ADD_GROUP] = true;
        }
        else {
            delete currentParams[this.SHOW_ADD_GROUP];
        }
        this.router.navigate([], {
            relativeTo: this.activeRoute,
            queryParams: currentParams
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GroupsComponent, deps: [{ token: i3.Permissions }, { token: SubAssetsService }, { token: SUB_ASSETS_CONFIG }, { token: i1$2.ActivatedRoute }, { token: i1$2.Router }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: GroupsComponent, isStandalone: true, selector: "c8y-groups-name", ngImport: i0, template: "<c8y-title>\n  {{ moduleConfig.name | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n  <c8y-breadcrumb-item\n    icon=\"c8y-group-open\"\n    label=\"{{ moduleConfig.name | translate }}\"\n  ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n  [placement]=\"'right'\"\n  *ngIf=\"moduleConfig.showAddGroupBtn\"\n>\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Add group' | translate }}\"\n    (click)=\"onAddGroupClick()\"\n    [disabled]=\"shouldDisableAddGroup\"\n    [attr.data-cy]=\"'groups-add-group-button'\"\n  >\n    <i\n      class=\"m-r-4\"\n      c8yIcon=\"plus-circle\"\n    ></i>\n    {{ 'Add group' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<c8y-help\n  src=\"/docs/device-management-application/grouping-devices/#grouping-devices\"\n  *ngIf=\"moduleConfig.showGroupsContextHelp\"\n></c8y-help>\n\n<c8y-add-group\n  [refresh]=\"refresh\"\n  (onCancel)=\"onAddGroupClick()\"\n  *ngIf=\"showAddGroup()\"\n></c8y-add-group>\n<c8y-sub-assets-grid\n  class=\"content-fullpage d-flex d-col border-top border-bottom\"\n  [refresh]=\"refresh\"\n  [filterable]=\"filterable\"\n  [sortable]=\"sortable\"\n  [columns]=\"columns\"\n  [columnsConfigKey]=\"'sub-assets-grid'\"\n  [baseQuery]=\"moduleConfig.baseQuery\"\n></c8y-sub-assets-grid>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "component", type: AddGroupComponent, selector: "c8y-add-group", inputs: ["currentGroupId", "refresh"], outputs: ["onDeviceQueryStringChange", "onCancel"] }, { kind: "component", type: SubAssetsGridComponent, selector: "c8y-sub-assets-grid", inputs: ["parent-group", "refresh", "title", "emptyStateText", "loadingItemsLabel", "columnsConfigKey", "columns", "pagination", "actionControls", "selectable", "baseQuery", "bulkActionControls", "filterable", "sortable", "displayOptions"], outputs: ["onColumnsChange", "itemsSelect"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GroupsComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-groups-name', imports: [
                        TitleComponent,
                        BreadcrumbComponent,
                        BreadcrumbItemComponent,
                        NgIf,
                        ActionBarItemComponent,
                        IconDirective,
                        HelpComponent,
                        AddGroupComponent,
                        SubAssetsGridComponent,
                        C8yTranslatePipe
                    ], template: "<c8y-title>\n  {{ moduleConfig.name | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n  <c8y-breadcrumb-item\n    icon=\"c8y-group-open\"\n    label=\"{{ moduleConfig.name | translate }}\"\n  ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n  [placement]=\"'right'\"\n  *ngIf=\"moduleConfig.showAddGroupBtn\"\n>\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Add group' | translate }}\"\n    (click)=\"onAddGroupClick()\"\n    [disabled]=\"shouldDisableAddGroup\"\n    [attr.data-cy]=\"'groups-add-group-button'\"\n  >\n    <i\n      class=\"m-r-4\"\n      c8yIcon=\"plus-circle\"\n    ></i>\n    {{ 'Add group' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<c8y-help\n  src=\"/docs/device-management-application/grouping-devices/#grouping-devices\"\n  *ngIf=\"moduleConfig.showGroupsContextHelp\"\n></c8y-help>\n\n<c8y-add-group\n  [refresh]=\"refresh\"\n  (onCancel)=\"onAddGroupClick()\"\n  *ngIf=\"showAddGroup()\"\n></c8y-add-group>\n<c8y-sub-assets-grid\n  class=\"content-fullpage d-flex d-col border-top border-bottom\"\n  [refresh]=\"refresh\"\n  [filterable]=\"filterable\"\n  [sortable]=\"sortable\"\n  [columns]=\"columns\"\n  [columnsConfigKey]=\"'sub-assets-grid'\"\n  [baseQuery]=\"moduleConfig.baseQuery\"\n></c8y-sub-assets-grid>\n" }]
        }], ctorParameters: () => [{ type: i3.Permissions }, { type: SubAssetsService }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [SUB_ASSETS_CONFIG]
                }] }, { type: i1$2.ActivatedRoute }, { type: i1$2.Router }] });

class SubAssetsComponent {
    constructor(activeRoute, subAssetsService, contextRouteService, permissionsService, moduleConfig, router) {
        this.activeRoute = activeRoute;
        this.subAssetsService = subAssetsService;
        this.contextRouteService = contextRouteService;
        this.permissionsService = permissionsService;
        this.moduleConfig = moduleConfig;
        this.router = router;
        this.SHOW_ADD_GROUP = 'showAddGroup';
        this.toggle = false;
        this.showAddGroup = signal(false, ...(ngDevMode ? [{ debugName: "showAddGroup" }] : []));
        this.showAssignDevices = false;
        this.showAssignChildDevices = false;
        this.refresh = new EventEmitter();
        this.filterable = true;
        this.shouldDisableAddGroup = false;
        this.shouldDisableAssignDevices = false;
        this.shouldShowAssetsProperties = false;
        this.customProperties = [];
        this.isSmartGroup = false;
        this.destroyed = new Subject();
        this.activeRoute.parent.data.pipe(takeUntil$1(this.destroyed)).subscribe(({ contextData }) => {
            this.init(contextData);
        });
    }
    async ngOnInit() {
        this.displayOptions = {
            striped: true,
            bordered: false,
            gridHeader: true,
            filter: true,
            hover: true
        };
        this.isSmartGroup = this.subAssetsService.isSmartGroup(this.group);
        this.activeRoute.queryParamMap
            .pipe(delay(50), // It allows seeing drawer animation.
        takeUntil$1(this.destroyed), tap(params => this.showAddGroup.set(params.has(this.SHOW_ADD_GROUP))))
            .subscribe();
    }
    async init(contextData) {
        this.group = { ...contextData };
        this.title = this.group.name;
        this.currentGroupId = this.group.id;
        this.shouldDisableAddGroup = !(await this.permissionsService.canEdit([
            Permissions.ROLE_INVENTORY_ADMIN,
            Permissions.ROLE_INVENTORY_CREATE,
            Permissions.ROLE_MANAGED_OBJECT_ADMIN,
            Permissions.ROLE_MANAGED_OBJECT_CREATE
        ], this.group));
        this.shouldDisableAssignDevices = !(await this.subAssetsService.canAssignDevice(this.group));
        this.customProperties = await this.subAssetsService.getCustomProperties(this.group);
        this.shouldShowAssetsProperties =
            this.moduleConfig.showProperties && this.customProperties.length > 0;
    }
    groupChange(group) {
        this.group = group;
        this.title = group.name;
        this.contextRouteService.setContext(this.activeRoute, group);
        this.contextRouteService.refreshContext();
        this.refresh.emit();
    }
    onAddGroupClick() {
        this.showAddGroup.set(!this.showAddGroup());
        this.handleShowAddGroupQueryParam();
    }
    ngOnDestroy() {
        this.destroyed.next();
        this.destroyed.complete();
    }
    /**
     * Updates the query parameter `showAddGroup` based on the value of `showAddGroup` property.
     * - If `showAddGroup` is `true`, adds `showAddGroup=true` to the query parameters.
     * - If `showAddGroup` is `false`, removes `showAddGroup` from the query parameters.
     */
    handleShowAddGroupQueryParam() {
        const currentParams = { ...this.activeRoute.snapshot.queryParams };
        if (this.showAddGroup()) {
            currentParams[this.SHOW_ADD_GROUP] = true;
        }
        else {
            delete currentParams[this.SHOW_ADD_GROUP];
        }
        this.router.navigate([], {
            relativeTo: this.activeRoute,
            queryParams: currentParams
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsComponent, deps: [{ token: i1$2.ActivatedRoute }, { token: SubAssetsService }, { token: i3.ContextRouteService }, { token: i3.Permissions }, { token: SUB_ASSETS_CONFIG }, { token: i1$2.Router }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SubAssetsComponent, isStandalone: true, selector: "c8y-sub-assets", ngImport: i0, template: "<c8y-title>\n  {{ title }}\n</c8y-title>\n\n<c8y-action-bar-item\n  [placement]=\"'right'\"\n  *ngIf=\"!isSmartGroup && moduleConfig.showAddGroupBtn\"\n>\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Add group' | translate }}\"\n    (click)=\"onAddGroupClick()\"\n    [disabled]=\"shouldDisableAddGroup\"\n  >\n    <i\n      class=\"m-r-4\"\n      c8yIcon=\"plus-circle\"\n    ></i>\n    <span translate>Add group</span>\n  </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n  [placement]=\"'right'\"\n  *ngIf=\"!isSmartGroup && moduleConfig.showAssignDeviceBtn\"\n>\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Assign devices' | translate }}\"\n    (click)=\"showAssignDevices = !showAssignDevices\"\n    [disabled]=\"shouldDisableAssignDevices\"\n  >\n    <i\n      class=\"m-r-4\"\n      c8yIcon=\"plus-circle\"\n    ></i>\n    <span translate>Assign devices</span>\n  </button>\n</c8y-action-bar-item>\n\n<c8y-help\n  src=\"/docs/device-management-application/grouping-devices/#using-smart-groups\"\n  *ngIf=\"isSmartGroup; else assetsHelp\"\n></c8y-help>\n\n<ng-template #assetsHelp>\n  <c8y-help src=\"/docs/cockpit/managing-assets/#managing-assets\"></c8y-help>\n</ng-template>\n\n<div\n  class=\"card content-fullpage\"\n  [ngClass]=\"{\n    'card--grid grid__col--8-4--md grid__row--fit-auto': shouldShowAssetsProperties,\n    'd-flex d-col': !shouldShowAssetsProperties\n  }\"\n>\n  <c8y-group-info\n    class=\"grid__col--fullspan\"\n    *ngIf=\"moduleConfig.showDetails\"\n    [group]=\"group\"\n    (groupChange)=\"groupChange($event)\"\n  ></c8y-group-info>\n  <c8y-sub-assets-grid\n    class=\"d-contents\"\n    [refresh]=\"refresh\"\n    [parent-group]=\"group\"\n    [filterable]=\"filterable\"\n    [displayOptions]=\"displayOptions\"\n    [columnsConfigKey]=\"'sub-assets-grid'\"\n    [baseQuery]=\"moduleConfig.baseQuery\"\n  ></c8y-sub-assets-grid>\n  <div\n    class=\"inner-scroll bg-level-1\"\n    *ngIf=\"shouldShowAssetsProperties\"\n  >\n    <c8y-asset-properties\n      class=\"d-contents\"\n      [properties]=\"customProperties\"\n      [asset]=\"group\"\n      (assetChange)=\"groupChange($event)\"\n    ></c8y-asset-properties>\n  </div>\n</div>\n\n<div [ngClass]=\"{ drawerOpen: showAddGroup() }\">\n  <div\n    class=\"bottom-drawer has-backdrop\"\n    aria-labelledby=\"drawerTitle\"\n    aria-modal=\"true\"\n    role=\"dialog\"\n    [cdkTrapFocus]=\"showAddGroup()\"\n  >\n    <c8y-add-group\n      [currentGroupId]=\"currentGroupId\"\n      [refresh]=\"refresh\"\n      (onCancel)=\"onAddGroupClick()\"\n      *ngIf=\"showAddGroup()\"\n    ></c8y-add-group>\n  </div>\n</div>\n\n<div [ngClass]=\"{ drawerOpen: showAssignDevices }\">\n  <div\n    class=\"bottom-drawer has-backdrop\"\n    aria-labelledby=\"drawerTitle\"\n    aria-modal=\"true\"\n    role=\"dialog\"\n    [cdkTrapFocus]=\"showAssignDevices\"\n  >\n    <div class=\"d-flex d-col no-align-items fit-h\">\n      <c8y-assign-devices\n        class=\"d-contents\"\n        (onCancel)=\"showAssignDevices = false\"\n        [refresh]=\"refresh\"\n        [currentGroupId]=\"currentGroupId\"\n        (onShowChildDevices)=\"showAssignChildDevices = $event\"\n        (selectedDevice)=\"showChildrenForDevice = $event\"\n        *ngIf=\"showAssignDevices\"\n      ></c8y-assign-devices>\n    </div>\n  </div>\n</div>\n\n<div [ngClass]=\"{ drawerOpen: showAssignChildDevices }\">\n  <div\n    class=\"bottom-drawer has-backdrop m-t-40\"\n    aria-labelledby=\"childDevicesDrawerTitle\"\n    aria-modal=\"true\"\n    role=\"dialog\"\n    [cdkTrapFocus]=\"showAssignChildDevices\"\n  >\n    <div class=\"d-flex d-col no-align-items fit-h\">\n      <c8y-assign-child-devices\n        class=\"d-contents\"\n        *ngIf=\"showAssignChildDevices\"\n        (onCancel)=\"showAssignChildDevices = false\"\n        [refresh]=\"refresh\"\n        [currentGroupId]=\"currentGroupId\"\n        [parentDevice]=\"showChildrenForDevice\"\n      ></c8y-assign-child-devices>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: GroupInfoComponent, selector: "c8y-group-info", inputs: ["group"], outputs: ["groupChange"] }, { kind: "component", type: SubAssetsGridComponent, selector: "c8y-sub-assets-grid", inputs: ["parent-group", "refresh", "title", "emptyStateText", "loadingItemsLabel", "columnsConfigKey", "columns", "pagination", "actionControls", "selectable", "baseQuery", "bulkActionControls", "filterable", "sortable", "displayOptions"], outputs: ["onColumnsChange", "itemsSelect"] }, { kind: "component", type: AssetPropertiesComponent, selector: "c8y-asset-properties", inputs: ["asset", "properties"], outputs: ["assetChange"] }, { kind: "component", type: AddGroupComponent, selector: "c8y-add-group", inputs: ["currentGroupId", "refresh"], outputs: ["onDeviceQueryStringChange", "onCancel"] }, { kind: "component", type: AssignDevicesComponent, selector: "c8y-assign-devices", inputs: ["currentGroupId", "refresh"], outputs: ["onCancel", "onShowChildDevices", "selectedDevice"] }, { kind: "component", type: AssignChildDevicesComponent, selector: "c8y-assign-child-devices", inputs: ["currentGroupId", "parentDevice", "refresh", "onlySelect"], outputs: ["onCancel", "onSelectedDevices"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-sub-assets', imports: [
                        TitleComponent,
                        NgIf,
                        ActionBarItemComponent,
                        IconDirective,
                        C8yTranslateDirective,
                        HelpComponent,
                        NgClass,
                        CdkTrapFocus,
                        GroupInfoComponent,
                        SubAssetsGridComponent,
                        AssetPropertiesComponent,
                        AddGroupComponent,
                        AssignDevicesComponent,
                        AssignChildDevicesComponent,
                        C8yTranslatePipe
                    ], template: "<c8y-title>\n  {{ title }}\n</c8y-title>\n\n<c8y-action-bar-item\n  [placement]=\"'right'\"\n  *ngIf=\"!isSmartGroup && moduleConfig.showAddGroupBtn\"\n>\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Add group' | translate }}\"\n    (click)=\"onAddGroupClick()\"\n    [disabled]=\"shouldDisableAddGroup\"\n  >\n    <i\n      class=\"m-r-4\"\n      c8yIcon=\"plus-circle\"\n    ></i>\n    <span translate>Add group</span>\n  </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n  [placement]=\"'right'\"\n  *ngIf=\"!isSmartGroup && moduleConfig.showAssignDeviceBtn\"\n>\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Assign devices' | translate }}\"\n    (click)=\"showAssignDevices = !showAssignDevices\"\n    [disabled]=\"shouldDisableAssignDevices\"\n  >\n    <i\n      class=\"m-r-4\"\n      c8yIcon=\"plus-circle\"\n    ></i>\n    <span translate>Assign devices</span>\n  </button>\n</c8y-action-bar-item>\n\n<c8y-help\n  src=\"/docs/device-management-application/grouping-devices/#using-smart-groups\"\n  *ngIf=\"isSmartGroup; else assetsHelp\"\n></c8y-help>\n\n<ng-template #assetsHelp>\n  <c8y-help src=\"/docs/cockpit/managing-assets/#managing-assets\"></c8y-help>\n</ng-template>\n\n<div\n  class=\"card content-fullpage\"\n  [ngClass]=\"{\n    'card--grid grid__col--8-4--md grid__row--fit-auto': shouldShowAssetsProperties,\n    'd-flex d-col': !shouldShowAssetsProperties\n  }\"\n>\n  <c8y-group-info\n    class=\"grid__col--fullspan\"\n    *ngIf=\"moduleConfig.showDetails\"\n    [group]=\"group\"\n    (groupChange)=\"groupChange($event)\"\n  ></c8y-group-info>\n  <c8y-sub-assets-grid\n    class=\"d-contents\"\n    [refresh]=\"refresh\"\n    [parent-group]=\"group\"\n    [filterable]=\"filterable\"\n    [displayOptions]=\"displayOptions\"\n    [columnsConfigKey]=\"'sub-assets-grid'\"\n    [baseQuery]=\"moduleConfig.baseQuery\"\n  ></c8y-sub-assets-grid>\n  <div\n    class=\"inner-scroll bg-level-1\"\n    *ngIf=\"shouldShowAssetsProperties\"\n  >\n    <c8y-asset-properties\n      class=\"d-contents\"\n      [properties]=\"customProperties\"\n      [asset]=\"group\"\n      (assetChange)=\"groupChange($event)\"\n    ></c8y-asset-properties>\n  </div>\n</div>\n\n<div [ngClass]=\"{ drawerOpen: showAddGroup() }\">\n  <div\n    class=\"bottom-drawer has-backdrop\"\n    aria-labelledby=\"drawerTitle\"\n    aria-modal=\"true\"\n    role=\"dialog\"\n    [cdkTrapFocus]=\"showAddGroup()\"\n  >\n    <c8y-add-group\n      [currentGroupId]=\"currentGroupId\"\n      [refresh]=\"refresh\"\n      (onCancel)=\"onAddGroupClick()\"\n      *ngIf=\"showAddGroup()\"\n    ></c8y-add-group>\n  </div>\n</div>\n\n<div [ngClass]=\"{ drawerOpen: showAssignDevices }\">\n  <div\n    class=\"bottom-drawer has-backdrop\"\n    aria-labelledby=\"drawerTitle\"\n    aria-modal=\"true\"\n    role=\"dialog\"\n    [cdkTrapFocus]=\"showAssignDevices\"\n  >\n    <div class=\"d-flex d-col no-align-items fit-h\">\n      <c8y-assign-devices\n        class=\"d-contents\"\n        (onCancel)=\"showAssignDevices = false\"\n        [refresh]=\"refresh\"\n        [currentGroupId]=\"currentGroupId\"\n        (onShowChildDevices)=\"showAssignChildDevices = $event\"\n        (selectedDevice)=\"showChildrenForDevice = $event\"\n        *ngIf=\"showAssignDevices\"\n      ></c8y-assign-devices>\n    </div>\n  </div>\n</div>\n\n<div [ngClass]=\"{ drawerOpen: showAssignChildDevices }\">\n  <div\n    class=\"bottom-drawer has-backdrop m-t-40\"\n    aria-labelledby=\"childDevicesDrawerTitle\"\n    aria-modal=\"true\"\n    role=\"dialog\"\n    [cdkTrapFocus]=\"showAssignChildDevices\"\n  >\n    <div class=\"d-flex d-col no-align-items fit-h\">\n      <c8y-assign-child-devices\n        class=\"d-contents\"\n        *ngIf=\"showAssignChildDevices\"\n        (onCancel)=\"showAssignChildDevices = false\"\n        [refresh]=\"refresh\"\n        [currentGroupId]=\"currentGroupId\"\n        [parentDevice]=\"showChildrenForDevice\"\n      ></c8y-assign-child-devices>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1$2.ActivatedRoute }, { type: SubAssetsService }, { type: i3.ContextRouteService }, { type: i3.Permissions }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [SUB_ASSETS_CONFIG]
                }] }, { type: i1$2.Router }] });

class SubAssetsModule {
    static config(config = {}) {
        return {
            ngModule: SubAssetsModule,
            providers: [
                {
                    provide: SUB_ASSETS_CONFIG,
                    useValue: { ...defaultModuleConfig, ...config }
                }
            ]
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsModule, imports: [CoreModule,
            DeviceGridModule,
            AddGroupModule,
            PopoverModule,
            BsDropdownModule,
            TooltipModule,
            FilterMapperModule,
            MapModule,
            AssetTypeCellRendererComponent,
            SubAssetsGridsModule,
            SubAssetsComponent,
            GroupsComponent,
            GroupInfoComponent,
            DeleteAssetsModalComponent,
            UnassignModalComponent,
            AssetPropertiesComponent,
            AssetPropertiesItemComponent,
            AssetLocationComponent], exports: [SubAssetsGridComponent, AssetLocationComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsModule, providers: [
            {
                provide: SUB_ASSETS_CONFIG,
                useValue: defaultModuleConfig
            },
            hookRoute([
                {
                    context: ViewContext.Group,
                    path: 'subassets',
                    priority: 1000,
                    icon: 'c8y-group-open',
                    label: gettext('Subassets'),
                    component: SubAssetsComponent,
                    featureId: 'subassets'
                },
                {
                    path: 'group',
                    component: GroupsComponent
                }
            ]),
            SubAssetsService
        ], imports: [CoreModule,
            DeviceGridModule,
            AddGroupModule,
            PopoverModule,
            BsDropdownModule,
            TooltipModule,
            FilterMapperModule,
            MapModule,
            AssetTypeCellRendererComponent,
            SubAssetsGridsModule,
            SubAssetsComponent,
            GroupsComponent,
            GroupInfoComponent,
            DeleteAssetsModalComponent,
            UnassignModalComponent,
            AssetPropertiesComponent,
            AssetPropertiesItemComponent,
            AssetLocationComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SubAssetsModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CoreModule,
                        DeviceGridModule,
                        AddGroupModule,
                        PopoverModule,
                        BsDropdownModule,
                        TooltipModule,
                        FilterMapperModule,
                        MapModule,
                        AssetTypeCellRendererComponent,
                        SubAssetsGridsModule,
                        SubAssetsComponent,
                        GroupsComponent,
                        GroupInfoComponent,
                        DeleteAssetsModalComponent,
                        UnassignModalComponent,
                        AssetPropertiesComponent,
                        AssetPropertiesItemComponent,
                        AssetLocationComponent
                    ],
                    exports: [SubAssetsGridComponent, AssetLocationComponent],
                    providers: [
                        {
                            provide: SUB_ASSETS_CONFIG,
                            useValue: defaultModuleConfig
                        },
                        hookRoute([
                            {
                                context: ViewContext.Group,
                                path: 'subassets',
                                priority: 1000,
                                icon: 'c8y-group-open',
                                label: gettext('Subassets'),
                                component: SubAssetsComponent,
                                featureId: 'subassets'
                            },
                            {
                                path: 'group',
                                component: GroupsComponent
                            }
                        ]),
                        SubAssetsService
                    ]
                }]
        }] });

/**
 * Generated bundle index. Do not edit.
 */

export { AddGroupComponent, AddGroupModule, AddGroupService, AssetLocationComponent, AssetPropertiesComponent, AssetPropertiesItemComponent, AssignChildDevicesComponent, AssignDevicesComponent, DeleteAssetsModalComponent, GroupInfoComponent, GroupsComponent, SmartGroupGridConfigurationStrategy, SubAssetsComponent, SubAssetsGridComponent, SubAssetsGridConfigurationStrategy, SubAssetsModule, SubAssetsService, UnassignModalComponent, defaultMapLocation };
//# sourceMappingURL=c8y-ngx-components-sub-assets.mjs.map