nm-gallery
src/app/shared/widgets/gallery/gallery.component.ts
changeDetection | ChangeDetectionStrategy.OnPush |
selector | nm-gallery |
styleUrls | gallery.component.scss |
templateUrl | ./gallery.component.html |
Widget inputs |
Widget outputs |
Properties |
|
Methods |
|
Inputs |
Outputs |
constructor(_widgetframeService: WidgetframeService, _progressbarService: ProgressbarService, gallery: Gallery, lightbox: Lightbox, ngZone: NgZone, cdr: ChangeDetectorRef)
|
|||||||||||||||||||||
Parameters :
|
assets
|
Sets the assets. |
height
|
Sets the height of the gallery (in pixels).
Type:
Default value: |
href
|
Sets the href for backend REST service returns JSON reponse containing assets. |
showSpinner
|
Shows\Hides the spinner.
Default value: |
thumbnailsEnabled
|
Enable\Disable thumbnails.
Default value: |
width
|
Sets the width of the gallery (in pixels).
Type: |
closed
|
Emits when the gallery popup is closed $event type: Subject<any>
|
opened
|
Emits when the gallery popup is opened $event type: Subject<any>
|
Static fallBackImage |
fallBackImage()
|
Returns :
string
|
indexChange | ||||||
indexChange(index: any)
|
||||||
Parameters :
Returns :
void
|
mapToTapEvent | ||||||
mapToTapEvent(event: MouseEvent)
|
||||||
Parameters :
Returns :
{ center: { x: any; y: any; }; }
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
openLightbox | ||||||
openLightbox(index: number)
|
||||||
Parameters :
Returns :
void
|
Private processImages | ||||||
processImages(images: any[])
|
||||||
Parameters :
Returns :
void
|
Static toGalleryItems | ||||||
toGalleryItems(images: any[])
|
||||||
Parameters :
Returns :
GalleryItem[]
|
Static toLightboxItem | ||||
toLightboxItem(item: )
|
||||
Parameters :
Returns :
any
|
Static toLightboxItems | ||||||
toLightboxItems(images: any[])
|
||||||
Parameters :
Returns :
any
|
Private assetObservables |
assetObservables:
|
Default value : new ReplaySubject<Observable<any[]>>(1)
|
currentIndex |
currentIndex:
|
Type : number
|
Private hrefObservables |
hrefObservables:
|
Default value : new ReplaySubject<Observable<string>>(1)
|
id |
id:
|
Type : string
|
items |
items:
|
Type : Subject<GalleryItem[]>
|
Default value : new ReplaySubject(1)
|
itemTemplate |
itemTemplate:
|
Type : TemplateRef<any>
|
Decorators : ViewChild
|
lightboxId |
lightboxId:
|
Type : string
|
lightboxRef |
lightboxRef:
|
Type : GalleryRef
|
loading |
loading:
|
Default value : false
|
Private unsubscribe |
unsubscribe:
|
Default value : NgUnsubscribe.create()
|
assets | ||||
setassets(assets: )
|
||||
Sets the assets.
Parameters :
Returns :
void
|
href | ||||
sethref(href: )
|
||||
Sets the href for backend REST service returns JSON reponse containing assets.
Parameters :
Returns :
void
|
import {
debounceTime,
distinctUntilChanged,
filter,
map,
switchAll,
switchMap,
takeUntil,
tap,
} from "rxjs/operators";
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
NgZone,
OnDestroy,
OnInit,
Output,
TemplateRef,
ViewChild,
} from "@angular/core";
import { WidgetframeService } from "../widgetframe/widgetframe.service";
import { ProgressbarService } from "../../components/progressbar/progressbar.service";
import { Observable, of, ReplaySubject, Subject } from "rxjs";
import { NgUnsubscribe } from "../../ng-unsubscribe";
import {
Gallery,
GalleryItem,
GalleryItemType,
GalleryRef,
IframeItem,
ImageItem,
VideoItem,
YoutubeItem,
} from "ng-gallery";
import { Lightbox } from "ng-gallery/lightbox";
import { uuid } from "../configuration";
declare var contextPath: string;
@Component({
selector: "nm-gallery",
templateUrl: "./gallery.component.html",
styleUrls: ["./gallery.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class GalleryComponent implements OnInit, OnDestroy {
private unsubscribe = NgUnsubscribe.create();
@ViewChild("itemTemplate", { static: true }) itemTemplate: TemplateRef<any>;
/**
* Sets the width of the gallery (in pixels).
*/
@Input() width: string;
/**
* Sets the height of the gallery (in pixels).
*/
@Input() height: string = "200px";
/**
* Enable\Disable thumbnails.
*/
@Input() thumbnailsEnabled = true;
/**
* Shows\Hides the spinner.
*/
@Input() showSpinner = false;
private assetObservables = new ReplaySubject<Observable<any[]>>(1);
/**
* Sets the assets.
*/
@Input() set assets(assets: Observable<any[]> | any[]) {
if (assets == null) {
return;
}
if (Array.isArray(assets)) {
this.assetObservables.next(of(assets));
} else {
this.assetObservables.next(assets);
}
}
private hrefObservables = new ReplaySubject<Observable<string>>(1);
/**
* Sets the href for backend REST service returns JSON reponse containing assets.
*/
@Input() set href(href: Subject<string> | string) {
if (href == null) {
return;
}
if (typeof href === "string") {
this.hrefObservables.next(of(href));
} else {
this.hrefObservables.next(href);
}
}
/**
* Emits when the gallery popup is opened
*/
@Output() opened: Subject<any>;
/**
* Emits when the gallery popup is closed
*/
@Output() closed: Subject<any>;
id: string;
lightboxId: string;
lightboxRef: GalleryRef;
currentIndex: number;
items: Subject<GalleryItem[]> = new ReplaySubject(1);
loading = false;
constructor(
private _widgetframeService: WidgetframeService,
private _progressbarService: ProgressbarService,
private gallery: Gallery,
private lightbox: Lightbox,
private ngZone: NgZone,
private cdr: ChangeDetectorRef
) {
this.opened = lightbox.opened;
this.closed = lightbox.closed;
this.id = uuid();
this.lightboxId = `lb-${this.id};`;
}
ngOnInit() {
this.lightboxRef = this.gallery.ref(this.lightboxId);
this.lightboxRef.setConfig({
itemTemplate: this.itemTemplate,
thumb: this.thumbnailsEnabled,
});
// update the lightbox in lockstep, but make sure, to rewrite images to imageViewer
// to allow zooming etc
this.items
.pipe(
takeUntil(this.unsubscribe),
map((items) =>
items.map((item) => {
return GalleryComponent.toLightboxItem(item);
})
)
)
.subscribe((items) => this.lightboxRef.load(items));
this.assetObservables
.asObservable()
.pipe(switchAll(), takeUntil(this.unsubscribe))
.subscribe((assets) => {
this.processImages(assets);
});
this.hrefObservables
.pipe(
switchAll(),
filter((data) => !!data),
tap(() => {
this.loading = true;
this.cdr.markForCheck();
}),
switchMap((href) => this._widgetframeService.getData(href)),
takeUntil(this.unsubscribe),
debounceTime(100),
distinctUntilChanged()
)
.subscribe(
(data) => {
this._progressbarService.addRequest();
const images = [];
if (data._embedded != null) {
if (data._embedded["asset-relations"] != undefined) {
for (var relation of data._embedded["asset-relations"]) {
if (relation["_embedded"]) {
for (var assets of relation["_embedded"]["assets"]) {
images.push(assets);
}
}
}
}
if (data._embedded["images"] != undefined) {
for (var image of data._embedded["images"]) {
images.push(image);
}
}
if (data._embedded["main-asset"] != undefined) {
images.push(data._embedded["main-asset"]);
}
this.processImages(images);
}
this.loading = false;
this._progressbarService.requestFinished();
this.cdr.markForCheck();
},
(error) => {
this.loading = false;
this._progressbarService.requestFinished();
this.cdr.markForCheck();
}
);
}
mapToTapEvent(event: MouseEvent) {
return { center: { x: event.clientX, y: event.clientY } };
}
indexChange(index: any) {
this.currentIndex = index.currIndex;
}
openLightbox(index: number) {
this.lightbox.open(index, this.lightboxId);
}
ngOnDestroy() {
this.unsubscribe.destroy();
}
private processImages(images: any[]) {
const items = GalleryComponent.toGalleryItems(images);
this.items.next(items);
}
public static toLightboxItems(images: any[]) {
const mapped = GalleryComponent.toGalleryItems(images);
return mapped.map((item) => GalleryComponent.toLightboxItem(item));
}
public static toLightboxItem(item) {
if (item.type === GalleryItemType.Image) {
return { type: "imageViewer", data: item.data };
}
return item;
}
public static toGalleryItems(images: any[]): GalleryItem[] {
if (images == null) {
return [];
}
const items: GalleryItem[] = [];
for (const image of images) {
if (image._links == undefined) {
continue;
}
if (image.type === "image") {
let small: string;
let big: string;
if (image._links.thumbnail != undefined) {
small = image._links.thumbnail.href;
} else {
small = image._links.default.href;
}
if (image._links.full != undefined) {
big = image._links.full.href;
} else {
big = image._links.default.href;
}
items.push(new ImageItem({ src: big, thumb: small }));
} else if (image.type === "youtube") {
// autoplay == true required, otherwise the gallery resets
// the iframe's src to "null", which then loads the base-href (i.e., portal)
items.push(new YoutubeItem({ src: image.youtubeId, autoplay: true }));
} else if (image.type === "link") {
const thumb = contextPath + "/assets/placeholder_281x202.jpg";
items.push(new IframeItem({ src: image._links.default.href, thumb }));
} else if (image.type === "document") {
const thumb =
image.extension === "pdf"
? contextPath + "/assets/placeholder_pdf_281x202.jpg"
: contextPath + "/assets/placeholder_281x202.jpg";
items.push(new IframeItem({ src: image._links.default.href, thumb }));
} else if (image.type === "video") {
items.push(
new VideoItem({
src: image._links.default.href,
thumb: contextPath + "/assets/placeholder_movie_281x202.jpg",
})
);
}
}
if (images.length == 0) {
const fallback = GalleryComponent.fallBackImage();
items.push(new ImageItem({ src: fallback, thumb: fallback }));
}
return items;
}
static fallBackImage() {
return contextPath + "/assets/placeholder_281x202.jpg";
}
}
<gallery
#gallery
[id]="id"
[items]="items | async"
[thumb]="thumbnailsEnabled"
[thumbWidth]="90"
[thumbHeight]="50"
[ngStyle]="{ width: width, height: height }"
[itemTemplate]="itemTemplate"
[thumbTemplate]="thumbTemplate"
(indexChange)="indexChange($event)"
(itemClick)="openLightbox($event)"
*ngIf="!loading; else spinner"
>
<button
mat-icon-button
class="nm-gallery-fullScreen"
(click)="openLightbox(currentIndex)"
>
<mat-icon svgIcon="fullscreen"></mat-icon>
</button>
</gallery>
<ng-template
#itemTemplate
let-index="index"
let-type="type"
let-data="data"
let-currIndex="currIndex"
>
<ng-container *ngIf="type === 'imageViewer' && index === currIndex">
<ngx-imageviewer
[src]="data.src"
[width]="800"
[height]="600"
#imageViewer
(click)="imageViewer.onTap(mapToTapEvent($event))"
>
</ngx-imageviewer>
</ng-container>
</ng-template>
<ng-template #thumbTemplate let-type="type">
<mat-icon
*ngIf="type === 'youtube'"
class="nm-gallery-thumbnailIcon"
svgIcon="youtube"
></mat-icon>
<mat-icon
*ngIf="type === 'video'"
class="nm-gallery-thumbnailIcon"
svgIcon="play"
></mat-icon>
</ng-template>
<ng-template #spinner>
<div class="spinner-container" [ngStyle]="{ width: width, height: height }">
<mat-spinner [diameter]="40"></mat-spinner>
</div>
</ng-template>