<commit_before>//this is the plugin / base code
    (function($){
       $.fn.oneStarter = function(location){
                function _s1(el,location) {
                  this.element = el;
                  this.loaded = false;
                  this.location = location;
                }
                _s1.prototype.overrideStyle = function() {
                        //update the basic CSS

                        //update body
                        $('body').addClass('sg-phone--content clear ng-scope');
                        if(this.location == 'record-action' || this.location == 'global-action' ) {
                          if(document.URL.indexOf('apex') < 0) { //this is Chatter

                            this.element.css('background-color','white');
                            this.element.css('height','250px');
                            this.element.css('overflow-y','auto');
                            this.element.css('overflow-','auto');
                            this.element.css('overflow','auto');

                          } else { //this is one.app

                          }

                          $('body').css('margin-right','10px');
                          if(Sfdc) {
                            Sfdc.canvas.client.resize({height : "1000px", width : "900px"});
                            console.log(Sfdc.canvas.client.size());
                          }
                        }
                        if(this.location == 'app') {
                          $('body').css('margin','10px');
                          $('body').css('margin-right','20px');
                          }
                        this.element.addClass('one-app-dynamic');

                        //font styles
                        $('.one-app-dynamic .simple-bold').addClass('man f3 text-color-1 fw-semibold');

                        //record icons
                        $('.one-app-dynamic .icon').addClass('bgs-100 a-mid mhm sq-30');

                        //buttons
                        $('.one-app-dynamic button').addClass('btn bg-secondary-btn btn--secondary pvs size-full brm border border--2 text-color-4 f3 fw-semibold');
                        $('.one-app-dynamic button').css('height','32px');

                        //fields and text fields
                        $('.one-app-dynamic section').addClass('one-field-section');
                        $('.one-app-dynamic :text').addClass('mbm size-full phm pvm input input--default input--ph-1 input--focus-1');
                        $('.one-app-dynamic :radio').addClass('radio radio--default radio--states-1 brc mrs bg-secondary-btn sq-22 a-mid dib');
                        $('.one-app-dynamic textarea').addClass('mbm size-full phm pvm input input--default input--ph-1 input--focus-1');
                        $('.one-app-dynamic select').addClass('mbm size-full phm pvm input input--default input--ph-1 input--focus-1');

                        $('.one-app-dynamic .lookup').before('Lookup');

                        //divs and sections
                        $('.one-app-dynamic article').addClass('mam bg-1 border border--3 brm');
                        $('.one-app-dynamic .padded').addClass('pam mtn');
                        $('.one-app-dynamic article header').addClass('clear pam border-bottom border--8');
                        $('.one-app-dynamic article header h1').addClass('fl man fw-normal f5 text-color-1');

                        //lists
                        $('.one-app-dynamic ul.list-simple').addClass('list-plain fw-normal bg-2 man pa');
                        $('.one-app-dynamic ul').css('padding-left','0px');
                        $('.one-app-dynamic ul.list-simple li').addClass('active--list-1 pam text-color-1 f4 border-bottom border--3');
                        $('.one-app-dynamic yl.list-plain li').addClass('f5 text-color-2');

                        //a
                        $('.one-app-dynamic a.link-right').addClass('fr');
                        $('.one-app-dynamic span.link-label').addClass('fl f5');
                        $('.one-app-dynamic span.link-icon-right').addClass('lh-16 fl mls f6 text-color-2');

                        //create carousel divs
                        //this.setCarousel($('div#one-carousel'));
                    }
               _s1.prototype.close = function() {
                        loadSfdc.canvas.publisher.publish({name: "publisher.close",payload:{ refresh:"true" }});
                    }
               _s1.prototype.enableSubmit = function(callback) {
                        if(document.URL.indexOf('apex') < 0) {

                             this.element.append('<button id="dyn_one_submit">Submit</button>');
                             $('#dyn_one_submit').css('position','fixed');
                             $('#dyn_one_submit').css('right','5px');
                             $('#dyn_one_submit').css('top','5px');
                             $('#dyn_one_submit').addClass('btn bg-secondary-btn btn--secondary pvs size-full brm border border--2 text-color-4 f3 fw-semibold');
                             $('#dyn_one_submit').css('height','32px');
                             $('#dyn_one_submit').css('width','75px');

                             $('#dyn_one_submit').click(callback);

                        } else { //one.app

                             Sfdc.canvas.publisher.publish({name: "publisher.setValidForSubmit", payload:"true"});
                             Sfdc.canvas.publisher.subscribe({name: "publisher.post", onData:function(e) {
                                callback();
                             }});

                        }

                    }
                _s1.prototype.disableSubmit = function() {
                        if(document.URL.indexOf('apex') < 0) {

                             $('#dyn_one_submit').remove();

                        } else { //one.app

                            Sfdc.canvas.publisher.publish({name: "publisher.setValidForSubmit", payload:"false"});
                            Sfdc.canvas.publisher.unsubscribe({name: "publisher.post"});

                        }
                    }

                _s1.prototype.addError = function(ele) {
                    if(ele == null) {
                      ele = this.element;
                    }
                    ele.addClass('input--error');
                }
                _s1.prototype.removeError = function(ele) {
                    if(ele == null) {
                      ele = this.element;
                    }
                    ele.removeClass('input--error');
                }
                _s1.prototype.carousel = function(ele) {
                    if(ele == null) {
                      ele = this.element;
                    }
                    ele.addClass('one-dark-body');

                    //create parent div
                    var dark_header = ele.wrap("

");

                    //stye carousel divs
                    ele.children('div').addClass('one-body-content');

                    //create pagination list
                    var pag_ul = ele.parent().before('

');
                    var count = ele.children('div').length;

                    for(var x = 0; x < count; x++) {
                      ele.parent().prev().append('
-+-
');
                      }

                    $(".one-body-content").siblings().hide();
                  currentDiv_body = $(".one-body-content").siblings().first();
                  currentDiv_body.show();

                  $(".js-indicator-body-a").removeClass('bg-10');
                  $(".js-indicator-body-a").removeClass('ig_2');
                  currentIndicator_body = $(".js-indicator-body").siblings().first();
                  currentIndicator_body.children(0).addClass('bg-10');
                  currentIndicator_body.children(0).addClass('ig-2');
                  currentIndicator_body.children(0).removeClass('bg-9');
                  currentIndicator_body.children(0).removeClass('is_4');

                    $('#one-body-carousel').swipe( {
                      allowPageScroll:"vertical",
                      excludedElements: "",
                      swipe:function(event, direction, distance, duration, fingerCount) {
                         if(direction == 'left') {
                            $(".one-body-content").siblings().hide();
                            $(".js-indicator-body-a").removeClass('bg-10');
                            $(".js-indicator-body-a").removeClass('ig_2');
                            $(".js-indicator-body-a").addClass('bg-9');
                            $(".js-indicator-body-a").addClass('is_4');

                            currentDiv_body = currentDiv_body.next();
                            currentIndicator_body = currentIndicator_body.next();
                            if(!currentDiv_body.hasClass('one-body-content')) {
                                currentDiv_body = $(".one-body-content").siblings().first();
                                currentIndicator_body = $(".js-indicator-body").siblings().first();
                                }
                            currentDiv_body.show();
                            currentIndicator_body.children(0).addClass('bg-10');
                            currentIndicator_body.children(0).addClass('ig-2');
                            currentIndicator_body.children(0).removeClass('bg-9');
                            currentIndicator_body.children(0).removeClass('is_4');
                        $.event.trigger({
                          type: 'carousel_change',
                          message: currentDiv_body.attr('id'),
                          time: new Date()
                          });
                         }
                         if(direction == 'right') {
                            $(".one-body-content").siblings().hide();
                            $(".js-indicator-body-a").removeClass('bg-10');
                            $(".js-indicator-body-a").removeClass('ig_2');
                            $(".js-indicator-body-a").addClass('bg-9');
                            $(".js-indicator-body-a").addClass('is_4');

                            currentDiv_body = currentDiv_body.prev();
                            currentIndicator_body = currentIndicator_body.prev();
                            if(!currentDiv_body.hasClass('one-body-content')) {
                              currentDiv_body = $(".one-body-content").last();
                              currentIndicator_body = $(".js-indicator-body").siblings().last();
                              }
                            currentDiv_body.show();
                            currentIndicator_body.children(0).addClass('bg-10');
                            currentIndicator_body.children(0).addClass('ig-2');
                            currentIndicator_body.children(0).removeClass('bg-9');
                            currentIndicator_body.children(0).removeClass('is_4');
                            $.event.trigger({
                          type: 'carousel_change',
                          message: currentDiv_body.attr('id'),
                          time: new Date()
                          });
                          }
                          //    event.preventDefault();
                        },
                        threshold:100,
                        fingers:'all'
                    });
               }
              var js1 = new _s1(this,location);
              js1.overrideStyle();
              return js1;

       }

    })(jQuery);<commit_msg>Adding default VF styles and fixing enableSubmit (added delay)<commit_after>//this is the plugin / base code
    (function($){
       $.fn.oneStarter = function(location){
                function _s1(el,location) {
                  this.element = el;
                  this.loaded = false;
                  this.location = location;
                }
                _s1.prototype.overrideStyle = function() {
                        //update the basic CSS

                        //update body
                        $('body').addClass('sg-phone--content clear ng-scope');
                        if(this.location == 'record-action' || this.location == 'global-action' ) {
                          if(document.URL.indexOf('apex') < 0) { //this is Chatter

                            this.element.css('background-color','white');
                            this.element.css('height','250px');
                            this.element.css('overflow-y','auto');
                            this.element.css('overflow-','auto');
                            this.element.css('overflow','auto');

                          } else { //this is one.app

                          }

                          $('body').css('margin-right','10px');
                          if(Sfdc) {
                            Sfdc.canvas.client.resize({height : "1000px", width : "900px"});
                            console.log(Sfdc.canvas.client.size());
                          }
                        }
                        if(this.location == 'app') {
                          $('body').css('margin','10px');
                          $('body').css('margin-right','20px');
                          }
                        this.element.addClass('one-app-dynamic');

                        //font styles
                        $('.one-app-dynamic .simple-bold').addClass('man f3 text-color-1 fw-semibold');

                        //record icons
                        $('.one-app-dynamic .icon').addClass('bgs-100 a-mid mhm sq-30');

                        //buttons
                        $('.one-app-dynamic button').addClass('btn bg-secondary-btn btn--secondary pvs size-full brm border border--2 text-color-4 f3 fw-semibold');
                        $('.one-app-dynamic button').css('height','32px');

                        $('.one-app-dynamic .btn').addClass('btn bg-secondary-btn btn--secondary pvs size-full brm border border--2 text-color-4 f3 fw-semibold');
                        $('.one-app-dynamic .btn').css('height','32px');

                        //lookup icons dont really work
                        $('.one-app-dynamic .lookupIcon').css('display','none');

                        //fields and text fields
                        $('.one-app-dynamic section').addClass('one-field-section');
                        $('.one-app-dynamic :text').addClass('mbm size-full phm pvm input input--default input--ph-1 input--focus-1');
                        $('.one-app-dynamic :radio').addClass('radio radio--default radio--states-1 brc mrs bg-secondary-btn sq-22 a-mid dib');
                        $('.one-app-dynamic textarea').addClass('mbm size-full phm pvm input input--default input--ph-1 input--focus-1');
                        $('.one-app-dynamic select').addClass('mbm size-full phm pvm input input--default input--ph-1 input--focus-1');

                        $('.one-app-dynamic .lookup').before('Lookup');
                        $('.one-app-dynamic .lookupInput :text').before('Lookup');

                        //divs and sections
                        $('.one-app-dynamic article').addClass('mam bg-1 border border--3 brm');
                        $('.one-app-dynamic .padded').addClass('pam mtn');
                        $('.one-app-dynamic article header').addClass('clear pam border-bottom border--8');
                        $('.one-app-dynamic article header h1').addClass('fl man fw-normal f5 text-color-1');

                        //lists
                        $('.one-app-dynamic ul.list-simple').addClass('list-plain fw-normal bg-2 man pa');
                        $('.one-app-dynamic ul').css('padding-left','0px');
                        $('.one-app-dynamic ul.list-simple li').addClass('active--list-1 pam text-color-1 f4 border-bottom border--3');
                        $('.one-app-dynamic yl.list-plain li').addClass('f5 text-color-2');

                        //a
                        $('.one-app-dynamic a.link-right').addClass('fr');
                        $('.one-app-dynamic span.link-label').addClass('fl f5');
                        $('.one-app-dynamic span.link-icon-right').addClass('lh-16 fl mls f6 text-color-2');

                        //create carousel divs
                        //this.setCarousel($('div#one-carousel'));
                    }
               _s1.prototype.close = function() {
                        Sfdc.canvas.publisher.publish({name: "publisher.close",payload:{ refresh:"true" }});
                    }
               _s1.prototype.enableSubmit = function(callback) {
                        if(document.URL.indexOf('apex') < 0) {

                             this.element.append('<button id="dyn_one_submit">Submit</button>');
                             $('#dyn_one_submit').css('position','fixed');
                             $('#dyn_one_submit').css('right','5px');
                             $('#dyn_one_submit').css('top','5px');
                             $('#dyn_one_submit').addClass('btn bg-secondary-btn btn--secondary pvs size-full brm border border--2 text-color-4 f3 fw-semibold');
                             $('#dyn_one_submit').css('height','32px');
                             $('#dyn_one_submit').css('width','75px');

                             $('#dyn_one_submit').click(callback);

                        } else { //one.app
                          setTimeout(function () {
                             Sfdc.canvas.publisher.publish({name: "publisher.setValidForSubmit", payload:"true"});
                             Sfdc.canvas.publisher.subscribe({name: "publisher.post", onData:function(e) {
                                callback();
                             }});
                            },500);
                        }

                    }
                _s1.prototype.disableSubmit = function() {
                        if(document.URL.indexOf('apex') < 0) {

                             $('#dyn_one_submit').remove();

                        } else { //one.app

                            Sfdc.canvas.publisher.publish({name: "publisher.setValidForSubmit", payload:"false"});
                            Sfdc.canvas.publisher.unsubscribe({name: "publisher.post"});

                        }
                    }

                _s1.prototype.addError = function(ele) {
                    if(ele == null) {
                      ele = this.element;
                    }
                    ele.addClass('input--error');
                }
                _s1.prototype.removeError = function(ele) {
                    if(ele == null) {
                      ele = this.element;
                    }
                    ele.removeClass('input--error');
                }
                _s1.prototype.carousel = function(ele) {
                    if(ele == null) {
                      ele = this.element;
                    }
                    ele.addClass('one-dark-body');

                    //create parent div
                    var dark_header = ele.wrap("

");

                    //stye carousel divs
                    ele.children('div').addClass('one-body-content');

                    //create pagination list
                    var pag_ul = ele.parent().before('

');
                    var count = ele.children('div').length;

                    for(var x = 0; x < count; x++) {
                      ele.parent().prev().append('
-+-
');
                      }

                    $(".one-body-content").siblings().hide();
                  currentDiv_body = $(".one-body-content").siblings().first();
                  currentDiv_body.show();

                  $(".js-indicator-body-a").removeClass('bg-10');
                  $(".js-indicator-body-a").removeClass('ig_2');
                  currentIndicator_body = $(".js-indicator-body").siblings().first();
                  currentIndicator_body.children(0).addClass('bg-10');
                  currentIndicator_body.children(0).addClass('ig-2');
                  currentIndicator_body.children(0).removeClass('bg-9');
                  currentIndicator_body.children(0).removeClass('is_4');

                    $('#one-body-carousel').swipe( {
                      allowPageScroll:"vertical",
                      excludedElements: "",
                      swipe:function(event, direction, distance, duration, fingerCount) {
                         if(direction == 'left') {
                            $(".one-body-content").siblings().hide();
                            $(".js-indicator-body-a").removeClass('bg-10');
                            $(".js-indicator-body-a").removeClass('ig_2');
                            $(".js-indicator-body-a").addClass('bg-9');
                            $(".js-indicator-body-a").addClass('is_4');

                            currentDiv_body = currentDiv_body.next();
                            currentIndicator_body = currentIndicator_body.next();
                            if(!currentDiv_body.hasClass('one-body-content')) {
                                currentDiv_body = $(".one-body-content").siblings().first();
                                currentIndicator_body = $(".js-indicator-body").siblings().first();
                                }
                            currentDiv_body.show();
                            currentIndicator_body.children(0).addClass('bg-10');
                            currentIndicator_body.children(0).addClass('ig-2');
                            currentIndicator_body.children(0).removeClass('bg-9');
                            currentIndicator_body.children(0).removeClass('is_4');
                        $.event.trigger({
                          type: 'carousel_change',
                          message: currentDiv_body.attr('id'),
                          time: new Date()
                          });
                         }
                         if(direction == 'right') {
                            $(".one-body-content").siblings().hide();
                            $(".js-indicator-body-a").removeClass('bg-10');
                            $(".js-indicator-body-a").removeClass('ig_2');
                            $(".js-indicator-body-a").addClass('bg-9');
                            $(".js-indicator-body-a").addClass('is_4');

                            currentDiv_body = currentDiv_body.prev();
                            currentIndicator_body = currentIndicator_body.prev();
                            if(!currentDiv_body.hasClass('one-body-content')) {
                              currentDiv_body = $(".one-body-content").last();
                              currentIndicator_body = $(".js-indicator-body").siblings().last();
                              }
                            currentDiv_body.show();
                            currentIndicator_body.children(0).addClass('bg-10');
                            currentIndicator_body.children(0).addClass('ig-2');
                            currentIndicator_body.children(0).removeClass('bg-9');
                            currentIndicator_body.children(0).removeClass('is_4');
                            $.event.trigger({
                          type: 'carousel_change',
                          message: currentDiv_body.attr('id'),
                          time: new Date()
                          });
                          }
                          //    event.preventDefault();
                        },
                        threshold:100,
                        fingers:'all'
                    });
               }
              var js1 = new _s1(this,location);
              js1.overrideStyle();
              return js1;

       }

    })(jQuery);<|endoftext|>


<commit_before>'use strict';
/* istanbul ignore if */
if (typeof global.Promise === 'function') {
  exports.Promise = global.Promise;
} else {
  exports.Promise = require('lie');
}
// uniquify a list, similar to underscore's _.uniq
exports.uniq = function (arr) {
  var map = {};
  arr.forEach(function (element) {
    map[element] = true;
  });
  return Object.keys(map);
};

exports.inherits = require('inherits');
exports.extend = require('extend');
var argsarray = require('argsarray');

exports.promisedCallback = function (promise, callback) {
  if (callback) {
    promise.then(function (res) {
      callback(null, res);
    }, function (reason) {
      callback(reason);
    });
  }
  return promise;
};

exports.callbackify = function (fun) {
  return argsarray(function (args) {
    var cb = args.pop();
    var promise = fun.apply(this, args);
    if (typeof cb === 'function') {
      exports.promisedCallback(promise, cb);
    }
    return promise;
  });
};

// Promise finally util similar to Q.finally
exports.fin = function (promise, cb) {
  return promise.then(function (res) {
    var promise2 = cb();
    if (typeof promise2.then === 'function') {
      return promise2.then(function () {
        return res;
      });
    }
    return res;
  }, function (reason) {
    var promise2 = cb();
    if (typeof promise2.then === 'function') {
      return promise2.then(function () {
        throw reason;
      });
    }
    throw reason;
  });
};

exports.sequentialize = function (queue, promiseFactory) {
  return function () {
    var args = arguments;
    var that = this;
    return queue.add(function () {
      return promiseFactory.apply(that, args);
    });
  };
};

var crypto = require('crypto');
var md5 = require('md5-jkmyers');

exports.MD5 = function (string) {
  /* istanbul ignore else */
  if (!process.browser) {
    return crypto.createHash('md5').update(string).digest('hex');
  } else {
    return md5(string);
  }
};<commit_msg>(#175) - fix promisedCallback<commit_after>'use strict';
/* istanbul ignore if */
if (typeof global.Promise === 'function') {
  exports.Promise = global.Promise;
} else {
  exports.Promise = require('lie');
}
// uniquify a list, similar to underscore's _.uniq
exports.uniq = function (arr) {
  var map = {};
  arr.forEach(function (element) {
    map[element] = true;
  });
  return Object.keys(map);
};

exports.inherits = require('inherits');
exports.extend = require('extend');
var argsarray = require('argsarray');

exports.promisedCallback = function (promise, callback) {
  if (callback) {
    promise.then(function (res) {
      process.nextTick(function () {
        callback(null, res);
      });
    }, function (reason) {
      process.nextTick(function () {
        callback(reason);
      });
    });
  }
  return promise;
};

exports.callbackify = function (fun) {
  return argsarray(function (args) {
    var cb = args.pop();
    var promise = fun.apply(this, args);
    if (typeof cb === 'function') {
      exports.promisedCallback(promise, cb);
    }
    return promise;
  });
};

// Promise finally util similar to Q.finally
exports.fin = function (promise, cb) {
  return promise.then(function (res) {
    var promise2 = cb();
    if (typeof promise2.then === 'function') {
      return promise2.then(function () {
        return res;
      });
    }
    return res;
  }, function (reason) {
    var promise2 = cb();
    if (typeof promise2.then === 'function') {
      return promise2.then(function () {
        throw reason;
      });
    }
    throw reason;
  });
};

exports.sequentialize = function (queue, promiseFactory) {
  return function () {
    var args = arguments;
    var that = this;
    return queue.add(function () {
      return promiseFactory.apply(that, args);
    });
  };
};

var crypto = require('crypto');
var md5 = require('md5-jkmyers');

exports.MD5 = function (string) {
  /* istanbul ignore else */
  if (!process.browser) {
    return crypto.createHash('md5').update(string).digest('hex');
  } else {
    return md5(string);
  }
};<|endoftext|>


<commit_before>import React from 'react'

import { enterHotUpdate } from '../global/generation'
import AppContainer from '../AppContainer.dev'
import { resolveType } from './resolver'

const lazyConstructor = '_ctor'

export const updateLazy = (target, type) => {
  const ctor = type[lazyConstructor]
  if (target[lazyConstructor] !== type[lazyConstructor]) {
    // just execute `import` and RHL.register will do the job
    ctor()
  }
  if (!target[lazyConstructor].isPatchedByReactHotLoader) {
    target[lazyConstructor] = () =>
      ctor().then(m => {
        const C = resolveType(m.default)
        // chunks has been updated - new hot loader process is taking a place
        enterHotUpdate()
        return {
          default: React.forwardRef((props, ref) => (
            <AppContainer>
              <C {...props} ref={ref} />
            </AppContainer>
          )),
        }
      })
    target[lazyConstructor].isPatchedByReactHotLoader = true
  }
}

export const updateMemo = (target, { type }) => {
  target.type = resolveType(type)
}

export const updateForward = (target, { render }) => {
  target.render = render
}

export const updateContext = () => {
  // nil
}
<commit_msg>fix: invariant violation react 15<commit_after>import React from 'react'

import { enterHotUpdate } from '../global/generation'
import AppContainer from '../AppContainer.dev'
import { resolveType } from './resolver'

const lazyConstructor = '_ctor'

export const updateLazy = (target, type) => {
  const ctor = type[lazyConstructor]
  if (target[lazyConstructor] !== type[lazyConstructor]) {
    // just execute `import` and RHL.register will do the job
    ctor()
  }
  if (!target[lazyConstructor].isPatchedByReactHotLoader) {
    target[lazyConstructor] = () =>
      ctor().then(m => {
        const C = resolveType(m.default)
        // chunks has been updated - new hot loader process is taking a place
        enterHotUpdate()
        if (!React.forwardRef) {
          return {
            default: props => (
              <AppContainer>
                <C {...props} />
              </AppContainer>
            ),
          }
        }
        return {
          default: React.forwardRef((props, ref) => (
            <AppContainer>
              <C {...props} ref={ref} />
            </AppContainer>
          )),
        }
      })
    target[lazyConstructor].isPatchedByReactHotLoader = true
  }
}

export const updateMemo = (target, { type }) => {
  target.type = resolveType(type)
}

export const updateForward = (target, { render }) => {
  target.render = render
}

export const updateContext = () => {
  // nil
}
<|endoftext|>


<commit_before>var https = require('https');
var url = require('url');
var my_config = require('./config');

module.exports.callMethod = function(methodName, options, callback_error, callback) {
  options = options || {};
  callback = callback || function() {};
  callback_error = callback_error || function() {};

  var token = my_config.token;

  var url_description = url.parse('https://api.telegram.org/bot' + token + '/' + methodName);
  url_description.query = options;

  https.get(url.format(url_description), function(result) {
    var body = [];
    result.on('data', function(data) {
      body.push(data);
    });
    result.on('end', function() {
      body = Buffer.concat(body).toString();
      try {
        body = JSON.parse(body);
      } catch (e) {
        callback_error('Got invalid JSON');
        return;
      }
      if (result.statusCode == 200 && body.ok) {
        callback(body.result);
      } else {
        callback_error(body.description);
      }
    });
  }).on('error', function(err) {
    callback_error('Unable to make HTTPS request');
  });
}

module.exports.reportError = function(message) {
  var author_id = my_config.author_id;
  module.exports.callMethod('sendMessage', {
    chat_id: author_id,
    text: '===== ERROR =====\n' + message,
  });
}

module.exports.errorReporter = function(type) {
  return function(message) {
    module.exports.reportError(type + ': '+ message);
  }
}
<commit_msg>Better error reporting in util.js; console.log of errors<commit_after>var https = require('https');
var url = require('url');
var my_config = require('./config');

module.exports.callMethod = function(methodName, options, callback_error, callback) {
  options = options || {};
  callback = callback || function() {};
  callback_error = callback_error || function() {};

  var token = my_config.token;

  var url_description = url.parse('https://api.telegram.org/bot' + token + '/' + methodName);
  url_description.query = options;

  https.get(url.format(url_description), function(result) {
    var body = [];
    result.on('data', function(data) {
      body.push(data);
    });
    result.on('end', function() {
      body = Buffer.concat(body).toString();
      try {
        body = JSON.parse(body);
      } catch (e) {
        callback_error('Got invalid JSON:\n' + e + "\nBody:\n" + body);
        return;
      }
      if (result.statusCode == 200 && body.ok) {
        callback(body.result);
      } else {
        callback_error(body.description);
      }
    });
  }).on('error', function(err) {
    callback_error('Unable to make HTTPS request:\n' + err);
  });
}

module.exports.reportError = function(message) {
  var author_id = my_config.author_id;
  var time = new Date();
  message = "===== ERROR =====\n" + time + "\nTimestamp: " + time.getTime() + "\n" + message;
  console.log(message);
  module.exports.callMethod('sendMessage', {
    chat_id: author_id,
    text: message,
  });
}

module.exports.errorReporter = function(type) {
  return function(message) {
    module.exports.reportError(type + ': '+ message);
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Walter Bender
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with this library; if not, write to the Free Software
// Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA

// Definition of special blocks less commonly included.

// Define block actions here (flow blocks and arg blocks)
var evalFlowDict = {
    'publish': "if (args.length == 1) {doPublish(args[0]);};",
    'savesvg': "if (args.length == 1) {doSaveSVG(canvas, turtles, args[0])};",
    'print': "if (args.length == 1) {var msgContainer = msgText.parent; msgContainer.visible = true; msgText.text = args[0].toString(); msgContainer.updateCache(); stage.swapChildren(msgContainer, last(stage.children));};",
    'showblocks': "showBlocks(); turtleDelay = DEFAULTDELAY;",
    'hideblocks': "hideBlocks(); turtleDelay = 0;",
    'speak': "meSpeak.speak(args[0]);"
};

var evalArgDict = {
    'time': 'var d = new Date(); blocks.blockList[blk].value = (d.getTime() - time) / 1000;',
    'mousex': 'blocks.blockList[blk].value = stageX;',
    'mousey': 'blocks.blockList[blk].value = stageY;',
    'mousebutton': 'blocks.blockList[blk].value = stageMouseDown;',
    'keyboard': 'blocks.blockList[blk].value = currentKeyCode; lastKeyCode = currentKeyCode; currentKey = ""; currentKeyCode = 0;',
};

// Define block prototypes here
function initAdvancedProtoBlocks(palettes, blocks) {
    blocks.palettes = palettes;

    // Sensors palette
    var timeBlock = new ProtoBlock('time');
    timeBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['time'] = timeBlock;
    timeBlock.parameterBlock();
    timeBlock.staticLabels.push('time');

    var mousexBlock = new ProtoBlock('mousex');
    mousexBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['mousex'] = mousexBlock;
    mousexBlock.parameterBlock();
    mousexBlock.staticLabels.push('mouse x');

    var mouseyBlock = new ProtoBlock('mousey');
    mouseyBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['mousey'] = mouseyBlock;
    mouseyBlock.parameterBlock();
    mouseyBlock.staticLabels.push('mouse y');

    var mousebuttonBlock = new ProtoBlock('mousebutton');
    mousebuttonBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['mousebutton'] = mousebuttonBlock;
    mousebuttonBlock.booleanZeroArgBlock()
    mousebuttonBlock.staticLabels.push('mouse button');

    var keyboardBlock = new ProtoBlock('keyboard');
    keyboardBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['keyboard'] = keyboardBlock;
    keyboardBlock.parameterBlock();
    keyboardBlock.staticLabels.push('keyboard');

    var loudnessBlock = new ProtoBlock('loudness');
    loudnessBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['loudness'] = loudnessBlock;
    loudnessBlock.parameterBlock();
    loudnessBlock.staticLabels.push('loudness');

    // Extras palette
    var waitBlock = new ProtoBlock('wait');
    waitBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['wait'] = waitBlock;
    waitBlock.oneArgBlock();
    waitBlock.staticLabels.push('wait');
    waitBlock.defaults.push(1);

    var vspaceBlock = new ProtoBlock('vspace');
    vspaceBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['vspace'] = vspaceBlock;
    vspaceBlock.zeroArgBlock();
    // vspaceBlock.staticLabels.push('');

    var printBlock = new ProtoBlock('print');
    printBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['print'] = printBlock;
    printBlock.oneArgBlock();
    printBlock.staticLabels.push('print');
    printBlock.docks[1][2] = 'anyin';

    var getxTurtleBlock = new ProtoBlock('xturtle');
    getxTurtleBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['xturtle'] = getxTurtleBlock;
    getxTurtleBlock.oneArgMathBlock();
    getxTurtleBlock.staticLabels.push('turtle x');
    getxTurtleBlock.defaults.push('0');
    getxTurtleBlock.docks[1][2] = 'textin';

    var getyTurtleBlock = new ProtoBlock('yturtle');
    getyTurtleBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['yturtle'] = getyTurtleBlock;
    getyTurtleBlock.oneArgMathBlock();
    getyTurtleBlock.staticLabels.push('turtle y');
    getyTurtleBlock.defaults.push('0');
    getyTurtleBlock.docks[1][2] = 'textin';

    var startTurtleBlock = new ProtoBlock('startTurtle');
    startTurtleBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['startTurtle'] = startTurtleBlock;
    startTurtleBlock.oneArgBlock();
    startTurtleBlock.fontsize = '16px';
    startTurtleBlock.docks[1][2] = 'anyin';
    startTurtleBlock.defaults.push(0);
    startTurtleBlock.staticLabels.push('start turtle');

    var stopTurtleBlock = new ProtoBlock('stopTurtle');
    stopTurtleBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['stopTurtle'] = stopTurtleBlock;
    stopTurtleBlock.oneArgBlock();
    stopTurtleBlock.fontsize = '16px';
    stopTurtleBlock.docks[1][2] = 'anyin';
    stopTurtleBlock.defaults.push(0);
    stopTurtleBlock.staticLabels.push('stop turtle');

    var pubBlock = new ProtoBlock('publish');
    pubBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['publish'] = pubBlock;
    pubBlock.oneArgBlock();
    pubBlock.defaults.push('comment');
    pubBlock.staticLabels.push('publish');
    pubBlock.docks[1][2] = 'textin';

    var svgBlock = new ProtoBlock('savesvg');
    svgBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['savesvg'] = svgBlock;
    svgBlock.oneArgBlock();
    svgBlock.defaults.push('title');
    svgBlock.staticLabels.push('save svg');
    svgBlock.docks[1][2] = 'textin';

    var showBlocks = new ProtoBlock('showblocks');
    showBlocks.palette = palettes.dict['extras'];
    blocks.protoBlockDict['showblocks'] = showBlocks;
    showBlocks.zeroArgBlock();
    showBlocks.staticLabels.push('show');

    var hideBlocks = new ProtoBlock('hideblocks');
    hideBlocks.palette = palettes.dict['extras'];
    blocks.protoBlockDict['hideblocks'] = hideBlocks;
    hideBlocks.zeroArgBlock();
    hideBlocks.staticLabels.push('hide');

    var evalBlock = new ProtoBlock('eval');
    evalBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['eval'] = evalBlock;
    evalBlock.twoArgMathBlock();
    evalBlock.docks[1][2] = 'textin';
    evalBlock.defaults.push('x');
    evalBlock.defaults.push(100);
    evalBlock.staticLabels.push('eval');
    evalBlock.staticLabels.push('f(x)');
    evalBlock.staticLabels.push('x');

    var speakBlock = new ProtoBlock('speak');
    speakBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['speak'] = speakBlock;
    speakBlock.oneArgBlock();
    speakBlock.staticLabels.push('speak');
    speakBlock.defaults.push('hello');
    speakBlock.docks[1][2] = 'textin';

    var audioBlock = new ProtoBlock('playback');
    audioBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['playback'] = audioBlock;
    audioBlock.defaults.push(null);
    audioBlock.oneArgBlock();
    audioBlock.docks[1][2] = 'mediain';
    audioBlock.staticLabels.push('playback');

    var audioStopBlock = new ProtoBlock('stopplayback');
    audioStopBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['stopplayback'] = audioStopBlock;
    audioStopBlock.zeroArgBlock();
    audioStopBlock.staticLabels.push('stop');

    // Push protoblocks onto their palettes.
    for (var protoblock in blocks.protoBlockDict) {
        blocks.protoBlockDict[protoblock].palette.add(blocks.protoBlockDict[protoblock]);
    }

    // Populate the lists of block types.
    blocks.findBlockTypes();
}

// Block-specific code goes here

// Publish to FB
function doPublish(desc) {
    var url = doSave();
    console.log('push ' + url + ' to FB');
    var descElem = docById("description");
    var msg = desc + ' ' + descElem.value + ' ' + url;
    console.log('comment: ' + msg);
    var post_cb = function() {
        FB.api('/me/feed', 'post', {message: msg});
    };

    FB.login(post_cb, {scope: 'publish_actions'});
}

function doSaveSVG(canvas, turtles, desc) {
    var head = '<!DOCTYPE html>\n\n\n<title>' + desc + '</title>\n\n\n';
    var svg = doSVG(canvas, turtles, canvas.width, canvas.height, 1.0);
    var tail = '\n';
    // TODO: figure out if popups are blocked
    var svgWindow = window.open('data:image/svg+xml;utf8,' + svg, desc, '"width=' + canvas.width + ', height=' + canvas.height + '"');
}
<commit_msg>allow string or int args to turtle x,y<commit_after>// Copyright (c) 2014 Walter Bender
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with this library; if not, write to the Free Software
// Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA

// Definition of special blocks less commonly included.

// Define block actions here (flow blocks and arg blocks)
var evalFlowDict = {
    'publish': "if (args.length == 1) {doPublish(args[0]);};",
    'savesvg': "if (args.length == 1) {doSaveSVG(canvas, turtles, args[0])};",
    'print': "if (args.length == 1) {var msgContainer = msgText.parent; msgContainer.visible = true; msgText.text = args[0].toString(); msgContainer.updateCache(); stage.swapChildren(msgContainer, last(stage.children));};",
    'showblocks': "showBlocks(); turtleDelay = DEFAULTDELAY;",
    'hideblocks': "hideBlocks(); turtleDelay = 0;",
    'speak': "meSpeak.speak(args[0]);"
};

var evalArgDict = {
    'time': 'var d = new Date(); blocks.blockList[blk].value = (d.getTime() - time) / 1000;',
    'mousex': 'blocks.blockList[blk].value = stageX;',
    'mousey': 'blocks.blockList[blk].value = stageY;',
    'mousebutton': 'blocks.blockList[blk].value = stageMouseDown;',
    'keyboard': 'blocks.blockList[blk].value = currentKeyCode; lastKeyCode = currentKeyCode; currentKey = ""; currentKeyCode = 0;',
};

// Define block prototypes here
function initAdvancedProtoBlocks(palettes, blocks) {
    blocks.palettes = palettes;

    // Sensors palette
    var timeBlock = new ProtoBlock('time');
    timeBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['time'] = timeBlock;
    timeBlock.parameterBlock();
    timeBlock.staticLabels.push('time');

    var mousexBlock = new ProtoBlock('mousex');
    mousexBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['mousex'] = mousexBlock;
    mousexBlock.parameterBlock();
    mousexBlock.staticLabels.push('mouse x');

    var mouseyBlock = new ProtoBlock('mousey');
    mouseyBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['mousey'] = mouseyBlock;
    mouseyBlock.parameterBlock();
    mouseyBlock.staticLabels.push('mouse y');

    var mousebuttonBlock = new ProtoBlock('mousebutton');
    mousebuttonBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['mousebutton'] = mousebuttonBlock;
    mousebuttonBlock.booleanZeroArgBlock()
    mousebuttonBlock.staticLabels.push('mouse button');

    var keyboardBlock = new ProtoBlock('keyboard');
    keyboardBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['keyboard'] = keyboardBlock;
    keyboardBlock.parameterBlock();
    keyboardBlock.staticLabels.push('keyboard');

    var loudnessBlock = new ProtoBlock('loudness');
    loudnessBlock.palette = palettes.dict['sensors'];
    blocks.protoBlockDict['loudness'] = loudnessBlock;
    loudnessBlock.parameterBlock();
    loudnessBlock.staticLabels.push('loudness');

    // Extras palette
    var waitBlock = new ProtoBlock('wait');
    waitBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['wait'] = waitBlock;
    waitBlock.oneArgBlock();
    waitBlock.staticLabels.push('wait');
    waitBlock.defaults.push(1);

    var vspaceBlock = new ProtoBlock('vspace');
    vspaceBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['vspace'] = vspaceBlock;
    vspaceBlock.zeroArgBlock();
    // vspaceBlock.staticLabels.push('');

    var printBlock = new ProtoBlock('print');
    printBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['print'] = printBlock;
    printBlock.oneArgBlock();
    printBlock.staticLabels.push('print');
    printBlock.docks[1][2] = 'anyin';

    var getxTurtleBlock = new ProtoBlock('xturtle');
    getxTurtleBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['xturtle'] = getxTurtleBlock;
    getxTurtleBlock.oneArgMathBlock();
    getxTurtleBlock.staticLabels.push('turtle x');
    getxTurtleBlock.defaults.push(0);
    getxTurtleBlock.docks[1][2] = 'anyin';

    var getyTurtleBlock = new ProtoBlock('yturtle');
    getyTurtleBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['yturtle'] = getyTurtleBlock;
    getyTurtleBlock.oneArgMathBlock();
    getyTurtleBlock.staticLabels.push('turtle y');
    getyTurtleBlock.defaults.push(0);
    getyTurtleBlock.docks[1][2] = 'anyin';

    var startTurtleBlock = new ProtoBlock('startTurtle');
    startTurtleBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['startTurtle'] = startTurtleBlock;
    startTurtleBlock.oneArgBlock();
    startTurtleBlock.fontsize = '16px';
    startTurtleBlock.docks[1][2] = 'anyin';
    startTurtleBlock.defaults.push(0);
    startTurtleBlock.staticLabels.push('start turtle');

    var stopTurtleBlock = new ProtoBlock('stopTurtle');
    stopTurtleBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['stopTurtle'] = stopTurtleBlock;
    stopTurtleBlock.oneArgBlock();
    stopTurtleBlock.fontsize = '16px';
    stopTurtleBlock.docks[1][2] = 'anyin';
    stopTurtleBlock.defaults.push(0);
    stopTurtleBlock.staticLabels.push('stop turtle');

    var pubBlock = new ProtoBlock('publish');
    pubBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['publish'] = pubBlock;
    pubBlock.oneArgBlock();
    pubBlock.defaults.push('comment');
    pubBlock.staticLabels.push('publish');
    pubBlock.docks[1][2] = 'textin';

    var svgBlock = new ProtoBlock('savesvg');
    svgBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['savesvg'] = svgBlock;
    svgBlock.oneArgBlock();
    svgBlock.defaults.push('title');
    svgBlock.staticLabels.push('save svg');
    svgBlock.docks[1][2] = 'textin';

    var showBlocks = new ProtoBlock('showblocks');
    showBlocks.palette = palettes.dict['extras'];
    blocks.protoBlockDict['showblocks'] = showBlocks;
    showBlocks.zeroArgBlock();
    showBlocks.staticLabels.push('show');

    var hideBlocks = new ProtoBlock('hideblocks');
    hideBlocks.palette = palettes.dict['extras'];
    blocks.protoBlockDict['hideblocks'] = hideBlocks;
    hideBlocks.zeroArgBlock();
    hideBlocks.staticLabels.push('hide');

    var evalBlock = new ProtoBlock('eval');
    evalBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['eval'] = evalBlock;
    evalBlock.twoArgMathBlock();
    evalBlock.docks[1][2] = 'textin';
    evalBlock.defaults.push('x');
    evalBlock.defaults.push(100);
    evalBlock.staticLabels.push('eval');
    evalBlock.staticLabels.push('f(x)');
    evalBlock.staticLabels.push('x');

    var speakBlock = new ProtoBlock('speak');
    speakBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['speak'] = speakBlock;
    speakBlock.oneArgBlock();
    speakBlock.staticLabels.push('speak');
    speakBlock.defaults.push('hello');
    speakBlock.docks[1][2] = 'textin';

    var audioBlock = new ProtoBlock('playback');
    audioBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['playback'] = audioBlock;
    audioBlock.defaults.push(null);
    audioBlock.oneArgBlock();
    audioBlock.docks[1][2] = 'mediain';
    audioBlock.staticLabels.push('playback');

    var audioStopBlock = new ProtoBlock('stopplayback');
    audioStopBlock.palette = palettes.dict['extras'];
    blocks.protoBlockDict['stopplayback'] = audioStopBlock;
    audioStopBlock.zeroArgBlock();
    audioStopBlock.staticLabels.push('stop');

    // Push protoblocks onto their palettes.
    for (var protoblock in blocks.protoBlockDict) {
        blocks.protoBlockDict[protoblock].palette.add(blocks.protoBlockDict[protoblock]);
    }

    // Populate the lists of block types.
    blocks.findBlockTypes();
}

// Block-specific code goes here

// Publish to FB
function doPublish(desc) {
    var url = doSave();
    console.log('push ' + url + ' to FB');
    var descElem = docById("description");
    var msg = desc + ' ' + descElem.value + ' ' + url;
    console.log('comment: ' + msg);
    var post_cb = function() {
        FB.api('/me/feed', 'post', {message: msg});
    };

    FB.login(post_cb, {scope: 'publish_actions'});
}

function doSaveSVG(canvas, turtles, desc) {
    var head = '<!DOCTYPE html>\n\n\n<title>' + desc + '</title>\n\n\n';
    var svg = doSVG(canvas, turtles, canvas.width, canvas.height, 1.0);
    var tail = '\n';
    // TODO: figure out if popups are blocked
    var svgWindow = window.open('data:image/svg+xml;utf8,' + svg, desc, '"width=' + canvas.width + ', height=' + canvas.height + '"');
}
<|endoftext|>


<commit_before>import { VACCINE_ACTIONS } from '../actions/VaccineActions';

const initialState = () => ({
  isSyncingTemps: false,
  setLogIntervalFor: '',
});

export const VaccineReducer = (state = initialState(), action) => {
  const { type } = action;

  switch (type) {
    case VACCINE_ACTIONS.DOWNLOAD_LOGS_START: {
      return { ...state, isSyncingTemps: true };
    }

    case VACCINE_ACTIONS.DOWNLOAD_LOGS_ERROR: {
      return { ...state, isSyncingTemps: false };
    }

    case VACCINE_ACTIONS.DOWNLOAD_LOGS_COMPLETE: {
      return { ...state, isSyncingTemps: false };
    }

    case VACCINE_ACTIONS.SET_LOG_INTERVAL_START: {
      const { payload } = action;
      const { macAddress } = payload;

      return { ...state, setLogIntervalFor: macAddress };
    }

    case VACCINE_ACTIONS.SET_LOG_INTERVAL_SUCCESS:
    case VACCINE_ACTIONS.SET_LOG_INTERVAL_ERROR: {
      return { ...state, setLogIntervalFor: '' };
    }

    case VACCINE_ACTIONS.DISABLE_BUTTON_START: {
      const { payload } = action;
      const { macAddress } = payload;

      return { ...state, sendingDisableButtonTo: macAddress };
    }

    case VACCINE_ACTIONS.DISABLE_BUTTON_STOP: {
      return { ...state, sendingDisableButtonTo: '' };
    }

    default:
      return state;
  }
};
<commit_msg>Add update to VaccineReducer to hole and handle state of the last download time and status<commit_after>import { VACCINE_ACTIONS } from '../actions/VaccineActions';

const LAST_DOWNLOAD_STATUS = {
  OK: 'OK',
  ERROR: 'ERROR',
};

const initialState = () => ({
  isSyncingTemps: false,
  setLogIntervalFor: '',
  downloadingLogsFrom: '',
  lastDownloadStatus: {},
  lastDownloadTime: {},
});

export const VaccineReducer = (state = initialState(), action) => {
  const { type } = action;

  switch (type) {
    case VACCINE_ACTIONS.SENSOR_DOWNLOAD_START: {
      const { payload } = action;
      const { sensor } = payload;
      const { macAddress } = sensor;

      return { ...state, downloadingLogsFrom: macAddress };
    }

    case VACCINE_ACTIONS.SENSOR_DOWNLOAD_SUCCESS: {
      const { lastDownloadStatus, lastDownloadTime } = state;
      const { payload } = action;
      const { sensor } = payload;
      const { macAddress } = sensor;

      const newLastDownloadStatus = {
        ...lastDownloadStatus,
        [macAddress]: LAST_DOWNLOAD_STATUS.OK,
      };

      const newLastDownloadTime = {
        ...lastDownloadTime,
        [macAddress]: new Date(),
      };

      return {
        ...state,
        lastDownloadStatus: newLastDownloadStatus,
        lastDownloadTime: newLastDownloadTime,
        downloadingLogsFrom: '',
      };
    }

    case VACCINE_ACTIONS.SENSOR_DOWNLOAD_ERROR: {
      const { lastDownloadStatus, lastDownloadTime } = state;
      const { payload } = action;
      const { sensor } = payload;
      const { macAddress } = sensor;

      const newLastDownloadStatus = {
        ...lastDownloadStatus,
        [macAddress]: LAST_DOWNLOAD_STATUS.ERROR,
      };

      const newLastDownloadTime = {
        ...lastDownloadTime,
        [macAddress]: new Date(),
      };

      return {
        ...state,
        lastDownloadStatus: newLastDownloadStatus,
        lastDownloadTime: newLastDownloadTime,
        downloadingLogsFrom: '',
      };
    }

    case VACCINE_ACTIONS.DOWNLOAD_LOGS_START: {
      return { ...state, isSyncingTemps: true };
    }

    case VACCINE_ACTIONS.DOWNLOAD_LOGS_ERROR: {
      return { ...state, isSyncingTemps: false };
    }

    case VACCINE_ACTIONS.DOWNLOAD_LOGS_COMPLETE: {
      return { ...state, isSyncingTemps: false };
    }

    case VACCINE_ACTIONS.SET_LOG_INTERVAL_START: {
      const { payload } = action;
      const { macAddress } = payload;

      return { ...state, setLogIntervalFor: macAddress };
    }

    case VACCINE_ACTIONS.SET_LOG_INTERVAL_SUCCESS:
    case VACCINE_ACTIONS.SET_LOG_INTERVAL_ERROR: {
      return { ...state, setLogIntervalFor: '' };
    }

    case VACCINE_ACTIONS.DISABLE_BUTTON_START: {
      const { payload } = action;
      const { macAddress } = payload;

      return { ...state, sendingDisableButtonTo: macAddress };
    }

    case VACCINE_ACTIONS.DISABLE_BUTTON_STOP: {
      return { ...state, sendingDisableButtonTo: '' };
    }

    default:
      return state;
  }
};
<|endoftext|>


<commit_before>function addTask(taskModel, task) {
    if (task.length > 0) {
        tasksModel.insert(0, {task: task, time: "30m", remaining: "00:30:00", state: "paused", done: false})
    }
}

<commit_msg>set the current Index to the newly created task<commit_after>/*
  General functions
*/

function addTask(taskModel, task, tasksList) {
    if (task.length > 0) {
        tasksModel.insert(0, {task: task, time: "30m", remaining: "00:30:00", state: "paused", done: false})
        tasksList.currentIndex = 0;
    }
}

<|endoftext|>


<commit_before>/*global define,$ */
/*jslint browser:true */
/** @license
 | Copyright 2015 Esri
 |
 | Licensed under the Apache License, Version 2.0 (the "License");
 | you may not use this file except in compliance with the License.
 | You may obtain a copy of the License at
 |
 |    http://www.apache.org/licenses/LICENSE-2.0
 |
 | Unless required by applicable law or agreed to in writing, software
 | distributed under the License is distributed on an "AS IS" BASIS,
 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | See the License for the specific language governing permissions and
 | limitations under the License.
 */
//============================================================================================================================//
define(['diag'], function (diag) {
    'use strict';
    var dataAccess;
    dataAccess = {

        fixedQueryParams: "&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&distance=&units=esriSRUnit_Meter&returnGeometry=true&maxAllowableOffset=&geometryPrecision=&returnExtentOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&resultOffset=&resultRecordCount=&returnZ=false&returnM=false&quantizationParameters=&f=json&outSR=4326",
        featureServiceUrl: null,
        featureServiceLayerId: null,
        objectIdField: null,
        validCandidateCondition: null,
        proxyProgram: null,
        exclusionList: {},

        //--------------------------------------------------------------------------------------------------------------------//

        /**
         * Initializes the module.
         * @param {string} featureServiceUrl URL to feature service providing data
         * @param {number} featureServiceLayerId Id that the feature layer reports as its id
         * @param {string} objectIdField Field that the feature layer reports as its objectIdField
         * @param {string} validCandidateCondition Query 'where' clause to use to get survey candidates, e.g.,
         * "SRVNAME+is+null+or+SRVNAME=''", where SRVNAME is the name of the field used to store the name of the surveyor
         * @param {string} proxyProgram Path to the app's proxy, usually defined in the js/configuration.json file, e.g.,
         * "proxy/proxy.ashx"; use null if browser doesn't need proxy to query and update feature service (at this time,
         * only IE9 needs the proxy)
         */
        init: function (featureServiceUrl, featureServiceLayerId, objectIdField, validCandidateCondition, proxyProgram) {
            dataAccess.featureServiceUrl = featureServiceUrl;
            if (dataAccess.featureServiceUrl.lastIndexOf("/") !== dataAccess.featureServiceUrl.length - 1) {
                dataAccess.featureServiceUrl += "/";
            }
            dataAccess.featureServiceLayerId = featureServiceLayerId;
            dataAccess.objectIdField = objectIdField;
            dataAccess.validCandidateCondition = validCandidateCondition;
            dataAccess.proxyProgram = proxyProgram;
        },

        /**
         * Adds an item to the to-be-skipped list.
         * @param {number} item Object to be skipped; NOP if already in the list
         */
        addItemToExclusionList: function (item) {
            dataAccess.exclusionList[item] = true;
        },

        /**
         * Checks if an item is in the to-be-skipped list.
         * @param {number} item Object to be checked
         * @return {boolean} True if item is in list
         */
        isItemInExclusionList: function (item) {
            return dataAccess.exclusionList.hasOwnProperty(item);
        },

        /**
         * Empties the to-be-skipped list.
         */
        resetExclusionList: function () {
            dataAccess.exclusionList = {};
        },

        /**
         * Returns a list that doesn't include the items in the to-be-skipped list.
         * @param {array} itemList List to be filtered
         * @return {array} Filtered list
         */
        filterList: function (itemList) {
            return $.grep(itemList, function (element) {
                return !dataAccess.isItemInExclusionList(element);
            });
        },

        /**
         * Selects an item from a list of items; selection is subject to an exclusion limitation.
         * @param {array} itemList List of items to choose from
         * @param {boolean} randomizeSelection True if pseudorandom selection should be used
         * @return {object} Selected item or null if list is empty or only contains items
         * that are also in the skip list
         */
        pickFromList: function (itemList, randomizeSelection) {
            var item = null, filteredItems;

            if (itemList.length > 0) {
                filteredItems = dataAccess.filterList(itemList);
                if (filteredItems.length > 0) {
                    // Pick a candidate from amongst the available
                    item = randomizeSelection
                        ? filteredItems[Math.floor(Math.random() * filteredItems.length)]
                        : filteredItems[0];
                }
            }

            return item;
        },

        /**
         * Gets the number of features satisfying a condition.
         * @param {string} [condition] Condition to test; if omitted, the validCandidateCondition provided to this module's
         * init() function is used; a sample condition is "SRVNAME='" + username + "'", where SRVNAME is the name of the
         * field used to store the name of the surveyor, to count how many surveys the user given by 'username' has completed
         * @return {object} Deferred to provide count when it arrives; a count of -1 is used to flag an error
         */
        getObjectCount: function (condition) {
            var deferred, url;
            deferred = $.Deferred();

            url = dataAccess.featureServiceUrl + "query?where=" + (condition || dataAccess.validCandidateCondition)
                    + "&objectIds=&returnIdsOnly=false&returnCountOnly=true&outFields=" + dataAccess.fixedQueryParams
                    + "&callback=?";
            $.getJSON(url, function handleObjectCountClosure(results) {
                dataAccess.handleObjectCount(results, deferred, condition);
            });

            return deferred;
        },

        /**
         * Handles the callback for an object-count query.
         * @param {object} results Results provided by callback; .error if there's an error; .count contains count
         * otherwise
         * @param {object} deferred Deferred to receive results of interpreting results
         * @param {string} condition Condition used in query for diagnostic display
         */
        handleObjectCount: function (results, deferred, condition) {
            if (!results || results.error) {
                deferred.reject(-1);
            }
            diag.appendWithLF("surveys " + (condition
                ? "for \"" + condition + "\""
                : "available") + ": " + results.count);
            deferred.resolve(results.count);
        },

        /**
         * Gets a survey candidate from the list of available unsurveyed candidates.
         * @param {boolean} [randomizeSelection] Indicates if a feature should be selected randomly from the list of available
         * features;  if omitted or false, the first available feature in the list of object ids returned by the feature
         * service is used
         * @return {object} Deferred indicating when candidate is ready; successful resolution includes object with
         * obj and attachments properties; 'obj' contains an attributes property with the candidate's attributes and
         * attachments contains an array containing objects each of which describes an attachment using id and url properties;
         * if there are no more candidates, deferred resolves successfully but with 'obj'=null and 'attachments'=[]; if
         * the fetch fails, the deferred resolves with a failure
         */
        getCandidate: function (randomizeSelection) {
            var deferred, url;
            deferred = $.Deferred();

            // Get the ids of available unsurveyed candidates
            url = dataAccess.featureServiceUrl + "query?where=" + dataAccess.validCandidateCondition
                    + "&objectIds=&returnIdsOnly=true&returnCountOnly=false&outFields=" + dataAccess.fixedQueryParams
                    + "&callback=?";
            $.getJSON(url, function handleCandidatesClosure(results) {
                dataAccess.handleCandidates(results, randomizeSelection, deferred);
            });

            return deferred;
        },

        handleCandidates: function (results, randomizeSelection, deferred) {
            var objectId;

            if (!results || results.error) {
                deferred.reject({
                    id: null,
                    obj: null,
                    attachments: []
                });
                return;
            }

            // Pick a candidate from amongst the available
            objectId = dataAccess.pickFromList(results.objectIds, randomizeSelection);

            // No more surveys!
            if (objectId === null) {
                deferred.resolve({
                    id: null,
                    obj: null,
                    attachments: []
                });
                return;
            }

            // Get its info
            dataAccess.getCandidateInfo(objectId, deferred);
        },

        getCandidateInfo: function (objectId, deferred) {
            var attributesDeferred, objectAttrsUrl, attachmentsDeferred, objectAttachmentsUrl;

            // Get the candidate's attributes
            attributesDeferred = $.Deferred();
            objectAttrsUrl = dataAccess.featureServiceUrl + "query?objectIds=" + objectId
                    + "&returnIdsOnly=false&returnCountOnly=false&outFields=*" + dataAccess.fixedQueryParams
                    + "&callback=?";
            $.getJSON(objectAttrsUrl, function handleCandidateAttrsClosure(results) {
                dataAccess.handleCandidateAttrs(results, attributesDeferred);
            });

            // Get the candidate's attachments
            attachmentsDeferred = $.Deferred();
            objectAttachmentsUrl = dataAccess.featureServiceUrl + objectId + "/attachments?f=json&callback=?";
            $.getJSON(objectAttachmentsUrl, function handleCandidateAttachmentsClosure(results) {
                dataAccess.handleCandidateAttachments(objectId, results, attributesDeferred, attachmentsDeferred);
            });

            // Return the attributes and attachments
            $.when(attributesDeferred, attachmentsDeferred).then(function (attributesData, attachmentsData) {
                deferred.resolve({
                    id: objectId,
                    obj: attributesData,
                    attachments: attachmentsData
                });
            }, function () {
                deferred.reject();
            });
        },

        handleCandidateAttrs: function (results, attributesDeferred) {
            // No attributes is a problem
            if (!results || results.error || !results.features || results.features.length === 0) {
                attributesDeferred.reject();
                return;
            }

            attributesDeferred.resolve(results.features[0]);
        },

        handleCandidateAttachments: function (objectId, results, attributesDeferred, attachmentsDeferred) {
            var attachments = [];

            if (!results || results.error) {
                attachmentsDeferred.resolve(null);
                return;
            }

            // Empty list of attachments is possible
            if (results && results.attachmentInfos) {

                attributesDeferred.then(function (feature) {
                    // Watch for request to reverse order of attachments
                    var doReversal = false;
                    if (feature && feature.attributes && feature.attributes.REVERSE) {
                        doReversal = dataAccess.toBoolean(feature.attributes.REVERSE, false);
                    }

                    // Build list of attachments
                    if (doReversal) {
                        results.attachmentInfos.reverse();
                    }
                    $.each(results.attachmentInfos, function (ignore, attachment) {
                        attachments.push({
                            id: attachment.id,
                            url: dataAccess.featureServiceUrl + objectId + "/attachments/" + attachment.id
                        });
                    });
                    attachmentsDeferred.resolve(attachments);
                }, function () {
                    attachmentsDeferred.resolve(null);
                });
            } else {
                attachmentsDeferred.resolve(attachments);
            }
        },

        /**
         * Updates a candidate to its feature service.
         * @param {object} candidate Candidate to write to its feature service; contains object with obj property; 'obj'
         * contains an attributes property with the candidate's attributes; only the 'obj' property is used; any other
         * properties in 'candidate' are ignored
         * @return {object} Deferred to provide information about success or failure of update
         */
        updateCandidate: function (candidate) {
            var deferred, url, update;
            deferred = $.Deferred();

            update = "f=json&id=" + dataAccess.featureServiceLayerId + "&updates=%5B" + dataAccess.stringifyForApplyEdits(candidate.obj) + "%5D";
            url = (dataAccess.proxyProgram
                ? dataAccess.proxyProgram + "?"
                : "") + dataAccess.featureServiceUrl + "applyEdits";
            $.post(url, update, function (results, status) {
                // seek
                //   * status === "success"
                //   * results.updateResults[0].objectId === candidate.obj[dataAccess.objectIdField]
                //   * results.updateResults[0].success === true
                diag.append("update obj #" + candidate.obj.attributes[dataAccess.objectIdField] + " result: ");
                if (status === "success" && results && results.updateResults.length > 0) {
                    if (results.updateResults[0].success === true
                            && results.updateResults[0].objectId === candidate.obj.attributes[dataAccess.objectIdField]) {
                        diag.appendWithLF("OK");
                        deferred.resolve();
                    } else if (results.updateResults[0].error) {
                        diag.appendWithLF("fail #" + results.updateResults[0].error.code
                                + " (" + results.updateResults[0].error.description + ")");
                        deferred.reject();
                    } else {
                        diag.appendWithLF("unspecified fail");
                        deferred.reject();
                    }
                } else {
                    diag.appendWithLF("overall fail: " + status);
                    deferred.reject();
                }
            }, "json").fail(function (err) {
                // Unable to POST; can be IE 9 proxy problem
                diag.appendWithLF("update obj #" + candidate.obj.attributes[dataAccess.objectIdField]
                        + " POST fail: " + JSON.stringify(err) + "; failing URL: " + url);
                deferred.reject();
            });

            return deferred;
        },

        //--------------------------------------------------------------------------------------------------------------------//

        /**
         * Converts a value into the escaped form required by updates to a feature service.
         * @param {null|string|object} value Value to escape
         * @return {string} Escaped value
         * @private
         */
        stringifyForApplyEdits: function (value) {
            var isFirst = true, result = "";

            if (value === null) {
                result += 'null';
            } else if (typeof value === "string") {
                result += '%22' + encodeURIComponent(value) + '%22';
            } else if (typeof value === "object") {
                result += '%7B';
                $.each(value, function (part) {
                    if (value.hasOwnProperty(part)) {
                        result += (isFirst
                            ? ''
                            : '%2C') + part + '%3A' + dataAccess.stringifyForApplyEdits(value[part]);
                        isFirst = false;
                    }
                });
                result += '%7D';
            } else {
                result += value;
            }
            return result;
        },

        /** Normalizes a boolean value to true or false.
         * @param {boolean|string} boolValue A true or false value that is returned directly or a string
         * "true", "t", "yes", "y", "false", "f", "no", "n" (case-insensitive) or a number (0 for false; non-zero for true)
         * that is interpreted and returned; if neither a boolean nor a usable string nor a number, falls back to defaultValue
         * @param {boolean} [defaultValue] A true or false that is returned if boolValue can't be used; if not defined, true
         * is returned
         * @private
         */
        toBoolean: function (boolValue, defaultValue) {
            var lowercaseValue;

            // Shortcut true|false
            if (boolValue === true) {
                return true;
            }
            if (boolValue === false) {
                return false;
            }

            // Handle a true|false string
            if (typeof boolValue === "string") {
                lowercaseValue = boolValue.toLowerCase();
                if (lowercaseValue === "true" || lowercaseValue === "t" || lowercaseValue === "yes" || lowercaseValue === "y" || lowercaseValue === "1") {
                    return true;
                }
                if (lowercaseValue === "false" || lowercaseValue === "f" || lowercaseValue === "no" || lowercaseValue === "n" || lowercaseValue === "0") {
                    return false;
                }
            } else if (typeof boolValue === "number") {
                return boolValue !== 0;
            }
            // Fall back to default
            if (defaultValue === undefined) {
                return true;
            }
            return defaultValue;
        }

    };
    return dataAccess;
});
<commit_msg>Removed geometry from survey update<commit_after>/*global define,$ */
/*jslint browser:true */
/** @license
 | Copyright 2015 Esri
 |
 | Licensed under the Apache License, Version 2.0 (the "License");
 | you may not use this file except in compliance with the License.
 | You may obtain a copy of the License at
 |
 |    http://www.apache.org/licenses/LICENSE-2.0
 |
 | Unless required by applicable law or agreed to in writing, software
 | distributed under the License is distributed on an "AS IS" BASIS,
 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | See the License for the specific language governing permissions and
 | limitations under the License.
 */
//============================================================================================================================//
define(['diag'], function (diag) {
    'use strict';
    var dataAccess;
    dataAccess = {

        fixedQueryParams: "&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&distance=&units=esriSRUnit_Meter&returnGeometry=true&maxAllowableOffset=&geometryPrecision=&returnExtentOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&resultOffset=&resultRecordCount=&returnZ=false&returnM=false&quantizationParameters=&f=json&outSR=4326",
        featureServiceUrl: null,
        featureServiceLayerId: null,
        objectIdField: null,
        validCandidateCondition: null,
        proxyProgram: null,
        exclusionList: {},

        //--------------------------------------------------------------------------------------------------------------------//

        /**
         * Initializes the module.
         * @param {string} featureServiceUrl URL to feature service providing data
         * @param {number} featureServiceLayerId Id that the feature layer reports as its id
         * @param {string} objectIdField Field that the feature layer reports as its objectIdField
         * @param {string} validCandidateCondition Query 'where' clause to use to get survey candidates, e.g.,
         * "SRVNAME+is+null+or+SRVNAME=''", where SRVNAME is the name of the field used to store the name of the surveyor
         * @param {string} proxyProgram Path to the app's proxy, usually defined in the js/configuration.json file, e.g.,
         * "proxy/proxy.ashx"; use null if browser doesn't need proxy to query and update feature service (at this time,
         * only IE9 needs the proxy)
         */
        init: function (featureServiceUrl, featureServiceLayerId, objectIdField, validCandidateCondition, proxyProgram) {
            dataAccess.featureServiceUrl = featureServiceUrl;
            if (dataAccess.featureServiceUrl.lastIndexOf("/") !== dataAccess.featureServiceUrl.length - 1) {
                dataAccess.featureServiceUrl += "/";
            }
            dataAccess.featureServiceLayerId = featureServiceLayerId;
            dataAccess.objectIdField = objectIdField;
            dataAccess.validCandidateCondition = validCandidateCondition;
            dataAccess.proxyProgram = proxyProgram;
        },

        /**
         * Adds an item to the to-be-skipped list.
         * @param {number} item Object to be skipped; NOP if already in the list
         */
        addItemToExclusionList: function (item) {
            dataAccess.exclusionList[item] = true;
        },

        /**
         * Checks if an item is in the to-be-skipped list.
         * @param {number} item Object to be checked
         * @return {boolean} True if item is in list
         */
        isItemInExclusionList: function (item) {
            return dataAccess.exclusionList.hasOwnProperty(item);
        },

        /**
         * Empties the to-be-skipped list.
         */
        resetExclusionList: function () {
            dataAccess.exclusionList = {};
        },

        /**
         * Returns a list that doesn't include the items in the to-be-skipped list.
         * @param {array} itemList List to be filtered
         * @return {array} Filtered list
         */
        filterList: function (itemList) {
            return $.grep(itemList, function (element) {
                return !dataAccess.isItemInExclusionList(element);
            });
        },

        /**
         * Selects an item from a list of items; selection is subject to an exclusion limitation.
         * @param {array} itemList List of items to choose from
         * @param {boolean} randomizeSelection True if pseudorandom selection should be used
         * @return {object} Selected item or null if list is empty or only contains items
         * that are also in the skip list
         */
        pickFromList: function (itemList, randomizeSelection) {
            var item = null, filteredItems;

            if (itemList.length > 0) {
                filteredItems = dataAccess.filterList(itemList);
                if (filteredItems.length > 0) {
                    // Pick a candidate from amongst the available
                    item = randomizeSelection
                        ? filteredItems[Math.floor(Math.random() * filteredItems.length)]
                        : filteredItems[0];
                }
            }

            return item;
        },

        /**
         * Gets the number of features satisfying a condition.
         * @param {string} [condition] Condition to test; if omitted, the validCandidateCondition provided to this module's
         * init() function is used; a sample condition is "SRVNAME='" + username + "'", where SRVNAME is the name of the
         * field used to store the name of the surveyor, to count how many surveys the user given by 'username' has completed
         * @return {object} Deferred to provide count when it arrives; a count of -1 is used to flag an error
         */
        getObjectCount: function (condition) {
            var deferred, url;
            deferred = $.Deferred();

            url = dataAccess.featureServiceUrl + "query?where=" + (condition || dataAccess.validCandidateCondition)
                    + "&objectIds=&returnIdsOnly=false&returnCountOnly=true&outFields=" + dataAccess.fixedQueryParams
                    + "&callback=?";
            $.getJSON(url, function handleObjectCountClosure(results) {
                dataAccess.handleObjectCount(results, deferred, condition);
            });

            return deferred;
        },

        /**
         * Handles the callback for an object-count query.
         * @param {object} results Results provided by callback; .error if there's an error; .count contains count
         * otherwise
         * @param {object} deferred Deferred to receive results of interpreting results
         * @param {string} condition Condition used in query for diagnostic display
         */
        handleObjectCount: function (results, deferred, condition) {
            if (!results || results.error) {
                deferred.reject(-1);
            }
            diag.appendWithLF("surveys " + (condition
                ? "for \"" + condition + "\""
                : "available") + ": " + results.count);
            deferred.resolve(results.count);
        },

        /**
         * Gets a survey candidate from the list of available unsurveyed candidates.
         * @param {boolean} [randomizeSelection] Indicates if a feature should be selected randomly from the list of available
         * features;  if omitted or false, the first available feature in the list of object ids returned by the feature
         * service is used
         * @return {object} Deferred indicating when candidate is ready; successful resolution includes object with
         * obj and attachments properties; 'obj' contains an attributes property with the candidate's attributes and
         * attachments contains an array containing objects each of which describes an attachment using id and url properties;
         * if there are no more candidates, deferred resolves successfully but with 'obj'=null and 'attachments'=[]; if
         * the fetch fails, the deferred resolves with a failure
         */
        getCandidate: function (randomizeSelection) {
            var deferred, url;
            deferred = $.Deferred();

            // Get the ids of available unsurveyed candidates
            url = dataAccess.featureServiceUrl + "query?where=" + dataAccess.validCandidateCondition
                    + "&objectIds=&returnIdsOnly=true&returnCountOnly=false&outFields=" + dataAccess.fixedQueryParams
                    + "&callback=?";
            $.getJSON(url, function handleCandidatesClosure(results) {
                dataAccess.handleCandidates(results, randomizeSelection, deferred);
            });

            return deferred;
        },

        handleCandidates: function (results, randomizeSelection, deferred) {
            var objectId;

            if (!results || results.error) {
                deferred.reject({
                    id: null,
                    obj: null,
                    attachments: []
                });
                return;
            }

            // Pick a candidate from amongst the available
            objectId = dataAccess.pickFromList(results.objectIds, randomizeSelection);

            // No more surveys!
            if (objectId === null) {
                deferred.resolve({
                    id: null,
                    obj: null,
                    attachments: []
                });
                return;
            }

            // Get its info
            dataAccess.getCandidateInfo(objectId, deferred);
        },

        getCandidateInfo: function (objectId, deferred) {
            var attributesDeferred, objectAttrsUrl, attachmentsDeferred, objectAttachmentsUrl;

            // Get the candidate's attributes
            attributesDeferred = $.Deferred();
            objectAttrsUrl = dataAccess.featureServiceUrl + "query?objectIds=" + objectId
                    + "&returnIdsOnly=false&returnCountOnly=false&outFields=*" + dataAccess.fixedQueryParams
                    + "&callback=?";
            $.getJSON(objectAttrsUrl, function handleCandidateAttrsClosure(results) {
                dataAccess.handleCandidateAttrs(results, attributesDeferred);
            });

            // Get the candidate's attachments
            attachmentsDeferred = $.Deferred();
            objectAttachmentsUrl = dataAccess.featureServiceUrl + objectId + "/attachments?f=json&callback=?";
            $.getJSON(objectAttachmentsUrl, function handleCandidateAttachmentsClosure(results) {
                dataAccess.handleCandidateAttachments(objectId, results, attributesDeferred, attachmentsDeferred);
            });

            // Return the attributes and attachments
            $.when(attributesDeferred, attachmentsDeferred).then(function (attributesData, attachmentsData) {
                deferred.resolve({
                    id: objectId,
                    obj: attributesData,
                    attachments: attachmentsData
                });
            }, function () {
                deferred.reject();
            });
        },

        handleCandidateAttrs: function (results, attributesDeferred) {
            // No attributes is a problem
            if (!results || results.error || !results.features || results.features.length === 0) {
                attributesDeferred.reject();
                return;
            }

            attributesDeferred.resolve(results.features[0]);
        },

        handleCandidateAttachments: function (objectId, results, attributesDeferred, attachmentsDeferred) {
            var attachments = [];

            if (!results || results.error) {
                attachmentsDeferred.resolve(null);
                return;
            }

            // Empty list of attachments is possible
            if (results && results.attachmentInfos) {

                attributesDeferred.then(function (feature) {
                    // Watch for request to reverse order of attachments
                    var doReversal = false;
                    if (feature && feature.attributes && feature.attributes.REVERSE) {
                        doReversal = dataAccess.toBoolean(feature.attributes.REVERSE, false);
                    }

                    // Build list of attachments
                    if (doReversal) {
                        results.attachmentInfos.reverse();
                    }
                    $.each(results.attachmentInfos, function (ignore, attachment) {
                        attachments.push({
                            id: attachment.id,
                            url: dataAccess.featureServiceUrl + objectId + "/attachments/" + attachment.id
                        });
                    });
                    attachmentsDeferred.resolve(attachments);
                }, function () {
                    attachmentsDeferred.resolve(null);
                });
            } else {
                attachmentsDeferred.resolve(attachments);
            }
        },

        /**
         * Updates a candidate to its feature service.
         * @param {object} candidate Candidate to write to its feature service; contains object with obj property; 'obj'
         * contains an attributes property with the candidate's attributes; only the 'obj' property is used; any other
         * properties in 'candidate' are ignored
         * @return {object} Deferred to provide information about success or failure of update
         */
        updateCandidate: function (candidate) {
            var deferred, url, update, updatePacket;
            deferred = $.Deferred();

            // Create update content from attributes only--we don't need or want to send coordinates
            updatePacket = {
                attributes: candidate.obj.attributes
            };
            update = "f=json&id=" + dataAccess.featureServiceLayerId + "&updates=%5B" + dataAccess.stringifyForApplyEdits(updatePacket) + "%5D";

            // POST the update
            url = (dataAccess.proxyProgram
                ? dataAccess.proxyProgram + "?"
                : "") + dataAccess.featureServiceUrl + "applyEdits";
            $.post(url, update, function (results, status) {
                // seek
                //   * status === "success"
                //   * results.updateResults[0].objectId === candidate.obj[dataAccess.objectIdField]
                //   * results.updateResults[0].success === true
                diag.append("update obj #" + candidate.obj.attributes[dataAccess.objectIdField] + " result: ");
                if (status === "success" && results && results.updateResults.length > 0) {
                    if (results.updateResults[0].success === true
                            && results.updateResults[0].objectId === candidate.obj.attributes[dataAccess.objectIdField]) {
                        diag.appendWithLF("OK");
                        deferred.resolve();
                    } else if (results.updateResults[0].error) {
                        diag.appendWithLF("fail #" + results.updateResults[0].error.code
                                + " (" + results.updateResults[0].error.description + ")");
                        deferred.reject();
                    } else {
                        diag.appendWithLF("unspecified fail");
                        deferred.reject();
                    }
                } else {
                    diag.appendWithLF("overall fail: " + status);
                    deferred.reject();
                }
            }, "json").fail(function (err) {
                // Unable to POST; can be IE 9 proxy problem
                diag.appendWithLF("update obj #" + candidate.obj.attributes[dataAccess.objectIdField]
                        + " POST fail: " + JSON.stringify(err) + "; failing URL: " + url);
                deferred.reject();
            });

            return deferred;
        },

        //--------------------------------------------------------------------------------------------------------------------//

        /**
         * Converts a value into the escaped form required by updates to a feature service.
         * @param {null|string|object} value Value to escape
         * @return {string} Escaped value
         * @private
         */
        stringifyForApplyEdits: function (value) {
            var isFirst = true, result = "";

            if (value === null) {
                result += 'null';
            } else if (typeof value === "string") {
                result += '%22' + encodeURIComponent(value) + '%22';
            } else if (typeof value === "object") {
                result += '%7B';
                $.each(value, function (part) {
                    if (value.hasOwnProperty(part)) {
                        result += (isFirst
                            ? ''
                            : '%2C') + part + '%3A' + dataAccess.stringifyForApplyEdits(value[part]);
                        isFirst = false;
                    }
                });
                result += '%7D';
            } else {
                result += value;
            }
            return result;
        },

        /** Normalizes a boolean value to true or false.
         * @param {boolean|string} boolValue A true or false value that is returned directly or a string
         * "true", "t", "yes", "y", "false", "f", "no", "n" (case-insensitive) or a number (0 for false; non-zero for true)
         * that is interpreted and returned; if neither a boolean nor a usable string nor a number, falls back to defaultValue
         * @param {boolean} [defaultValue] A true or false that is returned if boolValue can't be used; if not defined, true
         * is returned
         * @private
         */
        toBoolean: function (boolValue, defaultValue) {
            var lowercaseValue;

            // Shortcut true|false
            if (boolValue === true) {
                return true;
            }
            if (boolValue === false) {
                return false;
            }

            // Handle a true|false string
            if (typeof boolValue === "string") {
                lowercaseValue = boolValue.toLowerCase();
                if (lowercaseValue === "true" || lowercaseValue === "t" || lowercaseValue === "yes" || lowercaseValue === "y" || lowercaseValue === "1") {
                    return true;
                }
                if (lowercaseValue === "false" || lowercaseValue === "f" || lowercaseValue === "no" || lowercaseValue === "n" || lowercaseValue === "0") {
                    return false;
                }
            } else if (typeof boolValue === "number") {
                return boolValue !== 0;
            }
            // Fall back to default
            if (defaultValue === undefined) {
                return true;
            }
            return defaultValue;
        }

    };
    return dataAccess;
});
<|endoftext|>