<commit_before>var service = null;
var privateGadgetNames = null;
var nameOfGadgetBeingEdited = '';
var entryOfGadgetBeingEdited = null;
var privateGadgetSpecFeedUrl = null;

var SERVICE_NAME = 'esp';
var APP_NAME = 'private-gadget-editor';

var SPINNER = '';
var DEFAULT_SPINNER_ID = 'spinner';

function $(id) {
  return document.getElementById(id);
};

function startSpinner(id) {
  $(id ? id : DEFAULT_SPINNER_ID).innerHTML = SPINNER;
};

function stopSpinner(id) {
  $(id ? id : DEFAULT_SPINNER_ID).innerHTML = '';
};

function initEditor() {
  if (privateGadgetSpecFeedUrl) {
    initGadgetNameList();
  }
};

function noCache(url) {
  return url + '?nocache=' + (new Date().getTime());
};

function setNameOfGadgetBeingEdited(name) {
  nameOfGadgetBeingEdited = name;
  if (name) {
    $('spec-url-wrapper').style.display = 'inline';
    var specUrl = 'http://www.google.com/a/feeds/server/g/domain/' +
        detectDomainName() + '/PrivateGadgetSpec/' + name;
    $('spec-url').href = specUrl;
  } else {
    $('spec-url-wrapper').style.display = 'none';
  }
};

function initGadgetNameList() {
  service = new google.gdata.client.FeedServerService(SERVICE_NAME, APP_NAME);
  service.setGadgetsAuthentication('SIGNED');
  service.getFeed(noCache(privateGadgetSpecFeedUrl), function(response) {
    stopSpinner();
    var entries = response && response.feed.entry ? response.feed.entry : [];
    showPrivateGadgetNames(setPrivateGadgetNames(entries));
  }, function(response) {
    stopSpinner()
    showMessage('Error: failed to load private gadget specs');
  });
  startSpinner();
};

function setPrivateGadgetNames(entries) {
  privateGadgetNames = [];
  for (var i = 0; i < entries.length; i++) {
    var name = entries[i].id.$t;
    name = name.substring(name.lastIndexOf('/') + 1);
    privateGadgetNames.push(name);
  }
  return privateGadgetNames;
};

function showPrivateGadgetNames() {
  var html = ['<select id="gadget-select" onchange="editSelectedGadget()">'];
  html.push('<option value="">Select to open</option>');
  for (var i = 0; i < privateGadgetNames.length; i++) {
    var privateGadgetName = privateGadgetNames[i];
    html.push('<option ', privateGadgetName == nameOfGadgetBeingEdited ? 'selected' : '',
        '>', privateGadgetName, '</option>');
  }
  document.getElementById('gadget-list').innerHTML = html.join('');
};

function getSelectedGadgetName() {
  return document.getElementById('gadget-select').value;
};

function editSelectedGadget() {
  var name = getSelectedGadgetName();
  if (name) {
    service.getEntry(noCache(privateGadgetSpecFeedUrl + '/' + name), function(response) {
      stopSpinner();
      setNameOfGadgetBeingEdited(name);
      entryOfGadgetBeingEdited = response.entry;
      editor.setCode(response.entry.content.entity.specContent);
      editor.editor.syntaxHighlight('init');
    }, function(response) {
      stopSpinner();
      showMessage('Error: failed to open gadget spec "' + name + '"');
    });
    startSpinner();
  } else {
    newGadget();
  }
};

function deleteSelectedGadget() {
  var name = getSelectedGadgetName();
  if (name) {
    service.deleteEntry(privateGadgetSpecFeedUrl + '/' + name, function(response) {
      stopSpinner();
      initEditor();
      newGadget();
    }, function(response) {
      stopSpinner();
      showMessage('Error: failed to delete gadget spec "' + name + '"');
    });
    startSpinner();
  } else {
    alert('Please select a gadget to delete.');
  }
};

function newGadget() {
  setNameOfGadgetBeingEdited('');
  editor.setCode(getGadgetSpecTemplate());
  editor.editor.syntaxHighlight('init');
  showPrivateGadgetNames();
  entryOfGadgetBeingEdited = {xmlns: 'http://www.w3.org/2005/Atom', content: {
      type: 'application/xml', entity: {name: '', specContent: ''}}};
};

function saveGadget(changeName) {
  entryOfGadgetBeingEdited.content.entity.specContent = editor.getCode();
  if (nameOfGadgetBeingEdited && !changeName) {
    service.updateEntry(privateGadgetSpecFeedUrl + '/' + nameOfGadgetBeingEdited,
        entryOfGadgetBeingEdited, function(response) {
      stopSpinner();
    }, function(error) {
      stopSpinner();
      showMessage('Error: failed to update gadget spec "' + nameOfGadgetBeingEdited + '"' + error);
    });
    startSpinner();
  } else {
    var name = changeName ?
      prompt('Please enter new name of gadget (e.g. hello.xml)') :
      prompt('Please enter name of new gadget (e.g. hello.xml)');
    if (!name) {
      return;
    }
    setNameOfGadgetBeingEdited(name);
    if (nameOfGadgetBeingEdited) {
      delete entryOfGadgetBeingEdited.content.entity.id;
      entryOfGadgetBeingEdited.content.entity.name = nameOfGadgetBeingEdited;
      service.insertEntry(privateGadgetSpecFeedUrl,
          entryOfGadgetBeingEdited, function(response) {
        stopSpinner();
        privateGadgetNames.push(nameOfGadgetBeingEdited);
        showPrivateGadgetNames();
      }, function(error) {
        stopSpinner();
        showMessage('Error: failed to add gadget spec "' + nameOfGadgetBeingEdited + '": ' + error);
      });
      startSpinner();
    }
  }
};

function openGadgetByUrl() {
  var gadgetSpecUrl = prompt('Please enter public URL of gadget spec');
  if (gadgetSpecUrl) {
    var params = {};
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;
    gadgets.io.makeRequest(gadgetSpecUrl, function(response) {
      if (response.rc > 299) {
        showMessage('Error: ' + response.errors);
      } else {
        setNameOfGadgetBeingEdited(null);
        entryOfGadgetBeingEdited = {xmlns: 'http://www.w3.org/2005/Atom', content: {
          type: 'application/xml', entity: {name: '', specContent: response.text}}};
        editor.setCode(response.text);
        editor.editor.syntaxHighlight('init');
      }
    }, params);
  }
};

function getGadgetSpecTemplate() {
  var textArea = document.getElementById('gadget-spec-template');
  return textArea.value || textArea.defaultValue;
};

function showMessage(message) {
  var miniMessage = new gadgets.MiniMessage(null, document.getElementById('message-box'));
  miniMessage.createDismissibleMessage(message);
};

//// google.load('gdata', '1.x', {packages: ['core']});
// google.load('gdata', '1.x', {packages: ['core'], 'other_params': 'debug=1'});
// google.setOnLoadCallback(initEditor);

function initCodePress() {
  editor.style.height = '400px';
  CodePressWrapper.init();

  if (location.href.indexOf('codePressReloaded') < 0) {
    setTimeout(function() {
      if (!$('codepress-iframe').editor) {
        location.href += '&codePressReloaded';
        location.reload();
      }
    }, 500);
  }
};

function detectDomainName() {
  var params = location.href.split('&');
  for (var i = 0; i < params.length; i++) {
    if (params[i].indexOf('parent=') == 0) {
      var p = params[i].split('=');
      var parent = decodeURIComponent(p[1]);
      var r = /google.com\/a\/([^\/]*)\//.exec(parent);
      var domainName = r ? r[1] : null;
      return domainName;
    }
  }

  return null;
};

function initGadget() {
  var domainName = detectDomainName();
  if (domainName) {
    privateGadgetSpecFeedUrl = 'http://feedserver-enterprise.googleusercontent.com/a/' +
        domainName + '/g/PrivateGadgetSpec';
  } else {
    showMessage('Error: domain name missing');
  }

  gadgets.window.adjustHeight();
};

function init() {
  initCodePress();
  initGadget();
  initEditor();
};

gadgets.util.registerOnLoadHandler(init);
<commit_msg>added better domain detection to accommodate when there is a port number<commit_after>var service = null;
var privateGadgetNames = null;
var nameOfGadgetBeingEdited = '';
var entryOfGadgetBeingEdited = null;
var privateGadgetSpecFeedUrl = null;

var SERVICE_NAME = 'esp';
var APP_NAME = 'private-gadget-editor';

var SPINNER = '';
var DEFAULT_SPINNER_ID = 'spinner';

function $(id) {
  return document.getElementById(id);
};

function startSpinner(id) {
  $(id ? id : DEFAULT_SPINNER_ID).innerHTML = SPINNER;
};

function stopSpinner(id) {
  $(id ? id : DEFAULT_SPINNER_ID).innerHTML = '';
};

function initEditor() {
  if (privateGadgetSpecFeedUrl) {
    initGadgetNameList();
  }
};

function noCache(url) {
  return url + '?nocache=' + (new Date().getTime());
};

function setNameOfGadgetBeingEdited(name) {
  nameOfGadgetBeingEdited = name;
  if (name) {
    $('spec-url-wrapper').style.display = 'inline';
    var specUrl = 'http://www.google.com/a/feeds/server/g/domain/' +
        detectDomainName() + '/PrivateGadgetSpec/' + name;
    $('spec-url').href = specUrl;
  } else {
    $('spec-url-wrapper').style.display = 'none';
  }
};

function initGadgetNameList() {
  service = new google.gdata.client.FeedServerService(SERVICE_NAME, APP_NAME);
  service.setGadgetsAuthentication('SIGNED');
  service.getFeed(noCache(privateGadgetSpecFeedUrl), function(response) {
    stopSpinner();
    var entries = response && response.feed.entry ? response.feed.entry : [];
    showPrivateGadgetNames(setPrivateGadgetNames(entries));
  }, function(response) {
    stopSpinner()
    showMessage('Error: failed to load private gadget specs');
  });
  startSpinner();
};

function setPrivateGadgetNames(entries) {
  privateGadgetNames = [];
  for (var i = 0; i < entries.length; i++) {
    var name = entries[i].id.$t;
    name = name.substring(name.lastIndexOf('/') + 1);
    privateGadgetNames.push(name);
  }
  return privateGadgetNames;
};

function showPrivateGadgetNames() {
  var html = ['<select id="gadget-select" onchange="editSelectedGadget()">'];
  html.push('<option value="">Select to open</option>');
  for (var i = 0; i < privateGadgetNames.length; i++) {
    var privateGadgetName = privateGadgetNames[i];
    html.push('<option ', privateGadgetName == nameOfGadgetBeingEdited ? 'selected' : '',
        '>', privateGadgetName, '</option>');
  }
  document.getElementById('gadget-list').innerHTML = html.join('');
};

function getSelectedGadgetName() {
  return document.getElementById('gadget-select').value;
};

function editSelectedGadget() {
  var name = getSelectedGadgetName();
  if (name) {
    service.getEntry(noCache(privateGadgetSpecFeedUrl + '/' + name), function(response) {
      stopSpinner();
      setNameOfGadgetBeingEdited(name);
      entryOfGadgetBeingEdited = response.entry;
      editor.setCode(response.entry.content.entity.specContent);
      editor.editor.syntaxHighlight('init');
    }, function(response) {
      stopSpinner();
      showMessage('Error: failed to open gadget spec "' + name + '"');
    });
    startSpinner();
  } else {
    newGadget();
  }
};

