@c8y/ngx-components 1021.25.5 → 1021.29.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 (113) hide show
  1. package/alarms/alarm-details.component.d.ts +8 -13
  2. package/alarms/alarm-details.component.d.ts.map +1 -1
  3. package/alarms/alarm-details.service.d.ts +3 -20
  4. package/alarms/alarm-details.service.d.ts.map +1 -1
  5. package/alarms/alarm-info.component.d.ts +0 -1
  6. package/alarms/alarm-info.component.d.ts.map +1 -1
  7. package/branding/shared/data/branding-version.service.d.ts.map +1 -1
  8. package/branding/shared/lazy/branding-theme-form/branding-theme-form.component.d.ts.map +1 -1
  9. package/core/bootstrap/bootstrap.component.d.ts.map +1 -1
  10. package/core/common/geo.service.d.ts.map +1 -1
  11. package/core/common/inter-app.service.d.ts +1 -0
  12. package/core/common/inter-app.service.d.ts.map +1 -1
  13. package/core/plugins/plugins.model.d.ts +3 -1
  14. package/core/plugins/plugins.model.d.ts.map +1 -1
  15. package/core/plugins/plugins.service.d.ts.map +1 -1
  16. package/device-map/bounds-resolver.service.d.ts +12 -0
  17. package/device-map/bounds-resolver.service.d.ts.map +1 -0
  18. package/device-map/c8y-ngx-components-device-map.d.ts.map +1 -0
  19. package/device-map/device-map-navigation.factory.d.ts +9 -0
  20. package/device-map/device-map-navigation.factory.d.ts.map +1 -0
  21. package/device-map/device-map.component.d.ts +10 -0
  22. package/device-map/device-map.component.d.ts.map +1 -0
  23. package/device-map/device-map.feature.d.ts +3 -0
  24. package/device-map/device-map.feature.d.ts.map +1 -0
  25. package/device-map/index.d.ts +6 -0
  26. package/device-map/index.d.ts.map +1 -0
  27. package/device-map/location-resolver.service.d.ts +8 -0
  28. package/device-map/location-resolver.service.d.ts.map +1 -0
  29. package/ecosystem/application-plugins/application-plugins.component.d.ts.map +1 -1
  30. package/ecosystem/application-plugins/orphaned-status-cell-renderer.component.d.ts.map +1 -1
  31. package/esm2022/alarms/alarm-details.component.mjs +14 -30
  32. package/esm2022/alarms/alarm-details.service.mjs +5 -25
  33. package/esm2022/alarms/alarm-info.component.mjs +1 -1
  34. package/esm2022/branding/shared/data/branding-version.service.mjs +9 -5
  35. package/esm2022/branding/shared/lazy/branding-theme-form/branding-theme-form.component.mjs +5 -2
  36. package/esm2022/core/bootstrap/bootstrap.component.mjs +4 -3
  37. package/esm2022/core/common/geo.service.mjs +2 -5
  38. package/esm2022/core/common/inter-app.service.mjs +3 -2
  39. package/esm2022/core/plugins/plugins.model.mjs +2 -1
  40. package/esm2022/core/plugins/plugins.service.mjs +7 -5
  41. package/esm2022/core/version/websdk-plugin-version.factory.mjs +2 -2
  42. package/esm2022/device-map/bounds-resolver.service.mjs +21 -0
  43. package/esm2022/device-map/c8y-ngx-components-device-map.mjs +5 -0
  44. package/esm2022/device-map/device-map-navigation.factory.mjs +25 -0
  45. package/esm2022/device-map/device-map.component.mjs +30 -0
  46. package/esm2022/device-map/device-map.feature.mjs +15 -0
  47. package/esm2022/device-map/index.mjs +6 -0
  48. package/esm2022/device-map/location-resolver.service.mjs +25 -0
  49. package/esm2022/ecosystem/application-plugins/application-plugins.component.mjs +66 -22
  50. package/esm2022/ecosystem/application-plugins/orphaned-status-cell-renderer.component.mjs +7 -1
  51. package/esm2022/location/location.component.mjs +3 -3
  52. package/esm2022/map/map-status.component.mjs +20 -7
  53. package/esm2022/map/map.component.mjs +15 -7
  54. package/esm2022/map/map.model.mjs +2 -2
  55. package/esm2022/map/map.module.mjs +25 -4
  56. package/esm2022/map/map.service.mjs +73 -7
  57. package/esm2022/repository/firmware/list/firmware-list.component.mjs +10 -10
  58. package/esm2022/repository/software/list/software-list.component.mjs +10 -10
  59. package/esm2022/tracking/tracking-marker-popup.component.mjs +10 -3
  60. package/esm2022/tracking/tracking.component.mjs +3 -4
  61. package/esm2022/tracking/tracking.service.mjs +6 -3
  62. package/fesm2022/c8y-ngx-components-alarms.mjs +18 -54
  63. package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
  64. package/fesm2022/c8y-ngx-components-branding-shared-data.mjs +8 -4
  65. package/fesm2022/c8y-ngx-components-branding-shared-data.mjs.map +1 -1
  66. package/fesm2022/c8y-ngx-components-branding-shared-lazy.mjs +4 -1
  67. package/fesm2022/c8y-ngx-components-branding-shared-lazy.mjs.map +1 -1
  68. package/fesm2022/c8y-ngx-components-device-map.mjs +106 -0
  69. package/fesm2022/c8y-ngx-components-device-map.mjs.map +1 -0
  70. package/fesm2022/c8y-ngx-components-ecosystem-application-plugins.mjs +71 -21
  71. package/fesm2022/c8y-ngx-components-ecosystem-application-plugins.mjs.map +1 -1
  72. package/fesm2022/c8y-ngx-components-ecosystem.mjs +71 -21
  73. package/fesm2022/c8y-ngx-components-ecosystem.mjs.map +1 -1
  74. package/fesm2022/c8y-ngx-components-location.mjs +2 -2
  75. package/fesm2022/c8y-ngx-components-location.mjs.map +1 -1
  76. package/fesm2022/c8y-ngx-components-map.mjs +122 -14
  77. package/fesm2022/c8y-ngx-components-map.mjs.map +1 -1
  78. package/fesm2022/c8y-ngx-components-repository-firmware.mjs +9 -9
  79. package/fesm2022/c8y-ngx-components-repository-firmware.mjs.map +1 -1
  80. package/fesm2022/c8y-ngx-components-repository-software.mjs +9 -9
  81. package/fesm2022/c8y-ngx-components-repository-software.mjs.map +1 -1
  82. package/fesm2022/c8y-ngx-components-tracking.mjs +16 -7
  83. package/fesm2022/c8y-ngx-components-tracking.mjs.map +1 -1
  84. package/fesm2022/c8y-ngx-components.mjs +14 -12
  85. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  86. package/locales/de.po +13 -1
  87. package/locales/es.po +13 -1
  88. package/locales/fr.po +13 -1
  89. package/locales/ja_JP.po +15 -3
  90. package/locales/ko.po +13 -1
  91. package/locales/locales.pot +12 -0
  92. package/locales/nl.po +13 -1
  93. package/locales/pl.po +13 -1
  94. package/locales/pt_BR.po +13 -1
  95. package/locales/zh_CN.po +13 -1
  96. package/locales/zh_TW.po +13 -1
  97. package/map/map-status.component.d.ts +3 -1
  98. package/map/map-status.component.d.ts.map +1 -1
  99. package/map/map.component.d.ts +2 -1
  100. package/map/map.component.d.ts.map +1 -1
  101. package/map/map.model.d.ts +1 -0
  102. package/map/map.model.d.ts.map +1 -1
  103. package/map/map.module.d.ts +2 -1
  104. package/map/map.module.d.ts.map +1 -1
  105. package/map/map.service.d.ts +27 -2
  106. package/map/map.service.d.ts.map +1 -1
  107. package/package.json +1 -1
  108. package/repository/firmware/list/firmware-list.component.d.ts.map +1 -1
  109. package/repository/software/list/software-list.component.d.ts.map +1 -1
  110. package/tracking/tracking-marker-popup.component.d.ts +5 -1
  111. package/tracking/tracking-marker-popup.component.d.ts.map +1 -1
  112. package/tracking/tracking.component.d.ts.map +1 -1
  113. package/tracking/tracking.service.d.ts.map +1 -1
