Skip to content
This repository has been archived by the owner on Mar 29, 2024. It is now read-only.

Commit

Permalink
Improved tip up components to handle stacking and support dynamic tip…
Browse files Browse the repository at this point in the history
… up contents
  • Loading branch information
ppacher committed Feb 1, 2022
1 parent 73f9874 commit 84e176f
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 35 deletions.
2 changes: 1 addition & 1 deletion modules/portmaster/src/app/shared/tipup/anchor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class TipUpAnchorDirective implements TipupPlacement {
isActiveAnchor = false;

@Input('tipUpAnchor')
set position(posSpec: string) {
set position(posSpec: string | undefined) {
const parts = (posSpec || '').split(';')
if (parts.length > 2) {
if (isDevMode()) {
Expand Down
4 changes: 2 additions & 2 deletions modules/portmaster/src/app/shared/tipup/tipup-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class TipUpComponent implements OnInit, TipUp {
) { }

ngOnInit() {
const doc = MyYamlFile[this.token];
const doc = this.tipupService.getTipUp(this.token);
if (!!doc) {
Object.assign(this, doc);
this.urlText = doc.urlText || 'Read More';
Expand All @@ -38,8 +38,8 @@ export class TipUpComponent implements OnInit, TipUp {
return;
}

this.dialogRef.close();
this.tipupService.open(this.nextKey);
this.dialogRef.close();
}

async runAction(btn: Button) {
Expand Down
106 changes: 90 additions & 16 deletions modules/portmaster/src/app/shared/tipup/tipup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { deepCloneNode, extendStyles, matchElementSize, removeNode } from './clo
import { getCssSelector, synchronizeCssStyles } from './css-utils';
import { TipUpComponent } from './tipup-component';
import { TipupPlacement, TIPUP_TOKEN } from './utils';
import MyYamlFile, { Button, TipUp } from 'js-yaml-loader!../../../i18n/helptexts.yaml';


@Directive({
Expand Down Expand Up @@ -42,6 +43,32 @@ export class TipUpTriggerDirective implements OnDestroy {
get textKey() { return this._textKey; }
private _textKey: string = '';

/**
* The text to display inside the tip up. If unset, the tipup definition
* will be loaded form helptexts.yaml.
* This input property is mainly designed for programatic/dynamic tip-up generation
*/
@Input('tipUpText')
text: string | undefined;

@Input('tipUpTitle')
title: string | undefined;

/**
* asTipUp returns a tip-up definition built from the input
* properties tipUpText and tipUpTitle. If none are set
* then null is returned.
*/
asTipUp(): TipUp | null {
if (!this.text) {
return MyYamlFile[this.textKey];
}
return {
title: this.title || '',
content: this.text,
}
}

/**
* The default anchor for the tipup if non is provided via Dependency-Injection
* or using tipUpAnchorRef
Expand Down Expand Up @@ -145,6 +172,8 @@ export class TipUpTriggerDirective implements OnDestroy {
[tipUpTrigger]="key"
[tipUpDefaultAnchor]="parent"
[tipUpPlacement]="placement"
[tipUpText]="text"
[tipUpTitle]="title"
[tipUpAnchorRef]="anchor">
<g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" >
<path stroke="#ffff" shape-rendering="geometricPrecision" d="M12 21v0c-4.971 0-9-4.029-9-9v0c0-4.971 4.029-9 9-9v0c4.971 0 9 4.029 9 9v0c0 4.971-4.029 9-9 9z"/>
Expand Down Expand Up @@ -173,6 +202,10 @@ export class TipUpIconComponent implements TipupPlacement {
@Input()
key: string = '';

// see TipUpTrigger tipUpText and tipUpTitle
@Input() text: string | undefined = undefined;
@Input() title: string | undefined = undefined;

@Input()
anchor: ElementRef<any> | HTMLElement | null = null;

Expand Down Expand Up @@ -259,6 +292,10 @@ export class TipUpService {
}
}

getTipUp(key: string): TipUp | null {
return this.tipups.get(key)?.asTipUp() || null;
}

private _latestTipUp: DialogRef<TipUpComponent> | null = null;

createTipup(
Expand All @@ -268,11 +305,11 @@ export class TipUpService {
opts: TipupPlacement | null = {},
injector?: Injector): DialogRef<TipUpComponent> {

console.log("anchor", anchor);

if (!!this._latestTipUp) {
this._latestTipUp.close();
this._latestTipUp = null;
const lastTipUp = this._latestTipUp
let closePrevious = () => {
if (!!lastTipUp) {
lastTipUp.close();
}
}

// make sure we have an ElementRef to work with
Expand Down Expand Up @@ -319,18 +356,20 @@ export class TipUpService {
parent: injector || this.injector,
});

this._latestTipUp = this.dialog.create(TipUpComponent, {

const newTipUp = this.dialog.create(TipUpComponent, {
dragable: false,
autoclose: true,
backdrop: 'light',
injector: inj,
positionStrategy: postitionStrategy
});
this._latestTipUp = newTipUp;

const _preview = this._createPreview(anchor.nativeElement, _getShadowRoot(anchor.nativeElement));

// construct a CSS selector that targets the clicked origin (TipUpTriggerDirective) from within
// the anchor. We use that path to high light the copy of the trigger-directive in the preview.
// the anchor. We use that path to highlight the copy of the trigger-directive in the preview.
if (!!origin) {
const originSelector = getCssSelector(origin.elementRef.nativeElement, anchor.nativeElement);
let target: HTMLElement | null = null;
Expand All @@ -343,20 +382,35 @@ export class TipUpService {
this.renderer.addClass(target, 'active-tipup-trigger')
}

this._latestTipUp.onStateChange
newTipUp.onStateChange
.pipe(
filter(state => state === 'open'),
take(1)
)
.subscribe(() => {
closePrevious();
_preview.attach()
})

newTipUp.onStateChange
.pipe(
filter(state => state === 'closing'),
take(1)
)
.subscribe(() => {
this._latestTipUp = null;
removeNode(_preview);
if (this._latestTipUp === newTipUp) {
this._latestTipUp = null;
}
_preview.classList.remove('visible');
setTimeout(() => {
removeNode(_preview);
}, 300)
});

return this._latestTipUp;
return newTipUp;
}

private _createPreview(element: HTMLElement, shadowRoot: ShadowRoot | null): HTMLElement {
private _createPreview(element: HTMLElement, shadowRoot: ShadowRoot | null): HTMLElement & { attach: () => void } {
const preview = deepCloneNode(element);
// clone all CSS styles by applying them directly to the copied
// nodes. Though, we skip the opacity property because we use that
Expand All @@ -376,8 +430,8 @@ export class TipUpService {
'top': '0',
'left': '0',
'z-index': '1000',
'opacity': '1'
}, new Set(['position', 'opacity']));
'opacity': 'unset',
}, new Set(['position']));

// We add a dedicated class to the preview element so
// it can handle special higlighting itself.
Expand Down Expand Up @@ -418,9 +472,29 @@ export class TipUpService {
}
}

this._getPreviewInserationPoint(shadowRoot).appendChild(preview);
let attach = () => {
const parent = this._getPreviewInserationPoint(shadowRoot)
const cdkOverlayContainer = parent.getElementsByClassName('cdk-overlay-container')[0]
// if we find a cdkOverlayContainer in our inseration point (which we expect to be there)
// we insert the preview element right after the overlay-backdrop. This way the tip-up
// dialog will still be on top of the preview.
if (!!cdkOverlayContainer) {
const reference = cdkOverlayContainer.getElementsByClassName("cdk-overlay-backdrop")[0].nextSibling;
cdkOverlayContainer.insertBefore(preview, reference)
} else {
parent.appendChild(preview);
}

setTimeout(() => {
preview.classList.add('visible');
})
}

Object.defineProperty(preview, 'attach', {
value: attach,
})

return preview;
return preview as any;
}

private _getPreviewInserationPoint(shadowRoot: ShadowRoot | null): HTMLElement {
Expand Down
41 changes: 25 additions & 16 deletions modules/portmaster/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
}

.form-field {
display : flex;
display: flex;
justify-content: flext-start;
align-items : center;
align-items: center;

*:not(:last-child) {
@apply mr-1;
Expand All @@ -35,11 +35,11 @@

.sidebar {
@apply bg-background;
height : 100vh;
height: 100vh;
flex-shrink: 0;
flex-grow : 0;
flex-grow: 0;
@apply px-2;
display : flex;
display: flex;
flex-direction: column;

&.no-scroll {
Expand All @@ -58,12 +58,12 @@

.header {
display: flex;
width : 100%;
width: 100%;
@apply pl-12;
@apply pr-5;
@apply mb-2;
align-items: center;
height : 3rem;
height: 3rem;
flex-shrink: 0;

&:first-of-type {
Expand All @@ -72,11 +72,11 @@

>* {
flex-grow: 1;
margin : 0;
margin: 0;
}

>app-expertise {
flex-grow : 0;
flex-grow: 0;
flex-shrink: 0;
}
}
Expand All @@ -88,22 +88,31 @@

.tableFixHead thead th {
position: sticky;
top : 0;
top: 0;
}


fa-icon.tipup,
fa-icon[icon="question-circle"],
fa-icon[icon="question"] {
max-width : 10px;
max-height : 10px;
opacity : 0.8;
display : inline-block;
font-size : 0.75rem;
color : rgb(250 250 250 / 55%);
max-width: 10px;
max-height: 10px;
opacity: 0.8;
display: inline-block;
font-size: 0.75rem;
color: rgb(250 250 250 / 55%);
margin-left: 3px;

&:hover {
opacity: unset;
}
}

.tipup-preview {
transition: all .25s ease-in-out !important;
opacity: 0 !important;

&.visible {
opacity: 1 !important;
}
}

0 comments on commit 84e176f

Please sign in to comment.