function deleteSelectedGadget() {
  var name = getSelectedGadgetName();
  if (name) {
    service.deleteEntry(privateGadgetSpecFeedUrl + '/' + name, function(response) {
      stopSpinner();
      initEditor();
      newGadget();
    }, function(response) {
      stopSpinner();
      showMessage('Error: failed to delete gadget spec "' + name + '"');
    });
    startSpinner();
  } else {
    alert('Please select a gadget to delete.');
  }
};

function newGadget() {
  setNameOfGadgetBeingEdited('');
  editor.setCode(getGadgetSpecTemplate());
  editor.editor.syntaxHighlight('init');
  showPrivateGadgetNames();
  entryOfGadgetBeingEdited = {xmlns: 'http://www.w3.org/2005/Atom', content: {
      type: 'application/xml', entity: {name: '', specContent: ''}}};
};

function saveGadget(changeName) {
  entryOfGadgetBeingEdited.content.entity.specContent = editor.getCode();
  if (nameOfGadgetBeingEdited && !changeName) {
    service.updateEntry(privateGadgetSpecFeedUrl + '/' + nameOfGadgetBeingEdited,
        entryOfGadgetBeingEdited, function(response) {
      stopSpinner();
    }, function(error) {
      stopSpinner();
      showMessage('Error: failed to update gadget spec "' + nameOfGadgetBeingEdited + '"' + error);
    });
    startSpinner();
  } else {
    var name = changeName ?
      prompt('Please enter new name of gadget (e.g. hello.xml)') :
      prompt('Please enter name of new gadget (e.g. hello.xml)');
    if (!name) {
      return;
    }
    setNameOfGadgetBeingEdited(name);
    if (nameOfGadgetBeingEdited) {
      delete entryOfGadgetBeingEdited.content.entity.id;
      entryOfGadgetBeingEdited.content.entity.name = nameOfGadgetBeingEdited;
      service.insertEntry(privateGadgetSpecFeedUrl,
          entryOfGadgetBeingEdited, function(response) {
        stopSpinner();
        privateGadgetNames.push(nameOfGadgetBeingEdited);
        showPrivateGadgetNames();
      }, function(error) {
        stopSpinner();
        showMessage('Error: failed to add gadget spec "' + nameOfGadgetBeingEdited + '": ' + error);
      });
      startSpinner();
    }
  }
};

function openGadgetByUrl() {
  var gadgetSpecUrl = prompt('Please enter public URL of gadget spec');
  if (gadgetSpecUrl) {
    var params = {};
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;
    gadgets.io.makeRequest(gadgetSpecUrl, function(response) {
      if (response.rc > 299) {
        showMessage('Error: ' + response.errors);
      } else {
        setNameOfGadgetBeingEdited(null);
        entryOfGadgetBeingEdited = {xmlns: 'http://www.w3.org/2005/Atom', content: {
          type: 'application/xml', entity: {name: '', specContent: response.text}}};
        editor.setCode(response.text);
        editor.editor.syntaxHighlight('init');
      }
    }, params);
  }
};

function getGadgetSpecTemplate() {
  var textArea = document.getElementById('gadget-spec-template');
  return textArea.value || textArea.defaultValue;
};

function showMessage(message) {
  var miniMessage = new gadgets.MiniMessage(null, document.getElementById('message-box'));
  miniMessage.createDismissibleMessage(message);
};

//// google.load('gdata', '1.x', {packages: ['core']});
// google.load('gdata', '1.x', {packages: ['core'], 'other_params': 'debug=1'});
// google.setOnLoadCallback(initEditor);

function initCodePress() {
  editor.style.height = '400px';
  CodePressWrapper.init();

  if (location.href.indexOf('codePressReloaded') < 0) {
    setTimeout(function() {
      if (!$('codepress-iframe').editor) {
        location.href += '&codePressReloaded';
        location.reload();
      }
    }, 500);
  }
};

function detectDomainName() {
  var params = location.href.split('&');
  for (var i = 0; i < params.length; i++) {
    if (params[i].indexOf('parent=') == 0) {
      var p = params[i].split('=');
      var parent = decodeURIComponent(p[1]);
      var r = /google.com(:[0-9]+)?\/a\/([^\/]*)\//.exec(parent);
      var domainName = r ? r[2] : null;
      return domainName;
    }
  }

  return null;
};

function initGadget() {
  var domainName = detectDomainName();
  if (domainName) {
    privateGadgetSpecFeedUrl = 'http://feedserver-enterprise.googleusercontent.com/a/' +
        domainName + '/g/PrivateGadgetSpec';
  } else {
    showMessage('Error: domain name missing');
  }

  gadgets.window.adjustHeight();
};

function init() {
  initCodePress();
  initGadget();
  initEditor();
};

gadgets.util.registerOnLoadHandler(init);
<|endoftext|>


<commit_before>const Path = require('path')
const webpack = require('webpack')

module.exports = {
  pages: {
    'components/central': { entry: './src/components/central/main.ts'},
    'components/ko-paginator': { entry: './src/components/ko-paginator/main.ts'},
    'components/motd': { entry: './src/components/motd/main.js'},
    'components/navbar': { entry: './src/components/navbar/main.ts'},
    'components/project-picker': { entry: './src/components/project-picker/main.ts'},
    'components/first-run': { entry: './src/components/first-run/main.ts' },
    'components/theme': { entry: './src/components/theme/main.ts'},
    'components/tour': { entry: './src/components/tour/main.js'},
    'components/version-notification': { entry: './src/components/version-notification/main.js'},
    'components/version': { entry: './src/components/version/main.js'},
    'components/community-news-notification': { entry: './src/components/community-news-notification/main.js'},
    'pages/project-dashboard': { entry: './src/pages/project-dashboard/main.js'},
    'pages/project-activity': { entry: './src/pages/project-activity/main.js'},
    'pages/repository': { entry: './src/pages/repository/main.js'},
    'pages/command': { entry: './src/pages/command/main.ts'},
    'pages/community-news': { entry: './src/pages/community-news/main.js'},
    'pages/project-nodes-config': { entry: './src/pages/project-nodes-config/main.js'},
    'pages/execution-show': { entry: './src/pages/execution-show/main.js'},
    'pages/webhooks': { entry: './src/pages/webhooks/main.js'},
    'pages/user-summary': {entry: './src/pages/menu/main.js'},
    'pages/dynamic-form': {entry: './src/pages/dynamic-form/main.js'},
    'pages/job/editor': {entry: './src/pages/job/editor/main.js'},

  },

  outputDir: process.env.VUE_APP_OUTPUT_DIR,
  publicPath: '/assets/static/',
  filenameHashing: false,
  parallel: true,
  css: {
    sourceMap: true,
    /** Workaround for Vue CLI accounting for nested page paths
     * https://github.com/vuejs/vue-cli/issues/4378
    */
    extract: {
      filename: '/css/[name].css',
      chunkFilename: '/css/[name].css',
    },
    loaderOptions: {
      less: {
        lessOptions: {
          javascriptEnabled: true
        }
      }
    }
  },
  chainWebpack: config => {
    /** Do not create index pages for entry points */
    config.entryPoints.store.forEach( (_, entry) => {
      config.plugins.delete(`html-${entry}`)
      config.plugins.delete(`preload-${entry}`)
      config.plugins.delete(`prefetch-${entry}`)
    })

    /** Process source maps from deps */
    config.module.rule('source-map-loader')
      .test(/\.js$/)
      .include.add(/ui-trellis\/lib/).end()
      .enforce('pre')
      .use('source-map-loader')
      .loader('source-map-loader')
      .end()
  },
  configureWebpack: {
    devtool: process.env.VUE_APP_DEVTOOL,
    output: {
      filename: '[name].js',
      library: 'rundeckCore',
    },
    externals: {'vue': 'Vue'},
    plugins: [
      new webpack.NormalModuleReplacementPlugin( /node_modules\/ant-design-vue\/es\/style\/index\.less/, function(resource) {
        if (resource.resource) {
          resource.resource = resource.resource.replace(/node_modules\/ant-design-vue\/es\/style\/index\.less/, 'src/antScope.less')
        }
      }),
      /** Generate source maps for CSS as it does not support eval-source-map */
      new webpack.SourceMapDevToolPlugin({
        filename: "[file].map",
        include: [/\.css$/]
      })
    ]
  }
};
<commit_msg>[Re]Design webhooks<commit_after>const Path = require('path')
const webpack = require('webpack')

module.exports = {
  pages: {
    'components/central': { entry: './src/components/central/main.ts'},
    'components/ko-paginator': { entry: './src/components/ko-paginator/main.ts'},
    'components/motd': { entry: './src/components/motd/main.js'},
    'components/navbar': { entry: './src/components/navbar/main.ts'},
    'components/project-picker': { entry: './src/components/project-picker/main.ts'},
    'components/first-run': { entry: './src/components/first-run/main.ts' },
    'components/theme': { entry: './src/components/theme/main.ts'},
    'components/tour': { entry: './src/components/tour/main.js'},
    'components/version-notification': { entry: './src/components/version-notification/main.js'},
    'components/version': { entry: './src/components/version/main.js'},
    'components/community-news-notification': { entry: './src/components/community-news-notification/main.js'},
    'pages/project-dashboard': { entry: './src/pages/project-dashboard/main.js'},
    'pages/project-activity': { entry: './src/pages/project-activity/main.js'},
    'pages/repository': { entry: './src/pages/repository/main.js'},
    'pages/command': { entry: './src/pages/command/main.ts'},
    'pages/community-news': { entry: './src/pages/community-news/main.js'},
    'pages/project-nodes-config': { entry: './src/pages/project-nodes-config/main.js'},
    'pages/execution-show': { entry: './src/pages/execution-show/main.js'},
    'pages/webhooks': { entry: './src/pages/webhooks/main.js'},
    'pages/user-summary': {entry: './src/pages/menu/main.js'},
    'pages/dynamic-form': {entry: './src/pages/dynamic-form/main.js'},
    'pages/job/editor': {entry: './src/pages/job/editor/main.js'},

  },

  outputDir: process.env.VUE_APP_OUTPUT_DIR,
  publicPath: '/assets/static/',
  filenameHashing: false,
  parallel: true,
  css: {
    sourceMap: true,
    /** Workaround for Vue CLI accounting for nested page paths
     * https://github.com/vuejs/vue-cli/issues/4378
    */
    extract: {
      filename: '/css/[name].css',
      chunkFilename: '/css/[name].css',
    },
    loaderOptions: {
      less: {
        lessOptions: {
          javascriptEnabled: true
        }
      }
    }
  },
  chainWebpack: config => {
    /** Do not create index pages for entry points */
    config.entryPoints.store.forEach( (_, entry) => {
      config.plugins.delete(`html-${entry}`)
      config.plugins.delete(`preload-${entry}`)
      config.plugins.delete(`prefetch-${entry}`)
    })

    /** Process source maps from deps */
    config.module.rule('source-map-loader')
      .test(/\.js$/)
      .include.add(/ui-trellis\/lib/).end()
      .enforce('pre')
      .use('source-map-loader')
      .loader('source-map-loader')
      .end()
  },
  configureWebpack: {
    devtool: process.env.VUE_APP_DEVTOOL,
    output: {
      filename: '[name].js',
      library: 'rundeckCore',
    },
    devServer: {
      hot: true,
      watchOptions: {
        followSymlinks: true,
      },
      proxy: {
        ".": {
          target: "http://xubuntu:4440"
        }
      }
    },
    externals: {'vue': 'Vue'},
    plugins: [
      new webpack.NormalModuleReplacementPlugin( /node_modules\/ant-design-vue\/es\/style\/index\.less/, function(resource) {
        if (resource.resource) {
          resource.resource = resource.resource.replace(/node_modules\/ant-design-vue\/es\/style\/index\.less/, 'src/antScope.less')
        }
      }),
      /** Generate source maps for CSS as it does not support eval-source-map */
      new webpack.SourceMapDevToolPlugin({
        filename: "[file].map",
        include: [/\.css$/]
      })
    ]
  }
};
<|endoftext|>


