@c8y/ngx-components 1021.63.2 → 1021.67.0

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 (197) hide show
  1. package/auth-configuration/sso-configuration/template-parts/signature-configuration.component.d.ts +7 -2
  2. package/auth-configuration/sso-configuration/template-parts/signature-configuration.component.d.ts.map +1 -1
  3. package/core/bottom-drawer/bottom-drawer-ref.d.ts +4 -0
  4. package/core/bottom-drawer/bottom-drawer-ref.d.ts.map +1 -1
  5. package/core/breadcrumb/breadcrumb-item.component.d.ts +1 -1
  6. package/core/breadcrumb/breadcrumb-item.component.d.ts.map +1 -1
  7. package/core/breadcrumb/breadcrumb-outlet.component.d.ts +1 -1
  8. package/core/breadcrumb/breadcrumb-outlet.component.d.ts.map +1 -1
  9. package/core/breadcrumb/breadcrumb.component.d.ts +1 -1
  10. package/core/breadcrumb/breadcrumb.component.d.ts.map +1 -1
  11. package/core/breadcrumb/breadcrumb.module.d.ts +7 -7
  12. package/core/breadcrumb/breadcrumb.module.d.ts.map +1 -1
  13. package/core/common/common.module.d.ts +38 -38
  14. package/core/common/date-format.service.d.ts +30 -0
  15. package/core/common/date-format.service.d.ts.map +1 -0
  16. package/core/common/date.pipe.d.ts +7 -3
  17. package/core/common/date.pipe.d.ts.map +1 -1
  18. package/core/common/index.d.ts +1 -0
  19. package/core/common/index.d.ts.map +1 -1
  20. package/core/common/outlet.directive.d.ts +1 -1
  21. package/core/common/outlet.directive.d.ts.map +1 -1
  22. package/core/common/user-preferences/user-preferences-store-current-user.d.ts +11 -0
  23. package/core/common/user-preferences/user-preferences-store-current-user.d.ts.map +1 -0
  24. package/core/common/user-preferences/user-preferences.service.d.ts +40 -1
  25. package/core/common/user-preferences/user-preferences.service.d.ts.map +1 -1
  26. package/core/date-picker/date-picker.component.d.ts +3 -1
  27. package/core/date-picker/date-picker.component.d.ts.map +1 -1
  28. package/core/date-time-picker/date-time-picker.component.d.ts +6 -3
  29. package/core/date-time-picker/date-time-picker.component.d.ts.map +1 -1
  30. package/core/dynamic-forms/date/date.type.component.d.ts +3 -0
  31. package/core/dynamic-forms/date/date.type.component.d.ts.map +1 -1
  32. package/core/plugins/plugins.model.d.ts +1 -0
  33. package/core/plugins/plugins.model.d.ts.map +1 -1
  34. package/core/plugins/plugins.service.d.ts +7 -2
  35. package/core/plugins/plugins.service.d.ts.map +1 -1
  36. package/core/time-interval/time-interval.component.d.ts +4 -2
  37. package/core/time-interval/time-interval.component.d.ts.map +1 -1
  38. package/ecosystem/application-plugins/application-plugin-readme.component.d.ts +15 -0
  39. package/ecosystem/application-plugins/application-plugin-readme.component.d.ts.map +1 -0
  40. package/ecosystem/application-plugins/application-plugins.component.d.ts +4 -2
  41. package/ecosystem/application-plugins/application-plugins.component.d.ts.map +1 -1
  42. package/ecosystem/application-plugins/application-plugins.module.d.ts +4 -3
  43. package/ecosystem/application-plugins/application-plugins.module.d.ts.map +1 -1
  44. package/ecosystem/application-plugins/install-plugin.component.d.ts +8 -4
  45. package/ecosystem/application-plugins/install-plugin.component.d.ts.map +1 -1
  46. package/ecosystem/application-plugins/plugin-list.component.d.ts +10 -26
  47. package/ecosystem/application-plugins/plugin-list.component.d.ts.map +1 -1
  48. package/ecosystem/application-plugins/plugin-list.service.d.ts +27 -0
  49. package/ecosystem/application-plugins/plugin-list.service.d.ts.map +1 -0
  50. package/ecosystem/ecosystem.module.d.ts +2 -1
  51. package/ecosystem/ecosystem.module.d.ts.map +1 -1
  52. package/ecosystem/packages/package-changelog-tab/package-changelog-tab.component.d.ts +15 -0
  53. package/ecosystem/packages/package-changelog-tab/package-changelog-tab.component.d.ts.map +1 -0
  54. package/ecosystem/packages/package-changelog.guard.d.ts +10 -0
  55. package/ecosystem/packages/package-changelog.guard.d.ts.map +1 -0
  56. package/ecosystem/packages/package-details/package-details.component.d.ts +7 -9
  57. package/ecosystem/packages/package-details/package-details.component.d.ts.map +1 -1
  58. package/ecosystem/packages/package-versions/package-contents/contents-plugins/contents-plugins.component.d.ts +5 -1
  59. package/ecosystem/packages/package-versions/package-contents/contents-plugins/contents-plugins.component.d.ts.map +1 -1
  60. package/ecosystem/packages/package-versions/package-contents/packages-contents.component.d.ts +8 -3
  61. package/ecosystem/packages/package-versions/package-contents/packages-contents.component.d.ts.map +1 -1
  62. package/ecosystem/packages/package-versions/packages-versions.component.d.ts +9 -2
  63. package/ecosystem/packages/package-versions/packages-versions.component.d.ts.map +1 -1
  64. package/ecosystem/shared/index.d.ts +1 -0
  65. package/ecosystem/shared/index.d.ts.map +1 -1
  66. package/ecosystem/shared/package-changelog/package-changelog.component.d.ts +24 -0
  67. package/ecosystem/shared/package-changelog/package-changelog.component.d.ts.map +1 -0
  68. package/ecosystem/shared/shared-ecosystem.module.d.ts +2 -1
  69. package/ecosystem/shared/shared-ecosystem.module.d.ts.map +1 -1
  70. package/esm2022/auth-configuration/sso-configuration/template-parts/signature-configuration.component.mjs +11 -7
  71. package/esm2022/core/bottom-drawer/bottom-drawer-ref.mjs +9 -3
  72. package/esm2022/core/breadcrumb/breadcrumb-item.component.mjs +3 -3
  73. package/esm2022/core/breadcrumb/breadcrumb-outlet.component.mjs +19 -9
  74. package/esm2022/core/breadcrumb/breadcrumb.component.mjs +3 -3
  75. package/esm2022/core/breadcrumb/breadcrumb.module.mjs +16 -5
  76. package/esm2022/core/common/common.module.mjs +6 -6
  77. package/esm2022/core/common/date-format.service.mjs +81 -0
  78. package/esm2022/core/common/date.pipe.mjs +29 -6
  79. package/esm2022/core/common/index.mjs +2 -1
  80. package/esm2022/core/common/outlet.directive.mjs +4 -3
  81. package/esm2022/core/common/user-preferences/user-preferences-store-current-user.mjs +22 -0
  82. package/esm2022/core/common/user-preferences/user-preferences.service.mjs +106 -16
  83. package/esm2022/core/date-picker/date-picker.component.mjs +11 -4
  84. package/esm2022/core/date-time-picker/date-time-picker.component.mjs +20 -11
  85. package/esm2022/core/dynamic-forms/date/date.type.component.mjs +12 -4
  86. package/esm2022/core/plugins/plugins.model.mjs +1 -1
  87. package/esm2022/core/plugins/plugins.service.mjs +31 -5
  88. package/esm2022/core/time-interval/time-interval.component.mjs +9 -2
  89. package/esm2022/ecosystem/application-plugins/application-plugin-readme.component.mjs +26 -0
  90. package/esm2022/ecosystem/application-plugins/application-plugins.component.mjs +29 -14
  91. package/esm2022/ecosystem/application-plugins/application-plugins.module.mjs +6 -3
  92. package/esm2022/ecosystem/application-plugins/install-plugin.component.mjs +21 -15
  93. package/esm2022/ecosystem/application-plugins/plugin-list-item.component.mjs +3 -3
  94. package/esm2022/ecosystem/application-plugins/plugin-list.component.mjs +26 -202
  95. package/esm2022/ecosystem/application-plugins/plugin-list.service.mjs +200 -0
  96. package/esm2022/ecosystem/application-plugins/update-plugin-of-app/update-plugin-of-app.component.mjs +3 -3
  97. package/esm2022/ecosystem/application-properties/update-application-modal/update-application-modal.component.mjs +1 -1
  98. package/esm2022/ecosystem/ecosystem.module.mjs +21 -5
  99. package/esm2022/ecosystem/packages/package-changelog-tab/package-changelog-tab.component.mjs +33 -0
  100. package/esm2022/ecosystem/packages/package-changelog.guard.mjs +22 -0
  101. package/esm2022/ecosystem/packages/package-details/package-details.component.mjs +25 -44
  102. package/esm2022/ecosystem/packages/package-versions/package-contents/contents-plugins/contents-plugins.component.mjs +14 -4
  103. package/esm2022/ecosystem/packages/package-versions/package-contents/packages-contents.component.mjs +27 -8
  104. package/esm2022/ecosystem/packages/package-versions/packages-versions.component.mjs +22 -8
  105. package/esm2022/ecosystem/shared/index.mjs +2 -1
  106. package/esm2022/ecosystem/shared/list-filters/list-filters.component.mjs +3 -3
  107. package/esm2022/ecosystem/shared/package-changelog/package-changelog.component.mjs +82 -0
  108. package/esm2022/ecosystem/shared/package-version-select/package-version-select.component.mjs +3 -3
  109. package/esm2022/ecosystem/shared/shared-ecosystem.module.mjs +12 -6
  110. package/esm2022/operations/bulk-operation-scheduler/operation-scheduler.component.mjs +9 -7
  111. package/esm2022/operations/bulk-operations-list/bulk-operations-list.component.mjs +1 -1
  112. package/esm2022/upgrade/ng1/downgraded.services.mjs +3 -2
  113. package/esm2022/upgrade/ng1/index.mjs +3 -2
  114. package/esm2022/widgets/cockpit/index.mjs +3 -1
  115. package/esm2022/widgets/cockpit-exports/index.mjs +8 -1
  116. package/esm2022/widgets/definitions/index.mjs +2 -1
  117. package/esm2022/widgets/definitions/radial-gauge/c8y-ngx-components-widgets-definitions-radial-gauge.mjs +5 -0
  118. package/esm2022/widgets/definitions/radial-gauge/index.mjs +33 -0
  119. package/esm2022/widgets/implementations/info-gauge/index.mjs +2 -2
  120. package/esm2022/widgets/implementations/info-gauge/info-gauge-widget-config/gauge.model.mjs +295 -0
  121. package/esm2022/widgets/implementations/info-gauge/info-gauge-widget-config/info-gauge-widget-config.component.mjs +141 -11
  122. package/esm2022/widgets/implementations/info-gauge/info-gauge-widget-config/preset-preview/preset-preview.component.mjs +67 -0
  123. package/esm2022/widgets/implementations/info-gauge/info-gauge-widget-view/info-gauge-widget-view.component.mjs +34 -6
  124. package/esm2022/widgets/implementations/info-gauge/info-gauge-widget.module.mjs +9 -4
  125. package/esm2022/widgets/implementations/info-gauge/radial-gauge/radial-gauge.component.mjs +97 -0
  126. package/esm2022/widgets/implementations/info-gauge/radial-gauge/radial-gauge.service.mjs +369 -0
  127. package/fesm2022/c8y-ngx-components-auth-configuration.mjs +9 -5
  128. package/fesm2022/c8y-ngx-components-auth-configuration.mjs.map +1 -1
  129. package/fesm2022/c8y-ngx-components-ecosystem-application-plugins.mjs +209 -142
  130. package/fesm2022/c8y-ngx-components-ecosystem-application-plugins.mjs.map +1 -1
  131. package/fesm2022/c8y-ngx-components-ecosystem-shared.mjs +96 -13
  132. package/fesm2022/c8y-ngx-components-ecosystem-shared.mjs.map +1 -1
  133. package/fesm2022/c8y-ngx-components-ecosystem.mjs +336 -186
  134. package/fesm2022/c8y-ngx-components-ecosystem.mjs.map +1 -1
  135. package/fesm2022/c8y-ngx-components-operations-bulk-operation-scheduler.mjs +7 -5
  136. package/fesm2022/c8y-ngx-components-operations-bulk-operation-scheduler.mjs.map +1 -1
  137. package/fesm2022/c8y-ngx-components-operations-bulk-operations-list.mjs +1 -1
  138. package/fesm2022/c8y-ngx-components-operations-bulk-operations-list.mjs.map +1 -1
  139. package/fesm2022/c8y-ngx-components-upgrade.mjs +3 -1
  140. package/fesm2022/c8y-ngx-components-upgrade.mjs.map +1 -1
  141. package/fesm2022/c8y-ngx-components-widgets-cockpit-exports.mjs +7 -0
  142. package/fesm2022/c8y-ngx-components-widgets-cockpit-exports.mjs.map +1 -1
  143. package/fesm2022/c8y-ngx-components-widgets-cockpit.mjs +2 -0
  144. package/fesm2022/c8y-ngx-components-widgets-cockpit.mjs.map +1 -1
  145. package/fesm2022/c8y-ngx-components-widgets-definitions-radial-gauge.mjs +40 -0
  146. package/fesm2022/c8y-ngx-components-widgets-definitions-radial-gauge.mjs.map +1 -0
  147. package/fesm2022/c8y-ngx-components-widgets-definitions.mjs +1 -0
  148. package/fesm2022/c8y-ngx-components-widgets-definitions.mjs.map +1 -1
  149. package/fesm2022/c8y-ngx-components-widgets-implementations-info-gauge.mjs +991 -28
  150. package/fesm2022/c8y-ngx-components-widgets-implementations-info-gauge.mjs.map +1 -1
  151. package/fesm2022/c8y-ngx-components.mjs +833 -550
  152. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  153. package/locales/de.po +45 -6
  154. package/locales/es.po +45 -6
  155. package/locales/fr.po +45 -6
  156. package/locales/ja_JP.po +45 -6
  157. package/locales/ko.po +45 -6
  158. package/locales/locales.pot +73 -10
  159. package/locales/nl.po +45 -6
  160. package/locales/pl.po +45 -6
  161. package/locales/pt_BR.po +45 -6
  162. package/locales/zh_CN.po +45 -6
  163. package/locales/zh_TW.po +45 -6
  164. package/operations/bulk-operation-scheduler/operation-scheduler.component.d.ts +4 -2
  165. package/operations/bulk-operation-scheduler/operation-scheduler.component.d.ts.map +1 -1
  166. package/package.json +1 -1
  167. package/upgrade/ng1/downgraded.services.d.ts +1 -0
  168. package/upgrade/ng1/downgraded.services.d.ts.map +1 -1
  169. package/upgrade/ng1/index.d.ts.map +1 -1
  170. package/widgets/cockpit/index.d.ts +29 -0
  171. package/widgets/cockpit/index.d.ts.map +1 -1
  172. package/widgets/cockpit-exports/index.d.ts +6 -0
  173. package/widgets/cockpit-exports/index.d.ts.map +1 -1
  174. package/widgets/definitions/index.d.ts +1 -0
  175. package/widgets/definitions/index.d.ts.map +1 -1
  176. package/widgets/definitions/radial-gauge/c8y-ngx-components-widgets-definitions-radial-gauge.d.ts.map +1 -0
  177. package/widgets/definitions/radial-gauge/index.d.ts +33 -0
  178. package/widgets/definitions/radial-gauge/index.d.ts.map +1 -0
  179. package/widgets/implementations/info-gauge/index.d.ts +1 -1
  180. package/widgets/implementations/info-gauge/index.d.ts.map +1 -1
  181. package/widgets/implementations/info-gauge/info-gauge-widget-config/gauge.model.d.ts +339 -0
  182. package/widgets/implementations/info-gauge/info-gauge-widget-config/gauge.model.d.ts.map +1 -0
  183. package/widgets/implementations/info-gauge/info-gauge-widget-config/info-gauge-widget-config.component.d.ts +27 -7
  184. package/widgets/implementations/info-gauge/info-gauge-widget-config/info-gauge-widget-config.component.d.ts.map +1 -1
  185. package/widgets/implementations/info-gauge/info-gauge-widget-config/preset-preview/preset-preview.component.d.ts +33 -0
  186. package/widgets/implementations/info-gauge/info-gauge-widget-config/preset-preview/preset-preview.component.d.ts.map +1 -0
  187. package/widgets/implementations/info-gauge/info-gauge-widget-view/info-gauge-widget-view.component.d.ts +7 -3
  188. package/widgets/implementations/info-gauge/info-gauge-widget-view/info-gauge-widget-view.component.d.ts.map +1 -1
  189. package/widgets/implementations/info-gauge/info-gauge-widget.module.d.ts +2 -1
  190. package/widgets/implementations/info-gauge/info-gauge-widget.module.d.ts.map +1 -1
  191. package/widgets/implementations/info-gauge/radial-gauge/radial-gauge.component.d.ts +37 -0
  192. package/widgets/implementations/info-gauge/radial-gauge/radial-gauge.component.d.ts.map +1 -0
  193. package/widgets/implementations/info-gauge/radial-gauge/radial-gauge.service.d.ts +146 -0
  194. package/widgets/implementations/info-gauge/radial-gauge/radial-gauge.service.d.ts.map +1 -0
  195. package/esm2022/widgets/implementations/info-gauge/info-gauge.model.mjs +0 -2
  196. package/widgets/implementations/info-gauge/info-gauge.model.d.ts +0 -7
  197. package/widgets/implementations/info-gauge/info-gauge.model.d.ts.map +0 -1
