[BREAK] remove old livechat client (#15133)
parent
c0f106b2f8
commit
5fdd2f2bcf
@ -1,18 +1,10 @@ |
||||
<template name="livechatInstallation"> |
||||
{{#requiresPermission 'view-livechat-manager'}} |
||||
<p>{{{_ "To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site"}}}</p> |
||||
|
||||
<p>{{{_ "To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site"}}}</p> |
||||
<div class="livechat-code"> |
||||
<textarea class="clipboard" data-clipboard-target=".livechat-code textarea">{{script}}</textarea> |
||||
<button class="rc-button rc-button--primary clipboard" data-clipboard-target=".livechat-code textarea"><i class="icon-docs"></i>{{_ "Copy_to_clipboard"}}</button> |
||||
</div> |
||||
|
||||
<p>{{{_ "To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site"}}}</p> |
||||
|
||||
<div class="livechat-code clipboard-old"> |
||||
<textarea class="clipboard" data-clipboard-target=".clipboard-old textarea">{{oldScript}}</textarea> |
||||
<button class="rc-button rc-button--primary clipboard" data-clipboard-target=".clipboard-old textarea"><i class="icon-docs"></i>{{_ "Copy_to_clipboard"}}</button> |
||||
</div> |
||||
|
||||
{{/requiresPermission}} |
||||
</template> |
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,31 +0,0 @@ |
||||
{ |
||||
"extends": ["@rocket.chat/eslint-config"], |
||||
"parser": "babel-eslint", |
||||
"globals": { |
||||
"AgentUsers" : false, |
||||
"CachedChatSubscription" : false, |
||||
"ChatMessage" : false, |
||||
"ChatMessages" : false, |
||||
"chatMessages" : false, |
||||
"ChatRoom" : false, |
||||
"ChatSubscription" : false, |
||||
"Department" : false, |
||||
"getAvatarUrlFromUsername" : false, |
||||
"getNextAgent" : false, |
||||
"handleError" : false, |
||||
"LivechatCustomField" : false, |
||||
"LivechatDepartment" : false, |
||||
"LivechatDepartmentAgents" : false, |
||||
"livechatManagerRoutes" : true, |
||||
"LivechatMonitoring" : false, |
||||
"LivechatPageVisited" : false, |
||||
"LivechatTrigger" : false, |
||||
"parentCall" : false, |
||||
"RoomHistoryManager" : false, |
||||
"RoomManager" : false, |
||||
"t" : false, |
||||
"Trigger" : false, |
||||
"Triggers" : false, |
||||
"visitor" : false |
||||
} |
||||
} |
||||
@ -1,19 +0,0 @@ |
||||
# This file contains information which helps Meteor properly upgrade your |
||||
# app when you run 'meteor update'. You should check it into version control |
||||
# with your project. |
||||
|
||||
notices-for-0.9.0 |
||||
notices-for-0.9.1 |
||||
0.9.4-platform-file |
||||
notices-for-facebook-graph-api-2 |
||||
1.2.0-standard-minifiers-package |
||||
1.2.0-meteor-platform-split |
||||
1.2.0-cordova-changes |
||||
1.2.0-breaking-changes |
||||
1.3.0-split-minifiers-package |
||||
1.3.5-remove-old-dev-bundle-link |
||||
1.4.0-remove-old-dev-bundle-link |
||||
1.4.1-add-shell-server-package |
||||
1.4.3-split-account-service-packages |
||||
1.5-add-dynamic-import-package |
||||
1.7-split-underscore-from-meteor-base |
||||
@ -1,2 +0,0 @@ |
||||
dev_bundle |
||||
local |
||||
@ -1,7 +0,0 @@ |
||||
# This file contains a token that is unique to your project. |
||||
# Check it into your repository along with the rest of this directory. |
||||
# It can be used for purposes such as: |
||||
# - ensuring you don't accidentally deploy one app on top of another |
||||
# - providing package authors with aggregated statistics |
||||
|
||||
90q00kzhqkdn1l0ptwl |
||||
@ -1,41 +0,0 @@ |
||||
# Meteor packages used by this project, one per line. |
||||
# Check this file (and the other files in this directory) into your repository. |
||||
# |
||||
# 'meteor add' and 'meteor remove' will edit this file for you, |
||||
# but you can also edit it by hand. |
||||
|
||||
meteor@1.9.2 |
||||
webapp@1.7.1 |
||||
logging@1.1.20 |
||||
tracker@1.2.0 |
||||
deps@1.0.12 |
||||
session@1.2.0 |
||||
ddp@1.4.0 |
||||
livedata@1.0.18 |
||||
mongo@1.6.0 |
||||
blaze |
||||
ui |
||||
spacebars |
||||
templating |
||||
check@1.3.1 |
||||
jquery@1.11.10 |
||||
random@1.1.0 |
||||
ejson@1.1.0 |
||||
rocketchat:streamer |
||||
kadira:flow-router |
||||
kadira:blaze-layout |
||||
konecty:nrr |
||||
less@2.8.0 |
||||
momentjs:moment |
||||
mizzao:timesync |
||||
reactive-var@1.0.11 |
||||
accounts-password@1.5.1 |
||||
rocketchat:tap-i18n |
||||
ecmascript@0.12.3 |
||||
es5-shim@4.8.0 |
||||
standard-minifier-css@1.5.2 |
||||
standard-minifier-js@2.4.0 |
||||
shell-server@0.4.0 |
||||
dynamic-import@0.5.0 |
||||
|
||||
konecty:user-presence |
||||
@ -1,2 +0,0 @@ |
||||
browser |
||||
server |
||||
@ -1 +0,0 @@ |
||||
METEOR@1.8.0.1 |
||||
@ -1,98 +0,0 @@ |
||||
accounts-base@1.4.3 |
||||
accounts-password@1.5.1 |
||||
aldeed:simple-schema@1.5.4 |
||||
allow-deny@1.1.0 |
||||
babel-compiler@7.2.3 |
||||
babel-runtime@1.3.0 |
||||
base64@1.0.11 |
||||
binary-heap@1.0.11 |
||||
blaze@2.3.3 |
||||
blaze-tools@1.0.10 |
||||
boilerplate-generator@1.6.0 |
||||
caching-compiler@1.2.1 |
||||
caching-html-compiler@1.1.3 |
||||
callback-hook@1.1.0 |
||||
cfs:http-methods@0.0.32 |
||||
check@1.3.1 |
||||
coffeescript@1.0.17 |
||||
ddp@1.4.0 |
||||
ddp-client@2.3.3 |
||||
ddp-common@1.4.0 |
||||
ddp-rate-limiter@1.0.7 |
||||
ddp-server@2.2.0 |
||||
deps@1.0.12 |
||||
diff-sequence@1.1.1 |
||||
dynamic-import@0.5.1 |
||||
ecmascript@0.12.3 |
||||
ecmascript-runtime@0.7.0 |
||||
ecmascript-runtime-client@0.8.0 |
||||
ecmascript-runtime-server@0.7.1 |
||||
ejson@1.1.0 |
||||
email@1.2.3 |
||||
es5-shim@4.8.0 |
||||
fetch@0.1.0 |
||||
geojson-utils@1.0.10 |
||||
html-tools@1.0.11 |
||||
htmljs@1.0.11 |
||||
http@1.4.2 |
||||
id-map@1.1.0 |
||||
inter-process-messaging@0.1.0 |
||||
jquery@1.11.11 |
||||
kadira:blaze-layout@2.3.0 |
||||
kadira:flow-router@2.12.1 |
||||
konecty:nrr@2.0.2 |
||||
konecty:user-presence@2.3.0 |
||||
less@2.8.0 |
||||
livedata@1.0.18 |
||||
localstorage@1.2.0 |
||||
logging@1.1.20 |
||||
mdg:validation-error@0.5.1 |
||||
meteor@1.9.2 |
||||
meteorspark:util@0.2.0 |
||||
minifier-css@1.4.1 |
||||
minifier-js@2.4.0 |
||||
minimongo@1.4.5 |
||||
mizzao:timesync@0.5.0 |
||||
modern-browsers@0.1.3 |
||||
modules@0.13.0 |
||||
modules-runtime@0.10.3 |
||||
momentjs:moment@2.22.2 |
||||
mongo@1.6.0 |
||||
mongo-decimal@0.1.0 |
||||
mongo-dev-server@1.1.0 |
||||
mongo-id@1.0.7 |
||||
npm-bcrypt@0.9.3 |
||||
npm-mongo@3.1.1 |
||||
observe-sequence@1.0.16 |
||||
ordered-dict@1.1.0 |
||||
promise@0.11.1 |
||||
raix:eventemitter@0.1.3 |
||||
random@1.1.0 |
||||
rate-limit@1.0.9 |
||||
reactive-dict@1.2.1 |
||||
reactive-var@1.0.11 |
||||
reload@1.2.0 |
||||
retry@1.1.0 |
||||
rocketchat:streamer@1.0.1 |
||||
routepolicy@1.1.0 |
||||
service-configuration@1.0.11 |
||||
session@1.2.0 |
||||
sha@1.0.9 |
||||
shell-server@0.4.0 |
||||
socket-stream-client@0.2.2 |
||||
spacebars@1.0.15 |
||||
spacebars-compiler@1.1.3 |
||||
srp@1.0.12 |
||||
standard-minifier-css@1.5.2 |
||||
standard-minifier-js@2.4.0 |
||||
rocketchat:tap-i18n@1.9.1 |
||||
templating@1.3.2 |
||||
templating-compiler@1.3.3 |
||||
templating-runtime@1.3.2 |
||||
templating-tools@1.1.2 |
||||
tracker@1.2.0 |
||||
ui@1.0.13 |
||||
underscore@1.0.10 |
||||
url@1.2.0 |
||||
webapp@1.7.2 |
||||
webapp-hashing@1.0.9 |
||||
@ -1,8 +0,0 @@ |
||||
<template name="modal"> |
||||
<div class="modal"> |
||||
<div class="overlay"></div> |
||||
<div class="wrapper"> |
||||
{{> Template.contentBlock}} |
||||
</div> |
||||
</div> |
||||
</template> |
||||
@ -1,37 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
this.CustomFields = (function() { |
||||
let queue = {}; |
||||
let initiated = false; |
||||
|
||||
const setCustomField = function(token, key, value, overwrite = true) { |
||||
if (!initiated) { |
||||
// queue by key
|
||||
queue[key] = { token, value, overwrite }; |
||||
return; |
||||
} |
||||
Meteor.call('livechat:setCustomField', token, key, value, overwrite); |
||||
}; |
||||
|
||||
const init = function() { |
||||
Tracker.autorun(function() { |
||||
if (visitor.getId()) { |
||||
initiated = true; |
||||
Object.keys(queue).forEach((key) => { |
||||
setCustomField.call(this, queue[key].token, key, queue[key].value, queue[key].overwrite); |
||||
}); |
||||
queue = {}; |
||||
} else { |
||||
initiated = false; |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
return { |
||||
init, |
||||
setCustomField, |
||||
}; |
||||
}()); |
||||
@ -1,174 +0,0 @@ |
||||
/* globals fileUpload, Livechat, Handlebars, showError, sendFileUpload */ |
||||
/* exported LivechatFileUpload, fileUpload, sendFileUpload */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import swal from 'sweetalert2'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
const handleRequestError = (response) => { |
||||
if (!response.success) { |
||||
let reason = t('FileUpload_Error'); |
||||
switch (response.reason) { |
||||
case 'error-type-not-allowed': |
||||
reason = t('FileUpload_MediaType_NotAccepted'); |
||||
break; |
||||
case 'error-size-not-allowed': |
||||
reason = t('File_exceeds_allowed_size_of_bytes', { size: response.sizeAllowed }); |
||||
} |
||||
|
||||
swal({ |
||||
text: reason, |
||||
type: 'error', |
||||
timer: 4000, |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
function sendFileRequest(file, roomId, token) { |
||||
const url = `${ Meteor.absoluteUrl() }api/v1/livechat/upload/${ roomId }`; |
||||
const form = new FormData(); |
||||
form.append('file', file); |
||||
|
||||
const request = new XMLHttpRequest(); |
||||
request.open('POST', url); |
||||
request.responseType = 'json'; |
||||
request.setRequestHeader('X-Visitor-Token', token); |
||||
|
||||
request.onload = () => { |
||||
if (request.status !== 200) { |
||||
handleRequestError(request.response); |
||||
} |
||||
}; |
||||
|
||||
request.onerror = () => { |
||||
handleRequestError(request.response); |
||||
}; |
||||
|
||||
request.send(form); |
||||
} |
||||
|
||||
function readAsDataURL(file, callback) { |
||||
const reader = new FileReader(); |
||||
reader.onload = (ev) => callback(ev.target.result, file); |
||||
|
||||
return reader.readAsDataURL(file); |
||||
} |
||||
|
||||
function getUploadPreview(file, callback) { |
||||
// If greater then 10MB don't try and show a preview
|
||||
if (file.file.size > (10 * 1000000)) { |
||||
return callback(file, null); |
||||
} if (file.file.type == null) { |
||||
callback(file, null); |
||||
} else if ((file.file.type.indexOf('audio') > -1) || (file.file.type.indexOf('video') > -1) || (file.file.type.indexOf('image') > -1)) { |
||||
file.type = file.file.type.split('/')[0]; |
||||
return readAsDataURL(file.file, (content) => callback(file, content)); |
||||
} else { |
||||
return callback(file, null); |
||||
} |
||||
} |
||||
|
||||
function formatBytes(bytes, decimals) { |
||||
if (bytes === 0) { |
||||
return '0 Bytes'; |
||||
} |
||||
|
||||
const k = 1000; |
||||
const dm = (decimals + 1) || 3; |
||||
|
||||
const sizes = [ |
||||
'Bytes', |
||||
'KB', |
||||
'MB', |
||||
'GB', |
||||
'TB', |
||||
'PB', |
||||
]; |
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k)); |
||||
|
||||
return `${ parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) } ${ sizes[i] }`; |
||||
} |
||||
|
||||
function sendFileMessage(file, roomId) { |
||||
if (visitor.isSubscribed(roomId)) { |
||||
return sendFileRequest(file, roomId, visitor.getToken()); |
||||
} |
||||
|
||||
Meteor.call('livechat:startFileUploadRoom', roomId, visitor.getToken(), (error, result) => { |
||||
if (error) { |
||||
return showError(error.message); |
||||
} |
||||
|
||||
Livechat.room = result.room._id; |
||||
visitor.subscribeToRoom(result.room._id); |
||||
visitor.setRoom(result.room._id); |
||||
sendFileRequest(file, roomId, visitor.getToken()); |
||||
parentCall('callback', 'chat-started'); |
||||
}); |
||||
} |
||||
|
||||
sendFileUpload = (file) => getUploadPreview(file, function(file, preview) { |
||||
let html = ''; |
||||
if (file.type === 'audio') { |
||||
html = `<div class='upload-preview'><audio style="width: 100%;" controls="controls"><source src="${ preview }" type="audio/wav">Your browser does not support the audio element.</audio></div>`; |
||||
} else if (file.type === 'video') { |
||||
html = `<div class='upload-preview'><video style="width: 100%;" controls="controls"><source src="${ preview }" type="video/webm">Your browser does not support the video element.</video></div>`; |
||||
} else if (file.type === 'image') { |
||||
html = `<div class='upload-preview'><div class='upload-preview-file' style='background-image: url(${ preview })'></div></div>`; |
||||
} else { |
||||
const fileSize = formatBytes(file.file.size); |
||||
html = `<div class='upload-preview'><div>${ Handlebars._escape(file.name) } - ${ fileSize }</div></div>`; |
||||
} |
||||
|
||||
swal({ |
||||
title: t('Upload_file_question'), |
||||
html, |
||||
showCancelButton: true, |
||||
cancelButtonText: t('No'), |
||||
confirmButtonText: t('Yes'), |
||||
}).then((result) => { |
||||
if (!result.value) { |
||||
return; |
||||
} |
||||
|
||||
const roomId = visitor.getRoom(true); |
||||
|
||||
if (visitor.getId()) { |
||||
return sendFileMessage(file.file, roomId); |
||||
} |
||||
|
||||
const guest = { |
||||
token: visitor.getToken(), |
||||
}; |
||||
|
||||
if (Livechat.department) { |
||||
guest.department = Livechat.department; |
||||
} |
||||
|
||||
Meteor.call('livechat:registerGuest', guest, (error, result) => { |
||||
if (error) { |
||||
return showError(error.reason); |
||||
} |
||||
|
||||
visitor.setId(result.userId); |
||||
sendFileMessage(file.file, roomId); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
fileUpload = (file) => { |
||||
if (file.size === 0) { |
||||
swal({ |
||||
title: t('FileUpload_File_Empty'), |
||||
text: '', |
||||
type: 'error', |
||||
timer: 1000, |
||||
showConfirmButton: false, |
||||
}); |
||||
|
||||
return; |
||||
} |
||||
|
||||
return sendFileUpload(file); |
||||
}; |
||||
@ -1,73 +0,0 @@ |
||||
/* globals LivechatVideoCall, JitsiMeetExternalAPI */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
LivechatVideoCall = new class LivechatVideoCall { |
||||
constructor() { |
||||
this.live = new ReactiveVar(false); |
||||
this.calling = new ReactiveVar(false); |
||||
|
||||
if (typeof JitsiMeetExternalAPI === 'undefined') { |
||||
const prefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || ''; |
||||
$.getScript(`${ prefix }/packages/rocketchat_videobridge/client/public/external_api.js`); |
||||
} |
||||
} |
||||
|
||||
askPermissions(callback) { |
||||
return callback(true); |
||||
} |
||||
|
||||
request() { |
||||
this.askPermissions((granted) => { |
||||
if (granted) { |
||||
this.calling.set(true); |
||||
Meteor.call('livechat:startVideoCall', visitor.getRoom(true), (error, result) => { |
||||
if (error) { |
||||
return; |
||||
} |
||||
visitor.subscribeToRoom(result.roomId); |
||||
|
||||
// after get ok from server, start the chat
|
||||
this.start(result.domain, result.jitsiRoom); |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
start(domain, room) { |
||||
Meteor.defer(() => { |
||||
const interfaceConfig = {}; |
||||
interfaceConfig.TOOLBAR_BUTTONS = '[""]'; |
||||
interfaceConfig.APP_NAME = '"Livechat"'; |
||||
interfaceConfig.INITIAL_TOOLBAR_TIMEOUT = '5000'; |
||||
interfaceConfig.MIN_WIDTH = '300'; |
||||
interfaceConfig.FILM_STRIP_MAX_HEIGHT = '50'; |
||||
|
||||
this.api = new JitsiMeetExternalAPI(domain, room, $('.video-call').width(), $('.video-call').height(), $('.video-call .container').get(0), {}, interfaceConfig); |
||||
|
||||
this.api.addEventListener('videoConferenceJoined', () => { |
||||
this.api.executeCommand('toggleFilmStrip', []); |
||||
}); |
||||
|
||||
this.live.set(true); |
||||
}); |
||||
} |
||||
|
||||
finish() { |
||||
this.live.set(false); |
||||
this.calling.set(false); |
||||
this.api.dispose(); |
||||
} |
||||
|
||||
isActive() { |
||||
return this.live.get() || this.calling.get(); |
||||
} |
||||
|
||||
isLive() { |
||||
return this.live.get(); |
||||
} |
||||
}(); |
||||
|
||||
/* exported LivechatVideoCall */ |
||||
@ -1,305 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
this.Livechat = new class Livechat { |
||||
constructor() { |
||||
this._online = new ReactiveVar(null); |
||||
|
||||
this._customColor = new ReactiveVar(); |
||||
this._onlineColor = new ReactiveVar('#C1272D'); |
||||
this._offlineColor = new ReactiveVar('#666666'); |
||||
|
||||
this._customFontColor = new ReactiveVar(); |
||||
this._onlineFontColor = new ReactiveVar('#FFFFFF'); |
||||
this._offlineFontColor = new ReactiveVar('#FFFFFF'); |
||||
|
||||
this._title = new ReactiveVar('Rocket.Chat'); |
||||
this._registrationForm = new ReactiveVar(true); |
||||
this._showSwitchDepartmentForm = new ReactiveVar(false); |
||||
this._allowSwitchingDepartments = new ReactiveVar(false); |
||||
this._offlineMessage = new ReactiveVar(''); |
||||
this._offlineUnavailableMessage = new ReactiveVar(''); |
||||
this._displayOfflineForm = new ReactiveVar(true); |
||||
this._offlineSuccessMessage = new ReactiveVar(TAPi18n.__('Thanks_We_ll_get_back_to_you_soon')); |
||||
this._videoCall = new ReactiveVar(false); |
||||
this._fileUpload = new ReactiveVar(false); |
||||
this._transcriptMessage = new ReactiveVar(''); |
||||
this._conversationFinishedMessage = new ReactiveVar(''); |
||||
this._nameFieldRegistrationForm = new ReactiveVar(false); |
||||
this._emailFieldRegistrationForm = new ReactiveVar(false); |
||||
this._connecting = new ReactiveVar(false); |
||||
this._room = new ReactiveVar(null); |
||||
this._department = new ReactiveVar(null); |
||||
this._widgetOpened = new ReactiveVar(false); |
||||
this._ready = new ReactiveVar(false); |
||||
this._agent = new ReactiveVar(); |
||||
this._registrationFormMessage = new ReactiveVar(''); |
||||
|
||||
this.stream = new Meteor.Streamer('livechat-room'); |
||||
|
||||
this._guestName = new ReactiveVar(); |
||||
this._guestEmail = new ReactiveVar(); |
||||
|
||||
Tracker.autorun(() => { |
||||
if (this._room.get() && visitor.getId()) { |
||||
RoomHistoryManager.getMoreIfIsEmpty(this._room.get()); |
||||
visitor.subscribeToRoom(this._room.get()); |
||||
visitor.setRoom(this._room.get()); |
||||
|
||||
Meteor.call('livechat:getAgentData', { roomId: this._room.get(), token: visitor.getToken() }, (error, result) => { |
||||
if (!error) { |
||||
this._agent.set(result); |
||||
} |
||||
}); |
||||
this.stream.on(this._room.get(), { visitorToken: visitor.getToken() }, (eventData) => { |
||||
if (!eventData || !eventData.type) { |
||||
return; |
||||
} |
||||
|
||||
if (eventData.type === 'agentData') { |
||||
this._agent.set(eventData.data); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
get online() { |
||||
return this._online.get(); |
||||
} |
||||
|
||||
get color() { |
||||
if (!this._online.get()) { |
||||
return this._offlineColor.get(); |
||||
} |
||||
return this._customColor.get() || this._onlineColor.get(); |
||||
} |
||||
|
||||
get fontColor() { |
||||
if (!this._online.get()) { |
||||
return this._offlineFontColor.get(); |
||||
} |
||||
return this._customFontColor.get() || this._onlineFontColor.get(); |
||||
} |
||||
|
||||
get title() { |
||||
return this._title.get(); |
||||
} |
||||
|
||||
get registrationForm() { |
||||
return this._registrationForm.get(); |
||||
} |
||||
|
||||
get showSwitchDepartmentForm() { |
||||
return this._showSwitchDepartmentForm.get(); |
||||
} |
||||
|
||||
get allowSwitchingDepartments() { |
||||
return this._allowSwitchingDepartments.get(); |
||||
} |
||||
|
||||
get offlineMessage() { |
||||
return this._offlineMessage.get(); |
||||
} |
||||
|
||||
get offlineUnavailableMessage() { |
||||
return this._offlineUnavailableMessage.get(); |
||||
} |
||||
|
||||
get displayOfflineForm() { |
||||
return this._displayOfflineForm.get(); |
||||
} |
||||
|
||||
get offlineSuccessMessage() { |
||||
return this._offlineSuccessMessage.get(); |
||||
} |
||||
|
||||
get videoCall() { |
||||
return this._videoCall.get(); |
||||
} |
||||
|
||||
get fileUpload() { |
||||
return this._fileUpload.get(); |
||||
} |
||||
|
||||
get transcriptMessage() { |
||||
return this._transcriptMessage.get(); |
||||
} |
||||
|
||||
get conversationFinishedMessage() { |
||||
return this._conversationFinishedMessage.get(); |
||||
} |
||||
|
||||
get nameFieldRegistrationForm() { |
||||
return this._nameFieldRegistrationForm.get(); |
||||
} |
||||
|
||||
get emailFieldRegistrationForm() { |
||||
return this._emailFieldRegistrationForm.get(); |
||||
} |
||||
|
||||
get department() { |
||||
return this._department.get(); |
||||
} |
||||
|
||||
get connecting() { |
||||
return this._connecting.get(); |
||||
} |
||||
|
||||
get agent() { |
||||
return this._agent.get(); |
||||
} |
||||
|
||||
get guestName() { |
||||
return this._guestName.get(); |
||||
} |
||||
|
||||
get guestEmail() { |
||||
return this._guestEmail.get(); |
||||
} |
||||
|
||||
get room() { |
||||
return this._room.get(); |
||||
} |
||||
|
||||
get registrationFormMessage() { |
||||
return this._registrationFormMessage.get(); |
||||
} |
||||
|
||||
set online(value) { |
||||
this._online.set(value); |
||||
} |
||||
|
||||
set title(value) { |
||||
this._title.set(value); |
||||
} |
||||
|
||||
set registrationForm(value) { |
||||
this._registrationForm.set(value); |
||||
} |
||||
|
||||
set showSwitchDepartmentForm(value) { |
||||
this._showSwitchDepartmentForm.set(value); |
||||
} |
||||
|
||||
set allowSwitchingDepartments(value) { |
||||
this._allowSwitchingDepartments.set(value); |
||||
} |
||||
|
||||
set offlineMessage(value) { |
||||
this._offlineMessage.set(value); |
||||
} |
||||
|
||||
set offlineUnavailableMessage(value) { |
||||
this._offlineUnavailableMessage.set(value); |
||||
} |
||||
|
||||
set displayOfflineForm(value) { |
||||
this._displayOfflineForm.set(value); |
||||
} |
||||
|
||||
set offlineSuccessMessage(value) { |
||||
this._offlineSuccessMessage.set(value); |
||||
} |
||||
|
||||
set customColor(value) { |
||||
this._customColor.set(value); |
||||
} |
||||
|
||||
set onlineColor(value) { |
||||
this._onlineColor.set(value); |
||||
} |
||||
|
||||
set offlineColor(value) { |
||||
this._offlineColor.set(value); |
||||
} |
||||
|
||||
set customFontColor(value) { |
||||
this._customFontColor.set(value); |
||||
} |
||||
|
||||
set onlineFontColor(value) { |
||||
this._onlineFontColor.set(value); |
||||
} |
||||
|
||||
set offlineFontColor(value) { |
||||
this._offlineFontColor.set(value); |
||||
} |
||||
|
||||
set videoCall(value) { |
||||
this._videoCall.set(value); |
||||
} |
||||
|
||||
set fileUpload(value) { |
||||
this._fileUpload.set(value); |
||||
} |
||||
|
||||
set transcriptMessage(value) { |
||||
this._transcriptMessage.set(value); |
||||
} |
||||
|
||||
set conversationFinishedMessage(value) { |
||||
this._conversationFinishedMessage.set(value); |
||||
} |
||||
|
||||
set nameFieldRegistrationForm(value) { |
||||
this._nameFieldRegistrationForm.set(value); |
||||
} |
||||
|
||||
set emailFieldRegistrationForm(value) { |
||||
this._emailFieldRegistrationForm.set(value); |
||||
} |
||||
|
||||
set connecting(value) { |
||||
this._connecting.set(value); |
||||
} |
||||
|
||||
set room(roomId) { |
||||
this._room.set(roomId); |
||||
} |
||||
|
||||
set department(departmentId) { |
||||
const dept = Department.findOne({ _id: departmentId }) || Department.findOne({ name: departmentId }); |
||||
this._department.set(dept && dept._id); |
||||
} |
||||
|
||||
set agent(agentData) { |
||||
this._agent.set(agentData); |
||||
} |
||||
|
||||
set guestName(name) { |
||||
return this._guestName.set(name); |
||||
} |
||||
|
||||
set guestEmail(email) { |
||||
return this._guestEmail.set(email); |
||||
} |
||||
|
||||
set registrationFormMessage(value) { |
||||
this._registrationFormMessage.set(value); |
||||
} |
||||
|
||||
ready() { |
||||
this._ready.set(true); |
||||
} |
||||
|
||||
isReady() { |
||||
return this._ready.get(); |
||||
} |
||||
|
||||
setWidgetOpened() { |
||||
return this._widgetOpened.set(true); |
||||
} |
||||
|
||||
setWidgetClosed() { |
||||
return this._widgetOpened.set(false); |
||||
} |
||||
|
||||
isWidgetOpened() { |
||||
return this._widgetOpened.get(); |
||||
} |
||||
}(); |
||||
@ -1,6 +0,0 @@ |
||||
import Autolinker from 'autolinker'; |
||||
|
||||
this.livechatAutolinker = new Autolinker({ |
||||
twitter: false, |
||||
phone: false, |
||||
}); |
||||
@ -1,282 +0,0 @@ |
||||
/* globals MsgTyping, showError, Livechat */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Random } from 'meteor/random'; |
||||
import _ from 'underscore'; |
||||
import s from 'underscore.string'; |
||||
import toastr from 'toastr'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
this.ChatMessages = class ChatMessages { |
||||
init(node) { |
||||
this.editing = {}; |
||||
|
||||
// this.messageMaxSize = RocketChat.settings.get('Message_MaxAllowedSize')
|
||||
this.wrapper = $(node).find('.wrapper'); |
||||
this.input = $(node).find('.input-message').get(0); |
||||
// this.bindEvents()
|
||||
} |
||||
|
||||
resize() { |
||||
const dif = 60 + $('.messages-container').find('footer').outerHeight(); |
||||
return $('.messages-box').css({ |
||||
height: `calc(100% - ${ dif }px)`, |
||||
}); |
||||
} |
||||
|
||||
toPrevMessage() { |
||||
const msgs = this.wrapper.get(0).querySelectorAll('.own:not(.system)'); |
||||
if (msgs.length) { |
||||
if (this.editing.element) { |
||||
if (msgs[this.editing.index - 1]) { |
||||
this.edit(msgs[this.editing.index - 1], this.editing.index - 1); |
||||
} |
||||
} else { |
||||
this.edit(msgs[msgs.length - 1], msgs.length - 1); |
||||
} |
||||
} |
||||
} |
||||
|
||||
toNextMessage() { |
||||
if (this.editing.element) { |
||||
const msgs = this.wrapper.get(0).querySelectorAll('.own:not(.system)'); |
||||
if (msgs[this.editing.index + 1]) { |
||||
this.edit(msgs[this.editing.index + 1], this.editing.index + 1); |
||||
} else { |
||||
this.clearEditing(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
getEditingIndex(element) { |
||||
const msgs = this.wrapper.get(0).querySelectorAll('.own:not(.system)'); |
||||
let index = 0; |
||||
for (const msg of Array.from(msgs)) { |
||||
if (msg === element) { |
||||
return index; |
||||
} |
||||
index++; |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
edit(element, index) { |
||||
if (element.classList.contains('system')) { |
||||
return; |
||||
} |
||||
this.clearEditing(); |
||||
const id = element.getAttribute('id'); |
||||
const message = ChatMessage.findOne({ _id: id, 'u._id': visitor.getId() }); |
||||
this.input.value = message.msg; |
||||
this.editing.element = element; |
||||
this.editing.index = index || this.getEditingIndex(element); |
||||
this.editing.id = id; |
||||
element.classList.add('editing'); |
||||
this.input.classList.add('editing'); |
||||
setTimeout(() => { |
||||
this.input.focus(); |
||||
}, 5); |
||||
} |
||||
|
||||
clearEditing() { |
||||
if (this.editing.element) { |
||||
this.editing.element.classList.remove('editing'); |
||||
this.input.classList.remove('editing'); |
||||
this.editing.id = null; |
||||
this.editing.element = null; |
||||
this.editing.index = null; |
||||
this.input.value = this.editing.saved || ''; |
||||
} else { |
||||
this.editing.saved = this.input.value; |
||||
} |
||||
} |
||||
|
||||
send(rid, input) { |
||||
if (s.trim(input.value) === '') { |
||||
return; |
||||
} |
||||
if (this.isMessageTooLong(input)) { |
||||
return toastr.error(t('Message_too_long')); |
||||
} |
||||
// KonchatNotification.removeRoomNotification(rid)
|
||||
const msg = input.value; |
||||
input.value = ''; |
||||
if (!rid) { |
||||
rid = visitor.getRoom(true); |
||||
} |
||||
|
||||
const sendMessage = () => { |
||||
const msgObject = { |
||||
_id: Random.id(), |
||||
rid, |
||||
msg, |
||||
token: visitor.getToken(), |
||||
}; |
||||
MsgTyping.stop(rid); |
||||
|
||||
let agent; |
||||
const currentAgent = !visitor.roomSubscribed && Livechat.agent; |
||||
if (currentAgent) { |
||||
agent = { |
||||
agentId: currentAgent._id, |
||||
username: currentAgent.username, |
||||
}; |
||||
} |
||||
|
||||
Meteor.call('sendMessageLivechat', msgObject, agent, (error, result) => { |
||||
if (error) { |
||||
ChatMessage.update(msgObject._id, { $set: { error: true } }); |
||||
showError(error.reason); |
||||
} |
||||
|
||||
Livechat.room = result.rid; |
||||
|
||||
if (result && result.rid && !visitor.isSubscribed(result.rid)) { |
||||
Livechat.connecting = result.showConnecting; |
||||
ChatMessage.update(result._id, _.omit(result, '_id')); |
||||
|
||||
visitor.setConnected(); |
||||
|
||||
parentCall('callback', 'chat-started'); |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
if (!visitor.getId() || visitor.getDepartment() !== Livechat.department) { |
||||
const guest = { |
||||
token: visitor.getToken(), |
||||
}; |
||||
|
||||
if (Livechat.department) { |
||||
guest.department = Livechat.department; |
||||
} |
||||
|
||||
if (Livechat.guestName) { |
||||
guest.name = Livechat.guestName; |
||||
} |
||||
|
||||
if (Livechat.guestEmail) { |
||||
guest.email = Livechat.guestEmail; |
||||
} |
||||
|
||||
Meteor.call('livechat:registerGuest', guest, (error, result) => { |
||||
if (error) { |
||||
return showError(error.reason); |
||||
} |
||||
|
||||
visitor.setId(result.userId); |
||||
visitor.setData(result.visitor); |
||||
|
||||
sendMessage(); |
||||
}); |
||||
} else { |
||||
sendMessage(); |
||||
} |
||||
} |
||||
|
||||
deleteMsg(message) { |
||||
Meteor.call('deleteMessage', message, (error) => { |
||||
if (error) { |
||||
return handleError(error); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
update(id, rid, input) { |
||||
if (s.trim(input.value) !== '') { |
||||
const msg = input.value; |
||||
Meteor.call('updateMessage', { id, msg }); |
||||
this.clearEditing(); |
||||
MsgTyping.stop(rid); |
||||
} |
||||
} |
||||
|
||||
startTyping(rid, input) { |
||||
if (s.trim(input.value) !== '') { |
||||
MsgTyping.start(rid); |
||||
} else { |
||||
MsgTyping.stop(rid); |
||||
} |
||||
} |
||||
|
||||
bindEvents() { |
||||
if (this.wrapper && this.wrapper.length) { |
||||
$('.input-message').autogrow({ |
||||
postGrowCallback: () => { |
||||
this.resize(); |
||||
}, |
||||
}); |
||||
} |
||||
} |
||||
|
||||
keyup(rid, event) { |
||||
let i; |
||||
const input = event.currentTarget; |
||||
const k = event.which; |
||||
const keyCodes = [ |
||||
13, // Enter
|
||||
20, // Caps lock
|
||||
16, // Shift
|
||||
9, // Tab
|
||||
27, // Escape Key
|
||||
17, // Control Key
|
||||
91, // Windows Command Key
|
||||
19, // Pause Break
|
||||
18, // Alt Key
|
||||
93, // Right Click Point Key
|
||||
45, // Insert Key
|
||||
34, // Page Down
|
||||
35, // Page Up
|
||||
144, // Num Lock
|
||||
145, // Scroll Lock
|
||||
]; |
||||
for (i = 35; i <= 40; i++) { keyCodes.push(i); } // Home, End, Arrow Keys
|
||||
for (i = 112; i <= 123; i++) { keyCodes.push(i); } // F1 - F12
|
||||
|
||||
if (!Array.from(keyCodes).includes(k)) { |
||||
this.startTyping(rid, input); |
||||
} |
||||
} |
||||
|
||||
keydown(rid, event) { |
||||
const input = event.currentTarget; |
||||
const k = event.which; |
||||
this.resize(input); |
||||
if (k === 13 && !event.shiftKey && !event.ctrlKey && !event.altKey) { // Enter without shift/ctrl/alt
|
||||
event.preventDefault(); |
||||
event.stopPropagation(); |
||||
if (this.editing.id) { |
||||
this.update(this.editing.id, rid, input); |
||||
} else { |
||||
this.send(rid, input); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
if (k === 27) { |
||||
if (this.editing.id) { |
||||
event.preventDefault(); |
||||
event.stopPropagation(); |
||||
this.clearEditing(); |
||||
} |
||||
// else if k is 38 or k is 40 # Arrow Up or down
|
||||
// if k is 38
|
||||
// return if input.value.slice(0, input.selectionStart).match(/[\n]/) isnt null
|
||||
// this.toPrevMessage()
|
||||
// else
|
||||
// return if input.value.slice(input.selectionEnd, input.value.length).match(/[\n]/) isnt null
|
||||
// this.toNextMessage()
|
||||
|
||||
// event.preventDefault()
|
||||
// event.stopPropagation()
|
||||
|
||||
// ctrl (command) + shift + k -> clear room messages
|
||||
} else if (k === 75 && ((navigator.platform.indexOf('Mac') !== -1 && event.metaKey && event.shiftKey) || (navigator.platform.indexOf('Mac') === -1 && event.ctrlKey && event.shiftKey))) { |
||||
RoomHistoryManager.clear(rid); |
||||
} |
||||
} |
||||
|
||||
isMessageTooLong(input) { |
||||
return input && input.value.length > this.messageMaxSize; |
||||
} |
||||
}; |
||||
@ -1,4 +0,0 @@ |
||||
import { Mongo } from 'meteor/mongo'; |
||||
|
||||
this.ChatMessage = new Mongo.Collection(null); |
||||
this.Department = new Mongo.Collection(null); |
||||
@ -1,65 +0,0 @@ |
||||
/* globals LivechatVideoCall, Livechat */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Blaze } from 'meteor/blaze'; |
||||
import { Template } from 'meteor/templating'; |
||||
import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; |
||||
import swal from 'sweetalert2'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
// Functions to call on messages of type 'command'
|
||||
this.Commands = { |
||||
survey() { |
||||
if (!$('body #survey').length) { |
||||
Blaze.render(Template.survey, $('body').get(0)); |
||||
} |
||||
}, |
||||
|
||||
endCall() { |
||||
LivechatVideoCall.finish(); |
||||
}, |
||||
|
||||
promptTranscript() { |
||||
if (Livechat.transcript) { |
||||
const visitorData = visitor.getData(); |
||||
const email = visitorData && visitorData.visitorEmails && visitorData.visitorEmails.length > 0 ? visitorData.visitorEmails[0].address : ''; |
||||
const transcriptMessage = Livechat.transcriptMessage ? Livechat.transcriptMessage : TAPi18n.__('Would_you_like_a_copy_if_this_chat_emailed'); |
||||
|
||||
swal({ |
||||
title: t('Chat_ended'), |
||||
text: transcriptMessage, |
||||
input: 'email', |
||||
inputValue: email, |
||||
inputPlaceholder: t('Type_your_email'), |
||||
showCancelButton: true, |
||||
cancelButtonText: t('no'), |
||||
confirmButtonText: t('yes'), |
||||
}).then((result) => { |
||||
if ((typeof result.value === 'boolean') && !result.value) { |
||||
return true; |
||||
} |
||||
|
||||
if (!result.value || result.value.trim() === '') { |
||||
swal.showValidationError(t('please enter your email')); |
||||
return false; |
||||
} |
||||
|
||||
Meteor.call('livechat:sendTranscript', visitor.getToken(), visitor.getRoom(), result.value, (err) => { |
||||
if (err) { |
||||
console.error(err); |
||||
} |
||||
swal({ |
||||
title: t('transcript_sent'), |
||||
type: 'success', |
||||
timer: 1000, |
||||
showConfirmButton: false, |
||||
}); |
||||
}); |
||||
}); |
||||
} |
||||
}, |
||||
|
||||
connected() { |
||||
Livechat.connecting = false; |
||||
}, |
||||
}; |
||||
@ -1,7 +0,0 @@ |
||||
this.showError = (msg) => { |
||||
$('.error').addClass('show').find('span').html(msg); |
||||
}; |
||||
|
||||
this.hideError = () => { |
||||
$('.error').removeClass('show'); |
||||
}; |
||||
@ -1,91 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
import visitor from '../../../imports/client/visitor'; |
||||
|
||||
this.Notifications = new class { |
||||
constructor(...args) { |
||||
this.logged = visitor.getId() !== null; |
||||
this.loginCb = []; |
||||
Tracker.autorun(() => { |
||||
if (visitor.getId() !== null && this.logged === false) { |
||||
this.loginCb.forEach((cb) => cb()); |
||||
} |
||||
this.logged = visitor.getId() !== null; |
||||
}); |
||||
this.debug = false; |
||||
this.streamAll = new Meteor.Streamer('notify-all'); |
||||
this.streamLogged = new Meteor.Streamer('notify-logged'); |
||||
this.streamRoom = new Meteor.Streamer('notify-room'); |
||||
this.streamRoomUsers = new Meteor.Streamer('notify-room-users'); |
||||
this.streamUser = new Meteor.Streamer('notify-user'); |
||||
if (this.debug === true) { |
||||
this.onAll(function() { |
||||
return console.log('RocketChat.Notifications: onAll', args); |
||||
}); |
||||
this.onUser(function() { |
||||
return console.log('RocketChat.Notifications: onAll', args); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
onLogin(cb) { |
||||
this.loginCb.push(cb); |
||||
if (this.logged) { |
||||
return cb(); |
||||
} |
||||
} |
||||
|
||||
notifyRoom(room, eventName, ...args) { |
||||
if (this.debug === true) { |
||||
console.log('RocketChat.Notifications: notifyRoom', room, eventName, ...args); |
||||
} |
||||
args.unshift(`${ room }/${ eventName }`); |
||||
return this.streamRoom.emit.apply(this.streamRoom, args); |
||||
} |
||||
|
||||
notifyUser(userId, eventName, ...args) { |
||||
if (this.debug === true) { |
||||
console.log('RocketChat.Notifications: notifyUser', userId, eventName, ...args); |
||||
} |
||||
args.unshift(`${ userId }/${ eventName }`); |
||||
return this.streamUser.emit.apply(this.streamUser, args); |
||||
} |
||||
|
||||
onAll(eventName, callback) { |
||||
return this.streamAll.on(eventName, { token: visitor.getToken() }, callback); |
||||
} |
||||
|
||||
onLogged(eventName, callback) { |
||||
return this.onLogin(() => this.streamLogged.on(eventName, { token: visitor.getToken() }, callback)); |
||||
} |
||||
|
||||
onRoom(room, eventName, callback) { |
||||
if (this.debug === true) { |
||||
this.streamRoom.on(room, { token: visitor.getToken() }, function() { |
||||
return console.log(`RocketChat.Notifications: onRoom ${ room }`, room, eventName, callback); |
||||
}); |
||||
} |
||||
return this.streamRoom.on(`${ room }/${ eventName }`, { token: visitor.getToken() }, callback); |
||||
} |
||||
|
||||
onUser(eventName, callback) { |
||||
return this.streamUser.on(`${ visitor.getId() }/${ eventName }`, { token: visitor.getToken() }, callback); |
||||
} |
||||
|
||||
unAll(callback) { |
||||
return this.streamAll.removeListener('notify', callback); |
||||
} |
||||
|
||||
unLogged(callback) { |
||||
return this.streamLogged.removeListener('notify', callback); |
||||
} |
||||
|
||||
unRoom(room, eventName, callback) { |
||||
return this.streamRoom.removeListener(`${ room }/${ eventName }`, callback); |
||||
} |
||||
|
||||
unUser(eventName, callback) { |
||||
return this.streamUser.removeListener(`${ visitor.getId() }/${ eventName }`, callback); |
||||
} |
||||
}(); |
||||
@ -1,238 +0,0 @@ |
||||
/* globals readMessage UserRoles RoomRoles*/ |
||||
|
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Blaze } from 'meteor/blaze'; |
||||
import _ from 'underscore'; |
||||
|
||||
import visitor from '../../../imports/client/visitor'; |
||||
|
||||
export const RoomHistoryManager = new class { |
||||
constructor() { |
||||
this.defaultLimit = 50; |
||||
this.histories = {}; |
||||
} |
||||
|
||||
getRoom(rid) { |
||||
if (this.histories[rid] == null) { |
||||
this.histories[rid] = { |
||||
hasMore: new ReactiveVar(true), |
||||
hasMoreNext: new ReactiveVar(false), |
||||
isLoading: new ReactiveVar(false), |
||||
unreadNotLoaded: new ReactiveVar(0), |
||||
firstUnread: new ReactiveVar(), |
||||
loaded: undefined, |
||||
}; |
||||
} |
||||
|
||||
return this.histories[rid]; |
||||
} |
||||
|
||||
getMore(rid, limit) { |
||||
if (limit == null) { limit = this.defaultLimit; } |
||||
const room = this.getRoom(rid); |
||||
if (room.hasMore.curValue !== true) { |
||||
return; |
||||
} |
||||
|
||||
room.isLoading.set(true); |
||||
|
||||
// $('.messages-box .wrapper').data('previous-height', $('.messages-box .wrapper').get(0)?.scrollHeight - $('.messages-box .wrapper').get(0)?.scrollTop)
|
||||
// ScrollListener.setLoader true
|
||||
const lastMessage = ChatMessage.findOne({ rid }, { fields: { ts: 1 }, sort: { ts: 1 } }); |
||||
// lastMessage ?= ChatMessage.findOne({rid: rid}, {sort: {ts: 1}})
|
||||
|
||||
let ts; |
||||
if (lastMessage) { |
||||
ts = lastMessage.ts; |
||||
} else { |
||||
ts = new Date(); |
||||
} |
||||
|
||||
Meteor.call('livechat:loadHistory', { token: visitor.getToken(), rid, ts, limit }, (err, result) => { |
||||
if (err) { |
||||
return; |
||||
} |
||||
|
||||
if (result && result.messages) { |
||||
result.messages.forEach((item) => { |
||||
if (item.t !== 'command') { |
||||
ChatMessage.upsert({ _id: item._id }, item); |
||||
} |
||||
}); |
||||
room.isLoading.set(false); |
||||
room.loaded += result.messages.length; |
||||
if (result.messages.length < limit) { |
||||
room.hasMore.set(false); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
getMoreNext(rid, limit) { |
||||
if (limit == null) { limit = this.defaultLimit; } |
||||
const room = this.getRoom(rid); |
||||
if (room.hasMoreNext.curValue !== true) { |
||||
return; |
||||
} |
||||
|
||||
const instance = Blaze.getView($('.messages-box .wrapper')[0]).templateInstance(); |
||||
instance.atBottom = false; |
||||
|
||||
room.isLoading.set(true); |
||||
|
||||
const lastMessage = ChatMessage.findOne({ rid }, { sort: { ts: -1 } }); |
||||
|
||||
let typeName = undefined; |
||||
|
||||
const subscription = ChatSubscription.findOne({ rid }); |
||||
if (subscription != null) { |
||||
// const { ls } = subscription;
|
||||
typeName = subscription.t + subscription.name; |
||||
} else { |
||||
const curRoomDoc = ChatRoom.findOne({ _id: rid }); |
||||
typeName = (curRoomDoc != null ? curRoomDoc.t : undefined) + (curRoomDoc != null ? curRoomDoc.name : undefined); |
||||
} |
||||
|
||||
const { ts } = lastMessage; |
||||
|
||||
if (ts) { |
||||
return Meteor.call('loadNextMessages', rid, ts, limit, function(err, result) { |
||||
for (const item of Array.from((result != null ? result.messages : undefined) || [])) { |
||||
if (item.t !== 'command') { |
||||
const roles = [ |
||||
(item.u && item.u._id && UserRoles.findOne(item.u._id, { fields: { roles: 1 } })) || {}, |
||||
(item.u && item.u._id && RoomRoles.findOne({ rid: item.rid, 'u._id': item.u._id })) || {}, |
||||
].map((e) => e.roles); |
||||
item.roles = _.union.apply(_.union, roles); |
||||
ChatMessage.upsert({ _id: item._id }, item); |
||||
} |
||||
} |
||||
|
||||
Meteor.defer(() => RoomManager.updateMentionsMarksOfRoom(typeName)); |
||||
|
||||
room.isLoading.set(false); |
||||
if (room.loaded == null) { room.loaded = 0; } |
||||
|
||||
room.loaded += result.messages.length; |
||||
if (result.messages.length < limit) { |
||||
room.hasMoreNext.set(false); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
||||
getSurroundingMessages(message, limit) { |
||||
if (limit == null) { limit = this.defaultLimit; } |
||||
if (!(message != null ? message.rid : undefined)) { |
||||
return; |
||||
} |
||||
|
||||
const instance = Blaze.getView($('.messages-box .wrapper')[0]).templateInstance(); |
||||
|
||||
if (ChatMessage.findOne(message._id)) { |
||||
const wrapper = $('.messages-box .wrapper'); |
||||
const msgElement = $(`#${ message._id }`, wrapper); |
||||
const pos = (wrapper.scrollTop() + msgElement.offset().top) - (wrapper.height() / 2); |
||||
wrapper.animate({ |
||||
scrollTop: pos, |
||||
}, 500); |
||||
msgElement.addClass('highlight'); |
||||
|
||||
setTimeout(function() { |
||||
const messages = wrapper[0]; |
||||
instance.atBottom = messages.scrollTop >= (messages.scrollHeight - messages.clientHeight); |
||||
}); |
||||
|
||||
return setTimeout(() => msgElement.removeClass('highlight'), 500); |
||||
} |
||||
const room = this.getRoom(message.rid); |
||||
room.isLoading.set(true); |
||||
ChatMessage.remove({ rid: message.rid }); |
||||
|
||||
let typeName = undefined; |
||||
|
||||
const subscription = ChatSubscription.findOne({ rid: message.rid }); |
||||
if (subscription) { |
||||
// const { ls } = subscription;
|
||||
typeName = subscription.t + subscription.name; |
||||
} else { |
||||
const curRoomDoc = ChatRoom.findOne({ _id: message.rid }); |
||||
typeName = (curRoomDoc != null ? curRoomDoc.t : undefined) + (curRoomDoc != null ? curRoomDoc.name : undefined); |
||||
} |
||||
|
||||
return Meteor.call('loadSurroundingMessages', message, limit, function(err, result) { |
||||
for (const item of Array.from((result != null ? result.messages : undefined) || [])) { |
||||
if (item.t !== 'command') { |
||||
const roles = [ |
||||
(item.u && item.u._id && UserRoles.findOne(item.u._id, { fields: { roles: 1 } })) || {}, |
||||
(item.u && item.u._id && RoomRoles.findOne({ rid: item.rid, 'u._id': item.u._id })) || {}, |
||||
].map((e) => e.roles); |
||||
item.roles = _.union.apply(_.union, roles); |
||||
ChatMessage.upsert({ _id: item._id }, item); |
||||
} |
||||
} |
||||
|
||||
Meteor.defer(function() { |
||||
readMessage.refreshUnreadMark(message.rid, true); |
||||
RoomManager.updateMentionsMarksOfRoom(typeName); |
||||
const wrapper = $('.messages-box .wrapper'); |
||||
const msgElement = $(`#${ message._id }`, wrapper); |
||||
const pos = (wrapper.scrollTop() + msgElement.offset().top) - (wrapper.height() / 2); |
||||
wrapper.animate({ |
||||
scrollTop: pos, |
||||
}, 500); |
||||
|
||||
msgElement.addClass('highlight'); |
||||
|
||||
setTimeout(function() { |
||||
room.isLoading.set(false); |
||||
const messages = wrapper[0]; |
||||
instance.atBottom = !result.moreAfter && (messages.scrollTop >= (messages.scrollHeight - messages.clientHeight)); |
||||
return 500; |
||||
}); |
||||
|
||||
return setTimeout(() => msgElement.removeClass('highlight'), 500); |
||||
}); |
||||
if (room.loaded == null) { room.loaded = 0; } |
||||
room.loaded += result.messages.length; |
||||
room.hasMore.set(result.moreBefore); |
||||
return room.hasMoreNext.set(result.moreAfter); |
||||
}); |
||||
} |
||||
|
||||
hasMore(rid) { |
||||
const room = this.getRoom(rid); |
||||
return room.hasMore.get(); |
||||
} |
||||
|
||||
hasMoreNext(rid) { |
||||
const room = this.getRoom(rid); |
||||
return room.hasMoreNext.get(); |
||||
} |
||||
|
||||
|
||||
getMoreIfIsEmpty(rid) { |
||||
const room = this.getRoom(rid); |
||||
|
||||
if (room.loaded === undefined) { |
||||
return this.getMore(rid); |
||||
} |
||||
} |
||||
|
||||
|
||||
isLoading(rid) { |
||||
const room = this.getRoom(rid); |
||||
return room.isLoading.get(); |
||||
} |
||||
|
||||
clear(rid) { |
||||
ChatMessage.remove({ rid }); |
||||
if (this.histories[rid] != null) { |
||||
this.histories[rid].hasMore.set(true); |
||||
this.histories[rid].isLoading.set(false); |
||||
this.histories[rid].loaded = undefined; |
||||
} |
||||
} |
||||
}(); |
||||
this.RoomHistoryManager = RoomHistoryManager; |
||||
@ -1,24 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Session } from 'meteor/session'; |
||||
|
||||
this.getAvatarUrlFromUsername = (username) => { |
||||
const key = `avatar_random_${ username }`; |
||||
const random = Session.keys[key] || 0; |
||||
if (!username) { |
||||
return; |
||||
} |
||||
|
||||
return Meteor.absoluteUrl(`/avatar/${ username }?_dc=${ random }`); |
||||
}; |
||||
|
||||
this.updateAvatarOfUsername = (username) => { |
||||
const key = `avatar_random_${ username }`; |
||||
Session.set(key, Math.round(Math.random() * 1000)); |
||||
|
||||
Object.keys(RoomManager.openedRooms).forEach((key) => { |
||||
const room = RoomManager.openedRooms[key]; |
||||
const url = getAvatarUrlFromUsername(username); |
||||
$(room.dom).find(`.message[data-username='${ username }'] .avatar-image`).css('background-image', `url(${ url })`); |
||||
}); |
||||
return true; |
||||
}; |
||||
@ -1,102 +0,0 @@ |
||||
/* globals CustomFields, Livechat */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Random } from 'meteor/random'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
const api = { |
||||
pageVisited(info) { |
||||
if (info.change === 'url') { |
||||
Triggers.processRequest(info); |
||||
} |
||||
|
||||
Meteor.call('livechat:pageVisited', visitor.getToken(), visitor.getRoom(), info); |
||||
}, |
||||
|
||||
setCustomField(key, value, overwrite = true) { |
||||
CustomFields.setCustomField(visitor.getToken(), key, value, overwrite); |
||||
}, |
||||
|
||||
setTheme(theme) { |
||||
if (theme.color) { |
||||
Livechat.customColor = theme.color; |
||||
} |
||||
if (theme.fontColor) { |
||||
Livechat.customFontColor = theme.fontColor; |
||||
} |
||||
}, |
||||
|
||||
setDepartment(department) { |
||||
Livechat.department = department; |
||||
}, |
||||
|
||||
clearDepartment() { |
||||
Livechat.department = null; |
||||
}, |
||||
|
||||
widgetOpened() { |
||||
Livechat.setWidgetOpened(); |
||||
}, |
||||
|
||||
widgetClosed() { |
||||
Livechat.setWidgetClosed(); |
||||
}, |
||||
|
||||
setGuestToken(token) { |
||||
visitor.setToken(token); |
||||
}, |
||||
|
||||
setGuestName(name) { |
||||
visitor.setName(name); |
||||
}, |
||||
|
||||
setGuestEmail(email) { |
||||
visitor.setEmail(email); |
||||
}, |
||||
|
||||
registerGuest(data) { |
||||
if (typeof data !== 'object') { |
||||
return; |
||||
} |
||||
|
||||
if (!data.token) { |
||||
data.token = Random.id(); |
||||
} |
||||
|
||||
if (data.department) { |
||||
api.setDepartment(data.department); |
||||
} |
||||
|
||||
Meteor.call('livechat:registerGuest', data, function(error, result) { |
||||
if (!error) { |
||||
visitor.reset(); |
||||
} |
||||
|
||||
if (result && result.visitor && result.visitor.token) { |
||||
visitor.setToken(result.visitor.token); |
||||
visitor.setId(result.userId); |
||||
visitor.setData(result.visitor); |
||||
} |
||||
}); |
||||
}, |
||||
}; |
||||
|
||||
window.addEventListener('message', function(msg) { |
||||
if (typeof msg.data === 'object' && msg.data.src !== undefined && msg.data.src === 'rocketchat') { |
||||
if (api[msg.data.fn] !== undefined && typeof api[msg.data.fn] === 'function') { |
||||
const args = [].concat(msg.data.args || []); |
||||
api[msg.data.fn].apply(null, args); |
||||
} |
||||
} |
||||
}, false); |
||||
|
||||
// tell parent window that we are ready
|
||||
Meteor.startup(function() { |
||||
Tracker.autorun((c) => { |
||||
if (Livechat.isReady()) { |
||||
parentCall('ready'); |
||||
c.stop(); |
||||
} |
||||
}); |
||||
}); |
||||
@ -1,90 +0,0 @@ |
||||
/* globals Notifications, Livechat */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
import _ from 'underscore'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
export const MsgTyping = (function() { |
||||
const timeout = 15000; |
||||
const timeouts = {}; |
||||
let renew = true; |
||||
const renewTimeout = 10000; |
||||
const selfTyping = new ReactiveVar(false); |
||||
const usersTyping = {}; |
||||
const dep = new Tracker.Dependency(); |
||||
let oldRoom; |
||||
|
||||
const addStream = function(room) { |
||||
if (!_.isEmpty(usersTyping[room] && usersTyping[room].users)) { |
||||
return; |
||||
} |
||||
usersTyping[room] = { users: {} }; |
||||
return Notifications.onRoom(room, 'typing', function(username, typing/* , extraData*/) { |
||||
const user = Meteor.user(); |
||||
if (username === (user && user.username)) { |
||||
return; |
||||
} |
||||
const { users } = usersTyping[room]; |
||||
if (typing === true) { |
||||
users[username] = Meteor.setTimeout(function() { |
||||
delete users[username]; |
||||
usersTyping[room].users = users; |
||||
return dep.changed(); |
||||
}, timeout); |
||||
} else { |
||||
delete users[username]; |
||||
} |
||||
usersTyping[room].users = users; |
||||
return dep.changed(); |
||||
}); |
||||
}; |
||||
|
||||
Tracker.autorun(() => { |
||||
if (Livechat.room && visitor.getId()) { |
||||
if (oldRoom) { |
||||
Notifications.unRoom(oldRoom, 'typing'); |
||||
} |
||||
addStream(Livechat.room); |
||||
oldRoom = Livechat.room; |
||||
} |
||||
}); |
||||
|
||||
const stop = function(room) { |
||||
renew = true; |
||||
selfTyping.set(false); |
||||
if (timeouts && timeouts[room]) { |
||||
clearTimeout(timeouts[room]); |
||||
timeouts[room] = null; |
||||
} |
||||
const visitorData = visitor.getData(); |
||||
return Notifications.notifyRoom(room, 'typing', visitorData && visitorData.username, false, { token: visitor.getToken() }); |
||||
}; |
||||
const start = function(room) { |
||||
if (!renew) { return; } |
||||
|
||||
setTimeout(() => { renew = true; }, renewTimeout); |
||||
|
||||
renew = false; |
||||
selfTyping.set(true); |
||||
const visitorData = visitor.getData(); |
||||
Notifications.notifyRoom(room, 'typing', visitorData && visitorData.username, true, { token: visitor.getToken() }); |
||||
clearTimeout(timeouts[room]); |
||||
timeouts[room] = Meteor.setTimeout(() => stop(room), timeout); |
||||
return timeouts[room]; |
||||
}; |
||||
|
||||
const get = function(room) { |
||||
dep.depend(); |
||||
if (!usersTyping[room]) { |
||||
usersTyping[room] = { users: {} }; |
||||
} |
||||
const { users } = usersTyping[room]; |
||||
return _.keys(users) || []; |
||||
}; |
||||
|
||||
return { start, stop, get, selfTyping }; |
||||
}()); |
||||
|
||||
this.MsgTyping = MsgTyping; |
||||
@ -1,9 +0,0 @@ |
||||
this.parentCall = (method, args = []) => { |
||||
const data = { |
||||
src: 'rocketchat', |
||||
fn: method, |
||||
args, |
||||
}; |
||||
|
||||
window.parent.postMessage(data, '*'); |
||||
}; |
||||
@ -1,27 +0,0 @@ |
||||
import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; |
||||
import _ from 'underscore'; |
||||
|
||||
this.t = function(key, ...replaces) { |
||||
if (_.isObject(replaces[0])) { |
||||
return TAPi18n.__(key, replaces); |
||||
} |
||||
return TAPi18n.__(key, { |
||||
postProcess: 'sprintf', |
||||
sprintf: replaces, |
||||
}); |
||||
}; |
||||
|
||||
this.tr = function(key, options, ...replaces) { |
||||
if (_.isObject(replaces[0])) { |
||||
return TAPi18n.__(key, options, replaces); |
||||
} |
||||
return TAPi18n.__(key, options, { |
||||
postProcess: 'sprintf', |
||||
sprintf: replaces, |
||||
}); |
||||
}; |
||||
|
||||
this.isRtl = (lang) => { |
||||
const language = lang || localStorage.getItem('userLanguage') || 'en-US'; |
||||
return ['ar', 'dv', 'fa', 'he', 'ku', 'ps', 'sd', 'ug', 'ur', 'yi'].includes(language.split('-').shift().toLowerCase()); |
||||
}; |
||||
@ -1,183 +0,0 @@ |
||||
/* globals Livechat */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Random } from 'meteor/random'; |
||||
import { Session } from 'meteor/session'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
const firedTriggers = JSON.parse(localStorage.getItem('rocketChatFiredTriggers')) || []; |
||||
|
||||
// promise cache for multiple calls (let's say multiple triggers running before the previous finished)
|
||||
const agentCacheExpiry = 3600000; |
||||
let agentPromise; |
||||
function getAgent(triggerAction) { |
||||
if (agentPromise) { |
||||
return agentPromise; |
||||
} |
||||
agentPromise = new Promise((resolve, reject) => { |
||||
const { params } = triggerAction; |
||||
if (params.sender === 'queue') { |
||||
const cache = localStorage.getItem('triggerAgent'); |
||||
if (cache) { |
||||
const cacheAgent = JSON.parse(cache); |
||||
|
||||
// cache valid for 1h
|
||||
if (cacheAgent.ts && Date.now() - cacheAgent.ts < agentCacheExpiry) { |
||||
return resolve(cacheAgent.agent); |
||||
} |
||||
} |
||||
|
||||
Meteor.call('livechat:getNextAgent', { |
||||
token: visitor.getToken(), |
||||
department: Livechat.department, |
||||
}, (error, result) => { |
||||
if (error) { |
||||
return reject(error); |
||||
} |
||||
localStorage.setItem('triggerAgent', JSON.stringify({ |
||||
agent: result, |
||||
ts: Date.now(), |
||||
})); |
||||
|
||||
resolve(result); |
||||
}); |
||||
} else if (params.sender === 'custom') { |
||||
resolve({ |
||||
username: params.name, |
||||
}); |
||||
} else { |
||||
reject('Unknown sender'); |
||||
} |
||||
}); |
||||
|
||||
// expire the promise cache as well
|
||||
setTimeout(() => { |
||||
agentPromise = null; |
||||
}, agentCacheExpiry); |
||||
|
||||
return agentPromise; |
||||
} |
||||
|
||||
this.Triggers = (function() { |
||||
let triggers = []; |
||||
let initiated = false; |
||||
let requests = []; |
||||
let enabled = true; |
||||
|
||||
const fire = function(trigger) { |
||||
if (!enabled || visitor.getId()) { |
||||
return; |
||||
} |
||||
trigger.actions.forEach(function(action) { |
||||
if (action.name === 'send-message') { |
||||
// flag to skip the trigger if the action is 'send-message'
|
||||
trigger.skip = true; |
||||
|
||||
getAgent(action).then((agent) => { |
||||
let roomId = visitor.getRoom(); |
||||
|
||||
if (!roomId) { |
||||
roomId = Random.id(); |
||||
visitor.setRoom(roomId); |
||||
} |
||||
|
||||
Session.set('triggered', true); |
||||
ChatMessage.insert({ |
||||
msg: action.params.msg, |
||||
rid: roomId, |
||||
u: agent, |
||||
}); |
||||
|
||||
if (agent._id) { |
||||
Livechat.agent = agent; |
||||
} |
||||
|
||||
parentCall('openWidget'); |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
if (trigger.runOnce) { |
||||
trigger.skip = true; |
||||
firedTriggers.push(trigger._id); |
||||
localStorage.setItem('rocketChatFiredTriggers', JSON.stringify(firedTriggers)); |
||||
} |
||||
}; |
||||
|
||||
const processRequest = function(request) { |
||||
if (!initiated) { |
||||
return requests.push(request); |
||||
} |
||||
triggers.forEach(function(trigger) { |
||||
if (trigger.skip) { |
||||
return; |
||||
} |
||||
trigger.conditions.forEach(function(condition) { |
||||
switch (condition.name) { |
||||
case 'page-url': |
||||
if (request.location.href.match(new RegExp(condition.value))) { |
||||
fire(trigger); |
||||
} |
||||
break; |
||||
|
||||
case 'time-on-site': |
||||
if (trigger.timeout) { |
||||
clearTimeout(trigger.timeout); |
||||
} |
||||
trigger.timeout = setTimeout(function() { |
||||
fire(trigger); |
||||
}, parseInt(condition.value) * 1000); |
||||
break; |
||||
} |
||||
}); |
||||
}); |
||||
}; |
||||
|
||||
const setTriggers = function(newTriggers) { |
||||
triggers = newTriggers; |
||||
}; |
||||
|
||||
const init = function(newTriggers) { |
||||
if (initiated) { |
||||
return; |
||||
} |
||||
|
||||
initiated = true; |
||||
|
||||
if (newTriggers) { |
||||
setTriggers(newTriggers); |
||||
} |
||||
|
||||
firedTriggers.forEach((triggerId) => { |
||||
triggers.forEach((trigger) => { |
||||
if (trigger._id === triggerId) { |
||||
trigger.skip = true; |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
if (requests.length > 0 && triggers.length > 0) { |
||||
requests.forEach(function(request) { |
||||
processRequest(request); |
||||
}); |
||||
|
||||
requests = []; |
||||
} |
||||
}; |
||||
|
||||
const setDisabled = function() { |
||||
enabled = false; |
||||
}; |
||||
|
||||
const setEnabled = function() { |
||||
enabled = true; |
||||
}; |
||||
|
||||
return { |
||||
init, |
||||
processRequest, |
||||
setTriggers, |
||||
setDisabled, |
||||
setEnabled, |
||||
}; |
||||
}()); |
||||
@ -1,30 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { TimeSync } from 'meteor/mizzao:timesync'; |
||||
import s from 'underscore.string'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
Meteor.methods({ |
||||
sendMessageLivechat(message) { |
||||
if (s.trim(message.msg) !== '') { |
||||
if (isNaN(TimeSync.serverOffset())) { |
||||
message.ts = new Date(); |
||||
} else { |
||||
message.ts = new Date(Date.now() + TimeSync.serverOffset()); |
||||
} |
||||
|
||||
const user = Meteor.user(); |
||||
|
||||
message.u = { |
||||
_id: visitor.getId(), |
||||
username: (user && user.username) || 'visitor', |
||||
}; |
||||
|
||||
message.temp = true; |
||||
|
||||
// message = RocketChat.callbacks.run 'beforeSaveMessage', message
|
||||
|
||||
ChatMessage.insert(message); |
||||
} |
||||
}, |
||||
}); |
||||
@ -1,16 +0,0 @@ |
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
import { BlazeLayout } from 'meteor/kadira:blaze-layout'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
BlazeLayout.setRoot('body'); |
||||
|
||||
FlowRouter.route('/livechat', { |
||||
name: 'index', |
||||
triggersEnter: [ |
||||
() => visitor.register(), |
||||
], |
||||
action() { |
||||
BlazeLayout.render('main', { center: 'livechatWindow' }); |
||||
}, |
||||
}); |
||||
@ -1,6 +0,0 @@ |
||||
/* globals CustomFields */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
Meteor.startup(function() { |
||||
CustomFields.init(); |
||||
}); |
||||
@ -1,36 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Random } from 'meteor/random'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
Meteor.startup(() => { |
||||
if (!localStorage.getItem('rocketChatLivechat')) { |
||||
localStorage.setItem('rocketChatLivechat', Random.id()); |
||||
} else { |
||||
Tracker.autorun((c) => { |
||||
if (!visitor.getId() && visitor.getToken()) { |
||||
Meteor.call('livechat:loginByToken', visitor.getToken(), (err, result) => { |
||||
if (result && result._id) { |
||||
visitor.setId(result._id); |
||||
c.stop(); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
Meteor.startup(() => { |
||||
let connected = false; |
||||
Tracker.autorun(function() { |
||||
const connectionStatus = Meteor.status(); |
||||
if (visitor.getRoom() && visitor.getToken() && connectionStatus.connected && !connected) { |
||||
connected = connectionStatus.connected; |
||||
document.cookie = `rc_rid=${ visitor.getRoom() }; path=/`; |
||||
document.cookie = `rc_token=${ visitor.getToken() }; path=/`; |
||||
document.cookie = 'rc_room_type=l; path=/'; |
||||
visitor.setConnected(); |
||||
} |
||||
}); |
||||
}); |
||||
@ -1,933 +0,0 @@ |
||||
@import "utils/_reset.import.less"; |
||||
@import "utils/_variables.import.less"; |
||||
@import "utils/_keyframes.import.less"; |
||||
@import "utils/_loading.import.less"; |
||||
|
||||
* { |
||||
box-sizing: border-box; |
||||
-moz-box-sizing: border-box; |
||||
-webkit-box-sizing: border-box; |
||||
} |
||||
|
||||
html, |
||||
body { |
||||
height: 100%; |
||||
} |
||||
|
||||
body { |
||||
margin: 0; |
||||
font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif, "Meiryo UI"; |
||||
font-size: 0.8rem; |
||||
color: @primary-font-color; |
||||
height: 100%; |
||||
width: 100%; |
||||
-webkit-font-smoothing: antialiased; |
||||
line-height: 1rem; |
||||
padding: 0; |
||||
overflow: hidden; |
||||
position: relative; |
||||
border-top-right-radius: 5px; |
||||
border-top-left-radius: 5px; |
||||
} |
||||
|
||||
input, |
||||
select, |
||||
textarea { |
||||
font-family: inherit; |
||||
font-size: inherit; |
||||
line-height: inherit; |
||||
padding: 5px; |
||||
margin: 5px 0; |
||||
border: 1px solid #e7e7e7; |
||||
border-radius: 5px; |
||||
outline: none; |
||||
} |
||||
|
||||
button { |
||||
background: none; |
||||
border: none; |
||||
padding: 0; |
||||
text-align: left; |
||||
cursor: pointer; |
||||
text-transform: inherit; |
||||
color: inherit; |
||||
font-style: inherit; |
||||
} |
||||
|
||||
input:focus { |
||||
outline: none; |
||||
box-shadow: 0 0 0; |
||||
} |
||||
|
||||
.button { |
||||
&:extend(.unselectable); |
||||
display: inline-block; |
||||
padding: 9px 12px; |
||||
font-weight: 500; |
||||
font-size: 13px; |
||||
margin: 4px; |
||||
text-transform: uppercase; |
||||
word-spacing: 0; |
||||
box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.125); |
||||
border: none; |
||||
border-radius: 0; |
||||
line-height: 16px; |
||||
position: relative; |
||||
cursor: pointer; |
||||
color: rgba(255, 255, 255, 0.85); |
||||
background-color: lighten(desaturate(@primary-background-color, 15%), 12.5%); |
||||
|
||||
span { |
||||
position: relative; |
||||
z-index: 2; |
||||
} |
||||
|
||||
&::before { |
||||
background-color: rgba(0, 0, 0, 0.1); |
||||
content: " "; |
||||
position: absolute; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
opacity: 0; |
||||
z-index: 1; |
||||
transition: opacity 0.1s ease-out; |
||||
} |
||||
|
||||
&:hover { |
||||
text-decoration: none; |
||||
color: #ffffff; |
||||
|
||||
&::before { |
||||
opacity: 1; |
||||
} |
||||
} |
||||
|
||||
&.secondary { |
||||
background-color: @tertiary-background-color; |
||||
color: @primary-font-color; |
||||
|
||||
&::before { |
||||
background-color: rgba(0, 0, 0, 0.045); |
||||
} |
||||
} |
||||
|
||||
&.clean { |
||||
font-size: 14px; |
||||
box-shadow: 0 0 3px rgba(0, 0, 0, 0.08); |
||||
|
||||
&.primary { |
||||
font-weight: 600; |
||||
} |
||||
} |
||||
|
||||
&.button-block { |
||||
display: block; |
||||
width: 100%; |
||||
} |
||||
} |
||||
|
||||
.field-error { |
||||
border: 1px solid red; |
||||
} |
||||
|
||||
.livechat-room { |
||||
display: flex; |
||||
flex-direction: column; |
||||
height: 100%; |
||||
border-top-right-radius: inherit; |
||||
border-top-left-radius: inherit; |
||||
|
||||
&.popout { |
||||
border-top-right-radius: 0; |
||||
border-top-left-radius: 0; |
||||
} |
||||
|
||||
.title { |
||||
flex: 1 0 @header-min-height; |
||||
line-height: @header-min-height; |
||||
border-top-right-radius: inherit; |
||||
border-top-left-radius: inherit; |
||||
color: #ffffff; |
||||
z-index: 10; |
||||
padding: 0 10px; |
||||
user-select: none; |
||||
cursor: move; |
||||
|
||||
h1 { |
||||
margin: 0; |
||||
font-size: 10pt; |
||||
display: inline-block; |
||||
} |
||||
|
||||
.toolbar { |
||||
display: inline-block; |
||||
float: right; |
||||
|
||||
svg { |
||||
cursor: pointer; |
||||
fill: currentColor; |
||||
width: 14px; |
||||
margin: 0 5px; |
||||
vertical-align: middle; |
||||
|
||||
&:last-of-type { |
||||
margin-right: 0; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.header { |
||||
flex: 1 0 60px; |
||||
display: flex; |
||||
box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.2); |
||||
background-color: #fcfcfc; |
||||
color: @secondary-font-color; |
||||
z-index: 2; |
||||
|
||||
.picture { |
||||
flex: 0 1 60px; |
||||
padding: 5px 10px; |
||||
|
||||
img { |
||||
width: 50px; |
||||
height: 50px; |
||||
border-radius: 6px; |
||||
border: 1px solid @window-border-color; |
||||
} |
||||
} |
||||
|
||||
.info { |
||||
flex: 1; |
||||
padding: 5px 0; |
||||
|
||||
h2 { |
||||
color: @primary-font-color; |
||||
font-size: 14px; |
||||
} |
||||
|
||||
li { |
||||
font-size: 11px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.messages { |
||||
flex: 1 1 100%; |
||||
background-color: #ffffff; |
||||
border-left: 1px solid @window-border-color; |
||||
border-right: 1px solid @window-border-color; |
||||
overflow-y: auto; |
||||
|
||||
.wrapper { |
||||
padding-bottom: 6px; |
||||
|
||||
ul { |
||||
list-style-type: none; |
||||
padding: 0; |
||||
|
||||
li { |
||||
padding: 0; |
||||
} |
||||
} |
||||
|
||||
.message { |
||||
font-size: 12px; |
||||
padding: 8px 10px 0; |
||||
position: relative; |
||||
line-height: 18px; |
||||
min-height: 36px; |
||||
|
||||
&::after { |
||||
content: ''; |
||||
display: block; |
||||
clear: both; |
||||
} |
||||
|
||||
.content { |
||||
width: 75%; |
||||
background-color: #f3f3f3; |
||||
border: 1px solid desaturate(darken(#f3f3f3, 10%), 40%); |
||||
margin-left: 38px; |
||||
border-radius: 6px; |
||||
padding: 5px; |
||||
float: left; |
||||
word-wrap: break-word; |
||||
word-break: break-word; |
||||
-ms-hyphens: auto; |
||||
-moz-hyphens: auto; |
||||
-webkit-hyphens: auto; |
||||
hyphens: auto; |
||||
|
||||
&::before { |
||||
border-style: solid; |
||||
border-color: transparent desaturate(darken(#f3f3f3, 10%), 40%) transparent transparent; |
||||
content: " "; |
||||
height: 0; |
||||
width: 0; |
||||
font-size: 0; |
||||
pointer-events: none; |
||||
border-width: 5px; |
||||
position: absolute; |
||||
left: 38px; |
||||
} |
||||
} |
||||
|
||||
&:nth-child(1) { |
||||
margin-top: 0; |
||||
} |
||||
|
||||
&.new-day { |
||||
margin-top: 60px; |
||||
|
||||
&::before { |
||||
content: attr(data-date); |
||||
display: block; |
||||
position: absolute; |
||||
top: -30px; |
||||
left: calc(~'50% - 70px'); |
||||
font-size: 10px; |
||||
font-weight: 600; |
||||
text-align: center; |
||||
color: @secondary-font-color; |
||||
z-index: 1; |
||||
padding: 0 10px; |
||||
background-color: #ffffff; |
||||
min-width: 120px; |
||||
} |
||||
|
||||
.content { |
||||
&::after { |
||||
content: " "; |
||||
display: block; |
||||
position: absolute; |
||||
top: -20px; |
||||
left: 0; |
||||
width: 100%; |
||||
border-top: 1px solid #dddddd; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.edit-message { |
||||
display: none; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
&.own { |
||||
.content { |
||||
background-color: #feffd7; |
||||
border: 1px solid desaturate(darken(#feffd7, 10%), 40%); |
||||
float: right; |
||||
margin-right: 3px; |
||||
|
||||
&::before { |
||||
border-style: solid; |
||||
border-color: transparent transparent transparent desaturate(darken(#feffd7, 10%), 40%); |
||||
content: " "; |
||||
height: 0; |
||||
width: 0; |
||||
font-size: 0; |
||||
pointer-events: none; |
||||
border-width: 5px; |
||||
position: absolute; |
||||
right: 3px; |
||||
left: inherit; |
||||
} |
||||
} |
||||
|
||||
.thumb { |
||||
display: none; |
||||
} |
||||
} |
||||
|
||||
.delete-message { |
||||
display: none; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.user { |
||||
display: inline-block; |
||||
font-weight: 600; |
||||
color: #444444; |
||||
margin-right: 5px; |
||||
outline: none; |
||||
|
||||
&:hover { |
||||
color: #333333; |
||||
} |
||||
} |
||||
|
||||
.thumb { |
||||
position: absolute; |
||||
left: 10px; |
||||
top: 6px; |
||||
display: block; |
||||
width: 30px; |
||||
height: 30px; |
||||
} |
||||
|
||||
.info { |
||||
color: @info-font-color; |
||||
display: inline-block; |
||||
float: right; |
||||
margin: 9px -1px -5px 9px; |
||||
font-size: 9px; |
||||
text-align: right; |
||||
left: -10px; |
||||
width: 55px; |
||||
|
||||
.edited { |
||||
display: inline-block; |
||||
} |
||||
|
||||
.edit-message { |
||||
float: left; |
||||
margin-left: 1px; |
||||
} |
||||
|
||||
.delete-message { |
||||
float: left; |
||||
} |
||||
} |
||||
|
||||
&.sequential { |
||||
padding-top: 2px; |
||||
min-height: 20px; |
||||
|
||||
.user { |
||||
display: none; |
||||
} |
||||
|
||||
.thumb { |
||||
display: none; |
||||
} |
||||
} |
||||
|
||||
&.system { |
||||
.body { |
||||
color: @info-font-color; |
||||
font-style: italic; |
||||
|
||||
em { |
||||
font-weight: 600; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.avatar-initials { |
||||
line-height: 40px; |
||||
} |
||||
|
||||
a { |
||||
color: @link-font-color; |
||||
font-weight: 400; |
||||
|
||||
&:hover { |
||||
color: darken(@link-font-color, 10%); |
||||
text-decoration: underline; |
||||
} |
||||
} |
||||
|
||||
.body { |
||||
opacity: 1; |
||||
transition: opacity 1s linear; |
||||
|
||||
.inline-image { |
||||
display: inline-block; |
||||
overflow: hidden; |
||||
|
||||
border-radius: 3px; |
||||
background-repeat: no-repeat; |
||||
background-position: center left; |
||||
background-size: contain; |
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); |
||||
|
||||
line-height: 0; |
||||
|
||||
img { |
||||
max-width: 100%; |
||||
max-height: 200px; |
||||
|
||||
cursor: pointer; |
||||
|
||||
opacity: 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
&.temp .body { |
||||
opacity: 0.5; |
||||
} |
||||
|
||||
&.msg-error .body { |
||||
text-decoration: line-through; |
||||
} |
||||
|
||||
.avatar { |
||||
height: 100%; |
||||
width: 100%; |
||||
|
||||
.avatar-image { |
||||
height: 100%; |
||||
width: 100%; |
||||
min-height: 20px; |
||||
min-width: 20px; |
||||
display: block; |
||||
position: relative; |
||||
background-color: transparent; |
||||
background-size: cover; |
||||
background-repeat: no-repeat; |
||||
background-position: center; |
||||
border-radius: 4px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.new-message { |
||||
margin: 0 -65px; |
||||
position: absolute; |
||||
background: #428bca; |
||||
border-radius: 20px; |
||||
width: 130px; |
||||
height: 30px; |
||||
text-align: center; |
||||
color: #ffffff; |
||||
line-height: 30px; |
||||
font-size: 0.8em; |
||||
cursor: pointer; |
||||
bottom: 8px; |
||||
left: 50%; |
||||
z-index: 5; |
||||
transition: transform 0.3s ease-out; |
||||
transform: translateY(-40px); |
||||
|
||||
&.not { |
||||
transform: translateY(100%); |
||||
} |
||||
} |
||||
|
||||
.error { |
||||
bottom: @footer-min-height; |
||||
position: fixed; |
||||
width: 100%; |
||||
background-color: #f7d799; |
||||
padding: 5px; |
||||
z-index: 8; |
||||
transition: transform 0.2s ease-out; |
||||
transform: translateY(100%); |
||||
|
||||
&.show { |
||||
transform: translateY(0); |
||||
} |
||||
} |
||||
} |
||||
|
||||
.footer { |
||||
flex: 1 0 @footer-min-height; |
||||
z-index: 10; |
||||
background-color: #fcfcfc; |
||||
border-top: 1px solid @window-border-color; |
||||
border-left: 1px solid @window-border-color; |
||||
border-right: 1px solid @window-border-color; |
||||
|
||||
.message-bar { |
||||
display: flex; |
||||
flex-direction: row; |
||||
padding-top: 6px; |
||||
|
||||
.input-wrapper { |
||||
flex-grow: 1; |
||||
border-width: 1px; |
||||
border-radius: 4px; |
||||
margin-left: 6px; |
||||
border-color: @input-border-color; |
||||
display: flex; |
||||
align-items: center; |
||||
|
||||
textarea { |
||||
display: block; |
||||
padding: 6px 8px; |
||||
padding-right: 38px; |
||||
overflow-y: auto; |
||||
resize: none; |
||||
margin: 0; |
||||
max-height: 200px; |
||||
width: 100%; |
||||
font-size: 12px; |
||||
-webkit-appearance: none; |
||||
height: 28px; |
||||
line-height: normal; |
||||
background-color: transparent; |
||||
position: relative; |
||||
border: 0; |
||||
} |
||||
|
||||
.upload-button-box { |
||||
display: flex; |
||||
padding: 0 5px; |
||||
|
||||
svg { |
||||
width: 15px; |
||||
height: 15px; |
||||
cursor: pointer; |
||||
color: @secondary-font-color; |
||||
fill: @secondary-font-color; |
||||
|
||||
&:hover { |
||||
fill: @primary-font-color; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.buttons { |
||||
color: @secondary-font-color; |
||||
fill: @secondary-font-color; |
||||
display: flex; |
||||
align-items: center; |
||||
padding: 0 5px; |
||||
|
||||
svg { |
||||
width: 15px; |
||||
height: 15px; |
||||
margin: 0 4px; |
||||
cursor: pointer; |
||||
transition: fill 0.15s ease-out; |
||||
|
||||
&:hover { |
||||
fill: @primary-font-color; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.toggle-options { |
||||
clear: both; |
||||
color: @secondary-font-color; |
||||
margin-left: 6px; |
||||
outline: none; |
||||
margin-top: 5px; |
||||
font-size: 0.65rem; |
||||
} |
||||
|
||||
.typing { |
||||
clear: both; |
||||
color: @secondary-font-color; |
||||
margin-left: 8px; |
||||
outline: none; |
||||
margin-top: 2px; |
||||
font-size: 0.65rem; |
||||
} |
||||
|
||||
.options-menu { |
||||
min-width: 100px; |
||||
bottom: 21px; |
||||
left: 6px; |
||||
border-radius: 2px; |
||||
padding: 6px 0; |
||||
background-color: #ffffff; |
||||
color: @secondary-font-color; |
||||
box-shadow: |
||||
0 1px 1px 0 rgba(0, 0, 0, 0.2), |
||||
0 2px 10px 0 rgba(0, 0, 0, 0.16); |
||||
position: absolute; |
||||
z-index: 200; |
||||
transition: transform 0.15s ease, visibility 0.15s ease, opacity 0.15s ease; |
||||
transform: translateY(30px); |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
|
||||
&.show { |
||||
transform: translateY(0); |
||||
opacity: 1; |
||||
display: block; |
||||
visibility: visible; |
||||
} |
||||
|
||||
ul { |
||||
li { |
||||
padding: 0 13px 0 8px; |
||||
|
||||
&:hover { |
||||
background-color: #eeeeee; |
||||
} |
||||
|
||||
button { |
||||
display: block; |
||||
padding: 4px 2px; |
||||
outline: none; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.offline { |
||||
flex: 1 1 100%; |
||||
background-color: white; |
||||
padding: 1em 10px; |
||||
border-left: 1px solid @window-border-color; |
||||
border-right: 1px solid @window-border-color; |
||||
|
||||
.offline-message { |
||||
padding: 1em 0; |
||||
} |
||||
|
||||
.message-sent { |
||||
text-align: center; |
||||
} |
||||
|
||||
form { |
||||
input, |
||||
textarea { |
||||
display: block; |
||||
width: 100%; |
||||
} |
||||
|
||||
.buttons { |
||||
text-align: center; |
||||
} |
||||
|
||||
.error { |
||||
display: none; |
||||
background-color: #f7d799; |
||||
padding: 5px; |
||||
|
||||
&.show { |
||||
display: block; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.livechat-form { |
||||
flex: 1 1 100%; |
||||
display: block; |
||||
background-color: #ffffff; |
||||
border-left: 1px solid @window-border-color; |
||||
border-right: 1px solid @window-border-color; |
||||
padding: 5px; |
||||
|
||||
input, |
||||
select { |
||||
display: block; |
||||
background-color: #ffffff; |
||||
} |
||||
|
||||
.error { |
||||
display: none; |
||||
background-color: #f7d799; |
||||
padding: 5px; |
||||
|
||||
&.show { |
||||
display: block; |
||||
} |
||||
} |
||||
|
||||
form { |
||||
padding: 0 1em; |
||||
text-align: center; |
||||
|
||||
input, |
||||
select { |
||||
width: 100%; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.modal { |
||||
border-top-right-radius: inherit; |
||||
border-top-left-radius: inherit; |
||||
|
||||
.overlay { |
||||
border-top-right-radius: inherit; |
||||
border-top-left-radius: inherit; |
||||
background-color: rgba(0, 0, 0, 0.5); |
||||
position: fixed; |
||||
height: 100%; |
||||
width: 100%; |
||||
z-index: 990; |
||||
top: 0; |
||||
left: 0; |
||||
} |
||||
|
||||
.wrapper { |
||||
z-index: 999; |
||||
background: white; |
||||
position: fixed; |
||||
height: 80%; |
||||
width: 80%; |
||||
top: 15%; |
||||
left: 10%; |
||||
border-radius: 6px; |
||||
display: flex; |
||||
flex-direction: column; |
||||
|
||||
header { |
||||
flex: 1 0 40px; |
||||
padding: 0 15px; |
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1); |
||||
line-height: 40px; |
||||
white-space: nowrap; |
||||
text-overflow: ellipsis; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.content { |
||||
overflow-y: auto; |
||||
padding: 10px; |
||||
flex: 1 1 100%; |
||||
|
||||
.instructions { |
||||
margin-top: 5px; |
||||
} |
||||
|
||||
.survey-item { |
||||
margin-top: 20px; |
||||
|
||||
.question { |
||||
display: block; |
||||
} |
||||
|
||||
.answer { |
||||
margin-right: 5px; |
||||
display: inline-block; |
||||
text-align: center; |
||||
} |
||||
} |
||||
} |
||||
|
||||
footer { |
||||
flex: 1 0 60px; |
||||
border-top: 1px solid rgba(0, 0, 0, 0.1); |
||||
line-height: 60px; |
||||
text-align: right; |
||||
padding-right: 20px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.powered-by { |
||||
margin-top: -20px; |
||||
line-height: 20px; |
||||
right: 0; |
||||
z-index: 10; |
||||
text-align: right; |
||||
font-size: 0.65rem; |
||||
height: 20px; |
||||
color: #666666; |
||||
padding: 0 1em; |
||||
opacity: 0.5; |
||||
align-self: flex-end; |
||||
transition: opacity 0.15s ease-out; |
||||
|
||||
&:hover { |
||||
opacity: 1; |
||||
} |
||||
|
||||
a { |
||||
text-decoration: none; |
||||
margin-left: 1px; |
||||
|
||||
img { |
||||
height: 14px; |
||||
vertical-align: middle; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.sweet-overlay { |
||||
border-top-right-radius: inherit; |
||||
border-top-left-radius: inherit; |
||||
} |
||||
|
||||
.video-call { |
||||
position: fixed; |
||||
top: @header-min-height; |
||||
bottom: 0; |
||||
left: 0; |
||||
right: 0; |
||||
background-color: #000000; |
||||
z-index: 11; |
||||
|
||||
.video-overlay { |
||||
position: fixed; |
||||
top: @header-min-height; |
||||
bottom: 0; |
||||
left: 0; |
||||
right: 0; |
||||
z-index: 13; |
||||
|
||||
.toolbar { |
||||
position: absolute; |
||||
bottom: 40px; |
||||
width: 100%; |
||||
text-align: center; |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
transform: translateY(50px); |
||||
transition: opacity 0.175s ease-out, transform 0.175s ease-out, visibility 0.175s ease-out; |
||||
|
||||
&.visible { |
||||
opacity: 1; |
||||
visibility: visible; |
||||
transform: translateY(0); |
||||
} |
||||
|
||||
.end-call { |
||||
background-color: red; |
||||
fill: white; |
||||
border-radius: 50%; |
||||
height: 60px; |
||||
width: 60px; |
||||
text-align: center; |
||||
outline: none; |
||||
|
||||
svg { |
||||
width: 30px; |
||||
height: 30px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.container { |
||||
z-index: 12; |
||||
} |
||||
} |
||||
|
||||
.upload-preview { |
||||
.upload-preview-file { |
||||
height: 200px; |
||||
|
||||
background-repeat: no-repeat; |
||||
background-position: center center; |
||||
background-size: contain; |
||||
} |
||||
} |
||||
|
||||
@media all and(max-height: 200px) { |
||||
.livechat-room { |
||||
.title { |
||||
height: 100%; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.footer { |
||||
display: none; |
||||
} |
||||
|
||||
.messages { |
||||
display: none; |
||||
} |
||||
|
||||
.powered-by { |
||||
display: none; |
||||
} |
||||
} |
||||
} |
||||
@ -1,183 +0,0 @@ |
||||
// keyframes |
||||
|
||||
@-webkit-keyframes fadeIn { |
||||
0% { |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
} |
||||
|
||||
1% { |
||||
opacity: 0; |
||||
visibility: visible; |
||||
} |
||||
|
||||
100% { |
||||
opacity: 1; |
||||
visibility: visible; |
||||
} |
||||
} |
||||
|
||||
@keyframes fadeIn { |
||||
0% { |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
} |
||||
|
||||
1% { |
||||
opacity: 0; |
||||
visibility: visible; |
||||
} |
||||
|
||||
100% { |
||||
opacity: 1; |
||||
visibility: visible; |
||||
} |
||||
} |
||||
|
||||
@-webkit-keyframes fadeOut { |
||||
0% { |
||||
opacity: 1; |
||||
visibility: visible; |
||||
} |
||||
|
||||
99% { |
||||
opacity: 0; |
||||
visibility: visible; |
||||
} |
||||
|
||||
100% { |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
} |
||||
} |
||||
|
||||
@keyframes fadeOut { |
||||
0% { |
||||
opacity: 1; |
||||
visibility: visible; |
||||
} |
||||
|
||||
99% { |
||||
opacity: 0; |
||||
visibility: visible; |
||||
} |
||||
|
||||
100% { |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
} |
||||
} |
||||
|
||||
@-webkit-keyframes highlight { |
||||
0% { |
||||
background: #ffff99; |
||||
} |
||||
|
||||
100% { |
||||
background: none; |
||||
} |
||||
} |
||||
|
||||
@-moz-keyframes highlight { |
||||
0% { |
||||
background: #ffff99; |
||||
} |
||||
|
||||
100% { |
||||
background: none; |
||||
} |
||||
} |
||||
|
||||
@-o-keyframes highlight { |
||||
0% { |
||||
background: #ffff99; |
||||
} |
||||
|
||||
100% { |
||||
background: none; |
||||
} |
||||
} |
||||
|
||||
@keyframes highlight { |
||||
0% { |
||||
background: #ffff99; |
||||
} |
||||
|
||||
100% { |
||||
background: none; |
||||
} |
||||
} |
||||
|
||||
@keyframes modalEnter { |
||||
0% { |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
} |
||||
|
||||
1% { |
||||
opacity: 0; |
||||
visibility: visible; |
||||
transform: translateY(-150px); |
||||
} |
||||
|
||||
100% { |
||||
opacity: 1; |
||||
visibility: visible; |
||||
transform: translateY(0); |
||||
} |
||||
} |
||||
|
||||
@-webkit-keyframes modalEnter { |
||||
0% { |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
} |
||||
|
||||
1% { |
||||
opacity: 0; |
||||
visibility: visible; |
||||
-webkit-transform: translateY(-150px); |
||||
} |
||||
|
||||
100% { |
||||
opacity: 1; |
||||
visibility: visible; |
||||
-webkit-transform: translateY(0); |
||||
} |
||||
} |
||||
|
||||
@keyframes modalExit { |
||||
0% { |
||||
opacity: 1; |
||||
visibility: visible; |
||||
} |
||||
|
||||
99% { |
||||
opacity: 0; |
||||
visibility: visible; |
||||
transform: translateY(150px); |
||||
} |
||||
|
||||
100% { |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
} |
||||
} |
||||
|
||||
@-webkit-keyframes modalExit { |
||||
0% { |
||||
opacity: 1; |
||||
visibility: visible; |
||||
} |
||||
|
||||
99% { |
||||
opacity: 0; |
||||
visibility: visible; |
||||
-webkit-transform: translateY(150px); |
||||
} |
||||
|
||||
100% { |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
} |
||||
} |
||||
@ -1,53 +0,0 @@ |
||||
.loading-animation { |
||||
color: @secondary-font-color; |
||||
font-size: 1.3rem; |
||||
margin-left: 32px; |
||||
margin-top: 12px; |
||||
margin-bottom: 5px; |
||||
} |
||||
|
||||
.loading-animation > div { |
||||
width: 3px; |
||||
height: 3px; |
||||
border-radius: 100%; |
||||
display: inline-block; |
||||
background-color: @secondary-font-color; |
||||
-webkit-animation: loading-bouncedelay 1.4s infinite ease-in-out both; |
||||
animation: loading-bouncedelay 1.4s infinite ease-in-out both; |
||||
} |
||||
|
||||
.loading-animation .bounce1 { |
||||
-webkit-animation-delay: -0.32s; |
||||
animation-delay: -0.32s; |
||||
} |
||||
|
||||
.loading-animation .bounce2 { |
||||
-webkit-animation-delay: -0.16s; |
||||
animation-delay: -0.16s; |
||||
} |
||||
|
||||
@-webkit-keyframes loading-bouncedelay { |
||||
0%, |
||||
80%, |
||||
100% { |
||||
-webkit-transform: scale(0); |
||||
} |
||||
|
||||
40% { |
||||
-webkit-transform: scale(1); |
||||
} |
||||
} |
||||
|
||||
@keyframes loading-bouncedelay { |
||||
0%, |
||||
80%, |
||||
100% { |
||||
-webkit-transform: scale(0); |
||||
transform: scale(0); |
||||
} |
||||
|
||||
40% { |
||||
-webkit-transform: scale(1); |
||||
transform: scale(1); |
||||
} |
||||
} |
||||
@ -1,140 +0,0 @@ |
||||
/** |
||||
* Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) |
||||
* http://cssreset.com |
||||
*/ |
||||
|
||||
html, |
||||
body, |
||||
div, |
||||
span, |
||||
applet, |
||||
object, |
||||
iframe, |
||||
h1, |
||||
h2, |
||||
h3, |
||||
h4, |
||||
h5, |
||||
h6, |
||||
p, |
||||
blockquote, |
||||
pre, |
||||
a, |
||||
abbr, |
||||
acronym, |
||||
address, |
||||
big, |
||||
cite, |
||||
code, |
||||
del, |
||||
dfn, |
||||
em, |
||||
img, |
||||
ins, |
||||
kbd, |
||||
q, |
||||
s, |
||||
samp, |
||||
small, |
||||
strike, |
||||
strong, |
||||
sub, |
||||
sup, |
||||
tt, |
||||
var, |
||||
b, |
||||
u, |
||||
i, |
||||
center, |
||||
dl, |
||||
dt, |
||||
dd, |
||||
ol, |
||||
ul, |
||||
li, |
||||
fieldset, |
||||
form, |
||||
label, |
||||
legend, |
||||
table, |
||||
caption, |
||||
tbody, |
||||
tfoot, |
||||
thead, |
||||
tr, |
||||
th, |
||||
td, |
||||
article, |
||||
aside, |
||||
canvas, |
||||
details, |
||||
embed, |
||||
figure, |
||||
figcaption, |
||||
footer, |
||||
header, |
||||
hgroup, |
||||
menu, |
||||
nav, |
||||
output, |
||||
ruby, |
||||
section, |
||||
summary, |
||||
time, |
||||
mark, |
||||
audio, |
||||
video { |
||||
margin: 0; |
||||
padding: 0; |
||||
font-size: 100%; |
||||
// font: inherit; |
||||
vertical-align: baseline; |
||||
border: 0 solid; // set default border style |
||||
&::after, |
||||
&::before { |
||||
border: 0 solid; |
||||
} |
||||
} |
||||
|
||||
/* HTML5 display-role reset for older browsers */ |
||||
|
||||
article, |
||||
aside, |
||||
details, |
||||
figcaption, |
||||
figure, |
||||
footer, |
||||
header, |
||||
hgroup, |
||||
menu, |
||||
nav, |
||||
section { |
||||
display: block; |
||||
} |
||||
|
||||
body { |
||||
line-height: 1; |
||||
} |
||||
|
||||
ol, |
||||
ul { |
||||
list-style: none; |
||||
} |
||||
|
||||
blockquote, |
||||
q { |
||||
quotes: none; |
||||
} |
||||
|
||||
blockquote::before, |
||||
blockquote::after, |
||||
q::before, |
||||
q::after { |
||||
content: ''; |
||||
content: none; |
||||
} |
||||
|
||||
table { |
||||
border-collapse: collapse; |
||||
border-spacing: 0; |
||||
} |
||||
@ -1,33 +0,0 @@ |
||||
@header-min-height: 30px; |
||||
@footer-min-height: 55px; |
||||
|
||||
@rooms-box-width: 260px; |
||||
@flex-tab-width: 400px; |
||||
@flex-tab-webrtc-width: 400px; |
||||
@flex-tab-webrtc-2-width: 850px; |
||||
|
||||
// Colors |
||||
// -------------- |
||||
|
||||
//@primary-background-color: #045080; |
||||
//@primary-background-color: #38393d; |
||||
|
||||
@primary-background-color: #04436a; |
||||
@secondary-background-color: #f4f4f4; |
||||
@tertiary-background-color: #eaeaea; |
||||
|
||||
@link-font-color: #008ce3; |
||||
|
||||
@primary-font-color: #444444; |
||||
@secondary-font-color: #7f7f7f; |
||||
@tertiary-font-color: rgba(255, 255, 255, 0.6); |
||||
@quaternary-font-color: rgba(255, 255, 255, 0.85); |
||||
@info-font-color: #aaaaaa; |
||||
|
||||
@status-online: #4dff4d; |
||||
@status-offline: rgba(150, 150, 150, 0.5); |
||||
@status-busy: #d30230; |
||||
@status-away: #fcb316; |
||||
|
||||
@window-border-color: #e7e7e7; |
||||
@input-border-color: #cbced1; |
||||
@ -1,5 +0,0 @@ |
||||
<template name="avatar"> |
||||
<div class="avatar"> |
||||
<div class="avatar-image" style="{{imageUrl}}"></div> |
||||
</div> |
||||
</template> |
||||
@ -1,24 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Session } from 'meteor/session'; |
||||
import { Template } from 'meteor/templating'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
Template.avatar.helpers({ |
||||
imageUrl() { |
||||
let { username } = this; |
||||
if (!username && this.userId) { |
||||
const user = Meteor.users.findOne(this.userId, { fields: { username: 1 } }); |
||||
username = user && user.username; |
||||
} |
||||
|
||||
const currentUser = visitor.getData(); |
||||
if (!username || (currentUser && currentUser.username === username)) { |
||||
return; |
||||
} |
||||
|
||||
Session.get(`avatar_random_${ username }`); |
||||
|
||||
return `background-image:url(${ getAvatarUrlFromUsername(username) });`; |
||||
}, |
||||
}); |
||||
@ -1,57 +0,0 @@ |
||||
<template name="livechatWindow"> |
||||
{{#if livechatStarted}} |
||||
{{#if showWidget}} |
||||
<div class="livechat-room {{#if popoutActive}}popout{{/if}}"> |
||||
<div class="title" style="background-color:{{color}}; color: {{fontColor}}"> |
||||
<div class="toolbar"> |
||||
|
||||
{{#unless popoutActive}} |
||||
{{#if isOpened}} |
||||
<svg class="minimize" title="Minimize" viewBox="0 0 448 448" xmlns="http://www.w3.org/2000/svg"> |
||||
<path d="M448 328v48c0 22-18 40-40 40h-368c-22 0-40-18-40-40v-48c0-22 18-40 40-40h368c22 0 40 18 40 40z"></path> |
||||
</svg> |
||||
{{else}} |
||||
<svg class="maximize" title="Maximize" viewBox="0 0 448 448" xmlns="http://www.w3.org/2000/svg"> |
||||
<path d="M64 352h320v-192h-320v192zM448 72v304c0 22-18 40-40 40h-368c-22 0-40-18-40-40v-304c0-22 18-40 40-40h368c22 0 40 18 40 40z"></path> |
||||
</svg> |
||||
{{/if}} |
||||
{{/unless}} |
||||
{{#if soundActive}} |
||||
<svg class="sound" title="Toggle notification sound" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"> |
||||
<path d="M912 1696q0-16-16-16-59 0-101.5-42.5t-42.5-101.5q0-16-16-16t-16 16q0 73 51.5 124.5t124.5 51.5q16 0 16-16zm816-288q0 52-38 90t-90 38h-448q0 106-75 181t-181 75-181-75-75-181h-448q-52 0-90-38t-38-90q50-42 91-88t85-119.5 74.5-158.5 50-206 19.5-260q0-152 117-282.5t307-158.5q-8-19-8-39 0-40 28-68t68-28 68 28 28 68q0 20-8 39 190 28 307 158.5t117 282.5q0 139 19.5 260t50 206 74.5 158.5 85 119.5 91 88z" /> |
||||
</svg> |
||||
{{else}} |
||||
<svg class="sound" title="Toggle notification sound" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"> |
||||
<path d="M1430 852q61 356 298 556 0 52-38 90t-90 38h-448q0 106-75 181t-181 75-180.5-74.5-75.5-180.5zm-534 860q16 0 16-16t-16-16q-59 0-101.5-42.5t-42.5-101.5q0-16-16-16t-16 16q0 73 51.5 124.5t124.5 51.5zm1002-1600q8 10 7.5 23.5t-10.5 22.5l-1872 1622q-10 8-23.5 7t-21.5-11l-84-96q-8-10-7.5-23.5t10.5-21.5l186-161q-19-32-19-66 50-42 91-88t85-119.5 74.5-158.5 50-206 19.5-260q0-152 117-282.5t307-158.5q-8-19-8-39 0-40 28-68t68-28 68 28 28 68q0 20-8 39 124 18 219 82.5t148 157.5l418-363q10-8 23.5-7t21.5 11z" /> |
||||
</svg> |
||||
{{/if}} |
||||
{{#unless popoutActive}} |
||||
<svg class="popout" aria-label="{{_ "Open_in_a_new_window"}}" viewBox="0 0 448 448" xmlns="http://www.w3.org/2000/svg"> |
||||
<path d="M320 232v-120c0-8.75-7.25-16-16-16h-120c-6.5 0-12.25 4-14.75 9.75-2.5 6-1.25 13 3.5 17.5l36 36-133.5 133.5c-6.25 6.25-6.25 16.25 0 22.5l25.5 25.5c6.25 6.25 16.25 6.25 22.5 0l133.5-133.5 36 36c3 3.25 7 4.75 11.25 4.75 2 0 4.25-0.5 6.25-1.25 5.75-2.5 9.75-8.25 9.75-14.75zM384 104v240c0 39.75-32.25 72-72 72h-240c-39.75 0-72-32.25-72-72v-240c0-39.75 32.25-72 72-72h240c39.75 0 72 32.25 72 72z"></path> |
||||
</svg> |
||||
{{/unless}} |
||||
</div> |
||||
<h1>{{title}}</h1> |
||||
</div> |
||||
{{#if livechatOnline}} |
||||
{{#if showRegisterForm}} |
||||
{{> register}} |
||||
{{else}} |
||||
{{> messages}} |
||||
{{#if showSwitchDepartmentForm}} |
||||
{{> switchDepartment}} |
||||
{{/if}} |
||||
{{/if}} |
||||
{{else}} |
||||
<div class="offline"> |
||||
{{> offlineForm (offlineData)}} |
||||
</div> |
||||
{{/if}} |
||||
{{> poweredBy }} |
||||
</div> |
||||
{{/if}} |
||||
{{/if}} |
||||
{{#if videoCalling}} |
||||
{{> videoCall}} |
||||
{{/if}} |
||||
</template> |
||||
@ -1,243 +0,0 @@ |
||||
/* globals Department, Livechat, LivechatVideoCall */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
import { Session } from 'meteor/session'; |
||||
import { Template } from 'meteor/templating'; |
||||
import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
function showDepartments() { |
||||
return Department.find({ showOnRegistration: true }).count() > 1; |
||||
} |
||||
|
||||
Template.livechatWindow.helpers({ |
||||
title() { |
||||
return Livechat.title; |
||||
}, |
||||
color() { |
||||
return Livechat.color; |
||||
}, |
||||
fontColor() { |
||||
return Livechat.fontColor; |
||||
}, |
||||
popoutActive() { |
||||
return FlowRouter.getQueryParam('mode') === 'popout'; |
||||
}, |
||||
soundActive() { |
||||
return Session.get('sound'); |
||||
}, |
||||
showRegisterForm() { |
||||
if (Session.get('triggered') || visitor.getId()) { |
||||
return false; |
||||
} |
||||
return Livechat.registrationForm && (Livechat.nameFieldRegistrationForm || Livechat.emailFieldRegistrationForm || showDepartments()); |
||||
}, |
||||
showSwitchDepartmentForm() { |
||||
return Livechat.showSwitchDepartmentForm; |
||||
}, |
||||
livechatStarted() { |
||||
return Livechat.online !== null; |
||||
}, |
||||
livechatOnline() { |
||||
return Livechat.online; |
||||
}, |
||||
offlineMessage() { |
||||
return Livechat.offlineMessage; |
||||
}, |
||||
offlineData() { |
||||
return { |
||||
offlineMessage: Livechat.offlineMessage.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br>$2'), |
||||
offlineSuccessMessage: Livechat.offlineSuccessMessage, |
||||
offlineUnavailableMessage: Livechat.offlineUnavailableMessage.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br>$2'), |
||||
displayOfflineForm: Livechat.displayOfflineForm, |
||||
}; |
||||
}, |
||||
videoCalling() { |
||||
return LivechatVideoCall.isActive(); |
||||
}, |
||||
isOpened() { |
||||
return Livechat.isWidgetOpened(); |
||||
}, |
||||
showWidget() { |
||||
return Livechat.online || Livechat.displayOfflineForm; |
||||
}, |
||||
}); |
||||
|
||||
Template.livechatWindow.events({ |
||||
'mousedown .title'({ target, clientX: x, clientY: y }) { |
||||
parentCall('startDragWindow', { x, y }); |
||||
|
||||
this.onDrag = ({ clientX: x, clientY: y }) => { |
||||
parentCall('dragWindow', { |
||||
x: x - target.getBoundingClientRect().left, |
||||
y: y - target.getBoundingClientRect().top, |
||||
}); |
||||
}; |
||||
|
||||
this.onDragStop = () => { |
||||
parentCall('stopDragWindow'); |
||||
window.removeEventListener('mousemove', this.onDrag); |
||||
window.removeEventListener('mousedown', this.onDragStop); |
||||
this.onDrag = null; |
||||
this.onDragStop = null; |
||||
}; |
||||
|
||||
window.addEventListener('mousemove', this.onDrag); |
||||
window.addEventListener('mouseup', this.onDragStop); |
||||
}, |
||||
'click .title'() { |
||||
parentCall('restoreWindow'); |
||||
}, |
||||
'click .maximize'(e) { |
||||
parentCall('toggleWindow'); |
||||
e.stopPropagation(); |
||||
}, |
||||
'click .minimize'(e) { |
||||
parentCall('toggleWindow'); |
||||
e.stopPropagation(); |
||||
}, |
||||
'click .popout'(event) { |
||||
event.stopPropagation(); |
||||
parentCall('openPopout'); |
||||
}, |
||||
'click .sound'(event) { |
||||
event.stopPropagation(); |
||||
Session.set({ sound: !Session.get('sound') }); |
||||
}, |
||||
}); |
||||
|
||||
Template.livechatWindow.onCreated(function() { |
||||
Session.set({ sound: true }); |
||||
|
||||
TAPi18n.conf.i18n_files_route = Meteor._relativeToSiteRootUrl('/tap-i18n'); |
||||
|
||||
const availableLanguages = TAPi18n.getLanguages(); |
||||
|
||||
const defaultAppLanguage = () => { |
||||
let lng = window.navigator.userLanguage || window.navigator.language || 'en'; |
||||
const regexp = /([a-z]{2}-)([a-z]{2})/; |
||||
if (regexp.test(lng)) { |
||||
lng = lng.replace(regexp, function(match, ...parts) { |
||||
return parts[0] + parts[1].toUpperCase(); |
||||
}); |
||||
} |
||||
return lng; |
||||
}; |
||||
|
||||
const loadDepartments = (departments) => { |
||||
Department.remove({}); |
||||
departments.forEach((department) => { |
||||
Department.insert(department); |
||||
}); |
||||
}; |
||||
|
||||
const normalizeLanguageString = (languageString) => { |
||||
let [languageCode, countryCode] = languageString.split ? languageString.split(/[-_]/) : []; |
||||
if (!languageCode || languageCode.length !== 2) { |
||||
return 'en'; |
||||
} |
||||
languageCode = languageCode.toLowerCase(); |
||||
|
||||
if (!countryCode || countryCode.length !== 2) { |
||||
countryCode = null; |
||||
} else { |
||||
countryCode = countryCode.toUpperCase(); |
||||
} |
||||
|
||||
return countryCode ? `${ languageCode }-${ countryCode }` : languageCode; |
||||
}; |
||||
|
||||
this.autorun(() => { |
||||
// get all needed live chat info for the user
|
||||
Meteor.call('livechat:getInitialData', visitor.getToken(), Livechat.department, (err, result) => { |
||||
if (err) { |
||||
return console.error(err); |
||||
} |
||||
|
||||
if (!result.enabled) { |
||||
Triggers.setDisabled(); |
||||
return parentCall('removeWidget'); |
||||
} |
||||
|
||||
if (!result.online) { |
||||
Triggers.setDisabled(); |
||||
Livechat.title = result.offlineTitle; |
||||
Livechat.offlineColor = result.offlineColor; |
||||
Livechat.offlineMessage = result.offlineMessage; |
||||
Livechat.displayOfflineForm = result.displayOfflineForm; |
||||
Livechat.offlineUnavailableMessage = result.offlineUnavailableMessage; |
||||
Livechat.offlineSuccessMessage = result.offlineSuccessMessage; |
||||
Livechat.online = false; |
||||
} else { |
||||
Livechat.title = result.title; |
||||
Livechat.onlineColor = result.color; |
||||
Livechat.online = true; |
||||
Livechat.transcript = result.transcript; |
||||
Livechat.transcriptMessage = result.transcriptMessage; |
||||
Livechat.conversationFinishedMessage = result.conversationFinishedMessage; |
||||
} |
||||
Livechat.videoCall = result.videoCall; |
||||
Livechat.fileUpload = result.fileUpload; |
||||
Livechat.registrationForm = result.registrationForm; |
||||
Livechat.nameFieldRegistrationForm = result.nameFieldRegistrationForm; |
||||
Livechat.emailFieldRegistrationForm = result.emailFieldRegistrationForm; |
||||
Livechat.registrationFormMessage = result.registrationFormMessage; |
||||
Livechat.connecting = !!(result.room && !result.agentData && result.showConnecting); |
||||
|
||||
loadDepartments(result.departments); |
||||
|
||||
if (result.visitor) { |
||||
visitor.setData(result.visitor); |
||||
|
||||
if (result.visitor.department) { |
||||
Livechat.department = result.visitor.department; |
||||
} |
||||
|
||||
if (result.visitor.name) { |
||||
Livechat.guestName = result.visitor.name; |
||||
} |
||||
|
||||
if (result.visitor.visitorEmails && result.visitor.visitorEmails.length > 0) { |
||||
Livechat.guestEmail = result.visitor.visitorEmails[0].address; |
||||
} |
||||
|
||||
if (!Livechat.department) { |
||||
Livechat.department = result.visitor.department; |
||||
} |
||||
} |
||||
|
||||
let room; |
||||
if (result.room && (!result.room.departmentId || !Livechat.department || result.room.departmentId === Livechat.department)) { |
||||
room = result.room._id; |
||||
|
||||
visitor.setConnected(); |
||||
} |
||||
Livechat.room = room; |
||||
|
||||
if (result.agentData) { |
||||
Livechat.agent = result.agentData; |
||||
} |
||||
|
||||
let language = normalizeLanguageString(result.language || defaultAppLanguage()); |
||||
|
||||
if (!availableLanguages[language]) { |
||||
language = language.split('-').shift(); |
||||
} |
||||
|
||||
TAPi18n.setLanguage(language); |
||||
|
||||
Triggers.init(result.triggers); |
||||
|
||||
Livechat.allowSwitchingDepartments = result.allowSwitchingDepartments; |
||||
|
||||
Livechat.ready(); |
||||
}); |
||||
}); |
||||
|
||||
$(window).on('focus', () => { |
||||
if (Livechat.isWidgetOpened()) { |
||||
$('textarea').focus(); |
||||
} |
||||
}); |
||||
}); |
||||
@ -1,8 +0,0 @@ |
||||
<template name="loading"> |
||||
<div class="loading-animation"> |
||||
{{_ "Connecting_to_an_Agent"}} |
||||
<div class="bounce bounce1"></div> |
||||
<div class="bounce bounce2"></div> |
||||
<div class="bounce bounce3"></div> |
||||
</div> |
||||
</template> |
||||
@ -1,21 +0,0 @@ |
||||
<head> |
||||
<title>Rocket.Chat</title> |
||||
<meta charset="utf-8" /> |
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> |
||||
<meta http-equiv="expires" content="-1" /> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
<meta name="fragment" content="!" /> |
||||
<meta name="distribution" content="global" /> |
||||
<meta name="rating" content="general" /> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" /> |
||||
<audio id="chatAudioNotification" preload> |
||||
<source src="sounds/chime.mp3" type="audio/mpeg" /> |
||||
</audio> |
||||
</head> |
||||
|
||||
<body> |
||||
</body> |
||||
|
||||
<template name="main"> |
||||
{{> Template.dynamic template=center}} |
||||
</template> |
||||
@ -1,26 +0,0 @@ |
||||
<template name="message"> |
||||
<li id="{{_id}}" class="message background-transparent-dark-hover sequential {{system}} {{t}} {{own}} {{isTemp}} {{error}}" data-username="{{u.username}}" data-date="{{date}}"> |
||||
<div class="content"> |
||||
<span class="thumb thumb-small" data-username="{{u.username}}" tabindex="1">{{> avatar username=u.username}}</span> |
||||
<span class="user" data-username="{{u.username}}" tabindex="1"> |
||||
{{#if own}} |
||||
{{_ "You"}} |
||||
{{else}} |
||||
{{sender}} |
||||
{{/if}} |
||||
</span> |
||||
<div class="body" dir="auto"> |
||||
{{{body}}} |
||||
{{#each attachments}} |
||||
{{> messageAttachment}} |
||||
{{/each}} |
||||
<span class="info"> |
||||
<span class="time">{{time}}</span> |
||||
{{#if edit}} |
||||
<span class="edited">({{_ "edited"}})</span> |
||||
{{/if}} |
||||
</span> |
||||
</div> |
||||
</div> |
||||
</li> |
||||
</template> |
||||
@ -1,119 +0,0 @@ |
||||
/* globals Livechat, t, tr, livechatAutolinker */ |
||||
import { Blaze } from 'meteor/blaze'; |
||||
import { Template } from 'meteor/templating'; |
||||
import moment from 'moment'; |
||||
import s from 'underscore.string'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
Template.message.helpers({ |
||||
own() { |
||||
if (this.u && this.u._id === visitor.getId()) { |
||||
return 'own'; |
||||
} |
||||
}, |
||||
time() { |
||||
return moment(this.ts).format('LT'); |
||||
}, |
||||
date() { |
||||
return moment(this.ts).format('LL'); |
||||
}, |
||||
isTemp() { |
||||
if (this.temp === true) { |
||||
return 'temp'; |
||||
} |
||||
}, |
||||
error() { |
||||
if (this.error) { |
||||
return 'msg-error'; |
||||
} |
||||
}, |
||||
body() { |
||||
switch (this.t) { |
||||
case 'r': |
||||
return t('Room_name_changed', { room_name: this.msg, user_by: this.u.username }); |
||||
case 'au': |
||||
return t('User_added_by', { user_added: this.msg, user_by: this.u.username }); |
||||
case 'ru': |
||||
return t('User_removed_by', { user_removed: this.msg, user_by: this.u.username }); |
||||
case 'ul': |
||||
return tr('User_left', { context: this.u.gender }, { user_left: this.u.username }); |
||||
case 'uj': |
||||
return tr('User_joined', { context: this.u.gender }, { user: this.u.username }); |
||||
case 'wm': |
||||
return t('Welcome', { user: this.u.username }); |
||||
case 'livechat-close': |
||||
return Livechat.conversationFinishedMessage ? Livechat.conversationFinishedMessage : t('Conversation_finished'); |
||||
// case 'rtc': return RocketChat.callbacks.run('renderRtcMessage', this);
|
||||
default: |
||||
this.html = this.msg; |
||||
if (s.trim(this.html) !== '') { |
||||
this.html = s.escapeHTML(this.html); |
||||
} |
||||
// message = RocketChat.callbacks.run 'renderMessage', this
|
||||
const message = this; |
||||
this.html = message.html.replace(/\n/gm, '<br/>'); |
||||
return livechatAutolinker.link(this.html); |
||||
} |
||||
}, |
||||
|
||||
system() { |
||||
if (['s', 'p', 'f', 'r', 'au', 'ru', 'ul', 'wm', 'uj', 'livechat-close'].includes(this.t)) { |
||||
return 'system'; |
||||
} |
||||
}, |
||||
|
||||
sender() { |
||||
const { agent } = Livechat; |
||||
if (agent && this.u.username === agent.username) { |
||||
return agent.name || agent.username; |
||||
} |
||||
return this.u.username; |
||||
}, |
||||
}); |
||||
|
||||
Template.message.onViewRendered = function(context) { |
||||
const view = this; |
||||
this._domrange.onAttached(function(domRange) { |
||||
const lastNode = domRange.lastNode(); |
||||
const previousNode = lastNode.previousElementSibling; |
||||
const nextNode = lastNode.nextElementSibling; |
||||
|
||||
if (!previousNode || previousNode.dataset.date !== lastNode.dataset.date) { |
||||
$(lastNode).addClass('new-day'); |
||||
$(lastNode).removeClass('sequential'); |
||||
} else if (previousNode.dataset.username !== lastNode.dataset.username) { |
||||
$(lastNode).removeClass('sequential'); |
||||
} |
||||
|
||||
if (nextNode && nextNode.dataset.date === lastNode.dataset.date) { |
||||
$(nextNode).removeClass('new-day'); |
||||
$(nextNode).addClass('sequential'); |
||||
} else { |
||||
$(nextNode).addClass('new-day'); |
||||
$(nextNode).removeClass('sequential'); |
||||
} |
||||
|
||||
if (!nextNode || nextNode.dataset.username !== lastNode.dataset.username) { |
||||
$(nextNode).removeClass('sequential'); |
||||
} |
||||
|
||||
if (context.urls && context.urls.length > 0 && Template.oembedBaseWidget) { |
||||
context.urls.forEach((item) => { |
||||
const urlNode = lastNode.querySelector(`.body a[href="${ item.url }"]`); |
||||
if (urlNode) { |
||||
$(urlNode).replaceWith(Blaze.toHTMLWithData(Template.oembedBaseWidget, item)); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
if (!nextNode) { |
||||
if (lastNode.classList.contains('own')) { |
||||
view.parentView.parentView.parentView.parentView.parentView.templateInstance().atBottom = true; |
||||
} else if (view.parentView.parentView.parentView.parentView.parentView.templateInstance().atBottom !== true) { |
||||
const newMessage = document.querySelector('.new-message'); |
||||
newMessage.className = 'new-message'; |
||||
} |
||||
} |
||||
}); |
||||
}; |
||||
@ -1,60 +0,0 @@ |
||||
<template name="messageAttachment"> |
||||
<div class="attachment"> |
||||
<div class="attachment-block"> |
||||
<div class="attachment-block-border background-info-font-color" style="background-color: {{color}}"></div> |
||||
{{#if title}} |
||||
<div class="attachment-title"> |
||||
{{#if title_link}} |
||||
<a href="{{title_link}}" target="_blank" rel="noopener noreferrer">{{title}}</a> |
||||
{{#if title_link_download}} |
||||
<a class="icon-download attachment-download-icon" href="{{title_link}}" target="_blank" download="" rel="noopener noreferrer"></a> |
||||
{{/if}} |
||||
{{else}} |
||||
{{title}} |
||||
{{/if}} |
||||
</div> |
||||
{{/if}} |
||||
|
||||
{{#if image_url}} |
||||
<div class="attachment-image"> |
||||
<figure> |
||||
<div class="inline-image" style="background-image: url('{{image_url}}');"> |
||||
<img src="{{image_url}}" height="{{getImageHeight image_dimensions.height}}" class="gallery-item" data-title="{{title}}" data-description="{{description}}"> |
||||
</div> |
||||
{{#if description}} |
||||
<figcaption class="attachment-description">{{description}}</figcaption> |
||||
{{/if}} |
||||
</figure> |
||||
</div> |
||||
{{/if}} |
||||
|
||||
{{#if audio_url}} |
||||
<div class="attachment-audio"> |
||||
<audio controls> |
||||
<source src="{{audio_url}}" type="{{audio_type}}" data-description="{{description}}"> |
||||
Your browser does not support the audio element. |
||||
</audio> |
||||
</div> |
||||
{{/if}} |
||||
|
||||
{{#if video_url}} |
||||
<div class="attachment-video"> |
||||
<video controls class="inline-video"> |
||||
<source src="{{video_url}}" type="{{video_type}}" data-description="{{description}}"> |
||||
Your browser does not support the video element. |
||||
</video> |
||||
</div> |
||||
{{/if}} |
||||
|
||||
{{#unless image_url}} |
||||
{{#if description}} |
||||
<div class="attachment-description">{{description}}</div> |
||||
{{/if}} |
||||
{{/unless}} |
||||
|
||||
{{#each attachments}} |
||||
{{> messageAttachment}} |
||||
{{/each}} |
||||
</div> |
||||
</div> |
||||
</template> |
||||
@ -1,8 +0,0 @@ |
||||
import { Template } from 'meteor/templating'; |
||||
|
||||
Template.messageAttachment.helpers({ |
||||
|
||||
getImageHeight(height = 200) { |
||||
return height; |
||||
}, |
||||
}); |
||||
@ -1,78 +0,0 @@ |
||||
<template name="messages"> |
||||
{{#with agentData}} |
||||
<div class="header"> |
||||
<div class="picture"> |
||||
<img src="{{avatar}}"> |
||||
</div> |
||||
<div class="info"> |
||||
<ul> |
||||
<li><h2>{{name}}</h2></li> |
||||
{{#if email}} |
||||
<li>{{email}}</li> |
||||
{{/if}} |
||||
{{#if phone}} |
||||
<li>{{phone}}</li> |
||||
{{/if}} |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
{{/with}} |
||||
<div class="messages"> |
||||
<div class="wrapper"> |
||||
<ul> |
||||
{{#each messages}} |
||||
{{#nrr nrrargs 'message' .}}{{/nrr}} |
||||
{{/each}} |
||||
</ul> |
||||
</div> |
||||
<div class="new-message background-primary-action-color color-primary-action-contrast not"> |
||||
<span>{{_ "New_messages"}}</span> |
||||
</div> |
||||
|
||||
<div class="error error-color error-background"> |
||||
<span></span> |
||||
</div> |
||||
</div> |
||||
<div class="footer"> |
||||
<div class="message-bar"> |
||||
<div class="input-wrapper"> |
||||
<textarea class="input-message" placeholder="{{_ "Type_your_message"}}"></textarea> |
||||
{{#if fileUploadEnabled}} |
||||
<div class="upload-button-box"> |
||||
<svg class="upload-button" aria-label="{{_ "FileUpload"}}" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="M149.106 512c-33.076 0-66.153-12.59-91.333-37.771-50.364-50.361-50.364-132.305-.002-182.665L319.842 29.498c39.331-39.331 103.328-39.331 142.66 0 39.331 39.332 39.331 103.327 0 142.657l-222.63 222.626c-28.297 28.301-74.347 28.303-102.65 0-28.3-28.301-28.3-74.349 0-102.649l170.301-170.298c4.686-4.686 12.284-4.686 16.97 0l5.661 5.661c4.686 4.686 4.686 12.284 0 16.971l-170.3 170.297c-15.821 15.821-15.821 41.563.001 57.385 15.821 15.82 41.564 15.82 57.385 0l222.63-222.626c26.851-26.851 26.851-70.541 0-97.394-26.855-26.851-70.544-26.849-97.395 0L80.404 314.196c-37.882 37.882-37.882 99.519 0 137.401 37.884 37.881 99.523 37.882 137.404.001l217.743-217.739c4.686-4.686 12.284-4.686 16.97 0l5.661 5.661c4.686 4.686 4.686 12.284 0 16.971L240.44 474.229C215.26 499.41 182.183 512 149.106 512z"></path></svg> |
||||
</div> |
||||
{{/if}} |
||||
</div> |
||||
<div class="buttons"> |
||||
<svg class="send-button" aria-label="{{_ "Send"}}" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1764 11q33 24 27 64l-256 1536q-5 29-32 45-14 8-31 8-11 0-24-5l-453-185-242 295q-18 23-49 23-13 0-22-4-19-7-30.5-23.5t-11.5-36.5v-349l864-1059-1069 925-395-162q-37-14-40-55-2-40 32-59l1664-960q15-9 32-9 20 0 36 11z"/></svg> |
||||
{{#if videoCallEnabled}} |
||||
<svg class="video-button" aria-label="{{_ "Video"}}" viewBox="0 0 459 459" xmlns="http://www.w3.org/2000/svg"><path d="M357,191.25V102c0-15.3-10.2-25.5-25.5-25.5h-306C10.2,76.5,0,86.7,0,102v255c0,15.3,10.2,25.5,25.5,25.5h306 c15.3,0,25.5-10.2,25.5-25.5v-89.25l102,102V89.25L357,191.25z"/></svg> |
||||
{{/if}} |
||||
</div> |
||||
</div> |
||||
|
||||
{{#if usersTyping.users}} |
||||
{{#with usersTyping}} |
||||
<div class="typing"> |
||||
<strong>{{users}}</strong> |
||||
{{#if multi}} |
||||
{{#if selfTyping}} |
||||
{{_ "are_also_typing"}} |
||||
{{else}} |
||||
{{_ "are_typing"}} |
||||
{{/if}} |
||||
{{else}} |
||||
{{#if selfTyping}} |
||||
{{_ "is_also_typing" context="male"}} |
||||
{{else}} |
||||
{{_ "is_typing" context="male"}} |
||||
{{/if}} |
||||
{{/if}} |
||||
</div> |
||||
{{/with}} |
||||
{{else}} |
||||
{{> options show=showOptions}} |
||||
<button class="toggle-options secondary-font-color">{{optionsLink}}</button> |
||||
{{/if}} |
||||
</div> |
||||
</template> |
||||
@ -1,245 +0,0 @@ |
||||
/* globals Livechat, LivechatVideoCall, MsgTyping, fileUpload, showError, hideError */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Template } from 'meteor/templating'; |
||||
import _ from 'underscore'; |
||||
import mime from 'mime-type/with-db'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
Template.messages.helpers({ |
||||
messages() { |
||||
return ChatMessage.find({ |
||||
rid: visitor.getRoom(), |
||||
t: { |
||||
$nin: ['t', 'livechat_navigation_history'], |
||||
}, |
||||
}, { |
||||
sort: { |
||||
ts: 1, |
||||
}, |
||||
}); |
||||
}, |
||||
showOptions() { |
||||
if (Template.instance().showOptions.get()) { |
||||
return 'show'; |
||||
} |
||||
return ''; |
||||
}, |
||||
optionsLink() { |
||||
if (Template.instance().showOptions.get()) { |
||||
return t('Close_menu'); |
||||
} |
||||
return t('Options'); |
||||
}, |
||||
videoCallEnabled() { |
||||
return Livechat.videoCall; |
||||
}, |
||||
fileUploadEnabled() { |
||||
return Livechat.fileUpload && Template.instance().isMessageFieldEmpty.get(); |
||||
}, |
||||
usersTyping() { |
||||
const users = MsgTyping.get(visitor.getRoom()); |
||||
if (users.length === 0) { |
||||
return; |
||||
} |
||||
if (users.length === 1) { |
||||
return { |
||||
multi: false, |
||||
selfTyping: MsgTyping.selfTyping.get(), |
||||
users: users[0], |
||||
}; |
||||
} |
||||
// usernames = _.map messages, (message) -> return message.u.username
|
||||
let last = users.pop(); |
||||
if (users.length > 4) { |
||||
last = t('others'); |
||||
} |
||||
// else
|
||||
let usernames = users.join(', '); |
||||
usernames = [usernames, last]; |
||||
return { |
||||
multi: true, |
||||
selfTyping: MsgTyping.selfTyping.get(), |
||||
users: usernames.join(` ${ t('and') } `), |
||||
}; |
||||
}, |
||||
agentData() { |
||||
const { agent } = Livechat; |
||||
if (!agent) { |
||||
return null; |
||||
} |
||||
|
||||
const agentData = { |
||||
avatar: getAvatarUrlFromUsername(agent.username), |
||||
}; |
||||
|
||||
if (agent.name) { |
||||
agentData.name = agent.name; |
||||
} |
||||
|
||||
if (agent.emails && agent.emails[0] && agent.emails[0].address) { |
||||
agentData.email = agent.emails[0].address; |
||||
} |
||||
|
||||
if (agent.phone && agent.phone.length > 0) { |
||||
agentData.phone = agent.phone[0].phoneNumber; |
||||
} else if (agent.customFields && agent.customFields.phone) { |
||||
agentData.phone = agent.customFields.phone; |
||||
} |
||||
|
||||
return agentData; |
||||
}, |
||||
}); |
||||
|
||||
Template.messages.events({ |
||||
'keyup .input-message'(event, instance) { |
||||
instance.chatMessages.keyup(visitor.getRoom(), event, instance); |
||||
instance.updateMessageInputHeight(event.currentTarget); |
||||
instance.isMessageFieldEmpty.set(event.target.value === ''); |
||||
}, |
||||
'keydown .input-message'(event, instance) { |
||||
return instance.chatMessages.keydown(visitor.getRoom(), event, instance); |
||||
}, |
||||
'click .send-button'(event, instance) { |
||||
const input = instance.find('.input-message'); |
||||
const sent = instance.chatMessages.send(visitor.getRoom(), input); |
||||
input.focus(); |
||||
instance.updateMessageInputHeight(input); |
||||
instance.isMessageFieldEmpty.set(input.value === ''); |
||||
|
||||
return sent; |
||||
}, |
||||
'click .new-message'(event, instance) { |
||||
instance.atBottom = true; |
||||
return instance.find('.input-message').focus(); |
||||
}, |
||||
'click .error'(event) { |
||||
return $(event.currentTarget).removeClass('show'); |
||||
}, |
||||
'click .toggle-options'(event, instance) { |
||||
instance.showOptions.set(!instance.showOptions.get()); |
||||
}, |
||||
'click .video-button'(event) { |
||||
event.preventDefault(); |
||||
|
||||
if (!visitor.getId()) { |
||||
Meteor.call('livechat:registerGuest', { token: visitor.getToken() }, (error, result) => { |
||||
if (error) { |
||||
return console.log(error.reason); |
||||
} |
||||
|
||||
visitor.setId(result.userId); |
||||
visitor.setData(result.visitor); |
||||
LivechatVideoCall.request(); |
||||
}); |
||||
} else { |
||||
LivechatVideoCall.request(); |
||||
} |
||||
}, |
||||
'click .upload-button'(event) { |
||||
event.preventDefault(); |
||||
|
||||
const $input = $(document.createElement('input')); |
||||
$input.css('display', 'none'); |
||||
$input.attr({ |
||||
id: 'fileupload-input', |
||||
type: 'file', |
||||
}); |
||||
|
||||
$(document.body).append($input); |
||||
|
||||
$input.one('change', function(e) { |
||||
const { files } = e.target; |
||||
if (files && (files.length > 0)) { |
||||
const file = files[0]; |
||||
Object.defineProperty(file, 'type', { |
||||
value: mime.lookup(file.name), |
||||
}); |
||||
|
||||
fileUpload({ |
||||
file, |
||||
name: file.name, |
||||
}); |
||||
} |
||||
$input.remove(); |
||||
}); |
||||
|
||||
$input.click(); |
||||
}, |
||||
}); |
||||
|
||||
Template.messages.onCreated(function() { |
||||
this.atBottom = true; |
||||
this.isMessageFieldEmpty = new ReactiveVar(true); |
||||
this.showOptions = new ReactiveVar(false); |
||||
|
||||
this.updateMessageInputHeight = function(input) { |
||||
// Inital height is 28. If the scrollHeight is greater than that( we have more text than area ),
|
||||
// increase the size of the textarea. The max-height is set at 200
|
||||
// even if the scrollHeight become bigger than that it should never exceed that.
|
||||
// Account for no text in the textarea when increasing the height.
|
||||
// If there is no text, reset the height.
|
||||
const inputScrollHeight = $(input).prop('scrollHeight'); |
||||
if (inputScrollHeight > 28) { |
||||
const scrollHeight = inputScrollHeight >= 200 ? inputScrollHeight - 50 : inputScrollHeight - 20; |
||||
return $(input).height($(input).val() === '' ? '15px' : scrollHeight); |
||||
} |
||||
}; |
||||
|
||||
$(document).click((/* event*/) => { |
||||
if (!this.showOptions.get()) { |
||||
return; |
||||
} |
||||
const target = $(event.target); |
||||
if (!target.closest('.options-menu').length && !target.is('.options-menu') && !target.closest('.toggle-options').length && !target.is('.toggle-options')) { |
||||
this.showOptions.set(false); |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
Template.messages.onRendered(function() { |
||||
this.chatMessages = new ChatMessages(); |
||||
this.chatMessages.init(this.firstNode); |
||||
}); |
||||
|
||||
Template.messages.onRendered(function() { |
||||
const messages = this.find('.messages'); |
||||
const newMessage = this.find('.new-message'); |
||||
const template = this; |
||||
|
||||
if (messages) { |
||||
const onscroll = _.throttle(function() { |
||||
template.atBottom = messages.scrollTop >= messages.scrollHeight - messages.clientHeight; |
||||
}, 200); |
||||
Meteor.setInterval(function() { |
||||
if (template.atBottom) { |
||||
messages.scrollTop = messages.scrollHeight - messages.clientHeight; |
||||
newMessage.className = 'new-message not'; |
||||
} |
||||
}, 100); |
||||
messages.addEventListener('touchstart', function() { |
||||
template.atBottom = false; |
||||
}); |
||||
messages.addEventListener('touchend', function() { |
||||
onscroll(); |
||||
}); |
||||
messages.addEventListener('scroll', function() { |
||||
template.atBottom = false; |
||||
onscroll(); |
||||
}); |
||||
messages.addEventListener('mousewheel', function() { |
||||
template.atBottom = false; |
||||
onscroll(); |
||||
}); |
||||
messages.addEventListener('wheel', function() { |
||||
template.atBottom = false; |
||||
onscroll(); |
||||
}); |
||||
} |
||||
|
||||
Tracker.autorun(() => { |
||||
Livechat.connecting ? showError(t('Please_wait_for_the_next_available_agent')) : hideError(); |
||||
}); |
||||
}); |
||||
@ -1,27 +0,0 @@ |
||||
<template name="offlineForm"> |
||||
{{#if displayOfflineForm}} |
||||
{{#if messageSent}} |
||||
<p class="message-sent">{{{offlineSuccessMessage}}}</p> |
||||
{{else}} |
||||
<p class="offline-message">{{{offlineMessage}}}</p> |
||||
|
||||
<form> |
||||
<div class="error error-color error-background"> |
||||
<span>{{{error}}}</span> |
||||
</div> |
||||
|
||||
<input type="text" id="name" name="name" placeholder="{{_ "Type_your_name"}}"> |
||||
|
||||
<input type="email" id="email" name="email" placeholder="{{_ "Type_your_email"}}"> |
||||
|
||||
<textarea id="message" name="message" placeholder="{{_"Type_your_message"}}"></textarea> |
||||
|
||||
<div class="buttons"> |
||||
<button class="button send">{{_ "Send"}}</button> |
||||
</div> |
||||
</form> |
||||
{{/if}} |
||||
{{else}} |
||||
<p class="offline-message">{{{offlineUnavailableMessage}}}</p> |
||||
{{/if}} |
||||
</template> |
||||
@ -1,86 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Template } from 'meteor/templating'; |
||||
import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; |
||||
import _ from 'underscore'; |
||||
import s from 'underscore.string'; |
||||
|
||||
Template.offlineForm.helpers({ |
||||
error() { |
||||
return Template.instance().error.get(); |
||||
}, |
||||
messageSent() { |
||||
return Template.instance().messageSent.get(); |
||||
}, |
||||
offlineMessage() { |
||||
return !_.isEmpty(this.offlineMessage) ? this.offlineMessage.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br>$2') : TAPi18n.__('We_are_not_online_right_now_please_leave_a_message'); |
||||
}, |
||||
offlineSuccessMessage() { |
||||
if (!_.isEmpty(this.offlineSuccessMessage)) { |
||||
return this.offlineSuccessMessage.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br>$2'); |
||||
} |
||||
return TAPi18n.__('Thanks_We_ll_get_back_to_you_soon'); |
||||
}, |
||||
}); |
||||
|
||||
Template.offlineForm.events({ |
||||
'submit form'(event, instance) { |
||||
event.preventDefault(); |
||||
|
||||
const form = event.currentTarget; |
||||
|
||||
const data = { |
||||
name: form.elements.name.value, |
||||
email: form.elements.email.value, |
||||
message: form.elements.message.value, |
||||
}; |
||||
|
||||
if (!instance.validateForm(form)) { |
||||
instance.showError(TAPi18n.__('You_must_complete_all_fields')); |
||||
return; |
||||
} |
||||
|
||||
instance.$('.send').attr('disabled', 'disabled'); |
||||
|
||||
Meteor.call('livechat:sendOfflineMessage', data, (error) => { |
||||
instance.$('.send').attr('disabled', null); |
||||
|
||||
if (error) { |
||||
return instance.showError(error.reason); |
||||
} |
||||
instance.messageSent.set(true); |
||||
parentCall('callback', ['offline-form-submit', data]); |
||||
}); |
||||
}, |
||||
}); |
||||
|
||||
Template.offlineForm.onCreated(function() { |
||||
this.error = new ReactiveVar(); |
||||
this.messageSent = new ReactiveVar(false); |
||||
|
||||
this.validateForm = (form) => { |
||||
let valid = true; |
||||
|
||||
const fields = ['name', 'email', 'message']; |
||||
|
||||
for (let i = 0; i < fields.length; i++) { |
||||
$(form.elements[fields[i]]).removeClass('field-error'); |
||||
|
||||
if (_.isEmpty(s.trim(form.elements[fields[i]].value))) { |
||||
$(form.elements[fields[i]]).addClass('field-error'); |
||||
valid = false; |
||||
} |
||||
} |
||||
|
||||
return valid; |
||||
}; |
||||
|
||||
this.showError = (msg) => { |
||||
$('.error').addClass('show'); |
||||
this.error.set(msg); |
||||
}; |
||||
this.hideError = () => { |
||||
$('.error').removeClass('show'); |
||||
this.error.set(); |
||||
}; |
||||
}); |
||||
@ -1,10 +0,0 @@ |
||||
<template name="options"> |
||||
<div class="options-menu content-background-color {{show}}"> |
||||
<ul> |
||||
{{#if showDepartments}} |
||||
<li><button class="switch-department"><i class="icon-cancel"></i> {{_ "Switch_department"}}</button></li> |
||||
{{/if}} |
||||
<li><button class="end-chat"><i class="icon-cancel"></i> {{_ "End_chat"}}</button></li> |
||||
</ul> |
||||
</div> |
||||
</template> |
||||
@ -1,44 +0,0 @@ |
||||
/* globals Department, Livechat */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Template } from 'meteor/templating'; |
||||
import swal from 'sweetalert2'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
Template.options.helpers({ |
||||
showDepartments() { |
||||
return Livechat.allowSwitchingDepartments && Department.find({ showOnRegistration: true }).count() > 1; |
||||
}, |
||||
departments() { |
||||
return Department.find({ showOnRegistration: true }); |
||||
}, |
||||
selectedDepartment() { |
||||
return this._id === Livechat.department; |
||||
}, |
||||
}); |
||||
|
||||
Template.options.events({ |
||||
'click .end-chat'() { |
||||
swal({ |
||||
text: t('Are_you_sure_do_you_want_end_this_chat'), |
||||
title: '', |
||||
type: 'warning', |
||||
showCancelButton: true, |
||||
confirmButtonColor: '#DD6B55', |
||||
confirmButtonText: t('Yes'), |
||||
cancelButtonText: t('No'), |
||||
html: false, |
||||
}).then((result) => { |
||||
if (result.value) { |
||||
Meteor.call('livechat:closeByVisitor', { roomId: visitor.getRoom(), token: visitor.getToken() }, (error) => { |
||||
if (error) { |
||||
return console.log('Error ->', error); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
}, |
||||
'click .switch-department'() { |
||||
Livechat.showSwitchDepartmentForm = true; |
||||
}, |
||||
}); |
||||
@ -1,8 +0,0 @@ |
||||
<template name="poweredBy"> |
||||
<p class="powered-by"> |
||||
{{_ "Powered_by"}} |
||||
<a href="https://rocket.chat" target="_blank"> |
||||
<img class="logo" src="images/logo/logo.svg?v=1"> |
||||
</a> |
||||
</p> |
||||
</template> |
||||
@ -1,33 +0,0 @@ |
||||
<template name="register"> |
||||
<div class="livechat-form"> |
||||
<div class="error error-color error-background"> |
||||
<span>{{{error}}}</span> |
||||
</div> |
||||
|
||||
<p class="welcome"> |
||||
{{{welcomeMessage}}} |
||||
</p> |
||||
<form id="livechat-registration"> |
||||
{{#if showNameFieldRegisterForm}} |
||||
<input type="text" name="name" id="guestName" placeholder="{{_ "Name"}}" value={{getName}}> |
||||
{{/if}} |
||||
{{#if showEmailFieldRegisterForm}} |
||||
<input type="email" name="email" id="guestEmail" placeholder="{{_ "Email"}}" value={{getEmail}}> |
||||
{{/if}} |
||||
{{#if showDepartments}} |
||||
<select name="department"> |
||||
<option value="">{{_ "Select_a_department"}}</option> |
||||
{{#each departments}} |
||||
<option value="{{_id}}" selected="{{selectedDepartment}}">{{name}}</option> |
||||
{{/each}} |
||||
</select> |
||||
{{/if}} |
||||
<button type="submit" id="btnEntrar" class="button"> {{_ "Start_Chat"}} </button> |
||||
|
||||
{{#if videoCallEnabled}} |
||||
<br> |
||||
<button type="submit" class="button request-video"> {{_ "Request_video_chat"}} </button> |
||||
{{/if}} |
||||
</form> |
||||
</div> |
||||
</template> |
||||
@ -1,129 +0,0 @@ |
||||
/* globals Department, Livechat, LivechatVideoCall */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Template } from 'meteor/templating'; |
||||
import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; |
||||
import _ from 'underscore'; |
||||
import s from 'underscore.string'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
Template.register.helpers({ |
||||
error() { |
||||
return Template.instance().error.get(); |
||||
}, |
||||
welcomeMessage() { |
||||
return Livechat.registrationFormMessage; |
||||
}, |
||||
showDepartments() { |
||||
return Department.find({ showOnRegistration: true }).count() > 1; |
||||
}, |
||||
departments() { |
||||
return Department.find({ showOnRegistration: true }); |
||||
}, |
||||
videoCallEnabled() { |
||||
return Livechat.videoCall; |
||||
}, |
||||
selectedDepartment() { |
||||
return this._id === Livechat.department; |
||||
}, |
||||
showNameFieldRegisterForm() { |
||||
return Livechat.nameFieldRegistrationForm; |
||||
}, |
||||
showEmailFieldRegisterForm() { |
||||
return Livechat.emailFieldRegistrationForm; |
||||
}, |
||||
getName() { |
||||
return Livechat.guestName; |
||||
}, |
||||
getEmail() { |
||||
return Livechat.guestEmail; |
||||
}, |
||||
}); |
||||
|
||||
Template.register.events({ |
||||
'submit #livechat-registration'(e, instance) { |
||||
e.preventDefault(); |
||||
|
||||
const start = () => { |
||||
instance.hideError(); |
||||
if (instance.request === 'video') { |
||||
LivechatVideoCall.request(); |
||||
} |
||||
}; |
||||
const form = e.currentTarget; |
||||
|
||||
const fields = []; |
||||
let name = Livechat.guestName; |
||||
let email = Livechat.guestEmail; |
||||
|
||||
if (Livechat.nameFieldRegistrationForm) { |
||||
fields.push('name'); |
||||
name = instance.$('input[name=name]').val(); |
||||
} |
||||
|
||||
if (Livechat.emailFieldRegistrationForm) { |
||||
fields.push('email'); |
||||
email = instance.$('input[name=email]').val(); |
||||
} |
||||
|
||||
if (!instance.validateForm(form, fields)) { |
||||
return instance.showError(TAPi18n.__('You_must_complete_all_fields')); |
||||
} |
||||
let departmentId = instance.$('select[name=department]').val(); |
||||
if (!departmentId) { |
||||
const department = Department.findOne({ showOnRegistration: true }); |
||||
if (department) { |
||||
departmentId = department._id; |
||||
} |
||||
} |
||||
|
||||
Livechat.department = departmentId; |
||||
|
||||
const guest = { |
||||
token: visitor.getToken(), |
||||
name, |
||||
email, |
||||
department: Livechat.department, |
||||
}; |
||||
|
||||
Meteor.call('livechat:registerGuest', guest, function(error, result) { |
||||
if (error != null) { |
||||
return instance.showError(error.reason); |
||||
} |
||||
parentCall('callback', ['pre-chat-form-submit', _.omit(guest, 'token')]); |
||||
visitor.setId(result.userId); |
||||
visitor.setData(result.visitor); |
||||
start(); |
||||
}); |
||||
}, |
||||
'click .error'(e, instance) { |
||||
return instance.hideError(); |
||||
}, |
||||
'click .request-chat'(e, instance) { |
||||
instance.request = 'chat'; |
||||
}, |
||||
'click .request-video'(e, instance) { |
||||
instance.request = 'video'; |
||||
}, |
||||
}); |
||||
|
||||
Template.register.onCreated(function() { |
||||
this.error = new ReactiveVar(); |
||||
this.request = ''; |
||||
|
||||
this.validateForm = (form, fields) => { |
||||
const valid = fields.every((field) => !_.isEmpty(s.trim(form.elements[field].value))); |
||||
|
||||
return valid; |
||||
}; |
||||
|
||||
this.showError = (msg) => { |
||||
$('.error').addClass('show'); |
||||
this.error.set(msg); |
||||
}; |
||||
this.hideError = () => { |
||||
$('.error').removeClass('show'); |
||||
this.error.set(); |
||||
}; |
||||
}); |
||||
@ -1,65 +0,0 @@ |
||||
<template name="survey"> |
||||
<div id="survey"> |
||||
<div class="overlay"></div> |
||||
<div class="wrapper"> |
||||
<header title="{{_ 'Please_answer_survey'}}"> |
||||
<b>{{_ 'Please_answer_survey'}}</b> |
||||
</header> |
||||
<div class="content"> |
||||
<p class="instructions">{{_ 'Survey_instructions'}}</p> |
||||
<form id="survey" class="livechat-form"> |
||||
<div class="survey-item"> |
||||
<label class="question"> |
||||
{{_ "How_satisfied_were_you_with_this_chat"}} |
||||
</label> |
||||
<label class="answer"><input type="radio" name="satisfaction" value="1" />1</label> |
||||
<label class="answer"><input type="radio" name="satisfaction" value="2" />2</label> |
||||
<label class="answer"><input type="radio" name="satisfaction" value="3" />3</label> |
||||
<label class="answer"><input type="radio" name="satisfaction" value="4" />4</label> |
||||
<label class="answer"><input type="radio" name="satisfaction" value="5" />5</label> |
||||
</div> |
||||
<div class="survey-item"> |
||||
<label class="question"> |
||||
{{_ "How_knowledgeable_was_the_chat_agent"}} |
||||
</label> |
||||
<label class="answer"><input type="radio" name="agentKnowledge" value="1" />1</label> |
||||
<label class="answer"><input type="radio" name="agentKnowledge" value="2" />2</label> |
||||
<label class="answer"><input type="radio" name="agentKnowledge" value="3" />3</label> |
||||
<label class="answer"><input type="radio" name="agentKnowledge" value="4" />4</label> |
||||
<label class="answer"><input type="radio" name="agentKnowledge" value="5" />5</label> |
||||
</div> |
||||
<div class="survey-item"> |
||||
<label class="question"> |
||||
{{_ "How_responsive_was_the_chat_agent"}} |
||||
</label> |
||||
<label class="answer"><input type="radio" name="agentResposiveness" value="1" />1</label> |
||||
<label class="answer"><input type="radio" name="agentResposiveness" value="2" />2</label> |
||||
<label class="answer"><input type="radio" name="agentResposiveness" value="3" />3</label> |
||||
<label class="answer"><input type="radio" name="agentResposiveness" value="4" />4</label> |
||||
<label class="answer"><input type="radio" name="agentResposiveness" value="5" />5</label> |
||||
</div> |
||||
<div class="survey-item"> |
||||
<label class="question"> |
||||
{{_ "How_friendly_was_the_chat_agent"}} |
||||
</label> |
||||
<label class="answer"><input type="radio" name="agentFriendliness" value="1" />1</label> |
||||
<label class="answer"><input type="radio" name="agentFriendliness" value="2" />2</label> |
||||
<label class="answer"><input type="radio" name="agentFriendliness" value="3" />3</label> |
||||
<label class="answer"><input type="radio" name="agentFriendliness" value="4" />4</label> |
||||
<label class="answer"><input type="radio" name="agentFriendliness" value="5" />5</label> |
||||
</div> |
||||
<div class="survey-item"> |
||||
<label class="question"> |
||||
{{_ "Additional_Feedback"}} |
||||
</label> |
||||
<textarea name="additionalFeedback" rows="5"></textarea> |
||||
</div> |
||||
</form> |
||||
</div> |
||||
<footer> |
||||
<button type="button" class="button secondary skip"><span>{{_ "Skip"}}</span></button> |
||||
<button type="button" class="button primary send"><span>{{_ "Send"}}</span></button> |
||||
</footer> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
@ -1,24 +0,0 @@ |
||||
/* globals */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Template } from 'meteor/templating'; |
||||
import swal from 'sweetalert2'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
Template.survey.events({ |
||||
'click button.skip'(e, instance) { |
||||
instance.$('#survey').remove(); |
||||
}, |
||||
|
||||
'click button.send'(e, instance) { |
||||
const formData = instance.$('form').serializeArray(); |
||||
Meteor.call('livechat:saveSurveyFeedback', visitor.getToken(), visitor.getRoom(), formData, function(/* err, results*/) { |
||||
instance.$('#survey').remove(); |
||||
swal({ |
||||
title: t('Thank_you_for_your_feedback'), |
||||
type: 'success', |
||||
timer: 2000, |
||||
}); |
||||
}); |
||||
}, |
||||
}); |
||||
@ -1,21 +0,0 @@ |
||||
<template name="switchDepartment"> |
||||
{{#modal}} |
||||
<div class="switch-department-form livechat-form"> |
||||
<div class="error error-color error-background {{showError}}"> |
||||
<span>{{{error}}}</span> |
||||
</div> |
||||
<form> |
||||
<h2>{{_ "Choose_a_new_department"}}</h2> |
||||
<select name="department" class="switch-department-select"> |
||||
<option value="">{{_ "Select_a_department"}}</option> |
||||
{{#each departments}} |
||||
<option value="{{_id}}">{{name}}</option> |
||||
{{/each}} |
||||
</select> |
||||
|
||||
<button type="submit" id="btnOk" class="button"> {{_ "Change"}} </button> |
||||
<button type="button" id="btnCancel" class="button secondary"> {{_ "Cancel"}} </button> |
||||
</form> |
||||
</div> |
||||
{{/modal}} |
||||
</template> |
||||
@ -1,84 +0,0 @@ |
||||
/* globals Department, Livechat */ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Template } from 'meteor/templating'; |
||||
import swal from 'sweetalert2'; |
||||
|
||||
import visitor from '../../imports/client/visitor'; |
||||
|
||||
Template.switchDepartment.helpers({ |
||||
departments() { |
||||
return Department.find({ |
||||
showOnRegistration: true, |
||||
_id: { |
||||
$ne: Livechat.department, |
||||
}, |
||||
}); |
||||
}, |
||||
error() { |
||||
return Template.instance().error.get(); |
||||
}, |
||||
showError() { |
||||
return Template.instance().error.get() ? 'show' : ''; |
||||
}, |
||||
}); |
||||
|
||||
Template.switchDepartment.onCreated(function() { |
||||
this.error = new ReactiveVar(); |
||||
}); |
||||
|
||||
Template.switchDepartment.events({ |
||||
'submit form'(e, instance) { |
||||
e.stopPropagation(); |
||||
e.preventDefault(); |
||||
|
||||
const departmentId = instance.$('.switch-department-select').val(); |
||||
if (!departmentId) { |
||||
instance.error.set(t('Please_choose_a_department')); |
||||
return; |
||||
} |
||||
|
||||
instance.error.set(); |
||||
swal({ |
||||
text: t('Are_you_sure_do_you_want_switch_the_department'), |
||||
title: '', |
||||
type: 'warning', |
||||
showCancelButton: true, |
||||
confirmButtonColor: '#DD6B55', |
||||
confirmButtonText: t('Yes'), |
||||
cancelButtonText: t('No'), |
||||
html: false, |
||||
}).then((result) => { |
||||
if (!result.value) { |
||||
return; |
||||
} |
||||
|
||||
const guestData = { |
||||
roomId: visitor.getRoom(), |
||||
visitorToken: visitor.getToken(), |
||||
departmentId, |
||||
}; |
||||
|
||||
Meteor.call('livechat:setDepartmentForVisitor', guestData, (error, result) => { |
||||
if (error) { |
||||
instance.error.set(error.error); |
||||
} else if (result) { |
||||
instance.error.set(); |
||||
Livechat.department = departmentId; |
||||
Livechat.showSwitchDepartmentForm = false; |
||||
swal({ |
||||
title: t('Department_switched'), |
||||
type: 'success', |
||||
timer: 2000, |
||||
}); |
||||
} else { |
||||
instance.error.set(t('No_available_agents_to_transfer')); |
||||
} |
||||
}); |
||||
}); |
||||
}, |
||||
|
||||
'click #btnCancel'() { |
||||
Livechat.showSwitchDepartmentForm = false; |
||||
}, |
||||
}); |
||||
@ -1,27 +0,0 @@ |
||||
<template name="videoCall"> |
||||
<div class="video-call"> |
||||
<div class="video-overlay"> |
||||
<div class="toolbar {{visible}}"> |
||||
<button class="end-call"> |
||||
<svg viewBox="0 0 578 578" xmlns="http://www.w3.org/2000/svg"> |
||||
<path d="M577.83,456.128c1.225,9.385-1.635,17.545-8.568,24.48l-81.396,80.781 |
||||
c-3.672,4.08-8.465,7.551-14.381,10.404c-5.916,2.857-11.729,4.693-17.439,5.508c-0.408,0-1.635,0.105-3.676,0.309 |
||||
c-2.037,0.203-4.689,0.307-7.953,0.307c-7.754,0-20.301-1.326-37.641-3.979s-38.555-9.182-63.645-19.584 |
||||
c-25.096-10.404-53.553-26.012-85.376-46.818c-31.823-20.805-65.688-49.367-101.592-85.68 |
||||
c-28.56-28.152-52.224-55.08-70.992-80.783c-18.768-25.705-33.864-49.471-45.288-71.299 |
||||
c-11.425-21.828-19.993-41.616-25.705-59.364S4.59,177.362,2.55,164.51s-2.856-22.95-2.448-30.294 |
||||
c0.408-7.344,0.612-11.424,0.612-12.24c0.816-5.712,2.652-11.526,5.508-17.442s6.324-10.71,10.404-14.382L98.022,8.756 |
||||
c5.712-5.712,12.24-8.568,19.584-8.568c5.304,0,9.996,1.53,14.076,4.59s7.548,6.834,10.404,11.322l65.484,124.236 |
||||
c3.672,6.528,4.692,13.668,3.06,21.42c-1.632,7.752-5.1,14.28-10.404,19.584l-29.988,29.988c-0.816,0.816-1.53,2.142-2.142,3.978 |
||||
s-0.918,3.366-0.918,4.59c1.632,8.568,5.304,18.36,11.016,29.376c4.896,9.792,12.444,21.726,22.644,35.802 |
||||
s24.684,30.293,43.452,48.653c18.36,18.77,34.68,33.354,48.96,43.76c14.277,10.4,26.215,18.053,35.803,22.949 |
||||
c9.588,4.896,16.932,7.854,22.031,8.871l7.648,1.531c0.816,0,2.145-0.307,3.979-0.918c1.836-0.613,3.162-1.326,3.979-2.143 |
||||
l34.883-35.496c7.348-6.527,15.912-9.791,25.705-9.791c6.938,0,12.443,1.223,16.523,3.672h0.611l118.115,69.768 |
||||
C571.098,441.238,576.197,447.968,577.83,456.128z"/> |
||||
</svg> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
<div class="container"></div> |
||||
</div> |
||||
</template> |
||||
@ -1,38 +0,0 @@ |
||||
/* globals LivechatVideoCall */ |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Template } from 'meteor/templating'; |
||||
|
||||
Template.videoCall.helpers({ |
||||
visible() { |
||||
if (Template.instance().showToolbar.get()) { |
||||
return 'visible'; |
||||
} |
||||
}, |
||||
}); |
||||
|
||||
Template.videoCall.events({ |
||||
'click .end-call'() { |
||||
LivechatVideoCall.finish(); |
||||
}, |
||||
'click .video-overlay'(e, instance) { |
||||
if (instance.timeout) { |
||||
clearTimeout(instance.timeout); |
||||
} |
||||
instance.showToolbar.set(!instance.showToolbar.get()); |
||||
|
||||
if (instance.showToolbar.get()) { |
||||
instance.timeout = setTimeout(() => { |
||||
instance.showToolbar.set(false); |
||||
}, 3000); |
||||
} |
||||
}, |
||||
}); |
||||
|
||||
Template.videoCall.onCreated(function() { |
||||
this.timeout = null; |
||||
this.showToolbar = new ReactiveVar(true); |
||||
|
||||
this.timeout = setTimeout(() => { |
||||
this.showToolbar.set(false); |
||||
}, 10000); |
||||
}); |
||||
@ -1,48 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Bykomende terugvoer", |
||||
"Appearance": "voorkoms", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Is jy seker jy wil hierdie klets beëindig?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Is jy seker jy wil hierdie klets skakel en skakel afdeling?", |
||||
"Cancel": "kanselleer", |
||||
"Change": "verandering", |
||||
"Chat_ended": "Klets geëindig!", |
||||
"Choose_a_new_department": "Kies 'n nuwe departement", |
||||
"Close_menu": "Sluit spyskaart", |
||||
"Conversation_finished": "Gesprek afgehandel", |
||||
"End_chat": "Einde klets", |
||||
"How_friendly_was_the_chat_agent": "Hoe vriendelik was die kletsagent?", |
||||
"How_knowledgeable_was_the_chat_agent": "Hoe kundig was die kletsagent?", |
||||
"How_responsive_was_the_chat_agent": "Hoe reageer was die kletsagent?", |
||||
"How_satisfied_were_you_with_this_chat": "Hoe tevrede was jy met hierdie klets?", |
||||
"Installation": "installasie", |
||||
"New_messages": "Nuwe boodskappe", |
||||
"No": "Geen", |
||||
"Options": "opsies", |
||||
"Please_answer_survey": "Neem asseblief 'n oomblik om 'n vinnige opname oor hierdie gesprek te beantwoord", |
||||
"Please_choose_a_department": "Kies asseblief 'n departement", |
||||
"Please_fill_name_and_email": "Vul asb. Naam en e-pos in", |
||||
"Powered_by": "Aangedryf deur", |
||||
"Request_video_chat": "Vra videochat", |
||||
"Select_a_department": "Kies 'n departement", |
||||
"Switch_department": "Skakel afdeling", |
||||
"Department_switched": "Departement aangeskakel", |
||||
"Send": "stuur", |
||||
"Skip": "Huppel", |
||||
"Start_Chat": "Begin Chat", |
||||
"Survey": "opname", |
||||
"Survey_instructions": "Beoordeel elke vraag volgens jou tevredenheid, 1 wat beteken dat jy heeltemal ontevrede is en 5 wat beteken dat jy heeltemal tevrede is.", |
||||
"Thank_you_for_your_feedback": "Dankie vir jou terugvoering", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Dankie! Ons sal binnekort terugkom.", |
||||
"transcript_sent": "Transkripsie gestuur", |
||||
"Type_your_email": "Tik jou e-pos", |
||||
"Type_your_message": "Tik jou boodskap", |
||||
"Type_your_name": "Tik jou naam", |
||||
"Upload_file_question": "Laai leêr op?", |
||||
"User_joined": "Gebruiker aangesluit", |
||||
"User_left": "Gebruiker oor", |
||||
"We_are_not_online_right_now_please_leave_a_message": "Ons is nie aanlyn nie. Asseblief, laat 'n boodskap.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Ons is vanlyn. Jammer vir die ongerief.", |
||||
"Yes": "Ja", |
||||
"You": "jy", |
||||
"You_must_complete_all_fields": "U moet alle velde invul" |
||||
} |
||||
@ -1,48 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "əlavə Əlaqə", |
||||
"Appearance": "Görünüş", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Bu söhbəti bitirməyə əminsinizmi?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Bu söhbəti bitirmək və departamentinizə keçmək istədiyinizə əminsiniz?", |
||||
"Cancel": "Ləğv et", |
||||
"Change": "Change", |
||||
"Chat_ended": "Sohbet sona çatdı!", |
||||
"Choose_a_new_department": "Yeni bir şöbə seçin", |
||||
"Close_menu": "Menüyü bağla", |
||||
"Conversation_finished": "Söhbət başa çatdı", |
||||
"End_chat": "Söhbətə son verin", |
||||
"How_friendly_was_the_chat_agent": "Çağdaş agent nə qədər dost idi?", |
||||
"How_knowledgeable_was_the_chat_agent": "Chat agenti necə məlumatlı idi?", |
||||
"How_responsive_was_the_chat_agent": "Chat agenti necə həssas idi?", |
||||
"How_satisfied_were_you_with_this_chat": "Bu söhbət sizi necə razı etdi?", |
||||
"Installation": "Quraşdırma", |
||||
"New_messages": "Yeni mesajlar", |
||||
"No": "Yox", |
||||
"Options": "Seçimlər", |
||||
"Please_answer_survey": "Bu söhbət haqqında tez bir anketə cavab vermək üçün bir an çəkin", |
||||
"Please_choose_a_department": "Xahiş edirik bölməni seçin", |
||||
"Please_fill_name_and_email": "Xahiş edirik adı və e-poçtu doldurun", |
||||
"Powered_by": "Powered by", |
||||
"Request_video_chat": "Video chatdan istək", |
||||
"Select_a_department": "Bir şöbə seçin", |
||||
"Switch_department": "Şöbə keçid", |
||||
"Department_switched": "Şöbə keçdi", |
||||
"Send": "Göndər", |
||||
"Skip": "Atlayın", |
||||
"Start_Chat": "Chat başlayın", |
||||
"Survey": "Sorğu", |
||||
"Survey_instructions": "Hər sualınızı məmnuniyyətinizə görə qiymətləndirin, 1 mənası tamamilə razı deyilsiniz və 5 mənasını tamamilə məmnun edirsiniz.", |
||||
"Thank_you_for_your_feedback": "Əlaqə üçün təşəkkür edirik", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Təşəkkür edirik! Tezliklə sizə geri dönəcəyik.", |
||||
"transcript_sent": "Transcript göndərildi", |
||||
"Type_your_email": "E-poçtunuzu yazın", |
||||
"Type_your_message": "Mesajınızı yazın", |
||||
"Type_your_name": "Adınızı yazın", |
||||
"Upload_file_question": "Fayl yükləməyiniz?", |
||||
"User_joined": "İstifadəçi qatıldı", |
||||
"User_left": "İstifadəçi buraxdı", |
||||
"We_are_not_online_right_now_please_leave_a_message": "İndi online deyil. Xahiş edirik bir mesaj buraxın.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Biz offline. Narahatçılığa görə üzr istəyirik.", |
||||
"Yes": "Bəli", |
||||
"You": "Sən", |
||||
"You_must_complete_all_fields": "Bütün sahələri doldurmalısınız" |
||||
} |
||||
@ -1,8 +0,0 @@ |
||||
{ |
||||
"Are_you_sure_do_you_want_end_this_chat": "U sombol toy melés i nkwel ?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "U sombol toy melés li yo lini i nyu takbè i departement ipè ?", |
||||
"Change": "héñha", |
||||
"Chat_ended": "I nkwel i mal !", |
||||
"Conversation_finished": "I nkwel i mal !", |
||||
"End_chat": "Il yo li mal" |
||||
} |
||||
@ -1,49 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Дадатковая зваротная сувязь", |
||||
"Appearance": "Знешні выгляд", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Вы ўпэўнены, што жадаеце скончыць гэты чат?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Вы ўпэўненыы, што жадаеце скончыць гэты чат і пераключыць аддзел?", |
||||
"Cancel": "Адмяніць", |
||||
"Change": "Змена", |
||||
"Chat_ended": "Чат завершаны!", |
||||
"Choose_a_new_department": "Выбраць новы аддзел", |
||||
"Close_menu": "Закрыць меню", |
||||
"Conversation_finished": "Размова скончана", |
||||
"End_chat": "Скончыць чат", |
||||
"How_friendly_was_the_chat_agent": "Як дружалюбны быў чат агент?", |
||||
"How_knowledgeable_was_the_chat_agent": "Наколькі кампетэнтны быў супрацоўнік чата?", |
||||
"How_responsive_was_the_chat_agent": "Наколькі спагадны быў супрацоўнік чата?", |
||||
"How_satisfied_were_you_with_this_chat": "Наколькі вы былі задаволены гэтым чатам?", |
||||
"Installation": "Ўстаноўка", |
||||
"New_messages": "Новыя паведамленні", |
||||
"New_livechat_in_queue": "Новы чат у чарзе", |
||||
"No": "Няма", |
||||
"Options": "Опцыі", |
||||
"Please_answer_survey": "Калі ласка, знайдзіце час, каб адказаць на экспрэс-апытанне аб гэтым чаце", |
||||
"Please_choose_a_department": "Калі ласка, выберыце Аддзел", |
||||
"Please_fill_name_and_email": "Запоўніце, калі ласка, імя і адрас электроннай пошты", |
||||
"Powered_by": "Працуе на", |
||||
"Request_video_chat": "Запытаць відыачат", |
||||
"Select_a_department": "Выберыце аддзел", |
||||
"Switch_department": "Змяніць аддзел", |
||||
"Department_switched": "Аддзел пераключыўся", |
||||
"Send": "Паслаць", |
||||
"Skip": "Прапусціць", |
||||
"Start_Chat": "Пачаць чат", |
||||
"Survey": "Апытанне", |
||||
"Survey_instructions": "Ацаніце кожнае пытанне па вашай задаволенасці, 1 азначае, што вы цалкам незадаволеныя і 5 азначае, што вы цалкам задаволеныя.", |
||||
"Thank_you_for_your_feedback": "Дзякуй за ваш водгук", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Дзякуй! Мы звяжамся з вамі ў бліжэйшы час.", |
||||
"transcript_sent": "Cтэнаграма адпраўлена", |
||||
"Type_your_email": "Увядзіце адрас электроннай пошты", |
||||
"Type_your_message": "Увядзіце ваша паведамленне", |
||||
"Type_your_name": "Увядзіце сваё імя", |
||||
"Upload_file_question": "Загрузіць файл?", |
||||
"User_joined": "Карыстальнік далучыўся", |
||||
"User_left": "Карыстальнік выйшаў", |
||||
"We_are_not_online_right_now_please_leave_a_message": "Мы зараз не ў сеткі. Калі ласка, пакіньце паведамленне.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Мы не ў сеткі. Прабачце за дастаўленыя нязручнасці.", |
||||
"Yes": "Да", |
||||
"You": "Вы", |
||||
"You_must_complete_all_fields": "Вам неабходна запоўніць усе палі" |
||||
} |
||||
@ -1,48 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Допълнителни обратни връзки", |
||||
"Appearance": "Външен вид", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Сигурен ли си че искаш да прекратиш този чат?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Наистина ли искате да прекратите този разговор и да превключите отдела?", |
||||
"Cancel": "Отказ", |
||||
"Change": "Промени", |
||||
"Chat_ended": "Край на чата", |
||||
"Choose_a_new_department": "Изберете нов отдел", |
||||
"Close_menu": "Затваряне на менюто", |
||||
"Conversation_finished": "Разговорът завърши", |
||||
"End_chat": "Край на чата", |
||||
"How_friendly_was_the_chat_agent": "Колко приятелски беше чат агентът?", |
||||
"How_knowledgeable_was_the_chat_agent": "Колко интелигентен е агентът за чат?", |
||||
"How_responsive_was_the_chat_agent": "Колко чувствителен беше чат агентът?", |
||||
"How_satisfied_were_you_with_this_chat": "Колко сте доволни от този разговор?", |
||||
"Installation": "Инсталация", |
||||
"New_messages": "Ново съобщение", |
||||
"No": "Не", |
||||
"Options": "Настроики", |
||||
"Please_answer_survey": "Моля, отделете малко време, за да отговорите на кратко проучване за този разговор", |
||||
"Please_choose_a_department": "Моля, изберете отдела", |
||||
"Please_fill_name_and_email": "Моля попълнете име и електрона поща", |
||||
"Powered_by": "Осъществено от", |
||||
"Request_video_chat": "Заявка за видео чат", |
||||
"Select_a_department": "Изберете отдел", |
||||
"Switch_department": "Превключете отдела", |
||||
"Department_switched": "Отделът е включен", |
||||
"Send": "Изпрати", |
||||
"Skip": "Прескочи", |
||||
"Start_Chat": "Започни Чат", |
||||
"Survey": "Изследване", |
||||
"Survey_instructions": "Оценявайте всеки въпрос според вашето удовлетворение, 1 което означава, че сте напълно неудовлетворени и 5, което означава, че сте напълно доволни.", |
||||
"Thank_you_for_your_feedback": "Благодарим Ви за обратната връзка", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Благодаря! Ще се свържем скоро с вас.", |
||||
"transcript_sent": "Преписът е изпратен", |
||||
"Type_your_email": "Въведете имейла си", |
||||
"Type_your_message": "Въведете съобщението си", |
||||
"Type_your_name": "Въведете името си", |
||||
"Upload_file_question": "Качи фаил?", |
||||
"User_joined": "Потребителят се присъедини", |
||||
"User_left": "Потребителят остана", |
||||
"We_are_not_online_right_now_please_leave_a_message": "В момента не сме онлайн. Моля, оставете съобщение.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Ние не сме на линия. Съжалявам за неудобството.", |
||||
"Yes": "Да", |
||||
"You": "Ти", |
||||
"You_must_complete_all_fields": "Трябва да попълните всички полета" |
||||
} |
||||
@ -1,29 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Dodatne povratne informacije", |
||||
"Appearance": "Izgled", |
||||
"Are_you_sure_do_you_want_switch_the_department": "Jeste li sigurni da želite prebaciti odjel?", |
||||
"Cancel": "Otkaži", |
||||
"How_friendly_was_the_chat_agent": "Koliko ugodan je bio agent?", |
||||
"How_knowledgeable_was_the_chat_agent": "Koliko upućen je bio agent?", |
||||
"How_responsive_was_the_chat_agent": "Koliko brzo je odgovarao?", |
||||
"How_satisfied_were_you_with_this_chat": "Koliko ste zadovoljni ovim razgovorom?", |
||||
"Installation": "Instalacija", |
||||
"New_messages": "Nove Poruke", |
||||
"Options": "Opcije", |
||||
"Please_answer_survey": "Odvojite trenutak kako bi odgovorili na anketu o ovom razgovoru", |
||||
"Please_fill_name_and_email": "Molimo Vas da ispunite ime i e-mail", |
||||
"Select_a_department": "Odaberite odjel", |
||||
"Send": "Pošalji", |
||||
"Skip": "Preskoči", |
||||
"Start_Chat": "Početak Razgovora", |
||||
"Survey": "Anketa", |
||||
"Survey_instructions": "Ocijenite svako pitanje u skladu s Vašim zadovoljstvom, 1 znači da ste potpuno nezadovoljni i 5 znači da ste u potpunosti zadovoljni.", |
||||
"Thank_you_for_your_feedback": "Hvala vam na povratnim informacijama", |
||||
"Type_your_email": "Upišite Vaš e-mail", |
||||
"Type_your_message": "Upišite svoju poruku", |
||||
"Type_your_name": "Upišite svoje ime", |
||||
"Upload_file_question": "Prenesi datoteku?", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Mi smo izvan mreže. Oprostite na neugodnosti.", |
||||
"Yes": "Da", |
||||
"You": "Vi" |
||||
} |
||||
@ -1,52 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Comentaris addicionals", |
||||
"Appearance": "Aparença", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Segur que voleu finalitzar aquest xat?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Esteu segurs de finalitzar aquest xat i canviar de departament?", |
||||
"Are_you_sure_do_you_want_switch_the_department": "Segur que voleu canviar de departament?", |
||||
"Cancel": "Cancel·la", |
||||
"Change": "Canvia", |
||||
"Chat_ended": "Xat finalitzat!", |
||||
"Connecting_to_an_Agent": "Connectant amb un agent", |
||||
"Choose_a_new_department": "Tria un nou departament", |
||||
"Close_menu": "Tanca el menú", |
||||
"Conversation_finished": "Conversa acabada", |
||||
"End_chat": "Finalitza xat", |
||||
"How_friendly_was_the_chat_agent": "Ha sigut amable l'interlocutor?", |
||||
"How_knowledgeable_was_the_chat_agent": "Era un bon expert, en sabia?", |
||||
"How_responsive_was_the_chat_agent": "Heu rebut respostes ràpides?", |
||||
"How_satisfied_were_you_with_this_chat": "Ha quedat satisfet amb aquesta conversa?", |
||||
"Installation": "Instal·lació", |
||||
"New_messages": "Nous missatges", |
||||
"New_livechat_in_queue": "Nou xat a la cua", |
||||
"No": "No", |
||||
"Options": "Opcions", |
||||
"Please_answer_survey": "Si us plau, permeti'ns un moment per a una breu enquesta sobre aquest xat", |
||||
"Please_choose_a_department": "Si us plau, tria un departament", |
||||
"Please_fill_name_and_email": "Si us plau, omple el nom i l'adreça electrònica.", |
||||
"Please_wait_for_the_next_available_agent": "Si us plau, espereu el següent agent disponible.", |
||||
"Powered_by": "Funciona amb", |
||||
"Request_video_chat": "Demana vídeo xat", |
||||
"Select_a_department": "Selecciona un departament", |
||||
"Switch_department": "Canvia departament", |
||||
"Department_switched": "Departament canviat", |
||||
"Send": "Envia", |
||||
"Skip": "Salta", |
||||
"Start_Chat": "Inicia xat", |
||||
"Survey": "Enquesta", |
||||
"Survey_instructions": "Valoreu cada pregunta d'acord al nivell de satisfacció, sent 1 completament insatisfet i 5 completament satisfet.", |
||||
"Thank_you_for_your_feedback": "Gràcies per la teva col·laboració", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Gràcies! Aviat ens posarem en contacte.", |
||||
"transcript_sent": "Transcripció enviada", |
||||
"Type_your_email": "Escriu la teva adreça de correu-e", |
||||
"Type_your_message": "Escriu el missatge", |
||||
"Type_your_name": "Escriu el teu nom", |
||||
"Upload_file_question": "Pujar l'arxiu?", |
||||
"User_joined": "usuari unit", |
||||
"User_left": "L'usuari ha abandonat la sala", |
||||
"We_are_not_online_right_now_please_leave_a_message": "No estem en línia ara mateix. Sisplau, deixa un missatge.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Estem desconnectats. Disculpi les molèsties.", |
||||
"Yes": "Sí", |
||||
"You": "Tu", |
||||
"You_must_complete_all_fields": "Cal omplir tots els camps" |
||||
} |
||||
@ -1,52 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Dodatečný Feedback", |
||||
"Appearance": "Vzhled", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Opravdu chcete ukončit tuto konverzaci?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Opravdu ukončit tento chat a změnit oddělení?", |
||||
"Are_you_sure_do_you_want_switch_the_department": "Chcete změnit oddělení", |
||||
"Cancel": "Storno", |
||||
"Change": "Změnit", |
||||
"Chat_ended": "Konverzace ukončena!", |
||||
"Connecting_to_an_Agent": "Spojování s operátorem", |
||||
"Choose_a_new_department": "Vyberte nové oddělení", |
||||
"Close_menu": "Zavřít menu", |
||||
"Conversation_finished": "Konverzace ukončena", |
||||
"End_chat": "Ukončit konverzaci", |
||||
"How_friendly_was_the_chat_agent": "Byl operátor milý?", |
||||
"How_knowledgeable_was_the_chat_agent": "Věděl operátor jak vám pomoci?", |
||||
"How_responsive_was_the_chat_agent": "Odpovídal operátor rychle?", |
||||
"How_satisfied_were_you_with_this_chat": "Jak jste byli celkově spokojeni?", |
||||
"Installation": "Instalace", |
||||
"New_messages": "Nové zprávy", |
||||
"New_livechat_in_queue": "Nová konverzace ve frontě", |
||||
"No": "Ne", |
||||
"Options": "Volby", |
||||
"Please_answer_survey": "Věnujte nám prosím chvilku svého času na ohodnocení chatu.", |
||||
"Please_choose_a_department": "Prosím vyberte oddělení", |
||||
"Please_fill_name_and_email": "Prosím vyplňte jméno a e-mail", |
||||
"Please_wait_for_the_next_available_agent": "Počkejte prosím na dalšího dostupného operátora", |
||||
"Powered_by": "Používá technologii", |
||||
"Request_video_chat": "Zažádat o video chat", |
||||
"Select_a_department": "Vyberte oddělení", |
||||
"Switch_department": "Změnit oddělení", |
||||
"Department_switched": "Oddělení změněno", |
||||
"Send": "Poslat", |
||||
"Skip": "Přeskočit", |
||||
"Start_Chat": "Spustit chat", |
||||
"Survey": "Průzkum", |
||||
"Survey_instructions": "Hodnoťte každou otázku dle vaší spokojenosti, 1 - zcela NEspokojeni a 5 - zcela spokojeni.", |
||||
"Thank_you_for_your_feedback": "Děkujeme Vám za Vaše hodnocení", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Díky! Odpovíme Vám co nejdříve.", |
||||
"transcript_sent": "Kopie konverzace odeslána", |
||||
"Type_your_email": "Zadejte svůj e-mail", |
||||
"Type_your_message": "Napište zprávu", |
||||
"Type_your_name": "Zadejte své jméno", |
||||
"Upload_file_question": "Nahrát soubor?", |
||||
"User_joined": "Uživatel se připojil", |
||||
"User_left": "Uživatel odešel", |
||||
"We_are_not_online_right_now_please_leave_a_message": "Zrovna nejsme online. Zanechte nám prosím zprávu.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Jsme offline. Omluváme se za nepříjemnosti.", |
||||
"Yes": "Ano", |
||||
"You": "Vy", |
||||
"You_must_complete_all_fields": "Je potřeba vyplnit všechna pole" |
||||
} |
||||
@ -1,48 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Adborth Ychwanegol", |
||||
"Appearance": "Ymddangosiad", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Ydych chi'n siŵr eich bod am roi'r gorau i'r sgwrs hon?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Ydych chi'n siŵr eich bod am roi'r gorau i'r sgwrs hon a newid adran?", |
||||
"Cancel": "Diddymu", |
||||
"Change": "Newid", |
||||
"Chat_ended": "Daeth sgwrs i ben!", |
||||
"Choose_a_new_department": "Dewiswch adran newydd", |
||||
"Close_menu": "Dewislen agos", |
||||
"Conversation_finished": "Mae'r sgwrs wedi gorffen", |
||||
"End_chat": "Cam sgwrsio", |
||||
"How_friendly_was_the_chat_agent": "Pa mor gyfeillgar oedd yr asiant sgwrsio?", |
||||
"How_knowledgeable_was_the_chat_agent": "Pa mor wybodus oedd yr asiant sgwrsio?", |
||||
"How_responsive_was_the_chat_agent": "Pa mor ymatebol oedd yr asiant sgwrsio?", |
||||
"How_satisfied_were_you_with_this_chat": "Pa mor fodlon oeddech chi â'r sgwrs hon?", |
||||
"Installation": "Gosod", |
||||
"New_messages": "Negeseuon newydd", |
||||
"No": "Na", |
||||
"Options": "Dewisiadau", |
||||
"Please_answer_survey": "Cymerwch foment i ateb arolwg cyflym am y sgwrs hon", |
||||
"Please_choose_a_department": "Dewiswch adran", |
||||
"Please_fill_name_and_email": "Llenwch enw ac e-bost", |
||||
"Powered_by": "Wedi ei bweru gan", |
||||
"Request_video_chat": "Gwneud cais am sgwrs fideo", |
||||
"Select_a_department": "Dewiswch adran", |
||||
"Switch_department": "Newid adran", |
||||
"Department_switched": "Adran wedi newid", |
||||
"Send": "Anfon", |
||||
"Skip": "Skip", |
||||
"Start_Chat": "Dechrau Sgwrs", |
||||
"Survey": "Arolwg", |
||||
"Survey_instructions": "Cyfraddwch bob cwestiwn yn ôl eich boddhad, 1 sy'n golygu eich bod chi'n gwbl anfodlon a 5 yn golygu eich bod chi'n gwbl fodlon.", |
||||
"Thank_you_for_your_feedback": "Diolch i chi am eich adborth", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Diolch! Byddwn yn dychwelyd atoch yn fuan.", |
||||
"transcript_sent": "Trawsgrifiad wedi'i anfon", |
||||
"Type_your_email": "Teipiwch eich e-bost", |
||||
"Type_your_message": "Teipiwch eich neges", |
||||
"Type_your_name": "Teipiwch eich enw", |
||||
"Upload_file_question": "Llwytho ffeil?", |
||||
"User_joined": "Ymunodd y defnyddiwr", |
||||
"User_left": "Defnyddiwr ar ôl", |
||||
"We_are_not_online_right_now_please_leave_a_message": "Nid ydym ar-lein ar hyn o bryd. Os gwelwch yn dda, gadewch neges.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Rydym ni allan. Mae'n ddrwg gennym am yr anghyfleustra.", |
||||
"Yes": "Ydw", |
||||
"You": "Chi", |
||||
"You_must_complete_all_fields": "Rhaid i chi gwblhau pob maes" |
||||
} |
||||
@ -1,51 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Yderligere feedback", |
||||
"Appearance": "Udseende", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Er du sikker på, at du vil afslutte denne chat?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Er du sikker på, at du vil afslutte denne chat og skifte afdeling?", |
||||
"Are_you_sure_do_you_want_switch_the_department": "Er du sikker på, at du vil skifte afdeling?", |
||||
"Cancel": "Annuller", |
||||
"Change": "Skift", |
||||
"Chat_ended": "Chat afsluttet!", |
||||
"Connecting_to_an_Agent": "Forbindelse til en agent", |
||||
"Choose_a_new_department": "Vælg en ny afdeling", |
||||
"Close_menu": "Luk menuen", |
||||
"Conversation_finished": "Samtalen er slut", |
||||
"End_chat": "Afslut chat", |
||||
"How_friendly_was_the_chat_agent": "Hvor venlig var chatagenten?", |
||||
"How_knowledgeable_was_the_chat_agent": "Hvor vidende var chatagenten?", |
||||
"How_responsive_was_the_chat_agent": "Hvor lydhør var chatagenten?", |
||||
"How_satisfied_were_you_with_this_chat": "Hvor tilfreds var du med denne chat?", |
||||
"Installation": "Installation", |
||||
"New_messages": "Nye beskeder", |
||||
"New_livechat_in_queue": "Ny chat i kø", |
||||
"No": "Nej", |
||||
"Options": "Indstillinger", |
||||
"Please_answer_survey": "Brug et øjeblik på at besvare et spørgeskema om denne chat", |
||||
"Please_choose_a_department": "Vælg venligst en afdeling", |
||||
"Please_fill_name_and_email": "Udfyld venligst navn og e-mail", |
||||
"Powered_by": "Drevet af", |
||||
"Request_video_chat": "Anmod om videochat", |
||||
"Select_a_department": "Vælg en afdeling", |
||||
"Switch_department": "Skift afdeling", |
||||
"Department_switched": "Du har skiftet afdeling", |
||||
"Send": "Send", |
||||
"Skip": "Spring over", |
||||
"Start_Chat": "Start chat", |
||||
"Survey": "Spørgeskema", |
||||
"Survey_instructions": "Vurder hvert spørgsmål efter din tilfredshed: 1 betyder, at du er helt utilfreds, og 5 betyder, at du er helt tilfreds.", |
||||
"Thank_you_for_your_feedback": "Tak for din feedback", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Tak! Vi vender snart tilbage.", |
||||
"transcript_sent": "Transskription sendt", |
||||
"Type_your_email": "Indtast din e-mail", |
||||
"Type_your_message": "Skriv din besked", |
||||
"Type_your_name": "Indtast dit navn", |
||||
"Upload_file_question": "Upload fil?", |
||||
"User_joined": "Brugeren sluttede sig til", |
||||
"User_left": "Brugeren tog sin afsked", |
||||
"We_are_not_online_right_now_please_leave_a_message": "Vi er ikke online lige nu. Efterlad en besked til os.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Vi er offline. Beklager ulejligheden.", |
||||
"Yes": "Ja", |
||||
"You": "Du", |
||||
"You_must_complete_all_fields": "Du skal udfylde alle felter" |
||||
} |
||||
@ -1,50 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Zusätzliches Feedback", |
||||
"Appearance": "Erscheinungsbild", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Sind Sie sich sicher diesen Chat zu beenden?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Möchtest du diesen Chat wirklich beenden und die Abteilung wechseln?", |
||||
"Cancel": "Abbrechen", |
||||
"Change": "Veränderung", |
||||
"Chat_ended": "Chat beendet!", |
||||
"Connecting_to_an_Agent": "Verbinde mit einem Berater/in", |
||||
"Choose_a_new_department": "Wählen Sie eine neue Abteilung", |
||||
"Close_menu": "Menü schließen", |
||||
"Conversation_finished": "Gespräch beendet", |
||||
"End_chat": "Chat beenden", |
||||
"How_friendly_was_the_chat_agent": "Wie freundlich war der/die Berater/in?", |
||||
"How_knowledgeable_was_the_chat_agent": "Wie sachkundig war der Chat-Berater?", |
||||
"How_responsive_was_the_chat_agent": "Wie reaktionsschnell war der Chat-Agent?", |
||||
"How_satisfied_were_you_with_this_chat": "Wie zufrieden sind Sie mit diesem Gespräch?", |
||||
"Installation": "Installation", |
||||
"New_messages": "Neue Nachrichten", |
||||
"No": "Nein", |
||||
"Options": "Optionen", |
||||
"Please_answer_survey": "Bitte nehmen Sie sich einen Moment Zeit, um kurz einige Fragen zu dem Gespräch zu beantworten.", |
||||
"Please_choose_a_department": "Bitte wählen Sie eine Abteilung", |
||||
"Please_fill_name_and_email": "Bitte geben Sie einen Namen und eine E-Mail-Adresse ein.", |
||||
"Please_wait_for_the_next_available_agent": "Bitte warten bis eine Beratung frei wird", |
||||
"Powered_by": "Unterstützt von", |
||||
"Request_video_chat": "Video Chat anfragen", |
||||
"Select_a_department": "Abteilung auswählen", |
||||
"Switch_department": "Abteilung wechseln", |
||||
"Department_switched": "Abteilung gewechselt", |
||||
"Send": "Senden", |
||||
"Skip": "Überspringen", |
||||
"Start_Chat": "Chat beginnen", |
||||
"Survey": "Umfrage", |
||||
"Survey_instructions": "Bewerten Sie jede Frage nach Ihrer Zufriedenheit. 1 bedeutet, dass Sie völlig unzufrieden sind und 5 bedeutet, dass Sie vollständig zufrieden sind.", |
||||
"Thank_you_for_your_feedback": "Vielen Dank für Ihre Rückmeldung.", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Vielen Dank! Wir kommen auf Sie zeitnah zurück.", |
||||
"transcript_sent": "Transkript versendet", |
||||
"Type_your_email": "Geben Sie Ihre E-Mail-Adresse an", |
||||
"Type_your_message": "Geben Sie Ihre Nachricht ein.", |
||||
"Type_your_name": "Geben Sie Ihren Namen ein", |
||||
"Upload_file_question": "Möchten Sie eine Datei hochladen?", |
||||
"User_joined": "Benutzer.in wurde Mitglied", |
||||
"User_left": "Benutzer.in abgemeldet", |
||||
"We_are_not_online_right_now_please_leave_a_message": "Wir sind momentan nicht online. Bitte hinterlassen Sie eine Nachricht.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Wir sind offline. Entschuldigen Sie die Unannehmlichkeiten.", |
||||
"Yes": "Ja", |
||||
"You": "Sie", |
||||
"You_must_complete_all_fields": "Sie müssen alle Felder ausfüllen" |
||||
} |
||||
@ -1,52 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Zusätzliches Feedback", |
||||
"Appearance": "Erscheinungsbild", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Sind Sie sich sicher, dass Sie diesen Chat beenden wollen?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Sind Sie sich sicher, dass Sie diesen Chat beenden und die Abteilung wechseln wollen?", |
||||
"Are_you_sure_do_you_want_switch_the_department": "Sind Sie sich sicher, das Sie die Abteilung wechseln möchten?", |
||||
"Cancel": "Abbrechen", |
||||
"Change": "Ändern", |
||||
"Chat_ended": "Chat beendet!", |
||||
"Connecting_to_an_Agent": "Verbinde mit einem Berater/in", |
||||
"Choose_a_new_department": "Wählen Sie eine neue Abteilung aus", |
||||
"Close_menu": "Menü schließen", |
||||
"Conversation_finished": "Gespräch beendet", |
||||
"End_chat": "Chat beenden", |
||||
"How_friendly_was_the_chat_agent": "Wie freundlich war der/die Berater/in?", |
||||
"How_knowledgeable_was_the_chat_agent": "Wie sachkundig war der Chat-Berater?", |
||||
"How_responsive_was_the_chat_agent": "Wie reaktionsschnell war der Chat-Agent?", |
||||
"How_satisfied_were_you_with_this_chat": "Wie zufrieden sind Sie mit diesem Gespräch?", |
||||
"Installation": "Installation", |
||||
"New_messages": "Neue Nachrichten", |
||||
"New_livechat_in_queue": "Neuer Chat in der Wartschlange", |
||||
"No": "Nein", |
||||
"Options": "Optionen", |
||||
"Please_answer_survey": "Bitte nehmen Sie sich einen Moment Zeit, um kurz einige Fragen zu dem Gespräch zu beantworten.", |
||||
"Please_choose_a_department": "Bitte wählen Sie eine Abteilung aus", |
||||
"Please_fill_name_and_email": "Bitte gib Sie Ihren Namen und Ihre E-Mail-Adresse ein", |
||||
"Please_wait_for_the_next_available_agent": "Bitte warten bis eine Beratung frei wird", |
||||
"Powered_by": "Angetrieben von", |
||||
"Request_video_chat": "Video-Chat anfragen", |
||||
"Select_a_department": "Abteilung auswählen", |
||||
"Switch_department": "Abteilung wechseln", |
||||
"Department_switched": "Abteilung wurde gewechselt", |
||||
"Send": "Senden", |
||||
"Skip": "Überspringen", |
||||
"Start_Chat": "Chat beginnen", |
||||
"Survey": "Umfrage", |
||||
"Survey_instructions": "Bewerte jede Frage: 1 bedeutet, \"total unzufrieden\", 5 \"vollständig zufrieden\".", |
||||
"Thank_you_for_your_feedback": "Vielen Dank für Ihre Rückmeldung", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Vielen Dank! Wir kommen zeitnah auf Sie zurück.", |
||||
"transcript_sent": "Transkript versendet", |
||||
"Type_your_email": "Geben Sie Ihre E-Mail-Adresse an", |
||||
"Type_your_message": "Geben Sie Ihre Nachricht ein.", |
||||
"Type_your_name": "Geben Sie Ihren Namen ein", |
||||
"Upload_file_question": "Datei hochladen?", |
||||
"User_joined": "Benutzer.in ist dem Kanal beigetreten", |
||||
"User_left": "Benutzer.in hat den Kanal verlassen", |
||||
"We_are_not_online_right_now_please_leave_a_message": "Wir sind momentan nicht online. Bitte hinterlassen Sie eine Nachricht.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Tut uns leid, aber wir sind offline.", |
||||
"Yes": "Ja", |
||||
"You": "Sie", |
||||
"You_must_complete_all_fields": "Sie müssen alle Felder ausfüllen" |
||||
} |
||||
@ -1,48 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Πρόσθετα Σχόλια", |
||||
"Appearance": "Εμφάνιση", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Είστε σίγουρος ότι θέλετε να τερματίσετε τη συνομιλία;", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Είστε σίγουρος ότι θέλετε να τερματίσετε τη συνομιλία και να αλλάξετε τμήμα;", |
||||
"Cancel": "Ακύρωση", |
||||
"Change": "Αλλαγή", |
||||
"Chat_ended": "Η συνομιλία τελείωσε!", |
||||
"Choose_a_new_department": "Διαλέξτε ένα νέο τμήμα", |
||||
"Close_menu": "Κλείσιμο μενού", |
||||
"Conversation_finished": "Η συνομιλία τελείωσε", |
||||
"End_chat": "Τερματισμός συνομιλίας", |
||||
"How_friendly_was_the_chat_agent": "Πόσο φιλικός ήταν ο εκπρόσωπος μας;", |
||||
"How_knowledgeable_was_the_chat_agent": "Πόσο γνώστης του θέματος ήταν ο εκπρόσωπος μας;", |
||||
"How_responsive_was_the_chat_agent": "Πόσο καλή ανταπόκριση είχε ο εκπρόσωπος μας;", |
||||
"How_satisfied_were_you_with_this_chat": "Πόσο ικανοποιημένοι μείνατε με αυτήν την συνομιλία;", |
||||
"Installation": "Εγκατάσταση", |
||||
"New_messages": "Νέα μηνύματα", |
||||
"No": "Όχι", |
||||
"Options": "Επιλογές", |
||||
"Please_answer_survey": "Αφιερώστε λίγο χρόνο για να απαντήσετε σε μια σύντομη έρευνα σχετικά με αυτή τη συνομιλία", |
||||
"Please_choose_a_department": "Παρακαλούμε επιλέξτε τμήμα", |
||||
"Please_fill_name_and_email": "Παρακαλούμε συμπληρώστε το όνομα και το e-mail σας", |
||||
"Powered_by": "Powered by", |
||||
"Request_video_chat": "Αίτηση συνομιλίας με βίντεο", |
||||
"Select_a_department": "Επιλέξτε ένα τμήμα", |
||||
"Switch_department": "Αλλαγή τμήματος", |
||||
"Department_switched": "Το τμήμα άλλαξε", |
||||
"Send": "Αποστολή", |
||||
"Skip": "Παράλειψη", |
||||
"Start_Chat": "Έναρξη συνομιλίας", |
||||
"Survey": "Έρευνα", |
||||
"Survey_instructions": "Βαθμολογήστε κάθε ερώτηση, σύμφωνα με την ικανοποίησή σας, 1 που σημαίνει ότι μείνατε δυσαρεστημένοι και 5 σημαίνει ότι είστε απόλυτα ικανοποιημένοι.", |
||||
"Thank_you_for_your_feedback": "Ευχαριστούμε για τα σχόλιά σας", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Ευχαριστούμε! Θα επικοινωνήσουμε μαζί σας σύντομα.", |
||||
"transcript_sent": "Το αντίγραφο της συνομιλίας στάλθηκε", |
||||
"Type_your_email": "Πληκτρολογήστε το email σας", |
||||
"Type_your_message": "Πληκτρολογήστε το μήνυμά σας", |
||||
"Type_your_name": "Πληκτρολογήστε το όνομά σας", |
||||
"Upload_file_question": "Να ανέβει το αρχείο;", |
||||
"User_joined": "Ο χρήστης συνδέθηκε", |
||||
"User_left": "Ο χρήστης έφυγε", |
||||
"We_are_not_online_right_now_please_leave_a_message": "Δεν είμαστε συνδεδεμένοι αυτήν τη στιγμή. Παρακαλώ αφήστε μήνυμα.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Είμαστε εκτός σύνδεσης. Συγγνώμη για την ταλαιπωρία.", |
||||
"Yes": "Ναι", |
||||
"You": "Εσύ", |
||||
"You_must_complete_all_fields": "Πρέπει να συμπληρώσετε όλα τα πεδία" |
||||
} |
||||
@ -1,52 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Additional Feedback", |
||||
"Appearance": "Appearance", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Are you sure you want to end this chat?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Are you sure you want to end this chat and switch department?", |
||||
"Are_you_sure_do_you_want_switch_the_department": "Are you sure you want to switch the department?", |
||||
"Cancel": "Cancel", |
||||
"Change": "Change", |
||||
"Chat_ended": "Chat ended!", |
||||
"Connecting_to_an_Agent": "Connecting to an Agent", |
||||
"Choose_a_new_department": "Choose a new department", |
||||
"Close_menu": "Close menu", |
||||
"Conversation_finished": "Conversation finished", |
||||
"End_chat": "End chat", |
||||
"How_friendly_was_the_chat_agent": "How friendly was the chat agent?", |
||||
"How_knowledgeable_was_the_chat_agent": "How knowledgeable was the chat agent?", |
||||
"How_responsive_was_the_chat_agent": "How responsive was the chat agent?", |
||||
"How_satisfied_were_you_with_this_chat": "How satisfied were you with this chat?", |
||||
"Installation": "Installation", |
||||
"New_messages": "New messages", |
||||
"New_livechat_in_queue": "New chat in queue", |
||||
"No": "No", |
||||
"Options": "Options", |
||||
"Please_answer_survey": "Please take a moment to answer a quick survey about this chat", |
||||
"Please_choose_a_department": "Please choose a department", |
||||
"Please_fill_name_and_email": "Please fill name and email", |
||||
"Please_wait_for_the_next_available_agent": "Please, wait for the next available agent.", |
||||
"Powered_by": "Powered by", |
||||
"Request_video_chat": "Request video chat", |
||||
"Select_a_department": "Select a department", |
||||
"Switch_department": "Switch department", |
||||
"Department_switched": "Department switched", |
||||
"Send": "Send", |
||||
"Skip": "Skip", |
||||
"Start_Chat": "Start Chat", |
||||
"Survey": "Survey", |
||||
"Survey_instructions": "Rate each question according to your satisfaction, 1 meaning you are completely unsatisfied and 5 meaning you are completely satisfied.", |
||||
"Thank_you_for_your_feedback": "Thank you for your feedback", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Thanks! We'll get back to you soon.", |
||||
"transcript_sent": "Transcript sent", |
||||
"Type_your_email": "Type your email", |
||||
"Type_your_message": "Type your message", |
||||
"Type_your_name": "Type your name", |
||||
"Upload_file_question": "Upload file?", |
||||
"User_joined": "User joined", |
||||
"User_left": "User left", |
||||
"We_are_not_online_right_now_please_leave_a_message": "We are not online right now. Please, leave a message.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "We are offline. Sorry for the inconvenience.", |
||||
"Yes": "Yes", |
||||
"You": "You", |
||||
"You_must_complete_all_fields": "You must complete all fields" |
||||
} |
||||
@ -1,48 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Kromaj Rimarkojn", |
||||
"Appearance": "Aspekto", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Ĉu vi certas, ke vi volas fini ĉi tiun babilejon?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Ĉu vi certas, ke vi volas fini ĉi tiun babilejon kaj ŝanĝi la fakon?", |
||||
"Cancel": "Nuligi", |
||||
"Change": "Ŝanĝi", |
||||
"Chat_ended": "Babilejo finiĝis!", |
||||
"Choose_a_new_department": "Elektu novan fakon", |
||||
"Close_menu": "Fermi menuon", |
||||
"Conversation_finished": "Konversacio finis", |
||||
"End_chat": "Fina babilejo", |
||||
"How_friendly_was_the_chat_agent": "Kiel amika estis la babila agento?", |
||||
"How_knowledgeable_was_the_chat_agent": "Kiel scivola estis la babila agento?", |
||||
"How_responsive_was_the_chat_agent": "Kiel respondema estis la babila agento?", |
||||
"How_satisfied_were_you_with_this_chat": "Kiel kontenta vi estis kun ĉi tiu babilejo?", |
||||
"Installation": "Instalado", |
||||
"New_messages": "Novaj mesaĝoj", |
||||
"No": "Ne", |
||||
"Options": "Opcioj", |
||||
"Please_answer_survey": "Bonvolu preni momenton por respondi rapidan enketon pri ĉi tiu babilejo", |
||||
"Please_choose_a_department": "Bonvolu elekti fakon", |
||||
"Please_fill_name_and_email": "Bonvolu plenigi nomon kaj retpoŝton", |
||||
"Powered_by": "Funkciigita de", |
||||
"Request_video_chat": "Petu video-babilejon", |
||||
"Select_a_department": "Elektu fakon", |
||||
"Switch_department": "Ŝalti fako", |
||||
"Department_switched": "Fako ŝaltis", |
||||
"Send": "Sendu", |
||||
"Skip": "Preterpasi", |
||||
"Start_Chat": "Komencu babilejon", |
||||
"Survey": "Enketo", |
||||
"Survey_instructions": "Taksi ĉiun demandon laŭ via kontentigo, 1 signifante, ke vi estas tute malkontenta kaj 5 signifas, ke vi estas tute kontenta.", |
||||
"Thank_you_for_your_feedback": "Dankon pro viaj sugestoj", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Dankon! Ni revenos al vi baldaŭ.", |
||||
"transcript_sent": "Transskribo sendita", |
||||
"Type_your_email": "Tajpu vian retpoŝton", |
||||
"Type_your_message": "Tajpu vian mesaĝon", |
||||
"Type_your_name": "Tajpu vian nomon", |
||||
"Upload_file_question": "Alŝutu dosieron?", |
||||
"User_joined": "Uzanto aliĝis", |
||||
"User_left": "Uzanto maldekstre", |
||||
"We_are_not_online_right_now_please_leave_a_message": "Ni ne estas interrete nun. Bonvolu lasi mesaĝon.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Ni estas eksterrete. Pardonu la malkomforton.", |
||||
"Yes": "Jes", |
||||
"You": "Vi", |
||||
"You_must_complete_all_fields": "Vi devas kompletigi ĉiujn kampojn" |
||||
} |
||||
@ -1,52 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Comentarios adicionales", |
||||
"Appearance": "Apariencia", |
||||
"Are_you_sure_do_you_want_end_this_chat": "¿Estás seguro de que quieres terminar este chat?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "¿Estás seguro de que quieres terminar este chat y cambiar de departamento?", |
||||
"Are_you_sure_do_you_want_switch_the_department": "¿Está seguro que quiere cambiar el departamento?", |
||||
"Cancel": "Cancelar", |
||||
"Change": "Cambiar", |
||||
"Chat_ended": "Chat finalizado!", |
||||
"Connecting_to_an_Agent": "Conectando al Agente", |
||||
"Choose_a_new_department": "Selecciona un nuevo departamento", |
||||
"Close_menu": "Cerrar menú", |
||||
"Conversation_finished": "Conversación terminada", |
||||
"End_chat": "Finalizar chat", |
||||
"How_friendly_was_the_chat_agent": "¿Qué tan amigable fue el agente de chat?", |
||||
"How_knowledgeable_was_the_chat_agent": "¿Qué tan conocedor fue el agente de chat?", |
||||
"How_responsive_was_the_chat_agent": "¿Qué tan receptivo fue el agente de chat?", |
||||
"How_satisfied_were_you_with_this_chat": "¿Qué tan satisfecho estuviste con este chat?", |
||||
"Installation": "Instalación ", |
||||
"New_messages": "Nuevos mensajes", |
||||
"New_livechat_in_queue": "Nuevo chat en cola", |
||||
"No": "No", |
||||
"Options": "Opciones", |
||||
"Please_answer_survey": "Por favor, tómese un momento para responder una breve encuesta sobre este chat", |
||||
"Please_choose_a_department": "Por favor selecciona un departamento", |
||||
"Please_fill_name_and_email": "Por favor introduzca su nombre y correo electrónico.", |
||||
"Please_wait_for_the_next_available_agent": "Por favor, espera al siguiente agente disponible.", |
||||
"Powered_by": "Impulsado por", |
||||
"Request_video_chat": "Solicitar videochat", |
||||
"Select_a_department": "Seleccione un departamento", |
||||
"Switch_department": "Cambiar de departamento", |
||||
"Department_switched": "Departamento cambiado", |
||||
"Send": "Enviar", |
||||
"Skip": "Omitir", |
||||
"Start_Chat": "Iniciar chat", |
||||
"Survey": "Encuesta", |
||||
"Survey_instructions": "Califique cada pregunta de acuerdo a su nivel de satisfacción, 1 para completamente insatisfecho y 5 para completamente satisfecho.", |
||||
"Thank_you_for_your_feedback": "Gracias por sus comentarios", |
||||
"Thanks_We_ll_get_back_to_you_soon": "¡Gracias! Pronto nos pondremos en contacto con usted.", |
||||
"transcript_sent": "Transcripción enviada", |
||||
"Type_your_email": "Escriba su correo electrónico", |
||||
"Type_your_message": "Escriba su mensaje", |
||||
"Type_your_name": "Escriba su nombre", |
||||
"Upload_file_question": "Subir archivo?", |
||||
"User_joined": "Usuario unido", |
||||
"User_left": "El usuario ha abandonado la sala", |
||||
"We_are_not_online_right_now_please_leave_a_message": "No estamos en línea en este momento. Por favor, deje un mensaje.", |
||||
"We_are_offline_Sorry_for_the_inconvenience": "Estamos fuera de línea. Disculpe las molestias.", |
||||
"Yes": "Si", |
||||
"You": "Usted", |
||||
"You_must_complete_all_fields": "Debes completar todos los campos" |
||||
} |
||||
@ -1,44 +0,0 @@ |
||||
{ |
||||
"Additional_Feedback": "Täiendav tagasiside", |
||||
"Appearance": "Välimus", |
||||
"Are_you_sure_do_you_want_end_this_chat": "Oled sa kindel, et soovid vestlust lõpetada?", |
||||
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Oled sa kindel, et soovid lõpetada vestlust ja vahetada osakonda?", |
||||
"Are_you_sure_do_you_want_switch_the_department": "Oled sa kindel, et soovid osakonda vahetada?", |
||||
"Cancel": "Tühista", |
||||
"Change": "Muuda", |
||||
"Chat_ended": "Vestlus on lõppenud!", |
||||
"Choose_a_new_department": "Vali uus osakond", |
||||
"Close_menu": "Sulge menüü", |
||||
"Conversation_finished": "Vestlus on lõppenud", |
||||
"End_chat": "Lõpeta vestlus", |
||||
"How_friendly_was_the_chat_agent": "Kui sõbralik oli sinuga vestelnud agent?", |
||||
"How_knowledgeable_was_the_chat_agent": "Kui teadlik oli sinuga vestelnud agent? ", |
||||
"How_responsive_was_the_chat_agent": "Kui vastuvõtlik oli sinuga vestelnud agent? ", |
||||
"How_satisfied_were_you_with_this_chat": "Kui rahul olite selle vestlusega?", |
||||
"Installation": "Paigaldamine", |
||||
"New_messages": "Uued teated", |
||||
"New_livechat_in_queue": "Uus vestlus järjekorras", |
||||
"No": "Ei", |
||||
"Options": "Valikud", |
||||
"Please_answer_survey": "Palun võtke hetk, et vastata kiirele küsitlusele toimunud vestluse kohta", |
||||
"Please_choose_a_department": "Palun vali osakond", |
||||
"Please_fill_name_and_email": "Palun täitke nimi ja e-posti aadress", |
||||
"Powered_by": "Toetab", |
||||
"Request_video_chat": "Alusta videokõne", |
||||
"Select_a_department": "Valige osakond", |
||||
"Switch_department": "Vahetage osakonda", |
||||
"Department_switched": "Osakond vahetatud", |
||||
"Send": "Saada", |
||||
"Skip": "Jäta vahele", |
||||
"Start_Chat": "Alusta vestlust", |
||||
"Survey": "Uuring", |
||||
"Thank_you_for_your_feedback": "Aitäh tagasiside eest", |
||||
"Thanks_We_ll_get_back_to_you_soon": "Aitäh! Võtame sinuga peagi ühendust. ", |
||||
"transcript_sent": "Vestluse ajalugu saadetud", |
||||
"Type_your_email": "Sisesta oma e-mail", |
||||
"Type_your_message": "Sisestage oma sõnum", |
||||
"Type_your_name": "Sisestage oma nimi", |
||||
"Upload_file_question": "Faili üles laadima?", |
||||
"User_joined": "Kasutaja liitus", |
||||
"User_left": "Kasutaja lahkus" |
||||
} |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue