import { __awaiter } from 'tslib';
import * as i0 from '@angular/core';
import { Component, Injectable, EventEmitter, Input, Output, ViewChild, HostListener, NgModule, TemplateRef } from '@angular/core';
import { InventoryService, UserService, SmartGroupsService, SmartRulesService } from '@c8y/client';
import * as i3 from '@c8y/ngx-components';
import { gettext, CellRendererContext, AppStateService, AlertService, Permissions, ModalService, Status, DataGridComponent, C8yStepper, CoreModule, HOOK_ROUTE, ViewContext } from '@c8y/ngx-components';
import * as i5 from '@c8y/ngx-components/assets-navigator';
import { DeviceGroupService, AssetNodeService, GroupFragment } from '@c8y/ngx-components/assets-navigator';
import * as i1 from '@ngx-translate/core';
import { TranslateService } from '@ngx-translate/core';
import { BaseDeviceGridColumn, DeviceGridService, NameDeviceGridColumn, ModelDeviceGridColumn, SerialNumberDeviceGridColumn, RegistrationDateDeviceGridColumn, SystemIdDeviceGridColumn, ImeiDeviceGridColumn, AlarmsDeviceGridColumn, DeviceGridModule } from '@c8y/ngx-components/device-grid';
import { BehaviorSubject, Subject } from 'rxjs';
import * as i2 from '@c8y/client';
import * as i4 from '@c8y/client';
import * as i6 from '@c8y/client';
import * as i7 from '@c8y/client';
import { ActivatedRoute } from '@angular/router';
import { BsModalService } from 'ngx-bootstrap/modal';
import { PopoverModule } from 'ngx-bootstrap/popover';
import { Validators, FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';

class AssetTypeCellRendererComponent {
    constructor(context, deviceGroupService) {
        this.context = context;
        this.deviceGroupService = deviceGroupService;
    }
    ngOnInit() {
        this.isAnyGroup = this.deviceGroupService.isAnyGroup(this.context.item);
        this.isDevice = this.deviceGroupService.isDevice(this.context.item);
        this.groupIcon = this.deviceGroupService.icon(this.context.item);
        this.iconTitle = this.getIconTitle(this.groupIcon);
    }
    getIconTitle(icon) {
        switch (icon) {
            case 'c8y-group':
                return gettext('Group');
            case 'c8y-group-smart':
                return gettext('Smart group');
            case 'c8y-group-remote-inactive':
                return 'Inactive remote group';
            case 'c8y-group-remote':
                return gettext('Remote group');
            default:
                return gettext('Child device');
        }
    }
}
AssetTypeCellRendererComponent.decorators = [
    { type: Component, args: [{
                template: "<device-status class=\"m-l-8\" [mo]=\"context.item\" *ngIf=\"isDevice\"></device-status>\n<i\n  [c8yIcon]=\"groupIcon\"\n  title=\"{{ iconTitle | translate }}\"\n  class=\"m-l-8 c8y-icon-duocolor\"\n  *ngIf=\"isAnyGroup || !isDevice\"\n></i>\n"
            },] }
];
AssetTypeCellRendererComponent.ctorParameters = () => [
    { type: CellRendererContext },
    { type: DeviceGroupService }
];

class AssetTypeGridColumn extends BaseDeviceGridColumn {
    constructor(initialColumnConfig) {
        super(initialColumnConfig);
        this.name = 'type';
        this.header = gettext('Type');
        this.dataType = "icon" /* Icon */;
        this.cellRendererComponent = AssetTypeCellRendererComponent;
        this.sortable = true;
        this.sortingConfig = {
            pathSortingConfigs: [{ path: `c8y_IsDeviceGroup` }]
        };
    }
}

class SubAssetsService extends DeviceGridService {
    constructor(translateService, inventoryService, appState, user, assetNodeService, deviceGroupService, smartGroupsService, smartRulesService, alertService, permissionsService, modal) {
        super(inventoryService, translateService, alertService, modal);
        this.translateService = translateService;
        this.inventoryService = inventoryService;
        this.appState = appState;
        this.user = user;
        this.assetNodeService = assetNodeService;
        this.deviceGroupService = deviceGroupService;
        this.smartGroupsService = smartGroupsService;
        this.smartRulesService = smartRulesService;
        this.alertService = alertService;
        this.permissionsService = permissionsService;
        this.modal = modal;
        this.uiOnlyCountersUpdate = new BehaviorSubject(null);
        this.GRID_CONFIG_DEFAULT_STORAGE_KEY = 'sub-assets-grid-config';
        this.IS_DEVICE_GROUP_FRAGMENT = 'c8y_IsDeviceGroup';
        this.IS_DYNAMIC_GROUP_FRAGMENT = 'c8y_IsDynamicGroup';
    }
    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() {
        const { pagination } = this.getConfig();
        return {
            pageSize: pagination.pageSize,
            currentPage: 1
        };
    }
    getDefaultActionControls() {
        return [];
    }
    unassignAsset(asset, parentRef) {
        return __awaiter(this, void 0, void 0, function* () {
            const { id: assetId } = asset;
            const { id: parentId } = parentRef;
            if (this.isDevice(asset)) {
                try {
                    yield this.inventoryService.childAssetsRemove(assetId, parentId);
                    const alertMessage = this.translateService.instant(gettext('Asset unassigned.'));
                    this.alertService.success(alertMessage);
                }
                catch (error) {
                    const alertMessage = this.translateService.instant(gettext('Could not unassign asset.'));
                    this.alertService.danger(alertMessage);
                }
                yield this.deactivateSmartrulesForAsset(asset, parentRef);
            }
        });
    }
    isDevice(asset) {
        return (!asset.hasOwnProperty(this.IS_DEVICE_GROUP_FRAGMENT) &&
            !asset.hasOwnProperty(this.IS_DYNAMIC_GROUP_FRAGMENT));
    }
    deleteAsset(asset, parentRef, params = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const isGroup = asset.hasOwnProperty(this.IS_DEVICE_GROUP_FRAGMENT) ||
                this.smartGroupsService.isSmartGroup(asset);
            if (isGroup) {
                yield this.deleteGroup(asset, params);
            }
            else {
                yield this.deleteDevice(asset, params);
            }
            if (parentRef &&
                !this.smartGroupsService.isSmartGroup(asset) &&
                !this.smartGroupsService.isSmartGroupV2(asset)) {
                yield 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 [];
    }
    getData(columns, pagination, parentReference, baseQuery = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const isRoot = !parentReference;
            if (isRoot) {
                const query = this.buildCombinedRootQueryFilter(columns, pagination);
                return this.assetNodeService.getRootNodes(Object.assign(Object.assign({}, pagination), { query }));
            }
            const filters = Object.assign(Object.assign({}, this.getAssetsFilters(columns, pagination, baseQuery)), { withParents: false });
            if (this.deviceGroupService.isGroup(parentReference)) {
                return this.assetNodeService.getGroupItems(parentReference.id, filters);
            }
            if (this.deviceGroupService.isDynamicGroup(parentReference)) {
                return this.assetNodeService.getDynamicGroupItems(parentReference.c8y_DeviceQueryString, filters);
            }
            if (this.deviceGroupService.isDevice(parentReference)) {
                return this.assetNodeService.getDeviceChildren(parentReference.id, filters);
            }
        });
    }
    getCount(columns, pagination, parentReference, baseQuery = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaultFilters = {
                pageSize: 1,
                withChildren: false
            };
            const filters = !parentReference
                ? Object.assign({ query: this.buildCombinedRootQueryFilter(columns, pagination) }, defaultFilters) : Object.assign(Object.assign({}, this.getAssetsFilters(columns, pagination, baseQuery)), 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);
    }
    canEditGroup(group) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.permissionsService.canEdit(['ROLE_INVENTORY_ADMIN'], group);
        });
    }
    canCreateGroup() {
        const currentUser = this.appState.currentUser.value;
        const hasAdminRole = this.user.hasAnyRole(currentUser, [
            'ROLE_INVENTORY_ADMIN',
            'ROLE_INVENTORY_CREATE'
        ]);
        return hasAdminRole;
    }
    canAssignDevice(group) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.permissionsService.canEdit(['ROLE_INVENTORY_ADMIN'], group);
        });
    }
    canEditSmartGroup() {
        const SMART_GROUPS_ROLES_EDIT = ['ROLE_SMARTGROUP_UPDATE', 'ROLE_SMARTGROUP_ADMIN'];
        return this.permissionsService.hasAnyRole(SMART_GROUPS_ROLES_EDIT);
    }
    canDeleteSmartGroup() {
        const SMART_GROUPS_ROLES_DELETE = ['ROLE_SMARTGROUP_ADMIN', 'ROLE_INVENTORY_ADMIN'];
        return this.permissionsService.hasAnyRole(SMART_GROUPS_ROLES_DELETE);
    }
    isSmartGroup(group) {
        return (this.smartGroupsService.isSmartGroup(group) || this.smartGroupsService.isSmartGroupV2(group));
    }
    isUsingInventoryRoles() {
        const currentUser = this.appState.currentUser.value;
        const hasAnyInventoryRole = this.user.hasAnyRole(currentUser, [
            'ROLE_INVENTORY_ADMIN',
            'ROLE_INVENTORY_READ',
            'ROLE_INVENTORY_CREATE'
        ]);
        return !hasAnyInventoryRole;
    }
    getAssetsStatistics(parentReference, filters) {
        return __awaiter(this, void 0, void 0, function* () {
            const isRoot = !parentReference;
            if (isRoot) {
                return (yield this.assetNodeService.getRootNodes(filters)).paging.totalPages;
            }
            if (this.deviceGroupService.isGroup(parentReference)) {
                return (yield this.assetNodeService.getGroupItems(parentReference.id, filters)).paging
                    .totalPages;
            }
            if (this.deviceGroupService.isDynamicGroup(parentReference)) {
                return (yield this.assetNodeService.getDynamicGroupItems(parentReference.c8y_DeviceQueryString, filters)).paging.totalPages;
            }
            if (this.deviceGroupService.isDevice(parentReference)) {
                return (yield this.assetNodeService.getDeviceChildren(parentReference.id, filters)).paging
                    .totalPages;
            }
        });
    }
    buildCombinedRootQueryFilter(columns, pagination) {
        const queryFilter = this.assetNodeService.rootQueryFilter();
        const userQuery = this.getQueryObj(columns, pagination);
        const queryPart = this.queriesUtil.addOrderbys(queryFilter, userQuery.__orderby, 'append');
        const fullQuery = this.queriesUtil.addAndFilter(queryPart, userQuery.__filter);
        return this.queriesUtil.buildQuery(fullQuery);
    }
    deleteGroup(group, params = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const { cascade } = params;
            try {
                this.smartGroupsService.isSmartGroup(group) || this.smartGroupsService.isSmartGroupV2(group)
                    ? yield this.smartGroupsService.delete(group, { cascade })
                    : yield this.inventoryService.delete(group, { cascade });
                const alertMessage = this.translateService.instant(gettext('Asset deleted.'));
                this.alertService.success(alertMessage);
            }
            catch (error) {
                const alertMessage = this.translateService.instant(gettext('Could not delete asset.'));
                this.alertService.danger(alertMessage);
            }
        });
    }
    deleteDevice(device, params = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const { cascade, withDeviceUser } = params;
            try {
                const { owner } = device;
                const shouldRemoveOwner = withDeviceUser && owner && this.isDeviceUser(owner);
                shouldRemoveOwner
                    ? yield this.deleteDeviceWithUser(device, cascade)
                    : yield this.inventoryService.delete(device, { cascade });
                const alertMessage = this.translateService.instant(gettext('Asset deleted.'));
                this.alertService.success(alertMessage);
            }
            catch (error) {
                const alertMessage = this.translateService.instant(gettext('Could not delete asset.'));
                this.alertService.danger(alertMessage);
            }
        });
    }
    deactivateSmartrulesForAsset(asset, parentRef) {
        return __awaiter(this, void 0, void 0, function* () {
            const { id: assetId } = asset;
            const { id: parentId } = parentRef;
            const rules = (yield this.smartRulesService.listByContext(parentId)).data;
            const upateSmartrulesPromises = rules.map(rule => this.smartRulesService.bulkDeactivateEnabledSources(rule, [assetId]));
            try {
                yield 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_/);
    }
    deleteDeviceWithUser(device, cascade) {
        return __awaiter(this, void 0, void 0, function* () {
            const params = { cascade, withDeviceUser: true };
            try {
                return yield this.inventoryService.delete(device, params);
            }
            catch (error) {
                return yield this.inventoryService.delete(device, { cascade });
            }
        });
    }
    getAssetsFilters(columns, pagination, baseQuery) {
        const query = this.queriesUtil.addAndFilter(this.getQueryObj(columns), baseQuery);
        return {
            query: this.queriesUtil.buildQuery(query),
            pageSize: pagination.pageSize || this.DEFAULT_PAGE_SIZE,
            currentPage: pagination.currentPage,
            withTotalPages: true
        };
    }
}
SubAssetsService.ɵprov = i0.ɵɵdefineInjectable({ factory: function SubAssetsService_Factory() { return new SubAssetsService(i0.ɵɵinject(i1.TranslateService), i0.ɵɵinject(i2.InventoryService), i0.ɵɵinject(i3.AppStateService), i0.ɵɵinject(i4.UserService), i0.ɵɵinject(i5.AssetNodeService), i0.ɵɵinject(i5.DeviceGroupService), i0.ɵɵinject(i6.SmartGroupsService), i0.ɵɵinject(i7.SmartRulesService), i0.ɵɵinject(i3.AlertService), i0.ɵɵinject(i3.Permissions), i0.ɵɵinject(i3.ModalService)); }, token: SubAssetsService, providedIn: "root" });
SubAssetsService.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] }
];
SubAssetsService.ctorParameters = () => [
    { type: TranslateService },
    { type: InventoryService },
    { type: AppStateService },
    { type: UserService },
    { type: AssetNodeService },
    { type: DeviceGroupService },
    { type: SmartGroupsService },
    { type: SmartRulesService },
    { type: AlertService },
    { type: Permissions },
    { type: ModalService }
];

