<commit_before>import templateUrl from './details.html'
// import { Promise } from 'q'

/** @ngInject */
export function CatalogsDetailsState (routerHelper) {
  routerHelper.configureStates(getStates())
}

function getStates () {
  return {
    'catalogs.details': {
      url: '/:serviceTemplateId',
      templateUrl,
      controller: Controller,
      controllerAs: 'vm',
      title: __('Service Template Details')
    },
    'catalogs.duplicate': {
      url: '/duplicate/:serviceRequestId',
      templateUrl,
      controller: Controller,
      controllerAs: 'vm',
      title: __('Duplicate Service')
    }
  }
}

/** @ngInject */
function Controller ($stateParams, CollectionsApi, EventNotifications, ShoppingCart, DialogFieldRefresh, lodash) {
  const vm = this

  let dialogs = {}
  let serviceTemplate = {}
  let serviceRequest = {}

  function init () {
    vm.loading = true
    vm.addToCart = addToCart
    vm.cartAllowed = ShoppingCart.allowed
    vm.addToCartEnabled = false
    vm.alreadyInCart = alreadyInCart
    vm.addToCartDisabled = addToCartDisabled
    vm.refreshField = refreshField
    vm.setDialogData = setDialogData
    vm.dialogData = {}

    const serviceRequestPromise = () => {
      return new Promise((resolve, reject) => {
        if ($stateParams.serviceRequestId) {
          CollectionsApi.get('requests', $stateParams.serviceRequestId, {}).then((data) => { resolve(data) })
        } else {
          resolve(false)
        }
      })
    }
    serviceRequestPromise().then((resolvedServiceRequest) => {
      serviceRequest = resolvedServiceRequest

      const dialogRequest = new Promise((resolve, reject) => {
        const options = { expand: 'resources', attributes: 'content' }
        let serviceTemplateId = $stateParams.serviceTemplateId
        if (!serviceTemplateId) {
          serviceTemplateId = serviceRequest.source_id
        }
        CollectionsApi.query('service_templates/' + serviceTemplateId + '/service_dialogs', options).then((resolvedDialogs) => {
          dialogs = resolvedDialogs
          resolve(resolvedDialogs)
        })
      })

      const serviceTemplateRequest = new Promise((resolve, reject) => {
        let serviceTemplateId = $stateParams.serviceTemplateId
        if (!serviceTemplateId) {
          serviceTemplateId = serviceRequest.source_id
        }
        var options = { attributes: ['picture', 'picture.image_href'] }
        CollectionsApi.get('service_templates', serviceTemplateId, options).then((data) => {
          resolve(data)
        })
      })
      const allPromises = [dialogRequest, serviceTemplateRequest]
      Promise.all(allPromises).then((data) => {
        const SERVICE_TEMPLATE_RESPONSE = 1
        const DIALOGS_RESPONSE = 0
        dialogs = data[DIALOGS_RESPONSE]
        vm.serviceTemplate = data[SERVICE_TEMPLATE_RESPONSE]
        vm.parsedDialogs = []

        if (dialogs.subcount > 0) {
          if (serviceRequest) {
            const existingDialogValues = serviceRequest.options.dialog
            dialogs.resources[0].content.forEach((dialog) => {
              vm.parsedDialogs.push(DialogFieldRefresh.setFieldValueDefaults(dialog, existingDialogValues))
            })
          } else {
            vm.parsedDialogs = dialogs.resources[0].content
          }
        }

        vm.dialogUrl = `service_catalogs/${vm.serviceTemplate.service_template_catalog_id}/service_templates`
        vm.loading = false
      })
    })
  }

  init()

  /**
 * This function triggers a refresh of a single dialog field
 * @function refreshField
 * @param  {object} field
 * @returns {Promise}
 */
  function refreshField (field) {
    return DialogFieldRefresh.refreshDialogField(vm.dialogData, [field.name], vm.dialogUrl, vm.serviceTemplate.id)
  }
  /**
   * Stores resulting data output from a dialog
   * @function setDialogData
   * @param  {object} data
  */
  function setDialogData (data) {
    vm.addToCartEnabled = data.validations.isValid
    vm.dialogData = data.data
  }
  /**
   * Determines whether a user can add to cart
   * @function addToCartDisabled
   * @returns {boolean}
  */
  function addToCartDisabled () {
    return (!vm.cartAllowed() || !vm.addToCartEnabled)
  }

  /**
   * Prepares data from dialog to be submitted
   * @function dataForSubmit
   * @param {string} href
   * @returns {object}
  */
  function dataForSubmit (href) {
    var dialogFieldData = {}
    dialogFieldData[href] = '/api/service_templates/' + serviceTemplate.id

    return lodash.merge(vm.dialogData, dialogFieldData)
  }
  /**
   * Checks to see if a user is submitting a duplicate request
   * @function alreadyInCart
   * @returns {boolean}
  */
  function alreadyInCart () {
    return ShoppingCart.isDuplicate(dataForSubmit('service_template_href'))
  }

  /**
   * Adds service to cart
   * @function addToCart
  */
  function addToCart () {
    if (!ShoppingCart.allowed()) {
      return
    }

    var dialogFieldData = dataForSubmit('service_template_href')

    vm.addingToCart = true

    return ShoppingCart.add({
      description: vm.serviceTemplate.name,
      data: dialogFieldData
    })
      .then(addSuccess, addFailure)
      .then(function () {
        vm.addingToCart = false
      })

    function addSuccess (result) {
      if (result.duplicate) {
        EventNotifications.success(__("Item added to shopping cart, but it's a duplicate of an existing item"))
      } else {
        EventNotifications.success(__('Item added to shopping cart'))
      }
    }

    function addFailure (result) {
      var errors = result.split(',')
      for (var i = 0; i < errors.length; ++i) {
        EventNotifications.error(__('There was an error adding to shopping cart: ') + errors[i])
      }
    }
  }
}
<commit_msg>Removed empty line<commit_after>import templateUrl from './details.html'
// import { Promise } from 'q'

/** @ngInject */
export function CatalogsDetailsState (routerHelper) {
  routerHelper.configureStates(getStates())
}

function getStates () {
  return {
    'catalogs.details': {
      url: '/:serviceTemplateId',
      templateUrl,
      controller: Controller,
      controllerAs: 'vm',
      title: __('Service Template Details')
    },
    'catalogs.duplicate': {
      url: '/duplicate/:serviceRequestId',
      templateUrl,
      controller: Controller,
      controllerAs: 'vm',
      title: __('Duplicate Service')
    }
  }
}

/** @ngInject */
function Controller ($stateParams, CollectionsApi, EventNotifications, ShoppingCart, DialogFieldRefresh, lodash) {
  const vm = this

  let dialogs = {}
  let serviceTemplate = {}
  let serviceRequest = {}

  function init () {
    vm.loading = true
    vm.addToCart = addToCart
    vm.cartAllowed = ShoppingCart.allowed
    vm.addToCartEnabled = false
    vm.alreadyInCart = alreadyInCart
    vm.addToCartDisabled = addToCartDisabled
    vm.refreshField = refreshField
    vm.setDialogData = setDialogData
    vm.dialogData = {}

    const serviceRequestPromise = () => {
      return new Promise((resolve, reject) => {
        if ($stateParams.serviceRequestId) {
          CollectionsApi.get('requests', $stateParams.serviceRequestId, {}).then((data) => { resolve(data) })
        } else {
          resolve(false)
        }
      })
    }
    serviceRequestPromise().then((resolvedServiceRequest) => {
      serviceRequest = resolvedServiceRequest

      const dialogRequest = new Promise((resolve, reject) => {
        const options = { expand: 'resources', attributes: 'content' }
        let serviceTemplateId = $stateParams.serviceTemplateId
        if (!serviceTemplateId) {
          serviceTemplateId = serviceRequest.source_id
        }
        CollectionsApi.query('service_templates/' + serviceTemplateId + '/service_dialogs', options).then((resolvedDialogs) => {
          dialogs = resolvedDialogs
          resolve(resolvedDialogs)
        })
      })

      const serviceTemplateRequest = new Promise((resolve, reject) => {
        let serviceTemplateId = $stateParams.serviceTemplateId
        if (!serviceTemplateId) {
          serviceTemplateId = serviceRequest.source_id
        }
        var options = { attributes: ['picture', 'picture.image_href'] }
        CollectionsApi.get('service_templates', serviceTemplateId, options).then((data) => {
          resolve(data)
        })
      })
      const allPromises = [dialogRequest, serviceTemplateRequest]
      Promise.all(allPromises).then((data) => {
        const SERVICE_TEMPLATE_RESPONSE = 1
        const DIALOGS_RESPONSE = 0
        dialogs = data[DIALOGS_RESPONSE]
        vm.serviceTemplate = data[SERVICE_TEMPLATE_RESPONSE]
        vm.parsedDialogs = []

        if (dialogs.subcount > 0) {
          if (serviceRequest) {
            const existingDialogValues = serviceRequest.options.dialog
            dialogs.resources[0].content.forEach((dialog) => {
              vm.parsedDialogs.push(DialogFieldRefresh.setFieldValueDefaults(dialog, existingDialogValues))
            })
          } else {
            vm.parsedDialogs = dialogs.resources[0].content
          }
        }

        vm.dialogUrl = `service_catalogs/${vm.serviceTemplate.service_template_catalog_id}/service_templates`
        vm.loading = false
      })
    })
  }

  init()

  /**
 * This function triggers a refresh of a single dialog field
 * @function refreshField
 * @param  {object} field
 * @returns {Promise}
 */
  function refreshField (field) {
    return DialogFieldRefresh.refreshDialogField(vm.dialogData, [field.name], vm.dialogUrl, vm.serviceTemplate.id)
  }
  /**
   * Stores resulting data output from a dialog
   * @function setDialogData
   * @param  {object} data
  */
  function setDialogData (data) {
    vm.addToCartEnabled = data.validations.isValid
    vm.dialogData = data.data
  }
  /**
   * Determines whether a user can add to cart
   * @function addToCartDisabled
   * @returns {boolean}
  */
  function addToCartDisabled () {
    return (!vm.cartAllowed() || !vm.addToCartEnabled)
  }

  /**
   * Prepares data from dialog to be submitted
   * @function dataForSubmit
   * @param {string} href
   * @returns {object}
  */
  function dataForSubmit (href) {
    var dialogFieldData = {}
    dialogFieldData[href] = '/api/service_templates/' + serviceTemplate.id

    return lodash.merge(vm.dialogData, dialogFieldData)
  }
  /**
   * Checks to see if a user is submitting a duplicate request
   * @function alreadyInCart
   * @returns {boolean}
  */
  function alreadyInCart () {
    return ShoppingCart.isDuplicate(dataForSubmit('service_template_href'))
  }

  /**
   * Adds service to cart
   * @function addToCart
  */
  function addToCart () {
    if (!ShoppingCart.allowed()) {
      return
    }

    var dialogFieldData = dataForSubmit('service_template_href')

    vm.addingToCart = true

    return ShoppingCart.add({
      description: vm.serviceTemplate.name,
      data: dialogFieldData
    })
      .then(addSuccess, addFailure)
      .then(function () {
        vm.addingToCart = false
      })

    function addSuccess (result) {
      if (result.duplicate) {
        EventNotifications.success(__("Item added to shopping cart, but it's a duplicate of an existing item"))
      } else {
        EventNotifications.success(__('Item added to shopping cart'))
      }
    }

    function addFailure (result) {
      var errors = result.split(',')
      for (var i = 0; i < errors.length; ++i) {
        EventNotifications.error(__('There was an error adding to shopping cart: ') + errors[i])
      }
    }
  }
}
<|endoftext|>