@@ -1,17 +1,18 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Pipe, Component, Input, EventEmitter, Output, ViewChild, Injectable, NgModule } from '@angular/core';
2
+ import { Pipe, Component, Input, inject, Injectable, EventEmitter, Output, ViewChild, NgModule } from '@angular/core';
3
3
  import * as i2 from '@c8y/ngx-components';
4
- import { gettext, PackageType, ApplicationPluginStatus, PluginsService, PluginsExportScopes, DataGridComponent, CoreModule, hookRoute, ViewContext } from '@c8y/ngx-components';
5
- import * as i1 from '@c8y/ngx-components/ecosystem/shared';
6
- import { PRODUCT_EXPERIENCE_ECOSYSTEM, defaultPackageTypes, SharedEcosystemModule } from '@c8y/ngx-components/ecosystem/shared';
7
- import * as i1$2 from '@angular/router';
4
+ import { gettext, GainsightService, PluginsService, AlertService, HumanizeAppNamePipe, PackageType, ApplicationPluginStatus, BottomDrawerRef, PluginsExportScopes, DataGridComponent, CoreModule, hookRoute, ViewContext } from '@c8y/ngx-components';
5
+ import * as i3 from '@c8y/ngx-components/ecosystem/shared';
6
+ import { EcosystemService, PRODUCT_EXPERIENCE_ECOSYSTEM, defaultPackageTypes, SharedEcosystemModule } from '@c8y/ngx-components/ecosystem/shared';
7
+ import * as i1$1 from '@angular/router';
8
8
  import { pick, uniq } from 'lodash-es';
9
- import * as i1$1 from 'ngx-bootstrap/modal';
9
+ import * as i1 from 'ngx-bootstrap/modal';
10
+ import { BsModalService } from 'ngx-bootstrap/modal';
10
11
  import { Subject, BehaviorSubject, combineLatest, of, firstValueFrom, map as map$1 } from 'rxjs';
11
12
  import { map, takeUntil, shareReplay } from 'rxjs/operators';
12
- import * as i5 from '@angular/common';
13
+ import * as i3$1 from '@angular/common';
13
14
  import { ApplicationType } from '@c8y/client';
14
- import * as i4 from '@ngx-translate/core';
15
+ import { TranslateService } from '@ngx-translate/core';
15
16
  import * as i2$1 from '@angular/forms';
16
17
  import { FormControl } from '@angular/forms';
17
18
 
@@ -23,7 +24,7 @@ class AppStatePipe {
23
24
  const appState = this.ecosystemService.getAppState(app);
24
25
  return appState[arg];
25
26
  }
26
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppStatePipe, deps: [{ token: i1.EcosystemService }], target: i0.ɵɵFactoryTarget.Pipe }); }
27
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppStatePipe, deps: [{ token: i3.EcosystemService }], target: i0.ɵɵFactoryTarget.Pipe }); }
27
28
  static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: AppStatePipe, name: "appState" }); }
28
29
  }
29
30
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppStatePipe, decorators: [{
@@ -32,7 +33,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
32
33
  name: 'appState',
33
34
  pure: true
34
35
  }]
35
- }], ctorParameters: () => [{ type: i1.EcosystemService }] });
36
+ }], ctorParameters: () => [{ type: i3.EcosystemService }] });
36
37
 
37
38
  class AppsToUpdateRemotesSelectComponent {
38
39
  constructor(bsModalRef, wizardModalService, ecosystemService) {
@@ -102,13 +103,13 @@ class AppsToUpdateRemotesSelectComponent {
102
103
  async getOwnedHostedApps() {
103
104
  return (await this.ecosystemService.getWebApplications()).filter(app => this.ecosystemService.isOwner(app) && app.type !== ApplicationType.EXTERNAL);
104
105
  }
105
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppsToUpdateRemotesSelectComponent, deps: [{ token: i1$1.BsModalRef }, { token: i2.WizardModalService }, { token: i1.EcosystemService }], target: i0.ɵɵFactoryTarget.Component }); }
106
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AppsToUpdateRemotesSelectComponent, selector: "c8y-apps-to-update-remotes-select", inputs: { apps: "apps", updateType: "updateType", pluginName: "pluginName", appsDisabled: "appsDisabled" }, ngImport: i0, template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'c8y-modules'\"></i>\n <div class=\"modal-title h4\" id=\"modal-title\" translate>Custom applications</div>\n </div>\n <div class=\"inner-scroll\" id=\"modal-body\">\n <div class=\"p-16 text-center separator-bottom sticky-top bg-component\">\n <p class=\"text-medium\">\n {{ textConfig.header | translate }}\n </p>\n <c8y-filter (onSearch)=\"filterTerm$.next($event)\"></c8y-filter>\n </div>\n <c8y-list-group *ngIf=\"apps.length; else emptyList\">\n <c8y-li\n [ngClass]=\"{ disabled: updateType === 'install' && appsDisabled.has(app.id) }\"\n *ngFor=\"let app of filteredApps$ | async\"\n data-cy=\"apps-to-update-remotes-select--applications-list\"\n >\n <c8y-li-checkbox (onSelect)=\"setSelectedApps($event, app)\" data-cy=\"apps-to-update-remotes-select--app-checkbox\"></c8y-li-checkbox>\n <c8y-li-icon class=\"p-l-0 icon-32\">\n <c8y-app-icon\n class=\"list-group-icon\"\n [app]=\"app\"\n [contextPath]=\"app.contextPath\"\n [name]=\"app.name\"\n ></c8y-app-icon>\n </c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"p-r-8\">\n <p class=\"text-medium\" [innerText]=\"app | humanizeAppName | async\"></p>\n <p class=\"small text-muted\">{{ app.description }}</p>\n </div>\n <span class=\"label m-l-auto a-s-start\" [ngClass]=\"app | appState: 'class'\">\n {{ app | appState: 'label' | translate }}\n </span>\n </div>\n </c8y-li>\n </c8y-list-group>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ textConfig.applyButton | translate }}\"\n [disabled]=\"appsToUpdateRemotes.length === 0\"\n (click)=\"apply()\"\n >\n {{ textConfig.applyButton | translate }}\n </button>\n </div>\n</div>\n<ng-template #emptyList>\n <c8y-ui-empty-state\n [icon]=\"'c8y-modules'\"\n [title]=\"'No custom applications available.' | translate\"\n *ngIf=\"updateType !== 'install'\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <ng-container *ngIf=\"updateType === 'install'\">\n <c8y-ui-empty-state\n [icon]=\"'c8y-modules'\"\n [title]=\"'No custom applications available.' | translate\"\n [subtitle]=\"'Create a custom application by duplicating an existing one.' | translate\"\n [horizontal]=\"true\"\n >\n <button\n class=\"btn btn-sm btn-default m-t-8\"\n title=\"{{ 'Duplicate' | translate }}\"\n (click)=\"duplicateApp()\"\n >\n {{ 'Duplicate' | translate }}\n </button>\n </c8y-ui-empty-state>\n </ng-container>\n</ng-template>\n", dependencies: [{ kind: "component", type: i2.AppIconComponent, selector: "c8y-app-icon", inputs: ["contextPath", "name", "app"] }, { 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: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.FilterInputComponent, selector: "c8y-filter", inputs: ["icon", "filterTerm"], outputs: ["onSearch"] }, { kind: "component", type: i2.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i2.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i2.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i2.ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.HumanizeAppNamePipe, name: "humanizeAppName" }, { kind: "pipe", type: AppStatePipe, name: "appState" }] }); }
106
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppsToUpdateRemotesSelectComponent, deps: [{ token: i1.BsModalRef }, { token: i2.WizardModalService }, { token: i3.EcosystemService }], target: i0.ɵɵFactoryTarget.Component }); }
107
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AppsToUpdateRemotesSelectComponent, selector: "c8y-apps-to-update-remotes-select", inputs: { apps: "apps", updateType: "updateType", pluginName: "pluginName", appsDisabled: "appsDisabled" }, ngImport: i0, template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'c8y-modules'\"></i>\n <div class=\"modal-title h4\" id=\"modal-title\" translate>Custom applications</div>\n </div>\n <div class=\"inner-scroll\" id=\"modal-body\">\n <div class=\"p-16 text-center separator-bottom sticky-top bg-component\">\n <p class=\"text-medium\">\n {{ textConfig.header | translate }}\n </p>\n <c8y-filter (onSearch)=\"filterTerm$.next($event)\"></c8y-filter>\n </div>\n <c8y-list-group *ngIf=\"apps.length; else emptyList\">\n <c8y-li\n [ngClass]=\"{ disabled: updateType === 'install' && appsDisabled.has(app.id) }\"\n *ngFor=\"let app of filteredApps$ | async\"\n data-cy=\"apps-to-update-remotes-select--applications-list\"\n >\n <c8y-li-checkbox (onSelect)=\"setSelectedApps($event, app)\" data-cy=\"apps-to-update-remotes-select--app-checkbox\"></c8y-li-checkbox>\n <c8y-li-icon class=\"p-l-0 icon-32\">\n <c8y-app-icon\n class=\"list-group-icon\"\n [app]=\"app\"\n [contextPath]=\"app.contextPath\"\n [name]=\"app.name\"\n ></c8y-app-icon>\n </c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"p-r-8\">\n <p class=\"text-medium\" [innerText]=\"app | humanizeAppName | async\"></p>\n <p class=\"small text-muted\">{{ app.description }}</p>\n </div>\n <span class=\"label m-l-auto a-s-start\" [ngClass]=\"app | appState: 'class'\">\n {{ app | appState: 'label' | translate }}\n </span>\n </div>\n </c8y-li>\n </c8y-list-group>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ textConfig.applyButton | translate }}\"\n [disabled]=\"appsToUpdateRemotes.length === 0\"\n (click)=\"apply()\"\n >\n {{ textConfig.applyButton | translate }}\n </button>\n </div>\n</div>\n<ng-template #emptyList>\n <c8y-ui-empty-state\n [icon]=\"'c8y-modules'\"\n [title]=\"'No custom applications available.' | translate\"\n *ngIf=\"updateType !== 'install'\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <ng-container *ngIf=\"updateType === 'install'\">\n <c8y-ui-empty-state\n [icon]=\"'c8y-modules'\"\n [title]=\"'No custom applications available.' | translate\"\n [subtitle]=\"'Create a custom application by duplicating an existing one.' | translate\"\n [horizontal]=\"true\"\n >\n <button\n class=\"btn btn-sm btn-default m-t-8\"\n title=\"{{ 'Duplicate' | translate }}\"\n (click)=\"duplicateApp()\"\n >\n {{ 'Duplicate' | translate }}\n </button>\n </c8y-ui-empty-state>\n </ng-container>\n</ng-template>\n", dependencies: [{ kind: "component", type: i2.AppIconComponent, selector: "c8y-app-icon", inputs: ["contextPath", "name", "app"] }, { 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: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.FilterInputComponent, selector: "c8y-filter", inputs: ["icon", "filterTerm"], outputs: ["onSearch"] }, { kind: "component", type: i2.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i2.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i2.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i2.ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.HumanizeAppNamePipe, name: "humanizeAppName" }, { kind: "pipe", type: AppStatePipe, name: "appState" }] }); }
107
108
  }
