<commit_before>/* jshint esversion: 6 */

// battle API mode flags
const FLAGS = [
  { "mask": 1, "attr": "See others" },
  { "mask": 2, "attr": "See times" },
  { "mask": 4, "attr": "Allow starter" },
  { "mask": 8, "attr": "Apple bug" },
  { "mask": 16, "attr": "No volt" },
  { "mask": 32, "attr": "No turn" },
  { "mask": 64, "attr": "One turn" },
  { "mask": 128, "attr": "No brake" },
  { "mask": 256, "attr": "No throttle" },
  { "mask": 512, "attr": "Always throttle" },
  { "mask": 1024, "attr": "Drunk" },
  { "mask": 4096, "attr": "One wheel" },
  { "mask": 8192, "attr": "Multi" }
];

// battle API battle type
const TYPES = [
  "Normal", "One life", "First finish", "Slowness", "Survivor", "Last result", "Finish count", "1 Hour TT", "Flag tag", "Apple", "Speed"
];

var APIurl = "http://108.61.164.75:8880/current_battle?json=1";
var EOLurl = "http://elmaonline.net/battles/";
var timer;

// XHR requests, with promises
function getURL(url) {
  return new Promise((resolve, reject) => {
    var req = new XMLHttpRequest();
    req.open('GET', url);

    req.onload = () => {
      if (req.status == 200) {
        resolve(req.responseText);
      } else {
        reject(Error(req.statusText));
      }
    };

    req.onerror = () => {
      reject(Error("Network Error"));
    };

    req.send();
  });
}

// sets extension icon badge color based on time left of battle
function setTimeIndicatorIcon (timeState) {
  switch (timeState) {
    case 'green':
      chrome.browserAction.setBadgeText({text: "\u00A0"}); // invisible character
      chrome.browserAction.setBadgeBackgroundColor({color:[106, 161, 33, 255]});
      break;
    case 'yellow':
      chrome.browserAction.setBadgeText({text: "\u00A0"}); // invisible character
      chrome.browserAction.setBadgeBackgroundColor({color:[245, 219, 49, 255]});
      break;
    case 'red':
      chrome.browserAction.setBadgeText({text: "\u00A0"}); // invisible character
      chrome.browserAction.setBadgeBackgroundColor({color:[224, 27, 27, 255]});
      break;
    default:
      chrome.browserAction.setBadgeText({text: ''}); // empty string removes badge
      break;
  }
}

function getBattleInfo () {
  getURL(APIurl).then(response => {
    var res = JSON.parse(response);
    if (res.id) { // battle probably active if we get a battle id
      chrome.storage.sync.get("battle", result => {
        if (res.id === result.battle.id) { // if we already have battle info, skip fetching map etc.
          console.log('not new!');
        } else { // new battle, fetch map from EOL site
          getMap(res.id).then(map => {
            res.map = map;
            chrome.storage.sync.set({ "battle": res });
            console.log('new');
            console.log(res);
          });
        }
      });
    } else { // no battle active
      chrome.storage.sync.set({ "battle": {} });
      console.log('no battle');
    }
  });
}

function getMap (id) {
  return new Promise((resolve, reject) => {
    getURL(EOLurl + id).then(response => {
      var tempDOM = document.createElement('div');
      tempDOM.innerHTML = response;
      // getElementById not working for whatever reason, ghetto querySelector instead
      var map = tempDOM.querySelector('#right').getElementsByTagName("img")[0].getAttribute("src");
      resolve(map);
    });
  });
}

timer = new BattleTimer();

function BattleTimer (duration, elapsed) {
  this.duration = duration;
  this.elapsed = elapsed;
}

BattleTimer.prototype.start = function () {
  this.active = true;
  this.tick();
};

BattleTimer.prototype.tick = function (ms) {
  if (this.active) {
    // TODO: let user specify threshholds?
    // if time over half: green icon
    // if time under half, over quart: yellow icon
    // if time below quarter: red icon

    // TODO: set interval higher when new battle started:
    // Check time left, start at 2m if >2m left (in case aborted),
    // then increment down to match end of battle, then wait 2mins and 10s interval again?
    var timer = ms || 10000;
    setTimeout(() => {
      this.tick();
    }, ms);
  }
};

BattleTimer.prototype.stop = function () {
  this.active = false;
};

// new battle
function newBattle () {
  notifyBattle();
}

// notify
function notifyBattle () {

}

// start watching for new battles
function startBackground () {
  // TODO: put timers and stuff
}

// stop watching for new battles
function stopBackground () {
  setTimeIndicatorIcon(false);
  // TODO: remove timers etc. obv...
  timer.stop();
}

// start background processing
startBackground();
<commit_msg>Test notification API<commit_after>/* jshint esversion: 6 */

// battle API mode flags
const FLAGS = [
  { "mask": 1, "attr": "See others" },
  { "mask": 2, "attr": "See times" },
  { "mask": 4, "attr": "Allow starter" },
  { "mask": 8, "attr": "Apple bug" },
  { "mask": 16, "attr": "No volt" },
  { "mask": 32, "attr": "No turn" },
  { "mask": 64, "attr": "One turn" },
  { "mask": 128, "attr": "No brake" },
  { "mask": 256, "attr": "No throttle" },
  { "mask": 512, "attr": "Always throttle" },
  { "mask": 1024, "attr": "Drunk" },
  { "mask": 4096, "attr": "One wheel" },
  { "mask": 8192, "attr": "Multi" }
];

// battle API battle type
const TYPES = [
  "Normal", "One life", "First finish", "Slowness", "Survivor", "Last result", "Finish count", "1 Hour TT", "Flag tag", "Apple", "Speed"
];

var APIurl = "http://108.61.164.75:8880/current_battle?json=1";
var EOLurl = "http://elmaonline.net/battles/";
var timer;

// XHR requests, with promises
function getURL(url) {
  return new Promise((resolve, reject) => {
    var req = new XMLHttpRequest();
    req.open('GET', url);

    req.onload = () => {
      if (req.status == 200) {
        resolve(req.responseText);
      } else {
        reject(Error(req.statusText));
      }
    };

    req.onerror = () => {
      reject(Error("Network Error"));
    };

    req.send();
  });
}

// sets extension icon badge color based on time left of battle
function setTimeIndicatorIcon (timeState) {
  switch (timeState) {
    case 'green':
      chrome.browserAction.setBadgeText({text: "\u00A0"}); // invisible character
      chrome.browserAction.setBadgeBackgroundColor({color:[106, 161, 33, 255]});
      break;
    case 'yellow':
      chrome.browserAction.setBadgeText({text: "\u00A0"}); // invisible character
      chrome.browserAction.setBadgeBackgroundColor({color:[245, 219, 49, 255]});
      break;
    case 'red':
      chrome.browserAction.setBadgeText({text: "\u00A0"}); // invisible character
      chrome.browserAction.setBadgeBackgroundColor({color:[224, 27, 27, 255]});
      break;
    default:
      chrome.browserAction.setBadgeText({text: ''}); // empty string removes badge
      break;
  }
}

function getBattleInfo () {
  getURL(APIurl).then(response => {
    var res = JSON.parse(response);
    if (res.id) { // battle probably active if we get a battle id
      chrome.storage.sync.get("battle", result => {
        if (res.id === result.battle.id) { // if we already have battle info, skip fetching map etc.
          console.log('not new!');
        } else { // new battle, fetch map from EOL site
          getMap(res.id).then(map => {
            res.map = map;
            chrome.storage.sync.set({ "battle": res });
            console.log('new');
            console.log(res);
          });
        }
      });
    } else { // no battle active
      chrome.storage.sync.set({ "battle": {} });
      console.log('no battle');
    }
  });
}

function getMap (id) {
  return new Promise((resolve, reject) => {
    getURL(EOLurl + id).then(response => {
      var tempDOM = document.createElement('div');
      tempDOM.innerHTML = response;
      // getElementById not working for whatever reason, ghetto querySelector instead
      var map = tempDOM.querySelector('#right').getElementsByTagName("img")[0].getAttribute("src");
      resolve(map);
    });
  });
}

timer = new BattleTimer();

function BattleTimer (duration, elapsed) {
  this.duration = duration;
  this.elapsed = elapsed;
}

BattleTimer.prototype.start = function () {
  this.active = true;
  this.tick();
};

BattleTimer.prototype.tick = function (ms) {
  if (this.active) {
    // TODO: let user specify threshholds?
    // if time over half: green icon
    // if time under half, over quart: yellow icon
    // if time below quarter: red icon

    var timer = ms || 10000;
    setTimeout(() => {
      this.tick();
    }, ms);
  }
};

BattleTimer.prototype.stop = function () {
  this.active = false;
};

// new battle
function newBattle () {
  notifyBattle();
}

// notifications
function notifyBattle () {
  chrome.notifications.create('NewBattle', {
    type: 'image',
    iconUrl: 'images/icon128.png',
    imageUrl: '',
    title: "New battle",
    message: "hello there!"
    });
}

// start watching for new battles
function startBackground () {
  // TODO: put timers and stuff
}

// stop watching for new battles
function stopBackground () {
  setTimeIndicatorIcon(false);
  // TODO: remove timers etc. obv...
  timer.stop();
}

// start background processing
startBackground();
<|endoftext|>


<commit_before>import React from 'react'
import { addAttendeesData } from '../graphql/queries';
import withData from '../lib/withData';
import { capitalize, firstSentence } from '../lib/utils';
import colors from '../constants/colors';

class Nametags extends React.Component {

  static getInitialProps ({ query: { collectiveSlug, eventSlug } }) {
    return { collectiveSlug, eventSlug }
  }

  constructor(props) {
    super(props);
    this.dimensions = {
      unit: 'mm',
      page: {
        format: 'a4',
        width: 210,
        height: 297
      },
      nametag: {
        width: 100,
        height: 57,
        padding: 5
      }
    }

    this.cols = Math.floor(this.dimensions.page.width / this.dimensions.nametag.width);
    this.rows = Math.floor(this.dimensions.page.height / this.dimensions.nametag.height);

    this.dimensions.page.paddingTop = Math.floor((this.dimensions.page.height - this.rows * this.dimensions.nametag.height) / 2);
  }

  renderPage(pageNumber, responses) {
    const users = responses.map(r => r.user);
    while (users.length < 10) {
      users.push({});
    }
    return (

          {users.map(this.renderNametag)}

    )
  }

  renderNametag(user) {
    return (

{capitalize(user.firstName)} {capitalize(user.lastName)}

        {user.twitterHandle &&
@{user.twitterHandle}
 }

{firstSentence(user.description, 60)}

    )
  }

  render() {
    if (this.props.data.loading) return
Loading

    const responses = [];
    this.props.data.Event.responses.map(r => responses.push(r));
    return (

          {responses.map((response, index) => {
            if (index % 10 === 0) {
              return this.renderPage(index/10 + 1, responses.slice(index, index + 10));
            }
          })}

    );
  }
}

export default withData(addAttendeesData(Nametags));<commit_msg>don't wrap lastName<commit_after>import React from 'react'
import { addAttendeesData } from '../graphql/queries';
import withData from '../lib/withData';
import { capitalize, firstSentence } from '../lib/utils';
import colors from '../constants/colors';

class Nametags extends React.Component {

  static getInitialProps ({ query: { collectiveSlug, eventSlug } }) {
    return { collectiveSlug, eventSlug }
  }

  constructor(props) {
    super(props);
    this.dimensions = {
      unit: 'mm',
      page: {
        format: 'a4',
        width: 210,
        height: 297
      },
      nametag: {
        width: 100,
        height: 57,
        padding: 5
      }
    }

    this.cols = Math.floor(this.dimensions.page.width / this.dimensions.nametag.width);
    this.rows = Math.floor(this.dimensions.page.height / this.dimensions.nametag.height);

    this.dimensions.page.paddingTop = Math.floor((this.dimensions.page.height - this.rows * this.dimensions.nametag.height) / 2);
  }

  renderPage(pageNumber, responses) {
    const users = responses.map(r => r.user);
    while (users.length < 10) {
      users.push({});
    }
    return (

          {users.map(this.renderNametag)}

    )
  }

  renderNametag(user) {
    return (

{capitalize(user.firstName)} {capitalize(user.lastName)}

        {user.twitterHandle &&
@{user.twitterHandle}
 }

{firstSentence(user.description, 60)}

    )
  }

