<commit_before>// TODO(drheld): Count duchies / dukes / etc here.
var special_counts = new Object();

var scores = new Object();
var decks = new Object();

var deck_spot;
var points_spot;
var started = false;
var last_player = "";
var last_reveal_card = "";

function debugString() {
  return "[Scores: " + JSON.stringify(scores) + "] " +
         "[Cards: " + JSON.stringify(decks) + "]";
}

function pointsForCard(card) {
  if (card == undefined) {
    alert("Undefined card for points...");
    return 0;
  }
  if (card.indexOf("Colony") == 0) return 10;
  if (card.indexOf("Province") == 0) return 6;
  if (card.indexOf("Duchy") == 0) return 3;
  if (card.indexOf("Estate") == 0) return 1;
  if (card.indexOf("Curse") == 0) return -1;

  if (card.indexOf("Island") == 0) return 2;
  if (card.indexOf("Nobles") == 0) return 2;
  if (card.indexOf("Harem") == 0) return 2;
  if (card.indexOf("Great Hall") == 0) return 1;

  return 0;
}

function changeScore(player, points) {
  if (typeof scores[player] == "undefined") {
    scores[player] = 3;
  }
  points = parseInt(points);
  scores[player] = scores[player] + points;
}

function gainCard(player, card, count) {
  if (player == null) return;
  count = parseInt(count);

  if (typeof decks[player] == "undefined") {
    decks[player] = 10;
  }

  changeScore(player, pointsForCard(card) * count);
  decks[player] = decks[player] + count;
}

function findTrailingPlayer(text) {
  var arr = text.match(/ ([A-Za-z0-9]+)\./);
  if (arr.length == 2) {
    return arr[1];
  }
  return null;
}