class GroupInfoComponent {
    constructor(inventory, subAssetsService, deviceGroupService, smartGroupsService, alertService, translate, modalService) {
        this.inventory = inventory;
        this.subAssetsService = subAssetsService;
        this.deviceGroupService = deviceGroupService;
        this.smartGroupsService = smartGroupsService;
        this.alertService = alertService;
        this.translate = translate;
        this.modalService = modalService;
        this.onGroupChange = new EventEmitter();
        this.filterMsg = gettext('Smart groups are groups dynamically constructed based on filtering criteria.');
        this.canEditMsg = gettext('You can edit the filter here.');
        this.GROUP_UPDATED_MSG = gettext('Group updated.');
    }
    ngOnInit() {
        return __awaiter(this, void 0, void 0, function* () {
            this.canEdit = this.smartGroupsService.isSmartGroupV2(this.group)
                ? this.subAssetsService.canEditSmartGroup()
                : yield this.subAssetsService.canEditGroup(this.group);
            this.groupIcon = this.deviceGroupService.icon(this.group);
            this.smartGroupFilter = this.group.c8y_DeviceQueryString;
            this.setHintMsg();
        });
    }
    isSmartGroup() {
        return this.subAssetsService.isSmartGroup(this.group);
    }
    update(partialGroup) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const isSmartGroup = this.subAssetsService.isSmartGroup(this.group);
                isSmartGroup
                    ? yield this.updateSmartGroup(partialGroup)
                    : yield this.updateGroup(partialGroup);
            }
            catch (error) {
                this.alertService.addServerFailure(error);
            }
        });
    }
    setHintMsg() {
        const filterMsgTranslated = this.translate.instant(this.filterMsg);
        const canEditMsgTranslated = this.translate.instant(this.canEditMsg);
        this.filterHintMsg = this.canEdit
            ? `${filterMsgTranslated} ${canEditMsgTranslated}`
            : this.filterMsg;
    }
    updateGroup(partialGroup) {
        return __awaiter(this, void 0, void 0, function* () {
            const { id } = this.group;
            const group = Object.assign({ id }, partialGroup);
            const updatedGroup = (yield this.inventory.update(group)).data;
            this.setGroup(updatedGroup);
        });
    }
    updateSmartGroup(partialGroup) {
        return __awaiter(this, void 0, void 0, function* () {
            const { id } = this.group;
            const { c8y_DeviceQueryString } = partialGroup;
            const group = Object.assign({ id }, partialGroup);
            let updatedGroup;
            if (!c8y_DeviceQueryString) {
                updatedGroup = (yield this.smartGroupsService.update(group)).data;
                this.setGroup(updatedGroup);
                return;
            }
            try {
                const modalBody = gettext('You are about to change the smart group filter. Do you want to proceed?');
                const title = gettext('Smart group filter');
                yield this.modalService.confirm(title, modalBody, Status.WARNING, {
                    ok: gettext('Save'),
                    cancel: gettext('Cancel')
                });
                if (!(yield this.isQueryExecutable(c8y_DeviceQueryString))) {
                    return;
                }
            }
            catch (e) {
                return;
            }
            updatedGroup = (yield this.smartGroupsService.update(group)).data;
            this.setGroup(updatedGroup);
        });
    }
    setGroup(group) {
        this.onGroupChange.emit(group);
        this.alertService.success(this.GROUP_UPDATED_MSG);
    }
    isQueryExecutable(query) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const filter = { q: query };
                yield this.inventory.list(filter);
                return true;
            }
            catch (error) {
                this.alertService.addServerFailure(error);
                return false;
            }
        });
    }
}
GroupInfoComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-group-info',
                template: "<div class=\"bg-gray-white\">\n  <div class=\"card-block p-t-24 p-b-24 large-padding\">\n    <div class=\"content-flex-70\">\n      <div class=\"text-center\">\n        <i class=\"c8y-icon-duocolor icon-48\" [c8yIcon]=\"groupIcon + '-open'\"></i>\n        <p>\n          <small class=\"label label-info\" *ngIf=\"group.c8y_IsDynamicGroup\">\n            {{ 'Smart group' | translate }}\n          </small>\n          <small\n            class=\"label label-info\"\n            *ngIf=\"!group.c8y_IsDynamicGroup && !group.com_cumulocity_model_Agent\"\n          >\n            {{ 'Group' | translate }}\n          </small>\n          <small class=\"label label-info\" *ngIf=\"group.com_cumulocity_model_Agent\">\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 class=\"sr-only\" translate>\n                  Name\n                </label>\n\n                <p *ngIf=\"!canEdit\" class=\"form-control-static\">{{ group.name }}</p>\n                <div *ngIf=\"canEdit\" class=\"input-group input-group-editable\">\n                  <input\n                    type=\"text\"\n                    class=\"form-control\"\n                    [(ngModel)]=\"group.name\"\n                    name=\"name\"\n                    title=\"{{ 'Name' | translate }}\"\n                    size=\"{{ group.name.length + 2 }}\"\n                    placeholder=\"{{ 'e.g. My group' | translate }}\"\n                    maxlength=\"254\"\n                    required\n                  />\n                  <span></span>\n                  <div class=\"input-group-btn\">\n                    <button\n                      (click)=\"update({ name: group.name }); groupNameForm.form.markAsPristine()\"\n                      class=\"btn btn-primary\"\n                      title=\"{{ 'Save' | translate }}\"\n                      [disabled]=\"groupNameForm.form.invalid\"\n                    >\n                      {{ 'Save' | translate }}\n                    </button>\n                  </div>\n                </div>\n              </c8y-form-group>\n            </form>\n            <form #groupDescriptionForm=\"ngForm\">\n              <label class=\"sr-only\" translate>\n                Description\n              </label>\n              <p *ngIf=\"!canEdit\" class=\"form-control-static\">{{ group.c8y_Notes }}</p>\n              <div *ngIf=\"canEdit\" class=\"input-group input-group-editable\">\n                <textarea\n                  class=\"form-control\"\n                  [(ngModel)]=\"group.c8y_Notes\"\n                  name=\"description\"\n                  title=\"{{ 'Description' | translate }}\"\n                  cols=\"{{ group.c8y_Notes ? group.c8y_Notes.length : 25 }}\"\n                  placeholder=\"{{ 'e.g. My description' | translate }}\"\n                ></textarea>\n                <span></span>\n                <div class=\"input-group-btn\">\n                  <button\n                    (click)=\"\n                      update({ c8y_Notes: group.c8y_Notes });\n                      groupDescriptionForm.form.markAsPristine()\n                    \"\n                    class=\"btn btn-primary\"\n                    title=\"{{ 'Save' | translate }}\"\n                    [disabled]=\"groupDescriptionForm.form.invalid\"\n                  >\n                    {{ 'Save' | translate }}\n                  </button>\n                </div>\n              </div>\n            </form>\n\n            <form #smartGroupFilterForm=\"ngForm\" *ngIf=\"isSmartGroup()\">\n              <c8y-form-group class=\"m-b-0 m-t-8\">\n                <label class=\"m-b-0 text-nowrap\">\n                  {{ 'Smart group filter' | translate }}\n                  <button\n                    class=\"btn-clean text-primary m-r-4\"\n                    type=\"button\"\n                    popover=\"{{ filterHintMsg | translate }}\"\n                    triggers=\"focus\"\n                  >\n                    <i c8yIcon=\"question-circle-o\"></i>\n                  </button>\n                </label>\n\n                <p *ngIf=\"!canEdit\" class=\"form-control-static\">\n                  {{ smartGroupFilter }}\n                </p>\n                <div *ngIf=\"canEdit\" class=\"input-group input-group-editable\">\n                  <input\n                    type=\"text\"\n                    class=\"form-control\"\n                    [(ngModel)]=\"smartGroupFilter\"\n                    name=\"filter\"\n                    size=\"{{ smartGroupFilter.length + 2 }}\"\n                    placeholder=\"{{ 'e.g.' | translate }} $filter=(id eq '12*')\"\n                    maxlength=\"254\"\n                    title=\"{{ 'Smart group filter' | translate }}\"\n                  />\n                  <span></span>\n                  <div class=\"input-group-btn\">\n                    <button\n                      (click)=\"\n                        update({ c8y_DeviceQueryString: smartGroupFilter });\n                        smartGroupFilterForm.form.markAsPristine()\n                      \"\n                      class=\"btn btn-primary\"\n                      title=\"{{ 'Save' | translate }}\"\n                      [disabled]=\"smartGroupFilterForm.form.invalid\"\n                    >\n                      {{ 'Save' | translate }}\n                    </button>\n                  </div>\n                </div>\n              </c8y-form-group>\n            </form>\n          </div>\n          <div class=\"flex-grow\">\n            <p class=\"m-b-8\">\n              <i c8yIcon=\"info-circle\" class=\"text-info m-r-8\"></i>\n              <span class=\"text-label-small\">{{ 'Group info' | translate }}</span>\n            </p>\n            <ul class=\"list-unstyled small\">\n              <li class=\"p-t-4 p-b-4 flex-row separator-top-bottom text-nowrap\">\n                <label class=\"small m-b-0 m-r-8\">{{ 'Created' | translate }}</label>\n                <span class=\"flex-item-right\">{{ group.creationTime | c8yDate }}</span>\n              </li>\n              <li class=\"p-t-4 p-b-4 flex-row separator-bottom text-nowrap\">\n                <label class=\"small m-b-0 m-r-8\">{{ 'Last updated' | translate }}</label>\n                <span class=\"flex-item-right\">{{ group.lastUpdated | c8yDate }}</span>\n              </li>\n\n              <li\n                *ngIf=\"group.com_cumulocity_model_Agent\"\n                class=\"p-t-4 p-b-4 flex-row separator-bottom text-nowrap\"\n              >\n                <label class=\"small m-b-0 m-r-8\">{{ 'Status' | translate }}</label>\n                <span class=\"flex-item-right\" *ngIf=\"group.c8y_BrokerSource\">\n                  {{ group.c8y_BrokerSource.status }}\n                </span>\n                <span class=\"flex-item-right\" *ngIf=\"!group.c8y_BrokerSource\">\n                  {{ 'Offline' | translate }}\n                </span>\n              </li>\n            </ul>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n"
            },] }
];
GroupInfoComponent.ctorParameters = () => [
    { type: InventoryService },
    { type: SubAssetsService },
    { type: DeviceGroupService },
    { type: SmartGroupsService },
    { type: AlertService },
    { type: TranslateService },
    { type: ModalService }
];
GroupInfoComponent.propDecorators = {
    group: [{ type: Input }],
    onGroupChange: [{ type: Output }]
};