  render() {
    if (this.props.data.loading) return
Loading

    const responses = [];
    this.props.data.Event.responses.map(r => responses.push(r));
    return (

          {responses.map((response, index) => {
            if (index % 10 === 0) {
              return this.renderPage(index/10 + 1, responses.slice(index, index + 10));
            }
          })}

    );
  }
}

export default withData(addAttendeesData(Nametags));<|endoftext|>


<commit_before>var canvas;
var canvasContext;
var image;
var animation = new ConvertingAnimation();
var loggedIn = false;
var restricted = false;
var error = '';
var pendingStatusRequest = false;

function ConvertingAnimation() {
    this.timerId_ = 0;
    this.imageXPos_ = 0;
}

ConvertingAnimation.prototype.paintFrame = function() {
    canvasContext.save();

    var imgHeight = canvas.height - 6;
    var imgWidth = canvas.width - this.imageXPos_;

    canvasContext.drawImage(image, 0, 0);
    canvasContext.drawImage(image, 0, 3, imgWidth, imgHeight, this.imageXPos_, 3, imgWidth, imgHeight);

    if (this.imageXPos_) {
        canvasContext.drawImage(
            image, 0, 3, canvas.width, imgHeight, -canvas.width + this.imageXPos_, 3, canvas.width, imgHeight);
    }

    canvasContext.restore();

    chrome.browserAction.setIcon({imageData: canvasContext.getImageData(0, 0, canvas.width, canvas.height)});
    this.imageXPos_ += 1;

    if (this.imageXPos_ >= canvas.width)
        this.imageXPos_ = 0;
}

ConvertingAnimation.prototype.start = function() {
    if (this.timerId_)
        return;

    var self = this;
    this.timerId_ = window.setInterval(function() {
        self.paintFrame();
    }, 100);
}

ConvertingAnimation.prototype.stop = function() {
    if (!this.timerId_)
        return;
    window.clearInterval(this.timerId_);
    this.timerId_ = 0;
    this.imageXPos_ = 0;
    showStaticIcon();
}

function showStaticIcon() {
    if (animation.timerId_ != 0) return;
    canvasContext.drawImage(image, 0, 0);
    drawLoggedIn();
    chrome.browserAction.setIcon({imageData: canvasContext.getImageData(0, 0, canvas.width, canvas.height)});
}

function updateBadgeAndTitle() {
    if (error) {
        chrome.browserAction.setTitle({title: error});
        chrome.browserAction.setBadgeText({text: '!'});
        // TBD badge background color
    } else {
        var title = "Save as PDF - by pdfcrowd.com"
        chrome.browserAction.setTitle({title: title});
        chrome.browserAction.setBadgeText({text: ''});
    }
}

function showError(msg) {
    error = msg;
    updateBadgeAndTitle();
}

function clearError() {
    error = '';
    updateBadgeAndTitle();
}

function drawLoggedIn() {
    if (loggedIn && !restricted)
        return;

    canvasContext.save();
    canvasContext.fillStyle = "red";
    canvasContext.arc(15, 4, 2, 0, 2*Math.PI);
    canvasContext.fill();
    canvasContext.restore();
}

function updateLoggedIn(user) {
    loggedIn = user.authenticated;
    if (loggedIn)
        restricted = user.restricted;
    updateBadgeAndTitle();
    showStaticIcon();
}

function onDataReady(xhr, callbacks) {
    return function(data) {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                if (callbacks.onSuccess) {
                    try {
                        var data = JSON.parse(xhr.responseText);
                        callbacks.onSuccess(data);
                    } catch (e) {
                        showError("Conversion failed.");
                    }
                }
            } else {
                showError("Can't connect to Pdfcrowd")
            }
            if (callbacks.onComplete)
                callbacks.onComplete();
        }
    };
}

function createPdf(tab) {
    var rex = /^((?:chrome|file|chrome-extension|about):.*$)/i;
    var result = rex.exec(tab.url);
    if (result) {
        showError("Conversion of local URLs is not supported (" + result[1] + ").");
        return;
    }

    // is there an ongoing conversion?
    if (animation.timerId_ != 0) return;

    clearError();

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = onDataReady(xhr, {
        onSuccess: function(data) {
            if (data.status === 'ok') {
                chrome.tabs.update(tab.id, {url: data.url});
	        } else if (data.status === 'error') {
                showError(data.message);
            } else if (data.status === 'redirect') {
                      // tbd
            }
            updateLoggedIn(data.user);
        },

        onComplete: function() {
            animation.stop();
        }
    });

    var url = 'https://pdfcrowd.com/session/json/convert/uri/';
          xhr.open('POST', url, true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send("src="+escape(tab.url));
    animation.start();
};

function init() {

    var version = "1.9";
    //Show updated page first load
    if(localStorage.updatedToVersion && localStorage.updatedToVersion != version) {
        chrome.tabs.create( {url:"updated.html"} );
    }
    localStorage.updatedToVersion = version;

    image = document.getElementById("standard_icon")
    canvas = document.getElementById("canvas");
    canvasContext = canvas.getContext("2d");
    updateBadgeAndTitle();
    //findOutUserStatus();
}

chrome.browserAction.onClicked.addListener(function(tab) {
    createPdf(tab);
});

init();
<commit_msg>handle both APIs<commit_after>var canvas;
var canvasContext;
var image;
var animation = new ConvertingAnimation();
var loggedIn = false;
var restricted = false;
var error = '';
var pendingStatusRequest = false;

function ConvertingAnimation() {
    this.timerId_ = 0;
    this.imageXPos_ = 0;
}

ConvertingAnimation.prototype.paintFrame = function() {
    canvasContext.save();

    var imgHeight = canvas.height - 6;
    var imgWidth = canvas.width - this.imageXPos_;

    canvasContext.drawImage(image, 0, 0);
    canvasContext.drawImage(image, 0, 3, imgWidth, imgHeight, this.imageXPos_, 3, imgWidth, imgHeight);

    if (this.imageXPos_) {
        canvasContext.drawImage(
            image, 0, 3, canvas.width, imgHeight, -canvas.width + this.imageXPos_, 3, canvas.width, imgHeight);
    }

    canvasContext.restore();

    chrome.browserAction.setIcon({imageData: canvasContext.getImageData(0, 0, canvas.width, canvas.height)});
    this.imageXPos_ += 1;

    if (this.imageXPos_ >= canvas.width)
        this.imageXPos_ = 0;
}

ConvertingAnimation.prototype.start = function() {
    if (this.timerId_)
        return;

    var self = this;
    this.timerId_ = window.setInterval(function() {
        self.paintFrame();
    }, 100);
}

ConvertingAnimation.prototype.stop = function() {
    if (!this.timerId_)
        return;
    window.clearInterval(this.timerId_);
    this.timerId_ = 0;
    this.imageXPos_ = 0;
    showStaticIcon();
}

function showStaticIcon() {
    if (animation.timerId_ != 0) return;
    canvasContext.drawImage(image, 0, 0);
    drawLoggedIn();
    chrome.browserAction.setIcon({imageData: canvasContext.getImageData(0, 0, canvas.width, canvas.height)});
}

function updateBadgeAndTitle() {
    if (error) {
        chrome.browserAction.setTitle({title: error});
        chrome.browserAction.setBadgeText({text: '!'});
        // TBD badge background color
    } else {
        var title = "Save as PDF - by pdfcrowd.com"
        chrome.browserAction.setTitle({title: title});
        chrome.browserAction.setBadgeText({text: ''});
    }
}

function showError(msg) {
    error = msg;
    updateBadgeAndTitle();
}

function clearError() {
    error = '';
    updateBadgeAndTitle();
}

function drawLoggedIn() {
    if (loggedIn && !restricted)
        return;

    canvasContext.save();
    canvasContext.fillStyle = "red";
    canvasContext.arc(15, 4, 2, 0, 2*Math.PI);
    canvasContext.fill();
    canvasContext.restore();
}

function updateLoggedIn(user) {
    loggedIn = user.authenticated;
    if (loggedIn)
        restricted = user.restricted;
    updateBadgeAndTitle();
    showStaticIcon();
}

function onDataReady(xhr, callbacks) {
    return function(data) {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                if (callbacks.onSuccess) {
                    try {
                        var data = JSON.parse(xhr.responseText);
                        callbacks.onSuccess(data);
                    } catch (e) {
                        showError("Conversion failed.");
                    }
                }
            } else {
                showError("Can't connect to Pdfcrowd")
            }
            if (callbacks.onComplete)
                callbacks.onComplete();
        }
    };
}

function canRunConversion(tab) {
    var rex = /^((?:chrome|file|chrome-extension|about):.*$)/i;
    var result = rex.exec(tab.url);
    if (result) {
        showError("Conversion of local URLs is not supported (" + result[1] + ").");
        return false;
    }
    // is there an ongoing conversion?
    if (animation.timerId_ != 0) return false;

    return true;
}