function maybeHandleTurnChange(text) {
  if (text.indexOf("---") != -1) {
    // This must be a turn start.
    if (text.match(/Your turn/) != null) {
      last_player = "You";
    } else {
      var arr = text.match(/--- (.+)'s turn ---/);
      if (arr != null && arr.length == 2) {
        last_player = arr[1];
      } else {
        alert("Couldn't handle turn change: " + text);
      }
    }
    return true;
  }
  return false;
}

function maybeReturnToSupply(text) {
  if (text.indexOf("it to the supply") != -1) {
    gainCard(last_player, last_reveal_card, -1);
    return true;
  } else {
    var arr = text.match("([0-9]*) copies to the supply");
    if (arr != null && arr.length == 2) {
      gainCard(last_player, last_reveal_card, -arr[1]);
      return true;
    }
  }
  return false;
}

function maybeHandleSwindler(elems, text) {
  if (text.indexOf("replacing your") != -1) {
    if (elems.length == 2) {
      gainCard("You", elems[0].innerText, -1);
      gainCard("You", elems[1].innerText, 1);
    } else {
      alert("Replacing your has " + elems.length + " elements.");
    }
    return true;
  }
  if (text.indexOf("You replace") != -1) {
    if (elems.length == 2) {
      var arr = text.match("You replace ([^']*)'");
      if (arr != null && arr.length == 2) {
        gainCard(arr[1], elems[0].innerText, -1);
        gainCard(arr[1], elems[1].innerText, 1);
      } else {
        alert("Could not split: " + text);
      }
    } else {
      alert("Replacing your has " + elems.length + " elements.");
    }
    return true;
  }
  return false;
}

function maybeHandleSeaHag(elems, text_arr) {
  if (elems.length == 2 && pointsForCard(elems[1].innerText) == -1) {
    gainCard(text_arr[0], elems[1].innerText, 1);
    return true;
  }
}

function maybeHandleTrashing(elems, text, text_arr) {
  if (text_arr[0] == "trashing" ||  text_arr[1] == "trash") {
    for (elem in elems) {
      if (elems[elem].innerText != undefined) {
        var card = elems[elem].innerText;
        var count = getCardCount(card, text);
        gainCard(last_player, card, -count);
      }
    }
    return true;
  }
  return false;
}

function maybeHandleVp(text) {
  var re = new RegExp("[+]([0-9]+) ▼");
  var arr = (text.match(re));
  if (arr != null && arr.length == 2) {
    changeScore(last_player, arr[1]);
  }
}

function getCardCount(card, text) {
  var count = 1;
  var re = new RegExp("([0-9]+) " + card);
  var arr = (text.match(re));
  if (arr != null && arr.length == 2) {
    count = arr[1];
  }
  return count;
}

function handleLogEntry(node) {
  // Gaining VP could happen in combination with other stuff.
  maybeHandleVp(node.innerText);

  elems = node.getElementsByTagName("span");
  if (elems.length == 0) {
    if (maybeHandleTurnChange(node.innerText)) return;
    if (maybeReturnToSupply(node.innerText)) return;
    return;
  }

  // Remove leading stuff from the text.
  var text = node.innerText.split(" ");
  var i = 0;
  for (i = 0; i < text.length; i++) {
    if (text[i].match(/[A-Za-z0-9]/) != null) break;
  }
  if (i == text.length) return;
  text = text.slice(i);

  if (maybeHandleSwindler(elems, node.innerText)) return;
  if (maybeHandleSeaHag(elems, text)) return;
  if (maybeHandleTrashing(elems, node.innerText, text)) return;

  if (text[0] == "trashing" ||  text[1] == "trash") {
    for (elem in elems) {
      if (elems[elem].innerText != undefined) {
        var card = elems[elem].innerText;
        var count = getCardCount(card, node.innerText);
        gainCard(last_player, card, -count);
      }
    }
    return;
  }

  // Expect one element from here on out.
  if (elems.length > 1) return;

  // It's a single card action.
  var card = elems[0].innerText;

  if (text[0].indexOf("gaining") == 0) {
    var count = getCardCount(card, node.innerText);
    gainCard(last_player, card, count);
    return;
  }

  var player = text[0];
  var action = text[1];
  var delta = 0;
  if (action.indexOf("buy") == 0 || action.indexOf("gain") == 0) {
    var count = getCardCount(card, node.innerText);
    gainCard(player, card, count);
  } else if (action.indexOf("pass") == 0) {
    gainCard(player, card, -1);
    var other_player = findTrailingPlayer(node.innerText);
    gainCard(other_player, card, 1);
  } else if (action.indexOf("receive") == 0) {
    gainCard(player, card, 1);
    var other_player = findTrailingPlayer(node.innerText);
    gainCard(other_player, card, -1);
  } else if (action.indexOf("reveal") == 0) {
    last_reveal_card = card;
  }
}

function updateScores() {
  if (points_spot == undefined) return;
  var print_scores = "Points: "
  for (var score in scores) {
    print_scores = print_scores + " " + score + "=" + scores[score];
  }
  points_spot.innerHTML = print_scores;
}

function updateDeck() {
  if (deck_spot == undefined) return;
  var print_deck = "Cards: "
  for (var deck in decks) {
    print_deck = print_deck + " " + deck + "=" + decks[deck];
  }
  deck_spot.innerHTML = print_deck;
}

function initialize() {
  started = true;
  special_counts = new Object();
  scores = new Object();
  decks = new Object();

  updateScores();
  updateDeck();
}

function handle(doc) {
  if (doc.constructor == HTMLDivElement &&
      doc.innerText.indexOf("Say") == 0) {
    initialize();
    deck_spot = doc.children[5];
    points_spot = doc.children[6];
  }

  if (doc.constructor == HTMLElement && doc.parentNode.id == "log" &&
      doc.innerText.indexOf("Turn order") != -1) {
    initialize();
  }

  if (started && doc.constructor == HTMLElement && doc.parentNode.id == "log") {
    handleLogEntry(doc);
  }

  if (started) {
    updateScores();
    updateDeck();
  }
}

document.body.addEventListener('DOMNodeInserted', function(ev) {
  handle(ev.target);
});
<commit_msg>Handle gaining multiple cards at once such as from Mountebank.<commit_after>// TODO(drheld): Count duchies / dukes / etc here.
var special_counts = new Object();

var scores = new Object();
var decks = new Object();

var deck_spot;
var points_spot;
var started = false;
var last_player = "";
var last_reveal_card = "";

function debugString() {
  return "[Scores: " + JSON.stringify(scores) + "] " +
         "[Cards: " + JSON.stringify(decks) + "]";
}

function pointsForCard(card) {
  if (card == undefined) {
    alert("Undefined card for points...");
    return 0;
  }
  if (card.indexOf("Colony") == 0) return 10;
  if (card.indexOf("Province") == 0) return 6;
  if (card.indexOf("Duchy") == 0) return 3;
  if (card.indexOf("Estate") == 0) return 1;
  if (card.indexOf("Curse") == 0) return -1;

  if (card.indexOf("Island") == 0) return 2;
  if (card.indexOf("Nobles") == 0) return 2;
  if (card.indexOf("Harem") == 0) return 2;
  if (card.indexOf("Great Hall") == 0) return 1;

  return 0;
}

function changeScore(player, points) {
  if (typeof scores[player] == "undefined") {
    scores[player] = 3;
  }
  points = parseInt(points);
  scores[player] = scores[player] + points;
}

function gainCard(player, card, count) {
  if (player == null) return;
  count = parseInt(count);

  if (typeof decks[player] == "undefined") {
    decks[player] = 10;
  }

  changeScore(player, pointsForCard(card) * count);
  decks[player] = decks[player] + count;
}

function findTrailingPlayer(text) {
  var arr = text.match(/ ([A-Za-z0-9]+)\./);
  if (arr.length == 2) {
    return arr[1];
  }
  return null;
}

function maybeHandleTurnChange(text) {
  if (text.indexOf("---") != -1) {
    // This must be a turn start.
    if (text.match(/Your turn/) != null) {
      last_player = "You";
    } else {
      var arr = text.match(/--- (.+)'s turn ---/);
      if (arr != null && arr.length == 2) {
        last_player = arr[1];
      } else {
        alert("Couldn't handle turn change: " + text);
      }
    }
    return true;
  }
  return false;
}

function maybeReturnToSupply(text) {
  if (text.indexOf("it to the supply") != -1) {
    gainCard(last_player, last_reveal_card, -1);
    return true;
  } else {
    var arr = text.match("([0-9]*) copies to the supply");
    if (arr != null && arr.length == 2) {
      gainCard(last_player, last_reveal_card, -arr[1]);
      return true;
    }
  }
  return false;
}

function maybeHandleSwindler(elems, text) {
  if (text.indexOf("replacing your") != -1) {
    if (elems.length == 2) {
      gainCard("You", elems[0].innerText, -1);
      gainCard("You", elems[1].innerText, 1);
    } else {
      alert("Replacing your has " + elems.length + " elements.");
    }
    return true;
  }
  if (text.indexOf("You replace") != -1) {
    if (elems.length == 2) {
      var arr = text.match("You replace ([^']*)'");
      if (arr != null && arr.length == 2) {
        gainCard(arr[1], elems[0].innerText, -1);
        gainCard(arr[1], elems[1].innerText, 1);
      } else {
        alert("Could not split: " + text);
      }
    } else {
      alert("Replacing your has " + elems.length + " elements.");
    }
    return true;
  }
  return false;
}

function maybeHandleSeaHag(text_arr, text) {
  if (text.indexOf("a Curse on top of") != -1) {
    gainCard(text_arr[0], "Curse", 1);
    return true;
  }
  return false;
}

function maybeHandleVp(text) {
  var re = new RegExp("[+]([0-9]+) ▼");
  var arr = (text.match(re));
  if (arr != null && arr.length == 2) {
    changeScore(last_player, arr[1]);
  }
}

function getCardCount(card, text) {
  var count = 1;
  var re = new RegExp("([0-9]+) " + card);
  var arr = (text.match(re));
  if (arr != null && arr.length == 2) {
    count = arr[1];
  }
  return count;
}

function handleGainOrTrash(elems, text, multiplier) {
  for (elem in elems) {
    if (elems[elem].innerText != undefined) {
      var card = elems[elem].innerText;
      var count = getCardCount(card, text);
      gainCard(last_player, card, multiplier * count);
    }
  }
}

function handleLogEntry(node) {
  // Gaining VP could happen in combination with other stuff.
  maybeHandleVp(node.innerText);

  elems = node.getElementsByTagName("span");
  if (elems.length == 0) {
    if (maybeHandleTurnChange(node.innerText)) return;
    if (maybeReturnToSupply(node.innerText)) return;
    return;
  }

  // Remove leading stuff from the text.
  var text = node.innerText.split(" ");
  var i = 0;
  for (i = 0; i < text.length; i++) {
    if (text[i].match(/[A-Za-z0-9]/) != null) break;
  }
  if (i == text.length) return;
  text = text.slice(i);

  if (maybeHandleSwindler(elems, node.innerText)) return;
  if (maybeHandleSeaHag(text, node.innerText)) return;

  if (text[0] == "trashing" ||  text[1] == "trash") {
    handleGainOrTrash(elems, node.innerText, -1);
    return;
  }
  if (text[0].indexOf("gain") == 0 || text[1].indexOf("gain") == 0) {
    handleGainOrTrash(elems, node.innerText, 1);
    return;
  }

  // Expect one element from here on out.
  if (elems.length > 1) return;

  // It's a single card action.
  var card = elems[0].innerText;

  var player = text[0];
  var action = text[1];
  var delta = 0;
  if (action.indexOf("buy") == 0 || action.indexOf("gain") == 0) {
    var count = getCardCount(card, node.innerText);
    gainCard(player, card, count);
  } else if (action.indexOf("pass") == 0) {
    gainCard(player, card, -1);
    var other_player = findTrailingPlayer(node.innerText);
    gainCard(other_player, card, 1);
  } else if (action.indexOf("receive") == 0) {
    gainCard(player, card, 1);
    var other_player = findTrailingPlayer(node.innerText);
    gainCard(other_player, card, -1);
  } else if (action.indexOf("reveal") == 0) {
    last_reveal_card = card;
  }
}

function updateScores() {
  if (points_spot == undefined) return;
  var print_scores = "Points: "
  for (var score in scores) {
    print_scores = print_scores + " " + score + "=" + scores[score];
  }
  points_spot.innerHTML = print_scores;
}

function updateDeck() {
  if (deck_spot == undefined) return;
  var print_deck = "Cards: "
  for (var deck in decks) {
    print_deck = print_deck + " " + deck + "=" + decks[deck];
  }
  deck_spot.innerHTML = print_deck;
}

function initialize() {
  started = true;
  special_counts = new Object();
  scores = new Object();
  decks = new Object();

  updateScores();
  updateDeck();
}

function handle(doc) {
  if (doc.constructor == HTMLDivElement &&
      doc.innerText.indexOf("Say") == 0) {
    initialize();
    deck_spot = doc.children[5];
    points_spot = doc.children[6];
  }

  if (doc.constructor == HTMLElement && doc.parentNode.id == "log" &&
      doc.innerText.indexOf("Turn order") != -1) {
    initialize();
  }

  if (started && doc.constructor == HTMLElement && doc.parentNode.id == "log") {
    handleLogEntry(doc);
  }

  if (started) {
    updateScores();
    updateDeck();
  }
}

document.body.addEventListener('DOMNodeInserted', function(ev) {
  handle(ev.target);
});
<|endoftext|>


<commit_before>var request = require('request');
var cheerio = require('cheerio');
var util = require('util');
var promise = require('promise');
var fs = require('fs');
var htmlEscape = require("html-escape");
var getOpt = require('node-getopt');

var opt = getOpt.create([
    ['', 'page[=PAGE]'  , 'Rnages of pages to fetch (start:end)'],
    ['', 'output[=DIR]' , 'Output'],
    ['', 'overwrite'    , 'Whether to overwrite existing chapters'],
    ['h', 'help'        , 'Display help']
]).bindHelp().parseSystem();

function getOnePage(url) {
  return new Promise(function(resolve, reject) {
    console.log('Downloading', url);
    request(url, function(err, response, html) {
      if (err) {
        var errMsg = 'Error downloading' + url + err;
        console.log(errMsg);
        reject(errMsg);
      }
      console.log('Downloaded', url);
      resolve(html);
    });
  });
}

function getSections(url) {
  return getOnePage(url).then(function(content) {
    $ = cheerio.load(content);
    return $('td[id^=postmessage]').toArray();
  });
}

function writeFile(fileName, text) {
  fs.exists(fileName, function(exists) {
    if (exists) {
      if (opt.options['overwrite']) {
        console.log('Overwrite', fileName);
      } else {
        console.log('Skip', fileName);
        return;
      }
    } else {
      console.log('New file', fileName);
    }
    fs.writeFile(fileName, text);
  });
}

function processSections(index, sections) {
  for (i = 0; i < sections.length; ++i) {
    // Sanitize.
    var node = $(sections[i]);
    node.find('.pstatus').remove();
    node.find('ignore_js_op').remove();
    node.find('a').remove();
    node.find('br').replaceWith('\n\n');

    // Normalize line break and space.
    // Remove bad char which causes problems when translating to epub (0x0c).
    var text = node.text()
      .replace(/\r\n/g, '').replace(/\u3000|\xa0/g, ' ')
      .replace(/\x0c/g, '');

    // epub creator often treats text as html so needs to escape.
    text = htmlEscape(text);

    // Try best to guess redundant line break used to control layout on forum.
    text = text.replace(/([^。,？！」])\n\n([^\s])/g, '$1$2');

    console.log('Writing chapter', index);
    writeFile(String(index++) + '.part', text);
  }
  return index;
}

var URL_TEMPLATE = 'http://ck101.com/thread-1586268-%s-1.html';

function download(startPage, endPage) {
  // Use promise to chain parallel responses in order.
  var all = Promise.resolve(1);
  for (var i = startPage; i <= endPage; ++i) {
    var url = util.format(URL_TEMPLATE, i);

    // Create a closure so the "page" is copied. Otherwise the same
    // object is referenced when page is done in each iteration.
    all = (function(page){
      return all.then(function(index) {
        return page.then(processSections.bind(undefined, index));
      }, function(err) {
        console.log(err);
      });
    })(getSections(url));
  }

  all.then(function() {
    console.log('All Done.');
  }, function(err) {
    console.log(err);
  });
}

function getPageNum() {
  console.log('Getting num of pages');
  var firstPage = util.format(URL_TEMPLATE, 1);
  return getOnePage(firstPage).then(function(content) {
    $ = cheerio.load(content);
    return parseInt($('.pgt .pg a.last').text().match(/\d+/)[0], 10);
  });
}

function main() {
  if ('output' in opt.options) {
    try {
      process.chdir(opt.options['output']);
    } catch (e) {
      console.log('Couldn not change directory', e);
      return;
    };
  }

  var startPage = 1;
  var endPage = null;
  if ('page' in opt.options) {
    pageRange = opt.options['page'].split(':');
    startPage = parseInt(pageRange[0], 10) || startPage;
    endPage = parseInt(pageRange[1], 10) || endPage;
  }

  var last = endPage ? Promise.resolve(endPage) : getPageNum();
  last.then(function(endPage) {
    console.log('start page', startPage, 'end page', endPage);
    download(startPage, endPage);
  });
}

main();
<commit_msg>1. support post id 2. dry run flag 3. fix line break bug<commit_after>var request = require('request');
var cheerio = require('cheerio');
var util = require('util');
var promise = require('promise');
var fs = require('fs');
var htmlEscape = require("html-escape");
var getOpt = require('node-getopt');

var opt = getOpt.create([
    ['', 'post[=]' , 'post id'],
    ['', 'page[=PAGE]'  , 'Rnages of pages to fetch (start:end)'],
    ['', 'output[=DIR]' , 'Output'],
    ['', 'overwrite'    , 'Whether to overwrite existing chapters'],
    ['', 'dryrun'       , 'dry run'],
    ['h', 'help'        , 'Display help']
]).bindHelp().parseSystem();

function getOnePage(url) {
  return new Promise(function(resolve, reject) {
    console.log('Downloading', url);
    request(url, function(err, response, html) {
      if (err) {
        var errMsg = 'Error downloading' + url + err;
        console.log(errMsg);
        reject(errMsg);
      }
      console.log('Downloaded', url);
      resolve(html);
    });
  });
}

function getSections(url) {
  return getOnePage(url).then(function(content) {
    $ = cheerio.load(content);
    return $('td[id^=postmessage]').toArray();
  });
}

function writeFile(fileName, text) {
  fs.exists(fileName, function(exists) {
    if (exists) {
      if (opt.options['overwrite']) {
        console.log('Overwrite', fileName);
      } else {
        console.log('Skip', fileName);
        return;
      }
    } else {
      console.log('New file', fileName);
    }
    if (!opt.options['dryrun']) {
      fs.writeFile(fileName, text);
    }
  });
}

function processSections(index, sections) {
  for (i = 0; i < sections.length; ++i) {
    // Sanitize.
    var node = $(sections[i]);
    node.find('.pstatus').remove();
    node.find('ignore_js_op').remove();
    node.find('a').remove();
    node.find('br').replaceWith('\n');

    // Normalize line break and space.
    // Remove bad char which causes problems when translating to epub (0x0c).
    var text = node.text()
      .replace(/\r\n/g, '\n').replace(/\u3000|\xa0/g, ' ')
      .replace(/\x0c/g, '');

    // epub creator often treats text as html so needs to escape.
    text = htmlEscape(text);

    // Try best to guess redundant line break used to control layout on forum.
    text = text.replace(/([^。,？！」])\n\n([^\s])/g, '$1$2');

    console.log('Writing chapter', index);
    writeFile(String(index++) + '.part', text);
  }
  return index;
}

function download(post_url, startPage, endPage) {
  // Use promise to chain parallel responses in order.
  var all = Promise.resolve(1);
  for (var i = startPage; i <= endPage; ++i) {
    var url = util.format(post_url, i);

    // Create a closure so the "page" is copied. Otherwise the same
    // object is referenced when page is done in each iteration.
    all = (function(page){
      return all.then(function(index) {
        return page.then(processSections.bind(undefined, index));
      }, function(err) {
        console.log(err);
      });
    })(getSections(url));
  }

  all.then(function() {
    console.log('All Done.');
  }, function(err) {
    console.log(err);
  });
}

function getPageNum(post_url) {
  console.log('Getting num of pages');
  var firstPage = util.format(post_url, 1);
  return getOnePage(firstPage).then(function(content) {
    $ = cheerio.load(content);
    return parseInt($('.pgt .pg a.last').text().match(/\d+/)[0], 10);
  });
}

var YAODAO_ID = '1586268';
var URL_TEMPLATE = 'http://ck101.com/thread-%s-%s-1.html';

function main() {
  if ('output' in opt.options) {
    try {
      process.chdir(opt.options['output']);
    } catch (e) {
      console.log('Couldn not change directory', e);
      return;
    };
  }

  console.log(opt.options['post']);
  var post_url = util.format(URL_TEMPLATE, opt.options['post'] || YAODAO_ID);

  var startPage = 1;
  var endPage = null;
  if ('page' in opt.options) {
    pageRange = opt.options['page'].split(':');
    startPage = parseInt(pageRange[0], 10) || startPage;
    endPage = parseInt(pageRange[1], 10) || endPage;
  }

  var last = endPage ? Promise.resolve(endPage) : getPageNum(post_url);
  last.then(function(endPage) {
    console.log('start page', startPage, 'end page', endPage);
    download(post_url, startPage, endPage);
  });
}

main();
<|endoftext|>


<commit_before>'use strict';

angular.module('subutai.peer-registration.controller', [])
	.controller('PeerRegistrationCtrl', PeerRegistrationCtrl)
	.controller('PeerRegistrationPopupCtrl', PeerRegistrationPopupCtrl);

PeerRegistrationCtrl.$inject = ['$scope', 'peerRegistrationService', 'DTOptionsBuilder', 'DTColumnBuilder', '$resource', '$compile', 'SweetAlert', 'ngDialog'];
PeerRegistrationPopupCtrl.$inject = ['$scope', 'peerRegistrationService', 'ngDialog', 'SweetAlert'];

function PeerRegistrationCtrl($scope, peerRegistrationService, DTOptionsBuilder, DTColumnBuilder, $resource, $compile, SweetAlert, ngDialog) {

	var vm = this;

	// functions
	vm.peerFrom = peerFrom;
	vm.rejectPeerRequest = rejectPeerRequest;
	vm.approvePeerRequest = approvePeerRequest;
	vm.unregisterPeer = unregisterPeer;
	vm.cancelPeerRequest = cancelPeerRequest;

	vm.dtInstance = {};
	vm.users = {};
	vm.dtOptions = DTOptionsBuilder
		.fromFnPromise(function() {
			return $resource( peerRegistrationService.getPeersUrl() ).query().$promise;
		})
		.withPaginationType('full_numbers')
		.withOption('createdRow', createdRow)
		.withOption('columnDefs', [
			{className: "b-main-table__buttons-group", "targets": 3},
			{className: "b-main-table__peer-status-col", "targets": 2}
		])
		.withOption('stateSave', true);

	vm.dtColumns = [
		DTColumnBuilder.newColumn('peerInfo.name').withTitle('Name'),
		DTColumnBuilder.newColumn('peerInfo.ip').withTitle(' IP'),
		DTColumnBuilder.newColumn(null).withTitle('Status').renderWith(statusHTML),
		DTColumnBuilder.newColumn(null).withTitle('').notSortable().renderWith(actionButton),
	];

	function createdRow(row, data, dataIndex) {
		$compile(angular.element(row).contents())($scope);
	}

	function statusHTML(data, type, full, meta) {
		vm.users[data.id] = data;
		return '

';
	}

	function actionButton(data, type, full, meta) {
		var result = '';
		if(data.status == 'APPROVED') {
			result += 'Unregister';
		} else if(data.status == 'WAIT') {
			result += 'Cancel';
		} else if(data.status == 'REQUESTED') {
			result += 'Approve';
			result += 'Reject';
		}

		return result;
	}

	function peerFrom() {
		ngDialog.open({
			template: 'subutai-app/peerRegistration/partials/peerForm.html',
			controller: 'PeerRegistrationPopupCtrl',
			controllerAs: 'peerRegistrationPopupCtrl',
			preCloseCallback: function(value) {
				vm.dtInstance.reloadData(null, false);
			}
		});
	}

	function rejectPeerRequest(peerId) {
		peerRegistrationService.rejectPeerRequest(peerId).success(function (data) {
			vm.dtInstance.reloadData(null, false);
		});
	}

	function approvePeerRequest(peerId) {
		ngDialog.open({
			template: 'subutai-app/peerRegistration/partials/peerApprove.html',
			controller: 'PeerRegistrationPopupCtrl',
			controllerAs: 'peerRegistrationPopupCtrl',
			data: {"peerId": peerId},
			preCloseCallback: function(value) {
				vm.dtInstance.reloadData(null, false);
			}
		});
	}

	function unregisterPeer(peerId) {
		SweetAlert.swal({
			title: "Are you sure?",
			text: "Your unregister peer request!",
			type: "warning",
			showCancelButton: true,
			confirmButtonColor: "#ff3f3c",
			confirmButtonText: "Unregister",
			cancelButtonText: "Cancel",
			closeOnConfirm: false,
			closeOnCancel: true,
			showLoaderOnConfirm: true
		},
		function (isConfirm) {
			if (isConfirm) {
				peerRegistrationService.unregisterPeerRequest(peerId).success(function (data) {
					SweetAlert.swal("Unregistered!", "Your peer request has been unregistered.", "success");
					vm.dtInstance.reloadData(null, false);
				}).error(function (data) {
					SweetAlert.swal("ERROR!", data.ERROR, "error");
				});
			}
		});
	}

	function cancelPeerRequest(peerId) {
		SweetAlert.swal({
			title: "Are you sure?",
			text: "Your cancel peer request!",
			type: "warning",
			showCancelButton: true,
			confirmButtonColor: "#ff3f3c",
			confirmButtonText: "Cancel request",
			cancelButtonText: "No",
			closeOnConfirm: false,
			closeOnCancel: true,
			showLoaderOnConfirm: true
		},
		function (isConfirm) {
			if (isConfirm) {
				peerRegistrationService.cancelPeerRequest(peerId).success(function (data) {
					SweetAlert.swal("Canceled!", "Your peer request has been canceled.", "success");
					vm.dtInstance.reloadData(null, false);
				}).error(function (data) {
					SweetAlert.swal("ERROR!", data.ERROR, "error");
				});
			}
		});
	}

}

function PeerRegistrationPopupCtrl($scope, peerRegistrationService, ngDialog, SweetAlert) {

	var vm = this;
	vm.peerId = null;

	if($scope.ngDialogData !== undefined) {
		vm.peerId = $scope.ngDialogData.peerId;
	}

	vm.addPeer = addPeer;
	vm.approvePeerRequest = approvePeerRequest;

	function addPeer(newPeer) {
		var postData = 'ip=' + newPeer.ip + '&key_phrase=' + newPeer.keyphrase;
		peerRegistrationService.registerRequest(postData).success(function (data) {
			ngDialog.closeAll();
		}).error(function(error){
			SweetAlert.swal("ERROR!", "Peer request error: " + error, "error");
		});
	}

	function approvePeerRequest(keyPhrase) {
		peerRegistrationService.approvePeerRequest(vm.peerId, keyPhrase).success(function (data) {
			ngDialog.closeAll();
		}).error(function(error){
			SweetAlert.swal("ERROR!", "Peer approve error: " + error, "error");
		});
	}

}

<commit_msg>SS-4078 fixed error message handling in peer registration<commit_after>'use strict';

angular.module('subutai.peer-registration.controller', [])
	.controller('PeerRegistrationCtrl', PeerRegistrationCtrl)
	.controller('PeerRegistrationPopupCtrl', PeerRegistrationPopupCtrl);

PeerRegistrationCtrl.$inject = ['$scope', 'peerRegistrationService', 'DTOptionsBuilder', 'DTColumnBuilder', '$resource', '$compile', 'SweetAlert', 'ngDialog'];
PeerRegistrationPopupCtrl.$inject = ['$scope', 'peerRegistrationService', 'ngDialog', 'SweetAlert'];

function PeerRegistrationCtrl($scope, peerRegistrationService, DTOptionsBuilder, DTColumnBuilder, $resource, $compile, SweetAlert, ngDialog) {

	var vm = this;

	// functions
	vm.peerFrom = peerFrom;
	vm.rejectPeerRequest = rejectPeerRequest;
	vm.approvePeerRequest = approvePeerRequest;
	vm.unregisterPeer = unregisterPeer;
	vm.cancelPeerRequest = cancelPeerRequest;

	vm.dtInstance = {};
	vm.users = {};
	vm.dtOptions = DTOptionsBuilder
		.fromFnPromise(function() {
			return $resource( peerRegistrationService.getPeersUrl() ).query().$promise;
		})
		.withPaginationType('full_numbers')
		.withOption('createdRow', createdRow)
		.withOption('columnDefs', [
			{className: "b-main-table__buttons-group", "targets": 3},
			{className: "b-main-table__peer-status-col", "targets": 2}
		])
		.withOption('stateSave', true);

	vm.dtColumns = [
		DTColumnBuilder.newColumn('peerInfo.name').withTitle('Name'),
		DTColumnBuilder.newColumn('peerInfo.ip').withTitle(' IP'),
		DTColumnBuilder.newColumn(null).withTitle('Status').renderWith(statusHTML),
		DTColumnBuilder.newColumn(null).withTitle('').notSortable().renderWith(actionButton),
	];

	function createdRow(row, data, dataIndex) {
		$compile(angular.element(row).contents())($scope);
	}

	function statusHTML(data, type, full, meta) {
		vm.users[data.id] = data;
		return '

';
	}

	function actionButton(data, type, full, meta) {
		var result = '';
		if(data.status == 'APPROVED') {
			result += 'Unregister';
		} else if(data.status == 'WAIT') {
			result += 'Cancel';
		} else if(data.status == 'REQUESTED') {
			result += 'Approve';
			result += 'Reject';
		}

		return result;
	}

	function peerFrom() {
		ngDialog.open({
			template: 'subutai-app/peerRegistration/partials/peerForm.html',
			controller: 'PeerRegistrationPopupCtrl',
			controllerAs: 'peerRegistrationPopupCtrl',
			preCloseCallback: function(value) {
				vm.dtInstance.reloadData(null, false);
			}
		});
	}

	function rejectPeerRequest(peerId) {
		peerRegistrationService.rejectPeerRequest(peerId).success(function (data) {
			vm.dtInstance.reloadData(null, false);
		});
	}

	function approvePeerRequest(peerId) {
		ngDialog.open({
			template: 'subutai-app/peerRegistration/partials/peerApprove.html',
			controller: 'PeerRegistrationPopupCtrl',
			controllerAs: 'peerRegistrationPopupCtrl',
			data: {"peerId": peerId},
			preCloseCallback: function(value) {
				vm.dtInstance.reloadData(null, false);
			}
		});
	}

	function unregisterPeer(peerId) {
		SweetAlert.swal({
			title: "Are you sure?",
			text: "Your unregister peer request!",
			type: "warning",
			showCancelButton: true,
			confirmButtonColor: "#ff3f3c",
			confirmButtonText: "Unregister",
			cancelButtonText: "Cancel",
			closeOnConfirm: false,
			closeOnCancel: true,
			showLoaderOnConfirm: true
		},
		function (isConfirm) {
			if (isConfirm) {
				peerRegistrationService.unregisterPeerRequest(peerId).success(function (data) {
					SweetAlert.swal("Unregistered!", "Your peer request has been unregistered.", "success");
					vm.dtInstance.reloadData(null, false);
				}).error(function (data) {
					SweetAlert.swal("ERROR!", data, "error");
				});
			}
		});
	}

	function cancelPeerRequest(peerId) {
		SweetAlert.swal({
			title: "Are you sure?",
			text: "Your cancel peer request!",
			type: "warning",
			showCancelButton: true,
			confirmButtonColor: "#ff3f3c",
			confirmButtonText: "Cancel request",
			cancelButtonText: "No",
			closeOnConfirm: false,
			closeOnCancel: true,
			showLoaderOnConfirm: true
		},
		function (isConfirm) {
			if (isConfirm) {
				peerRegistrationService.cancelPeerRequest(peerId).success(function (data) {
					SweetAlert.swal("Canceled!", "Your peer request has been canceled.", "success");
					vm.dtInstance.reloadData(null, false);
				}).error(function (data) {
					SweetAlert.swal("ERROR!", data, "error");
				});
			}
		});
	}

}

function PeerRegistrationPopupCtrl($scope, peerRegistrationService, ngDialog, SweetAlert) {

	var vm = this;
	vm.peerId = null;

	if($scope.ngDialogData !== undefined) {
		vm.peerId = $scope.ngDialogData.peerId;
	}

	vm.addPeer = addPeer;
	vm.approvePeerRequest = approvePeerRequest;

	function addPeer(newPeer) {
		var postData = 'ip=' + newPeer.ip + '&key_phrase=' + newPeer.keyphrase;
		peerRegistrationService.registerRequest(postData).success(function (data) {
			ngDialog.closeAll();
		}).error(function(error){
			SweetAlert.swal("ERROR!", "Peer request error: " + error, "error");
		});
	}

	function approvePeerRequest(keyPhrase) {
		peerRegistrationService.approvePeerRequest(vm.peerId, keyPhrase).success(function (data) {
			ngDialog.closeAll();
		}).error(function(error){
			SweetAlert.swal("ERROR!", "Peer approve error: " + error, "error");
		});
	}

}

<|endoftext|>


<commit_before>/**
 * @author keke
 */
(function (_global) {
  'use strict';
  _global.__require__ = function (parentModule) {
    return function (name) {
      var m = __jverticle__.require(name, parentModule);
      if (m) {
        return m.exports;
      } else {
        return null;
      }
    }
  }
})(this);<commit_msg>expose global<commit_after>/**
 * @author keke
 */
(function (_global) {
  'use strict';
  _global.__require__ = function (parentModule) {
    return function (name) {
      var m = __jverticle__.require(name, parentModule);
      if (m) {
        return m.exports;
      } else {
        return null;
      }
    }
  };

  if (__exposeGlobal__) {
    _global.__global__ = _global;
  }
})(this);<|endoftext|>


<commit_before>/*!
 * Open as Media Type Chrome Extension
 *
 * Copyright 2012, Ori Livneh
 * Licensed under the BSD license; see LICENSE for more details.
 */

/*jslint maxerr: 50, maxlen: 80, indent: 4 */
/*global chrome: true */

(function () {
    "use strict";
    var headers_received = chrome.webRequest.onHeadersReceived,
        media_types = ['text/html', 'text/plain'],
        target_tab = 0,
        target_url = '',
        patch_headers = function (media_type) {
            var callback = function (details) {
                var headers = details.responseHeaders,
                    is_redirect = false;

                if (details.tabId === target_tab) {
                    // This is the request we want to intercept: the tab IDs
                    // and request URLs match.
                    headers.forEach(function (header) {
                        switch (header.name.toLowerCase()) {
                        case 'content-type':
                            header.value = media_type;
                            break;
                        case 'content-disposition':
                            // See <http://tools.ietf.org/html/rfc2183>
                            header.value = 'inline';
                            break;
                        case 'location':
                            is_redirect = true;
                            target_url = header.value;
                            break;
                        }
                    });
                    headers_received.removeListener(patch_headers);
                    // If it's a redirect, re-add a listener, specifying the
                    // new url as the url filter
                    if (is_redirect) {
                        headers_received.addListener(
                            patch_headers(media_type),
                            {urls: [target_url]},
                            ['blocking', 'responseHeaders']
                        );
                    }
                }
                return {responseHeaders: headers};
            };
            return callback;
        },
        click_handler = function (media_type) {
            // Handle a context menu item click
            var handler = function (info) {
                // Open the requested url in a new tab
                target_url = info.linkUrl;
                headers_received.addListener(
                    patch_headers(media_type),
                    {urls: [target_url]},
                    ['blocking', 'responseHeaders']
                );
                chrome.tabs.create({url: target_url}, function (tab) {
                    target_tab = tab.id;
                });
            };
            return handler;
        },
        uniquify = function (array) {
            // Remove duplicate items from array
            return array.filter(function (val, i) {
                return i === array.indexOf(val);
            });
        },
        build_menus = function () {
            // Create right-click context menu items
            var extra_types = (localStorage.extra_types || '').split('\n'),
                types = uniquify(media_types.concat(extra_types)),
                parent_id;

            parent_id = chrome.contextMenus.create({
                title: "Open as media type\u2026",
                contexts: ['link']
            });

            types.forEach(function (media_type) {
                chrome.contextMenus.create({
                    title: media_type,
                    contexts: ['link'],
                    parentId: parent_id,
                    onclick: click_handler(media_type)
                });
            });
        },
        options_updated_handler = function (e) {
            // Listen to StorageEvents and update menus as necessary
            if (e.key === 'extra_types' && e.newValue !== e.oldValue) {
                chrome.contextMenus.removeAll(build_menus);
            }
        };
    build_menus();
    window.addEventListener('storage', options_updated_handler);
}());
<commit_msg>add separator between default and custom types<commit_after>/*!
 * Open as Media Type Chrome Extension
 *
 * Copyright 2012, Ori Livneh
 * Licensed under the BSD license; see LICENSE for more details.
 */

/*jslint maxerr: 50, maxlen: 80, indent: 4 */
/*global chrome: true */

(function () {
    "use strict";
    var headers_received = chrome.webRequest.onHeadersReceived,
        media_types = ['text/html', 'text/plain'],
        target_tab = 0,
        target_url = '',
        patch_headers = function (media_type) {
            var callback = function (details) {
                var headers = details.responseHeaders,
                    is_redirect = false;

                if (details.tabId === target_tab) {
                    // This is the request we want to intercept: the tab IDs
                    // and request URLs match.
                    headers.forEach(function (header) {
                        switch (header.name.toLowerCase()) {
                        case 'content-type':
                            header.value = media_type;
                            break;
                        case 'content-disposition':
                            // See <http://tools.ietf.org/html/rfc2183>
                            header.value = 'inline';
                            break;
                        case 'location':
                            is_redirect = true;
                            target_url = header.value;
                            break;
                        }
                    });
                    headers_received.removeListener(patch_headers);
                    // If it's a redirect, re-add a listener, specifying the
                    // new url as the url filter
                    if (is_redirect) {
                        headers_received.addListener(
                            patch_headers(media_type),
                            {urls: [target_url]},
                            ['blocking', 'responseHeaders']
                        );
                    }
                }
                return {responseHeaders: headers};
            };
            return callback;
        },
        click_handler = function (media_type) {
            // Handle a context menu item click
            var handler = function (info) {
                // Open the requested url in a new tab
                target_url = info.linkUrl;
                headers_received.addListener(
                    patch_headers(media_type),
                    {urls: [target_url]},
                    ['blocking', 'responseHeaders']
                );
                chrome.tabs.create({url: target_url}, function (tab) {
                    target_tab = tab.id;
                });
            };
            return handler;
        },
        uniquify = function (array) {
            // Remove duplicate items from array
            return array.filter(function (val, i) {
                return i === array.indexOf(val);
            });
        },
        build_menus = function () {
            // Create right-click context menu items
            var extra_types = (localStorage.extra_types || '').split('\n'),
                types = uniquify(media_types.concat(extra_types)),
                parent_id;

            parent_id = chrome.contextMenus.create({
                title: "Open as media type\u2026",
                contexts: ['link']
            });

            types.forEach(function (media_type, index) {
                // Create at separator before user-set media types
                if (index === media_types.length) {
                    chrome.contextMenus.create({
                        type: 'separator',
                        contexts: ['link'],
                        parentId: parent_id,
                    });
                }
                // Create the menu item for this type
                chrome.contextMenus.create({
                    title: media_type,
                    contexts: ['link'],
                    parentId: parent_id,
                    onclick: click_handler(media_type)
                });
            });
        },
        options_updated_handler = function (e) {
            // Listen to StorageEvents and update menus as necessary
            if (e.key === 'extra_types' && e.newValue !== e.oldValue) {
                chrome.contextMenus.removeAll(build_menus);
            }
        };
    build_menus();
    window.addEventListener('storage', options_updated_handler);
}());
<|endoftext|>


<commit_before>hqDefine('app_manager/js/manage_releases_by_app_profile', [
    'jquery',
    'knockout',
    'underscore',
    'hqwebapp/js/initial_page_data',
    'hqwebapp/js/assert_properties',
    'translations/js/app_translations',
], function (
    $,
    ko,
    _,
    initialPageData,
    assertProperties
) {
    'use strict';
    $(function () {
        var AppRelease = function (details) {
            var self = {};
            assertProperties.assertRequired(details, ['id', 'app_id', 'active', 'app_name', 'profile_name',
                'version']);
            self.id = details.id;
            self.active = ko.observable(details.active);
            self.status = details.active ? gettext('Active') : gettext('Inactive');
            self.appName = details.app_name;
            self.version = details.version;
            self.profileName = details.profile_name;
            self.domId = "restriction_" + self.id;
            self.errorMessage = ko.observable();
            self.ajaxInProgress = ko.observable(false);
            self.actionText = ko.computed(function () {
                return (self.active() ? gettext("Remove") : gettext("Add"));
            });
            self.buttonClass = ko.computed(function () {
                return (self.active() ? "btn-danger" : "btn-success");
            });
            self.toggleStatus = function () {
                self.active(!self.active());
            };
            self.error = ko.observable();
            self.requestUrl = initialPageData.reverse('toggle_release_restriction_by_app_profile', self.id);
            self.toggleRestriction = function () {
                self.ajaxInProgress(true);
                var oldStatus = self.active();
                $.ajax({
                    method: 'POST',
                    url: self.requestUrl,
                    data: {'active': !self.active()},
                    success: function (data) {
                        if (data.success) {
                            self.toggleStatus();
                            self.error(false);
                        } else {
                            self.active(oldStatus);
                            self.errorMessage(data.message);
                        }
                    },
                    error: function () {
                        self.active(oldStatus);
                    },
                    complete: function () {
                        self.ajaxInProgress(false);
                        if (self.active() === oldStatus) {
                            self.error(true);
                        }
                    },
                });
            };
            return self;
        };

        function manageReleaseSearchViewModel() {
            var self = {};
            self.search = function () {
                var appId = $("#app-id-search-select").val();
                var profileId = $("#app-profile-id-input").val() || '';
                var version = $("#version-input").val() || '';
                window.location.search = ("build_profile_id=" + profileId + "&app_id=" + appId + "&version=" +
                    version);
            };
            self.clear = function () {
                window.location.search = "";
            };
            return self;
        }

        var appReleasesByAppProfile = _.map(initialPageData.get('app_releases_by_app_profile'), AppRelease);
        if (appReleasesByAppProfile.length) {
            $('#managed-releases').koApplyBindings({
                'appReleasesByAppProfile': ko.observableArray(appReleasesByAppProfile),
            });
        }
        var searchViewModel = manageReleaseSearchViewModel();
        $("#manage-app-releases").koApplyBindings(searchViewModel);
    });
});
<commit_msg>make status computed so that it updates with active field in UI<commit_after>hqDefine('app_manager/js/manage_releases_by_app_profile', [
    'jquery',
    'knockout',
    'underscore',
    'hqwebapp/js/initial_page_data',
    'hqwebapp/js/assert_properties',
    'translations/js/app_translations',
], function (
    $,
    ko,
    _,
    initialPageData,
    assertProperties
) {
    'use strict';
    $(function () {
        var AppRelease = function (details) {
            var self = {};
            assertProperties.assertRequired(details, ['id', 'app_id', 'active', 'app_name', 'profile_name',
                'version']);
            self.id = details.id;
            self.active = ko.observable(details.active);
            self.status = ko.computed(function() {
                return (self.active() ? gettext("Active") : gettext("Inactive"));
            })
            self.appName = details.app_name;
            self.version = details.version;
            self.profileName = details.profile_name;
            self.domId = "restriction_" + self.id;
            self.errorMessage = ko.observable();
            self.ajaxInProgress = ko.observable(false);
            self.actionText = ko.computed(function () {
                return (self.active() ? gettext("Remove") : gettext("Add"));
            });
            self.buttonClass = ko.computed(function () {
                return (self.active() ? "btn-danger" : "btn-success");
            });
            self.toggleStatus = function () {
                self.active(!self.active());
            };
            self.error = ko.observable();
            self.requestUrl = initialPageData.reverse('toggle_release_restriction_by_app_profile', self.id);
            self.toggleRestriction = function () {
                self.ajaxInProgress(true);
                var oldStatus = self.active();
                $.ajax({
                    method: 'POST',
                    url: self.requestUrl,
                    data: {'active': !self.active()},
                    success: function (data) {
                        if (data.success) {
                            self.toggleStatus();
                            self.error(false);
                        } else {
                            self.active(oldStatus);
                            self.errorMessage(data.message);
                        }
                    },
                    error: function () {
                        self.active(oldStatus);
                    },
                    complete: function () {
                        self.ajaxInProgress(false);
                        if (self.active() === oldStatus) {
                            self.error(true);
                        }
                    },
                });
            };
            return self;
        };

        function manageReleaseSearchViewModel() {
            var self = {};
            self.search = function () {
                var appId = $("#app-id-search-select").val();
                var profileId = $("#app-profile-id-input").val() || '';
                var version = $("#version-input").val() || '';
                window.location.search = ("build_profile_id=" + profileId + "&app_id=" + appId + "&version=" +
                    version);
            };
            self.clear = function () {
                window.location.search = "";
            };
            return self;
        }

        var appReleasesByAppProfile = _.map(initialPageData.get('app_releases_by_app_profile'), AppRelease);
        if (appReleasesByAppProfile.length) {
            $('#managed-releases').koApplyBindings({
                'appReleasesByAppProfile': ko.observableArray(appReleasesByAppProfile),
            });
        }
        var searchViewModel = manageReleaseSearchViewModel();
        $("#manage-app-releases").koApplyBindings(searchViewModel);
    });
});
<|endoftext|>


<commit_before>'use strict'

const debug = require('debug')('koa-restql:common');

const defaultLimit = 20;

module.exports.getAssociationName = (association) => {
    let isSingular  = association.isSingleAssociation
      , name        = association.options.name;

    return isSingular ? name.singular : name.plural;
}

const parseAttributes = (_attributes) => {
  let attrs;

  if (Array.isArray(_attributes)) {
    attrs = _attributes;
  } else if (typeof _attributes === 'string') {
    attrs = _attributes.split(/(,|\ )/);
  }

  return attrs;
}

const unionAttributes = (_attributes, attributes) => {

  if (typeof _attributes === 'object') {
    if (_attributes.include) {
      /**
       * @FIXME
       *
       * This is a bug in Sequelize
       * include doesn't work at all
       */
      _attributes.include = parseAttributes(_attributes.include);
    }
    if (_attributes.exclude) {
      _attributes.exclude = parseAttributes(_attributes.exclude);
    }
  } else {
    return parseAttributes(_attributes);
  }

  return _attributes;
}

const unionWhere = (_where, attributes) => {
  if (!_where || typeof _where !== 'object')
    return;

  let where;

  Object.keys(_where).forEach(key => {
    if (!/^_/.test(key)) {
      where = where || {};
      where[key] = _where[key];
    }
  })

  return where;
}

const unionOrder = (_order, attributes) => {
  if (!_order)
    return;

  if (Array.isArray(_order)) {
    if (!_order.length)
      return;

    return _order.filter(item => {
      if (!item)
        return false;

      let name;
      if (Array.isArray(item)) {
        name = item[0];
      } else if (typeof item === 'string'){
        name = item.split(' ')[0];
      }
      return name && !!attributes[name];
    }).map(item => {
      if (typeof item === 'string') {
        return item.split(' ');
      }
      return item;
    })
  } else if (typeof _order === 'string') {
    let order = _order.split(' ');
    if (attributes[order[0]]) {
      return [order];
    }
  }
}

const shouldIgnoreAssociation = (method, options) => {

  options = options || {}

  let ignore  = options.ignore;

  switch (typeof ignore) {
    case 'object':
      if (Array.isArray(ignore)) {
        if (ignore.indexOf(method.name) !== -1)
          return true;
      }
      break;
    case 'boolean':
      if (ignore) return true;
      break;
    default:
      break;
  }

  return false;
}

const parseInclude = (_include, associations, method) => {

  let include, association, where, attributes, through, required;

  if ('string' === typeof _include) {

    association = associations[_include];
    if (!association)
      return;

    if (shouldIgnoreAssociation(method, association.options.restql))
      return;

  } else if ('object' === typeof _include) {

    where       = _include.where;
    attributes  = _include.attributes;
    required    = _include.required;
    through     = _include.through;

    association = associations[_include.association];

    if (!association)
      return;

    let options = association.options
    if (shouldIgnoreAssociation(method, association.options.restql))
      return;

    if (_include.include) {
      include = unionInclude(_include.include, association.target.associations);
    }
  }

  return {
    where, attributes, through, association, required,
    include: include || []
  }
}

const unionInclude = (_include, associations, method) => {
  if (!_include)
    return;

  if (Array.isArray(_include)) {
    return _include.map(item => {
      return parseInclude(item, associations, method);
    }).filter(item => item);
  } else {
    let include = parseInclude(_include, associations, method);
    return include ? [ include ] : [];
  }
}

module.exports.parseQuery = (query, model, method) => {

  let attributes = model.attributes;

  debug(query);

  let _where      = unionWhere(query, attributes)
    , _attributes = unionAttributes(query._attributes, attributes)
    , _order      = unionOrder(query._order, attributes)
    , _through    = query._through
    , _include    = unionInclude(query._include, model.associations, method)
    , _offset     = query._offset ? +query._offset : 0
    , _limit      = query._limit ? +query._limit : defaultLimit
    , _ignoreDuplicates = query._ignoreDuplicates;

  debug(_where);
  debug(_attributes);
  debug(_order);
  debug(_through);
  debug(_include);
  debug(_offset);
  debug(_limit);
  debug(_ignoreDuplicates);

  return {
    _offset           : _offset,
    _limit            : _limit,
    _order            : _order,
    _where            : _where,
    _through          : _through,
    _include          : _include || [],
    _attributes       : _attributes || Object.keys(model.attributes),
    _ignoreDuplicates : _ignoreDuplicates
  };
}

module.exports.shouldIgnoreAssociation = shouldIgnoreAssociation;
<commit_msg>Fixed<commit_after>'use strict'

const debug = require('debug')('koa-restql:common');

const defaultLimit = 20;

module.exports.getAssociationName = (association) => {
    let isSingular  = association.isSingleAssociation
      , name        = association.options.name;

    return isSingular ? name.singular : name.plural;
}

const parseAttributes = (_attributes) => {
  let attrs;

  if (Array.isArray(_attributes)) {
    attrs = _attributes;
  } else if (typeof _attributes === 'string') {
    attrs = _attributes.split(/(,|\ )/);
  }

  return attrs;
}

const unionAttributes = (_attributes, attributes) => {

  if (typeof _attributes === 'object') {
    if (_attributes.include) {
      /**
       * @FIXME
       *
       * This is a bug in Sequelize
       * include doesn't work at all
       */
      _attributes.include = parseAttributes(_attributes.include);
    }
    if (_attributes.exclude) {
      _attributes.exclude = parseAttributes(_attributes.exclude);
    }
  } else {
    return parseAttributes(_attributes);
  }

  return _attributes;
}

const unionWhere = (_where, attributes) => {
  if (!_where || typeof _where !== 'object')
    return;

  let where;

  Object.keys(_where).forEach(key => {
    if (!/^_/.test(key)) {
      where = where || {};
      where[key] = _where[key];
    }
  })

  return where;
}

const unionOrder = (_order, attributes) => {
  if (!_order)
    return;

  if (Array.isArray(_order)) {
    if (!_order.length)
      return;

    return _order.filter(item => {
      if (!item)
        return false;

      let name;
      if (Array.isArray(item)) {
        name = item[0];
      } else if (typeof item === 'string'){
        name = item.split(' ')[0];
      }
      return name && !!attributes[name];
    }).map(item => {
      if (typeof item === 'string') {
        return item.split(' ');
      }
      return item;
    })
  } else if (typeof _order === 'string') {
    let order = _order.split(' ');
    if (attributes[order[0]]) {
      return [order];
    }
  }
}

const shouldIgnoreAssociation = (method, options) => {

  options = options || {}

  let ignore  = options.ignore;

  switch (typeof ignore) {
    case 'object':
      if (Array.isArray(ignore)) {
        if (ignore.indexOf(method.name) !== -1)
          return true;
      }
      break;
    case 'boolean':
      if (ignore) return true;
      break;
    default:
      break;
  }

  return false;
}

const parseInclude = (_include, associations, method) => {

  let include, association, where, attributes, through, required;

  if ('string' === typeof _include) {

    association = associations[_include];
    if (!association)
      return;

    if (shouldIgnoreAssociation(method, association.options.restql))
      return;

  } else if ('object' === typeof _include) {

    where       = _include.where;
    attributes  = _include.attributes;
    required    = !!+_include.required;
    through     = _include.through;

    association = associations[_include.association];

    if (!association)
      return;

    let options = association.options
    if (shouldIgnoreAssociation(method, association.options.restql))
      return;

    if (_include.include) {
      include = unionInclude(_include.include, association.target.associations);
    }
  }

  return {
    where, attributes, through, association, required,
    include: include || []
  }
}

const unionInclude = (_include, associations, method) => {
  if (!_include)
    return;

  if (Array.isArray(_include)) {
    return _include.map(item => {
      return parseInclude(item, associations, method);
    }).filter(item => item);
  } else {
    let include = parseInclude(_include, associations, method);
    return include ? [ include ] : [];
  }
}

module.exports.parseQuery = (query, model, method) => {

  let attributes = model.attributes;

  debug(query);

  let _where      = unionWhere(query, attributes)
    , _attributes = unionAttributes(query._attributes, attributes)
    , _order      = unionOrder(query._order, attributes)
    , _through    = query._through
    , _include    = unionInclude(query._include, model.associations, method)
    , _offset     = query._offset ? +query._offset : 0
    , _limit      = query._limit ? +query._limit : defaultLimit
    , _ignoreDuplicates = query._ignoreDuplicates;

  debug(_where);
  debug(_attributes);
  debug(_order);
  debug(_through);
  debug(_include);
  debug(_offset);
  debug(_limit);
  debug(_ignoreDuplicates);

  return {
    _offset           : _offset,
    _limit            : _limit,
    _order            : _order,
    _where            : _where,
    _through          : _through,
    _include          : _include || [],
    _attributes       : _attributes || Object.keys(model.attributes),
    _ignoreDuplicates : _ignoreDuplicates
  };
}

module.exports.shouldIgnoreAssociation = shouldIgnoreAssociation;
<|endoftext|>


<commit_before>exports.up = async knex => {
  await knex.raw(
    'alter table articles add fulltext `article-search-index` (title, markdown)',
  );
  // Using a raw query above since knex does not support fulltext indexing
};

exports.down = async knex => {
  await knex.schema.table('articles', table => {
    table.dropIndex(['title', 'markdown'], 'article-search-index');
  });
};
<commit_msg>Capitalized the sql commands for clarity<commit_after>exports.up = async knex => {
  await knex.raw(
    'ALTER TABLE articles ADD FULLTEXT `article-search-index` (title, markdown)',
  );
  // Using a raw query above since knex does not support fulltext indexing
};

exports.down = async knex => {
  await knex.schema.table('articles', table => {
    table.dropIndex(['title', 'markdown'], 'article-search-index');
  });
};
<|endoftext|>


<commit_before>//Escaping regexes
var AMP_REGEX = /&/g,
    NBSP_REGEX = /\u00a0/g,
    DOUBLE_QUOTE_REGEX = /"/g,
    LT_REGEX = /</g,
    GT_REGEX = />/g;

//Escape string
exports.escapeHtml = function (str, attrMode) {
    str = str
        .replace(AMP_REGEX, '&')
        .replace(NBSP_REGEX, ' ');

    if (attrMode)
        str = str.replace(DOUBLE_QUOTE_REGEX, '"');

    else {
        str = str
            .replace(LT_REGEX, '<')
            .replace(GT_REGEX, '>');
    }

    return str;
};

var getAttrValue = exports.getAttrValue = function (attrs, attrName) {
    for (var i = 0; i < attrs.length; i++) {
        if (attrs[i].name.toLowerCase() === attrName)
            return attrs[i].value;
    }

    return null;
};

exports.setAttrValue = function (attrs, attrName, value) {
    for (var i = 0; i < attrs.length; i++) {
        if (attrs[i].name.toLowerCase() === attrName) {
            attrs[i].value = value;
            break;
        }
    }
};

exports.isStylesheet = function (startTag) {
    if (startTag.tagName === 'link') {
        var relAttr = getAttrValue(startTag.attrs, 'rel');

        return relAttr && relAttr.toLowerCase() === 'stylesheet';
    }

    return false;
};

exports.isPlainText = function (inBody, leadingStartTag, text) {
    return inBody &&
           leadingStartTag !== 'script' &&
           leadingStartTag !== 'style' &&
           text.trim().length > 0;
};<commit_msg>Update common.js<commit_after>//Escaping regexes
var AMP_REGEX = /&/g,
    NBSP_REGEX = /\u00a0/g,
    DOUBLE_QUOTE_REGEX = /"/g,
    LT_REGEX = /</g,
    GT_REGEX = />/g;

exports.escapeHtml = function (str, attrMode) {
    str = str
        .replace(AMP_REGEX, '&')
        .replace(NBSP_REGEX, ' ');

    if (attrMode)
        str = str.replace(DOUBLE_QUOTE_REGEX, '"');

    else {
        str = str
            .replace(LT_REGEX, '<')
            .replace(GT_REGEX, '>');
    }

    return str;
};

var getAttrValue = exports.getAttrValue = function (attrs, attrName) {
    for (var i = 0; i < attrs.length; i++) {
        if (attrs[i].name.toLowerCase() === attrName)
            return attrs[i].value;
    }

    return null;
};

exports.setAttrValue = function (attrs, attrName, value) {
    for (var i = 0; i < attrs.length; i++) {
        if (attrs[i].name.toLowerCase() === attrName) {
            attrs[i].value = value;
            break;
        }
    }
};

exports.isStylesheet = function (startTag) {
    if (startTag.tagName === 'link') {
        var relAttr = getAttrValue(startTag.attrs, 'rel');

        return relAttr && relAttr.toLowerCase() === 'stylesheet';
    }

    return false;
};

exports.isPlainText = function (inBody, leadingStartTag, text) {
    return inBody &&
           leadingStartTag !== 'script' &&
           leadingStartTag !== 'style' &&
           text.trim().length > 0;
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
  Text,
  View,
  Image,
  TouchableHighlight,
  TouchableOpacity,
  Switch
} from 'react-native';
import styles from '../styles.ios.js';
import Nav from './Navbar.ios.js';
import SearchBar from './Searchbar.ios.js';
import { connect } from "react-redux";
import {bindActionCreators} from 'redux';
import * as app from '../actions/appActions.ios.js';
import getApp from '../reducers/appReducers.ios.js';
import camera from './Camera.ios.js';
import FacebookLogin from './FacebookLogin.ios.js';

class App extends Component {
  constructor(props) {
    super(props);
  }

  border(color) {
    return {
      borderColor: color,
      borderWidth: 5,
    }
  }

  changeNavigationHome() {
    this.props.navigator.push({
      id: 'Home'
    })
  }

  changeNavigationCamera() {
    this.props.navigator.push({
      component: camera,
      passProps: { store: this.props.store }
    })
  }

  rendering() {
    actions.rendering();
    this.forceUpdate()
  }
  render() {
    const {state, actions} = this.props;
    if (state.rendering) {
      return (
        <Image
          source= {{uri: 'https://media.blueapron.com/assets/loader/pot-loader-6047abec2ec57c18d848f623c036f7fe80236dce689bb48279036c4f914d0c9e.gif'}}
          style = {styles.loadingGif}
        />
      )
    }
    return (
      <View style={[styles.container]}>
        <View style={[styles.navigation]} >
          <Nav
            changeNavigationCamera={this.changeNavigationCamera.bind(this)}
          />
        </View>
        <View style={styles.app} >
          <Image style={styles.welcomeImage} source={require('../snacktimewelcome.jpg')}/>
          <FacebookLogin />
        </View>
        { /* conditional camera / search bar render */
          state.showSearchBar
            ?
              (
                <View style={[styles.searchBarPictureFrame]} >
                  <SearchBar store={this.props.store}
                             navigator={this.props.navigator}
                             rendering={actions.rendering}
                             lagOut={actions.laggedOut}
                             isRendering={state.rendering}
                  />
                </View>
              )
            :
              (
                <TouchableHighlight style={[styles.buttonView]}
                                    onPress={this.changeNavigationCamera.bind(this)}>
                  <Image
                    style={[styles.takePicture]}
                    source={{uri: 'https://s3.amazonaws.com/features.ifttt.com/newsletter_images/2015_February/camera512x512+(1).png'}}
                  />
                </TouchableHighlight>
              )
        }
        <View style={{flexDirection: 'row'}}>
          <Switch
            onValueChange={actions.showSearchBar}
            style={styles.switch}
            value={state.showSearchBar}
          />
        </View>
      </View>
    );
  }
}

export default connect(state => ({
    state: state.app
  }),
  (dispatch) => ({
    actions: bindActionCreators(app.default, dispatch)
  })
)(App);
<commit_msg>(config) Moved/organized static assets into Public/ folder<commit_after>import React, { Component } from 'react';
import {
  Text,
  View,
  Image,
  TouchableHighlight,
  TouchableOpacity,
  Switch
} from 'react-native';
import styles from '../styles.ios.js';
import Nav from './Navbar.ios.js';
import SearchBar from './Searchbar.ios.js';
import { connect } from "react-redux";
import {bindActionCreators} from 'redux';
import * as app from '../actions/appActions.ios.js';
import getApp from '../reducers/appReducers.ios.js';
import camera from './Camera.ios.js';
import FacebookLogin from './FacebookLogin.ios.js';

class App extends Component {
  constructor(props) {
    super(props);
  }

  border(color) {
    return {
      borderColor: color,
      borderWidth: 5,
    }
  }

  changeNavigationHome() {
    this.props.navigator.push({
      id: 'Home'
    })
  }

  changeNavigationCamera() {
    this.props.navigator.push({
      component: camera,
      passProps: { store: this.props.store }
    })
  }

  rendering() {
    actions.rendering();
    this.forceUpdate()
  }
  render() {
    const {state, actions} = this.props;
    if (state.rendering) {
      return (
        <Image
          source= {{uri: 'https://media.blueapron.com/assets/loader/pot-loader-6047abec2ec57c18d848f623c036f7fe80236dce689bb48279036c4f914d0c9e.gif'}}
          style = {styles.loadingGif}
        />
      )
    }
    return (
      <View style={[styles.container]}>
        <View style={[styles.navigation]} >
          <Nav
            changeNavigationCamera={this.changeNavigationCamera.bind(this)}
          />
        </View>
        <View style={styles.app} >
          <Image style={styles.welcomeImage} source={require('../public/snacktimewelcome.jpg')}/>
          <FacebookLogin />
        </View>
        { /* conditional camera / search bar render */
          state.showSearchBar
            ?
              (
                <View style={[styles.searchBarPictureFrame]} >
                  <SearchBar store={this.props.store}
                             navigator={this.props.navigator}
                             rendering={actions.rendering}
                             lagOut={actions.laggedOut}
                             isRendering={state.rendering}
                  />
                </View>
              )
            :
              (
                <TouchableHighlight style={[styles.buttonView]}
                                    onPress={this.changeNavigationCamera.bind(this)}>
                  <Image
                    style={[styles.takePicture]}
                    source={{uri: 'https://s3.amazonaws.com/features.ifttt.com/newsletter_images/2015_February/camera512x512+(1).png'}}
                  />
                </TouchableHighlight>
              )
        }
        <View style={{flexDirection: 'row'}}>
          <Switch
            onValueChange={actions.showSearchBar}
            style={styles.switch}
            value={state.showSearchBar}
          />
        </View>
      </View>
    );
  }
}

export default connect(state => ({
    state: state.app
  }),
  (dispatch) => ({
    actions: bindActionCreators(app.default, dispatch)
  })
)(App);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';

class Content extends Component {
  static displayName = 'Content';

  static propTypes = {
    backgroundColor: PropTypes.objectOf(PropTypes.string),
    output: PropTypes.arrayOf(PropTypes.element),
    prompt: PropTypes.objectOf(PropTypes.string),
    inputStyles: PropTypes.objectOf(PropTypes.string),
    handleChange: PropTypes.func,
    setHistoryCommand: PropTypes.func,
  };

  static contextTypes = {
    symbol: PropTypes.string,
    maximise: PropTypes.bool,
  };

  componentDidMount = () => {
    this.focusInput();
  };

  componentDidUpdate = () => {
    this.inputWrapper.scrollIntoView(false);
  }

  focusInput = () => {
    this.com.focus();
  };

  render() {
    const {
      backgroundColor,
      output,
      prompt,
      inputStyles,
      handleChange,
      setHistoryCommand,
    } = this.props;
    const { symbol, maximise } = this.context;

    return (

              {output}

 (this.inputWrapper = elm)}>
                {symbol}
                <input
                  className="terminal-main-input"
                  style={inputStyles}
                  type="text"
                  ref={com => (this.com = com)}
                  onKeyPress={handleChange}
                  onKeyDown={(e)=> setHistoryCommand(e, this.com)}
                />

    );
  }
}

export default Content;
<commit_msg>some changes<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';

class Content extends Component {
  static displayName = 'Content';

  static propTypes = {
    backgroundColor: PropTypes.objectOf(PropTypes.string),
    output: PropTypes.arrayOf(PropTypes.element),
    prompt: PropTypes.objectOf(PropTypes.string),
    inputStyles: PropTypes.objectOf(PropTypes.string),
    handleChange: PropTypes.func,
    setHistoryCommand: PropTypes.func,
  };

  static contextTypes = {
    symbol: PropTypes.string,
    maximise: PropTypes.bool,
  };

  componentDidMount = () => {
    this.focusInput();
  };

  componentDidUpdate = () => {
    this.inputWrapper.scrollIntoView(false);
  }

  focusInput = () => {
    this.com.focus();
  };

  render() {
    const {
      backgroundColor,
      output,
      prompt,
      inputStyles,
      handleChange,
      setHistoryCommand,
    } = this.props;
    const { symbol, maximise } = this.context;

    return (

              {output}

 (this.inputWrapper = elm)}>
                {symbol}
                <input
                  className="terminal-main-input"
                  style={inputStyles}
                  type="text"
                  ref={com => (this.com = com)}
                  onKeyPress={handleChange}
                  onKeyDown={(e) => setHistoryCommand(e, this.com)}
                />

    );
  }
}

