<commit_before>(function() {
  'use strict';

  function listenToClick(element, name, fn) {
    if (document.addEventListener) {
      element.addEventListener(name, fn, false);
    } else {
      element.attachEvent((name === 'click') ? 'onclick' : name, fn);
    }
  }

  function handleClicks(elem, fn) {
    if (document.addEventListener) {
      // For all major browsers, except IE 8 and earlier
      elem.addEventListener("click", fn, false);
      elem.addEventListener("touchstart", fn, false);
    } else if (document.attachEvent) {
      // For IE 8 and earlier versions
      elem.attachEvent("onclick", fn, false);
      elem.attachEvent("touchstart", fn, false);
    }
  };

  function hasClass(el, className) {
    if (el.classList)
      return el.classList.contains(className)
    else
      return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'))
  }

  function my_addClass(el, className) {
    if (el.classList)
      el.classList.add(className)
    else if (!hasClass(el, className)) el.className += " " + className
  }

  function my_removeClass(el, className) {
    if (el.classList)
      el.classList.remove(className)
    else if (hasClass(el, className)) {
      var reg = new RegExp('(\\s|^)' + className + '(\\s|$)')
      el.className=el.className.replace(reg, ' ')
    }
  }

  function scrollTop(element, to, duration) {
    var start = element.scrollTop,
        change = to - start,
        currentTime = 0,
        increment = 20;

    var animateScroll = function(){
      currentTime += increment;
      var val = Math.easeInOutQuad(currentTime, start, change, duration);
      element.scrollTop = val;
      if(currentTime < duration) {
        setTimeout(animateScroll, increment);
      }
    };
    animateScroll();
  }

  //t = current time
  //b = start value
  //c = change in value
  //d = duration
  Math.easeInOutQuad = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t + b;
    t--;
    return -c/2 * (t*(t-2) - 1) + b;
  }

  function each(o, cb, s){
    var n;
    if (!o){
      return 0;
    }
    s = !s ? o : s;
    if (o instanceof Array){
      // Indexed arrays, needed for Safari
      for (n=0; n<o.length; n++) {
        if (cb.call(s, o[n], n, o) === false){
          return 0;
        }
      }
    } else {
      // Hashtables
      for (n in o){
        if (o.hasOwnProperty(n)) {
          if (cb.call(s, o[n], n, o) === false){
            return 0;
          }
        }
      }
    }
    return 1;
  }

  var isValidEmail = function(email) {
    return /^.+@.+\..+$/.test(email);
  }

  domready(function() {

    var scrollElements = document.querySelectorAll('[data-scroll-element]');
    var sendEmailBtn = document.getElementById('squatch-send-email');
    var emailInput = document.getElementById('squatch-user-email');

    if (sendEmailBtn) {
      handleClicks(sendEmailBtn, function() {
        if (!isValidEmail(emailInput.value)) {
          my_addClass(emailInput, 'invalid');
          emailInput.onkeypress = function() {
            if (isValidEmail(this.value)) {
              my_removeClass(this, 'invalid');
              my_addClass(this, 'valid');
            }
          }
        } else {
          my_removeClass(emailInput, 'invalid');
          var registerForm = document.getElementsByClassName('squatch-register')[0];
          registerForm.style.paddingTop = '30px';
          registerForm.innerHTML = '
' + emailInput.value + '
Has been successfully registered
';

          if (window.parent.squatch.eventBus) {
            window.parent.squatch.eventBus.dispatch('email_submitted', this, emailInput.value /*, JWT*/);
          }
        }
      });
    }

    var inValidRange = function(offset, limit) {
      return offset >= 0 && offset < limit;
    };

    var setVisibility = function(element, nextOffset, limit) {
      if(inValidRange(nextOffset, limit)) {
        my_removeClass(element, 'disabled');
      } else {
        my_addClass(element, 'disabled');
      }
    };

    var setVisibilityAll = function(elements, newOffset) {
      var
        scrollElement,
        increment,
        nextOffset,
        limit;

      each(elements, function(el) {
        scrollElement = document.querySelector(el.dataset.scrollElement);
        increment  = parseInt(el.dataset.scrollIncrement);
        nextOffset = newOffset + increment;
        limit      = parseInt(scrollElement.dataset.scrollLimit);

        setVisibility(el, nextOffset, limit);
      });
    };

    var resetScroll = function(element) {
      element.scrollTop = 0;
      element.dataset.scrollOffset = 0;
    };

    each(document.querySelectorAll('[data-clipboard-target]'), function(el) {
      var clipboard = new Clipboard(el);
      var notification;

      var notify = function(clipboardNotification, notificationText) {
        notification = document.getElementById(clipboardNotification.slice(1));
        notification.textContent = notificationText;
        my_addClass(notification, 'in');
        setTimeout(function() {
          my_removeClass(notification, 'in');
        }, 1400);
      };

      var notifySuccess = function(e) {
        notify(e.trigger.dataset.clipboardNotification, "Copied!");
      };

      var notifyFailure = function(e) {
        //if the copy function failed the text should still be selected, so just ask the user to hit ctrl+c
        notify(e.trigger.dataset.clipboardNotification, "Press Ctrl+C to copy");
      };

      clipboard.on('success', notifySuccess);
      clipboard.on('error', notifyFailure);
      handleClicks(el, function(e) {
        if (window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('copy_btn_clicked', e.type);
        }
      });
    });

    each(scrollElements, function(el) {
      var element = document.querySelector(el.dataset.scrollElement);
      var increment = parseInt(el.dataset.scrollIncrement);
      var limit     = parseInt(element.dataset.scrollLimit.valueOf());
      var offset    = parseInt(element.dataset.scrollOffset.valueOf());
      var newOffset;

      element.dataset.scrollLimit = limit;

      var nextOffset = offset + increment;

      setVisibility(el, nextOffset, limit);

      // Force IE to forget previous scroll top value
      resetScroll(element);

      listenToClick(el, 'click', function() {
        offset = parseInt(element.dataset.scrollOffset);

        newOffset = offset + increment;

        if (inValidRange(newOffset, limit)) {
          scrollTop(element, document.getElementById(newOffset).offsetTop, 400);
          element.dataset.scrollOffset = newOffset;

          setVisibilityAll(scrollElements, newOffset);
        }
      });
    });

    each(document.querySelectorAll('[data-moment]'), function(el) {
      var time = moment(parseInt(el.textContent));
      el.textContent = time.fromNow();
    });

    each(document.getElementsByClassName('squatch-header-close'), function(el) {
      handleClicks(el, function(e) {
        if (window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('close_popup', e.type);
        }
      });
    });

    // CTA
    each(document.getElementsByClassName('cta-container'), function(el) {
      el.onclick = function(e) {
        if (window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('open_popup', e.type);
        }
      }
    });

    // Popup stuff
    each(document.querySelectorAll('[data-open-panel]'), function(el) {
      var element = document.getElementById(el.dataset.openPanel.slice(1));

      if (element) {
        el.onclick = function() {
          my_addClass(element, 'open');
        };
      }
    });

    each(document.querySelectorAll('[data-close-panel]'), function(el) {
      var element = document.getElementById(el.dataset.closePanel.slice(1));

      if (element) {
        el.onclick = function() {
          my_removeClass(element, 'open');
        };
      }
    });

    var setContainerHeight = function(containerEl) {
      var bodyEl           = document.getElementsByClassName('squatch-body')[0];
      var titleEl          = document.getElementsByClassName('squatch-title')[0];
      var titleStyle       = getComputedStyle(titleEl);
      var panelEl          = document.getElementById('squatch-panel');
      var referralsEl      = document.getElementsByClassName('squatch-referrals')[0];
      var referralsTitleEl = document.getElementsByClassName('squatch-referrals-title')[0];

      var bodyHeight = bodyEl.offsetHeight;
      var bodyHeightWithoutTitle = bodyHeight - titleEl.offsetHeight - parseInt(titleStyle.marginTop) - parseInt(titleStyle.marginBottom) - titleEl.offsetTop;
      var panelHeight = panelEl ? panelEl.offsetHeight : 0;

      if (referralsEl && referralsEl.style.display !== 'none') {
        panelHeight -= referralsEl.offsetHeight;
      }

      if (referralsTitleEl && referralsTitleEl.style.display !== 'none') {
        panelHeight -= referralsTitleEl.offsetHeight;
      }

      containerEl.style.height = bodyHeight + panelHeight + "px";

      var stylesheet = document.createElement('style');
      stylesheet.type = 'text/css';

      var css = '#squatch-panel.open {' +
        '-webkit-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-ms-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-o-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        'transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '}' +
        'html.lt-ie9 #squatch-panel.open {' +
        'top: -' + bodyHeightWithoutTitle + 'px;' +
        '}';

      if (stylesheet.styleSheet){
        // IE
        stylesheet.styleSheet.cssText = css;
      } else {
        // W3C Standard
        stylesheet.appendChild(document.createTextNode(css));
      }

      document.querySelector('head').appendChild(stylesheet);
    };

    var containerEl = document.getElementsByClassName('squatch-container-popup')[0];

    if (containerEl) {
     window.onload = function() {
       setContainerHeight(containerEl);
     }

    }
  });

})();
<commit_msg>Update widget.js<commit_after>(function() {
  'use strict';

  function listenToClick(element, name, fn) {
    if (document.addEventListener) {
      element.addEventListener(name, fn, false);
    } else {
      element.attachEvent((name === 'click') ? 'onclick' : name, fn);
    }
  }

  function handleClicks(elem, fn) {
    if (document.addEventListener) {
      // For all major browsers, except IE 8 and earlier
      elem.addEventListener("click", fn, false);
      elem.addEventListener("touchstart", fn, false);
    } else if (document.attachEvent) {
      // For IE 8 and earlier versions
      elem.attachEvent("onclick", fn, false);
      elem.attachEvent("touchstart", fn, false);
    }
  };

  function hasClass(el, className) {
    if (el.classList)
      return el.classList.contains(className)
    else
      return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'))
  }

  function my_addClass(el, className) {
    if (el.classList)
      el.classList.add(className)
    else if (!hasClass(el, className)) el.className += " " + className
  }

  function my_removeClass(el, className) {
    if (el.classList)
      el.classList.remove(className)
    else if (hasClass(el, className)) {
      var reg = new RegExp('(\\s|^)' + className + '(\\s|$)')
      el.className=el.className.replace(reg, ' ')
    }
  }

  function scrollTop(element, to, duration) {
    var start = element.scrollTop,
        change = to - start,
        currentTime = 0,
        increment = 20;

    var animateScroll = function(){
      currentTime += increment;
      var val = Math.easeInOutQuad(currentTime, start, change, duration);
      element.scrollTop = val;
      if(currentTime < duration) {
        setTimeout(animateScroll, increment);
      }
    };
    animateScroll();
  }

  //t = current time
  //b = start value
  //c = change in value
  //d = duration
  Math.easeInOutQuad = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t + b;
    t--;
    return -c/2 * (t*(t-2) - 1) + b;
  }

  function each(o, cb, s){
    var n;
    if (!o){
      return 0;
    }
    s = !s ? o : s;
    if (o instanceof Array){
      // Indexed arrays, needed for Safari
      for (n=0; n<o.length; n++) {
        if (cb.call(s, o[n], n, o) === false){
          return 0;
        }
      }
    } else {
      // Hashtables
      for (n in o){
        if (o.hasOwnProperty(n)) {
          if (cb.call(s, o[n], n, o) === false){
            return 0;
          }
        }
      }
    }
    return 1;
  }

  var isValidEmail = function(email) {
    return /^.+@.+\..+$/.test(email);
  }

  domready(function() {

    var scrollElements = document.querySelectorAll('[data-scroll-element]');
    var sendEmailBtn = document.getElementById('squatch-send-email');
    var emailInput = document.getElementById('squatch-user-email');

    if (sendEmailBtn) {
      handleClicks(sendEmailBtn, function() {
        if (!isValidEmail(emailInput.value)) {
          my_addClass(emailInput, 'invalid');
          emailInput.onkeypress = function() {
            if (isValidEmail(this.value)) {
              my_removeClass(this, 'invalid');
              my_addClass(this, 'valid');
            }
          }
        } else {
          my_removeClass(emailInput, 'invalid');
          var registerForm = document.getElementsByClassName('squatch-register')[0];
          registerForm.style.paddingTop = '30px';
          registerForm.innerHTML = '
' + emailInput.value + '
Has been successfully registered
';

          if (window.parent.squatch && window.parent.squatch.eventBus) {
            window.parent.squatch.eventBus.dispatch('email_submitted', this, emailInput.value /*, JWT*/);
          }
        }
      });
    }

    var inValidRange = function(offset, limit) {
      return offset >= 0 && offset < limit;
    };

    var setVisibility = function(element, nextOffset, limit) {
      if(inValidRange(nextOffset, limit)) {
        my_removeClass(element, 'disabled');
      } else {
        my_addClass(element, 'disabled');
      }
    };

    var setVisibilityAll = function(elements, newOffset) {
      var
        scrollElement,
        increment,
        nextOffset,
        limit;

      each(elements, function(el) {
        scrollElement = document.querySelector(el.dataset.scrollElement);
        increment  = parseInt(el.dataset.scrollIncrement);
        nextOffset = newOffset + increment;
        limit      = parseInt(scrollElement.dataset.scrollLimit);

        setVisibility(el, nextOffset, limit);
      });
    };

    var resetScroll = function(element) {
      element.scrollTop = 0;
      element.dataset.scrollOffset = 0;
    };

    each(document.querySelectorAll('[data-clipboard-target]'), function(el) {
      var clipboard = new Clipboard(el);
      var notification;

      var notify = function(clipboardNotification, notificationText) {
        notification = document.getElementById(clipboardNotification.slice(1));
        notification.textContent = notificationText;
        my_addClass(notification, 'in');
        setTimeout(function() {
          my_removeClass(notification, 'in');
        }, 1400);
      };

      var notifySuccess = function(e) {
        notify(e.trigger.dataset.clipboardNotification, "Copied!");
      };

      var notifyFailure = function(e) {
        //if the copy function failed the text should still be selected, so just ask the user to hit ctrl+c
        notify(e.trigger.dataset.clipboardNotification, "Press Ctrl+C to copy");
      };

      clipboard.on('success', notifySuccess);
      clipboard.on('error', notifyFailure);
      handleClicks(el, function(e) {
        if (window.parent.squatch && window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('copy_btn_clicked', e.type);
        }
      });
    });

    each(scrollElements, function(el) {
      var element = document.querySelector(el.dataset.scrollElement);
      var increment = parseInt(el.dataset.scrollIncrement);
      var limit     = parseInt(element.dataset.scrollLimit.valueOf());
      var offset    = parseInt(element.dataset.scrollOffset.valueOf());
      var newOffset;

      element.dataset.scrollLimit = limit;

      var nextOffset = offset + increment;

      setVisibility(el, nextOffset, limit);

      // Force IE to forget previous scroll top value
      resetScroll(element);

      listenToClick(el, 'click', function() {
        offset = parseInt(element.dataset.scrollOffset);

        newOffset = offset + increment;

        if (inValidRange(newOffset, limit)) {
          scrollTop(element, document.getElementById(newOffset).offsetTop, 400);
          element.dataset.scrollOffset = newOffset;

          setVisibilityAll(scrollElements, newOffset);
        }
      });
    });

    each(document.querySelectorAll('[data-moment]'), function(el) {
      var time = moment(parseInt(el.textContent));
      el.textContent = time.fromNow();
    });

    each(document.getElementsByClassName('squatch-header-close'), function(el) {
      handleClicks(el, function(e) {
        if (window.parent.squatch && window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('close_popup', e.type);
        }
      });
    });

    // CTA
    each(document.getElementsByClassName('cta-container'), function(el) {
      el.onclick = function(e) {
        if (window.parent.squatch && window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('open_popup', e.type);
        }
      }
    });

    // Popup stuff
    each(document.querySelectorAll('[data-open-panel]'), function(el) {
      var element = document.getElementById(el.dataset.openPanel.slice(1));

      if (element) {
        el.onclick = function() {
          my_addClass(element, 'open');
        };
      }
    });

    each(document.querySelectorAll('[data-close-panel]'), function(el) {
      var element = document.getElementById(el.dataset.closePanel.slice(1));

      if (element) {
        el.onclick = function() {
          my_removeClass(element, 'open');
        };
      }
    });

    var setContainerHeight = function(containerEl) {
      var bodyEl           = document.getElementsByClassName('squatch-body')[0];
      var titleEl          = document.getElementsByClassName('squatch-title')[0];
      var titleStyle       = getComputedStyle(titleEl);
      var panelEl          = document.getElementById('squatch-panel');
      var referralsEl      = document.getElementsByClassName('squatch-referrals')[0];
      var referralsTitleEl = document.getElementsByClassName('squatch-referrals-title')[0];

      var bodyHeight = bodyEl.offsetHeight;
      var bodyHeightWithoutTitle = bodyHeight - titleEl.offsetHeight - parseInt(titleStyle.marginTop) - parseInt(titleStyle.marginBottom) - titleEl.offsetTop;
      var panelHeight = panelEl ? panelEl.offsetHeight : 0;

      if (referralsEl && referralsEl.style.display !== 'none') {
        panelHeight -= referralsEl.offsetHeight;
      }

      if (referralsTitleEl && referralsTitleEl.style.display !== 'none') {
        panelHeight -= referralsTitleEl.offsetHeight;
      }

      containerEl.style.height = bodyHeight + panelHeight + "px";

      var stylesheet = document.createElement('style');
      stylesheet.type = 'text/css';

      var css = '#squatch-panel.open {' +
        '-webkit-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-ms-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-o-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        'transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '}' +
        'html.lt-ie9 #squatch-panel.open {' +
        'top: -' + bodyHeightWithoutTitle + 'px;' +
        '}';

      if (stylesheet.styleSheet){
        // IE
        stylesheet.styleSheet.cssText = css;
      } else {
        // W3C Standard
        stylesheet.appendChild(document.createTextNode(css));
      }

      document.querySelector('head').appendChild(stylesheet);
    };

    var containerEl = document.getElementsByClassName('squatch-container-popup')[0];

    if (containerEl) {
     window.onload = function() {
       setContainerHeight(containerEl);
     }

    }
  });

})();
<|endoftext|>