function createPdf(tab, apiUrl) {

    clearError();

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = onDataReady(xhr, {
        onSuccess: function(data) {
            if (data.status === 'ok') {
                chrome.tabs.update(tab.id, {url: data.url});
	        } else if (data.status === 'error') {
                showError(data.message);
            } else if (data.status === 'redirect') {
                      // tbd
            }
            updateLoggedIn(data.user);
        },

        onComplete: function() {
            animation.stop();
        }
    });

    xhr.open('POST', apiUrl, true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send("src=" + escape(tab.url));
    animation.start();
};

function init() {

    var version = "1.9";
    //Show updated page first load
    if(localStorage.updatedToVersion && localStorage.updatedToVersion != version) {
        chrome.tabs.create( {url:"updated.html"} );
    }
    localStorage.updatedToVersion = version;

    image = document.getElementById("standard_icon")
    canvas = document.getElementById("canvas");
    canvasContext = canvas.getContext("2d");
    updateBadgeAndTitle();
    //findOutUserStatus();
}

var baseUrl = 'https://pdfcrowd.com'
var apiUrls = {
    1: baseUrl + '/session/json/convert/uri/',
    2: baseUrl + '/session/json/convert/uri/v2/'
}

var apiVersionUrl = baseUrl + '/session/api-version/'

chrome.browserAction.onClicked.addListener(function(tab) {
    if (!canRunConversion(tab)) {
        return;
    }

    // find out the api version for the current user
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = onDataReady(xhr, {
        onSuccess: function(data) {
            var apiUrl = apiUrls[data.api_version];
            if (apiUrl === undefined) {
                apiUrl = apiUrls[2];
            }
            // create pdf
            createPdf(tab, apiUrl);
        },
    });
    xhr.open('GET', apiVersionUrl, true);
    xhr.send(null);
});

init();
<|endoftext|>


<commit_before>var debug = JSON.parse(localStorage.channel);
var liveNotify = new Notification('ADANADO!!', {
      icon: 'icon128.png',
      body: "É TEMPO! Começando "+debug.game+" ao vivo agora!",
      silent: true
    });

liveNotify.onclick = function(){
    chrome.tabs.create({'url': 'http://www.twitch.tv/cogumelandooficial/'}, function(tab){/*callback*/});
};
setTimeout(function(){
    liveNotify.close();
},10000);

var twitch = {
    name: 'Cogumelando',
    username: 'cogumelandooficial',
    streamTitle: 'LIVE',
    offAirTitle: 'OFF',
    offAirMessage: 'Off-air'
}

chrome.runtime.onStartup.addListener(function () {
    localStorage.removeItem('onStream');
    if(localStorage.length == 0){
        localStorage.setItem('persist',true);
        localStorage.setItem('sound',true);
        localStorage.setItem('interval',1);
    }
    noConnect();
    chrome.alarms.create("mainLoop", {delayInMinutes: 0.1,periodInMinutes: 1});
});
$.ajaxSetup({cache:false});

/*@deprecated
twitch.createLoop();
getTwitch(twitch.username);
twitch.mainLoop = setInterval(function(){
    getTwitch(twitch.username);
},twitch.ajaxInterval);
*/

chrome.alarms.onAlarm.addListener(function(alarm) {
    getTwitch(twitch.username);
});

function mythTwitch(twitchJson){
    twitch.channel = twitchJson;

    if(twitchJson.stream){
        localStorage.setItem('onStream',true);
        localStorage.setItem('channel',JSON.stringify(twitchJson.stream));

        chrome.browserAction.getBadgeText({},function(e){
            console.log(e);
            if(e != twitch.streamTitle && localStorage.sound){
                var notify = new Howl({
                    urls: ['adanado.ogg']
                }).play();
            }
        });

        twitch.game = twitchJson.stream.game;
        chrome.browserAction.setBadgeBackgroundColor({color: "#0d0"});
        chrome.browserAction.setBadgeText({text:twitch.streamTitle});
        chrome.browserAction.setTitle({title:twitch.name+' | '+twitch.game});

        console.log("Stream");

    }else{
        localStorage.removeItem('onStream');
        chrome.browserAction.setBadgeBackgroundColor({color: "#d00"});
        chrome.browserAction.setBadgeText({text:twitch.offAirTitle});
        chrome.browserAction.setTitle({title:twitch.name+' | '+twitch.offAirMessage});
        console.log("Off-air");
    }
}

function getTwitch(username){
    $.ajax({
        url:'https://api.twitch.tv/kraken/streams/'+username,
        success:function(channel) {
            console.log('Objeto recebido');
            mythTwitch(channel);
        },
        error:function() {
            console.log('Sem conexão');
            noConnect();
        }
    });
}

function noConnect(){
    chrome.browserAction.setBadgeText({text:"..."});
    chrome.browserAction.setBadgeBackgroundColor({color: "#999"});
    chrome.browserAction.setTitle({title:twitch.name});
}
<commit_msg>Add desktop notify - testado e incrementado no loop principal - falta colocar nas configurações<commit_after>
var twitch = {
    name: 'Cogumelando',
    username: 'cogumelandooficial',
    streamTitle: 'LIVE',
    offAirTitle: 'OFF',
    offAirMessage: 'Off-air',
    notifySfx: 'adanado.ogg'
}

chrome.runtime.onStartup.addListener(function (){
    localStorage.removeItem('onStream');
    if(localStorage.length == 0){
        localStorage.setItem('persist',true);
        localStorage.setItem('sound',true);
        localStorage.setItem('notify',true);
        localStorage.setItem('interval',1);
    }
    noConnect();
    chrome.alarms.create("mainLoop", {delayInMinutes: 0.1,periodInMinutes: 1});
});
$.ajaxSetup({cache:false});

/*@deprecated
twitch.createLoop();
getTwitch(twitch.username);
twitch.mainLoop = setInterval(function(){
    getTwitch(twitch.username);
},twitch.ajaxInterval);
*/

chrome.alarms.onAlarm.addListener(function(alarm) {
    getTwitch(twitch.username);
});

function mythTwitch(twitchJson){
    twitch.channel = twitchJson;

    if(twitchJson.stream){
        localStorage.setItem('onStream',true);
        localStorage.setItem('channel',JSON.stringify(twitchJson.stream));
        twitch.game = twitchJson.stream.game;

        chrome.browserAction.getBadgeText({},function(e){
            console.log(e);
            if(e != twitch.streamTitle){
                if(localStorage.notify){
                    var liveNotify = new Notification('ADANADO!!', {
                          icon: 'live.png',
                          body: "É TEMPO! Começando "+twitch.game+" ao vivo agora!",
                          silent: true
                        });

                    liveNotify.onclick = function(){
                        chrome.tabs.create({'url': 'http://www.twitch.tv/cogumelandooficial/'}, function(tab){/*callback*/});
                    };
                    setTimeout(function(){
                        liveNotify.close();
                    },10000);
                }
                if (localStorage.sound) {
                    var notify = new Howl({
                        urls: [twitch.notifySfx]
                    }).play();
                }
            }
        });

        chrome.browserAction.setBadgeBackgroundColor({color: "#0d0"});
        chrome.browserAction.setBadgeText({text:twitch.streamTitle});
        chrome.browserAction.setTitle({title:twitch.name+' | '+twitch.game});

        console.log("Stream");

    }else{
        localStorage.removeItem('onStream');
        chrome.browserAction.setBadgeBackgroundColor({color: "#d00"});
        chrome.browserAction.setBadgeText({text:twitch.offAirTitle});
        chrome.browserAction.setTitle({title:twitch.name+' | '+twitch.offAirMessage});
        console.log("Off-air");
    }
}

function getTwitch(username){
    $.ajax({
        url:'https://api.twitch.tv/kraken/streams/'+username,
        success:function(channel) {
            console.log('Objeto recebido');
            mythTwitch(channel);
        },
        error:function() {
            console.log('Sem conexão');
            noConnect();
        }
    });
}

function noConnect(){
    chrome.browserAction.setBadgeText({text:"..."});
    chrome.browserAction.setBadgeBackgroundColor({color: "#999"});
    chrome.browserAction.setTitle({title:twitch.name});
}
<|endoftext|>


<commit_before>//
// Make Medium Readable Again
//

var makeReadable = function() {
	// Un-position:fixed the top nav bar
	var topNav = document.querySelector('.metabar.u-fixed');
	if (topNav != null) {
		topNav.classList.remove('u-fixed');
	}
	// Remove the footer
	var getUpdatesBar = document.querySelector('.js-stickyFooter');
	if (getUpdatesBar != null) {
		getUpdatesBar.style.display = 'none';
	}
};

var hideDickbar = function() {
	document.querySelector('.js-postShareWidget').style.display = 'none';
	document.querySelector('footer > .container:first-child').style.display = 'none';
};

var disableLazyLoading = function() {
	var hiddenMedia = document.querySelectorAll('.js-progressiveMedia-inner');
	if (hiddenMedia == null) {
		return;
	}
	for (var i=0; i<hiddenMedia.length; i++) {
		var template = document.createElement('template');
		template.innerHTML = hiddenMedia[i].textContent;
		hiddenMedia[i].parentNode.appendChild(template.content.firstChild);
	}
};

// Only run this on Medium sites.
// Ensure that by checking for <meta property="al:ios:app_name" content="Medium"> in the document <head />
var metaCheck = document.head.querySelector('meta[property="al:ios:app_name"]');
if (metaCheck != null && metaCheck.content == "Medium") {
	makeReadable();

	chrome.storage.sync.get(null, function(items) {
		if (items.hideDickbar) {
			hideDickbar();
		}
		if (items.disableLazyImages) {
			disableLazyLoading();
		}
	});
}
<commit_msg>Check for null dickbars before applying styles<commit_after>//
// Make Medium Readable Again
//

var makeReadable = function() {
	// Un-position:fixed the top nav bar
	var topNav = document.querySelector('.metabar.u-fixed');
	if (topNav != null) {
		topNav.classList.remove('u-fixed');
	}
	// Remove the footer
	var getUpdatesBar = document.querySelector('.js-stickyFooter');
	if (getUpdatesBar != null) {
		getUpdatesBar.style.display = 'none';
	}
};

var hideDickbar = function() {
	var dickbar = document.querySelector('.js-postShareWidget');
	if (dickbar != null) {
		dickbar.style.display = 'none';
	}
	var footerDickbar = document.querySelector('footer > .container:first-child');
	if (footerDickbar != null) {
		footerDickbar.style.display = 'none';
	}
};

var disableLazyLoading = function() {
	var hiddenMedia = document.querySelectorAll('.js-progressiveMedia-inner');
	if (hiddenMedia == null) {
		return;
	}
	for (var i=0; i<hiddenMedia.length; i++) {
		var template = document.createElement('template');
		template.innerHTML = hiddenMedia[i].textContent;
		hiddenMedia[i].parentNode.appendChild(template.content.firstChild);
	}
};

// Only run this on Medium sites.
// Ensure that by checking for <meta property="al:ios:app_name" content="Medium"> in the document <head />
var metaCheck = document.head.querySelector('meta[property="al:ios:app_name"]');
if (metaCheck != null && metaCheck.content == "Medium") {
	makeReadable();

	chrome.storage.sync.get(null, function(items) {
		if (items.hideDickbar) {
			hideDickbar();
		}
		if (items.disableLazyImages) {
			disableLazyLoading();
		}
	});
}
<|endoftext|>


<commit_before>chrome.browserAction.onClicked.addListener(function(tab) {
  chrome.tabs.create({"url":"ui.html"});
});
<commit_msg>Background tab now only opens once.<commit_after>let doom;
chrome.browserAction.onClicked.addListener(function(initiatingTab) {
  chrome.tabs.getCurrent((tab) => {
    console.log("hi");
    if (!tab) {
      chrome.tabs.create({"url":"ui.html"});
      const bp = chrome.extension.getBackgroundPage();
    }
  });
});
<|endoftext|>


<commit_before>var rssFolderExists = false;
chrome.bookmarks.search({"title":"RSS"}, function(bookmarkTreeNodes) {
	if ( bookmarkTreeNodes.length > 0 ) {
		rssFolderExists = true;
	}
});
if ( ! rssFolderExists ) {
	chrome.bookmarks.create({
		"title": "RSS",
		"index": 0
	});
};
<commit_msg>Automatically add RSS folder to Other Bookmarks (if not exists)<commit_after>chrome.runtime.onInstalled.addListener(function(update) {
    if ( update.reason !== "chrome_update" ) {
        chrome.bookmarks.getTree(function(array) {
            var rootNode = array[0];
            var otherBookmarks = rootNode.children[1];
            if ( ! otherBookmarks.children.some(function(node) {return node.title === "RSS"}) ) {
                chrome.bookmarks.create({
                    index: 0,
                    title: "RSS"
                });
            }
        });
    }
});
<|endoftext|>


<commit_before>/*
 * BSD 3-Clause License
 *
 * Copyright (c) 2017, MapCreator
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 *  Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import ResourceProxy from '../proxy/ResourceProxy';
import {downloadFile} from '../utils/requests';
import CrudBase from './base/CrudBase';
import JobResult from './JobResult';
import JobRevision from './JobRevision';

export default class Job extends CrudBase {
  /**
   * Get the list of associated job results
   * @returns {SimpleResourceProxy} - A proxy for accessing the resource
   */
  get results() {
    return this._proxyResourceList(JobResult, `${this.url}/results`);
  }

  /**
   * Get the list job revisions
   * @returns {ResourceProxy} - A proxy for accessing the resource
   */
  get revisions() {
    const data = {
      jobId: this.id,
    };

    return new ResourceProxy(this.api, JobRevision, null, data);
  }

  /**
   * Resource name
   * @returns {String} - Resource name
   * @abstract
   */
  get resourceName() {
    return 'jobs';
  }

  /**
   * Get the most up to date preview url
   * @returns {string} - Last preview url
   * @deprecated
   * @see Job#previewUrl
   */
  get lastPreviewUrl() {
    return `${this.url}/preview`;
  }

  /**
   * Get the most up to date archive url
   * @returns {string} - Last archive url
   */
  get lastArchiveUrl() {
    return `${this.url}/revisions/last/result/archive`;
  }

  /**
   * Job result preview url, usable in an `<img>` tag
   * @returns {string} - Preview url
   */
  get previewUrl() {
    return `${this.url}/preview`;
  }

  /**
   * Get image blob url representation
   * @returns {Promise} - Resolves with a {@link String} containing a blob reference to the image and rejects with {@link ApiError}
   */
  downloadPreview() {
    return downloadFile(this.previewUrl, this._getDownloadHeaders()).then(data => data.blob);
  }

  /**
   * Get archive blob url
   * @returns {PromiseLike<{filename: string, blob: string}>} - Resolves with a blob reference and it's filename and rejects with {@link ApiError}
   */
  downloadOutput() {
    return downloadFile(`${this.url}/preview`, this._getDownloadHeaders());
  }

  /**
   * Get headers for downloading resources
   * @returns {{Accept: string, Authorization: string}} - Request headers
   * @private
   */
  _getDownloadHeaders() {
    return {
      Accept: 'application/json',
      Authorization: this.api.auth.token.toString(),
    };
  }
}
<commit_msg>Fix Job::downloadOutput route<commit_after>/*
 * BSD 3-Clause License
 *
 * Copyright (c) 2017, MapCreator
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 *  Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import ResourceProxy from '../proxy/ResourceProxy';
import {downloadFile} from '../utils/requests';
import CrudBase from './base/CrudBase';
import JobResult from './JobResult';
import JobRevision from './JobRevision';

export default class Job extends CrudBase {
  /**
   * Get the list of associated job results
   * @returns {SimpleResourceProxy} - A proxy for accessing the resource
   */
  get results() {
    return this._proxyResourceList(JobResult, `${this.url}/results`);
  }

  /**
   * Get the list job revisions
   * @returns {ResourceProxy} - A proxy for accessing the resource
   */
  get revisions() {
    const data = {
      jobId: this.id,
    };

    return new ResourceProxy(this.api, JobRevision, null, data);
  }

  /**
   * Resource name
   * @returns {String} - Resource name
   * @abstract
   */
  get resourceName() {
    return 'jobs';
  }

  /**
   * Get the most up to date preview url
   * @returns {string} - Last preview url
   * @deprecated
   * @see Job#previewUrl
   */
  get lastPreviewUrl() {
    return `${this.url}/preview`;
  }

  /**
   * Get the most up to date archive url
   * @returns {string} - Last archive url
   */
  get lastArchiveUrl() {
    return `${this.url}/revisions/last/result/archive`;
  }

  /**
   * Job result preview url, usable in an `<img>` tag
   * @returns {string} - Preview url
   */
  get previewUrl() {
    return `${this.url}/preview`;
  }

  /**
   * Get image blob url representation
   * @returns {Promise} - Resolves with a {@link String} containing a blob reference to the image and rejects with {@link ApiError}
   */
  downloadPreview() {
    return downloadFile(this.previewUrl, this._getDownloadHeaders()).then(data => data.blob);
  }

  /**
   * Get archive blob url
   * @returns {PromiseLike<{filename: string, blob: string}>} - Resolves with a blob reference and it's filename and rejects with {@link ApiError}
   */
  downloadOutput() {
    return downloadFile(`${this.url}/output`, this._getDownloadHeaders());
  }

  /**
   * Get headers for downloading resources
   * @returns {{Accept: string, Authorization: string}} - Request headers
   * @private
   */
  _getDownloadHeaders() {
    return {
      Accept: 'application/json',
      Authorization: this.api.auth.token.toString(),
    };
  }
}
<|endoftext|>


