<commit_before>/*
 * Copyright [1999-2014] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * filterableDropdown: Javascript counterpart for E::W::Form::Element::Filterable
 * Reserverd classname prefix: _fd
 **/
(function ($) {
  $.fn.filterableDropdown = function (options) {
  /*
   * options: object with following keys
   *   refresh  - To refresh the tags selected in an already instantiated object (this is useful in case some external code has modified the selected inputs)
   *   change   - Function to be called with the raw html as context, when changing the selection. This gets fired after dropdown is closed and tags are refreshed according to new selection
   */

    return this.each(function () {
      $.filterableDropdown($(this), options);
    });
  };

  $.filterableDropdown = function (el, options) {

    options = $.extend({}, options);

    // if already instantiated
    if (el.data('filterableDropdown')) {
      if (options.change) {
        el.off('afterAddRemove.filterableDropdown').on('afterAddRemove.filterableDropdown', options.change);
      }
      if (options.refresh) {
        el.trigger('close');
      }
      return;
    }

    el.on({
      'focusInput.filterableDropdown': function() {
        el.find('._fd_filter input').trigger('focus');
      },
      'open.filterableDropdown': function() {
        if (!el.data('filterableDropdown').closed) {
          return;
        }
        el.data('filterableDropdown').closed = false;
        el.addClass('open').find('._fd_filter').show().find('input').trigger('focus').trigger('keyup').next().html('▲');
        $(document).off('.filterableDropdown').on('mousedown.filterableDropdown', function() {
          el.trigger('close');
        });
      },
      'close.filterableDropdown': function() {
        var tag = el.data('filterableDropdown').tag;
        var inp = el.find('input[type=checkbox]:checked, input[type=radio]:checked');
        el.data('filterableDropdown').closed = true;
        el.removeClass('open').find('._fd_tag').remove().end().find('._fd_filter input').trigger('reset').next().html('▼').end().end().prepend(inp.map(function() {
          return tag.clone().data('input', this).show().find('span').first().html(this.nextSibling.innerHTML).end().end();
        }).toArray()).trigger('afterAddRemove');
        if (inp.length && inp.prop('type') === 'radio') {
          el.find('._fd_filter').hide();
        }
        $(document).off('.filterableDropdown');
        tag = inp = null;
      },
      'afterAddRemove.filterableDropdown': options.change || $.noop
    }).on('click', '._fdt_button', function() {
      var inp = $($(this).parent().data('input'));
      $(this.parentNode).remove();
      if (inp.prop('type') === 'checkbox') {
        inp.prop('checked', false);
        labels.trigger('refresh');
        el.trigger('afterAddRemove');
      } else {
        el.trigger('open');
      }
      inp = null;
    }).children().on({
      'mousedown.filterableDropdown': function(e) {
        e.stopPropagation(); // prevent closing if the dropdown if clicked inside the dropdown
      }
    }).find('input[type=checkbox], input[type=radio]').on({
      'keydown.filterableDropdown': function(e) {
        e.preventDefault(); // prevent the submission of form when pressed enter on the checkboxes
      },
      'click.filterableDropdown': function(e, enterKey) {
        var onlyOneOption = labels.filter(':visible').length === 1;
        labels.trigger('refresh');
        el.trigger(onlyOneOption || this.type === 'radio' ? 'close' : 'focusInput');
        if (onlyOneOption && enterKey && this.type !== 'radio') {
          el.trigger('open');
        }
        onlyOneOption = null;
      }
    });

    var labels = el.find('label').on({
      'mouseenter.filterableDropdown': function() {
        labels.removeClass('highlight');
        $(this).addClass('highlight');
      },
      'refresh.filterableDropdown': function() {
        $(this).toggleClass('selected', $(this.parentNode).find('input').prop('checked'));
      }
    }).trigger('refresh');

    el.find('._fd_filter input').on({
      'focus.filterableDropdown': function() {
        if (this.value == this.defaultValue) {
          $(this).val('');
        }
        el.trigger('open');
      },
      'reset.filterableDropdown': function() {
        $(this).val(this.defaultValue).trigger('keyup').trigger('blur');
      },
      'keyup.filterableDropdown mouseup.filterableDropdown': function(e) {
        var value = this.value;
        if (e.originalEvent && (value === this.defaultValue || e.which === 38 || e.which === 40 || e.which === 13 || el.data('filterableDropdown').previousValue === value)) {
          return false;
        }
        el.data('filterableDropdown').previousValue = value;
        labels.each(function() {
          var label       = $(this);
          this.innerHTML  = label.text(); // remove any previously added
          if (value.match(/^[a-z\s]+$/i)) {
            label.parent().hide();
            this.innerHTML = this.innerHTML.replace(new RegExp("(^|[^a-z]{1})(" + value + ")", 'i'), function() {
              label.parent().show();
              return arguments[1] + '' + arguments[2] + '';
            });
          } else {
            label.parent().show();
            labels.removeClass('highlight');
          }
        });
        if (!labels.filter('.highlight:visible').length) {
          labels.removeClass('highlight').filter(':visible').first().addClass('highlight');
        }
        el.find('._fd_nomatch').toggle(!labels.filter(':visible').parent().removeClass('first-child last-child').first().addClass('first-child').end().last().addClass('last-child').end().length);
        labels.parent().parent().scrollTop(0);
      },
      'keydown.filterableDropdown paste.filterableDropdown': function(e) {
        var labelsReverse, found = false;
        switch (e.which) {
          case 13:
            e.preventDefault();
            labels.filter('.highlight:visible').parent().find('input').prop('checked', function() { return !this.checked }).triggerHandler('click', true);
          break;
          case 9:
          case 27:
            el.trigger('close');
          break;
          case 38:
            labelsReverse = $(labels.get().reverse());
          case 40:
            e.preventDefault();
            if (!(labelsReverse || labels).filter(':visible').each(function() {
              var label = $(this);
              if (label.hasClass('highlight')) {
                label.removeClass('highlight');
                found = true;
              } else {
                label.toggleClass('highlight', found);
                if (found) {
                  var p       = label.parent();
                  var div     = p.parent();
                  var pH      = p.height();
                  var divH    = div.height();
                  var scroll  = p.offset().top - div.offset().top - 1;
                  if (scroll > 0) {
                    scroll = scroll + pH - divH;
                    if (scroll < 0) {
                      scroll = 0;
                    }
                  }
                  if (scroll) {
                    div.scrollTop(div.scrollTop() + scroll);
                  }
                  p = div = pH = divH = scroll = null;
                }
                found = false;
              }
            }).filter('.highlight').length) {
              (labelsReverse || labels).filter(':visible').last().addClass('highlight');
            }
          break;
          default:
            if (!this.value || this.value == this.defaultValue) {
              $(this).val('');
            }
          break;
          labelsReverse = found = null;
        }
      }
    }).next().on({
      'click.filterableDropdown': function(e) {
        el.trigger(el.data('filterableDropdown').closed ? 'open' : 'close');
      }
    });

    el.data('filterableDropdown', {tag: el.find('._fd_tag').remove()}).trigger('close');
  };
})(jQuery);<commit_msg>Refresh the labels highlightning on reset<commit_after>/*
 * Copyright [1999-2014] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * filterableDropdown: Javascript counterpart for E::W::Form::Element::Filterable
 * Reserverd classname prefix: _fd
 **/