class SubAssetsComponent {
    constructor(route, deviceGroupService, subAssetsService) {
        this.route = route;
        this.deviceGroupService = deviceGroupService;
        this.subAssetsService = subAssetsService;
        this.toggle = false;
        this.showAddGroup = false;
        this.showAssignDevices = false;
        this.showAssignChildDevices = false;
        this.refresh = new EventEmitter();
        this.filterable = true;
        this.shouldDisableAddGroup = false;
        this.shouldDisableAssignDevices = false;
        this.dataSub = this.route.parent.data.subscribe(({ contextData }) => {
            this.title = contextData.name;
            this.currentGroupId = contextData.id;
            this.group = contextData;
            this.filterable = !this.deviceGroupService.isDynamicGroup(contextData);
        });
    }
    ngOnInit() {
        return __awaiter(this, void 0, void 0, function* () {
            this.shouldDisableAddGroup = !this.subAssetsService.canCreateGroup();
            this.shouldDisableAssignDevices = yield !this.subAssetsService.canAssignDevice(this.group);
            this.displayOptions = {
                striped: true,
                bordered: false,
                gridHeader: true,
                filter: !this.isSmartGroup()
            };
        });
    }
    groupChange(group) {
        /**
         * Group is cached in the context-route guard. To avoid loading old data (when switching tabs) we need to update
         * this object in the cache.
         */
        Object.assign(this.group, group);
        this.title = group.name;
        this.refresh.emit();
    }
    isSmartGroup() {
        return this.subAssetsService.isSmartGroup(this.group);
    }
    ngOnDestroy() {
        if (this.dataSub) {
            this.dataSub.unsubscribe();
        }
    }
}
SubAssetsComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-sub-assets',
                template: "<c8y-title>\n  {{ title }}\n</c8y-title>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"!isSmartGroup()\">\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Add group' | translate }}\"\n    (click)=\"showAddGroup = !showAddGroup\"\n    [disabled]=\"shouldDisableAddGroup\"\n  >\n    <i c8yIcon=\"plus-circle\" class=\"m-r-4\"></i><span translate>Add group</span>\n  </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"!isSmartGroup()\">\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Assign devices' | translate }}\"\n    (click)=\"showAssignDevices = !showAssignDevices\"\n    [disabled]=\"shouldDisableAssignDevices\"\n  >\n    <i c8yIcon=\"plus-circle\" class=\"m-r-4\"></i><span translate>Assign devices</span>\n  </button>\n</c8y-action-bar-item>\n\n<div class=\"card content-fullpage d-flex d-col\">\n  <c8y-group-info [group]=\"group\" (onGroupChange)=\"groupChange($event)\"></c8y-group-info>\n  <c8y-sub-assets-grid\n    [refresh]=\"refresh\"\n    [parent-group]=\"group\"\n    [filterable]=\"filterable\"\n    [displayOptions]=\"displayOptions\"\n    class=\"d-contents\"\n  ></c8y-sub-assets-grid>\n</div>\n\n<div [ngClass]=\"{ drawerOpen: showAddGroup }\">\n  <div class=\"bottom-drawer\">\n    <c8y-add-group\n      [currentGroupId]=\"currentGroupId\"\n      [refresh]=\"refresh\"\n      (onCancel)=\"showAddGroup = false\"\n      *ngIf=\"showAddGroup\"\n    ></c8y-add-group>\n  </div>\n</div>\n\n<div [ngClass]=\"{ drawerOpen: showAssignDevices }\">\n  <div class=\"bottom-drawer\">\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 class=\"bottom-drawer m-t-40\">\n    <div class=\"d-flex d-col no-align-items fit-h\">\n      <c8y-assign-child-devices\n        *ngIf=\"showAssignChildDevices\"\n        class=\"d-contents\"\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"
            },] }
];
SubAssetsComponent.ctorParameters = () => [
    { type: ActivatedRoute },
    { type: DeviceGroupService },
    { type: SubAssetsService }
];