<commit_before>angular.module('wuw.services')

.factory('Deadlines', function($http, $q, Settings) {
    var deadlines = JSON.parse(Settings.getSetting('localDeadlines') || '[]');

    // add a new deadline (to server and locally)
    var add = function(newDeadline) {
        var deferred = $q.defer();
        $http({
            url: Settings.getSetting("apiUrl") + '/deadlines',
            method: "POST",
            headers: {'Content-Type': 'application/json'},
            data: newDeadline
        })
        .then(function(response) {
            deferred.resolve(response);
            newDeadline._id = response.data.id;
            deadlines.push(newDeadline);
            Settings.setSetting('localDeadlines', JSON.stringify(deadlines));
        },
        function(response) {
            deferred.reject(response);
        });
        return deferred.promise;
    };

    // return the deadline to a given id
    var get = function(id) {
        for (var i = 0; i < deadlines.length; i++) {
            if (deadlines[i]._id == id) {
                return deadlines[i];
            }
        }
    };

    // load all deadlines from the server and merge it with the local deadlines.
    var all = function() {
        var deferred = $q.defer();
        var localDeadlines = JSON.parse(Settings.getSetting('localDeadlines') || '[]');
        var mergedDeadlines = [];

        $http.get(Settings.getSetting("apiUrl") + '/deadlines').
        success(function(data, status, headers, config) {

            // iterate over each received deadline and merge it with the local deadlines
            for (var i = 0; i < data.length; i++) {
                var currDeadline = data[i];
                var mergedDeadline = null;
                for (var j = 0; j < localDeadlines.length; j++) {
                    currLocalDeadline = localDeadlines[j];
                    if (currLocalDeadline._id === currDeadline._id) {
                        mergedDeadline = {};
                        mergedDeadline._id = currDeadline._id;
                        mergedDeadline.info = currLocalDeadline.info;
                        mergedDeadline.deadline = currDeadline.deadline;
                        mergedDeadline.done = currLocalDeadline.done || false;
                    }
                }

                // if this deadline is not in our local deadlines, it is a new one
                if (!mergedDeadline) {
                    mergedDeadline = currDeadline;
                    mergedDeadline.done = false;
                }
                mergedDeadlines.push(mergedDeadline);
            }
            deadlines = mergedDeadlines;
            Settings.setSetting('localDeadlines', JSON.stringify(mergedDeadlines));
            deferred.resolve(mergedDeadlines);
        }).
        error(function(data, status, headers, config) {
            deferred.reject(data);
        });
        return deferred.promise;
    };

    // save the changes for a deadline locally
    var save = function(deadline) {
        // search for this deadline and save its changes
        for (var i = 0; i < deadlines.length; i++) {
            if (deadlines[i]._id === deadline._id) {
                deadlines[i].done = deadline.done;
                break;
            }
        }
        Settings.setSetting('localDeadlines', JSON.stringify(deadlines));
    };

    return {
        all: all,
        get: get,
        add: add,
        save: save
    }
});
<commit_msg>a new deadline is per default not done<commit_after>angular.module('wuw.services')

.factory('Deadlines', function($http, $q, Settings) {
    var deadlines = JSON.parse(Settings.getSetting('localDeadlines') || '[]');

    // add a new deadline (to server and locally)
    var add = function(newDeadline) {
        var deferred = $q.defer();
        newDeadline.done = false;
        $http({
            url: Settings.getSetting("apiUrl") + '/deadlines',
            method: "POST",
            headers: {'Content-Type': 'application/json'},
            data: newDeadline
        })
        .then(function(response) {
            deferred.resolve(response);
            newDeadline._id = response.data.id;
            deadlines.push(newDeadline);
            Settings.setSetting('localDeadlines', JSON.stringify(deadlines));
        },
        function(response) {
            deferred.reject(response);
        });
        return deferred.promise;
    };

    // return the deadline to a given id
    var get = function(id) {
        for (var i = 0; i < deadlines.length; i++) {
            if (deadlines[i]._id == id) {
                return deadlines[i];
            }
        }
    };

    // load all deadlines from the server and merge it with the local deadlines.
    var all = function() {
        var deferred = $q.defer();
        var localDeadlines = JSON.parse(Settings.getSetting('localDeadlines') || '[]');
        var mergedDeadlines = [];

        $http.get(Settings.getSetting("apiUrl") + '/deadlines').
        success(function(data, status, headers, config) {

            // iterate over each received deadline and merge it with the local deadlines
            for (var i = 0; i < data.length; i++) {
                var currDeadline = data[i];
                var mergedDeadline = null;
                for (var j = 0; j < localDeadlines.length; j++) {
                    currLocalDeadline = localDeadlines[j];
                    if (currLocalDeadline._id === currDeadline._id) {
                        mergedDeadline = {};
                        mergedDeadline._id = currDeadline._id;
                        mergedDeadline.info = currLocalDeadline.info;
                        mergedDeadline.deadline = currDeadline.deadline;
                        mergedDeadline.done = currLocalDeadline.done || false;
                    }
                }

                // if this deadline is not in our local deadlines, it is a new one
                if (!mergedDeadline) {
                    mergedDeadline = currDeadline;
                    mergedDeadline.done = false;
                }
                mergedDeadlines.push(mergedDeadline);
            }
            deadlines = mergedDeadlines;
            Settings.setSetting('localDeadlines', JSON.stringify(mergedDeadlines));
            deferred.resolve(mergedDeadlines);
        }).
        error(function(data, status, headers, config) {
            deferred.reject(data);
        });
        return deferred.promise;
    };

    // save the changes for a deadline locally
    var save = function(deadline) {
        // search for this deadline and save its changes
        for (var i = 0; i < deadlines.length; i++) {
            if (deadlines[i]._id === deadline._id) {
                deadlines[i].done = deadline.done;
                break;
            }
        }
        Settings.setSetting('localDeadlines', JSON.stringify(deadlines));
    };

    return {
        all: all,
        get: get,
        add: add,
        save: save
    }
});
<|endoftext|>


<commit_before>/**
 * AdjustmentsForm
 *
 * Um componente para para submeter formulários de ajustes de widgets.
 */
import React from 'react'
import PropTypes from 'prop-types'
import {
  FormGroup,
  ControlLabel,
  FormControl,
  ColorPicker,
  HelpBlock
} from '~client/components/forms'
import { SettingsForm } from '~client/ux/components'

const AdjustmentsSettingsForm = (props) => {
  const {
    children,
    fields: {
      call_to_action: callToAction,
      button_text: buttonText,
      count_text: countText,
      main_color: mainColor
    },
    widget,
    asyncWidgetUpdate,
    // TODO: Remover essa dependencia da mobilização
    dispatch,
    colorScheme,
    ...formProps
  } = props
  return (
    <SettingsForm
      {...formProps}
      onSubmit={values => {
        const settings = widget.settings || {}

        return asyncWidgetUpdate({
          ...widget,
          settings: { ...settings, ...values }
        })
      }}
      successMessage='Formulário configurado com sucesso!'
    >
      <FormGroup controlId='call-to-action-id' {...callToAction}>
        <ControlLabel>Título do formulário</ControlLabel>
        <FormControl
          type='text'
          placeholder='Ex: Preencha o formulário abaixo para assinar a petição.'
        />
      </FormGroup>
      <FormGroup controlId='button-text-id' {...buttonText}>
        <ControlLabel>Botão</ControlLabel>
        <FormControl
          type='text'
          placeholder='Defina o texto do botão de confirmação do formulário.'
        />
      </FormGroup>
      <FormGroup controlId='count-text-id' {...countText}>
        <ControlLabel>Contador</ControlLabel>
        <FormControl
          type='text'
          placeholder='Defina o texto que ficará ao lado do número de pessoas que agiram.'
        />
      </FormGroup>
      <FormGroup controlId='main-color-id' {...mainColor}>
        <ControlLabel>Cor padrão</ControlLabel>
        <HelpBlock>
          Selecione a cor no box abaixo ou insira o valor em hex, por exemplo: #DC3DCE.
        </HelpBlock>
        <ColorPicker
          dispatch={dispatch}
          theme={colorScheme.replace('-scheme', '')}
        />
      </FormGroup>
      {children}
    </SettingsForm>
  )
}

AdjustmentsSettingsForm.propTypes = {
  // Injected by redux-form
  fields: PropTypes.object.isRequired,
  handleSubmit: PropTypes.func.isRequired,
  submitting: PropTypes.bool.isRequired,
  error: PropTypes.string,
  // Injected by widgets/models/ModelForm
  colorScheme: PropTypes.string,
  // Injected by container
  mobilization: PropTypes.object.isRequired,
  widget: PropTypes.object.isRequired,
  asyncWidgetUpdate: PropTypes.func.isRequired
}

export default AdjustmentsSettingsForm
<commit_msg>chore(widget/adjustments): add help text to counter field<commit_after>/**
 * AdjustmentsForm
 *
 * Um componente para para submeter formulários de ajustes de widgets.
 */
import React from 'react'
import PropTypes from 'prop-types'
import {
  FormGroup,
  ControlLabel,
  FormControl,
  ColorPicker,
  HelpBlock
} from '~client/components/forms'
import { SettingsForm } from '~client/ux/components'

const AdjustmentsSettingsForm = (props) => {
  const {
    children,
    fields: {
      call_to_action: callToAction,
      button_text: buttonText,
      count_text: countText,
      main_color: mainColor
    },
    widget,
    asyncWidgetUpdate,
    // TODO: Remover essa dependencia da mobilização
    dispatch,
    colorScheme,
    ...formProps
  } = props
  return (
    <SettingsForm
      {...formProps}
      onSubmit={values => {
        const settings = widget.settings || {}

        return asyncWidgetUpdate({
          ...widget,
          settings: { ...settings, ...values }
        })
      }}
      successMessage='Formulário configurado com sucesso!'
    >
      <FormGroup controlId='call-to-action-id' {...callToAction}>
        <ControlLabel>Título do formulário</ControlLabel>
        <FormControl
          type='text'
          placeholder='Ex: Preencha o formulário abaixo para assinar a petição.'
        />
      </FormGroup>
      <FormGroup controlId='button-text-id' {...buttonText}>
        <ControlLabel>Botão</ControlLabel>
        <FormControl
          type='text'
          placeholder='Defina o texto do botão de confirmação do formulário.'
        />
      </FormGroup>
      <FormGroup controlId='count-text-id' {...countText}>
        <ControlLabel>Contador</ControlLabel>
        <FormControl
          type='text'
          placeholder='Defina o texto que ficará ao lado do número de pessoas que agiram.'
        />
        <HelpBlock>O contador será mostrado se existir um texto definido.</HelpBlock>
      </FormGroup>
      <FormGroup controlId='main-color-id' {...mainColor}>
        <ControlLabel>Cor padrão</ControlLabel>
        <HelpBlock>
          Selecione a cor no box abaixo ou insira o valor em hex, por exemplo: #DC3DCE.
        </HelpBlock>
        <ColorPicker
          dispatch={dispatch}
          theme={colorScheme.replace('-scheme', '')}
        />
      </FormGroup>
      {children}
    </SettingsForm>
  )
}

