@c8y/ngx-components 1011.0.24 → 1011.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. package/bundles/c8y-ngx-components-repository.umd.js +36 -14
  2. package/bundles/c8y-ngx-components-repository.umd.js.map +1 -1
  3. package/bundles/c8y-ngx-components-repository.umd.min.js +1 -1
  4. package/bundles/c8y-ngx-components-repository.umd.min.js.map +1 -1
  5. package/esm2015/repository/configuration-device-tab/device-configuration.component.js +7 -2
  6. package/esm2015/repository/configuration-device-tab/device-configuration.guard.js +4 -2
  7. package/esm2015/repository/firmware-device-tab/firmware-device-tab.component.js +4 -3
  8. package/esm2015/repository/firmware-device-tab/firmware-device-tab.guard.js +4 -5
  9. package/esm2015/repository/software-device-tab/device-software-list.component.js +10 -3
  10. package/esm2015/repository/software-device-tab/installed-software.component.js +10 -2
  11. package/esm2015/repository/software-device-tab/software-device-tab.component.js +2 -2
  12. package/esm2015/repository/software-device-tab/software-device-tab.guard.js +9 -5
  13. package/fesm2015/c8y-ngx-components-repository.js +37 -15
  14. package/fesm2015/c8y-ngx-components-repository.js.map +1 -1
  15. package/package.json +2 -2
  16. package/repository/c8y-ngx-components-repository.metadata.json +1 -1
  17. package/repository/configuration-device-tab/device-configuration.guard.d.ts +1 -1
  18. package/repository/firmware-device-tab/firmware-device-tab.component.d.ts +1 -0
  19. package/repository/firmware-device-tab/firmware-device-tab.guard.d.ts +1 -1
  20. package/repository/software-device-tab/device-software-list.component.d.ts +7 -2
  21. package/repository/software-device-tab/installed-software.component.d.ts +4 -0
  22. package/repository/software-device-tab/software-device-tab.guard.d.ts +2 -2
@@ -7,7 +7,7 @@ import { PopoverModule } from 'ngx-bootstrap/popover';
7
7
  import { SingleOperationDetailsModule } from '@c8y/ngx-components/operations/single-operation-details';
8
8
  import { __awaiter, __decorate } from 'tslib';
9
9
  import { QueriesUtil, OperationStatus, InventoryService, InventoryBinaryService, OperationService, EventService, EventBinaryService, Realtime, UserService } from '@c8y/client';
10
- import { isNil, set, assign, isUndefined, get, isString, head, cloneDeep, map as map$1, pick, remove, forEach, find, property, uniqBy, isEmpty, indexOf, filter as filter$1 } from 'lodash-es';
10
+ import { isNil, set, assign, isUndefined, get, isString, head, cloneDeep, map as map$1, pick, remove, forEach, find, property, uniqBy, isEmpty, indexOf, has, filter as filter$1 } from 'lodash-es';
11
11
  import { of, from, defer, throwError, merge, BehaviorSubject, pipe, combineLatest, Subject } from 'rxjs';
12
12
  import { map, take, switchMap, withLatestFrom, filter, takeWhile, tap, debounceTime, distinctUntilChanged, shareReplay, distinctUntilKeyChanged, takeUntil, mergeMap } from 'rxjs/operators';
13
13
  import { Router, ActivatedRoute } from '@angular/router';
@@ -2386,6 +2386,7 @@ class FirmwareDeviceTabComponent {
2386
2386
  return of([]);
2387
2387
  }
2388
2388
  }), shareReplay(1));
2389
+ this.supportsFirmwareOperations$ = this.device$.pipe(map((device) => get(device, 'c8y_SupportedOperations', []).indexOf('c8y_Firmware') > -1));
2389
2390
  this.changesOperation$ = new BehaviorSubject(null);
2390
2391
  this.changesInProgress$ = this.changesOperation$.pipe(map(operation => this.isInProgress(operation)));
2391
2392
  }