class DeleteAssetsModalComponent {
    constructor(translateService) {
        this.translateService = translateService;
        this.showWithCascadeCheckbox = true;
        this.showWithDeviceUserCheckbox = false;
        this.closeSubject = new Subject();
        this.labels = { ok: gettext('Delete'), cancel: gettext('Cancel') };
        this.title = gettext('Delete asset');
        this.status = Status.DANGER;
        this.config = {
            cascade: false,
            withDeviceUser: false
        };
    }
    ngOnInit() {
        this.message = this.translateService.instant(gettext('You are about to delete asset: "{{name}}". This operation is irreversible. Do you want to proceed?'), { name: this.asset.name });
    }
    ngAfterViewInit() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                yield this.modalRef.result;
                this.onClose();
            }
            catch (error) {
                this.onDismiss();
            }
        });
    }
    onClose() {
        this.closeSubject.next(this.config);
        this.closeSubject.complete();
    }
    onDismiss() {
        this.closeSubject.complete();
    }
}
DeleteAssetsModalComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-delete-assets-modal',
                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 type=\"checkbox\" name=\"cascade\" [(ngModel)]=\"config.cascade\" />\n        <span></span>\n        <span>\n          {{ 'Also delete all devices inside selected asset and its subassets.' | 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 type=\"checkbox\" name=\"withDeviceUser\" [(ngModel)]=\"config.withDeviceUser\" />\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"
            },] }
];
DeleteAssetsModalComponent.ctorParameters = () => [
    { type: TranslateService }
];
DeleteAssetsModalComponent.propDecorators = {
    showWithCascadeCheckbox: [{ type: Input }],
    showWithDeviceUserCheckbox: [{ type: Input }],
    asset: [{ type: Input }],
    modalRef: [{ type: ViewChild, args: ['modalRef', { static: false },] }]
};