AdjustmentsSettingsForm.propTypes = {
  // Injected by redux-form
  fields: PropTypes.object.isRequired,
  handleSubmit: PropTypes.func.isRequired,
  submitting: PropTypes.bool.isRequired,
  error: PropTypes.string,
  // Injected by widgets/models/ModelForm
  colorScheme: PropTypes.string,
  // Injected by container
  mobilization: PropTypes.object.isRequired,
  widget: PropTypes.object.isRequired,
  asyncWidgetUpdate: PropTypes.func.isRequired
}

export default AdjustmentsSettingsForm
<|endoftext|>


<commit_before>import React from 'react'
import * as THREE from 'three'
import * as OIMO from 'oimo'

import Example from '-/components/example'
import notes from './readme.md'

let rand = Math.random

const init = ({ canvas, container }) => {
  let renderer = new THREE.WebGLRenderer({ canvas })
  let scene = new THREE.Scene()
  const camera = new THREE.PerspectiveCamera(
    75,
    container.clientWidth / container.clientWidth,
    0.1,
    1000
  )
  camera.position.z = 10
  camera.position.y = 5

 const randInt = () =>{
   return Math.floor(Math.random() * 10);
 }
  let world = new OIMO.World({
    timestep: 1/30,
    iterations: 8,
    broadphase: 2, // 1: brute force, 2: sweep & prune, 3: volume tree
    worldscale: 1,
    random: true,
    info:true,
    gravity: [0,-9.8,0]

  });
  let ground = world.add({size:[50, 10, 50], pos:[0,0,0], density:1 });
  var size = 1000;
  var divisions = 1000;

  var gridHelper = new THREE.GridHelper( size, divisions );
  scene.add( gridHelper );
  gridHelper.position.copy(ground.getPosition())

  renderer.setSize(container.clientWidth, container.clientWidth)
  const geometry = new THREE.BoxGeometry(1, 1, 1)
  const material = new THREE.MeshLambertMaterial({ color: 0xaaff00 })
  const cube = new THREE.Mesh(geometry, material)
  //scene.add(cube)

  const light = new THREE.PointLight(0xffffff, 1, 100)
  light.position.set(0, 3, 5)
  scene.add(light)

  let body1 = world.add({
      type:'sphere', // type of shape : sphere, box, cylinder
      size:[1,1,1], // size of shape
      pos:[0,0,0], // start position in degree
      rot:[0,0,90], // start rotation in degree
      move:true, // dynamic or statique
      density: 1,
      friction: 0.2,
      restitution: 0.2,
      belongsTo: 1, // The bits of the collision groups to which the shape belongs.
      collidesWith: 0xffffffff // The bits of the collision groups with which the shape collides.
  });

  world.step();

  const sphere = new THREE.IcosahedronBufferGeometry(1, 1)
  //hand.scale(0.2, 0.8, 1.5)

  const spheremesh = new THREE.Mesh(
    sphere,
    new THREE.MeshLambertMaterial({ color: Math.random() * 0xffffff })
  )
scene.add(spheremesh)

  const animate = () => {
    spheremesh.position.copy(body1.getPosition())
    spheremesh.quaternion.copy( body1.getQuaternion() )
    //cube.rotation.x += 0.01
    //cube.rotation.y += 0.01
    if (renderer) {
      requestAnimationFrame(animate)
      renderer.render(scene, camera)
    }

  }
  world.postLoop = animate
  world.play();

  //animate()

  return () => {
    renderer.dispose()
    scene.dispose()
    scene = null
    renderer = null
  }
}

const Collisions = () => <Example notes={notes} init={init} />

export default React.memo(Collisions)
<commit_msg>fix ground position<commit_after>import React from 'react'
import * as THREE from 'three'
import * as OIMO from 'oimo'

import Example from '-/components/example'
import notes from './readme.md'

let rand = Math.random

const init = ({ canvas, container }) => {
  let renderer = new THREE.WebGLRenderer({ canvas })
  let scene = new THREE.Scene()
  const camera = new THREE.PerspectiveCamera(
    75,
    container.clientWidth / container.clientWidth,
    0.1,
    1000
  )
  camera.position.z = 10
  camera.position.y = 5

 const randInt = () =>{
   return Math.floor(Math.random() * 10);
 }
  let world = new OIMO.World({
    timestep: 1/30,
    iterations: 8,
    broadphase: 2, // 1: brute force, 2: sweep & prune, 3: volume tree
    worldscale: 1,
    random: true,
    info:true,
    gravity: [0,-9.8,0]

  });
  let ground = world.add({size:[50, 0.01, 50], pos:[0,0,0], density:1 });
  var size = 1000;
  var divisions = 1000;

  var gridHelper = new THREE.GridHelper( size, divisions );

  gridHelper.position.x=0
  gridHelper.position.y=0
  gridHelper.position.z=0

  scene.add( gridHelper );

  renderer.setSize(container.clientWidth, container.clientWidth)

  const light = new THREE.PointLight(0xffffff, 1, 100)
  light.position.set(0, 3, 5)
  scene.add(light)

  let body1 = world.add({
      type:'sphere', // type of shape : sphere, box, cylinder
      size:[1,1,1], // size of shape
      pos:[0,10,0], // start position in degree
      rot:[0,0,0], // start rotation in degree
      move:true, // dynamic or statique
      density: 1,
      friction: 0.2,
      restitution: 0.2,
      belongsTo: 1, // The bits of the collision groups to which the shape belongs.
      collidesWith: 0xffffffff // The bits of the collision groups with which the shape collides.
  });

  world.step();

  const sphere = new THREE.IcosahedronBufferGeometry(1, 1)
  //hand.scale(0.2, 0.8, 1.5)

  const spheremesh = new THREE.Mesh(
    sphere,
    new THREE.MeshLambertMaterial({ color: Math.random() * 0xffffff })
  )
scene.add(spheremesh)

  const animate = () => {
    spheremesh.position.copy(body1.getPosition())
    spheremesh.quaternion.copy( body1.getQuaternion() )
    //cube.rotation.x += 0.01
    //cube.rotation.y += 0.01
    if (renderer) {
      requestAnimationFrame(animate)
      renderer.render(scene, camera)
    }

  }
  world.postLoop = animate
  world.play();

  //animate()

  return () => {
    renderer.dispose()
    scene.dispose()
    scene = null
    renderer = null
  }
}

const Collisions = () => <Example notes={notes} init={init} />

export default React.memo(Collisions)
<|endoftext|>