<commit_before>/**
 * @module ember-flexberry
 */

import FlexberryBaseComponent from './flexberry-base-component';

/**
 * Component to view list of object.
 *
 * @class FlexberryObjectlistview
 * @extends FlexberryBaseComponent
 */
export default FlexberryBaseComponent.extend({
  actions: {
    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method sortByColumn
     * @param {Object} column Column to sort by.
     */
    sortByColumn: function(column) {
      throw new Error('No handler for sortByColumn action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... sortByColumn=(action "sortByColumn")}}.');
    },

    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method addColumnToSorting
     * @param {Object} column Column to add sorting by.
     */
    addColumnToSorting: function(column) {
      throw new Error('No handler for addColumnToSorting action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... addColumnToSorting=(action "addColumnToSorting")}}.');
    },

    /**
     * Handles action from row click (action is handled at route so it can't be closure action now).
     *
     * @method rowClick
     * @param {Object} record Clicked record.
     */
    rowClick: function(record) {
      this.sendAction('action', record);
    },

    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method previousPage
     */
    previousPage: function() {
      throw new Error('No handler for previousPage action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... previousPage=(action "previousPage")}}.');
    },

    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method nextPage
     */
    nextPage: function() {
      throw new Error('No handler for nextPage action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... nextPage=(action "nextPage")}}.');
    },

    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method gotoPage
     * @param {number} pageNumber Number of page to go to
     */
    gotoPage: function(pageNumber) {
      throw new Error('No handler for gotoPage action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... gotoPage=(action "gotoPage")}}.');
    },

    /**
     * A stub for call of custom user buttons. Used when no handler is defined.
     *
     * @method customButtons
     * @return {Array} Returns only 'undefined' (because is's a stub).
     */
    customButtons: function() {
      return undefined;
    },

    /**
     * Handler to get user button's actions and send action to corresponding controllers's handler.
     *
     * @method customButtonAction
     */
    customButtonAction: function(actionName) {
      if (!actionName) {
        throw new Error('No handler for custom button of flexberry-objectlistview toolbar was found.');
      }

      this.sendAction(actionName);
    },

    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method filterByAnyMatch
     * @param {pattern} The pattern to filter objects.
     */
    filterByAnyMatch: function(pattern) {
      throw new Error('No handler for filterByAnyMatch action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... filterByAnyMatch=(action "filterByAnyMatch")}}.');
    }
  },

  /**
   * Primary action for row click.
   *
   * @property action
   * @type String
   * @default 'rowClick'
   */
  action: 'rowClick',

  /**
   * Default cell component that will be used to display values in columns headers.
   *
   * @property {Object} headerCellComponent
   * @property {String} [headerCellComponent.componentName='object-list-view-header-cell']
   * @property {String} [headerCellComponent.componentProperties=null]
   */
  headerCellComponent: {
    componentName: 'object-list-view-header-cell',
    componentProperties: null
  },

  /**
   * Default cell component that will be used to display values in columns cells.
   *
   * @property {Object} cellComponent
   * @property {String} [cellComponent.componentName='object-list-view-cell']
   * @property {String} [cellComponent.componentProperties=null]
   */
  cellComponent: {
    componentName: 'object-list-view-cell',
    componentProperties: null
  },

  /**
   * Default cell component that will be used to display values in single column.
   *
   * @property {Object} singleColumnCellComponent
   * @property {String} [singleColumnCellComponent.componentName='object-list-view-single-column-cell']
   * @property {String} [singleColumnCellComponent.componentProperties=null]
   */
  singleColumnCellComponent: {
    componentName: 'object-list-view-single-column-cell',
    componentProperties: null
  },

  /**
   * Flag: indicates whether to use single column to display all model properties or not.
   *
   * @property useSingleColumn
   * @type Boolean
   * @default false
   */
  useSingleColumn: false,

  /**
   * Header title of single column.
   *
   * @property singleColumnHeaderTitle
   * @type String
   */
  singleColumnHeaderTitle: undefined,

  /**
   * Flag: indicates whether to show asterisk icon in first column of every changed row.
   *
   * @property showAsteriskInRow
   * @type Boolean
   * @default false
   */
  showAsteriskInRow: false,

  /**
   * Flag: indicates whether to show checkbox in first column of every row.
   *
   * @property showCheckBoxInRow
   * @type Boolean
   * @default false
   */
  showCheckBoxInRow: false,

  /**
   * Flag: indicates whether to show delete button in first column of every row.
   *
   * @property showDeleteButtonInRow
   * @type Boolean
   * @default false
   */
  showDeleteButtonInRow: false,

  /**
   * Flag: indicates whether to show dropdown menu with edit menu item, in last column of every row.
   *
   * @property showEditMenuItemInRow
   * @type Boolean
   * @default false
   */
  showEditMenuItemInRow: false,

  /**
   * Flag: indicates whether to show dropdown menu with delete menu item, in last column of every row.
   *
   * @property showDeleteMenuItemInRow
   * @type Boolean
   * @default false
   */
  showDeleteMenuItemInRow: false,

  /**
   * Additional menu items for dropdown menu in last column of every row.
   *
   * @property menuInRowAdditionalItems
   * @type boolean
   * @default null
   */
  menuInRowAdditionalItems: null,

  /**
   * Flag: indicates whether table rows are clickable.
   *
   * @property rowClickable
   * @type Boolean
   * @default true
   */
  rowClickable: true,

  /**
   * Flag: indicates whether ordering by clicking on column headers is allowed.
   *
   * @property headerClickable
   * @type Boolean
   * @default false
   */
  orderable: false,

  /**
   * Dictionary with sorting data related to columns.
   *
   * @property sorting
   * @type Object
   */
  sorting: null,

  /**
   * Model projection which should be used to display given content.
   *
   * @property modelProjection
   * @type Object
   * @default null
   */
  modelProjection: null,

  /**
   * Content to be displayed (models collection).
   *
   * @property content
   * @type ManyArray
   * @default null
   */
  content: null,

  /**
   * Model's name. Used by toolbar.
   *
   * @property modelName
   * @type String
   * @default null
   */
  modelName: null,

  /**
   * Flag: indicates whether to show creation button at toolbar.
   *
   * @property createNewButton
   * @type Boolean
   * @default false
   */
  createNewButton: false,

  /**
   * Flag: indicates whether to show refresh button at toolbar.
   *
   * @property refreshButton
   * @type Boolean
   * @default false
   */
  refreshButton: false,

  /**
   * Flag: indicates whether to show delete button at toolbar.
   *
   * @property deleteButton
   * @type Boolean
   * @default false
   */
  deleteButton: false,

  /**
   * Flag: indicates whether to show filter button at toolbar.
   *
   * @property filterButton
   * @type Boolean
   * @default false
   */
  filterButton: false,

  /**
   * Used to specify 'filter by any match' field value.
   *
   * @property filterText
   * @type String
   * @default null
   */
  filterText: null,

  /**
   * Array of pages to show.
   *
   * @property pages
   * @type ManyArray
   * @default null
   */
  pages: null,

  /**
   * Current number of records to show per page.
   *
   * @property perPageValue
   * @type number
   * @default null
   */
  perPageValue: null,

  /**
   * Array of numbers of records to show on one page.
   *
   * @property perPageValues
   * @type ManyArray
   * @default null
   */
  perPageValues: null,

  /**
   * Function to determine if current page has previous page.
   *
   * @property hasPreviousPage
   * @type Function
   * @default null
   */
  hasPreviousPage: null,

  /**
   * Function to determine if current page has next page.
   *
   * @property hasNextPage
   * @type Function
   * @default null
   */
  hasNextPage: null
});
<commit_msg>Change by CR<commit_after>/**
 * @module ember-flexberry
 */