(function ($) {
  $.fn.filterableDropdown = function (options) {
  /*
   * options: object with following keys
   *   refresh  - To refresh the tags selected in an already instantiated object (this is useful in case some external code has modified the selected inputs)
   *   change   - Function to be called with the raw html as context, when changing the selection. This gets fired after dropdown is closed and tags are refreshed according to new selection
   */

    return this.each(function () {
      $.filterableDropdown($(this), options);
    });
  };

  $.filterableDropdown = function (el, options) {

    options = $.extend({}, options);

    // if already instantiated
    if (el.data('filterableDropdown')) {
      if (options.change) {
        el.off('afterAddRemove.filterableDropdown').on('afterAddRemove.filterableDropdown', options.change);
      }
      if (options.refresh) {
        el.trigger('close').find('label').trigger('refresh');
      }
      return;
    }

    el.on({
      'focusInput.filterableDropdown': function() {
        el.find('._fd_filter input').trigger('focus');
      },
      'open.filterableDropdown': function() {
        if (!el.data('filterableDropdown').closed) {
          return;
        }
        el.data('filterableDropdown').closed = false;
        el.addClass('open').find('._fd_filter').show().find('input').trigger('focus').trigger('keyup').next().html('▲');
        $(document).off('.filterableDropdown').on('mousedown.filterableDropdown', function() {
          el.trigger('close');
        });
      },
      'close.filterableDropdown': function() {
        var tag = el.data('filterableDropdown').tag;
        var inp = el.find('input[type=checkbox]:checked, input[type=radio]:checked');
        el.data('filterableDropdown').closed = true;
        el.removeClass('open').find('._fd_tag').remove().end().find('._fd_filter input').trigger('reset').next().html('▼').end().end().prepend(inp.map(function() {
          return tag.clone().data('input', this).show().find('span').first().html(this.nextSibling.innerHTML).end().end();
        }).toArray()).trigger('afterAddRemove');
        if (inp.length && inp.prop('type') === 'radio') {
          el.find('._fd_filter').hide();
        }
        $(document).off('.filterableDropdown');
        tag = inp = null;
      },
      'afterAddRemove.filterableDropdown': options.change || $.noop
    }).on('click', '._fdt_button', function() {
      var inp = $($(this).parent().data('input'));
      $(this.parentNode).remove();
      if (inp.prop('type') === 'checkbox') {
        inp.prop('checked', false);
        labels.trigger('refresh');
        el.trigger('afterAddRemove');
      } else {
        el.trigger('open');
      }
      inp = null;
    }).children().on({
      'mousedown.filterableDropdown': function(e) {
        e.stopPropagation(); // prevent closing if the dropdown if clicked inside the dropdown
      }
    }).find('input[type=checkbox], input[type=radio]').on({
      'keydown.filterableDropdown': function(e) {
        e.preventDefault(); // prevent the submission of form when pressed enter on the checkboxes
      },
      'click.filterableDropdown': function(e, enterKey) {
        var onlyOneOption = labels.filter(':visible').length === 1;
        labels.trigger('refresh');
        el.trigger(onlyOneOption || this.type === 'radio' ? 'close' : 'focusInput');
        if (onlyOneOption && enterKey && this.type !== 'radio') {
          el.trigger('open');
        }
        onlyOneOption = null;
      }
    });

    var labels = el.find('label').on({
      'mouseenter.filterableDropdown': function() {
        labels.removeClass('highlight');
        $(this).addClass('highlight');
      },
      'refresh.filterableDropdown': function() {
        $(this).toggleClass('selected', $(this.parentNode).find('input').prop('checked'));
      }
    }).trigger('refresh');

    el.find('._fd_filter input').on({
      'focus.filterableDropdown': function() {
        if (this.value == this.defaultValue) {
          $(this).val('');
        }
        el.trigger('open');
      },
      'reset.filterableDropdown': function() {
        $(this).val(this.defaultValue).trigger('keyup').trigger('blur');
      },
      'keyup.filterableDropdown mouseup.filterableDropdown': function(e) {
        var value = this.value;
        if (e.originalEvent && (value === this.defaultValue || e.which === 38 || e.which === 40 || e.which === 13 || el.data('filterableDropdown').previousValue === value)) {
          return false;
        }
        el.data('filterableDropdown').previousValue = value;
        labels.each(function() {
          var label       = $(this);
          this.innerHTML  = label.text(); // remove any previously added
          if (value.match(/^[a-z\s]+$/i)) {
            label.parent().hide();
            this.innerHTML = this.innerHTML.replace(new RegExp("(^|[^a-z]{1})(" + value + ")", 'i'), function() {
              label.parent().show();
              return arguments[1] + '' + arguments[2] + '';
            });
          } else {
            label.parent().show();
            labels.removeClass('highlight');
          }
        });
        if (!labels.filter('.highlight:visible').length) {
          labels.removeClass('highlight').filter(':visible').first().addClass('highlight');
        }
        el.find('._fd_nomatch').toggle(!labels.filter(':visible').parent().removeClass('first-child last-child').first().addClass('first-child').end().last().addClass('last-child').end().length);
        labels.parent().parent().scrollTop(0);
      },
      'keydown.filterableDropdown paste.filterableDropdown': function(e) {
        var labelsReverse, found = false;
        switch (e.which) {
          case 13:
            e.preventDefault();
            labels.filter('.highlight:visible').parent().find('input').prop('checked', function() { return !this.checked }).triggerHandler('click', true);
          break;
          case 9:
          case 27:
            el.trigger('close');
          break;
          case 38:
            labelsReverse = $(labels.get().reverse());
          case 40:
            e.preventDefault();
            if (!(labelsReverse || labels).filter(':visible').each(function() {
              var label = $(this);
              if (label.hasClass('highlight')) {
                label.removeClass('highlight');
                found = true;
              } else {
                label.toggleClass('highlight', found);
                if (found) {
                  var p       = label.parent();
                  var div     = p.parent();
                  var pH      = p.height();
                  var divH    = div.height();
                  var scroll  = p.offset().top - div.offset().top - 1;
                  if (scroll > 0) {
                    scroll = scroll + pH - divH;
                    if (scroll < 0) {
                      scroll = 0;
                    }
                  }
                  if (scroll) {
                    div.scrollTop(div.scrollTop() + scroll);
                  }
                  p = div = pH = divH = scroll = null;
                }
                found = false;
              }
            }).filter('.highlight').length) {
              (labelsReverse || labels).filter(':visible').last().addClass('highlight');
            }
          break;
          default:
            if (!this.value || this.value == this.defaultValue) {
              $(this).val('');
            }
          break;
          labelsReverse = found = null;
        }
      }
    }).next().on({
      'click.filterableDropdown': function(e) {
        el.trigger(el.data('filterableDropdown').closed ? 'open' : 'close');
      }
    });

    el.data('filterableDropdown', {tag: el.find('._fd_tag').remove()}).trigger('close');
  };
})(jQuery);<|endoftext|>


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

  angular
    .module('webApp')
    .factory('CubeModelFactory', CubeModelFactory);

  function CubeModelFactory() {
    var cube = {};

    function init() {
      cube.name = "";
      cube.dimensions = [];
      cube.operators = [];
      cube.showCubeError = false;
      cube.checkpointConfig = {};
      cube.checkpointConfig.timeDimension = "";
      cube.checkpointConfig.interval = "";
      cube.checkpointConfig.timeAvailability = "";
      cube.checkpointConfig.granularity = "";
    };

    return {
      ResetCube: function () {
        init();
      },
      GetCube: function () {
        if (Object.keys(cube).length == 0) init();
        return cube;
      }
    }
  }

})
();

<commit_msg>fix(cube model factory): Fixed wrong attribute<commit_after>(function () {
  'use strict';

  angular
    .module('webApp')
    .factory('CubeModelFactory', CubeModelFactory);

  function CubeModelFactory() {
    var cube = {};

    function init() {
      cube.name = "";
      cube.dimensions = [];
      cube.operators = [];
      cube.checkpointConfig = {};
      cube.checkpointConfig.timeDimension = "";
      cube.checkpointConfig.interval = "";
      cube.checkpointConfig.timeAvailability = "";
      cube.checkpointConfig.granularity = "";
    };

    return {
      ResetCube: function () {
        init();
      },
      GetCube: function () {
        if (Object.keys(cube).length == 0) init();
        return cube;
      }
    }
  }

})
();

<|endoftext|>


<commit_before>// Sqrt(x)

// Implement int sqrt(int x).

// Compute and return the square root of x.

/**
 * @param {number} x
 * @return {number}
 */

const sqrt = function mySqrt(x) {
  if (x === 0) return 0;
  let left = 1;
  let right = Number.MAX_VALUE;
  while (true) {
    const mid = left + ((right - left) / 2);
    if (mid > x / mid) {
      right = mid - 1;
    } else {
      if (mid + 1 > x / (mid + 1)) return mid;
      left = mid + 1;
    }
  }
};

console.log(sqrt(5));
<commit_msg>add logic<commit_after>// Sqrt(x)

// Implement int sqrt(int x).

// Compute and return the square root of x.

/**
 * @param {number} x
 * @return {number}
 */

// if integer given is 0, return 0
// create a range from 1 - Max integer
// create a loop that will break once we find sqrt
  // reset mid to the difference of highest and lowest integer divided by, plus lowest integer
  // if our given integer divided by 2 is less than our mid
    // set our highest index to one less than mid
  // else
    // if mid plus 1 is greater than our given integer divided by mid plus 1
      // we found our sqrt
    // if we didnt find our sqrt
      // set our left to mid plus 1

const sqrt = function mySqrt(x) { // Binary Search approach
  if (x === 0) return 0;
  let left = 1;
  let right = Number.MAX_VALUE;
  let mid;
  while (true) {
    mid = left + ((right - left) / 2);
    if (mid > x / mid) {
      right = mid - 1;
    } else {
      if (mid + 1 > x / (mid + 1)) return mid;
      left = mid + 1;
    }
  }
};

console.log(sqrt(5));
<|endoftext|>