<commit_before>rekonApp = Sammy('#container', function(){

  $container = $(this.$element);

  header = function(header, url) {
    $container.find('h1').html(header + " –  " + url + "");
  };

  breadcrumb = function(crumb) {
    $('
').append(crumb).appendTo('ul#footer-navi');
  };

  searchable = function(selector) {
    $('#row_search').quicksearch(selector, {selector: 'th'});
  };

  this.use('Template');
  this.use('NestedParams');

  this.before(function(){
    $('#main').empty();
    $('#content h1').html('');
    $('#footer-navi li:not(.perm)').remove();
  });

  this.get('#/buckets', function(context){
    header('Buckets', Rekon.baseUrl());

    context.render('buckets.html.template').appendTo('#main');

    Rekon.client.buckets(function(buckets) {
      bucketRows = buckets.map(function(bucket){ return {bucket: bucket};});
      context.renderEach('bucket-row.html.template', bucketRows).replace('#buckets tbody').then(
        function(){ searchable('#buckets table tbody tr'); }
      );
    });
  });

  this.get('#/buckets/:bucket', function(context){
    var name   = this.params['bucket'];
    var bucket = new RiakBucket(name, Rekon.client);

    header('Bucket', Rekon.riakUrl(name));
    breadcrumb($('').attr('href', '#/bucket-props/' + name).text('Props'));
    breadcrumb($('').attr('href', Rekon.bucketUrl(name) + '/props').attr('target', '_blank').text('Props Riak').addClass('action'));

    context.render('bucket.html.template', {bucket: name}).appendTo('#main');

    bucket.keys(function(keys) {
      if (keys.length > 0) {
        keyRows = keys.map(function(key) { return {bucket:name, key:key}; });
        context.renderEach('key-row.html.template', keyRows).replace('#keys tbody').then(
          function(){ searchable('#bucket table tbody tr'); }
        );
      } else {
        context.render('bucket-empty.html.template').replace('#keys tbody');
      }
    });
  });

  this.get('#/bucket-props/:bucket', function(context) {
    var name   = this.params['bucket'];
    var bucket = new RiakBucket(name, Rekon.client);

    header('Bucket Properties', Rekon.bucketUrl(name));
    breadcrumb($('').attr('href', '#/buckets/' + name).text('Keys'));
    breadcrumb($('').attr('href', Rekon.riakUrl(name)).attr('target', '_blank').text('Riak').addClass('action'));

    bucket.getProps(function(props) {
      var pre_commit = [], post_commit = [];
      for (var i = 0; i < props.precommit.length; i++) {
        hook = props.precommit[i].mod + "/" + props.precommit[i].fun;
        pre_commit.push(hook);
      }
      for (var i = 0; i < props.postcommit.length; i++) {
        hook = props.postcommit[i].mod + "/" + props.postcommit[i].fun;
        post_commit.push(hook);
      }
      if(pre_commit.length == 0) {pre_commit = "None";}
      if(post_commit.length == 0) {post_commit = "None";}
      context.render('bucket-hooks.html.template', {pre_commit: pre_commit, post_commit: post_commit},
        function(){
          context.render('bucket-props.html.template', {props: props}).appendTo('#main').then(function(){
            var $selects, $select, i;
            $selects = $('select[data-select-value]');
            /* select the nvalue */
            $('select#n_val').val($('select#n_val').attr('data-select-value'));
            /* bind the limit based off of the n_val */
            Rekon.capControlsSelector();
            /* reselect cap control vals based off of nval */
            for(i=0; i<$selects.length;i++) {
              $select = $($selects[i]);
              $select.val($select.attr('data-select-value'));
            }
            $('select#n_val').change(Rekon.capControlsSelector);
          });
        }
      ).appendTo('#main');
    });
  });

  this.get('#/buckets/:bucket/keys/:key', function(context) {
    var name   = this.params['bucket'];
    var key    = this.params['key'];
    var bucket = new RiakBucket(name, Rekon.client);

    header('Key', Rekon.riakUrl(name + '/' + key));
    breadcrumb($('').attr('href', '#/buckets/' + name).text('Keys'));
    breadcrumb($('').attr('href', '#/buckets/' + name + '/' + key + '/edit').text('Edit').addClass('action'));
    breadcrumb($('').attr('href', Rekon.riakUrl(name + '/' + key)).attr('target', '_blank').
      text('Riak').addClass('action'));

    context.render('key.html.template').appendTo('#main');

    bucket.get(key, function(status, object) {
      context.render('key-content-type.html.template', {object: object}, function(){
        context.render('key-meta.html.template', {object: object}).appendTo('#key tbody');
      }).appendTo('#key tbody');

      switch(object.contentType) {
      case 'image/png':
      case 'image/jpeg':
      case 'image/jpg':
      case 'image/gif':
        context.render('value-image.html.template', {bucket: name, key: key}).appendTo('#value');
        return;
      case 'application/json':
        value = JSON.stringify(object.body, null, 4);
        break;
      default:
        value = object.body;
        break;
      }
      context.render('value-pre.html.template', {value: value}).appendTo('#value');
    });
  });

  this.get('#/buckets/:bucket/keys/:key/edit', function(context) {
    var name   = this.params['bucket'];
    var key    = this.params['key'];
    var bucket = new RiakBucket(name, Rekon.client);
    var app    = this;

    header('Edit Key', Rekon.riakUrl(name + '/' + key));
    breadcrumb($('').attr('href', '#/buckets/' + name).text('Keys'));
    breadcrumb($('').attr('href', '#/buckets/' + name + '/' + key).text('View').addClass('action'));
    breadcrumb($('').attr('href', Rekon.riakUrl(name + '/' + key)).attr('target', '_blank').
      text('Riak').addClass('action'));

    context.render('edit-key.html.template', {bucket: name, key: key}).appendTo('#main');

    bucket.get(key, function(status, object) {
      switch(object.contentType) {
      case 'image/png':
      case 'image/jpeg':
      case 'image/jpg':
      case 'image/gif':
        alert('Image editing is not supported currently.');
        app.redirect('#/buckets/' + name + '/' + key);
        return;
      case 'application/json':
        value = JSON.stringify(object.body, null, 4);
        break;
      default:
        value = object.body;
        break;
      }
      context.render('edit-key-content-type.html.template', {object: object}, function(html){
        context.render('key-meta.html.template', {object: object}).appendTo('#edit-key tbody');
      }).appendTo('#edit-key tbody').then(function(html){
        $select = $('select[name=content-type]');
        $select.val(object.contentType);
      });
      context.render('edit-value.html.template', {value: value}).appendTo('#edit-value');
    });
  });

  this.get('#/stats', function(context){
    header('Node Stats', document.location.origin + "/stats");

    $.getJSON('/stats', function(data) {
      context.render('stats.html.template', {stats:data}).appendTo('#main').then(
        function(){ searchable('#stats tbody tr'); }
      );
    });
  });

  this.post('#/buckets', function(context) {
    var name = this.params['bucket'];
    this.redirect('#/buckets/' + name);
  });

  this.post('#/buckets/:bucket', function(context){
    var app    = this;
    var name   = this.params['bucket'];
    var key    = this.params['key'] === '' ? undefined : this.params['key'];
    var object = new RiakObject(name, key, Rekon.client, '{}', 'application/json');
    object.store(function(status, rObject){
      switch(status) {
      case 'siblings':
        alert("Oh noes! Siblings have been born and Rekon doesn't handle that yet.");
        break;
      case 'failure':
        alert("There was an error creating a new Riak object.");
        break;
      case 'ok':
      default:
        console.log(rObject);
        app.redirect('#/buckets/' + name + '/' + rObject.key);
        break;
      }
    });
  });

  this.post('#/bucket-props/:bucket', function(context) {
    var app      = this;
    var name     = this.params['bucket'];
    var bucket   = new RiakBucket(name, Rekon.client);
    var props    = Rekon.typecastBucketProps(this.params['props']);

    bucket.props = props;
    bucket.store(function(){
      app.redirect("#/bucket-props/" + name);
    });
  });

  this.post('#/buckets/:bucket/:key', function(context){
    var app    = this;
    var name   = this.params['bucket'];
    var key    = this.params['key'];
    var bucket = new RiakBucket(name, Rekon.client);

    bucket.get(key, function(status, object) {
      object.contentType = app.params['content-type'];
      object.body        = app.params['value'];

      if (object.contentType == 'application/json') {
        object.body = JSON.parse(object.body);
      }

      object.store(function(status, rObject) {
        switch(status) {
        case 'siblings':
          alert("Oh noes! Siblings have been born and Rekon doesn't handle that yet.");
          break;
        case 'failure':
          alert("There was an error saving to Riak.");
          break;
        case 'ok':
        default:
          app.redirect('#/buckets/' + name + '/' + key);
          break;
        }
      });
    });
  });

  this.get('#/stats', function(context){
    header('Node Stats', document.location.origin + "/stats");

    $.getJSON('/stats', function(data) {
      context.render('stats.html.template', {stats:data}).appendTo('#main').then(
        function(){ searchable('#stats tbody tr'); }
      );
    });
  });

});

Rekon = {
  client : new RiakClient(),

  locationUrl : function() {
    return document.location.protocol + '//' + document.location.host;
  },

  baseUrl : function() {
    return this.locationUrl() + this.client.baseUrl;
  },

  bucketUrl : function(bucket_name) {
    return this.locationUrl() + this.client.baseUrl + '/' + bucket_name;
  },

  riakUrl : function(append) {
    if (append === undefined) {
      append = "";
    }
    // morph old style into new
    parts = append.split('/');
    if (parts.length > 1) {
      append = "/" + parts[0] + "/keys/" + parts[1];
    }
    else { // some calls just have the bucket
      append = "/" + parts[0] + "/keys";
    }
    return this.baseUrl() + append;
  },

  typecastBucketProps : function(props) {
    keys = ['w', 'r', 'dw', 'rw', 'n_val', 'young_vclock', 'old_vclock', 'small_vclock', 'big_vclock'];
    for(var i=0; i<keys.length; i++) {
      key = keys[i];
      val = parseInt(props[key], 10);
      if (val) {
        props[key] = parseInt(props[key], 10);
      }
    }
    props.allow_mult      = !!props.allow_mult;
    props.last_write_wins = !!props.last_write_wins;

    return props;
  },

  capControlsSelector : function() {
    var nVal = parseInt($('select#n_val').val(), 10);
    $('.cap-control').each(function(i, select) {
      var $select = $(select);
      var value   = parseInt($select.val(), 10);
      var endVal  = parseInt($select.find('option:last').val(), 10);
      if (isNaN(endVal)) { endVal = 0; }

      /* figure out if we need to append or trim */
      if (endVal > nVal) {
        $select.find('option').each(function(j, option) {
          var $option = $(option);
          if (parseInt($option.val(), 10) > nVal) {
            $option.remove();
          }
        });
        if (value) {
          $select.val($select.find('option:last').val());
        }
      }
      else if (endVal < nVal) {
        while(endVal < nVal) {
          endVal++;
          $('<option>').val(endVal).html(endVal).appendTo($select);
        }
      }
    });
  }

};

$('#keys a.delete').live('click', function(e){
  var link = this;
  e.preventDefault();
  if(!confirm("Are you sure you want to delete:\n" + $(link).attr('href'))) { return; }

  $.ajax({
    type: 'DELETE',
    url: $(link).attr('href')
  }).success(function(){
    $(link).closest('tr').remove();
  }).error(function(){
    alert('There was an error deleting this object from Riak.');
  });
});

var filterInteger = function(){
  var value = parseInt($(this).val(), 10);
  if (isNaN(value)) {
    value = 1;
  }
  $(this).val(value);
};

$("input[data-filter=integer]").live('blur', filterInteger);

/*
* Bootstrap the application
*/
jQuery(function($) {
  rekonApp.run('#/buckets');

});
<commit_msg>fix the edit breadcrumb, issue #16<commit_after>rekonApp = Sammy('#container', function(){

  $container = $(this.$element);

  header = function(header, url) {
    $container.find('h1').html(header + " –  " + url + "");
  };

  breadcrumb = function(crumb) {
    $('
').append(crumb).appendTo('ul#footer-navi');
  };

  searchable = function(selector) {
    $('#row_search').quicksearch(selector, {selector: 'th'});
  };

  this.use('Template');
  this.use('NestedParams');

  this.before(function(){
    $('#main').empty();
    $('#content h1').html('');
    $('#footer-navi li:not(.perm)').remove();
  });

  this.get('#/buckets', function(context){
    header('Buckets', Rekon.baseUrl());

    context.render('buckets.html.template').appendTo('#main');

    Rekon.client.buckets(function(buckets) {
      bucketRows = buckets.map(function(bucket){ return {bucket: bucket};});
      context.renderEach('bucket-row.html.template', bucketRows).replace('#buckets tbody').then(
        function(){ searchable('#buckets table tbody tr'); }
      );
    });
  });

  this.get('#/buckets/:bucket', function(context){
    var name   = this.params['bucket'];
    var bucket = new RiakBucket(name, Rekon.client);

    header('Bucket', Rekon.riakUrl(name));
    breadcrumb($('').attr('href', '#/bucket-props/' + name).text('Props'));
    breadcrumb($('').attr('href', Rekon.bucketUrl(name) + '/props').attr('target', '_blank').text('Props Riak').addClass('action'));

    context.render('bucket.html.template', {bucket: name}).appendTo('#main');

    bucket.keys(function(keys) {
      if (keys.length > 0) {
        keyRows = keys.map(function(key) { return {bucket:name, key:key}; });
        context.renderEach('key-row.html.template', keyRows).replace('#keys tbody').then(
          function(){ searchable('#bucket table tbody tr'); }
        );
      } else {
        context.render('bucket-empty.html.template').replace('#keys tbody');
      }
    });
  });

  this.get('#/bucket-props/:bucket', function(context) {
    var name   = this.params['bucket'];
    var bucket = new RiakBucket(name, Rekon.client);

    header('Bucket Properties', Rekon.bucketUrl(name));
    breadcrumb($('').attr('href', '#/buckets/' + name).text('Keys'));
    breadcrumb($('').attr('href', Rekon.riakUrl(name)).attr('target', '_blank').text('Riak').addClass('action'));

    bucket.getProps(function(props) {
      var pre_commit = [], post_commit = [];
      for (var i = 0; i < props.precommit.length; i++) {
        hook = props.precommit[i].mod + "/" + props.precommit[i].fun;
        pre_commit.push(hook);
      }
      for (var i = 0; i < props.postcommit.length; i++) {
        hook = props.postcommit[i].mod + "/" + props.postcommit[i].fun;
        post_commit.push(hook);
      }
      if(pre_commit.length == 0) {pre_commit = "None";}
      if(post_commit.length == 0) {post_commit = "None";}
      context.render('bucket-hooks.html.template', {pre_commit: pre_commit, post_commit: post_commit},
        function(){
          context.render('bucket-props.html.template', {props: props}).appendTo('#main').then(function(){
            var $selects, $select, i;
            $selects = $('select[data-select-value]');
            /* select the nvalue */
            $('select#n_val').val($('select#n_val').attr('data-select-value'));
            /* bind the limit based off of the n_val */
            Rekon.capControlsSelector();
            /* reselect cap control vals based off of nval */
            for(i=0; i<$selects.length;i++) {
              $select = $($selects[i]);
              $select.val($select.attr('data-select-value'));
            }
            $('select#n_val').change(Rekon.capControlsSelector);
          });
        }
      ).appendTo('#main');
    });
  });

  this.get('#/buckets/:bucket/keys/:key', function(context) {
    var name   = this.params['bucket'];
    var key    = this.params['key'];
    var bucket = new RiakBucket(name, Rekon.client);

    header('Key', Rekon.riakUrl(name + '/' + key));
    breadcrumb($('').attr('href', '#/buckets/' + name).text('Keys'));
    breadcrumb($('').attr('href', '#/buckets/' + name + '/keys/' + key + '/edit').text('Edit').addClass('action'));
    breadcrumb($('').attr('href', Rekon.riakUrl(name + '/' + key)).attr('target', '_blank').
      text('Riak').addClass('action'));

    context.render('key.html.template').appendTo('#main');

    bucket.get(key, function(status, object) {
      context.render('key-content-type.html.template', {object: object}, function(){
        context.render('key-meta.html.template', {object: object}).appendTo('#key tbody');
      }).appendTo('#key tbody');

      switch(object.contentType) {
      case 'image/png':
      case 'image/jpeg':
      case 'image/jpg':
      case 'image/gif':
        context.render('value-image.html.template', {bucket: name, key: key}).appendTo('#value');
        return;
      case 'application/json':
        value = JSON.stringify(object.body, null, 4);
        break;
      default:
        value = object.body;
        break;
      }
      context.render('value-pre.html.template', {value: value}).appendTo('#value');
    });
  });

  this.get('#/buckets/:bucket/keys/:key/edit', function(context) {
    var name   = this.params['bucket'];
    var key    = this.params['key'];
    var bucket = new RiakBucket(name, Rekon.client);
    var app    = this;

    header('Edit Key', Rekon.riakUrl(name + '/' + key));
    breadcrumb($('').attr('href', '#/buckets/' + name).text('Keys'));
    breadcrumb($('').attr('href', '#/buckets/' + name + '/' + key).text('View').addClass('action'));
    breadcrumb($('').attr('href', Rekon.riakUrl(name + '/' + key)).attr('target', '_blank').
      text('Riak').addClass('action'));

    context.render('edit-key.html.template', {bucket: name, key: key}).appendTo('#main');

    bucket.get(key, function(status, object) {
      switch(object.contentType) {
      case 'image/png':
      case 'image/jpeg':
      case 'image/jpg':
      case 'image/gif':
        alert('Image editing is not supported currently.');
        app.redirect('#/buckets/' + name + '/' + key);
        return;
      case 'application/json':
        value = JSON.stringify(object.body, null, 4);
        break;
      default:
        value = object.body;
        break;
      }
      context.render('edit-key-content-type.html.template', {object: object}, function(html){
        context.render('key-meta.html.template', {object: object}).appendTo('#edit-key tbody');
      }).appendTo('#edit-key tbody').then(function(html){
        $select = $('select[name=content-type]');
        $select.val(object.contentType);
      });
      context.render('edit-value.html.template', {value: value}).appendTo('#edit-value');
    });
  });

  this.get('#/stats', function(context){
    header('Node Stats', document.location.origin + "/stats");

    $.getJSON('/stats', function(data) {
      context.render('stats.html.template', {stats:data}).appendTo('#main').then(
        function(){ searchable('#stats tbody tr'); }
      );
    });
  });

  this.post('#/buckets', function(context) {
    var name = this.params['bucket'];
    this.redirect('#/buckets/' + name);
  });

  this.post('#/buckets/:bucket', function(context){
    var app    = this;
    var name   = this.params['bucket'];
    var key    = this.params['key'] === '' ? undefined : this.params['key'];
    var object = new RiakObject(name, key, Rekon.client, '{}', 'application/json');
    object.store(function(status, rObject){
      switch(status) {
      case 'siblings':
        alert("Oh noes! Siblings have been born and Rekon doesn't handle that yet.");
        break;
      case 'failure':
        alert("There was an error creating a new Riak object.");
        break;
      case 'ok':
      default:
        console.log(rObject);
        app.redirect('#/buckets/' + name + '/' + rObject.key);
        break;
      }
    });
  });

  this.post('#/bucket-props/:bucket', function(context) {
    var app      = this;
    var name     = this.params['bucket'];
    var bucket   = new RiakBucket(name, Rekon.client);
    var props    = Rekon.typecastBucketProps(this.params['props']);

    bucket.props = props;
    bucket.store(function(){
      app.redirect("#/bucket-props/" + name);
    });
  });

  this.post('#/buckets/:bucket/:key', function(context){
    var app    = this;
    var name   = this.params['bucket'];
    var key    = this.params['key'];
    var bucket = new RiakBucket(name, Rekon.client);

    bucket.get(key, function(status, object) {
      object.contentType = app.params['content-type'];
      object.body        = app.params['value'];

      if (object.contentType == 'application/json') {
        object.body = JSON.parse(object.body);
      }

      object.store(function(status, rObject) {
        switch(status) {
        case 'siblings':
          alert("Oh noes! Siblings have been born and Rekon doesn't handle that yet.");
          break;
        case 'failure':
          alert("There was an error saving to Riak.");
          break;
        case 'ok':
        default:
          app.redirect('#/buckets/' + name + '/' + key);
          break;
        }
      });
    });
  });

  this.get('#/stats', function(context){
    header('Node Stats', document.location.origin + "/stats");

    $.getJSON('/stats', function(data) {
      context.render('stats.html.template', {stats:data}).appendTo('#main').then(
        function(){ searchable('#stats tbody tr'); }
      );
    });
  });

});