@@ -0,0 +1,106 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable, Component, makeEnvironmentProviders } from '@angular/core';
3
+ import * as i3 from '@c8y/ngx-components/map';
4
+ import { MapModule, defaultMapConfig } from '@c8y/ngx-components/map';
5
+ import * as i2 from '@c8y/ngx-components';
6
+ import { NavigatorNode, gettext, CommonModule, CoreModule, hookRoute, hookNavigator } from '@c8y/ngx-components';
7
+ import * as i1 from '@angular/router';
8
+ import { TrackingMarkerPopupComponent } from '@c8y/ngx-components/tracking';
9
+
10
+ class BoundsResolverService {
11
+ constructor(mapService) {
12
+ this.mapService = mapService;
13
+ }
14
+ resolve() {
15
+ return this.mapService.getAllDevicesBounds();
16
+ }
17
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: BoundsResolverService, deps: [{ token: i3.MapService }], target: i0.ɵɵFactoryTarget.Injectable }); }
18
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: BoundsResolverService, providedIn: 'root' }); }
19
+ }
20
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: BoundsResolverService, decorators: [{
21
+ type: Injectable,
22
+ args: [{
23
+ providedIn: 'root'
24
+ }]
25
+ }], ctorParameters: () => [{ type: i3.MapService }] });
26
+
27
+ class DeviceMapNavigationFactory {
28
+ constructor() {
29
+ this.nav = new NavigatorNode({
30
+ label: gettext('Map'),
31
+ path: 'devicemap',
32
+ icon: 'c8y-location',
33
+ parent: {
34
+ label: gettext('Devices')
35
+ },
36
+ priority: 1900
37
+ });
38
+ }
39
+ async get() {
40
+ return this.nav;
41
+ }
42
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: DeviceMapNavigationFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
43
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: DeviceMapNavigationFactory }); }
44
+ }
45
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: DeviceMapNavigationFactory, decorators: [{
46
+ type: Injectable
47
+ }] });
48
+
49
+ class DeviceMapComponent {
50
+ constructor(route) {
51
+ const { location, bounds } = route.snapshot.data;
52
+ this.config = {
53
+ center: bounds?.isValid() ? bounds.getCenter() : location,
54
+ zoomLevel: 3,
55
+ refreshInterval: 30000,
56
+ bounds,
57
+ fitBoundsOptions: {
58
+ padding: [50, 50]
59
+ }
60
+ };
61
+ }
62
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: DeviceMapComponent, deps: [{ token: i1.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component }); }
63
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: DeviceMapComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<c8y-title>{{ 'Device map' | translate }}</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"exchange\"\n [label]=\"'Devices' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n icon=\"c8y-location\"\n [label]=\"'Map' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<div class=\"card card--grid content-fullpage\">\n <div\n class=\"bg-white p-relative\"\n style=\"min-height: 30vh\"\n >\n <c8y-map-status\n [clusterMap]=\"map\"\n [(config)]=\"config\"\n ></c8y-map-status>\n <c8y-cluster-map\n #map\n [config]=\"config\"\n >\n <div *c8yMapPopup=\"let context\">\n <c8y-tracking-marker-popup\n [showTrackingLink]=\"true\"\n [context]=\"context\"\n ></c8y-tracking-marker-popup>\n </div>\n </c8y-cluster-map>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "ngmodule", type: CoreModule }, { 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.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "ngmodule", type: MapModule }, { kind: "component", type: i3.MapStatusComponent, selector: "c8y-map-status", inputs: ["config", "clusterMap", "buttonsConfig"], outputs: ["configChange", "onUnfollow"] }, { kind: "component", type: i3.ClusterMapComponent, selector: "c8y-cluster-map", inputs: ["config", "rootNode", "asset", "showClusterColor"], outputs: ["mapChange"] }, { kind: "directive", type: i3.MapPopupDirective, selector: "[c8yMapPopup]" }, { kind: "component", type: TrackingMarkerPopupComponent, selector: "c8y-tracking-marker-popup", inputs: ["context", "showTrackingLink"] }] }); }
64
+ }
65
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: DeviceMapComponent, decorators: [{
66
+ type: Component,
67
+ args: [{ standalone: true, imports: [CommonModule, CoreModule, MapModule, TrackingMarkerPopupComponent], template: "<c8y-title>{{ 'Device map' | translate }}</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"exchange\"\n [label]=\"'Devices' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n icon=\"c8y-location\"\n [label]=\"'Map' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<div class=\"card card--grid content-fullpage\">\n <div\n class=\"bg-white p-relative\"\n style=\"min-height: 30vh\"\n >\n <c8y-map-status\n [clusterMap]=\"map\"\n [(config)]=\"config\"\n ></c8y-map-status>\n <c8y-cluster-map\n #map\n [config]=\"config\"\n >\n <div *c8yMapPopup=\"let context\">\n <c8y-tracking-marker-popup\n [showTrackingLink]=\"true\"\n [context]=\"context\"\n ></c8y-tracking-marker-popup>\n </div>\n </c8y-cluster-map>\n </div>\n</div>\n" }]
68
+ }], ctorParameters: () => [{ type: i1.ActivatedRoute }] });
69
+
70
+ class LocationResolverService {
71
+ resolve() {
72
+ return new Promise((resolve, _) => {
73
+ if (navigator.geolocation) {
74
+ navigator.geolocation.getCurrentPosition(gp => {
75
+ resolve([gp?.coords?.latitude, gp?.coords?.longitude]);
76
+ }, () => {
77
+ resolve(defaultMapConfig.center);
78
+ });
79
+ }
80
+ });
81
+ }
82
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: LocationResolverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
83
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: LocationResolverService, providedIn: 'root' }); }
84
+ }
85
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: LocationResolverService, decorators: [{
86
+ type: Injectable,
87
+ args: [{
88
+ providedIn: 'root'
89
+ }]
90
+ }] });
91
+
92
+ const deviceMapFeatureProvider = makeEnvironmentProviders([
93
+ hookRoute({
94
+ path: 'devicemap',
95
+ component: DeviceMapComponent,
96
+ resolve: { location: LocationResolverService, bounds: BoundsResolverService }
97
+ }),
98
+ hookNavigator(DeviceMapNavigationFactory)
99
+ ]);
100
+
101
+ /**
102
+ * Generated bundle index. Do not edit.
103
+ */
104
+
105
+ export { BoundsResolverService, DeviceMapComponent, DeviceMapNavigationFactory, LocationResolverService, deviceMapFeatureProvider };
106
+ //# sourceMappingURL=c8y-ngx-components-device-map.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"c8y-ngx-components-device-map.mjs","sources":["../../device-map/bounds-resolver.service.ts","../../device-map/device-map-navigation.factory.ts","../../device-map/device-map.component.ts","../../device-map/device-map.component.html","../../device-map/location-resolver.service.ts","../../device-map/device-map.feature.ts","../../device-map/c8y-ngx-components-device-map.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { MaybeAsync, Resolve } from '@angular/router';\nimport { MapService } from '@c8y/ngx-components/map';\nimport type * as L from 'leaflet';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class BoundsResolverService implements Resolve<L.LatLngBounds> {\n constructor(private mapService: MapService) {}\n\n resolve(): MaybeAsync<L.LatLngBounds> {\n return this.mapService.getAllDevicesBounds();\n }\n}\n","import { Injectable } from '@angular/core';\nimport { gettext, NavigatorNode, NavigatorNodeFactory } from '@c8y/ngx-components';\n\n@Injectable()\nexport class DeviceMapNavigationFactory implements NavigatorNodeFactory {\n nav = new NavigatorNode({\n label: gettext('Map'),\n path: 'devicemap',\n icon: 'c8y-location',\n parent: {\n label: gettext('Devices')\n },\n priority: 1900\n });\n\n async get() {\n return this.nav;\n }\n}\n","import { Component } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\nimport { CommonModule, CoreModule } from '@c8y/ngx-components';\nimport { ClusterMapConfig, MapModule } from '@c8y/ngx-components/map';\nimport { TrackingMarkerPopupComponent } from '@c8y/ngx-components/tracking';\n\n@Component({\n standalone: true,\n templateUrl: './device-map.component.html',\n imports: [CommonModule, CoreModule, MapModule, TrackingMarkerPopupComponent]\n})\nexport class DeviceMapComponent {\n config: ClusterMapConfig;\n\n constructor(route: ActivatedRoute) {\n const { location, bounds } = route.snapshot.data;\n this.config = {\n center: bounds?.isValid() ? bounds.getCenter() : location,\n zoomLevel: 3,\n refreshInterval: 30000,\n bounds,\n fitBoundsOptions: {\n padding: [50, 50]\n }\n };\n }\n}\n","<c8y-title>{{ 'Device map' | translate }}</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"exchange\"\n [label]=\"'Devices' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n icon=\"c8y-location\"\n [label]=\"'Map' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<div class=\"card card--grid content-fullpage\">\n <div\n class=\"bg-white p-relative\"\n style=\"min-height: 30vh\"\n >\n <c8y-map-status\n [clusterMap]=\"map\"\n [(config)]=\"config\"\n ></c8y-map-status>\n <c8y-cluster-map\n #map\n [config]=\"config\"\n >\n <div *c8yMapPopup=\"let context\">\n <c8y-tracking-marker-popup\n [showTrackingLink]=\"true\"\n [context]=\"context\"\n ></c8y-tracking-marker-popup>\n </div>\n </c8y-cluster-map>\n </div>\n</div>\n","import { Injectable } from '@angular/core';\nimport { MaybeAsync, Resolve } from '@angular/router';\nimport { defaultMapConfig } from '@c8y/ngx-components/map';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class LocationResolverService implements Resolve<[number, number]> {\n resolve(): MaybeAsync<[number, number]> {\n return new Promise((resolve, _) => {\n if (navigator.geolocation) {\n navigator.geolocation.getCurrentPosition(\n gp => {\n resolve([gp?.coords?.latitude, gp?.coords?.longitude]);\n },\n () => {\n resolve(defaultMapConfig.center);\n }\n );\n }\n });\n }\n}\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { hookNavigator, hookRoute } from '@c8y/ngx-components';\nimport { BoundsResolverService } from './bounds-resolver.service';\nimport { DeviceMapNavigationFactory } from './device-map-navigation.factory';\nimport { DeviceMapComponent } from './device-map.component';\nimport { LocationResolverService } from './location-resolver.service';\n\nexport const deviceMapFeatureProvider: EnvironmentProviders = makeEnvironmentProviders([\n hookRoute({\n path: 'devicemap',\n component: DeviceMapComponent,\n resolve: { location: LocationResolverService, bounds: BoundsResolverService }\n }),\n hookNavigator(DeviceMapNavigationFactory)\n]);\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1"],"mappings":"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"}
@@ -463,6 +463,12 @@ class OrphanedStatusCellRendererComponent {
463
463
  text: gettext('LATEST`plugin status`'),
464
464
  class: 'label-success'
465
465
  };