<commit_before>
openerp.web.formats = function(openerp) {
var _t = openerp.web._t;

/**
 * Intersperses ``separator`` in ``str`` at the positions indicated by
 * ``indices``.
 *
 * ``indices`` is an array of relative offsets (from the previous insertion
 * position, starting from the end of the string) at which to insert
 * ``separator``.
 *
 * There are two special values:
 *
 * ``-1``
 *   indicates the insertion should end now
 * ``0``
 *   indicates that the previous section pattern should be repeated (until all
 *   of ``str`` is consumed)
 *
 * @param {String} str
 * @param {Array<Number>} indices
 * @param {String} separator
 * @returns {String}
 */
openerp.web.intersperse = function (str, indices, separator) {
    separator = separator || '';
    var result = [], last = str.length;

    for(var i=0; i<indices.length; ++i) {
        var section = indices[i];
        if (section === -1 || last <= 0) {
            // Done with string, or -1 (stops formatting string)
            break;
        } else if(section === 0 && i === 0) {
            // repeats previous section, which there is none => stop
            break;
        } else if (section === 0) {
            // repeat previous section forever
            //noinspection AssignmentToForLoopParameterJS
            section = indices[--i];
        }
        result.push(str.substring(last-section, last));
        last -= section;
    }

    var s = str.substring(0, last);
    if (s) { result.push(s); }
    return result.reverse().join(separator);
};
/**
 * Insert "thousands" separators in the provided number (which is actually
 * a string)
 *
 * @param {String} num
 * @returns {String}
 */
openerp.web.insert_thousand_seps = function (num) {
    var negative = num[0] === '-';
    num = (negative ? num.slice(1) : num);
    return (negative ? '-' : '') + openerp.web.intersperse(
        num, _t.database.parameters.grouping, _t.database.parameters.thousands_sep);
};
/**
 * Formats a single atomic value based on a field descriptor
 *
 * @param {Object} value read from OpenERP
 * @param {Object} descriptor union of orm field and view field
 * @param {Object} [descriptor.widget] widget to use to display the value
 * @param {Object} descriptor.type fallback if no widget is provided, or if the provided widget is unknown
 * @param {Object} [descriptor.digits] used for the formatting of floats
 * @param {String} [value_if_empty=''] returned if the ``value`` argument is considered empty
 */
openerp.web.format_value = function (value, descriptor, value_if_empty) {
    // If NaN value, display as with a `false` (empty cell)
    if (typeof value === 'number' && isNaN(value)) {
        value = false;
    }
    //noinspection FallthroughInSwitchStatementJS
    switch (value) {
        case '':
            if (descriptor.type === 'char') {
                return '';
            }
            console.warn('Field', descriptor, 'had an empty string as value, treating as false...');
        case false:
        case Infinity:
        case -Infinity:
            return value_if_empty === undefined ?  '' : value_if_empty;
    }
    var l10n = _t.database.parameters;
    switch (descriptor.widget || descriptor.type) {
        case 'integer':
            return openerp.web.insert_thousand_seps(
                _.str.sprintf('%d', value));
        case 'float':
            var precision = descriptor.digits ? descriptor.digits[1] : 2;
            var formatted = _.str.sprintf('%.' + precision + 'f', value).split('.');
            formatted[0] = openerp.web.insert_thousand_seps(formatted[0]);
            return formatted.join(l10n.decimal_point);
        case 'float_time':
            return _.str.sprintf("%02d:%02d",
                    Math.floor(value),
                    Math.round((value % 1) * 60));
        case 'progressbar':
            return _.str.sprintf(
                '<progress value="%.2f" max="100.0">%.2f%%</progress>',
                    value, value);
        case 'many2one':
            // name_get value format
            return value[1];
        case 'datetime':
            if (typeof(value) == "string")
                value = openerp.web.auto_str_to_date(value);

            return value.format(l10n.date_format
                        + ' ' + l10n.time_format);
        case 'date':
            if (typeof(value) == "string")
                value = openerp.web.auto_str_to_date(value);
            return value.format(l10n.date_format);
        case 'time':
            if (typeof(value) == "string")
                value = openerp.web.auto_str_to_date(value);
            return value.format(l10n.time_format);
        case 'selection':
            // Each choice is [value, label]
            var result = _(descriptor.selection).detect(function (choice) {
                return choice[0] === value;
            });
            if (result) { return result[1]; }
            return;
        default:
            return value;
    }
};

openerp.web.parse_value = function (value, descriptor, value_if_empty) {
    var date_pattern = Date.normalizeFormat(_t.database.parameters.date_format),
        time_pattern = Date.normalizeFormat(_t.database.parameters.time_format);
    switch (value) {
        case false:
        case "":
            return value_if_empty === undefined ?  false : value_if_empty;
    }
    switch (descriptor.widget || descriptor.type) {
        case 'integer':
            var tmp;
            do {
                tmp = value;
                value = value.replace(openerp.web._t.database.parameters.thousands_sep, "");
            } while(tmp !== value);
            tmp = Number(value);
            if (isNaN(tmp))
                throw new Error(value + " is not a correct integer");
            return tmp;
        case 'float':
            var tmp = Number(value);
            if (!isNaN(tmp))
                return tmp;

            var tmp2 = value;
            do {
                tmp = tmp2;
                tmp2 = tmp.replace(openerp.web._t.database.parameters.thousands_sep, "");
            } while(tmp !== tmp2);
            var reformatted_value = tmp.replace(openerp.web._t.database.parameters.decimal_point, ".");
            var parsed = Number(reformatted_value);
            if (isNaN(parsed))
                throw new Error(value + " is not a correct float");
            return parsed;
        case 'float_time':
            var float_time_pair = value.split(":");
            if (float_time_pair.length != 2)
                return openerp.web.parse_value(value, {type: "float"});
            var hours = openerp.web.parse_value(float_time_pair[0], {type: "integer"});
            var minutes = openerp.web.parse_value(float_time_pair[1], {type: "integer"});
            return hours + (minutes / 60);
        case 'progressbar':
            return openerp.web.parse_value(value, {type: "float"});
        case 'datetime':
            var datetime = Date.parseExact(
                    value, (date_pattern + ' ' + time_pattern));
            if (datetime !== null)
                return openerp.web.datetime_to_str(datetime);
            datetime = Date.parse(value);
            if (datetime !== null)
                return openerp.web.datetime_to_str(datetime);
            throw new Error(value + " is not a valid datetime");
        case 'date':
            var date = Date.parseExact(value, date_pattern);
            if (date !== null)
                return openerp.web.date_to_str(date);
            date = Date.parse(value);
            if (date !== null)
                return openerp.web.date_to_str(date);
            throw new Error(value + " is not a valid date");
        case 'time':
            var time = Date.parseExact(value, time_pattern);
            if (time !== null)
                return openerp.web.time_to_str(time);
            time = Date.parse(value);
            if (time !== null)
                return openerp.web.time_to_str(time);
            throw new Error(value + " is not a valid time");
    }
    return value;
};

openerp.web.auto_str_to_date = function(value, type) {
    try {
        return openerp.web.str_to_datetime(value);
    } catch(e) {}
    try {
        return openerp.web.str_to_date(value);
    } catch(e) {}
    try {
        return openerp.web.str_to_time(value);
    } catch(e) {}
    throw new Error("'" + value + "' is not a valid date, datetime nor time");
};

openerp.web.auto_date_to_str = function(value, type) {
    switch(type) {
        case 'datetime':
            return openerp.web.datetime_to_str(value);
        case 'date':
            return openerp.web.date_to_str(value);
        case 'time':
            return openerp.web.time_to_str(value);
        default:
            throw new Error(type + " is not convertible to date, datetime nor time");
    }
};

/**
 * Formats a provided cell based on its field type
 *
 * @param {Object} row_data record whose values should be displayed in the cell
 * @param {Object} column column descriptor
 * @param {"button"|"field"} column.tag base control type
 * @param {String} column.type widget type for a field control
 * @param {String} [column.string] button label
 * @param {String} [column.icon] button icon
 * @param {String} [value_if_empty=''] what to display if the field's value is ``false``
 * @param {Boolean} [process_modifiers=true] should the modifiers be computed ?
 */
openerp.web.format_cell = function (row_data, column, value_if_empty, process_modifiers) {
    var attrs = {};
    if (process_modifiers !== false) {
        attrs = column.modifiers_for(row_data);
    }
    if (attrs.invisible) { return ''; }
    if (column.tag === 'button') {
        return _.template('<button type="button" title="<%-title%>" <%=additional_attributes%> >' +
            '<img src="<%-prefix%>/web/static/src/img/icons/<%-icon%>.png" alt="<%-alt%>"/>' +
            '</button>', {
                title: column.string || '',
                additional_attributes: isNaN(row_data["id"].value) && openerp.web.BufferedDataSet.virtual_id_regex.test(row_data["id"].value) ?
                    'disabled="disabled" class="oe-listview-button-disabled"' : '',
                prefix: openerp.connection.prefix,
                icon: column.icon,
                alt: column.string || '',
            });
    }
    if (!row_data[column.id]) {
        return value_if_empty === undefined ? '' : value_if_empty;
    }
    return openerp.web.format_value(
            row_data[column.id].value, column, value_if_empty);
}

};
<commit_msg>[FIX] support many2one widget selection in tree<commit_after>
openerp.web.formats = function(openerp) {
var _t = openerp.web._t;

/**
 * Intersperses ``separator`` in ``str`` at the positions indicated by
 * ``indices``.
 *
 * ``indices`` is an array of relative offsets (from the previous insertion
 * position, starting from the end of the string) at which to insert
 * ``separator``.
 *
 * There are two special values:
 *
 * ``-1``
 *   indicates the insertion should end now
 * ``0``
 *   indicates that the previous section pattern should be repeated (until all
 *   of ``str`` is consumed)
 *
 * @param {String} str
 * @param {Array<Number>} indices
 * @param {String} separator
 * @returns {String}
 */
openerp.web.intersperse = function (str, indices, separator) {
    separator = separator || '';
    var result = [], last = str.length;

    for(var i=0; i<indices.length; ++i) {
        var section = indices[i];
        if (section === -1 || last <= 0) {
            // Done with string, or -1 (stops formatting string)
            break;
        } else if(section === 0 && i === 0) {
            // repeats previous section, which there is none => stop
            break;
        } else if (section === 0) {
            // repeat previous section forever
            //noinspection AssignmentToForLoopParameterJS
            section = indices[--i];
        }
        result.push(str.substring(last-section, last));
        last -= section;
    }

    var s = str.substring(0, last);
    if (s) { result.push(s); }
    return result.reverse().join(separator);
};
/**
 * Insert "thousands" separators in the provided number (which is actually
 * a string)
 *
 * @param {String} num
 * @returns {String}
 */
openerp.web.insert_thousand_seps = function (num) {
    var negative = num[0] === '-';
    num = (negative ? num.slice(1) : num);
    return (negative ? '-' : '') + openerp.web.intersperse(
        num, _t.database.parameters.grouping, _t.database.parameters.thousands_sep);
};
/**
 * Formats a single atomic value based on a field descriptor
 *
 * @param {Object} value read from OpenERP
 * @param {Object} descriptor union of orm field and view field
 * @param {Object} [descriptor.widget] widget to use to display the value
 * @param {Object} descriptor.type fallback if no widget is provided, or if the provided widget is unknown
 * @param {Object} [descriptor.digits] used for the formatting of floats
 * @param {String} [value_if_empty=''] returned if the ``value`` argument is considered empty
 */
openerp.web.format_value = function (value, descriptor, value_if_empty) {
    // If NaN value, display as with a `false` (empty cell)
    if (typeof value === 'number' && isNaN(value)) {
        value = false;
    }
    //noinspection FallthroughInSwitchStatementJS
    switch (value) {
        case '':
            if (descriptor.type === 'char') {
                return '';
            }
            console.warn('Field', descriptor, 'had an empty string as value, treating as false...');
        case false:
        case Infinity:
        case -Infinity:
            return value_if_empty === undefined ?  '' : value_if_empty;
    }
    var l10n = _t.database.parameters;
    switch (descriptor.widget || descriptor.type) {
        case 'integer':
            return openerp.web.insert_thousand_seps(
                _.str.sprintf('%d', value));
        case 'float':
            var precision = descriptor.digits ? descriptor.digits[1] : 2;
            var formatted = _.str.sprintf('%.' + precision + 'f', value).split('.');
            formatted[0] = openerp.web.insert_thousand_seps(formatted[0]);
            return formatted.join(l10n.decimal_point);
        case 'float_time':
            return _.str.sprintf("%02d:%02d",
                    Math.floor(value),
                    Math.round((value % 1) * 60));
        case 'progressbar':
            return _.str.sprintf(
                '<progress value="%.2f" max="100.0">%.2f%%</progress>',
                    value, value);
        case 'many2one':
            // name_get value format
            return value[1];
        case 'datetime':
            if (typeof(value) == "string")
                value = openerp.web.auto_str_to_date(value);

            return value.format(l10n.date_format
                        + ' ' + l10n.time_format);
        case 'date':
            if (typeof(value) == "string")
                value = openerp.web.auto_str_to_date(value);
            return value.format(l10n.date_format);
        case 'time':
            if (typeof(value) == "string")
                value = openerp.web.auto_str_to_date(value);
            return value.format(l10n.time_format);
        case 'selection':
            // Each choice is [value, label]
            if(_.isArray(value)) {
                 value = value[0]
            }
            var result = _(descriptor.selection).detect(function (choice) {
                return choice[0] === value;
            });
            if (result) { return result[1]; }
            return;
        default:
            return value;
    }
};

openerp.web.parse_value = function (value, descriptor, value_if_empty) {
    var date_pattern = Date.normalizeFormat(_t.database.parameters.date_format),
        time_pattern = Date.normalizeFormat(_t.database.parameters.time_format);
    switch (value) {
        case false:
        case "":
            return value_if_empty === undefined ?  false : value_if_empty;
    }
    switch (descriptor.widget || descriptor.type) {
        case 'integer':
            var tmp;
            do {
                tmp = value;
                value = value.replace(openerp.web._t.database.parameters.thousands_sep, "");
            } while(tmp !== value);
            tmp = Number(value);
            if (isNaN(tmp))
                throw new Error(value + " is not a correct integer");
            return tmp;
        case 'float':
            var tmp = Number(value);
            if (!isNaN(tmp))
                return tmp;

            var tmp2 = value;
            do {
                tmp = tmp2;
                tmp2 = tmp.replace(openerp.web._t.database.parameters.thousands_sep, "");
            } while(tmp !== tmp2);
            var reformatted_value = tmp.replace(openerp.web._t.database.parameters.decimal_point, ".");
            var parsed = Number(reformatted_value);
            if (isNaN(parsed))
                throw new Error(value + " is not a correct float");
            return parsed;
        case 'float_time':
            var float_time_pair = value.split(":");
            if (float_time_pair.length != 2)
                return openerp.web.parse_value(value, {type: "float"});
            var hours = openerp.web.parse_value(float_time_pair[0], {type: "integer"});
            var minutes = openerp.web.parse_value(float_time_pair[1], {type: "integer"});
            return hours + (minutes / 60);
        case 'progressbar':
            return openerp.web.parse_value(value, {type: "float"});
        case 'datetime':
            var datetime = Date.parseExact(
                    value, (date_pattern + ' ' + time_pattern));
            if (datetime !== null)
                return openerp.web.datetime_to_str(datetime);
            datetime = Date.parse(value);
            if (datetime !== null)
                return openerp.web.datetime_to_str(datetime);
            throw new Error(value + " is not a valid datetime");
        case 'date':
            var date = Date.parseExact(value, date_pattern);
            if (date !== null)
                return openerp.web.date_to_str(date);
            date = Date.parse(value);
            if (date !== null)
                return openerp.web.date_to_str(date);
            throw new Error(value + " is not a valid date");
        case 'time':
            var time = Date.parseExact(value, time_pattern);
            if (time !== null)
                return openerp.web.time_to_str(time);
            time = Date.parse(value);
            if (time !== null)
                return openerp.web.time_to_str(time);
            throw new Error(value + " is not a valid time");
    }
    return value;
};

openerp.web.auto_str_to_date = function(value, type) {
    try {
        return openerp.web.str_to_datetime(value);
    } catch(e) {}
    try {
        return openerp.web.str_to_date(value);
    } catch(e) {}
    try {
        return openerp.web.str_to_time(value);
    } catch(e) {}
    throw new Error("'" + value + "' is not a valid date, datetime nor time");
};

openerp.web.auto_date_to_str = function(value, type) {
    switch(type) {
        case 'datetime':
            return openerp.web.datetime_to_str(value);
        case 'date':
            return openerp.web.date_to_str(value);
        case 'time':
            return openerp.web.time_to_str(value);
        default:
            throw new Error(type + " is not convertible to date, datetime nor time");
    }
};

/**
 * Formats a provided cell based on its field type
 *
 * @param {Object} row_data record whose values should be displayed in the cell
 * @param {Object} column column descriptor
 * @param {"button"|"field"} column.tag base control type
 * @param {String} column.type widget type for a field control
 * @param {String} [column.string] button label
 * @param {String} [column.icon] button icon
 * @param {String} [value_if_empty=''] what to display if the field's value is ``false``
 * @param {Boolean} [process_modifiers=true] should the modifiers be computed ?
 */
openerp.web.format_cell = function (row_data, column, value_if_empty, process_modifiers) {
    var attrs = {};
    if (process_modifiers !== false) {
        attrs = column.modifiers_for(row_data);
    }
    if (attrs.invisible) { return ''; }
    if (column.tag === 'button') {
        return _.template('<button type="button" title="<%-title%>" <%=additional_attributes%> >' +
            '<img src="<%-prefix%>/web/static/src/img/icons/<%-icon%>.png" alt="<%-alt%>"/>' +
            '</button>', {
                title: column.string || '',
                additional_attributes: isNaN(row_data["id"].value) && openerp.web.BufferedDataSet.virtual_id_regex.test(row_data["id"].value) ?
                    'disabled="disabled" class="oe-listview-button-disabled"' : '',
                prefix: openerp.connection.prefix,
                icon: column.icon,
                alt: column.string || '',
            });
    }
    if (!row_data[column.id]) {
        return value_if_empty === undefined ? '' : value_if_empty;
    }
    return openerp.web.format_value(
            row_data[column.id].value, column, value_if_empty);
}

};
<|endoftext|>


