From 630a624104d82d9eb280a173e4d33c3df5a44c08 Mon Sep 17 00:00:00 2001 From: Timo Date: Wed, 25 Nov 2020 11:04:09 +0200 Subject: [PATCH] tooltip added --- .../red-tooltip/custom-tooltip.directive.ts | 116 ++++++++++++++++++ .../red-tooltip/custom-tooltip.module.ts | 13 ++ .../tooltip-content.component.html | 10 ++ .../tooltip-content.component.scss | 19 +++ .../tooltip-content.component.ts | 15 +++ .../tooltip-content/tooltip.model.ts | 3 + 6 files changed, 176 insertions(+) create mode 100644 apps/red-ui/src/app/common/red-tooltip/custom-tooltip.directive.ts create mode 100644 apps/red-ui/src/app/common/red-tooltip/custom-tooltip.module.ts create mode 100644 apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.html create mode 100644 apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.scss create mode 100644 apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.ts create mode 100644 apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip.model.ts diff --git a/apps/red-ui/src/app/common/red-tooltip/custom-tooltip.directive.ts b/apps/red-ui/src/app/common/red-tooltip/custom-tooltip.directive.ts new file mode 100644 index 000000000..8f3ed0e44 --- /dev/null +++ b/apps/red-ui/src/app/common/red-tooltip/custom-tooltip.directive.ts @@ -0,0 +1,116 @@ +import { ComponentRef, Directive, ElementRef, HostListener, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; +import { Overlay, OverlayPositionBuilder, OverlayRef } from '@angular/cdk/overlay'; +import { ComponentPortal } from '@angular/cdk/portal'; +import { TooltipContentComponent } from './tooltip-content/tooltip-content.component'; +import { TooltipModel } from './tooltip-content/tooltip.model'; +import { ArOverlayPosition, Placement } from '../../common/model/ar-overlay-position'; +import { NavigationStart, Router } from '@angular/router'; + +@Directive({ + selector: '[redTooltip]', + exportAs: 'redTooltip' +}) +export class CustomTooltipDirective implements OnInit, OnChanges, OnDestroy { + @Input() redTooltip: string; + + @Input() placement: Placement = 'top'; + + private overlayRef: OverlayRef; + private tooltipRef: ComponentRef; + + private _enable = true; + protected test: string; + + constructor( + protected overlayPositionBuilder: OverlayPositionBuilder, + protected router: Router, + protected elementRef: ElementRef, + protected overlay: Overlay + ) {} + + ngOnInit(): void { + this.router.events.subscribe((event) => { + if (event instanceof NavigationStart) { + this.destroyOverlay(); + } + }); + } + + ngOnChanges(changes: SimpleChanges): void { + if (this.tooltipRef && this.redTooltip) { + this.tooltipRef.instance.tooltip = new TooltipModel(this.redTooltip); + } + } + + ngOnDestroy(): void { + this.destroyOverlay(); + } + + @HostListener('mouseover', ['$event']) + show($event) { + if (this._enable) { + $event.stopPropagation(); + $event.preventDefault(); + this.open(); + } + } + + open(model?: TooltipModel) { + if (!this.overlayRef) { + this.createOverlay(); + } + + if (model) { + this.redTooltip = model; + } + if (this.redTooltip) { + this.overlayRef.detach(); + const tooltipPortal = new ComponentPortal(TooltipContentComponent); + this.tooltipRef = this.overlayRef.attach(tooltipPortal); + this.tooltipRef.instance.tooltip = new TooltipModel(this.redTooltip); + } + } + + close() { + this.destroyOverlay(); + } + + @HostListener('mouseout') + hideFromMouseOut() { + this.detachOverlay(); + } + + @HostListener('mousedown') + hideFromClick() { + this._enable = false; + this.destroyOverlay(); + } + + @HostListener('mouseup') + _enableTooltip() { + this._enable = true; + } + + private createOverlay() { + const positionStrategy = this.overlayPositionBuilder + .flexibleConnectedTo(this.elementRef) + .withPositions(ArOverlayPosition.getConnectedPosition(this.placement)); + this.overlayRef = this.overlay.create({ + positionStrategy, + scrollStrategy: this.overlay.scrollStrategies.close() + }); + } + + private destroyOverlay() { + if (this.overlayRef) { + this.overlayRef.dispose(); + this.overlayRef = null; + } + } + + private detachOverlay() { + if (this.overlayRef && this.overlayRef.hasAttached()) { + this.overlayRef.detach(); + } + } +} diff --git a/apps/red-ui/src/app/common/red-tooltip/custom-tooltip.module.ts b/apps/red-ui/src/app/common/red-tooltip/custom-tooltip.module.ts new file mode 100644 index 000000000..3b95f0f58 --- /dev/null +++ b/apps/red-ui/src/app/common/red-tooltip/custom-tooltip.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { OverlayModule } from '@angular/cdk/overlay'; +import { CustomTooltipDirective } from './ar-tooltip.directive'; +import { TooltipContentComponent } from './tooltip-content/tooltip-content.component'; + +@NgModule({ + imports: [CommonModule, OverlayModule], + declarations: [CustomTooltipDirective, TooltipContentComponent], + exports: [CustomTooltipDirective], + entryComponents: [TooltipContentComponent] +}) +export class CustomTooltipModule {} diff --git a/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.html b/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.html new file mode 100644 index 000000000..c5337a6ed --- /dev/null +++ b/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.html @@ -0,0 +1,10 @@ +
+
+
{{ tooltip.title }}
+
{{ tooltip.body }}
+
+ +
{{ tooltip.title }}
+
{{ tooltip.body }}
+
+
diff --git a/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.scss b/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.scss new file mode 100644 index 000000000..f329c8ce2 --- /dev/null +++ b/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.scss @@ -0,0 +1,19 @@ +@import '../../../../../../../assets/styles/ar-typography'; + +.tooltip-wrapper { + background-color: $aci-white; + box-shadow: 2px 3px 20px 0 rgba(0, 0, 0, 0.1); + padding: 12px 16px; + max-width: 300px; + font-size: 13px; + opacity: 0.95; + + .tooltip-title { + @extend .aci-font-style-f8, .aci-grey-1; + padding-bottom: 4px; + } + + .tooltip-body { + @extend .aci-font-style-f9, .aci-grey-1; + } +} diff --git a/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.ts b/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.ts new file mode 100644 index 000000000..89b8b5c27 --- /dev/null +++ b/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip-content.component.ts @@ -0,0 +1,15 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { TooltipModel } from './tooltip.model'; + +@Component({ + selector: 'up-ext-tooltip-content', + templateUrl: './tooltip-content.component.html', + styleUrls: ['./tooltip-content.component.scss'] +}) +export class TooltipContentComponent implements OnInit { + @Input() tooltip: TooltipModel; + + constructor() {} + + ngOnInit() {} +} diff --git a/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip.model.ts b/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip.model.ts new file mode 100644 index 000000000..6dd21e043 --- /dev/null +++ b/apps/red-ui/src/app/common/red-tooltip/tooltip-content/tooltip.model.ts @@ -0,0 +1,3 @@ +export class TooltipModel { + constructor(public body: string) {} +}