UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

991 lines 103 kB
import * as i0 from '@angular/core';
import { EventEmitter, Injectable, Component, Pipe, Input, Output, ViewChild, NgModule } from '@angular/core';
import * as i1 from '@angular/router';
import * as i4 from '@c8y/client';
import { OperationStatus } from '@c8y/client';
import * as i2 from '@c8y/ngx-components';
import { gettext, Permissions, hookRoute, ViewContext, CoreModule, ValidationPattern, BuiltInActionType, Status, FilterInputComponent, NavigatorNode, hookNavigator, FormsModule } from '@c8y/ngx-components';
import * as i3 from '@c8y/ngx-components/repository/shared';
import { DeviceConfigurationOperation, RepositoryType, SharedRepositoryModule, RepositoryItemNameGridColumn, DescriptionGridColumn, FileGridColumn, DeviceTypeGridColumn, TypeGridColumn } from '@c8y/ngx-components/repository/shared';
import * as i6 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i5 from '@angular/forms';
import * as i8 from '@c8y/ngx-components/operations/operation-details';
import { OperationDetailsModule } from '@c8y/ngx-components/operations/operation-details';
import { has, cloneDeep, uniqBy, isUndefined } from 'lodash-es';
import { saveAs } from 'file-saver';
import * as i3$1 from 'ngx-bootstrap/modal';
import { map } from 'rxjs/operators';
import * as i7 from 'ngx-bootstrap/tabs';
import { TabsModule } from 'ngx-bootstrap/tabs';
import * as i4$1 from '@ngx-translate/core';
import { pipe } from 'rxjs';
import { TooltipModule } from 'ngx-bootstrap/tooltip';

class DeviceConfigurationService {
    constructor() {
        this.configurationsUpdated = new EventEmitter();
    }
    updateConfigurations(repositorySnapsOnly) {
        this.configurationsUpdated.emit(repositorySnapsOnly);
    }
    hasAnySupportedOperation(mo, operation) {
        const supported = mo.c8y_SupportedOperations;
        if (!supported) {
            return false;
        }
        if (!Array.isArray(operation)) {
            operation = [operation];
        }
        return supported.some(supportedOperation => operation.includes(supportedOperation));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceConfigurationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceConfigurationService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceConfigurationService, decorators: [{
            type: Injectable
        }] });

class TextBasedConfigurationComponent {
    constructor(route, alertService, repositoryService, deviceConfigurationService, inventoryService) {
        this.route = route;
        this.alertService = alertService;
        this.repositoryService = repositoryService;
        this.deviceConfigurationService = deviceConfigurationService;
        this.inventoryService = inventoryService;
        this.reloadingConfig = false;
    }
    async ngOnInit() {
        await this.load();
    }
    async load() {
        this.device = this.route.snapshot.parent.data.contextData;
        await this.loadDevice();
        await this.loadOperation();
        this.showTextBasedConfigReload = this.deviceConfigurationService.hasAnySupportedOperation(this.device, [DeviceConfigurationOperation.SEND_CONFIG]);
        this.showTextBasedConfigSave = this.deviceConfigurationService.hasAnySupportedOperation(this.device, [DeviceConfigurationOperation.CONFIG]);
        if (this.device.c8y_Configuration && this.device.c8y_Configuration.config) {
            this.config = this.device.c8y_Configuration.config;
        }
    }
    async loadOperation() {
        const operation = await this.repositoryService.getLastConfigUpdateOperation(this.device.id);
        if (operation !== null) {
            this.reloadingConfig =
                !!operation.c8y_SendConfiguration &&
                    (operation.status === OperationStatus.PENDING ||
                        operation.status === OperationStatus.EXECUTING);
            this.repositoryService.observeOperation(operation).subscribe(operationUpdate => {
                if (operationUpdate.status === OperationStatus.PENDING ||
                    operationUpdate.status === OperationStatus.EXECUTING) {
                    this.latestOperation = operationUpdate;
                }
                else
                    this.latestOperation = null;
            });
        }
    }
    get savingConfig() {
        return this.latestOperation
            ? !!this.latestOperation.c8y_Configuration &&
                (this.latestOperation.status === OperationStatus.PENDING ||
                    this.latestOperation.status === OperationStatus.EXECUTING)
            : false;
    }
    async reloadConfiguration() {
        this.reloadingConfig = true;
        const operationCfg = await this.repositoryService.createTextBasedConfigurationReloadOperation(this.device);
        try {
            this.repositoryService.createObservedOperation(operationCfg).subscribe(operationUpdate => this.onOperationReloadSuccess(operationUpdate), operationUpdate => this.onOperationReloadError(operationUpdate), () => this.onOperationReloadComplete());
        }
        catch (ex) {
            this.alertService.addServerFailure(ex);
        }
    }
    async updateConfiguration(config) {
        const operationCfg = await this.repositoryService.createTextBasedConfigurationUpdateOperation(this.device, config);
        try {
            this.repositoryService.createObservedOperation(operationCfg).subscribe(operationUpdate => this.onOperationUpdateSuccess(operationUpdate), operationUpdate => this.onOperationUpdateError(operationUpdate), () => this.onOperationUpdateComplete());
        }
        catch (ex) {
            this.alertService.addServerFailure(ex);
        }
    }
    onOperationReloadSuccess(operationUpdate) {
        this.latestOperation = operationUpdate;
        if (operationUpdate.status === OperationStatus.PENDING) {
            this.alertService.success(gettext('Configuration will be reloaded.'));
        }
    }
    onOperationReloadError(operationUpdate) {
        this.latestOperation = operationUpdate;
        this.reloadingConfig = false;
    }
    async onOperationReloadComplete() {
        await this.loadDevice();
        this.config = this.device.c8y_Configuration.config;
        this.reloadingConfig = false;
    }
    onOperationUpdateSuccess(operationUpdate) {
        this.latestOperation = operationUpdate;
        if (operationUpdate.status === OperationStatus.PENDING) {
            this.alertService.success(gettext('Configuration will be updated.'));
        }
    }
    onOperationUpdateError(operationUpdate) {
        this.latestOperation = operationUpdate;
    }
    onOperationUpdateComplete() {
        this.device.c8y_Configuration.config = this.config;
    }
    async loadDevice() {
        this.device = (await this.inventoryService.detail(this.device.id, {
            withChildren: false
        })).data;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TextBasedConfigurationComponent, deps: [{ token: i1.ActivatedRoute }, { token: i2.AlertService }, { token: i3.RepositoryService }, { token: DeviceConfigurationService }, { token: i4.InventoryService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: TextBasedConfigurationComponent, isStandalone: false, selector: "c8y-text-based-configuration", ngImport: i0, template: "<div class=\"d-flex d-col fit-h\">\n  <fieldset class=\"card-block bg-level-1 fit-w\">\n    <div class=\"content-flex-50\">\n      <div class=\"m-l-auto d-flex\">\n        <button\n          class=\"btn btn-default btn-sm a-s-center m-t-8 m-b-8\"\n          title=\"{{ 'Get configuration from device' | translate }}\"\n          type=\"button\"\n          *ngIf=\"showTextBasedConfigReload\"\n          (click)=\"reloadConfiguration()\"\n          [disabled]=\"reloadingConfig || savingConfig\"\n        >\n          <i\n            class=\"m-r-4\"\n            c8yIcon=\"refresh\"\n            *ngIf=\"reloadingConfig\"\n            [ngClass]=\"{ 'icon-spin': reloadingConfig }\"\n          ></i>\n          <i\n            class=\"m-r-4\"\n            c8yIcon=\"download\"\n            *ngIf=\"!reloadingConfig\"\n          ></i>\n\n          {{ 'Get configuration from device' | translate }}\n        </button>\n      </div>\n    </div>\n  </fieldset>\n  <div class=\"flex-grow\">\n    <textarea\n      class=\"form-control fit-h p-r-16 p-l-16\"\n      [attr.aria-label]=\"'Operations' | translate\"\n      [(ngModel)]=\"config\"\n      [disabled]=\"reloadingConfig || savingConfig\"\n      c8y-spellcheck=\"false\"\n    ></textarea>\n  </div>\n  <c8y-operation-details\n    class=\"bg-level-2 p-0\"\n    *ngIf=\"latestOperation !== undefined\"\n    [operation]=\"latestOperation\"\n  ></c8y-operation-details>\n  <div\n    class=\"card-footer fit-w separator\"\n    *ngIf=\"showTextBasedConfigSave\"\n  >\n    <button\n      class=\"btn btn-primary\"\n      id=\"send-config-btn\"\n      type=\"button\"\n      (click)=\"updateConfiguration(config)\"\n      [disabled]=\"reloadingConfig || savingConfig || !config\"\n      [ngClass]=\"{ 'btn-pending': savingConfig }\"\n    >\n      <span\n        title=\"{{ 'Send' | translate }}\"\n        *ngIf=\"!savingConfig\"\n      >\n        {{ 'Send configuration to device' | translate }}\n      </span>\n      <span\n        title=\"{{ 'Sending\u2026' | translate }}\"\n        *ngIf=\"savingConfig\"\n      >\n        {{ 'Sending\u2026' | translate }}\n      </span>\n    </button>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8.OperationDetailsComponent, selector: "c8y-operation-details", inputs: ["operation"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TextBasedConfigurationComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-text-based-configuration', standalone: false, template: "<div class=\"d-flex d-col fit-h\">\n  <fieldset class=\"card-block bg-level-1 fit-w\">\n    <div class=\"content-flex-50\">\n      <div class=\"m-l-auto d-flex\">\n        <button\n          class=\"btn btn-default btn-sm a-s-center m-t-8 m-b-8\"\n          title=\"{{ 'Get configuration from device' | translate }}\"\n          type=\"button\"\n          *ngIf=\"showTextBasedConfigReload\"\n          (click)=\"reloadConfiguration()\"\n          [disabled]=\"reloadingConfig || savingConfig\"\n        >\n          <i\n            class=\"m-r-4\"\n            c8yIcon=\"refresh\"\n            *ngIf=\"reloadingConfig\"\n            [ngClass]=\"{ 'icon-spin': reloadingConfig }\"\n          ></i>\n          <i\n            class=\"m-r-4\"\n            c8yIcon=\"download\"\n            *ngIf=\"!reloadingConfig\"\n          ></i>\n\n          {{ 'Get configuration from device' | translate }}\n        </button>\n      </div>\n    </div>\n  </fieldset>\n  <div class=\"flex-grow\">\n    <textarea\n      class=\"form-control fit-h p-r-16 p-l-16\"\n      [attr.aria-label]=\"'Operations' | translate\"\n      [(ngModel)]=\"config\"\n      [disabled]=\"reloadingConfig || savingConfig\"\n      c8y-spellcheck=\"false\"\n    ></textarea>\n  </div>\n  <c8y-operation-details\n    class=\"bg-level-2 p-0\"\n    *ngIf=\"latestOperation !== undefined\"\n    [operation]=\"latestOperation\"\n  ></c8y-operation-details>\n  <div\n    class=\"card-footer fit-w separator\"\n    *ngIf=\"showTextBasedConfigSave\"\n  >\n    <button\n      class=\"btn btn-primary\"\n      id=\"send-config-btn\"\n      type=\"button\"\n      (click)=\"updateConfiguration(config)\"\n      [disabled]=\"reloadingConfig || savingConfig || !config\"\n      [ngClass]=\"{ 'btn-pending': savingConfig }\"\n    >\n      <span\n        title=\"{{ 'Send' | translate }}\"\n        *ngIf=\"!savingConfig\"\n      >\n        {{ 'Send configuration to device' | translate }}\n      </span>\n      <span\n        title=\"{{ 'Sending\u2026' | translate }}\"\n        *ngIf=\"savingConfig\"\n      >\n        {{ 'Sending\u2026' | translate }}\n      </span>\n    </button>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: i2.AlertService }, { type: i3.RepositoryService }, { type: DeviceConfigurationService }, { type: i4.InventoryService }] });

class DeviceConfigurationGuard {
    constructor(deviceConfigurationService) {
        this.deviceConfigurationService = deviceConfigurationService;
    }
    canActivate(route) {
        const contextData = route.data.contextData || route.parent.data.contextData;
        if (!contextData) {
            return false;
        }
        return ((contextData.c8y_SupportedConfigurations &&
            contextData.c8y_SupportedConfigurations.length > 0) ||
            this.deviceConfigurationService.hasAnySupportedOperation(contextData, [
                DeviceConfigurationOperation.DOWNLOAD_CONFIG,
                DeviceConfigurationOperation.UPLOAD_CONFIG,
                DeviceConfigurationOperation.CONFIG,
                DeviceConfigurationOperation.SEND_CONFIG
            ]) ||
            has(contextData, 'c8y_Configuration'));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceConfigurationGuard, deps: [{ token: DeviceConfigurationService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceConfigurationGuard }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceConfigurationGuard, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: DeviceConfigurationService }] });

class ConfigurationFilterPipe {
    transform(items, filterTerm) {
        return filterTerm.trim().length === 0
            ? items
            : items.filter((item) => this.filterContainString(item.name, filterTerm) ||
                this.filterContainString(item.deviceType, filterTerm));
    }
    filterContainString(name, filterTerm) {
        const term = filterTerm.toLowerCase().trim();
        return name && name.toLowerCase().indexOf(term) > -1;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationFilterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
    static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationFilterPipe, isStandalone: false, name: "configurationFilterPipe" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationFilterPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'configurationFilterPipe',
                    standalone: false
                }]
        }] });