108
109
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppsToUpdateRemotesSelectComponent, decorators: [{
109
110
  type: Component,
110
111
  args: [{ selector: 'c8y-apps-to-update-remotes-select', template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'c8y-modules'\"></i>\n <div class=\"modal-title h4\" id=\"modal-title\" translate>Custom applications</div>\n </div>\n <div class=\"inner-scroll\" id=\"modal-body\">\n <div class=\"p-16 text-center separator-bottom sticky-top bg-component\">\n <p class=\"text-medium\">\n {{ textConfig.header | translate }}\n </p>\n <c8y-filter (onSearch)=\"filterTerm$.next($event)\"></c8y-filter>\n </div>\n <c8y-list-group *ngIf=\"apps.length; else emptyList\">\n <c8y-li\n [ngClass]=\"{ disabled: updateType === 'install' && appsDisabled.has(app.id) }\"\n *ngFor=\"let app of filteredApps$ | async\"\n data-cy=\"apps-to-update-remotes-select--applications-list\"\n >\n <c8y-li-checkbox (onSelect)=\"setSelectedApps($event, app)\" data-cy=\"apps-to-update-remotes-select--app-checkbox\"></c8y-li-checkbox>\n <c8y-li-icon class=\"p-l-0 icon-32\">\n <c8y-app-icon\n class=\"list-group-icon\"\n [app]=\"app\"\n [contextPath]=\"app.contextPath\"\n [name]=\"app.name\"\n ></c8y-app-icon>\n </c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"p-r-8\">\n <p class=\"text-medium\" [innerText]=\"app | humanizeAppName | async\"></p>\n <p class=\"small text-muted\">{{ app.description }}</p>\n </div>\n <span class=\"label m-l-auto a-s-start\" [ngClass]=\"app | appState: 'class'\">\n {{ app | appState: 'label' | translate }}\n </span>\n </div>\n </c8y-li>\n </c8y-list-group>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ textConfig.applyButton | translate }}\"\n [disabled]=\"appsToUpdateRemotes.length === 0\"\n (click)=\"apply()\"\n >\n {{ textConfig.applyButton | translate }}\n </button>\n </div>\n</div>\n<ng-template #emptyList>\n <c8y-ui-empty-state\n [icon]=\"'c8y-modules'\"\n [title]=\"'No custom applications available.' | translate\"\n *ngIf=\"updateType !== 'install'\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <ng-container *ngIf=\"updateType === 'install'\">\n <c8y-ui-empty-state\n [icon]=\"'c8y-modules'\"\n [title]=\"'No custom applications available.' | translate\"\n [subtitle]=\"'Create a custom application by duplicating an existing one.' | translate\"\n [horizontal]=\"true\"\n >\n <button\n class=\"btn btn-sm btn-default m-t-8\"\n title=\"{{ 'Duplicate' | translate }}\"\n (click)=\"duplicateApp()\"\n >\n {{ 'Duplicate' | translate }}\n </button>\n </c8y-ui-empty-state>\n </ng-container>\n</ng-template>\n" }]
111
- }], ctorParameters: () => [{ type: i1$1.BsModalRef }, { type: i2.WizardModalService }, { type: i1.EcosystemService }], propDecorators: { apps: [{
112
+ }], ctorParameters: () => [{ type: i1.BsModalRef }, { type: i2.WizardModalService }, { type: i3.EcosystemService }], propDecorators: { apps: [{
112
113
  type: Input
113
114
  }], updateType: [{
114
115
  type: Input
@@ -118,71 +119,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
118
119
  type: Input
119
120
  }] } });
120
121
 