import FlexberryBaseComponent from './flexberry-base-component';

/**
 * Component to view list of object.
 *
 * @class FlexberryObjectlistview
 * @extends FlexberryBaseComponent
 */
export default FlexberryBaseComponent.extend({
  actions: {
    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method sortByColumn
     * @param {Object} column Column to sort by.
     */
    sortByColumn: function(column) {
      throw new Error('No handler for sortByColumn action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... sortByColumn=(action "sortByColumn")}}.');
    },

    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method addColumnToSorting
     * @param {Object} column Column to add sorting by.
     */
    addColumnToSorting: function(column) {
      throw new Error('No handler for addColumnToSorting action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... addColumnToSorting=(action "addColumnToSorting")}}.');
    },

    /**
     * Handles action from row click (action is handled at route so it can't be closure action now).
     *
     * @method rowClick
     * @param {Object} record Clicked record.
     */
    rowClick: function(record) {
      this.sendAction('action', record);
    },

    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method previousPage
     */
    previousPage: function() {
      throw new Error('No handler for previousPage action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... previousPage=(action "previousPage")}}.');
    },

    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method nextPage
     */
    nextPage: function() {
      throw new Error('No handler for nextPage action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... nextPage=(action "nextPage")}}.');
    },

    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method gotoPage
     * @param {number} pageNumber Number of page to go to
     */
    gotoPage: function(pageNumber) {
      throw new Error('No handler for gotoPage action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... gotoPage=(action "gotoPage")}}.');
    },

    /**
     * A stub for call of custom user buttons. Used when no handler is defined.
       When not stab is used (closure action is defined), structured info about custom buttons is returned.
       Closure action has to return an array of structures:

       ```
       {
      	buttonName: '...', // Button displayed name.
      	buttonAction: '...', // Action that is called from controller on this button click (it has to be registered at component).
      	buttonClasses: '...' // Css classes for button.
       }
       ```

      Example of how to add user buttons:
       1) it has to be defined special method (it will be used as closure action) at corresponding controller (name is not fixed).
       ```
       actions: {
        getCustomButtons: function() {
          return [{
          	buttonName: 'UserButton',
          	buttonAction: 'userButtonActionTest',
          	buttonClasses: 'my-test-user-button test-click-button'
          }];
        }
       }
       ```

       2) it has to be defined set as 'buttonAction' methods.
       ```
       actions: {
        userButtonActionTest: function() {
          this.set('header', this.get('header') + ' clicked');
        }
       }
       ```

       3) defined methods have to be registered at conponent.
       ```
       {{flexberry-objectlistview
        ...
        customButtons = (action "getCustomButtons")
        userButtonActionTest = 'userButtonActionTest'
       }}
       ```
     * @method customButtons
     * @return Returns only `undefined` (because it's a stub).
     */
    customButtons: function() {
      return undefined;
    },

    /**
     * Handler to get user button's actions and send action to corresponding controllers's handler.
     *
     * @method customButtonAction
     */
    customButtonAction: function(actionName) {
      if (!actionName) {
        throw new Error('No handler for custom button of flexberry-objectlistview toolbar was found.');
      }

      this.sendAction(actionName);
    },

    /**
     * Handles action from object-list-view when no handler for this component is defined.
     *
     * @method filterByAnyMatch
     * @param {pattern} The pattern to filter objects.
     */
    filterByAnyMatch: function(pattern) {
      throw new Error('No handler for filterByAnyMatch action set for flexberry-objectlistview. ' +
                      'Set handler like {{flexberry-objectlistview ... filterByAnyMatch=(action "filterByAnyMatch")}}.');
    }
  },

  /**
   * Primary action for row click.
   *
   * @property action
   * @type String
   * @default 'rowClick'
   */
  action: 'rowClick',

  /**
   * Default cell component that will be used to display values in columns headers.
   *
   * @property {Object} headerCellComponent
   * @property {String} [headerCellComponent.componentName='object-list-view-header-cell']
   * @property {String} [headerCellComponent.componentProperties=null]
   */
  headerCellComponent: {
    componentName: 'object-list-view-header-cell',
    componentProperties: null
  },

  /**
   * Default cell component that will be used to display values in columns cells.
   *
   * @property {Object} cellComponent
   * @property {String} [cellComponent.componentName='object-list-view-cell']
   * @property {String} [cellComponent.componentProperties=null]
   */
  cellComponent: {
    componentName: 'object-list-view-cell',
    componentProperties: null
  },

  /**
   * Default cell component that will be used to display values in single column.
   *
   * @property {Object} singleColumnCellComponent
   * @property {String} [singleColumnCellComponent.componentName='object-list-view-single-column-cell']
   * @property {String} [singleColumnCellComponent.componentProperties=null]
   */
  singleColumnCellComponent: {
    componentName: 'object-list-view-single-column-cell',
    componentProperties: null
  },

  /**
   * Flag: indicates whether to use single column to display all model properties or not.
   *
   * @property useSingleColumn
   * @type Boolean
   * @default false
   */
  useSingleColumn: false,

  /**
   * Header title of single column.
   *
   * @property singleColumnHeaderTitle
   * @type String
   */
  singleColumnHeaderTitle: undefined,

  /**
   * Flag: indicates whether to show asterisk icon in first column of every changed row.
   *
   * @property showAsteriskInRow
   * @type Boolean
   * @default false
   */
  showAsteriskInRow: false,

  /**
   * Flag: indicates whether to show checkbox in first column of every row.
   *
   * @property showCheckBoxInRow
   * @type Boolean
   * @default false
   */
  showCheckBoxInRow: false,

  /**
   * Flag: indicates whether to show delete button in first column of every row.
   *
   * @property showDeleteButtonInRow
   * @type Boolean
   * @default false
   */
  showDeleteButtonInRow: false,

  /**
   * Flag: indicates whether to show dropdown menu with edit menu item, in last column of every row.
   *
   * @property showEditMenuItemInRow
   * @type Boolean
   * @default false
   */
  showEditMenuItemInRow: false,

  /**
   * Flag: indicates whether to show dropdown menu with delete menu item, in last column of every row.
   *
   * @property showDeleteMenuItemInRow
   * @type Boolean
   * @default false
   */
  showDeleteMenuItemInRow: false,

  /**
   * Additional menu items for dropdown menu in last column of every row.
   *
   * @property menuInRowAdditionalItems
   * @type boolean
   * @default null
   */
  menuInRowAdditionalItems: null,

  /**
   * Flag: indicates whether table rows are clickable.
   *
   * @property rowClickable
   * @type Boolean
   * @default true
   */
  rowClickable: true,

  /**
   * Flag: indicates whether ordering by clicking on column headers is allowed.
   *
   * @property headerClickable
   * @type Boolean
   * @default false
   */
  orderable: false,

  /**
   * Dictionary with sorting data related to columns.
   *
   * @property sorting
   * @type Object
   */
  sorting: null,

  /**
   * Model projection which should be used to display given content.
   *
   * @property modelProjection
   * @type Object
   * @default null
   */
  modelProjection: null,

  /**
   * Content to be displayed (models collection).
   *
   * @property content
   * @type ManyArray
   * @default null
   */
  content: null,

  /**
   * Model's name. Used by toolbar.
   *
   * @property modelName
   * @type String
   * @default null
   */
  modelName: null,

  /**
   * Flag: indicates whether to show creation button at toolbar.
   *
   * @property createNewButton
   * @type Boolean
   * @default false
   */
  createNewButton: false,

  /**
   * Flag: indicates whether to show refresh button at toolbar.
   *
   * @property refreshButton
   * @type Boolean
   * @default false
   */
  refreshButton: false,

  /**
   * Flag: indicates whether to show delete button at toolbar.
   *
   * @property deleteButton
   * @type Boolean
   * @default false
   */
  deleteButton: false,

  /**
   * Flag: indicates whether to show filter button at toolbar.
   *
   * @property filterButton
   * @type Boolean
   * @default false
   */
  filterButton: false,

  /**
   * Used to specify 'filter by any match' field value.
   *
   * @property filterText
   * @type String
   * @default null
   */
  filterText: null,

  /**
   * Array of pages to show.
   *
   * @property pages
   * @type ManyArray
   * @default null
   */
  pages: null,

  /**
   * Current number of records to show per page.
   *
   * @property perPageValue
   * @type number
   * @default null
   */
  perPageValue: null,

  /**
   * Array of numbers of records to show on one page.
   *
   * @property perPageValues
   * @type ManyArray
   * @default null
   */
  perPageValues: null,

  /**
   * Function to determine if current page has previous page.
   *
   * @property hasPreviousPage
   * @type Function
   * @default null
   */
  hasPreviousPage: null,

  /**
   * Function to determine if current page has next page.
   *
   * @property hasNextPage
   * @type Function
   * @default null
   */
  hasNextPage: null
});
<|endoftext|>


<commit_before>var $ = require('jquery-node-browserify');

var config = require('./config');
var demoRoutes = require('./demoRoutes');

var radius = 100;
var mapRoute = null;
var markers = [];

function init() {
  setLocalPoints(null);

  map = L.map('map');
  //map.on('load', setInitMap);
  marker = L.marker([config.defaultConfig.latitude, config.defaultConfig.longitude]).addTo(map);
  map.setView([config.defaultConfig.latitude, config.defaultConfig.longitude], config.defaultConfig.zoom);
  L.tileLayer(config.cloudmade.url, {
    attribution: config.cloudmade.attribution
  }).addTo(map);

  map.on('click', addMarker);
  $('.undo-btn').bind('click', undoDrawRoute);
  $('.save-markers-btn').bind('click', getLatLngsFromMarkers);
  $('.demo-A').bind('click', demoA);
}

function addMarker(e) {
  var lat = e.latlng.lat;
  var lng = e.latlng.lng;
  var m = L.marker([lat, lng]).addTo(map);
  markers.push(m);
  matching(lat, lng);
}