<commit_before>function EvDa(a){function G(a){return a.match(/[?*]/)}function H(a,b){return G(a)?p(m(b?b:B),function(b){return b.match(a)}):a}function I(a,b){var c={};return d(a)?(j(a,function(a){c[a]=b(a)}),c):b(a)}function J(a){if(a in B)return B[a];var b=a.split("."),c=b.pop(),d=b.join(".");if(d){var e=J(d);if(h(e)&&c in e)return e[c]}}function K(a,c,f){if(0===arguments.length)return{data:B,events:F,globs:E};if(d(a)){var g=b.call(arguments,1);return r(a,function(a){return K.apply(K.context,[a].concat(g))})}if(1==arguments.length){if(h(a)){var i={};return j(a,function(a,b){i[a]=K(a,b,f,{noexec:1})}),j(i,function(b){e(i[b])&&!e(a[b])&&(a[b]=i[b]())}),O(m(i)[0]),a}return I(a,J)}return K[e(c)||d(c)&&e(c[0])?v:"set"].apply(this,arguments)}function L(a){j(a.$,function(b){var c=G(b)?E:F;c[b]=n(c[b],a)})}function M(a,b,c){if(d(a)){var e=a.pop();return M(H(e),function(c,d){var e=1==a.length?a[0]:a;return M(e,b,d)},c)}if(h(a))return j(a,function(b,d){G(b)?t(b,I(b,function(){return M(b,d,c)})):a[b]=M(b,d,c)}),a;var f="set"+a;return F[f]&&(F[f](function(b){K.set.call(K.context,a,b,c)}),delete F[f]),b?a in B?b.call(K.context,B[a],c):K(a,b,t(c||{},y)):a in B}function N(a,b,c,d){a.S||(a.call(b,c,d),a.once&&L(a))}function O(a){var c=a.split("."),d=c.pop();parts_obj=[],parts_obj[d]=B[a],K.extend.apply(K.context,[c.join("."),parts_obj].concat(b.call(arguments,1)))}var b=Array.prototype.slice,c=Object.prototype.toString,d=[].isArray||function(a){return"[object Array]"===c.call(a)},e=function(a){return!!(a&&a.constructor&&a.call&&a.apply)},f=function(a){return!!(""===a||a&&a.charCodeAt&&a.substr)},g=function(a){return"[object Number]"===c.call(a)},h=function(a){return e(a)||f(a)||g(a)||d(a)?!1:null==a?"object"==String(a):"[object Object]"===c.call(a)||!0},i=function(a){return b.call(a)},j=[].forEach?function(a,b){if(d(a)||a.length)i(a).forEach(b);else for(var c in a)b(c,a[c])}:function(a,b){if(d(a))for(var c=0,e=a.length;e>c;c++)b(a[c],c);else for(var f in a)b(f,a[f])},k=function(a){return a.length?a[a.length-1]:void 0},l=function(a){var b=[];for(var c in a)b.push(a[c]);return b},m={}.keys||function(a){if(d(a))return a;var b=[];for(var c in a)b.push(c);return b},n=function(a,b){var c=[];return j(a,function(a){a!==b&&c.push(a)}),c},o=function(a){var b,c=[];return j(m(a).sort(),function(a){a!=b&&(b=a,c.push(a))}),c},p=function(a,b){var c=[];return j(a,function(a){b(a)&&c.push(a)}),c},q=function(a){return a&&"length"in a?a.length:0},r=[].map?function(a,b){return a.map(b)}:function(a,b){for(var c=[],d=0,e=a.length;e>d;d++)c.push(b(a[d],d));return c},s=function(a){return d(a)?b.call(a):h(a)?t(a,{}):a},t=function(a){return j(b.call(arguments,1),function(b){for(var c in b)void 0!==b[c]&&(a[c]=b[c])}),a},u="first",v="on",w="after",x=[u,v,w,"test","or"],y={once:1},z={},A={},B=a||{},D=[],E={},F={};return j(x,function(a){K[a]=function(c,d,e){if(_.isArray(d)){var f=b.call(arguments,2);return r(d,function(b){return K[a].apply(K.context,[c,b].concat(f))})}var g=F;return d?((d.$||(d.$=[])).push(a+c),G(c)&&(g=E),(g[a+c]||(g[a+c]=[])).push(d),t(d,e)):g[a+c]}}),t(K,{_:{},context:this,list:{},isPaused:!1,db:B,events:function(a,b){return b?F[b+a]:a?I(x.concat(["set"]),function(b){return F[b+a]}):F},del:L,whenSet:M,isset:M,pause:function(){return K.isPaused?!1:(K.isPaused=!0,K._.set=K.set,K.set=function(){D.push(["set",arguments])},!0)},play:function(){if(K.isPaused){K.isPaused=!1;var a=EvDa();return K.set=K._.set,j(D,function(b){a[b[0]].apply(a,b[1])}),D=[],K(a.db),!0}return!1},setter:function(a,b){return F["set"+a]=b,F[v+a]?M(a):void 0},when:function(a,c,g){if(h(a)){var i={},k={},m=function(a,b){k[b.key]=!1,b()},n=function(a,d){k[d.key]=!0,-1==l(k).indexOf(!1)&&c.apply(K.context,b.call(arguments))};return j(a,function(a,b){i[a+"-test"]=K.test(a,m),i[a]=K.when(a,b,n),k[a]=!1}),i}if(f(c))try{var o=new Function("x","return x"+c);o(),c=o}catch(p){}return K(a,function(a){(d(c)&&c.sort().join("")===a.sort().join("")||e(c)&&c(a)||a===c)&&g.apply(K.context,b.call(arguments))})},empty:function(){for(var a in B)delete B[a]},incr:function(a,b,c){return b=b||1,K.set(a,g(B[a])?B[a]+b:b,c)},decr:function(a,b,c){return b=b||1,K.set(a,B[a]-b||0,c)},push:function(a,b,c){return K.set(a,[].concat(B[a]||[],[b]),c)},pop:function(a,b){return K.set(a,B[a].slice(0,-1),b)},traceList:[],group:function(a){var b=i(arguments),a=b.shift(),c=K.apply(0,b);return K.list[a]||(K.list[a]=[]),e(c)?K.list[a].push(c):j(c,function(b){K.list[a].push(b)}),function(){return K.group.apply(0,[a].concat(i(arguments)))}},extend:function(a,c){return K.set.apply(K.context,[a,t({},B[a]||{},c)].concat(b.call(arguments,2)))},set:function(a,c,d,e){e=e||{};var f,g=e.bypass,h=e.coroutine||function(){return!0},i="value"in e,k=e.noexec;if(1==arguments.length){var l=function(){K.set.apply(K.context,[a].concat(b.call(arguments)))};return K.set.call(K.context,a,void 0),l}if(z[a]>0)return B[a];z[a]=(z[a]||0)+1;var n,y,m="test"+a,o=b.call(arguments),p=q(F[m]),r=0,x=p&&!g,C=function(){j(F["or"+a]||[],function(a){N(a,K.context,i?e.value:D.value,D)})},D=x?function(b){return y|=b===!1,--p?(r++,h(D,!1)?(f=F[m][r].call(K.context,i?e.value:D.value,D),(f===!0||f===!1)&&D(f)):C()):y?C():h(D,!0)?K.set(a,D.value,D.meta,{bypass:1}):C(),b}:{};if(D.old=s(B[a]),t(D,{meta:d||{},done:D,result:D,key:a,value:c}),x)z[a]--,A[a]!==!0&&(A[a]=!0,h(D,!1)?(f=F[m][r].call(K.context,i?e.value:D.value,D),(f===!0||f===!1)&&D(f)):C(),A[a]=!1),n=B[a];else{if(j(K.traceList,function(a){a.call(K.context,o)}),!h(D,!0))return n;c=D.value,B[a]=c;var E=arguments,G=function(){return j((F[u+a]||[]).concat(F[v+a]||[]),function(a){D.last=N(a,K.context,c,D)}),a.length>0&&O.apply(K.context,[a].concat(b.call(E,2))),j(F[w+a]||[],function(a){D.last=N(a,K.context,c,D)}),c};n=k?G:G.call(K.context)}return z[a]=0,n},fire:function(a){K.set(a,B[a])},once:function(a,b,c){return h(a)&&(a=l(a)),d(a)?r(a,function(a){K.once.call(K.context,a,b,c)}):b?K.once(K(a,b,c)):t(a,y)},enable:function(a){return j(K.list[a],function(b){b.S&&b.S[a]&&delete b.S[a],0==q(b.S)&&delete b.S}),K.list[a]},osetadd:function(a,b,c){var e=B[a]||[];return K(a,b,c,{coroutine:function(a,b){var c=d(a.value)?a.value:[a.value];return a.set=s(e),j(c,function(b){-1==a.set.indexOf(b)&&a.set.push(b)}),b&&(a.value=a.set),e.length!=a.set.length}})},setadd:function(a,b,c){var e=B[a]||[];return K(a,b,c,{coroutine:function(a,b){var c=d(a.value)?a.value:[a.value];return a.set=o(e.concat(c)),b&&(a.value=a.set),e.length!=a.set.length}})},setdel:function(a,b,c){var d=B[a]||[],e=n(d,b);return d.length!=e.length?K(a,e,c,{value:b}):e},disable:function(a){return j(K.list[a],function(b){(b.S||(b.S={}))[a]=!0}),K.list[a]},unset:function(){var a=!0;return j(arguments,function(b){a&=b in B;var g,h,i,c=b.split("."),d="",e=c.length,f=c[e-1];for(g=0;e>g;g++)if(d=c.slice(0,g).join("."),i=B[d]){for(h=g;e-1>h;h++)i=i[c[h]];delete i[f]}delete B[b]}),a},find:function(a){return p(m(B),function(b){return b.match(a)})},changed:function(a,b){return K.on(a,function(a,c){var d=q(a),e=q(c.old);1==d-e?b.call(K.context,k(a)):d>e&&b.call(K.context,i(a).slice(e))})},sniff:function(){var a={},b=+new Date,c=function(c){a[c[0]]||console.log(+new Date-b,c)},d=function(){},e=c;K.traceList.unshift(function(a){e(a)}),K.sniff=function(b){return arguments.length>0?f(b)?(a[b]=!a[b],"[Un]ignoring "+b):(e=b?c:d,b):m(a)}}}),K.setAdd=K.setadd,K.osetAdd=K.osetadd,K.setDel=K.setdel,K.isSet=K.isset,K.get=K,K.change=K.on,K.add=K.push,K.isArray=d,K}<commit_msg>minified<commit_after>function EvDa(a){function G(a){return a.match(/[?*]/)}function H(a,b){return G(a)?p(m(b?b:B),function(b){return b.match(a)}):a}function I(a,b){var c={};return d(a)?(j(a,function(a){c[a]=b(a)}),c):b(a)}function J(a){if(a in B)return B[a];var b=a.split("."),c=b.pop(),d=b.join(".");if(d){var e=J(d);if(h(e)&&c in e)return e[c]}}function K(a,c,f,g){if(g=g||{},0===arguments.length)return{data:B,events:F,globs:E};if(d(a)){var i=b.call(arguments,1);return r(a,function(a){return K.apply(K.context,[a].concat(i))})}if(1==arguments.length){if(h(a)){var k={};return g.noexec=1,j(a,function(a,b){k[a]=K(a,b,f,g)}),g.bypass||j(k,function(b){e(k[b])&&!e(a[b])&&(a[b]=k[b]())}),O(m(k)[0]),a}return I(a,J)}return K[e(c)||d(c)&&e(c[0])?v:"set"].apply(this,arguments)}function L(a){j(a.$,function(b){var c=G(b)?E:F;c[b]=n(c[b],a)})}function M(a,b,c){if(d(a)){var e=a.pop();return M(H(e),function(c,d){var e=1==a.length?a[0]:a;return M(e,b,d)},c)}if(h(a))return j(a,function(b,d){G(b)?t(b,I(b,function(){return M(b,d,c)})):a[b]=M(b,d,c)}),a;var f="set"+a;return F[f]&&(F[f](function(b){K.set.call(K.context,a,b,c)}),delete F[f]),b?a in B?b.call(K.context,B[a],c):K(a,b,t(c||{},y)):a in B}function N(a,b,c,d){a.S||(a.call(b,c,d),a.once&&L(a))}function O(a){var c=a.split("."),d=c.pop();parts_obj=[],parts_obj[d]=B[a],K.extend.apply(K.context,[c.join("."),parts_obj].concat(b.call(arguments,1)))}var b=Array.prototype.slice,c=Object.prototype.toString,d=[].isArray||function(a){return"[object Array]"===c.call(a)},e=function(a){return!!(a&&a.constructor&&a.call&&a.apply)},f=function(a){return!!(""===a||a&&a.charCodeAt&&a.substr)},g=function(a){return"[object Number]"===c.call(a)},h=function(a){return e(a)||f(a)||g(a)||d(a)?!1:null==a?"object"==String(a):"[object Object]"===c.call(a)||!0},i=function(a){return b.call(a)},j=[].forEach?function(a,b){if(d(a)||a.length)i(a).forEach(b);else for(var c in a)b(c,a[c])}:function(a,b){if(d(a))for(var c=0,e=a.length;e>c;c++)b(a[c],c);else for(var f in a)b(f,a[f])},k=function(a){return a.length?a[a.length-1]:void 0},l=function(a){var b=[];for(var c in a)b.push(a[c]);return b},m={}.keys||function(a){if(d(a))return a;var b=[];for(var c in a)b.push(c);return b},n=function(a,b){var c=[];return j(a,function(a){a!==b&&c.push(a)}),c},o=function(a){var b,c=[];return j(m(a).sort(),function(a){a!=b&&(b=a,c.push(a))}),c},p=function(a,b){var c=[];return j(a,function(a){b(a)&&c.push(a)}),c},q=function(a){return a&&"length"in a?a.length:0},r=[].map?function(a,b){return a.map(b)}:function(a,b){for(var c=[],d=0,e=a.length;e>d;d++)c.push(b(a[d],d));return c},s=function(a){return d(a)?b.call(a):h(a)?t(a,{}):a},t=function(a){return j(b.call(arguments,1),function(b){for(var c in b)void 0!==b[c]&&(a[c]=b[c])}),a},u="first",v="on",w="after",x=[u,v,w,"test","or"],y={once:1},z={},A={},B=a||{},D=[],E={},F={};return j(x,function(a){K[a]=function(c,d,e){if(_.isArray(d)){var f=b.call(arguments,2);return r(d,function(b){return K[a].apply(K.context,[c,b].concat(f))})}var g=F;return d?((d.$||(d.$=[])).push(a+c),G(c)&&(g=E),(g[a+c]||(g[a+c]=[])).push(d),t(d,e)):g[a+c]}}),t(K,{_:{},context:this,list:{},isPaused:!1,db:B,events:function(a,b){return b?F[b+a]:a?I(x.concat(["set"]),function(b){return F[b+a]}):F},del:L,whenSet:M,isset:M,pause:function(){return K.isPaused?!1:(K.isPaused=!0,K._.set=K.set,K.set=function(){D.push(["set",arguments])},!0)},play:function(){if(K.isPaused){K.isPaused=!1;var a=EvDa();return K.set=K._.set,j(D,function(b){a[b[0]].apply(a,b[1])}),D=[],K(a.db),!0}return!1},setter:function(a,b){return F["set"+a]=b,F[v+a]?M(a):void 0},when:function(a,c,g){if(h(a)){var i={},k={},m=function(a,b){k[b.key]=!1,b()},n=function(a,d){k[d.key]=!0,-1==l(k).indexOf(!1)&&c.apply(K.context,b.call(arguments))};return j(a,function(a,b){i[a+"-test"]=K.test(a,m),i[a]=K.when(a,b,n),k[a]=!1}),i}if(f(c))try{var o=new Function("x","return x"+c);o(),c=o}catch(p){}return K(a,function(a){(d(c)&&c.sort().join("")===a.sort().join("")||e(c)&&c(a)||a===c)&&g.apply(K.context,b.call(arguments))})},empty:function(){for(var a in B)delete B[a]},incr:function(a,b,c){return b=b||1,K.set(a,g(B[a])?B[a]+b:b,c)},decr:function(a,b,c){return b=b||1,K.set(a,B[a]-b||0,c)},push:function(a,b,c){return K.set(a,[].concat(B[a]||[],[b]),c)},pop:function(a,b){return K.set(a,B[a].slice(0,-1),b)},traceList:[],group:function(a){var b=i(arguments),a=b.shift(),c=K.apply(0,b);return K.list[a]||(K.list[a]=[]),e(c)?K.list[a].push(c):j(c,function(b){K.list[a].push(b)}),function(){return K.group.apply(0,[a].concat(i(arguments)))}},extend:function(a,c){return K.set.apply(K.context,[a,t({},B[a]||{},c)].concat(b.call(arguments,2)))},set:function(a,c,d,e){e=e||{};var f,g=e.bypass,h=e.coroutine||function(){return!0},i="value"in e,k=e.noexec;if(1==arguments.length){var l=function(){K.set.apply(K.context,[a].concat(b.call(arguments)))};return K.set.call(K.context,a,void 0),l}if(z[a]>0)return B[a];z[a]=(z[a]||0)+1;var n,y,m="test"+a,o=b.call(arguments),p=q(F[m]),r=0,x=p&&!g,C=function(){j(F["or"+a]||[],function(a){N(a,K.context,i?e.value:D.value,D)})},D=x?function(b){return y|=b===!1,--p?(r++,h(D,!1)?(f=F[m][r].call(K.context,i?e.value:D.value,D),(f===!0||f===!1)&&D(f)):C()):y?C():h(D,!0)?K.set(a,D.value,D.meta,{bypass:1}):C(),b}:{};if(D.old=s(B[a]),t(D,{meta:d||{},done:D,result:D,key:a,value:c}),x)z[a]--,A[a]!==!0&&(A[a]=!0,h(D,!1)?(f=F[m][r].call(K.context,i?e.value:D.value,D),(f===!0||f===!1)&&D(f)):C(),A[a]=!1),n=B[a];else{if(j(K.traceList,function(a){a.call(K.context,o)}),!h(D,!0))return n;c=D.value,B[a]=c;var E=arguments,G=function(){return j((F[u+a]||[]).concat(F[v+a]||[]),function(a){D.last=N(a,K.context,c,D)}),a.length>0&&O.apply(K.context,[a].concat(b.call(E,2))),j(F[w+a]||[],function(a){D.last=N(a,K.context,c,D)}),c};n=k?G:G.call(K.context)}return z[a]=0,n},fire:function(a){K.set(a,B[a])},once:function(a,b,c){return h(a)&&(a=l(a)),d(a)?r(a,function(a){K.once.call(K.context,a,b,c)}):b?K.once(K(a,b,c)):t(a,y)},enable:function(a){return j(K.list[a],function(b){b.S&&b.S[a]&&delete b.S[a],0==q(b.S)&&delete b.S}),K.list[a]},osetadd:function(a,b,c){var e=B[a]||[];return K(a,b,c,{coroutine:function(a,b){var c=d(a.value)?a.value:[a.value];return a.set=s(e),j(c,function(b){-1==a.set.indexOf(b)&&a.set.push(b)}),b&&(a.value=a.set),e.length!=a.set.length}})},setadd:function(a,b,c){var e=B[a]||[];return K(a,b,c,{coroutine:function(a,b){var c=d(a.value)?a.value:[a.value];return a.set=o(e.concat(c)),b&&(a.value=a.set),e.length!=a.set.length}})},setdel:function(a,b,c){var d=B[a]||[],e=n(d,b);return d.length!=e.length?K(a,e,c,{value:b}):e},disable:function(a){return j(K.list[a],function(b){(b.S||(b.S={}))[a]=!0}),K.list[a]},unset:function(){var a=!0;return j(arguments,function(b){a&=b in B;var g,h,i,c=b.split("."),d="",e=c.length,f=c[e-1];for(g=0;e>g;g++)if(d=c.slice(0,g).join("."),i=B[d]){for(h=g;e-1>h;h++)i=i[c[h]];delete i[f]}delete B[b]}),a},find:function(a){return p(m(B),function(b){return b.match(a)})},changed:function(a,b){return K.on(a,function(a,c){var d=q(a),e=q(c.old);1==d-e?b.call(K.context,k(a)):d>e&&b.call(K.context,i(a).slice(e))})},sniff:function(){var a={},b=+new Date,c=function(c){a[c[0]]||console.log(+new Date-b,c)},d=function(){},e=c;K.traceList.unshift(function(a){e(a)}),K.sniff=function(b){return arguments.length>0?f(b)?(a[b]=!a[b],"[Un]ignoring "+b):(e=b?c:d,b):m(a)}}}),K.setAdd=K.setadd,K.osetAdd=K.osetadd,K.setDel=K.setdel,K.isSet=K.isset,K.get=K,K.change=K.on,K.add=K.push,K.isArray=d,K}<|endoftext|>