<commit_before>import classNames from 'classnames';
import React from 'react';

import Avatar from './avatar';
import {compareUsers} from '../../util/utils';

export default class UserSearch extends React.Component {
    keyDidChange(e) {
        switch (e.keyCode) {
            // Enter
            case 13:
                e.preventDefault();
                this.props.optionDidSelect(null);
                break;
            // Down
            case 40:
                e.preventDefault();
                this.props.selectionWillChange(1);
                break;
            // Up
            case 38:
                e.preventDefault();
                this.props.selectionWillChange(-1);
                break;
            // Esc
            case 27:
                e.preventDefault();
                this.props.valueWillReset();
                break;
        }
    }

    render() {
        let mainClass = classNames('user-search', 'open');
        return (

                <input
                    type="text"
                    className="form-control"
                    placeholder={this.props.placeholder}
                    value={this.props.value || ''}
                    onBlur={() => this.props.focusDidChange(false)}
                    onChange={e => this.props.valueDidChange(e.target.value)}
                    onFocus={() => this.props.focusDidChange(true)}
                    onKeyDown={e => this.keyDidChange(e)}/>
                {this.renderOptions(this.props.options, this.props.highlight, this.props.focus, this.props.optionDidSelect)}

        );
    }

    renderOptionItem(user, highlight, clickListener) {
        let itemClass = classNames('user-search__item', {
            'user-search__item--highlight': compareUsers(user, highlight)
        });
        return
 clickListener(user)}>

<Avatar user={user}/>

{user.username}

;
    }

    renderOptions(list, selectedItem, focused, selectListener) {
        return (list.length === 0 || !focused) ? null : (

                {list.map(item => this.renderOptionItem(item, selectedItem, selectListener))}

        );
    }
}

UserSearch.propTypes = {
    focus              : React.PropTypes.bool,
    focusDidChange     : React.PropTypes.func.isRequired,
    highlight          : React.PropTypes.object,
    optionDidSelect    : React.PropTypes.func.isRequired,
    options            : React.PropTypes.array,
    placeholder        : React.PropTypes.string,
    selectionWillChange: React.PropTypes.func.isRequired,
    value              : React.PropTypes.string,
    valueDidChange     : React.PropTypes.func.isRequired,
    valueWillReset     : React.PropTypes.func.isRequired
};
<commit_msg>change click listener to use mouse down in search<commit_after>import classNames from 'classnames';
import React from 'react';

import Avatar from './avatar';
import {compareUsers} from '../../util/utils';

export default class UserSearch extends React.Component {
    keyDidChange(e) {
        switch (e.keyCode) {
            // Enter
            case 13:
                e.preventDefault();
                this.props.optionDidSelect(null);
                break;
            // Down
            case 40:
                e.preventDefault();
                this.props.selectionWillChange(1);
                break;
            // Up
            case 38:
                e.preventDefault();
                this.props.selectionWillChange(-1);
                break;
            // Esc
            case 27:
                e.preventDefault();
                this.props.valueWillReset();
                break;
        }
    }

    render() {
        let mainClass = classNames('user-search', 'open');
        return (

                <input
                    type="text"
                    className="form-control"
                    placeholder={this.props.placeholder}
                    value={this.props.value || ''}
                    onBlur={() => this.props.focusDidChange(false)}
                    onChange={e => this.props.valueDidChange(e.target.value)}
                    onFocus={() => this.props.focusDidChange(true)}
                    onKeyDown={e => this.keyDidChange(e)}/>
                {this.renderOptions(this.props.options, this.props.highlight, this.props.focus, this.props.optionDidSelect)}

        );
    }

    renderOptionItem(user, highlight, clickListener) {
        let itemClass = classNames('user-search__item', {
            'user-search__item--highlight': compareUsers(user, highlight)
        });
        return
 clickListener(user)}>

<Avatar user={user}/>

{user.username}

;
    }

    renderOptions(list, selectedItem, focused, selectListener) {
        return (list.length === 0 || !focused) ? null : (

                {list.map(item => this.renderOptionItem(item, selectedItem, selectListener))}

        );
    }
}

UserSearch.propTypes = {
    focus              : React.PropTypes.bool,
    focusDidChange     : React.PropTypes.func.isRequired,
    highlight          : React.PropTypes.object,
    optionDidSelect    : React.PropTypes.func.isRequired,
    options            : React.PropTypes.array,
    placeholder        : React.PropTypes.string,
    selectionWillChange: React.PropTypes.func.isRequired,
    value              : React.PropTypes.string,
    valueDidChange     : React.PropTypes.func.isRequired,
    valueWillReset     : React.PropTypes.func.isRequired
};
<|endoftext|>