121
- class PluginListItemComponent {
122
- constructor(pluginService) {
123
- this.pluginService = pluginService;
124
- this.hideSource = false;
125
- this.isItemSelected = new EventEmitter();
126
- this.packageType = PackageType.UNKNOWN;
127
- this.PACKAGE_TYPE = PackageType;
128
- }
129
- ngOnInit() {
130
- this.packageType = this.pluginService.getPackageType(this.plugin.originApp);
131
- }
132
- onChange(event) {
133
- this.plugin.selected = !this.plugin.selected;
134
- this.isItemSelected.next(event);
135
- }
136
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListItemComponent, deps: [{ token: i2.PluginsService }], target: i0.ɵɵFactoryTarget.Component }); }
137
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: PluginListItemComponent, selector: "c8y-plugin-list-item", inputs: { plugin: "plugin", selectable: "selectable", hideSource: "hideSource" }, outputs: { isItemSelected: "isItemSelected" }, ngImport: i0, template: "<c8y-li-checkbox\n class=\"p-r-16 p-l-0\"\n (change)=\"onChange($event.target.checked)\"\n *ngIf=\"selectable\"\n [disabled]=\"plugin.installed\"\n [selected]=\"plugin.selected\"\n></c8y-li-checkbox>\n<c8y-li-icon class=\"p-l-0 text-center\">\n <i class=\"c8y-plugin-icon\">\n <span>{{ plugin.name?.substr(0, 2) }}</span>\n </i>\n</c8y-li-icon>\n<div class=\"p-relative\">\n <div [ngClass]=\"{ 'p-r-8': selectable }\">\n <p>\n <span class=\"text-medium\">{{ plugin.name }}</span>\n <em class=\"text-muted small m-l-8\">{{ plugin.version }}</em>\n <span *ngIf=\"plugin.installed\">\n <i\n class=\"text-success\"\n [c8yIcon]=\"'check-circle'\"\n ></i>\n <em\n class=\"text-muted small\"\n translate\n >\n Installed`plugins`\n </em>\n </span>\n </p>\n <p class=\"small l-h-tight\">{{ plugin.description }}</p>\n </div>\n\n <span\n class=\"tag tag--info a-s-start m-t-8\"\n *ngIf=\"selectable && !hideSource\"\n >\n {{ plugin.contextPath }}\n </span>\n\n <span\n class=\"tag a-s-start m-t-8 m-l-4\"\n [ngClass]=\"{\n 'tag--default': packageType === PACKAGE_TYPE.COMMUNITY,\n 'tag--primary': packageType === PACKAGE_TYPE.OFFICIAL\n }\"\n >\n {{ plugin.originApp?.label || plugin.originApp?.manifest?.label | translatePackageLabel }}\n </span>\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.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i2.ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "pipe", type: i1.TranslatePackageLabelPipe, name: "translatePackageLabel" }] }); }
138
- }
139
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListItemComponent, decorators: [{
140
- type: Component,
141
- args: [{ selector: 'c8y-plugin-list-item', template: "<c8y-li-checkbox\n class=\"p-r-16 p-l-0\"\n (change)=\"onChange($event.target.checked)\"\n *ngIf=\"selectable\"\n [disabled]=\"plugin.installed\"\n [selected]=\"plugin.selected\"\n></c8y-li-checkbox>\n<c8y-li-icon class=\"p-l-0 text-center\">\n <i class=\"c8y-plugin-icon\">\n <span>{{ plugin.name?.substr(0, 2) }}</span>\n </i>\n</c8y-li-icon>\n<div class=\"p-relative\">\n <div [ngClass]=\"{ 'p-r-8': selectable }\">\n <p>\n <span class=\"text-medium\">{{ plugin.name }}</span>\n <em class=\"text-muted small m-l-8\">{{ plugin.version }}</em>\n <span *ngIf=\"plugin.installed\">\n <i\n class=\"text-success\"\n [c8yIcon]=\"'check-circle'\"\n ></i>\n <em\n class=\"text-muted small\"\n translate\n >\n Installed`plugins`\n </em>\n </span>\n </p>\n <p class=\"small l-h-tight\">{{ plugin.description }}</p>\n </div>\n\n <span\n class=\"tag tag--info a-s-start m-t-8\"\n *ngIf=\"selectable && !hideSource\"\n >\n {{ plugin.contextPath }}\n </span>\n\n <span\n class=\"tag a-s-start m-t-8 m-l-4\"\n [ngClass]=\"{\n 'tag--default': packageType === PACKAGE_TYPE.COMMUNITY,\n 'tag--primary': packageType === PACKAGE_TYPE.OFFICIAL\n }\"\n >\n {{ plugin.originApp?.label || plugin.originApp?.manifest?.label | translatePackageLabel }}\n </span>\n</div>\n" }]
142
- }], ctorParameters: () => [{ type: i2.PluginsService }], propDecorators: { plugin: [{
143
- type: Input
144
- }], selectable: [{
145
- type: Input
146
- }], hideSource: [{
147
- type: Input
148
- }], isItemSelected: [{
149
- type: Output
150
- }] } });
151
-
152
- class PluginListComponent {
153
- constructor(ecosystemService, bsModalService, pluginsService, alertService, translateService, gainsightService, humanizeAppNamePipe) {
154
- this.ecosystemService = ecosystemService;
155
- this.bsModalService = bsModalService;
156
- this.pluginsService = pluginsService;
157
- this.alertService = alertService;
158
- this.translateService = translateService;
159
- this.gainsightService = gainsightService;
160
- this.humanizeAppNamePipe = humanizeAppNamePipe;
122
+ class PluginListService {
123
+ constructor() {
161
124
  this.CURRENT_LOCATION = location.href;
162
- this.emptyListText = '';
163
- this.hideSource = false;
164
- /**
165
- * Shows the install button for each plugin separately. Currently used in package-details view.
166
- */
167
- this.installable = false;
168
- this.selectedItems = new EventEmitter();
169
- this.remotePlugins$ = new BehaviorSubject({});
170
- this.selectedPlugins = {};
171
125
  this.updatingPluginId = { install: '', uninstall: '' };
172
126
  this.appsDisabled = new Set();
173
- }
174
- updateSelectedItems(selected, plugin) {
175
- this.selectedPlugins[plugin.id] = selected ? plugin : undefined;
176
- const onlyInstalledPlugins = Object.values(this.selectedPlugins).filter(Boolean);
177
- this.selectedItems.emit(onlyInstalledPlugins);
178
- }
179
- async installPlugin(plugin) {
180
- await this.updateAppRemotes(plugin, 'install');
181
- }
182
- async uninstallPlugin(plugin) {
183
- await this.updateAppRemotes(plugin, 'uninstall');
184
- }
185
- async updateAppRemotes(plugin, updateType) {
127
+ this.gainsightService = inject(GainsightService);
128
+ this.pluginsService = inject(PluginsService);
129
+ this.alertService = inject(AlertService);
130
+ this.ecosystemService = inject(EcosystemService);
131
+ this.humanizeAppNamePipe = inject(HumanizeAppNamePipe);
132
+ this.translateService = inject(TranslateService);
133
+ this.bsModalService = inject(BsModalService);
134
+ }
135
+ async updateAppRemotes(plugin, updateType, pluginPackage) {
186
136
  this.updatingPluginId[updateType] = plugin?.id;
187
137
  let initialState;
188
138
  try {
@@ -230,7 +180,7 @@ class PluginListComponent {
230
180
  continue;
231
181
  }
232
182
  }
233
- await this.handleRemotesUpdate(app, plugin, updateType);
183
+ await this.handleRemotesUpdate(app, plugin, updateType, pluginPackage);
234
184
  const humanizedAppName = await firstValueFrom(this.humanizeAppNamePipe.transform(app));
235
185
  const successText = updateType === 'install'
236
186
  ? this.translateService.instant(gettext('Plugin installed to application "{{ appName }}".'), {
@@ -246,6 +196,27 @@ class PluginListComponent {
246
196
  }
247
197
  this.updatingPluginId[updateType] = '';
248
198
  }
199
+ async getAppsForUpdate(plugin, updateType) {
200
+ let apps = (await this.ecosystemService.getWebApplications()).filter(app => this.ecosystemService.isOwner(app) && app.type !== ApplicationType.EXTERNAL);
201
+ if (updateType === 'install') {
202
+ this.appsDisabled.clear();
203
+ for (const app of apps) {
204
+ if (this.isPluginInstalledInApp(plugin, app)) {
205
+ this.appsDisabled.add(app.id);
206
+ }
207
+ }
208
+ }
209
+ if (updateType === 'uninstall') {
210
+ const installedApps = [];
211
+ for (const app of apps) {
212
+ if (this.isPluginInstalledInApp(plugin, app)) {
213
+ installedApps.push(app);
214
+ }
215
+ }
216
+ apps = installedApps;
217
+ }
218
+ return apps;
219
+ }
249
220
  onUpdateEventHandleGS(plugin, app, updateType, error) {
250
221
  const pluginCustomEventInfo = pick(plugin, [
251
222
  'name',
@@ -269,27 +240,6 @@ class PluginListComponent {
269
240
  };
270
241
  this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.PACKAGE_PLUGINS, eventData);
271
242
  }
272
- async getAppsForUpdate(plugin, updateType) {
273
- let apps = (await this.ecosystemService.getWebApplications()).filter(app => this.ecosystemService.isOwner(app) && app.type !== ApplicationType.EXTERNAL);
274
- if (updateType === 'install') {
275
- this.appsDisabled.clear();
276
- for (const app of apps) {
277
- if (this.isPluginInstalledInApp(plugin, app)) {
278
- this.appsDisabled.add(app.id);
279
- }
280
- }
281
- }
282
- if (updateType === 'uninstall') {
283
- const installedApps = [];
284
- for (const app of apps) {
285
- if (this.isPluginInstalledInApp(plugin, app)) {
286
- installedApps.push(app);
287
- }
288
- }
289
- apps = installedApps;
290
- }
291
- return apps;
292
- }
293
243
  isPluginInstalledInApp(plugin, app) {
294
244
  const appRemotes = this.pluginsService.getMFRemotes(app) || {};
295
245
  for (const [remoteName, modules] of Object.entries(appRemotes)) {
@@ -304,20 +254,20 @@ class PluginListComponent {
304
254
  getPluginContextPathWithoutVersion(remote) {
305
255
  return remote.split('@')[0];
306
256
  }
307
- async handleRemotesUpdate(application, plugin, updateType) {
257
+ async handleRemotesUpdate(application, plugin, updateType, pluginPackage) {
308
258
  try {
309
259
  // When remotes object is not set in the configuration object of an application.
310
260
  // Fallback to setInitialRemotes is triggered.
311
261
  const { remotes, excludedRemotes } = await (updateType === 'install'
312
262
  ? this.pluginsService.addRemotes(application, plugin)
313
- : this.pluginsService.removeRemotes(application, this.getAllPluginsToRemove(plugin)));
263
+ : this.pluginsService.removeRemotes(application, this.getAllPluginsToRemove(plugin, pluginPackage)));
314
264
  if (!application.config) {
315
265
  application.config = {};
316
266
  }
317
267
  application.config.remotes = remotes;
318
268
  application.config.excludedRemotes = excludedRemotes;
319
269
  const actualRemotes = this.pluginsService.getMFRemotes(application);
320
- return this.emitRemotes(actualRemotes);
270
+ return actualRemotes;
321
271
  }
322
272
  catch (er) {
323
273
  if (er) {
@@ -326,18 +276,14 @@ class PluginListComponent {
326
276
  throw er;
327
277
  }
328
278
  }
329
- getAllPluginsToRemove(plugin) {
330
- return this.package.applicationVersions.map(av => ({
279
+ getAllPluginsToRemove(plugin, pluginPackage) {
280
+ return pluginPackage.applicationVersions.map(av => ({
331
281
  id: `${plugin.contextPath}@${av.version}/${plugin.module}`,
332
282
  idLatest: `${plugin.contextPath}/${plugin.module}`,
333
283
  module: plugin.module,
334
284
  path: plugin.path
335
285
  }));
336
286
  }
337
- emitRemotes(remotes) {
338
- this.remotePlugins$.next(remotes);
339
- return { ...this.remotePlugins$.value };
340
- }
341
287
  async selectApps(initialState) {
342
288
  try {
343
289
  return await this.bsModalService.show(AppsToUpdateRemotesSelectComponent, {
@@ -353,13 +299,86 @@ class PluginListComponent {
353
299
  return;
354
300
  }
355
301
  }
356
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListComponent, deps: [{ token: i1.EcosystemService }, { token: i1$1.BsModalService }, { token: i2.PluginsService }, { token: i2.AlertService }, { token: i4.TranslateService }, { token: i2.GainsightService }, { token: i2.HumanizeAppNamePipe }], target: i0.ɵɵFactoryTarget.Component }); }
357
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: PluginListComponent, selector: "c8y-plugin-list", inputs: { plugins$: "plugins$", emptyListText: "emptyListText", selectable: "selectable", hideSource: "hideSource", installable: "installable", package: "package" }, outputs: { selectedItems: "selectedItems" }, ngImport: i0, template: "<c8y-list-group class=\"bg-inherit\">\n <ng-container *ngIf=\"(plugins$ | async)?.length !== 0; else emptyList\">\n <ng-container *ngFor=\"let plugin of plugins$ | async\">\n <c8y-li [ngClass]=\"{ disabled: plugin.installed }\" class=\"bg-inherit\">\n <c8y-plugin-list-item\n (isItemSelected)=\"updateSelectedItems($event, plugin)\"\n [plugin]=\"plugin\"\n [selectable]=\"selectable\"\n [hideSource]=\"hideSource\"\n class=\"d-flex\"\n ></c8y-plugin-list-item>\n <div class=\"p-l-40 m-t-4\">\n <button\n *ngIf=\"installable\"\n (click)=\"uninstallPlugin(plugin)\"\n [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.uninstall }\"\n [disabled]=\"updatingPluginId.uninstall && plugin.id !== updatingPluginId.uninstall\"\n class=\"btn btn-danger btn-sm m-l-4\"\n title=\"{{ 'Uninstall plugin' | translate }}\"\n data-cy=\"plugin-list--uninstall-plugin-button\"\n translate\n >\n Uninstall plugin\n </button>\n <button\n *ngIf=\"installable\"\n (click)=\"installPlugin(plugin)\"\n [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.install }\"\n [disabled]=\"updatingPluginId.install && plugin.id !== updatingPluginId.install\"\n class=\"btn btn-default btn-sm m-l-8\"\n title=\"{{ 'Install plugin' | translate }}\"\n data-cy=\"plugin-list--install-plugin-button\"\n translate\n >\n Install plugin\n </button>\n </div>\n </c8y-li>\n </ng-container>\n </ng-container>\n</c8y-list-group>\n<ng-template #emptyList>\n <div class=\"c8y-empty-state text-left\" *ngIf=\"emptyListText\">\n <h1 c8yIcon=\"plugin\"></h1>\n <p>\n {{ emptyListText | translate }}\n </p>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i2.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: PluginListItemComponent, selector: "c8y-plugin-list-item", inputs: ["plugin", "selectable", "hideSource"], outputs: ["isItemSelected"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
302
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
303
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListService, providedIn: 'root' }); }
304
+ }
305
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListService, decorators: [{
306
+ type: Injectable,
307
+ args: [{
308
+ providedIn: 'root'
309
+ }]
310
+ }] });
311
+
312
+ class PluginListItemComponent {
313
+ constructor(pluginService) {
314
+ this.pluginService = pluginService;
315
+ this.hideSource = false;
316
+ this.isItemSelected = new EventEmitter();
317
+ this.packageType = PackageType.UNKNOWN;
318
+ this.PACKAGE_TYPE = PackageType;
319
+ }
320
+ ngOnInit() {
321
+ this.packageType = this.pluginService.getPackageType(this.plugin.originApp);
322
+ }
323
+ onChange(event) {
324
+ this.plugin.selected = !this.plugin.selected;
325
+ this.isItemSelected.next(event);
326
+ }
327
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListItemComponent, deps: [{ token: i2.PluginsService }], target: i0.ɵɵFactoryTarget.Component }); }
328
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: PluginListItemComponent, selector: "c8y-plugin-list-item", inputs: { plugin: "plugin", selectable: "selectable", hideSource: "hideSource" }, outputs: { isItemSelected: "isItemSelected" }, ngImport: i0, template: "<c8y-li-checkbox\n class=\"p-r-16 p-l-0\"\n (change)=\"onChange($event.target.checked)\"\n *ngIf=\"selectable\"\n [disabled]=\"plugin.installed\"\n [selected]=\"plugin.selected\"\n></c8y-li-checkbox>\n<c8y-li-icon class=\"p-l-0 text-center\">\n <i class=\"c8y-plugin-icon\">\n <span>{{ plugin.name?.substr(0, 2) }}</span>\n </i>\n</c8y-li-icon>\n<div class=\"p-relative flex-grow\">\n <div [ngClass]=\"{ 'p-r-8': selectable }\">\n <p>\n <span class=\"text-medium\">{{ plugin.name }}</span>\n <em class=\"text-muted small m-l-8\">{{ plugin.version }}</em>\n <span *ngIf=\"plugin.installed\">\n <i\n class=\"text-success\"\n [c8yIcon]=\"'check-circle'\"\n ></i>\n <em\n class=\"text-muted small\"\n translate\n >\n Installed`plugins`\n </em>\n </span>\n </p>\n <p class=\"small l-h-tight\">{{ plugin.description }}</p>\n </div>\n\n <span\n class=\"tag tag--info a-s-start m-t-8\"\n *ngIf=\"selectable && !hideSource\"\n >\n {{ plugin.contextPath }}\n </span>\n\n <span\n class=\"tag a-s-start m-t-8 m-l-4\"\n [ngClass]=\"{\n 'tag--default': packageType === PACKAGE_TYPE.COMMUNITY,\n 'tag--primary': packageType === PACKAGE_TYPE.OFFICIAL\n }\"\n >\n {{ plugin.originApp?.label || plugin.originApp?.manifest?.label | translatePackageLabel }}\n </span>\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: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i2.ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "pipe", type: i3.TranslatePackageLabelPipe, name: "translatePackageLabel" }] }); }
329
+ }
330
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListItemComponent, decorators: [{
331
+ type: Component,
332
+ args: [{ selector: 'c8y-plugin-list-item', template: "<c8y-li-checkbox\n class=\"p-r-16 p-l-0\"\n (change)=\"onChange($event.target.checked)\"\n *ngIf=\"selectable\"\n [disabled]=\"plugin.installed\"\n [selected]=\"plugin.selected\"\n></c8y-li-checkbox>\n<c8y-li-icon class=\"p-l-0 text-center\">\n <i class=\"c8y-plugin-icon\">\n <span>{{ plugin.name?.substr(0, 2) }}</span>\n </i>\n</c8y-li-icon>\n<div class=\"p-relative flex-grow\">\n <div [ngClass]=\"{ 'p-r-8': selectable }\">\n <p>\n <span class=\"text-medium\">{{ plugin.name }}</span>\n <em class=\"text-muted small m-l-8\">{{ plugin.version }}</em>\n <span *ngIf=\"plugin.installed\">\n <i\n class=\"text-success\"\n [c8yIcon]=\"'check-circle'\"\n ></i>\n <em\n class=\"text-muted small\"\n translate\n >\n Installed`plugins`\n </em>\n </span>\n </p>\n <p class=\"small l-h-tight\">{{ plugin.description }}</p>\n </div>\n\n <span\n class=\"tag tag--info a-s-start m-t-8\"\n *ngIf=\"selectable && !hideSource\"\n >\n {{ plugin.contextPath }}\n </span>\n\n <span\n class=\"tag a-s-start m-t-8 m-l-4\"\n [ngClass]=\"{\n 'tag--default': packageType === PACKAGE_TYPE.COMMUNITY,\n 'tag--primary': packageType === PACKAGE_TYPE.OFFICIAL\n }\"\n >\n {{ plugin.originApp?.label || plugin.originApp?.manifest?.label | translatePackageLabel }}\n </span>\n</div>\n" }]
333
+ }], ctorParameters: () => [{ type: i2.PluginsService }], propDecorators: { plugin: [{
334
+ type: Input
335
+ }], selectable: [{
336
+ type: Input
337
+ }], hideSource: [{
338
+ type: Input
339
+ }], isItemSelected: [{
340
+ type: Output
341
+ }] } });
342
+
343
+ class PluginListComponent {
344
+ constructor(pluginListService) {
345
+ this.pluginListService = pluginListService;
346
+ this.CURRENT_LOCATION = location.href;
347
+ this.emptyListText = '';
348
+ this.hideSource = false;
349
+ /**
350
+ * Shows the install button for each plugin separately. Currently used in package-details view.
351
+ */
352
+ this.installable = false;
353
+ this.selectedItems = new EventEmitter();
354
+ this.showOverview = new EventEmitter();
355
+ this.selectedPlugins = {};
356
+ this.updatingPluginId = this.pluginListService.updatingPluginId;
357
+ }
358
+ updateSelectedItems(selected, plugin) {
359
+ this.selectedPlugins[plugin.id] = selected ? plugin : undefined;
360
+ const onlyInstalledPlugins = Object.values(this.selectedPlugins).filter(Boolean);
361
+ this.selectedItems.emit(onlyInstalledPlugins);
362
+ }
363
+ showPluginOverview(plugin) {
364
+ if (plugin?.id === this.selectedPlugin?.id) {
365
+ return;
366
+ }
367
+ this.showOverview.emit(plugin);
368
+ }
369
+ async installPlugin(plugin) {
370
+ await this.pluginListService.updateAppRemotes(plugin, 'install', this.package);
371
+ }
372
+ async uninstallPlugin(plugin) {
373
+ await this.pluginListService.updateAppRemotes(plugin, 'uninstall', this.package);
374
+ }
375
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListComponent, deps: [{ token: PluginListService }], target: i0.ɵɵFactoryTarget.Component }); }
376
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: PluginListComponent, selector: "c8y-plugin-list", inputs: { plugins$: "plugins$", emptyListText: "emptyListText", selectable: "selectable", hideSource: "hideSource", installable: "installable", package: "package", selectedPlugin: "selectedPlugin" }, outputs: { selectedItems: "selectedItems", showOverview: "showOverview" }, ngImport: i0, template: "<c8y-list-group class=\"bg-inherit\">\n <ng-container *ngIf=\"(plugins$ | async)?.length !== 0; else emptyList\">\n <ng-container *ngFor=\"let plugin of plugins$ | async\">\n <c8y-li\n [ngClass]=\"{\n disabled: plugin.installed,\n selected: selectedPlugin?.id === plugin?.id\n }\"\n >\n <div class=\"d-flex fit-w\">\n <ng-container *ngIf=\"plugin.readmePath\">\n <button\n class=\"c8y-list__item__btn d-flex fit-w gap-4\"\n title=\"{{ 'Details' | translate }}\"\n (click)=\"showPluginOverview(plugin)\"\n >\n <c8y-plugin-list-item\n class=\"d-contents\"\n (isItemSelected)=\"updateSelectedItems($event, plugin)\"\n [plugin]=\"plugin\"\n [selectable]=\"selectable\"\n [hideSource]=\"hideSource\"\n ></c8y-plugin-list-item>\n <i\n class=\"icon-24 m-l-auto a-s-center\"\n c8yIcon=\"forward\"\n ></i>\n </button>\n </ng-container>\n <ng-container *ngIf=\"!plugin.readmePath\">\n <c8y-plugin-list-item\n class=\"d-contents\"\n (isItemSelected)=\"updateSelectedItems($event, plugin)\"\n [plugin]=\"plugin\"\n [selectable]=\"selectable\"\n [hideSource]=\"hideSource\"\n ></c8y-plugin-list-item>\n </ng-container>\n </div>\n <div class=\"p-l-40 m-t-4 d-flex flex-wrap gap-8\">\n <button\n class=\"btn btn-danger btn-sm\"\n title=\"{{ 'Uninstall plugin' | translate }}\"\n *ngIf=\"installable\"\n (click)=\"uninstallPlugin(plugin)\"\n [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.uninstall }\"\n [disabled]=\"updatingPluginId.uninstall && plugin.id === updatingPluginId.uninstall\"\n data-cy=\"plugin-list--uninstall-plugin-button\"\n translate\n >\n Uninstall plugin\n </button>\n <button\n class=\"btn btn-default btn-sm m-0\"\n title=\"{{ 'Install plugin' | translate }}\"\n *ngIf=\"installable\"\n (click)=\"installPlugin(plugin)\"\n [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.install }\"\n [disabled]=\"updatingPluginId.install && plugin.id === updatingPluginId.install\"\n data-cy=\"plugin-list--install-plugin-button\"\n translate\n >\n Install plugin\n </button>\n </div>\n </c8y-li>\n </ng-container>\n </ng-container>\n</c8y-list-group>\n<ng-template #emptyList>\n <c8y-ui-empty-state\n [icon]=\"'plugin'\"\n [title]=\"emptyListText | translate\"\n [horizontal]=\"true\"\n *ngIf=\"emptyListText\"\n ></c8y-ui-empty-state>\n</ng-template>\n", dependencies: [{ 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: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i2.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: PluginListItemComponent, selector: "c8y-plugin-list-item", inputs: ["plugin", "selectable", "hideSource"], outputs: ["isItemSelected"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3$1.AsyncPipe, name: "async" }] }); }
358
377
  }
