Showing
16 changed files
with
73 additions
and
22 deletions
@@ -56,7 +56,9 @@ public class TbRuleEngineProcessingStrategyFactory { | @@ -56,7 +56,9 @@ public class TbRuleEngineProcessingStrategyFactory { | ||
56 | private final boolean retryTimeout; | 56 | private final boolean retryTimeout; |
57 | private final int maxRetries; | 57 | private final int maxRetries; |
58 | private final double maxAllowedFailurePercentage; | 58 | private final double maxAllowedFailurePercentage; |
59 | - private final long pauseBetweenRetries; | 59 | + private final long maxPauseBetweenRetries; |
60 | + | ||
61 | + private long pauseBetweenRetries; | ||
60 | 62 | ||
61 | private int initialTotalCount; | 63 | private int initialTotalCount; |
62 | private int retryCount; | 64 | private int retryCount; |
@@ -69,6 +71,7 @@ public class TbRuleEngineProcessingStrategyFactory { | @@ -69,6 +71,7 @@ public class TbRuleEngineProcessingStrategyFactory { | ||
69 | this.maxRetries = configuration.getRetries(); | 71 | this.maxRetries = configuration.getRetries(); |
70 | this.maxAllowedFailurePercentage = configuration.getFailurePercentage(); | 72 | this.maxAllowedFailurePercentage = configuration.getFailurePercentage(); |
71 | this.pauseBetweenRetries = configuration.getPauseBetweenRetries(); | 73 | this.pauseBetweenRetries = configuration.getPauseBetweenRetries(); |
74 | + this.maxPauseBetweenRetries = configuration.getMaxPauseBetweenRetries(); | ||
72 | } | 75 | } |
73 | 76 | ||
74 | @Override | 77 | @Override |
@@ -108,6 +111,9 @@ public class TbRuleEngineProcessingStrategyFactory { | @@ -108,6 +111,9 @@ public class TbRuleEngineProcessingStrategyFactory { | ||
108 | } catch (InterruptedException e) { | 111 | } catch (InterruptedException e) { |
109 | throw new RuntimeException(e); | 112 | throw new RuntimeException(e); |
110 | } | 113 | } |
114 | + if (maxPauseBetweenRetries > pauseBetweenRetries) { | ||
115 | + pauseBetweenRetries = Math.min(maxPauseBetweenRetries, pauseBetweenRetries * 2); | ||
116 | + } | ||
111 | } | 117 | } |
112 | return new TbRuleEngineProcessingDecision(false, toReprocess); | 118 | return new TbRuleEngineProcessingDecision(false, toReprocess); |
113 | } | 119 | } |
@@ -765,6 +765,7 @@ queue: | @@ -765,6 +765,7 @@ queue: | ||
765 | retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited | 765 | retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited |
766 | failure-percentage: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | 766 | failure-percentage: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; |
767 | pause-between-retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRY_PAUSE:3}"# Time in seconds to wait in consumer thread before retries; | 767 | pause-between-retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_RETRY_PAUSE:3}"# Time in seconds to wait in consumer thread before retries; |
768 | + max-pause-between-retries: "${TB_QUEUE_RE_MAIN_PROCESSING_STRATEGY_MAX_RETRY_PAUSE:3}"# Max allowed time in seconds for pause between retries. | ||
768 | - name: "${TB_QUEUE_RE_HP_QUEUE_NAME:HighPriority}" | 769 | - name: "${TB_QUEUE_RE_HP_QUEUE_NAME:HighPriority}" |
769 | topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" | 770 | topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" |
770 | poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" | 771 | poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" |
@@ -780,6 +781,7 @@ queue: | @@ -780,6 +781,7 @@ queue: | ||
780 | retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRIES:0}" # Number of retries, 0 is unlimited | 781 | retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRIES:0}" # Number of retries, 0 is unlimited |
781 | failure-percentage: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | 782 | failure-percentage: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; |
782 | pause-between-retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; | 783 | pause-between-retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; |
784 | + max-pause-between-retries: "${TB_QUEUE_RE_HP_PROCESSING_STRATEGY_MAX_RETRY_PAUSE:5}"# Max allowed time in seconds for pause between retries. | ||
783 | - name: "${TB_QUEUE_RE_SQ_QUEUE_NAME:SequentialByOriginator}" | 785 | - name: "${TB_QUEUE_RE_SQ_QUEUE_NAME:SequentialByOriginator}" |
784 | topic: "${TB_QUEUE_RE_SQ_TOPIC:tb_rule_engine.sq}" | 786 | topic: "${TB_QUEUE_RE_SQ_TOPIC:tb_rule_engine.sq}" |
785 | poll-interval: "${TB_QUEUE_RE_SQ_POLL_INTERVAL_MS:25}" | 787 | poll-interval: "${TB_QUEUE_RE_SQ_POLL_INTERVAL_MS:25}" |
@@ -795,6 +797,7 @@ queue: | @@ -795,6 +797,7 @@ queue: | ||
795 | retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited | 797 | retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited |
796 | failure-percentage: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; | 798 | failure-percentage: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; |
797 | pause-between-retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; | 799 | pause-between-retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_RETRY_PAUSE:5}"# Time in seconds to wait in consumer thread before retries; |
800 | + max-pause-between-retries: "${TB_QUEUE_RE_SQ_PROCESSING_STRATEGY_MAX_RETRY_PAUSE:5}"# Max allowed time in seconds for pause between retries. | ||
798 | transport: | 801 | transport: |
799 | # For high priority notifications that require minimum latency and processing time | 802 | # For high priority notifications that require minimum latency and processing time |
800 | notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb_transport.notifications}" | 803 | notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb_transport.notifications}" |
@@ -24,5 +24,6 @@ public class TbRuleEngineQueueAckStrategyConfiguration { | @@ -24,5 +24,6 @@ public class TbRuleEngineQueueAckStrategyConfiguration { | ||
24 | private int retries; | 24 | private int retries; |
25 | private double failurePercentage; | 25 | private double failurePercentage; |
26 | private long pauseBetweenRetries; | 26 | private long pauseBetweenRetries; |
27 | + private long maxPauseBetweenRetries; | ||
27 | 28 | ||
28 | } | 29 | } |
@@ -54,7 +54,7 @@ | @@ -54,7 +54,7 @@ | ||
54 | "jstree": "^3.3.10", | 54 | "jstree": "^3.3.10", |
55 | "jstree-bootstrap-theme": "^1.0.1", | 55 | "jstree-bootstrap-theme": "^1.0.1", |
56 | "jszip": "^3.5.0", | 56 | "jszip": "^3.5.0", |
57 | - "leaflet": "^1.6.0", | 57 | + "leaflet": "^1.7.1", |
58 | "leaflet-editable": "^1.2.0", | 58 | "leaflet-editable": "^1.2.0", |
59 | "leaflet-polylinedecorator": "^1.6.0", | 59 | "leaflet-polylinedecorator": "^1.6.0", |
60 | "leaflet-providers": "^1.10.2", | 60 | "leaflet-providers": "^1.10.2", |
@@ -1277,7 +1277,7 @@ export class WidgetSubscription implements IWidgetSubscription { | @@ -1277,7 +1277,7 @@ export class WidgetSubscription implements IWidgetSubscription { | ||
1277 | const index = startIndex + dataIndex * dataKeysCount + dataKeyIndex; | 1277 | const index = startIndex + dataIndex * dataKeysCount + dataKeyIndex; |
1278 | let update = true; | 1278 | let update = true; |
1279 | let currentData: DataSetHolder; | 1279 | let currentData: DataSetHolder; |
1280 | - if (this.displayLegend && this.legendData.keys[index].dataKey.hidden) { | 1280 | + if (this.displayLegend && this.legendData.keys.find(key => key.dataIndex === index).dataKey.hidden) { |
1281 | currentData = this.hiddenData[index]; | 1281 | currentData = this.hiddenData[index]; |
1282 | } else { | 1282 | } else { |
1283 | currentData = this.data[index]; | 1283 | currentData = this.data[index]; |
@@ -14,9 +14,11 @@ | @@ -14,9 +14,11 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | +import { HasUUID } from '@shared/models/id/has-uuid'; | ||
18 | + | ||
17 | export declare type MenuSectionType = 'link' | 'toggle'; | 19 | export declare type MenuSectionType = 'link' | 'toggle'; |
18 | 20 | ||
19 | -export class MenuSection { | 21 | +export interface MenuSection extends HasUUID{ |
20 | name: string; | 22 | name: string; |
21 | type: MenuSectionType; | 23 | type: MenuSectionType; |
22 | path: string; | 24 | path: string; |
@@ -26,12 +28,12 @@ export class MenuSection { | @@ -26,12 +28,12 @@ export class MenuSection { | ||
26 | pages?: Array<MenuSection>; | 28 | pages?: Array<MenuSection>; |
27 | } | 29 | } |
28 | 30 | ||
29 | -export class HomeSection { | 31 | +export interface HomeSection { |
30 | name: string; | 32 | name: string; |
31 | places: Array<HomeSectionPlace>; | 33 | places: Array<HomeSectionPlace>; |
32 | } | 34 | } |
33 | 35 | ||
34 | -export class HomeSectionPlace { | 36 | +export interface HomeSectionPlace { |
35 | name: string; | 37 | name: string; |
36 | icon: string; | 38 | icon: string; |
37 | isMdiIcon?: boolean; | 39 | isMdiIcon?: boolean; |
@@ -24,6 +24,7 @@ import { HomeSection, MenuSection } from '@core/services/menu.models'; | @@ -24,6 +24,7 @@ import { HomeSection, MenuSection } from '@core/services/menu.models'; | ||
24 | import { BehaviorSubject, Observable, Subject } from 'rxjs'; | 24 | import { BehaviorSubject, Observable, Subject } from 'rxjs'; |
25 | import { Authority } from '@shared/models/authority.enum'; | 25 | import { Authority } from '@shared/models/authority.enum'; |
26 | import { AuthUser } from '@shared/models/user.model'; | 26 | import { AuthUser } from '@shared/models/user.model'; |
27 | +import { guid } from '@core/utils'; | ||
27 | 28 | ||
28 | @Injectable({ | 29 | @Injectable({ |
29 | providedIn: 'root' | 30 | providedIn: 'root' |
@@ -74,18 +75,21 @@ export class MenuService { | @@ -74,18 +75,21 @@ export class MenuService { | ||
74 | const sections: Array<MenuSection> = []; | 75 | const sections: Array<MenuSection> = []; |
75 | sections.push( | 76 | sections.push( |
76 | { | 77 | { |
78 | + id: guid(), | ||
77 | name: 'home.home', | 79 | name: 'home.home', |
78 | type: 'link', | 80 | type: 'link', |
79 | path: '/home', | 81 | path: '/home', |
80 | icon: 'home' | 82 | icon: 'home' |
81 | }, | 83 | }, |
82 | { | 84 | { |
85 | + id: guid(), | ||
83 | name: 'tenant.tenants', | 86 | name: 'tenant.tenants', |
84 | type: 'link', | 87 | type: 'link', |
85 | path: '/tenants', | 88 | path: '/tenants', |
86 | icon: 'supervisor_account' | 89 | icon: 'supervisor_account' |
87 | }, | 90 | }, |
88 | { | 91 | { |
92 | + id: guid(), | ||
89 | name: 'tenant-profile.tenant-profiles', | 93 | name: 'tenant-profile.tenant-profiles', |
90 | type: 'link', | 94 | type: 'link', |
91 | path: '/tenantProfiles', | 95 | path: '/tenantProfiles', |
@@ -93,12 +97,14 @@ export class MenuService { | @@ -93,12 +97,14 @@ export class MenuService { | ||
93 | isMdiIcon: true | 97 | isMdiIcon: true |
94 | }, | 98 | }, |
95 | { | 99 | { |
100 | + id: guid(), | ||
96 | name: 'widget.widget-library', | 101 | name: 'widget.widget-library', |
97 | type: 'link', | 102 | type: 'link', |
98 | path: '/widgets-bundles', | 103 | path: '/widgets-bundles', |
99 | icon: 'now_widgets' | 104 | icon: 'now_widgets' |
100 | }, | 105 | }, |
101 | { | 106 | { |
107 | + id: guid(), | ||
102 | name: 'admin.system-settings', | 108 | name: 'admin.system-settings', |
103 | type: 'toggle', | 109 | type: 'toggle', |
104 | path: '/settings', | 110 | path: '/settings', |
@@ -106,18 +112,21 @@ export class MenuService { | @@ -106,18 +112,21 @@ export class MenuService { | ||
106 | icon: 'settings', | 112 | icon: 'settings', |
107 | pages: [ | 113 | pages: [ |
108 | { | 114 | { |
115 | + id: guid(), | ||
109 | name: 'admin.general', | 116 | name: 'admin.general', |
110 | type: 'link', | 117 | type: 'link', |
111 | path: '/settings/general', | 118 | path: '/settings/general', |
112 | icon: 'settings_applications' | 119 | icon: 'settings_applications' |
113 | }, | 120 | }, |
114 | { | 121 | { |
122 | + id: guid(), | ||
115 | name: 'admin.outgoing-mail', | 123 | name: 'admin.outgoing-mail', |
116 | type: 'link', | 124 | type: 'link', |
117 | path: '/settings/outgoing-mail', | 125 | path: '/settings/outgoing-mail', |
118 | icon: 'mail' | 126 | icon: 'mail' |
119 | }, | 127 | }, |
120 | { | 128 | { |
129 | + id: guid(), | ||
121 | name: 'admin.security-settings', | 130 | name: 'admin.security-settings', |
122 | type: 'link', | 131 | type: 'link', |
123 | path: '/settings/security-settings', | 132 | path: '/settings/security-settings', |
@@ -186,36 +195,42 @@ export class MenuService { | @@ -186,36 +195,42 @@ export class MenuService { | ||
186 | const sections: Array<MenuSection> = []; | 195 | const sections: Array<MenuSection> = []; |
187 | sections.push( | 196 | sections.push( |
188 | { | 197 | { |
198 | + id: guid(), | ||
189 | name: 'home.home', | 199 | name: 'home.home', |
190 | type: 'link', | 200 | type: 'link', |
191 | path: '/home', | 201 | path: '/home', |
192 | icon: 'home' | 202 | icon: 'home' |
193 | }, | 203 | }, |
194 | { | 204 | { |
205 | + id: guid(), | ||
195 | name: 'rulechain.rulechains', | 206 | name: 'rulechain.rulechains', |
196 | type: 'link', | 207 | type: 'link', |
197 | path: '/ruleChains', | 208 | path: '/ruleChains', |
198 | icon: 'settings_ethernet' | 209 | icon: 'settings_ethernet' |
199 | }, | 210 | }, |
200 | { | 211 | { |
212 | + id: guid(), | ||
201 | name: 'customer.customers', | 213 | name: 'customer.customers', |
202 | type: 'link', | 214 | type: 'link', |
203 | path: '/customers', | 215 | path: '/customers', |
204 | icon: 'supervisor_account' | 216 | icon: 'supervisor_account' |
205 | }, | 217 | }, |
206 | { | 218 | { |
219 | + id: guid(), | ||
207 | name: 'asset.assets', | 220 | name: 'asset.assets', |
208 | type: 'link', | 221 | type: 'link', |
209 | path: '/assets', | 222 | path: '/assets', |
210 | icon: 'domain' | 223 | icon: 'domain' |
211 | }, | 224 | }, |
212 | { | 225 | { |
226 | + id: guid(), | ||
213 | name: 'device.devices', | 227 | name: 'device.devices', |
214 | type: 'link', | 228 | type: 'link', |
215 | path: '/devices', | 229 | path: '/devices', |
216 | icon: 'devices_other' | 230 | icon: 'devices_other' |
217 | }, | 231 | }, |
218 | { | 232 | { |
233 | + id: guid(), | ||
219 | name: 'device-profile.device-profiles', | 234 | name: 'device-profile.device-profiles', |
220 | type: 'link', | 235 | type: 'link', |
221 | path: '/deviceProfiles', | 236 | path: '/deviceProfiles', |
@@ -223,24 +238,28 @@ export class MenuService { | @@ -223,24 +238,28 @@ export class MenuService { | ||
223 | isMdiIcon: true | 238 | isMdiIcon: true |
224 | }, | 239 | }, |
225 | { | 240 | { |
241 | + id: guid(), | ||
226 | name: 'entity-view.entity-views', | 242 | name: 'entity-view.entity-views', |
227 | type: 'link', | 243 | type: 'link', |
228 | path: '/entityViews', | 244 | path: '/entityViews', |
229 | icon: 'view_quilt' | 245 | icon: 'view_quilt' |
230 | }, | 246 | }, |
231 | { | 247 | { |
248 | + id: guid(), | ||
232 | name: 'widget.widget-library', | 249 | name: 'widget.widget-library', |
233 | type: 'link', | 250 | type: 'link', |
234 | path: '/widgets-bundles', | 251 | path: '/widgets-bundles', |
235 | icon: 'now_widgets' | 252 | icon: 'now_widgets' |
236 | }, | 253 | }, |
237 | { | 254 | { |
255 | + id: guid(), | ||
238 | name: 'dashboard.dashboards', | 256 | name: 'dashboard.dashboards', |
239 | type: 'link', | 257 | type: 'link', |
240 | path: '/dashboards', | 258 | path: '/dashboards', |
241 | icon: 'dashboards' | 259 | icon: 'dashboards' |
242 | }, | 260 | }, |
243 | { | 261 | { |
262 | + id: guid(), | ||
244 | name: 'audit-log.audit-logs', | 263 | name: 'audit-log.audit-logs', |
245 | type: 'link', | 264 | type: 'link', |
246 | path: '/auditLogs', | 265 | path: '/auditLogs', |
@@ -342,30 +361,35 @@ export class MenuService { | @@ -342,30 +361,35 @@ export class MenuService { | ||
342 | const sections: Array<MenuSection> = []; | 361 | const sections: Array<MenuSection> = []; |
343 | sections.push( | 362 | sections.push( |
344 | { | 363 | { |
364 | + id: guid(), | ||
345 | name: 'home.home', | 365 | name: 'home.home', |
346 | type: 'link', | 366 | type: 'link', |
347 | path: '/home', | 367 | path: '/home', |
348 | icon: 'home' | 368 | icon: 'home' |
349 | }, | 369 | }, |
350 | { | 370 | { |
371 | + id: guid(), | ||
351 | name: 'asset.assets', | 372 | name: 'asset.assets', |
352 | type: 'link', | 373 | type: 'link', |
353 | path: '/assets', | 374 | path: '/assets', |
354 | icon: 'domain' | 375 | icon: 'domain' |
355 | }, | 376 | }, |
356 | { | 377 | { |
378 | + id: guid(), | ||
357 | name: 'device.devices', | 379 | name: 'device.devices', |
358 | type: 'link', | 380 | type: 'link', |
359 | path: '/devices', | 381 | path: '/devices', |
360 | icon: 'devices_other' | 382 | icon: 'devices_other' |
361 | }, | 383 | }, |
362 | { | 384 | { |
385 | + id: guid(), | ||
363 | name: 'entity-view.entity-views', | 386 | name: 'entity-view.entity-views', |
364 | type: 'link', | 387 | type: 'link', |
365 | path: '/entityViews', | 388 | path: '/entityViews', |
366 | icon: 'view_quilt' | 389 | icon: 'view_quilt' |
367 | }, | 390 | }, |
368 | { | 391 | { |
392 | + id: guid(), | ||
369 | name: 'dashboard.dashboards', | 393 | name: 'dashboard.dashboards', |
370 | type: 'link', | 394 | type: 'link', |
371 | path: '/dashboards', | 395 | path: '/dashboards', |
@@ -86,8 +86,7 @@ export default abstract class LeafletMap { | @@ -86,8 +86,7 @@ export default abstract class LeafletMap { | ||
86 | 86 | ||
87 | public initSettings(options: MapSettings) { | 87 | public initSettings(options: MapSettings) { |
88 | this.options.tinyColor = tinycolor(this.options.color || defaultSettings.color); | 88 | this.options.tinyColor = tinycolor(this.options.color || defaultSettings.color); |
89 | - const { disableScrollZooming, | ||
90 | - useClusterMarkers, | 89 | + const { useClusterMarkers, |
91 | zoomOnClick, | 90 | zoomOnClick, |
92 | showCoverageOnHover, | 91 | showCoverageOnHover, |
93 | removeOutsideVisibleBounds, | 92 | removeOutsideVisibleBounds, |
@@ -95,9 +94,6 @@ export default abstract class LeafletMap { | @@ -95,9 +94,6 @@ export default abstract class LeafletMap { | ||
95 | chunkedLoading, | 94 | chunkedLoading, |
96 | maxClusterRadius, | 95 | maxClusterRadius, |
97 | maxZoom }: MapSettings = options; | 96 | maxZoom }: MapSettings = options; |
98 | - if (disableScrollZooming) { | ||
99 | - this.map.scrollWheelZoom.disable(); | ||
100 | - } | ||
101 | if (useClusterMarkers) { | 97 | if (useClusterMarkers) { |
102 | const clusteringSettings: MarkerClusterGroupOptions = { | 98 | const clusteringSettings: MarkerClusterGroupOptions = { |
103 | zoomToBoundsOnClick: zoomOnClick, | 99 | zoomToBoundsOnClick: zoomOnClick, |
@@ -307,8 +303,11 @@ export default abstract class LeafletMap { | @@ -307,8 +303,11 @@ export default abstract class LeafletMap { | ||
307 | } else { | 303 | } else { |
308 | this.bounds = new L.LatLngBounds(null, null); | 304 | this.bounds = new L.LatLngBounds(null, null); |
309 | } | 305 | } |
306 | + if (this.options.disableScrollZooming) { | ||
307 | + this.map.scrollWheelZoom.disable(); | ||
308 | + } | ||
310 | if (this.options.draggableMarker) { | 309 | if (this.options.draggableMarker) { |
311 | - this.addMarkerControl(); | 310 | + this.addMarkerControl(); |
312 | } | 311 | } |
313 | if (this.options.editablePolygon) { | 312 | if (this.options.editablePolygon) { |
314 | this.addPolygonControl(); | 313 | this.addPolygonControl(); |
@@ -623,10 +622,10 @@ export default abstract class LeafletMap { | @@ -623,10 +622,10 @@ export default abstract class LeafletMap { | ||
623 | 622 | ||
624 | // Polyline | 623 | // Polyline |
625 | 624 | ||
626 | - updatePolylines(polyData: FormattedData[][], updateBounds = true, data?: FormattedData) { | 625 | + updatePolylines(polyData: FormattedData[][], updateBounds = true, activePolyline?: FormattedData) { |
627 | const keys: string[] = []; | 626 | const keys: string[] = []; |
628 | polyData.forEach((dataSource: FormattedData[]) => { | 627 | polyData.forEach((dataSource: FormattedData[]) => { |
629 | - data = data || dataSource[0]; | 628 | + const data = activePolyline || dataSource[0]; |
630 | if (dataSource.length && data.entityName === dataSource[0].entityName) { | 629 | if (dataSource.length && data.entityName === dataSource[0].entityName) { |
631 | if (this.polylines.get(data.entityName)) { | 630 | if (this.polylines.get(data.entityName)) { |
632 | this.updatePolyline(data, dataSource, this.options, updateBounds); | 631 | this.updatePolyline(data, dataSource, this.options, updateBounds); |
@@ -24,7 +24,7 @@ | @@ -24,7 +24,7 @@ | ||
24 | [ngClass]="{'tb-toggled' : sectionActive()}"></span> | 24 | [ngClass]="{'tb-toggled' : sectionActive()}"></span> |
25 | </a> | 25 | </a> |
26 | <ul id="docs-menu-{{section.name | nospace}}" class="tb-menu-toggle-list" [ngStyle]="{height: sectionHeight()}"> | 26 | <ul id="docs-menu-{{section.name | nospace}}" class="tb-menu-toggle-list" [ngStyle]="{height: sectionHeight()}"> |
27 | - <li *ngFor="let page of section.pages"> | 27 | + <li *ngFor="let page of section.pages; trackBy: trackBySectionPages"> |
28 | <tb-menu-link [section]="page"></tb-menu-link> | 28 | <tb-menu-link [section]="page"></tb-menu-link> |
29 | </li> | 29 | </li> |
30 | </ul> | 30 | </ul> |
@@ -44,4 +44,8 @@ export class MenuToggleComponent implements OnInit { | @@ -44,4 +44,8 @@ export class MenuToggleComponent implements OnInit { | ||
44 | return '0px'; | 44 | return '0px'; |
45 | } | 45 | } |
46 | } | 46 | } |
47 | + | ||
48 | + trackBySectionPages(index: number, section: MenuSection){ | ||
49 | + return section.id; | ||
50 | + } | ||
47 | } | 51 | } |
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | 16 | ||
17 | --> | 17 | --> |
18 | <ul fxFlex fxLayout="column" fxLayoutAlign="start stretch" class="tb-side-menu"> | 18 | <ul fxFlex fxLayout="column" fxLayoutAlign="start stretch" class="tb-side-menu"> |
19 | - <li *ngFor="let section of menuSections$| async" [ngSwitch]="section.type === 'link'"> | 19 | + <li *ngFor="let section of menuSections$ | async; trackBy: trackByMenuSection" [ngSwitch]="section.type === 'link'"> |
20 | <tb-menu-link *ngSwitchCase="true" [section]="section"></tb-menu-link> | 20 | <tb-menu-link *ngSwitchCase="true" [section]="section"></tb-menu-link> |
21 | <tb-menu-toggle *ngSwitchCase="false" [section]="section"></tb-menu-toggle> | 21 | <tb-menu-toggle *ngSwitchCase="false" [section]="section"></tb-menu-toggle> |
22 | </li> | 22 | </li> |
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | 16 | ||
17 | import { Component, OnInit } from '@angular/core'; | 17 | import { Component, OnInit } from '@angular/core'; |
18 | import { MenuService } from '@core/services/menu.service'; | 18 | import { MenuService } from '@core/services/menu.service'; |
19 | +import { MenuSection } from '@core/services/menu.models'; | ||
19 | 20 | ||
20 | @Component({ | 21 | @Component({ |
21 | selector: 'tb-side-menu', | 22 | selector: 'tb-side-menu', |
@@ -29,6 +30,10 @@ export class SideMenuComponent implements OnInit { | @@ -29,6 +30,10 @@ export class SideMenuComponent implements OnInit { | ||
29 | constructor(private menuService: MenuService) { | 30 | constructor(private menuService: MenuService) { |
30 | } | 31 | } |
31 | 32 | ||
33 | + trackByMenuSection(index: number, section: MenuSection){ | ||
34 | + return section.id; | ||
35 | + } | ||
36 | + | ||
32 | ngOnInit() { | 37 | ngOnInit() { |
33 | } | 38 | } |
34 | 39 |
@@ -19,7 +19,7 @@ | @@ -19,7 +19,7 @@ | ||
19 | <h1 fxFlex fxHide.gt-sm *ngIf="lastBreadcrumb$ | async; let breadcrumb"> | 19 | <h1 fxFlex fxHide.gt-sm *ngIf="lastBreadcrumb$ | async; let breadcrumb"> |
20 | {{ breadcrumb.ignoreTranslate ? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : breadcrumb.label) : (breadcrumb.label | translate) }} | 20 | {{ breadcrumb.ignoreTranslate ? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : breadcrumb.label) : (breadcrumb.label | translate) }} |
21 | </h1> | 21 | </h1> |
22 | - <span fxHide.lt-md fxLayout="row" *ngFor="let breadcrumb of breadcrumbs$ | async; last as isLast;" [ngSwitch]="isLast"> | 22 | + <span fxHide.lt-md fxLayout="row" *ngFor="let breadcrumb of breadcrumbs$ | async; trackBy: trackByBreadcrumbs; last as isLast;" [ngSwitch]="isLast"> |
23 | <a *ngSwitchCase="false" [routerLink]="breadcrumb.link" [queryParams]="breadcrumb.queryParams"> | 23 | <a *ngSwitchCase="false" [routerLink]="breadcrumb.link" [queryParams]="breadcrumb.queryParams"> |
24 | <mat-icon *ngIf="breadcrumb.isMdiIcon" [svgIcon]="breadcrumb.icon"> | 24 | <mat-icon *ngIf="breadcrumb.isMdiIcon" [svgIcon]="breadcrumb.icon"> |
25 | </mat-icon> | 25 | </mat-icon> |
@@ -20,6 +20,7 @@ import { BreadCrumb, BreadCrumbConfig } from './breadcrumb'; | @@ -20,6 +20,7 @@ import { BreadCrumb, BreadCrumbConfig } from './breadcrumb'; | ||
20 | import { ActivatedRoute, ActivatedRouteSnapshot, NavigationEnd, Router } from '@angular/router'; | 20 | import { ActivatedRoute, ActivatedRouteSnapshot, NavigationEnd, Router } from '@angular/router'; |
21 | import { distinctUntilChanged, filter, map } from 'rxjs/operators'; | 21 | import { distinctUntilChanged, filter, map } from 'rxjs/operators'; |
22 | import { TranslateService } from '@ngx-translate/core'; | 22 | import { TranslateService } from '@ngx-translate/core'; |
23 | +import { guid } from '@core/utils'; | ||
23 | 24 | ||
24 | @Component({ | 25 | @Component({ |
25 | selector: 'tb-breadcrumb', | 26 | selector: 'tb-breadcrumb', |
@@ -94,6 +95,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { | @@ -94,6 +95,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { | ||
94 | const isMdiIcon = icon.startsWith('mdi:'); | 95 | const isMdiIcon = icon.startsWith('mdi:'); |
95 | const link = [ route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/') ]; | 96 | const link = [ route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/') ]; |
96 | const breadcrumb = { | 97 | const breadcrumb = { |
98 | + id: guid(), | ||
97 | label, | 99 | label, |
98 | labelFunction, | 100 | labelFunction, |
99 | ignoreTranslate, | 101 | ignoreTranslate, |
@@ -110,4 +112,8 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { | @@ -110,4 +112,8 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { | ||
110 | } | 112 | } |
111 | return newBreadcrumbs; | 113 | return newBreadcrumbs; |
112 | } | 114 | } |
115 | + | ||
116 | + trackByBreadcrumbs(index: number, breadcrumb: BreadCrumb){ | ||
117 | + return breadcrumb.id; | ||
118 | + } | ||
113 | } | 119 | } |
@@ -16,8 +16,9 @@ | @@ -16,8 +16,9 @@ | ||
16 | 16 | ||
17 | import { ActivatedRouteSnapshot, Params } from '@angular/router'; | 17 | import { ActivatedRouteSnapshot, Params } from '@angular/router'; |
18 | import { TranslateService } from '@ngx-translate/core'; | 18 | import { TranslateService } from '@ngx-translate/core'; |
19 | +import { HasUUID } from '@shared/models/id/has-uuid'; | ||
19 | 20 | ||
20 | -export interface BreadCrumb { | 21 | +export interface BreadCrumb extends HasUUID{ |
21 | label: string; | 22 | label: string; |
22 | labelFunction?: () => string; | 23 | labelFunction?: () => string; |
23 | ignoreTranslate: boolean; | 24 | ignoreTranslate: boolean; |
@@ -5770,10 +5770,10 @@ leaflet.markercluster@^1.4.1: | @@ -5770,10 +5770,10 @@ leaflet.markercluster@^1.4.1: | ||
5770 | resolved "https://registry.yarnpkg.com/leaflet.markercluster/-/leaflet.markercluster-1.4.1.tgz#b53f2c4f2ca7306ddab1dbb6f1861d5e8aa6c5e5" | 5770 | resolved "https://registry.yarnpkg.com/leaflet.markercluster/-/leaflet.markercluster-1.4.1.tgz#b53f2c4f2ca7306ddab1dbb6f1861d5e8aa6c5e5" |
5771 | integrity sha512-ZSEpE/EFApR0bJ1w/dUGwTSUvWlpalKqIzkaYdYB7jaftQA/Y2Jav+eT4CMtEYFj+ZK4mswP13Q2acnPBnhGOw== | 5771 | integrity sha512-ZSEpE/EFApR0bJ1w/dUGwTSUvWlpalKqIzkaYdYB7jaftQA/Y2Jav+eT4CMtEYFj+ZK4mswP13Q2acnPBnhGOw== |
5772 | 5772 | ||
5773 | -leaflet@^1.6.0: | ||
5774 | - version "1.6.0" | ||
5775 | - resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.6.0.tgz#aecbb044b949ec29469eeb31c77a88e2f448f308" | ||
5776 | - integrity sha512-CPkhyqWUKZKFJ6K8umN5/D2wrJ2+/8UIpXppY7QDnUZW5bZL5+SEI2J7GBpwh4LIupOKqbNSQXgqmrEJopHVNQ== | 5773 | +leaflet@^1.7.1: |
5774 | + version "1.7.1" | ||
5775 | + resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.7.1.tgz#10d684916edfe1bf41d688a3b97127c0322a2a19" | ||
5776 | + integrity sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw== | ||
5777 | 5777 | ||
5778 | less-loader@6.1.0: | 5778 | less-loader@6.1.0: |
5779 | version "6.1.0" | 5779 | version "6.1.0" |