<commit_before>define({
  root:{
    "DELETE":
      "
${this.getLabel({formatLength: 'long', locale: 'nl'})}$ is verwijderd.
" +
      "
Het venster werd gesloten.
",

    "POST":
      "${this.getLabel({formatLength: 'long', locale: 'nl'})}$ is succesvol " +
      "aangemaakt.",

    "PUT":
      "De nieuwe waarden voor ${this.getLabel({formatLength: 'long', locale: 'nl'})}$ " +
      "zijn opgeslagen.",

    "ppwcode-vernacular-persistence/IdNotFoundException":
      "
${this.getLabel({formatLength: 'long', locale: 'nl'})}$ bestaat niet " +
      "meer.
" +
      "
Het venster werd gesloten.
",

    "ppwcode-vernacular-persistence/IdNotFoundException/UNKNOWN OBJECT":
      "Het gevraagde object bestaat niet meer.",

    "ppwcode-vernacular-persistence/ObjectAlreadyChangedException":
      "
${this.subjectRepresentation('nl')}$ is " +
      "ondertussen reeds in een ander venster of door een andere gebruiker aangepast.
" +
      "
Bekijk of uw wijzigingen nog nodig zijn, en herhaal ze indien nodig.
",

    "ppwcode-vernacular-exceptions/SemanticException[NOT UNIQUE]":
      "
Een waarde voor " +
      "${this.subjectRepresentation('nl')}$ die uniek moet " +
      "zijn, is niet uniek.
" +
      "
Pas de gegevens aan, en probeer opnieuw.
",

    "ppwcode-vernacular-exceptions/SemanticException":
      "
De ingevulde waarden voor " +
      "${this.subjectRepresentation('nl')}$ worden door " +
      "de server niet aanvaard.
" +
      "
(${(this.exception.key ? this.exception.key : '') + (this.exception.cause ? JSON.stringify(this.exception.cause) : '')}$)
" +
      "
Pas de gegevens aan, en probeer opnieuw.
",

    "ppwcode-vernacular-exceptions/SecurityException":
      "De gevraagde gegevens zijn voor u niet toegankelijk.",

    "error":
      "
Er heeft zich een onverwachte situatie voorgedaan. We verontschuldigen ons, maar uw laatste wijzigingen " +
      "zijn niet opgeslagen.
" +
      "
Herlaad de pagina, en probeer opnieuw.
" +
      "
Indien de fout zich blijft herhalen, kan u ons contacteren.
" +
      "
(${this.exception.message || this.exception.toString()}$)
"
  }
});
<commit_msg>More neutral message for generic SemanticException.<commit_after>define({
  root:{
    "DELETE":
      "
${this.getLabel({formatLength: 'long', locale: 'nl'})}$ is verwijderd.
" +
      "
Het venster werd gesloten.
",

    "POST":
      "${this.getLabel({formatLength: 'long', locale: 'nl'})}$ is succesvol " +
      "aangemaakt.",

    "PUT":
      "De nieuwe waarden voor ${this.getLabel({formatLength: 'long', locale: 'nl'})}$ " +
      "zijn opgeslagen.",

    "ppwcode-vernacular-persistence/IdNotFoundException":
      "
${this.getLabel({formatLength: 'long', locale: 'nl'})}$ bestaat niet " +
      "meer.
" +
      "
Het venster werd gesloten.
",

    "ppwcode-vernacular-persistence/IdNotFoundException/UNKNOWN OBJECT":
      "Het gevraagde object bestaat niet meer.",

    "ppwcode-vernacular-persistence/ObjectAlreadyChangedException":
      "
${this.subjectRepresentation('nl')}$ is " +
      "ondertussen reeds in een ander venster of door een andere gebruiker aangepast.
" +
      "
Bekijk of uw wijzigingen nog nodig zijn, en herhaal ze indien nodig.
",

    "ppwcode-vernacular-exceptions/SemanticException[NOT UNIQUE]":
      "
Een waarde voor " +
      "${this.subjectRepresentation('nl')}$ die uniek moet " +
      "zijn, is niet uniek.
" +
      "
Pas de gegevens aan, en probeer opnieuw.
",

    "ppwcode-vernacular-exceptions/SemanticException":
      "
Uw actie op " +
      "${this.subjectRepresentation('nl')}$ wordt door " +
      "de server niet aanvaard.
" +
      "
(${(this.exception.key ? this.exception.key : '') + (this.exception.cause ? JSON.stringify(this.exception.cause) : '')}$)
" +
      "
Pas eventueel de gegevens aan, en probeer opnieuw.
",

    "ppwcode-vernacular-exceptions/SecurityException":
      "De gevraagde gegevens zijn voor u niet toegankelijk.",

    "error":
      "
Er heeft zich een onverwachte situatie voorgedaan. We verontschuldigen ons, maar uw laatste wijzigingen " +
      "zijn niet opgeslagen.
" +
      "
Herlaad de pagina, en probeer opnieuw.
" +
      "
Indien de fout zich blijft herhalen, kan u ons contacteren.
" +
      "
(${this.exception.message || this.exception.toString()}$)
"
  }
});
<|endoftext|>


<commit_before>/**
 * Bitcoin services for pockets.
 */

var
  _bitcoin = require('bitcoinjs-lib'),
  base58 = require('bs58'),
  ecurve = require('ecurve'),
  BigInteger = require('bigi'),
  Buffer = require('buffer'),
  async = require('async'),
  _ = require('underscore'),
  request = process.browser ? require('browser-request') : require('request');

var bitcoin = module.exports;

/**
 * Validates a wallet address
 * @param {object} options contains the `address` attribute
 * @param {function} callback the callback function to run on done
 *  - `err` holds the error (if any occured)
 *  - `result` true/false indicating if the wallet is valid.
 */
bitcoin.validateWallet = function (options, callback) {
  function isAddress(string) {
    try {
      _bitcoin.Address.fromBase58Check(string);
    } catch (e) {
      return false;
    }
    return true;
  }

  if (isAddress(options.address))
    return callback(null);
  return callback(new Error('Invalid wallet address [' + options.address + '].'))
};