Rekon = {
  client : new RiakClient(),

  locationUrl : function() {
    return document.location.protocol + '//' + document.location.host;
  },

  baseUrl : function() {
    return this.locationUrl() + this.client.baseUrl;
  },

  bucketUrl : function(bucket_name) {
    return this.locationUrl() + this.client.baseUrl + '/' + bucket_name;
  },

  riakUrl : function(append) {
    if (append === undefined) {
      append = "";
    }
    // morph old style into new
    parts = append.split('/');
    if (parts.length > 1) {
      append = "/" + parts[0] + "/keys/" + parts[1];
    }
    else { // some calls just have the bucket
      append = "/" + parts[0] + "/keys";
    }
    return this.baseUrl() + append;
  },

  typecastBucketProps : function(props) {
    keys = ['w', 'r', 'dw', 'rw', 'n_val', 'young_vclock', 'old_vclock', 'small_vclock', 'big_vclock'];
    for(var i=0; i<keys.length; i++) {
      key = keys[i];
      val = parseInt(props[key], 10);
      if (val) {
        props[key] = parseInt(props[key], 10);
      }
    }
    props.allow_mult      = !!props.allow_mult;
    props.last_write_wins = !!props.last_write_wins;

    return props;
  },

  capControlsSelector : function() {
    var nVal = parseInt($('select#n_val').val(), 10);
    $('.cap-control').each(function(i, select) {
      var $select = $(select);
      var value   = parseInt($select.val(), 10);
      var endVal  = parseInt($select.find('option:last').val(), 10);
      if (isNaN(endVal)) { endVal = 0; }

      /* figure out if we need to append or trim */
      if (endVal > nVal) {
        $select.find('option').each(function(j, option) {
          var $option = $(option);
          if (parseInt($option.val(), 10) > nVal) {
            $option.remove();
          }
        });
        if (value) {
          $select.val($select.find('option:last').val());
        }
      }
      else if (endVal < nVal) {
        while(endVal < nVal) {
          endVal++;
          $('<option>').val(endVal).html(endVal).appendTo($select);
        }
      }
    });
  }

};