359
378
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PluginListComponent, decorators: [{
360
379
  type: Component,
361
- args: [{ selector: 'c8y-plugin-list', template: "<c8y-list-group class=\"bg-inherit\">\n <ng-container *ngIf=\"(plugins$ | async)?.length !== 0; else emptyList\">\n <ng-container *ngFor=\"let plugin of plugins$ | async\">\n <c8y-li [ngClass]=\"{ disabled: plugin.installed }\" class=\"bg-inherit\">\n <c8y-plugin-list-item\n (isItemSelected)=\"updateSelectedItems($event, plugin)\"\n [plugin]=\"plugin\"\n [selectable]=\"selectable\"\n [hideSource]=\"hideSource\"\n class=\"d-flex\"\n ></c8y-plugin-list-item>\n <div class=\"p-l-40 m-t-4\">\n <button\n *ngIf=\"installable\"\n (click)=\"uninstallPlugin(plugin)\"\n [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.uninstall }\"\n [disabled]=\"updatingPluginId.uninstall && plugin.id !== updatingPluginId.uninstall\"\n class=\"btn btn-danger btn-sm m-l-4\"\n title=\"{{ 'Uninstall plugin' | translate }}\"\n data-cy=\"plugin-list--uninstall-plugin-button\"\n translate\n >\n Uninstall plugin\n </button>\n <button\n *ngIf=\"installable\"\n (click)=\"installPlugin(plugin)\"\n [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.install }\"\n [disabled]=\"updatingPluginId.install && plugin.id !== updatingPluginId.install\"\n class=\"btn btn-default btn-sm m-l-8\"\n title=\"{{ 'Install plugin' | translate }}\"\n data-cy=\"plugin-list--install-plugin-button\"\n translate\n >\n Install plugin\n </button>\n </div>\n </c8y-li>\n </ng-container>\n </ng-container>\n</c8y-list-group>\n<ng-template #emptyList>\n <div class=\"c8y-empty-state text-left\" *ngIf=\"emptyListText\">\n <h1 c8yIcon=\"plugin\"></h1>\n <p>\n {{ emptyListText | translate }}\n </p>\n </div>\n</ng-template>\n" }]
362
- }], ctorParameters: () => [{ type: i1.EcosystemService }, { type: i1$1.BsModalService }, { type: i2.PluginsService }, { type: i2.AlertService }, { type: i4.TranslateService }, { type: i2.GainsightService }, { type: i2.HumanizeAppNamePipe }], propDecorators: { plugins$: [{
380
+ args: [{ selector: 'c8y-plugin-list', template: "<c8y-list-group class=\"bg-inherit\">\n <ng-container *ngIf=\"(plugins$ | async)?.length !== 0; else emptyList\">\n <ng-container *ngFor=\"let plugin of plugins$ | async\">\n <c8y-li\n [ngClass]=\"{\n disabled: plugin.installed,\n selected: selectedPlugin?.id === plugin?.id\n }\"\n >\n <div class=\"d-flex fit-w\">\n <ng-container *ngIf=\"plugin.readmePath\">\n <button\n class=\"c8y-list__item__btn d-flex fit-w gap-4\"\n title=\"{{ 'Details' | translate }}\"\n (click)=\"showPluginOverview(plugin)\"\n >\n <c8y-plugin-list-item\n class=\"d-contents\"\n (isItemSelected)=\"updateSelectedItems($event, plugin)\"\n [plugin]=\"plugin\"\n [selectable]=\"selectable\"\n [hideSource]=\"hideSource\"\n ></c8y-plugin-list-item>\n <i\n class=\"icon-24 m-l-auto a-s-center\"\n c8yIcon=\"forward\"\n ></i>\n </button>\n </ng-container>\n <ng-container *ngIf=\"!plugin.readmePath\">\n <c8y-plugin-list-item\n class=\"d-contents\"\n (isItemSelected)=\"updateSelectedItems($event, plugin)\"\n [plugin]=\"plugin\"\n [selectable]=\"selectable\"\n [hideSource]=\"hideSource\"\n ></c8y-plugin-list-item>\n </ng-container>\n </div>\n <div class=\"p-l-40 m-t-4 d-flex flex-wrap gap-8\">\n <button\n class=\"btn btn-danger btn-sm\"\n title=\"{{ 'Uninstall plugin' | translate }}\"\n *ngIf=\"installable\"\n (click)=\"uninstallPlugin(plugin)\"\n [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.uninstall }\"\n [disabled]=\"updatingPluginId.uninstall && plugin.id === updatingPluginId.uninstall\"\n data-cy=\"plugin-list--uninstall-plugin-button\"\n translate\n >\n Uninstall plugin\n </button>\n <button\n class=\"btn btn-default btn-sm m-0\"\n title=\"{{ 'Install plugin' | translate }}\"\n *ngIf=\"installable\"\n (click)=\"installPlugin(plugin)\"\n [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.install }\"\n [disabled]=\"updatingPluginId.install && plugin.id === updatingPluginId.install\"\n data-cy=\"plugin-list--install-plugin-button\"\n translate\n >\n Install plugin\n </button>\n </div>\n </c8y-li>\n </ng-container>\n </ng-container>\n</c8y-list-group>\n<ng-template #emptyList>\n <c8y-ui-empty-state\n [icon]=\"'plugin'\"\n [title]=\"emptyListText | translate\"\n [horizontal]=\"true\"\n *ngIf=\"emptyListText\"\n ></c8y-ui-empty-state>\n</ng-template>\n" }]
381
+ }], ctorParameters: () => [{ type: PluginListService }], propDecorators: { plugins$: [{
363
382
  type: Input
364
383
  }], emptyListText: [{
365
384
  type: Input
@@ -371,8 +390,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
371
390
  type: Input
372
391
  }], package: [{
373
392
  type: Input
393
+ }], selectedPlugin: [{
394
+ type: Input
374
395
  }], selectedItems: [{
375
396
  type: Output
397
+ }], showOverview: [{
398
+ type: Output
376
399
  }] } });
377
400
 
378
401
  class OnlyLatestFilterComponent {
@@ -385,18 +408,19 @@ class OnlyLatestFilterComponent {
385
408
  return !enabled || !!plugin.tags?.includes('latest');
386
409
  });
387
410
  }
388
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OnlyLatestFilterComponent, deps: [{ token: i1.ListFiltersComponent }], target: i0.ɵɵFactoryTarget.Component }); }
411
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OnlyLatestFilterComponent, deps: [{ token: i3.ListFiltersComponent }], target: i0.ɵɵFactoryTarget.Component }); }
389
412
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: OnlyLatestFilterComponent, selector: "c8y-only-latest-filter", ngImport: i0, template: "<label class=\"c8y-switch\">\n <input\n type=\"checkbox\"\n checked=\"checked\"\n [formControl]=\"onlyLatestFormControl\"\n />\n <span></span>\n {{ 'Show only latest version of plugins' | translate }}\n</label>\n", dependencies: [{ kind: "directive", type: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
390
413
  }
391
414
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OnlyLatestFilterComponent, decorators: [{
392
415
  type: Component,
393
416
  args: [{ selector: 'c8y-only-latest-filter', template: "<label class=\"c8y-switch\">\n <input\n type=\"checkbox\"\n checked=\"checked\"\n [formControl]=\"onlyLatestFormControl\"\n />\n <span></span>\n {{ 'Show only latest version of plugins' | translate }}\n</label>\n" }]
394
- }], ctorParameters: () => [{ type: i1.ListFiltersComponent }] });
417
+ }], ctorParameters: () => [{ type: i3.ListFiltersComponent }] });
395
418
 
396
419
  class InstallPluginComponent {
397
- constructor(bsModalRef, ecosystemService) {
398
- this.bsModalRef = bsModalRef;
420
+ constructor(bottomDrawerRef, ecosystemService, pluginsService) {
421
+ this.bottomDrawerRef = bottomDrawerRef;
399
422
  this.ecosystemService = ecosystemService;
423
+ this.pluginsService = pluginsService;
400
424
  this.filteredPlugins$ = new BehaviorSubject([]);
401
425
  this.selectedPlugins = [];
402
426
  this.packageTypes = defaultPackageTypes;
@@ -413,20 +437,26 @@ class InstallPluginComponent {
413
437
  })), src => filterPipe(src));
414
438
  }
415
439
  cancel() {
416
- this.bsModalRef.hide();
440
+ this.bottomDrawerRef.close();
417
441
  this._cancel();
418
442
  }
419
443
  install() {
420
444
  this._install(this.selectedPlugins);
421
- this.bsModalRef.hide();
445
+ this.bottomDrawerRef.close();
422
446
  }
