UNPKG

angular-chat-widget-rasa

Version:

A chatbot widget that is able to connect to a rasa chatbot using SocketIO

212 lines 19 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, ElementRef, HostListener, Input, ViewChild } from '@angular/core'; import { Subject } from 'rxjs'; import { fadeIn, fadeInOut } from '../animations'; import { ChatService } from '../chatbot-rasa.service'; /** @type {?} */ const rand = (/** * @param {?} max * @return {?} */ max => Math.floor(Math.random() * max)); const ɵ0 = rand; export class ChatWidgetComponent { /** * @param {?} chatService */ constructor(chatService) { this.theme = 'blue'; this.botName = 'Bot'; this.botAvatar = `https://cdn.dribbble.com/users/275794/screenshots/3128598/gbot_800.png`; this.userAvatar = `https://storage.proboards.com/6172192/images/gKhXFw_5W0SD4nwuMev1.png`; this.url = 'http://localhost:5002'; this.startingMessage = 'Hi, how can we help you?'; this.opened = true; this._visible = false; this.focus = new Subject(); this.messages = []; this.chatService = chatService; this.chatService.connect(this.url); } /** * @return {?} */ get visible() { return this._visible; } /** * @param {?} visible * @return {?} */ set visible(visible) { this._visible = visible; if (this._visible) { setTimeout((/** * @return {?} */ () => { this.scrollToBottom(); this.focusMessage(); }), 0); } } /** * @param {?} from * @param {?} text * @param {?} type * @return {?} */ addMessage(from, text, type) { this.messages.unshift({ from, text, type, date: new Date().getTime(), }); this.scrollToBottom(); } /** * @return {?} */ scrollToBottom() { if (this.bottom !== undefined) { this.bottom.nativeElement.scrollIntoView(); } } /** * @return {?} */ focusMessage() { this.focus.next(true); } /** * @return {?} */ ngOnInit() { this.client = { name: 'Guest User', status: 'online', avatar: this.userAvatar, }; this.operator = { name: this.botName, status: 'online', avatar: this.botAvatar, }; if (this.opened) { setTimeout((/** * @return {?} */ () => this.visible = true), 1000); } setTimeout((/** * @return {?} */ () => { this.addMessage(this.operator, this.startingMessage, 'received'); }), 1500); this.chatService .getMessages() .subscribe((/** * @param {?} message * @return {?} */ (message) => { setTimeout((/** * @return {?} */ () => { this.addMessage(this.operator, message.text, 'received'); }), 1000); })); } /** * @return {?} */ toggleChat() { this.visible = !this.visible; } /** * @param {?} __0 * @return {?} */ sendMessage({ message }) { if (message.trim() === '') { return; } this.addMessage(this.client, message, 'sent'); this.chatService.sendMessage(message); } /** * @param {?} event * @return {?} */ handleKeyboardEvent(event) { if (event.key === '/') { this.focusMessage(); } if (event.key === '?' && !this._visible) { this.toggleChat(); } } } ChatWidgetComponent.decorators = [ { type: Component, args: [{ selector: 'chat-widget', template: "<div class=\"wrapper {{theme}}\">\n <div class=\"chat-box\" *ngIf=\"visible\" [@fadeInOut]=\"visible\">\n <div class=\"chat-box-header\">\n <div class=\"\">\n <div class=\"operator-status\">\n {{operator.status}}\n <span class=\"operator-status-online\">\u25CF</span>\n <button class=\"chat-button-header\" (click)=\"toggleChat()\">\u2715</button>\n </div>\n <chat-avatar [image]=\"operator.avatar\"></chat-avatar>\n <h3 class=\"operator-name\">\n {{operator.name}}\n </h3>\n </div>\n </div>\n <div class=\"chat-box-main\">\n <div class=\"chat-message-bottom\" #bottom></div>\n <ng-container *ngFor=\"let message of messages\">\n <div class=\"chat-message\" [class.chat-message-received]=\"message.type === 'received'\"\n [@fadeIn]\n [class.chat-message-sent]=\"message.type === 'sent'\">\n <div >\n <chat-avatar [image]=\"message.from.avatar\" class=\"chat-message-from-avatar\"></chat-avatar>\n <div class=\"chat-message-text\">\n {{message.text}}\n </div>\n </div>\n <div class=\"chat-message-date\">\n {{message.date | date: 'short'}}\n </div>\n </div>\n </ng-container>\n </div>\n <div class=\"chat-box-footer\">\n <chat-input (send)=\"sendMessage($event)\" (dismiss)=\"toggleChat()\" [focus]=\"focus\"></chat-input>\n </div>\n </div>\n <button class=\"chat-button\" (click)=\"toggleChat()\">\n <span [@fadeIn] *ngIf=\"visible\">\u2715</span>\n <span [@fadeIn] *ngIf=\"!visible\">?</span>\n </button>\n</div>\n", animations: [fadeInOut, fadeIn], styles: ["*{box-sizing:border-box;position:relative;font-family:\"Open Sans\",\"Helvetica Neue\",sans-serif}.wrapper{position:absolute;top:0;bottom:0;height:100vh;width:100vw}.chat-button{z-index:1;width:60px;height:60px;position:absolute;bottom:20px;right:40px;box-shadow:0 5px 40px rgba(0,0,0,.16);background:#1976d2;border-radius:50%;border:none;outline:0;color:#fff;font-size:32px}.chat-button-header{z-index:1;font-weight:700;color:#fff;border:1px solid #fff;background-color:inherit;padding:5px 9px;margin-left:5px}.chat-button:focus{border:2px solid #fff}.chat-box{z-index:2;position:absolute;left:0;height:100vh;width:100vw;margin:0;display:flex;flex-direction:column;box-shadow:0 5px 40px rgba(0,0,0,.16);background:#1976d2}.chat-box-hidden{display:none}.chat-box-header{padding:10px;color:#fff}.chat-box-main{flex:1;width:100%;background:#f5f5f5;display:flex;flex-direction:column-reverse;overflow:auto}.chat-box-footer{color:#fff;height:50px}.operator-name{margin:0;padding:1px}.operator-status{float:right;padding:4px}.operator-status span{margin-left:4px}.operator-status-online{color:#7cfc00}.operator-status-offline{color:red}.operator-avatar{height:30px;width:30px;border-radius:50%;float:left;margin-right:10px}.chat-message{display:block;width:auto;margin:5px;align-self:flex-start;flex-direction:row;max-width:80%;word-wrap:break-word}.chat-message-date{font-size:11px;color:#8d898d;padding:5px}.chat-message-from-avatar{height:35px;width:35px;border-radius:50%}.chat-message-text{margin-left:10px;padding:10px;border-radius:3px}.chat-message-received{margin-right:50px}.chat-message-received .chat-message-text{background:#b9d6f2;margin-left:50px;border-bottom-left-radius:0}.chat-message-received .chat-message-text:before{position:absolute;content:\" \";left:-10px;bottom:0;border-right:10px solid #b9d6f2;border-top:10px solid transparent;z-index:0}.chat-message-received .chat-message-date{margin-left:50px}.chat-message-received .chat-message-from-avatar{position:absolute;left:0;bottom:-15px}.chat-message-sent{align-self:flex-end}.chat-message-sent .chat-message-from{float:right}.chat-message-sent .chat-message-text{background:#84dccf;margin-right:50px;border-bottom-right-radius:0}.chat-message-sent .chat-message-text:after{position:absolute;content:\" \";right:-10px;bottom:0;border-left:10px solid #84dccf;border-top:10px solid transparent;z-index:0}.chat-message-sent .chat-message-date{text-align:right;padding-right:50px}.chat-message-sent .chat-message-from-avatar{position:absolute;right:0;bottom:-15px}.blue .chat-box,.blue .chat-button{background:#1976d2}.grey .chat-box,.grey .chat-button{background:#454549}.red .chat-box,.red .chat-button{background:#dd0031}@media (min-width:576px){.wrapper{top:auto;right:0;width:300px}.chat-button{display:block}.chat-button-header{display:none}.chat-box{top:auto;left:auto;bottom:100px;right:40px;height:60vh;width:300px;border-radius:10px}}@media (min-width:768px){.chat-box{height:70vh}}@media (min-width:992px){.chat-box{height:80vh}}"] }] } ]; /** @nocollapse */ ChatWidgetComponent.ctorParameters = () => [ { type: ChatService } ]; ChatWidgetComponent.propDecorators = { bottom: [{ type: ViewChild, args: ['bottom',] }], theme: [{ type: Input }], botName: [{ type: Input }], botAvatar: [{ type: Input }], userAvatar: [{ type: Input }], url: [{ type: Input }], startingMessage: [{ type: Input }], opened: [{ type: Input }], visible: [{ type: Input }], handleKeyboardEvent: [{ type: HostListener, args: ['document:keypress', ['$event'],] }] }; if (false) { /** @type {?} */ ChatWidgetComponent.prototype.bottom; /** @type {?} */ ChatWidgetComponent.prototype.theme; /** @type {?} */ ChatWidgetComponent.prototype.botName; /** @type {?} */ ChatWidgetComponent.prototype.botAvatar; /** @type {?} */ ChatWidgetComponent.prototype.userAvatar; /** @type {?} */ ChatWidgetComponent.prototype.url; /** @type {?} */ ChatWidgetComponent.prototype.startingMessage; /** @type {?} */ ChatWidgetComponent.prototype.opened; /** @type {?} */ ChatWidgetComponent.prototype._visible; /** * @type {?} * @private */ ChatWidgetComponent.prototype.chatService; /** @type {?} */ ChatWidgetComponent.prototype.focus; /** @type {?} */ ChatWidgetComponent.prototype.operator; /** @type {?} */ ChatWidgetComponent.prototype.client; /** @type {?} */ ChatWidgetComponent.prototype.messages; } export { ɵ0 }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC13aWRnZXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vYW5ndWxhci1jaGF0LXdpZGdldC1yYXNhLyIsInNvdXJjZXMiOlsibGliL2NoYXQtd2lkZ2V0L2NoYXQtd2lkZ2V0LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBVSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDN0YsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQTtBQUM5QixPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUNqRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0seUJBQXlCLENBQUM7O01BRWhELElBQUk7Ozs7QUFBRyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFBOztBQVFuRCxNQUFNLE9BQU8sbUJBQW1COzs7O0lBYzlCLFlBQVksV0FBd0I7UUFacEIsVUFBSyxHQUE0QixNQUFNLENBQUE7UUFDdkMsWUFBTyxHQUFXLEtBQUssQ0FBQztRQUN4QixjQUFTLEdBQVcsd0VBQXdFLENBQUE7UUFDNUYsZUFBVSxHQUFXLHVFQUF1RSxDQUFBO1FBQzVGLFFBQUcsR0FBVyx1QkFBdUIsQ0FBQTtRQUNyQyxvQkFBZSxHQUFXLDBCQUEwQixDQUFBO1FBQ3BELFdBQU0sR0FBWSxJQUFJLENBQUE7UUFFL0IsYUFBUSxHQUFHLEtBQUssQ0FBQTtRQXVCaEIsVUFBSyxHQUFHLElBQUksT0FBTyxFQUFFLENBQUE7UUFNckIsYUFBUSxHQUFHLEVBQUUsQ0FBQTtRQXhCbEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFDL0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdB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SSxLQUFLLENBQUMsR0FBRyxLQUFLLEdBQUcsRUFBRTtZQUNyQixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUE7U0FDcEI7UUFDRCxJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUN2QyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUE7U0FDbEI7SUFDSCxDQUFDOzs7WUFoSEYsU0FBUyxTQUFDO2dCQUNULFFBQVEsRUFBRSxhQUFhO2dCQUN2Qix1cERBQTJDO2dCQUUzQyxVQUFVLEVBQUUsQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDOzthQUNoQzs7OztZQVRRLFdBQVc7OztxQkFXakIsU0FBUyxTQUFDLFFBQVE7b0JBQ2xCLEtBQUs7c0JBQ0wsS0FBSzt3QkFDTCxLQUFLO3lCQUNMLEtBQUs7a0JBQ0wsS0FBSzs4QkFDTCxLQUFLO3FCQUNMLEtBQUs7c0JBZUwsS0FBSztrQ0EyRUwsWUFBWSxTQUFDLG1CQUFtQixFQUFFLENBQUMsUUFBUSxDQUFDOzs7O0lBakc3QyxxQ0FBdUM7O0lBQ3ZDLG9DQUF1RDs7SUFDdkQsc0NBQXdDOztJQUN4Qyx3Q0FBNEc7O0lBQzVHLHlDQUE0Rzs7SUFDNUcsa0NBQXFEOztJQUNyRCw4Q0FBb0U7O0lBQ3BFLHFDQUFzQzs7SUFFdEMsdUNBQXVCOzs7OztJQUV2QiwwQ0FBaUM7O0lBcUJqQyxvQ0FBNEI7O0lBRTVCLHVDQUFnQjs7SUFFaEIscUNBQWM7O0lBRWQsdUNBQW9CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkluaXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnXG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcydcbmltcG9ydCB7IGZhZGVJbiwgZmFkZUluT3V0IH0gZnJvbSAnLi4vYW5pbWF0aW9ucydcbmltcG9ydCB7IENoYXRTZXJ2aWNlIH0gZnJvbSAnLi4vY2hhdGJvdC1yYXNhLnNlcnZpY2UnO1xuXG5jb25zdCByYW5kID0gbWF4ID0+IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIG1heClcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY2hhdC13aWRnZXQnLFxuICB0ZW1wbGF0ZVVybDogJy4vY2hhdC13aWRnZXQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jaGF0LXdpZGdldC5jb21wb25lbnQuY3NzJ10sXG4gIGFuaW1hdGlvbnM6IFtmYWRlSW5PdXQsIGZhZGVJbl0sXG59KVxuZXhwb3J0IGNsYXNzIENoYXRXaWRnZXRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBAVmlld0NoaWxkKCdib3R0b20nKSBib3R0b206IEVsZW1lbnRSZWZcbiAgQElucHV0KCkgcHVibGljIHRoZW1lOiAnYmx1ZScgfCAnZ3JleScgfCAncmVkJyA9ICdibHVlJ1xuICBASW5wdXQoKSBwdWJsaWMgYm90TmFtZTogc3RyaW5nID0gJ0JvdCc7XG4gIEBJbnB1dCgpIHB1YmxpYyBib3RBdmF0YXI6IHN0cmluZyA9IGBodHRwczovL2Nkbi5kcmliYmJsZS5jb20vdXNlcnMvMjc1Nzk0L3NjcmVlbnNob3RzLzMxMjg1OTgvZ2JvdF84MDAucG5nYFxuICBASW5wdXQoKSBwdWJsaWMgdXNlckF2YXRhcjogc3RyaW5nID0gYGh0dHBzOi8vc3RvcmFnZS5wcm9ib2FyZHMuY29tLzYxNzIxOTIvaW1hZ2VzL2dLaFhGd181VzBTRDRud3VNZXYxLnBuZ2BcbiAgQElucHV0KCkgcHVibGljIHVybDogc3RyaW5nID0gJ2h0dHA6Ly9sb2NhbGhvc3Q6NTAwMidcbiAgQElucHV0KCkgcHVibGljIHN0YXJ0aW5nTWVzc2FnZTogc3RyaW5nID0gJ0hpLCBob3cgY2FuIHdlIGhlbHAgeW91PydcbiAgQElucHV0KCkgcHVibGljIG9wZW5lZDogYm9vbGVhbiA9IHRydWVcblxuICBwdWJsaWMgX3Zpc2libGUgPSBmYWxzZVxuXG4gIHByaXZhdGUgY2hhdFNlcnZpY2U6IENoYXRTZXJ2aWNlO1xuXG4gIGNvbnN0cnVjdG9yKGNoYXRTZXJ2aWNlOiBDaGF0U2VydmljZSkge1xuICAgIHRoaXMuY2hhdFNlcnZpY2UgPSBjaGF0U2VydmljZTtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmNvbm5lY3QodGhpcy51cmwpO1xuICB9XG5cbiAgcHVibGljIGdldCB2aXNpYmxlKCkge1xuICAgIHJldHVybiB0aGlzLl92aXNpYmxlXG4gIH1cblxuICBASW5wdXQoKSBwdWJsaWMgc2V0IHZpc2libGUodmlzaWJsZSkge1xuICAgIHRoaXMuX3Zpc2libGUgPSB2aXNpYmxlXG4gICAgaWYgKHRoaXMuX3Zpc2libGUpIHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLnNjcm9sbFRvQm90dG9tKClcbiAgICAgICAgdGhpcy5mb2N1c01lc3NhZ2UoKVxuICAgICAgfSwgMClcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZm9jdXMgPSBuZXcgU3ViamVjdCgpXG5cbiAgcHVibGljIG9wZXJhdG9yO1xuXG4gIHB1YmxpYyBjbGllbnQ7XG5cbiAgcHVibGljIG1lc3NhZ2VzID0gW11cblxuICBwdWJsaWMgYWRkTWVzc2FnZShmcm9tLCB0ZXh0LCB0eXBlOiAncmVjZWl2ZWQnIHwgJ3NlbnQnKSB7XG4gICAgdGhpcy5tZXNzYWdlcy51bnNoaWZ0KHtcbiAgICAgIGZyb20sXG4gICAgICB0ZXh0LFxuICAgICAgdHlwZSxcbiAgICAgIGRhdGU6IG5ldyBEYXRlKCkuZ2V0VGltZSgpLFxuICAgIH0pXG4gICAgdGhpcy5zY3JvbGxUb0JvdHRvbSgpXG4gIH1cblxuICBwdWJsaWMgc2Nyb2xsVG9Cb3R0b20oKSB7XG4gICAgaWYgKHRoaXMuYm90dG9tICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuYm90dG9tLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsSW50b1ZpZXcoKVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBmb2N1c01lc3NhZ2UoKSB7XG4gICAgdGhpcy5mb2N1cy5uZXh0KHRydWUpXG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmNsaWVudCA9IHtcbiAgICAgIG5hbWU6ICdHdWVzdCBVc2VyJyxcbiAgICAgIHN0YXR1czogJ29ubGluZScsXG4gICAgICBhdmF0YXI6IHRoaXMudXNlckF2YXRhcixcbiAgICB9O1xuXG4gICAgdGhpcy5vcGVyYXRvciAgPSB7XG4gICAgICBuYW1lOiB0aGlzLmJvdE5hbWUsXG4gICAgICBzdGF0dXM6ICdvbmxpbmUnLFxuICAgICAgYXZhdGFyOiB0aGlzLmJvdEF2YXRhcixcbiAgICB9O1xuICAgIGlmKHRoaXMub3BlbmVkKXtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy52aXNpYmxlID0gdHJ1ZSwgMTAwMClcbiAgICB9XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLmFkZE1lc3NhZ2UodGhpcy5vcGVyYXRvciwgdGhpcy5zdGFydGluZ01lc3NhZ2UsICdyZWNlaXZlZCcpXG4gICAgfSwgMTUwMClcbiAgICB0aGlzLmNoYXRTZXJ2aWNlXG4gICAgICAuZ2V0TWVzc2FnZXMoKVxuICAgICAgLnN1YnNjcmliZSgobWVzc2FnZSkgPT4ge1xuICAgICAgICBzZXRUaW1lb3V0KCgpPT4ge3RoaXMuYWRkTWVzc2FnZSh0aGlzLm9wZXJhdG9yLCBtZXNzYWdlLnRleHQsICdyZWNlaXZlZCcpfSwxMDAwKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHRvZ2dsZUNoYXQoKSB7XG4gICAgdGhpcy52aXNpYmxlID0gIXRoaXMudmlzaWJsZVxuICB9XG5cbiAgcHVibGljIHNlbmRNZXNzYWdlKHsgbWVzc2FnZSB9KSB7XG4gICAgaWYgKG1lc3NhZ2UudHJpbSgpID09PSAnJykge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIHRoaXMuYWRkTWVzc2FnZSh0aGlzLmNsaWVudCwgbWVzc2FnZSwgJ3NlbnQnKVxuICAgIHRoaXMuY2hhdFNlcnZpY2Uuc2VuZE1lc3NhZ2UobWVzc2FnZSlcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmtleXByZXNzJywgWyckZXZlbnQnXSlcbiAgaGFuZGxlS2V5Ym9hcmRFdmVudChldmVudDogS2V5Ym9hcmRFdmVudCkge1xuICAgIGlmIChldmVudC5rZXkgPT09ICcvJykge1xuICAgICAgdGhpcy5mb2N1c01lc3NhZ2UoKVxuICAgIH1cbiAgICBpZiAoZXZlbnQua2V5ID09PSAnPycgJiYgIXRoaXMuX3Zpc2libGUpIHtcbiAgICAgIHRoaXMudG9nZ2xlQ2hhdCgpXG4gICAgfVxuICB9XG5cbn1cbiJdfQ==