bitcoin.createWallet = function (options, callback) {
  try {
    var key = _bitcoin.ECKey.makeRandom();
    var address = key.pub.getAddress(_bitcoin.networks.testnet).toString();
    return callback(null, {key: key.toWIF(_bitcoin.networks.testnet), address: address});
  }
  catch (ex) {
    return callback(ex);
  }
};

bitcoin.balance = function (options, callback) {
  var balance = null;
  var uri = 'https://test-insight.bitpay.com/api/addr/';
  uri += options.wallet.address;
  request.get(uri, function (err, headers, body) {
    if (err)
      return callback(err);
    if (headers.statusCode !== 200)
      return callback(new Error('Failed to get address balance.'));
    try {
      var details = JSON.parse(body);
      balance = details.balance + details.unconfirmedBalance;
    }
    catch (ex) {
      return callback(ex);
    }

    return callback(null, balance);
  });
};

bitcoin.choose_vouts = function (txs, totalamount) {
  var inplay = [];
  var inplayAmount = 0;
  var change = [];

  var sorted = _.sortBy(txs, function (x) {
    return x.amount;
  });

  sorted.forEach(function (tx) {
    if (inplayAmount < totalamount) {
      inplay.push(tx);
      inplayAmount += tx.amount;
    }
  });
  return inplay;
};

bitcoin.buildTransaction = function (options, callback) {
  options.tx = new _bitcoin.TransactionBuilder();
  var key = _bitcoin.ECKey.fromWIF(options.from.wallet.key);
  var uri = 'https://test-insight.bitpay.com/api/addr/';
  uri += options.from.wallet.address + '/utxo';
  console.log('fetching utxo ', uri);
  request.get(uri, function (err, headers, body) {
    if (err)
      return callback(err);
    if (headers.statusCode !== 200)
      return callback(new Error('Failed to get address balance.'));
    var details = JSON.parse(body);
    options.vouts = bitcoin.choose_vouts(details, options.amount);
    options.vouts.forEach(function (vout, i) {
      console.log('adding vout for wallet [' + options.from.wallet.address + '], ', vout.txid, vout.vout);
      options.tx.addInput(vout.txid, vout.vout)
    });
    options.tx.addOutput(options.to.wallet.address, options.amount * 100000000);
    options.vouts.forEach(function (vout, i) {
      options.tx.sign(i, key);
    });
    options.toHex = options.tx.build().toHex();
    return callback(null, options.toHex);
  });
};

bitcoin.handleTransaction = function (options, callback) {
  var transactions = options.transactions;
  //should be a complete transaction and handle it
  engine.pockets.snapshot({}, function (err, snapshot) {
    //console.log('before snapshot', snapshot);
    //mock up, update balances and trigger event.
    async.map(transactions, function (transaction, cb) {
      var amount = transaction.amount;
      engine.pockets.get({name: transaction.from.name, mock: true}, function (err, fromPocket) {
        engine.pockets.get({name: transaction.to.name, mock: true}, function (err, toPocket) {
          if (err)
            return cb(err);

          if (fromPocket)
            fromPocket.wallet.balance = fromPocket.wallet.balance - Math.abs(amount);
          toPocket.wallet.balance = toPocket.wallet.balance + Math.abs(amount);
          console.log('[' + transaction.from.name + '] --> [' + transaction.to.name + ']', Math.abs(amount));
          //console.log('Updating wallet [' + transaction.to.name + '] adding ' + amount);

          if (options.mock || engine.options.mock)
            return cb(null);

          bitcoin.buildTransaction(transaction, function (err, tx_hex) {
            if (err)
              return cb(err);

            var uri = 'https://test-insight.bitpay.com/api/tx/send';
            request.post(uri, {form: {rawtx: tx_hex}}, function (err, headers, body) {
              if (err)
                return cb(err);
              if (headers.statusCode !== 200)
                return cb(new Error('Failed to send transaction.'));
              return cb();
            });
          });
        });
      });
    }, function (err, results) {
      if (err)
        return callback(err);
      engine.pockets.snapshot({}, function (err, snapshot) {
        console.log('after snapshot', snapshot);
        engine.events.emit('wallet-update');
        return callback(null, options);
      });
    });
  });
};

bitcoin.sendMoney = function (options, callback) {
  //should be a complete transaction and handle it
  engine.pockets.snapshot({}, function (err, snapshot) {
    //console.log('before snapshot', snapshot);
    //mock up, update balances and trigger event.
    var amount = options.amount;
    engine.pockets.get({name: options.from.name, mock: true}, function (err, fromPocket) {
      if (fromPocket)
        fromPocket.wallet.balance = fromPocket.wallet.balance - Math.abs(amount);
      options.to.wallet.balance = options.to.wallet.balance + Math.abs(amount);
      console.log('[' + options.from.name + '] --> [' + options.to.name + ']', Math.abs(amount));
      //console.log('Updating wallet [' + transaction.to.name + '] adding ' + amount);

      if (options.mock || engine.options.mock) {
        return callback(null);
      }

      bitcoin.buildTransaction(options, function (err, tx_hex) {
        if (err)
          return callback(err);
        var uri = 'https://test-insight.bitpay.com/api/tx/send';
        request.post(uri, {form: {rawtx: tx_hex}}, function (err, headers, body) {
          if (err)
            return callback(err);
          if (headers.statusCode !== 200)
            return callback(new Error('Failed to send transaction.'));
          engine.pockets.snapshot({}, function (err, snapshot) {
            console.log('after snapshot', snapshot);
            engine.events.emit('wallet-update');
            return callback(null, options);
          });
        });
      });
    });
  });
};<commit_msg>#1 additional jsdocs<commit_after>/**
 * Bitcoin services for pockets.
 */

var
  _bitcoin = require('bitcoinjs-lib'),
  base58 = require('bs58'),
  ecurve = require('ecurve'),
  BigInteger = require('bigi'),
  Buffer = require('buffer'),
  async = require('async'),
  _ = require('underscore'),
  request = process.browser ? require('browser-request') : require('request');

var bitcoin = module.exports;

/**
 * Validates a wallet address
 * @param {object} options contains the `address` attribute
 * @param {function} callback the callback function to run on done
 *  - `err` holds the error (if any occured)
 *  - `result` true/false indicating if the wallet is valid.
 */
bitcoin.validateWallet = function (options, callback) {
  function isAddress(string) {
    try {
      _bitcoin.Address.fromBase58Check(string);
    } catch (e) {
      return false;
    }
    return true;
  }

  if (isAddress(options.address))
    return callback(null);
  return callback(new Error('Invalid wallet address [' + options.address + '].'))
};

/**
 * Create a new wallet
 * @param {object} options contains the options for creating a wallet
 * @param {function} callback the callback function to run on done
 *  - `err` holds the error (if any occured)
 *  - `result` true/false indicating if the wallet is valid.
 */
bitcoin.createWallet = function (options, callback) {
  try {
    var key = _bitcoin.ECKey.makeRandom();
    var address = key.pub.getAddress(_bitcoin.networks.testnet).toString();
    return callback(null, {key: key.toWIF(_bitcoin.networks.testnet), address: address});
  }
  catch (ex) {
    return callback(ex);
  }
};

/**
 * Fetch a wallet balance
 * @param {object} options contains the options for fetching balances
 * - `wallet` holds the details of the wallet to check
 * @param {function} callback the callback function to run on done
 *  - `err` holds the error (if any occured)
 *  - `result` true/false indicating if the wallet is valid.
 */
bitcoin.balance = function (options, callback) {
  var balance = null;
  var uri = 'https://test-insight.bitpay.com/api/addr/';
  uri += options.wallet.address;
  request.get(uri, function (err, headers, body) {
    if (err)
      return callback(err);
    if (headers.statusCode !== 200)
      return callback(new Error('Failed to get address balance.'));
    try {
      var details = JSON.parse(body);
      balance = details.balance + details.unconfirmedBalance;
    }
    catch (ex) {
      return callback(ex);
    }

    return callback(null, balance);
  });
};

/**
 * Chooses the array of transactions to use as tx inputs
 * @param {array} txs array of transactions holding id, amount, vout
 * @param {number} totalamount the total amount to send
 * @returns {Array} Array of valid txs to use as inputs
 */
bitcoin.choose_vouts = function (txs, totalamount) {
  var inplay = [];
  var inplayAmount = 0;
  var change = [];

  var sorted = _.sortBy(txs, function (x) {
    return x.amount;
  });

  sorted.forEach(function (tx) {
    if (inplayAmount < totalamount) {
      inplay.push(tx);
      inplayAmount += tx.amount;
    }
  });
  return inplay;
};

/**
 * Build a new transaction
 * @param {object} options object containing a transaction
 * - `from` holds the source wallet
 * - `to` holds the destination wallet
 * - `amount` the amount to send
 * @param {function} callback function to receive results
 * - `err` the error (if any occured)
 * - `result` the function result
 */
bitcoin.buildTransaction = function (options, callback) {
  options.tx = new _bitcoin.TransactionBuilder();
  var key = _bitcoin.ECKey.fromWIF(options.from.wallet.key);
  var uri = 'https://test-insight.bitpay.com/api/addr/';
  uri += options.from.wallet.address + '/utxo';
  console.log('fetching utxo ', uri);
  request.get(uri, function (err, headers, body) {
    if (err)
      return callback(err);
    if (headers.statusCode !== 200)
      return callback(new Error('Failed to get address balance.'));
    var details = JSON.parse(body);
    options.vouts = bitcoin.choose_vouts(details, options.amount);
    options.vouts.forEach(function (vout, i) {
      console.log('adding vout for wallet [' + options.from.wallet.address + '], ', vout.txid, vout.vout);
      options.tx.addInput(vout.txid, vout.vout)
    });
    options.tx.addOutput(options.to.wallet.address, options.amount * 100000000);
    options.vouts.forEach(function (vout, i) {
      options.tx.sign(i, key);
    });
    options.toHex = options.tx.build().toHex();
    return callback(null, options.toHex);
  });
};

/**
 * Send money from a pocket to pocket
 * @param {object} options object containing a transaction
 * - `from` holds the source pocket
 * - `to` holds the destination pocket
 * - `amount` the amount to send
 * @param {function} callback function to receive results
 * - `err` the error (if any occured)
 * - `result` the function result
 */
bitcoin.handleTransaction = function (options, callback) {
  var transactions = options.transactions;
  //should be a complete transaction and handle it
  engine.pockets.snapshot({}, function (err, snapshot) {
    //console.log('before snapshot', snapshot);
    //mock up, update balances and trigger event.
    async.map(transactions, function (transaction, cb) {
      var amount = transaction.amount;
      engine.pockets.get({name: transaction.from.name, mock: true}, function (err, fromPocket) {
        engine.pockets.get({name: transaction.to.name, mock: true}, function (err, toPocket) {
          if (err)
            return cb(err);

          if (fromPocket)
            fromPocket.wallet.balance = fromPocket.wallet.balance - Math.abs(amount);
          toPocket.wallet.balance = toPocket.wallet.balance + Math.abs(amount);
          console.log('[' + transaction.from.name + '] --> [' + transaction.to.name + ']', Math.abs(amount));
          //console.log('Updating wallet [' + transaction.to.name + '] adding ' + amount);

          if (options.mock || engine.options.mock)
            return cb(null);

          bitcoin.buildTransaction(transaction, function (err, tx_hex) {
            if (err)
              return cb(err);

            var uri = 'https://test-insight.bitpay.com/api/tx/send';
            request.post(uri, {form: {rawtx: tx_hex}}, function (err, headers, body) {
              if (err)
                return cb(err);
              if (headers.statusCode !== 200)
                return cb(new Error('Failed to send transaction.'));
              return cb();
            });
          });
        });
      });
    }, function (err, results) {
      if (err)
        return callback(err);
      engine.pockets.snapshot({}, function (err, snapshot) {
        console.log('after snapshot', snapshot);
        engine.events.emit('wallet-update');
        return callback(null, options);
      });
    });
  });
};