<commit_before>/* global module:false */
module.exports = function(grunt) {
	var port = grunt.option('port') || 8000;
	var base = grunt.option('base') || '.';

	// Project configuration
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		meta: {
			banner:
				'/*!\n' +
				' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
				' * http://lab.hakim.se/reveal-js\n' +
				' * MIT licensed\n' +
				' *\n' +
				' * Copyright (C) 2016 Hakim El Hattab, http://hakim.se\n' +
				' */'
		},

		qunit: {
			files: [ 'test/*.html' ]
		},

		uglify: {
			options: {
				banner: '<%= meta.banner %>\n'
			},
			build: {
				src: 'js/reveal.js',
				dest: 'js/reveal.min.js'
			}
		},

		sass: {
			core: {
				files: {
					'css/reveal.css': 'css/reveal.scss',
				}
			},
			themes: {
				files: [
					{
						expand: true,
						cwd: 'css/theme/source',
						src: ['*.scss'],
						dest: 'css/theme',
						ext: '.css'
					}
				]
			}
		},

		autoprefixer: {
			dist: {
				src: 'css/reveal.css'
			}
		},

		cssmin: {
			compress: {
				files: {
					'css/reveal.min.css': [ 'css/reveal.css' ]
				}
			}
		},

		jshint: {
			options: {
				curly: false,
				eqeqeq: true,
				immed: true,
				latedef: true,
				newcap: true,
				noarg: true,
				sub: true,
				undef: true,
				eqnull: true,
				browser: true,
				expr: true,
				globals: {
					head: false,
					module: false,
					console: false,
					unescape: false,
					define: false,
					exports: false
				}
			},
			files: [ 'Gruntfile.js', 'js/reveal.js' ]
		},

		connect: {
			server: {
				options: {
					port: port,
					base: base,
					livereload: true,
					open: true
				}
			}
		},

		zip: {
			'reveal-js-presentation.zip': [
				'index.html',
				'css/**',
				'js/**',
				'lib/**',
				'images/**',
				'plugin/**',
				'**.md'
			]
		},

		watch: {
			js: {
				files: [ 'Gruntfile.js', 'js/reveal.js' ],
				tasks: 'js'
			},
			theme: {
				files: [ 'css/theme/source/*.scss', 'css/theme/template/*.scss' ],
				tasks: 'css-themes'
			},
			css: {
				files: [ 'css/reveal.scss' ],
				tasks: 'css-core'
			},
			html: {
				files: [ '*.html']
			},
			markdown: {
				files: [ '*.md' ]
			},
			options: {
				livereload: true
			}
		}

	});

	// Dependencies
	grunt.loadNpmTasks( 'grunt-contrib-qunit' );
	grunt.loadNpmTasks( 'grunt-contrib-jshint' );
	grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
	grunt.loadNpmTasks( 'grunt-contrib-uglify' );
	grunt.loadNpmTasks( 'grunt-contrib-watch' );
	grunt.loadNpmTasks( 'grunt-sass' );
	grunt.loadNpmTasks( 'grunt-contrib-connect' );
	grunt.loadNpmTasks( 'grunt-autoprefixer' );
	grunt.loadNpmTasks( 'grunt-zip' );

	// Default task
	grunt.registerTask( 'default', [ 'css', 'js' ] );

	// JS task
	grunt.registerTask( 'js', [ 'jshint', 'uglify', 'qunit' ] );

	// Theme CSS
	grunt.registerTask( 'css-themes', [ 'sass:themes' ] );

	// Core framework CSS
	grunt.registerTask( 'css-core', [ 'sass:core', 'autoprefixer', 'cssmin' ] );

	// All CSS
	grunt.registerTask( 'css', [ 'sass', 'autoprefixer', 'cssmin' ] );

	// Package presentation to archive
	grunt.registerTask( 'package', [ 'default', 'zip' ] );

	// Serve presentation locally
	grunt.registerTask( 'serve', [ 'connect', 'watch' ] );

	// Run tests
	grunt.registerTask( 'test', [ 'jshint', 'qunit' ] );

};
<commit_msg>Delete Gruntfile.js<commit_after><|endoftext|>


<commit_before>// Component having content to be shown on modal when any event is clicked

import React, {Component} from 'react'
import BigCalendar from 'react-big-calendar';
import moment from 'moment';
import {connect} from 'react-redux'
import {FormGroup, ControlLabel, FormControl} from 'react-bootstrap';

import TtnButton from 'core/Button/btn';
import Dropdown from './../Dropdown'
import TsmsForm from './../Form';
import MultiSelectDropdown from './../MultiSelectDropDown'
import {deleteActivity,updateActivities} from './../../actions/activity.actions'
import ModalComp from './../ModalComp'
import DeleteModal from './../DeleteModal'

BigCalendar.setLocalizer(
    BigCalendar.momentLocalizer(moment)
);

class ModalContent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            edit: false,
            hh:'',
            mm:0,
            activityType:'',
            description:'',
            collaborators:[],
            deleteModal:false
        }
    }

    onEdit = (event) => {
        event.preventDefault();
        this.setState({
            edit: true
        })
    };

    cancelEdit = (event) => {
        event.preventDefault();
        this.setState({
            edit: false
        })
    };

    saveEditedEvent = (event) => {
        event.preventDefault();
        let updatedEvent = this.props.eventInfo.moreInfo;
        updatedEvent.activityType = this.state.activityType || updatedEvent.activityType;
        updatedEvent.hh = this.state.hh || updatedEvent.hh;
        updatedEvent.mm = this.state.mm || updatedEvent.mm;
        updatedEvent.description = this.state.description || updatedEvent.description;

        console.log(updatedEvent);
        this.props.updateActivities(updatedEvent);
        this.props.closeCalendar();
    }

    onInputChange = (event) => {
        this.setState({
            [event.target.name] : event.target.value
        })
    };

    deleteEvent = (event) => {
        event.preventDefault();
        this.setState({
            deleteModal : true
        })
    };

    setSelectedValue = (item, property) => {
        this.setState({
            [property]: item
        })
    };

    onSelectedVal = (newCollab) => {
        (this.state.collaborators.length && this.state.collaborators.indexOf(newCollab) > -1) ? null : this.state.collaborators.push(newCollab);
        this.setState({collaborators: this.state.collaborators});
    };

    onDeleteCollab = (deletedVal) => {
        this.state.collaborators.splice(this.state.collaborators.indexOf(deletedVal), 1);
        this.setState({
            collaborators: this.state.collaborators
        })
    };

    close = () => {
        this.setState({deleteModal: false})
    };

    deleteEventDone = () => {
        console.log("Delete :",this.props.eventInfo);
        this.props.deleteActivity(this.props.eventInfo.moreInfo._id)
        this.setState({
            deleteModal:false
        })
        this.props.closeCalendar();
    };

    render() {
        let hour = [1,2 ,3,4,5,6,7 ,8 ];
        let minutes = [10,20,30,40,50];
        let activityTitles = ['Westcon','Knowlegde Meet','Daily Time Analysis'];

        return (

{
                this.state.edit ?

                        <TsmsForm formClassName="add-activity">

                                <FormGroup controlId="projectCategory">
                                    <ControlLabel>Activity Type:*</ControlLabel>
                                    <Dropdown data={activityTitles}
                                              title={this.state.activityType || this.props.eventInfo.moreInfo.activityType}
                                              onSelect={(item) => this.setSelectedValue(item,'activityType')}
                                    />
                                </FormGroup>
                                <FormGroup controlId="hh">
                                    <ControlLabel>hh:*</ControlLabel>
                                    <Dropdown data={hour}
                                              title={this.state.hh || this.props.eventInfo.moreInfo.hh}
                                              onSelect={(item) => this.setSelectedValue(item,'hh')}/>
                                </FormGroup>
                                <FormGroup controlId="mm">
                                    <ControlLabel>mm:*</ControlLabel>
                                    <Dropdown data={minutes}
                                              title={this.state.mm || this.props.eventInfo.moreInfo.mm}
                                              onSelect={(item) => this.setSelectedValue(item,'mm')}/>
                                </FormGroup>
                                <FormGroup controlId="description">
                                    <ControlLabel>Description:</ControlLabel>
                                    <FormControl type="text" label="Description" placeholder="Description" value={this.state.description || this.props.eventInfo.moreInfo.description} onChange={this.onInputChange} name="description"/>
                                </FormGroup>

Collaborators : {this.props.eventInfo.moreInfo.collaborators}

                                <TtnButton iconButton
                                           level="secondary"
                                           rounded icon ="glyphicon glyphicon-ok"
                                           onClick={this.saveEditedEvent}/>
                                <TtnButton iconButton
                                           level="secondary"
                                           rounded icon ="glyphicon glyphicon-remove"
                                           onClick={this.cancelEdit}/>

                        </TsmsForm>

 :

Activity : {this.props.eventInfo.moreInfo.activityType}

hh : {this.props.eventInfo.moreInfo.hh}

mm : {this.props.eventInfo.moreInfo.mm}

Description : {this.props.eventInfo.moreInfo.description}

Collaborators : {this.props.eventInfo.moreInfo.collaborators}

                        {
                            this.props.month === new Date().getMonth() ?

                                <TtnButton iconButton
                                           level="secondary"
                                           rounded icon ="glyphicon glyphicon-pencil"
                                           onClick={this.onEdit}/>
                                <TtnButton iconButton
                                           level="secondary"
                                           rounded icon ="glyphicon glyphicon-trash"
                                           onClick={this.deleteEvent}/>

 : null
                        }

            }
                <ModalComp modalShow={this.state.deleteModal}
                           modalHide = {(e) => {this.close(e)}}
                           modalHeaderMsg='Delete Activity'
                           modalBody = {<DeleteModal message={this.props.date} deleteActivity={this.deleteEventDone} close={this.close}/>}
                           modalFooterClose = {this.close}
                           modalFooterText = 'Close'
                />

        )
    }
}
const mapDispatchToProps = (dispatch) => ({
    deleteActivity : (activityId) => {dispatch(deleteActivity(activityId))},
    updateActivities : (activityLog) => {dispatch(updateActivities(activityLog))}
});

export default connect(null,mapDispatchToProps)(ModalContent);

<commit_msg>Calendar edit description rectified<commit_after>// Component having content to be shown on modal when any event is clicked

import React, {Component} from 'react'
import BigCalendar from 'react-big-calendar';
import moment from 'moment';
import {connect} from 'react-redux'
import {FormGroup, ControlLabel, FormControl} from 'react-bootstrap';

import TtnButton from 'core/Button/btn';
import Dropdown from './../Dropdown'
import TsmsForm from './../Form';
import MultiSelectDropdown from './../MultiSelectDropDown'
import {deleteActivity,updateActivities} from './../../actions/activity.actions'
import ModalComp from './../ModalComp'
import DeleteModal from './../DeleteModal'

BigCalendar.setLocalizer(
    BigCalendar.momentLocalizer(moment)
);

