@lenne.tech/ng-base 0.3.3 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/lenne.tech-ng-base-src-lib-base.umd.js +711 -736
- package/bundles/lenne.tech-ng-base-src-lib-base.umd.js.map +1 -1
- package/bundles/lenne.tech-ng-base.umd.js +711 -736
- package/bundles/lenne.tech-ng-base.umd.js.map +1 -1
- package/esm2015/lib/base/classes/helper.class.js +19 -1
- package/esm2015/lib/base/directives/match-height.directive.js +19 -14
- package/esm2015/lib/base/services/graphql.service.js +2 -2
- package/esm2015/lib/base/services/image.service.js +24 -38
- package/esm2015/lib/base/services/scroll.service.js +9 -30
- package/esm2015/src/lib/base/classes/helper.class.js +19 -1
- package/esm2015/src/lib/base/directives/match-height.directive.js +19 -14
- package/esm2015/src/lib/base/services/graphql.service.js +2 -2
- package/esm2015/src/lib/base/services/image.service.js +24 -38
- package/esm2015/src/lib/base/services/scroll.service.js +9 -30
- package/fesm2015/lenne.tech-ng-base-src-lib-base.js +542 -555
- package/fesm2015/lenne.tech-ng-base-src-lib-base.js.map +1 -1
- package/fesm2015/lenne.tech-ng-base.js +542 -555
- package/fesm2015/lenne.tech-ng-base.js.map +1 -1
- package/lib/base/classes/helper.class.d.ts +7 -0
- package/lib/base/directives/match-height.directive.d.ts +7 -7
- package/lib/base/services/image.service.d.ts +1 -2
- package/lib/base/services/scroll.service.d.ts +1 -2
- package/package.json +1 -1
- package/src/lib/base/classes/helper.class.d.ts +7 -0
- package/src/lib/base/directives/match-height.directive.d.ts +7 -7
- package/src/lib/base/lenne.tech-ng-base-src-lib-base.metadata.json +1 -1
- package/src/lib/base/services/image.service.d.ts +1 -2
- package/src/lib/base/services/scroll.service.d.ts +1 -2
|
@@ -2,13 +2,14 @@ import * as i1 from 'apollo-angular';
|
|
|
2
2
|
import { APOLLO_OPTIONS, gql, Apollo } from 'apollo-angular';
|
|
3
3
|
import { HttpLink } from 'apollo-angular/http';
|
|
4
4
|
import * as i0 from '@angular/core';
|
|
5
|
-
import { InjectionToken, Injectable, Inject, Directive, ElementRef, Input, Output, HostBinding,
|
|
5
|
+
import { InjectionToken, Injectable, Inject, Directive, ElementRef, Input, Output, HostBinding, PLATFORM_ID, HostListener, Pipe, NgModule } from '@angular/core';
|
|
6
6
|
import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
|
|
7
7
|
import { ApolloLink, split, concat } from '@apollo/client/core';
|
|
8
8
|
import { InMemoryCache } from '@apollo/client/cache';
|
|
9
9
|
import { WebSocketLink } from '@apollo/client/link/ws';
|
|
10
10
|
import { getMainDefinition } from '@apollo/client/utilities';
|
|
11
11
|
import { __awaiter } from 'tslib';
|
|
12
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
12
13
|
import * as i1$2 from '@angular/platform-browser';
|
|
13
14
|
import { DomSanitizer, Title, Meta } from '@angular/platform-browser';
|
|
14
15
|
import * as i1$1 from '@angular/router';
|
|
@@ -419,362 +420,6 @@ LazyLoadDirective.propDecorators = {
|
|
|
419
420
|
src: [{ type: Input }]
|
|
420
421
|
};
|
|
421
422
|
|
|
422
|
-
/**
|
|
423
|
-
* Image service
|
|
424
|
-
*/
|
|
425
|
-
class ImageService {
|
|
426
|
-
/**
|
|
427
|
-
* Preaload images (for lazy handling)
|
|
428
|
-
*
|
|
429
|
-
* @param options
|
|
430
|
-
* @protected
|
|
431
|
-
*/
|
|
432
|
-
preLoadImages(options) {
|
|
433
|
-
// Init configuration
|
|
434
|
-
const config = Object.assign({ doneFunnction: undefined, elements: document, regExp: undefined, timeout: undefined }, options);
|
|
435
|
-
return new Promise((resolve) => {
|
|
436
|
-
var _a;
|
|
437
|
-
// Init variables
|
|
438
|
-
let resolved = false;
|
|
439
|
-
let timeoutId;
|
|
440
|
-
// HTMLCollection to array
|
|
441
|
-
if (config.elements instanceof HTMLCollection) {
|
|
442
|
-
config.elements = Array.from(config.elements);
|
|
443
|
-
}
|
|
444
|
-
// Single element to array
|
|
445
|
-
if (!Array.isArray(config.elements)) {
|
|
446
|
-
config.elements = [config.elements];
|
|
447
|
-
}
|
|
448
|
-
// Init loading
|
|
449
|
-
const promises = [];
|
|
450
|
-
// Get all images
|
|
451
|
-
let images = [];
|
|
452
|
-
config.elements.forEach((element) => {
|
|
453
|
-
images = images.concat(Array.from(element.getElementsByTagName('img')));
|
|
454
|
-
});
|
|
455
|
-
// Prepare images
|
|
456
|
-
for (const image of images) {
|
|
457
|
-
const src = image.getAttribute('src');
|
|
458
|
-
// Check if changes are necessary and possible
|
|
459
|
-
if ((image.complete && image.naturalHeight !== 0) || // already laoded
|
|
460
|
-
image.getAttribute('loading') !== 'lazy' || // loading attribute !== lazy
|
|
461
|
-
!src || // Image has no src
|
|
462
|
-
((_a = config.regExp) === null || _a === void 0 ? void 0 : _a.test(src)) // Test if src matches regular expression
|
|
463
|
-
) {
|
|
464
|
-
continue;
|
|
465
|
-
}
|
|
466
|
-
// Replace lazy loading image with immediately loading image
|
|
467
|
-
const newImage = document.createElement('img');
|
|
468
|
-
Array.from(image.attributes).forEach((attr) => {
|
|
469
|
-
if (attr.name !== 'loading' && attr.name !== 'src') {
|
|
470
|
-
newImage.setAttribute(attr.name, attr.value);
|
|
471
|
-
}
|
|
472
|
-
});
|
|
473
|
-
image.replaceWith(newImage);
|
|
474
|
-
// Wait for laoding
|
|
475
|
-
promises.push(this.loadImage(newImage, src));
|
|
476
|
-
}
|
|
477
|
-
if (config.timeout) {
|
|
478
|
-
timeoutId = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
479
|
-
resolved = true;
|
|
480
|
-
if (config.doneFunnction) {
|
|
481
|
-
yield config.doneFunction();
|
|
482
|
-
}
|
|
483
|
-
resolve(undefined);
|
|
484
|
-
}));
|
|
485
|
-
}
|
|
486
|
-
// Wait until all images loaded
|
|
487
|
-
Promise.all(promises)
|
|
488
|
-
.catch((e) => console.error('Error during image loading', e))
|
|
489
|
-
.finally(() => __awaiter(this, void 0, void 0, function* () {
|
|
490
|
-
// Check if already resolved
|
|
491
|
-
if (resolved) {
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
// Stop timeout
|
|
495
|
-
if (timeoutId) {
|
|
496
|
-
clearTimeout(timeoutId);
|
|
497
|
-
}
|
|
498
|
-
// Return result
|
|
499
|
-
let result;
|
|
500
|
-
if (config.doneFunnction) {
|
|
501
|
-
result = yield config.doneFunction();
|
|
502
|
-
}
|
|
503
|
-
resolve(result);
|
|
504
|
-
}));
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* Load image for image element
|
|
509
|
-
*
|
|
510
|
-
* @param imageElement
|
|
511
|
-
* @param src
|
|
512
|
-
* @protected
|
|
513
|
-
*/
|
|
514
|
-
loadImage(imageElement, src) {
|
|
515
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
516
|
-
src = src || imageElement.src;
|
|
517
|
-
return new Promise((resolve, reject) => {
|
|
518
|
-
imageElement.onload = () => resolve(imageElement);
|
|
519
|
-
imageElement.onerror = reject;
|
|
520
|
-
imageElement.src = src;
|
|
521
|
-
});
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
ImageService.ɵprov = i0.ɵɵdefineInjectable({ factory: function ImageService_Factory() { return new ImageService(); }, token: ImageService, providedIn: "root" });
|
|
526
|
-
ImageService.decorators = [
|
|
527
|
-
{ type: Injectable, args: [{
|
|
528
|
-
providedIn: 'root',
|
|
529
|
-
},] }
|
|
530
|
-
];
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* Set same height (maximum) to different elements
|
|
534
|
-
*/
|
|
535
|
-
class MatchHeightDirective {
|
|
536
|
-
constructor(el, imageService, zone) {
|
|
537
|
-
this.el = el;
|
|
538
|
-
this.imageService = imageService;
|
|
539
|
-
this.zone = zone;
|
|
540
|
-
this.loadLazyImages = true;
|
|
541
|
-
}
|
|
542
|
-
onResize() {
|
|
543
|
-
this.matchHeight(this.el.nativeElement, this.ltMatchHeight);
|
|
544
|
-
}
|
|
545
|
-
ngAfterViewChecked() {
|
|
546
|
-
this.matchHeight(this.el.nativeElement, this.ltMatchHeight);
|
|
547
|
-
}
|
|
548
|
-
matchHeight(parent, target) {
|
|
549
|
-
// Timeout is set to force Angular to wait for all actions and only continue once the process has run through.
|
|
550
|
-
// Otherwise, an infinite loop will occur.
|
|
551
|
-
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
552
|
-
if (!parent) {
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
let classNames;
|
|
556
|
-
if (!Array.isArray(target)) {
|
|
557
|
-
classNames = [target];
|
|
558
|
-
}
|
|
559
|
-
else {
|
|
560
|
-
classNames = target;
|
|
561
|
-
}
|
|
562
|
-
for (const className of classNames) {
|
|
563
|
-
// find all child structureElements with the selected class name
|
|
564
|
-
const children = parent.getElementsByClassName(className);
|
|
565
|
-
if (!children || children.length < 2) {
|
|
566
|
-
continue;
|
|
567
|
-
}
|
|
568
|
-
// Load images of children
|
|
569
|
-
if (this.loadLazyImages) {
|
|
570
|
-
yield this.imageService.preLoadImages({ elements: children });
|
|
571
|
-
}
|
|
572
|
-
// reset all children height
|
|
573
|
-
Array.from(children).forEach((element) => {
|
|
574
|
-
element.style.height = 'initial';
|
|
575
|
-
});
|
|
576
|
-
// get all the child structureElements heights
|
|
577
|
-
const itemHeights = Array.from(children).map((x) => x.getBoundingClientRect().height);
|
|
578
|
-
// find out the tallest one
|
|
579
|
-
const maxHeight = itemHeights.reduce((prev, curr) => (curr > prev ? curr : prev), 0);
|
|
580
|
-
// update the child structureElements height to the tallest one
|
|
581
|
-
Array.from(children).forEach((element) => (element.style.height = `${maxHeight}px`));
|
|
582
|
-
}
|
|
583
|
-
}), 1);
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
MatchHeightDirective.decorators = [
|
|
587
|
-
{ type: Directive, args: [{
|
|
588
|
-
selector: '[ltMatchHeight]',
|
|
589
|
-
},] }
|
|
590
|
-
];
|
|
591
|
-
MatchHeightDirective.ctorParameters = () => [
|
|
592
|
-
{ type: ElementRef },
|
|
593
|
-
{ type: ImageService },
|
|
594
|
-
{ type: NgZone }
|
|
595
|
-
];
|
|
596
|
-
MatchHeightDirective.propDecorators = {
|
|
597
|
-
ltMatchHeight: [{ type: Input }],
|
|
598
|
-
loadLazyImages: [{ type: Input }],
|
|
599
|
-
onResize: [{ type: HostListener, args: ['window:resize',] }]
|
|
600
|
-
};
|
|
601
|
-
|
|
602
|
-
/**
|
|
603
|
-
* Reszise detection
|
|
604
|
-
* (inpsired by: https://stackblitz.com/edit/angular-resizable)
|
|
605
|
-
*/
|
|
606
|
-
class ResizableDirective {
|
|
607
|
-
constructor(el) {
|
|
608
|
-
this.el = el;
|
|
609
|
-
this.resizableGrabWidth = 8;
|
|
610
|
-
this.resizableMinWidth = 10;
|
|
611
|
-
this.dragging = false;
|
|
612
|
-
}
|
|
613
|
-
ngOnInit() {
|
|
614
|
-
this.addListenerToDocument();
|
|
615
|
-
this.addListenerToElement();
|
|
616
|
-
}
|
|
617
|
-
mouseMoveG(evt) {
|
|
618
|
-
if (!this.dragging) {
|
|
619
|
-
return;
|
|
620
|
-
}
|
|
621
|
-
this.newWidth(evt.clientX - this.el.nativeElement.offsetLeft);
|
|
622
|
-
evt.stopPropagation();
|
|
623
|
-
}
|
|
624
|
-
newWidth(wid) {
|
|
625
|
-
const result = Math.max(this.resizableMinWidth, wid);
|
|
626
|
-
this.el.nativeElement.style.width = result + 'px';
|
|
627
|
-
}
|
|
628
|
-
mouseDown(evt) {
|
|
629
|
-
if (this.inDragRegion(evt)) {
|
|
630
|
-
this.dragging = true;
|
|
631
|
-
this.preventGlobalMouseEvents();
|
|
632
|
-
evt.stopPropagation();
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
restoreGlobalMouseEvents() {
|
|
636
|
-
document.body.style['pointer-events'] = 'auto';
|
|
637
|
-
}
|
|
638
|
-
mouseUpG(evt) {
|
|
639
|
-
if (!this.dragging) {
|
|
640
|
-
return;
|
|
641
|
-
}
|
|
642
|
-
this.restoreGlobalMouseEvents();
|
|
643
|
-
this.dragging = false;
|
|
644
|
-
evt.stopPropagation();
|
|
645
|
-
}
|
|
646
|
-
mouseMove(evt) {
|
|
647
|
-
if (this.inDragRegion(evt) || this.dragging) {
|
|
648
|
-
this.el.nativeElement.style.cursor = 'col-resize';
|
|
649
|
-
}
|
|
650
|
-
else {
|
|
651
|
-
this.el.nativeElement.style.cursor = 'default';
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
preventGlobalMouseEvents() {
|
|
655
|
-
document.body.style['pointer-events'] = 'none';
|
|
656
|
-
}
|
|
657
|
-
inDragRegion(evt) {
|
|
658
|
-
return this.el.nativeElement.clientWidth - evt.clientX + this.el.nativeElement.offsetLeft < this.resizableGrabWidth;
|
|
659
|
-
}
|
|
660
|
-
addListenerToDocument() {
|
|
661
|
-
document.addEventListener('mousemove', (e) => {
|
|
662
|
-
this.mouseMoveG(e);
|
|
663
|
-
}, true);
|
|
664
|
-
document.addEventListener('mouseup', (e) => {
|
|
665
|
-
this.mouseUpG(e);
|
|
666
|
-
}, true);
|
|
667
|
-
}
|
|
668
|
-
addListenerToElement() {
|
|
669
|
-
this.el.nativeElement.addEventListener('mousedown', (e) => {
|
|
670
|
-
this.mouseDown(e);
|
|
671
|
-
}, true);
|
|
672
|
-
this.el.nativeElement.addEventListener('mousemove', (e) => {
|
|
673
|
-
this.mouseMove(e);
|
|
674
|
-
}, true);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
ResizableDirective.decorators = [
|
|
678
|
-
{ type: Directive, args: [{
|
|
679
|
-
selector: '[ltResizable]',
|
|
680
|
-
},] }
|
|
681
|
-
];
|
|
682
|
-
ResizableDirective.ctorParameters = () => [
|
|
683
|
-
{ type: ElementRef }
|
|
684
|
-
];
|
|
685
|
-
ResizableDirective.propDecorators = {
|
|
686
|
-
resizableGrabWidth: [{ type: Input }],
|
|
687
|
-
resizableMinWidth: [{ type: Input }]
|
|
688
|
-
};
|
|
689
|
-
|
|
690
|
-
/**
|
|
691
|
-
* Truncate string with ellipses
|
|
692
|
-
*/
|
|
693
|
-
class EllipsesPipe {
|
|
694
|
-
transform(value, limit) {
|
|
695
|
-
if (!value) {
|
|
696
|
-
return null;
|
|
697
|
-
}
|
|
698
|
-
return value.length > limit ? value.substring(0, limit) + '...' : value;
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
EllipsesPipe.decorators = [
|
|
702
|
-
{ type: Pipe, args: [{
|
|
703
|
-
name: 'ltEllipses',
|
|
704
|
-
},] }
|
|
705
|
-
];
|
|
706
|
-
|
|
707
|
-
/**
|
|
708
|
-
* Declarate html as safe
|
|
709
|
-
*/
|
|
710
|
-
class SafeHtmlPipe {
|
|
711
|
-
constructor(sanitized) {
|
|
712
|
-
this.sanitized = sanitized;
|
|
713
|
-
}
|
|
714
|
-
transform(value) {
|
|
715
|
-
return this.sanitized.bypassSecurityTrustHtml(value);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
SafeHtmlPipe.decorators = [
|
|
719
|
-
{ type: Pipe, args: [{ name: 'ltSafeHtml' },] }
|
|
720
|
-
];
|
|
721
|
-
SafeHtmlPipe.ctorParameters = () => [
|
|
722
|
-
{ type: DomSanitizer }
|
|
723
|
-
];
|
|
724
|
-
|
|
725
|
-
// Imported and exported elements
|
|
726
|
-
const elements = [
|
|
727
|
-
// Directives
|
|
728
|
-
ContextMenuDirective,
|
|
729
|
-
LazyLoadDirective,
|
|
730
|
-
MatchHeightDirective,
|
|
731
|
-
ResizableDirective,
|
|
732
|
-
// Pipes
|
|
733
|
-
EllipsesPipe,
|
|
734
|
-
SafeHtmlPipe,
|
|
735
|
-
];
|
|
736
|
-
/**
|
|
737
|
-
* Base module
|
|
738
|
-
*/
|
|
739
|
-
class BaseModule {
|
|
740
|
-
/**
|
|
741
|
-
* Set configuration of base module in root module of the app
|
|
742
|
-
*/
|
|
743
|
-
static forRoot(baseModuleConfig = {}) {
|
|
744
|
-
// Default config
|
|
745
|
-
const config = Object.assign({ apiUrl: 'localhost:3000', authGuardRedirectUrl: '/auth', logging: false, version: null, prefix: null, scrollDetectionOffset: 200, scrollOffset: 100, storageType: 'local' }, baseModuleConfig);
|
|
746
|
-
// Prepare providers
|
|
747
|
-
const providers = [
|
|
748
|
-
{
|
|
749
|
-
provide: BASE_MODULE_CONFIG,
|
|
750
|
-
useValue: baseModuleConfig,
|
|
751
|
-
},
|
|
752
|
-
];
|
|
753
|
-
// Add apollo features if API URL is set
|
|
754
|
-
if (baseModuleConfig.apiUrl) {
|
|
755
|
-
providers.push({
|
|
756
|
-
provide: APOLLO_OPTIONS,
|
|
757
|
-
useFactory: apolloOptionsFactory,
|
|
758
|
-
deps: [BASE_MODULE_CONFIG, HttpLink, AuthService],
|
|
759
|
-
});
|
|
760
|
-
}
|
|
761
|
-
else if (config.logging) {
|
|
762
|
-
console.log('apiUrl is missing, ApolloLink is not initialized');
|
|
763
|
-
}
|
|
764
|
-
// Return root module
|
|
765
|
-
return {
|
|
766
|
-
ngModule: BaseModule,
|
|
767
|
-
providers,
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
BaseModule.decorators = [
|
|
772
|
-
{ type: NgModule, args: [{
|
|
773
|
-
declarations: elements,
|
|
774
|
-
exports: elements,
|
|
775
|
-
},] }
|
|
776
|
-
];
|
|
777
|
-
|
|
778
423
|
/**
|
|
779
424
|
* Helper class
|
|
780
425
|
*/
|
|
@@ -838,214 +483,577 @@ class Helper {
|
|
|
838
483
|
if (!source || typeof source !== 'object' || Array.isArray(source)) {
|
|
839
484
|
return target;
|
|
840
485
|
}
|
|
841
|
-
// Update properties
|
|
842
|
-
for (const key of Object.keys(target)) {
|
|
843
|
-
if (source[key] !== undefined && (config.funcAllowed || typeof (source[key] !== 'function'))) {
|
|
844
|
-
if (typeof source[key] === 'string' && config.dateStringToDate) {
|
|
845
|
-
if (Array.isArray(config.dateStringToDate)) {
|
|
846
|
-
if (config.dateStringToDate.includes(key)) {
|
|
847
|
-
target[key] = Helper.parseDate(source[key]);
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
else {
|
|
851
|
-
target[key] = Helper.parseDate(source[key]);
|
|
852
|
-
}
|
|
486
|
+
// Update properties
|
|
487
|
+
for (const key of Object.keys(target)) {
|
|
488
|
+
if (source[key] !== undefined && (config.funcAllowed || typeof (source[key] !== 'function'))) {
|
|
489
|
+
if (typeof source[key] === 'string' && config.dateStringToDate) {
|
|
490
|
+
if (Array.isArray(config.dateStringToDate)) {
|
|
491
|
+
if (config.dateStringToDate.includes(key)) {
|
|
492
|
+
target[key] = Helper.parseDate(source[key]);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
target[key] = Helper.parseDate(source[key]);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
target[key] = source[key];
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
// Return target
|
|
505
|
+
return target;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Create Object or Objects of specified type with specified data
|
|
509
|
+
*/
|
|
510
|
+
static maps(data, targetClass) {
|
|
511
|
+
// Check data
|
|
512
|
+
if (!data || typeof data !== 'object') {
|
|
513
|
+
return undefined;
|
|
514
|
+
}
|
|
515
|
+
// Check array
|
|
516
|
+
if (!Array.isArray(data)) {
|
|
517
|
+
data = [data];
|
|
518
|
+
}
|
|
519
|
+
// Map
|
|
520
|
+
return data.map((item) => {
|
|
521
|
+
return targetClass.map(item);
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Get plain parameter
|
|
526
|
+
*/
|
|
527
|
+
static getPlainParameter(parameter) {
|
|
528
|
+
var _a, _b, _c;
|
|
529
|
+
if (!parameter) {
|
|
530
|
+
return parameter;
|
|
531
|
+
}
|
|
532
|
+
return (_c = (_b = (_a = parameter === null || parameter === void 0 ? void 0 : parameter.split('?')) === null || _a === void 0 ? void 0 : _a.shift()) === null || _b === void 0 ? void 0 : _b.split('#')) === null || _c === void 0 ? void 0 : _c.shift();
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Get ID of an url parameter
|
|
536
|
+
*/
|
|
537
|
+
static getParameterId(parameter) {
|
|
538
|
+
var _a;
|
|
539
|
+
if (!parameter) {
|
|
540
|
+
return parameter;
|
|
541
|
+
}
|
|
542
|
+
return (_a = Helper.getPlainParameter(parameter)) === null || _a === void 0 ? void 0 : _a.split('-').pop();
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Delay
|
|
546
|
+
*/
|
|
547
|
+
static delay(ms) {
|
|
548
|
+
const promise = new Promise((resolve) => setTimeout(resolve, ms));
|
|
549
|
+
return promise;
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Deep freeze
|
|
553
|
+
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze
|
|
554
|
+
*/
|
|
555
|
+
static deepFreeze(object, preparedObjects = []) {
|
|
556
|
+
// Prevent infinit regress
|
|
557
|
+
if (preparedObjects.includes(object)) {
|
|
558
|
+
return object;
|
|
559
|
+
}
|
|
560
|
+
preparedObjects.push(object);
|
|
561
|
+
// Retrieve the property names defined on object
|
|
562
|
+
const propNames = Object.getOwnPropertyNames(object);
|
|
563
|
+
// Freeze properties before freezing self
|
|
564
|
+
for (const name of propNames) {
|
|
565
|
+
const value = object[name];
|
|
566
|
+
if (value && typeof value === 'object') {
|
|
567
|
+
Helper.deepFreeze(value, preparedObjects);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return Object.freeze(object);
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Generates an unique identifier with 24 characters
|
|
574
|
+
*/
|
|
575
|
+
static getUID() {
|
|
576
|
+
let dt = new Date().getTime();
|
|
577
|
+
const uuid = 'xxxxxxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
578
|
+
// eslint-disable-next-line no-bitwise
|
|
579
|
+
const r = (dt + Math.random() * 16) % 16 | 0;
|
|
580
|
+
dt = Math.floor(dt / 16);
|
|
581
|
+
// eslint-disable-next-line no-bitwise
|
|
582
|
+
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
|
583
|
+
});
|
|
584
|
+
return uuid;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Parse date string to date object
|
|
588
|
+
*/
|
|
589
|
+
static parseDate(dateString) {
|
|
590
|
+
const reISO = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/;
|
|
591
|
+
const reMsAjax = /^\/Date\((d|-|.*)\)[\/|\\]$/;
|
|
592
|
+
if (typeof dateString === 'string') {
|
|
593
|
+
const isoExec = reISO.exec(dateString);
|
|
594
|
+
if (isoExec) {
|
|
595
|
+
return new Date(dateString);
|
|
596
|
+
}
|
|
597
|
+
const msAjaxExec = reMsAjax.exec(dateString);
|
|
598
|
+
if (msAjaxExec) {
|
|
599
|
+
const cleaned = msAjaxExec[1].split(/[-+,.]/);
|
|
600
|
+
return new Date(cleaned[0] ? +cleaned[0] : 0 - +cleaned[1]);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
return dateString;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Get browser name and version
|
|
607
|
+
*/
|
|
608
|
+
static getBrowser() {
|
|
609
|
+
const userAgent = navigator.userAgent;
|
|
610
|
+
let data = userAgent.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
|
|
611
|
+
let version;
|
|
612
|
+
if (/trident/i.test(data[1])) {
|
|
613
|
+
version = /\brv[ :]+(\d+)/g.exec(userAgent) || [];
|
|
614
|
+
return { name: 'IE', version: version[1] || '' };
|
|
615
|
+
}
|
|
616
|
+
if (data[1] === 'Chrome') {
|
|
617
|
+
version = userAgent.match(/\bOPR|Edge\/(\d+)/);
|
|
618
|
+
if (version != null) {
|
|
619
|
+
return { name: 'Opera', version: version[1] };
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
data = data[2] ? [data[1], data[2]] : [navigator.appName, navigator.appVersion, '-?'];
|
|
623
|
+
version = userAgent.match(/version\/(\d+)/i);
|
|
624
|
+
if (version !== null) {
|
|
625
|
+
data.splice(1, 1, version[1]);
|
|
626
|
+
}
|
|
627
|
+
return {
|
|
628
|
+
name: data[0],
|
|
629
|
+
version: data[1],
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Whether first parameter is a deep subset of second parameter
|
|
634
|
+
* Hint: functions will be ignored
|
|
635
|
+
*/
|
|
636
|
+
static isSubset(a, b) {
|
|
637
|
+
// Equal
|
|
638
|
+
if (a === b) {
|
|
639
|
+
return true;
|
|
640
|
+
}
|
|
641
|
+
// Different type
|
|
642
|
+
if (typeof a !== typeof b) {
|
|
643
|
+
return false;
|
|
644
|
+
}
|
|
645
|
+
// Process array
|
|
646
|
+
if (Array.isArray(a)) {
|
|
647
|
+
for (const [key, value] of Object.entries(a)) {
|
|
648
|
+
if (Helper.isSubset(value, b[key])) {
|
|
649
|
+
return false;
|
|
853
650
|
}
|
|
854
|
-
|
|
855
|
-
|
|
651
|
+
}
|
|
652
|
+
return true;
|
|
653
|
+
}
|
|
654
|
+
// Process object
|
|
655
|
+
if (typeof a === 'object') {
|
|
656
|
+
const plain = JSON.parse(JSON.stringify(a));
|
|
657
|
+
for (const [key, value] of Object.entries(plain)) {
|
|
658
|
+
if (Helper.isSubset(value, b[key])) {
|
|
659
|
+
return false;
|
|
856
660
|
}
|
|
857
661
|
}
|
|
662
|
+
return true;
|
|
858
663
|
}
|
|
859
|
-
//
|
|
860
|
-
return
|
|
664
|
+
// Else
|
|
665
|
+
return true;
|
|
861
666
|
}
|
|
862
667
|
/**
|
|
863
|
-
*
|
|
668
|
+
* Whether parameters are equal (have equal properties)
|
|
669
|
+
* Hint: functions will be ignored
|
|
864
670
|
*/
|
|
865
|
-
static
|
|
866
|
-
|
|
867
|
-
if (!data || typeof data !== 'object') {
|
|
868
|
-
return undefined;
|
|
869
|
-
}
|
|
870
|
-
// Check array
|
|
871
|
-
if (!Array.isArray(data)) {
|
|
872
|
-
data = [data];
|
|
873
|
-
}
|
|
874
|
-
// Map
|
|
875
|
-
return data.map((item) => {
|
|
876
|
-
return targetClass.map(item);
|
|
877
|
-
});
|
|
671
|
+
static isEqual(a, b) {
|
|
672
|
+
return Helper.isSubset(a, b) && Helper.isSubset(b, a);
|
|
878
673
|
}
|
|
879
674
|
/**
|
|
880
|
-
*
|
|
675
|
+
* First level difference of two objects
|
|
676
|
+
* Hint: functions will be ignored and when an array or an object is different the hole array or object will used as property value
|
|
677
|
+
*
|
|
678
|
+
* @returns Record<string, any> Object with properties from first object
|
|
881
679
|
*/
|
|
882
|
-
static
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
680
|
+
static getDiff(a, b, clone = true) {
|
|
681
|
+
const result = {};
|
|
682
|
+
let firstObject = a;
|
|
683
|
+
if (clone) {
|
|
684
|
+
firstObject = JSON.parse(JSON.stringify(a));
|
|
886
685
|
}
|
|
887
|
-
|
|
686
|
+
for (const [key, value] of Object.entries(firstObject)) {
|
|
687
|
+
if (!Helper.isSubset(value, b[key])) {
|
|
688
|
+
result[key] = value;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
return result;
|
|
888
692
|
}
|
|
889
693
|
/**
|
|
890
|
-
*
|
|
694
|
+
* Check if propertie is type of HTMLCollection or NodeList
|
|
695
|
+
* See https://stackoverflow.com/a/7238344
|
|
696
|
+
*
|
|
697
|
+
* @param nodes
|
|
891
698
|
*/
|
|
892
|
-
static
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
return
|
|
699
|
+
static isNodeList(nodes) {
|
|
700
|
+
try {
|
|
701
|
+
const stringRepr = Object.prototype.toString.call(nodes);
|
|
702
|
+
return (typeof nodes === 'object' &&
|
|
703
|
+
/^\[object (HTMLCollection|NodeList|Object)\]$/.test(stringRepr) &&
|
|
704
|
+
typeof nodes.length === 'number' &&
|
|
705
|
+
(nodes.length === 0 || (typeof nodes[0] === 'object' && nodes[0].nodeType > 0)));
|
|
706
|
+
}
|
|
707
|
+
catch (e) {
|
|
708
|
+
return false;
|
|
896
709
|
}
|
|
897
|
-
return (_a = Helper.getPlainParameter(parameter)) === null || _a === void 0 ? void 0 : _a.split('-').pop();
|
|
898
710
|
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Image service
|
|
715
|
+
*/
|
|
716
|
+
class ImageService {
|
|
899
717
|
/**
|
|
900
|
-
*
|
|
718
|
+
* Preaload images (for lazy handling)
|
|
719
|
+
*
|
|
720
|
+
* @param options
|
|
721
|
+
* @protected
|
|
901
722
|
*/
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
723
|
+
preLoadImages(options) {
|
|
724
|
+
// Init configuration
|
|
725
|
+
const config = Object.assign({ doneFunnction: undefined, elements: document, regExp: undefined }, options);
|
|
726
|
+
return new Promise((resolve) => {
|
|
727
|
+
var _a;
|
|
728
|
+
// Convert element(s) into array
|
|
729
|
+
if (!Array.isArray(config.elements)) {
|
|
730
|
+
// NodeList or HTMLCollection
|
|
731
|
+
if (Helper.isNodeList(config.elements)) {
|
|
732
|
+
config.elements = Array.from(config.elements);
|
|
733
|
+
}
|
|
734
|
+
// Single element
|
|
735
|
+
else {
|
|
736
|
+
config.elements = [config.elements];
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
// Init loading
|
|
740
|
+
const promises = [];
|
|
741
|
+
// Get all images
|
|
742
|
+
let images = [];
|
|
743
|
+
config.elements.forEach((element) => {
|
|
744
|
+
images = images.concat(Array.from(element.getElementsByTagName('img')));
|
|
745
|
+
});
|
|
746
|
+
// Prepare images
|
|
747
|
+
for (let image of images) {
|
|
748
|
+
const src = image.getAttribute('src');
|
|
749
|
+
// Check if changes are necessary and possible
|
|
750
|
+
if ((image.complete && image.naturalHeight !== 0) || // already laoded
|
|
751
|
+
!src || // Image has no src
|
|
752
|
+
((_a = config.regExp) === null || _a === void 0 ? void 0 : _a.test(src)) // Test if src matches regular expression
|
|
753
|
+
) {
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
// Replace lazy loading image with immediately loading image
|
|
757
|
+
if (image.getAttribute('loading') === 'lazy') {
|
|
758
|
+
const newImage = document.createElement('img');
|
|
759
|
+
Array.from(image.attributes).forEach((attr) => {
|
|
760
|
+
if (attr.name !== 'loading' && attr.name !== 'src') {
|
|
761
|
+
newImage.setAttribute(attr.name, attr.value);
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
image.replaceWith(newImage);
|
|
765
|
+
image = newImage;
|
|
766
|
+
}
|
|
767
|
+
// Wait for laoding
|
|
768
|
+
promises.push(this.loadImage(image, src));
|
|
769
|
+
}
|
|
770
|
+
// Wait until all images loaded
|
|
771
|
+
Promise.all(promises)
|
|
772
|
+
.catch((e) => console.error('Error during image loading', e))
|
|
773
|
+
.finally(() => __awaiter(this, void 0, void 0, function* () {
|
|
774
|
+
// Return result
|
|
775
|
+
let result;
|
|
776
|
+
if (config.doneFunnction) {
|
|
777
|
+
result = yield config.doneFunction();
|
|
778
|
+
}
|
|
779
|
+
resolve(result);
|
|
780
|
+
}));
|
|
781
|
+
});
|
|
905
782
|
}
|
|
906
783
|
/**
|
|
907
|
-
*
|
|
908
|
-
*
|
|
784
|
+
* Load image for image element
|
|
785
|
+
*
|
|
786
|
+
* @param imageElement
|
|
787
|
+
* @param src
|
|
788
|
+
* @protected
|
|
909
789
|
*/
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
return
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
790
|
+
loadImage(imageElement, src) {
|
|
791
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
792
|
+
src = src || imageElement.src;
|
|
793
|
+
return new Promise((resolve, reject) => {
|
|
794
|
+
imageElement.onload = () => resolve(imageElement);
|
|
795
|
+
imageElement.onerror = reject;
|
|
796
|
+
imageElement.src = src;
|
|
797
|
+
});
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
ImageService.ɵprov = i0.ɵɵdefineInjectable({ factory: function ImageService_Factory() { return new ImageService(); }, token: ImageService, providedIn: "root" });
|
|
802
|
+
ImageService.decorators = [
|
|
803
|
+
{ type: Injectable, args: [{
|
|
804
|
+
providedIn: 'root',
|
|
805
|
+
},] }
|
|
806
|
+
];
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* Set same height (maximum) to different elements
|
|
810
|
+
*/
|
|
811
|
+
class MatchHeightDirective {
|
|
812
|
+
constructor(el, imageService, platformId) {
|
|
813
|
+
this.el = el;
|
|
814
|
+
this.imageService = imageService;
|
|
815
|
+
// Replace lazy loading images with immediate loading images
|
|
816
|
+
this.loadImages = true;
|
|
817
|
+
this.isBrowser = isPlatformBrowser(platformId);
|
|
818
|
+
}
|
|
819
|
+
onResize() {
|
|
820
|
+
this.matchHeight(this.el.nativeElement, this.ltMatchHeight);
|
|
821
|
+
}
|
|
822
|
+
ngOnInit() {
|
|
823
|
+
this.matchHeight(this.el.nativeElement, this.ltMatchHeight);
|
|
824
|
+
}
|
|
825
|
+
matchHeight(parent, target) {
|
|
826
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
827
|
+
if (!parent) {
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
let classNames;
|
|
831
|
+
if (!Array.isArray(target)) {
|
|
832
|
+
classNames = [target];
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
classNames = target;
|
|
836
|
+
}
|
|
837
|
+
for (const className of classNames) {
|
|
838
|
+
// find all child structureElements with the selected class name
|
|
839
|
+
const children = parent.getElementsByClassName(className);
|
|
840
|
+
if (!children || children.length < 2) {
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
// Load images of children
|
|
844
|
+
if (this.loadImages) {
|
|
845
|
+
yield this.imageService.preLoadImages({ elements: children });
|
|
846
|
+
}
|
|
847
|
+
// reset all children height
|
|
848
|
+
Array.from(children).forEach((element) => {
|
|
849
|
+
element.style.height = 'initial';
|
|
850
|
+
});
|
|
851
|
+
// get all the child structureElements heights
|
|
852
|
+
const itemHeights = Array.from(children).map((element) => {
|
|
853
|
+
if (element.getBoundingClientRect) {
|
|
854
|
+
return element.getBoundingClientRect().height;
|
|
855
|
+
}
|
|
856
|
+
return 0;
|
|
857
|
+
});
|
|
858
|
+
// find out the tallest one
|
|
859
|
+
const maxHeight = itemHeights.reduce((prev, curr) => (curr > prev ? curr : prev), 0);
|
|
860
|
+
// update the child structureElements height to the tallest one
|
|
861
|
+
Array.from(children).forEach((element) => (element.style.height = `${maxHeight}px`));
|
|
923
862
|
}
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
MatchHeightDirective.decorators = [
|
|
867
|
+
{ type: Directive, args: [{
|
|
868
|
+
selector: '[ltMatchHeight]',
|
|
869
|
+
},] }
|
|
870
|
+
];
|
|
871
|
+
MatchHeightDirective.ctorParameters = () => [
|
|
872
|
+
{ type: ElementRef },
|
|
873
|
+
{ type: ImageService },
|
|
874
|
+
{ type: String, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
|
|
875
|
+
];
|
|
876
|
+
MatchHeightDirective.propDecorators = {
|
|
877
|
+
ltMatchHeight: [{ type: Input }],
|
|
878
|
+
loadImages: [{ type: Input }],
|
|
879
|
+
onResize: [{ type: HostListener, args: ['window:resize',] }]
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* Reszise detection
|
|
884
|
+
* (inpsired by: https://stackblitz.com/edit/angular-resizable)
|
|
885
|
+
*/
|
|
886
|
+
class ResizableDirective {
|
|
887
|
+
constructor(el) {
|
|
888
|
+
this.el = el;
|
|
889
|
+
this.resizableGrabWidth = 8;
|
|
890
|
+
this.resizableMinWidth = 10;
|
|
891
|
+
this.dragging = false;
|
|
892
|
+
}
|
|
893
|
+
ngOnInit() {
|
|
894
|
+
this.addListenerToDocument();
|
|
895
|
+
this.addListenerToElement();
|
|
896
|
+
}
|
|
897
|
+
mouseMoveG(evt) {
|
|
898
|
+
if (!this.dragging) {
|
|
899
|
+
return;
|
|
924
900
|
}
|
|
925
|
-
|
|
901
|
+
this.newWidth(evt.clientX - this.el.nativeElement.offsetLeft);
|
|
902
|
+
evt.stopPropagation();
|
|
926
903
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
static getUID() {
|
|
931
|
-
let dt = new Date().getTime();
|
|
932
|
-
const uuid = 'xxxxxxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
933
|
-
// eslint-disable-next-line no-bitwise
|
|
934
|
-
const r = (dt + Math.random() * 16) % 16 | 0;
|
|
935
|
-
dt = Math.floor(dt / 16);
|
|
936
|
-
// eslint-disable-next-line no-bitwise
|
|
937
|
-
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
|
938
|
-
});
|
|
939
|
-
return uuid;
|
|
904
|
+
newWidth(wid) {
|
|
905
|
+
const result = Math.max(this.resizableMinWidth, wid);
|
|
906
|
+
this.el.nativeElement.style.width = result + 'px';
|
|
940
907
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
const reMsAjax = /^\/Date\((d|-|.*)\)[\/|\\]$/;
|
|
947
|
-
if (typeof dateString === 'string') {
|
|
948
|
-
const isoExec = reISO.exec(dateString);
|
|
949
|
-
if (isoExec) {
|
|
950
|
-
return new Date(dateString);
|
|
951
|
-
}
|
|
952
|
-
const msAjaxExec = reMsAjax.exec(dateString);
|
|
953
|
-
if (msAjaxExec) {
|
|
954
|
-
const cleaned = msAjaxExec[1].split(/[-+,.]/);
|
|
955
|
-
return new Date(cleaned[0] ? +cleaned[0] : 0 - +cleaned[1]);
|
|
956
|
-
}
|
|
908
|
+
mouseDown(evt) {
|
|
909
|
+
if (this.inDragRegion(evt)) {
|
|
910
|
+
this.dragging = true;
|
|
911
|
+
this.preventGlobalMouseEvents();
|
|
912
|
+
evt.stopPropagation();
|
|
957
913
|
}
|
|
958
|
-
return dateString;
|
|
959
914
|
}
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
*/
|
|
963
|
-
static getBrowser() {
|
|
964
|
-
const userAgent = navigator.userAgent;
|
|
965
|
-
let data = userAgent.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
|
|
966
|
-
let version;
|
|
967
|
-
if (/trident/i.test(data[1])) {
|
|
968
|
-
version = /\brv[ :]+(\d+)/g.exec(userAgent) || [];
|
|
969
|
-
return { name: 'IE', version: version[1] || '' };
|
|
970
|
-
}
|
|
971
|
-
if (data[1] === 'Chrome') {
|
|
972
|
-
version = userAgent.match(/\bOPR|Edge\/(\d+)/);
|
|
973
|
-
if (version != null) {
|
|
974
|
-
return { name: 'Opera', version: version[1] };
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
data = data[2] ? [data[1], data[2]] : [navigator.appName, navigator.appVersion, '-?'];
|
|
978
|
-
version = userAgent.match(/version\/(\d+)/i);
|
|
979
|
-
if (version !== null) {
|
|
980
|
-
data.splice(1, 1, version[1]);
|
|
981
|
-
}
|
|
982
|
-
return {
|
|
983
|
-
name: data[0],
|
|
984
|
-
version: data[1],
|
|
985
|
-
};
|
|
915
|
+
restoreGlobalMouseEvents() {
|
|
916
|
+
document.body.style['pointer-events'] = 'auto';
|
|
986
917
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
*/
|
|
991
|
-
static isSubset(a, b) {
|
|
992
|
-
// Equal
|
|
993
|
-
if (a === b) {
|
|
994
|
-
return true;
|
|
918
|
+
mouseUpG(evt) {
|
|
919
|
+
if (!this.dragging) {
|
|
920
|
+
return;
|
|
995
921
|
}
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
922
|
+
this.restoreGlobalMouseEvents();
|
|
923
|
+
this.dragging = false;
|
|
924
|
+
evt.stopPropagation();
|
|
925
|
+
}
|
|
926
|
+
mouseMove(evt) {
|
|
927
|
+
if (this.inDragRegion(evt) || this.dragging) {
|
|
928
|
+
this.el.nativeElement.style.cursor = 'col-resize';
|
|
999
929
|
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
for (const [key, value] of Object.entries(a)) {
|
|
1003
|
-
if (Helper.isSubset(value, b[key])) {
|
|
1004
|
-
return false;
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
return true;
|
|
930
|
+
else {
|
|
931
|
+
this.el.nativeElement.style.cursor = 'default';
|
|
1008
932
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
933
|
+
}
|
|
934
|
+
preventGlobalMouseEvents() {
|
|
935
|
+
document.body.style['pointer-events'] = 'none';
|
|
936
|
+
}
|
|
937
|
+
inDragRegion(evt) {
|
|
938
|
+
return this.el.nativeElement.clientWidth - evt.clientX + this.el.nativeElement.offsetLeft < this.resizableGrabWidth;
|
|
939
|
+
}
|
|
940
|
+
addListenerToDocument() {
|
|
941
|
+
document.addEventListener('mousemove', (e) => {
|
|
942
|
+
this.mouseMoveG(e);
|
|
943
|
+
}, true);
|
|
944
|
+
document.addEventListener('mouseup', (e) => {
|
|
945
|
+
this.mouseUpG(e);
|
|
946
|
+
}, true);
|
|
947
|
+
}
|
|
948
|
+
addListenerToElement() {
|
|
949
|
+
this.el.nativeElement.addEventListener('mousedown', (e) => {
|
|
950
|
+
this.mouseDown(e);
|
|
951
|
+
}, true);
|
|
952
|
+
this.el.nativeElement.addEventListener('mousemove', (e) => {
|
|
953
|
+
this.mouseMove(e);
|
|
954
|
+
}, true);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
ResizableDirective.decorators = [
|
|
958
|
+
{ type: Directive, args: [{
|
|
959
|
+
selector: '[ltResizable]',
|
|
960
|
+
},] }
|
|
961
|
+
];
|
|
962
|
+
ResizableDirective.ctorParameters = () => [
|
|
963
|
+
{ type: ElementRef }
|
|
964
|
+
];
|
|
965
|
+
ResizableDirective.propDecorators = {
|
|
966
|
+
resizableGrabWidth: [{ type: Input }],
|
|
967
|
+
resizableMinWidth: [{ type: Input }]
|
|
968
|
+
};
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* Truncate string with ellipses
|
|
972
|
+
*/
|
|
973
|
+
class EllipsesPipe {
|
|
974
|
+
transform(value, limit) {
|
|
975
|
+
if (!value) {
|
|
976
|
+
return null;
|
|
1018
977
|
}
|
|
1019
|
-
|
|
1020
|
-
return true;
|
|
978
|
+
return value.length > limit ? value.substring(0, limit) + '...' : value;
|
|
1021
979
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
980
|
+
}
|
|
981
|
+
EllipsesPipe.decorators = [
|
|
982
|
+
{ type: Pipe, args: [{
|
|
983
|
+
name: 'ltEllipses',
|
|
984
|
+
},] }
|
|
985
|
+
];
|
|
986
|
+
|
|
987
|
+
/**
|
|
988
|
+
* Declarate html as safe
|
|
989
|
+
*/
|
|
990
|
+
class SafeHtmlPipe {
|
|
991
|
+
constructor(sanitized) {
|
|
992
|
+
this.sanitized = sanitized;
|
|
993
|
+
}
|
|
994
|
+
transform(value) {
|
|
995
|
+
return this.sanitized.bypassSecurityTrustHtml(value);
|
|
1028
996
|
}
|
|
997
|
+
}
|
|
998
|
+
SafeHtmlPipe.decorators = [
|
|
999
|
+
{ type: Pipe, args: [{ name: 'ltSafeHtml' },] }
|
|
1000
|
+
];
|
|
1001
|
+
SafeHtmlPipe.ctorParameters = () => [
|
|
1002
|
+
{ type: DomSanitizer }
|
|
1003
|
+
];
|
|
1004
|
+
|
|
1005
|
+
// Imported and exported elements
|
|
1006
|
+
const elements = [
|
|
1007
|
+
// Directives
|
|
1008
|
+
ContextMenuDirective,
|
|
1009
|
+
LazyLoadDirective,
|
|
1010
|
+
MatchHeightDirective,
|
|
1011
|
+
ResizableDirective,
|
|
1012
|
+
// Pipes
|
|
1013
|
+
EllipsesPipe,
|
|
1014
|
+
SafeHtmlPipe,
|
|
1015
|
+
];
|
|
1016
|
+
/**
|
|
1017
|
+
* Base module
|
|
1018
|
+
*/
|
|
1019
|
+
class BaseModule {
|
|
1029
1020
|
/**
|
|
1030
|
-
*
|
|
1031
|
-
* Hint: functions will be ignored and when an array or an object is different the hole array or object will used as property value
|
|
1032
|
-
*
|
|
1033
|
-
* @returns Record<string, any> Object with properties from first object
|
|
1021
|
+
* Set configuration of base module in root module of the app
|
|
1034
1022
|
*/
|
|
1035
|
-
static
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1023
|
+
static forRoot(baseModuleConfig = {}) {
|
|
1024
|
+
// Default config
|
|
1025
|
+
const config = Object.assign({ apiUrl: 'localhost:3000', authGuardRedirectUrl: '/auth', logging: false, version: null, prefix: null, scrollDetectionOffset: 200, scrollOffset: 100, storageType: 'local' }, baseModuleConfig);
|
|
1026
|
+
// Prepare providers
|
|
1027
|
+
const providers = [
|
|
1028
|
+
{
|
|
1029
|
+
provide: BASE_MODULE_CONFIG,
|
|
1030
|
+
useValue: baseModuleConfig,
|
|
1031
|
+
},
|
|
1032
|
+
];
|
|
1033
|
+
// Add apollo features if API URL is set
|
|
1034
|
+
if (baseModuleConfig.apiUrl) {
|
|
1035
|
+
providers.push({
|
|
1036
|
+
provide: APOLLO_OPTIONS,
|
|
1037
|
+
useFactory: apolloOptionsFactory,
|
|
1038
|
+
deps: [BASE_MODULE_CONFIG, HttpLink, AuthService],
|
|
1039
|
+
});
|
|
1040
1040
|
}
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
result[key] = value;
|
|
1044
|
-
}
|
|
1041
|
+
else if (config.logging) {
|
|
1042
|
+
console.log('apiUrl is missing, ApolloLink is not initialized');
|
|
1045
1043
|
}
|
|
1046
|
-
|
|
1044
|
+
// Return root module
|
|
1045
|
+
return {
|
|
1046
|
+
ngModule: BaseModule,
|
|
1047
|
+
providers,
|
|
1048
|
+
};
|
|
1047
1049
|
}
|
|
1048
1050
|
}
|
|
1051
|
+
BaseModule.decorators = [
|
|
1052
|
+
{ type: NgModule, args: [{
|
|
1053
|
+
declarations: elements,
|
|
1054
|
+
exports: elements,
|
|
1055
|
+
},] }
|
|
1056
|
+
];
|
|
1049
1057
|
|
|
1050
1058
|
/**
|
|
1051
1059
|
* Standard class
|
|
@@ -1838,7 +1846,7 @@ class GraphQLService {
|
|
|
1838
1846
|
continue;
|
|
1839
1847
|
}
|
|
1840
1848
|
// Skip value if not exists
|
|
1841
|
-
if (value === undefined
|
|
1849
|
+
if (value === undefined || value === null) {
|
|
1842
1850
|
continue;
|
|
1843
1851
|
}
|
|
1844
1852
|
// Add current key to metadata
|
|
@@ -2153,7 +2161,7 @@ class ScrollService {
|
|
|
2153
2161
|
scrollTo(id, options = {}) {
|
|
2154
2162
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2155
2163
|
// Prepare config
|
|
2156
|
-
const config = Object.assign({ checkUrl:
|
|
2164
|
+
const config = Object.assign({ checkUrl: false, loadImagesBefore: true, resetStyles: false, setOverflow: true, stopPropagation: true }, options);
|
|
2157
2165
|
// Check current URL
|
|
2158
2166
|
if (config.checkUrl && this.router.url !== '/' && !this.router.url.startsWith('/#')) {
|
|
2159
2167
|
yield this.router.navigate(['/'], { fragment: id });
|
|
@@ -2231,37 +2239,16 @@ class ScrollService {
|
|
|
2231
2239
|
* Scroll done promise
|
|
2232
2240
|
*/
|
|
2233
2241
|
scrollDone(options = {}) {
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
2238
|
-
// Init variables
|
|
2239
|
-
let rejected = false;
|
|
2240
|
-
let timeoutId;
|
|
2241
|
-
// Set timeout handling if necessary
|
|
2242
|
-
if (config.timeout) {
|
|
2243
|
-
timeoutId = window.setTimeout(() => {
|
|
2244
|
-
rejected = true;
|
|
2245
|
-
reject(new Error('Timeout for scrollDone after:' + config.timeout));
|
|
2246
|
-
}, config.timeout);
|
|
2247
|
-
}
|
|
2242
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2243
|
+
// Init configuration
|
|
2244
|
+
const config = Object.assign({ doneFunction: undefined }, options);
|
|
2248
2245
|
// Wait for scroll done
|
|
2249
2246
|
yield this.scrollDoneDetection();
|
|
2250
|
-
//
|
|
2251
|
-
if (
|
|
2252
|
-
|
|
2253
|
-
if (timeoutId) {
|
|
2254
|
-
window.clearTimeout(timeoutId);
|
|
2255
|
-
}
|
|
2256
|
-
// Get result (if doneFunction is set)
|
|
2257
|
-
let result;
|
|
2258
|
-
if (config.doneFunction) {
|
|
2259
|
-
result = yield config.doneFunction();
|
|
2260
|
-
}
|
|
2261
|
-
// Scroll done
|
|
2262
|
-
resolve(result);
|
|
2247
|
+
// Get result
|
|
2248
|
+
if (config.doneFunction) {
|
|
2249
|
+
return config.doneFunction();
|
|
2263
2250
|
}
|
|
2264
|
-
})
|
|
2251
|
+
});
|
|
2265
2252
|
}
|
|
2266
2253
|
/**
|
|
2267
2254
|
* Scroll done detecton
|