export default Content;
<|endoftext|>


<commit_before>// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you 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.

import $ from 'jquery';
import * as ko from 'knockout';

import dataCatalog from 'catalog/dataCatalog';
import huePubSub from 'utils/huePubSub';
import I18n from 'utils/i18n';
import sqlUtils from 'sql/sqlUtils';

class AsteriskData {
  constructor(data, connector, namespace, compute, defaultDatabase) {
    const self = this;
    self.loading = ko.observable(true);
    self.hasErrors = ko.observable(false);
    self.columns = [];

    self.selectedColumns = ko.pureComputed(() => {
      return self.columns.filter(column => {
        return column.selected();
      });
    });

    self.expand = function () {
      const colsToExpand =
        self.selectedColumns().length === 0 ? self.columns : self.selectedColumns();
      const colIndex = {};
      const colsTableMap = {};
      self.columns.forEach(col => {
        if (colsTableMap[col.name]) {
          colsTableMap[col.name].push(col.table);
        } else {
          colsTableMap[col.name] = [col.table];
        }
      });
      colsToExpand.forEach(col => {
        if (colIndex[col.name]) {
          colIndex[col.name]++;
        } else {
          colIndex[col.name] = 1;
        }
      });
      Object.keys(colIndex).forEach(name => {
        if (colIndex[name] === 1 && colsTableMap[name].length === 1) {
          delete colIndex[name];
        }
      });

      Promise.all(
        colsToExpand.map(async column => {
          if (column.tableAlias) {
            return (
              (await sqlUtils.backTickIfNeeded(connector, column.tableAlias)) +
              '.' +
              (await sqlUtils.backTickIfNeeded(connector, column.name))
            );
          }
          if (colIndex[column.name]) {
            return (
              (await sqlUtils.backTickIfNeeded(connector, column.table)) +
              '.' +
              (await sqlUtils.backTickIfNeeded(connector, column.name))
            );
          }
          return await sqlUtils.backTickIfNeeded(connector, column.name);
        })
      ).then(backtickedCols => {
        huePubSub.publish('ace.replace', {
          location: data.location,
          text: backtickedCols.join(', ')
        });
      });

      huePubSub.publish('context.popover.hide');
    };

    const deferrals = [];
    data.tables.forEach(table => {
      if (table.identifierChain) {
        const fetchDeferred = $.Deferred();
        deferrals.push(fetchDeferred);
        const path = $.map(table.identifierChain, identifier => {
          return identifier.name;
        });
        if (path.length === 1) {
          path.unshift(defaultDatabase);
        }
        dataCatalog
          .getEntry({
            namespace: namespace,
            compute: compute,
            connector: connector,
            path: path
          })
          .then(entry => {
            entry
              .getSourceMeta({ silenceErrors: true })
              .then(sourceMeta => {
                if (typeof sourceMeta.extended_columns !== 'undefined') {
                  const newColumns = [];
                  sourceMeta.extended_columns.forEach(column => {
                    const clonedColumn = $.extend({}, column);
                    clonedColumn.extendedType = clonedColumn.type
                      .replace(/</g, '<')
                      .replace(/>/g, '<');
                    if (clonedColumn.type.indexOf('<') !== -1) {
                      clonedColumn.type = clonedColumn.type.substring(
                        0,
                        clonedColumn.type.indexOf('<')
                      );
                    }
                    clonedColumn.selected = ko.observable(false);
                    clonedColumn.table =
                      table.identifierChain[table.identifierChain.length - 1].name;
                    if (table.alias) {
                      clonedColumn.tableAlias = table.alias;
                    }
                    newColumns.push(clonedColumn);
                  });
                  self.columns = self.columns.concat(newColumns);
                }
                fetchDeferred.resolve();
              })
              .catch(fetchDeferred.reject);
          })
          .catch(fetchDeferred.reject);
      }
    });

    if (deferrals.length === 0) {
      self.loading(false);
    }
    $.when.apply($, deferrals).done(
      () => {
        self.loading(false);
      },
      () => {
        if (self.columns.length === 0) {
          self.hasErrors(true);
        }
      }
    );
  }
}