class UnassignModalComponent {
    constructor(translateService) {
        this.translateService = translateService;
        this.closeSubject = new Subject();
        this.labels = { ok: gettext('Unassign'), cancel: gettext('Cancel') };
        this.title = gettext('Unassign asset');
        this.status = Status.WARNING;
    }
    ngOnInit() {
        this.message = this.translateService.instant(gettext('You are about to unassign asset "{{name}}". Do you want to proceed?'), { name: this.asset.name });
    }
    ngAfterViewInit() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                yield this.modalRef.result;
                this.onClose();
            }
            catch (error) {
                this.onDismiss();
            }
        });
    }
    onClose() {
        this.closeSubject.next(true);
        this.closeSubject.complete();
    }
    onDismiss() {
        this.closeSubject.complete();
    }
}
UnassignModalComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-unassign-modal',
                template: "<c8y-confirm-modal [title]=\"title\" [status]=\"status\" [labels]=\"labels\" #modalRef>\n  <span>{{ message | translate }}</span>\n</c8y-confirm-modal>\n"
            },] }
];
UnassignModalComponent.ctorParameters = () => [
    { type: TranslateService }
];
UnassignModalComponent.propDecorators = {
    asset: [{ type: Input }],
    modalRef: [{ type: ViewChild, args: ['modalRef', { static: false },] }]
};