class SaveToRepositoryComponent {
    constructor(modal, alertService, repositoryService) {
        this.modal = modal;
        this.alertService = alertService;
        this.repositoryService = repositoryService;
        this.result = new Promise((resolve, reject) => {
            this._save = resolve;
            this._cancel = reject;
        });
    }
    async save() {
        {
            try {
                const configSnapshotData = {
                    selected: {
                        configurationType: this.configSnapshot.configurationType
                    },
                    version: this.configSnapshot.name,
                    deviceType: this.configSnapshot.deviceType,
                    description: this.configSnapshot.description,
                    binary: {
                        file: new File([this.configSnapshot.binary], this.configSnapshot.name)
                    }
                };
                await this.repositoryService.create(configSnapshotData, RepositoryType.CONFIGURATION);
                this.alertService.success(gettext('Configuration saved.'));
                this._save();
            }
            catch (ex) {
                this.alertService.addServerFailure(ex);
            }
        }
    }
    close() {
        this._cancel();
        this.modal.hide();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SaveToRepositoryComponent, deps: [{ token: i3$1.BsModalRef }, { token: i2.AlertService }, { token: i3.RepositoryService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SaveToRepositoryComponent, isStandalone: false, selector: "c8y-save-config-to-configuration-repository", ngImport: i0, template: "<div class=\"modal-header dialog-header\">\n  <i c8yIcon=\"gears\"></i>\n  <h4 id=\"modal-title\" translate>\n    Save configuration\n  </h4>\n</div>\n<div class=\"modal-body\" id=\"modal-body\">\n  <form #saveConfigurationSnapshot=\"ngForm\" class=\"p-t-24\">\n    <c8y-form-group>\n      <label translate for=\"name\">Name</label>\n      <input\n        id=\"name\"\n        type=\"text\"\n        class=\"form-control\"\n        autocomplete=\"off\"\n        name=\"name\"\n        [(ngModel)]=\"configSnapshot.name\"\n        required\n      />\n    </c8y-form-group>\n    <c8y-form-group>\n      <label translate for=\"deviceType\">Device type</label>\n      <input\n        id=\"deviceType\"\n        class=\"form-control\"\n        rows=\"6\"\n        name=\"deviceType\"\n        [(ngModel)]=\"configSnapshot.deviceType\"\n      />\n    </c8y-form-group>\n    <c8y-form-group>\n      <label translate for=\"description\">Description</label>\n      <input\n        type=\"text\"\n        id=\"description\"\n        class=\"form-control\"\n        maxlength=\"254\"\n        autocomplete=\"off\"\n        name=\"description\"\n        [(ngModel)]=\"configSnapshot.description\"\n      />\n    </c8y-form-group>\n    <c8y-form-group>\n      <label translate for=\"configurationType\">Configuration type</label>\n      <input\n        id=\"configurationType\"\n        class=\"form-control\"\n        rows=\"6\"\n        name=\"configurationType\"\n        [(ngModel)]=\"configSnapshot.configurationType\"\n      />\n    </c8y-form-group>\n  </form>\n</div>\n<div class=\"modal-footer\">\n  <button title=\"{{ 'Cancel' | translate }}\" class=\"btn btn-default\" (click)=\"close()\" translate>\n    Cancel\n  </button>\n\n  <button\n    title=\"{{ 'Save configuration to repository' | translate }}\"\n    class=\"btn btn-primary\"\n    (click)=\"save()\"\n    [disabled]=\"saveConfigurationSnapshot.form.invalid\"\n    translate\n  >\n    Save\n  </button>\n</div>\n", dependencies: [{ kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i2.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i2.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SaveToRepositoryComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-save-config-to-configuration-repository', standalone: false, template: "<div class=\"modal-header dialog-header\">\n  <i c8yIcon=\"gears\"></i>\n  <h4 id=\"modal-title\" translate>\n    Save configuration\n  </h4>\n</div>\n<div class=\"modal-body\" id=\"modal-body\">\n  <form #saveConfigurationSnapshot=\"ngForm\" class=\"p-t-24\">\n    <c8y-form-group>\n      <label translate for=\"name\">Name</label>\n      <input\n        id=\"name\"\n        type=\"text\"\n        class=\"form-control\"\n        autocomplete=\"off\"\n        name=\"name\"\n        [(ngModel)]=\"configSnapshot.name\"\n        required\n      />\n    </c8y-form-group>\n    <c8y-form-group>\n      <label translate for=\"deviceType\">Device type</label>\n      <input\n        id=\"deviceType\"\n        class=\"form-control\"\n        rows=\"6\"\n        name=\"deviceType\"\n        [(ngModel)]=\"configSnapshot.deviceType\"\n      />\n    </c8y-form-group>\n    <c8y-form-group>\n      <label translate for=\"description\">Description</label>\n      <input\n        type=\"text\"\n        id=\"description\"\n        class=\"form-control\"\n        maxlength=\"254\"\n        autocomplete=\"off\"\n        name=\"description\"\n        [(ngModel)]=\"configSnapshot.description\"\n      />\n    </c8y-form-group>\n    <c8y-form-group>\n      <label translate for=\"configurationType\">Configuration type</label>\n      <input\n        id=\"configurationType\"\n        class=\"form-control\"\n        rows=\"6\"\n        name=\"configurationType\"\n        [(ngModel)]=\"configSnapshot.configurationType\"\n      />\n    </c8y-form-group>\n  </form>\n</div>\n<div class=\"modal-footer\">\n  <button title=\"{{ 'Cancel' | translate }}\" class=\"btn btn-default\" (click)=\"close()\" translate>\n    Cancel\n  </button>\n\n  <button\n    title=\"{{ 'Save configuration to repository' | translate }}\"\n    class=\"btn btn-primary\"\n    (click)=\"save()\"\n    [disabled]=\"saveConfigurationSnapshot.form.invalid\"\n    translate\n  >\n    Save\n  </button>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i3$1.BsModalRef }, { type: i2.AlertService }, { type: i3.RepositoryService }] });

class SourceCodePreviewComponent {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SourceCodePreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SourceCodePreviewComponent, isStandalone: false, selector: "c8y-source-code-preview", inputs: { isDisabled: "isDisabled", text: "text" }, ngImport: i0, template: "<textarea\n  [disabled]=\"isDisabled\"\n  class=\"text-monospace form-control no-resize flex-grow\"\n  rows=\"4\"\n  >{{ text }}</textarea\n>\n" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SourceCodePreviewComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-source-code-preview', standalone: false, template: "<textarea\n  [disabled]=\"isDisabled\"\n  class=\"text-monospace form-control no-resize flex-grow\"\n  rows=\"4\"\n  >{{ text }}</textarea\n>\n" }]
        }], propDecorators: { isDisabled: [{
                type: Input
            }], text: [{
                type: Input
            }] } });

class ConfigurationPreviewComponent {
    set configurationType(type) {
        this._configurationType = type;
        this.setOperation(type);
    }
    get configurationType() {
        return this._configurationType;
    }
    constructor(deviceConfigurationService, operationRealtime, bsModal, user, appState, repositoryService, operationService, alertService) {
        this.deviceConfigurationService = deviceConfigurationService;
        this.operationRealtime = operationRealtime;
        this.bsModal = bsModal;
        this.user = user;
        this.appState = appState;
        this.repositoryService = repositoryService;
        this.operationService = operationService;
        this.alertService = alertService;
        this.isLegacy = false;
        this.canCallAction = true;
        this.deviceConfigurationOperation = DeviceConfigurationOperation;
    }
    async ngOnInit() {
        this.setCanCallAction();
        this.setOperation(this._configurationType);
        this.operationsSubscription = this.operationRealtime
            .onAll$(this.device.id)
            .pipe(map(({ data }) => data))
            .subscribe(operation => {
            this.updatePreview(operation);
        });
    }
    async setOperation(configType) {
        const operationList = await this.repositoryService.getConfigFileOperationList(this.device.id, this.operationToTrigger);
        const operation = this.isLegacy
            ? operationList.find(op => op[this.operationToTrigger] && !op[this.operationToTrigger].type)
            : operationList.find(op => op[this.operationToTrigger].type === configType);
        this.operation =
            operation && operation.status !== OperationStatus.SUCCESSFUL ? operation : undefined;
    }
    setCanCallAction() {
        this.canCallAction = this.deviceConfigurationService.hasAnySupportedOperation(this.device, this.operationToTrigger);
    }
    async createDeviceOperation() {
        let operationCfg;
        if (this.operationToTrigger === DeviceConfigurationOperation.DOWNLOAD_CONFIG) {
            operationCfg = this.repositoryService.getDownloadConfigurationFileOperation(this.device, this._configurationType, this.configSnapshot, this.isLegacy);
        }
        if (this.operationToTrigger === DeviceConfigurationOperation.UPLOAD_CONFIG) {
            operationCfg = this.repositoryService.getUploadConfigurationFileOperation(this.device, this._configurationType, this.isLegacy);
        }
        try {
            this.operation = (await this.operationService.create(operationCfg)).data;
        }
        catch (ex) {
            this.alertService.addServerFailure(ex);
        }
    }
    showOperation() {
        if (this.operationToTrigger === DeviceConfigurationOperation.DOWNLOAD_CONFIG) {
            return !!this.operation;
        }
        return (this.operation &&
            [OperationStatus.PENDING, OperationStatus.EXECUTING].includes(this.operation.status));
    }
    showBinary() {
        if (this.operationToTrigger === DeviceConfigurationOperation.DOWNLOAD_CONFIG) {
            return true;
        }
        return !this.showOperation();
    }
    isCreateOperationDisabled() {
        return (this.operation &&
            [OperationStatus.PENDING, OperationStatus.EXECUTING].includes(this.operation.status));
    }
    updatePreview(operation) {
        if (operation &&
            operation[this.operationToTrigger] &&
            (this.isLegacy ||
                (operation[this.operationToTrigger].type &&
                    operation[this.operationToTrigger].type === this.configurationType))) {
            this.operation = operation;
            this.updateSnapshotsOnConfigUpload(operation);
        }
    }
    download() {
        const blob = new Blob([this.configSnapshot.binary], { type: this.configSnapshot.binaryType });
        let fileName = this.configSnapshot.name;
        switch (this.configSnapshot.binaryType) {
            case 'text/csv':
            case 'application/csv':
                fileName = fileName.concat('.csv');
                break;
            case 'text/yaml':
            case 'application/x-yaml':
                fileName = fileName.concat('.yaml');
                break;
            case 'application/json':
                fileName = fileName.concat('.json');
                break;
        }
        saveAs(blob, fileName);
    }
    async saveToRepository() {
        const initialState = {
            configSnapshot: cloneDeep(this.configSnapshot)
        };
        const modal = this.bsModal.show(SaveToRepositoryComponent, {
            class: 'modal-sm',
            ariaDescribedby: 'modal-body',
            ariaLabelledBy: 'modal-title',
            initialState,
            ignoreBackdropClick: true
        }).content;
        try {
            await modal.result;
            this.deviceConfigurationService.updateConfigurations(true);
            modal.close();
        }
        catch (ex) {
            // do nothing
        }
    }
    hasPermission() {
        return (this.user.hasAnyRole(this.appState.currentUser.value, [
            Permissions.ROLE_INVENTORY_ADMIN,
            Permissions.ROLE_INVENTORY_CREATE
        ]) ||
            (this.user.hasAnyRole(this.appState.currentUser.value, [
                Permissions.ROLE_MANAGED_OBJECT_ADMIN,
                Permissions.ROLE_MANAGED_OBJECT_CREATE
            ]) &&
                this.user.hasAnyRole(this.appState.currentUser.value, [
                    Permissions.ROLE_BINARY_ADMIN,
                    Permissions.ROLE_BINARY_CREATE
                ])));
    }
    ngOnDestroy() {
        if (this.operationsSubscription) {
            this.operationsSubscription.unsubscribe();
        }
    }
    async updateSnapshotsOnConfigUpload(operation) {
        if (operation[DeviceConfigurationOperation.UPLOAD_CONFIG] &&
            operation.status === OperationStatus.SUCCESSFUL) {
            this.deviceConfigurationService.updateConfigurations();
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationPreviewComponent, deps: [{ token: DeviceConfigurationService }, { token: i2.OperationRealtimeService }, { token: i3$1.BsModalService }, { token: i4.UserService }, { token: i2.AppStateService }, { token: i3.RepositoryService }, { token: i4.OperationService }, { token: i2.AlertService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ConfigurationPreviewComponent, isStandalone: false, selector: "c8y-device-configuration-preview", inputs: { device: "device", configurationType: "configurationType", configSnapshot: "configSnapshot", canSaveSnapshot: "canSaveSnapshot", actionButtonText: "actionButtonText", actionButtonIcon: "actionButtonIcon", isLegacy: "isLegacy", operationToTrigger: "operationToTrigger" }, ngImport: i0, template: "<div class=\"content-flex-55 p-b-16\">\n  <div class=\"col-7 p-t-4\">\n    <p>\n      <span class=\"text-label-small text-uppercase m-r-4\" translate>Configuration</span>\n      <span *ngIf=\"configSnapshot?.name; else emptyText\">\n        <strong>{{ configSnapshot.name }}</strong>\n      </span>\n      <ng-template #emptyText>---</ng-template>\n    </p>\n    <p>\n      <span class=\"text-label-small text-uppercase m-r-4\" translate>Last updated</span>\n      <small *ngIf=\"configSnapshot?.time; else emptyDate\">\n        {{ configSnapshot.time | c8yDate }}\n      </small>\n      <ng-template #emptyDate>---</ng-template>\n    </p>\n  </div>\n  <div class=\"col-5\">\n    <button\n      id=\"action-btn\"\n      class=\"btn btn-default btn-sm pull-right\"\n      type=\"button\"\n      title=\"{{ actionButtonText | translate }}\"\n      (click)=\"createDeviceOperation()\"\n      [disabled]=\"isCreateOperationDisabled()\"\n      *ngIf=\"canCallAction\"\n    >\n      <i [c8yIcon]=\"actionButtonIcon\"></i>\n      {{ actionButtonText | translate }}\n    </button>\n  </div>\n</div>\n<div class=\"c8y-empty-state text-left\" *ngIf=\"!configSnapshot?.binary && showBinary()\">\n  <h1 [c8yIcon]=\"'file-image-o'\"></h1>\n  <p>\n    <strong translate>No preview available.</strong>\n    <br />\n    <small *ngIf=\"configSnapshot?.binary !== ''; else emptyFile\" translate>\n      The file is not available.\n    </small>\n    <ng-template #emptyFile>\n      <small translate>The file is empty.</small>\n    </ng-template>\n  </p>\n</div>\n<div *ngIf=\"configSnapshot?.binary && showBinary()\" class=\"flex-grow d-flex d-col\">\n  <c8y-source-code-preview\n    [text]=\"configSnapshot.binary\"\n    [isDisabled]=\"true\"\n    class=\"d-contents\"\n  ></c8y-source-code-preview>\n  <div *ngIf=\"canSaveSnapshot\" class=\"p-t-16\">\n    <button\n      title=\"{{ 'Download' | translate }}\"\n      type=\"button\"\n      class=\"btn btn-primary btn-sm pull-right m-l-8\"\n      (click)=\"download()\"\n    >\n      {{ 'Download' | translate }}\n    </button>\n    <button\n      title=\"{{ 'Save to repository' | translate }}\"\n      *ngIf=\"hasPermission()\"\n      type=\"button\"\n      class=\"btn btn-default btn-sm pull-right\"\n      (click)=\"saveToRepository()\"\n    >\n      {{ 'Save to repository' | translate }}\n    </button>\n  </div>\n</div>\n<div *ngIf=\"showOperation()\">\n  <c8y-operation-details [operation]=\"operation\"></c8y-operation-details>\n</div>\n", dependencies: [{ kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: i8.OperationDetailsComponent, selector: "c8y-operation-details", inputs: ["operation"] }, { kind: "component", type: SourceCodePreviewComponent, selector: "c8y-source-code-preview", inputs: ["isDisabled", "text"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2.DatePipe, name: "c8yDate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationPreviewComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-device-configuration-preview', standalone: false, template: "<div class=\"content-flex-55 p-b-16\">\n  <div class=\"col-7 p-t-4\">\n    <p>\n      <span class=\"text-label-small text-uppercase m-r-4\" translate>Configuration</span>\n      <span *ngIf=\"configSnapshot?.name; else emptyText\">\n        <strong>{{ configSnapshot.name }}</strong>\n      </span>\n      <ng-template #emptyText>---</ng-template>\n    </p>\n    <p>\n      <span class=\"text-label-small text-uppercase m-r-4\" translate>Last updated</span>\n      <small *ngIf=\"configSnapshot?.time; else emptyDate\">\n        {{ configSnapshot.time | c8yDate }}\n      </small>\n      <ng-template #emptyDate>---</ng-template>\n    </p>\n  </div>\n  <div class=\"col-5\">\n    <button\n      id=\"action-btn\"\n      class=\"btn btn-default btn-sm pull-right\"\n      type=\"button\"\n      title=\"{{ actionButtonText | translate }}\"\n      (click)=\"createDeviceOperation()\"\n      [disabled]=\"isCreateOperationDisabled()\"\n      *ngIf=\"canCallAction\"\n    >\n      <i [c8yIcon]=\"actionButtonIcon\"></i>\n      {{ actionButtonText | translate }}\n    </button>\n  </div>\n</div>\n<div class=\"c8y-empty-state text-left\" *ngIf=\"!configSnapshot?.binary && showBinary()\">\n  <h1 [c8yIcon]=\"'file-image-o'\"></h1>\n  <p>\n    <strong translate>No preview available.</strong>\n    <br />\n    <small *ngIf=\"configSnapshot?.binary !== ''; else emptyFile\" translate>\n      The file is not available.\n    </small>\n    <ng-template #emptyFile>\n      <small translate>The file is empty.</small>\n    </ng-template>\n  </p>\n</div>\n<div *ngIf=\"configSnapshot?.binary && showBinary()\" class=\"flex-grow d-flex d-col\">\n  <c8y-source-code-preview\n    [text]=\"configSnapshot.binary\"\n    [isDisabled]=\"true\"\n    class=\"d-contents\"\n  ></c8y-source-code-preview>\n  <div *ngIf=\"canSaveSnapshot\" class=\"p-t-16\">\n    <button\n      title=\"{{ 'Download' | translate }}\"\n      type=\"button\"\n      class=\"btn btn-primary btn-sm pull-right m-l-8\"\n      (click)=\"download()\"\n    >\n      {{ 'Download' | translate }}\n    </button>\n    <button\n      title=\"{{ 'Save to repository' | translate }}\"\n      *ngIf=\"hasPermission()\"\n      type=\"button\"\n      class=\"btn btn-default btn-sm pull-right\"\n      (click)=\"saveToRepository()\"\n    >\n      {{ 'Save to repository' | translate }}\n    </button>\n  </div>\n</div>\n<div *ngIf=\"showOperation()\">\n  <c8y-operation-details [operation]=\"operation\"></c8y-operation-details>\n</div>\n" }]
        }], ctorParameters: () => [{ type: DeviceConfigurationService }, { type: i2.OperationRealtimeService }, { type: i3$1.BsModalService }, { type: i4.UserService }, { type: i2.AppStateService }, { type: i3.RepositoryService }, { type: i4.OperationService }, { type: i2.AlertService }], propDecorators: { device: [{
                type: Input
            }], configurationType: [{
                type: Input
            }], configSnapshot: [{
                type: Input
            }], canSaveSnapshot: [{
                type: Input
            }], actionButtonText: [{
                type: Input
            }], actionButtonIcon: [{
                type: Input
            }], isLegacy: [{
                type: Input
            }], operationToTrigger: [{
                type: Input
            }] } });

class DeviceConfigurationListComponent {
    constructor() {
        this.configSelected = new EventEmitter();
        this.filterTerm = '';
    }
    showConfigurationTypePreview(config) {
        this.selectedConfig = config;
        this.configSelected.emit(config);
    }
    updatePipe(filterTerm) {
        this.filterTerm = filterTerm;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceConfigurationListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DeviceConfigurationListComponent, isStandalone: false, selector: "c8y-device-configuration-list", inputs: { items: "items", itemIcon: "itemIcon", emptyState: "emptyState", isFilterEnabled: "isFilterEnabled" }, outputs: { configSelected: "configSelected" }, ngImport: i0, template: "<div class=\"p-l-16 m-b-8\" *ngIf=\"isFilterEnabled\">\n  <c8y-filter [icon]=\"'search'\" (onSearch)=\"updatePipe($event)\"></c8y-filter>\n</div>\n\n<!-- EMPTY STATE -->\n<div class=\"c8y-empty-state text-left\" *ngIf=\"items?.length === 0\">\n  <h1 [c8yIcon]=\"emptyState.icon\"></h1>\n  <p>\n    <strong>{{ emptyState.title | translate }}</strong>\n    <br />\n    <small>{{ emptyState.text | translate }}</small>\n  </p>\n</div>\n\n<!-- CONFIGURATIONS AVAILABLE -->\n<div class=\"c8y-nav-stacked\">\n  <button\n    type=\"button\"\n    class=\"c8y-stacked-item d-flex\"\n    [class.active]=\"config === selectedConfig\"\n    *ngFor=\"let config of items | configurationFilterPipe: filterTerm\"\n    (click)=\"showConfigurationTypePreview(config)\"\n  >\n    <div class=\"list-item-icon\">\n      <i [c8yIcon]=\"itemIcon\"></i>\n    </div>\n    <div class=\"list-item-body text-truncate\">\n      <div class=\"d-flex\">\n        <span class=\"text-truncate\" title=\"{{ config.name }}\">{{ config.name }}</span>\n        <span class=\"text-label-small m-l-auto m-t-auto m-b-auto\">{{ config.deviceType }}</span>\n      </div>\n    </div>\n  </button>\n</div>\n\n<!-- for Carlos: config.configurationType to differentiate whether a config matches configuration type. -->\n", dependencies: [{ kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: i2.FilterInputComponent, selector: "c8y-filter", inputs: ["icon", "filterTerm"], outputs: ["onSearch"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: ConfigurationFilterPipe, name: "configurationFilterPipe" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceConfigurationListComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-device-configuration-list', standalone: false, template: "<div class=\"p-l-16 m-b-8\" *ngIf=\"isFilterEnabled\">\n  <c8y-filter [icon]=\"'search'\" (onSearch)=\"updatePipe($event)\"></c8y-filter>\n</div>\n\n<!-- EMPTY STATE -->\n<div class=\"c8y-empty-state text-left\" *ngIf=\"items?.length === 0\">\n  <h1 [c8yIcon]=\"emptyState.icon\"></h1>\n  <p>\n    <strong>{{ emptyState.title | translate }}</strong>\n    <br />\n    <small>{{ emptyState.text | translate }}</small>\n  </p>\n</div>\n\n<!-- CONFIGURATIONS AVAILABLE -->\n<div class=\"c8y-nav-stacked\">\n  <button\n    type=\"button\"\n    class=\"c8y-stacked-item d-flex\"\n    [class.active]=\"config === selectedConfig\"\n    *ngFor=\"let config of items | configurationFilterPipe: filterTerm\"\n    (click)=\"showConfigurationTypePreview(config)\"\n  >\n    <div class=\"list-item-icon\">\n      <i [c8yIcon]=\"itemIcon\"></i>\n    </div>\n    <div class=\"list-item-body text-truncate\">\n      <div class=\"d-flex\">\n        <span class=\"text-truncate\" title=\"{{ config.name }}\">{{ config.name }}</span>\n        <span class=\"text-label-small m-l-auto m-t-auto m-b-auto\">{{ config.deviceType }}</span>\n      </div>\n    </div>\n  </button>\n</div>\n\n<!-- for Carlos: config.configurationType to differentiate whether a config matches configuration type. -->\n" }]
        }], propDecorators: { items: [{
                type: Input
            }], itemIcon: [{
                type: Input
            }], emptyState: [{
                type: Input
            }], isFilterEnabled: [{
                type: Input
            }], configSelected: [{
                type: Output
            }] } });

class DeviceConfigurationComponent {
    constructor(route, deviceConfigurationService, realtime, repositoryService) {
        this.route = route;
        this.deviceConfigurationService = deviceConfigurationService;
        this.realtime = realtime;
        this.repositoryService = repositoryService;
        this.supportedConfigurations = [];
        this.showBinaryBasedConfig = false;
        this.configSnapshot = {};
        this.reloading = false;
        this.deviceConfigurationService.configurationsUpdated.subscribe(repositorySnapsOnly => {
            this.updateSnapshots(repositorySnapsOnly);
        });
    }
    ngOnInit() {
        this.device = this.route.snapshot.parent.data.contextData;
        if (this.device.c8y_SupportedConfigurations) {
            this.supportedConfigurations = this.device.c8y_SupportedConfigurations.map(item => ({
                name: item
            }));
        }
        if (this.deviceConfigurationService.hasAnySupportedOperation(this.device, [
            DeviceConfigurationOperation.DOWNLOAD_CONFIG,
            DeviceConfigurationOperation.UPLOAD_CONFIG
        ])) {
            this.supportedConfigurations.push({
                name: gettext('Legacy configuration snapshot'),
                isLegacy: true
            });
        }
        if (this.supportedConfigurations.length > 0) {
            this.showBinaryBasedConfig = true;
        }
        this.repositorySnapshotsEmptyState = {
            icon: 'gears',
            title: gettext('No configurations available.'),
            text: gettext('Add configuration to configuration repository')
        };
        this.showTextBasedConfig =
            this.deviceConfigurationService.hasAnySupportedOperation(this.device, [
                DeviceConfigurationOperation.CONFIG,
                DeviceConfigurationOperation.SEND_CONFIG
            ]) || has(this.device, 'c8y_Configuration');
    }
    async onConfigTypeSelected(config) {
        this.configurationType = config.name;
        this.isLegacy = config.isLegacy;
        this.updateSnapshots();
    }
    async onRepositoryConfigSelected(config) {
        this.repositorySnapshot = {
            id: config.id,
            time: config.creationTime,
            name: config.name,
            binaryUrl: config.url,
            deviceType: config.deviceType,
            configurationType: config.configurationType
        };
        if (config.url) {
            try {
                const binary = await this.repositoryService.getBinaryFile(config.url, {
                    allowExternal: false
                });
                if (binary) {
                    this.repositorySnapshot.binary = await binary.text();
                }
            }
            catch (ex) {
                // do nothing
            }
        }
    }
    async updateSnapshots(repositorySnapsOnly) {
        this.reloading = true;
        this.repositorySnapshot = undefined;
        this.repositorySnapshots = await this.repositoryService.getSnapshotsFromRepository(this.device, this.configurationType);
        if (!repositorySnapsOnly) {
            this.configSnapshot = this.isLegacy
                ? await this.repositoryService.getLegacyConfigSnapshot(this.device)
                : await this.repositoryService.getConfigSnapshot(this.device, this.configurationType);
        }
        if (this.showTextBasedConfig) {
            await this.textBasedConfigurationComponent.load();
        }
        this.reloading = false;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceConfigurationComponent, deps: [{ token: i1.ActivatedRoute }, { token: DeviceConfigurationService }, { token: i4.Realtime }, { token: i3.RepositoryService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DeviceConfigurationComponent, isStandalone: false, selector: "c8y-device-configuration", viewQueries: [{ propertyName: "textBasedConfigurationComponent", first: true, predicate: TextBasedConfigurationComponent, descendants: true }], ngImport: i0, template: "<c8y-action-bar-item [placement]=\"'right'\">\n  <button class=\"btn btn-link\" title=\"{{ 'Reload' | translate }}\" (click)=\"updateSnapshots()\">\n    <i c8yIcon=\"refresh\" [ngClass]=\"{ 'icon-spin': reloading }\"></i>\n    {{ 'Reload' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<div class=\"card content-fullpage card-has-tabs\">\n  <tabset>\n    <div class=\"card-header separator\" *ngIf=\"showBinaryBasedConfig && !showTextBasedConfig\">\n      <div class=\"card-title\">{{ 'Configurations' | translate }}</div>\n    </div>\n    <div class=\"card-header separator\" *ngIf=\"!showBinaryBasedConfig && showTextBasedConfig\">\n      <div class=\"card-title\">{{ 'Text-based configuration' | translate }}</div>\n    </div>\n    <tab heading=\"{{ 'Configurations' | translate }}\" *ngIf=\"showBinaryBasedConfig\">\n      <div class=\"card--grid card grid__col--4-8--md grid__row--6-6--md m-b-0\">\n        <!-- DEVICE SUPPORTED CONFIGURATIONS -->\n        <div class=\"card--grid__inner-scroll bg-level-1\">\n          <div class=\"p-l-16 p-r-16\">\n            <h5 class=\"legend form-block\">\n              <span translate>Device-supported configurations</span>\n            </h5>\n          </div>\n          <c8y-device-configuration-list\n            [items]=\"supportedConfigurations\"\n            [itemIcon]=\"'gears'\"\n            (configSelected)=\"onConfigTypeSelected($event)\"\n          ></c8y-device-configuration-list>\n        </div>\n\n        <!-- CONFIGURATION PREVIEW -->\n        <div class=\"card--grid__inner-scroll d-flex d-col flex-grow\">\n          <div class=\"card-block d-flex d-col flex-grow\">\n            <h5 class=\"legend form-block\"><span translate>Preview</span></h5>\n\n            <!-- EMPTY STATE -->\n\n            <c8y-ui-empty-state\n              *ngIf=\"!configurationType\"\n              [icon]=\"'file-text'\"\n              [title]=\"'No configuration selected.' | translate\"\n              [subtitle]=\"'Select a configuration to preview.' | translate\"\n              [horizontal]=\"true\"\n            ></c8y-ui-empty-state>\n\n            <!-- PREVIEW AVAILABLE STATE -->\n            <c8y-device-configuration-preview\n              *ngIf=\"configurationType\"\n              [device]=\"device\"\n              [configurationType]=\"configurationType\"\n              [configSnapshot]=\"configSnapshot\"\n              [canSaveSnapshot]=\"true\"\n              [operationToTrigger]=\"'c8y_UploadConfigFile'\"\n              [actionButtonText]=\"'Get snapshot from device' | translate\"\n              [actionButtonIcon]=\"'download'\"\n              [isLegacy]=\"isLegacy\"\n              class=\"d-flex d-col flex-grow\"\n            ></c8y-device-configuration-preview>\n          </div>\n        </div>\n\n        <!-- AVAILABLE SUPPORTED CONFIGURATIONS -->\n        <div class=\"card--grid__inner-scroll bg-level-1\">\n          <div class=\"p-l-16 p-r-16\">\n            <h5 class=\"legend form-block\" translate>Available supported configurations</h5>\n          </div>\n\n          <!-- EMPTY STATE -->\n\n          <c8y-ui-empty-state\n            *ngIf=\"!configurationType\"\n            [icon]=\"'gears'\"\n            [title]=\"'No selection.' | translate\"\n            [subtitle]=\"\n              'Select a configuration from the device-supported configuration list.' | translate\n            \"\n            [horizontal]=\"true\"\n          ></c8y-ui-empty-state>\n\n          <div class=\"p-r-16\" *ngIf=\"configurationType\">\n            <c8y-device-configuration-list\n              [items]=\"repositorySnapshots\"\n              [itemIcon]=\"'file-text'\"\n              [emptyState]=\"repositorySnapshotsEmptyState\"\n              [isFilterEnabled]=\"true\"\n              (configSelected)=\"onRepositoryConfigSelected($event)\"\n            ></c8y-device-configuration-list>\n          </div>\n        </div>\n\n        <!-- CONFIGURATION PREVIEW -->\n        <div class=\"card--grid__inner-scroll d-flex d-col flex-grow\">\n          <div class=\"card-block flex-grow d-flex d-col\">\n            <h5 class=\"legend form-block\" translate>Preview</h5>\n\n            <!-- EMPTY STATE -->\n            <c8y-ui-empty-state\n              *ngIf=\"!repositorySnapshot\"\n              [icon]=\"'file-text'\"\n              [title]=\"'No configuration selected.' | translate\"\n              [subtitle]=\"'Select a configuration to preview.' | translate\"\n              [horizontal]=\"true\"\n            ></c8y-ui-empty-state>\n\n            <!-- CONFIGURATION SELECTED STATE -->\n            <c8y-device-configuration-preview\n              *ngIf=\"repositorySnapshot\"\n              [device]=\"device\"\n              [configurationType]=\"configurationType\"\n              [configSnapshot]=\"repositorySnapshot\"\n              [operationToTrigger]=\"'c8y_DownloadConfigFile'\"\n              [actionButtonText]=\"'Send configuration to device' | translate\"\n              [actionButtonIcon]=\"'upload'\"\n              [isLegacy]=\"isLegacy\"\n              class=\"d-flex d-col flex-grow\"\n            ></c8y-device-configuration-preview>\n          </div>\n        </div>\n      </div>\n    </tab>\n    <tab heading=\"{{ 'Text-based configuration' | translate }}\" *ngIf=\"showTextBasedConfig\">\n      <c8y-text-based-configuration></c8y-text-based-configuration>\n    </tab>\n  </tabset>\n</div>\n", dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.TabsetAriaDirective, selector: "tabset" }, { kind: "directive", type: i7.TabDirective, selector: "tab, [tab]", inputs: ["heading", "id", "disabled", "removable", "customClass", "active"], outputs: ["selectTab", "deselect", "removed"], exportAs: ["tab"] }, { kind: "component", type: i7.TabsetComponent, selector: "tabset", inputs: ["vertical", "justified", "type"] }, { kind: "component", type: DeviceConfigurationListComponent, selector: "c8y-device-configuration-list", inputs: ["items", "itemIcon", "emptyState", "isFilterEnabled"], outputs: ["configSelected"] }, { kind: "component", type: ConfigurationPreviewComponent, selector: "c8y-device-configuration-preview", inputs: ["device", "configurationType", "configSnapshot", "canSaveSnapshot", "actionButtonText", "actionButtonIcon", "isLegacy", "operationToTrigger"] }, { kind: "component", type: TextBasedConfigurationComponent, selector: "c8y-text-based-configuration" }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DeviceConfigurationComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-device-configuration', standalone: false, template: "<c8y-action-bar-item [placement]=\"'right'\">\n  <button class=\"btn btn-link\" title=\"{{ 'Reload' | translate }}\" (click)=\"updateSnapshots()\">\n    <i c8yIcon=\"refresh\" [ngClass]=\"{ 'icon-spin': reloading }\"></i>\n    {{ 'Reload' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<div class=\"card content-fullpage card-has-tabs\">\n  <tabset>\n    <div class=\"card-header separator\" *ngIf=\"showBinaryBasedConfig && !showTextBasedConfig\">\n      <div class=\"card-title\">{{ 'Configurations' | translate }}</div>\n    </div>\n    <div class=\"card-header separator\" *ngIf=\"!showBinaryBasedConfig && showTextBasedConfig\">\n      <div class=\"card-title\">{{ 'Text-based configuration' | translate }}</div>\n    </div>\n    <tab heading=\"{{ 'Configurations' | translate }}\" *ngIf=\"showBinaryBasedConfig\">\n      <div class=\"card--grid card grid__col--4-8--md grid__row--6-6--md m-b-0\">\n        <!-- DEVICE SUPPORTED CONFIGURATIONS -->\n        <div class=\"card--grid__inner-scroll bg-level-1\">\n          <div class=\"p-l-16 p-r-16\">\n            <h5 class=\"legend form-block\">\n              <span translate>Device-supported configurations</span>\n            </h5>\n          </div>\n          <c8y-device-configuration-list\n            [items]=\"supportedConfigurations\"\n            [itemIcon]=\"'gears'\"\n            (configSelected)=\"onConfigTypeSelected($event)\"\n          ></c8y-device-configuration-list>\n        </div>\n\n        <!-- CONFIGURATION PREVIEW -->\n        <div class=\"card--grid__inner-scroll d-flex d-col flex-grow\">\n          <div class=\"card-block d-flex d-col flex-grow\">\n            <h5 class=\"legend form-block\"><span translate>Preview</span></h5>\n\n            <!-- EMPTY STATE -->\n\n            <c8y-ui-empty-state\n              *ngIf=\"!configurationType\"\n              [icon]=\"'file-text'\"\n              [title]=\"'No configuration selected.' | translate\"\n              [subtitle]=\"'Select a configuration to preview.' | translate\"\n              [horizontal]=\"true\"\n            ></c8y-ui-empty-state>\n\n            <!-- PREVIEW AVAILABLE STATE -->\n            <c8y-device-configuration-preview\n              *ngIf=\"configurationType\"\n              [device]=\"device\"\n              [configurationType]=\"configurationType\"\n              [configSnapshot]=\"configSnapshot\"\n              [canSaveSnapshot]=\"true\"\n              [operationToTrigger]=\"'c8y_UploadConfigFile'\"\n              [actionButtonText]=\"'Get snapshot from device' | translate\"\n              [actionButtonIcon]=\"'download'\"\n              [isLegacy]=\"isLegacy\"\n              class=\"d-flex d-col flex-grow\"\n            ></c8y-device-configuration-preview>\n          </div>\n        </div>\n\n        <!-- AVAILABLE SUPPORTED CONFIGURATIONS -->\n        <div class=\"card--grid__inner-scroll bg-level-1\">\n          <div class=\"p-l-16 p-r-16\">\n            <h5 class=\"legend form-block\" translate>Available supported configurations</h5>\n          </div>\n\n          <!-- EMPTY STATE -->\n\n          <c8y-ui-empty-state\n            *ngIf=\"!configurationType\"\n            [icon]=\"'gears'\"\n            [title]=\"'No selection.' | translate\"\n            [subtitle]=\"\n              'Select a configuration from the device-supported configuration list.' | translate\n            \"\n            [horizontal]=\"true\"\n          ></c8y-ui-empty-state>\n\n          <div class=\"p-r-16\" *ngIf=\"configurationType\">\n            <c8y-device-configuration-list\n              [items]=\"repositorySnapshots\"\n              [itemIcon]=\"'file-text'\"\n              [emptyState]=\"repositorySnapshotsEmptyState\"\n              [isFilterEnabled]=\"true\"\n              (configSelected)=\"onRepositoryConfigSelected($event)\"\n            ></c8y-device-configuration-list>\n          </div>\n        </div>\n\n        <!-- CONFIGURATION PREVIEW -->\n        <div class=\"card--grid__inner-scroll d-flex d-col flex-grow\">\n          <div class=\"card-block flex-grow d-flex d-col\">\n            <h5 class=\"legend form-block\" translate>Preview</h5>\n\n            <!-- EMPTY STATE -->\n            <c8y-ui-empty-state\n              *ngIf=\"!repositorySnapshot\"\n              [icon]=\"'file-text'\"\n              [title]=\"'No configuration selected.' | translate\"\n              [subtitle]=\"'Select a configuration to preview.' | translate\"\n              [horizontal]=\"true\"\n            ></c8y-ui-empty-state>\n\n            <!-- CONFIGURATION SELECTED STATE -->\n            <c8y-device-configuration-preview\n              *ngIf=\"repositorySnapshot\"\n              [device]=\"device\"\n              [configurationType]=\"configurationType\"\n              [configSnapshot]=\"repositorySnapshot\"\n              [operationToTrigger]=\"'c8y_DownloadConfigFile'\"\n              [actionButtonText]=\"'Send configuration to device' | translate\"\n              [actionButtonIcon]=\"'upload'\"\n              [isLegacy]=\"isLegacy\"\n              class=\"d-flex d-col flex-grow\"\n            ></c8y-device-configuration-preview>\n          </div>\n        </div>\n      </div>\n    </tab>\n    <tab heading=\"{{ 'Text-based configuration' | translate }}\" *ngIf=\"showTextBasedConfig\">\n      <c8y-text-based-configuration></c8y-text-based-configuration>\n    </tab>\n  </tabset>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: DeviceConfigurationService }, { type: i4.Realtime }, { type: i3.RepositoryService }], propDecorators: { textBasedConfigurationComponent: [{
                type: ViewChild,
                args: [TextBasedConfigurationComponent]
            }] } });

class ConfigurationRepositoryDeviceTabModule {
    static forRoot() {
        return {
            ngModule: ConfigurationRepositoryDeviceTabModule,
            providers: [
                DeviceConfigurationGuard,
                hookRoute({
                    context: ViewContext.Device,
                    path: 'device-configuration',
                    component: DeviceConfigurationComponent,
                    label: gettext('Configuration'),
                    icon: 'gears',
                    priority: 600,
                    canActivate: [DeviceConfigurationGuard]
                })
            ]
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryDeviceTabModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryDeviceTabModule, declarations: [DeviceConfigurationComponent,
            DeviceConfigurationListComponent,
            ConfigurationPreviewComponent,
            ConfigurationFilterPipe,
            SaveToRepositoryComponent,
            SourceCodePreviewComponent,
            TextBasedConfigurationComponent], imports: [CommonModule,
            CoreModule,
            SharedRepositoryModule,
            OperationDetailsModule, i7.TabsModule] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryDeviceTabModule, providers: [DeviceConfigurationService], imports: [CommonModule,
            CoreModule,
            SharedRepositoryModule,
            OperationDetailsModule,
            TabsModule.forRoot()] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryDeviceTabModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CommonModule,
                        CoreModule,
                        SharedRepositoryModule,
                        OperationDetailsModule,
                        TabsModule.forRoot()
                    ],
                    declarations: [
                        DeviceConfigurationComponent,
                        DeviceConfigurationListComponent,
                        ConfigurationPreviewComponent,
                        ConfigurationFilterPipe,
                        SaveToRepositoryComponent,
                        SourceCodePreviewComponent,
                        TextBasedConfigurationComponent
                    ],
                    providers: [DeviceConfigurationService]
                }]
        }] });

