import { IComponentController } from 'angular' import { Component, Inject } from '../decorators' import ClipboardService from './clipboard.service' export type FeedbackType = 'success' | 'danger' | 'info' | 'warning' export interface FeedbackOptions { autoCopyContents?: string clipboardContents?: string copyLinkText?: string copySuccessMessage?: string manualClose?: boolean trustAsHtml?: boolean type?: FeedbackType } export interface FeedbackAlert { clipboardContents?: string copyLinkText?: string copySuccessMessage?: string message?: string trustAsHtml: boolean type: FeedbackType } @Component({ selector: 'feedbackManager', template: require('./feedback.component.html'), }) export default class FeedbackManager implements IComponentController { protected alerts: FeedbackAlert[] = [] private timer: ng.IPromise | undefined constructor( @Inject('$interval') private $interval: ng.IIntervalService, @Inject('$rootScope') private $rootScope: ng.IRootScopeService, @Inject('$sce') private $sce: ng.ISCEService, @Inject('$timeout') private $timeout: ng.ITimeoutService, @Inject('clipboardService') private clipboardService: ClipboardService, ) {} $onInit() { // Handle clicks on copy-links inside feedback window.addEventListener('click', this.handleFeedbackClick) this.$rootScope.$on('showFeedback', (event, args: FeedbackOptions & {alertMessage: string}) => { if (args.autoCopyContents && args.clipboardContents) { throw new Error('The clipboardContents and autoCopyContents options are mutually exclusive.') } if (args.autoCopyContents) { this.clipboardService.writeToClipboard(args.autoCopyContents, args.copySuccessMessage) return } this.addAlert(args.alertMessage, args) }) } $onDestroy() { window.removeEventListener('click', this.handleFeedbackClick) } protected closeAlert() { this.removeTimer(this.timer) this.alerts = [] } private handleFeedbackClick = (event: MouseEvent) => { this.$timeout(() => { const target = event.target as HTMLElement | null if (!target?.closest('.c-feedback_container')) { return } const toCopy = target?.getAttribute('data-clipboard-text') const onSuccess = target?.getAttribute('data-clipboard-success') if (toCopy) { this.clipboardService.writeToClipboard(toCopy, onSuccess || undefined) } }) } private addAlert(message: string, options: FeedbackOptions) { this.removeTimer(this.timer) const trustAsHtml = !!options.trustAsHtml const alert: FeedbackAlert = { clipboardContents: options.clipboardContents || undefined, copyLinkText: options.copyLinkText, copySuccessMessage: options.copySuccessMessage, trustAsHtml, type: options.type || 'warning', } if (trustAsHtml) { alert.message = this.$sce.trustAsHtml(message) as string } else { alert.message = message } this.alerts = [alert] if (!options.manualClose) { this.timer = this.$interval(() => { this.closeAlert() }, 5000, 1) } } private removeTimer(timer: ng.IPromise | undefined) { if (timer) { this.$interval.cancel(timer) } } }