class SubAssetsGridComponent {
    constructor(subAssetsGridService, bsModalService, smartGroupsService) {
        this.subAssetsGridService = subAssetsGridService;
        this.bsModalService = bsModalService;
        this.smartGroupsService = smartGroupsService;
        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.bulkActionControls = this.subAssetsGridService.getDefaultBulkActionControls();
        this.displayOptions = {
            striped: true,
            bordered: false,
            gridHeader: true,
            filter: true
        };
        this.serverSideDataCallback = this.onDataSourceModifier.bind(this);
    }
    get columns() {
        return this._columns;
    }
    set columns(value) {
        if (value) {
            this._columns = this.subAssetsGridService.getUserConfiguredColumns(value);
        }
        else {
            this._columns = this.subAssetsGridService.getUserConfiguredColumns(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 = Object.assign(Object.assign({}, this.displayOptions), displayOptions);
    }
    ngOnInit() {
        this.columns = this.subAssetsGridService.getDefaultColumns(this.filterable, this.sortable);
        if (!this.filterable || !this.sortable) {
            this.columns.forEach(column => {
                column.filterable = this.filterable;
                column.sortable = this.sortable;
            });
        }
        this.setActionControls();
    }
    setActionControls() {
        return __awaiter(this, void 0, void 0, function* () {
            const actionControls = [];
            const { data: isMicroserviceInstalled } = yield this.smartGroupsService.isSmartGroupsV2MicroserviceInstalled();
            const deleteAction = {
                type: "DELETE" /* Delete */,
                callback: (asset) => this.onDeleteAsset(asset, this.parentGroup),
                showIf: (asset) => {
                    if (this.smartGroupsService.isSmartGroupV2(asset)) {
                        return isMicroserviceInstalled ? this.subAssetsGridService.canDeleteSmartGroup() : false;
                    }
                    if (this.smartGroupsService.isSmartGroup(asset)) {
                        return this.subAssetsGridService.canDeleteSmartGroup();
                    }
                    return true;
                }
            };
            actionControls.push(deleteAction);
            const unassignAction = {
                type: 'UNASSIGN',
                icon: 'unlink',
                text: gettext('Unassign'),
                callback: (asset) => this.onUnassignAsset(asset, this.parentGroup),
                showIf: (asset) => this.subAssetsGridService.isDevice(asset) &&
                    !this.subAssetsGridService.isSmartGroup(this.parentGroup)
            };
            actionControls.push(unassignAction);
            if (!this.actionControls) {
                this.actionControls = actionControls;
            }
        });
    }
    onUnassignAsset(asset, parentRef) {
        const initialState = {
            asset
        };
        const modalRef = this.bsModalService.show(UnassignModalComponent, { initialState });
        modalRef.content.closeSubject.subscribe((result) => __awaiter(this, void 0, void 0, function* () {
            if (result) {
                yield this.subAssetsGridService.unassignAsset(asset, parentRef);
                this.refresh.emit();
            }
        }));
    }
    onDeleteAsset(asset, parentRef) {
        return __awaiter(this, void 0, void 0, function* () {
            const initialState = {
                showWithDeviceUserCheckbox: this.subAssetsGridService.shouldShowWithDeviceUserCheckbox(asset),
                asset,
                showWithCascadeCheckbox: !this.smartGroupsService.isSmartGroup(asset) &&
                    !this.smartGroupsService.isSmartGroupV2(asset)
            };
            const modalRef = this.bsModalService.show(DeleteAssetsModalComponent, { initialState });
            modalRef.content.closeSubject.subscribe((result) => __awaiter(this, void 0, void 0, function* () {
                if (result) {
                    this.subAssetsGridService.uiOnlyCountersUpdate.next('DECREASE');
                    yield this.subAssetsGridService.deleteAsset(asset, parentRef, result);
                    this.refresh.emit();
                }
            }));
        });
    }
    ngOnChanges(changes) {
        if (changes.parentGroup && !changes.parentGroup.firstChange) {
            this.dataGrid.reload();
        }
    }
    trackByName(_index, column) {
        return column.name;
    }
    onDataSourceModifier(dataSourceModifier) {
        return __awaiter(this, void 0, void 0, function* () {
            const promises = [];
            let counters;
            promises.push(this.subAssetsGridService.getData(dataSourceModifier.columns, dataSourceModifier.pagination, this.parentGroup, this.baseQuery));
            const action = this.subAssetsGridService.uiOnlyCountersUpdate.value;
            if (action) {
                counters = this.uiOnlyCountersUpdate(action);
                this.subAssetsGridService.uiOnlyCountersUpdate.next(null);
            }
            else {
                promises.push(this.subAssetsGridService.getTotal(this.parentGroup, this.baseQuery));
                promises.push(this.subAssetsGridService.getCount(dataSourceModifier.columns, dataSourceModifier.pagination, this.parentGroup, this.baseQuery));
            }
            const [dataResponse, size, filteredSize] = yield Promise.all(promises);
            if (!counters) {
                counters = {
                    size,
                    filteredSize
                };
            }
            this.onColumnsChange.emit(dataSourceModifier.columns);
            return Object.assign({ res: dataResponse.res, data: dataResponse.data, paging: dataResponse.paging }, counters);
        });
    }
    configChange(config) {
        this.subAssetsGridService.saveConfig(config);
    }
    // workaround since the totalPages value is cached on the BE
    uiOnlyCountersUpdate(action) {
        const currentAllItemsCount = this.dataGrid.filteringLabelsParams.allItemsCount;
        const currentFilteredItemsCount = this.dataGrid.filteringLabelsParams.filteredItemsCount;
        let counters;
        if (action === 'DECREASE') {
            counters = {
                size: currentAllItemsCount - 1,
                filteredSize: currentFilteredItemsCount - 1
            };
        }
        if (action === 'INCREASE') {
            counters = {
                size: currentAllItemsCount + 1,
                filteredSize: currentFilteredItemsCount + 1
            };
        }
        return counters;
    }
}
SubAssetsGridComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-sub-assets-grid',
                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  [refresh]=\"refresh\"\n  [displayOptions]=\"displayOptions\"\n  (onConfigChange)=\"configChange($event)\"\n  (itemsSelect)=\"itemsSelect.emit($event)\"\n  class=\"d-contents\"\n>\n  <ng-container *ngFor=\"let column of columns; trackBy: trackByName\">\n    <c8y-column [name]=\"column.name\"></c8y-column>\n  </ng-container>\n  <div class=\"c8y-empty-state\">\n    <h1 c8yIcon=\"c8y-group-add\" class=\"c8y-icon-duocolor\"></h1>\n    <div>\n      <p>\n        <strong>{{ 'No items to display.' | translate }}</strong>\n      </p>\n      <small>{{ emptyStateText | translate }}</small>\n    </div>\n  </div>\n</c8y-data-grid>\n"
            },] }
];
SubAssetsGridComponent.ctorParameters = () => [
    { type: SubAssetsService },
    { type: BsModalService },
    { type: SmartGroupsService }
];
SubAssetsGridComponent.propDecorators = {
    parentGroup: [{ type: Input, args: ['parent-group',] }],
    refresh: [{ type: Input }],
    title: [{ type: Input }],
    emptyStateText: [{ type: Input }],
    loadingItemsLabel: [{ 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 AddGroupService {
    constructor(inventoryService) {
        this.inventoryService = inventoryService;
        this.GROUP_FRAGMENT_TYPE = 'c8y_IsDeviceGroup';
    }
    createGroupAndAssignDevices(groupForm, groupContextId, selectedDevices) {
        return __awaiter(this, void 0, void 0, function* () {
            let group;
            const { name, description } = groupForm;
            const newGroupMO = this.getGroupMO(name, description, groupContextId);
            if (groupContextId) {
                group = (yield this.inventoryService.childAssetsCreate(newGroupMO, groupContextId)).data;
            }
            else {
                group = (yield this.inventoryService.create(newGroupMO)).data;
            }
            if (selectedDevices.length > 0) {
                yield 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;
    }
    assignDevices(id, selectedDevices) {
        return __awaiter(this, void 0, void 0, function* () {
            const promises = [];
            selectedDevices.forEach(moId => {
                promises.push(this.inventoryService.childAssetsAdd(moId, id));
            });
            return yield Promise.all(promises);
        });
    }
}
AddGroupService.decorators = [
    { type: Injectable }
];
AddGroupService.ctorParameters = () => [
    { type: InventoryService }
];

class AddGroupComponent {
    constructor(deviceGridService, fb, addGroupService, alert, subAssetsService) {
        this.deviceGridService = deviceGridService;
        this.fb = fb;
        this.addGroupService = addGroupService;
        this.alert = alert;
        this.subAssetsService = subAssetsService;
        this.refresh = new EventEmitter();
        this.onDeviceQueryStringChange = new EventEmitter();
        this.onCancel = new EventEmitter();
        this.pendingStatus = false;
        this.pagination = { pageSize: 20, currentPage: 1 };
        this.selected = [];
        this.canCreateGroup = false;
        this.canAssignDevice = false;
        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();
    }
    onEscapeKeyDown(event) {
        this.onCancel.emit();
    }
    ngOnInit() {
        return __awaiter(this, void 0, void 0, function* () {
            this.formGroupStepOne = this.fb.group({
                name: ['', Validators.required],
                description: ['']
            });
            this.subscription = this.onCancel.subscribe(() => this.resetStepper());
            this.canCreateGroup = this.subAssetsService.canCreateGroup();
            this.canAssignDevice = yield this.subAssetsService.canAssignDevice({
                id: this.currentGroupId
            });
        });
    }
    ngAfterViewInit() {
        this.nameInput = this.nameInputRef.nativeElement;
        this.setFocusOnNameInput();
    }
    createGroup() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.canCreateGroup === false) {
                return;
            }
            this.pendingStatus = true;
            this.subAssetsService.uiOnlyCountersUpdate.next('INCREASE');
            yield this.addGroupService.createGroupAndAssignDevices(this.formGroupStepOne.value, this.currentGroupId, this.selected);
            this.pendingStatus = false;
            this.resetStepper();
            this.alert.success(gettext('Group created.'));
            this.refresh.emit();
            this.onCancel.emit();
        });
    }
    onSelected(selectedDevicesIDs) {
        this.selected = 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();
        }
    }
}
AddGroupComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-add-group',
                template: "<c8y-title *ngIf=\"!currentGroupId\">\n  {{ 'Add group' | translate }}\n</c8y-title>\n\n<div class=\"d-contents\" *ngIf=\"!currentGroupId; else stepper\">\n  <ng-container [ngTemplateOutlet]=\"stepper\"></ng-container>\n</div>\n\n<ng-template #stepper>\n  <c8y-stepper\n    class=\"flex-col flex-nowrap no-align-items fit-h c8y-stepper--no-btns\"\n    [disableDefaultIcons]=\"{ edit: true, done: false }\"\n    [customClasses]=\"['col-md-6', 'col-md-offset-3', 'm-t-24', 'm-b-40', 'p-0', 'flex-no-shrink']\"\n    linear\n  >\n    <cdk-step [stepControl]=\"formGroupStepOne\" [label]=\"'New group' | 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            <h4 class=\"text-center text-medium\">\n              {{ 'New group' | translate }}\n            </h4>\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>\n                  <div [formGroup]=\"formGroupStepOne\">\n                    <c8y-form-group>\n                      <label translate>Name</label>\n                      <input\n                        class=\"form-control\"\n                        type=\"text\"\n                        formControlName=\"name\"\n                        placeholder=\"{{ 'e.g. First floor' | translate }} \"\n                        maxlength=\"254\"\n                        #nameRef\n                        required\n                      />\n                      <c8y-messages>\n                        <c8y-message *ngIf=\"!formGroupStepOne.untouched && !nameRef.value\" translate\n                          >This field is required.</c8y-message\n                        >\n                      </c8y-messages>\n                    </c8y-form-group>\n\n                    <c8y-form-group>\n                      <label translate>Description</label>\n                      <input\n                        class=\"form-control\"\n                        type=\"text\"\n                        formControlName=\"description\"\n                        placeholder=\"{{ 'e.g. first floor devices' | translate }}\"\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 class=\"alert alert-info max-width-100\" translate *ngIf=\"!canAssignDevice\">\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            <h4 class=\"text-center text-medium\">\n              {{ 'Assign devices' | translate }}\n            </h4>\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]=\"[]\"\n          [infiniteScroll]=\"'auto'\"\n          [selectable]=\"'true'\"\n          [pagination]=\"pagination\"\n          (itemsSelect)=\"onSelected($event)\"\n          [refresh]=\"refresh\"\n          class=\"d-contents\"\n        >\n          <div class=\"c8y-empty-state\">\n            <h1 c8yIcon=\"search\"></h1>\n            <div>\n              <p>\n                <strong>{{ 'No matching devices.' | translate }}</strong>\n              </p>\n              <small>{{ 'Refine your search terms' | translate }}</small>\n            </div>\n          </div>\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"
            },] }
];
AddGroupComponent.ctorParameters = () => [
    { type: DeviceGridService },
    { type: FormBuilder },
    { type: AddGroupService },
    { type: AlertService },
    { type: SubAssetsService }
];
AddGroupComponent.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'],] }],
    onEscapeKeyDown: [{ type: HostListener, args: ['document:keydown.escape', ['$event'],] }]
};