function matching(lat, lng) {
  $.ajax({
    type: 'POST',
    url: 'http://82.130.25.39:8080/query/nearby',
    data: {
      lng: lng,
      lat: lat,
      radius: radius
    }
  }).done(function(data) {
    if (data.length) {
      var localPoints = getLocalPoints();
      var matching = new M.STMatching();
      var points = matching.getCandidatePoints(lng, lat, localPoints, data);
      setLocalPoints(points);
      var routes = matching.findRoute(points);
      drawRoute(routes);
    }
  });
}

function demoA() {
  var routeA = demoRoutes.routeA,
    len = routeA.length,
    i = 2,
    markersL = [];

  var bikeIcon = L.icon({
    iconUrl: 'js/images/marker-bike-green-shadowed.png',
    iconSize: [25, 39],
    iconAnchor: [12, 39],
    shadowUrl: null
  });

  var latlng1 = L.latLng(routeA[0][0], routeA[0][1]);
  var latlng2 = L.latLng(routeA[1][0], routeA[1][1]);
  setTimeout(function() {
    matching(routeA[0][0], routeA[0][1])
  }, 1000);

  setTimeout(function() {
    matching(routeA[1][0], routeA[1][1])
  }, 2000);

  map.setView([routeA[0][0], routeA[0][1]], 18);

  markersL.push(latlng1, latlng2);
  console.log(markersL);
  animatedMarker = L.animatedMarker(markersL, {
    icon: bikeIcon,
    interval: 12000,
    onEnd: function() {
      if(i<len) {
        console.log(animatedMarker);
        this.addLatLng(L.latLng([routeA[i][0], routeA[i][1]]));
        matching(routeA[i][0], routeA[i][1])
      }
      i += 1;
    }
  });
  map.addLayer(animatedMarker);
}

function drawRoute(routes) {
  if (mapRoute) map.removeLayer(mapRoute);

  var routePoints = [];
  for (var i = 0; i < routes.length; i++) {
    var point = {
      lat: routes[i].latitude,
      lon: routes[i].longitude
    };
    routePoints.push(point);
  }
  if (routePoints.length >= 2) {
    mapRoute = L.polyline(routePoints).addTo(map);
  }
}

function undoDrawRoute() {
  if (mapRoute) var routeLength = mapRoute.getLatLngs().length;
  if (routeLength) {
    mapRoute.spliceLatLngs(routeLength - 1, 1);

    var points = getLocalPoints();
    points.pop();
    setLocalPoints(points);

    var m = markers.pop();
    map.removeLayer(m);
  }
}

function getLatLngsFromMarkers() {
  var latlngs = [];
  $.each(markers, function(i, marker) {
    var latlng = [marker.getLatLng().lat, marker.getLatLng().lng];
    latlngs.push(latlng);
  });
  console.log(JSON.stringify(latlngs));
}

function findRoute(points) {
  var cPoints = points[points.length - 1];
  var point = cPoints[0];
  var routes = [];
  for (var i = 1; i < cPoints.length; i++) {
    var _point = cPoints[i];
    if (_point.probability > point.probability) point = _point;
  }
  routes.unshift(point);

  var prePointId = point.prePointId;
  for (var i = points.length - 2; i >= 0; i--) {
    var _points = points[i];
    for (var j = 0; j < _points.length; j++) {
      var _point = _points[j];
      if (_point.id === prePointId) {
        routes.unshift(_point);
        prePointId = _point.prePointId;
      }
    }
  }
  //console.log(routes);
  return routes;
}

function getLocalPoints() {
  var localPoints = null;
  var localPointsJson = localStorage.getItem('localPoints');
  if (localPointsJson !== null) {
    try {
      localPoints = JSON.parse(localPointsJson);
    } catch (e) {
      console.log('Invalid localStorage contents');
      localPoints = null;
    }
  }
  return localPoints;
}

function setLocalPoints(points) {
  var localPointsJson = JSON.stringify(points);
  localStorage.setItem('localPoints', localPointsJson);
}

function setInitMap() {
  //Get geolocation
  if (navigator.geolocation) {
    navigator.geolocation.watchPosition(function(position) {
      var latitude = position.coords.latitude;
      var longitude = position.coords.longitude;
      setPosition(latitude, longitude);
    });
  } else {
    console.log("Not support Geolocation!");
    var latitude = config.defaultConfig.latitude;
    var longitude = config.defaultConfig.longitude;
    setPosition(latitude, longitude);
  }
}

function setPosition(latitude, longitude) {
  map.setView([latitude, longitude], config.defaultConfig.zoom);
  marker.setLatLng([latitude, longitude]);
}

init();
<commit_msg>change map source<commit_after>var $ = require('jquery-node-browserify');

var config = require('./config');
var demoRoutes = require('./demoRoutes');

var radius = 100;
var mapRoute = null;
var markers = [];

function init() {
  setLocalPoints(null);

  map = L.map('map');
  //map.on('load', setInitMap);
  marker = L.marker([config.defaultConfig.latitude, config.defaultConfig.longitude]).addTo(map);
  map.setView([config.defaultConfig.latitude, config.defaultConfig.longitude], config.defaultConfig.zoom);
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '© OpenStreetMap contributors'
  }).addTo(map);
  /*L.tileLayer(config.cloudmade.url, {*/
    //attribution: config.cloudmade.attribution
  /*}).addTo(map);*/

  map.on('click', addMarker);
  $('.undo-btn').bind('click', undoDrawRoute);
  $('.save-markers-btn').bind('click', getLatLngsFromMarkers);
  $('.demo-A').bind('click', demoA);
}

function addMarker(e) {
  var lat = e.latlng.lat;
  var lng = e.latlng.lng;
  var m = L.marker([lat, lng]).addTo(map);
  markers.push(m);
  matching(lat, lng);
}

function matching(lat, lng) {
  $.ajax({
    type: 'POST',
    url: 'http://82.130.25.39:8080/query/nearby',
    data: {
      lng: lng,
      lat: lat,
      radius: radius
    }
  }).done(function(data) {
    if (data.length) {
      var localPoints = getLocalPoints();
      var matching = new M.STMatching();
      var points = matching.getCandidatePoints(lng, lat, localPoints, data);
      setLocalPoints(points);
      var routes = matching.findRoute(points);
      drawRoute(routes);
    }
  });
}

function demoA() {
  var routeA = demoRoutes.routeA,
    len = routeA.length,
    i = 2,
    markersL = [];

  var bikeIcon = L.icon({
    iconUrl: 'js/images/marker-bike-green-shadowed.png',
    iconSize: [25, 39],
    iconAnchor: [12, 39],
    shadowUrl: null
  });

  var latlng1 = L.latLng(routeA[0][0], routeA[0][1]);
  var latlng2 = L.latLng(routeA[1][0], routeA[1][1]);
  setTimeout(function() {
    matching(routeA[0][0], routeA[0][1])
  }, 1000);

  setTimeout(function() {
    matching(routeA[1][0], routeA[1][1])
  }, 2000);

  map.setView([routeA[0][0], routeA[0][1]], 18);

  markersL.push(latlng1, latlng2);
  console.log(markersL);
  animatedMarker = L.animatedMarker(markersL, {
    icon: bikeIcon,
    interval: 12000,
    onEnd: function() {
      if (i < len) {
        console.log(animatedMarker);
        this.addLatLng(L.latLng([routeA[i][0], routeA[i][1]]));
        matching(routeA[i][0], routeA[i][1])
      }
      i += 1;
    }
  });
  map.addLayer(animatedMarker);
}

function drawRoute(routes) {
  if (mapRoute) map.removeLayer(mapRoute);

  var routePoints = [];
  for (var i = 0; i < routes.length; i++) {
    var point = {
      lat: routes[i].latitude,
      lon: routes[i].longitude
    };
    routePoints.push(point);
  }
  if (routePoints.length >= 2) {
    mapRoute = L.polyline(routePoints).addTo(map);
  }
}

function undoDrawRoute() {
  if (mapRoute) var routeLength = mapRoute.getLatLngs().length;
  if (routeLength) {
    mapRoute.spliceLatLngs(routeLength - 1, 1);

    var points = getLocalPoints();
    points.pop();
    setLocalPoints(points);

    var m = markers.pop();
    map.removeLayer(m);
  }
}

function getLatLngsFromMarkers() {
  var latlngs = [];
  $.each(markers, function(i, marker) {
    var latlng = [marker.getLatLng().lat, marker.getLatLng().lng];
    latlngs.push(latlng);
  });
  console.log(JSON.stringify(latlngs));
}

function findRoute(points) {
  var cPoints = points[points.length - 1];
  var point = cPoints[0];
  var routes = [];
  for (var i = 1; i < cPoints.length; i++) {
    var _point = cPoints[i];
    if (_point.probability > point.probability) point = _point;
  }
  routes.unshift(point);

  var prePointId = point.prePointId;
  for (var i = points.length - 2; i >= 0; i--) {
    var _points = points[i];
    for (var j = 0; j < _points.length; j++) {
      var _point = _points[j];
      if (_point.id === prePointId) {
        routes.unshift(_point);
        prePointId = _point.prePointId;
      }
    }
  }
  //console.log(routes);
  return routes;
}

function getLocalPoints() {
  var localPoints = null;
  var localPointsJson = localStorage.getItem('localPoints');
  if (localPointsJson !== null) {
    try {
      localPoints = JSON.parse(localPointsJson);
    } catch (e) {
      console.log('Invalid localStorage contents');
      localPoints = null;
    }
  }
  return localPoints;
}

function setLocalPoints(points) {
  var localPointsJson = JSON.stringify(points);
  localStorage.setItem('localPoints', localPointsJson);
}

function setInitMap() {
  //Get geolocation
  if (navigator.geolocation) {
    navigator.geolocation.watchPosition(function(position) {
      var latitude = position.coords.latitude;
      var longitude = position.coords.longitude;
      setPosition(latitude, longitude);
    });
  } else {
    console.log("Not support Geolocation!");
    var latitude = config.defaultConfig.latitude;
    var longitude = config.defaultConfig.longitude;
    setPosition(latitude, longitude);
  }
}

function setPosition(latitude, longitude) {
  map.setView([latitude, longitude], config.defaultConfig.zoom);
  marker.setLatLng([latitude, longitude]);
}

init();
<|endoftext|>


<commit_before><commit_msg>use template literal, improved UI<commit_after><|endoftext|>


<commit_before>
/**
 * Internal dependencies
 */
import createTracking from './createTracking';
import { DATA_LAYER } from './constants';
import {
	disableTracking,
	enableTracking,
	isTrackingEnabled,
} from './index';

const resetGlobals = () => {
	delete global._googlesitekitBaseData;
	delete global[ DATA_LAYER ];
};

const fakeTimeouts = ( func ) => {
	jest.useFakeTimers();
	const promise = func();
	jest.runAllTimers();
	return promise;
};

describe( 'createTracking', () => {
	afterEach( resetGlobals );
	it( 'initializes disabled tracking based on user preference', () => {
		const { isTrackingEnabled: isEnabled } = createTracking( { trackingEnabled: false } );

		expect( isEnabled() ).toStrictEqual( false );
	} );

	it( 'initializes enabled tracking based on user preference', () => {
		const { isTrackingEnabled: isEnabled } = createTracking( { trackingEnabled: true } );

		expect( isEnabled() ).toStrictEqual( true );
	} );
} );

describe( 'disableTracking and isTrackingEnabled', () => {
	afterEach( resetGlobals );

	it( 'does not mutate global tracking settings when toggling active state', () => {
		global._googlesitekitBaseData = { trackingEnabled: true };

		disableTracking();

		expect( isTrackingEnabled() ).toStrictEqual( false );
		expect( global._googlesitekitBaseData.trackingEnabled ).toStrictEqual( true );
	} );
} );