<commit_before>import mm723Image from '../../images/MM723_CNL_combo@2x.jpg';
import mm600Image from '../../images/MM600_CNL_combo@2x.jpg';
import { remote } from 'electron';

const i18n = remote.getGlobal( 'i18n' );

const devices = {
  accuchekusb: {
    instructions: i18n.t('Plug in meter with micro-USB cable'),
    name: 'Roche Accu-Chek Aviva Connect, Guide & Guide Me',
    key: 'accuchekusb',
    source: {type: 'device', driverId: 'AccuChekUSB'},
    enabled: {mac: true, win: true, linux: true},
    powerOnlyWarning: true,  // shows warning for power-only USB cables
  },
  carelink: {
    instructions: [i18n.t('Import from CareLink'), i18n.t('(We will not store your credentials)')],
    isFetching: false,
    key: 'carelink',
    name: 'Medtronic',
    // for the device selection list
    selectName: 'Medtronic (CareLink import)',
    source: {type: 'carelink'},
    enabled: {mac: true, win: true, linux: true}
  },
  caresensble: {
    instructions: i18n.t('Once paired, hold in right arrow until "BT Send" appears on the screen'),
    name: 'CareSens N Premier & Dual (using Bluetooth)',
    key: 'caresensble',
    source: {type: 'device', driverId: 'BluetoothLE'},
    enabled: {mac: true, win: false, linux: true}
  },
  caresens: {
    instructions: i18n.t('Plug in meter with cable and make sure the meter is switched on'),
    name: 'CareSens N Premier & Dual',
    key: 'caresens',
    source: {type: 'device', driverId: 'CareSens'},
    enabled: {mac: true, win: true, linux: true}
  },
  relionpremier: {
    instructions: i18n.t('Plug in meter with cable and make sure the meter is switched on'),
    name: 'ReliOn Premier (BLU, Voice & Classic)',
    key: 'relionpremier',
    source: {type: 'device', driverId: 'ReliOnPremier'},
    enabled: {mac: true, win: true, linux: true}
  },
  glucocardexpression: {
    instructions: {
                    text: i18n.t('Plug in meter with cable and set meter to'),
                    linkText: i18n.t('PC Link Mode'),
                    link: 'https://support.tidepool.org/hc/en-us/articles/4402234174100',
                  },
    name: 'GLUCOCARD Expression',
    key: 'glucocardexpression',
    source: {type: 'device', driverId: 'GlucocardExpression'},
    enabled: {mac: true, win: true, linux: true}
  },
  glucocardshine: {
    instructions: i18n.t('Plug in meter with cable and make sure the meter is switched on'),
    name: 'GLUCOCARD Shine & Shine XL',
    key: 'glucocardshine',
    source: {type: 'device', driverId: 'GlucocardShine'},
    enabled: {mac: true, win: true, linux: true}
  },
  glucocardshinehid: {
    instructions: i18n.t('Make sure the meter is switched off and plug in with micro-USB cable'),
    name: 'GLUCOCARD Shine Connex & Shine Express',
    key: 'glucocardshinehid',
    source: {type: 'device', driverId: 'GlucocardShineHID'},
    enabled: {mac: true, win: true, linux: true}
  },
  medtronic: {
    instructions: i18n.t('Connect your Contour Next Link to your computer'),
    image: {
      'src': mm723Image,
      'height': 128,
      'width': 200,
      'alt': 'Contour Next Link'
    },
    key: 'medtronic',
    name: 'Medtronic 523, 723, Veo or 530G',
    selectName: 'Medtronic 523, 723, Veo or 530G (using Contour Next Link)',
    source: {type: 'device', driverId: 'Medtronic'},
    enabled: {mac: true, win: true, linux: true}
  },
  medtronic600: {
    instructions: i18n.t('Connect your Contour Next Link 2.4 to your computer'),
    image: {
      'src': mm600Image,
      'height': 128,
      'width': 200,
      'alt': 'Bayer Contour Next Link 2.4'
    },
    key: 'medtronic600',
    name: 'Medtronic 630G, 640G or 670G',
    selectName: 'Medtronic 630G, 640G, 670G (using Contour Next Link 2.4)',
    showDriverLink: {mac: false, win: false},
    source: {type: 'device', driverId: 'Medtronic600'},
    enabled: {mac: true, win: true, linux: true}
  },
  omnipod: {
    instructions: [i18n.t('Classic PDM: Plug into USB. Wait for Export to complete. Click Upload.'), i18n.t('DASH PDM: Unlock. Plug into USB. Tap Export on PDM. Click Upload.')],
    key: 'omnipod',
    name: 'Insulet OmniPod',
    source: {type: 'device', driverId: 'InsuletOmniPod', extension: '.ibf'},
    enabled: {mac: true, win: true, linux: true},
    powerOnlyWarning: true,
  },
  dexcom: {
    instructions: i18n.t('Plug in receiver with micro-USB'),
    key: 'dexcom',
    name: 'Dexcom',
    source: {type: 'device', driverId: 'Dexcom'},
    enabled: {mac: true, win: true, linux: true}
  },
  precisionxtra: {
    instructions: i18n.t('Plug in meter with cable'),
    key: 'precisionxtra',
    name: 'Abbott Precision Xtra',
    source: {type: 'device', driverId: 'AbbottPrecisionXtra'},
    enabled: {mac: false, win: true, linux: true}
  },
  tandem: {
    instructions: i18n.t('Plug in pump with micro-USB'),
    key: 'tandem',
    name: 'Tandem',
    source: {type: 'device', driverId: 'Tandem'},
    enabled: {mac: true, win: true, linux: true},
    powerOnlyWarning: true,
  },
  abbottfreestylelite: {
    instructions: i18n.t('Plug in meter with cable'),
    key: 'abbottfreestylelite',
    name: 'Abbott FreeStyle Lite & Freedom Lite',
    source: {type: 'device', driverId: 'AbbottFreeStyleLite'},
    enabled: {mac: false, win: true, linux: true}
  },
  abbottfreestylelibre: {
    instructions: i18n.t('Plug in meter with micro-USB cable'),
    key: 'abbottfreestylelibre',
    name: 'Abbott FreeStyle Libre',
    source: {type: 'device', driverId: 'AbbottFreeStyleLibre'},
    enabled: {linux: true, mac: true, win: true},
    powerOnlyWarning: true,
  },
  abbottfreestyleneo: {
    instructions: i18n.t('Plug in meter with micro-USB cable'),
    key: 'abbottfreestyleneo',
    name: 'Abbott FreeStyle Precision/Optium Neo',
    source: {type: 'device', driverId: 'AbbottFreeStyleNeo'},
    enabled: {linux: true, mac: true, win: true},
    powerOnlyWarning: true,
  },
  bayercontournext: {
    instructions: i18n.t('Plug meter into USB port'),
    key: 'bayercontournext',
    name: 'Ascensia (Bayer) Contour Next',
    source: {type: 'device', driverId: 'BayerContourNext'},
    enabled: {mac: true, win: true, linux: true}
  },
  bayercontour: {
    instructions: i18n.t('Plug in meter with cable and make sure meter is switched on'),
    key: 'bayercontour',
    name: 'Ascensia (Bayer) Contour Next EZ, Contour, Contour Link or Contour Plus',
    source: {type: 'device', driverId: 'BayerContour'},
    enabled: {mac: true, win: true, linux: true}
  },
  animas: {
    instructions: i18n.t('Suspend and align back of pump with IR dongle front'),
    key: 'animas',
    name: 'Animas',
    source: {type: 'device', driverId: 'Animas'},
    enabled: {mac: true, win: true, linux: true}
  },
  onetouchverio: {
    instructions: i18n.t('Plug in meter with micro-USB'),
    name: 'OneTouch Verio, Verio Flex and Verio Reflect',
    key: 'onetouchverio',
    source: {type: 'device', driverId: 'OneTouchVerio'},
    enabled: {linux: true, mac: true, win: true},
    powerOnlyWarning: true,
  },
  onetouchverioiq: {
    instructions: i18n.t('Plug in meter with mini-USB'),
    name: 'OneTouch VerioIQ',
    key: 'onetouchverioiq',
    source: {type: 'device', driverId: 'OneTouchVerioIQ'},
    enabled: {mac: true, win: true, linux: true},
    powerOnlyWarning: true,
  },
  onetouchultramini: {
    instructions: i18n.t('Plug in meter with cable and make sure the meter is switched off'),
    name: 'OneTouch UltraMini',
    key: 'onetouchultramini',
    source: {type: 'device', driverId: 'OneTouchUltraMini'},
    enabled: {mac: true, win: true, linux: true}
  },
  onetouchultra2: {
    instructions: i18n.t('Plug in meter with cable and make sure the meter is switched off'),
    name: 'OneTouch Ultra 2',
    key: 'onetouchultra2',
    source: {type: 'device', driverId: 'OneTouchUltra2'},
    enabled: {mac: true, win: true, linux: true}
  },
  truemetrix: {
    instructions: i18n.t('True Metrix & True Metrix Air: Place meter in cradle \u2022 True Metrix Go: Plug in meter with micro-USB cable'),
    name: 'Trividia Health True Metrix',
    key: 'truemetrix',
    source: {type: 'device', driverId: 'TrueMetrix'},
    enabled: {mac: true, win: true, linux: true}
  },
};

export default devices;
<commit_msg>alphabetize Choose Devices list<commit_after>import mm723Image from '../../images/MM723_CNL_combo@2x.jpg';
import mm600Image from '../../images/MM600_CNL_combo@2x.jpg';
import { remote } from 'electron';

const i18n = remote.getGlobal( 'i18n' );