class ModalContent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            edit: false,
            hh:'',
            mm:0,
            activityType:'',
            description:this.props.eventInfo.moreInfo.description,
            collaborators:[],
            deleteModal:false
        }
    }

    onEdit = (event) => {
        event.preventDefault();
        this.setState({
            edit: true
        })
    };

    cancelEdit = (event) => {
        event.preventDefault();
        this.setState({
            edit: false
        })
    };

    saveEditedEvent = (event) => {
        event.preventDefault();
        let updatedEvent = this.props.eventInfo.moreInfo;
        updatedEvent.activityType = this.state.activityType || updatedEvent.activityType;
        updatedEvent.hh = this.state.hh || updatedEvent.hh;
        updatedEvent.mm = this.state.mm || updatedEvent.mm;
        updatedEvent.description = this.state.description || updatedEvent.description;

        console.log(updatedEvent);
        this.props.updateActivities(updatedEvent);
        this.props.closeCalendar();
    }

    onInputChange = (event) => {
        this.setState({
            description : event.target.value
        })
    };

    deleteEvent = (event) => {
        event.preventDefault();
        this.setState({
            deleteModal : true
        })
    };

    setSelectedValue = (item, property) => {
        this.setState({
            [property]: item
        })
    };

    onSelectedVal = (newCollab) => {
        (this.state.collaborators.length && this.state.collaborators.indexOf(newCollab) > -1) ? null : this.state.collaborators.push(newCollab);
        this.setState({collaborators: this.state.collaborators});
    };

    onDeleteCollab = (deletedVal) => {
        this.state.collaborators.splice(this.state.collaborators.indexOf(deletedVal), 1);
        this.setState({
            collaborators: this.state.collaborators
        })
    };

    close = () => {
        this.setState({deleteModal: false})
    };

    deleteEventDone = () => {
        console.log("Delete :",this.props.eventInfo);
        this.props.deleteActivity(this.props.eventInfo.moreInfo._id)
        this.setState({
            deleteModal:false
        })
        this.props.closeCalendar();
    };

    render() {
        let hour = [1,2 ,3,4,5,6,7 ,8 ];
        let minutes = [10,20,30,40,50];
        let activityTitles = ['Westcon','Knowlegde Meet','Daily Time Analysis'];

        return (

{
                this.state.edit ?

                        <TsmsForm formClassName="add-activity">

                                <FormGroup controlId="projectCategory">
                                    <ControlLabel>Activity Type:*</ControlLabel>
                                    <Dropdown data={activityTitles}
                                              title={this.state.activityType || this.props.eventInfo.moreInfo.activityType}
                                              onSelect={(item) => this.setSelectedValue(item,'activityType')}
                                    />
                                </FormGroup>
                                <FormGroup controlId="hh">
                                    <ControlLabel>hh:*</ControlLabel>
                                    <Dropdown data={hour}
                                              title={this.state.hh || this.props.eventInfo.moreInfo.hh}
                                              onSelect={(item) => this.setSelectedValue(item,'hh')}/>
                                </FormGroup>
                                <FormGroup controlId="mm">
                                    <ControlLabel>mm:*</ControlLabel>
                                    <Dropdown data={minutes}
                                              title={this.state.mm || this.props.eventInfo.moreInfo.mm}
                                              onSelect={(item) => this.setSelectedValue(item,'mm')}/>
                                </FormGroup>
                                <FormGroup controlId="description">
                                    <ControlLabel>Description:</ControlLabel>
                                    <FormControl type="text" label="Description" placeholder="Description" value={this.state.description} onChange={this.onInputChange} name="description"/>
                                </FormGroup>

Collaborators : {this.props.eventInfo.moreInfo.collaborators}

                                <TtnButton iconButton
                                           level="secondary"
                                           rounded icon ="glyphicon glyphicon-ok"
                                           onClick={this.saveEditedEvent}/>
                                <TtnButton iconButton
                                           level="secondary"
                                           rounded icon ="glyphicon glyphicon-remove"
                                           onClick={this.cancelEdit}/>

                        </TsmsForm>

 :

Activity : {this.props.eventInfo.moreInfo.activityType}

hh : {this.props.eventInfo.moreInfo.hh}

mm : {this.props.eventInfo.moreInfo.mm}

Description : {this.props.eventInfo.moreInfo.description}

Collaborators : {this.props.eventInfo.moreInfo.collaborators}

                        {
                            this.props.month === new Date().getMonth() ?

                                <TtnButton iconButton
                                           level="secondary"
                                           rounded icon ="glyphicon glyphicon-pencil"
                                           onClick={this.onEdit}/>
                                <TtnButton iconButton
                                           level="secondary"
                                           rounded icon ="glyphicon glyphicon-trash"
                                           onClick={this.deleteEvent}/>

 : null
                        }

            }
                <ModalComp modalShow={this.state.deleteModal}
                           modalHide = {(e) => {this.close(e)}}
                           modalHeaderMsg='Delete Activity'
                           modalBody = {<DeleteModal message={this.props.date} deleteActivity={this.deleteEventDone} close={this.close}/>}
                           modalFooterClose = {this.close}
                           modalFooterText = 'Close'
                />

        )
    }
}
const mapDispatchToProps = (dispatch) => ({
    deleteActivity : (activityId) => {dispatch(deleteActivity(activityId))},
    updateActivities : (activityLog) => {dispatch(updateActivities(activityLog))}
});

export default connect(null,mapDispatchToProps)(ModalContent);

<|endoftext|>


<commit_before>/*
  QuoJS 1.0
  (c) 2011, 2012 Javi Jiménez Villar (@soyjavi)
  http://quojs.tapquo.com
*/

(function($$) {

    /**
     * ?
     */
    $$.fn.attr = function(name, value) {
        if ($$.toType(name) === 'string' && value === undefined) {
            return this[0].getAttribute(name);
        } else {
            return this.each(function() {
                this.setAttribute(name, value);
            });
        }
    }

    /**
     * ?
     */
    $$.fn.data = function(name, value) {
        return this.attr('data-' + name, value);
    }

    /**
     * ?
     */
    $$.fn.val = function(value) {
        if (value) {
            return this.each(function() {
                this.value = value;
            });
        } else {
            return (this.length > 0 ? this[0].value : null)
        }
    }

    /**
     * ?
     */
    $$.fn.height = function() {

    }

    /**
     * ?
     */
    $$.fn.width = function() {

    }

    /**
     * ?
     */
    $$.fn.offset = function() {
        var bounding = this[0].getBoundingClientRect();

        return {
            left: bounding.left + window.pageXOffset,
            top: bounding.top + window.pageYOffset,
            width: bounding.width,
            height: bounding.height
        };
    }

    /**
     * ?
     */
    $$.fn.remove = function() {
        return this.each(function() {
            if (this.parentNode != null) {
                this.parentNode.removeChild(this);
            }
        });
    }

})(Quo);<commit_msg>New height() & width() methods<commit_after>/*
  QuoJS 1.0
  (c) 2011, 2012 Javi Jiménez Villar (@soyjavi)
  http://quojs.tapquo.com
*/

(function($$) {

    /**
     * ?
     */
    $$.fn.attr = function(name, value) {
        if ($$.toType(name) === 'string' && value === undefined) {
            return this[0].getAttribute(name);
        } else {
            return this.each(function() {
                this.setAttribute(name, value);
            });
        }
    };

    /**
     * ?
     */
    $$.fn.data = function(name, value) {
        return this.attr('data-' + name, value);
    };

    /**
     * ?
     */
    $$.fn.val = function(value) {
        if (value) {
            return this.each(function() {
                this.value = value;
            });
        } else {
            return (this.length > 0 ? this[0].value : null)
        }
    };

    /**
     * ?
     */
    $$.fn.height = function() {
        var offset = this.offset();
        return offset.height;
    };

    /**
     * ?
     */
    $$.fn.width = function() {
        var offset = this.offset();
        return offset.width;
    };

    /**
     * ?
     */
    $$.fn.offset = function() {
        var bounding = this[0].getBoundingClientRect();

        return {
            left: bounding.left + window.pageXOffset,
            top: bounding.top + window.pageYOffset,
            width: bounding.width,
            height: bounding.height
        };
    };

    /**
     * ?
     */
    $$.fn.remove = function() {
        return this.each(function() {
            if (this.parentNode != null) {
                this.parentNode.removeChild(this);
            }
        });
    };

})(Quo);<|endoftext|>


<commit_before>/*
 *  KNXBridge.js
 *
 *  David Janes
 *  IOTDB.org
 *  2015-11-29
 *
 *  Copyright [2013-2015] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

var iotdb = require('iotdb');
var _ = iotdb._;

var url = require('url');
var knx_js = require('knx.js');

var logger = iotdb.logger({
    name: 'homestar-knx',
    module: 'KNXBridge',
});

/*
    localIpAddress, 13671);
  var KnxConnectionTunneling = require('knx.js').KnxConnectionTunneling;
  var connection = new KnxConnectionTunneling('192.168.80.101', 3671, localIpAddress, 13671);
  */

/**
 *  See {iotdb.bridge.Bridge#Bridge} for documentation.
 *

 *  @param {object|undefined} native
 *  only used for instances, should be
 */
var KNXBridge = function (initd, native) {
    var self = this;

    self.initd = _.defaults(initd,
        iotdb.keystore().get("bridges/KNXBridge/initd"), {
            host: null,
            port: 3671,
            tunnel: null,
            raw: false, // pass GAs unchanged (debugging mainly)
            uuid: null, // seed for the Thing-ID
            number: 0, // can be used to share a single UUID
            knx: {}, // trés important
        }
    );
    self.native = native; // the thing that does the work - keep this name

    if (self.initd.tunnel) {
        var turl = url.parse(self.initd.tunnel);
        self.initd.tunnel_host = turl.hostname;
        self.initd.tunnel_port = parseInt(turl.port);
    }

    if ((self.initd.tunnel_host === '') || (self.initd.tunnel_host === '0.0.0.0')) {
        self.initd.tunnel_host = _.net.ipv4();
    }

    if ((self.initd.host === '') || (self.initd.host === '0.0.0.0')) {
        self.initd.host = _.net.ipv4();
    }

    // preprocess knx (probably unnecessary for exemplars)
    self.knx_writed = {};
    self.knx_readd = {};

    if (!_.is.Empty(self.initd.knx)) {
        if (_.is.Dictionary(self.initd.knx)) {
            _.mapObject(self.initd.knx, function (coded, code) {
                coded = _.deepCopy(coded);
                coded.code = code;

                if (coded.write) {
                    self.knx_writed[coded.code] = coded;
                }
                if (coded.read) {
                    self.knx_readd[coded.read] = coded;
                }
            });
        }
    }

    if (self.native) {
        self.queue = _.queue("KNXBridge");
        self.scratchd = {};

        if (!self.initd.uuid) {
            logger.error({
                method: "KXBridge",
                initd: self.initd,
                cause: "caller should initialize with an 'uuid'",
            }, "missing initd.uuid - problematic");
        }
    }
};