/**
 * Send money from a pocket to a wallet
 * @param {object} options object containing a transaction
 * - `from` holds the source pocket
 * - `to` holds the destination wallet
 * - `amount` the amount to send
 * @param {function} callback function to receive results
 * - `err` the error (if any occured)
 * - `result` the function result
 */
bitcoin.sendMoney = function (options, callback) {
  //should be a complete transaction and handle it
  engine.pockets.snapshot({}, function (err, snapshot) {
    //console.log('before snapshot', snapshot);
    //mock up, update balances and trigger event.
    var amount = options.amount;
    engine.pockets.get({name: options.from.name, mock: true}, function (err, fromPocket) {
      if (fromPocket)
        fromPocket.wallet.balance = fromPocket.wallet.balance - Math.abs(amount);
      options.to.wallet.balance = options.to.wallet.balance + Math.abs(amount);
      console.log('[' + options.from.name + '] --> [' + options.to.name + ']', Math.abs(amount));
      //console.log('Updating wallet [' + transaction.to.name + '] adding ' + amount);

      if (options.mock || engine.options.mock) {
        return callback(null);
      }

      bitcoin.buildTransaction(options, function (err, tx_hex) {
        if (err)
          return callback(err);
        var uri = 'https://test-insight.bitpay.com/api/tx/send';
        request.post(uri, {form: {rawtx: tx_hex}}, function (err, headers, body) {
          if (err)
            return callback(err);
          if (headers.statusCode !== 200)
            return callback(new Error('Failed to send transaction.'));
          engine.pockets.snapshot({}, function (err, snapshot) {
            console.log('after snapshot', snapshot);
            engine.events.emit('wallet-update');
            return callback(null, options);
          });
        });
      });
    });
  });
};<|endoftext|>


<commit_before>const mainCommands = new Set([
  'help',
  'list',
  'remove',
  'alias',
  'domains',
  'dns',
  'certs',
  'secrets',
  'billing',
  'upgrade',
  'teams',
  'logs',
  'scale',
  'logout',
  'whoami'
])

const aliases = {
  list: ['ls'],
  remove: ['rm'],
  alias: ['ln', 'aliases'],
  domains: ['domain'],
  certs: ['cert'],
  secrets: ['secret'],
  billing: ['cc'],
  upgrade: ['downgrade'],
  teams: ['team', 'switch'],
  logs: ['log']
}

const specialCommands = [
  'deploy',
  'login'
]

const subcommands = new Set([...specialCommands, ...Array.from(mainCommands)])

// Add aliases to available sub commands
for (const alias in aliases) {
  const items = aliases[alias]

  for (const item of items) {
    subcommands.add(item)
  }
}

const list = {
  title: 'now.sh',
  subcommands,
  get deploy() {
    return require('./deploy')
  },
  get login() {
    return require('./login')
  }
}

for (const subcommand of mainCommands) {
  let handlers = [subcommand]

  if (aliases[subcommand]) {
    handlers = handlers.concat(aliases[subcommand])
  }

  for (const handler of handlers) {
    Object.defineProperty(list, handler, {
      get() {
        return require(`./commands/bin/${subcommand}`)
      }
    })
  }
}

module.exports = list
<commit_msg>Better order for .sh commands<commit_after>const mainCommands = new Set([
  'help',
  'list',
  'remove',
  'alias',
  'domains',
  'dns',
  'certs',
  'secrets',
  'billing',
  'upgrade',
  'teams',
  'logs',
  'scale',
  'logout',
  'whoami'
])

const specialCommands = new Set([
  'deploy',
  'login'
])

const aliases = {
  list: ['ls'],
  remove: ['rm'],
  alias: ['ln', 'aliases'],
  domains: ['domain'],
  certs: ['cert'],
  secrets: ['secret'],
  billing: ['cc'],
  upgrade: ['downgrade'],
  teams: ['team', 'switch'],
  logs: ['log']
}

const subcommands = new Set([
  ...Array.from(mainCommands),
  ...Array.from(specialCommands)
])

// Add aliases to available sub commands
for (const alias in aliases) {
  const items = aliases[alias]

  for (const item of items) {
    subcommands.add(item)
  }
}

const list = {
  title: 'now.sh',
  subcommands,
  get deploy() {
    return require('./deploy')
  },
  get login() {
    return require('./login')
  }
}

for (const subcommand of mainCommands) {
  let handlers = [subcommand]

  if (aliases[subcommand]) {
    handlers = handlers.concat(aliases[subcommand])
  }

  for (const handler of handlers) {
    Object.defineProperty(list, handler, {
      get() {
        return require(`./commands/bin/${subcommand}`)
      }
    })
  }
}

module.exports = list
<|endoftext|>


<commit_before>'use strict';

module.change_code = 1;

var alexa = require("alexa-app");
var gcm = require("node-gcm");
var app = new alexa.app("robot");

const gcmServerKey = process.env.GCM_SERVER_KEY;
const registrationToken = process.env.REGISTRATION_TOKEN;

var sender = new gcm.Sender(gcmServerKey);
var registrationTokens = [registrationToken];

var n = ["north", "forward", "up"];
var ne = ["north east"];
var e = ["east", "right"];
var se = ["south east"];
var s = ["south", "back", "backward", "reverse", "down"];
var sw = ["south west"];
var w = ["west", "left"];
var nw = ["north west"];

// index is a code
var directionsCodes = [n, ne, e, se, s, sw, w, nw];
var directions = [].concat.apply([], directionsCodes);

function directionToCode(direction) {
  for (var i = 0; i < directionsCodes.length; i++) {
    for (var j = 0; j < directionsCodes[i].length; j++) {
      if (directionsCodes[i][j] == direction) {
        return i;
      }
    }
  }
  return -1;
}

var lightsCode = 9;

app.dictionary = {
  "directions": directions
};

app.launch(function(request, response) {
  response.shouldEndSession(false);
  console.log("Session started");
  response.say("Welcome to marks control service");
});

app.sessionEnded(function(request, response) {
  console.log("Session ended");
});

app.intent("RobotLightsIntent", {
    "utterances": [
    "{toggle|switch|} lights"
     // "red on",
    ]
  },
  function(request, response)
           {
            response.shouldEndSession(false);
          // var message = new gcm.Message({
           //   data: { code: lightsCode }
                                       // });
   // sender.send(message, { registrationTokens: registrationTokens }, function (err, data)
     //    {
    //    if (err) {
      //    console.error(err);
      //    response.say("Sorry, there was an unexpected error. Could not send message to robot.");
                //  }
       //   else
         // {
          console.log(data);
          response.say("Turning red light on");
           //}
            //response.send();
      // });
  //  return false;
  }
);

app.intent("RobotStatsIntent", {
    "utterances": [
      "{tell|give|say} {me|} stats",
    ]
  },
  function(request, response)
           {
            response.shouldEndSession(false);
            if (request.hasSession())
               {
                 var session = request.getSession();
                  console.log(session.details.attributes);
                  var stats = "";
                  for (var key in session.details.attributes)
                    {
                      var counter = session.get(key);
                      stats += ", " + key + " " + counter;
                    }
                 if (stats.length > 0)
                   {
                    response.say("The stats are " + stats);
                   }
                 else
                   {
                     response.say("No moves, yet");
                   }
               }
               else
                  {
                   response.say("Sorry, session is not active, no stats are available");
                   }
         }
);

app.intent("RobotStopIntent", {
    "utterances": [
      "{exit|quit|stop|end|bye}",
    ]
  },
  function(request, response) {
    response.say("It was a real pleasure talking to you. Have a good day!");
  }
);

module.exports = app;
<commit_msg>Update index.js<commit_after>'use strict';

module.change_code = 1;

var alexa = require("alexa-app");
var gcm = require("node-gcm");
var app = new alexa.app("robot");

const gcmServerKey = process.env.GCM_SERVER_KEY;
const registrationToken = process.env.REGISTRATION_TOKEN;

var sender = new gcm.Sender(gcmServerKey);
var registrationTokens = [registrationToken];

var n = ["north", "forward", "up"];
var ne = ["north east"];
var e = ["east", "right"];
var se = ["south east"];
var s = ["south", "back", "backward", "reverse", "down"];
var sw = ["south west"];
var w = ["west", "left"];
var nw = ["north west"];

// index is a code
var directionsCodes = [n, ne, e, se, s, sw, w, nw];
var directions = [].concat.apply([], directionsCodes);

function directionToCode(direction) {
  for (var i = 0; i < directionsCodes.length; i++) {
    for (var j = 0; j < directionsCodes[i].length; j++) {
      if (directionsCodes[i][j] == direction) {
        return i;
      }
    }
  }
  return -1;
}

var lightsCode = 9;

app.dictionary = {
  "directions": directions
};

app.launch(function(request, response) {
  response.shouldEndSession(false);
  console.log("Session started");
  response.say("Welcome to marks control service");
});

app.sessionEnded(function(request, response) {
  console.log("Session ended");
});

app.intent("RobotLightsIntent", {
    "utterances": [
   // "{toggle|switch|} lights"
     "red on",
    ]
  },
  function(request, response)
           {
            response.shouldEndSession(false);
          // var message = new gcm.Message({
           //   data: { code: lightsCode }
                                       // });
   // sender.send(message, { registrationTokens: registrationTokens }, function (err, data)
     //    {
    //    if (err) {
      //    console.error(err);
      //    response.say("Sorry, there was an unexpected error. Could not send message to robot.");
                //  }
       //   else
         // {
        //  console.log(data);
          response.say("Turning red L E D light on");
           //}
            //response.send();
      // });
  //  return false;
  }
);

app.intent("RobotStatsIntent", {
    "utterances": [
      "{tell|give|say} {me|} stats",
    ]
  },
  function(request, response)
           {
            response.shouldEndSession(false);
            if (request.hasSession())
               {
                 var session = request.getSession();
                  console.log(session.details.attributes);
                  var stats = "";
                  for (var key in session.details.attributes)
                    {
                      var counter = session.get(key);
                      stats += ", " + key + " " + counter;
                    }
                 if (stats.length > 0)
                   {
                    response.say("The stats are " + stats);
                   }
                 else
                   {
                     response.say("No moves, yet");
                   }
               }
               else
                  {
                   response.say("Sorry, session is not active, no stats are available");
                   }
         }
);

app.intent("RobotStopIntent", {
    "utterances": [
      "{exit|quit|stop|end|bye}",
    ]
  },
  function(request, response) {
    response.say("It was a real pleasure talking to you. Have a good day!");
  }
);

module.exports = app;
<|endoftext|>