Merge remote-tracking branch 'upstream/master' into feature/edge-alarm-comment-support
This commit is contained in:
commit
92c23aa0cb
@ -66,12 +66,11 @@
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="linkType === ImageLinkType.none && !disabled" class="tb-image-select-buttons-container">
|
||||
<button #browseGalleryButton
|
||||
mat-stroked-button
|
||||
<button mat-stroked-button
|
||||
type="button"
|
||||
color="primary"
|
||||
class="tb-image-select-button"
|
||||
(click)="toggleGallery($event, browseGalleryButton)">
|
||||
(click)="openGallery($event)">
|
||||
<tb-icon matButtonIcon>filter</tb-icon>
|
||||
<span translate>image.browse-from-gallery</span>
|
||||
</button>
|
||||
|
||||
@ -14,16 +14,7 @@
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
import {
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
forwardRef,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Renderer2,
|
||||
ViewContainerRef
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectorRef, Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { PageComponent } from '@shared/components/page.component';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '@core/core.state';
|
||||
@ -33,12 +24,13 @@ import {
|
||||
extractParamsFromImageResourceUrl,
|
||||
ImageResourceInfo,
|
||||
isBase64DataImageUrl,
|
||||
isImageResourceUrl, prependTbImagePrefix, removeTbImagePrefix
|
||||
isImageResourceUrl,
|
||||
prependTbImagePrefix,
|
||||
removeTbImagePrefix
|
||||
} from '@shared/models/resource.models';
|
||||
import { ImageService } from '@core/http/image.service';
|
||||
import { MatButton } from '@angular/material/button';
|
||||
import { TbPopoverService } from '@shared/components/popover.service';
|
||||
import { ImageGalleryComponent } from '@shared/components/image/image-gallery.component';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ImageGalleryDialogComponent } from '@shared/components/image/image-gallery-dialog.component';
|
||||
|
||||
export enum ImageLinkType {
|
||||
none = 'none',
|
||||
@ -87,10 +79,8 @@ export class GalleryImageInputComponent extends PageComponent implements OnInit,
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
private imageService: ImageService,
|
||||
private cd: ChangeDetectorRef,
|
||||
private renderer: Renderer2,
|
||||
private viewContainerRef: ViewContainerRef,
|
||||
private popoverService: TbPopoverService) {
|
||||
private dialog: MatDialog,
|
||||
private cd: ChangeDetectorRef) {
|
||||
super(store);
|
||||
}
|
||||
|
||||
@ -194,32 +184,22 @@ export class GalleryImageInputComponent extends PageComponent implements OnInit,
|
||||
this.linkType = ImageLinkType.external;
|
||||
}
|
||||
|
||||
toggleGallery($event: Event, browseGalleryButton: MatButton) {
|
||||
openGallery($event: Event): void {
|
||||
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.dialog.open<ImageGalleryDialogComponent, any,
|
||||
ImageResourceInfo>(ImageGalleryDialogComponent, {
|
||||
autoFocus: false,
|
||||
disableClose: false,
|
||||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog']
|
||||
}).afterClosed().subscribe((image) => {
|
||||
if (image) {
|
||||
this.linkType = ImageLinkType.resource;
|
||||
this.imageResource = image;
|
||||
this.updateModel(image.link);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
<!--
|
||||
|
||||
Copyright © 2016-2024 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.
|
||||
|
||||
-->
|
||||
<div class="tb-image-gallery-dialog">
|
||||
<button class="tb-image-gallery-close tb-mat-20"
|
||||
mat-icon-button
|
||||
(click)="cancel()"
|
||||
type="button">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
<tb-image-gallery
|
||||
pageMode="false"
|
||||
dialogMode
|
||||
mode="grid"
|
||||
selectionMode
|
||||
(imageSelected)="imageSelected($event)">
|
||||
</tb-image-gallery>
|
||||
</div>
|
||||
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright © 2016-2024 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 {
|
||||
.tb-image-gallery-dialog {
|
||||
position: relative;
|
||||
padding: 24px 32px 16px 32px;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
@media #{$mat-gt-xs} {
|
||||
width: 80vw;
|
||||
height: 80vh;
|
||||
max-height: 80vh;
|
||||
}
|
||||
@media #{$mat-gt-sm} {
|
||||
width: 700px;
|
||||
}
|
||||
@media #{$mat-gt-md} {
|
||||
width: 900px;
|
||||
}
|
||||
@media #{$mat-gt-xl} {
|
||||
width: 900px;
|
||||
}
|
||||
.tb-image-gallery-close {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
z-index: 1;
|
||||
color: rgba(0, 0, 0, 0.38);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
///
|
||||
/// Copyright © 2016-2024 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 { Component, Inject, OnInit, SkipSelf } from '@angular/core';
|
||||
import { ErrorStateMatcher } from '@angular/material/core';
|
||||
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '@core/core.state';
|
||||
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { DialogComponent } from '@shared/components/dialog.component';
|
||||
import { Router } from '@angular/router';
|
||||
import { ImageService } from '@core/http/image.service';
|
||||
import { ImageResourceInfo, imageResourceType } from '@shared/models/resource.models';
|
||||
import {
|
||||
UploadImageDialogComponent,
|
||||
UploadImageDialogData
|
||||
} from '@shared/components/image/upload-image-dialog.component';
|
||||
import { UrlHolder } from '@shared/pipe/image.pipe';
|
||||
import { ImportExportService } from '@shared/import-export/import-export.service';
|
||||
import { EmbedImageDialogComponent, EmbedImageDialogData } from '@shared/components/image/embed-image-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-image-gallery-dialog',
|
||||
templateUrl: './image-gallery-dialog.component.html',
|
||||
styleUrls: ['./image-gallery-dialog.component.scss']
|
||||
})
|
||||
export class ImageGalleryDialogComponent extends
|
||||
DialogComponent<ImageGalleryDialogComponent, ImageResourceInfo> implements OnInit {
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
protected router: Router,
|
||||
private imageService: ImageService,
|
||||
private dialog: MatDialog,
|
||||
public dialogRef: MatDialogRef<ImageGalleryDialogComponent, ImageResourceInfo>) {
|
||||
super(store, router, dialogRef);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
this.dialogRef.close(null);
|
||||
}
|
||||
|
||||
imageSelected(image: ImageResourceInfo): void {
|
||||
this.dialogRef.close(image);
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,11 +15,11 @@
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<div class="tb-images tb-absolute-fill" [ngClass]="{'tb-popover-mode': popoverMode, 'mat-padding': !popoverMode}">
|
||||
<div class="tb-images tb-absolute-fill" [ngClass]="{'tb-dialog-mode': dialogMode, 'mat-padding': !dialogMode}">
|
||||
<div fxFlex fxLayout="column" class="tb-images-content" [ngClass]="{'tb-outlined-border': pageMode}">
|
||||
<mat-toolbar class="mat-mdc-table-toolbar"
|
||||
fxLayout.lt-md="column" fxLayoutAlign.lt-md="start stretch"
|
||||
[fxShow]="!textSearchMode && (mode === 'grid' || dataSource?.selection.isEmpty())" [ngClass.lt-md]="{'multi-row': !isSysAdmin}">
|
||||
fxLayout.lt-lg="column" fxLayoutAlign.lt-lg="start stretch"
|
||||
[fxShow]="!textSearchMode && (mode === 'grid' || dataSource?.selection.isEmpty())" [ngClass.lt-lg]="{'multi-row': !isSysAdmin}">
|
||||
<div fxFlex fxLayout="row" fxLayoutAlign="start center">
|
||||
<div class="mat-toolbar-tools">
|
||||
<span fxHide fxShow.gt-sm class="tb-images-title" translate>image.gallery</span>
|
||||
@ -44,11 +44,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<mat-slide-toggle *ngIf="!isSysAdmin"
|
||||
fxHide fxShow.gt-sm
|
||||
fxHide fxShow.gt-md
|
||||
[ngModel]="includeSystemImages"
|
||||
(ngModelChange)="includeSystemImagesChanged($event)">{{ 'image.include-system-images' | translate }}</mat-slide-toggle>
|
||||
</div>
|
||||
<section fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
|
||||
<section fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap.gt-md="16px">
|
||||
<span fxFlex></span>
|
||||
<section fxLayout="row" fxLayoutAlign="start center">
|
||||
<button [disabled]="isLoading$ | async"
|
||||
@ -79,7 +79,7 @@
|
||||
(click)="uploadImage()"
|
||||
matTooltip="{{'image.upload-image' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>upload</mat-icon>
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
</section>
|
||||
<button fxHide fxShow.gt-md
|
||||
@ -91,7 +91,7 @@
|
||||
</button>
|
||||
</section>
|
||||
</div>
|
||||
<mat-slide-toggle *ngIf="!isSysAdmin" fxHide fxShow.lt-md
|
||||
<mat-slide-toggle *ngIf="!isSysAdmin" fxHide fxShow.lt-lg
|
||||
[ngModel]="includeSystemImages"
|
||||
(ngModelChange)="includeSystemImagesChanged($event)">{{ 'image.include-system-images' | translate }}</mat-slide-toggle>
|
||||
</mat-toolbar>
|
||||
@ -293,7 +293,7 @@
|
||||
[hidePageSize]="hidePageSize"
|
||||
showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
<div fxFlex class="mat-padding" *ngIf="mode === 'grid'" fxLayout="column">
|
||||
<div *ngIf="mode === 'grid'" fxFlex [ngClass]="{'mat-padding': !dialogMode}" fxLayout="column">
|
||||
<tb-scroll-grid fxFlex
|
||||
[columns]="gridColumns"
|
||||
[itemSize]="gridImagesItemSizeStrategy"
|
||||
|
||||
@ -19,36 +19,12 @@ $tb-button-selected-color: rgb(255, 110, 64) !default;
|
||||
|
||||
.tb-images {
|
||||
|
||||
&.tb-popover-mode {
|
||||
padding-top: 8px;
|
||||
&.tb-dialog-mode {
|
||||
position: relative;
|
||||
width: 300px;
|
||||
height: 500px;
|
||||
max-width: calc(100vw - 50px);
|
||||
max-height: calc(100vh - 100px);
|
||||
@media #{$mat-gt-xs} {
|
||||
width: 500px;
|
||||
height: 600px;
|
||||
}
|
||||
@media #{$mat-gt-sm} {
|
||||
width: 700px;
|
||||
height: 600px;
|
||||
}
|
||||
@media #{$mat-gt-md} {
|
||||
width: 1000px;
|
||||
height: 700px;
|
||||
}
|
||||
@media #{$mat-gt-xmd} {
|
||||
width: 1300px;
|
||||
height: 700px;
|
||||
}
|
||||
@media #{$mat-gt-xl} {
|
||||
width: 1600px;
|
||||
height: 800px;
|
||||
}
|
||||
@media screen and (min-width: 2320px) {
|
||||
width: 2000px;
|
||||
height: 800px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.mat-toolbar.mat-mdc-table-toolbar {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -88,15 +88,11 @@ const pageGridColumns: ScrollGridColumns = {
|
||||
}
|
||||
};
|
||||
|
||||
const popoverGridColumns: ScrollGridColumns = {
|
||||
columns: 1,
|
||||
const dialogGridColumns: ScrollGridColumns = {
|
||||
columns: 2,
|
||||
breakpoints: {
|
||||
'screen and (min-width: 2320px)': 8,
|
||||
'gt-lg': 6,
|
||||
'screen and (min-width: 1600px)': 5,
|
||||
'gt-md': 4,
|
||||
'gt-sm': 3,
|
||||
'gt-xs': 2
|
||||
'gt-xs': 3
|
||||
}
|
||||
};
|
||||
|
||||
@ -111,18 +107,25 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe
|
||||
@HostBinding('style.display')
|
||||
private display = 'block';
|
||||
|
||||
@HostBinding('style.width')
|
||||
private width = '100%';
|
||||
|
||||
@HostBinding('style.height')
|
||||
private height = '100%';
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
pageMode = true;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
popoverMode = false;
|
||||
dialogMode = false;
|
||||
|
||||
@Input()
|
||||
mode: 'list' | 'grid' = 'list';
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
selectionMode = false;
|
||||
|
||||
@Output()
|
||||
@ -194,7 +197,7 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.gridColumns = this.popoverMode ? popoverGridColumns : pageGridColumns;
|
||||
this.gridColumns = this.dialogMode ? dialogGridColumns : pageGridColumns;
|
||||
this.displayedColumns = this.computeDisplayedColumns();
|
||||
let sortOrder: SortOrder = this.defaultSortOrder;
|
||||
this.pageSizeOptions = [this.defaultPageSize, this.defaultPageSize * 2, this.defaultPageSize * 3];
|
||||
|
||||
@ -215,6 +215,7 @@ import { ImagesInUseDialogComponent } from '@shared/components/image/images-in-u
|
||||
import { GalleryImageInputComponent } from '@shared/components/image/gallery-image-input.component';
|
||||
import { MultipleGalleryImageInputComponent } from '@shared/components/image/multiple-gallery-image-input.component';
|
||||
import { EmbedImageDialogComponent } from '@shared/components/image/embed-image-dialog.component';
|
||||
import { ImageGalleryDialogComponent } from '@shared/components/image/image-gallery-dialog.component';
|
||||
|
||||
export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) {
|
||||
return markedOptionsService;
|
||||
@ -410,7 +411,8 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
ImagesInUseDialogComponent,
|
||||
GalleryImageInputComponent,
|
||||
MultipleGalleryImageInputComponent,
|
||||
EmbedImageDialogComponent
|
||||
EmbedImageDialogComponent,
|
||||
ImageGalleryDialogComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@ -660,7 +662,8 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
ImagesInUseDialogComponent,
|
||||
GalleryImageInputComponent,
|
||||
MultipleGalleryImageInputComponent,
|
||||
EmbedImageDialogComponent
|
||||
EmbedImageDialogComponent,
|
||||
ImageGalleryDialogComponent
|
||||
]
|
||||
})
|
||||
export class SharedModule { }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user