const ɵ0$1 = [
    {
        path: 'add-group',
        component: AddGroupComponent
    }
];
class AddGroupModule {
}
AddGroupModule.decorators = [
    { type: NgModule, args: [{
                declarations: [AddGroupComponent],
                imports: [CoreModule, DeviceGridModule, FormsModule, ReactiveFormsModule],
                entryComponents: [AddGroupComponent],
                exports: [AddGroupComponent],
                providers: [
                    {
                        provide: HOOK_ROUTE,
                        useValue: ɵ0$1,
                        multi: true
                    },
                    AddGroupService
                ]
            },] }
];

class GroupsComponent {
    constructor(permissions, subAssetsService) {
        this.permissions = permissions;
        this.subAssetsService = subAssetsService;
        this.refresh = new EventEmitter();
        this.showAddGroup = false;
        this.filterable = false;
        this.sortable = true;
        this.shouldDisableAddGroup = false;
    }
    ngOnInit() {
        if (!this.permissions.hasRole('ROLE_INVENTORY_READ')) {
            this.sortable = false;
        }
        this.shouldDisableAddGroup = !this.subAssetsService.canCreateGroup();
    }
}
GroupsComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-groups-name',
                template: "<c8y-title>\n  {{ 'Groups' | translate }}\n</c8y-title>\n<c8y-action-bar-item [placement]=\"'right'\">\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Add group' | translate }}\"\n    (click)=\"showAddGroup = !showAddGroup\"\n    [disabled]=\"shouldDisableAddGroup\"\n  >\n    <i c8yIcon=\"plus-circle\" class=\"m-r-4\"></i><span translate>Add group</span>\n  </button>\n</c8y-action-bar-item>\n <!-- TODO: uncomment when help is available \n  <c8y-help src=\"/users-guide/device-management/#grouping-devices\"></c8y-help> \n-->\n\n<div [ngClass]=\"{ drawerOpen: showAddGroup }\">\n  <div class=\"bottom-drawer\">\n    <c8y-add-group\n      [refresh]=\"refresh\"\n      (onCancel)=\"showAddGroup = false\"\n      *ngIf=\"showAddGroup\"\n    ></c8y-add-group>\n  </div>\n</div>\n<c8y-sub-assets-grid\n  [refresh]=\"refresh\"\n  [filterable]=\"filterable\"\n  [sortable]=\"sortable\"\n  class=\"content-fullpage d-flex d-col\"\n></c8y-sub-assets-grid>\n"
            },] }
];
GroupsComponent.ctorParameters = () => [
    { type: Permissions },
    { type: SubAssetsService }
];