class ConfigurationDetailComponent {
    constructor(repositoryService, bsModalRef, alert) {
        this.repositoryService = repositoryService;
        this.bsModalRef = bsModalRef;
        this.alert = alert;
        this.binary = {
            file: undefined,
            url: undefined
        };
        this.pattern = '';
        this.mo = {};
        this.saving = false;
        this.uploadChoice = 'uploadBinary';
        this.textForConfigurationUrlPopover = gettext(`Path for binaries can vary depending on device agent implementation, for example:
    /configuration/binaries/configuration1.bin
    https://configuration/binary/123
    ftp://configuration/binary/123.tar.gz
    Configurations with external URLs only work with the configuration typed devices (file-based configuration), not with devices with a legacy configuration.
  `);
        this.result = new Promise((resolve, reject) => {
            this._save = resolve;
            this._cancel = reject;
        });
        this.ValidationPattern = ValidationPattern;
    }
    async ngOnInit() {
        this.configs = await this.repositoryService.listRepositoryEntries(RepositoryType.CONFIGURATION);
        if (this.mo) {
            this.uploadChoice = this.binary.file ? 'uploadBinary' : 'uploadUrl';
            this.existingBinary = this.binary.file;
            this.configurationTypeMO = this.mo;
        }
        this.setPipe('');
        this.submitButtonTitle = this.mo.id
            ? gettext('Update configuration')
            : gettext('Add configuration');
    }
    cancel() {
        this.bsModalRef.hide();
        this._cancel();
    }
    setPipe(filterStr) {
        this.pattern = filterStr;
        this.filterPipe = pipe(map(data => uniqBy(data, 'configurationType')), map(data => {
            return data.filter(mo => mo.configurationType &&
                mo.configurationType.toLowerCase().indexOf(filterStr.toLowerCase()) > -1);
        }));
    }
    onFile(dropped) {
        this.configurationForm.form.markAsDirty();
        if (!isUndefined(dropped.url)) {
            this.binary = {
                url: dropped.url
            };
            return;
        }
        else if (dropped.droppedFiles) {
            this.binary = {
                file: dropped.droppedFiles[0].file
            };
            return;
        }
        else {
            this.binary = {
                file: undefined,
                url: undefined
            };
        }
    }
    async save() {
        try {
            this.saving = true;
            const { version, description, binary, deviceType } = this;
            if (this.existingBinary === this.binary.file) {
                binary.file = undefined;
            }
            await this.repositoryService.create({
                version,
                description,
                binary,
                deviceType,
                configurationType: this.configurationTypeMO?.configurationType
            }, RepositoryType.CONFIGURATION, this.mo);
            this.alert.success(this.mo.id ? gettext('Configuration updated.') : gettext('Configuration created.'));
            this.bsModalRef.hide();
            this._save();
        }
        catch (ex) {
            this.alert.addServerFailure(ex);
            this._cancel();
        }
        finally {
            this.saving = false;
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationDetailComponent, deps: [{ token: i3.RepositoryService }, { token: i3$1.BsModalRef }, { token: i2.AlertService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ConfigurationDetailComponent, isStandalone: false, selector: "c8y-configuration-detail", viewQueries: [{ propertyName: "configurationForm", first: true, predicate: ["configurationForm"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"viewport-modal\">\n  <div\n    class=\"modal-header dialog-header\"\n    id=\"configurationModalTitle\"\n  >\n    <i [c8yIcon]=\"'cogs'\"></i>\n    <h4\n      id=\"modal-title\"\n      translate\n      *ngIf=\"mo.id\"\n    >\n      Update configuration\n    </h4>\n    <h4\n      id=\"modal-title\"\n      translate\n      *ngIf=\"!mo.id\"\n    >\n      Add configuration\n    </h4>\n  </div>\n\n  <form\n    class=\"d-contents\"\n    #configurationForm=\"ngForm\"\n    (ngSubmit)=\"configurationForm.form.valid && save()\"\n  >\n    <div\n      class=\"modal-inner-scroll\"\n      id=\"modal-body\"\n    >\n      <div\n        class=\"modal-body\"\n        id=\"configurationModalDescription\"\n      >\n        <c8y-form-group>\n          <label translate>Name</label>\n          <input\n            class=\"form-control\"\n            placeholder=\"{{ 'e.g.' | translate }} hosts\"\n            name=\"version\"\n            type=\"text\"\n            autocomplete=\"off\"\n            required\n            maxlength=\"254\"\n            [(ngModel)]=\"version\"\n            [pattern]=\"ValidationPattern.rules.noWhiteSpaceOnly.pattern\"\n          />\n        </c8y-form-group>\n\n        <c8y-form-group>\n          <label translate>Device type</label>\n          <input\n            class=\"form-control\"\n            placeholder=\"{{ 'e.g.' | translate }} c8y_Linux\"\n            name=\"deviceType\"\n            type=\"text\"\n            autocomplete=\"off\"\n            maxlength=\"254\"\n            [(ngModel)]=\"deviceType\"\n            [pattern]=\"ValidationPattern.rules.noWhiteSpaceOnly.pattern\"\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. Host configuration' | translate }} c8y_Linux\"\n            name=\"description\"\n            type=\"text\"\n            autocomplete=\"off\"\n            maxlength=\"254\"\n            [(ngModel)]=\"description\"\n            [pattern]=\"ValidationPattern.rules.noWhiteSpaceOnly.pattern\"\n          />\n        </c8y-form-group>\n\n        <c8y-form-group>\n          <label translate>Configuration type</label>\n          <c8y-typeahead\n            placeholder=\"{{ 'e.g.' | translate }} ssh\"\n            name=\"confType\"\n            [(ngModel)]=\"configurationTypeMO\"\n            maxlength=\"254\"\n            (onSearch)=\"setPipe($event)\"\n            displayProperty=\"configurationType\"\n          >\n            <c8y-li\n              class=\"p-l-8 p-r-8 c8y-list__item--link\"\n              *c8yFor=\"let config of configs; pipe: filterPipe; notFound: notFoundTemplate\"\n              (click)=\"configurationTypeMO = config; setPipe('')\"\n              [active]=\"configurationTypeMO === config\"\n            >\n              <c8y-highlight\n                [text]=\"config.configurationType || '--'\"\n                [pattern]=\"pattern\"\n              ></c8y-highlight>\n            </c8y-li>\n            <ng-template #notFoundTemplate>\n              <c8y-li\n                class=\"bg-level-2 p-8\"\n                *ngIf=\"pattern.length > 0\"\n              >\n                <span translate>No match found.</span>\n                <button\n                  class=\"btn btn-primary btn-xs m-l-8\"\n                  title=\"{{ 'Add new`configuration type`' | translate }}\"\n                  type=\"button\"\n                  translate\n                >\n                  Add new`configuration type`\n                </button>\n              </c8y-li>\n            </ng-template>\n          </c8y-typeahead>\n        </c8y-form-group>\n\n        <c8y-form-group>\n          <div\n            class=\"legend form-block m-t-40\"\n            translate\n          >\n            Configuration file\n          </div>\n          <c8y-file-picker\n            [maxAllowedFiles]=\"1\"\n            (onFilesPicked)=\"onFile($event)\"\n            [uploadChoice]=\"uploadChoice\"\n            [fileUrl]=\"binary.url\"\n            [fileBinary]=\"binary.file\"\n            [fileUrlPopover]=\"textForConfigurationUrlPopover\"\n          ></c8y-file-picker>\n        </c8y-form-group>\n      </div>\n    </div>\n\n    <div class=\"modal-footer\">\n      <button\n        class=\"btn btn-default\"\n        title=\"{{ 'Cancel' | translate }}\"\n        type=\"button\"\n        (click)=\"cancel()\"\n        [disabled]=\"saving\"\n      >\n        <span translate>Cancel</span>\n      </button>\n      <button\n        class=\"btn btn-primary\"\n        title=\"{{ submitButtonTitle | translate }}\"\n        type=\"submit\"\n        [ngClass]=\"{ 'btn-pending': saving }\"\n        [disabled]=\"\n          !configurationForm.valid ||\n          configurationForm.pristine ||\n          (!binary?.url?.trim() && !binary?.file) ||\n          saving\n        \"\n      >\n        {{ submitButtonTitle | translate }}\n      </button>\n    </div>\n  </form>\n</div>\n", dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: i2.HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "component", type: i2.TypeaheadComponent, selector: "c8y-typeahead", inputs: ["required", "maxlength", "disabled", "allowFreeEntries", "placeholder", "displayProperty", "icon", "name", "autoClose", "hideNew", "container", "selected", "highlightFirstItem"], outputs: ["onSearch", "onIconClick"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i5.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i2.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i2.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "component", type: i2.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i2.FilePickerComponent, selector: "c8y-file-picker", inputs: ["maxAllowedFiles", "uploadChoice", "allowedUploadChoices", "fileUrl", "fileBinary", "config", "filePickerIndex", "fileUrlPopover"], outputs: ["onFilesPicked"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationDetailComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-configuration-detail', standalone: false, template: "<div class=\"viewport-modal\">\n  <div\n    class=\"modal-header dialog-header\"\n    id=\"configurationModalTitle\"\n  >\n    <i [c8yIcon]=\"'cogs'\"></i>\n    <h4\n      id=\"modal-title\"\n      translate\n      *ngIf=\"mo.id\"\n    >\n      Update configuration\n    </h4>\n    <h4\n      id=\"modal-title\"\n      translate\n      *ngIf=\"!mo.id\"\n    >\n      Add configuration\n    </h4>\n  </div>\n\n  <form\n    class=\"d-contents\"\n    #configurationForm=\"ngForm\"\n    (ngSubmit)=\"configurationForm.form.valid && save()\"\n  >\n    <div\n      class=\"modal-inner-scroll\"\n      id=\"modal-body\"\n    >\n      <div\n        class=\"modal-body\"\n        id=\"configurationModalDescription\"\n      >\n        <c8y-form-group>\n          <label translate>Name</label>\n          <input\n            class=\"form-control\"\n            placeholder=\"{{ 'e.g.' | translate }} hosts\"\n            name=\"version\"\n            type=\"text\"\n            autocomplete=\"off\"\n            required\n            maxlength=\"254\"\n            [(ngModel)]=\"version\"\n            [pattern]=\"ValidationPattern.rules.noWhiteSpaceOnly.pattern\"\n          />\n        </c8y-form-group>\n\n        <c8y-form-group>\n          <label translate>Device type</label>\n          <input\n            class=\"form-control\"\n            placeholder=\"{{ 'e.g.' | translate }} c8y_Linux\"\n            name=\"deviceType\"\n            type=\"text\"\n            autocomplete=\"off\"\n            maxlength=\"254\"\n            [(ngModel)]=\"deviceType\"\n            [pattern]=\"ValidationPattern.rules.noWhiteSpaceOnly.pattern\"\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. Host configuration' | translate }} c8y_Linux\"\n            name=\"description\"\n            type=\"text\"\n            autocomplete=\"off\"\n            maxlength=\"254\"\n            [(ngModel)]=\"description\"\n            [pattern]=\"ValidationPattern.rules.noWhiteSpaceOnly.pattern\"\n          />\n        </c8y-form-group>\n\n        <c8y-form-group>\n          <label translate>Configuration type</label>\n          <c8y-typeahead\n            placeholder=\"{{ 'e.g.' | translate }} ssh\"\n            name=\"confType\"\n            [(ngModel)]=\"configurationTypeMO\"\n            maxlength=\"254\"\n            (onSearch)=\"setPipe($event)\"\n            displayProperty=\"configurationType\"\n          >\n            <c8y-li\n              class=\"p-l-8 p-r-8 c8y-list__item--link\"\n              *c8yFor=\"let config of configs; pipe: filterPipe; notFound: notFoundTemplate\"\n              (click)=\"configurationTypeMO = config; setPipe('')\"\n              [active]=\"configurationTypeMO === config\"\n            >\n              <c8y-highlight\n                [text]=\"config.configurationType || '--'\"\n                [pattern]=\"pattern\"\n              ></c8y-highlight>\n            </c8y-li>\n            <ng-template #notFoundTemplate>\n              <c8y-li\n                class=\"bg-level-2 p-8\"\n                *ngIf=\"pattern.length > 0\"\n              >\n                <span translate>No match found.</span>\n                <button\n                  class=\"btn btn-primary btn-xs m-l-8\"\n                  title=\"{{ 'Add new`configuration type`' | translate }}\"\n                  type=\"button\"\n                  translate\n                >\n                  Add new`configuration type`\n                </button>\n              </c8y-li>\n            </ng-template>\n          </c8y-typeahead>\n        </c8y-form-group>\n\n        <c8y-form-group>\n          <div\n            class=\"legend form-block m-t-40\"\n            translate\n          >\n            Configuration file\n          </div>\n          <c8y-file-picker\n            [maxAllowedFiles]=\"1\"\n            (onFilesPicked)=\"onFile($event)\"\n            [uploadChoice]=\"uploadChoice\"\n            [fileUrl]=\"binary.url\"\n            [fileBinary]=\"binary.file\"\n            [fileUrlPopover]=\"textForConfigurationUrlPopover\"\n          ></c8y-file-picker>\n        </c8y-form-group>\n      </div>\n    </div>\n\n    <div class=\"modal-footer\">\n      <button\n        class=\"btn btn-default\"\n        title=\"{{ 'Cancel' | translate }}\"\n        type=\"button\"\n        (click)=\"cancel()\"\n        [disabled]=\"saving\"\n      >\n        <span translate>Cancel</span>\n      </button>\n      <button\n        class=\"btn btn-primary\"\n        title=\"{{ submitButtonTitle | translate }}\"\n        type=\"submit\"\n        [ngClass]=\"{ 'btn-pending': saving }\"\n        [disabled]=\"\n          !configurationForm.valid ||\n          configurationForm.pristine ||\n          (!binary?.url?.trim() && !binary?.file) ||\n          saving\n        \"\n      >\n        {{ submitButtonTitle | translate }}\n      </button>\n    </div>\n  </form>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i3.RepositoryService }, { type: i3$1.BsModalRef }, { type: i2.AlertService }], propDecorators: { configurationForm: [{
                type: ViewChild,
                args: ['configurationForm', { static: true }]
            }] } });

class ConfigurationListComponent {
    constructor(alert, gridService, repositoryService, bsModalService, modalService, translateService, inventoryBinaryService) {
        this.alert = alert;
        this.gridService = gridService;
        this.repositoryService = repositoryService;
        this.bsModalService = bsModalService;
        this.modalService = modalService;
        this.translateService = translateService;
        this.inventoryBinaryService = inventoryBinaryService;
        this.refresh$ = new EventEmitter();
        this.pagination = {
            pageSize: 50,
            currentPage: 1
        };
        this.noResultsMessage = gettext('No results to display.');
        this.noDataMessage = gettext('There are no configuration snapshots defined.');
        this.noResultsSubtitle = gettext('Refine your search terms or check your spelling.');
        this.noDataSubtitle = gettext('Add a configuration snapshot first.');
        this.actionControls = [];
        this.columns = [
            new RepositoryItemNameGridColumn({
                filterLabel: gettext('Filter configurations by name'),
                placeholder: gettext('SSH'),
                callback: this.edit.bind(this)
            }),
            new DescriptionGridColumn({
                filterLabel: gettext('Filter configurations by description'),
                placeholder: gettext('SSH configuration')
            }),
            new FileGridColumn(),
            new DeviceTypeGridColumn({
                path: 'deviceType',
                filterLabel: gettext('Filter configurations by device type')
            }),
            new TypeGridColumn({
                header: gettext('Configuration type'),
                filterLabel: gettext('Filter by configuration type'),
                example: 'ssh',
                path: 'configurationType',
                repositoryType: RepositoryType.CONFIGURATION
            })
        ];
        this.sizeRequestDone = false;
        this.DELETED_SUCCESS_MSG = gettext('Configuration deleted.');
        this.serverSideDataCallback = this.onDataSourceModifier.bind(this);
    }
    ngOnInit() {
        this.actionControls.push({
            type: BuiltInActionType.Edit,
            callback: this.edit.bind(this)
        });
        this.actionControls.push({
            type: BuiltInActionType.Delete,
            callback: this.delete.bind(this)
        });
        this.actionControls.push({
            type: 'download',
            icon: 'download',
            text: gettext('Download'),
            showIf: row => this.isBinaryFile(row),
            callback: this.download.bind(this)
        });
    }
    async onDataSourceModifier(dataSourceModifier) {
        const dataRequest = this.repositoryService.listRepositoryEntries(RepositoryType.CONFIGURATION, {
            query: this.gridService.getQueryObj(dataSourceModifier.columns),
            skipDefaultOrder: true,
            params: {
                pageSize: dataSourceModifier.pagination.pageSize,
                currentPage: dataSourceModifier.pagination.currentPage,
                withTotalPages: true
            }
        });
        const filtererdSizeRequest = this.repositoryService
            .listRepositoryEntries(RepositoryType.CONFIGURATION, {
            query: this.gridService.getQueryObj(dataSourceModifier.columns),
            skipDefaultOrder: true,
            params: { pageSize: 1 }
        })
            .then(response => response?.paging?.totalPages);
        this.size$ = this.repositoryService
            .listRepositoryEntries(RepositoryType.CONFIGURATION, {
            skipDefaultOrder: true,
            params: { pageSize: 1 }
        })
            .then(response => {
            this.sizeRequestDone = true;
            return response?.paging?.totalPages;
        });
        const [dataResponse, size, filteredSize] = await Promise.all([
            dataRequest,
            this.size$,
            filtererdSizeRequest
        ]);
        const { res, data, paging } = dataResponse;
        const serverSideDataResult = {
            res,
            data,
            paging,
            filteredSize,
            size
        };
        return serverSideDataResult;
    }
    async add() {
        try {
            await this.bsModalService.show(ConfigurationDetailComponent, {
                class: 'modal-sm',
                ariaDescribedby: 'configurationModalDescription',
                ariaLabelledBy: 'configurationModalTitle',
                ignoreBackdropClick: true,
                keyboard: false
            }).content.result;
            this.refresh$.next();
        }
        catch (ex) {
            // intended empty
        }
    }
    async edit(configuration) {
        const fileBinary = await this.repositoryService.getBinaryFile(configuration.url, {
            allowExternal: false
        });
        try {
            const modal = this.bsModalService.show(ConfigurationDetailComponent, {
                class: 'modal-sm',
                ariaDescribedby: 'configurationModalDescription',
                ariaLabelledBy: 'configurationModalTitle',
                ignoreBackdropClick: true,
                keyboard: false,
                initialState: {
                    version: configuration.name,
                    deviceType: configuration.deviceType,
                    description: configuration.description,
                    binary: { file: fileBinary, url: configuration.url }
                }
            }).content;
            modal.mo = configuration;
            await modal.result;
            this.refresh$.next();
        }
        catch (ex) {
            // intended empty
        }
    }
    isBinaryFile(configuration) {
        return configuration.url
            ? !!this.inventoryBinaryService.getIdFromUrl(configuration.url)
            : false;
    }
    async download(configuration) {
        const fileBinary = await this.repositoryService.getBinaryFile(configuration.url, {
            allowExternal: false
        });
        saveAs(fileBinary);
    }
    async delete(configuration) {
        try {
            const title = gettext('Delete configuration snapshot');
            const confirmationText = gettext('You are about to delete the configuration snapshot {{ name }}.');
            const hint = gettext('This operation is irreversible.');
            const proceed = gettext('Do you want to proceed?');
            const body = [
                this.translateService.instant(confirmationText, {
                    name: configuration.name
                }),
                this.translateService.instant(hint),
                this.translateService.instant(proceed)
            ].join(' ');
            const labels = {
                ok: gettext('Delete')
            };
            await this.modalService.confirm(title, body, Status.DANGER, labels);
            await this.repositoryService.delete(configuration);
            this.alert.success(this.DELETED_SUCCESS_MSG);
            this.refresh$.next();
        }
        catch (ex) {
            if (ex) {
                this.alert.addServerFailure(ex);
            }
        }
    }
    trackByName(_index, column) {
        return column.name;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationListComponent, deps: [{ token: i2.AlertService }, { token: i2.DataGridService }, { token: i3.RepositoryService }, { token: i3$1.BsModalService }, { token: i2.ModalService }, { token: i4$1.TranslateService }, { token: i4.InventoryBinaryService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ConfigurationListComponent, isStandalone: false, selector: "c8y-configuration-list", viewQueries: [{ propertyName: "filter", first: true, predicate: FilterInputComponent, descendants: true }], ngImport: i0, template: "<c8y-title>\n  <span\n    class=\"m-r-4\"\n    translate\n  >\n    Configuration repository\n  </span>\n  <small>\n    {{ size$ | async }}\n    <span translate>snapshots</span>\n  </small>\n</c8y-title>\n\n<c8y-breadcrumb>\n  <c8y-breadcrumb-item\n    icon=\"c8y-management\"\n    label=\"{{ 'Management' | translate }}\"\n  ></c8y-breadcrumb-item>\n  <c8y-breadcrumb-item\n    icon=\"gears\"\n    label=\"{{ 'Configuration repository' | translate }}\"\n  ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Add configuration snapshot' | translate }}\"\n    type=\"button\"\n    (click)=\"add()\"\n  >\n    <i c8yIcon=\"plus-circle\"></i>\n    {{ 'Add configuration snapshot' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<c8y-help\n  src=\"/docs/device-management-application/managing-device-data/#managing-configurations\"\n></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n  <c8y-data-grid\n    [title]=\"'Configurations' | translate\"\n    [refresh]=\"refresh$\"\n    [pagination]=\"pagination\"\n    [columns]=\"columns\"\n    [actionControls]=\"actionControls\"\n    [infiniteScroll]=\"'auto'\"\n    [serverSideDataCallback]=\"serverSideDataCallback\"\n  >\n    <c8y-ui-empty-state\n      [icon]=\"stats?.size > 0 ? 'search' : 'gears'\"\n      [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n      [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\"\n      *emptyStateContext=\"let stats\"\n      [horizontal]=\"stats?.size > 0\"\n    >\n      <ng-container *ngIf=\"stats?.size === 0\">\n        <p>\n          <button\n            class=\"btn btn-primary\"\n            title=\"{{ 'Add configuration snapshot' | translate }}\"\n            type=\"button\"\n            (click)=\"add()\"\n          >\n            {{ 'Add configuration snapshot' | translate }}\n          </button>\n        </p>\n        <p c8y-guide-docs>\n          <small\n            translate\n            ngNonBindable\n          >\n            Find out more in the\n            <a\n              c8y-guide-href=\"/docs/device-management-application/managing-device-data/#managing-configurations\"\n            >\n              user documentation\n            </a>\n            .\n          </small>\n        </p>\n      </ng-container>\n    </c8y-ui-empty-state>\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</div>\n", dependencies: [{ kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i2.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i2.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i2.EmptyStateContextDirective, selector: "[emptyStateContext]" }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.ColumnDirective, selector: "c8y-column", inputs: ["name"] }, { kind: "component", type: i2.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: "component", type: i2.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: i2.GuideHrefDirective, selector: "[c8y-guide-href]", inputs: ["c8y-guide-href"] }, { kind: "component", type: i2.GuideDocsComponent, selector: "[c8y-guide-docs]" }, { kind: "component", type: i2.HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationListComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-configuration-list', standalone: false, template: "<c8y-title>\n  <span\n    class=\"m-r-4\"\n    translate\n  >\n    Configuration repository\n  </span>\n  <small>\n    {{ size$ | async }}\n    <span translate>snapshots</span>\n  </small>\n</c8y-title>\n\n<c8y-breadcrumb>\n  <c8y-breadcrumb-item\n    icon=\"c8y-management\"\n    label=\"{{ 'Management' | translate }}\"\n  ></c8y-breadcrumb-item>\n  <c8y-breadcrumb-item\n    icon=\"gears\"\n    label=\"{{ 'Configuration repository' | translate }}\"\n  ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Add configuration snapshot' | translate }}\"\n    type=\"button\"\n    (click)=\"add()\"\n  >\n    <i c8yIcon=\"plus-circle\"></i>\n    {{ 'Add configuration snapshot' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<c8y-help\n  src=\"/docs/device-management-application/managing-device-data/#managing-configurations\"\n></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n  <c8y-data-grid\n    [title]=\"'Configurations' | translate\"\n    [refresh]=\"refresh$\"\n    [pagination]=\"pagination\"\n    [columns]=\"columns\"\n    [actionControls]=\"actionControls\"\n    [infiniteScroll]=\"'auto'\"\n    [serverSideDataCallback]=\"serverSideDataCallback\"\n  >\n    <c8y-ui-empty-state\n      [icon]=\"stats?.size > 0 ? 'search' : 'gears'\"\n      [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n      [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\"\n      *emptyStateContext=\"let stats\"\n      [horizontal]=\"stats?.size > 0\"\n    >\n      <ng-container *ngIf=\"stats?.size === 0\">\n        <p>\n          <button\n            class=\"btn btn-primary\"\n            title=\"{{ 'Add configuration snapshot' | translate }}\"\n            type=\"button\"\n            (click)=\"add()\"\n          >\n            {{ 'Add configuration snapshot' | translate }}\n          </button>\n        </p>\n        <p c8y-guide-docs>\n          <small\n            translate\n            ngNonBindable\n          >\n            Find out more in the\n            <a\n              c8y-guide-href=\"/docs/device-management-application/managing-device-data/#managing-configurations\"\n            >\n              user documentation\n            </a>\n            .\n          </small>\n        </p>\n      </ng-container>\n    </c8y-ui-empty-state>\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</div>\n" }]
        }], ctorParameters: () => [{ type: i2.AlertService }, { type: i2.DataGridService }, { type: i3.RepositoryService }, { type: i3$1.BsModalService }, { type: i2.ModalService }, { type: i4$1.TranslateService }, { type: i4.InventoryBinaryService }], propDecorators: { filter: [{
                type: ViewChild,
                args: [FilterInputComponent, { static: false }]
            }] } });