const devices = {
  carelink: {
    instructions: [i18n.t('Import from CareLink'), i18n.t('(We will not store your credentials)')],
    isFetching: false,
    key: 'carelink',
    name: 'Medtronic',
    // for the device selection list
    selectName: 'Medtronic (CareLink import)',
    source: {type: 'carelink'},
    enabled: {mac: true, win: true, linux: true}
  },
  abbottfreestylelibre: {
    instructions: i18n.t('Plug in meter with micro-USB cable'),
    key: 'abbottfreestylelibre',
    name: 'Abbott FreeStyle Libre',
    source: {type: 'device', driverId: 'AbbottFreeStyleLibre'},
    enabled: {linux: true, mac: true, win: true},
    powerOnlyWarning: true,
  },
  abbottfreestylelite: {
    instructions: i18n.t('Plug in meter with cable'),
    key: 'abbottfreestylelite',
    name: 'Abbott FreeStyle Lite & Freedom Lite',
    source: {type: 'device', driverId: 'AbbottFreeStyleLite'},
    enabled: {mac: false, win: true, linux: true}
  },
  abbottfreestyleneo: {
    instructions: i18n.t('Plug in meter with micro-USB cable'),
    key: 'abbottfreestyleneo',
    name: 'Abbott FreeStyle Precision/Optium Neo',
    source: {type: 'device', driverId: 'AbbottFreeStyleNeo'},
    enabled: {linux: true, mac: true, win: true},
    powerOnlyWarning: true,
  },
  precisionxtra: {
    instructions: i18n.t('Plug in meter with cable'),
    key: 'precisionxtra',
    name: 'Abbott Precision Xtra',
    source: {type: 'device', driverId: 'AbbottPrecisionXtra'},
    enabled: {mac: false, win: true, linux: true}
  },
  animas: {
    instructions: i18n.t('Suspend and align back of pump with IR dongle front'),
    key: 'animas',
    name: 'Animas',
    source: {type: 'device', driverId: 'Animas'},
    enabled: {mac: true, win: true, linux: true}
  },
  bayercontournext: {
    instructions: i18n.t('Plug meter into USB port'),
    key: 'bayercontournext',
    name: 'Ascensia (Bayer) Contour Next',
    source: {type: 'device', driverId: 'BayerContourNext'},
    enabled: {mac: true, win: true, linux: true}
  },
  bayercontour: {
    instructions: i18n.t('Plug in meter with cable and make sure meter is switched on'),
    key: 'bayercontour',
    name: 'Ascensia (Bayer) Contour Next EZ, Contour, Contour Link or Contour Plus',
    source: {type: 'device', driverId: 'BayerContour'},
    enabled: {mac: true, win: true, linux: true}
  },
  caresens: {
    instructions: i18n.t('Plug in meter with cable and make sure the meter is switched on'),
    name: 'CareSens N Premier & Dual',
    key: 'caresens',
    source: {type: 'device', driverId: 'CareSens'},
    enabled: {mac: true, win: true, linux: true}
  },
  caresensble: {
    instructions: i18n.t('Once paired, hold in right arrow until "BT Send" appears on the screen'),
    name: 'CareSens N Premier & Dual (using Bluetooth)',
    key: 'caresensble',
    source: {type: 'device', driverId: 'BluetoothLE'},
    enabled: {mac: true, win: false, linux: true}
  },
  dexcom: {
    instructions: i18n.t('Plug in receiver with micro-USB'),
    key: 'dexcom',
    name: 'Dexcom',
    source: {type: 'device', driverId: 'Dexcom'},
    enabled: {mac: true, win: true, linux: true}
  },
  glucocardexpression: {
    instructions: {
                    text: i18n.t('Plug in meter with cable and set meter to'),
                    linkText: i18n.t('PC Link Mode'),
                    link: 'https://support.tidepool.org/hc/en-us/articles/4402234174100',
                  },
    name: 'GLUCOCARD Expression',
    key: 'glucocardexpression',
    source: {type: 'device', driverId: 'GlucocardExpression'},
    enabled: {mac: true, win: true, linux: true}
  },
  glucocardshine: {
    instructions: i18n.t('Plug in meter with cable and make sure the meter is switched on'),
    name: 'GLUCOCARD Shine & Shine XL',
    key: 'glucocardshine',
    source: {type: 'device', driverId: 'GlucocardShine'},
    enabled: {mac: true, win: true, linux: true}
  },
  glucocardshinehid: {
    instructions: i18n.t('Make sure the meter is switched off and plug in with micro-USB cable'),
    name: 'GLUCOCARD Shine Connex & Shine Express',
    key: 'glucocardshinehid',
    source: {type: 'device', driverId: 'GlucocardShineHID'},
    enabled: {mac: true, win: true, linux: true}
  },
  omnipod: {
    instructions: [i18n.t('Classic PDM: Plug into USB. Wait for Export to complete. Click Upload.'), i18n.t('DASH PDM: Unlock. Plug into USB. Tap Export on PDM. Click Upload.')],
    key: 'omnipod',
    name: 'Insulet Omnipod',
    source: {type: 'device', driverId: 'InsuletOmniPod', extension: '.ibf'},
    enabled: {mac: true, win: true, linux: true},
    powerOnlyWarning: true,
  },
  medtronic: {
    instructions: i18n.t('Connect your Contour Next Link to your computer'),
    image: {
      'src': mm723Image,
      'height': 128,
      'width': 200,
      'alt': 'Contour Next Link'
    },
    key: 'medtronic',
    name: 'Medtronic 523, 723, Veo or 530G',
    selectName: 'Medtronic 523, 723, Veo or 530G (using Contour Next Link)',
    source: {type: 'device', driverId: 'Medtronic'},
    enabled: {mac: true, win: true, linux: true}
  },
  medtronic600: {
    instructions: i18n.t('Connect your Contour Next Link 2.4 to your computer'),
    image: {
      'src': mm600Image,
      'height': 128,
      'width': 200,
      'alt': 'Bayer Contour Next Link 2.4'
    },
    key: 'medtronic600',
    name: 'Medtronic 630G, 640G or 670G',
    selectName: 'Medtronic 630G, 640G, 670G (using Contour Next Link 2.4)',
    showDriverLink: {mac: false, win: false},
    source: {type: 'device', driverId: 'Medtronic600'},
    enabled: {mac: true, win: true, linux: true}
  },
  onetouchverio: {
    instructions: i18n.t('Plug in meter with micro-USB'),
    name: 'OneTouch Verio, Verio Flex and Verio Reflect',
    key: 'onetouchverio',
    source: {type: 'device', driverId: 'OneTouchVerio'},
    enabled: {linux: true, mac: true, win: true},
    powerOnlyWarning: true,
  },
  onetouchverioiq: {
    instructions: i18n.t('Plug in meter with mini-USB'),
    name: 'OneTouch VerioIQ',
    key: 'onetouchverioiq',
    source: {type: 'device', driverId: 'OneTouchVerioIQ'},
    enabled: {mac: true, win: true, linux: true},
    powerOnlyWarning: true,
  },
  onetouchultramini: {
    instructions: i18n.t('Plug in meter with cable and make sure the meter is switched off'),
    name: 'OneTouch UltraMini',
    key: 'onetouchultramini',
    source: {type: 'device', driverId: 'OneTouchUltraMini'},
    enabled: {mac: true, win: true, linux: true}
  },
  onetouchultra2: {
    instructions: i18n.t('Plug in meter with cable and make sure the meter is switched off'),
    name: 'OneTouch Ultra 2',
    key: 'onetouchultra2',
    source: {type: 'device', driverId: 'OneTouchUltra2'},
    enabled: {mac: true, win: true, linux: true}
  },
  relionpremier: {
    instructions: i18n.t('Plug in meter with cable and make sure the meter is switched on'),
    name: 'ReliOn Premier (BLU, Voice & Classic)',
    key: 'relionpremier',
    source: {type: 'device', driverId: 'ReliOnPremier'},
    enabled: {mac: true, win: true, linux: true}
  },
  accuchekusb: {
    instructions: i18n.t('Plug in meter with micro-USB cable'),
    name: 'Roche Accu-Chek Aviva Connect, Guide & Guide Me',
    key: 'accuchekusb',
    source: {type: 'device', driverId: 'AccuChekUSB'},
    enabled: {mac: true, win: true, linux: true},
    powerOnlyWarning: true,  // shows warning for power-only USB cables
  },
  tandem: {
    instructions: i18n.t('Plug in pump with micro-USB'),
    key: 'tandem',
    name: 'Tandem',
    source: {type: 'device', driverId: 'Tandem'},
    enabled: {mac: true, win: true, linux: true},
    powerOnlyWarning: true,
  },
  truemetrix: {
    instructions: i18n.t('True Metrix & True Metrix Air: Place meter in cradle \u2022 True Metrix Go: Plug in meter with micro-USB cable'),
    name: 'Trividia Health True Metrix',
    key: 'truemetrix',
    source: {type: 'device', driverId: 'TrueMetrix'},
    enabled: {mac: true, win: true, linux: true}
  },
};

export default devices;
<|endoftext|>


<commit_before>import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron'
import { bech32 } from 'lib/utils'
import { setError } from './error'

// ------------------------------------
// Constants
// ------------------------------------
export const GET_DESCRIBE_NETWORK = 'GET_DESCRIBE_NETWORK'
export const RECEIVE_DESCRIBE_NETWORK = 'RECEIVE_DESCRIBE_NETWORK'

export const GET_QUERY_ROUTES = 'GET_QUERY_ROUTES'
export const RECEIVE_QUERY_ROUTES = 'RECEIVE_QUERY_ROUTES'
export const RECEIVE_QUERY_ROUTES_FAILED = 'RECEIVE_QUERY_ROUTES_FAILED'

export const SET_CURRENT_ROUTE = 'SET_CURRENT_ROUTE'

export const SET_CURRENT_CHANNEL = 'SET_CURRENT_CHANNEL'

export const SET_CURRENT_TAB = 'SET_CURRENT_TAB'

export const SET_CURRENT_PEER = 'SET_CURRENT_PEER'

export const UPDATE_PAY_REQ = 'UPDATE_PAY_REQ'
export const RESET_PAY_REQ = 'RESET_PAY_REQ'

export const UPDATE_SELECTED_PEERS = 'UPDATE_SELECTED_PEERS'
export const CLEAR_SELECTED_PEERS = 'CLEAR_SELECTED_PEERS'

export const UPDATE_SELECTED_CHANNELS = 'UPDATE_SELECTED_CHANNELS'
export const CLEAR_SELECTED_CHANNELS = 'CLEAR_SELECTED_CHANNELS'

export const GET_INFO_AND_QUERY_ROUTES = 'GET_INFO_AND_QUERY_ROUTES'
export const RECEIVE_INFO_AND_QUERY_ROUTES = 'RECEIVE_INFO_AND_QUERY_ROUTES'
export const CLEAR_QUERY_ROUTES = 'CLEAR_QUERY_ROUTES'

// ------------------------------------
// Actions
// ------------------------------------
export function getDescribeNetwork() {
  return {
    type: GET_DESCRIBE_NETWORK
  }
}

export function getQueryRoutes(pubkey) {
  return {
    type: GET_QUERY_ROUTES,
    pubkey
  }
}

export function setCurrentRoute(route) {
  return {
    type: SET_CURRENT_ROUTE,
    route
  }
}

export function setCurrentChannel(selectedChannel) {
  return {
    type: SET_CURRENT_CHANNEL,
    selectedChannel
  }
}

export function setCurrentTab(currentTab) {
  return {
    type: SET_CURRENT_TAB,
    currentTab
  }
}

export function setCurrentPeer(currentPeer) {
  return {
    type: SET_CURRENT_PEER,
    currentPeer
  }
}

export function updatePayReq(pay_req) {
  return {
    type: UPDATE_PAY_REQ,
    pay_req
  }
}

export function resetPayReq() {
  return {
    type: RESET_PAY_REQ
  }
}

export function updateSelectedPeers(peer) {
  return {
    type: UPDATE_SELECTED_PEERS,
    peer
  }
}

export function updateSelectedChannels(channel) {
  return {
    type: UPDATE_SELECTED_CHANNELS,
    channel
  }
}

export function getInvoiceAndQueryRoutes() {
  return {
    type: GET_INFO_AND_QUERY_ROUTES
  }
}

export function clearQueryRoutes() {
  return {
    type: CLEAR_QUERY_ROUTES
  }
}

export function clearSelectedPeers() {
  return {
    type: CLEAR_SELECTED_PEERS
  }
}

export function clearSelectedChannels() {
  return {
    type: CLEAR_SELECTED_CHANNELS
  }
}

// Send IPC event for describeNetwork
export const fetchDescribeNetwork = () => dispatch => {
  dispatch(getDescribeNetwork())
  ipcRenderer.send('lnd', { msg: 'describeNetwork' })
}

// Receive IPC event for describeNetwork
export const receiveDescribeNetwork = (event, { nodes }) => dispatch =>
  dispatch({ type: RECEIVE_DESCRIBE_NETWORK, nodes })

export const queryRoutes = (pubkey, amount) => dispatch => {
  dispatch(getQueryRoutes(pubkey))
  ipcRenderer.send('lnd', { msg: 'queryRoutes', data: { pubkey, amount } })
}

export const queryRoutesFailed = (event, { error }) => dispatch => {
  dispatch({ type: RECEIVE_QUERY_ROUTES_FAILED })
  dispatch(setError(error))
}