$('#keys a.delete').live('click', function(e){
  var link = this;
  e.preventDefault();
  if(!confirm("Are you sure you want to delete:\n" + $(link).attr('href'))) { return; }

  $.ajax({
    type: 'DELETE',
    url: $(link).attr('href')
  }).success(function(){
    $(link).closest('tr').remove();
  }).error(function(){
    alert('There was an error deleting this object from Riak.');
  });
});

var filterInteger = function(){
  var value = parseInt($(this).val(), 10);
  if (isNaN(value)) {
    value = 1;
  }
  $(this).val(value);
};

$("input[data-filter=integer]").live('blur', filterInteger);

/*
* Bootstrap the application
*/
jQuery(function($) {
  rekonApp.run('#/buckets');

});
<|endoftext|>


<commit_before>
requirejs.config({
    paths: {
        jquery: 'libs/jquery/jquery-1.11.1.min',
        jqBlockUI: 'libs/jquery/jquery.blockUI',
        jqCookie: 'libs/jquery/jquery.cookie',
        underscore: 'libs/lodash.underscore.min',
        Backbone: 'libs/backbone-min',
        Bootstrap: 'libs/bootstrap.min',
        Handlebars: 'libs/handlebars',
        DateFormat: 'libs/date.format',
        XPlans: 'libs/xplans',
        md5: 'libs/md5',
        DDLBuilder: 'libs/ddl_builder',
        utils: 'fiddle_backbone/utils'
    },
    shim: {
        DateFormat: {
            exports: 'dateFormat'
        },
        'XPlans/oracle/loadswf': {
            deps: ['XPlans/oracle/flashver'],
            exports: "loadswf"
        },
        'XPlans/mssql': {
            exports: "QP"
        },
        jqBlockUI: ['jquery'],
        jqCookie: ['jquery'],
        Bootstrap: ['jquery']
    }
});

require([
        'jquery',
        'underscore',
        'fiddle_backbone/app',
        'DDLBuilder/ddl_builder',

        'Bootstrap',
        'jqBlockUI',
        'jqCookie',

        'utils/handlebarsHelpers/divider_display',
        'utils/handlebarsHelpers/each_simple_value_with_index',
        'utils/handlebarsHelpers/each_with_index',
        'utils/handlebarsHelpers/result_display_padded',
        'utils/handlebarsHelpers/result_display',
        'utils/handlebarsHelpers/code_format',
        'utils/handlebarsHelpers/add'
    ],
    function($, _, App, ddl_builder) {

    $.blockUI.defaults.overlayCSS.cursor = 'auto';
    $.blockUI.defaults.css.cursor = 'auto';

    fiddleBackbone = App.initialize();

    // Now follows miscellaneous UI event bindings

    /* TEXT TO DDL */

    $("#textToDDLModal .btn").click(function (e){
        e.preventDefault();

        var builder = new ddl_builder({
                tableName: $("#tableName").val()
            })
            .setupForDBType(fiddleBackbone.dbTypes.getSelectedType().get("simple_name"), fiddleBackbone.schemaDef.get('statement_separator'));

        var ddl = builder.parse($("#raw").val());

        $("#parseResults").text(ddl);

        if ($(this).attr('id') == 'appendDDL')
        {
            fiddleBackbone.schemaDef.set("ddl", fiddleBackbone.schemaDef.get("ddl") + "\n\n" + ddl);
            fiddleBackbone.schemaDef.trigger("reloaded");
            $('#textToDDLModal').modal('hide');
        }
    });

    /* FULLSCREEN EDITS */

    function toggleFullscreenNav(option)
    {

        if ($("#exit_fullscreen").css('display') == "none")
        {
            $("body").css("overflow-y", "hidden");
            $(".navbar-fixed-top").css("position", "fixed").css("margin", 0);

            $("#exit_fullscreen").css('display', 'block');
            $("#exit_fullscreen span").text("Exit Fullscreen " + option);
            $(".nav-collapse, .btn-navbar, #db_type_label_collapsed .navbar-text").css('display', 'none');
        }
        else
        {
            $("body").css("overflow-y", "auto");
            $("body").css("height", "100%");
            $(".navbar-fixed-top").css("position", "").css("margin", "");

            $("#exit_fullscreen").css('display', 'none');
            $(".nav-collapse, .btn-navbar, #db_type_label_collapsed .navbar-text").css('display', '');
        }

    }

    $("#exit_fullscreen").on('click', function (e) {
        e.preventDefault();

        fiddleBackbone.schemaDefView.editor.setFullscreen(false);
        fiddleBackbone.queryView.editor.setFullscreen(false);

        toggleFullscreenNav('');
        resizeLayout();
    });

    $("#schemaFullscreen").on('click', function (e) {
        e.preventDefault();

        fiddleBackbone.schemaDefView.editor.setFullscreen(true);

        toggleFullscreenNav('Schema Editor');
    });

    $("#queryFullscreen").on('click', function (e) {
        e.preventDefault();

        fiddleBackbone.queryView.editor.setFullscreen(true);

        toggleFullscreenNav('Query Editor');
    });

    /* SCHEMA BROWSER */

    $("#schemaBrowser").on('click', function (e) {
        e.preventDefault();
        if (!$(this).attr('disabled')) {
            $('#fiddleFormDDL .CodeMirror, .ddl_actions').css('display', 'none');
            $('#browser, .browser_actions').css('display', 'block');
        }
    });

    $("#browser").on('click', '.tables a', function (e) {
        e.preventDefault();
        $('i', this).toggleClass("icon-minus icon-plus");
        $(this).siblings('.columns').toggle();
    });

    $("#ddlEdit").on('click', function (e) {
        e.preventDefault();
        $('#fiddleFormDDL .CodeMirror, .ddl_actions').css('display', 'block');
        $('#browser, .browser_actions').css('display', 'none');

    })

    /* RESIZING UI*/
    function resizeLayout(){

        var wheight = $(window).height() - 165;
        if (wheight > 400) {
            var container_width = $("#schema-output").width();

            $('#schema-output').height((wheight - 10) * 0.7);
            $('#output').css("min-height", ((wheight - 10) * 0.3) + "px");

            if (!fiddleBackbone.schemaDefView.editor.isFullscreen()) {
                $('#fiddleFormDDL .CodeMirror-scroll').css('height', ($('#fiddleFormDDL').height() - (5 + $('#fiddleFormDDL .action_buttons').height())) + "px");
                $('#schema_ddl').css('height', ($('#fiddleFormDDL').height() - (15 + $('#fiddleFormDDL .action_buttons').height())) + "px");
                $('#fiddleFormDDL .CodeMirror-scroll .CodeMirror-gutter').height($('#fiddleFormDDL .CodeMirror-scroll').height() - 2);
            }
            else {
                $('#fiddleFormDDL .CodeMirror-scroll, #schema_ddl').css('height', $(window).height() + "px");
                $('#fiddleFormDDL .CodeMirror-scroll .CodeMirror-gutter').height('height', $(window).height() + "px");

            }

            // textarea sql
            if (!fiddleBackbone.queryView.editor.isFullscreen()) {
                $('#fiddleFormSQL .CodeMirror-scroll').css('height', ($('#fiddleFormSQL').height() - (5 + $('#fiddleFormSQL .action_buttons').height())) + "px");
                $('#sql').css('height', ($('#fiddleFormSQL').height() - (15 + $('#fiddleFormSQL .action_buttons').height())) + "px");
                $('#fiddleFormSQL .CodeMirror-scroll .CodeMirror-gutter').height($('#fiddleFormSQL .CodeMirror-scroll').height() - 2);
            }
            else {

                $('#fiddleFormSQL .CodeMirror-scroll, #sql').css('height', $(window).height() + "px");
                $('#fiddleFormSQL .CodeMirror-scroll .CodeMirror-gutter').css('height', $(window).height() + "px");

            }

    //        $('#sql').width($('#fiddleFormSQL').width() - 10);
    //        $('#schema_ddl').width($('#fiddleFormDDL').width() - 10);

            $('#browser').height($('#fiddleFormDDL .CodeMirror-scroll').height());

            var adjustBlockMsg = function (blockedObj) {
                var msgSize =
                    {
                        "height": $(".blockMsg", blockedObj).height(),
                        "width": $(".blockMsg", blockedObj).width()
                    };
                var objSize =
                    {
                        "height": $(blockedObj).height(),
                        "width": $(blockedObj).width()
                    };

                $(".blockMsg", blockedObj)
                    .css("top", (objSize.height-msgSize.height)/2)
                    .css("left", (objSize.width-msgSize.width)/2);

            }

            adjustBlockMsg($("div.sql.panel"));
            adjustBlockMsg($("#output"));

            fiddleBackbone.schemaDefView.refresh();
            fiddleBackbone.queryView.refresh();
        }
    }

    $(window).bind('resize', resizeLayout);
    setTimeout(resizeLayout, 1);

    /* COLLAPSING NAV (for responsive UI) */

    $(".nav").on('click', 'a', function (e) {

        if ($(this).parent('li').attr('id') !== 'db_type_id' &&
            $(this).parent('li').attr('id') !== 'userOptions') {

            $(".nav-collapse.in").collapse('hide');

        } else {
            $(this).parents('div.nav-collapse.in').css('height', 'auto');
        }
    });

});
<commit_msg>Adjusting references to new lodash filename<commit_after>
requirejs.config({
    paths: {
        jquery: 'libs/jquery/jquery-1.11.1.min',
        jqBlockUI: 'libs/jquery/jquery.blockUI',
        jqCookie: 'libs/jquery/jquery.cookie',
        underscore: 'libs/lodash.min',
        Backbone: 'libs/backbone-min',
        Bootstrap: 'libs/bootstrap.min',
        Handlebars: 'libs/handlebars',
        DateFormat: 'libs/date.format',
        XPlans: 'libs/xplans',
        md5: 'libs/md5',
        DDLBuilder: 'libs/ddl_builder',
        utils: 'fiddle_backbone/utils'
    },
    shim: {
        DateFormat: {
            exports: 'dateFormat'
        },
        'XPlans/oracle/loadswf': {
            deps: ['XPlans/oracle/flashver'],
            exports: "loadswf"
        },
        'XPlans/mssql': {
            exports: "QP"
        },
        jqBlockUI: ['jquery'],
        jqCookie: ['jquery'],
        Bootstrap: ['jquery']
    }
});