466
+ case ApplicationPluginStatus.AUTO:
467
+ return {
468
+ value: statusValue,
469
+ text: gettext('AUTO`plugin status`'),
470
+ class: 'label-success'
471
+ };
466
472
  default:
467
473
  return null;
468
474
  }
@@ -587,8 +593,25 @@ class ApplicationPluginsComponent {
587
593
  this.allAvailablePlugins$
588
594
  ]).pipe(map(([remotePlugins, allPlugins]) => this.getInstalledPlugins(allPlugins, remotePlugins)), shareReplay(1));
589
595
  this.orphanedPlugins$ = this.installedPlugins$.pipe(map(plugins => plugins.filter(p => p.status === ApplicationPluginStatus.ORPHANED)));
590
- this.isStandard$ = combineLatest([this.installedPlugins$, this.selfPlugins$]).pipe(map(([installedPlugins, selfPlugins]) => installedPlugins.filter(p => selfPlugins.some(selfPlugin => selfPlugin.id === p.id))
591
- .length === selfPlugins.length && installedPlugins.length === selfPlugins.length));
596
+ this.isStandard$ = combineLatest([this.installedPlugins$, this.selfPlugins$]).pipe(map(([installedPlugins, selfPlugins]) => {
597
+ const manifestRemotes = this.app?.manifest?.remotes || {};
598
+ // ensure that every installed plugin is a self plugin or a plugin from the manifest
599
+ const allInstalledPluginsAreSelf = installedPlugins.every(p => selfPlugins.some(selfPlugin => selfPlugin.id === p.id) ||
600
+ (Array.isArray(manifestRemotes[p.contextPath]) &&
601
+ manifestRemotes[p.contextPath].includes(p.module)));
602
+ // ensure that every self plugin is installed
603
+ const allSelfPluginsAreInstalled = selfPlugins.every(selfPlugin => installedPlugins.some(p => p.id === selfPlugin.id));
604
+ const configRemotes = this.app?.config?.remotes || {};
605
+ // ensure that every remote from the manifest is in the config
606
+ // if no config exists we are also all good
607
+ const everyRemoteFromManifestIsInConfig = !this.app?.config?.remotes ||
608
+ Object.keys(manifestRemotes).every(contextPath => Array.isArray(configRemotes[contextPath]) &&
609
+ Array.isArray(manifestRemotes[contextPath]) &&
610
+ manifestRemotes[contextPath].every(module => configRemotes[contextPath].includes(module)));
611
+ return (allInstalledPluginsAreSelf &&
612
+ allSelfPluginsAreInstalled &&
613
+ everyRemoteFromManifestIsInConfig);
614
+ }));
592
615
  this.title = gettext('Installed plugins');
