[BREAK] remove old livechat client (#15133)

pull/14885/head^2
Guilherme Gazzo 6 years ago committed by GitHub
parent c0f106b2f8
commit 5fdd2f2bcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .scripts/fix-i18n.js
  2. 2
      .scripts/npm-postinstall.js
  3. 505
      app/livechat/client/stylesheets/livechat.less
  4. 309
      app/livechat/client/views/app/livechatAppearance.html
  5. 101
      app/livechat/client/views/app/livechatAppearance.js
  6. 10
      app/livechat/client/views/app/livechatInstallation.html
  7. 20
      app/livechat/client/views/app/livechatInstallation.js
  8. 28
      app/livechat/lib/Assets.js
  9. 9
      app/livechat/server/livechat.js
  10. 1417
      package-lock.json
  11. 1
      package.json
  12. 1
      packages/rocketchat-i18n/i18n/de-IN.i18n.json
  13. 3
      packages/rocketchat-i18n/i18n/de.i18n.json
  14. 3
      packages/rocketchat-i18n/i18n/en.i18n.json
  15. 1
      packages/rocketchat-i18n/i18n/hu.i18n.json
  16. 3
      packages/rocketchat-i18n/i18n/ja.i18n.json
  17. 3
      packages/rocketchat-i18n/i18n/pt-BR.i18n.json
  18. 3
      packages/rocketchat-i18n/i18n/pt.i18n.json
  19. 1
      packages/rocketchat-i18n/i18n/ru.i18n.json
  20. 3
      packages/rocketchat-i18n/i18n/tr.i18n.json
  21. 3
      packages/rocketchat-i18n/i18n/zh.i18n.json
  22. 1
      packages/rocketchat-i18n/package.js
  23. 31
      packages/rocketchat-livechat/.app/.eslintrc
  24. 19
      packages/rocketchat-livechat/.app/.meteor/.finished-upgraders
  25. 2
      packages/rocketchat-livechat/.app/.meteor/.gitignore
  26. 7
      packages/rocketchat-livechat/.app/.meteor/.id
  27. 41
      packages/rocketchat-livechat/.app/.meteor/packages
  28. 2
      packages/rocketchat-livechat/.app/.meteor/platforms
  29. 1
      packages/rocketchat-livechat/.app/.meteor/release
  30. 98
      packages/rocketchat-livechat/.app/.meteor/versions
  31. 8
      packages/rocketchat-livechat/.app/client/components/modal.html
  32. 37
      packages/rocketchat-livechat/.app/client/lib/CustomFields.js
  33. 174
      packages/rocketchat-livechat/.app/client/lib/LivechatFileUpload.js
  34. 73
      packages/rocketchat-livechat/.app/client/lib/LivechatVideoCall.js
  35. 305
      packages/rocketchat-livechat/.app/client/lib/_livechat.js
  36. 6
      packages/rocketchat-livechat/.app/client/lib/autolinker.js
  37. 282
      packages/rocketchat-livechat/.app/client/lib/chatMessages.js
  38. 4
      packages/rocketchat-livechat/.app/client/lib/collections.js
  39. 65
      packages/rocketchat-livechat/.app/client/lib/commands.js
  40. 7
      packages/rocketchat-livechat/.app/client/lib/error.js
  41. 91
      packages/rocketchat-livechat/.app/client/lib/fromApp/Notifications.js
  42. 238
      packages/rocketchat-livechat/.app/client/lib/fromApp/RoomHistoryManager.js
  43. 24
      packages/rocketchat-livechat/.app/client/lib/fromApp/avatar.js
  44. 102
      packages/rocketchat-livechat/.app/client/lib/hooks.js
  45. 90
      packages/rocketchat-livechat/.app/client/lib/msgTyping.js
  46. 9
      packages/rocketchat-livechat/.app/client/lib/parentCall.js
  47. 27
      packages/rocketchat-livechat/.app/client/lib/tapi18n.js
  48. 183
      packages/rocketchat-livechat/.app/client/lib/triggers.js
  49. 30
      packages/rocketchat-livechat/.app/client/methods/sendMessageExternal.js
  50. 16
      packages/rocketchat-livechat/.app/client/routes/router.js
  51. 6
      packages/rocketchat-livechat/.app/client/startup/customFields.js
  52. 36
      packages/rocketchat-livechat/.app/client/startup/visitor.js
  53. 933
      packages/rocketchat-livechat/.app/client/stylesheets/main.less
  54. 183
      packages/rocketchat-livechat/.app/client/stylesheets/utils/_keyframes.import.less
  55. 53
      packages/rocketchat-livechat/.app/client/stylesheets/utils/_loading.import.less
  56. 140
      packages/rocketchat-livechat/.app/client/stylesheets/utils/_reset.import.less
  57. 33
      packages/rocketchat-livechat/.app/client/stylesheets/utils/_variables.import.less
  58. 5
      packages/rocketchat-livechat/.app/client/views/avatar.html
  59. 24
      packages/rocketchat-livechat/.app/client/views/avatar.js
  60. 57
      packages/rocketchat-livechat/.app/client/views/livechatWindow.html
  61. 243
      packages/rocketchat-livechat/.app/client/views/livechatWindow.js
  62. 8
      packages/rocketchat-livechat/.app/client/views/loading.html
  63. 21
      packages/rocketchat-livechat/.app/client/views/main.html
  64. 26
      packages/rocketchat-livechat/.app/client/views/message.html
  65. 119
      packages/rocketchat-livechat/.app/client/views/message.js
  66. 60
      packages/rocketchat-livechat/.app/client/views/messageAttachment.html
  67. 8
      packages/rocketchat-livechat/.app/client/views/messageAttachment.js
  68. 78
      packages/rocketchat-livechat/.app/client/views/messages.html
  69. 245
      packages/rocketchat-livechat/.app/client/views/messages.js
  70. 27
      packages/rocketchat-livechat/.app/client/views/offlineForm.html
  71. 86
      packages/rocketchat-livechat/.app/client/views/offlineForm.js
  72. 10
      packages/rocketchat-livechat/.app/client/views/options.html
  73. 44
      packages/rocketchat-livechat/.app/client/views/options.js
  74. 8
      packages/rocketchat-livechat/.app/client/views/poweredBy.html
  75. 33
      packages/rocketchat-livechat/.app/client/views/register.html
  76. 129
      packages/rocketchat-livechat/.app/client/views/register.js
  77. 65
      packages/rocketchat-livechat/.app/client/views/survey.html
  78. 24
      packages/rocketchat-livechat/.app/client/views/survey.js
  79. 21
      packages/rocketchat-livechat/.app/client/views/switchDepartment.html
  80. 84
      packages/rocketchat-livechat/.app/client/views/switchDepartment.js
  81. 27
      packages/rocketchat-livechat/.app/client/views/videoCall.html
  82. 38
      packages/rocketchat-livechat/.app/client/views/videoCall.js
  83. 48
      packages/rocketchat-livechat/.app/i18n/af.i18n.json
  84. 48
      packages/rocketchat-livechat/.app/i18n/ar.i18n.json
  85. 48
      packages/rocketchat-livechat/.app/i18n/az.i18n.json
  86. 8
      packages/rocketchat-livechat/.app/i18n/bas-CM.i18n.json
  87. 49
      packages/rocketchat-livechat/.app/i18n/be-BY.i18n.json
  88. 48
      packages/rocketchat-livechat/.app/i18n/bg.i18n.json
  89. 29
      packages/rocketchat-livechat/.app/i18n/bs.i18n.json
  90. 52
      packages/rocketchat-livechat/.app/i18n/ca.i18n.json
  91. 52
      packages/rocketchat-livechat/.app/i18n/cs.i18n.json
  92. 48
      packages/rocketchat-livechat/.app/i18n/cy.i18n.json
  93. 51
      packages/rocketchat-livechat/.app/i18n/da.i18n.json
  94. 50
      packages/rocketchat-livechat/.app/i18n/de-AT.i18n.json
  95. 52
      packages/rocketchat-livechat/.app/i18n/de.i18n.json
  96. 48
      packages/rocketchat-livechat/.app/i18n/el.i18n.json
  97. 52
      packages/rocketchat-livechat/.app/i18n/en.i18n.json
  98. 48
      packages/rocketchat-livechat/.app/i18n/eo.i18n.json
  99. 52
      packages/rocketchat-livechat/.app/i18n/es.i18n.json
  100. 44
      packages/rocketchat-livechat/.app/i18n/et.i18n.json
  101. Some files were not shown because too many files have changed in this diff Show More

@ -26,4 +26,3 @@ const fixFiles = (path, source, newlineAtEnd = false) => {
};
fixFiles('./packages/rocketchat-i18n', '/i18n/en.i18n.json');
fixFiles('./packages/rocketchat-livechat/.app/i18n', '/en.i18n.json');

@ -9,5 +9,3 @@ execSync('mkdir -p public/fonts/');
execSync('cp node_modules/katex/dist/fonts/* public/fonts/');
execSync('cp node_modules/pdfjs-dist/build/pdf.worker.min.js public/');
execSync('cd packages/rocketchat-livechat/.app && (meteor npm install || npm install) && cd -');

@ -60,510 +60,7 @@
.livechat-content {
display: flex;
flex-direction: row;
}
.livechat-settings-div,
.livechat-preview-div {
flex: 1 1;
margin-bottom: 0 !important;
padding: 1em;
}
.livechat-settings-div {
border-right: 1px solid #cccccc;
}
.livechat-preview {
width: 340px;
height: 350px;
margin: 0 auto;
border-bottom: 1px solid #cccccc;
position: relative;
.preview-wrapper {
position: absolute;
width: 100%;
padding: 0 20px;
height: 300px;
bottom: 0;
font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif, "Meiryo UI";
font-size: 0.8rem;
color: @primary-font-color;
-webkit-font-smoothing: antialiased;
line-height: 1rem;
input,
button,
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;
}
input {
height: 28px;
}
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);
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;
}
}
&.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%;
}
}
.livechat-room {
display: flex;
flex-direction: column;
height: 100%;
.title {
flex: 1 0 @header-min-height;
line-height: @header-min-height;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
color: #ffffff;
z-index: 10;
cursor: pointer;
h1 {
margin: 0;
padding: 0 5px;
font-size: 9pt;
display: inline-block;
text-transform: none;
}
.toolbar {
display: inline-block;
float: right;
padding-right: 5px;
}
}
.messages {
flex: 1 1 100%;
background-color: #ffffff;
border-left: 1px solid #e7e7e7;
border-right: 1px solid #e7e7e7;
overflow-y: auto;
.wrapper {
padding-bottom: 6px;
ul {
list-style-type: none;
padding: 0;
li {
padding: 0;
}
}
.message {
font-size: 12px;
padding-left: 40px;
position: relative;
line-height: 18px;
margin: 12px 10px 0;
min-height: 36px;
&: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: 10;
padding: 0 10px;
background-color: #ffffff;
min-width: 120px;
}
&::after {
content: " ";
display: block;
position: absolute;
top: -20px;
left: 0;
width: 100%;
border-top: 1px solid #dddddd;
}
}
.edit-message {
display: none;
cursor: pointer;
}
&.own:hover:not(.system) .edit-message {
display: inline-block;
}
.delete-message {
display: none;
cursor: pointer;
}
&.own:hover:not(.system) .delete-message {
display: inline-block;
}
.user {
display: inline-block;
font-weight: 600;
color: #444444;
margin-right: 5px;
outline: none;
&:hover {
color: #333333;
}
}
.thumb {
position: absolute;
left: 0;
top: 0;
display: block;
width: 30px;
height: 30px;
}
.info {
font-size: 10px;
color: @info-font-color;
}
&.sequential {
padding-top: 5px;
margin-top: 0;
margin-bottom: 0;
min-height: 20px;
.user {
display: none;
}
.thumb {
display: none;
}
.info {
position: absolute;
text-align: right;
left: -20px;
width: 55px;
.time {
display: none;
}
.edited {
display: inline-block;
}
.edit-message {
float: left;
margin-left: 1px;
}
.delete-message {
float: left;
}
}
&:hover {
.time {
display: inline-block;
}
.edited {
display: none;
}
}
}
&.system {
.body {
color: @info-font-color;
font-style: italic;
text-transform: lowercase;
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;
}
&.temp .body {
opacity: 0.5;
}
&.msg-error .body {
text-decoration: line-through;
}
.avatar .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: 40px;
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 #e7e7e7;
border-left: 1px solid #e7e7e7;
border-right: 1px solid #e7e7e7;
.input-wrapper {
padding: 6px 6px 0;
padding-right: 30px;
textarea {
display: block;
padding: 6px 8px;
padding-right: 38px;
overflow-y: auto;
resize: none;
border: 1px solid #e7e7e7;
border-radius: 5px;
max-height: 200px;
width: 100%;
font-size: 12px;
-webkit-appearance: none;
height: 28px;
line-height: normal;
background-color: #ffffff;
position: relative;
outline: none;
}
}
.send-button {
float: right;
position: relative;
right: 7px;
top: -28px;
color: @secondary-font-color;
cursor: pointer;
transition: color 0.15s ease-out;
&:hover {
color: @primary-font-color;
}
}
}
.offline {
flex: 1 1 100%;
background-color: white;
padding: 1em 10px;
border-left: 1px solid #e7e7e7;
border-right: 1px solid #e7e7e7;
.offline-message {
padding: 1em 0;
}
.message-sent {
text-align: center;
}
form {
input,
textarea {
display: block;
width: 100%;
}
textarea {
height: 3.5em;
}
.buttons {
text-align: center;
}
.error {
display: none;
background-color: #f7d799;
padding: 5px;
&.show {
display: block;
}
}
}
}
}
}
&.closed,
&.closed-offline {
.preview-wrapper {
height: 32px;
.livechat-room .title .toolbar {
display: none;
}
.messages {
display: none;
}
.footer {
display: none;
}
.offline {
display: none;
}
}
}
max-width: 960px;
}
.department-agents {

@ -2,213 +2,124 @@
{{#requiresPermission 'view-livechat-manager'}}
<div class='livechat-content'>
<div class="livechat-settings-div">
<h2>{{_ "Settings"}}</h2>
<form class="rocket-form">
<fieldset>
<legend>{{_ "Livechat_online"}}</legend>
<div class="input-line">
<label for="title">{{_ "Title"}}</label>
<input type="text" class="preview-settings rc-input__element" name="title" id="title" value="{{title}}">
</div>
<div class="input-line">
<label for="color">{{_ "Title_bar_color"}}</label>
<div>
<input type="text" class="preview-settings colorpicker-input rc-input__element" name="color" id="color" value="{{color}}">
<span class="colorpicker-swatch border-component-color" style="background-color: {{color}}"></span>
</div>
</div>
<div class="input-line">
<label for="showAgentEmail">{{_ "Show_agent_email"}}</label>
<div class="inline-fields">
<input type="radio" class="preview-settings" name="showAgentEmail" id="showAgentEmailFormTrue" checked="{{showAgentEmailFormTrueChecked}}" value="true">
<label for="showAgentEmailFormTrue">{{_ "True"}}</label>
<input type="radio" class="preview-settings" name="showAgentEmail" id="showAgentEmailFormFalse" checked="{{showAgentEmailFormFalseChecked}}" value="false">
<label for="showAgentEmailFormFalse">{{_ "False"}}</label>
</div>
</div>
</fieldset>
<fieldset>
<legend>{{_ "Livechat_offline"}}</legend>
<div class="input-line">
<label for="displayOfflineForm">{{_ "Display_offline_form"}}</label>
<div class="inline-fields">
<input type="radio" class="preview-settings" name="displayOfflineForm" id="displayOfflineFormTrue" checked="{{displayOfflineFormTrueChecked}}" value="true">
<label for="displayOfflineFormTrue">{{_ "True"}}</label>
<input type="radio" class="preview-settings" name="displayOfflineForm" id="displayOfflineFormFalse" checked="{{displayOfflineFormFalseChecked}}" value="false">
<label for="displayOfflineFormFalse">{{_ "False"}}</label>
</div>
</div>
<div class="input-line">
<label for="offlineUnavailableMessage">{{_ "Offline_form_unavailable_message"}}</label>
<textarea class="preview-settings rc-input__element" name="offlineUnavailableMessage" id="offlineUnavailableMessage">{{offlineUnavailableMessage}}</textarea>
</div>
<div class="input-line">
<label for="offlineMessage">{{_ "Offline_message"}}</label>
<textarea class="preview-settings rc-input__element" name="offlineMessage" id="offlineMessage">{{offlineMessage}}</textarea>
</div>
<div class="input-line">
<label for="titleOffline">{{_ "Title_offline"}}</label>
<input type="text" class="preview-settings rc-input__element" name="titleOffline" id="titleOffline" value="{{titleOffline}}">
</div>
<div class="input-line">
<label for="colorOffline">{{_ "Title_bar_color_offline"}}</label>
<div>
<input type="text" class="preview-settings colorpicker-input rc-input__element" name="colorOffline" id="colorOffline" value="{{colorOffline}}">
<span class="colorpicker-swatch border-component-color" style="background-color: {{colorOffline}}"></span>
</div>
</div>
<div class="input-line">
<label for="emailOffline">{{_ "Email_address_to_send_offline_messages"}}</label>
<input type="text" class="preview-settings rc-input__element" name="emailOffline" id="emailOffline" value="{{emailOffline}}">
<h2>{{_ "Settings"}}</h2>
<form class="rocket-form">
<fieldset>
<legend>{{_ "Livechat_online"}}</legend>
<div class="input-line">
<label for="title">{{_ "Title"}}</label>
<input type="text" class="preview-settings rc-input__element" name="title" id="title" value="{{title}}">
</div>
<div class="input-line">
<label for="color">{{_ "Title_bar_color"}}</label>
<div>
<input type="text" class="preview-settings colorpicker-input rc-input__element" name="color" id="color" value="{{color}}">
<span class="colorpicker-swatch border-component-color" style="background-color: {{color}}"></span>
</div>
<div class="input-line">
<label for="offlineSuccessMessage">{{_ "Offline_success_message"}}</label>
<textarea class="preview-settings rc-input__element" name="offlineSuccessMessage" id="offlineSuccessMessage">{{offlineSuccessMessage}}</textarea>
</div>
<div class="input-line">
<label for="showAgentEmail">{{_ "Show_agent_email"}}</label>
<div class="inline-fields">
<input type="radio" class="preview-settings" name="showAgentEmail" id="showAgentEmailFormTrue" checked="{{showAgentEmailFormTrueChecked}}" value="true">
<label for="showAgentEmailFormTrue">{{_ "True"}}</label>
<input type="radio" class="preview-settings" name="showAgentEmail" id="showAgentEmailFormFalse" checked="{{showAgentEmailFormFalseChecked}}" value="false">
<label for="showAgentEmailFormFalse">{{_ "False"}}</label>
</div>
</fieldset>
<fieldset>
<legend>{{_ "Livechat_registration_form"}}</legend>
<!--
<label class="rc-switch__label">
<input class="rc-switch__input" type="checkbox" name="registrationFormEnabled" checked="{{registrationFormEnabled}}"/>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
<span class="rc-switch__text">
{{_ "Show_preregistration_form"}}
</span>
</label>
-->
<label class="rc-switch__label">
<input class="rc-switch__input js-input-check" type="checkbox" name="registrationFormEnabled" {{registrationFormEnabled}}/>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
<span class="rc-switch__text">{{_ "Enabled"}}</span>
</label>
<label class="rc-switch__label">
<input class="rc-switch__input js-input-check" type="checkbox" name="registrationFormNameFieldEnabled" {{registrationFormNameFieldEnabled}}/>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
<span class="rc-switch__text">{{_ "Show_name_field"}}</span>
</label>
<label class="rc-switch__label">
<input class="rc-switch__input js-input-check" type="checkbox" name="registrationFormEmailFieldEnabled" {{registrationFormEmailFieldEnabled}}/>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
<span class="rc-switch__text">{{_ "Show_email_field"}}</span>
</label>
<div class="input-line">
<label for="registrationFormMessage">{{_ "Livechat_Registration_form_message"}}</label>
<textarea class="preview-settings rc-input__element" name="registrationFormMessage" id="registrationFormMessage">{{registrationFormMessage}}</textarea>
</div>
</fieldset>
<fieldset>
<legend>{{_ "Livechat_offline"}}</legend>
<div class="input-line">
<label for="displayOfflineForm">{{_ "Display_offline_form"}}</label>
<div class="inline-fields">
<input type="radio" class="preview-settings" name="displayOfflineForm" id="displayOfflineFormTrue" checked="{{displayOfflineFormTrueChecked}}" value="true">
<label for="displayOfflineFormTrue">{{_ "True"}}</label>
<input type="radio" class="preview-settings" name="displayOfflineForm" id="displayOfflineFormFalse" checked="{{displayOfflineFormFalseChecked}}" value="false">
<label for="displayOfflineFormFalse">{{_ "False"}}</label>
</div>
</fieldset>
<fieldset>
<legend>{{_ "Conversation_finished"}}</legend>
<div class="input-line">
<label for="conversationFinishedMessage">{{_ "Conversation_finished_message"}}</label>
<textarea class="preview-settings rc-input__element" name="conversationFinishedMessage" id="conversationFinishedMessage">{{conversationFinishedMessage}}</textarea>
</div>
<div class="input-line">
<label for="offlineUnavailableMessage">{{_ "Offline_form_unavailable_message"}}</label>
<textarea class="preview-settings rc-input__element" name="offlineUnavailableMessage" id="offlineUnavailableMessage">{{offlineUnavailableMessage}}</textarea>
</div>
<div class="input-line">
<label for="offlineMessage">{{_ "Offline_message"}}</label>
<textarea class="preview-settings rc-input__element" name="offlineMessage" id="offlineMessage">{{offlineMessage}}</textarea>
</div>
<div class="input-line">
<label for="titleOffline">{{_ "Title_offline"}}</label>
<input type="text" class="preview-settings rc-input__element" name="titleOffline" id="titleOffline" value="{{titleOffline}}">
</div>
<div class="input-line">
<label for="colorOffline">{{_ "Title_bar_color_offline"}}</label>
<div>
<input type="text" class="preview-settings colorpicker-input rc-input__element" name="colorOffline" id="colorOffline" value="{{colorOffline}}">
<span class="colorpicker-swatch border-component-color" style="background-color: {{colorOffline}}"></span>
</div>
</fieldset>
<div class="rc-button__group submit">
<button class="rc-button rc-button--danger reset-settings" type="button"><i class="icon-ccw"></i>{{_ "Reset"}}</button>
<button class="rc-button rc-button--primary save"><i class="icon-floppy"></i>{{_ "Save"}}</button>
</div>
</form>
</div>
<div class="livechat-preview-div">
<h2>{{_ "Preview"}}</h2>
<select class="preview-mode">
<optgroup label="{{_ "Online"}}">
<option value="opened">{{_ "Chat_window"}}</option>
<option value="closed">{{_ "Chat_button"}}</option>
</optgroup>
<optgroup label="{{_ "Offline"}}">
<option value="opened-offline">{{_ "Offline_form"}}</option>
<option value="offline-unavailable">{{_ "Offline_unavailable"}}</option>
<option value="offline-success">{{_ "Success_message"}}</option>
<option value="closed-offline">{{_ "Chat_button"}}</option>
</optgroup>
</select>
<div class="livechat-preview {{previewState}}">
<div class="preview-wrapper">
{{#with sampleData}}
<div class="livechat-room">
<div class="title" style="background-color:{{sampleColor}}">
<div class="toolbar">
&nbsp;
<i class="popout icon-link-ext" title="Open in a new window"></i>
</div>
<h1>{{sampleTitle}}</h1>
</div>
{{#if showOnline}}
<div class="messages">
<div class="wrapper">
<ul>
{{#each messages}}
<li id="{{_id}}" class="message {{sequential}}" data-username="{{u.username}}" data-date="{{date}}">
<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">{{u.username}}</span>
<span class="info">
<span class="time">{{time}}</span>
</span>
<div class="body" dir="auto">
{{{body}}}
</div>
</li>
{{/each}}
</ul>
</div>
</div>
<div class="footer">
<div class="input-wrapper">
<textarea class="input-message rc-input__element" placeholder="Type your message"></textarea>
</div>
<i class="send-button icon-paper-plane" aria-label="{{_ "Send"}}"></i>
</div>
{{/if}}
{{#if showOfflineForm}}
<div class="offline">
<p class="offline-message">{{{sampleOfflineMessage}}}</p>
<form>
<input type="text" class="rc-input__element" id="name" name="name" placeholder="{{_ "Type_your_name"}}">
<input type="email" class="rc-input__element" id="email" name="email" placeholder="{{_ "Type_your_email"}}">
<textarea id="message" class="rc-input__element" name="message" placeholder="{{_"Type_your_message"}}" rows="2"></textarea>
<div class="buttons">
<button class="button primary send">{{_ "Send"}}</button>
</div>
</form>
</div>
{{/if}}
{{#if showOfflineSuccess}}
<div class="offline">
<p class="message-sent">{{{sampleOfflineSuccessMessage}}}</p>
</div>
{{/if}}
{{#if showOfflineUnavailable}}
<div class="offline">
<p class="offline-message">{{{sampleOfflineUnavailableMessage}}}</p>
</div>
{{/if}}
</div>
{{/with}}
<div class="input-line">
<label for="emailOffline">{{_ "Email_address_to_send_offline_messages"}}</label>
<input type="text" class="preview-settings rc-input__element" name="emailOffline" id="emailOffline" value="{{emailOffline}}">
</div>
<div class="input-line">
<label for="offlineSuccessMessage">{{_ "Offline_success_message"}}</label>
<textarea class="preview-settings rc-input__element" name="offlineSuccessMessage" id="offlineSuccessMessage">{{offlineSuccessMessage}}</textarea>
</div>
</fieldset>
<fieldset>
<legend>{{_ "Livechat_registration_form"}}</legend>
<!--
<label class="rc-switch__label">
<input class="rc-switch__input" type="checkbox" name="registrationFormEnabled" checked="{{registrationFormEnabled}}"/>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
<span class="rc-switch__text">
{{_ "Show_preregistration_form"}}
</span>
</label>
-->
<label class="rc-switch__label">
<input class="rc-switch__input js-input-check" type="checkbox" name="registrationFormEnabled" {{registrationFormEnabled}}/>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
<span class="rc-switch__text">{{_ "Enabled"}}</span>
</label>
<label class="rc-switch__label">
<input class="rc-switch__input js-input-check" type="checkbox" name="registrationFormNameFieldEnabled" {{registrationFormNameFieldEnabled}}/>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
<span class="rc-switch__text">{{_ "Show_name_field"}}</span>
</label>
<label class="rc-switch__label">
<input class="rc-switch__input js-input-check" type="checkbox" name="registrationFormEmailFieldEnabled" {{registrationFormEmailFieldEnabled}}/>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
<span class="rc-switch__text">{{_ "Show_email_field"}}</span>
</label>
<div class="input-line">
<label for="registrationFormMessage">{{_ "Livechat_Registration_form_message"}}</label>
<textarea class="preview-settings rc-input__element" name="registrationFormMessage" id="registrationFormMessage">{{registrationFormMessage}}</textarea>
</div>
</fieldset>
<fieldset>
<legend>{{_ "Conversation_finished"}}</legend>
<div class="input-line">
<label for="conversationFinishedMessage">{{_ "Conversation_finished_message"}}</label>
<textarea class="preview-settings rc-input__element" name="conversationFinishedMessage" id="conversationFinishedMessage">{{conversationFinishedMessage}}</textarea>
</div>
</fieldset>
<div class="rc-button__group submit">
<button class="rc-button rc-button--danger reset-settings" type="button"><i class="icon-ccw"></i>{{_ "Reset"}}</button>
<button class="rc-button rc-button--primary save"><i class="icon-floppy"></i>{{_ "Save"}}</button>
</div>
</div>
</form>
</div>
{{/requiresPermission}}
</template>

@ -2,10 +2,8 @@
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
import { ReactiveVar } from 'meteor/reactive-var';
import { Random } from 'meteor/random';
import { Template } from 'meteor/templating';
import s from 'underscore.string';
import moment from 'moment';
import toastr from 'toastr';
import { t, handleError } from '../../../../utils';
@ -14,22 +12,6 @@ import './livechatAppearance.html';
const LivechatAppearance = new Mongo.Collection('livechatAppearance');
Template.livechatAppearance.helpers({
previewState() {
return Template.instance().previewState.get();
},
showOnline() {
return Template.instance().previewState.get().indexOf('offline') === -1;
},
showOfflineForm() {
const state = Template.instance().previewState.get();
return state === 'opened-offline' || state === 'closed-offline';
},
showOfflineSuccess() {
return Template.instance().previewState.get() === 'offline-success';
},
showOfflineUnavailable() {
return Template.instance().previewState.get() === 'offline-unavailable';
},
color() {
return Template.instance().color.get();
},
@ -107,91 +89,11 @@ Template.livechatAppearance.helpers({
registrationFormMessage() {
return Template.instance().registrationFormMessage.get();
},
sampleColor() {
if (Template.instance().previewState.get().indexOf('offline') !== -1) {
return Template.instance().colorOffline.get();
}
return Template.instance().color.get();
},
sampleTitle() {
if (Template.instance().previewState.get().indexOf('offline') !== -1) {
return Template.instance().titleOffline.get();
}
return Template.instance().title.get();
},
sampleData() {
return {
messages: [
{
_id: Random.id(),
u: {
username: 'guest',
},
time: moment(this.ts).format('LT'),
date: moment(this.ts).format('LL'),
body: 'Hello',
sequential: null,
},
{
_id: Random.id(),
u: {
username: 'rocketchat-agent',
},
time: moment(this.ts).format('LT'),
date: moment(this.ts).format('LL'),
body: 'Hey, what can I help you with?',
sequential: null,
},
{
_id: Random.id(),
u: {
username: 'guest',
},
time: moment(this.ts).format('LT'),
date: moment(this.ts).format('LL'),
body: 'I\'m looking for informations about your product.',
sequential: null,
},
{
_id: Random.id(),
u: {
username: 'rocketchat-agent',
},
time: moment(this.ts).format('LT'),
date: moment(this.ts).format('LL'),
body: 'Our product is open source, you can do what you want with it! =D',
sequential: null,
},
{
_id: Random.id(),
u: {
username: 'guest',
},
time: moment(this.ts).format('LT'),
date: moment(this.ts).format('LL'),
body: 'Yay, thanks. That\'s awesome.',
sequential: null,
},
{
_id: Random.id(),
u: {
username: 'rocketchat-agent',
},
time: moment(this.ts).format('LT'),
date: moment(this.ts).format('LL'),
body: 'You\'re welcome.',
sequential: null,
},
],
};
},
});
Template.livechatAppearance.onCreated(function() {
this.subscribe('livechat:appearance');
this.previewState = new ReactiveVar('opened');
this.title = new ReactiveVar(null);
this.color = new ReactiveVar(null);
@ -272,9 +174,6 @@ Template.livechatAppearance.onCreated(function() {
});
Template.livechatAppearance.events({
'change .preview-mode'(e, instance) {
instance.previewState.set(e.currentTarget.value);
},
'change .js-input-check'(e, instance) {
instance[e.currentTarget.name].set(e.currentTarget.checked);
},

@ -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>

@ -4,23 +4,7 @@ import s from 'underscore.string';
import { settings } from '../../../../settings';
import './livechatInstallation.html';
const latestVersion = '1.0.0';
Template.livechatInstallation.helpers({
oldScript() {
const siteUrl = s.rtrim(settings.get('Site_Url'), '/');
return `<!-- Start of Rocket.Chat Livechat Script -->
<script type="text/javascript">
(function(w, d, s, u) {
w.RocketChat = function(c) { w.RocketChat._.push(c) }; w.RocketChat._ = []; w.RocketChat.url = u;
var h = d.getElementsByTagName(s)[0], j = d.createElement(s);
j.async = true; j.src = '${ siteUrl }/packages/rocketchat_livechat/assets/rocketchat-livechat.min.js?_=201702160944';
h.parentNode.insertBefore(j, h);
})(window, document, 'script', '${ siteUrl }/livechat');
</script>
<!-- End of Rocket.Chat Livechat Script -->`;
},
script() {
const siteUrl = s.rtrim(settings.get('Site_Url'), '/');
return `<!-- Start of Rocket.Chat Livechat Script -->
@ -28,9 +12,9 @@ Template.livechatInstallation.helpers({
(function(w, d, s, u) {
w.RocketChat = function(c) { w.RocketChat._.push(c) }; w.RocketChat._ = []; w.RocketChat.url = u;
var h = d.getElementsByTagName(s)[0], j = d.createElement(s);
j.async = true; j.src = '${ siteUrl }/livechat/${ latestVersion }/rocketchat-livechat.min.js?_=201903270000';
j.async = true; j.src = '${ siteUrl }/livechat/rocketchat-livechat.min.js?_=201903270000';
h.parentNode.insertBefore(j, h);
})(window, document, 'script', '${ siteUrl }/livechat?version=${ latestVersion }');
})(window, document, 'script', '${ siteUrl }/livechat');
</script>
<!-- End of Rocket.Chat Livechat Script -->`;
},

@ -1,29 +1 @@
import { Autoupdate } from 'meteor/autoupdate';
export const addServerUrlToIndex = (file) => file.replace('<body>', `<body><script> SERVER_URL = '${ __meteor_runtime_config__.ROOT_URL }'; </script>`);
export const addServerUrlToHead = (head) => {
let baseUrl;
if (__meteor_runtime_config__.ROOT_URL_PATH_PREFIX && __meteor_runtime_config__.ROOT_URL_PATH_PREFIX.trim() !== '') {
baseUrl = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;
} else {
baseUrl = '/';
}
if (/\/$/.test(baseUrl) === false) {
baseUrl += '/';
}
return `<html>
<head>
<link rel="stylesheet" type="text/css" class="__meteor-css__" href="${ baseUrl }livechat/livechat.css?_dc=${ Autoupdate.autoupdateVersion }">
<script type="text/javascript">
__meteor_runtime_config__ = ${ JSON.stringify(__meteor_runtime_config__) };
</script>
<base href="${ baseUrl }">
${ head }
</head>
<body>
<script type="text/javascript" src="${ baseUrl }livechat/livechat.js?_dc=${ Autoupdate.autoupdateVersion }"></script>
</body>
</html>`;
};

@ -5,12 +5,9 @@ import { Meteor } from 'meteor/meteor';
import { WebApp } from 'meteor/webapp';
import { settings } from '../../settings/server';
import { addServerUrlToIndex, addServerUrlToHead } from '../lib/Assets';
import { addServerUrlToIndex } from '../lib/Assets';
const latestVersion = '1.0.0';
const indexHtmlWithServerURL = addServerUrlToIndex(Assets.getText('livechat/index.html'));
const headHtmlWithServerURL = addServerUrlToHead(Assets.getText('livechat/head.html'));
const isLatestVersion = (version) => version && version === latestVersion;
WebApp.connectHandlers.use('/livechat', Meteor.bindEnvironment((req, res, next) => {
const reqUrl = url.parse(req.url);
@ -18,8 +15,6 @@ WebApp.connectHandlers.use('/livechat', Meteor.bindEnvironment((req, res, next)
return next();
}
const { version } = req.query;
const html = isLatestVersion(version) ? indexHtmlWithServerURL : headHtmlWithServerURL;
res.setHeader('content-type', 'text/html; charset=utf-8');
@ -38,6 +33,6 @@ WebApp.connectHandlers.use('/livechat', Meteor.bindEnvironment((req, res, next)
res.setHeader('X-FRAME-OPTIONS', `ALLOW-FROM ${ referer.protocol }//${ referer.host }`);
}
res.write(html);
res.write(indexHtmlWithServerURL);
res.end();
}));

1417
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -93,6 +93,7 @@
"devDependencies": {
"@octokit/rest": "^16.1.0",
"@rocket.chat/eslint-config": "^0.3.0",
"@rocket.chat/livechat": "^1.1.4",
"acorn": "^6.0.7",
"autoprefixer": "^9.4.1",
"babel-eslint": "^10.0.1",

@ -2900,7 +2900,6 @@
"Today": "Heute",
"To_additional_emails": "Zu zusätzlichen E-Mails",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Um den Rocket.Chat-Livechat auf Deiner Webseite zu installieren, kopiere den Code und füge ihn oberhalb des letzten <strong>&lt;/body&gt;</strong>-Tags Deiner Seite ein.",
"To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Um die <strong>neue Version</strong> von Rocket.Chat Livechat auf Ihrer Website zu installieren, kopieren &amp; fügen diesen Code oberhalb des letzten <strong>&lt;/body&gt;</strong>-Tags auf Ihrer Website ein.",
"to_see_more_details_on_how_to_integrate": "um weitere Informationen zur Integration zu sehen",
"To_users": "An Benutzer",
"Toggle_original_translated": "Zwischen \"Original\" und \"Übersetzt\" wechseln",

@ -2927,7 +2927,6 @@
"Today": "Heute",
"To_additional_emails": "Zu zusätzlichen E-Mails",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Um den Rocket.Chat-LiveChat auf Ihrer Webseite zu installieren, kopieren und fügen Sie den Code oberhalb des letzten <strong>&lt;/body&gt;</strong>-Tags Ihrer Seite ein.",
"To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Um die <strong>neue Version</strong> von Rocket.Chat Livechat auf Ihrer Website zu installieren, kopieren &amp; fügen Sie diesen Code oberhalb des letzten <strong>&lt;/body&gt;</strong>-Tags auf Ihrer Website ein.",
"to_see_more_details_on_how_to_integrate": "um weitere Informationen zur Integration zu sehen",
"To_users": "An Benutzer",
"Toggle_original_translated": "Zwischen \"Original\" und \"Übersetzt\" wechseln",
@ -3284,4 +3283,4 @@
"Your_question": "Ihre Frage",
"Your_server_link": "Ihre Serververbindung",
"Your_workspace_is_ready": "Ihr Arbeitsbereich ist einsatzbereit 🎉"
}
}

@ -2980,7 +2980,6 @@
"Today": "Today",
"To_additional_emails": "To additional emails",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "To install Rocket.Chat Livechat in your website, copy &amp; paste this code above the last <strong>&lt;/body&gt;</strong> tag on your site.",
"To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "To install the <strong> new version</strong> of Rocket.Chat Livechat in your website, copy &amp; paste this code above the last <strong>&lt;/body&gt;</strong> tag on your site.",
"to_see_more_details_on_how_to_integrate": "to see more details on how to integrate.",
"To_users": "To Users",
"Toggle_original_translated": "Toggle original/translated",
@ -3339,4 +3338,4 @@
"Your_question": "Your question",
"Your_server_link": "Your server link",
"Your_workspace_is_ready": "Your workspace is ready to use 🎉"
}
}

@ -2863,7 +2863,6 @@
"Today": "Ma",
"To_additional_emails": "További e-mailek",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Telepíteni Rocket.Chat GYIK a honlapon, másolja be ezt a kódot a fenti utolsó <strong>&lt;/body&gt;</strong> tag a webhelyen.",
"To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Hogy telepítsd a Rocket.Chat LiveChat <strong>új verzióját</strong> a weboldaladra, másold és illeszd be a fenti kódot az utolsó <strong>&lt;/body&gt;</strong> html tag elé.",
"to_see_more_details_on_how_to_integrate": "További részletek megtekintéséhez, hogyan integrálják.",
"To_users": "Ahhoz, hogy a felhasználók",
"Toggle_original_translated": "Váltás az eredeti / lefordítva",

@ -2978,7 +2978,6 @@
"Today": "今日",
"To_additional_emails": "追加のメールへ",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Webサイトへ Rocket.Chat ライブチャットを導入するには、あなたのサイトの <strong>&lt;/body&gt;</strong> タグの前に、このコードをコピー &amp; ペーストしてください。",
"To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Webサイトへ<strong>新しいバージョン</strong>のRocket.Chat ライブチャットを導入するには、あなたのサイトの最後の <strong>&lt;/body&gt;</strong> タグの前に、このコードをコピー &amp; ペーストしてください。",
"to_see_more_details_on_how_to_integrate": "統合する方法の詳細を確認してください。",
"To_users": "宛先ユーザー",
"Toggle_original_translated": "元に戻す/翻訳済み",
@ -3337,4 +3336,4 @@
"Your_question": "あなたの質問",
"Your_server_link": "サーバーのURLはこちら",
"Your_workspace_is_ready": "ワークスペースの準備ができました🎉"
}
}

@ -2871,7 +2871,6 @@
"Today": "Hoje",
"To_additional_emails": "Para e-mails adicionais",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Para instalar Rocket.Chat Livechat no seu website, copie e cole este código acima da última tag <strong>&lt;/ body&gt;</strong> em seu site.",
"To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Para instalar a <strong>nova versão</strong> do Rocket.Chat Livechat no seu website, copie e cole este código acima da última tag <strong>&lt;/ body&gt;</strong> em seu site.",
"to_see_more_details_on_how_to_integrate": "para ver mais detalhes sobre como integrar.",
"To_users": "Para Usuários",
"Toggle_original_translated": "Alternar original / traduzido",
@ -3227,4 +3226,4 @@
"Your_question": "A sua pergunta",
"Your_server_link": "O link do seu servidor",
"Your_workspace_is_ready": "O seu espaço de trabalho está pronto a usar 🎉"
}
}

@ -2860,7 +2860,6 @@
"Today": "Hoje",
"To_additional_emails": "Para emails adicionais",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Para instalar Rocket.Chat Livechat no seu website, copie e cole este código acima da última tag <strong>&lt;/ body&gt;</strong> em seu site.",
"To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Para instalar a <strong>nova versão</strong> do Rocket.Chat Livechat no seu website, copie e cole este código acima da última tag <strong>&lt;/ body&gt;</strong> em seu site.",
"to_see_more_details_on_how_to_integrate": "para ver mais detalhes sobre como integrar.",
"To_users": "Para Utilizadores",
"Toggle_original_translated": "Alternar original / traduzido",
@ -3209,4 +3208,4 @@
"Your_question": "A sua pergunta",
"Your_server_link": "O link do seu servidor",
"Your_workspace_is_ready": "O seu espaço de trabalho está pronto a usar 🎉"
}
}

@ -2967,7 +2967,6 @@
"Today": "Сегодня",
"To_additional_emails": "Дополнительные email адресаты",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Для того, чтобы установить Rocket.Chat Livechat на вашем сайте, скопируйте и вставьте этот код выше последнего <strong>&lt;/body&gt;</strong> тега на вашем сайте.",
"To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Чтобы установить <strong>новую версию </strong>Rocket.Chat Livechat на свой веб-сайт, скопируйте &amp; вставьте этот код над последним тегом <strong>&lt; / body &gt; </strong>на своем сайте.",
"to_see_more_details_on_how_to_integrate": "чтобы увидеть более подробную информацию о том, как интегрировать.",
"To_users": "Пользователям",
"Toggle_original_translated": "Переключить оригинал/перевод",

@ -2883,7 +2883,6 @@
"Today": "Bugün",
"To_additional_emails": "Ek e-postalara",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": ", Web sitenize Rocket.Chat LIVECHAT yüklemek için kopyalayıp sitenizde son <strong>&lt;/body&gt;</strong> etiketinin üzerinde bu kodu yapıştırın.",
"To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "Websitenize Rocket.Chat Livechat'in <strong>yeni sürümünü</strong> yüklemek için, bu kodu kopyalayıp sitenizdeki son <strong>&lt;/body&gt;</strong> tag'inin üstüne yapıştırın.",
"to_see_more_details_on_how_to_integrate": "entegre etmek konusunda daha fazla ayrıntı görmek için.",
"To_users": "Kullanıcılara",
"Toggle_original_translated": "Orijinal / çevrilmiş",
@ -3239,4 +3238,4 @@
"Your_question": "Sorunuz",
"Your_server_link": "Sunucu bağlantınız",
"Your_workspace_is_ready": "Çalışma alanınız kullanılmaya hazır 🎉"
}
}

@ -2954,7 +2954,6 @@
"Today": "今天",
"To_additional_emails": "额外的电子邮件",
"To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "要在您的网站中安装 Rocket.Chat 即时聊天,请将以下代码复制粘贴到您的网页代码中最后一个 <strong>&lt;/body&gt;</strong> 标签之上。",
"To_install_the_new_version_of_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site": "要安装 Rocket.Chat 实时聊天的 <strong>新版本</strong> 复制和粘贴此代码在你站点的最后一个<strong>&lt;/body&gt;</strong> 标签上方。",
"to_see_more_details_on_how_to_integrate": "以便查看更多关于集成的细节。",
"To_users": "给用户",
"Toggle_original_translated": "切换地区/语言",
@ -3313,4 +3312,4 @@
"Your_question": "你的问题",
"Your_server_link": "您的服务器链接",
"Your_workspace_is_ready": "您的工作区已准备好使用🎉"
}
}

@ -6,7 +6,6 @@ Package.describe({
});
const additionalPackages = {
livechat: 'rocketchat-livechat/.app/i18n',
};
const fs = Npm.require('fs');

@ -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,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,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">
&nbsp;
{{#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": "ملاحظات إضافية",
"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,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…
Cancel
Save