describe( 'enableTracking and isTrackingEnabled', () => {
	afterEach( resetGlobals );

	it( 'does not mutate global tracking settings when toggling active state', () => {
		global._googlesitekitBaseData = { trackingEnabled: false };

		enableTracking();

		expect( isTrackingEnabled() ).toStrictEqual( true );
		expect( global._googlesitekitBaseData.trackingEnabled ).toStrictEqual( false );
	} );
} );

describe( 'trackEvent', () => {
	afterEach( resetGlobals );

	it( 'adds a tracking event to the dataLayer', async () => {
		const config = {
			referenceSiteURL: 'https://www.example.com/',
			userIDHash: 'a1b2c3',
			trackingID: 'UA-12345678-1',
			isFirstAdmin: true,
			trackingEnabled: true,
		};

		let pushArgs;
		const dataLayer = {
			[ DATA_LAYER ]: {
				push: ( ...args ) => pushArgs = args,
			},
		};
		const { trackEvent } = createTracking( config, dataLayer );

		// Ignore warning (see below) since irrelevant for this test.
		await fakeTimeouts( () => trackEvent( 'category', 'name', 'label', 'value' ) );

		// dataLayerPush must push an instance of `Arguments` onto the data layer.
		// Because `arguments` is a special, `Array`-like object (but not an actual `Array`),
		// we can only create it using the magic `arguments` variable
		// made available to normal, non-arrow functions.
		expect( console ).toHaveWarned();
		expect( pushArgs.length ).toEqual( 1 );
		expect( Object.prototype.toString.apply( pushArgs[ 0 ] ) ).toEqual( '[object Arguments]' );
		expect( pushArgs[ 0 ].length ).toEqual( 3 );
		const [ event, eventName, eventData ] = pushArgs[ 0 ];
		expect( event ).toEqual( 'event' );
		expect( eventName ).toEqual( 'name' );
		expect( eventData ).toEqual( expect.objectContaining( {
			send_to: config.trackingID,
			event_category: 'category',
			event_label: 'label',
			event_value: 'value',
			dimension1: 'https://www.example.com',
			dimension2: 'true',
			dimension3: config.userIDHash,
		} ) );
		expect( pushArgs[ 0 ][ 2 ] ).toHaveProperty( 'event_callback' );
	} );

	it( 'does not push to dataLayer when tracking is disabled', async () => {
		const push = jest.fn();
		const dataLayer = {
			[ DATA_LAYER ]: { push },
		};
		const { trackEvent } = createTracking( { trackingEnabled: false }, dataLayer );

		await fakeTimeouts( () => trackEvent( 'test-category', 'test-name', 'test-label', 'test-value' ) );
		expect( push ).not.toHaveBeenCalled();
	} );

	it( 'resolves without warning when event_callback is called', async () => {
		const dataLayer = {
			[ DATA_LAYER ]: {
				push: ( args ) => args[ 2 ].event_callback(),
			},
		};
		const { trackEvent } = createTracking( { trackingEnabled: true }, dataLayer );

		const consoleWarnSpy = jest.spyOn( global.console, 'warn' );
		await fakeTimeouts( () => trackEvent( 'test-category', 'test-name', 'test-label', 'test-value' ) );
		expect( consoleWarnSpy ).not.toHaveBeenCalled();
		consoleWarnSpy.mockClear();
	} );

	it( 'resolves with warning when event_callback is not called (within one second)', async () => {
		const dataLayer = {
			[ DATA_LAYER ]: {
				push: () => {},
			},
		};

		const { trackEvent } = createTracking( { trackingEnabled: true }, dataLayer );

		const consoleWarnSpy = jest.spyOn( global.console, 'warn' );
		await fakeTimeouts( () => trackEvent( 'test-category', 'test-name', 'test-label', 'test-value' ) );
		expect( console ).toHaveWarned();
		expect( consoleWarnSpy ).toHaveBeenCalledWith( 'Tracking event "test-name" (category "test-category") took too long to fire.' );
		consoleWarnSpy.mockClear();
	} );

	it( 'not push to dataLayer with the opt-out set', async () => {
		const push = jest.fn();
		const dataLayer = {
			[ DATA_LAYER ]: { push },
		};

		const mockGlobal = {
			_gaUserPrefs: {
				ioo: () => true,
			},
		};
		const iooSpy = jest.spyOn( mockGlobal._gaUserPrefs, 'ioo' );
		const { trackEvent } = createTracking( { trackingEnabled: true }, dataLayer, mockGlobal );
		await fakeTimeouts( () => trackEvent( 'test-category', 'test-name', 'test-label', 'test-value' ) );
		expect( iooSpy ).toHaveBeenCalled();
		expect( push ).not.toHaveBeenCalled();
	} );
} );
<commit_msg>Update change of key in trackEvent test.<commit_after>
/**
 * Internal dependencies
 */
import createTracking from './createTracking';
import { DATA_LAYER } from './constants';
import {
	disableTracking,
	enableTracking,
	isTrackingEnabled,
} from './index';

const resetGlobals = () => {
	delete global._googlesitekitBaseData;
	delete global[ DATA_LAYER ];
};

const fakeTimeouts = ( func ) => {
	jest.useFakeTimers();
	const promise = func();
	jest.runAllTimers();
	return promise;
};

describe( 'createTracking', () => {
	afterEach( resetGlobals );
	it( 'initializes disabled tracking based on user preference', () => {
		const { isTrackingEnabled: isEnabled } = createTracking( { trackingEnabled: false } );

		expect( isEnabled() ).toStrictEqual( false );
	} );

	it( 'initializes enabled tracking based on user preference', () => {
		const { isTrackingEnabled: isEnabled } = createTracking( { trackingEnabled: true } );

		expect( isEnabled() ).toStrictEqual( true );
	} );
} );

describe( 'disableTracking and isTrackingEnabled', () => {
	afterEach( resetGlobals );

	it( 'does not mutate global tracking settings when toggling active state', () => {
		global._googlesitekitBaseData = { trackingEnabled: true };

		disableTracking();

		expect( isTrackingEnabled() ).toStrictEqual( false );
		expect( global._googlesitekitBaseData.trackingEnabled ).toStrictEqual( true );
	} );
} );

describe( 'enableTracking and isTrackingEnabled', () => {
	afterEach( resetGlobals );

	it( 'does not mutate global tracking settings when toggling active state', () => {
		global._googlesitekitBaseData = { trackingEnabled: false };

		enableTracking();

		expect( isTrackingEnabled() ).toStrictEqual( true );
		expect( global._googlesitekitBaseData.trackingEnabled ).toStrictEqual( false );
	} );
} );

describe( 'trackEvent', () => {
	afterEach( resetGlobals );

	it( 'adds a tracking event to the dataLayer', async () => {
		const config = {
			referenceSiteURL: 'https://www.example.com/',
			userIDHash: 'a1b2c3',
			trackingID: 'UA-12345678-1',
			isFirstAdmin: true,
			trackingEnabled: true,
		};

		let pushArgs;
		const dataLayer = {
			[ DATA_LAYER ]: {
				push: ( ...args ) => pushArgs = args,
			},
		};
		const { trackEvent } = createTracking( config, dataLayer );

		// Ignore warning (see below) since irrelevant for this test.
		await fakeTimeouts( () => trackEvent( 'category', 'name', 'label', 'value' ) );

		// dataLayerPush must push an instance of `Arguments` onto the data layer.
		// Because `arguments` is a special, `Array`-like object (but not an actual `Array`),
		// we can only create it using the magic `arguments` variable
		// made available to normal, non-arrow functions.
		expect( console ).toHaveWarned();
		expect( pushArgs.length ).toEqual( 1 );
		expect( Object.prototype.toString.apply( pushArgs[ 0 ] ) ).toEqual( '[object Arguments]' );
		expect( pushArgs[ 0 ].length ).toEqual( 3 );
		const [ event, eventName, eventData ] = pushArgs[ 0 ];
		expect( event ).toEqual( 'event' );
		expect( eventName ).toEqual( 'name' );
		expect( eventData ).toEqual( expect.objectContaining( {
			send_to: config.trackingID,
			event_category: 'category',
			event_label: 'label',
			value: 'value',
			dimension1: 'https://www.example.com',
			dimension2: 'true',
			dimension3: config.userIDHash,
		} ) );
		expect( pushArgs[ 0 ][ 2 ] ).toHaveProperty( 'event_callback' );
	} );

	it( 'does not push to dataLayer when tracking is disabled', async () => {
		const push = jest.fn();
		const dataLayer = {
			[ DATA_LAYER ]: { push },
		};
		const { trackEvent } = createTracking( { trackingEnabled: false }, dataLayer );

		await fakeTimeouts( () => trackEvent( 'test-category', 'test-name', 'test-label', 'test-value' ) );
		expect( push ).not.toHaveBeenCalled();
	} );

	it( 'resolves without warning when event_callback is called', async () => {
		const dataLayer = {
			[ DATA_LAYER ]: {
				push: ( args ) => args[ 2 ].event_callback(),
			},
		};
		const { trackEvent } = createTracking( { trackingEnabled: true }, dataLayer );

		const consoleWarnSpy = jest.spyOn( global.console, 'warn' );
		await fakeTimeouts( () => trackEvent( 'test-category', 'test-name', 'test-label', 'test-value' ) );
		expect( consoleWarnSpy ).not.toHaveBeenCalled();
		consoleWarnSpy.mockClear();
	} );

	it( 'resolves with warning when event_callback is not called (within one second)', async () => {
		const dataLayer = {
			[ DATA_LAYER ]: {
				push: () => {},
			},
		};

		const { trackEvent } = createTracking( { trackingEnabled: true }, dataLayer );

		const consoleWarnSpy = jest.spyOn( global.console, 'warn' );
		await fakeTimeouts( () => trackEvent( 'test-category', 'test-name', 'test-label', 'test-value' ) );
		expect( console ).toHaveWarned();
		expect( consoleWarnSpy ).toHaveBeenCalledWith( 'Tracking event "test-name" (category "test-category") took too long to fire.' );
		consoleWarnSpy.mockClear();
	} );

	it( 'not push to dataLayer with the opt-out set', async () => {
		const push = jest.fn();
		const dataLayer = {
			[ DATA_LAYER ]: { push },
		};

		const mockGlobal = {
			_gaUserPrefs: {
				ioo: () => true,
			},
		};
		const iooSpy = jest.spyOn( mockGlobal._gaUserPrefs, 'ioo' );
		const { trackEvent } = createTracking( { trackingEnabled: true }, dataLayer, mockGlobal );
		await fakeTimeouts( () => trackEvent( 'test-category', 'test-name', 'test-label', 'test-value' ) );
		expect( iooSpy ).toHaveBeenCalled();
		expect( push ).not.toHaveBeenCalled();
	} );
} );
<|endoftext|>


<commit_before>// Libs
import isArray from 'lodash/lang/isArray';
import isObject from 'lodash/lang/isObject';
// Dependencies
import builder from 'focus-core/component/builder';
// Stores
import applicationStore from 'focus-core/application/built-in-store';
// Mixins
import stylableBehaviour from '../../mixin/stylable';
// Components
import Button from '../../components/button';
import { component as Dropdown } from '../../common/select-action';

const ContentActions = {

    mixins: [stylableBehaviour],

    /** @inheritdoc */
    getInitialState() {
        return this._getStateFromStore();
    },

    /** @inheritdoc */
    componentWillMount() {
        applicationStore.addActionsChangeListener(this._handleComponentChange);
    },

    /** @inheritdoc */
    componentWillUnmount() {
        applicationStore.removeActionsChangeListener(this._handleComponentChange);
    },

    /**
     * Get state from store
     * @return {Object} actions extracted from the store
     */
    _getStateFromStore() {
        return {
            actions: applicationStore.getActions() || { primary: [], secondary: [] }
        };
    },

    /**
     * Component change handler
     */
    _handleComponentChange() {
        this.setState(this._getStateFromStore());
    },

    /** @inheritdoc */
    render() {
        const { actions: { primary, secondary } } = this.state;
        return (

                {primary.map((primary) => {
                    if (Array.isArray(primary.action)) {
                        return (
                            <Dropdown
                                iconProps={{ name: primary.icon, iconLibrary: primary.iconLibrary }}
                                operationList={primary.action}
                                shape='fab'
                            />
                        );
                    } else {
                        return (
                            <Button
                                handleOnClick={primary.action}
                                icon={primary.icon}
                                iconLibrary={primary.iconLibrary}
                                label={primary.label}
                                shape='fab'
                                style={{ className: primary.className }}
                                type='button'
                            />
                        );
                    }
                })}
                {isArray(secondary) && (
                    <Dropdown
                        iconProps={{ name: 'more_vert' }}
                        operationList={secondary}
                        shape='fab'
                    />
                )}
                {isObject(secondary) && (
                    <Dropdown
                        iconProps={{ name: secondary.icon || 'more_vert', iconLibrary: secondary.iconLibrary }}
                        operationList={secondary.action}
                        shape='fab'
                    />
                )}

        );
    }
};