require([
        'jquery',
        'underscore',
        'fiddle_backbone/app',
        'DDLBuilder/ddl_builder',

        'Bootstrap',
        'jqBlockUI',
        'jqCookie',

        'utils/handlebarsHelpers/divider_display',
        'utils/handlebarsHelpers/each_simple_value_with_index',
        'utils/handlebarsHelpers/each_with_index',
        'utils/handlebarsHelpers/result_display_padded',
        'utils/handlebarsHelpers/result_display',
        'utils/handlebarsHelpers/code_format',
        'utils/handlebarsHelpers/add'
    ],
    function($, _, App, ddl_builder) {

    $.blockUI.defaults.overlayCSS.cursor = 'auto';
    $.blockUI.defaults.css.cursor = 'auto';

    fiddleBackbone = App.initialize();

    // Now follows miscellaneous UI event bindings

    /* TEXT TO DDL */

    $("#textToDDLModal .btn").click(function (e){
        e.preventDefault();

        var builder = new ddl_builder({
                tableName: $("#tableName").val()
            })
            .setupForDBType(fiddleBackbone.dbTypes.getSelectedType().get("simple_name"), fiddleBackbone.schemaDef.get('statement_separator'));

        var ddl = builder.parse($("#raw").val());

        $("#parseResults").text(ddl);

        if ($(this).attr('id') == 'appendDDL')
        {
            fiddleBackbone.schemaDef.set("ddl", fiddleBackbone.schemaDef.get("ddl") + "\n\n" + ddl);
            fiddleBackbone.schemaDef.trigger("reloaded");
            $('#textToDDLModal').modal('hide');
        }
    });

    /* FULLSCREEN EDITS */

    function toggleFullscreenNav(option)
    {

        if ($("#exit_fullscreen").css('display') == "none")
        {
            $("body").css("overflow-y", "hidden");
            $(".navbar-fixed-top").css("position", "fixed").css("margin", 0);

            $("#exit_fullscreen").css('display', 'block');
            $("#exit_fullscreen span").text("Exit Fullscreen " + option);
            $(".nav-collapse, .btn-navbar, #db_type_label_collapsed .navbar-text").css('display', 'none');
        }
        else
        {
            $("body").css("overflow-y", "auto");
            $("body").css("height", "100%");
            $(".navbar-fixed-top").css("position", "").css("margin", "");

            $("#exit_fullscreen").css('display', 'none');
            $(".nav-collapse, .btn-navbar, #db_type_label_collapsed .navbar-text").css('display', '');
        }

    }

    $("#exit_fullscreen").on('click', function (e) {
        e.preventDefault();

        fiddleBackbone.schemaDefView.editor.setFullscreen(false);
        fiddleBackbone.queryView.editor.setFullscreen(false);

        toggleFullscreenNav('');
        resizeLayout();
    });

    $("#schemaFullscreen").on('click', function (e) {
        e.preventDefault();

        fiddleBackbone.schemaDefView.editor.setFullscreen(true);

        toggleFullscreenNav('Schema Editor');
    });

    $("#queryFullscreen").on('click', function (e) {
        e.preventDefault();

        fiddleBackbone.queryView.editor.setFullscreen(true);

        toggleFullscreenNav('Query Editor');
    });

    /* SCHEMA BROWSER */

    $("#schemaBrowser").on('click', function (e) {
        e.preventDefault();
        if (!$(this).attr('disabled')) {
            $('#fiddleFormDDL .CodeMirror, .ddl_actions').css('display', 'none');
            $('#browser, .browser_actions').css('display', 'block');
        }
    });

    $("#browser").on('click', '.tables a', function (e) {
        e.preventDefault();
        $('i', this).toggleClass("icon-minus icon-plus");
        $(this).siblings('.columns').toggle();
    });

    $("#ddlEdit").on('click', function (e) {
        e.preventDefault();
        $('#fiddleFormDDL .CodeMirror, .ddl_actions').css('display', 'block');
        $('#browser, .browser_actions').css('display', 'none');

    })

    /* RESIZING UI*/
    function resizeLayout(){

        var wheight = $(window).height() - 165;
        if (wheight > 400) {
            var container_width = $("#schema-output").width();

            $('#schema-output').height((wheight - 10) * 0.7);
            $('#output').css("min-height", ((wheight - 10) * 0.3) + "px");

            if (!fiddleBackbone.schemaDefView.editor.isFullscreen()) {
                $('#fiddleFormDDL .CodeMirror-scroll').css('height', ($('#fiddleFormDDL').height() - (5 + $('#fiddleFormDDL .action_buttons').height())) + "px");
                $('#schema_ddl').css('height', ($('#fiddleFormDDL').height() - (15 + $('#fiddleFormDDL .action_buttons').height())) + "px");
                $('#fiddleFormDDL .CodeMirror-scroll .CodeMirror-gutter').height($('#fiddleFormDDL .CodeMirror-scroll').height() - 2);
            }
            else {
                $('#fiddleFormDDL .CodeMirror-scroll, #schema_ddl').css('height', $(window).height() + "px");
                $('#fiddleFormDDL .CodeMirror-scroll .CodeMirror-gutter').height('height', $(window).height() + "px");

            }

            // textarea sql
            if (!fiddleBackbone.queryView.editor.isFullscreen()) {
                $('#fiddleFormSQL .CodeMirror-scroll').css('height', ($('#fiddleFormSQL').height() - (5 + $('#fiddleFormSQL .action_buttons').height())) + "px");
                $('#sql').css('height', ($('#fiddleFormSQL').height() - (15 + $('#fiddleFormSQL .action_buttons').height())) + "px");
                $('#fiddleFormSQL .CodeMirror-scroll .CodeMirror-gutter').height($('#fiddleFormSQL .CodeMirror-scroll').height() - 2);
            }
            else {

                $('#fiddleFormSQL .CodeMirror-scroll, #sql').css('height', $(window).height() + "px");
                $('#fiddleFormSQL .CodeMirror-scroll .CodeMirror-gutter').css('height', $(window).height() + "px");

            }

    //        $('#sql').width($('#fiddleFormSQL').width() - 10);
    //        $('#schema_ddl').width($('#fiddleFormDDL').width() - 10);

            $('#browser').height($('#fiddleFormDDL .CodeMirror-scroll').height());

            var adjustBlockMsg = function (blockedObj) {
                var msgSize =
                    {
                        "height": $(".blockMsg", blockedObj).height(),
                        "width": $(".blockMsg", blockedObj).width()
                    };
                var objSize =
                    {
                        "height": $(blockedObj).height(),
                        "width": $(blockedObj).width()
                    };

                $(".blockMsg", blockedObj)
                    .css("top", (objSize.height-msgSize.height)/2)
                    .css("left", (objSize.width-msgSize.width)/2);

            }

            adjustBlockMsg($("div.sql.panel"));
            adjustBlockMsg($("#output"));

            fiddleBackbone.schemaDefView.refresh();
            fiddleBackbone.queryView.refresh();
        }
    }

    $(window).bind('resize', resizeLayout);
    setTimeout(resizeLayout, 1);

    /* COLLAPSING NAV (for responsive UI) */

    $(".nav").on('click', 'a', function (e) {

        if ($(this).parent('li').attr('id') !== 'db_type_id' &&
            $(this).parent('li').attr('id') !== 'userOptions') {

            $(".nav-collapse.in").collapse('hide');

        } else {
            $(this).parents('div.nav-collapse.in').css('height', 'auto');
        }
    });

});
<|endoftext|>


<commit_before>#!/usr/bin/env node

const https = require('https');
const http2 = require('http2');
const fs = require('fs');
const mimeTypes = require('mime-types');
const WebSocket = require('ws');
const os = require('os');

/**
 * Extract parameters
 */
let verbose = false;
let path = '';

for (const arg of process.argv) {
  if (arg.startsWith('--path')) {
    path = arg.split('=')[1].trim();
  } else if (arg === '--verbose') {
    verbose = true;
  }
}

/**
 * Create HTTP2 Server
 */
const server = http2.createSecureServer({
  key: fs.readFileSync(`${__dirname}/server.key`),
  cert: fs.readFileSync(`${__dirname}/server.crt`),
}, (request, response) => {
  const url = `.${request.url}`;
  if (fs.existsSync(url) && fs.statSync(url).isDirectory() && !request.url.endsWith('/')) {
    response.writeHead(301, {
      'Location': `${request.url}/`,
    });
    response.end();
  }
});

let port = 3000;

server.on('error', (error) => {
  if (error.code === 'EADDRINUSE') {
    port++;
    server.listen(port);
  } else {
    console.error(error);
  }
});

server.on('listening', () => {
  /**
   * Log currently used URLs
   */
  const networkInterfaces = os.networkInterfaces();
  console.log(`https://localhost:${port}/${path}`);
  for (const key of Object.keys(networkInterfaces)) {
    const networkInterfacesArray = networkInterfaces[key];
    for (const networkInterface of networkInterfacesArray) {
      if (networkInterface.family !== 'IPv4' || networkInterface.internal) {
        continue;
      }
      console.log(`https://${networkInterface.address}:${port}/${path}`);
    }
  }
  console.log('\n');

  /**
   * Create WebSocket server to reload page on file change
   */
  const webSocketServer = https.createServer({
    key: fs.readFileSync(`${__dirname}/server.key`),
    cert: fs.readFileSync(`${__dirname}/server.crt`),
  });
  const wss = new WebSocket.Server({ server: webSocketServer });
  webSocketServer.listen(++port);

  fs.watch('.', { recursive: true }, (eventType, filename) => {
    if (!filename || filename.startsWith('.git')) {
      return;
    }
    if (verbose) {
      console.log(`${filename} just changed, reload.`);
    }
    for (const client of wss.clients) {
      if (client.readyState === WebSocket.OPEN) {
        client.send('reload');
      }
    }
  });
});