export const receiveQueryRoutes = (event, { routes }) => dispatch =>
  dispatch({ type: RECEIVE_QUERY_ROUTES, routes })

// take a payreq and query routes for it
export const fetchInvoiceAndQueryRoutes = payreq => dispatch => {
  dispatch(getInvoiceAndQueryRoutes())
  ipcRenderer.send('lnd', { msg: 'getInvoiceAndQueryRoutes', data: { payreq } })
}

export const receiveInvoiceAndQueryRoutes = (event, { routes }) => dispatch =>
  dispatch({ type: RECEIVE_INFO_AND_QUERY_ROUTES, routes })

// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
  [GET_DESCRIBE_NETWORK]: state => ({ ...state, networkLoading: true }),
  [RECEIVE_DESCRIBE_NETWORK]: (state, { nodes }) => ({
    ...state,
    networkLoading: false,
    nodes
  }),

  [GET_QUERY_ROUTES]: (state, { pubkey }) => ({
    ...state,
    networkLoading: true,
    selectedNode: { pubkey, routes: [], currentRoute: {} }
  }),
  [RECEIVE_QUERY_ROUTES]: (state, { routes }) => ({
    ...state,
    networkLoading: false,
    selectedNode: { pubkey: state.selectedNode.pubkey, routes, currentRoute: routes[0] }
  }),
  [RECEIVE_QUERY_ROUTES_FAILED]: state => ({
    ...state,
    networkLoading: false,
    selectedNode: {}
  }),

  [SET_CURRENT_ROUTE]: (state, { route }) => ({ ...state, currentRoute: route }),

  [SET_CURRENT_CHANNEL]: (state, { selectedChannel }) => ({ ...state, selectedChannel }),

  [SET_CURRENT_TAB]: (state, { currentTab }) => ({ ...state, currentTab }),

  [SET_CURRENT_PEER]: (state, { currentPeer }) => ({ ...state, currentPeer }),

  [UPDATE_PAY_REQ]: (state, { pay_req }) => ({ ...state, pay_req }),
  [RESET_PAY_REQ]: state => ({ ...state, pay_req: '' }),

  [GET_INFO_AND_QUERY_ROUTES]: state => ({ ...state, fetchingInvoiceAndQueryingRoutes: true }),
  [RECEIVE_INFO_AND_QUERY_ROUTES]: (state, { routes }) => ({
    ...state,
    fetchingInvoiceAndQueryingRoutes: false,
    payReqRoutes: routes
  }),
  [CLEAR_QUERY_ROUTES]: state => ({ ...state, payReqRoutes: [], currentRoute: {} }),

  [UPDATE_SELECTED_PEERS]: (state, { peer }) => {
    let selectedPeers

    if (state.selectedPeers.includes(peer)) {
      selectedPeers = state.selectedPeers.filter(
        selectedPeer => selectedPeer.pub_key !== peer.pub_key
      )
    }

    if (!state.selectedPeers.includes(peer)) {
      selectedPeers = [...state.selectedPeers, peer]
    }

    return {
      ...state,
      selectedPeers
    }
  },
  [CLEAR_SELECTED_PEERS]: state => ({ ...state, selectedPeers: [] }),

  [UPDATE_SELECTED_CHANNELS]: (state, { channel }) => {
    let selectedChannels

    if (state.selectedChannels.includes(channel)) {
      selectedChannels = state.selectedChannels.filter(
        selectedChannel => selectedChannel.chan_id !== channel.chan_id
      )
    }

    if (!state.selectedChannels.includes(channel)) {
      selectedChannels = [...state.selectedChannels, channel]
    }

    return {
      ...state,
      selectedChannels
    }
  },
  [CLEAR_SELECTED_CHANNELS]: state => ({ ...state, selectedChannels: [] })
}

// ------------------------------------
// Selectors
// ------------------------------------
const networkSelectors = {}
const selectedPeersSelector = state => state.network.selectedPeers
const selectedChannelsSelector = state => state.network.selectedChannels
const payReqSelector = state => state.network.pay_req
const currentRouteSelector = state => state.network.currentRoute

// networkSelectors.currentRouteHopChanIds = createSelector(
//   currentRouteSelector,
//   (currentRoute) => {
//     if (!currentRoute.hops) { return [] }

//     return currentRoute.hops.map(hop => hop.chan_id)
//   }
// )

networkSelectors.selectedPeerPubkeys = createSelector(selectedPeersSelector, peers =>
  peers.map(peer => peer.pub_key)
)

networkSelectors.selectedChannelIds = createSelector(selectedChannelsSelector, channels =>
  channels.map(channel => channel.chan_id)
)

networkSelectors.payReqIsLn = createSelector(payReqSelector, input => {
  if (!input.startsWith('ln')) {
    return false
  }

  try {
    bech32.decode(input)
    return true
  } catch (e) {
    return false
  }
})

networkSelectors.currentRouteChanIds = createSelector(currentRouteSelector, route => {
  if (!route.hops || !route.hops.length) {
    return []
  }

  return route.hops.map(hop => hop.chan_id)
})

export { networkSelectors }

// ------------------------------------
// Initial State
// ------------------------------------
const initialState = {
  networkLoading: false,
  nodes: [],
  selectedChannel: {},
  selectedNode: {},

  currentTab: 1,

  currentPeer: {},
  currentRoute: {},

  fetchingInvoiceAndQueryingRoutes: false,
  pay_req: '',
  payReqRoutes: [],
  selectedPeers: [],
  selectedChannels: []
}

// ------------------------------------
// Reducer
// ------------------------------------
export default function activityReducer(state = initialState, action) {
  const handler = ACTION_HANDLERS[action.type]

  return handler ? handler(state, action) : state
}
<commit_msg>Revert "perf(redux): don't store channel edges"<commit_after>import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron'
import { bech32 } from 'lib/utils'
import { setError } from './error'

// ------------------------------------
// Constants
// ------------------------------------
export const GET_DESCRIBE_NETWORK = 'GET_DESCRIBE_NETWORK'
export const RECEIVE_DESCRIBE_NETWORK = 'RECEIVE_DESCRIBE_NETWORK'

export const GET_QUERY_ROUTES = 'GET_QUERY_ROUTES'
export const RECEIVE_QUERY_ROUTES = 'RECEIVE_QUERY_ROUTES'
export const RECEIVE_QUERY_ROUTES_FAILED = 'RECEIVE_QUERY_ROUTES_FAILED'

export const SET_CURRENT_ROUTE = 'SET_CURRENT_ROUTE'

export const SET_CURRENT_CHANNEL = 'SET_CURRENT_CHANNEL'

export const SET_CURRENT_TAB = 'SET_CURRENT_TAB'

export const SET_CURRENT_PEER = 'SET_CURRENT_PEER'

export const UPDATE_PAY_REQ = 'UPDATE_PAY_REQ'
export const RESET_PAY_REQ = 'RESET_PAY_REQ'

export const UPDATE_SELECTED_PEERS = 'UPDATE_SELECTED_PEERS'
export const CLEAR_SELECTED_PEERS = 'CLEAR_SELECTED_PEERS'

export const UPDATE_SELECTED_CHANNELS = 'UPDATE_SELECTED_CHANNELS'
export const CLEAR_SELECTED_CHANNELS = 'CLEAR_SELECTED_CHANNELS'

export const GET_INFO_AND_QUERY_ROUTES = 'GET_INFO_AND_QUERY_ROUTES'
export const RECEIVE_INFO_AND_QUERY_ROUTES = 'RECEIVE_INFO_AND_QUERY_ROUTES'
export const CLEAR_QUERY_ROUTES = 'CLEAR_QUERY_ROUTES'

// ------------------------------------
// Actions
// ------------------------------------
export function getDescribeNetwork() {
  return {
    type: GET_DESCRIBE_NETWORK
  }
}

export function getQueryRoutes(pubkey) {
  return {
    type: GET_QUERY_ROUTES,
    pubkey
  }
}

export function setCurrentRoute(route) {
  return {
    type: SET_CURRENT_ROUTE,
    route
  }
}

export function setCurrentChannel(selectedChannel) {
  return {
    type: SET_CURRENT_CHANNEL,
    selectedChannel
  }
}

export function setCurrentTab(currentTab) {
  return {
    type: SET_CURRENT_TAB,
    currentTab
  }
}

export function setCurrentPeer(currentPeer) {
  return {
    type: SET_CURRENT_PEER,
    currentPeer
  }
}

export function updatePayReq(pay_req) {
  return {
    type: UPDATE_PAY_REQ,
    pay_req
  }
}

export function resetPayReq() {
  return {
    type: RESET_PAY_REQ
  }
}

export function updateSelectedPeers(peer) {
  return {
    type: UPDATE_SELECTED_PEERS,
    peer
  }
}

export function updateSelectedChannels(channel) {
  return {
    type: UPDATE_SELECTED_CHANNELS,
    channel
  }
}

export function getInvoiceAndQueryRoutes() {
  return {
    type: GET_INFO_AND_QUERY_ROUTES
  }
}

export function clearQueryRoutes() {
  return {
    type: CLEAR_QUERY_ROUTES
  }
}

export function clearSelectedPeers() {
  return {
    type: CLEAR_SELECTED_PEERS
  }
}

export function clearSelectedChannels() {
  return {
    type: CLEAR_SELECTED_CHANNELS
  }
}

// Send IPC event for describeNetwork
export const fetchDescribeNetwork = () => dispatch => {
  dispatch(getDescribeNetwork())
  ipcRenderer.send('lnd', { msg: 'describeNetwork' })
}

// Receive IPC event for describeNetwork
export const receiveDescribeNetwork = (event, { nodes, edges }) => dispatch =>
  dispatch({ type: RECEIVE_DESCRIBE_NETWORK, nodes, edges })

export const queryRoutes = (pubkey, amount) => dispatch => {
  dispatch(getQueryRoutes(pubkey))
  ipcRenderer.send('lnd', { msg: 'queryRoutes', data: { pubkey, amount } })
}

export const queryRoutesFailed = (event, { error }) => dispatch => {
  dispatch({ type: RECEIVE_QUERY_ROUTES_FAILED })
  dispatch(setError(error))
}

export const receiveQueryRoutes = (event, { routes }) => dispatch =>
  dispatch({ type: RECEIVE_QUERY_ROUTES, routes })

// take a payreq and query routes for it
export const fetchInvoiceAndQueryRoutes = payreq => dispatch => {
  dispatch(getInvoiceAndQueryRoutes())
  ipcRenderer.send('lnd', { msg: 'getInvoiceAndQueryRoutes', data: { payreq } })
}

export const receiveInvoiceAndQueryRoutes = (event, { routes }) => dispatch =>
  dispatch({ type: RECEIVE_INFO_AND_QUERY_ROUTES, routes })

// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
  [GET_DESCRIBE_NETWORK]: state => ({ ...state, networkLoading: true }),
  [RECEIVE_DESCRIBE_NETWORK]: (state, { nodes, edges }) => ({
    ...state,
    networkLoading: false,
    nodes,
    edges
  }),

  [GET_QUERY_ROUTES]: (state, { pubkey }) => ({
    ...state,
    networkLoading: true,
    selectedNode: { pubkey, routes: [], currentRoute: {} }
  }),
  [RECEIVE_QUERY_ROUTES]: (state, { routes }) => ({
    ...state,
    networkLoading: false,
    selectedNode: { pubkey: state.selectedNode.pubkey, routes, currentRoute: routes[0] }
  }),
  [RECEIVE_QUERY_ROUTES_FAILED]: state => ({
    ...state,
    networkLoading: false,
    selectedNode: {}
  }),

  [SET_CURRENT_ROUTE]: (state, { route }) => ({ ...state, currentRoute: route }),

  [SET_CURRENT_CHANNEL]: (state, { selectedChannel }) => ({ ...state, selectedChannel }),

  [SET_CURRENT_TAB]: (state, { currentTab }) => ({ ...state, currentTab }),

  [SET_CURRENT_PEER]: (state, { currentPeer }) => ({ ...state, currentPeer }),

  [UPDATE_PAY_REQ]: (state, { pay_req }) => ({ ...state, pay_req }),
  [RESET_PAY_REQ]: state => ({ ...state, pay_req: '' }),

  [GET_INFO_AND_QUERY_ROUTES]: state => ({ ...state, fetchingInvoiceAndQueryingRoutes: true }),
  [RECEIVE_INFO_AND_QUERY_ROUTES]: (state, { routes }) => ({
    ...state,
    fetchingInvoiceAndQueryingRoutes: false,
    payReqRoutes: routes
  }),
  [CLEAR_QUERY_ROUTES]: state => ({ ...state, payReqRoutes: [], currentRoute: {} }),

  [UPDATE_SELECTED_PEERS]: (state, { peer }) => {
    let selectedPeers

    if (state.selectedPeers.includes(peer)) {
      selectedPeers = state.selectedPeers.filter(
        selectedPeer => selectedPeer.pub_key !== peer.pub_key
      )
    }

    if (!state.selectedPeers.includes(peer)) {
      selectedPeers = [...state.selectedPeers, peer]
    }

    return {
      ...state,
      selectedPeers
    }
  },
  [CLEAR_SELECTED_PEERS]: state => ({ ...state, selectedPeers: [] }),

  [UPDATE_SELECTED_CHANNELS]: (state, { channel }) => {
    let selectedChannels

    if (state.selectedChannels.includes(channel)) {
      selectedChannels = state.selectedChannels.filter(
        selectedChannel => selectedChannel.chan_id !== channel.chan_id
      )
    }

    if (!state.selectedChannels.includes(channel)) {
      selectedChannels = [...state.selectedChannels, channel]
    }

    return {
      ...state,
      selectedChannels
    }
  },
  [CLEAR_SELECTED_CHANNELS]: state => ({ ...state, selectedChannels: [] })
}