423
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InstallPluginComponent, deps: [{ token: i1$1.BsModalRef }, { token: i1.EcosystemService }], target: i0.ɵɵFactoryTarget.Component }); }
424
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: InstallPluginComponent, selector: "c8y-install-plugin", inputs: { plugins$: "plugins$" }, ngImport: i0, template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'plugin'\"></i>\n <div\n class=\"modal-title h4\"\n id=\"modal-title\"\n translate\n >\n Available plugins\n </div>\n </div>\n <div class=\"p-t-8 p-16 text-center separator-bottom flex-no-shrink\">\n <p\n class=\"text-medium m-b-8\"\n translate\n >\n Select the compatible plugins to install\n </p>\n <c8y-list-filters\n (filterPipeChange)=\"setFilterPipe($event)\"\n [packageTypes]=\"packageTypes\"\n >\n <c8y-archived-filter></c8y-archived-filter>\n <c8y-only-latest-filter></c8y-only-latest-filter>\n </c8y-list-filters>\n </div>\n <div\n class=\"modal-inner-scroll\"\n id=\"modal-body\"\n >\n <c8y-plugin-list\n class=\"m-t-16\"\n (selectedItems)=\"selectedPlugins = $event\"\n [emptyListText]=\"'No plugins available' | translate\"\n [plugins$]=\"filteredPlugins$\"\n [selectable]=\"true\"\n ></c8y-plugin-list>\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 data-cy=\"install-plugin--cancel-button\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Install' | translate }}\"\n type=\"button\"\n (click)=\"install()\"\n [disabled]=\"selectedPlugins.length === 0\"\n data-cy=\"install-plugin--install-button\"\n >\n {{ 'Install' | translate }}\n <span\n class=\"badge\"\n *ngIf=\"selectedPlugins.length as length\"\n >\n {{ length }}\n </span>\n </button>\n </div>\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.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i1.ListFiltersComponent, selector: "c8y-list-filters", inputs: ["packageTypes", "packageAvailabilities", "packageContents"], outputs: ["filterPipeChange"] }, { kind: "component", type: i1.ArchivedFilterComponent, selector: "c8y-archived-filter" }, { kind: "component", type: PluginListComponent, selector: "c8y-plugin-list", inputs: ["plugins$", "emptyListText", "selectable", "hideSource", "installable", "package"], outputs: ["selectedItems"] }, { kind: "component", type: OnlyLatestFilterComponent, selector: "c8y-only-latest-filter" }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
447
+ async showPluginOverview(plugin) {
448
+ this.selectedPlugin = plugin;
449
+ const baseUrl = `/apps/${plugin.id}/`;
450
+ this.pluginBaseUrl = baseUrl;
451
+ this.pluginMarkdown = await this.pluginsService.getReadmeFileContent(baseUrl);
452
+ }
453
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InstallPluginComponent, deps: [{ token: i2.BottomDrawerRef }, { token: i3.EcosystemService }, { token: i2.PluginsService }], target: i0.ɵɵFactoryTarget.Component }); }
454
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: InstallPluginComponent, selector: "c8y-install-plugin", inputs: { plugins$: "plugins$" }, host: { classAttribute: "d-contents" }, ngImport: i0, template: " <div class=\"card-header gap-8 d-col p-l-24 p-r-24 separator-bottom flex-no-shrink\">\n <div\n class=\"card-title h4 text-center\"\n translate\n >\n Available plugins\n </div>\n <c8y-list-filters\n (filterPipeChange)=\"setFilterPipe($event)\"\n [packageTypes]=\"packageTypes\"\n >\n <c8y-archived-filter></c8y-archived-filter>\n <c8y-only-latest-filter></c8y-only-latest-filter>\n </c8y-list-filters>\n </div>\n <div class=\"d-grid grid__col--5-7--md min-height-0 flex-grow\">\n <c8y-plugin-list\n class=\"inner-scroll bg-level-1\"\n (selectedItems)=\"selectedPlugins = $event\"\n [emptyListText]=\"'No matching plugins' | translate\"\n [plugins$]=\"filteredPlugins$\"\n [selectable]=\"true\"\n [selectedPlugin]=\"selectedPlugin\"\n (showOverview)=\"showPluginOverview($event)\"\n ></c8y-plugin-list>\n <div class=\"inner-scroll bg-component\">\n <div class=\"card-header separator sticky-top bg-inherit\"\n *ngIf=\"pluginMarkdown\">\n <button\n class=\"m-l-auto btn-clean\"\n title=\"{{ 'Close' | translate }}\"\n type=\"button\"\n (click)=\"selectedPlugin = null; pluginMarkdown = null\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n </div>\n <div class=\"card-block p-l-24 p-r-24\">\n <div\n class=\"markdown-content\"\n *ngIf=\"pluginMarkdown\"\n [innerHTML]=\"pluginMarkdown | markdownToHtml: { baseUrl: pluginBaseUrl } | async\"\n ></div>\n <c8y-ui-empty-state\n [icon]=\"'user-manual'\"\n [title]=\"'No plugin selected' | translate\"\n [subtitle]=\"\n 'Select a plugin from the list to view its documentation.' | translate\"\n *ngIf=\"!pluginMarkdown\"\n [horizontal]=\"true\"\n >\n <p>\n <small >\n {{ 'Documentation availability varies by plugin.' | translate }}\n </small>\n </p>\n </c8y-ui-empty-state>\n </div>\n </div>\n </div>\n <div class=\"text-center card-footer p-24 separator\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n data-cy=\"install-plugin--cancel-button\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Install' | translate }}\"\n type=\"button\"\n (click)=\"install()\"\n [disabled]=\"selectedPlugins.length === 0\"\n data-cy=\"install-plugin--install-button\"\n >\n {{ 'Install' | translate }}\n <span\n class=\"badge\"\n *ngIf=\"selectedPlugins.length as length\"\n >\n {{ length }}\n </span>\n </button>\n </div>\n\n", dependencies: [{ 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: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.ListFiltersComponent, selector: "c8y-list-filters", inputs: ["packageTypes", "packageAvailabilities", "packageContents"], outputs: ["filterPipeChange"] }, { kind: "component", type: i3.ArchivedFilterComponent, selector: "c8y-archived-filter" }, { kind: "component", type: PluginListComponent, selector: "c8y-plugin-list", inputs: ["plugins$", "emptyListText", "selectable", "hideSource", "installable", "package", "selectedPlugin"], outputs: ["selectedItems", "showOverview"] }, { kind: "component", type: OnlyLatestFilterComponent, selector: "c8y-only-latest-filter" }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.MarkdownToHtmlPipe, name: "markdownToHtml" }] }); }
425
455
  }
426
456
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InstallPluginComponent, decorators: [{
427
457
  type: Component,
428
- args: [{ selector: 'c8y-install-plugin', template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'plugin'\"></i>\n <div\n class=\"modal-title h4\"\n id=\"modal-title\"\n translate\n >\n Available plugins\n </div>\n </div>\n <div class=\"p-t-8 p-16 text-center separator-bottom flex-no-shrink\">\n <p\n class=\"text-medium m-b-8\"\n translate\n >\n Select the compatible plugins to install\n </p>\n <c8y-list-filters\n (filterPipeChange)=\"setFilterPipe($event)\"\n [packageTypes]=\"packageTypes\"\n >\n <c8y-archived-filter></c8y-archived-filter>\n <c8y-only-latest-filter></c8y-only-latest-filter>\n </c8y-list-filters>\n </div>\n <div\n class=\"modal-inner-scroll\"\n id=\"modal-body\"\n >\n <c8y-plugin-list\n class=\"m-t-16\"\n (selectedItems)=\"selectedPlugins = $event\"\n [emptyListText]=\"'No plugins available' | translate\"\n [plugins$]=\"filteredPlugins$\"\n [selectable]=\"true\"\n ></c8y-plugin-list>\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 data-cy=\"install-plugin--cancel-button\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Install' | translate }}\"\n type=\"button\"\n (click)=\"install()\"\n [disabled]=\"selectedPlugins.length === 0\"\n data-cy=\"install-plugin--install-button\"\n >\n {{ 'Install' | translate }}\n <span\n class=\"badge\"\n *ngIf=\"selectedPlugins.length as length\"\n >\n {{ length }}\n </span>\n </button>\n </div>\n</div>\n" }]
429
- }], ctorParameters: () => [{ type: i1$1.BsModalRef }, { type: i1.EcosystemService }], propDecorators: { plugins$: [{
458
+ args: [{ selector: 'c8y-install-plugin', host: { class: 'd-contents' }, template: " <div class=\"card-header gap-8 d-col p-l-24 p-r-24 separator-bottom flex-no-shrink\">\n <div\n class=\"card-title h4 text-center\"\n translate\n >\n Available plugins\n </div>\n <c8y-list-filters\n (filterPipeChange)=\"setFilterPipe($event)\"\n [packageTypes]=\"packageTypes\"\n >\n <c8y-archived-filter></c8y-archived-filter>\n <c8y-only-latest-filter></c8y-only-latest-filter>\n </c8y-list-filters>\n </div>\n <div class=\"d-grid grid__col--5-7--md min-height-0 flex-grow\">\n <c8y-plugin-list\n class=\"inner-scroll bg-level-1\"\n (selectedItems)=\"selectedPlugins = $event\"\n [emptyListText]=\"'No matching plugins' | translate\"\n [plugins$]=\"filteredPlugins$\"\n [selectable]=\"true\"\n [selectedPlugin]=\"selectedPlugin\"\n (showOverview)=\"showPluginOverview($event)\"\n ></c8y-plugin-list>\n <div class=\"inner-scroll bg-component\">\n <div class=\"card-header separator sticky-top bg-inherit\"\n *ngIf=\"pluginMarkdown\">\n <button\n class=\"m-l-auto btn-clean\"\n title=\"{{ 'Close' | translate }}\"\n type=\"button\"\n (click)=\"selectedPlugin = null; pluginMarkdown = null\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n </div>\n <div class=\"card-block p-l-24 p-r-24\">\n <div\n class=\"markdown-content\"\n *ngIf=\"pluginMarkdown\"\n [innerHTML]=\"pluginMarkdown | markdownToHtml: { baseUrl: pluginBaseUrl } | async\"\n ></div>\n <c8y-ui-empty-state\n [icon]=\"'user-manual'\"\n [title]=\"'No plugin selected' | translate\"\n [subtitle]=\"\n 'Select a plugin from the list to view its documentation.' | translate\"\n *ngIf=\"!pluginMarkdown\"\n [horizontal]=\"true\"\n >\n <p>\n <small >\n {{ 'Documentation availability varies by plugin.' | translate }}\n </small>\n </p>\n </c8y-ui-empty-state>\n </div>\n </div>\n </div>\n <div class=\"text-center card-footer p-24 separator\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n data-cy=\"install-plugin--cancel-button\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Install' | translate }}\"\n type=\"button\"\n (click)=\"install()\"\n [disabled]=\"selectedPlugins.length === 0\"\n data-cy=\"install-plugin--install-button\"\n >\n {{ 'Install' | translate }}\n <span\n class=\"badge\"\n *ngIf=\"selectedPlugins.length as length\"\n >\n {{ length }}\n </span>\n </button>\n </div>\n\n" }]
459
+ }], ctorParameters: () => [{ type: i2.BottomDrawerRef }, { type: i3.EcosystemService }, { type: i2.PluginsService }], propDecorators: { plugins$: [{
430
460
  type: Input
431
461
  }] } });
432
462
 
@@ -484,7 +514,7 @@ class OrphanedStatusCellRendererComponent {
484
514
  }
485
515
  }