class AsteriskContextTabs {
  constructor(data, connector, namespace, compute, defaultDatabase) {
    const self = this;
    self.data = new AsteriskData(data, connector, namespace, compute, defaultDatabase);

    self.tabs = [
      {
        id: 'details',
        label: I18n('Details'),
        template: 'context-popover-asterisk-details',
        templateData: self.data
      }
    ];
    self.activeTab = ko.observable('details');
  }
}

export default AsteriskContextTabs;
<commit_msg>[editor] Fix asterisk expansion of selected columns<commit_after>// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you 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.

import $ from 'jquery';
import * as ko from 'knockout';

import dataCatalog from 'catalog/dataCatalog';
import huePubSub from 'utils/huePubSub';
import I18n from 'utils/i18n';
import sqlUtils from 'sql/sqlUtils';

class AsteriskData {
  constructor(data, connector, namespace, compute, defaultDatabase) {
    const self = this;
    self.loading = ko.observable(true);
    self.hasErrors = ko.observable(false);
    self.columns = [];

    self.selectedColumns = ko.pureComputed(
      () => (!self.loading() && self.columns.filter(column => column.selected())) || []
    );

    self.expand = function () {
      const colsToExpand =
        self.selectedColumns().length === 0 ? self.columns : self.selectedColumns();
      const colIndex = {};
      const colsTableMap = {};
      self.columns.forEach(col => {
        if (colsTableMap[col.name]) {
          colsTableMap[col.name].push(col.table);
        } else {
          colsTableMap[col.name] = [col.table];
        }
      });
      colsToExpand.forEach(col => {
        if (colIndex[col.name]) {
          colIndex[col.name]++;
        } else {
          colIndex[col.name] = 1;
        }
      });
      Object.keys(colIndex).forEach(name => {
        if (colIndex[name] === 1 && colsTableMap[name].length === 1) {
          delete colIndex[name];
        }
      });

      Promise.all(
        colsToExpand.map(async column => {
          if (column.tableAlias) {
            return (
              (await sqlUtils.backTickIfNeeded(connector, column.tableAlias)) +
              '.' +
              (await sqlUtils.backTickIfNeeded(connector, column.name))
            );
          }
          if (colIndex[column.name]) {
            return (
              (await sqlUtils.backTickIfNeeded(connector, column.table)) +
              '.' +
              (await sqlUtils.backTickIfNeeded(connector, column.name))
            );
          }
          return await sqlUtils.backTickIfNeeded(connector, column.name);
        })
      ).then(backtickedCols => {
        huePubSub.publish('ace.replace', {
          location: data.location,
          text: backtickedCols.join(', ')
        });
      });

      huePubSub.publish('context.popover.hide');
    };

    const deferrals = [];
    data.tables.forEach(table => {
      if (table.identifierChain) {
        const fetchDeferred = $.Deferred();
        deferrals.push(fetchDeferred);
        const path = $.map(table.identifierChain, identifier => {
          return identifier.name;
        });
        if (path.length === 1) {
          path.unshift(defaultDatabase);
        }
        dataCatalog
          .getEntry({
            namespace: namespace,
            compute: compute,
            connector: connector,
            path: path
          })
          .then(entry => {
            entry
              .getSourceMeta({ silenceErrors: true })
              .then(sourceMeta => {
                if (typeof sourceMeta.extended_columns !== 'undefined') {
                  const newColumns = [];
                  sourceMeta.extended_columns.forEach(column => {
                    const clonedColumn = $.extend({}, column);
                    clonedColumn.extendedType = clonedColumn.type
                      .replace(/</g, '<')
                      .replace(/>/g, '<');
                    if (clonedColumn.type.indexOf('<') !== -1) {
                      clonedColumn.type = clonedColumn.type.substring(
                        0,
                        clonedColumn.type.indexOf('<')
                      );
                    }
                    clonedColumn.selected = ko.observable(false);
                    clonedColumn.table =
                      table.identifierChain[table.identifierChain.length - 1].name;
                    if (table.alias) {
                      clonedColumn.tableAlias = table.alias;
                    }
                    newColumns.push(clonedColumn);
                  });
                  self.columns = self.columns.concat(newColumns);
                }
                fetchDeferred.resolve();
              })
              .catch(fetchDeferred.reject);
          })
          .catch(fetchDeferred.reject);
      }
    });

    if (deferrals.length === 0) {
      self.loading(false);
    }
    $.when.apply($, deferrals).done(
      () => {
        self.loading(false);
      },
      () => {
        if (self.columns.length === 0) {
          self.hasErrors(true);
        }
      }
    );
  }
}