// ------------------------------------
// Selectors
// ------------------------------------
const networkSelectors = {}
const selectedPeersSelector = state => state.network.selectedPeers
const selectedChannelsSelector = state => state.network.selectedChannels
const payReqSelector = state => state.network.pay_req
const currentRouteSelector = state => state.network.currentRoute

// networkSelectors.currentRouteHopChanIds = createSelector(
//   currentRouteSelector,
//   (currentRoute) => {
//     if (!currentRoute.hops) { return [] }

//     return currentRoute.hops.map(hop => hop.chan_id)
//   }
// )

networkSelectors.selectedPeerPubkeys = createSelector(selectedPeersSelector, peers =>
  peers.map(peer => peer.pub_key)
)

networkSelectors.selectedChannelIds = createSelector(selectedChannelsSelector, channels =>
  channels.map(channel => channel.chan_id)
)

networkSelectors.payReqIsLn = createSelector(payReqSelector, input => {
  if (!input.startsWith('ln')) {
    return false
  }

  try {
    bech32.decode(input)
    return true
  } catch (e) {
    return false
  }
})

networkSelectors.currentRouteChanIds = createSelector(currentRouteSelector, route => {
  if (!route.hops || !route.hops.length) {
    return []
  }

  return route.hops.map(hop => hop.chan_id)
})

export { networkSelectors }

// ------------------------------------
// Initial State
// ------------------------------------
const initialState = {
  networkLoading: false,
  nodes: [],
  edges: [],
  selectedChannel: {},
  selectedNode: {},

  currentTab: 1,

  currentPeer: {},
  currentRoute: {},

  fetchingInvoiceAndQueryingRoutes: false,
  pay_req: '',
  payReqRoutes: [],
  selectedPeers: [],
  selectedChannels: []
}

// ------------------------------------
// Reducer
// ------------------------------------
export default function activityReducer(state = initialState, action) {
  const handler = ACTION_HANDLERS[action.type]

  return handler ? handler(state, action) : state
}
<|endoftext|>


<commit_before>/*****
  Reviews redux set will deal with single and multiple reviews.
  Single review in state.reviews.selected.
  Multiple reviews in state.reviews.list.
*****/

/* -------------------<   ACTIONS   >--------------------- */

const SET_REVIEWS_LIST = 'SET_REVIEWS_LIST';
const SET_CURRENT_REVIEW = 'SET_CURRENT_REVIEW';
const ADD_REVIEW = 'ADD_REVIEW';

/* ---------------<   ACTION CREATORS   >------------------- */

// export const authenticated = user => ({
//   type: AUTHENTICATED, user
// })

/* -------------------<   REDUCERS   >--------------------- */

const initialState = {
  list: [],
  selected: {}
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
  }
  return state;
};

/* ------------------<   DISPATCHERS   >-------------------- */
import axios from 'axios';

// Fetch all reviews for a product
export const fetchReviews = () => dispatch => {
  axios.get(`/api/reviews`)
  .then(res => res.data)
  .then(reviews => dispatach(setReviews(reviews)))
  .catch(err => console.log(err))
};

// Fetch all reviews for a user

// Fetch a single review

export default reducer;
<commit_msg>added reviews dipatchers to fetchReviews for all products, single product and for users<commit_after>/*****
  Reviews redux set will deal with single and multiple reviews.
  Single review in state.reviews.selected.
  Multiple reviews in state.reviews.list.
*****/

/* -------------------<   ACTIONS   >--------------------- */

const SET_REVIEWS_LIST = 'SET_REVIEWS_LIST';
const SET_CURRENT_REVIEW = 'SET_CURRENT_REVIEW';
const ADD_REVIEW = 'ADD_REVIEW';

/* ---------------<   ACTION CREATORS   >------------------- */

// export const authenticated = user => ({
//   type: AUTHENTICATED, user
// })

/* -------------------<   REDUCERS   >--------------------- */

const initialState = {
  list: [],
  selected: {}
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
  }
  return state;
};

/* ------------------<   DISPATCHERS   >-------------------- */
import axios from 'axios';

// Fetch all reviews for a product
export const fetchReviews = () => dispatch => {
  axios.get(`/api/reviews`)
  .then(res => res.data)
  .then(reviews => dispatach(setReviews(reviews)))
  .catch(err => console.log(err))
};

// Fetch all reviews for a user
export const fetchUserReviews = (userId) => dispatch => {
  axios.get(`/api/users/{userId}/reviews`)
  .then(res => res.data)
  .then(reviews => dispatach(setReviews(reviews)))
  .catch(err => console.log(err))
};

// Fetch a single review
export const fetchReview = (reviewId) => dispatch => {
  axios.get(`/api/reviews/reviewId`)
  .then(res => res.data)
  .then(review => dispatch(setReview(review)))
  .catch(err => console.log(err))
};

export default reducer;
<|endoftext|>


<commit_before>import {fromJS, Map} from 'immutable'
import {call, put} from 'redux-saga/effects';
import {Apis} from 'shared/api_client';
import {List} from 'immutable'

// Test limit with 2 (not 1, infinate looping)
export function* loadFollows(method, account, type, start = '', limit = 100) {
    const res = fromJS(yield Apis.follow(method, account, start, type, limit))
    // console.log('res.toJS()', res.toJS())
    let cnt = 0
    let lastFollowing = null
    const key = method === "get_following" ? "following" : "follower";
    yield put({type: 'global/UPDATE', payload: {
        key: ['follow', method, account],
        notSet: Map(),
        updater: m => {
            m = m.update('result', Map(), m2 => {
                res.forEach(value => {
                    cnt++
                    let what = value.get('what')
                    if(typeof what === 'string') what = new List([what]) // TODO: after shared-db upgrade, this line can be removed
                    const following = lastFollowing = value.get(key)
                    m2 = m2.set(following, what)
                })
                return m2
            })
            const count = m.get('result') ? m.get('result').filter(a => {
                return a.get(0) === "blog";
            }).size : 0;
            return m.merge({count, [type]: {loading: true, error: null}})
        }
    }})
    if(cnt === limit) {
        yield call(loadFollows, method, account, type, lastFollowing)
    } else {
        yield put({type: 'global/UPDATE', payload: {
            key: ['follow', method, account],
            updater: m => m.merge({[type]: {loading: false, error: null}})
        }})
    }
}
<commit_msg>Separate follow types for data comming in from the API. #745<commit_after>import {fromJS, Map, Set, List} from 'immutable'
import {call, put} from 'redux-saga/effects';
import {Apis} from 'shared/api_client';

/**
    This loadFollows both 'blog' and 'ignore'
*/

// Test limit with 2 (not 1, infinate looping)
export function* loadFollows(method, account, type, start = '', limit = 100) {
    const res = fromJS(yield Apis.follow(method, account, start, type, limit))
    // console.log('res.toJS()', res.toJS())

    let cnt = 0
    let lastAccountName = null
    const accountNameKey = method === "get_following" ? "following" : "follower";

    yield put({type: 'global/UPDATE', payload: {
        key: ['follow', method, account],
        notSet: Map(),
        updater: m => {
            m = m.asMutable()
            res.forEach(value => {
                cnt++

                let whatList = value.get('what')
                if(typeof whatList === 'string')
                    whatList = new List([whatList]) // TODO: after shared-db upgrade, this line can be removed

                const accountName = lastAccountName = value.get(accountNameKey)
                whatList.forEach(what => {
                    //currently this is always true: what === type
                    m.update(what + '_loading', Set(), s => s.add(accountName))
                })
            })
            m.merge({[type]: {loading: true, error: null}})
            return m.asImmutable()
        }
    }})

    if(cnt === limit) {
        // This is paging each block of up to limit results
        yield call(loadFollows, method, account, type, lastAccountName)
    } else {
        // This condition happens only once at the very end of the list.
        // Every account has a different followers and following list for: blog, ignore
        yield put({type: 'global/UPDATE', payload: {
            key: ['follow', method, account],
            updater: m => {
                m = m.asMutable()
                const result = m.get(type + '_loading')
                m.delete(type + '_loading')
                m.merge({
                    [type + '_count']: result.size,
                    [type + '_result']: result,
                    [type]: {loading: false, error: null},
                })
                return m.asImmutable()
            }
        }})
    }
}
<|endoftext|>


<commit_before>/*
 * File: app/view/DistributionForm.js
 *
 * This file was generated by Sencha Architect version 2.2.2.
 * http://www.sencha.com/products/architect/
 *
 * This file requires use of the Ext JS 4.2.x library, under independent license.
 * License of Sencha Architect does not include license for Ext JS 4.2.x. For more
 * details see http://www.sencha.com/license or contact license@sencha.com.
 *
 * This file will be auto-generated each and everytime you save your project.
 *
 * Do NOT hand edit this file.
 */