593
616
  this.loadMoreItemsLabel = gettext('Load more packages');
594
617
  this.loadingItemsLabel = gettext('Loading packages…');
@@ -620,9 +643,16 @@ class ApplicationPluginsComponent {
620
643
  {
621
644
  name: 'Version',
622
645
  header: gettext('Version'),
623
- path: 'displayVersion',
646
+ path: 'version',
624
647
  filterable: false
625
648
  },
649
+ {
650
+ name: 'Tag',
651
+ header: gettext('Tag`noun`'),
652
+ path: 'installedViaTag',
653
+ filterable: false,
654
+ cellRendererComponent: LabelCellRendererComponent
655
+ },
626
656
  {
627
657
  name: 'description',
628
658
  header: gettext('Description'),
@@ -894,29 +924,46 @@ class ApplicationPluginsComponent {
894
924
  }
895
925
  getInstallModalInitState() {
896
926
  return {
897
- plugins$: combineLatest([
898
- this.allAvailablePlugins$,
899
- this.installedPlugins$.pipe(map(plugins => plugins.map(p => p.id)))
900
- ]).pipe(map(([allPlugins, installedPlugins]) => {
901
- const plugins = [];
902
- allPlugins.map(p => plugins.push({
903
- ...p,
904
- installed: !!installedPlugins.includes(p.id)
905
- }));
906
- return plugins;
927
+ plugins$: combineLatest([this.allAvailablePlugins$, this.installedPlugins$]).pipe(map(([allPlugins, installedPlugins]) => {
928
+ // to not mutate the original array and objects contained in it
929
+ const allPluginsAsNewObjects = allPlugins.map(p => ({ ...p }));
930
+ for (const plugin of installedPlugins) {
931
+ let installedPlugin = allPluginsAsNewObjects.find(p => p.id === plugin.id);
932
+ if (!installedPlugin && plugin.installedViaTag) {
933
+ installedPlugin = allPluginsAsNewObjects.find(p => p.contextPath === plugin.contextPath &&
934
+ p.module === plugin.module &&
935
+ p.tags?.includes(plugin.installedViaTag));
936
+ }
937
+ if (installedPlugin) {
938
+ installedPlugin.installed = true;
939
+ continue;
940
+ }
941
+ }
942
+ return allPluginsAsNewObjects.map(p => ({ ...p, installed: !!p.installed }));
907
943
  }), shareReplay(1))
908
944
  };
909
945
  }
910
946
  getOrphanedPlugins(orphanedPluginIds, allPlugins) {
911
947
  const orphanedPlugins = orphanedPluginIds.map(p => this.extractDetails(p));
912
948
  const orphanedPluginsUpdated = orphanedPlugins.map(p => {
949
+ const pluginWithMatchingTag = allPlugins.find(tmp => tmp.contextPath === p.contextPath &&
950
+ tmp.module === p.module &&
951
+ tmp.tags?.includes(p.version || 'latest'));
952
+ if (pluginWithMatchingTag) {
953
+ return {
954
+ ...pluginWithMatchingTag,
955
+ id: p.id,
956
+ status: ApplicationPluginStatus.AUTO,
957
+ installedViaTag: p.version || 'latest'
958
+ };
959
+ }
913
960
  const pluginInDifferentVersion = allPlugins.find(tmp => tmp.contextPath === p.contextPath && tmp.module === p.module);
914
961
  if (pluginInDifferentVersion) {
915
962
  return {
916
963
  ...pluginInDifferentVersion,
917
- version: p.version || pluginInDifferentVersion.version,
964
+ version: p.version,
918
965
  id: p.id,
919
- status: p.version ? ApplicationPluginStatus.OUTDATED : ApplicationPluginStatus.LATEST
966
+ status: ApplicationPluginStatus.OUTDATED
920
967
  };
921
968
  }
922
969
  return p;
@@ -949,12 +996,15 @@ class ApplicationPluginsComponent {
949
996
  }));
950
997
  const orphanedPluginIds = remotePlugins.filter(r => !availablePlugins.find(plugin => plugin.id === r));
951
998
  const orphanedPlugins = this.getOrphanedPlugins(orphanedPluginIds, allPlugins);
952
- const { actuallyOrphanedPlugins, revokedPlugins } = this.splitOrphanedPluginsIntoOrphanedAndRevokedPlugins(allPlugins, orphanedPlugins);
953
- return [...availablePlugins, ...revokedPlugins, ...actuallyOrphanedPlugins].map(plugin => ({
954
- ...plugin,
955
- // adding 'v' prefix so version string is not treated as date in data grid
956
- displayVersion: 'v' + plugin.version
957
- }));
999
+ const notActuallyOrphanedPlugins = orphanedPlugins.filter(p => p.status === ApplicationPluginStatus.AUTO);
1000
+ const orphanedOrRevokedPlugins = orphanedPlugins.filter(p => p.status !== ApplicationPluginStatus.AUTO);
1001
+ const { actuallyOrphanedPlugins, revokedPlugins } = this.splitOrphanedPluginsIntoOrphanedAndRevokedPlugins(allPlugins, orphanedOrRevokedPlugins);
1002
+ return [
1003
+ ...availablePlugins,
1004
+ ...notActuallyOrphanedPlugins,
1005
+ ...revokedPlugins,
1006
+ ...actuallyOrphanedPlugins
1007
+ ];
958
1008
  }
959
1009
  extractDetails(pluginId) {
960
1010
  const contextPath = this.getStringMatchingRegex(pluginId, /^[^@]*(@|\/)/);