server.on('stream', (stream, headers) => {
  const requestAuthority = headers[http2.constants.HTTP2_HEADER_AUTHORITY];
  const requestScheme = headers[http2.constants.HTTP2_HEADER_SCHEME];
  const requestPath = headers[http2.constants.HTTP2_HEADER_PATH];

  const url = new URL(`${requestScheme}://${requestAuthority}${requestPath}`);

  let filePath = `.${url.pathname}`;

  /**
   * If path is a directory then set index.html file by default
   */
  if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {
    if (!filePath.endsWith('/')) {
      return;
    }
    filePath += 'index.html';
  }

  /**
   * Add socket code on html pages for live reloading
   */
  if (filePath.endsWith('.html')) {
    try {
      let fileContent = fs.readFileSync(filePath, {
        encoding: 'utf-8',
      });
      fileContent = fileContent.replace('', `

`);
      stream.end(fileContent);
    } catch (error) {
      if (error.code === 'ENOENT') {
        stream.respond({ ':status': http2.constants.HTTP_STATUS_NOT_FOUND });
      } else {
        stream.respond({ ':status': http2.constants.HTTP_STATUS_INTERNAL_SERVER_ERROR });
      }
      stream.end();
    }
  } else {
    const responseMimeType = String(mimeTypes.lookup(filePath));
    stream.respondWithFile(filePath, {
      'content-type': responseMimeType,
    }, {
      onError: (error) => {
        if (error.code === 'ENOENT') {
          stream.respond({ ':status': http2.constants.HTTP_STATUS_NOT_FOUND });
        } else {
          stream.respond({ ':status': http2.constants.HTTP_STATUS_INTERNAL_SERVER_ERROR });
        }
        stream.end();
      },
    });
  }
});

server.listen(port);
<commit_msg>add Accept-Ranges in server for chrome streaming<commit_after>#!/usr/bin/env node

const https = require('https');
const http2 = require('http2');
const fs = require('fs');
const mimeTypes = require('mime-types');
const WebSocket = require('ws');
const os = require('os');

/**
 * Extract parameters
 */
let verbose = false;
let path = '';

for (const arg of process.argv) {
  if (arg.startsWith('--path')) {
    path = arg.split('=')[1].trim();
  } else if (arg === '--verbose') {
    verbose = true;
  }
}

/**
 * Create HTTP2 Server
 */
const server = http2.createSecureServer({
  key: fs.readFileSync(`${__dirname}/server.key`),
  cert: fs.readFileSync(`${__dirname}/server.crt`),
}, (request, response) => {
  const url = `.${request.url}`;
  if (fs.existsSync(url) && fs.statSync(url).isDirectory() && !request.url.endsWith('/')) {
    response.writeHead(301, {
      'Location': `${request.url}/`,
    });
    response.end();
  }
});

let port = 3000;

server.on('error', (error) => {
  if (error.code === 'EADDRINUSE') {
    port++;
    server.listen(port);
  } else {
    console.error(error);
  }
});

server.on('listening', () => {
  /**
   * Log currently used URLs
   */
  const networkInterfaces = os.networkInterfaces();
  console.log(`https://localhost:${port}/${path}`);
  for (const key of Object.keys(networkInterfaces)) {
    const networkInterfacesArray = networkInterfaces[key];
    for (const networkInterface of networkInterfacesArray) {
      if (networkInterface.family !== 'IPv4' || networkInterface.internal) {
        continue;
      }
      console.log(`https://${networkInterface.address}:${port}/${path}`);
    }
  }
  console.log('\n');

  /**
   * Create WebSocket server to reload page on file change
   */
  const webSocketServer = https.createServer({
    key: fs.readFileSync(`${__dirname}/server.key`),
    cert: fs.readFileSync(`${__dirname}/server.crt`),
  });
  const wss = new WebSocket.Server({ server: webSocketServer });
  webSocketServer.listen(++port);

  fs.watch('.', { recursive: true }, (eventType, filename) => {
    if (!filename || filename.startsWith('.git')) {
      return;
    }
    if (verbose) {
      console.log(`${filename} just changed, reload.`);
    }
    for (const client of wss.clients) {
      if (client.readyState === WebSocket.OPEN) {
        client.send('reload');
      }
    }
  });
});

server.on('stream', (stream, headers) => {
  const requestAuthority = headers[http2.constants.HTTP2_HEADER_AUTHORITY];
  const requestScheme = headers[http2.constants.HTTP2_HEADER_SCHEME];
  const requestPath = headers[http2.constants.HTTP2_HEADER_PATH];
  const requestRange = headers[http2.constants.HTTP2_HEADER_RANGE];

  const url = new URL(`${requestScheme}://${requestAuthority}${requestPath}`);

  let filePath = `.${url.pathname}`;

  /**
   * If path is a directory then set index.html file by default
   */
  if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {
    if (!filePath.endsWith('/')) {
      return;
    }
    filePath += 'index.html';
  }

  /**
   * Add socket code on html pages for live reloading
   */
  if (filePath.endsWith('.html')) {
    try {
      let fileContent = fs.readFileSync(filePath, {
        encoding: 'utf-8',
      });
      fileContent = fileContent.replace('', `

`);
      stream.end(fileContent);
    } catch (error) {
      if (error.code === 'ENOENT') {
        stream.respond({ ':status': http2.constants.HTTP_STATUS_NOT_FOUND });
      } else {
        stream.respond({ ':status': http2.constants.HTTP_STATUS_INTERNAL_SERVER_ERROR });
      }
      stream.end();
    }
  } else {
    const responseHeaders = {
      'content-type': String(mimeTypes.lookup(filePath)),
    };
    if (requestRange) {
      responseHeaders['Accept-Ranges'] = 'bytes';
    }
    stream.respondWithFile(filePath, responseHeaders, {
      onError: (error) => {
        if (error.code === 'ENOENT') {
          stream.respond({ ':status': http2.constants.HTTP_STATUS_NOT_FOUND });
        } else {
          stream.respond({ ':status': http2.constants.HTTP_STATUS_INTERNAL_SERVER_ERROR });
        }
        stream.end();
      },
    });
  }
});

server.listen(port);
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict'
const exec = require('child_process').execSync
const fs = require('fs')
const path = require('path')
const util = require('util')

const ghauth = require('ghauth')
const ghissues = require('ghissues')
const pkgToId = require('pkg-to-id')
const program = require('commander')
const semverRegex = require('semver-regex')
const winston = require('winston')

const pkg = require('./package')

function parseArguments (defaults) {
  program
    .version(defaults.version)
    .description(defaults.description)
    .option('-u, --user [user]', 'GitHub user', defaults.user)
    .option('-p, --project [project]', 'GitHub project', defaults.project)
    .option('-t, --tag [tag]', 'Git tag', defaults.tag)
    .option('-l, --log-level [logLevel]',
            'Log level',
            /^(error|warn|info|verbose|debug|silly)$/i,
            defaults.logLevel)
    .option('-n --dry-run',
            'Log actions, but skip adding comments to GitHub PRs')
    .parse(process.argv)
}

function main () {
  const logger = new winston.Logger({
    transports: [new winston.transports.Console()]
  })
  logger.cli()
  logger.info('%s v%s', pkg.name, pkg.version)

  const pkgFile = path.join(process.cwd(), 'package.json')
  const pkgData = fs.existsSync(pkgFile) ? require(pkgFile) : {}
  const pkgId = pkgToId(pkgData)
  const tags = exec("git tag --sort='-version:refname'")
    .toString().split('\n').filter(tag => semverRegex().test(tag))

  const defaults = {
    version: pkg.version,
    description: pkg.description,
    user: pkgId.user,
    project: pkgId.name,
    tag: tags[0],
    logLevel: 'info'
  }
  parseArguments(defaults)

  logger.level = program.logLevel
  logger.debug('pkgId:', pkgId)
  logger.debug('Tags: %s', tags)
  logger.debug('program:', {
    user: program.user,
    project: program.project,
    tag: program.tag,
    logLevel: program.logLevel,
    dryRun: program.dryRun
  })

  if (tags.length === 0) {
    logger.error('No tags found in repository')
    process.exit(1)
  }
  if (!semverRegex().test(program.tag)) {
    logger.error('Tag not semver compliant: %s', program.tag)
    process.exit(1)
  }

  const toTagIndex = tags.indexOf(program.tag)
  if (toTagIndex === -1) {
    logger.error('Tag not found in repository: %s', program.tag)
    process.exit(1)
  }
  const toTag = program.tag
  const fromTag = tags[toTagIndex + 1]

  const revRange = (typeof fromTag !== 'undefined') ? `${fromTag}..${toTag}` : toTag
  const gitLogCmd = `git log ${revRange} --format='%s' --grep='^Merge pull request #[0-9]\\+ from '`
  logger.debug('Command: %s', gitLogCmd)

  const commits = exec(gitLogCmd).toString().trimRight()
  logger.debug('Commits: %s', commits)

  const prs = commits.split('\n').map(function (line) {
    const match = /Merge pull request #(\d+) from /.exec(line)
    if (match) {
      return parseInt(match[1], 10)
    }
    return false
  }).filter(Boolean)
  logger.debug('PRs: %s', prs)

  const authOptions = {
    configName: pkg.name,
    note: util.format('%s: %s', pkg.name, pkg.description)
  }

  ghauth(authOptions, function (error, authData) {
    if (error) {
      logger.error('GitHub Authorization failure: %s', error)
      process.exit(1)
    }
    logger.debug('GitHub Authorization success for user: %s', authData.user)
    prs.forEach(function (pr) {
      logger.info('Adding comment to PR#%d', pr)
      if (!program.dryRun) {
        ghissues.createComment(
          authData, program.user, program.project, pr, toTag, function (error, comment) {
            if (error) {
              logger.error('Error adding comment to PR#%d: %s', pr, error)
            }
            logger.debug('Comment: %s', comment)
          })
      }
    })

    logger.info('Done!')
  })
}

if (require.main === module) {
  main()
}
<commit_msg>Move code to write comments to a separate function<commit_after>#!/usr/bin/env node
'use strict'
const exec = require('child_process').execSync
const fs = require('fs')
const path = require('path')
const util = require('util')

const ghauth = require('ghauth')
const ghissues = require('ghissues')
const pkgToId = require('pkg-to-id')
const program = require('commander')
const semverRegex = require('semver-regex')
const winston = require('winston')

