Browse Source

Unable to open customer chat widget via separate open button. Fixes #2435

Martin Edenhofer 6 years ago
parent
commit
9300fd732c

+ 7 - 2
public/assets/chat/chat.coffee

@@ -1,9 +1,13 @@
 do($ = window.jQuery, window) ->
 
   scripts = document.getElementsByTagName('script')
+
+  # search for script to get protocol and hostname for ws connection
   myScript = scripts[scripts.length - 1]
-  scriptHost = myScript.src.match('.*://([^:/]*).*')[1]
-  scriptProtocol = myScript.src.match('(.*)://[^:/]*.*')[1]
+  scriptProtocol = window.location.protocol.replace(':', '') # set default protocol
+  if myScript && myScript.src
+    scriptHost = myScript.src.match('.*://([^:/]*).*')[1]
+    scriptProtocol = myScript.src.match('(.*)://[^:/]*.*')[1]
 
   # Define the plugin class
   class Base
@@ -875,6 +879,7 @@ do($ = window.jQuery, window) ->
 
       @isOpen = true
       @log.debug 'open widget'
+      @show()
 
       if !@sessionId
         @showLoader()

+ 67 - 63
public/assets/chat/chat.js

@@ -1,64 +1,3 @@
-if (!window.zammadChatTemplates) {
-  window.zammadChatTemplates = {};
-}
-window.zammadChatTemplates["agent"] = function (__obj) {
-  if (!__obj) __obj = {};
-  var __out = [], __capture = function(callback) {
-    var out = __out, result;
-    __out = [];
-    callback.call(this);
-    result = __out.join('');
-    __out = out;
-    return __safe(result);
-  }, __sanitize = function(value) {
-    if (value && value.ecoSafe) {
-      return value;
-    } else if (typeof value !== 'undefined' && value != null) {
-      return __escape(value);
-    } else {
-      return '';
-    }
-  }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
-  __safe = __obj.safe = function(value) {
-    if (value && value.ecoSafe) {
-      return value;
-    } else {
-      if (!(typeof value !== 'undefined' && value != null)) value = '';
-      var result = new String(value);
-      result.ecoSafe = true;
-      return result;
-    }
-  };
-  if (!__escape) {
-    __escape = __obj.escape = function(value) {
-      return ('' + value)
-        .replace(/&/g, '&')
-        .replace(/</g, '&lt;')
-        .replace(/>/g, '&gt;')
-        .replace(/"/g, '&quot;');
-    };
-  }
-  (function() {
-    (function() {
-      if (this.agent.avatar) {
-        __out.push('\n<img class="zammad-chat-agent-avatar" src="');
-        __out.push(__sanitize(this.agent.avatar));
-        __out.push('">\n');
-      }
-    
-      __out.push('\n<span class="zammad-chat-agent-sentence">\n  <span class="zammad-chat-agent-name">');
-    
-      __out.push(__sanitize(this.agent.name));
-    
-      __out.push('</span>\n</span>');
-    
-    }).call(this);
-    
-  }).call(__obj);
-  __obj.safe = __objSafe, __obj.escape = __escape;
-  return __out.join('');
-};
-
 var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
   slice = [].slice,
   extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@@ -68,8 +7,11 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
   var Base, Io, Log, Timeout, ZammadChat, myScript, scriptHost, scriptProtocol, scripts;
   scripts = document.getElementsByTagName('script');
   myScript = scripts[scripts.length - 1];
-  scriptHost = myScript.src.match('.*://([^:/]*).*')[1];
-  scriptProtocol = myScript.src.match('(.*)://[^:/]*.*')[1];
+  scriptProtocol = window.location.protocol.replace(':', '');
+  if (myScript && myScript.src) {
+    scriptHost = myScript.src.match('.*://([^:/]*).*')[1];
+    scriptProtocol = myScript.src.match('(.*)://[^:/]*.*')[1];
+  }
   Base = (function() {
     Base.prototype.defaults = {
       debug: false
@@ -1167,6 +1109,7 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
       }
       this.isOpen = true;
       this.log.debug('open widget');
+      this.show();
       if (!this.sessionId) {
         this.showLoader();
       }
@@ -1899,6 +1842,67 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
   return window.ZammadChat = ZammadChat;
 })(window.jQuery, window);
 
+if (!window.zammadChatTemplates) {
+  window.zammadChatTemplates = {};
+}
+window.zammadChatTemplates["agent"] = function (__obj) {
+  if (!__obj) __obj = {};
+  var __out = [], __capture = function(callback) {
+    var out = __out, result;
+    __out = [];
+    callback.call(this);
+    result = __out.join('');
+    __out = out;
+    return __safe(result);
+  }, __sanitize = function(value) {
+    if (value && value.ecoSafe) {
+      return value;
+    } else if (typeof value !== 'undefined' && value != null) {
+      return __escape(value);
+    } else {
+      return '';
+    }
+  }, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
+  __safe = __obj.safe = function(value) {
+    if (value && value.ecoSafe) {
+      return value;
+    } else {
+      if (!(typeof value !== 'undefined' && value != null)) value = '';
+      var result = new String(value);
+      result.ecoSafe = true;
+      return result;
+    }
+  };
+  if (!__escape) {
+    __escape = __obj.escape = function(value) {
+      return ('' + value)
+        .replace(/&/g, '&amp;')
+        .replace(/</g, '&lt;')
+        .replace(/>/g, '&gt;')
+        .replace(/"/g, '&quot;');
+    };
+  }
+  (function() {
+    (function() {
+      if (this.agent.avatar) {
+        __out.push('\n<img class="zammad-chat-agent-avatar" src="');
+        __out.push(__sanitize(this.agent.avatar));
+        __out.push('">\n');
+      }
+    
+      __out.push('\n<span class="zammad-chat-agent-sentence">\n  <span class="zammad-chat-agent-name">');
+    
+      __out.push(__sanitize(this.agent.name));
+    
+      __out.push('</span>\n</span>');
+    
+    }).call(this);
+    
+  }).call(__obj);
+  __obj.safe = __objSafe, __obj.escape = __escape;
+  return __out.join('');
+};
+
 if (!window.zammadChatTemplates) {
   window.zammadChatTemplates = {};
 }

File diff suppressed because it is too large
+ 0 - 0
public/assets/chat/chat.min.js


+ 1 - 1
public/assets/chat/znuny.html

@@ -157,7 +157,7 @@
     debug: true,
     background: '#494d52',
     flat: true,
-    shown: false,
+    show: true,
     idleTimeout: 1,
     idleTimeoutIntervallCheck: 0.5,
     inactiveTimeout: 2,

+ 202 - 0
public/assets/chat/znuny_open_by_button.html

@@ -0,0 +1,202 @@
+<!doctype html>
+<html lang="de-de">
+<head>
+  <meta charset="utf-8">
+  <title>Zammad Chat</title>
+  <link rel="stylesheet" href="znuny.css">
+  <meta name="viewport" content="width=device-width,initial-scale=1.0">
+  <style>
+    body {
+      margin: 0;
+      font-family: sans-serif;
+    }
+
+    .mockup {
+      vertical-align: bottom;
+    }
+
+    .settings {
+      position: fixed;
+      left: 20px;
+      top: 20px;
+      background: white;
+      font-size: 14px;
+      padding: 10px;
+      border-radius: 5px;
+      box-shadow: 0 3px 10px rgba(0,0,0,.3);
+      width: 500px;
+    }
+
+    .settings input {
+      vertical-align: middle;
+    }
+    .settings input + input {
+      margin-right: 3px;
+    }
+
+    table td:first-child {
+      text-align: right;
+      padding-right: 0;
+    }
+
+    table td.log {
+      text-align: left;
+      padding-right: 0;
+      word-break: break-all;
+    }
+
+    td {
+      padding: 5px;
+    }
+
+    h2 {
+      font-size: 1em;
+      margin: 0;
+    }
+
+    @media only screen and (max-width: 768px) {
+      .settings {
+        display: none;
+      }
+    }
+
+    .Box {
+      background: hsl(0,0%,91%);
+      width: 26px;
+      height: 24px;
+      color: hsl(0,0%,47%);
+      float: left;
+    }
+    .Box.Active {
+      background: hsl(0,0%,36%);
+      color: white;
+    }
+  </style>
+</head>
+<body>
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+<img class="mockup" width="100%" src="znuny.png">
+
+<div class="settings">
+  <table>
+    <tr>
+      <td><h2>Settings</h2>
+      <td>
+    <tr>
+      <td>
+        <input id="flat" type="checkbox" data-option="flat">
+      <td>
+        <label for="flat">Flat Design</label>
+    <tr>
+      <td>
+        <input type="color" id="color" value="#AE99D6" data-option="color">
+      <td>
+        <label for="color">Color</label>
+    <tr>
+      <td>
+        <input type="range" id="borderRadius" value="5" min="0" max="20" data-option="borderRadius">
+        <input type="number" value="5" min="5" max="20" data-option="borderRadius">px
+      <td>
+        <label for="borderRadius">Border Radius</label>
+    <tr>
+      <td>
+        <input type="range" id="fontSize" value="12" min="11" max="18" data-option="fontSize">
+        <input type="number" value="12" min="11" max="18" data-option="fontSize">px
+      <td>
+        <label for="fontSize">Font Size</label>
+    <tr>
+      <td>
+      <td><button class="open-zammad-chat">Open Chat</button>
+    <tr>
+      <td class="log"><h2>Log</h2>
+      <td>
+    <tr>
+      <td colspan="2" class="log js-chatLogDisplay">
+  </table>
+</div>
+
+<script src="jquery-2.1.4.min.js"></script>
+<script src="chat.js"></script>
+<script>
+  function getSearchParameters() {
+        var prmstr = window.location.search.substr(1);
+        return prmstr != null && prmstr != '' ? transformToAssocArray(prmstr) : {};
+  }
+  function transformToAssocArray( prmstr ) {
+      var params = {};
+      var prmarr = prmstr.split('&');
+      for ( var i = 0; i < prmarr.length; i++) {
+          var tmparr = prmarr[i].split('=');
+          params[tmparr[0]] = tmparr[1];
+      }
+      return params;
+  }
+  var hostname = window.location.hostname;
+  var port = window.location.port;
+  var params = getSearchParameters();
+  var host = 'ws://'+ (location.host || 'localhost').split(':')[0] +':6042'
+  if (params['port']) {
+    host = 'ws://' + hostname + ':' + params['port']
+  }
+  cssUrl = 'http://' + hostname + ':' + port + '/assets/chat/chat.css'
+
+  var chat = new ZammadChat({
+    chatId: 1,
+    host: host,
+    cssUrl: cssUrl,
+    debug: true,
+    background: '#494d52',
+    flat: true,
+    show: false,
+    idleTimeout: 1,
+    idleTimeoutIntervallCheck: 0.5,
+    inactiveTimeout: 2,
+    inactiveTimeoutIntervallCheck: 0.5,
+    waitingListTimeout: 1.2,
+    waitingListTimeoutIntervallCheck: 0.5,
+  });
+
+  $('.settings :input').on({
+    change: function(){
+      switch($(this).attr('data-option')){
+        case "flat":
+          $('.zammad-chat').toggleClass('zammad-chat--flat', this.checked);
+          break;
+        case "color":
+          setScssVariable('themeColor', this.value);
+          updateStyle();
+          break;
+        case "borderRadius":
+          setScssVariable('borderRadius', this.value + "px");
+          updateStyle();
+          break;
+      }
+    },
+    input: function(){
+      switch($(this).attr('data-option')){
+        case "borderRadius":
+          $('[data-option="borderRadius"]').val(this.value);
+          setScssVariable('borderRadius', this.value + "px");
+          updateStyle();
+          break;
+        case "fontSize":
+          $('[data-option="fontSize"]').val(this.value);
+          setScssVariable('fontSize', this.value + "px");
+          updateStyle();
+          break;
+      }
+    }
+  });
+</script>
+</body>
+</html>

+ 99 - 0
test/browser/chat_test.rb

@@ -591,6 +591,78 @@ class ChatTest < TestCase
     )
   end
 
+  def test_open_chat_by_button
+    chat_url = "#{browser_url}/assets/chat/znuny_open_by_button.html?port=#{ENV['WS_PORT']}"
+    agent = browser_instance
+    login(
+      browser:  agent,
+      username: 'master@example.com',
+      password: 'test',
+      url:      browser_url,
+    )
+    tasks_close_all(
+      browser: agent,
+    )
+    click(
+      browser: agent,
+      css:     'a[href="#customer_chat"]',
+    )
+    agent.find_elements(css: '.active .chat-window .js-disconnect:not(.is-hidden)').each(&:click)
+    agent.find_elements(css: '.active .chat-window .js-close').each(&:click)
+
+    customer = browser_instance
+    location(
+      browser: customer,
+      url:     chat_url,
+    )
+    watch_for(
+      browser: customer,
+      css:     '.zammad-chat',
+      timeout: 5,
+    )
+    exists_not(
+      browser: customer,
+      css:     '.zammad-chat-is-shown',
+    )
+    exists_not(
+      browser: customer,
+      css:     '.zammad-chat-is-open',
+    )
+    click(
+      browser: customer,
+      css:     '.open-zammad-chat',
+    )
+    watch_for(
+      browser: customer,
+      css:     '.zammad-chat-is-shown',
+      timeout: 4,
+    )
+    watch_for(
+      browser: customer,
+      css:     '.zammad-chat-is-open',
+      timeout: 4,
+    )
+    watch_for(
+      browser: customer,
+      css:     '.zammad-chat',
+      value:   '(waiting|warte)',
+    )
+    click(
+      browser: customer,
+      css:     '.zammad-chat-header-icon-close',
+    )
+    watch_for_disappear(
+      browser: customer,
+      css:     '.zammad-chat-is-shown',
+      timeout: 4,
+    )
+    watch_for_disappear(
+      browser: customer,
+      css:     '.zammad-chat-is-open',
+      timeout: 4,
+    )
+  end
+
   def test_timeouts
     chat_url = "#{browser_url}/assets/chat/znuny.html?port=#{ENV['WS_PORT']}"
     agent = browser_instance
@@ -762,4 +834,31 @@ class ChatTest < TestCase
 
   end
 
+  def disable_chat
+    login(
+      browser:  agent,
+      username: 'master@example.com',
+      password: 'test',
+      url:      browser_url,
+    )
+    tasks_close_all(
+      browser: agent,
+    )
+
+    # disable chat
+    click(
+      browser: agent,
+      css:     'a[href="#manage"]',
+    )
+    click(
+      browser: agent,
+      css:     '.content.active a[href="#channels/chat"]',
+    )
+    switch(
+      browser: agent,
+      css:     '.content.active .js-chatSetting',
+      type:    'off',
+    )
+  end
+
 end

Some files were not shown because too many files changed in this diff