const { mixin, component } = builder(ContentActions);
export { mixin, component };
export default { mixin, component };
<commit_msg>take review into account<commit_after>// Libs
import isArray from 'lodash/lang/isArray';
import isObject from 'lodash/lang/isObject';
// Dependencies
import builder from 'focus-core/component/builder';
// Stores
import applicationStore from 'focus-core/application/built-in-store';
// Mixins
import stylableBehaviour from '../../mixin/stylable';
// Components
import Button from '../../components/button';
import { component as Dropdown } from '../../common/select-action';

const ContentActions = {

    mixins: [stylableBehaviour],

    /** @inheritdoc */
    getInitialState() {
        return this._getStateFromStore();
    },

    /** @inheritdoc */
    componentWillMount() {
        applicationStore.addActionsChangeListener(this._handleComponentChange);
    },

    /** @inheritdoc */
    componentWillUnmount() {
        applicationStore.removeActionsChangeListener(this._handleComponentChange);
    },

    /**
     * Get state from store
     * @return {Object} actions extracted from the store
     */
    _getStateFromStore() {
        return {
            actions: applicationStore.getActions() || { primary: [], secondary: [] }
        };
    },

    /**
     * Component change handler
     */
    _handleComponentChange() {
        this.setState(this._getStateFromStore());
    },

    /**
     * Render a fab component.
     * @param {object} fab Fab.
     * @returns {JSXElement} Component.
     */
    renderFabAction(fab) {
        if (isArray(fab.action)) {
            return (
                <Dropdown
                    iconProps={{ name: fab.icon, iconLibrary: fab.iconLibrary }}
                    operationList={fab.action}
                    shape='fab'
                />
            );
        } else {
            return (
                <Button
                    handleOnClick={fab.action}
                    icon={fab.icon}
                    iconLibrary={fab.iconLibrary}
                    label={fab.label}
                    style={{ className: fab.className }}
                    shape='fab'
                    type='button'
                />
            );
        }
    },

    /** @inheritdoc */
    render() {
        const { actions: { primary, secondary } } = this.state;
        return (

                {primary.map((action) => this.renderFabAction(action))}
                {isArray(secondary) && this.renderFabAction({ action: secondary })}
                {isObject(secondary) && this.renderFabAction(secondary)}

        );
    }
};

const { mixin, component } = builder(ContentActions);
export { mixin, component };
export default { mixin, component };
<|endoftext|>


<commit_before>function callback(response) {
    var date = new Date();
    var chart = new CanvasJS.Chart("chartContainer",
    {
        zoomEnabled: true,

        title:{
        text: "Repo with " + response.data.length + " stars created at " + response.created_at
    },
    data: [
        {
            type: "area",
            xValueType: "dateTime",
            dataPoints: response.data
        }
    ]
    });

    chart.render();
}
function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
    }
    return "";
}
$(document).ready(function() {
    $("#loader").hide();
    var token = getCookie("token");
    if (token !== "") {
        $(".token").hide();
    }
    callback({data:[], created_at: new Date().toISOString()});
    $("#form").submit(function(e) {
        e.preventDefault();
        var repo = $("#repo").val();
        if (token === "") {
            token = $("#token").val();
        }
        //console.log(repo, token);
        $("#loader").show();
        $.get("/api?repo=" + repo + "&token=" + token, function(data){
            //console.log(data);
            var obj = JSON.parse(data);
            //console.log(obj);
            callback(obj);
            if (obj.length !== 0) {
                var lastTimestamp = obj.pop().x;
                $("#legend").html("Last star on the repository put at: " + new Date(lastTimestamp).toDateString());
            }
            $("#loader").hide();
            });
    });
});
<commit_msg>change loader<commit_after>function callback(response) {
    var date = new Date();
    $("#loader").hide();
    var chart = new CanvasJS.Chart("chartContainer",
    {
        zoomEnabled: true,

        title:{
        text: "Repo with " + response.data.length + " stars created at " + response.created_at
    },
    data: [
        {
            type: "area",
            xValueType: "dateTime",
            dataPoints: response.data
        }
    ]
    });

    chart.render();
}
function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
    }
    return "";
}
$(document).ready(function() {
    $("#loader").hide();
    var token = getCookie("token");
    if (token !== "") {
        $(".token").hide();
    }
    callback({data:[], created_at: new Date().toISOString()});
    $("#form").submit(function(e) {
        e.preventDefault();
        var repo = $("#repo").val();
        if (token === "") {
            token = $("#token").val();
        }
        //console.log(repo, token);
        $("#loader").show();
        $.get("/api?repo=" + repo + "&token=" + token, function(data){
            //console.log(data);
            var obj = JSON.parse(data);
            //console.log(obj);
            callback(obj);
            if (obj.length !== 0) {
                var lastTimestamp = obj.pop().x;
                $("#legend").html("Last star on the repository put at: " + new Date(lastTimestamp).toDateString());
            }
            });
    });
});
<|endoftext|>


<commit_before>var SRCDS = SRCDS || {};
SRCDS.CSGO = SRCDS.CSGO || {};

SRCDS.CSGO.MapsArmsRace = ["ar_baggage", "ar_monastery", "ar_shoots", "de_lake", "de_stmarc"];

SRCDS.CSGO.MapsClassic = ["cs_agency", "cs_assault", "cs_backalley", "cs_cruise", "cs_downtown", "cs_insertion", "cs_italy", "cs_militia", "cs_motel",
        "cs_office", "cs_rush", "cs_thunder", "cs_workout", "de_ali", "de_austria", "de_aztec", "de_bank", "de_bazaar", "de_blackgold",
        "de_cache", "de_canals", "de_castle", "de_cbble", "de_coast", "de_dust", "de_dust2", "de_empire", "de_facade", "de_favela",
        "de_inferno", "de_lake", "de_lite", "de_log", "de_marquis", "de_mikla", "de_mirage", "de_mist", "de_nuke", "de_nuke_se",
        "de_overgrown", "de_overpass", "de_rails", "de_resort", "de_royal", "de_safehouse", "de_santorini", "de_seaside", "de_season",
        "de_shortdust", "de_shorttrain", "de_stmarc", "de_sugarcane", "de_thrill", "de_train", "de_tulip", "de_vertigo", "de_zoo"];

SRCDS.CSGO.MapsDeathmatch = ["ar_baggage", "ar_monastery", "ar_shoots", "cs_agency", "cs_assault", "cs_backalley", "cs_cruise", "cs_downtown", "cs_insertion",
        "cs_italy", "cs_militia", "cs_motel", "cs_office", "cs_rush", "cs_thunder", "cs_workout", "de_austria", "de_aztec", "de_bank",
        "de_canals", "de_cbble", "de_dust", "de_dust2", "de_inferno", "de_lake", "de_lite", "de_mirage", "de_nuke", "de_nuke_se",
        "de_overpass", "de_safehouse", "de_shortdust", "de_shorttrain", "de_stmarc", "de_thrill", "de_sugarcane", "de_vertigo"];

SRCDS.CSGO.MapsTest = ["de_orange", "fy_pool_day", "gg_ctm_csgo", "orangebox_warmup_day"];

SRCDS.CSGO.MapsTourney = ["de_cache", "de_cbble", "de_inferno", "de_nuke", "de_mirage", "de_overpass", "de_train"];

SRCDS.CSGO.LaunchArmsRace = function (hostname, map, ip) {
    "use strict";

    let dockerArgs = '',
        srcdsArgs = '';

    hostname = (hostname) ? String(hostname) : 'LL Arms Race Server';
    hostname = hostname.split(' ').join('_');

    if (!map) {
        alert('ERROR - NO MAP WAS SPECIFIED!');
        return;
    }

    if (!ip) {
        alert('ERROR - NO SERVER WAS SPECIFIED!');
        return;
    }

    // Docker Command
    dockerArgs += '--name ' + Docker.GenerateContainerName("CSGOArms") + ' ';
    dockerArgs += Docker.NetString_SRCDS(ip) + ' ';
    dockerArgs += 'lacledeslan/gamesvr-csgo-freeplay ';

    // CSGO Arms Race Server Specific
    srcdsArgs = '-game csgo ';
    srcdsArgs += '-console ';
    srcdsArgs += '+game_type 1 ';
    srcdsArgs += '+game_mode 0 ';
    srcdsArgs += '-usercon ';
    srcdsArgs += '-tickrate 128 ';
    srcdsArgs += '+mapgroup ll_arms ';
    srcdsArgs += '+map ' + map + ' ';
    srcdsArgs += '-maxplayers_override 16 ';
    srcdsArgs += '+hostname "' + hostname + '" ';
    srcdsArgs += '+sv_lan 1 ';
    srcdsArgs += '+rcon_password "' + RCON_PASS.join('') + '" ';

    UI.displayModal(
        "CSGO Arms Race",
        {
            "Launch String": UI.formatCommands('docker run -d ', dockerArgs, ['./srcds_run ', srcdsArgs]),
            "Client Connect": 'connect ' + ip + ':27015'
        }
    );
};

SRCDS.CSGO.LaunchClassic = function (hostname, map, ip) {
    "use strict";

    let dockerArgs = '',
        srcdsArgs = '';

    hostname = (hostname) ? String(hostname) : 'LL Classic Server';
    hostname = hostname.split(' ').join('_');

    if (!map) {
        alert('ERROR - NO MAP WAS SPECIFIED!');
        return;
    }

    if (!ip) {
        alert('ERROR - NO SERVER WAS SPECIFIED!');
        return;
    }

    // Docker Args
    dockerArgs += '--name ' + Docker.GenerateContainerName("CSGOClassic") + ' ';
    dockerArgs += Docker.NetString_SRCDS(ip) + ' ';
    dockerArgs += 'lacledeslan/gamesvr-csgo-freeplay ';

    // CSGO Classic Server Specific
    srcdsArgs += '-game csgo ';
    srcdsArgs += '-console ';
    srcdsArgs += '+game_type 0 ';
    srcdsArgs += '+game_mode 0 ';
    srcdsArgs += '-usercon ';
    srcdsArgs += '-tickrate 128 ';
    srcdsArgs += '+mapgroup ll_bombhostage ';
    srcdsArgs += '+map ' + map + ' ';
    srcdsArgs += '-maxplayers_override 16 ';
    srcdsArgs += '+hostname "' + hostname + '" ';
    srcdsArgs += '+sv_lan 1 ';
    srcdsArgs += '+rcon_password "' + RCON_PASS.join('') + '" ';

    UI.displayModal(
        "CSGO Classic",
        {
            "Launch String": UI.formatCommands('docker run -d ', dockerArgs, ['./srcds_run ', srcdsArgs]),
            "Client Connect": 'connect ' + ip + ':27015'
        }
    );
};