class AssignDevicesComponent {
    constructor(alert, subAssetsService, inventoryService) {
        this.alert = alert;
        this.subAssetsService = subAssetsService;
        this.inventoryService = inventoryService;
        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();
        }
    }
    onEscapeKeyDown(event) {
        this.onCancel.emit();
    }
    ngOnInit() {
        return __awaiter(this, void 0, void 0, function* () {
            this.setNotIncludedInGroupQuery();
            this.canAssignDevice = yield 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('Display child devices button'),
            template: this.showDevicesToggle,
            callback: () => {
                this.showChildren = !this.showChildren;
                this.setActionControls(this.showChildren);
            }
        };
        headerActionControls.push(showChildDevices);
        this.headerActionControls = headerActionControls;
    }
    setActionControls(showChildren) {
        const actionControls = [];
        const selectChildrenAction = {
            type: 'SHOW_TARGET_CHILD_DEVICES',
            icon: 'enter-bottom',
            text: gettext('Show 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();
    }
    assignDevices() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.canAssignDevice === false) {
                return;
            }
            this.pendingStatus = true;
            try {
                yield this.inventoryService.childAssetsBulkAdd(this.selected, this.currentGroupId);
                this.refresh.emit();
                this.alert.success(gettext('Devices assigned to the group.'));
            }
            catch (error) {
                this.alert.danger(gettext('Could not assign devices to the group'), error);
            }
            this.pendingStatus = false;
            this.selected = [];
            this.onCancel.emit();
        });
    }
    onSelected(selectedDevicesIDs) {
        this.selected = selectedDevicesIDs;
    }
    selectChildren(asset) {
        this.onShowChildDevices.emit(true);
        this.selectedDevice.emit(asset);
    }
}
AssignDevicesComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-assign-devices',
                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\">\n        {{ 'Assign devices' | translate }}\n      </h4>\n    </div>\n  </div>\n</div>\n<c8y-device-grid\n  [title]=\"'Select devices' | translate\"\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  class=\"flex-grow col-xs-12 no-gutter\"\n>\n  <div class=\"c8y-empty-state\">\n    <h1 c8yIcon=\"search\"></h1>\n    <div>\n      <p>\n        <strong>{{ 'No matching devices.' | translate }}</strong>\n      </p>\n      <small>{{ 'Refine your search terms' | translate }}</small>\n    </div>\n  </div>\n</c8y-device-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\n<ng-template #showDevicesToggle let-control=\"headerActionControl\">\n  <label class=\"c8y-switch\">\n    <input type=\"checkbox\" [(ngModel)]=\"showChildren\" (click)=\"control.callback()\" />\n    <span></span>\n    <span>{{ control.text | translate }}</span>\n  </label>\n  <button\n    class=\"btn-clean m-r-8\"\n    [popover]=\"childDevicesPop\"\n    placement=\"bottom\"\n    [outsideClick]=\"true\"\n  >\n    <i c8yIcon=\"question-circle-o\" class=\"text-primary\"></i>\n  </button>\n  <ng-template #childDevicesPop>\n    <span translate>\n      Displays the button\n      <button class=\"btn btn-xs btn-icon btn-default no-pointer\">\n        <i class=\"text-primary dlt-c8y-icon-enter-bottom\"></i>\n      </button>\n      next to target devices with children. Clicking it displays a list with all child devices of\n      the selected target device.\n    </span>\n  </ng-template>\n</ng-template>\n"
            },] }
];
AssignDevicesComponent.ctorParameters = () => [
    { type: AlertService },
    { type: SubAssetsService },
    { type: InventoryService }
];
AssignDevicesComponent.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'],] }],
    onEscapeKeyDown: [{ type: HostListener, args: ['document:keydown.escape', ['$event'],] }]
};

class AssignChildDevicesComponent {
    constructor(alert, subAssetsService, inventoryService) {
        this.alert = alert;
        this.subAssetsService = subAssetsService;
        this.inventoryService = inventoryService;
        this.onCancel = new EventEmitter();
        this.refresh = new EventEmitter();
        this.selected = [];
        this.canAssignDevice = false;
        this.pendingStatus = false;
    }
    onEnterKeyDown(event) {
        if (this.selected.length > 0) {
            this.assignDevices();
        }
    }
    onEscapeKeyDown(event) {
        this.onCancel.emit();
    }
    ngOnInit() {
        return __awaiter(this, void 0, void 0, function* () {
            this.setNotIncludedInGroupQuery();
            this.canAssignDevice = yield this.subAssetsService.canAssignDevice({
                id: this.currentGroupId
            });
        });
    }
    setNotIncludedInGroupQuery() {
        const notIncludedInGroupQuery = { __not: { __bygroupid: this.currentGroupId } };
        this.baseQuery = notIncludedInGroupQuery;
    }
    assignDevices() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.canAssignDevice === false) {
                return;
            }
            this.pendingStatus = true;
            try {
                yield this.inventoryService.childAssetsBulkAdd(this.selected, this.currentGroupId);
                this.refresh.emit();
                this.alert.success(gettext('Child devices assigned to the group.'));
            }
            catch (error) {
                this.alert.danger(gettext('Could not assign child devices to the group'), error);
            }
            this.pendingStatus = false;
            this.selected = [];
            this.onCancel.emit();
        });
    }
    onSelected(selectedDevicesIDs) {
        this.selected = selectedDevicesIDs;
    }
}
AssignChildDevicesComponent.decorators = [
    { type: Component, args: [{
                selector: 'c8y-assign-child-devices',
                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\">\n        {{ 'Assign child devices' | translate }}\n      </h4>\n    </div>\n  </div>\n</div>\n\n<div class=\"d-flex d-col no-align-items fit-h\">\n  <c8y-sub-assets-grid\n    [title]=\"'Select child devices' | translate\"\n    [emptyStateText]=\"'All child devices are already assigned to the group' | translate\"\n    [refresh]=\"refresh\"\n    [actionControls]=\"[]\"\n    [selectable]=\"true\"\n    [parent-group]=\"parentDevice\"\n    [baseQuery]=\"baseQuery\"\n    (itemsSelect)=\"onSelected($event)\"\n    class=\"d-contents\"\n  >\n  </c8y-sub-assets-grid>\n</div>\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"
            },] }
];
AssignChildDevicesComponent.ctorParameters = () => [
    { type: AlertService },
    { type: SubAssetsService },
    { type: InventoryService }
];
AssignChildDevicesComponent.propDecorators = {
    currentGroupId: [{ type: Input }],
    parentDevice: [{ type: Input }],
    onCancel: [{ type: Output }],
    refresh: [{ type: Input }],
    onEnterKeyDown: [{ type: HostListener, args: ['document:keydown.enter', ['$event'],] }],
    onEscapeKeyDown: [{ type: HostListener, args: ['document:keydown.escape', ['$event'],] }]
};

const ɵ0 = [
    {
        context: ViewContext.Group,
        path: 'subassets',
        priority: 1000,
        icon: 'c8y-group-open',
        label: gettext('Subassets'),
        component: SubAssetsComponent
    },
    {
        path: 'group',
        component: GroupsComponent
    }
];
class SubAssetsModule {
}
SubAssetsModule.decorators = [
    { type: NgModule, args: [{
                declarations: [
                    SubAssetsComponent,
                    SubAssetsGridComponent,
                    AssetTypeCellRendererComponent,
                    GroupsComponent,
                    GroupInfoComponent,
                    DeleteAssetsModalComponent,
                    UnassignModalComponent,
                    AssignDevicesComponent,
                    AssignChildDevicesComponent
                ],
                imports: [CoreModule, DeviceGridModule, AddGroupModule, PopoverModule],
                entryComponents: [
                    SubAssetsComponent,
                    AssetTypeCellRendererComponent,
                    GroupsComponent,
                    DeleteAssetsModalComponent,
                    UnassignModalComponent
                ],
                exports: [],
                providers: [
                    {
                        provide: HOOK_ROUTE,
                        useValue: ɵ0,
                        multi: true
                    },
                    SubAssetsService
                ]
            },] }
];

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

export { AddGroupComponent, AddGroupModule, AddGroupService, AssetTypeCellRendererComponent, AssetTypeGridColumn, AssignChildDevicesComponent, AssignDevicesComponent, DeleteAssetsModalComponent, GroupInfoComponent, GroupsComponent, SubAssetsComponent, SubAssetsGridComponent, SubAssetsModule, SubAssetsService, UnassignModalComponent, AssetTypeCellRendererComponent as ɵa, DeleteAssetsModalComponent as ɵb, UnassignModalComponent as ɵc, AddGroupModule as ɵd, AddGroupComponent as ɵe, AddGroupService as ɵf };
//# sourceMappingURL=c8y-ngx-components-sub-assets.js.map