486
516
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OrphanedStatusCellRendererComponent, deps: [{ token: i2.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
487
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: OrphanedStatusCellRendererComponent, selector: "c8y-orphaned-status-cell-renderer", ngImport: i0, template: "<span\n *ngIf=\"label\"\n class=\"label\"\n [ngClass]=\"label.class\"\n [title]=\"label.text | translate\"\n>\n {{ label.text | translate }}\n</span>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
517
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: OrphanedStatusCellRendererComponent, selector: "c8y-orphaned-status-cell-renderer", ngImport: i0, template: "<span\n *ngIf=\"label\"\n class=\"label\"\n [ngClass]=\"label.class\"\n [title]=\"label.text | translate\"\n>\n {{ label.text | translate }}\n</span>\n", dependencies: [{ kind: "directive", type: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
488
518
  }
489
519
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OrphanedStatusCellRendererComponent, decorators: [{
490
520
  type: Component,
@@ -583,22 +613,44 @@ class UpdatePluginOfAppComponent {
583
613
  this.bsModalRef.hide();
584
614
  this._cancel();
585
615
  }
586
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UpdatePluginOfAppComponent, deps: [{ token: i1$1.BsModalRef }, { token: i2.PluginsService }, { token: i2.AlertService }, { token: i1.EcosystemService }, { token: i2.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
587
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UpdatePluginOfAppComponent, selector: "c8y-update-plugin-of-app", ngImport: i0, template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'c8y-modules'\"></i>\n <h4 *ngIf=\"!downgrade\" id=\"modal-title\" translate>Update plugin</h4>\n <h4 *ngIf=\"downgrade\" id=\"modal-title\" translate>Downgrade plugin</h4>\n </div>\n <div class=\"inner-scroll\" id=\"modal-body\">\n <div class=\"p-16\">\n <div class=\"d-block fit-w bg-gray-white\">\n <c8y-package-version-select\n [packageContextPath]=\"plugin?.contextPath\"\n [(ngModel)]=\"applicationVersion\"\n ></c8y-package-version-select>\n <div\n *ngIf=\"plugin?.version && plugin.version === applicationVersion?.version\"\n class=\"alert alert-info\"\n role=\"alert\"\n >\n <span translate ngNonBindable [translateParams]=\"applicationVersion\">\n Select another version, as {{ version }} is currently used.\n </span>\n </div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"c8y-checkbox\">\n <input [(ngModel)]=\"updateAll\" type=\"checkbox\" />\n <span></span>\n <span translate ngNonBindable [translateParams]=\"plugin\">\n Set version for all plugins using the same context path \"{{ contextPath }}\".\n </span>\n </label>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Set version' | translate }}\"\n [disabled]=\"!applicationVersion || plugin?.version === applicationVersion?.version\"\n (click)=\"update()\"\n >\n {{ 'Set version' | translate }}\n </button>\n </div>\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.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i1.PackageVersionSelectComponent, selector: "c8y-package-version-select", inputs: ["label", "packageContextPath", "packageId"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
616
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UpdatePluginOfAppComponent, deps: [{ token: i1.BsModalRef }, { token: i2.PluginsService }, { token: i2.AlertService }, { token: i3.EcosystemService }, { token: i2.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
617
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UpdatePluginOfAppComponent, selector: "c8y-update-plugin-of-app", ngImport: i0, template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'installing-updates'\"></i>\n <h4\n id=\"modal-title\"\n *ngIf=\"!downgrade\"\n translate\n >\n Update plugin\n </h4>\n <h4\n id=\"modal-title\"\n *ngIf=\"downgrade\"\n translate\n >\n Downgrade plugin\n </h4>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"card-block p-r-24 p-l-24 sticky-top bg-component separator-bottom\">\n <c8y-package-version-select\n [packageContextPath]=\"plugin?.contextPath\"\n [(ngModel)]=\"applicationVersion\"\n ></c8y-package-version-select>\n <div\n class=\"alert alert-info\"\n role=\"alert\"\n *ngIf=\"plugin?.version && plugin.version === applicationVersion?.version\"\n >\n <span\n translate\n ngNonBindable\n [translateParams]=\"applicationVersion\"\n >\n Select another version, as {{ version }} is currently used.\n </span>\n </div>\n <div class=\"form-group\">\n <label class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"updateAll\"\n />\n <span></span>\n <span\n translate\n ngNonBindable\n [translateParams]=\"plugin\"\n >\n Set version for all plugins using the same context path \"{{ contextPath }}\".\n </span>\n </label>\n </div>\n <p class=\"legend form-block\">\n {{ 'Change log' | translate }}\n </p>\n </div>\n <div class=\"card-block p-l-24 p-r-24\">\n\n <div\n class=\"markdown-content markdown-content--to-h3\"\n >\n <c8y-contents-changelog\n [package]=\"plugin.originApp\"\n [selectedVersion]=\"applicationVersion?.version\"\n [previousVersion]=\"plugin?.version\"\n ></c8y-contents-changelog>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Set version' | translate }}\"\n [disabled]=\"!applicationVersion || plugin?.version === applicationVersion?.version\"\n (click)=\"update()\"\n >\n {{ 'Set version' | translate }}\n </button>\n </div>\n</div>", dependencies: [{ kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.PackageVersionSelectComponent, selector: "c8y-package-version-select", inputs: ["label", "packageContextPath", "packageId"] }, { kind: "component", type: i3.PackageChangelogComponent, selector: "c8y-contents-changelog", inputs: ["package", "selectedVersion", "previousVersion"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
588
618
  }
589
619
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UpdatePluginOfAppComponent, decorators: [{
590
620
  type: Component,
591
- args: [{ selector: 'c8y-update-plugin-of-app', template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'c8y-modules'\"></i>\n <h4 *ngIf=\"!downgrade\" id=\"modal-title\" translate>Update plugin</h4>\n <h4 *ngIf=\"downgrade\" id=\"modal-title\" translate>Downgrade plugin</h4>\n </div>\n <div class=\"inner-scroll\" id=\"modal-body\">\n <div class=\"p-16\">\n <div class=\"d-block fit-w bg-gray-white\">\n <c8y-package-version-select\n [packageContextPath]=\"plugin?.contextPath\"\n [(ngModel)]=\"applicationVersion\"\n ></c8y-package-version-select>\n <div\n *ngIf=\"plugin?.version && plugin.version === applicationVersion?.version\"\n class=\"alert alert-info\"\n role=\"alert\"\n >\n <span translate ngNonBindable [translateParams]=\"applicationVersion\">\n Select another version, as {{ version }} is currently used.\n </span>\n </div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"c8y-checkbox\">\n <input [(ngModel)]=\"updateAll\" type=\"checkbox\" />\n <span></span>\n <span translate ngNonBindable [translateParams]=\"plugin\">\n Set version for all plugins using the same context path \"{{ contextPath }}\".\n </span>\n </label>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Set version' | translate }}\"\n [disabled]=\"!applicationVersion || plugin?.version === applicationVersion?.version\"\n (click)=\"update()\"\n >\n {{ 'Set version' | translate }}\n </button>\n </div>\n</div>\n" }]
592
- }], ctorParameters: () => [{ type: i1$1.BsModalRef }, { type: i2.PluginsService }, { type: i2.AlertService }, { type: i1.EcosystemService }, { type: i2.GainsightService }] });
621
+ args: [{ selector: 'c8y-update-plugin-of-app', template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'installing-updates'\"></i>\n <h4\n id=\"modal-title\"\n *ngIf=\"!downgrade\"\n translate\n >\n Update plugin\n </h4>\n <h4\n id=\"modal-title\"\n *ngIf=\"downgrade\"\n translate\n >\n Downgrade plugin\n </h4>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"card-block p-r-24 p-l-24 sticky-top bg-component separator-bottom\">\n <c8y-package-version-select\n [packageContextPath]=\"plugin?.contextPath\"\n [(ngModel)]=\"applicationVersion\"\n ></c8y-package-version-select>\n <div\n class=\"alert alert-info\"\n role=\"alert\"\n *ngIf=\"plugin?.version && plugin.version === applicationVersion?.version\"\n >\n <span\n translate\n ngNonBindable\n [translateParams]=\"applicationVersion\"\n >\n Select another version, as {{ version }} is currently used.\n </span>\n </div>\n <div class=\"form-group\">\n <label class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"updateAll\"\n />\n <span></span>\n <span\n translate\n ngNonBindable\n [translateParams]=\"plugin\"\n >\n Set version for all plugins using the same context path \"{{ contextPath }}\".\n </span>\n </label>\n </div>\n <p class=\"legend form-block\">\n {{ 'Change log' | translate }}\n </p>\n </div>\n <div class=\"card-block p-l-24 p-r-24\">\n\n <div\n class=\"markdown-content markdown-content--to-h3\"\n >\n <c8y-contents-changelog\n [package]=\"plugin.originApp\"\n [selectedVersion]=\"applicationVersion?.version\"\n [previousVersion]=\"plugin?.version\"\n ></c8y-contents-changelog>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Set version' | translate }}\"\n [disabled]=\"!applicationVersion || plugin?.version === applicationVersion?.version\"\n (click)=\"update()\"\n >\n {{ 'Set version' | translate }}\n </button>\n </div>\n</div>" }]
622
+ }], ctorParameters: () => [{ type: i1.BsModalRef }, { type: i2.PluginsService }, { type: i2.AlertService }, { type: i3.EcosystemService }, { type: i2.GainsightService }] });
623
+
624
+ class ApplicationPluginReadmeComponent {
625
+ constructor() {
626
+ this.bottomDrawerRef = inject(BottomDrawerRef);
627
+ this.pluginsService = inject(PluginsService);
628
+ }
629
+ async ngOnInit() {
630
+ const baseUrl = `/apps/${this.plugin.id}/`;
631
+ this.pluginBaseUrl = baseUrl;
632
+ this.pluginMarkdown = await this.pluginsService.getReadmeFileContent(baseUrl);
633
+ }
634
+ close() {
635
+ this.bottomDrawerRef.close();
636
+ }
637
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApplicationPluginReadmeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
638
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ApplicationPluginReadmeComponent, selector: "c8y-application-plugin-readme", host: { classAttribute: "d-contents" }, ngImport: i0, template: "<div class=\"card-header gap-8 d-col p-l-24 p-r-24 separator-bottom flex-no-shrink\">\n <span class=\"card-title h4 text-center\">\n {{ plugin.name }}\n </span>\n</div>\n<div class=\"inner-scroll flex-grow\">\n <div\n class=\"markdown-content col-lg-8 p-24 m-l-auto m-r-auto\"\n style=\"float: none\"\n *ngIf=\"pluginMarkdown\"\n [innerHTML]=\"pluginMarkdown | markdownToHtml: { baseUrl: pluginBaseUrl } | async\"\n ></div>\n <div class=\"d-flex\">\n <c8y-ui-empty-state\n class=\"col-lg-3 col-sm-4 m-l-auto m-r-auto\"\n [icon]=\"'user-manual'\"\n [title]=\"'No README.md found for plugin' | translate\"\n [subtitle]=\"\n 'To view the contents of &quot;README&quot;, add the file &quot;README.md&quot; to the plugin.'\n | translate\n \"\n *ngIf=\"!pluginMarkdown\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </div>\n</div>\n<div class=\"text-center card-footer p-24 separator\">\n <button\n class=\"btn btn-default\"\n (click)=\"close()\"\n >\n {{ 'Close' | translate }}\n </button>\n</div>\n", dependencies: [{ kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.MarkdownToHtmlPipe, name: "markdownToHtml" }] }); }
639
+ }
640
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApplicationPluginReadmeComponent, decorators: [{
641
+ type: Component,
642
+ args: [{ selector: 'c8y-application-plugin-readme', host: { class: 'd-contents' }, template: "<div class=\"card-header gap-8 d-col p-l-24 p-r-24 separator-bottom flex-no-shrink\">\n <span class=\"card-title h4 text-center\">\n {{ plugin.name }}\n </span>\n</div>\n<div class=\"inner-scroll flex-grow\">\n <div\n class=\"markdown-content col-lg-8 p-24 m-l-auto m-r-auto\"\n style=\"float: none\"\n *ngIf=\"pluginMarkdown\"\n [innerHTML]=\"pluginMarkdown | markdownToHtml: { baseUrl: pluginBaseUrl } | async\"\n ></div>\n <div class=\"d-flex\">\n <c8y-ui-empty-state\n class=\"col-lg-3 col-sm-4 m-l-auto m-r-auto\"\n [icon]=\"'user-manual'\"\n [title]=\"'No README.md found for plugin' | translate\"\n [subtitle]=\"\n 'To view the contents of &quot;README&quot;, add the file &quot;README.md&quot; to the plugin.'\n | translate\n \"\n *ngIf=\"!pluginMarkdown\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </div>\n</div>\n<div class=\"text-center card-footer p-24 separator\">\n <button\n class=\"btn btn-default\"\n (click)=\"close()\"\n >\n {{ 'Close' | translate }}\n </button>\n</div>\n" }]
643
+ }] });
593
644
 
