From cf942478b3783bb4bb24a53d23f21c85d7842816 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 27 Nov 2023 14:56:22 +0200 Subject: [PATCH] UI: Improve image references component style. Improve browse image gallery popup. --- .../image/gallery-image-input.component.scss | 13 ++- .../image/gallery-image-input.component.ts | 16 ++-- .../image/image-gallery.component.html | 8 +- .../image/image-gallery.component.scss | 18 ++-- .../image/image-gallery.component.ts | 73 +++++++++------ .../image/image-references.component.html | 27 +++--- .../image/image-references.component.scss | 92 +++++++++++++++++++ .../image/image-references.component.ts | 2 +- .../image/images-in-use-dialog.component.scss | 1 + ui-ngx/src/form.scss | 1 + 10 files changed, 192 insertions(+), 59 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/image/image-references.component.scss diff --git a/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.scss b/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.scss index 6b64516816..77b3aaec7a 100644 --- a/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.scss +++ b/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.scss @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +@import "../../../../../scss/constants"; + $containerHeight: 96px !default; :host { @@ -94,6 +97,11 @@ $containerHeight: 96px !default; gap: 4px; .tb-resource-image-name { color: rgba(0, 0, 0, 0.54); + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 2; + display: -webkit-box; + -webkit-box-orient: vertical; font-size: 12px; font-style: normal; font-weight: 500; @@ -166,9 +174,12 @@ $containerHeight: 96px !default; justify-content: center; align-items: center; gap: 4px; - padding: 16px; + padding: 8px; line-height: normal; font-size: 12px; + @media #{$mat-gt-xs} { + padding: 16px; + } .mat-icon { width: 24px; height: 24px; diff --git a/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.ts b/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.ts index 527fe28d12..e0e4166918 100644 --- a/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.ts +++ b/ui-ngx/src/app/modules/home/components/image/gallery-image-input.component.ts @@ -97,8 +97,7 @@ export class GalleryImageInputComponent extends PageComponent implements OnInit, ngOnInit() { this.externalLinkControl.valueChanges.subscribe((value) => { if (this.linkType === ImageLinkType.external) { - this.imageUrl = value; - this.updateModel(); + this.updateModel(value); } }); } @@ -168,21 +167,23 @@ export class GalleryImageInputComponent extends PageComponent implements OnInit, } } - private updateModel() { + private updateModel(value: string) { this.cd.markForCheck(); - this.propagateChange(this.imageUrl); + if (this.imageUrl !== value) { + this.imageUrl = value; + this.propagateChange(this.imageUrl); + } } private reset() { this.linkType = ImageLinkType.none; - this.imageUrl = null; this.imageResource = null; this.externalLinkControl.setValue(null, {emitEvent: false}); } clearImage() { this.reset(); - this.updateModel(); + this.updateModel(null); } setLink($event: Event) { @@ -214,9 +215,8 @@ export class GalleryImageInputComponent extends PageComponent implements OnInit, imageGalleryPopover.tbComponentRef.instance.imageSelected.subscribe((image) => { imageGalleryPopover.hide(); this.linkType = ImageLinkType.resource; - this.imageUrl = image.link; this.imageResource = image; - this.updateModel(); + this.updateModel(image.link); }); } } diff --git a/ui-ngx/src/app/modules/home/components/image/image-gallery.component.html b/ui-ngx/src/app/modules/home/components/image/image-gallery.component.html index 6b46bb1779..882f411dd9 100644 --- a/ui-ngx/src/app/modules/home/components/image/image-gallery.component.html +++ b/ui-ngx/src/app/modules/home/components/image/image-gallery.component.html @@ -45,7 +45,8 @@ {{ 'image.include-system-images' | translate }} + [ngModel]="includeSystemImages" + (ngModelChange)="includeSystemImagesChanged($event)">{{ 'image.include-system-images' | translate }}
@@ -91,7 +92,8 @@
{{ 'image.include-system-images' | translate }} + [ngModel]="includeSystemImages" + (ngModelChange)="includeSystemImagesChanged($event)">{{ 'image.include-system-images' | translate }}
@@ -259,7 +261,7 @@ + *matRowDef="let image; columns: displayedColumns;" (click)="rowClick($event, image)"> diff --git a/ui-ngx/src/app/modules/home/components/image/image-gallery.component.scss b/ui-ngx/src/app/modules/home/components/image/image-gallery.component.scss index 00b40ff2e1..e82fcc84b1 100644 --- a/ui-ngx/src/app/modules/home/components/image/image-gallery.component.scss +++ b/ui-ngx/src/app/modules/home/components/image/image-gallery.component.scss @@ -28,23 +28,27 @@ $tb-button-selected-color: rgb(255, 110, 64) !default; max-width: calc(100vw - 50px); max-height: calc(100vh - 100px); @media #{$mat-gt-xs} { - width: 400px; - height: 600px; - } - @media #{$mat-gt-sm} { width: 500px; height: 600px; } - @media #{$mat-gt-md} { + @media #{$mat-gt-sm} { width: 700px; + height: 600px; + } + @media #{$mat-gt-md} { + width: 1000px; height: 700px; } @media #{$mat-gt-xmd} { - width: 900px; + width: 1300px; height: 700px; } @media #{$mat-gt-xl} { - width: 1200px; + width: 1600px; + height: 800px; + } + @media screen and (min-width: 2320px) { + width: 2000px; height: 800px; } } diff --git a/ui-ngx/src/app/modules/home/components/image/image-gallery.component.ts b/ui-ngx/src/app/modules/home/components/image/image-gallery.component.ts index c8d65d2732..0bad2f1f42 100644 --- a/ui-ngx/src/app/modules/home/components/image/image-gallery.component.ts +++ b/ui-ngx/src/app/modules/home/components/image/image-gallery.component.ts @@ -88,11 +88,14 @@ const pageGridColumns: ScrollGridColumns = { }; const popoverGridColumns: ScrollGridColumns = { - columns: 2, + columns: 1, breakpoints: { - 'gt-lg': 5, - 'screen and (min-width: 1600px)': 4, - 'gt-md': 3 + 'screen and (min-width: 2320px)': 8, + 'gt-lg': 6, + 'screen and (min-width: 1600px)': 5, + 'gt-md': 4, + 'gt-sm': 3, + 'gt-xs': 2 } }; @@ -141,7 +144,7 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe dataSource: ImagesDatasource; textSearch = this.fb.control('', {nonNullable: true}); - includeSystemImages = this.fb.control(false); + includeSystemImages = false; gridColumns: ScrollGridColumns; @@ -257,29 +260,29 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe } else { this.gridImagesFilter = { search: isNotEmptyStr(value) ? encodeURI(value) : null, - includeSystemImages: this.includeSystemImages.value + includeSystemImages: this.includeSystemImages }; this.cd.markForCheck(); } }); - this.includeSystemImages.valueChanges.pipe( - takeUntil(this.destroy$) - ).subscribe(value => { - this.displayedColumns = this.computeDisplayedColumns(); - this.gridImagesFilter = { - search: this.gridImagesFilter.search, - includeSystemImages: value - }; - if (this.mode === 'list') { - this.paginator.pageIndex = 0; - this.updateData(); - } else { - this.cd.markForCheck(); - } - }); this.updateMode(); } + public includeSystemImagesChanged(value: boolean) { + this.includeSystemImages = value; + this.displayedColumns = this.computeDisplayedColumns(); + this.gridImagesFilter = { + search: this.gridImagesFilter.search, + includeSystemImages: this.includeSystemImages + }; + if (this.mode === 'list') { + this.paginator.pageIndex = 0; + this.updateData(); + } else { + this.cd.markForCheck(); + } + } + public setMode(targetMode: 'list' | 'grid') { if (this.mode !== targetMode) { if (this.widgetResize$) { @@ -307,14 +310,20 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe } private computeDisplayedColumns(): string[] { + let columns: string[]; if (this.selectionMode) { - return ['preview', 'title', 'imageSelect']; + columns = ['preview', 'title']; + if (!this.isSysAdmin && this.includeSystemImages) { + columns.push('system'); + } + columns.push('imageSelect'); + } else { + columns = ['select', 'preview', 'title', 'createdTime', 'resolution', 'size']; + if (!this.isSysAdmin && this.includeSystemImages) { + columns.push('system'); + } + columns.push('actions'); } - const columns = ['select', 'preview', 'title', 'createdTime', 'resolution', 'size']; - if (!this.isSysAdmin && this.includeSystemImages.value) { - columns.push('system'); - } - columns.push('actions'); return columns; } @@ -411,7 +420,7 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe } else { this.pageLink.sortOrder = null; } - this.dataSource.loadEntities(this.pageLink, this.includeSystemImages.value); + this.dataSource.loadEntities(this.pageLink, this.includeSystemImages); } else { this.gridComponent.update(); } @@ -599,6 +608,14 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe this.imageSelected.next(image); } + rowClick($event, image: ImageResourceInfo) { + if (this.selectionMode) { + this.selectImage($event, image); + } else { + this.dataSource.selection.toggle(image); + } + } + uploadImage(): void { this.dialog.open(UploadImageDialogComponent, { diff --git a/ui-ngx/src/app/modules/home/components/image/image-references.component.html b/ui-ngx/src/app/modules/home/components/image/image-references.component.html index fd8fd29fbe..611d744cfa 100644 --- a/ui-ngx/src/app/modules/home/components/image/image-references.component.html +++ b/ui-ngx/src/app/modules/home/components/image/image-references.component.html @@ -20,15 +20,17 @@ -
    +
      -
    • - {{ 'image.system-entities' | translate }} +
    • +
      {{ 'image.system-entities' | translate }}
    • -
    • - {{ 'tenant.tenant' | translate }} {{ '"' + entry[1].tenantName + '"' }} {{ 'image.entities' | translate }} +
    • +
      + {{ 'tenant.tenant' | translate }} {{ entry[1].tenantName }} {{ 'image.entities' | translate }} +
    • @@ -37,12 +39,15 @@
      - + + + + + +
      {{ referencedEntity.typeName }} + {{ referencedEntity.entity.name }} + {{ referencedEntity.entity.name }} +
      diff --git a/ui-ngx/src/app/modules/home/components/image/image-references.component.scss b/ui-ngx/src/app/modules/home/components/image/image-references.component.scss new file mode 100644 index 0000000000..e9a527e747 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/image/image-references.component.scss @@ -0,0 +1,92 @@ +/** + * 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"; + +:host { + ul.tb-references { + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 12px; + } + li.tb-entities-container { + padding: 8px 12px 12px 12px; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + border-radius: 8px; + } + a.tb-reference { + color: $tb-primary-color; + font-weight: inherit; + } + .tb-entities-title { + display: flex; + gap: 8px; + color: rgba(0, 0, 0, 0.87); + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: 0.25px; + } + table.tb-entities-list-table { + position: relative; + overflow: hidden; + padding: 8px 10px 8px 4px; + border-radius: 4px; + background: #fff; + align-self: stretch; + z-index: 1; + color: rgba(0, 0, 0, 0.76); + &:before { + display: block; + height: auto; + content: ""; + position: absolute; + inset: 0; + border-radius: 4px; + border: 1px solid $tb-primary-color; + background: transparent; + opacity: 0.4; + pointer-events: none; + } + td.tb-entity-type { + white-space: nowrap; + padding-right: 20px; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: 0.25px; + &:before { + content: "•"; + padding-left: 8px; + padding-right: 8px; + } + } + td.tb-entity-name { + width: 100%; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: 0.2px; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/image/image-references.component.ts b/ui-ngx/src/app/modules/home/components/image/image-references.component.ts index ae63b93514..b236c6d47c 100644 --- a/ui-ngx/src/app/modules/home/components/image/image-references.component.ts +++ b/ui-ngx/src/app/modules/home/components/image/image-references.component.ts @@ -49,7 +49,7 @@ type ReferencedEntitiesEntry = [string, TenantReferencedEntities]; @Component({ selector: 'tb-image-references', templateUrl: './image-references.component.html', - styleUrls: [] + styleUrls: ['./image-references.component.scss'] }) export class ImageReferencesComponent implements OnInit { diff --git a/ui-ngx/src/app/modules/home/components/image/images-in-use-dialog.component.scss b/ui-ngx/src/app/modules/home/components/image/images-in-use-dialog.component.scss index a53c97404d..ba8531802e 100644 --- a/ui-ngx/src/app/modules/home/components/image/images-in-use-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/components/image/images-in-use-dialog.component.scss @@ -17,6 +17,7 @@ .tb-images-in-use-content { display: flex; flex-direction: column; + gap: 24px; &.multiple { gap: 16px; } diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss index 3b29fe986c..3e6ea6a2cc 100644 --- a/ui-ngx/src/form.scss +++ b/ui-ngx/src/form.scss @@ -523,6 +523,7 @@ right: 0; background: $tb-primary-color; opacity: 0.04; + pointer-events: none; } }