class AsteriskContextTabs {
  constructor(data, connector, namespace, compute, defaultDatabase) {
    const self = this;
    self.data = new AsteriskData(data, connector, namespace, compute, defaultDatabase);

    self.tabs = [
      {
        id: 'details',
        label: I18n('Details'),
        template: 'context-popover-asterisk-details',
        templateData: self.data
      }
    ];
    self.activeTab = ko.observable('details');
  }
}

export default AsteriskContextTabs;
<|endoftext|>


<commit_before>// http://processors.wiki.ti.com/index.php/SensorTag_User_Guide

var IR_TEMPERATURE_UUID                     = 'f000aa0004514000b000000000000000';

var IR_TEMPERATURE_CONFIG_UUID              = 'f000aa0204514000b000000000000000';
var IR_TEMPERATURE_DATA_UUID                = 'f000aa0104514000b000000000000000';
var IR_TEMPERATURE_PERIOD_UUID              = 'f000aa0304514000b000000000000000';

var SIMPLE_KEY_UUID                         = 'ffe0';
var SIMPLE_KEY_DATA_UUID                    = 'ffe1';

// DEVICE ID: (Biomonitor >  0x0106) : (BabyMonitor > Device_ID 0x0703)

var DEVICE_ID_UUID                     = 'f000AC00-0451-4000-B000-00000000-0000';

