UI: Improve image references component style. Improve browse image gallery popup.
This commit is contained in:
parent
bda319c3e8
commit
cf942478b3
@ -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;
|
||||
|
||||
@ -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();
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +45,8 @@
|
||||
</div>
|
||||
<mat-slide-toggle *ngIf="!isSysAdmin"
|
||||
fxHide fxShow.gt-sm
|
||||
[formControl]="includeSystemImages">{{ 'image.include-system-images' | translate }}</mat-slide-toggle>
|
||||
[ngModel]="includeSystemImages"
|
||||
(ngModelChange)="includeSystemImagesChanged($event)">{{ 'image.include-system-images' | translate }}</mat-slide-toggle>
|
||||
</div>
|
||||
<section fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
|
||||
<span fxFlex></span>
|
||||
@ -91,7 +92,8 @@
|
||||
</section>
|
||||
</div>
|
||||
<mat-slide-toggle *ngIf="!isSysAdmin" fxHide fxShow.lt-md
|
||||
[formControl]="includeSystemImages">{{ 'image.include-system-images' | translate }}</mat-slide-toggle>
|
||||
[ngModel]="includeSystemImages"
|
||||
(ngModelChange)="includeSystemImagesChanged($event)">{{ 'image.include-system-images' | translate }}</mat-slide-toggle>
|
||||
</mat-toolbar>
|
||||
<mat-toolbar class="mat-mdc-table-toolbar" [fxShow]="textSearchMode && (mode === 'grid' || dataSource?.selection.isEmpty())">
|
||||
<div class="mat-toolbar-tools">
|
||||
@ -259,7 +261,7 @@
|
||||
<mat-header-row [ngClass]="{'mat-row-select': true}" *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row>
|
||||
<mat-row [ngClass]="{'mat-row-select': true,
|
||||
'mat-selected': dataSource.selection.isSelected(image)}"
|
||||
*matRowDef="let image; columns: displayedColumns;" (click)="dataSource.selection.toggle(image)"></mat-row>
|
||||
*matRowDef="let image; columns: displayedColumns;" (click)="rowClick($event, image)"></mat-row>
|
||||
</table>
|
||||
<ng-container *ngIf="(dataSource.isEmpty() | async) && !dataSource.dataLoading">
|
||||
<ng-container *ngTemplateOutlet="noImages"></ng-container>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,18 +260,20 @@ 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.updateMode();
|
||||
}
|
||||
|
||||
public includeSystemImagesChanged(value: boolean) {
|
||||
this.includeSystemImages = value;
|
||||
this.displayedColumns = this.computeDisplayedColumns();
|
||||
this.gridImagesFilter = {
|
||||
search: this.gridImagesFilter.search,
|
||||
includeSystemImages: value
|
||||
includeSystemImages: this.includeSystemImages
|
||||
};
|
||||
if (this.mode === 'list') {
|
||||
this.paginator.pageIndex = 0;
|
||||
@ -276,8 +281,6 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe
|
||||
} else {
|
||||
this.cd.markForCheck();
|
||||
}
|
||||
});
|
||||
this.updateMode();
|
||||
}
|
||||
|
||||
public setMode(targetMode: 'list' | 'grid') {
|
||||
@ -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');
|
||||
}
|
||||
const columns = ['select', 'preview', 'title', 'createdTime', 'resolution', 'size'];
|
||||
if (!this.isSysAdmin && this.includeSystemImages.value) {
|
||||
columns.push('imageSelect');
|
||||
} else {
|
||||
columns = ['select', 'preview', 'title', 'createdTime', 'resolution', 'size'];
|
||||
if (!this.isSysAdmin && this.includeSystemImages) {
|
||||
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, UploadImageDialogData,
|
||||
ImageResourceInfo>(UploadImageDialogComponent, {
|
||||
|
||||
@ -20,15 +20,17 @@
|
||||
</ng-container>
|
||||
<ng-template #complexEntityReferences>
|
||||
<ng-container *ngIf="contentReady; else loading">
|
||||
<ul>
|
||||
<ul class="tb-references">
|
||||
<ng-container *ngFor="let entry of referencedEntitiesEntries">
|
||||
<li *ngIf="isSystem(entry[0]); else tenantEntities">
|
||||
{{ 'image.system-entities' | translate }}
|
||||
<li class="tb-entities-container tb-primary-fill" *ngIf="isSystem(entry[0]); else tenantEntities">
|
||||
<div class="tb-entities-title">{{ 'image.system-entities' | translate }}</div>
|
||||
<ng-container *ngTemplateOutlet="referencesList; context:{entriesList: entry[1].entities, showDetailsLink: true}"></ng-container>
|
||||
</li>
|
||||
<ng-template #tenantEntities>
|
||||
<li>
|
||||
{{ 'tenant.tenant' | translate }} <a [routerLink]="entry[1].tenantDetailsUrl">{{ '"' + entry[1].tenantName + '"' }}</a> {{ 'image.entities' | translate }}
|
||||
<li class="tb-entities-container tb-primary-fill">
|
||||
<div class="tb-entities-title">
|
||||
{{ 'tenant.tenant' | translate }} <a class="tb-reference" [routerLink]="entry[1].tenantDetailsUrl">{{ entry[1].tenantName }}</a> {{ 'image.entities' | translate }}
|
||||
</div>
|
||||
<ng-container *ngTemplateOutlet="referencesList; context:{entriesList: entry[1].entities, showDetailsLink: false}"></ng-container>
|
||||
</li>
|
||||
</ng-template>
|
||||
@ -37,12 +39,15 @@
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
<ng-template #referencesList let-entriesList="entriesList" let-showDetailsLink="showDetailsLink">
|
||||
<ul>
|
||||
<li *ngFor="let referencedEntity of entriesList">
|
||||
{{ referencedEntity.typeName }} <a *ngIf="showDetailsLink" [routerLink]="referencedEntity.detailsUrl">{{ '"' + referencedEntity.entity.name + '"' }}</a>
|
||||
<b *ngIf="!showDetailsLink">{{ '"' + referencedEntity.entity.name + '"' }}</b>
|
||||
</li>
|
||||
</ul>
|
||||
<table class="tb-entities-list-table">
|
||||
<tr *ngFor="let referencedEntity of entriesList">
|
||||
<td class="tb-entity-type">{{ referencedEntity.typeName }}</td>
|
||||
<td class="tb-entity-name">
|
||||
<a *ngIf="showDetailsLink" class="tb-reference" [routerLink]="referencedEntity.detailsUrl">{{ referencedEntity.entity.name }}</a>
|
||||
<span *ngIf="!showDetailsLink">{{ referencedEntity.entity.name }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</ng-template>
|
||||
<ng-template #loading>
|
||||
<mat-spinner [diameter]="32" strokeWidth="2"></mat-spinner>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 {
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
.tb-images-in-use-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
&.multiple {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
@ -523,6 +523,7 @@
|
||||
right: 0;
|
||||
background: $tb-primary-color;
|
||||
opacity: 0.04;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user