class ConfigurationRepositoryNavigationFactory {
    constructor() {
        this.node = new NavigatorNode({
            label: gettext('Configuration repository'),
            path: 'configuration',
            icon: 'gears',
            parent: gettext('Management'),
            priority: 800
        });
    }
    get() {
        return this.node;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryNavigationFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryNavigationFactory }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryNavigationFactory, decorators: [{
            type: Injectable
        }], ctorParameters: () => [] });

class ConfigurationRepositoryListModule {
    static forRoot() {
        return {
            ngModule: ConfigurationRepositoryListModule,
            providers: [
                hookNavigator(ConfigurationRepositoryNavigationFactory),
                hookRoute({
                    path: 'configuration',
                    component: ConfigurationListComponent
                })
            ]
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryListModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryListModule, declarations: [ConfigurationListComponent, ConfigurationDetailComponent], imports: [CommonModule, CoreModule, SharedRepositoryModule, TooltipModule] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryListModule, imports: [CommonModule, CoreModule, SharedRepositoryModule, TooltipModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryListModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [CommonModule, CoreModule, SharedRepositoryModule, TooltipModule],
                    declarations: [ConfigurationListComponent, ConfigurationDetailComponent]
                }]
        }] });

class ConfigurationRepositoryModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryModule, imports: [CoreModule,
            FormsModule, ConfigurationRepositoryListModule, ConfigurationRepositoryDeviceTabModule] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryModule, imports: [CoreModule,
            FormsModule,
            ConfigurationRepositoryListModule.forRoot(),
            ConfigurationRepositoryDeviceTabModule.forRoot()] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfigurationRepositoryModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CoreModule,
                        FormsModule,
                        ConfigurationRepositoryListModule.forRoot(),
                        ConfigurationRepositoryDeviceTabModule.forRoot()
                    ]
                }]
        }] });

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

export { ConfigurationDetailComponent, ConfigurationFilterPipe, ConfigurationListComponent, ConfigurationPreviewComponent, ConfigurationRepositoryDeviceTabModule, ConfigurationRepositoryListModule, ConfigurationRepositoryModule, DeviceConfigurationComponent, DeviceConfigurationGuard, DeviceConfigurationListComponent, DeviceConfigurationService, SaveToRepositoryComponent, SourceCodePreviewComponent, TextBasedConfigurationComponent };
//# sourceMappingURL=c8y-ngx-components-repository-configuration.mjs.map