var DEVICE_ID_DATA_UUID                = 'f000ac0104514000b000000000000000';
var DEVICE_ID_ADDRESS_UUID             = 'f000ac0204514000b000000000000000';
var DEVICE_ID_DEVICE_UUID              = 'f000ac0304514000b000000000000000';

function SensorTagCommon() {
  this.onIrTemperatureChangeBinded      = this.onIrTemperatureChange.bind(this);
  this.onSimpleKeyChangeBinded          = this.onSimpleKeyChange.bind(this);
}

SensorTagCommon.prototype.toString = function() {
  return JSON.stringify({
    id: this.id,
    type: this.type
  });
};

SensorTagCommon.prototype.writePeriodCharacteristic = function(serviceUuid, characteristicUuid, period, callback) {
  period /= 10; // input is scaled by units of 10ms

  if (period < 1) {
    period = 1;
  } else if (period > 255) {
    period = 255;
  }

  this.writeUInt8Characteristic(serviceUuid, characteristicUuid, period, callback);
};

// Device ID
SensorTagCommon.prototype.setDeviceID = function(callback) {
  var period_hex = '0x0303';
  var characteristic = this._characteristics[DEVICE_ID_UUID][DEVICE_ID_DEVICE_UUID];
  var buf_period_hex = new Buffer([period_hex]);
  characteristic.write(buf_period_hex, true, function(error) {
    console.log('Device ID: ' + period_hex);
    });
    callback();
};

