From 35de014fe1987fceb765a785206fbb418c6bf6a2 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 27 Nov 2023 18:34:46 +0200 Subject: [PATCH] UI: Implement multiple gallery images input. Replace image inputs to image gallery inputs. --- .../dashboard-image-dialog.component.html | 8 +- .../dashboard-image-dialog.component.ts | 8 +- .../dashboard-page.component.html | 2 +- .../dashboard-page.component.ts | 8 +- .../dashboard-settings-dialog.component.html | 8 +- .../layout/dashboard-layout.component.html | 4 +- .../layout/dashboard-layout.component.ts | 13 +- .../home/components/home-components.module.ts | 25 +- .../image/gallery-image-input.component.html | 2 + .../image/gallery-image-input.component.ts | 2 +- ...ultiple-gallery-image-input.component.html | 111 +++++++++ ...ultiple-gallery-image-input.component.scss | 225 ++++++++++++++++++ .../multiple-gallery-image-input.component.ts | 180 ++++++++++++++ .../add-device-profile-dialog.component.html | 5 +- .../profile/asset-profile.component.html | 5 +- .../profile/device-profile.component.html | 5 +- .../shared-home-components.module.ts | 28 ++- .../components/widget/lib/maps/leaflet-map.ts | 24 +- .../components/widget/lib/maps/map-models.ts | 2 + .../components/widget/lib/maps/markers.ts | 5 + ...image-map-provider-settings.component.html | 4 +- .../map/markers-settings.component.html | 12 +- ...p-animation-marker-settings.component.html | 12 +- .../modules/home/pages/admin/admin.module.ts | 2 + .../dashboard/dashboard-form.component.html | 5 +- .../home/pages/dashboard/dashboard.module.ts | 2 + .../pages/widget/widget-editor.component.html | 5 +- .../pages/widget/widget-library.module.ts | 2 + .../pages/widget/widget-type.component.html | 5 +- .../widget/widgets-bundle.component.html | 5 - 30 files changed, 628 insertions(+), 96 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/image/multiple-gallery-image-input.component.html create mode 100644 ui-ngx/src/app/modules/home/components/image/multiple-gallery-image-input.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/image/multiple-gallery-image-input.component.ts diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.html index 9019161c29..8939d885d3 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-image-dialog.component.html @@ -40,8 +40,8 @@
-
{{ 'dashboard.no-image' | translate }}
- +
{{ 'dashboard.no-image' | translate }}
+
Right % @@ -62,9 +62,9 @@
- - +
-
diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index 6f6e39c52c..6fdd07c9ca 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -668,12 +668,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC } } - public get dashboardLogo(): SafeUrl { - if (!this.dashboardLogoCache) { - const logo = this.dashboard.configuration.settings.dashboardLogoUrl || this.defaultDashboardLogo; - this.dashboardLogoCache = this.sanitizer.bypassSecurityTrustUrl(logo); - } - return this.dashboardLogoCache; + public get dashboardLogo(): string { + return this.dashboard.configuration.settings.dashboardLogoUrl || this.defaultDashboardLogo; } public showRightLayoutSwitch(): boolean { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html index 2090e5f42c..d526f180e0 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html @@ -55,10 +55,10 @@ {{ 'dashboard.display-dashboard-logo' | translate }} - - +
dashboard.toolbar-settings @@ -144,10 +144,10 @@ openOnInput formControlName="backgroundColor"> - - + dashboard.background-size-mode diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.html index f724f81f04..d43f2af10f 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.html @@ -23,7 +23,7 @@
; hotKeys: Hotkey[] = []; @@ -92,6 +94,7 @@ export class DashboardLayoutComponent extends PageComponent implements ILayoutCo constructor(protected store: Store, private translate: TranslateService, private itembuffer: ItemBufferService, + private imagePipe: ImagePipe, private sanitizer: DomSanitizer) { super(store); this.initHotKeys(); @@ -188,8 +191,10 @@ export class DashboardLayoutComponent extends PageComponent implements ILayoutCo 'background-attachment': 'scroll', 'background-size': this.layoutCtx.gridSettings.backgroundSizeMode || '100%', 'background-position': '0% 0%'}; - this.backgroundImage = this.layoutCtx.gridSettings.backgroundImageUrl ? - this.sanitizer.bypassSecurityTrustStyle('url(' + this.layoutCtx.gridSettings.backgroundImageUrl + ')') : 'none'; + this.backgroundImage$ = this.layoutCtx.gridSettings.backgroundImageUrl ? + this.imagePipe.transform(this.layoutCtx.gridSettings.backgroundImageUrl, {asString: true, ignoreLoadingImage: true}).pipe( + map((imageUrl) => this.sanitizer.bypassSecurityTrustStyle('url(' + imageUrl + ')')) + ) : of('none'); } reload() { diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts index 14fcb6bddc..735ef9742b 100644 --- a/ui-ngx/src/app/modules/home/components/home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts @@ -181,13 +181,6 @@ import { DeleteTimeseriesPanelComponent } from '@home/components/attribute/delet import { ExportWidgetsBundleDialogComponent } from '@home/components/import-export/export-widgets-bundle-dialog.component'; -import { ScrollGridComponent } from '@home/components/grid/scroll-grid.component'; -import { ImageGalleryComponent } from '@home/components/image/image-gallery.component'; -import { UploadImageDialogComponent } from '@home/components/image/upload-image-dialog.component'; -import { ImageDialogComponent } from '@home/components/image/image-dialog.component'; -import { ImagesInUseDialogComponent } from '@home/components/image/images-in-use-dialog.component'; -import { ImageReferencesComponent } from '@home/components/image/image-references.component'; -import { GalleryImageInputComponent } from '@home/components/image/gallery-image-input.component'; @NgModule({ declarations: @@ -332,14 +325,7 @@ import { GalleryImageInputComponent } from '@home/components/image/gallery-image RateLimitsComponent, RateLimitsTextComponent, RateLimitsDetailsDialogComponent, - SendNotificationButtonComponent, - ScrollGridComponent, - ImageGalleryComponent, - UploadImageDialogComponent, - ImageDialogComponent, - ImageReferencesComponent, - ImagesInUseDialogComponent, - GalleryImageInputComponent + SendNotificationButtonComponent ], imports: [ CommonModule, @@ -477,14 +463,7 @@ import { GalleryImageInputComponent } from '@home/components/image/gallery-image RateLimitsComponent, RateLimitsTextComponent, RateLimitsDetailsDialogComponent, - SendNotificationButtonComponent, - ScrollGridComponent, - ImageGalleryComponent, - UploadImageDialogComponent, - ImageDialogComponent, - ImageReferencesComponent, - ImagesInUseDialogComponent, - GalleryImageInputComponent + SendNotificationButtonComponent ], providers: [ WidgetComponentService, diff --git a/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.html b/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.html index ce81ce4a1b..0ef4aa4bb0 100644 --- a/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.html +++ b/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.html @@ -68,6 +68,7 @@
+
+
+
+
{{ 'image-input.no-images' | translate }}
+ +
+
+ +
+
+
+ + +
+
+
+ + +
+
+ + + +
{{ 'image.no-image-selected' | translate }}
+
diff --git a/ui-ngx/src/app/modules/home/components/image/multiple-gallery-image-input.component.scss b/ui-ngx/src/app/modules/home/components/image/multiple-gallery-image-input.component.scss new file mode 100644 index 0000000000..bd1eb6ef67 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/image/multiple-gallery-image-input.component.scss @@ -0,0 +1,225 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@import "../../../../../scss/constants"; + +$imagesContainerHeight: 106px !default; +$selectContainerHeight: 96px !default; +$previewSize: 64px !default; + +.image-card { + margin-bottom: 8px; + &.image-dnd-placeholder { + height: 82px; + width: 146px; + border: 2px dashed rgba(0, 0, 0, 0.2); + background: rgba(0, 0, 0, 0.1); + border-radius: 4px; + } + &.image-dragging { + display: none !important; + } + .image-title { + font-size: 11px; + font-weight: 400; + line-height: 14px; + color: rgba(0, 0, 0, 0.6); + padding-bottom: 4px; + } + + .image-content-container { + background: #FFFFFF; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 4px; + height: $previewSize; + } + + .tb-image-preview { + width: auto; + max-width: $previewSize - 2px; + height: auto; + max-height: $previewSize - 2px; + } + + .tb-image-preview-container { + position: relative; + width: $previewSize; + height: $previewSize; + margin-top: -1px; + margin-bottom: -1px; + border: 1px solid rgba(0, 0, 0, 0.54); + + .tb-image-preview { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + + .tb-image-action-container { + position: relative; + height: $previewSize - 2px; + display: flex; + align-items: center; + justify-content: center; + min-width: 40px; + } +} + +:host { + .tb-container { + margin-top: 0; + padding: 0 0 16px; + display: flex; + flex-direction: column; + gap: 8px; + label.tb-title { + display: block; + padding-bottom: 0; + } + } + + .images-container { + padding: 12px 12px 4px; + background: rgba(0, 0, 0, 0.03); + border-radius: 4px; + flex-wrap: wrap; + margin-bottom: 8px; + &.no-images { + height: $imagesContainerHeight; + padding-bottom: 12px; + align-items: center; + justify-content: center; + } + } + + .no-images-prompt { + font-size: 18px; + color: rgba(0, 0, 0, 0.54); + } + + .tb-image-select-container { + width: 100%; + height: $selectContainerHeight; + border-radius: 4px; + border: 1px solid rgba(0, 0, 0, 0.12); + display: flex; + align-items: center; + + .tb-image-container { + width: $selectContainerHeight - 1px; + height: $selectContainerHeight - 2px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 4px; + border-right: 1px solid rgba(0, 0, 0, 0.12); + background: #fff; + overflow: hidden; + + .tb-image-preview { + width: auto; + max-width: $selectContainerHeight - 2px; + height: auto; + max-height: $selectContainerHeight - 2px; + } + + .tb-no-image { + text-align: center; + color: rgba(0, 0, 0, 0.38); + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; + letter-spacing: 0.4px; + } + } + + .tb-image-info-container { + display: flex; + flex: 1; + align-self: stretch; + padding: 0 8px; + justify-content: flex-end; + align-items: center; + gap: 4px; + + .tb-external-image-container { + display: flex; + flex: 1; + align-self: stretch; + padding: 16px 8px 0 16px; + flex-direction: column; + align-items: flex-start; + gap: 4px; + .tb-external-link-label { + color: rgba(0, 0, 0, 0.54); + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; + letter-spacing: 0.4px; + } + .tb-external-link-input-container { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 4px; + align-self: stretch; + .tb-inline-field { + width: 100%; + } + .tb-image-decline-btn { + color: rgba(0,0,0,0.38); + } + } + } + + } + + .tb-image-select-buttons-container { + display: flex; + flex: 1; + align-self: stretch; + padding: 8px; + gap: 8px; + justify-content: center; + align-items: flex-start; + .tb-image-select-button { + width: 100%; + height: 100%; + align-self: stretch; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 4px; + padding: 8px; + line-height: normal; + font-size: 12px; + @media #{$mat-gt-xs} { + padding: 16px; + } + .mat-icon { + width: 24px; + height: 24px; + font-size: 24px; + margin: 0; + } + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/image/multiple-gallery-image-input.component.ts b/ui-ngx/src/app/modules/home/components/image/multiple-gallery-image-input.component.ts new file mode 100644 index 0000000000..aa36ef4881 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/image/multiple-gallery-image-input.component.ts @@ -0,0 +1,180 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { ChangeDetectorRef, Component, forwardRef, Input, OnDestroy, Renderer2, ViewContainerRef } from '@angular/core'; +import { PageComponent } from '@shared/components/page.component'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, } from '@angular/forms'; +import { moveItemInArray } from '@angular/cdk/drag-drop'; +import { DndDropEvent } from 'ngx-drag-drop'; +import { isUndefined } from '@core/utils'; +import { coerceBoolean } from '@shared/decorators/coercion'; +import { ImageLinkType } from '@home/components/image/gallery-image-input.component'; +import { TbPopoverService } from '@shared/components/popover.service'; +import { MatButton } from '@angular/material/button'; +import { ImageGalleryComponent } from '@home/components/image/image-gallery.component'; + +@Component({ + selector: 'tb-multiple-gallery-image-input', + templateUrl: './multiple-gallery-image-input.component.html', + styleUrls: ['./multiple-gallery-image-input.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MultipleGalleryImageInputComponent), + multi: true + } + ] +}) +export class MultipleGalleryImageInputComponent extends PageComponent implements OnDestroy, ControlValueAccessor { + + @Input() + label: string; + + @Input() + @coerceBoolean() + required = false; + + @Input() + disabled: boolean; + + imageUrls: string[]; + + ImageLinkType = ImageLinkType; + + linkType: ImageLinkType = ImageLinkType.none; + + externalLinkControl = new FormControl(null); + + dragIndex: number; + + private propagateChange = null; + + constructor(protected store: Store, + private cd: ChangeDetectorRef, + private renderer: Renderer2, + private viewContainerRef: ViewContainerRef, + private popoverService: TbPopoverService) { + super(store); + } + + ngOnDestroy() { + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + } + + writeValue(value: string[]): void { + this.reset(); + this.imageUrls = value || []; + } + + private updateModel() { + this.cd.markForCheck(); + this.propagateChange(this.imageUrls); + } + + private reset() { + this.linkType = ImageLinkType.none; + this.externalLinkControl.setValue(null, {emitEvent: false}); + } + + clearImage(index: number) { + this.imageUrls.splice(index, 1); + this.updateModel(); + } + + setLink($event: Event) { + if ($event) { + $event.stopPropagation(); + } + this.linkType = ImageLinkType.external; + } + + declineLink($event: Event) { + if ($event) { + $event.stopPropagation(); + } + this.reset(); + } + + applyLink($event: Event) { + if ($event) { + $event.stopPropagation(); + } + this.imageUrls.push(this.externalLinkControl.value); + this.reset(); + this.updateModel(); + } + + toggleGallery($event: Event, browseGalleryButton: MatButton) { + if ($event) { + $event.stopPropagation(); + } + const trigger = browseGalleryButton._elementRef.nativeElement; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const ctx: any = { + pageMode: false, + popoverMode: true, + mode: 'grid', + selectionMode: true + }; + const imageGalleryPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, ImageGalleryComponent, 'top', true, null, + ctx, + {}, + {}, {}, true); + imageGalleryPopover.tbComponentRef.instance.imageSelected.subscribe((image) => { + imageGalleryPopover.hide(); + this.imageUrls.push(image.link); + this.updateModel(); + }); + } + } + + imageDragStart(index: number) { + setTimeout(() => { + this.dragIndex = index; + this.cd.markForCheck(); + }); + } + + imageDragEnd() { + this.dragIndex = -1; + this.cd.markForCheck(); + } + + imageDrop(event: DndDropEvent) { + let index = event.index; + if (isUndefined(index)) { + index = this.imageUrls.length; + } + moveItemInArray(this.imageUrls, this.dragIndex, index); + this.dragIndex = -1; + this.updateModel(); + } +} diff --git a/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.html b/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.html index 779bc94f8f..4480d76fab 100644 --- a/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.html @@ -78,11 +78,10 @@ {{ 'device-profile.type-required' | translate }}
- - + device-profile.description diff --git a/ui-ngx/src/app/modules/home/components/profile/asset-profile.component.html b/ui-ngx/src/app/modules/home/components/profile/asset-profile.component.html index dcd1899321..88b55d508b 100644 --- a/ui-ngx/src/app/modules/home/components/profile/asset-profile.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/asset-profile.component.html @@ -83,11 +83,10 @@ [ruleChainType]="edgeRuleChainType"> {{'asset-profile.default-edge-rule-chain-hint' | translate}} - - + asset-profile.description diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile.component.html b/ui-ngx/src/app/modules/home/components/profile/device-profile.component.html index 7f9505e3ff..af0330953f 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device-profile.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device-profile.component.html @@ -108,11 +108,10 @@ {{ 'device-profile.type-required' | translate }} - - + device-profile.description diff --git a/ui-ngx/src/app/modules/home/components/shared-home-components.module.ts b/ui-ngx/src/app/modules/home/components/shared-home-components.module.ts index 865e7cf224..bce8a4e5f7 100644 --- a/ui-ngx/src/app/modules/home/components/shared-home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/shared-home-components.module.ts @@ -22,6 +22,14 @@ import { SHARED_HOME_COMPONENTS_MODULE_TOKEN } from '@home/components/tokens'; import { AlarmCommentComponent } from '@home/components/alarm/alarm-comment.component'; import { AlarmCommentDialogComponent } from '@home/components/alarm/alarm-comment-dialog.component'; import { AlarmAssigneeComponent } from '@home/components/alarm/alarm-assignee.component'; +import { ScrollGridComponent } from '@home/components/grid/scroll-grid.component'; +import { ImageGalleryComponent } from '@home/components/image/image-gallery.component'; +import { UploadImageDialogComponent } from '@home/components/image/upload-image-dialog.component'; +import { ImageDialogComponent } from '@home/components/image/image-dialog.component'; +import { ImageReferencesComponent } from '@home/components/image/image-references.component'; +import { ImagesInUseDialogComponent } from '@home/components/image/images-in-use-dialog.component'; +import { GalleryImageInputComponent } from '@home/components/image/gallery-image-input.component'; +import { MultipleGalleryImageInputComponent } from '@home/components/image/multiple-gallery-image-input.component'; @NgModule({ providers: [ @@ -32,7 +40,15 @@ import { AlarmAssigneeComponent } from '@home/components/alarm/alarm-assignee.co AlarmDetailsDialogComponent, AlarmCommentComponent, AlarmCommentDialogComponent, - AlarmAssigneeComponent + AlarmAssigneeComponent, + ScrollGridComponent, + ImageGalleryComponent, + UploadImageDialogComponent, + ImageDialogComponent, + ImageReferencesComponent, + ImagesInUseDialogComponent, + GalleryImageInputComponent, + MultipleGalleryImageInputComponent ], imports: [ CommonModule, @@ -42,7 +58,15 @@ import { AlarmAssigneeComponent } from '@home/components/alarm/alarm-assignee.co AlarmDetailsDialogComponent, AlarmCommentComponent, AlarmCommentDialogComponent, - AlarmAssigneeComponent + AlarmAssigneeComponent, + ScrollGridComponent, + ImageGalleryComponent, + UploadImageDialogComponent, + ImageDialogComponent, + ImageReferencesComponent, + ImagesInUseDialogComponent, + GalleryImageInputComponent, + MultipleGalleryImageInputComponent ] }) export class SharedHomeComponentsModule { } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts index 64ef1a6303..7f611bc16a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts @@ -32,7 +32,7 @@ import { WidgetUnitedMapSettings } from './map-models'; import { Marker } from './markers'; -import { Observable, of } from 'rxjs'; +import { map, Observable, of, switchMap } from 'rxjs'; import { Polyline } from './polyline'; import { Polygon } from './polygon'; import { Circle } from './circle'; @@ -63,6 +63,7 @@ import { import { MatDialog } from '@angular/material/dialog'; import { FormattedData, ReplaceInfo } from '@shared/models/widget.models'; import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance; +import { ImagePipe } from '@shared/pipe/image.pipe'; export default abstract class LeafletMap { @@ -895,16 +896,27 @@ export default abstract class LeafletMap { const currentImage: MarkerImageInfo = this.options.useMarkerImageFunction ? safeExecute(this.options.parsedMarkerImageFunction, [data, this.options.markerImages, markersData, data.dsIndex]) : this.options.currentImage; - const imageSize = `height: ${this.options.markerImageSize || 34}px; width: ${this.options.markerImageSize || 34}px;`; - const style = currentImage ? 'background-image: url(' + currentImage.url + '); ' + imageSize : ''; - this.options.icon = { icon: L.divIcon({ - html: `
{ + const size = this.options.useMarkerImageFunction && currentImage ? currentImage.size : this.options.markerImageSize; + const imageSize = `height: ${size || 34}px; width: ${size || 34}px;`; + const style = imageUrl ? 'background-image: url(' + imageUrl + '); ' + imageSize : ''; + return { icon: L.divIcon({ + html: `
` - }), size: [30, 30]}; + }), size: [size, size]}; + }) + ); + this.options.icon = null; } else { this.options.icon = null; + this.options.icon$ = null; } if (this.markers.get(data.entityName)) { m = this.updateMarker(data.entityName, data, markersData, this.options); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts index bac18f5af6..50b975497d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts @@ -17,6 +17,7 @@ import { Datasource, FormattedData } from '@app/shared/models/widget.models'; import tinycolor from 'tinycolor2'; import { BaseIconOptions, Icon } from 'leaflet'; +import { Observable } from 'rxjs'; export const DEFAULT_MAP_PAGE_SIZE = 16384; export const DEFAULT_ZOOM_LEVEL = 8; @@ -337,6 +338,7 @@ export interface WidgetMarkersSettings extends MarkersSettings, WidgetToolipSett currentImage: MarkerImageInfo; tinyColor: tinycolor.Instance; icon: MarkerIconInfo; + icon$?: Observable; } export const defaultMarkersSettings: MarkersSettings = { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts index 29d92b2057..f5f302cee3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts @@ -155,6 +155,11 @@ export class Marker { if (this.settings.icon) { onMarkerIconReady(this.settings.icon); return; + } else if (this.settings.icon$) { + this.settings.icon$.subscribe((res) => { + onMarkerIconReady(res); + }); + return; } const currentImage: MarkerImageInfo = this.settings.useMarkerImageFunction ? safeExecute(this.settings.parsedMarkerImageFunction, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.html index c111f84e9f..a9d7a2c8ff 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.html @@ -16,9 +16,9 @@ -->
- - +
widgets.maps.image-map-background-from-entity-attribute
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/markers-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/markers-settings.component.html index 2b5de971b5..8de4820690 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/markers-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/markers-settings.component.html @@ -170,10 +170,10 @@ - - + widgets.maps.custom-marker-image-size @@ -186,10 +186,10 @@ functionTitle="{{ 'widgets.maps.marker-image-function' | translate }}" helpId="widget/lib/map/marker_image_fn"> - - + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-marker-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-marker-settings.component.html index fd14bebdf7..0f31ab54a7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-marker-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-marker-settings.component.html @@ -70,10 +70,10 @@ - - + widgets.maps.custom-marker-image-size @@ -86,10 +86,10 @@ functionTitle="{{ 'widgets.maps.marker-image-function' | translate }}" helpId="widget/lib/map/marker_image_fn"> - - + + diff --git a/ui-ngx/src/app/modules/home/pages/admin/admin.module.ts b/ui-ngx/src/app/modules/home/pages/admin/admin.module.ts index 533fd0fea1..2d8bfe98fe 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/admin.module.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/admin.module.ts @@ -33,6 +33,7 @@ import { QueueComponent } from '@home/pages/admin/queue/queue.component'; import { RepositoryAdminSettingsComponent } from '@home/pages/admin/repository-admin-settings.component'; import { AutoCommitAdminSettingsComponent } from '@home/pages/admin/auto-commit-admin-settings.component'; import { TwoFactorAuthSettingsComponent } from '@home/pages/admin/two-factor-auth-settings.component'; +import { SharedHomeComponentsModule } from '@home/components/shared-home-components.module'; @NgModule({ declarations: @@ -54,6 +55,7 @@ import { TwoFactorAuthSettingsComponent } from '@home/pages/admin/two-factor-aut imports: [ CommonModule, SharedModule, + SharedHomeComponentsModule, HomeComponentsModule, AdminRoutingModule ] diff --git a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.html b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.html index 0cb6adc7be..41c36e9440 100644 --- a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.html +++ b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.html @@ -125,11 +125,10 @@
dashboard.mobile-app-settings
- - + {{ 'dashboard.mobile-hide' | translate }} diff --git a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard.module.ts b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard.module.ts index b9feff9be7..cd60a6ddee 100644 --- a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard.module.ts +++ b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard.module.ts @@ -24,6 +24,7 @@ import { DashboardRoutingModule } from './dashboard-routing.module'; import { MakeDashboardPublicDialogComponent } from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component'; import { HomeComponentsModule } from '@modules/home/components/home-components.module'; import { DashboardTabsComponent } from '@home/pages/dashboard/dashboard-tabs.component'; +import { SharedHomeComponentsModule } from '@home/components/shared-home-components.module'; @NgModule({ declarations: [ @@ -35,6 +36,7 @@ import { DashboardTabsComponent } from '@home/pages/dashboard/dashboard-tabs.com imports: [ CommonModule, SharedModule, + SharedHomeComponentsModule, HomeComponentsModule, HomeDialogsModule, DashboardRoutingModule diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.html b/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.html index f3410f9893..2251bd4022 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.html +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-editor.component.html @@ -240,11 +240,10 @@
- - + widget.description diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html index 89d122eccd..978a79ad63 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html @@ -58,11 +58,6 @@ label="{{'widgets-bundle.image-preview' | translate}}" formControlName="image"> - widgets-bundle.description