SRCDS.CSGO.LaunchDeathmatch = function (hostname, map, ip) {
    "use strict";

    let dockerArgs = '',
        srcdsArgs = '';

    hostname = (hostname) ? String(hostname) : 'LL Team Deathmatch Server';
    hostname = hostname.split(' ').join('_');

    if (!map) {
        alert('ERROR - NO MAP WAS SPECIFIED!');
        return;
    }

    if (!ip) {
        alert('ERROR - NO SERVER WAS SPECIFIED!');
        return;
    }

    // Docker Args
    dockerArgs += '--name ' + Docker.GenerateContainerName("CSGODeathmatch") + ' ';
    dockerArgs += Docker.NetString_SRCDS(ip) + ' ';
    dockerArgs += 'lacledeslan/gamesvr-csgo-freeplay ';

    // CSGO Classic Server Specific
    srcdsArgs += '-port 27015 ';
    srcdsArgs += '-game csgo ';
    srcdsArgs += '-console ';
    srcdsArgs += '+game_type 1 ';
    srcdsArgs += '+game_mode 2 ';
    srcdsArgs += '-usercon ';
    srcdsArgs += '-tickrate 128 ';
    srcdsArgs += '+mapgroup mg_deathmatch ';
    srcdsArgs += '+map ' + map + ' ';
    srcdsArgs += '-maxplayers_override 16 ';
    srcdsArgs += '+hostname "' + hostname + '" ';
    srcdsArgs += '+sv_lan 1 ';
    srcdsArgs += '+rcon_password "' + RCON_PASS.join('') + '" ';

    UI.displayModal(
        "CSGO Deathmatch",
        {
            "Launch String": UI.formatCommands('docker run -d ', dockerArgs, ['./srcds_run ', srcdsArgs]),
            "Client Connect": 'connect ' + ip + ':27015'
        }
    );
};

SRCDS.CSGO.LaunchClientTest = function (map, ip) {
    "use strict";

    let dockerArgs = '',
        hostname = "CSGO Client Test Server",
        srcdsArgs = '',
        team1 = "Isotopes",
        team2 = "Gotham Rogues";

    if (!map) {
        alert('ERROR - NO MAP WAS SPECIFIED!');
        return;
    }

    if (!ip) {
        alert('ERROR - NO SERVER WAS SELECTED');
        return;
    }

    ip = ip.toString().trim();

    hostname = hostname.split(' ').join('_');

    // Docker Command
    dockerArgs += '--name ' + Docker.GenerateContainerName("CSGOTest") + ' ';
    dockerArgs += Docker.NetString_SRCDS(ip) + ' ';
    dockerArgs += 'lacledeslan/gamesvr-csgo-test ';

    // SRCDS Command
    srcdsArgs = '-port 27015 ';
    srcdsArgs += '-game csgo ';
    srcdsArgs += '+game_type 0 ';
    srcdsArgs += '+game_mode 1 ';
    srcdsArgs += '-tickrate 128 ';
    srcdsArgs += '-console ';
    srcdsArgs += '-usercon ';
    srcdsArgs += '+mapgroup ll_orange ';
    srcdsArgs += '+map ' + map + ' ';
    srcdsArgs += '+hostname "' + hostname + '" ';
    srcdsArgs += '+sv_lan 1 ';
    srcdsArgs += '+mp_teamname_1 "' + team1 + '" ';
    srcdsArgs += '+mp_teamname_2 "' + team2 + '" ';
    srcdsArgs += '+rcon_password "' + RCON_PASS.join('') + '" ';
    srcdsArgs += '-maxplayers_override 16 ';

    UI.displayModal(
        "CSGO Client Test",
        {
            "Launch String": UI.formatCommands('docker run -d ', dockerArgs, ['./srcds_run ', srcdsArgs]),
            "Client Connect": 'connect ' + ip + ':27015'
        }
    );
};

SRCDS.CSGO.LaunchTourney = function (bracketID, bracketLetter, team1, team2, map, ip) {
    "use strict";

    if (stringIsNullOrEmpty(bracketID)) {
        alert('Bracket ID was left empty!');
        return;
    }
    bracketID = _.padStart(bracketID, 2, '0');

    if (stringIsNullOrEmpty(bracketLetter)) {
        alert('Bracket Letter was left empty!');
        return;
    }
    bracketLetter = bracketLetter.toString().trim();

    if (!isWholeNumber(bracketID)) {
        alert('Bracket ID must be a positive whole number!');
        return;
    }

    let dockerArgs = '',
    dockerContainerName = Docker.GenerateContainerName("CSGOTourn" + bracketID + bracketLetter),
        hostname = "",
        pass = password.generateArray(),
        srcdsArgs = '',
        tvConnectString = '';

    bracketID = _.padStart(bracketID.toString().trim(), 2, "0");

    team1 = team1.trim();
    if (String(team1).length < 1) {
        alert('Team 1 was left empty!');
        return;
    }

    team2 = team2.trim();
    if (String(team2).length < 1) {
        alert('Team 2 was left empty!');
        return;
    }

    if (!map) {
        alert('ERROR - NO MAP WAS SPECIFIED!');
        return;
    }

    ip = ip.trim();

    // Generate hostname
    if (team1 !== undefined || team2 !== undefined) {
        team1 = String(team1 || 'Unknown');
        team2 = String(team2 || 'Unknown');
        hostname = 'CSGO Match ' + bracketID + bracketLetter + ' ' + team1 + ' v ' + team2;
    }

    hostname = hostname.split(' ').join('_');

    // Docker Args
    dockerArgs += '--name ' + dockerContainerName + ' ';
    dockerArgs += Docker.NetString_SRCDS(ip) + ' ';
    dockerArgs += '-v /home/sysoper/logs/' + dockerContainerName + ':/app/bin/csgo/logs ';
    dockerArgs += '-v /home/sysoper/logs/' + dockerContainerName + '/warmod:/app/bin/csgo/addons/sourcemod/logs ';
    dockerArgs += 'lacledeslan/gamesvr-csgo-tourney ';

    // CS:GO Tournament Server Specific
    srcdsArgs = '-game csgo ';
    srcdsArgs += '+game_type 0 ';
    srcdsArgs += '+game_mode 1 ';
    srcdsArgs += '-tickrate 128 ';
    srcdsArgs += '-console ';
    srcdsArgs += '-usercon ';
    srcdsArgs += '+map ' + map + ' ';
    srcdsArgs += '+hostname "' + hostname + '" ';
    srcdsArgs += '+sv_password "' + pass.join('') + '" ';
    srcdsArgs += '+sv_lan 1 ';
    srcdsArgs += '+mp_teamname_1 "' + team1 + '" ';
    srcdsArgs += '+mp_teamname_2 "' + team2 + '" ';
    srcdsArgs += '+rcon_password "' + RCON_PASS.join('') + '" ';
    srcdsArgs += '+tv_name "zLLTV_CSGO_BRACKET_' + bracketID + '" ';
    srcdsArgs += '+tv_password "' + TV_PASS.join('') + '" ';
    srcdsArgs += '+tv_relaypassword "' + TV_PASS.join('') + '" ';

    tvConnectString = 'connect ' + ip + ':27020; password ' + TV_PASS.html();

    UI.displayModal(
        "CSGO Tourney",
        {
            "Launch String": UI.formatCommands('docker run -d ', dockerArgs, ['./srcds_run ', srcdsArgs]),
            "Client Connect": 'connect ' + ip + ':27015; ' + 'password ' + pass.html(),
            "TV Connect": tvConnectString
        }
    );
};

SRCDS.CSGO.TourneyRoundRestore = function (roundNumber) {
    "use strict";

    let filename = 'LL_round' + _.padStart(roundNumber - 1, 2, '0'),
        restoreCommand = '';

    restoreCommand += 'mp_backup_restore_load_file ' + filename + '; ';
    restoreCommand += 'mp_backup_restore_load_file ' + filename + '; ';
    restoreCommand += 'wm_block_warm_up_grenades 0;';

    UI.displayModal(
        "CSGO Tourney Restore Round #" + roundNumber,
        {
            "Round Restore": restoreCommand,
            "Unpause After Round Restore (all players ready)": "mp_unpause_match"
        }
    );
};

/// Add Maps to all appropriate HTML SELECT controls
document.addEventListener('DOMContentLoaded', function () {
    "use strict";

    UI.populateSelectFromCollection(".selectCSGOArmsRaceMaps", SRCDS.CSGO.MapsArmsRace);
    UI.populateSelectFromCollection(".selectCSGOClassicMaps", SRCDS.CSGO.MapsClassic);
    UI.populateSelectFromCollection(".selectCSGODeathmatchMaps", SRCDS.CSGO.MapsDeathmatch);
    UI.populateSelectFromCollection(".selectCSGOTestMaps", SRCDS.CSGO.MapsTest, true);
    UI.populateSelectFromCollection(".selectCSGOTourneyMaps", SRCDS.CSGO.MapsTourney);

    Array.prototype.forEach.call(document.querySelectorAll(".selectCSGORoundRestore"), function (selectControl) {
        let option;

        for (let i = 0; i < 30; i++) {
            option = document.createElement("option");
            option.text = _.padStart(i + 1, 2, '0');
            option.value = i + 1;
            selectControl.add(option);
        }
    });
});
<commit_msg>Fixed paths for log volume mounts<commit_after>var SRCDS = SRCDS || {};
SRCDS.CSGO = SRCDS.CSGO || {};

SRCDS.CSGO.MapsArmsRace = ["ar_baggage", "ar_monastery", "ar_shoots", "de_lake", "de_stmarc"];

SRCDS.CSGO.MapsClassic = ["cs_agency", "cs_assault", "cs_backalley", "cs_cruise", "cs_downtown", "cs_insertion", "cs_italy", "cs_militia", "cs_motel",
        "cs_office", "cs_rush", "cs_thunder", "cs_workout", "de_ali", "de_austria", "de_aztec", "de_bank", "de_bazaar", "de_blackgold",
        "de_cache", "de_canals", "de_castle", "de_cbble", "de_coast", "de_dust", "de_dust2", "de_empire", "de_facade", "de_favela",
        "de_inferno", "de_lake", "de_lite", "de_log", "de_marquis", "de_mikla", "de_mirage", "de_mist", "de_nuke", "de_nuke_se",
        "de_overgrown", "de_overpass", "de_rails", "de_resort", "de_royal", "de_safehouse", "de_santorini", "de_seaside", "de_season",
        "de_shortdust", "de_shorttrain", "de_stmarc", "de_sugarcane", "de_thrill", "de_train", "de_tulip", "de_vertigo", "de_zoo"];

SRCDS.CSGO.MapsDeathmatch = ["ar_baggage", "ar_monastery", "ar_shoots", "cs_agency", "cs_assault", "cs_backalley", "cs_cruise", "cs_downtown", "cs_insertion",
        "cs_italy", "cs_militia", "cs_motel", "cs_office", "cs_rush", "cs_thunder", "cs_workout", "de_austria", "de_aztec", "de_bank",
        "de_canals", "de_cbble", "de_dust", "de_dust2", "de_inferno", "de_lake", "de_lite", "de_mirage", "de_nuke", "de_nuke_se",
        "de_overpass", "de_safehouse", "de_shortdust", "de_shorttrain", "de_stmarc", "de_thrill", "de_sugarcane", "de_vertigo"];

SRCDS.CSGO.MapsTest = ["de_orange", "fy_pool_day", "gg_ctm_csgo", "orangebox_warmup_day"];

SRCDS.CSGO.MapsTourney = ["de_cache", "de_cbble", "de_inferno", "de_nuke", "de_mirage", "de_overpass", "de_train"];