KNXBridge.prototype = new iotdb.Bridge();

KNXBridge.prototype.name = function () {
    return "KNXBridge";
};

/* --- lifecycle --- */

/**
 *  See {iotdb.bridge.Bridge#discover} for documentation.
 */
KNXBridge.prototype.discover = function () {
    var self = this;

    logger.info({
        method: "discover"
    }, "called");

    if (self.initd.host) {
        self._knx(function (error, native) {
            if (error) {
                logger.error({
                    method: "discover",
                    initd: self.initd,
                    error: _.error.message(error),
                }, "no way to connect to KNX");

                return;
            }

            self.discovered(new KNXBridge(self.initd, native));
        });
    } else {
        logger.error({
            method: "discover",
            initd: self.initd,
            cause: "host and port expected",
        }, "no way to connect to KNX");
    }
};

/**
 *  See {iotdb.bridge.Bridge#connect} for documentation.
 */
KNXBridge.prototype.connect = function (connectd) {
    var self = this;
    if (!self.native) {
        return;
    }

    self._validate_connect(connectd);

    self.connectd = _.defaults(
        connectd, {
            subscribes: [],
            data_in: function (paramd) {
                self._data_in(paramd);
            },
            post_in: function (paramd) {
                return paramd.cookd;
            },
            pre_out: function (paramd) {
                return paramd.cookd;
            },
            data_out: function (paramd) {
                self._data_out(paramd);
            },
        }, self.connectd
    );

    self._setup_read();
    self.pull();
};

KNXBridge.prototype._data_in = function (paramd) {
    var self = this;

    if (self.initd.raw) {
        paramd.cookd = _.deepCopy(paramd.rawd);
    } else {
        _.mapObject(paramd.rawd, function (value, knx_ga) {
            // it's OK - data can come that we don't know about
            var coded = self.knx_readd[knx_ga];
            if (!coded) {
                return;
            }

            paramd.cookd[coded.code] = value;
        });
    }
};

KNXBridge.prototype._data_out = function (paramd) {
    var self = this;

    if (self.initd.raw) {
        paramd.rawd = _.deepCopy(paramd.cookd);
    } else {
        _.mapObject(paramd.cookd, function (value, code) {
            var coded = self.knx_writed[code];
            if (!coded) {
                return;
            }

            paramd.rawd[coded.write] = value;
        });
    }
};

KNXBridge.prototype._setup_read = function () {
    var self = this;

    var _on_change = function (knx_ga, data, datagram) {
        if (!self.knx_readd[knx_ga]) {
            return;
        }

        logger.info({
            method: "_setup_read/on(status)",
            knx_ga: knx_ga,
            data: data,
            datagram: datagram,
        }, "got 'status'/'event'");

        var rawd = {};
        rawd[knx_ga] = data;
        var paramd = {
            rawd: rawd,
            cookd: {},
            scratchd: self.scratchd,
        };
        self.connectd.data_in(paramd);

        var cookd = self.connectd.post_in(paramd);
        if (cookd !== undefined) {
            paramd.cookd = cookd;
        }

        paramd.cookd['@__validate'] = true;
        self.pulled(paramd.cookd);
    };

    self.native.on('status', function (knx_ga, data, datagram) {
        _on_change(knx_ga, data, datagram);
    });
    self.native.on('event', function (knx_ga, data, datagram) {
        _on_change(knx_ga, data, datagram);
    });

    self.connectd.subscribes.map(function (knx_ga) {
        logger.info({
            method: "_setup_read",
            knx_ga: knx_ga,
        }, "subscribe to GA (connectd.subscribes)");
        self.native.RequestStatus(knx_ga);
    });

    _.mapObject(self.knx_readd, function (coded, knx_ga) {
        logger.info({
            method: "_setup_read",
            knx_ga: knx_ga,
        }, "subscribe to GA (knx_readd)");
        self.native.RequestStatus(knx_ga);
    });
};

KNXBridge.prototype._forget = function () {
    var self = this;
    if (!self.native) {
        return;
    }

    logger.info({
        method: "_forget"
    }, "called");

    self.native = null;
    self.pulled();
};

/**
 *  See {iotdb.bridge.Bridge#disconnect} for documentation.
 */
KNXBridge.prototype.disconnect = function () {
    var self = this;
    if (!self.native || !self.native) {
        return;
    }

    self._forget();
};

/* --- data --- */

/**
 *  See {iotdb.bridge.Bridge#push} for documentation.
 */
KNXBridge.prototype.push = function (pushd, done) {
    var self = this;
    if (!self.native) {
        done(new Error("not connected"));
        return;
    }

    self._validate_push(pushd);

    logger.info({
        method: "push",
        pushd: pushd
    }, "push");

    var paramd = {
        rawd: {},
        cookd: pushd,
        scratchd: self.scratchd,
    };

    var cookd = self.connectd.pre_out(paramd);
    if (cookd !== undefined) {
        paramd.cookd = cookd;
    }

    self.connectd.data_out(paramd);

    _.mapObject(paramd.rawd, function (value, key) {
        self._send(key, value);
    });

    done(); // XXX - this needs to be counted per key
};

KNXBridge.prototype._send = function (key, value) {
    var self = this;

    var qitem = {
        run: function () {
            logger.info({
                method: "_send",
                key: key,
                value: value,
            }, "send");

            if (self.native) {
                self.native.Action(key, value);
            }
            self.queue.finished(qitem);
        },
        coda: function () {
            // done();
        },
    };
    self.queue.add(qitem);
};

/**
 *  See {iotdb.bridge.Bridge#pull} for documentation.
 */
KNXBridge.prototype.pull = function () {
    var self = this;
    if (!self.native) {
        return;
    }
};

/* --- state --- */

/**
 *  See {iotdb.bridge.Bridge#meta} for documentation.
 */
KNXBridge.prototype.meta = function () {
    var self = this;
    if (!self.native) {
        return;
    }

    return {
        "iot:thing-id": _.id.thing_urn.unique("KNX", self.initd.uuid, self.initd.number),
        "iot:device-id": _.id.thing_urn.unique("KNX", self.initd.uuid),
        "schema:name": self.native.name || "KNX",

        // "iot:thing-number": self.initd.number,
        // "schema:manufacturer": "",
        // "schema:model": "",
    };
};

/**
 *  See {iotdb.bridge.Bridge#reachable} for documentation.
 */
KNXBridge.prototype.reachable = function () {
    return this.native !== null;
};

/**
 *  See {iotdb.bridge.Bridge#configure} for documentation.
 */
KNXBridge.prototype.configure = function (app) {};

/* -- internals -- */
var __knxd = {};
var __pendingsd = {};

/**
 *  This returns a connection object per ( host, port, tunnel_host, tunnel_port )
 *  tuple, ensuring the correct connection object exists and is connected.
 *  It calls back with the connection object
 *
 *  The code is complicated because we have to keep callbacks stored
 *  in '__pendingsd' until the connection is actually made
 */
KNXBridge.prototype._knx = function (callback) {
    var self = this;

    var key = [self.initd.host, "" + self.initd.port, self.initd.tunnel_host, "" + self.initd.tunnel_port].join("@@");

    var knx = __knxd[key];
    if (knx === undefined) {
        var connect = false;

        var pendings = __pendingsd[key];
        if (pendings === undefined) {
            pendings = [];
            __pendingsd[key] = pendings;
            connect = true;
        }

        pendings.push(callback);

        if (connect) {
            logger.info({
                method: "_knx",
                npending: pendings.length,
                host: self.initd.host,
                port: self.initd.port,
                tunnel_host: self.initd.tunnel_host,
                tunnel_port: self.initd.tunnel_port
            }, "connecting to KNX");

            if (self.initd.tunnel_host) {
                knx = new knx_js.KnxConnectionTunneling(
                    self.initd.host, self.initd.port,
                    self.initd.tunnel_host, self.initd.tunnel_port
                );
            } else {
                knx = new knx_js.KnxConnection(
                    self.initd.host, self.initd.port
                );
            }

            // probably should be error checking here
            knx.Connect(function () {
                logger.info({
                    method: "_knx",
                    npending: pendings.length,
                    host: self.initd.host,
                    port: self.initd.port,
                    tunnel_host: self.initd.tunnel_host,
                    tunnel_port: self.initd.tunnel_port,
                    connected: knx.connected
                }, "connected to KNX! (?)");

                if (knx.connected) {
                    __knxd[key] = knx;

                    pendings.map(function (pending) {
                        pending(null, knx);
                    });
                } else {
                    var error = new Error("could not establish a connection");
                    pendings.map(function (pending) {
                        pending(error, null);
                    });
                }

                delete __pendingsd[key];
            });
        }
    } else {
        callback(null, knx);
    }
};

/*
 *  API
 */
exports.Bridge = KNXBridge;
<commit_msg>remove deepCopy and shallowCopy<commit_after>/*
 *  KNXBridge.js
 *
 *  David Janes
 *  IOTDB.org
 *  2015-11-29
 *
 *  Copyright [2013-2015] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

var iotdb = require('iotdb');
var _ = iotdb._;

var url = require('url');
var knx_js = require('knx.js');

var logger = iotdb.logger({
    name: 'homestar-knx',
    module: 'KNXBridge',
});

/*
    localIpAddress, 13671);
  var KnxConnectionTunneling = require('knx.js').KnxConnectionTunneling;
  var connection = new KnxConnectionTunneling('192.168.80.101', 3671, localIpAddress, 13671);
  */

/**
 *  See {iotdb.bridge.Bridge#Bridge} for documentation.
 *

 *  @param {object|undefined} native
 *  only used for instances, should be
 */
