@spotinst/spinnaker-deck
Version:
Spinnaker-Deck service, forked with support to Spotinst
138 lines (123 loc) • 4.34 kB
text/typescript
import { IComponentOptions, IController, ITimeoutService, module } from 'angular';
import ANGULARTICS from 'angulartics';
import { HelpContentsRegistry } from './helpContents.registry';
export interface IHelpFieldContents {
content: string;
placement: string;
}
export class HelpFieldCtrl implements IController {
public content: string;
public expand: boolean;
public label: string;
public contents: IHelpFieldContents;
public displayPopover: boolean;
public popoverTemplate: string = require('./helpField.popover.html');
private key: string;
private fallback: string;
private placement: string;
private popoverShownStart: number;
private popoverClose: PromiseLike<void>;
public static $inject = ['$timeout', '$analytics'];
constructor(private $timeout: ITimeoutService, private $analytics: any) {}
public $onInit(): void {
if (!this.content && this.key) {
this.content = HelpContentsRegistry.getHelpField(this.key) || this.fallback;
}
this.contents = {
content: this.content,
placement: this.placement || 'auto',
};
}
public $onChanges(): void {
this.$onInit();
}
public $onDestroy(): void {
if (this.popoverClose) {
this.$timeout.cancel(this.popoverClose);
}
}
public showPopover(): void {
this.displayPopover = true;
this.popoverShownStart = Date.now();
this.popoverHovered();
}
public hidePopover(defer: boolean): void {
if (defer) {
this.popoverClose = this.$timeout(() => {
this.displayPopover = false;
}, 300);
} else {
this.displayPopover = false;
}
// only track the event if the popover was on the screen for a little while, i.e. it wasn't accidentally
// moused over
if (Date.now() - this.popoverShownStart > 500) {
this.$analytics.eventTrack('Help contents viewed', { category: 'Help', label: this.key || this.content });
}
this.popoverShownStart = null;
}
public popoverHovered(): void {
if (this.popoverClose) {
this.$timeout.cancel(this.popoverClose);
this.popoverClose = null;
}
}
}
export const helpFieldComponent: IComponentOptions = {
bindings: {
key: '@',
fallback: '@',
content: '@',
placement: '@',
expand: '=',
label: '@',
},
controller: HelpFieldCtrl,
template: `
<div class="text-only" ng-if="$ctrl.label">
<a href class="help-field" ng-if="!$ctrl.expand && $ctrl.contents.content"
uib-popover-template="$ctrl.popoverTemplate"
ng-mouseenter="$ctrl.showPopover()"
ng-mouseleave="$ctrl.hidePopover(true)"
popover-placement="{{$ctrl.contents.placement}}"
popover-is-open="$ctrl.displayPopover"
popover-trigger="'none'"
ng-bind-html="$ctrl.label">
</a>
</div>
<div ng-if="!$ctrl.label" style="display: inline-block;">
<div ng-if="$ctrl.expand && $ctrl.contents.content"
class="help-contents small"
ng-bind-html="$ctrl.contents.content"></div>
<a href class="help-field" ng-if="!$ctrl.expand && $ctrl.contents.content"
uib-popover-template="$ctrl.popoverTemplate"
ng-mouseenter="$ctrl.showPopover()"
ng-mouseleave="$ctrl.hidePopover(true)"
popover-placement="{{$ctrl.contents.placement}}"
popover-is-open="$ctrl.displayPopover"
popover-trigger="'none'">
<i class="small glyphicon glyphicon-question-sign"></i>
</a>
</div>
`,
};
export const helpFieldWrapperComponent: IComponentOptions = {
bindings: {
id: '<',
fallback: '<',
content: '<',
placement: '<',
expand: '<',
label: '<',
},
template: `<help-field content="{{::$ctrl.content}}"
key="{{::$ctrl.id}}"
fallback="{{$ctrl.fallback}}"
placement="{{$ctrl.placement}}"
expand="$ctrl.expand"
label="{{$ctrl.label}}"></help-field>`,
};
export const HELP_FIELD_COMPONENT = 'spinnaker.core.help.helpField.component';
module(HELP_FIELD_COMPONENT, [ANGULARTICS])
.component('helpField', helpFieldComponent)
.component('helpFieldWrapper', helpFieldWrapperComponent);