SRCDS.CSGO.LaunchArmsRace = function (hostname, map, ip) {
    "use strict";

    let dockerArgs = '',
        srcdsArgs = '';

    hostname = (hostname) ? String(hostname) : 'LL Arms Race Server';
    hostname = hostname.split(' ').join('_');

    if (!map) {
        alert('ERROR - NO MAP WAS SPECIFIED!');
        return;
    }

    if (!ip) {
        alert('ERROR - NO SERVER WAS SPECIFIED!');
        return;
    }

    // Docker Command
    dockerArgs += '--name ' + Docker.GenerateContainerName("CSGOArms") + ' ';
    dockerArgs += Docker.NetString_SRCDS(ip) + ' ';
    dockerArgs += 'lacledeslan/gamesvr-csgo-freeplay ';

    // CSGO Arms Race Server Specific
    srcdsArgs = '-game csgo ';
    srcdsArgs += '-console ';
    srcdsArgs += '+game_type 1 ';
    srcdsArgs += '+game_mode 0 ';
    srcdsArgs += '-usercon ';
    srcdsArgs += '-tickrate 128 ';
    srcdsArgs += '+mapgroup ll_arms ';
    srcdsArgs += '+map ' + map + ' ';
    srcdsArgs += '-maxplayers_override 16 ';
    srcdsArgs += '+hostname "' + hostname + '" ';
    srcdsArgs += '+sv_lan 1 ';
    srcdsArgs += '+rcon_password "' + RCON_PASS.join('') + '" ';

    UI.displayModal(
        "CSGO Arms Race",
        {
            "Launch String": UI.formatCommands('docker run -d ', dockerArgs, ['./srcds_run ', srcdsArgs]),
            "Client Connect": 'connect ' + ip + ':27015'
        }
    );
};

SRCDS.CSGO.LaunchClassic = function (hostname, map, ip) {
    "use strict";

    let dockerArgs = '',
        srcdsArgs = '';

    hostname = (hostname) ? String(hostname) : 'LL Classic Server';
    hostname = hostname.split(' ').join('_');

    if (!map) {
        alert('ERROR - NO MAP WAS SPECIFIED!');
        return;
    }

    if (!ip) {
        alert('ERROR - NO SERVER WAS SPECIFIED!');
        return;
    }

    // Docker Args
    dockerArgs += '--name ' + Docker.GenerateContainerName("CSGOClassic") + ' ';
    dockerArgs += Docker.NetString_SRCDS(ip) + ' ';
    dockerArgs += 'lacledeslan/gamesvr-csgo-freeplay ';

    // CSGO Classic Server Specific
    srcdsArgs += '-game csgo ';
    srcdsArgs += '-console ';
    srcdsArgs += '+game_type 0 ';
    srcdsArgs += '+game_mode 0 ';
    srcdsArgs += '-usercon ';
    srcdsArgs += '-tickrate 128 ';
    srcdsArgs += '+mapgroup ll_bombhostage ';
    srcdsArgs += '+map ' + map + ' ';
    srcdsArgs += '-maxplayers_override 16 ';
    srcdsArgs += '+hostname "' + hostname + '" ';
    srcdsArgs += '+sv_lan 1 ';
    srcdsArgs += '+rcon_password "' + RCON_PASS.join('') + '" ';

    UI.displayModal(
        "CSGO Classic",
        {
            "Launch String": UI.formatCommands('docker run -d ', dockerArgs, ['./srcds_run ', srcdsArgs]),
            "Client Connect": 'connect ' + ip + ':27015'
        }
    );
};

SRCDS.CSGO.LaunchDeathmatch = function (hostname, map, ip) {
    "use strict";

    let dockerArgs = '',
        srcdsArgs = '';

    hostname = (hostname) ? String(hostname) : 'LL Team Deathmatch Server';
    hostname = hostname.split(' ').join('_');

    if (!map) {
        alert('ERROR - NO MAP WAS SPECIFIED!');
        return;
    }

    if (!ip) {
        alert('ERROR - NO SERVER WAS SPECIFIED!');
        return;
    }

    // Docker Args
    dockerArgs += '--name ' + Docker.GenerateContainerName("CSGODeathmatch") + ' ';
    dockerArgs += Docker.NetString_SRCDS(ip) + ' ';
    dockerArgs += 'lacledeslan/gamesvr-csgo-freeplay ';

    // CSGO Classic Server Specific
    srcdsArgs += '-port 27015 ';
    srcdsArgs += '-game csgo ';
    srcdsArgs += '-console ';
    srcdsArgs += '+game_type 1 ';
    srcdsArgs += '+game_mode 2 ';
    srcdsArgs += '-usercon ';
    srcdsArgs += '-tickrate 128 ';
    srcdsArgs += '+mapgroup mg_deathmatch ';
    srcdsArgs += '+map ' + map + ' ';
    srcdsArgs += '-maxplayers_override 16 ';
    srcdsArgs += '+hostname "' + hostname + '" ';
    srcdsArgs += '+sv_lan 1 ';
    srcdsArgs += '+rcon_password "' + RCON_PASS.join('') + '" ';

    UI.displayModal(
        "CSGO Deathmatch",
        {
            "Launch String": UI.formatCommands('docker run -d ', dockerArgs, ['./srcds_run ', srcdsArgs]),
            "Client Connect": 'connect ' + ip + ':27015'
        }
    );
};

SRCDS.CSGO.LaunchClientTest = function (map, ip) {
    "use strict";

    let dockerArgs = '',
        hostname = "CSGO Client Test Server",
        srcdsArgs = '',
        team1 = "Isotopes",
        team2 = "Gotham Rogues";

    if (!map) {
        alert('ERROR - NO MAP WAS SPECIFIED!');
        return;
    }

    if (!ip) {
        alert('ERROR - NO SERVER WAS SELECTED');
        return;
    }

    ip = ip.toString().trim();

    hostname = hostname.split(' ').join('_');

    // Docker Command
    dockerArgs += '--name ' + Docker.GenerateContainerName("CSGOTest") + ' ';
    dockerArgs += Docker.NetString_SRCDS(ip) + ' ';
    dockerArgs += 'lacledeslan/gamesvr-csgo-test ';

    // SRCDS Command
    srcdsArgs = '-port 27015 ';
    srcdsArgs += '-game csgo ';
    srcdsArgs += '+game_type 0 ';
    srcdsArgs += '+game_mode 1 ';
    srcdsArgs += '-tickrate 128 ';
    srcdsArgs += '-console ';
    srcdsArgs += '-usercon ';
    srcdsArgs += '+mapgroup ll_orange ';
    srcdsArgs += '+map ' + map + ' ';
    srcdsArgs += '+hostname "' + hostname + '" ';
    srcdsArgs += '+sv_lan 1 ';
    srcdsArgs += '+mp_teamname_1 "' + team1 + '" ';
    srcdsArgs += '+mp_teamname_2 "' + team2 + '" ';
    srcdsArgs += '+rcon_password "' + RCON_PASS.join('') + '" ';
    srcdsArgs += '-maxplayers_override 16 ';

    UI.displayModal(
        "CSGO Client Test",
        {
            "Launch String": UI.formatCommands('docker run -d ', dockerArgs, ['./srcds_run ', srcdsArgs]),
            "Client Connect": 'connect ' + ip + ':27015'
        }
    );
};

SRCDS.CSGO.LaunchTourney = function (bracketID, bracketLetter, team1, team2, map, ip) {
    "use strict";

    if (stringIsNullOrEmpty(bracketID)) {
        alert('Bracket ID was left empty!');
        return;
    }
    bracketID = _.padStart(bracketID, 2, '0');

    if (stringIsNullOrEmpty(bracketLetter)) {
        alert('Bracket Letter was left empty!');
        return;
    }
    bracketLetter = bracketLetter.toString().trim();

    if (!isWholeNumber(bracketID)) {
        alert('Bracket ID must be a positive whole number!');
        return;
    }

    let dockerArgs = '',
    dockerContainerName = Docker.GenerateContainerName("CSGOTourn" + bracketID + bracketLetter),
        hostname = "",
        pass = password.generateArray(),
        srcdsArgs = '',
        tvConnectString = '';

    bracketID = _.padStart(bracketID.toString().trim(), 2, "0");

    team1 = team1.trim();
    if (String(team1).length < 1) {
        alert('Team 1 was left empty!');
        return;
    }

    team2 = team2.trim();
    if (String(team2).length < 1) {
        alert('Team 2 was left empty!');
        return;
    }

    if (!map) {
        alert('ERROR - NO MAP WAS SPECIFIED!');
        return;
    }

    ip = ip.trim();

    // Generate hostname
    if (team1 !== undefined || team2 !== undefined) {
        team1 = String(team1 || 'Unknown');
        team2 = String(team2 || 'Unknown');
        hostname = 'CSGO Match ' + bracketID + bracketLetter + ' ' + team1 + ' v ' + team2;
    }

    hostname = hostname.split(' ').join('_');

    // Docker Args
    dockerArgs += '--name ' + dockerContainerName + ' ';
    dockerArgs += Docker.NetString_SRCDS(ip) + ' ';
    dockerArgs += '-v /home/sysoper/logs/' + dockerContainerName + ':/app/csgo/logs ';
    dockerArgs += '-v /home/sysoper/logs/' + dockerContainerName + '/warmod:/app/csgo/addons/sourcemod/logs ';
    dockerArgs += 'lacledeslan/gamesvr-csgo-tourney ';

    // CS:GO Tournament Server Specific
    srcdsArgs = '-game csgo ';
    srcdsArgs += '+game_type 0 ';
    srcdsArgs += '+game_mode 1 ';
    srcdsArgs += '-tickrate 128 ';
    srcdsArgs += '-console ';
    srcdsArgs += '-usercon ';
    srcdsArgs += '+map ' + map + ' ';
    srcdsArgs += '+hostname "' + hostname + '" ';
    srcdsArgs += '+sv_password "' + pass.join('') + '" ';
    srcdsArgs += '+sv_lan 1 ';
    srcdsArgs += '+mp_teamname_1 "' + team1 + '" ';
    srcdsArgs += '+mp_teamname_2 "' + team2 + '" ';
    srcdsArgs += '+rcon_password "' + RCON_PASS.join('') + '" ';
    srcdsArgs += '+tv_name "zLLTV_CSGO_BRACKET_' + bracketID + '" ';
    srcdsArgs += '+tv_password "' + TV_PASS.join('') + '" ';
    srcdsArgs += '+tv_relaypassword "' + TV_PASS.join('') + '" ';

    tvConnectString = 'connect ' + ip + ':27020; password ' + TV_PASS.html();

    UI.displayModal(
        "CSGO Tourney",
        {
            "Launch String": UI.formatCommands('docker run -d ', dockerArgs, ['./srcds_run ', srcdsArgs]),
            "Client Connect": 'connect ' + ip + ':27015; ' + 'password ' + pass.html(),
            "TV Connect": tvConnectString
        }
    );
};

SRCDS.CSGO.TourneyRoundRestore = function (roundNumber) {
    "use strict";

    let filename = 'LL_round' + _.padStart(roundNumber - 1, 2, '0'),
        restoreCommand = '';

    restoreCommand += 'mp_backup_restore_load_file ' + filename + '; ';
    restoreCommand += 'mp_backup_restore_load_file ' + filename + '; ';
    restoreCommand += 'wm_block_warm_up_grenades 0;';

    UI.displayModal(
        "CSGO Tourney Restore Round #" + roundNumber,
        {
            "Round Restore": restoreCommand,
            "Unpause After Round Restore (all players ready)": "mp_unpause_match"
        }
    );
};

/// Add Maps to all appropriate HTML SELECT controls
document.addEventListener('DOMContentLoaded', function () {
    "use strict";

    UI.populateSelectFromCollection(".selectCSGOArmsRaceMaps", SRCDS.CSGO.MapsArmsRace);
    UI.populateSelectFromCollection(".selectCSGOClassicMaps", SRCDS.CSGO.MapsClassic);
    UI.populateSelectFromCollection(".selectCSGODeathmatchMaps", SRCDS.CSGO.MapsDeathmatch);
    UI.populateSelectFromCollection(".selectCSGOTestMaps", SRCDS.CSGO.MapsTest, true);
    UI.populateSelectFromCollection(".selectCSGOTourneyMaps", SRCDS.CSGO.MapsTourney);

    Array.prototype.forEach.call(document.querySelectorAll(".selectCSGORoundRestore"), function (selectControl) {
        let option;

        for (let i = 0; i < 30; i++) {
            option = document.createElement("option");
            option.text = _.padStart(i + 1, 2, '0');
            option.value = i + 1;
            selectControl.add(option);
        }
    });
});
<|endoftext|>