const pkg = require('./package')

const logger = new winston.Logger({
  transports: [new winston.transports.Console()]
})
logger.cli()

function parseArguments (defaults) {
  program
    .version(defaults.version)
    .description(defaults.description)
    .option('-u, --user [user]', 'GitHub user', defaults.user)
    .option('-p, --project [project]', 'GitHub project', defaults.project)
    .option('-t, --tag [tag]', 'Git tag', defaults.tag)
    .option('-l, --log-level [logLevel]',
            'Log level',
            /^(error|warn|info|verbose|debug|silly)$/i,
            defaults.logLevel)
    .option('-n --dry-run',
            'Log actions, but skip adding comments to GitHub PRs')
    .parse(process.argv)
}

function writeComments (authOptions, prs, comment) {
  ghauth(authOptions, function (error, authData) {
    if (error) {
      logger.error('GitHub Authorization failure: %s', error)
      process.exit(1)
    }
    logger.debug('GitHub Authorization success for user: %s', authData.user)
    prs.forEach(function (pr) {
      logger.info('Adding comment to PR#%d', pr)
      if (!program.dryRun) {
        ghissues.createComment(
          authData, program.user, program.project, pr, comment, function (error, comment) {
            if (error) {
              logger.error('Error adding comment to PR#%d: %s', pr, error)
            } else {
              logger.debug('Comment: %s', comment)
            }
          })
      }
    })

    logger.info('Done!')
  })
}

function main () {
  logger.info('%s v%s', pkg.name, pkg.version)

  const pkgFile = path.join(process.cwd(), 'package.json')
  const pkgData = fs.existsSync(pkgFile) ? require(pkgFile) : {}
  const pkgId = pkgToId(pkgData)
  const tags = exec("git tag --sort='-version:refname'")
    .toString().split('\n').filter(tag => semverRegex().test(tag))

  const defaults = {
    version: pkg.version,
    description: pkg.description,
    user: pkgId.user,
    project: pkgId.name,
    tag: tags[0],
    logLevel: 'info'
  }
  parseArguments(defaults)

  logger.level = program.logLevel
  logger.debug('pkgId:', pkgId)
  logger.debug('Tags: %s', tags)
  logger.debug('program:', {
    user: program.user,
    project: program.project,
    tag: program.tag,
    logLevel: program.logLevel,
    dryRun: program.dryRun
  })

  if (tags.length === 0) {
    logger.error('No tags found in repository')
    process.exit(1)
  }
  if (!semverRegex().test(program.tag)) {
    logger.error('Tag not semver compliant: %s', program.tag)
    process.exit(1)
  }

  const toTagIndex = tags.indexOf(program.tag)
  if (toTagIndex === -1) {
    logger.error('Tag not found in repository: %s', program.tag)
    process.exit(1)
  }
  const toTag = program.tag
  const fromTag = tags[toTagIndex + 1]

  const revRange = (typeof fromTag !== 'undefined') ? `${fromTag}..${toTag}` : toTag
  const gitLogCmd = `git log ${revRange} --format='%s' --grep='^Merge pull request #[0-9]\\+ from '`
  logger.debug('Command: %s', gitLogCmd)

  const commits = exec(gitLogCmd).toString().trimRight()
  logger.debug('Commits: %s', commits)

  const prs = commits.split('\n').map(function (line) {
    const match = /Merge pull request #(\d+) from /.exec(line)
    if (match) {
      return parseInt(match[1], 10)
    }
    return false
  }).filter(Boolean)
  logger.debug('PRs: %s', prs)

  const authOptions = {
    configName: pkg.name,
    note: util.format('%s: %s', pkg.name, pkg.description)
  }
  writeComments(authOptions, prs, toTag)
}

if (require.main === module) {
  main()
}
<|endoftext|>


<commit_before>var path = require('path');
var assert = require('assert');
var Databox = require(path.join('../lib/', 'databox.js'));

describe('Databox', function () {
    describe('Setup', function () {
        it('Should set push_token', function () {
            var push_token = 123;
            var d = new Databox({
                'push_token': push_token
            });

            assert.equal(d.push_token, push_token);
        });

        it('Should cry if no \'push_token\'', function(){
            assert.throws(function(){
                new Databox();
            }, Error);

            assert.throws(function(){
                new Databox({});
            }, Error);
        });
    });

    describe('Config', function(){
        var databox, config;
        beforeEach(function(){
            databox = new Databox({
                'push_token': "some_token"
            });
            config = databox.config;
        });

        it('Should have user_agent', function(){
            assert(config.user_agent.match(/\d+\.\d+\.\d+/i) !== null);
        });

        it('Should have push_host', function(){
            assert(config.push_host.match(/databox/) !== null);
        });
    });
});
<commit_msg>Adding some more tests.<commit_after>var path = require('path');
var assert = require('assert');
var util = require('util');
var Databox = require(path.join('../lib/', 'databox.js'));

describe('Databox', function () {

    describe('Setup', function () {
        it('Should set push_token', function () {
            var push_token = 123;
            var d = new Databox({
                'push_token': push_token
            });

            assert.equal(d.push_token, push_token);
        });

        it('Should cry if no \'push_token\'', function () {
            assert.throws(function () {
                new Databox();
            }, Error);

            assert.throws(function () {
                new Databox({});
            }, Error);
        });
    });

    describe('Config', function () {
        var databox, config;
        beforeEach(function () {
            databox = new Databox({
                'push_token': "some_token"
            });
            config = databox.config;
        });

        it('Should have user_agent', function () {
            assert(config.user_agent.match(/\d+\.\d+\.\d+/i) !== null);
        });

        it('Should have push_host', function () {
            assert(config.push_host.match(/databox/) !== null);
        });
    });

    describe('Pushing', function () {
        var databox;
        before(function () {
            databox = new Databox({
                'push_token': 'token'
            });
        });

        it('Should push KPI w/ #push', function (done) {
            var key = 'me.key';
            var value = 299;

            Databox.prototype._pushJSONRequest = function (options, data, cb) {
                var i_value = data[0][util.format('$%s', key)];
                assert.equal(i_value, value);
                done();
            };

            databox.push({
                key: key,
                value: value
            });
        });

        it('Should push KPI w/ #push & callback', function (done) {
            var key = 'me.key';
            var value = 299;

            Databox.prototype._pushJSONRequest = function (options, data, cb) {
                cb([{status: 'ok'}]);
            };

            databox.push({
                key: key,
                value: value
            }, function(data){
                assert(data !== null);
                done();
            });
        });

        it('Should push KPIs w/ #insertAll', function (done) {
            var key = 'me.key';
            var value = 299;

            Databox.prototype._pushJSONRequest = function (options, data, cb) {
                var i_value = data[0][util.format('$%s', key)];
                assert.equal(i_value, value);
                assert(data.length, 2);
                done();
            };

            databox.insertAll([
                {
                    key: key,
                    value: value
                }, {
                    key: key,
                    value: value,
                    date: '2015-01-01 12:00:00'
                }
            ]);
        });
    });
});
<|endoftext|>


<commit_before>/*

TODO check the pending not 200 requests (seen with node-static, but check also http operation requests)

*/
var http = require('http');
var WebSocketServer = require('ws').Server;
var parse = require('url').parse;
var EventEmitter = require('events').EventEmitter;
var M = require('./api').server;
var user_api = require('./api').user;

function send (link, code, data) {
    link.req.resume();
    link.send(code, data);
}

function operator (link) {
    var miid = link.operation.miid;
    var method = link.operation.method;

    // check for miid in cache
    if (!M.miids[miid])  {
        return send(link, 404, 'Miid not found.');
    }

    // check for miid in cache
    if (!M.miids[miid][method])  {
        return send(link, 404, 'Method not found.');
    }

    // call method whit moduleInstance as this
    M.miids[miid][method](link);
    link.req.resume();
}

function forwardRequest (link) {

    if (link.path[0] == M.config.coreKey) {

        if (link.path.length < 3) {
            return send(link, 404, 'Invalid operation url.');
        }

        // if no operation was found in the request URL
        if (!link.path[1] || !link.path[1]) {
            return send(link, 404, 'Missing module instance ID or operation name.');
        }

        // attach api
        link.API = link.path[1] === M.config.coreMiid ? M : user_api;

        link.operation = {
            miid: link.path[1],
            method: link.path[2]
        };

        link.path = link.path.slice(3);

        operator(link);

    } else {
        M.route(link);
        link.req.resume();
    }
}