Ext.define('C.view.DistributionForm', {
	extend: 'Ext.form.Panel',

	autoRender: true,
	border: '0 0 0 0',
	margin: 10,
	style: 'border: none',
	width: 280,
	layout: {
		type: 'auto'
	},
	bodyPadding: 10,
	title: 'My Form',

	initComponent: function() {
		var me = this;

		Ext.applyIf(me, {
			items: [
				{
					xtype: 'container',
					items: [
						{
							xtype: 'textfield',
							width: 220,
							fieldLabel: 'Name',
							labelWidth: 70,
							name: 'name'
						},
						{
							xtype: 'textfield',
							width: 220,
							fieldLabel: 'Type',
							labelWidth: 70,
							name: 'type'
						},
						{
							xtype: 'textfield',
							width: 220,
							fieldLabel: 'Description',
							labelWidth: 70,
							name: 'description'
						},
						{
							xtype: 'combobox',
							itemId: 'distrType',
							width: 220,
							fieldLabel: 'Types',
							labelWidth: 70,
							name: 'distrType',
							allowBlank: false,
							displayField: 'distrType',
							forceSelection: true,
							queryMode: 'local',
							store: 'DistrTypeStore',
							valueField: 'distrType',
							listeners: {
								change: {
									fn: me.onDistrTypeChange,
									scope: me
								}
							}
						},
						{
							xtype: 'textareafield',
							itemId: 'val',
							width: 220,
							fieldLabel: 'Values',
							labelWidth: 70,
							name: 'val',
							growAppend: '-',
							cols: 30,
							listeners: {
								beforerender: {
									fn: me.onTextareafieldBeforeRender,
									scope: me
								},
								change: {
									fn: me.onValChange,
									scope: me
								}
							}
						},
						{
							xtype: 'textareafield',
							itemId: 'params',
							width: 220,
							fieldLabel: 'Parameters',
							labelWidth: 70,
							name: 'params',
							listeners: {
								beforerender: {
									fn: me.onTextareafieldBeforeRender1,
									scope: me
								}
							}
						},
						{
							xtype: 'button',
							itemId: 'btn',
							margin: '10 0 0 90',
							width: 70,
							text: 'Update',
							listeners: {
								click: {
									fn: me.onButtonClick2,
									scope: me
								}
							}
						}
					]
				}
			]
		});

		me.callParent(arguments);
	},

	onDistrTypeChange: function(field, newValue, oldValue, eOpts) {
		if (newValue == 'Histogram') {
			this.down('#val').show();
			this.down('#params').setValue('[]');
			this.down('#params').hide();
			/*if (this.query('chart')[1]) {
			this.query('chart')[1].show();
			this.query('chart')[0].hide();
			}*/
		}
		else {
			this.down('#params').show();
			this.down('#val').setValue('[]');
			this.down('#val').hide();
			/*if (this.query('chart')[1] ) {
			this.query('chart')[1].hide();
			this.query('chart')[0].show();
			}*/
		}

	},

	onTextareafieldBeforeRender: function(component, eOpts) {
		component.helpText = 'For Histogram one needs to insert values:
[1,2,3,4...]';
		component.url = 'https://github.com/cassandra-project/platform/wiki/Activity-Model-form';
	},

	onValChange: function(field, newValue, oldValue, eOpts) {
		var valuesDistr = newValue.trim();
		try {
			valuesDistr = JSON.parse(valuesDistr);
		}
		catch(e) {
			return false;
		}
		if (this.query('chart')[1]) {
			if ( valuesDistr.length > 100) {
				this.query('chart')[1].hide();
				this.query('chart')[0].show();
			}
		}
	},

	onTextareafieldBeforeRender1: function(component, eOpts) {
		component.helpText = 'For the Uniform Distribution one needs to insert an expression with start and end values:
[{"start":100,"end":200}]

For the Normal Distribution one needs to insert an expression with mean and std values:
[{"mean":45,"std":10}]

Finally, for the Gaussian Mixture Models one needs to insert tuples of w, mean and std:
[{"w":1 , "mean":45,"std":10}, {"w":1 , "mean":100,"std":10}]' ;
		component.url = 'https://github.com/cassandra-project/platform/wiki/Activity-Model-form';
	},

	onButtonClick2: function(button, e, eOpts) {
		var myFormCmp = this;
		var myForm = this.getForm();
		var record =myForm.getRecord();
		var values = myForm.getValues();

		var parameters = myForm.getFieldValues().params.trim();
		var valuesDistr = myForm.getFieldValues().val.trim();
		var myDistrChart = this.query('chart')[0];
		var myDistrChartStore = this.query('chart')[0].store;
		var distr_type = this.distr_type;

		if(parameters) {
			try {
				parameters = JSON.parse(parameters);
			}
			catch(e) {
				Ext.MessageBox.show({
					title:'"Parameters" field: Invalid input',
					msg: 'A valid input example would be:
[{"w":103,"mean":203.3,"std":103.4}]',
					icon: Ext.MessageBox.ERROR
				});
				return false;
			}
		}
		else
		parameters = [];

		if(valuesDistr) {
			try {
				valuesDistr = JSON.parse(valuesDistr);
			}
			catch(e) {
				Ext.MessageBox.show({
					title:'"Values" field: Invalid input',
					msg: 'A valid input example would be: [3,4]',
					icon: Ext.MessageBox.ERROR
				});
				return false;
			}
		}
		else
		valuesDistr = [];

		if (record) {
			var distr_store = record.store;

			record.set({
				'name':values.name,
				'type': values.type,
				'description': values.description,
				'distrType': values.distrType,
				'parameters': parameters,
				'values': valuesDistr
			});

			if (record.isNew)
			record.isNew = false;

		}

		else {
			var propertiesCmp = Ext.getCmp('MainTabPanel').getActiveTab().query('form')[0];
			var actmod_record = propertiesCmp.getForm().getRecord();
			var distr_store = actmod_record.c.store;

			distr_store.insert(0,{
				name:values.name,
				type: values.type,
				description: values.description,
				distrType: values.distrType,
				values: valuesDistr,
				parameters: parameters,
				actmod_id:actmod_record.get('_id')
			});

		}

		distr_store.on(
		'update',
		function(store, record, operation, eOpts ) {
			if (record.isNew) {
				actmod_record.set(distr_type,record.get('_id') );
				myForm.loadRecord(record);
				myDistrChartStore.proxy.url += '/' + record.get('_id');

			}
			myDistrChartStore.on('load', function(store){
				var exp = store.proxy.reader.rawData.data[0].exp;
				var html = (exp < 0) ? ' x 10' + exp + ''  : ' ';
				myFormCmp.down('#expLabel').update(html);

				if (myFormCmp.query('chart')[1]) {
					if (record.get('distrType') == "Histogram") {
						myFormCmp.query('chart')[0].hide();
						myFormCmp.query('chart')[1].show();
					}
					else {
						myFormCmp.query('chart')[1].hide();
						myFormCmp.query('chart')[0].show();
					}
				}
			});
			myDistrChartStore.load();
		},
		null,
		{ single : true }
		);

		this.dirtyForm = false;

	}

});<commit_msg>implements #349<commit_after>/*
 * File: app/view/DistributionForm.js
 *
 * This file was generated by Sencha Architect version 2.2.2.
 * http://www.sencha.com/products/architect/
 *
 * This file requires use of the Ext JS 4.2.x library, under independent license.
 * License of Sencha Architect does not include license for Ext JS 4.2.x. For more
 * details see http://www.sencha.com/license or contact license@sencha.com.
 *
 * This file will be auto-generated each and everytime you save your project.
 *
 * Do NOT hand edit this file.
 */

Ext.define('C.view.DistributionForm', {
	extend: 'Ext.form.Panel',

	autoRender: true,
	border: '0 0 0 0',
	margin: 10,
	style: 'border: none',
	width: 280,
	layout: {
		type: 'auto'
	},
	bodyPadding: 10,
	title: 'My Form',

	initComponent: function() {
		var me = this;

		Ext.applyIf(me, {
			items: [
				{
					xtype: 'container',
					items: [
						{
							xtype: 'textfield',
							width: 220,
							fieldLabel: 'Name',
							labelWidth: 70,
							name: 'name'
						},
						{
							xtype: 'textfield',
							width: 220,
							fieldLabel: 'Type',
							labelWidth: 70,
							name: 'type'
						},
						{
							xtype: 'textfield',
							width: 220,
							fieldLabel: 'Description',
							labelWidth: 70,
							name: 'description'
						},
						{
							xtype: 'combobox',
							itemId: 'distrType',
							width: 220,
							fieldLabel: 'Types',
							labelWidth: 70,
							name: 'distrType',
							allowBlank: false,
							displayField: 'distrType',
							forceSelection: true,
							queryMode: 'local',
							store: 'DistrTypeStore',
							valueField: 'distrType',
							listeners: {
								change: {
									fn: me.onDistrTypeChange,
									scope: me
								}
							}
						},
						{
							xtype: 'textareafield',
							itemId: 'val',
							width: 220,
							fieldLabel: 'Values',
							labelWidth: 70,
							name: 'val',
							growAppend: '-',
							cols: 30,
							listeners: {
								beforerender: {
									fn: me.onTextareafieldBeforeRender,
									scope: me
								},
								change: {
									fn: me.onValChange,
									scope: me
								}
							}
						},
						{
							xtype: 'textareafield',
							itemId: 'params',
							width: 220,
							fieldLabel: 'Parameters',
							labelWidth: 70,
							name: 'params',
							listeners: {
								beforerender: {
									fn: me.onTextareafieldBeforeRender1,
									scope: me
								}
							}
						},
						{
							xtype: 'button',
							itemId: 'btn',
							margin: '10 0 0 90',
							width: 70,
							text: 'Update',
							listeners: {
								click: {
									fn: me.onButtonClick2,
									scope: me
								}
							}
						}
					]
				}
			]
		});

		me.callParent(arguments);
	},

	onDistrTypeChange: function(field, newValue, oldValue, eOpts) {
		if (newValue == 'Histogram') {
			this.down('#val').show();
			this.down('#params').setValue('[]');
			this.down('#params').hide();
			/*if (this.query('chart')[1]) {
			this.query('chart')[1].show();
			this.query('chart')[0].hide();
			}*/
		}
		else {
			this.down('#params').show();
			this.down('#val').setValue('[]');
			this.down('#val').hide();
			/*if (this.query('chart')[1] ) {
			this.query('chart')[1].hide();
			this.query('chart')[0].show();
			}*/
		}

	},

	onTextareafieldBeforeRender: function(component, eOpts) {
		component.helpText = 'For Histogram one needs to insert values:
[1,2,3,4...]';
		component.url = 'https://github.com/cassandra-project/platform/wiki/Activity-Model-form';
	},

	onValChange: function(field, newValue, oldValue, eOpts) {
		var valuesDistr = newValue.trim();
		try {
			valuesDistr = JSON.parse(valuesDistr);
		}
		catch(e) {
			return false;
		}
		if (this.query('chart')[1]) {
			if ( valuesDistr.length > 100) {
				this.query('chart')[1].hide();
				this.query('chart')[0].show();
			}
		}
	},

	onTextareafieldBeforeRender1: function(component, eOpts) {
		component.helpText = 'For the Uniform Distribution one needs to insert an expression with start and end values:
[{"start":100,"end":200}]

For the Normal Distribution one needs to insert an expression with mean and std values:
[{"mean":45,"std":10}]

Finally, for the Gaussian Mixture Models one needs to insert tuples of w (which should sum up to 1), mean and std:
[{"w":0.5 , "mean":45,"std":10}, {"w":0.5 , "mean":100,"std":10}]' ;
		component.url = 'https://github.com/cassandra-project/platform/wiki/Activity-Model-form';
	},

	onButtonClick2: function(button, e, eOpts) {
		var myFormCmp = this;
		var myForm = this.getForm();
		var record =myForm.getRecord();
		var values = myForm.getValues();

		var parameters = myForm.getFieldValues().params.trim();
		var valuesDistr = myForm.getFieldValues().val.trim();
		var myDistrChart = this.query('chart')[0];
		var myDistrChartStore = this.query('chart')[0].store;
		var distr_type = this.distr_type;

		if(parameters) {
			try {
				parameters = JSON.parse(parameters);
			}
			catch(e) {
				Ext.MessageBox.show({
					title:'"Parameters" field: Invalid input',
					msg: 'A valid input example would be:
[{"w":103,"mean":203.3,"std":103.4}]',
					icon: Ext.MessageBox.ERROR
				});
				return false;
			}
		}
		else
		parameters = [];

		if(valuesDistr) {
			try {
				valuesDistr = JSON.parse(valuesDistr);
			}
			catch(e) {
				Ext.MessageBox.show({
					title:'"Values" field: Invalid input',
					msg: 'A valid input example would be: [3,4]',
					icon: Ext.MessageBox.ERROR
				});
				return false;
			}
		}
		else
		valuesDistr = [];

		if (record) {
			var distr_store = record.store;

			record.set({
				'name':values.name,
				'type': values.type,
				'description': values.description,
				'distrType': values.distrType,
				'parameters': parameters,
				'values': valuesDistr
			});

			if (record.isNew)
			record.isNew = false;

		}

		else {
			var propertiesCmp = Ext.getCmp('MainTabPanel').getActiveTab().query('form')[0];
			var actmod_record = propertiesCmp.getForm().getRecord();
			var distr_store = actmod_record.c.store;

			distr_store.insert(0,{
				name:values.name,
				type: values.type,
				description: values.description,
				distrType: values.distrType,
				values: valuesDistr,
				parameters: parameters,
				actmod_id:actmod_record.get('_id')
			});

		}

		distr_store.on(
		'update',
		function(store, record, operation, eOpts ) {
			if (record.isNew) {
				actmod_record.set(distr_type,record.get('_id') );
				myForm.loadRecord(record);
				myDistrChartStore.proxy.url += '/' + record.get('_id');

			}
			myDistrChartStore.on('load', function(store){
				var exp = store.proxy.reader.rawData.data[0].exp;
				var html = (exp < 0) ? ' x 10' + exp + ''  : ' ';
				myFormCmp.down('#expLabel').update(html);

				if (myFormCmp.query('chart')[1]) {
					if (record.get('distrType') == "Histogram") {
						myFormCmp.query('chart')[0].hide();
						myFormCmp.query('chart')[1].show();
					}
					else {
						myFormCmp.query('chart')[1].hide();
						myFormCmp.query('chart')[0].show();
					}
				}
			});
			myDistrChartStore.load();
		},
		null,
		{ single : true }
		);

		this.dirtyForm = false;

	}

});<|endoftext|>