SensorTagCommon.prototype.readDeviceId = function() {
  this.readDataCharacteristic(DEVICE_ID_UUID, DEVICE_ID_DATA_UUID, function(error, data) {
    var deviceID = data.readInt16LE(0);
    callback(deviceID);
  }
};

// CC2650SensorTag.prototype.convertDeviceID = function(data) {
//   var deviceID = data.readInt16LE(0) / 128.0;
//   callback(deviceID);
// };

//////////

SensorTagCommon.prototype.enableConfigCharacteristic = function(serviceUuid, characteristicUuid, callback) {
  this.writeUInt8Characteristic(serviceUuid, characteristicUuid, 0x01, callback);
};

SensorTagCommon.prototype.disableConfigCharacteristic = function(serviceUuid, characteristicUuid, callback) {
  this.writeUInt8Characteristic(serviceUuid, characteristicUuid, 0x00, callback);
};

// Temperature
SensorTagCommon.prototype.setIrTemperaturePeriod = function(period, callback) {
  var period_hex = '0x' + (+period).toString(16).toUpperCase();
  var characteristic = this._characteristics[IR_TEMPERATURE_UUID][IR_TEMPERATURE_PERIOD_UUID];
  var buf_period_hex = new Buffer([period_hex]);
  characteristic.write(buf_period_hex, true, function(error) {
    console.log('IR temp period set to: ' + period_hex);
    });
    callback();
};

SensorTagCommon.prototype.enableIrTemperature = function(callback) {
  this.enableConfigCharacteristic(IR_TEMPERATURE_UUID, IR_TEMPERATURE_CONFIG_UUID, callback);
};

SensorTagCommon.prototype.disableIrTemperature = function(callback) {
  this.disableConfigCharacteristic(IR_TEMPERATURE_UUID, IR_TEMPERATURE_CONFIG_UUID, callback);
};

SensorTagCommon.prototype.readIrTemperature = function(callback) {
  this.readDataCharacteristic(IR_TEMPERATURE_UUID, IR_TEMPERATURE_DATA_UUID, function(error, data) {
    if (error) {
      return callback(error);
    }

    this.convertIrTemperatureData(data, function(objectTemperature, ambientTemperature) {
      callback(null, objectTemperature, ambientTemperature);
    }.bind(this));
  }.bind(this));
};

SensorTagCommon.prototype.onIrTemperatureChange = function(data) {
  this.convertIrTemperatureData(data, function(objectTemperature, ambientTemperature) {
    this.emit('irTemperatureChange', objectTemperature, ambientTemperature);
  }.bind(this));
};

SensorTagCommon.prototype.notifyIrTemperature = function(callback) {
  this.notifyCharacteristic(IR_TEMPERATURE_UUID, IR_TEMPERATURE_DATA_UUID, true, this.onIrTemperatureChangeBinded, callback);
};

SensorTagCommon.prototype.unnotifyIrTemperature = function(callback) {
  this.notifyCharacteristic(IR_TEMPERATURE_UUID, IR_TEMPERATURE_DATA_UUID, false, this.onIrTemperatureChangeBinded, callback);
};

SensorTagCommon.prototype.onSimpleKeyChange = function(data) {
  this.convertSimpleKeyData(data, function(/*left, right, ...*/) {
    var emitArguments = Array.prototype.slice.call(arguments);
    emitArguments.unshift('simpleKeyChange');

    this.emit.apply(this, emitArguments);
  }.bind(this));
};

SensorTagCommon.prototype.convertSimpleKeyData = function(data, callback) {
  var b = data.readUInt8(0);

  var left = (b & 0x2) ? true : false;
  var right = (b & 0x1) ? true : false;

  callback(left, right);
};

SensorTagCommon.prototype.notifySimpleKey = function(callback) {
  this.notifyCharacteristic(SIMPLE_KEY_UUID, SIMPLE_KEY_DATA_UUID, true, this.onSimpleKeyChangeBinded, callback);
};

SensorTagCommon.prototype.unnotifySimpleKey = function(callback) {
  this.notifyCharacteristic(SIMPLE_KEY_UUID, SIMPLE_KEY_DATA_UUID, false, this.onSimpleKeyChangeBinded, callback);
};

module.exports = SensorTagCommon;
<commit_msg>readData in setDeviceID<commit_after>// http://processors.wiki.ti.com/index.php/SensorTag_User_Guide

var IR_TEMPERATURE_UUID                     = 'f000aa0004514000b000000000000000';

var IR_TEMPERATURE_CONFIG_UUID              = 'f000aa0204514000b000000000000000';
var IR_TEMPERATURE_DATA_UUID                = 'f000aa0104514000b000000000000000';
var IR_TEMPERATURE_PERIOD_UUID              = 'f000aa0304514000b000000000000000';

var SIMPLE_KEY_UUID                         = 'ffe0';
var SIMPLE_KEY_DATA_UUID                    = 'ffe1';

// DEVICE ID: (Biomonitor >  0x0106) : (BabyMonitor > Device_ID 0x0703)

var DEVICE_ID_UUID                     = 'f000AC00-0451-4000-B000-00000000-0000';

var DEVICE_ID_DATA_UUID                = 'f000ac0104514000b000000000000000';
var DEVICE_ID_ADDRESS_UUID             = 'f000ac0204514000b000000000000000';
var DEVICE_ID_DEVICE_UUID              = 'f000ac0304514000b000000000000000';

function SensorTagCommon() {
  this.onIrTemperatureChangeBinded      = this.onIrTemperatureChange.bind(this);
  this.onSimpleKeyChangeBinded          = this.onSimpleKeyChange.bind(this);
}

SensorTagCommon.prototype.toString = function() {
  return JSON.stringify({
    id: this.id,
    type: this.type
  });
};

SensorTagCommon.prototype.writePeriodCharacteristic = function(serviceUuid, characteristicUuid, period, callback) {
  period /= 10; // input is scaled by units of 10ms

  if (period < 1) {
    period = 1;
  } else if (period > 255) {
    period = 255;
  }

  this.writeUInt8Characteristic(serviceUuid, characteristicUuid, period, callback);
};

// Device ID
SensorTagCommon.prototype.setDeviceID = function(callback) {
  var period_hex = '0x0303';
  var characteristic = this._characteristics[DEVICE_ID_UUID][DEVICE_ID_DEVICE_UUID];
  var buf_period_hex = new Buffer([period_hex]);
  characteristic.write(buf_period_hex, true, function(error) {
    console.log('Device ID: ' + period_hex);
    });
    this.readDataCharacteristic(DEVICE_ID_UUID, DEVICE_ID_DATA_UUID, function(error, data) {
      var deviceID = data.readInt16LE(0);
      callback(deviceID);
    });
    // callback();
};

SensorTagCommon.prototype.readDeviceId = function() {
  this.readDataCharacteristic(DEVICE_ID_UUID, DEVICE_ID_DATA_UUID, function(error, data) {
    var deviceID = data.readInt16LE(0);
    callback(deviceID);
  });
};

// CC2650SensorTag.prototype.convertDeviceID = function(data) {
//   var deviceID = data.readInt16LE(0) / 128.0;
//   callback(deviceID);
// };

//////////

SensorTagCommon.prototype.enableConfigCharacteristic = function(serviceUuid, characteristicUuid, callback) {
  this.writeUInt8Characteristic(serviceUuid, characteristicUuid, 0x01, callback);
};

SensorTagCommon.prototype.disableConfigCharacteristic = function(serviceUuid, characteristicUuid, callback) {
  this.writeUInt8Characteristic(serviceUuid, characteristicUuid, 0x00, callback);
};

// Temperature
SensorTagCommon.prototype.setIrTemperaturePeriod = function(period, callback) {
  var period_hex = '0x' + (+period).toString(16).toUpperCase();
  var characteristic = this._characteristics[IR_TEMPERATURE_UUID][IR_TEMPERATURE_PERIOD_UUID];
  var buf_period_hex = new Buffer([period_hex]);
  characteristic.write(buf_period_hex, true, function(error) {
    console.log('IR temp period set to: ' + period_hex);
    });
    callback();
};

SensorTagCommon.prototype.enableIrTemperature = function(callback) {
  this.enableConfigCharacteristic(IR_TEMPERATURE_UUID, IR_TEMPERATURE_CONFIG_UUID, callback);
};

SensorTagCommon.prototype.disableIrTemperature = function(callback) {
  this.disableConfigCharacteristic(IR_TEMPERATURE_UUID, IR_TEMPERATURE_CONFIG_UUID, callback);
};

SensorTagCommon.prototype.readIrTemperature = function(callback) {
  this.readDataCharacteristic(IR_TEMPERATURE_UUID, IR_TEMPERATURE_DATA_UUID, function(error, data) {
    if (error) {
      return callback(error);
    }

    this.convertIrTemperatureData(data, function(objectTemperature, ambientTemperature) {
      callback(null, objectTemperature, ambientTemperature);
    }.bind(this));
  }.bind(this));
};

SensorTagCommon.prototype.onIrTemperatureChange = function(data) {
  this.convertIrTemperatureData(data, function(objectTemperature, ambientTemperature) {
    this.emit('irTemperatureChange', objectTemperature, ambientTemperature);
  }.bind(this));
};

SensorTagCommon.prototype.notifyIrTemperature = function(callback) {
  this.notifyCharacteristic(IR_TEMPERATURE_UUID, IR_TEMPERATURE_DATA_UUID, true, this.onIrTemperatureChangeBinded, callback);
};

SensorTagCommon.prototype.unnotifyIrTemperature = function(callback) {
  this.notifyCharacteristic(IR_TEMPERATURE_UUID, IR_TEMPERATURE_DATA_UUID, false, this.onIrTemperatureChangeBinded, callback);
};

SensorTagCommon.prototype.onSimpleKeyChange = function(data) {
  this.convertSimpleKeyData(data, function(/*left, right, ...*/) {
    var emitArguments = Array.prototype.slice.call(arguments);
    emitArguments.unshift('simpleKeyChange');

    this.emit.apply(this, emitArguments);
  }.bind(this));
};

SensorTagCommon.prototype.convertSimpleKeyData = function(data, callback) {
  var b = data.readUInt8(0);

  var left = (b & 0x2) ? true : false;
  var right = (b & 0x1) ? true : false;

  callback(left, right);
};

SensorTagCommon.prototype.notifySimpleKey = function(callback) {
  this.notifyCharacteristic(SIMPLE_KEY_UUID, SIMPLE_KEY_DATA_UUID, true, this.onSimpleKeyChangeBinded, callback);
};

SensorTagCommon.prototype.unnotifySimpleKey = function(callback) {
  this.notifyCharacteristic(SIMPLE_KEY_UUID, SIMPLE_KEY_DATA_UUID, false, this.onSimpleKeyChangeBinded, callback);
};

module.exports = SensorTagCommon;
<|endoftext|>