function requestHandler (req, res) {

    var url = parse(req.url, true);
    var path = url.pathname.replace(/\/$|^\//g, "").split("/", 42);
    var link = new EventEmitter();
    link.req = req;
    link.res = res;
    link.send = M.send.sendHttp;
    link.path = path || [];
    link.query = url.query || {};
    link.pathname = url.pathname;

    // invoke streaming api
    link.stream = M.send.stream(link);

    // set a empty response header object
    link.res.headers = {};

    // get the session
    M.session.get(link, forwardRequest);
}

function messageHandler (ws, link, data) {

    // TODO define a protocoll
    /*
        Request: ['miid', 'operation'[, {}, msgId]]
        Response: [miid, operation, err, data]
    */

    // parse data
    try {
        data = JSON.parse(data.toString());
    } catch (err) {
        // TODO handle error
         return ws.send('400 Bad request');
    }

    link.data = data[2];
    link.msgId = data[3] || null;
    link.path = [M.config.coreKey, data[0], data[1]];

    forwardRequest(link);
}

// start http server
var server = http.createServer(requestHandler);
// start ws server
var wss = new WebSocketServer({server: server});
wss.on('connection', function(ws) {

    // TODO make link an instance of event emitter and the "this" of an operation
    // TODO the link should contain the api for the module programmer

    // ws link
    var link = new EventEmitter();
    link.ws = ws;
    link.send = M.send.sendWs;

    // http fake link (for compatibility reasons)
    link.req = {
        headers: ws.upgradeReq.headers,
        pause: function () {},
        resume: function () {}
    };
    link.res = {headers: {}};
    link.query = {};
    link.pathname = '';
    link.stream = function () {};

    // get the session
    M.session.get(link, function (link) {
        // listen to messages
        ws.on('message', function (data) {
            messageHandler(ws, link, data);
        });
    });
});

// start listen and write app id to stdout
M.on('ready', function () {
    server.listen(M.config.port, M.config.host, function () {
        process.stdout.write(M.config.id);
    });
});
<commit_msg>how to broadcast messages?<commit_after>/*

TODO check the pending not 200 requests (seen with node-static, but check also http operation requests)

*/
var http = require('http');
var WebSocketServer = require('ws').Server;
var parse = require('url').parse;
var EventEmitter = require('events').EventEmitter;
var M = require('./api').server;
var user_api = require('./api').user;

function send (link, code, data) {
    link.req.resume();
    link.send(code, data);
}

function operator (link) {
    var miid = link.operation.miid;
    var method = link.operation.method;

    // check for miid in cache
    if (!M.miids[miid])  {
        return send(link, 404, 'Miid not found.');
    }

    // check for miid in cache
    if (!M.miids[miid][method])  {
        return send(link, 404, 'Method not found.');
    }

    // call method whit moduleInstance as this
    M.miids[miid][method](link);
    link.req.resume();
}

function forwardRequest (link) {

    if (link.path[0] == M.config.coreKey) {

        if (link.path.length < 3) {
            return send(link, 404, 'Invalid operation url.');
        }

        // if no operation was found in the request URL
        if (!link.path[1] || !link.path[1]) {
            return send(link, 404, 'Missing module instance ID or operation name.');
        }

        // attach api
        link.API = link.path[1] === M.config.coreMiid ? M : user_api;

        link.operation = {
            miid: link.path[1],
            method: link.path[2]
        };

        link.path = link.path.slice(3);

        operator(link);

    } else {
        M.route(link);
        link.req.resume();
    }
}

function requestHandler (req, res) {

    var url = parse(req.url, true);
    var path = url.pathname.replace(/\/$|^\//g, "").split("/", 42);
    var link = new EventEmitter();
    link.req = req;
    link.res = res;
    link.send = M.send.sendHttp;
    link.path = path || [];
    link.query = url.query || {};
    link.pathname = url.pathname;

    // invoke streaming api
    link.stream = M.send.stream(link);

    // set a empty response header object
    link.res.headers = {};

    // get the session
    M.session.get(link, forwardRequest);
}

function messageHandler (ws, link, data) {

    // TODO define a protocoll
    /*
        Request: ['miid', 'operation'[, {}, msgId]]
        Response: [miid, operation, err, data]
    */

    // parse data
    try {
        data = JSON.parse(data.toString());
    } catch (err) {
        // TODO handle error
         return ws.send('400 Bad request');
    }

    link.data = data[2];
    link.msgId = data[3] || null;
    link.path = [M.config.coreKey, data[0], data[1]];

    forwardRequest(link);
}

// start http server
var server = http.createServer(requestHandler);
// start ws server
var wss = new WebSocketServer({server: server});
wss.on('connection', function(ws) {

    // TODO how to broadcast messages?

    // ws link
    var link = new EventEmitter();
    link.ws = ws;
    link.send = M.send.sendWs;

    // http fake link (for compatibility reasons)
    link.req = {
        headers: ws.upgradeReq.headers,
        pause: function () {},
        resume: function () {}
    };
    link.res = {headers: {}};
    link.query = {};
    link.pathname = '';
    link.stream = function () {};

    // get the session
    M.session.get(link, function (link) {
        // listen to messages
        ws.on('message', function (data) {
            messageHandler(ws, link, data);
        });
    });
});

// start listen and write app id to stdout
M.on('ready', function () {
    server.listen(M.config.port, M.config.host, function () {
        process.stdout.write(M.config.id);
    });
});
<|endoftext|>


<commit_before>/*******************************************************************************
* Copyright (C) 2012 eBay Inc.
*
* 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.
******************************************************************************/

module.exports = function(app, config) {

	var agentApiClient = require('./services/agent-api-client').create(config);

	app.get("/units/list", app.ensureLoggedIn, function(req, res) {
		var group = req.query.group;
		var agentsResp = [];
//

		agentApiClient.getUnitListForAgentGroup(group, function(results) {

			results.forEach(function(item) {
				agentsResp.push({
					name: item.agent.name,
					group: group,
					loadBalancerState: item.agent.loadBalancerState,
					units: item.units
				});
			});
			res.json(agentsResp);
		});

	});

	app.get("/units/all", app.ensureLoggedIn, function(req, res) {
		var group = req.query.group;
		var agentsResp = [];
		res.json(config.agents);

	});

};<commit_msg>removed not used<commit_after>/*******************************************************************************
* Copyright (C) 2012 eBay Inc.
*
* 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.
******************************************************************************/

module.exports = function(app, config) {

	var agentApiClient = require('./services/agent-api-client').create(config);

	app.get("/units/list", app.ensureLoggedIn, function(req, res) {
		var group = req.query.group;
		var agentsResp = [];
		agentApiClient.getUnitListForAgentGroup(group, function(results) {

			results.forEach(function(item) {
				agentsResp.push({
					name: item.agent.name,
					group: group,
					loadBalancerState: item.agent.loadBalancerState,
					units: item.units
				});
			});
			res.json(agentsResp);
		});

	});

	app.get("/units/all", app.ensureLoggedIn, function(req, res) {
		res.json(config.agents);
	});

};<|endoftext|>


<commit_before>$(function() {

	// chat aliases
	var you = 'You';
	var robot = 'Robin';

	// slow reply by 400 to 800 ms
	var delayStart = 400;
	var delayEnd = 800;

	// initialize
	var bot = new chatBot();
	var chat = $('.chat');
	var waiting = 0;
	$('.busy').text(robot + ' is typing...');

	// submit user input and get chat-bot's reply
	var submitChat = function() {

		var input = $('.input input').val();
		if(input == '') return;

		$('.input input').val('');
		updateChat(you, input);

		var reply = bot.respondTo(input);
		if(reply == null) return;

		speak(reply);
		ping();

		var latency = Math.floor((Math.random() * (delayEnd - delayStart)) + delayStart);
		$('.busy').css('display', 'block');
		waiting++;
		setTimeout( function() {
			if(typeof reply === 'string') {
				updateChat(robot, reply);
			} else {
				for(var r in reply) {
					updateChat(robot, reply[r]);
				}
			}
			if(--waiting == 0) $('.busy').css('display', 'none');
		}, latency);
	}

	var speak = function(texts){
		if(window.speechSynthesis){
	        for(var i=0; i < texts.length; i++){
	            var utterance = new SpeechSynthesisUtterance(texts[i]);
	            utterance.lang = 'en-US';
	            window.speechSynthesis.speak(utterance);
	        }
		}
    }

    var ping = function(){

    	var payload = {
            "value1": "demo",
            "value2": "demo2"
        };

		var data = new FormData();
		data.append( "json", JSON.stringify( payload ) );

        fetch("http://anyorigin.com/go?url=https://maker.ifttt.com/trigger/winter-games-game1/with/key/dvHJXlCso1laUplLipy7LT",
        {
        	method: "POST",
        	mode: 'cors',
        	headers: new Headers({
				"Content-Type": "application/json"
			}),
            //body: JSON.stringify({"value1": "demo", "value2": "demo2"})
            body : data
        })
        .then(function(res){ console.log(res); })
        // $.post({
        //     url: 'https://crossorigin.me/https://maker.ifttt.com/trigger/winter-games-game1/with/key/dvHJXlCso1laUplLipy7LT',
        //     contentType : "application/json",
        //     dataType: "jsonp",
        //     //dataType: 'json',
        //     //jsonpCallback: "logResults",
        //     data: JSON.stringify({ value1: "demo" })
        // });
    }

	// add a new line to the chat
	var updateChat = function(party, text) {

		var style = 'you';
		if(party != you) {
			style = 'other';
		}

		var line = $('

');
		line.find('.party').addClass(style).text(party + ':');
		line.find('.text').text(text);

		chat.append(line);

		chat.stop().animate({ scrollTop: chat.prop("scrollHeight")});

	}

	// event binding
	$('.input').bind('keydown', function(e) {
		if(e.keyCode == 13) {
			submitChat();
		}
	});
	$('.input a').bind('click', submitChat);

	// initial chat state
	updateChat(robot, 'Hi buddy, Can I help you?');
	$('#chatbar').focus();

});<commit_msg>minor change<commit_after>$(function() {

	// chat aliases
	var you = 'You';
	var robot = 'Robin';

	// slow reply by 400 to 800 ms
	var delayStart = 400;
	var delayEnd = 800;

	// initialize
	var bot = new chatBot();
	var chat = $('.chat');
	var waiting = 0;
	$('.busy').text(robot + ' is typing...');

	// submit user input and get chat-bot's reply
	var submitChat = function() {

		var input = $('.input input').val();
		if(input == '') return;

		$('.input input').val('');
		updateChat(you, input);

		var reply = bot.respondTo(input);
		if(reply == null) return;

		speak(reply);
		ping();

		var latency = Math.floor((Math.random() * (delayEnd - delayStart)) + delayStart);
		$('.busy').css('display', 'block');
		waiting++;
		setTimeout( function() {
			if(typeof reply === 'string') {
				updateChat(robot, reply);
			} else {
				for(var r in reply) {
					updateChat(robot, reply[r]);
				}
			}
			if(--waiting == 0) $('.busy').css('display', 'none');
		}, latency);
	}

	var speak = function(texts){
		if(window.speechSynthesis){
	        for(var i=0; i < texts.length; i++){
	            var utterance = new SpeechSynthesisUtterance(texts[i]);
	            utterance.lang = 'en-US';
	            window.speechSynthesis.speak(utterance);
	        }
		}
    }

    var ping = function(){

    	var payload = {
            "value1": "demo",
            "value2": "demo2"
        };

		var data = new FormData();
		data.append( "json", JSON.stringify( payload ) );

		var ifttt = "https://maker.ifttt.com/trigger/winter-games-game1/with/key/dvHJXlCso1laUplLipy7LT";
        //fetch("http://anyorigin.com/go?url=https://maker.ifttt.com/trigger/winter-games-game1/with/key/dvHJXlCso1laUplLipy7LT",
        fetch("http://whateverorigin.org/get?url=" + encodeURIComponent(ifttt)
        {
        	method: "POST",
        	mode: 'cors',
        	headers: new Headers({
				"Content-Type": "application/json"
			}),
            //body: JSON.stringify({"value1": "demo", "value2": "demo2"})
            body : data
        })
        .then(function(res){ console.log(res); })
        // $.post({
        //     url: 'https://crossorigin.me/https://maker.ifttt.com/trigger/winter-games-game1/with/key/dvHJXlCso1laUplLipy7LT',
        //     contentType : "application/json",
        //     dataType: "jsonp",
        //     //dataType: 'json',
        //     //jsonpCallback: "logResults",
        //     data: JSON.stringify({ value1: "demo" })
        // });
    }

	// add a new line to the chat
	var updateChat = function(party, text) {

		var style = 'you';
		if(party != you) {
			style = 'other';
		}

		var line = $('

');
		line.find('.party').addClass(style).text(party + ':');
		line.find('.text').text(text);

		chat.append(line);

		chat.stop().animate({ scrollTop: chat.prop("scrollHeight")});

	}

	// event binding
	$('.input').bind('keydown', function(e) {
		if(e.keyCode == 13) {
			submitChat();
		}
	});
	$('.input a').bind('click', submitChat);

	// initial chat state
	updateChat(robot, 'Hi buddy, Can I help you?');
	$('#chatbar').focus();

});<|endoftext|>