angular-chat-widget-rasa
Version:
A chatbot widget that is able to connect to a rasa chatbot using SocketIO
501 lines (490 loc) • 20.6 kB
JavaScript
import { CommonModule } from '@angular/common';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Subject } from 'rxjs';
import { animate, style, transition, trigger } from '@angular/animations';
import io from 'socket.io-client';
import { Observable } from 'rxjs/Observable';
import { Component, Input, Injectable, EventEmitter, Output, ViewChild, ViewEncapsulation, HostListener, NgModule, defineInjectable } from '@angular/core';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var ChatAvatarComponent = /** @class */ (function () {
function ChatAvatarComponent() {
}
ChatAvatarComponent.decorators = [
{ type: Component, args: [{
selector: 'chat-avatar',
template: "\n <img [attr.src]=\"image\" class=\"avatar\" />\n ",
styles: ["\n .avatar {\n height: 30px;\n width: 30px;\n border-radius: 50%;\n float: left;\n margin-right: 10px;\n }\n "]
}] }
];
ChatAvatarComponent.propDecorators = {
image: [{ type: Input }]
};
return ChatAvatarComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
var fadeInOut = trigger('fadeInOut', [
transition(':enter', [
style({ opacity: 0 }),
animate(250)
]),
transition('* => void', [
animate(250, style({
opacity: 0,
}))
])
]);
/** @type {?} */
var fadeIn = trigger('fadeIn', [
transition(':enter', [
style({ opacity: 0 }),
animate(500)
]),
transition(':leave', [
style({ opacity: 0 }),
animate(1)
]),
]);
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var ChatService = /** @class */ (function () {
function ChatService() {
var _this = this;
this.getMessages = (/**
* @return {?}
*/
function () {
return Observable.create((/**
* @param {?} observer
* @return {?}
*/
function (observer) {
_this.socket.on('bot_uttered', (/**
* @param {?} message
* @return {?}
*/
function (message) {
observer.next(message);
}));
}));
});
}
/**
* @param {?} url
* @return {?}
*/
ChatService.prototype.connect = /**
* @param {?} url
* @return {?}
*/
function (url) {
var _this = this;
this.socket = io(url);
this.socket.on('connect', (/**
* @return {?}
*/
function () {
_this.socket.emit('session_request', { 'session_id': _this.socket.id });
}));
this.socket.on('session_confirm', (/**
* @param {?} remote_id
* @return {?}
*/
function (remote_id) {
}));
this.socket.on('connect_error', (/**
* @param {?} error
* @return {?}
*/
function (error) {
console.log(error);
}));
this.socket.on('error', (/**
* @param {?} error
* @return {?}
*/
function (error) {
console.log(error);
}));
this.socket.on('disconnect', (/**
* @param {?} reason
* @return {?}
*/
function (reason) {
console.log(reason);
}));
};
/**
* @param {?} message
* @return {?}
*/
ChatService.prototype.sendMessage = /**
* @param {?} message
* @return {?}
*/
function (message) {
this.socket.emit('user_uttered', { 'message': message });
};
ChatService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] }
];
/** @nocollapse */
ChatService.ctorParameters = function () { return []; };
/** @nocollapse */ ChatService.ngInjectableDef = defineInjectable({ factory: function ChatService_Factory() { return new ChatService(); }, token: ChatService, providedIn: "root" });
return ChatService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var ChatWidgetComponent = /** @class */ (function () {
function ChatWidgetComponent(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);
}
Object.defineProperty(ChatWidgetComponent.prototype, "visible", {
get: /**
* @return {?}
*/
function () {
return this._visible;
},
set: /**
* @param {?} visible
* @return {?}
*/
function (visible) {
var _this = this;
this._visible = visible;
if (this._visible) {
setTimeout((/**
* @return {?}
*/
function () {
_this.scrollToBottom();
_this.focusMessage();
}), 0);
}
},
enumerable: true,
configurable: true
});
/**
* @param {?} from
* @param {?} text
* @param {?} type
* @return {?}
*/
ChatWidgetComponent.prototype.addMessage = /**
* @param {?} from
* @param {?} text
* @param {?} type
* @return {?}
*/
function (from, text, type) {
this.messages.unshift({
from: from,
text: text,
type: type,
date: new Date().getTime(),
});
this.scrollToBottom();
};
/**
* @return {?}
*/
ChatWidgetComponent.prototype.scrollToBottom = /**
* @return {?}
*/
function () {
if (this.bottom !== undefined) {
this.bottom.nativeElement.scrollIntoView();
}
};
/**
* @return {?}
*/
ChatWidgetComponent.prototype.focusMessage = /**
* @return {?}
*/
function () {
this.focus.next(true);
};
/**
* @return {?}
*/
ChatWidgetComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
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 {?}
*/
function () { return _this.visible = true; }), 1000);
}
setTimeout((/**
* @return {?}
*/
function () {
_this.addMessage(_this.operator, _this.startingMessage, 'received');
}), 1500);
this.chatService
.getMessages()
.subscribe((/**
* @param {?} message
* @return {?}
*/
function (message) {
setTimeout((/**
* @return {?}
*/
function () { _this.addMessage(_this.operator, message.text, 'received'); }), 1000);
}));
};
/**
* @return {?}
*/
ChatWidgetComponent.prototype.toggleChat = /**
* @return {?}
*/
function () {
this.visible = !this.visible;
};
/**
* @param {?} __0
* @return {?}
*/
ChatWidgetComponent.prototype.sendMessage = /**
* @param {?} __0
* @return {?}
*/
function (_a) {
var message = _a.message;
if (message.trim() === '') {
return;
}
this.addMessage(this.client, message, 'sent');
this.chatService.sendMessage(message);
};
/**
* @param {?} event
* @return {?}
*/
ChatWidgetComponent.prototype.handleKeyboardEvent = /**
* @param {?} event
* @return {?}
*/
function (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 = function () { return [
{ 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'],] }]
};
return ChatWidgetComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var ChatInputComponent = /** @class */ (function () {
function ChatInputComponent() {
this.buttonText = '↩︎';
this.focus = new EventEmitter();
this.send = new EventEmitter();
this.dismiss = new EventEmitter();
}
/**
* @return {?}
*/
ChatInputComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
this.focus.subscribe((/**
* @return {?}
*/
function () { return _this.focusMessage(); }));
};
/**
* @return {?}
*/
ChatInputComponent.prototype.focusMessage = /**
* @return {?}
*/
function () {
this.message.nativeElement.focus();
};
/**
* @return {?}
*/
ChatInputComponent.prototype.getMessage = /**
* @return {?}
*/
function () {
return this.message.nativeElement.value;
};
/**
* @return {?}
*/
ChatInputComponent.prototype.clearMessage = /**
* @return {?}
*/
function () {
this.message.nativeElement.value = '';
};
/**
* @return {?}
*/
ChatInputComponent.prototype.onSubmit = /**
* @return {?}
*/
function () {
/** @type {?} */
var message = this.getMessage();
if (message.trim() === '') {
return;
}
this.send.emit({ message: message });
this.clearMessage();
this.focusMessage();
};
ChatInputComponent.decorators = [
{ type: Component, args: [{
selector: 'chat-input',
template: "\n <textarea type=\"text\" class=\"chat-input-text\" placeholder=\"Type message...\"\n #message (keydown.enter)=\"onSubmit()\" (keyup.enter)=\"message.value = ''\" (keyup.escape)=\"dismiss.emit()\"></textarea>\n <button type=\"submit\" class=\"chat-input-submit\" (click)=\"onSubmit()\">\n {{buttonText}}\n </button>\n ",
encapsulation: ViewEncapsulation.None,
styles: [".chat-input-text{margin:14px 0 0 14px;height:25px;width:70%;border:0;resize:none;border:none;overflow:auto;outline:0;box-shadow:none;font-size:14px;background-color:inherit;color:inherit}.chat-input-text::-webkit-input-placeholder{color:inherit}.chat-input-text::-moz-placeholder{color:inherit}.chat-input-text::-ms-input-placeholder{color:inherit}.chat-input-submit{margin:14px 12px;float:right;background-color:inherit;color:inherit;font-size:24px;border:0;outline:0}"]
}] }
];
ChatInputComponent.propDecorators = {
buttonText: [{ type: Input }],
focus: [{ type: Input }],
send: [{ type: Output }],
dismiss: [{ type: Output }],
message: [{ type: ViewChild, args: ['message',] }]
};
return ChatInputComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var ChatConfigComponent = /** @class */ (function () {
function ChatConfigComponent() {
this.text = 'Select theme';
this.themeChange = new EventEmitter();
this.themes = ['blue', 'grey', 'red'];
}
/**
* @param {?} theme
* @return {?}
*/
ChatConfigComponent.prototype.setTheme = /**
* @param {?} theme
* @return {?}
*/
function (theme) {
this.theme = theme;
this.themeChange.emit(this.theme);
};
ChatConfigComponent.decorators = [
{ type: Component, args: [{
selector: 'chat-config',
template: "\n <div class=\"chat-config\">\n {{text}}\n <button *ngFor=\"let item of themes\"\n class=\"btn\" [class.btn-active]=\"item === theme\"\n (click)=\"setTheme(item)\">\n {{item}}\n </button>\n </div>\n ",
styles: ["\n .chat-config {\n padding: 20px;\n }\n .btn {\n padding: 5px;\n margin: 0px 2px;\n border: 1px solid #dedede;\n outline: none;\n }\n .btn-active {\n border: 1px solid #a0a0a0;\n }\n .btn:focus {\n border: 1px solid #333;\n }\n "]
}] }
];
ChatConfigComponent.propDecorators = {
theme: [{ type: Input }],
text: [{ type: Input }],
themeChange: [{ type: Output }]
};
return ChatConfigComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var ChatbotRasaModule = /** @class */ (function () {
function ChatbotRasaModule() {
}
ChatbotRasaModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule, BrowserAnimationsModule],
declarations: [ChatAvatarComponent, ChatWidgetComponent, ChatInputComponent, ChatConfigComponent],
exports: [ChatWidgetComponent, ChatConfigComponent],
entryComponents: [ChatWidgetComponent, ChatConfigComponent],
providers: [ChatService]
},] }
];
return ChatbotRasaModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
export { ChatbotRasaModule, fadeIn as ɵd, fadeInOut as ɵc, ChatAvatarComponent as ɵa, ChatConfigComponent as ɵg, ChatInputComponent as ɵf, ChatWidgetComponent as ɵb, ChatService as ɵe };
//# sourceMappingURL=angular-chat-widget-rasa.js.map