594
645
  class ApplicationPluginsComponent {
595
- constructor(activatedRoute, ecosystemService, bsModalService, pluginsService, alertService, gainsightService) {
646
+ constructor(activatedRoute, ecosystemService, bsModalService, pluginsService, alertService, gainsightService, bottomDrawerService) {
596
647
  this.activatedRoute = activatedRoute;
597
648
  this.ecosystemService = ecosystemService;
598
649
  this.bsModalService = bsModalService;
599
650
  this.pluginsService = pluginsService;
600
651
  this.alertService = alertService;
601
652
  this.gainsightService = gainsightService;
653
+ this.bottomDrawerService = bottomDrawerService;
602
654
  this.PRODUCT_EXPERIENCE = PRODUCT_EXPERIENCE_ECOSYSTEM;
603
655
  this.CURRENT_LOCATION = location.href;
604
656
  this.remotePlugins$ = new BehaviorSubject({});
@@ -729,13 +781,11 @@ class ApplicationPluginsComponent {
729
781
  targetApplicationName: this.app.name,
730
782
  targetApplicationContextPath: this.app.contextPath
731
783
  });
732
- const pluginsToAdd = await this.bsModalService.show(InstallPluginComponent, {
733
- class: 'modal-md',
734
- ariaDescribedby: 'modal-body',
735
- ariaLabelledBy: 'modal-title',
784
+ const drawer = this.bottomDrawerService.openDrawer(InstallPluginComponent, {
736
785
  initialState: this.getInstallModalInitState(),
737
- ignoreBackdropClick: true
738
- }).content.result;
786
+ closeOnNavigation: true
787
+ });
788
+ const pluginsToAdd = await drawer.instance.result;
739
789
  const isArchived = await this.ecosystemService.verifyArchived(pluginsToAdd);
740
790
  if (!isArchived) {
741
791
  return;
@@ -798,10 +848,19 @@ class ApplicationPluginsComponent {
798
848
  }
799
849
  getActionControls() {
800
850
  return [
851
+ {
852
+ type: 'showReadme',
853
+ text: gettext('Show readme'),
854
+ icon: 'documents',
855
+ showIf: (plugin) => {
856
+ return !!plugin.readmePath;
857
+ },
858
+ callback: plugin => this.showPluginReadme(plugin)
859
+ },
801
860
  {
802
861
  type: 'customUpdate',
803
862
  text: gettext('Update'),
804
- icon: 'caret-square-o-up',
863
+ icon: 'installing-updates',
805
864
  showIf: plugin => {
806
865
  return (plugin.status === ApplicationPluginStatus.OUTDATED ||
807
866
  plugin.status === ApplicationPluginStatus.REVOKED);
@@ -811,7 +870,7 @@ class ApplicationPluginsComponent {
811
870
  {
812
871
  type: 'customDowngrade',
813
872
  text: gettext('Downgrade'),
814
- icon: 'caret-square-o-down',
873
+ icon: 'installing-updates',
815
874
  showIf: (plugin) => {
816
875
  if (plugin.scope === PluginsExportScopes.SELF ||
817
876
  plugin.scope === PluginsExportScopes.SELF_OPTIONAL) {
@@ -823,6 +882,12 @@ class ApplicationPluginsComponent {
823
882
  }
824
883
  ];
825
884
  }
885
+ showPluginReadme(plugin) {
886
+ this.bottomDrawerService.openDrawer(ApplicationPluginReadmeComponent, {
887
+ initialState: { plugin },
888
+ closeOnNavigation: true
889
+ });
890
+ }
826
891
  getBulkActionControls() {
827
892
  return [
828
893
  {
@@ -836,7 +901,7 @@ class ApplicationPluginsComponent {
836
901
  async updatePlugin(app, plugin, downgrade = false) {
837
902
  try {
838
903
  await this.bsModalService.show(UpdatePluginOfAppComponent, {
839
- class: 'modal-sm',
904
+ class: 'modal-md',
840
905
  ariaDescribedby: 'modal-body',
841
906
  ariaLabelledBy: 'modal-title',
842
907
  initialState: {
@@ -1046,13 +1111,13 @@ class ApplicationPluginsComponent {
1046
1111
  targetApplicationContextPath: this.app.contextPath
1047
1112
  });
1048
1113
  }
1049
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApplicationPluginsComponent, deps: [{ token: i1$2.ActivatedRoute }, { token: i1.EcosystemService }, { token: i1$1.BsModalService }, { token: i2.PluginsService }, { token: i2.AlertService }, { token: i2.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
1050
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ApplicationPluginsComponent, selector: "c8y-app-plugins", inputs: { appId: "appId" }, viewQueries: [{ propertyName: "dataGrid", first: true, predicate: DataGridComponent, descendants: true }], ngImport: i0, template: "<c8y-title>{{ app | humanizeAppName | async }}</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-atom'\"\n [label]=\"'Ecosystem' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-modules'\"\n [label]=\"'Applications' | translate\"\n [path]=\"'ecosystem/application/applications'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item [label]=\"app | humanizeAppName | async\"></c8y-breadcrumb-item>\n <c8y-breadcrumb-item [label]=\"'Plugins' | translate\"></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n *ngIf=\"!(isStandard$ | async)\"\n>\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reset to default plugins' | translate }}\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n (click)=\"resetToDefault()\"\n >\n <i c8yIcon=\"undo\"></i>\n {{ 'Reset to default' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Install plugins' | translate }}\"\n (click)=\"installPlugins()\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Install plugins' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<ng-container *ngIf=\"orphanedPlugins$ | async as orphanedPlugins\">\n <c8y-action-bar-item\n *ngIf=\"orphanedPlugins?.length\"\n [placement]=\"'right'\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Clean up orphaned plugins' | translate }}\"\n (click)=\"cleanupOrphanedPlugins(orphanedPlugins)\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n >\n <i c8yIcon=\"erase\"></i>\n {{ 'Clean up orphaned plugins' | translate }}\n </button>\n </c8y-action-bar-item>\n</ng-container>\n\n<div class=\"content-fullpage d-flex d-col border-top\">\n <c8y-data-grid\n class=\"d-contents\"\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [displayOptions]=\"displayOptions\"\n [columns]=\"columns\"\n [rows]=\"installedPlugins$ | async\"\n [pagination]=\"pagination\"\n [selectable]=\"true\"\n [actionControls]=\"actionControls\"\n [bulkActionControls]=\"bulkActionControls\"\n [headerActionControls]=\"headerActionControls\"\n (onReload)=\"refresh()\"\n >\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'plugin'\"\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 <p *ngIf=\"stats?.size === 0\">\n <button\n class=\"btn btn-primary btn-sm\"\n title=\"{{ 'Install plugins' | translate }}\"\n (click)=\"installPlugins()\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n translate\n >\n Install plugins\n </button>\n </p>\n </c8y-ui-empty-state>\n </c8y-data-grid>\n</div>\n", dependencies: [{ 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: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.DataGridComponent, selector: "c8y-data-grid", inputs: ["title", "loadMoreItemsLabel", "loadingItemsLabel", "showSearch", "refresh", "columns", "rows", "pagination", "infiniteScroll", "serverSideDataCallback", "selectable", "singleSelection", "selectionPrimaryKey", "displayOptions", "actionControls", "bulkActionControls", "headerActionControls", "searchText", "configureColumnsEnabled", "showCounterWarning", "activeClassName", "expandableRows", "hideReload"], 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: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.HumanizeAppNamePipe, name: "humanizeAppName" }] }); }
1114
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApplicationPluginsComponent, deps: [{ token: i1$1.ActivatedRoute }, { token: i3.EcosystemService }, { token: i1.BsModalService }, { token: i2.PluginsService }, { token: i2.AlertService }, { token: i2.GainsightService }, { token: i2.BottomDrawerService }], target: i0.ɵɵFactoryTarget.Component }); }
1115
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ApplicationPluginsComponent, selector: "c8y-app-plugins", inputs: { appId: "appId" }, viewQueries: [{ propertyName: "dataGrid", first: true, predicate: DataGridComponent, descendants: true }], ngImport: i0, template: "<c8y-title>{{ app | humanizeAppName | async }}</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-atom'\"\n [label]=\"'Ecosystem' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-modules'\"\n [label]=\"'Applications' | translate\"\n [path]=\"'ecosystem/application/applications'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item [label]=\"app | humanizeAppName | async\"></c8y-breadcrumb-item>\n <c8y-breadcrumb-item [label]=\"'Plugins' | translate\"></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n *ngIf=\"!(isStandard$ | async)\"\n>\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reset to default plugins' | translate }}\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n (click)=\"resetToDefault()\"\n >\n <i c8yIcon=\"undo\"></i>\n {{ 'Reset to default' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Install plugins' | translate }}\"\n (click)=\"installPlugins()\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Install plugins' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<ng-container *ngIf=\"orphanedPlugins$ | async as orphanedPlugins\">\n <c8y-action-bar-item\n *ngIf=\"orphanedPlugins?.length\"\n [placement]=\"'right'\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Clean up orphaned plugins' | translate }}\"\n (click)=\"cleanupOrphanedPlugins(orphanedPlugins)\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n >\n <i c8yIcon=\"erase\"></i>\n {{ 'Clean up orphaned plugins' | translate }}\n </button>\n </c8y-action-bar-item>\n</ng-container>\n\n<div class=\"content-fullpage d-flex d-col border-top\">\n <c8y-data-grid\n class=\"d-contents\"\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [displayOptions]=\"displayOptions\"\n [columns]=\"columns\"\n [rows]=\"installedPlugins$ | async\"\n [pagination]=\"pagination\"\n [selectable]=\"true\"\n [actionControls]=\"actionControls\"\n [bulkActionControls]=\"bulkActionControls\"\n [headerActionControls]=\"headerActionControls\"\n (onReload)=\"refresh()\"\n >\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'plugin'\"\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 <p *ngIf=\"stats?.size === 0\">\n <button\n class=\"btn btn-primary btn-sm\"\n title=\"{{ 'Install plugins' | translate }}\"\n (click)=\"installPlugins()\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n translate\n >\n Install plugins\n </button>\n </p>\n </c8y-ui-empty-state>\n </c8y-data-grid>\n</div>\n", dependencies: [{ 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: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.DataGridComponent, selector: "c8y-data-grid", inputs: ["title", "loadMoreItemsLabel", "loadingItemsLabel", "showSearch", "refresh", "columns", "rows", "pagination", "infiniteScroll", "serverSideDataCallback", "selectable", "singleSelection", "selectionPrimaryKey", "displayOptions", "actionControls", "bulkActionControls", "headerActionControls", "searchText", "configureColumnsEnabled", "showCounterWarning", "activeClassName", "expandableRows", "hideReload"], 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: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.HumanizeAppNamePipe, name: "humanizeAppName" }] }); }
1051
1116
  }
1052
1117
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApplicationPluginsComponent, decorators: [{
1053
1118
  type: Component,
1054
1119
  args: [{ selector: 'c8y-app-plugins', template: "<c8y-title>{{ app | humanizeAppName | async }}</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-atom'\"\n [label]=\"'Ecosystem' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-modules'\"\n [label]=\"'Applications' | translate\"\n [path]=\"'ecosystem/application/applications'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item [label]=\"app | humanizeAppName | async\"></c8y-breadcrumb-item>\n <c8y-breadcrumb-item [label]=\"'Plugins' | translate\"></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n *ngIf=\"!(isStandard$ | async)\"\n>\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reset to default plugins' | translate }}\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n (click)=\"resetToDefault()\"\n >\n <i c8yIcon=\"undo\"></i>\n {{ 'Reset to default' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Install plugins' | translate }}\"\n (click)=\"installPlugins()\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Install plugins' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<ng-container *ngIf=\"orphanedPlugins$ | async as orphanedPlugins\">\n <c8y-action-bar-item\n *ngIf=\"orphanedPlugins?.length\"\n [placement]=\"'right'\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Clean up orphaned plugins' | translate }}\"\n (click)=\"cleanupOrphanedPlugins(orphanedPlugins)\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n >\n <i c8yIcon=\"erase\"></i>\n {{ 'Clean up orphaned plugins' | translate }}\n </button>\n </c8y-action-bar-item>\n</ng-container>\n\n<div class=\"content-fullpage d-flex d-col border-top\">\n <c8y-data-grid\n class=\"d-contents\"\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [displayOptions]=\"displayOptions\"\n [columns]=\"columns\"\n [rows]=\"installedPlugins$ | async\"\n [pagination]=\"pagination\"\n [selectable]=\"true\"\n [actionControls]=\"actionControls\"\n [bulkActionControls]=\"bulkActionControls\"\n [headerActionControls]=\"headerActionControls\"\n (onReload)=\"refresh()\"\n >\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'plugin'\"\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 <p *ngIf=\"stats?.size === 0\">\n <button\n class=\"btn btn-primary btn-sm\"\n title=\"{{ 'Install plugins' | translate }}\"\n (click)=\"installPlugins()\"\n [ngClass]=\"{ 'btn-pending': isLoading }\"\n translate\n >\n Install plugins\n </button>\n </p>\n </c8y-ui-empty-state>\n </c8y-data-grid>\n</div>\n" }]
1055
- }], ctorParameters: () => [{ type: i1$2.ActivatedRoute }, { type: i1.EcosystemService }, { type: i1$1.BsModalService }, { type: i2.PluginsService }, { type: i2.AlertService }, { type: i2.GainsightService }], propDecorators: { appId: [{
1120
+ }], ctorParameters: () => [{ type: i1$1.ActivatedRoute }, { type: i3.EcosystemService }, { type: i1.BsModalService }, { type: i2.PluginsService }, { type: i2.AlertService }, { type: i2.GainsightService }, { type: i2.BottomDrawerService }], propDecorators: { appId: [{
1056
1121
  type: Input
1057
1122
  }], dataGrid: [{
1058
1123
  type: ViewChild,
@@ -1078,12 +1143,12 @@ class ApplicationPluginsGuard {
1078
1143
  // apps like e.g. the public-options should not have the plugins tab
1079
1144
  !manifest.noAppSwitcher);
1080
1145
  }
1081
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApplicationPluginsGuard, deps: [{ token: i1.EcosystemService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1146
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApplicationPluginsGuard, deps: [{ token: i3.EcosystemService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1082
1147
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApplicationPluginsGuard }); }
1083
1148
  }
1084
1149
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApplicationPluginsGuard, decorators: [{
1085
1150
  type: Injectable
1086
- }], ctorParameters: () => [{ type: i1.EcosystemService }] });
1151
+ }], ctorParameters: () => [{ type: i3.EcosystemService }] });
1087
1152
 
1088
1153
  class ApplicationPluginsModule {
1089
1154
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ApplicationPluginsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
@@ -1096,7 +1161,8 @@ class ApplicationPluginsModule {
1096
1161
  LabelCellRendererComponent,
1097
1162
  OrphanedStatusCellRendererComponent,
1098
1163
  UpdatePluginOfAppComponent,
1099
- OnlyLatestFilterComponent], imports: [CoreModule, SharedEcosystemModule], exports: [ApplicationPluginsComponent,
1164
+ OnlyLatestFilterComponent,
1165
+ ApplicationPluginReadmeComponent], imports: [CoreModule, SharedEcosystemModule], exports: [ApplicationPluginsComponent,
1100
1166
  PluginListItemComponent,
1101
1167
  InstallPluginComponent,
1102
1168
  PluginListComponent,
@@ -1135,7 +1201,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
1135
1201
  LabelCellRendererComponent,
1136
1202
  OrphanedStatusCellRendererComponent,
1137
1203
  UpdatePluginOfAppComponent,
1138
- OnlyLatestFilterComponent
1204
+ OnlyLatestFilterComponent,
1205
+ ApplicationPluginReadmeComponent
1139
1206
  ],
1140
1207
  exports: [
1141
1208
  ApplicationPluginsComponent,