@@ -2520,7 +2521,7 @@ class FirmwareDeviceTabComponent {
2520
2521
  FirmwareDeviceTabComponent.decorators = [
2521
2522
  { type: Component, args: [{
2522
2523
  selector: 'c8y-firmware-device-tab',
2523
- template: "<div class=\"row\">\n <div class=\"col-lg-12 col-lg-max\">\n <div class=\"card\">\n <div class=\"card-header separator\">\n <h4 class=\"card-title\" translate>Current firmware</h4>\n </div>\n <div class=\"inner-scroll\">\n <fieldset *ngIf=\"changesOperation$ | async\" class=\"card-block bg-gray-white\">\n <c8y-single-operation [operation]=\"changesOperation$ | async\"></c8y-single-operation>\n </fieldset>\n <div class=\"card-block p-t-0 p-b-0\">\n \n <!-- EMPTY STATE -->\n <ng-container *ngIf=\"isEmpty(deviceFirmwareFragment$ | async); else firmwareBlock\">\n <div class=\"c8y-empty-state text-center\">\n <h1 c8yIcon=\"c8y-firmware\" class=\"c8y-icon-duocolor\"></h1>\n <p>\n <strong translate>No firmware installed.</strong> <br />\n <small translate>Click below to install firmware into this device.</small>\n </p>\n </div>\n </ng-container>\n\n <!-- FIRMWARE -->\n <ng-template #firmwareBlock>\n <c8y-list-group class=\"no-border-last\">\n <c8y-li>\n <c8y-li-icon>\n <i c8yIcon=\"c8y-firmware\"></i>\n </c8y-li-icon>\n\n <c8y-li-body *ngIf=\"deviceFirmwareFragment$ | async as deviceFirmwareFragment\">\n <!-- Firmware title -->\n <p class=\"m-b-16 text-medium\">\n {{ deviceFirmwareFragment.name }}\n </p>\n <!-- Firmware description -->\n <div *ngIf=\"repositoryEntry$ | async as repositoryEntry\">\n <p class=\"text-label-small\" translate>\n Description\n </p>\n <p>\n {{ repositoryEntry.description }}\n </p>\n </div>\n\n <!-- BASE/PATCH VERSION -->\n <div class=\"m-b-16\">\n <p class=\"text-label-small\" translate>\n Version\n </p>\n <p *ngIf=\"deviceFirmwareFragment.version; else versionNotSpecified\">\n {{ deviceFirmwareFragment.version }}\n </p>\n <ng-template #versionNotSpecified>\n <p>\n <em class=\"text-muted\"> ({{ 'not specified`version`' | translate }}) </em>\n </p>\n </ng-template>\n </div>\n\n <!-- ADD PATCH -->\n <button\n *ngIf=\"(this.patches$ | async)?.length > 0\"\n (click)=\"addPatch()\"\n class=\"btn btn-xs btn-primary\"\n [disabled]=\"changesInProgress$ | async\"\n title=\"{{ 'Patches available' | translate }}\"\n >\n {{ 'Patches available' | translate }}\n </button>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </ng-template>\n </div>\n </div>\n <div class=\"card-footer separator-top\">\n\n <!-- INSTALL FIRMWARE -->\n <button\n *ngIf=\"isEmpty(deviceFirmwareFragment$ | async)\"\n class=\"btn btn-primary\"\n (click)=\"installFirmware()\"\n title=\"{{ 'Install firmware' | translate }}\"\n >\n {{ 'Install firmware' | translate }}\n </button>\n\n <!-- REPLACE FIRMWARE -->\n <button\n *ngIf=\"!isEmpty(deviceFirmwareFragment$ | async)\"\n class=\"btn btn-primary\"\n (click)=\"installFirmware()\"\n [disabled]=\"changesInProgress$ | async\"\n title=\"{{ 'Replace firmware' | translate }}\"\n >\n {{ 'Replace firmware' | translate }}\n </button>\n </div>\n </div>\n </div>\n</div>\n"
2524
+ template: "<div class=\"row\">\n <div class=\"col-lg-12 col-lg-max\">\n <div class=\"card\">\n <div class=\"card-header separator\">\n <h4 class=\"card-title\" translate>Current firmware</h4>\n </div>\n <div class=\"inner-scroll\">\n <fieldset *ngIf=\"changesOperation$ | async\" class=\"card-block bg-gray-white\">\n <c8y-single-operation [operation]=\"changesOperation$ | async\"></c8y-single-operation>\n </fieldset>\n <div class=\"card-block p-t-0 p-b-0\">\n <!-- EMPTY STATE -->\n <ng-container *ngIf=\"isEmpty(deviceFirmwareFragment$ | async); else firmwareBlock\">\n <div class=\"c8y-empty-state text-center\">\n <h1 c8yIcon=\"c8y-firmware\" class=\"c8y-icon-duocolor\"></h1>\n <p>\n <strong translate>No firmware installed.</strong> <br />\n <small translate>Click below to install firmware into this device.</small>\n </p>\n </div>\n </ng-container>\n\n <!-- FIRMWARE -->\n <ng-template #firmwareBlock>\n <c8y-list-group class=\"no-border-last\">\n <c8y-li>\n <c8y-li-icon>\n <i c8yIcon=\"c8y-firmware\"></i>\n </c8y-li-icon>\n\n <c8y-li-body *ngIf=\"deviceFirmwareFragment$ | async as deviceFirmwareFragment\">\n <!-- Firmware title -->\n <p class=\"m-b-16 text-medium\">\n {{ deviceFirmwareFragment.name }}\n </p>\n <!-- Firmware description -->\n <div *ngIf=\"repositoryEntry$ | async as repositoryEntry\">\n <p class=\"text-label-small\" translate>Description</p>\n <p>\n {{ repositoryEntry.description }}\n </p>\n </div>\n\n <!-- BASE/PATCH VERSION -->\n <div class=\"m-b-16\">\n <p class=\"text-label-small\" translate>Version</p>\n <p *ngIf=\"deviceFirmwareFragment.version; else versionNotSpecified\">\n {{ deviceFirmwareFragment.version }}\n </p>\n <ng-template #versionNotSpecified>\n <p>\n <em class=\"text-muted\"> ({{ 'not specified`version`' | translate }}) </em>\n </p>\n </ng-template>\n </div>\n\n <!-- ADD PATCH -->\n <button\n *ngIf=\"\n (supportsFirmwareOperations$ | async) && (this.patches$ | async)?.length > 0\n \"\n (click)=\"addPatch()\"\n class=\"btn btn-xs btn-primary\"\n [disabled]=\"changesInProgress$ | async\"\n title=\"{{ 'Patches available' | translate }}\"\n >\n {{ 'Patches available' | translate }}\n </button>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </ng-template>\n </div>\n </div>\n <div *ngIf=\"supportsFirmwareOperations$ | async\" class=\"card-footer separator-top\">\n <!-- INSTALL FIRMWARE -->\n <button\n *ngIf=\"isEmpty(deviceFirmwareFragment$ | async)\"\n class=\"btn btn-primary\"\n (click)=\"installFirmware()\"\n title=\"{{ 'Install firmware' | translate }}\"\n >\n {{ 'Install firmware' | translate }}\n </button>\n\n <!-- REPLACE FIRMWARE -->\n <button\n *ngIf=\"!isEmpty(deviceFirmwareFragment$ | async)\"\n class=\"btn btn-primary\"\n (click)=\"installFirmware()\"\n [disabled]=\"changesInProgress$ | async\"\n title=\"{{ 'Replace firmware' | translate }}\"\n >\n {{ 'Replace firmware' | translate }}\n </button>\n </div>\n </div>\n </div>\n</div>\n"
2524
2525
  },] }
2525
2526
  ];
2526
2527
  FirmwareDeviceTabComponent.ctorParameters = () => [
@@ -2536,9 +2537,8 @@ class FirmwareDeviceTabGuard {
2536
2537
  canActivate(route) {
2537
2538
  const contextData = get(route, 'data.contextData') || get(route, 'parent.data.contextData');
2538
2539
  const supportedOperations = get(contextData, SUPPORTED_OPERATIONS_FRAGMENT);
2539
- return !!supportedOperations
2540
- ? indexOf(supportedOperations, FIRMWARE_FRAGMENT) >= 0
2541
- : false;
2540
+ return ((!!supportedOperations ? indexOf(supportedOperations, FIRMWARE_FRAGMENT) >= 0 : false) ||
2541
+ has(contextData, 'c8y_Firmware'));
2542
2542
  }
2543
2543
  }
2544
2544
  FirmwareDeviceTabGuard.decorators = [
@@ -2634,7 +2634,7 @@ class SoftwareDeviceTabComponent {
2634
2634
  SoftwareDeviceTabComponent.decorators = [
2635
2635
  { type: Component, args: [{
2636
2636
  selector: 'c8y-software-device-tab',
2637
- template: "<c8y-action-bar-item [placement]=\"'right'\">\n <button class=\"btn btn-link\" title=\"{{ 'Reload' | translate }}\" (click)=\"loadDevice()\">\n <i c8yIcon=\"refresh\" [ngClass]=\"{ 'icon-spin': reloading }\"></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class=\"card d-grid grid__col--8-4--md m-b-0\">\n <c8y-installed-software\n class=\"card--fullpage bg-white\"\n [deviceTypeQuery]=\"deviceTypeQuery$ | async\"\n [softwareList]=\"list$ | async\"\n [deviceSoftwareChanges]=\"changes$ | async\"\n [deviceSoftwareChangesOperation]=\"changesOperation$ | async\"\n [deviceSoftwareChangesInProgress]=\"changesInProgress$ | async\"\n (changes)=\"addChanges($event)\"\n ></c8y-installed-software>\n <c8y-device-software-changes\n class=\"card--fullpage bg-gray-white\"\n [changes]=\"changes$ | async\"\n [changesInProgress]=\"changesInProgress$ | async\"\n (clear)=\"clearChanges()\"\n (drop)=\"dropChange($event)\"\n (apply)=\"applyChanges()\"\n ></c8y-device-software-changes>\n</div>\n"
2637
+ template: "<c8y-action-bar-item [placement]=\"'right'\">\n <button class=\"btn btn-link\" title=\"{{ 'Reload' | translate }}\" (click)=\"loadDevice()\">\n <i c8yIcon=\"refresh\" [ngClass]=\"{ 'icon-spin': reloading }\"></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class=\"card d-grid grid__col--8-4--md m-b-0\">\n <c8y-installed-software\n class=\"card--fullpage bg-white\"\n [device]=\"device$ | async\"\n [deviceTypeQuery]=\"deviceTypeQuery$ | async\"\n [softwareList]=\"list$ | async\"\n [deviceSoftwareChanges]=\"changes$ | async\"\n [deviceSoftwareChangesOperation]=\"changesOperation$ | async\"\n [deviceSoftwareChangesInProgress]=\"changesInProgress$ | async\"\n (changes)=\"addChanges($event)\"\n ></c8y-installed-software>\n <c8y-device-software-changes\n class=\"card--fullpage bg-gray-white\"\n [changes]=\"changes$ | async\"\n [changesInProgress]=\"changesInProgress$ | async\"\n (clear)=\"clearChanges()\"\n (drop)=\"dropChange($event)\"\n (apply)=\"applyChanges()\"\n ></c8y-device-software-changes>\n</div>\n"
2638
2638
  },] }
2639
2639
  ];
2640
2640
  SoftwareDeviceTabComponent.ctorParameters = () => [
@@ -2648,11 +2648,14 @@ class SoftwareDeviceTabGuard {
2648
2648
  this.operations = ['c8y_SoftwareUpdate', 'c8y_SoftwareList', 'c8y_Software'];
2649
2649
  }
2650
2650
  canActivate(route) {
2651
- return this.isAnyOperationSupported(route);
2652
- }
2653
- isAnyOperationSupported(route) {
2654
- const device = route.data.contextData || route.parent.data.contextData;
2655
- const supportedOperations = (device && device.c8y_SupportedOperations) || [];
2651
+ const device = get(route, 'data.contextData') || get(route, 'parent.data.contextData');
2652
+ return (this.isAnyOperationSupported(device) ||
2653
+ has(device, 'c8y_Software') ||
2654
+ has(device, 'c8y_SoftwareList') ||
2655
+ has(device, 'c8y_SupportedSoftwareTypes'));
2656
+ }
2657
+ isAnyOperationSupported(device) {
2658
+ const supportedOperations = (device === null || device === void 0 ? void 0 : device.c8y_SupportedOperations) || [];
2656
2659
  return this.operations.some(operation => supportedOperations.indexOf(operation) >= 0);
2657
2660
  }
2658
2661
  }
@@ -2666,6 +2669,12 @@ class InstalledSoftwareComponent {
2666
2669
  this.inventory = inventory;
2667
2670
  this.bsModal = bsModal;
2668
2671
  this.changes = new EventEmitter();
2672
+ this.supportsSoftwareOperations = false;
2673
+ this.operationTypes = ['c8y_SoftwareUpdate', 'c8y_SoftwareList', 'c8y_Software'];
2674
+ }
2675
+ ngOnInit() {
2676
+ const supportedOperations = get(this.device, 'c8y_SupportedOperations', []);
2677
+ this.supportsSoftwareOperations = this.operationTypes.some(operationType => supportedOperations.indexOf(operationType) > -1);
2669
2678
  }
2670
2679
  installSoftware() {
2671
2680
  this.displaySoftwareSelectModal({
@@ -2740,7 +2749,7 @@ class InstalledSoftwareComponent {
2740
2749
  InstalledSoftwareComponent.decorators = [
2741
2750
  { type: Component, args: [{
2742
2751
  selector: 'c8y-installed-software',
2743
- template: "<div class=\"inner-scroll d-flex d-col\">\n <div class=\"card-header large-padding separator sticky-top\">\n <h4 class=\"card-title\" translate>Installed software</h4>\n </div>\n <div class=\"flex-grow\">\n <fieldset *ngIf=\"deviceSoftwareChangesOperation\" class=\"card-block large-padding bg-gray-lighter\">\n <c8y-single-operation [operation]=\"deviceSoftwareChangesOperation\"></c8y-single-operation>\n </fieldset>\n\n <fieldset class=\"d-contents\" [disabled]=\"deviceSoftwareChangesInProgress\">\n <!-- EMPTY STATE -->\n <div class=\"card-block\" *ngIf=\"softwareList.length === 0\">\n <div class=\"c8y-empty-state text-center m-t-16\">\n <h1 class=\"c8y-icon c8y-icon-tools c8y-icon-duocolor\"></h1>\n <p>\n <strong translate>No software installed.</strong> <br />\n <small translate>Click below to install software into this device.</small>\n </p>\n </div>\n </div>\n\n <!-- NOT EMPTY STATE -->\n <ng-container *ngIf=\"softwareList.length > 0\">\n <c8y-device-software-list\n [softwareList]=\"softwareList\"\n [deviceSoftwareChanges]=\"deviceSoftwareChanges\"\n (update)=\"updateSoftware($event)\"\n (remove)=\"removeSoftware($event)\"\n class=\"d-block p-l-16 p-r-16\"\n >\n </c8y-device-software-list>\n </ng-container>\n </fieldset>\n </div>\n<!-- INSTALL SOFTWARE-->\n <div class=\"card-footer large-padding separator sticky-bottom\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Install software' | translate }}\"\n (click)=\"installSoftware()\"\n [disabled]=\"deviceSoftwareChangesInProgress\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Install software' | translate }}\n </button>\n </div>\n</div>\n"
2752
+ template: "<div class=\"inner-scroll d-flex d-col\">\n <div class=\"card-header large-padding separator sticky-top\">\n <h4 class=\"card-title\" translate>Installed software</h4>\n </div>\n <div class=\"flex-grow\">\n <fieldset *ngIf=\"deviceSoftwareChangesOperation\" class=\"card-block large-padding bg-gray-lighter\">\n <c8y-single-operation [operation]=\"deviceSoftwareChangesOperation\"></c8y-single-operation>\n </fieldset>\n\n <fieldset class=\"d-contents\" [disabled]=\"deviceSoftwareChangesInProgress\">\n <!-- EMPTY STATE -->\n <div class=\"card-block\" *ngIf=\"softwareList.length === 0\">\n <div class=\"c8y-empty-state text-center m-t-16\">\n <h1 class=\"c8y-icon c8y-icon-tools c8y-icon-duocolor\"></h1>\n <p>\n <strong translate>No software installed.</strong> <br />\n <small translate>Click below to install software into this device.</small>\n </p>\n </div>\n </div>\n\n <!-- NOT EMPTY STATE -->\n <ng-container *ngIf=\"softwareList.length > 0\">\n <c8y-device-software-list\n [device]=\"device\"\n [softwareList]=\"softwareList\"\n [deviceSoftwareChanges]=\"deviceSoftwareChanges\"\n (update)=\"updateSoftware($event)\"\n (remove)=\"removeSoftware($event)\"\n class=\"d-block p-l-16 p-r-16\"\n >\n </c8y-device-software-list>\n </ng-container>\n </fieldset>\n </div>\n <!-- INSTALL SOFTWARE-->\n <div *ngIf=\"supportsSoftwareOperations\" class=\"card-footer large-padding separator sticky-bottom\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Install software' | translate }}\"\n (click)=\"installSoftware()\"\n [disabled]=\"deviceSoftwareChangesInProgress\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Install software' | translate }}\n </button>\n </div>\n</div>\n"
2744
2753
  },] }
2745
2754
  ];
2746
2755
  InstalledSoftwareComponent.ctorParameters = () => [
@@ -2749,6 +2758,7 @@ InstalledSoftwareComponent.ctorParameters = () => [
2749
2758
  { type: BsModalService }
2750
2759
  ];
2751
2760
  InstalledSoftwareComponent.propDecorators = {
2761
+ device: [{ type: Input }],
2752
2762
  softwareList: [{ type: Input }],
2753
2763
  deviceSoftwareChanges: [{ type: Input }],
2754
2764
  deviceSoftwareChangesOperation: [{ type: Input }],
@@ -2761,6 +2771,12 @@ class DeviceSoftwareListComponent {
2761
2771
  constructor() {
2762
2772
  this.update = new EventEmitter();
2763
2773
  this.remove = new EventEmitter();
2774
+ this.supportsSoftwareOperations = false;
2775
+ this.operationTypes = ['c8y_SoftwareUpdate', 'c8y_SoftwareList', 'c8y_Software'];
2776
+ }
2777
+ ngOnInit() {
2778
+ const supportedOperations = get(this.device, 'c8y_SupportedOperations', []);
2779
+ this.supportsSoftwareOperations = this.operationTypes.some(operationType => supportedOperations.indexOf(operationType) > -1);
2764
2780
  }
2765
2781
  ngAfterContentInit() {
2766
2782
  this.showUpdate = this.update.observers.length > 0;
@@ -2774,11 +2790,12 @@ class DeviceSoftwareListComponent {
2774
2790
  DeviceSoftwareListComponent.decorators = [
2775
2791
  { type: Component, args: [{
2776
2792
  selector: 'c8y-device-software-list',
2777
- template: "<c8y-list-group class=\"no-border-last\">\n <c8y-li\n [ngClass]=\"{ disabled: isSoftwareGoingToBeChanged(software) }\"\n *ngFor=\"let software of softwareList\"\n >\n <!-- SOFTWARE ICON -->\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-20\">\n <div title=\"{{ software.name }}\" class=\"col-8\">\n <!-- SOFTWARE NAME -->\n <p class=\"text-truncate\">{{ software.name }}</p>\n <!-- SOFTWARE VERSION -->\n <p class=\"text-truncate\">\n <span class=\"text-label-small m-r-4\" translate>\n Version\n </span>\n <span title=\"{{ software.version }}\">\n {{ software.version }}\n </span>\n </p>\n </div>\n\n <div *ngIf=\"showUpdate || showRemove\" class=\"col-4 text-right\">\n <!-- UPDATE SOFTWARE -->\n <button\n *ngIf=\"showUpdate && !isSoftwareGoingToBeChanged(software)\"\n class=\"btn btn-default btn-xs showOnHover\"\n (click)=\"update.emit(software)\"\n title=\"{{ 'Update`software,verb`' | translate }}\"\n translate\n >\n Update\n </button>\n\n <!-- REMOVE SOFTWARE -->\n <button\n *ngIf=\"showRemove && !isSoftwareGoingToBeChanged(software)\"\n title=\"{{ 'Remove`software`' | translate }}\"\n class=\"showOnHover btn btn-dot pull-right\"\n (click)=\"remove.emit(software)\"\n >\n <i c8yIcon=\"minus-circle\" class=\"text-danger\"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n</c8y-list-group>\n"
2793
+ template: "<c8y-list-group class=\"no-border-last\">\n <c8y-li\n [ngClass]=\"{ disabled: isSoftwareGoingToBeChanged(software) }\"\n *ngFor=\"let software of softwareList\"\n >\n <!-- SOFTWARE ICON -->\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-20\">\n <div title=\"{{ software.name }}\" class=\"col-8\">\n <!-- SOFTWARE NAME -->\n <p class=\"text-truncate\">{{ software.name }}</p>\n <!-- SOFTWARE VERSION -->\n <p class=\"text-truncate\">\n <span class=\"text-label-small m-r-4\" translate>\n Version\n </span>\n <span title=\"{{ software.version }}\">\n {{ software.version }}\n </span>\n </p>\n </div>\n\n <div\n *ngIf=\"supportsSoftwareOperations && (showUpdate || showRemove)\"\n class=\"col-4 text-right\"\n >\n <!-- UPDATE SOFTWARE -->\n <button\n *ngIf=\"showUpdate && !isSoftwareGoingToBeChanged(software)\"\n class=\"btn btn-default btn-xs showOnHover\"\n (click)=\"update.emit(software)\"\n title=\"{{ 'Update`software,verb`' | translate }}\"\n translate\n >\n Update\n </button>\n\n <!-- REMOVE SOFTWARE -->\n <button\n *ngIf=\"showRemove && !isSoftwareGoingToBeChanged(software)\"\n title=\"{{ 'Remove`software`' | translate }}\"\n class=\"showOnHover btn btn-dot pull-right\"\n (click)=\"remove.emit(software)\"\n >\n <i c8yIcon=\"minus-circle\" class=\"text-danger\"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n</c8y-list-group>\n"
2778
2794
  },] }
2779
2795
  ];
2780
2796
  DeviceSoftwareListComponent.propDecorators = {
2781
2797
  softwareList: [{ type: Input }],
2798
+ device: [{ type: Input }],
2782
2799
  deviceSoftwareChanges: [{ type: Input }],
2783
2800
  update: [{ type: Output }],
2784
2801
  remove: [{ type: Output }]
@@ -2997,7 +3014,11 @@ class DeviceConfigurationComponent {
2997
3014
  title: gettext('No configurations available.'),
2998
3015
  text: gettext('Add configuration to configuration repository')
2999
3016
  };
3000
- this.showTextBasedConfig = this.deviceConfigurationService.hasAnySupportedOperation(this.device, [DeviceConfigurationOperation.CONFIG, DeviceConfigurationOperation.SEND_CONFIG]);
3017
+ this.showTextBasedConfig =
3018
+ this.deviceConfigurationService.hasAnySupportedOperation(this.device, [
3019
+ DeviceConfigurationOperation.CONFIG,
3020
+ DeviceConfigurationOperation.SEND_CONFIG
3021
+ ]) || has(this.device, 'c8y_Configuration');
3001
3022
  }
3002
3023
  onConfigTypeSelected(config) {
3003
3024
  return __awaiter(this, void 0, void 0, function* () {
@@ -3339,7 +3360,8 @@ class DeviceConfigurationGuard {
3339
3360
  DeviceConfigurationOperation.UPLOAD_CONFIG,
3340
3361
  DeviceConfigurationOperation.CONFIG,
3341
3362
  DeviceConfigurationOperation.SEND_CONFIG
3342
- ]));
3363
+ ]) ||
3364
+ has(contextData, 'c8y_Configuration'));
3343
3365
  }
3344
3366
  }
3345
3367
  DeviceConfigurationGuard.decorators = [