var KNXBridge = function (initd, native) {
    var self = this;

    self.initd = _.defaults(initd,
        iotdb.keystore().get("bridges/KNXBridge/initd"), {
            host: null,
            port: 3671,
            tunnel: null,
            raw: false, // pass GAs unchanged (debugging mainly)
            uuid: null, // seed for the Thing-ID
            number: 0, // can be used to share a single UUID
            knx: {}, // trés important
        }
    );
    self.native = native; // the thing that does the work - keep this name

    if (self.initd.tunnel) {
        var turl = url.parse(self.initd.tunnel);
        self.initd.tunnel_host = turl.hostname;
        self.initd.tunnel_port = parseInt(turl.port);
    }

    if ((self.initd.tunnel_host === '') || (self.initd.tunnel_host === '0.0.0.0')) {
        self.initd.tunnel_host = _.net.ipv4();
    }

    if ((self.initd.host === '') || (self.initd.host === '0.0.0.0')) {
        self.initd.host = _.net.ipv4();
    }

    // preprocess knx (probably unnecessary for exemplars)
    self.knx_writed = {};
    self.knx_readd = {};

    if (!_.is.Empty(self.initd.knx)) {
        if (_.is.Dictionary(self.initd.knx)) {
            _.mapObject(self.initd.knx, function (coded, code) {
                coded = _.d.clone.deep(coded);
                coded.code = code;

                if (coded.write) {
                    self.knx_writed[coded.code] = coded;
                }
                if (coded.read) {
                    self.knx_readd[coded.read] = coded;
                }
            });
        }
    }

    if (self.native) {
        self.queue = _.queue("KNXBridge");
        self.scratchd = {};

        if (!self.initd.uuid) {
            logger.error({
                method: "KXBridge",
                initd: self.initd,
                cause: "caller should initialize with an 'uuid'",
            }, "missing initd.uuid - problematic");
        }
    }
};

KNXBridge.prototype = new iotdb.Bridge();

KNXBridge.prototype.name = function () {
    return "KNXBridge";
};

/* --- lifecycle --- */

/**
 *  See {iotdb.bridge.Bridge#discover} for documentation.
 */
KNXBridge.prototype.discover = function () {
    var self = this;

    logger.info({
        method: "discover"
    }, "called");

    if (self.initd.host) {
        self._knx(function (error, native) {
            if (error) {
                logger.error({
                    method: "discover",
                    initd: self.initd,
                    error: _.error.message(error),
                }, "no way to connect to KNX");

                return;
            }

            self.discovered(new KNXBridge(self.initd, native));
        });
    } else {
        logger.error({
            method: "discover",
            initd: self.initd,
            cause: "host and port expected",
        }, "no way to connect to KNX");
    }
};

/**
 *  See {iotdb.bridge.Bridge#connect} for documentation.
 */
KNXBridge.prototype.connect = function (connectd) {
    var self = this;
    if (!self.native) {
        return;
    }

    self._validate_connect(connectd);

    self.connectd = _.defaults(
        connectd, {
            subscribes: [],
            data_in: function (paramd) {
                self._data_in(paramd);
            },
            post_in: function (paramd) {
                return paramd.cookd;
            },
            pre_out: function (paramd) {
                return paramd.cookd;
            },
            data_out: function (paramd) {
                self._data_out(paramd);
            },
        }, self.connectd
    );

    self._setup_read();
    self.pull();
};

KNXBridge.prototype._data_in = function (paramd) {
    var self = this;

    if (self.initd.raw) {
        paramd.cookd = _.d.clone.deep(paramd.rawd);
    } else {
        _.mapObject(paramd.rawd, function (value, knx_ga) {
            // it's OK - data can come that we don't know about
            var coded = self.knx_readd[knx_ga];
            if (!coded) {
                return;
            }

            paramd.cookd[coded.code] = value;
        });
    }
};

KNXBridge.prototype._data_out = function (paramd) {
    var self = this;

    if (self.initd.raw) {
        paramd.rawd = _.d.clone.deep(paramd.cookd);
    } else {
        _.mapObject(paramd.cookd, function (value, code) {
            var coded = self.knx_writed[code];
            if (!coded) {
                return;
            }

            paramd.rawd[coded.write] = value;
        });
    }
};

KNXBridge.prototype._setup_read = function () {
    var self = this;

    var _on_change = function (knx_ga, data, datagram) {
        if (!self.knx_readd[knx_ga]) {
            return;
        }

        logger.info({
            method: "_setup_read/on(status)",
            knx_ga: knx_ga,
            data: data,
            datagram: datagram,
        }, "got 'status'/'event'");

        var rawd = {};
        rawd[knx_ga] = data;
        var paramd = {
            rawd: rawd,
            cookd: {},
            scratchd: self.scratchd,
        };
        self.connectd.data_in(paramd);

        var cookd = self.connectd.post_in(paramd);
        if (cookd !== undefined) {
            paramd.cookd = cookd;
        }

        paramd.cookd['@__validate'] = true;
        self.pulled(paramd.cookd);
    };

    self.native.on('status', function (knx_ga, data, datagram) {
        _on_change(knx_ga, data, datagram);
    });
    self.native.on('event', function (knx_ga, data, datagram) {
        _on_change(knx_ga, data, datagram);
    });

    self.connectd.subscribes.map(function (knx_ga) {
        logger.info({
            method: "_setup_read",
            knx_ga: knx_ga,
        }, "subscribe to GA (connectd.subscribes)");
        self.native.RequestStatus(knx_ga);
    });

    _.mapObject(self.knx_readd, function (coded, knx_ga) {
        logger.info({
            method: "_setup_read",
            knx_ga: knx_ga,
        }, "subscribe to GA (knx_readd)");
        self.native.RequestStatus(knx_ga);
    });
};

KNXBridge.prototype._forget = function () {
    var self = this;
    if (!self.native) {
        return;
    }

    logger.info({
        method: "_forget"
    }, "called");

    self.native = null;
    self.pulled();
};

/**
 *  See {iotdb.bridge.Bridge#disconnect} for documentation.
 */
KNXBridge.prototype.disconnect = function () {
    var self = this;
    if (!self.native || !self.native) {
        return;
    }

    self._forget();
};

/* --- data --- */

/**
 *  See {iotdb.bridge.Bridge#push} for documentation.
 */
KNXBridge.prototype.push = function (pushd, done) {
    var self = this;
    if (!self.native) {
        done(new Error("not connected"));
        return;
    }

    self._validate_push(pushd);

    logger.info({
        method: "push",
        pushd: pushd
    }, "push");

    var paramd = {
        rawd: {},
        cookd: pushd,
        scratchd: self.scratchd,
    };

    var cookd = self.connectd.pre_out(paramd);
    if (cookd !== undefined) {
        paramd.cookd = cookd;
    }

    self.connectd.data_out(paramd);

    _.mapObject(paramd.rawd, function (value, key) {
        self._send(key, value);
    });

    done(); // XXX - this needs to be counted per key
};

KNXBridge.prototype._send = function (key, value) {
    var self = this;

    var qitem = {
        run: function () {
            logger.info({
                method: "_send",
                key: key,
                value: value,
            }, "send");

            if (self.native) {
                self.native.Action(key, value);
            }
            self.queue.finished(qitem);
        },
        coda: function () {
            // done();
        },
    };
    self.queue.add(qitem);
};

/**
 *  See {iotdb.bridge.Bridge#pull} for documentation.
 */
KNXBridge.prototype.pull = function () {
    var self = this;
    if (!self.native) {
        return;
    }
};

/* --- state --- */

/**
 *  See {iotdb.bridge.Bridge#meta} for documentation.
 */
KNXBridge.prototype.meta = function () {
    var self = this;
    if (!self.native) {
        return;
    }

    return {
        "iot:thing-id": _.id.thing_urn.unique("KNX", self.initd.uuid, self.initd.number),
        "iot:device-id": _.id.thing_urn.unique("KNX", self.initd.uuid),
        "schema:name": self.native.name || "KNX",

        // "iot:thing-number": self.initd.number,
        // "schema:manufacturer": "",
        // "schema:model": "",
    };
};

/**
 *  See {iotdb.bridge.Bridge#reachable} for documentation.
 */
KNXBridge.prototype.reachable = function () {
    return this.native !== null;
};

/**
 *  See {iotdb.bridge.Bridge#configure} for documentation.
 */
KNXBridge.prototype.configure = function (app) {};

/* -- internals -- */
var __knxd = {};
var __pendingsd = {};

/**
 *  This returns a connection object per ( host, port, tunnel_host, tunnel_port )
 *  tuple, ensuring the correct connection object exists and is connected.
 *  It calls back with the connection object
 *
 *  The code is complicated because we have to keep callbacks stored
 *  in '__pendingsd' until the connection is actually made
 */
KNXBridge.prototype._knx = function (callback) {
    var self = this;

    var key = [self.initd.host, "" + self.initd.port, self.initd.tunnel_host, "" + self.initd.tunnel_port].join("@@");

    var knx = __knxd[key];
    if (knx === undefined) {
        var connect = false;

        var pendings = __pendingsd[key];
        if (pendings === undefined) {
            pendings = [];
            __pendingsd[key] = pendings;
            connect = true;
        }

        pendings.push(callback);

        if (connect) {
            logger.info({
                method: "_knx",
                npending: pendings.length,
                host: self.initd.host,
                port: self.initd.port,
                tunnel_host: self.initd.tunnel_host,
                tunnel_port: self.initd.tunnel_port
            }, "connecting to KNX");

            if (self.initd.tunnel_host) {
                knx = new knx_js.KnxConnectionTunneling(
                    self.initd.host, self.initd.port,
                    self.initd.tunnel_host, self.initd.tunnel_port
                );
            } else {
                knx = new knx_js.KnxConnection(
                    self.initd.host, self.initd.port
                );
            }

            // probably should be error checking here
            knx.Connect(function () {
                logger.info({
                    method: "_knx",
                    npending: pendings.length,
                    host: self.initd.host,
                    port: self.initd.port,
                    tunnel_host: self.initd.tunnel_host,
                    tunnel_port: self.initd.tunnel_port,
                    connected: knx.connected
                }, "connected to KNX! (?)");

                if (knx.connected) {
                    __knxd[key] = knx;

                    pendings.map(function (pending) {
                        pending(null, knx);
                    });
                } else {
                    var error = new Error("could not establish a connection");
                    pendings.map(function (pending) {
                        pending(error, null);
                    });
                }

                delete __pendingsd[key];
            });
        }
    } else {
        callback(null, knx);
    }
};

/*
 *  API
 */
exports.Bridge = KNXBridge;
<|endoftext|>