<commit_before>'use strict';
/*jshint browser: true*/

/*global require: false*/
var utils = require('./utils');

var months = [
  'January',
  'February',
  'March',
  'April',
  'May',
  'June',
  'July',
  'August',
  'September',
  'October',
  'November',
  'December'
];

var attr = utils.attr;
var query = utils.query;
var mkEl = utils.mkEl;
var keys = utils.keys;
var tmpl = utils.tmpl;

function mkListItems(target, texts, clickCb, that) {
  var items = [];
  that = that || {};

  texts.forEach(function (text, i) {
    var el = mkEl('li');
    el.innerHTML = '' + text + '';

    el.addEventListener('click', function (evt) {
      evt.preventDefault();
      items.forEach(function (e) {
        var cl = e.classList;
        if (e === el) {
          if (!cl.contains('active')) {
            cl.add('active');
          }
        }
        else {
          cl.remove('active');
        }
      });

      clickCb.call(that, i, el);
    });

    target.appendChild(el);

    items.push(el);
  });

  return items;
}

function camDownloadsWidget(info, holder) {
  var majorList = query('ul.major', holder);
  var patchList = query('ul.patch', holder);
  var serverList = query('ul.server', holder);
  var infoDiv = query('.selected-server', holder);
  var standaloneDiv = query('.standalone', infoDiv);

  var releaseTitle = query('.info h3', holder);
  var notesA = query('a.notes', holder);
  var dateSpan = query('span.date', holder);
  var zipA = query('a.zip', holder);
  var targzA = query('a.tar-gz', holder);
  var warA = query('a.war', holder);

  var branches = keys(info.branches).sort(function (a, b) {
    return (a > b ? -1 : (a < b ? 1 : 0));
  });

  function getReleaseInfo(branch, version) {
    return info.branches[branch].find(function (release) {
      return release.number === version;
    });
  }

  function getBranchVersions(branch) {
    return info.branches[branch].map(function (release) {
      return release.number;
    }).filter(function (item) { return !!item; });
  }

  function getServers(release) {
    var servers = keys(info.servers);
    if (release.excludeServers) {
      servers = servers.filter(function (name) {
        return release.excludeServers.indexOf(name) < 0;
      });
    }
    return servers;
  }

  var dlBasePath = 'https://camunda.org/enterprise-release/camunda-bpm/';
  function mkServerClickHandler(servers, version, branch) {
    return function (s) {
      var selectedServer = servers[s];
      var release = getReleaseInfo(branch, version);
      infoDiv.classList.add('accessible');

      var dl = tmpl('{server}/{branch}/{version}/camunda-bpm-ee-{server}-{version}-ee', {
        version:  version,
        branch:   (version.indexOf('alpha') > -1) ? 'nightly' : branch,
        server:   selectedServer
      });

      releaseTitle.innerHTML = version + '-ee for ' + info.servers[selectedServer];

      var parts = release.date.split('.').map(function (part) {
        return parseInt(part, 10);
      });
      dateSpan.innerHTML = parts[2] + ' ' + months[parts[1] - 1] + ' ' + parts[0];

      attr(notesA, 'href', release.note);

      attr(warA, 'href', dlBasePath + tmpl('{server}/{branch}/{version}/camunda-webapp-ee-{server}-standalone-{version}-ee', {
        version:  version,
        branch:   (version.indexOf('alpha') > -1) ? 'nightly' : branch,
        server:   selectedServer === 'wildfly' || selectedServer === 'wildfly10' ? 'jboss' : selectedServer
      }) + '.war');

      attr(targzA, 'href', dlBasePath + dl + '.tar.gz');

      attr(zipA, 'href', dlBasePath + dl + '.zip');

      if (selectedServer.startsWith('ibm-was') || selectedServer === 'oracle-wls') {
        dl = tmpl('{vendor}-{server}/{branch}/{version}/camunda-ee-{vendor}-{server}-{version}-ee', {
          version:  version,
          branch:   (version.indexOf('alpha') > -1) ? 'nightly' : branch,
          vendor:   selectedServer.split('-')[0],
          server:   selectedServer.split('-')[1]
        });

        attr(targzA, 'href', dlBasePath + dl + '.tar.gz');

        attr(zipA, 'href', dlBasePath + dl + '.zip');

        attr(warA, 'href', dlBasePath + tmpl('{vendor}-{server}/{branch}/{version}/camunda-webapp-ee-{server}-standalone-{version}-ee', {
          version:  version,
          branch:   (version.indexOf('alpha') > -1) ? 'nightly' : branch,
          vendor:   selectedServer.split('-')[0],
          server:   selectedServer.split('-')[1]
        }) + '.war');
      }

      if (release.excludeFormats && release.excludeFormats.indexOf('war') > -1) {
        standaloneDiv.style.display = 'none';
      }
      else {
        standaloneDiv.style.display = 'block';
      }
    };
  }

  function mkVersionClickHandler(branchName) {
    var patchReleases = getBranchVersions(branchName);

    return function selectVersion(r) {
      serverList.innerHTML = '';

      infoDiv.classList.remove('accessible');

      var selectedVersion = patchReleases[r];

      var releaseInfo = getReleaseInfo(branchName, selectedVersion);

      var releaseServers = getServers(releaseInfo);

      return mkListItems(serverList, releaseServers.map(function (name) {
        return info.servers[name];
      }), mkServerClickHandler(releaseServers, selectedVersion, branchName));
    };
  }

  function selectBranch(b) {
    patchList.innerHTML = '';

    serverList.innerHTML = '';

    infoDiv.classList.remove('accessible');

    var branchName = branches[b];

    var patchReleases = getBranchVersions(branchName);

    return mkListItems(patchList, patchReleases, mkVersionClickHandler(branchName));
  }

  var branchEls = mkListItems(majorList, branches, selectBranch);

  if (info.selected) {
    var b = branches.indexOf(info.selected.branch);

    var versionEls = selectBranch(b);

    branchEls[b].classList.add('active');

    var patchReleases = getBranchVersions(branches[b]);

    var v = patchReleases.indexOf(info.selected.version);

    var serverEls = mkVersionClickHandler(branches[b])(v);

    versionEls[v].classList.add('active');

    var servers = getServers(patchReleases[v]);

    var s = servers.indexOf(info.selected.server);

    serverEls[s].classList.add('active');

    mkServerClickHandler(servers, info.selected.version, info.selected.branch)(s);
  }
}

var camDownloadsEl = query('.cam-downloads');
if (window.camDownloads && camDownloadsEl) {
  camDownloadsWidget(window.camDownloads, camDownloadsEl);
}
<commit_msg>chore(scripts): change download table<commit_after>'use strict';
/*jshint browser: true*/

/*global require: false*/
var utils = require('./utils');

var months = [
  'January',
  'February',
  'March',
  'April',
  'May',
  'June',
  'July',
  'August',
  'September',
  'October',
  'November',
  'December'
];

var attr = utils.attr;
var query = utils.query;
var mkEl = utils.mkEl;
var keys = utils.keys;
var tmpl = utils.tmpl;

function mkListItems(target, texts, clickCb, that) {
  var items = [];
  that = that || {};

  texts.forEach(function (text, i) {
    var el = mkEl('li');
    el.innerHTML = '' + text + '';

    el.addEventListener('click', function (evt) {
      evt.preventDefault();
      items.forEach(function (e) {
        var cl = e.classList;
        if (e === el) {
          if (!cl.contains('active')) {
            cl.add('active');
          }
        }
        else {
          cl.remove('active');
        }
      });

      clickCb.call(that, i, el);
    });

    target.appendChild(el);

    items.push(el);
  });

  return items;
}

function camDownloadsWidget(info, holder) {
  var majorList = query('ul.major', holder);
  var patchList = query('ul.patch', holder);
  var serverList = query('ul.server', holder);
  var infoDiv = query('.selected-server', holder);
  var standaloneDiv = query('.standalone', infoDiv);

  var releaseTitle = query('.info h3', holder);
  var notesA = query('a.notes', holder);
  var dateSpan = query('span.date', holder);
  var zipA = query('a.zip', holder);
  var targzA = query('a.tar-gz', holder);
  var warA = query('a.war', holder);

  var branches = keys(info.branches).sort(function (a, b) {
    return (a > b ? -1 : (a < b ? 1 : 0));
  });

  function getReleaseInfo(branch, version) {
    return info.branches[branch].find(function (release) {
      return release.number === version;
    });
  }

  function getBranchVersions(branch) {
    return info.branches[branch].map(function (release) {
      return release.number;
    }).filter(function (item) { return !!item; });
  }

  function getServers(release) {
    var servers = keys(info.servers);
    if (release.excludeServers) {
      servers = servers.filter(function (name) {
        return release.excludeServers.indexOf(name) < 0;
      });
    }
    return servers;
  }

  var dlBasePath = 'https://camunda.org/enterprise-release/camunda-bpm/';
  function mkServerClickHandler(servers, version, branch) {
    return function (s) {
      var selectedServer = servers[s];
      var release = getReleaseInfo(branch, version);
      infoDiv.classList.add('accessible');

      var dl = tmpl('{server}/{branch}/{version}/camunda-bpm-ee-{server}-{version}-ee', {
        version:  version,
        branch:   (version.indexOf('alpha') > -1) ? 'nightly' : branch,
        server:   selectedServer
      });

      releaseTitle.innerHTML = version + '-ee for ' + info.servers[selectedServer];

      var parts = release.date.split('.').map(function (part) {
        return parseInt(part, 10);
      });
      dateSpan.innerHTML = parts[2] + ' ' + months[parts[1] - 1] + ' ' + parts[0];

      attr(notesA, 'href', release.note);

      attr(warA, 'href', dlBasePath + tmpl('{server}/{branch}/{version}/camunda-webapp-ee-{server}-standalone-{version}-ee', {
        version:  version,
        branch:   (version.indexOf('alpha') > -1) ? 'nightly' : branch,
        server:   selectedServer.match(/wildfly*/) ? 'jboss' : selectedServer
      }) + '.war');

      attr(targzA, 'href', dlBasePath + dl + '.tar.gz');

      attr(zipA, 'href', dlBasePath + dl + '.zip');

      if (selectedServer.startsWith('ibm-was') || selectedServer === 'oracle-wls') {
        dl = tmpl('{vendor}-{server}/{branch}/{version}/camunda-ee-{vendor}-{server}-{version}-ee', {
          version:  version,
          branch:   (version.indexOf('alpha') > -1) ? 'nightly' : branch,
          vendor:   selectedServer.split('-')[0],
          server:   selectedServer.split('-')[1]
        });

        attr(targzA, 'href', dlBasePath + dl + '.tar.gz');

        attr(zipA, 'href', dlBasePath + dl + '.zip');

        attr(warA, 'href', dlBasePath + tmpl('{vendor}-{server}/{branch}/{version}/camunda-webapp-ee-{server}-standalone-{version}-ee', {
          version:  version,
          branch:   (version.indexOf('alpha') > -1) ? 'nightly' : branch,
          vendor:   selectedServer.split('-')[0],
          server:   selectedServer.split('-')[1]
        }) + '.war');
      }

      if (release.excludeFormats && release.excludeFormats.indexOf('war') > -1) {
        standaloneDiv.style.display = 'none';
      }
      else {
        standaloneDiv.style.display = 'block';
      }
    };
  }

  function mkVersionClickHandler(branchName) {
    var patchReleases = getBranchVersions(branchName);

    return function selectVersion(r) {
      serverList.innerHTML = '';

      infoDiv.classList.remove('accessible');

      var selectedVersion = patchReleases[r];

      var releaseInfo = getReleaseInfo(branchName, selectedVersion);

      var releaseServers = getServers(releaseInfo);

      return mkListItems(serverList, releaseServers.map(function (name) {
        return info.servers[name];
      }), mkServerClickHandler(releaseServers, selectedVersion, branchName));
    };
  }

  function selectBranch(b) {
    patchList.innerHTML = '';

    serverList.innerHTML = '';

    infoDiv.classList.remove('accessible');

    var branchName = branches[b];

    var patchReleases = getBranchVersions(branchName);

    return mkListItems(patchList, patchReleases, mkVersionClickHandler(branchName));
  }

  var branchEls = mkListItems(majorList, branches, selectBranch);

  if (info.selected) {
    var b = branches.indexOf(info.selected.branch);

    var versionEls = selectBranch(b);

    branchEls[b].classList.add('active');

    var patchReleases = getBranchVersions(branches[b]);

    var v = patchReleases.indexOf(info.selected.version);

    var serverEls = mkVersionClickHandler(branches[b])(v);

    versionEls[v].classList.add('active');

    var servers = getServers(patchReleases[v]);

    var s = servers.indexOf(info.selected.server);

    serverEls[s].classList.add('active');

    mkServerClickHandler(servers, info.selected.version, info.selected.branch)(s);
  }
}

var camDownloadsEl = query('.cam-downloads');
if (window.camDownloads && camDownloadsEl) {
  camDownloadsWidget(window.camDownloads, camDownloadsEl);
}
<|endoftext|>


<commit_before>const io = require('socket.io-client');

const msgTypes = [
  'error',
  'strims'
];

const socket = io('https://api.overrustle.com/streams');

function init(store) {
  msgTypes.forEach(type => {
    socket.on(type, payload => {
      // rename old server's "strims" to "streams"
      if (type === 'strims') {
        type = 'streams';
      }

      store.dispatch({ type, payload });
    });
  });
}

function emit(type, payload) {
  socket.send(payload);
}

export { init, emit };
<commit_msg>add note about `socket.io`<commit_after>// TODO: remove `socket.io` and use native WebSockets once the new server is up
import io from 'socket.io-client';

const socket = io('https://api.overrustle.com/streams');

// the types of payloads we can expect from the server
const MSG_TYPES = [
  'error',
  'strims',
];

function init(store) {
  MSG_TYPES.forEach(type => {
    socket.on(type, payload => {
      // rename old server's "strims" to "streams"
      if (type === 'strims') {
        type = 'streams';
      }

      store.dispatch({ type, payload });
    });
  });
}

function emit(type, payload) {
  socket.emit(type, payload);
}

export { init, emit };
<|endoftext|>


<commit_before>(function() {
	//CKEDITOR
	CKEDITOR.plugins.add( 'hubzerohighlight', {
		init: function( editor ) {
			var mode = '';
			//console.log(editor);
			editor.on('mode', function(event) {
				// run
				highlight();

				// add css for mark elements
				if (editor.mode != 'source')
				{
					this.document.appendStyleSheet('/media/editors/ckeditor/plugins/hubzerohighlight/plugin.css');
				}
			});

			editor.on('beforeSave', function(event) {

				var data  = this.getData();

				// remove old mark tags
				data = data.replace(//g, '');
				data = data.replace(/<\/mark>/g, '');
				data = data.replace(//g, '');
				data = data.replace(/<\/mark>/g, '');
				data = data.replace(//g, '');
				data = data.replace(/<\/mark>/g, '');

				// set new data
				this.setData(data);
			});

			editor.on('blur', function(event) {
				highlight();

				// add css for mark elements
				if (editor.mode != 'source')
				{
					this.document.appendStyleSheet('/media/editors/ckeditor/plugins/hubzerohighlight/plugin.css');
				}
			});

			function highlight()
			{
				var data  = editor.getData();

				// remove old mark tags
				data = data.replace(//g, '');
				data = data.replace(/<\/mark>/g, '');
				data = data.replace(//g, '');
				data = data.replace(/<\/mark>/g, '');
				data = data.replace(//g, '');
				data = data.replace(/<\/mark>/g, '');

				// add new mark tags
				if (editor.mode == 'wysiwyg')
				{
					data = data.replace(/(\[\[[^\]]*]])/g, '$1');
					data = data.replace(/(<group:include[^>]*>)/g, '$1');
					data = data.replace(/({xhub:[^}]*})/g, '$1');
				}

				// set new data
				editor.setData(data);
			}
		}
	});
})();<commit_msg>[HABRI][#422]] Updated hub zero highlight plugin for CKEditor to not run in ie8. Cant get it to stop throwing error on highlight, causes form to not submit correctly.<commit_after>(function() {
	//CKEDITOR
	CKEDITOR.plugins.add( 'hubzerohighlight', {
		init: function( editor ) {
			var $      = jq,
				mode   = '',
				plugin = this;

			// dont highlight for ie8
			if ($('html').hasClass('ie8'))
			{
				return;
			}

			editor.on('mode', function(event) {
				plugin.highlight(editor);

				// add css for mark elements
				if (editor.mode != 'source')
				{
					this.document.appendStyleSheet('/media/editors/ckeditor/plugins/hubzerohighlight/plugin.css');
				}
			});

			editor.on('blur', function(event) {
				plugin.highlight(editor);

				// add css for mark elements
				if (editor.mode != 'source')
				{
					this.document.appendStyleSheet('/media/editors/ckeditor/plugins/hubzerohighlight/plugin.css');
				}
			});

			var form = $(editor.element.$.form);
			form.submit(function(event) {
				var data  = editor.getData();

				// remove old mark tags
				data = data.replace(//g, '');
				data = data.replace(/<\/mark>/g, '');
				data = data.replace(//g, '');
				data = data.replace(/<\/mark>/g, '');
				data = data.replace(//g, '');
				data = data.replace(/<\/mark>/g, '');

				// set new data
				editor.setData(data);
			});
		},

		highlight: function( editor )
		{
			console.log('highlight');

			// get current data
			var data  = editor.getData();

			// remove old mark tags
			data = data.replace(//g, '');
			data = data.replace(/<\/mark>/g, '');
			data = data.replace(//g, '');
			data = data.replace(/<\/mark>/g, '');
			data = data.replace(//g, '');
			data = data.replace(/<\/mark>/g, '');

			// add new mark tags
			if (editor.mode == 'wysiwyg')
			{
				data = data.replace(/(\[\[[^\]]*]])/g, '$1');
				data = data.replace(/(<group:include[^>]*>)/g, '$1');
				data = data.replace(/({xhub:[^}]*})/g, '$1');
			}

			// set new data
			editor.setData(data);
		}
	});
})();<|endoftext|>


<commit_before>// ==UserScript==
// @name        Animmex video width fix
// @description Sets the player size to 100% on animmex
// @namespace   hansen-i-nate24215@gmail.com
// @include     https://amx.*.xyz/*
// @include     http://amx.*.xyz/*
// @include     https://www.animmex.net/*
// @include     http://www.animmex.net/*
// @version     1.2
// @grant       none
// @license     MIT License (Expat); opensource.org/licenses/MIT
// ==/UserScript==
'use strict';

function addStyle(css) {
  const head = document.head || document.getElementsByTagName('head')[0];
  if (!head) return;

  const style = document.createElement('style');
  style.type = 'text/css';

  try {
    style.textContent = css;
  } catch(e) {
    style.innerHTML = css;
  }

  head.appendChild(style);
};

// only has effect under amx.*.xyz
addStyle(`
.video-js, #video_1 {
    width: 100% !important;
    height: 100% !important;
}
`);

// we can't use a CSS selector here because it might bugger up!
const voteBox = document.getElementsByClassName('vote-box');
if (voteBox.length > 0) { // will only be true under animmex.net
  voteBox[0].parentElement.style.width = '100%';
}

// we want @grant none so we can assign this to `window` and block ze popups
window.open = function(){};
<commit_msg>animmex fix now saves current time<commit_after>// ==UserScript==
// @name        Animmex video width fix
// @description Sets the player size to 100% on animmex
// @namespace   hansen-i-nate24215@gmail.com
// @include     https://amx.*.xyz/*
// @include     http://amx.*.xyz/*
// @include     https://www.animmex.net/*
// @include     http://www.animmex.net/*
// @version     1.4
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_addStyle
// @license     MIT License (Expat); opensource.org/licenses/MIT
// ==/UserScript==
'use strict';

const _unsafeWindow = typeof unsafeWindow != 'undefined' ? unsafeWindow : window.wrappedJSObject;

if (typeof GM_addStyle == 'undefined') {
  var GM_addStyle = function(css) {//not let or const
    const head = document.head || document.getElementsByTagName('head')[0];
    if (!head) return;

    const style = document.createElement('style');
    style.type = 'text/css';

    try {
      style.textContent = css;
    } catch(e) {
      style.innerHTML = css;
    }

    head.appendChild(style);
  };
}

// only has effect under amx.*.xyz
GM_addStyle(`
.video-js, #video_1 {
    width: 100% !important;
    height: 100% !important;
}
`);

// we can't use a CSS selector here because it might bugger up!
const voteBox = document.getElementsByClassName('vote-box');
if (voteBox.length > 0) { // will only be true under animmex.net
  voteBox[0].parentElement.style.width = '100%';
}

const videos = document.getElementsByTagName('video');

if (videos.length!==0){
  const videoId = videos[0].getAttribute('poster');
  videos[0].currentTime=GM_getValue(videoId, 0);

  window.addEventListener('beforeunload', function() {
    GM_setValue(videoId, videos[0].currentTime);
  });
}

function browserContext() {
  /***** DO NOT REFERENCE EXTERNAL VARIABLES FROM THIS FUNCTION *****/
  'use strict';
  const noopfn = function(){};
  window.open = noopfn;

  window.init = noopfn;//not native; animmex thing
  try{
  Object.defineProperty(window, 'init', {
    configurable:true,
    set:noopfn,
    get:()=>noopfn
  });
  }catch(e){}
}

window.eval(browserContext.toSource() +';browserContext()');

<|endoftext|>


<commit_before>(function (window, document) {

    var layout   = document.getElementById('layout'),
        menu     = document.getElementById('menu'),
        menuLink = document.getElementById('menuLink'),
        content  = document.getElementById('main');

    function toggleClass(element, className) {
        var classes = element.className.split(/\s+/),
            length = classes.length,
            i = 0;

        for(; i < length; i++) {
          if (classes[i] === className) {
            classes.splice(i, 1);
            break;
          }
        }
        // The className is not found
        if (length === classes.length) {
            classes.push(className);
        }

        element.className = classes.join(' ');
    }

    function toggleAll(e) {
        var active = 'active';

        e.preventDefault();
        toggleClass(layout, active);
        toggleClass(menu, active);
        toggleClass(menuLink, active);
    }

    menuLink.onclick = function (e) {
        toggleAll(e);
    };

    content.onclick = function(e) {
        if (menu.className.indexOf('active') != -1)
            toggleAll(e);
    }

}(this, this.document));
<commit_msg>fix lint errors<commit_after>(function (window, document) {

    var layout   = document.getElementById('layout'),
        menu     = document.getElementById('menu'),
        menuLink = document.getElementById('menuLink'),
        content  = document.getElementById('main');

    function toggleClass(element, className) {
        var classes = element.className.split(/\s+/),
            length = classes.length,
            i = 0;

        for(; i < length; i++) {
          if (classes[i] === className) {
            classes.splice(i, 1);
            break;
          }
        }
        // The className is not found
        if (length === classes.length) {
            classes.push(className);
        }

        element.className = classes.join(' ');
    }

    function toggleAll(e) {
        var active = 'active';

        e.preventDefault();
        toggleClass(layout, active);
        toggleClass(menu, active);
        toggleClass(menuLink, active);
    }

    menuLink.onclick = function (e) {
        toggleAll(e);
    };

    content.onclick = function(e) {
        if (menu.className.indexOf('active') !== -1) {
            toggleAll(e);
        }
    };

}(this, this.document));
<|endoftext|>


<commit_before>LandingController = RouteController.extend({
  layoutTemplate: 'landingLayout',
  onBeforeAction: function () {
    $('body').addClass('landing');
    this.next();
  },
  action: function () {
    this.layout('landingLayout');
    this.render();
  },
  onStop: function () {
    $('body').removeClass('landing');
  }
});
Router.route('/landing', {
  layoutTemplate: '',
  controller: LandingController,
  action: function () {
    this.layout('');
    this.render();
  }
});
Router.route('/login', {
  controller: LandingController
});
Router.route('/signup', {
  controller: LandingController
});
Router.route('/forgot', {
  name: 'forgotPassword',
  controller: LandingController
});
Router.route('/invite', {
  controller: LandingController,
  action: function () {
    var self = this;
    var query = self.params.query;
    var inviterId = query && query.inviter_id;
    var inviteCode = query && query.invite_code;

    Meteor.call('validLink', inviterId, inviteCode, function (error, result) {
      if (!result || error) {
        self.layout('mainLayout');
        self.render('notFound');
      } else {
        self.layout('landingLayout');
        self.render();
      }
    });
    self.render('loading');
  }
});
Router.route('/settings', {
  name: 'settings',
  onBeforeAction: function () {
    if (!Meteor.loggingIn() && !Meteor.userId()) {
      this.redirect('home');
    }
    this.next();
  },
  action: function () {
    this.layout('mainLayout');
    this.render();
  }
});
<commit_msg>Prevent validLink call from rerunning upon submitting invite form and triggering a 404 flash<commit_after>LandingController = RouteController.extend({
  layoutTemplate: 'landingLayout',
  onBeforeAction: function () {
    $('body').addClass('landing');
    this.next();
  },
  action: function () {
    this.layout('landingLayout');
    this.render();
  },
  onStop: function () {
    $('body').removeClass('landing');
  }
});
Router.route('/landing', {
  layoutTemplate: '',
  controller: LandingController,
  action: function () {
    this.layout('');
    this.render();
  }
});
Router.route('/login', {
  controller: LandingController
});
Router.route('/signup', {
  controller: LandingController
});
Router.route('/forgot', {
  name: 'forgotPassword',
  controller: LandingController
});
Router.route('/invite', {
  controller: LandingController,
  onRun: function () {
    this._firstRun = true;
  },
  action: function () {
    var self = this;

    if (self._firstRun) {
      self._firstRun = false;

      var query = self.params.query;
      var inviterId = query && query.inviter_id;
      var inviteCode = query && query.invite_code;

      Meteor.call('validLink', inviterId, inviteCode, function (error, result) {
        if (!result || error) {
          // self.layout('mainLayout');
          // self.render('notFound');
          self.redirect('notFound');
        } else {
          self.layout('landingLayout');
          self.render();
        }
      });
    }
    self.render('loading');
  }
});
Router.route('/settings', {
  name: 'settings',
  onBeforeAction: function () {
    if (!Meteor.loggingIn() && !Meteor.userId()) {
      this.redirect('home');
    }
    this.next();
  },
  action: function () {
    this.layout('mainLayout');
    this.render();
  }
});
Router.route('/notFound', {
  layoutTemplate: 'mainLayout'
});
<|endoftext|>


<commit_before>module('Language: be-nl', {
    setup: function() {
        numeral.language('be-nl');
    }
});

// Numbers -----------------------
test('Format Numbers', 22, function() {
    var tests = [
        [10000,'0,0.0000','10 000,0000'],
        [10000.23,'0,0','10 000'],
        [-10000,'0,0.0','-10 000,0'],
        [10000.1234,'0.000','10000,123'],
        [-10000,'(0,0.0000)','(10 000,0000)'],
        [-.23,'.00','-,23'],
        [-.23,'(.00)','(,23)'],
        [.23,'0.00000','0,23000'],
        [1230974,'0.0a','1,2 mln'],
        [1460,'0a','1k'],
        [-104000,'0a','-104k'],
        [0,'0o','0de'],
        [1,'0o','1ste'],
        [2,'0o','2de'],
        [8,'0o','8ste'],
        [19,'0o','19de'],
        [20,'0o','20ste'],
        [100,'0o','100ste'],
        [102,'0o','102de'],
        [108,'0o','108ste'],
        [109,'0o','109de'],
        [1,'0[.]0','1']
    ];

    for (var i = 0; i < tests.length; i++) {
        strictEqual(numeral(tests[i][0]).format(tests[i][1]), tests[i][2], tests[i][1]);
    }
});

// Currency -----------------------
test('Format Currency', 4, function() {
    var tests = [
        [1000.234,'$0,0.00','€ 1 000,23'],
        [-1000.234,'($0,0)','(€ 1 000)'],
        [-1000.234,'$0.00','-€ 1000,23'],
        [1230974,'($0.00a)','€ 1,23 mln']
    ];

    for (var i = 0; i < tests.length; i++) {
        strictEqual(numeral(tests[i][0]).format(tests[i][1]), tests[i][2], tests[i][1]);
    }
});

// Percentages -----------------------
test('Format Percentages', 4, function() {
    var tests = [
        [1,'0%','100%'],
        [.974878234,'0.000%','97,488%'],
        [-.43,'0%','-43%'],
        [.43,'(0.000%)','43,000%']
    ];

    for (var i = 0; i < tests.length; i++) {
        strictEqual(numeral(tests[i][0]).format(tests[i][1]), tests[i][2], tests[i][1]);
    }
});

// Unformat ------------------------
test('Unformat', 9, function() {
    var tests = [
        ['10 000,123',10000.123],
        ['(0,12345)',-.12345],
        ['(€ 1,23 mln)',-1230000],
        ['10k',10000],
        ['-10k',-10000],
        ['23e',23],
        ['€ 10 000,00',10000],
        ['-76%',-.76],
        ['2:23:57',8637]
    ];

    for (var i = 0; i < tests.length; i++) {
        strictEqual(numeral().unformat(tests[i][0]), tests[i][1], tests[i][0]);
    }
});
<commit_msg>Set zeroFormat to null before test.<commit_after>module('Language: be-nl', {
    setup: function() {
        numeral.language('be-nl');
        numeral.zeroFormat(null);
    }
});

// Numbers -----------------------
test('Format Numbers', 22, function() {
    var tests = [
        [10000,'0,0.0000','10 000,0000'],
        [10000.23,'0,0','10 000'],
        [-10000,'0,0.0','-10 000,0'],
        [10000.1234,'0.000','10000,123'],
        [-10000,'(0,0.0000)','(10 000,0000)'],
        [-.23,'.00','-,23'],
        [-.23,'(.00)','(,23)'],
        [.23,'0.00000','0,23000'],
        [1230974,'0.0a','1,2 mln'],
        [1460,'0a','1k'],
        [-104000,'0a','-104k'],
        [0,'0o','0de'],
        [1,'0o','1ste'],
        [2,'0o','2de'],
        [8,'0o','8ste'],
        [19,'0o','19de'],
        [20,'0o','20ste'],
        [100,'0o','100ste'],
        [102,'0o','102de'],
        [108,'0o','108ste'],
        [109,'0o','109de'],
        [1,'0[.]0','1']
    ];

    for (var i = 0; i < tests.length; i++) {
        strictEqual(numeral(tests[i][0]).format(tests[i][1]), tests[i][2], tests[i][1]);
    }
});

// Currency -----------------------
test('Format Currency', 4, function() {
    var tests = [
        [1000.234,'$0,0.00','€ 1 000,23'],
        [-1000.234,'($0,0)','(€ 1 000)'],
        [-1000.234,'$0.00','-€ 1000,23'],
        [1230974,'($0.00a)','€ 1,23 mln']
    ];

    for (var i = 0; i < tests.length; i++) {
        strictEqual(numeral(tests[i][0]).format(tests[i][1]), tests[i][2], tests[i][1]);
    }
});

// Percentages -----------------------
test('Format Percentages', 4, function() {
    var tests = [
        [1,'0%','100%'],
        [.974878234,'0.000%','97,488%'],
        [-.43,'0%','-43%'],
        [.43,'(0.000%)','43,000%']
    ];

    for (var i = 0; i < tests.length; i++) {
        strictEqual(numeral(tests[i][0]).format(tests[i][1]), tests[i][2], tests[i][1]);
    }
});

// Unformat ------------------------
test('Unformat', 9, function() {
    var tests = [
        ['10 000,123',10000.123],
        ['(0,12345)',-.12345],
        ['(€ 1,23 mln)',-1230000],
        ['10k',10000],
        ['-10k',-10000],
        ['23e',23],
        ['€ 10 000,00',10000],
        ['-76%',-.76],
        ['2:23:57',8637]
    ];

    for (var i = 0; i < tests.length; i++) {
        strictEqual(numeral().unformat(tests[i][0]), tests[i][1], tests[i][0]);
    }
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  ScrollView,
  Dimensions,
  Button,
  ActivityIndicator,
  Image,
  Modal,
  AlertIOS,
  TextInput,
  TouchableOpacity
} from 'react-native';
import Camera from 'react-native-camera';
import NavigationBar from 'react-native-navbar';

// PARENT

export default class FoodrFrontend extends Component {
  constructor() {
    super()
    this.state = {
      currentPage: 'IndexPage',
      previousPage: 'DefaultPage',
      foundProduct: {},
      foundProductSaved: false,
      userId: false, // false if not logged in
      searchTerm: ''
    }
    this.updateCurrentPage = this.updateCurrentPage.bind(this)
    this.searchProduct = this.searchProduct.bind(this)
    this.updateSearchTerm = this.updateSearchTerm.bind(this)
    this.saveSearch = this.saveSearch.bind(this)
  }

  searchProduct(upc) {
    this.updateCurrentPage('SearchingPage')

    // fetch('https://dbc-foodr-api.herokuapp.com/products/' + upc + "?user_id=" + this.state.userId)
    fetch('http://localhost:3000/products/' + upc + "?user_id=" + this.state.userId)
    .then((data) => data.json())
    .then((jsonData) => {
      this.setState({ foundProduct: jsonData })
      if (this.state.foundProduct.found) {
        this.setState({foundProductSaved: jsonData.search.is_saved})
        this.updateCurrentPage('ProductPage')
      } else {
        this.updateCurrentPage('NoResultsPage')
      }
    });
  }

  saveSearch(searchId) {
    if (this.state.userId) {
      fetch('http://localhost:3000/searches/' + searchId + '/save', {method: 'POST'})
      .then(data => data.json())
      .then(jsonData => {
        if (jsonData.save_successful) {
          this.setState({foundProductSaved: true});
          AlertIOS.alert('Product Saved!');
        } else {
          this.setState({foundProductSaved: false});
          AlertIOS.alert('Product was not saved.');
        }
      })
    } else {
      AlertIOS.alert('Please sign up or login to save an item.');
    }
  }

  updateCurrentPage(pageName) {
    this.setState({currentPage: pageName})
  }

  updateSearchTerm(searchTerm) {
    this.setState({searchTerm: searchTerm})
  }

  render() {
    const titleConfig = {
      title: 'FOODR',
    };

    const leftButtonConfig = {
      title: 'Profile',
      handler: () => this.updateCurrentPage('UserProfilePage'),
    };

    const rightButtonConfig = {
      title: 'Scan',
      handler: () => this.updateCurrentPage('CameraPage'),
    };

    switch(this.state.currentPage) {
      case 'IndexPage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
              rightButton={rightButtonConfig}
            />
            <IndexPage
              updateCurrentPage = {this.updateCurrentPage}
            />
          </View>
        )
      case 'SearchPage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
              rightButton={rightButtonConfig}
            />
            <ScrollView>
              <SearchPage
                searchProduct = {this.searchProduct}
                updateSearchTerm = {this.updateSearchTerm}
              />
            </ScrollView>
          </View>
        )
      case 'CameraPage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
            />
            <ScrollView>
              <CameraPage
                updateCurrentPage = {this.updateCurrentPage}
                searchProduct = {this.searchProduct}
                updateSearchTerm = {this.updateSearchTerm}
              />
            </ScrollView>
          </View>
        )
      case 'ProductPage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
              rightButton={rightButtonConfig}
            />
            <ScrollView>
              <ProductPage
                foundProduct = {this.state.foundProduct}
                foundProductSaved = {this.state.foundProductSaved}
                updateCurrentPage = {this.updateCurrentPage}
                saveSearch = {this.saveSearch}
              />
            </ScrollView>
        </View>
        )
      case 'NoResultsPage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
              rightButton={rightButtonConfig}
            />
            <NoResultsPage
              updateCurrentPage = {this.updateCurrentPage}
              searchTerm = {this.state.searchTerm}
              />
          </View>
        )
      case 'SearchingPage':
        return(
          <View style={styles.parentContainer}>
            <SearchingPage />
          </View>
        )
      case 'UserProfilePage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
              rightButton={rightButtonConfig}
            />
            <ScrollView>
              <UserProfilePage />
            </ScrollView>
          </View>
        )
      default:
        return(
          <DefaultPage />
        )
    }
  }
}

// CHILDREN

// VICTORIA

class CameraPage extends Component {
  constructor() {
    super()
    this.onBarCodeRead = this.onBarCodeRead.bind(this)
    this.onPressSearchButton = this.onPressSearchButton.bind(this)

    // for testing
    this.existingItem = this.existingItem.bind(this)
    this.nonExistingItem = this.nonExistingItem.bind(this)
  }

  onBarCodeRead(e) {
    this.props.updateSearchTerm('Product')
    this.props.searchProduct(e.data)
  }

  onPressSearchButton(){
    this.props.updateCurrentPage("SearchPage")
  }

  // for testing
  existingItem() {
    this.props.updateSearchTerm('Product')
    this.props.searchProduct('03077504')
  }

  nonExistingItem() {
    this.props.updateSearchTerm('Product')
    this.props.searchProduct('asdf')
  }

  render() {
    return(
      <View style={styles.body}>
        <Text style={styles.header}>Place Barcode in View</Text>
        <Camera
          ref={(cam) => {this.camera = cam;}}
          style={styles.cameraView}
          onBarCodeRead = {this.onBarCodeRead}
          aspect={Camera.constants.Aspect.fill}>
        </Camera>
        <Text style={styles.contentSmall}>The camera will automatically detect when a barcode is present</Text>

        <Text style={styles.contentSmall}>{"\n\n"}No item to scan?</Text>

        <TouchableOpacity>
          <Button
            title="Enter a Search Term"
            onPress={this.onPressSearchButton}
          />
          <Button
            title="Test: Existing Item"
            onPress={this.existingItem}
            color='red'
          />
          <Button
            title="Test: Nonexisting Item"
            onPress={this.nonExistingItem}
            color='red'
          />
        </TouchableOpacity>
      </View>
    );
  }
}

// TIFF

class ProductPage extends Component {
  constructor() {
    super()
    this.saveItem = this.saveItem.bind(this)
  }

  saveItem() {
    this.props.saveSearch(this.props.foundProduct.search.id);
  }

  scoreConverter() {
    let numberScore = this.props.foundProduct.product.score
      switch(numberScore) {
        case 5:
          return ('A');
        case 4:
          return ('B');
        case 3:
          return ('C');
        case 2:
          return ('D');
        case 1:
          return ('F');
        default:
          return ('Not Found');
      }
  }

  renderIngredientList() {
    return this.props.foundProduct.ingredients.map(ingredient =>
      <View style={styles.inlineContainer} key={ingredient.id}>
        { ingredient.is_natural ?
          <Image
            style={{width: 50, height: 50}}
            source={{uri: "https://image.flaticon.com/icons/png/512/32/32070.png"}}
          />
          :
          <Image
            style={{width: 50, height: 50}}
            source={{uri: "https://d30y9cdsu7xlg0.cloudfront.net/png/909435-200.png"}}
          />
         }

        <IngredientModal ingredient = {ingredient} />
      </View>
    );
  }

  render() {
    return(
      <View style={styles.body}>
        <Image
          style={{width: 375, height: 200}}
          source={{uri: this.props.foundProduct.product.img_url}}
        />
        <Text style={styles.header}>{this.props.foundProduct.product.name}</Text>
        <Text>Score: {this.scoreConverter()}</Text>

        {this.props.foundProductSaved ?
          <Text>Product is Saved</Text>
          :
          <Button
            onPress={this.saveItem}
            title="Save Product"
          />
        }

        <Text style={styles.header}>Ingredients:</Text>
        {this.renderIngredientList()}

      </View>
    )
  }
}

class IngredientModal extends Component {
  constructor() {
    super()
    this.state = {
      modalVisible: false
    }
    this.setModalVisible = this.setModalVisible.bind(this)
  }

  setModalVisible(visible) {
    this.setState({modalVisible: visible});
  }

  render() {
    return (
      <View>
        <Modal
          animationType={"slide"}
          transparent={false}
          visible={this.state.modalVisible}
        >
          <ScrollView style={{marginTop: 22}}>
            <Image
              style={{width: 375, height: 200}}
              source={{uri: this.props.ingredient.img_url}}
            />

            <Text style={styles.header}>{this.props.ingredient.name}</Text>
            <Text style={styles.contentSmall}>{this.props.ingredient.description}</Text>

            <TouchableOpacity>
              <Button
                onPress={() => {this.setModalVisible(!this.state.modalVisible)}}
                title="Back to Product"
              />
            </TouchableOpacity>
          </ScrollView>
        </Modal>

        <TouchableOpacity>
          <Button
            onPress={() => {this.setModalVisible(true)}}
            title={this.props.ingredient.name}
          />
        </TouchableOpacity>
      </View>
    );
  }
}

// KANAN

class NoResultsPage extends Component {
  constructor(){
    super()
    this.searchAgain = this.searchAgain.bind(this)
    this.scanAgain = this.scanAgain.bind(this)
  }

  searchAgain(){
    this.props.updateCurrentPage("SearchPage")
  }

  scanAgain(){
    this.props.updateCurrentPage("CameraPage")
  }

  render() {
    return (
      <View style={styles.centerContainer}>
        <Text style={styles.header}>{this.props.searchTerm} was not found</Text>
        <Text style={styles.contentSmall}>Would you like to try another product?</Text>
        <TouchableOpacity>
          <Button
           title="Scan a Product"
           onPress={this.scanAgain}
          />
        </TouchableOpacity>

        <Text>or</Text>

        <TouchableOpacity>
          <Button
           title="Enter a Search Term"
           onPress={this.searchAgain}
          />
        </TouchableOpacity>
      </View>
    );
  }
}

// KANAN

class SearchPage extends Component {
  constructor(){
    super();
    this.state = {
      text: ''
    };
    this.startSearch = this.startSearch.bind(this)
  }

  startSearch() {
    this.props.updateSearchTerm(this.state.text)
    this.props.searchProduct(this.state.text)
  }

  render() {
    return (
      <View style={styles.body}>
        <Text style={styles.header}>Search for a Product:</Text>
        <TextInput
          placeholder="Enter a Product Name or UPC"
          placeholderTextColor='#949799'
          returnKeyType="search"
          keyboardType="default"
          style={styles.input}
          onChangeText={(text) => this.setState({text})}
          onSubmitEditing={this.startSearch}
        />
        <TouchableOpacity>
          <Button title="Search" onPress={this.startSearch}/>
        </TouchableOpacity>
      </View>
    )
  }
}

// KANAN

class IndexPage extends Component {
  constructor(){
    super()
    this._onPressSearchButton = this._onPressSearchButton.bind(this)
    this._onPressScanButton = this._onPressScanButton.bind(this)
    this._onPressSignUpButton = this._onPressSignUpButton.bind(this)
    this._onPressSignInButton = this._onPressSignInButton.bind(this)
  }

  _onPressSearchButton(){
    this.props.updateCurrentPage("SearchPage")
  }

  _onPressScanButton(){
    this.props.updateCurrentPage("CameraPage")
  }

  _onPressSignUpButton(){
    this.props.updateCurrentPage("IndexPage")
  }

  _onPressSignInButton(){
    this.props.updateCurrentPage("IndexPage")
  }

  render() {
    return (
      <View style={styles.centerContainer}>
        <TouchableOpacity>
          <Button title="Scan Product" onPress={this._onPressScanButton} />
        </TouchableOpacity>
        <TouchableOpacity>
          <Button title="Search Product" onPress={this._onPressSearchButton} />
        </TouchableOpacity>
        <TouchableOpacity>
          <Button onPress={this._onPressSignUpButton} title="Sign Up" />
        </TouchableOpacity>
        <TouchableOpacity>
          <Button onPress={this._onPressSignInButton} title="Sign In" />
        </TouchableOpacity>
      </View>
    );
  }
}

// DONE

class SearchingPage extends Component {
  render() {
    return(
      <View style={styles.centerContainer}>
        <ActivityIndicator
          animating = {true}
          size = 'large'
          style={{marginBottom: 20}}
        />
        <Text>Searching...</Text>
      </View>
    );
  }
}

// FOR TESTING

class UserProfilePage extends Component {
  render() {
    return(
      <View style={styles.body}>
        <Text style={styles.header}>User Profile Page</Text>
        <Text>This is where the users info will go.</Text>
      </View>
    );
  }
}

class DefaultPage extends Component {
  render() {
    return(
      <View style={styles.body}>
        <Text style={styles.header}>Default Page</Text>
        <Text>The case statement hit default</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  parentContainer: {
    flex: 1,
    backgroundColor: '#F5FCFF',
  },
  inlineContainer: {
    flexWrap: 'wrap',
    flexDirection: 'row',
  },
  centerContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  body: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  input: {
    height: 40,
    width: 300,
    borderRadius: 10,
    margin: 10,
    textAlign: 'center',
    borderColor: 'gray',
    borderWidth: 1,
  },
  header: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  contentSmall: {
    textAlign: 'center',
    margin: 10,
  },
  cameraView: {
    height: 300,
    width: '100%',
  },
  navbar: {
    justifyContent: 'space-around',
    width: '100%',
    backgroundColor: '#EAF1F4',
  },
});

AppRegistry.registerComponent('FoodrFrontend', () => FoodrFrontend);
<commit_msg>Remove previousPage state<commit_after>import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  ScrollView,
  Dimensions,
  Button,
  ActivityIndicator,
  Image,
  Modal,
  AlertIOS,
  TextInput,
  TouchableOpacity
} from 'react-native';
import Camera from 'react-native-camera';
import NavigationBar from 'react-native-navbar';

// PARENT

export default class FoodrFrontend extends Component {
  constructor() {
    super()
    this.state = {
      currentPage: 'IndexPage',
      foundProduct: {},
      foundProductSaved: false,
      userId: false, // false if not logged in
      searchTerm: ''
    }
    this.updateCurrentPage = this.updateCurrentPage.bind(this)
    this.searchProduct = this.searchProduct.bind(this)
    this.updateSearchTerm = this.updateSearchTerm.bind(this)
    this.saveSearch = this.saveSearch.bind(this)
  }

  searchProduct(upc) {
    this.updateCurrentPage('SearchingPage')

    // fetch('https://dbc-foodr-api.herokuapp.com/products/' + upc + "?user_id=" + this.state.userId)
    fetch('http://localhost:3000/products/' + upc + "?user_id=" + this.state.userId)
    .then((data) => data.json())
    .then((jsonData) => {
      this.setState({ foundProduct: jsonData })
      if (this.state.foundProduct.found) {
        this.setState({foundProductSaved: jsonData.search.is_saved})
        this.updateCurrentPage('ProductPage')
      } else {
        this.updateCurrentPage('NoResultsPage')
      }
    });
  }

  saveSearch(searchId) {
    if (this.state.userId) {
      fetch('http://localhost:3000/searches/' + searchId + '/save', {method: 'POST'})
      .then(data => data.json())
      .then(jsonData => {
        if (jsonData.save_successful) {
          this.setState({foundProductSaved: true});
          AlertIOS.alert('Product Saved!');
        } else {
          this.setState({foundProductSaved: false});
          AlertIOS.alert('Product was not saved.');
        }
      })
    } else {
      AlertIOS.alert('Please sign up or login to save an item.');
    }
  }

  updateCurrentPage(pageName) {
    this.setState({currentPage: pageName})
  }

  updateSearchTerm(searchTerm) {
    this.setState({searchTerm: searchTerm})
  }

  render() {
    const titleConfig = {
      title: 'FOODR',
    };

    const leftButtonConfig = {
      title: 'Profile',
      handler: () => this.updateCurrentPage('UserProfilePage'),
    };

    const rightButtonConfig = {
      title: 'Scan',
      handler: () => this.updateCurrentPage('CameraPage'),
    };

    switch(this.state.currentPage) {
      case 'IndexPage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
              rightButton={rightButtonConfig}
            />
            <IndexPage
              updateCurrentPage = {this.updateCurrentPage}
            />
          </View>
        )
      case 'SearchPage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
              rightButton={rightButtonConfig}
            />
            <ScrollView>
              <SearchPage
                searchProduct = {this.searchProduct}
                updateSearchTerm = {this.updateSearchTerm}
              />
            </ScrollView>
          </View>
        )
      case 'CameraPage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
            />
            <ScrollView>
              <CameraPage
                updateCurrentPage = {this.updateCurrentPage}
                searchProduct = {this.searchProduct}
                updateSearchTerm = {this.updateSearchTerm}
              />
            </ScrollView>
          </View>
        )
      case 'ProductPage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
              rightButton={rightButtonConfig}
            />
            <ScrollView>
              <ProductPage
                foundProduct = {this.state.foundProduct}
                foundProductSaved = {this.state.foundProductSaved}
                updateCurrentPage = {this.updateCurrentPage}
                saveSearch = {this.saveSearch}
              />
            </ScrollView>
        </View>
        )
      case 'NoResultsPage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
              rightButton={rightButtonConfig}
            />
            <NoResultsPage
              updateCurrentPage = {this.updateCurrentPage}
              searchTerm = {this.state.searchTerm}
              />
          </View>
        )
      case 'SearchingPage':
        return(
          <View style={styles.parentContainer}>
            <SearchingPage />
          </View>
        )
      case 'UserProfilePage':
        return(
          <View style={styles.parentContainer}>
            <NavigationBar
              style={styles.navbar}
              leftButton={leftButtonConfig}
              title={titleConfig}
              rightButton={rightButtonConfig}
            />
            <ScrollView>
              <UserProfilePage />
            </ScrollView>
          </View>
        )
      default:
        return(
          <DefaultPage />
        )
    }
  }
}

// CHILDREN

// VICTORIA

class CameraPage extends Component {
  constructor() {
    super()
    this.onBarCodeRead = this.onBarCodeRead.bind(this)
    this.onPressSearchButton = this.onPressSearchButton.bind(this)

    // for testing
    this.existingItem = this.existingItem.bind(this)
    this.nonExistingItem = this.nonExistingItem.bind(this)
  }

  onBarCodeRead(e) {
    this.props.updateSearchTerm('Product')
    this.props.searchProduct(e.data)
  }

  onPressSearchButton(){
    this.props.updateCurrentPage("SearchPage")
  }

  // for testing
  existingItem() {
    this.props.updateSearchTerm('Product')
    this.props.searchProduct('03077504')
  }

  nonExistingItem() {
    this.props.updateSearchTerm('Product')
    this.props.searchProduct('asdf')
  }

  render() {
    return(
      <View style={styles.body}>
        <Text style={styles.header}>Place Barcode in View</Text>
        <Camera
          ref={(cam) => {this.camera = cam;}}
          style={styles.cameraView}
          onBarCodeRead = {this.onBarCodeRead}
          aspect={Camera.constants.Aspect.fill}>
        </Camera>
        <Text style={styles.contentSmall}>The camera will automatically detect when a barcode is present</Text>

        <Text style={styles.contentSmall}>{"\n\n"}No item to scan?</Text>

        <TouchableOpacity>
          <Button
            title="Enter a Search Term"
            onPress={this.onPressSearchButton}
          />
          <Button
            title="Test: Existing Item"
            onPress={this.existingItem}
            color='red'
          />
          <Button
            title="Test: Nonexisting Item"
            onPress={this.nonExistingItem}
            color='red'
          />
        </TouchableOpacity>
      </View>
    );
  }
}

// TIFF

class ProductPage extends Component {
  constructor() {
    super()
    this.saveItem = this.saveItem.bind(this)
  }

  saveItem() {
    this.props.saveSearch(this.props.foundProduct.search.id);
  }

  scoreConverter() {
    let numberScore = this.props.foundProduct.product.score
      switch(numberScore) {
        case 5:
          return ('A');
        case 4:
          return ('B');
        case 3:
          return ('C');
        case 2:
          return ('D');
        case 1:
          return ('F');
        default:
          return ('Not Found');
      }
  }

  renderIngredientList() {
    return this.props.foundProduct.ingredients.map(ingredient =>
      <View style={styles.inlineContainer} key={ingredient.id}>
        { ingredient.is_natural ?
          <Image
            style={{width: 50, height: 50}}
            source={{uri: "https://image.flaticon.com/icons/png/512/32/32070.png"}}
          />
          :
          <Image
            style={{width: 50, height: 50}}
            source={{uri: "https://d30y9cdsu7xlg0.cloudfront.net/png/909435-200.png"}}
          />
         }

        <IngredientModal ingredient = {ingredient} />
      </View>
    );
  }

  render() {
    return(
      <View style={styles.body}>
        <Image
          style={{width: 375, height: 200}}
          source={{uri: this.props.foundProduct.product.img_url}}
        />
        <Text style={styles.header}>{this.props.foundProduct.product.name}</Text>
        <Text>Score: {this.scoreConverter()}</Text>

        {this.props.foundProductSaved ?
          <Text>Product is Saved</Text>
          :
          <Button
            onPress={this.saveItem}
            title="Save Product"
          />
        }

        <Text style={styles.header}>Ingredients:</Text>
        {this.renderIngredientList()}

      </View>
    )
  }
}

class IngredientModal extends Component {
  constructor() {
    super()
    this.state = {
      modalVisible: false
    }
    this.setModalVisible = this.setModalVisible.bind(this)
  }

  setModalVisible(visible) {
    this.setState({modalVisible: visible});
  }

  render() {
    return (
      <View>
        <Modal
          animationType={"slide"}
          transparent={false}
          visible={this.state.modalVisible}
        >
          <ScrollView style={{marginTop: 22}}>
            <Image
              style={{width: 375, height: 200}}
              source={{uri: this.props.ingredient.img_url}}
            />

            <Text style={styles.header}>{this.props.ingredient.name}</Text>
            <Text style={styles.contentSmall}>{this.props.ingredient.description}</Text>

            <TouchableOpacity>
              <Button
                onPress={() => {this.setModalVisible(!this.state.modalVisible)}}
                title="Back to Product"
              />
            </TouchableOpacity>
          </ScrollView>
        </Modal>

        <TouchableOpacity>
          <Button
            onPress={() => {this.setModalVisible(true)}}
            title={this.props.ingredient.name}
          />
        </TouchableOpacity>
      </View>
    );
  }
}

// KANAN

class NoResultsPage extends Component {
  constructor(){
    super()
    this.searchAgain = this.searchAgain.bind(this)
    this.scanAgain = this.scanAgain.bind(this)
  }

  searchAgain(){
    this.props.updateCurrentPage("SearchPage")
  }

  scanAgain(){
    this.props.updateCurrentPage("CameraPage")
  }

  render() {
    return (
      <View style={styles.centerContainer}>
        <Text style={styles.header}>{this.props.searchTerm} was not found</Text>
        <Text style={styles.contentSmall}>Would you like to try another product?</Text>
        <TouchableOpacity>
          <Button
           title="Scan a Product"
           onPress={this.scanAgain}
          />
        </TouchableOpacity>

        <Text>or</Text>

        <TouchableOpacity>
          <Button
           title="Enter a Search Term"
           onPress={this.searchAgain}
          />
        </TouchableOpacity>
      </View>
    );
  }
}

// KANAN

class SearchPage extends Component {
  constructor(){
    super();
    this.state = {
      text: ''
    };
    this.startSearch = this.startSearch.bind(this)
  }

  startSearch() {
    this.props.updateSearchTerm(this.state.text)
    this.props.searchProduct(this.state.text)
  }

  render() {
    return (
      <View style={styles.body}>
        <Text style={styles.header}>Search for a Product:</Text>
        <TextInput
          placeholder="Enter a Product Name or UPC"
          placeholderTextColor='#949799'
          returnKeyType="search"
          keyboardType="default"
          style={styles.input}
          onChangeText={(text) => this.setState({text})}
          onSubmitEditing={this.startSearch}
        />
        <TouchableOpacity>
          <Button title="Search" onPress={this.startSearch}/>
        </TouchableOpacity>
      </View>
    )
  }
}

// KANAN

class IndexPage extends Component {
  constructor(){
    super()
    this._onPressSearchButton = this._onPressSearchButton.bind(this)
    this._onPressScanButton = this._onPressScanButton.bind(this)
    this._onPressSignUpButton = this._onPressSignUpButton.bind(this)
    this._onPressSignInButton = this._onPressSignInButton.bind(this)
  }

  _onPressSearchButton(){
    this.props.updateCurrentPage("SearchPage")
  }

  _onPressScanButton(){
    this.props.updateCurrentPage("CameraPage")
  }

  _onPressSignUpButton(){
    this.props.updateCurrentPage("IndexPage")
  }

  _onPressSignInButton(){
    this.props.updateCurrentPage("IndexPage")
  }

  render() {
    return (
      <View style={styles.centerContainer}>
        <TouchableOpacity>
          <Button title="Scan Product" onPress={this._onPressScanButton} />
        </TouchableOpacity>
        <TouchableOpacity>
          <Button title="Search Product" onPress={this._onPressSearchButton} />
        </TouchableOpacity>
        <TouchableOpacity>
          <Button onPress={this._onPressSignUpButton} title="Sign Up" />
        </TouchableOpacity>
        <TouchableOpacity>
          <Button onPress={this._onPressSignInButton} title="Sign In" />
        </TouchableOpacity>
      </View>
    );
  }
}

// DONE

class SearchingPage extends Component {
  render() {
    return(
      <View style={styles.centerContainer}>
        <ActivityIndicator
          animating = {true}
          size = 'large'
          style={{marginBottom: 20}}
        />
        <Text>Searching...</Text>
      </View>
    );
  }
}

// FOR TESTING

class UserProfilePage extends Component {
  render() {
    return(
      <View style={styles.body}>
        <Text style={styles.header}>User Profile Page</Text>
        <Text>This is where the users info will go.</Text>
      </View>
    );
  }
}

class DefaultPage extends Component {
  render() {
    return(
      <View style={styles.body}>
        <Text style={styles.header}>Default Page</Text>
        <Text>The case statement hit default</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  parentContainer: {
    flex: 1,
    backgroundColor: '#F5FCFF',
  },
  inlineContainer: {
    flexWrap: 'wrap',
    flexDirection: 'row',
  },
  centerContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  body: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  input: {
    height: 40,
    width: 300,
    borderRadius: 10,
    margin: 10,
    textAlign: 'center',
    borderColor: 'gray',
    borderWidth: 1,
  },
  header: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  contentSmall: {
    textAlign: 'center',
    margin: 10,
  },
  cameraView: {
    height: 300,
    width: '100%',
  },
  navbar: {
    justifyContent: 'space-around',
    width: '100%',
    backgroundColor: '#EAF1F4',
  },
});

AppRegistry.registerComponent('FoodrFrontend', () => FoodrFrontend);
<|endoftext|>


<commit_before>var estraverse = require("estraverse");
var traverse   = require("./traverse");
var esprima    = require("esprima");
var path       = require("path");
var fs         = require("fs");
var _          = require("lodash");

_.each(esprima.Syntax, function (name) {
  estraverse.VisitorKeys[name] = estraverse.VisitorKeys[name] || [];
});

exports.parse = function (code, opts) {
  opts = _.defaults(opts || {}, {
    comment: true,
    tokens:  true,
    range:   true,
    loc:     true
  });

  code = [].concat(code).join("");

  try {
    var tree = esprima.parse(code, opts);

    if (tree.tokens && tree.comments) {
      estraverse.attachComments(tree, tree.comments, tree.tokens);
    }

    return tree;
  } catch (err) {
    if (err.lineNumber) {
      var frame = exports.codeFrame(code, err.lineNumber, err.column);
      err.message = err.message + frame;
    }
    throw err;
  }
};

exports.canCompile = function (filename) {
  return path.extname(filename) === ".js";
};

exports.sourceMapToComment = function (map) {
  var json = JSON.stringify(map);
  var base64 = new Buffer(json).toString("base64");
  return "//# sourceMappingURL=data:application/json;base64," + base64;
};

exports.pushMutatorMap = function (mutatorMap, key, kind, method) {
  var map = mutatorMap[key] = mutatorMap[key] || {};
  if (map[kind]) {
    throw new Error("a " + kind + " already exists for this property");
  } else {
    map[kind] = method;
  }
};

exports.buildDefineProperties = function (mutatorMap, keyNode) {
  var objExpr = {
    type: "ObjectExpression",
    properties: []
  };

  _.each(mutatorMap, function (map, key) {
    var mapNode = {
      type: "ObjectExpression",
      properties: []
    };

    var propNode = {
      type: "Property",
      key: {
        type: "Identifier",
        name: key
      },
      value: mapNode,
      kind: "init"
    };

    _.each(map, function (methodNode, type) {
      if (methodNode.type === "MethodDefinition") methodNode = methodNode.value;
      mapNode.properties.push({
        type: "Property",
        key: {
          type: "Identifier",
          name: type
        },
        value: methodNode,
        kind: "init"
      });
    });

    objExpr.properties.push(propNode);
  });

  return exports.template("object-define-properties", {
    OBJECT: keyNode,
    PROPS: objExpr
  }, true);
};

exports.template = function (name, nodes, keepExpression) {
  var template = _.cloneDeep(exports.templates[name]);

  if (!_.isEmpty(nodes)) {
    traverse.replace(template, function (node) {
      if (node.type === "Identifier" && _.has(nodes, node.name)) {
        var newNode = nodes[node.name];
        if (_.isString(newNode)) {
          node.name = newNode;
        } else {
          return newNode;
        }
      }
    });
  }

  var normaliseNode = function (node) {
    if (!keepExpression && node.type === "ExpressionStatement") {
      return node.expression;
    } else {
      return node;
    }
  };

  var body = template.body;

  if (body.length <= 1) {
    return normaliseNode(body[0]);
  } else {
    return body.map(normaliseNode);
  }
};

exports.codeFrame = function (lines, lineNumber, colNumber) {
  if (!lineNumber) return "";

  colNumber = Math.max(colNumber, 0);

  lines = lines.split("\n");
  var start = Math.max(lineNumber - 3, 0);
  var end   = Math.min(lines.length, lineNumber + 3);
  var width = (end + "").length;

  return "\n" + lines.slice(start, end).map(function (line, i) {
    var curr = i + start + 1;

    var gutter = curr === lineNumber ? "> " : "  ";

    var sep = curr + exports.repeat(width + 1);
    gutter += sep + "| ";

    var str = gutter + line;

    if (colNumber && curr === lineNumber) {
      str += "\n";
      str += exports.repeat(gutter.length - 2);
      str += "|" + exports.repeat(colNumber) + "^";
    }

    return str;
  }).join("\n");
};

exports.repeat = function (width, cha) {
  cha = cha || " ";
  return new Array(width + 1).join(cha);
};

var templatesCacheLoc = __dirname + "/../../templates.json";

if (fs.existsSync(templatesCacheLoc)) {
  exports.templates = require(templatesCacheLoc);
} else {
  exports.templates = {};

  var templatesLoc = __dirname + "/templates";

  _.each(fs.readdirSync(templatesLoc), function (name) {
    var key = path.basename(name, path.extname(name));

    var code = fs.readFileSync(templatesLoc + "/" + name, "utf8");
    exports.templates[key] = exports.parse(code, {
      comment: false,
      tokens:  false,
      range:   false,
      loc:     false
    });
  });
}
<commit_msg>add util.errorWithNode method that returns an error with mapped location properties<commit_after>var estraverse = require("estraverse");
var traverse   = require("./traverse");
var esprima    = require("esprima");
var path       = require("path");
var fs         = require("fs");
var _          = require("lodash");

_.each(esprima.Syntax, function (name) {
  estraverse.VisitorKeys[name] = estraverse.VisitorKeys[name] || [];
});

exports.parse = function (code, opts) {
  opts = _.defaults(opts || {}, {
    comment: true,
    tokens:  true,
    range:   true,
    loc:     true
  });

  code = [].concat(code).join("");

  try {
    var tree = esprima.parse(code, opts);

    if (tree.tokens && tree.comments) {
      estraverse.attachComments(tree, tree.comments, tree.tokens);
    }

    return tree;
  } catch (err) {
    if (err.lineNumber) {
      var frame = exports.codeFrame(code, err.lineNumber, err.column);
      err.message = err.message + frame;
    }
    throw err;
  }
};

exports.errorWithNode = function (node, msg) {
  var err = new Error(msg);
  err.lineNumber = node.loc.start.line;
  err.column = node.loc.start.column;
  return err;
};

exports.canCompile = function (filename) {
  return path.extname(filename) === ".js";
};

exports.sourceMapToComment = function (map) {
  var json = JSON.stringify(map);
  var base64 = new Buffer(json).toString("base64");
  return "//# sourceMappingURL=data:application/json;base64," + base64;
};

exports.pushMutatorMap = function (mutatorMap, key, kind, method) {
  var map = mutatorMap[key] = mutatorMap[key] || {};
  if (map[kind]) {
    throw new Error("a " + kind + " already exists for this property");
  } else {
    map[kind] = method;
  }
};

exports.buildDefineProperties = function (mutatorMap, keyNode) {
  var objExpr = {
    type: "ObjectExpression",
    properties: []
  };

  _.each(mutatorMap, function (map, key) {
    var mapNode = {
      type: "ObjectExpression",
      properties: []
    };

    var propNode = {
      type: "Property",
      key: {
        type: "Identifier",
        name: key
      },
      value: mapNode,
      kind: "init"
    };

    _.each(map, function (methodNode, type) {
      if (methodNode.type === "MethodDefinition") methodNode = methodNode.value;
      mapNode.properties.push({
        type: "Property",
        key: {
          type: "Identifier",
          name: type
        },
        value: methodNode,
        kind: "init"
      });
    });

    objExpr.properties.push(propNode);
  });

  return exports.template("object-define-properties", {
    OBJECT: keyNode,
    PROPS: objExpr
  }, true);
};

exports.template = function (name, nodes, keepExpression) {
  var template = _.cloneDeep(exports.templates[name]);

  if (!_.isEmpty(nodes)) {
    traverse.replace(template, function (node) {
      if (node.type === "Identifier" && _.has(nodes, node.name)) {
        var newNode = nodes[node.name];
        if (_.isString(newNode)) {
          node.name = newNode;
        } else {
          return newNode;
        }
      }
    });
  }

  var normaliseNode = function (node) {
    if (!keepExpression && node.type === "ExpressionStatement") {
      return node.expression;
    } else {
      return node;
    }
  };

  var body = template.body;

  if (body.length <= 1) {
    return normaliseNode(body[0]);
  } else {
    return body.map(normaliseNode);
  }
};

exports.codeFrame = function (lines, lineNumber, colNumber) {
  if (!lineNumber) return "";

  colNumber = Math.max(colNumber, 0);

  lines = lines.split("\n");
  var start = Math.max(lineNumber - 3, 0);
  var end   = Math.min(lines.length, lineNumber + 3);
  var width = (end + "").length;

  return "\n" + lines.slice(start, end).map(function (line, i) {
    var curr = i + start + 1;

    var gutter = curr === lineNumber ? "> " : "  ";

    var sep = curr + exports.repeat(width + 1);
    gutter += sep + "| ";

    var str = gutter + line;

    if (colNumber && curr === lineNumber) {
      str += "\n";
      str += exports.repeat(gutter.length - 2);
      str += "|" + exports.repeat(colNumber) + "^";
    }

    return str;
  }).join("\n");
};

exports.repeat = function (width, cha) {
  cha = cha || " ";
  return new Array(width + 1).join(cha);
};

var templatesCacheLoc = __dirname + "/../../templates.json";

if (fs.existsSync(templatesCacheLoc)) {
  exports.templates = require(templatesCacheLoc);
} else {
  exports.templates = {};

  var templatesLoc = __dirname + "/templates";

  _.each(fs.readdirSync(templatesLoc), function (name) {
    var key = path.basename(name, path.extname(name));

    var code = fs.readFileSync(templatesLoc + "/" + name, "utf8");
    exports.templates[key] = exports.parse(code, {
      comment: false,
      tokens:  false,
      range:   false,
      loc:     false
    });
  });
}
<|endoftext|>


<commit_before>import { ShaderMaterial } from '../../../three/src/materials/ShaderMaterial.js';
import { ShaderLib } from '../../../three/src/renderers/shaders/ShaderLib.js';
import { UniformsUtils } from '../../../three/src/renderers/shaders/UniformsUtils.js';
import DEFAULT_VERTEX from '../../../three/src/renderers/shaders/ShaderChunk/default_vertex.glsl.js';
import DEFAULT_FRAGMENT from '../../../three/src/renderers/shaders/ShaderChunk/default_fragment.glsl.js';

import Shader from '../../core/3d/Shader.js';
// import THREEShader from '../shader/THREEShader.js';

export default class THREEShaderMaterial extends ShaderMaterial {
  constructor({
    type = '',
    vertex = undefined,
    fragment = undefined,
    vertexChunks = [],
    fragmentChunks = [],
    uniforms = {},
    ...options
  } = {}) {
    const shader = new Shader({
      vertex: vertex || (type ? ShaderLib[type].vertexShader : DEFAULT_VERTEX),
      fragment: fragment || (type ? ShaderLib[type].fragmentShader : DEFAULT_FRAGMENT),
      uniforms,
      vertexChunks,
      fragmentChunks,
    });

    const threeUniforms = {};
    for (const [key, value] of Object.entries(shader.uniforms)) {
      if (value.value !== undefined) {
        continue;
      }
      threeUniforms[key] = {
        value,
      };
    }

    super({
      fragmentShader: shader.fragment,
      vertexShader: shader.vertex,
      uniforms: {
        ...(type ? UniformsUtils.clone(ShaderLib[type].uniforms) : {}),
        ...threeUniforms,
      },
      ...options,
    });

    this.lights = /lambert|phong|standard/.test(type);

    if (this.envMap) {
      this.envMap = this.envMap;
    }

    for (const key of Object.keys(this.uniforms)) {
      Object.defineProperty(this, key, {
        configurable: true,
        get: function () {
          return this.uniforms[key].value;
        },
        set: function (value) {
          this.uniforms[key].value = value;
        },
      });
    }
  }

  // add({ vertexChunks, fragmentChunks, uniforms }) {
  //   this._shader.add({ vertexChunks, fragmentChunks, uniforms });

  //   this.fragmentShader = this._shader.fragmentShader;
  //   this.vertexShader = this._shader.vertexShader;

  //   for (const name in this._shader.uniforms) {
  //     const key = name; // Firefox fix
  //     this.uniforms[key] = this._shader.uniforms[key];

  //     let setter;
  //     if (key === 'envMap') {
  //       setter = function (value) {
  //         if (value && value.generateMipmaps && value.image) {
  //           this.maxMipLevel = Math.log2(Math.max(value.image.width, value.image.height));
  //         }
  //         this.uniforms[key].value = value;
  //       };
  //     } else {
  //       setter = function (value) {
  //         this.uniforms[key].value = value;
  //       };
  //     }

  //     Object.defineProperty(this, key, {
  //       configurable: true,
  //       get: function () {
  //         return this.uniforms[key].value;
  //       },
  //       set: setter,
  //     });
  //   }

  //   // if (["boneTexture", "boneTextureSize"].includes(key)) {
  //   //   continue;
  //   // }

  //   delete this.uniforms.boneTexture;
  //   delete this.uniforms.boneTextureSize;
  //   delete this.uniforms.bindMatrix;
  //   delete this.uniforms.bindMatrixInverse;

  //   this.needsUpdate = true;
  // }
}
<commit_msg>THREEShaderMaterial convert to webGL1 by defalut<commit_after>import { ShaderMaterial } from '../../../three/src/materials/ShaderMaterial.js';
import { ShaderLib } from '../../../three/src/renderers/shaders/ShaderLib.js';
import { UniformsUtils } from '../../../three/src/renderers/shaders/UniformsUtils.js';
import DEFAULT_VERTEX from '../../../three/src/renderers/shaders/ShaderChunk/default_vertex.glsl.js';
import DEFAULT_FRAGMENT from '../../../three/src/renderers/shaders/ShaderChunk/default_fragment.glsl.js';

import Shader from '../../core/3d/Shader.js';
// import THREEShader from '../shader/THREEShader.js';

const toWebGL1 = (source, type) => {
  source = source.replace(/#version.*?\n/g, '');
  source = source.replace(/\btexture\b/g, 'texture2D');
  if (type === 'vertex') {
    source = source.replace(/(^\s*)\bin\b/gm, '$1attribute');
    source = source.replace(/(^\s*)\bout\b/gm, '$1varying');
  } else {
    source = source.replace(/(^\s*)\bin\b/gm, '$1varying');
    const results = /out vec4 (.*?);/.exec(source);
    if (results) {
      const fragColorName = results[1];
      source = source.replace(/out.*?;/, '');
      source = source.replace(new RegExp(`\\b${fragColorName}\\b`, 'g'), 'gl_FragColor');
    }
  }
  return source;
};

export default class THREEShaderMaterial extends ShaderMaterial {
  constructor({
    type = '',
    vertex = undefined,
    fragment = undefined,
    vertexChunks = [],
    fragmentChunks = [],
    uniforms = {},
    ...options
  } = {}) {
    const shader = new Shader({
      vertex: vertex || (type ? ShaderLib[type].vertexShader : DEFAULT_VERTEX),
      fragment: fragment || (type ? ShaderLib[type].fragmentShader : DEFAULT_FRAGMENT),
      uniforms,
      vertexChunks,
      fragmentChunks,
    });

    const threeUniforms = {};
    for (const [key, value] of Object.entries(shader.uniforms)) {
      if (value.value !== undefined) {
        continue;
      }
      threeUniforms[key] = {
        value,
      };
    }

    super({
      fragmentShader: toWebGL1(shader.fragment, 'fragment'),
      vertexShader: toWebGL1(shader.vertex, 'vertex'),
      uniforms: {
        ...(type ? UniformsUtils.clone(ShaderLib[type].uniforms) : {}),
        ...threeUniforms,
      },
      ...options,
    });

    this.lights = /lambert|phong|standard/.test(type);

    for (const key of Object.keys(this.uniforms)) {
      Object.defineProperty(this, key, {
        configurable: true,
        get: function () {
          return this.uniforms[key].value;
        },
        set: function (value) {
          this.uniforms[key].value = value;
        },
      });
    }
  }

  clone() {
    const clone = super.clone();
    for (const key of Object.keys(clone.uniforms)) {
      Object.defineProperty(clone, key, {
        configurable: true,
        get: function () {
          return this.uniforms[key].value;
        },
        set: function (value) {
          this.uniforms[key].value = value;
        },
      });
    }
    return clone;
  }

  // add({ vertexChunks, fragmentChunks, uniforms }) {
  //   this._shader.add({ vertexChunks, fragmentChunks, uniforms });

  //   this.fragmentShader = this._shader.fragmentShader;
  //   this.vertexShader = this._shader.vertexShader;

  //   for (const name in this._shader.uniforms) {
  //     const key = name; // Firefox fix
  //     this.uniforms[key] = this._shader.uniforms[key];

  //     let setter;
  //     if (key === 'envMap') {
  //       setter = function (value) {
  //         if (value && value.generateMipmaps && value.image) {
  //           this.maxMipLevel = Math.log2(Math.max(value.image.width, value.image.height));
  //         }
  //         this.uniforms[key].value = value;
  //       };
  //     } else {
  //       setter = function (value) {
  //         this.uniforms[key].value = value;
  //       };
  //     }

  //     Object.defineProperty(this, key, {
  //       configurable: true,
  //       get: function () {
  //         return this.uniforms[key].value;
  //       },
  //       set: setter,
  //     });
  //   }

  //   // if (["boneTexture", "boneTextureSize"].includes(key)) {
  //   //   continue;
  //   // }

  //   delete this.uniforms.boneTexture;
  //   delete this.uniforms.boneTextureSize;
  //   delete this.uniforms.bindMatrix;
  //   delete this.uniforms.bindMatrixInverse;

  //   this.needsUpdate = true;
  // }
}
<|endoftext|>


<commit_before>/*
 * Graph general cash flow (balance over time)
 */

import { Map as map, List as list } from 'immutable';
import { formatCurrency } from '../../../../misc/format';
import { rgba } from '../../../../misc/color';
import {
    COLOR_BALANCE_ACTUAL, COLOR_BALANCE_PREDICTED, COLOR_BALANCE_STOCKS,
    COLOR_DARK, COLOR_TRANSLUCENT_LIGHT,
    FONT_GRAPH_KEY_SMALL
} from '../../../../misc/config';

import { connect } from 'react-redux';
import { aShowAllToggled } from '../../../../actions/graph.actions';
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import GraphCashFlow, { getFutureKey, getValuesWithTime } from './cash-flow';

function AfterCanvas({ showAll, onShowAll }) {
    const className = classNames('show-all', 'noselect', {
        noselect: true,
        enabled: showAll
    });

    const onClick = () => onShowAll();

    return
        {'Show all'}

    ;
}

AfterCanvas.propTypes = {
    showAll: PropTypes.bool.isRequired,
    onShowAll: PropTypes.func.isRequired
};

function drawFundsLine(dataFunds, ctx, drawCubicLine) {
    // plot funds data
    ctx.lineWidth = 2;
    drawCubicLine(
        dataFunds,
        [rgba(COLOR_BALANCE_STOCKS)],
        {
            fill: true,
            stroke: false,
            tension: 1
        }
    );
}

function drawTargets(targets, ctx) {
    ctx.beginPath();
    ctx.fillStyle = rgba(COLOR_TRANSLUCENT_LIGHT);
    ctx.fillRect(48, 70, 100, targets.size * 22 + 4);
    ctx.closePath();

    ctx.fillStyle = rgba(COLOR_DARK);
    ctx.font = FONT_GRAPH_KEY_SMALL;
    ctx.textBaseline = 'top';

    targets.forEach((target, key) => {
        const tag = target.get('tag');
        const value = formatCurrency(target.get('value'), {
            raw: true, noPence: true, abbreviate: true, precision: 0
        });

        const xPix = 50;
        const yPix = 72 + 22 * key;

        ctx.fillText(`${value} (${tag})`, xPix, yPix);
    });
}

function drawKeyActual(ctx) {
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = rgba(COLOR_BALANCE_ACTUAL);
    ctx.moveTo(50, 40);
    ctx.lineTo(74, 40);
    ctx.stroke();
    ctx.closePath();

    ctx.font = FONT_GRAPH_KEY_SMALL;
    ctx.textBaseline = 'middle';
    ctx.fillStyle = rgba(COLOR_DARK);
    ctx.fillText('Actual', 78, 40);
}
function drawKeyPredicted(ctx) {
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = rgba(COLOR_BALANCE_PREDICTED);
    ctx.moveTo(130, 40);
    ctx.lineTo(154, 40);
    ctx.stroke();
    ctx.closePath();
    ctx.fillText('Predicted', 158, 40);
}
function drawKeyFunds(ctx) {
    ctx.fillText('Stocks', 78, 57);
    ctx.fillStyle = rgba(COLOR_BALANCE_STOCKS);
    ctx.fillRect(50, 54, 24, 6);
}
function drawKey(ctx) {
    drawKeyActual(ctx);
    drawKeyPredicted(ctx);
    drawKeyFunds(ctx);
}

function onDraw({ targets, data: { dataBalance, dataFunds } }, { ctx }, { drawCubicLine }) {
    // plot past + future predicted data
    if (!(dataBalance && dataFunds)) {
        return;
    }

    ctx.lineWidth = 2;
    drawCubicLine(dataBalance, [
        rgba(COLOR_BALANCE_ACTUAL), rgba(COLOR_BALANCE_PREDICTED)
    ]);

    // plot past + future predicted ISA stock value
    drawFundsLine(dataFunds, ctx, drawCubicLine);

    drawTargets(targets, ctx);

    drawKey(ctx);
}

function getRanges(dataBalance) {
    const dataY = dataBalance.map(item => item.last());
    const dataX = dataBalance.map(item => item.first());

    const minYValue = dataY.min();
    const minY = Math.min(0, minYValue);
    const maxY = dataY.max();
    const minX = dataX.min();
    const maxX = dataX.max();

    return { minY, maxY, minX, maxX };
}

function processData({ cost, showAll, ...props }) {
    let oldOffset = 0;

    let balance = cost.get('balanceWithPredicted');
    let funds = cost.get('funds');

    if (showAll) {
        oldOffset = cost.get('old').size;
        balance = cost.get('old').concat(balance);
        funds = cost.get('fundsOld').concat(funds);
    }

    const futureKey = oldOffset + getFutureKey(props);

    const dataBalance = getValuesWithTime(balance, { oldOffset, ...props });

    const dataFunds = funds.map((value, key) => list([
        dataBalance.getIn([key, 0]),
        value
    ]));

    const ranges = getRanges(dataBalance);

    const colorTransition = [futureKey - 1];

    return {
        oldOffset,
        ...ranges,
        colorTransition,
        data: { dataBalance, dataFunds }
    };
}

function GraphBalance(props) {
    const after = <AfterCanvas {...props} />;

    return <GraphCashFlow
        title="Balance"
        after={after}
        onDraw={onDraw}
        breakAtToday={true}
        {...processData(props)}
        {...props}
    />;
}

GraphBalance.propTypes = {
    cost: PropTypes.instanceOf(map).isRequired,
    showAll: PropTypes.bool.isRequired,
    targets: PropTypes.instanceOf(list).isRequired
};

const mapStateToProps = state => ({
    currentYearMonth: state.getIn(['pages', 'overview', 'data', 'currentYearMonth']),
    startYearMonth: state.getIn(['pages', 'overview', 'data', 'startYearMonth']),
    cost: state.getIn(['pages', 'overview', 'data', 'cost']),
    showAll: state.getIn(['other', 'showAllBalanceGraph']),
    targets: state.getIn(['pages', 'overview', 'data', 'targets'])
});

const mapDispatchToProps = dispatch => ({
    onShowAll: () => dispatch(aShowAllToggled())
});

export default connect(mapStateToProps, mapDispatchToProps)(GraphBalance);

<commit_msg>Don't use today break on balance graph<commit_after>/*
 * Graph general cash flow (balance over time)
 */

import { Map as map, List as list } from 'immutable';
import { formatCurrency } from '../../../../misc/format';
import { rgba } from '../../../../misc/color';
import {
    COLOR_BALANCE_ACTUAL, COLOR_BALANCE_PREDICTED, COLOR_BALANCE_STOCKS,
    COLOR_DARK, COLOR_TRANSLUCENT_LIGHT,
    FONT_GRAPH_KEY_SMALL
} from '../../../../misc/config';

import { connect } from 'react-redux';
import { aShowAllToggled } from '../../../../actions/graph.actions';
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import GraphCashFlow, { getFutureKey, getValuesWithTime } from './cash-flow';

function AfterCanvas({ showAll, onShowAll }) {
    const className = classNames('show-all', 'noselect', {
        noselect: true,
        enabled: showAll
    });

    const onClick = () => onShowAll();

    return
        {'Show all'}

    ;
}

AfterCanvas.propTypes = {
    showAll: PropTypes.bool.isRequired,
    onShowAll: PropTypes.func.isRequired
};

function drawFundsLine(dataFunds, ctx, drawCubicLine) {
    // plot funds data
    ctx.lineWidth = 2;
    drawCubicLine(
        dataFunds,
        [rgba(COLOR_BALANCE_STOCKS)],
        {
            fill: true,
            stroke: false,
            tension: 1
        }
    );
}

function drawTargets(targets, ctx) {
    ctx.beginPath();
    ctx.fillStyle = rgba(COLOR_TRANSLUCENT_LIGHT);
    ctx.fillRect(48, 70, 100, targets.size * 22 + 4);
    ctx.closePath();

    ctx.fillStyle = rgba(COLOR_DARK);
    ctx.font = FONT_GRAPH_KEY_SMALL;
    ctx.textBaseline = 'top';

    targets.forEach((target, key) => {
        const tag = target.get('tag');
        const value = formatCurrency(target.get('value'), {
            raw: true, noPence: true, abbreviate: true, precision: 0
        });

        const xPix = 50;
        const yPix = 72 + 22 * key;

        ctx.fillText(`${value} (${tag})`, xPix, yPix);
    });
}

function drawKeyActual(ctx) {
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = rgba(COLOR_BALANCE_ACTUAL);
    ctx.moveTo(50, 40);
    ctx.lineTo(74, 40);
    ctx.stroke();
    ctx.closePath();

    ctx.font = FONT_GRAPH_KEY_SMALL;
    ctx.textBaseline = 'middle';
    ctx.fillStyle = rgba(COLOR_DARK);
    ctx.fillText('Actual', 78, 40);
}
function drawKeyPredicted(ctx) {
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = rgba(COLOR_BALANCE_PREDICTED);
    ctx.moveTo(130, 40);
    ctx.lineTo(154, 40);
    ctx.stroke();
    ctx.closePath();
    ctx.fillText('Predicted', 158, 40);
}
function drawKeyFunds(ctx) {
    ctx.fillText('Stocks', 78, 57);
    ctx.fillStyle = rgba(COLOR_BALANCE_STOCKS);
    ctx.fillRect(50, 54, 24, 6);
}
function drawKey(ctx) {
    drawKeyActual(ctx);
    drawKeyPredicted(ctx);
    drawKeyFunds(ctx);
}

function onDraw({ targets, data: { dataBalance, dataFunds } }, { ctx }, { drawCubicLine }) {
    // plot past + future predicted data
    if (!(dataBalance && dataFunds)) {
        return;
    }

    ctx.lineWidth = 2;
    drawCubicLine(dataBalance, [
        rgba(COLOR_BALANCE_ACTUAL), rgba(COLOR_BALANCE_PREDICTED)
    ]);

    // plot past + future predicted ISA stock value
    drawFundsLine(dataFunds, ctx, drawCubicLine);

    drawTargets(targets, ctx);

    drawKey(ctx);
}

function getRanges(dataBalance) {
    const dataY = dataBalance.map(item => item.last());
    const dataX = dataBalance.map(item => item.first());

    const minYValue = dataY.min();
    const minY = Math.min(0, minYValue);
    const maxY = dataY.max();
    const minX = dataX.min();
    const maxX = dataX.max();

    return { minY, maxY, minX, maxX };
}

function processData({ cost, showAll, ...props }) {
    let oldOffset = 0;

    let balance = cost.get('balanceWithPredicted');
    let funds = cost.get('funds');

    if (showAll) {
        oldOffset = cost.get('old').size;
        balance = cost.get('old').concat(balance);
        funds = cost.get('fundsOld').concat(funds);
    }

    const futureKey = oldOffset + getFutureKey(props);

    const dataBalance = getValuesWithTime(balance, { oldOffset, ...props });

    const dataFunds = funds.map((value, key) => list([
        dataBalance.getIn([key, 0]),
        value
    ]));

    const ranges = getRanges(dataBalance);

    const colorTransition = [futureKey - 1];

    return {
        oldOffset,
        ...ranges,
        colorTransition,
        data: { dataBalance, dataFunds }
    };
}

function GraphBalance(props) {
    const after = <AfterCanvas {...props} />;

    return <GraphCashFlow
        title="Balance"
        after={after}
        onDraw={onDraw}
        {...processData(props)}
        {...props}
    />;
}

GraphBalance.propTypes = {
    cost: PropTypes.instanceOf(map).isRequired,
    showAll: PropTypes.bool.isRequired,
    targets: PropTypes.instanceOf(list).isRequired
};

const mapStateToProps = state => ({
    currentYearMonth: state.getIn(['pages', 'overview', 'data', 'currentYearMonth']),
    startYearMonth: state.getIn(['pages', 'overview', 'data', 'startYearMonth']),
    cost: state.getIn(['pages', 'overview', 'data', 'cost']),
    showAll: state.getIn(['other', 'showAllBalanceGraph']),
    targets: state.getIn(['pages', 'overview', 'data', 'targets'])
});

const mapDispatchToProps = dispatch => ({
    onShowAll: () => dispatch(aShowAllToggled())
});

export default connect(mapStateToProps, mapDispatchToProps)(GraphBalance);

<|endoftext|>


<commit_before>/**
 * スクリプトタスク
 * JSファイルをwebpackを使ってコンパイルして出力する
 */
var gulp = require('gulp'),
    through = require('through2'),
    path = require('path'),
    ws = require('webpack-stream'),
    webpack = require('webpack');

/**
 * webpackコンパイル開始
 * @param watch
 * @returns {*}
 */
function exeWebPack(watch) {
    var conf = Object.create(require('../webpack.config.js'));
    conf.watch = watch;
    if(global.__IS_PRODUCTION) {
        delete conf.devtool;
        conf.plugins = conf.plugins || [];
        conf.plugins.push(new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: true
            }
        }));
    }
    return gulp.src(__CONFIG.path.js.src)
        .pipe(through.obj(function(file,charset,callback) {
            conf.entry = conf.entry || {};
            var fileName = path.basename(file.path).replace(/\.(ts|js)$/,'');
            conf.entry[fileName] = file.path;
            this.push(file);
            callback();
        }))
        .pipe(ws(conf,webpack))
        .pipe(gulp.dest(__CONFIG.path.js.dest))
        .pipe($.browser.stream());
}

/**
 * スクリプトコンパイルタスク
 */
gulp.task('script', function() {
    return exeWebPack(false);
});

/**
 * スクリプト監視タスク
 */
gulp.task('watchScript', function() {
    return exeWebPack(true);
});
<commit_msg>fix(gulp): webpack-mergeのconf仕様変更に合わせてEntryパス生成タスクを作成して修正<commit_after>/**
 * スクリプトタスク
 * JSファイルをwebpackを使ってコンパイルして出力する
 */
var _ = require('lodash'),
    gulp = require('gulp'),
    through = require('through2'),
    path = require('path'),
    ws = require('webpack-stream'),
    webpack = require('webpack'),
    conf = _.clone(require('../webpack.config.js'));

/**
 * webpackコンパイル開始
 * @param watch
 * @returns {*}
 */
function exeWebPack(watch) {
    conf.watch = watch;
    gulp.src(__CONFIG.path.js.src)
        .pipe(ws(conf,webpack))
        .pipe(gulp.dest(__CONFIG.path.js.dest))
        .pipe($.browser.stream());
}

gulp.task('_setEntries', function() {
    return gulp.src(__CONFIG.path.js.src)
        .pipe(through.obj(function(file,charset,callback) {
            conf.entry = conf.entry || {};
            var fileName = path.basename(file.path).replace(/\.(ts|js)$/,'');
            conf.entry[fileName] = file.path;
            this.push(file);
            callback();
        }));
});

/**
 * スクリプトコンパイルタスク
 */
gulp.task('script',['_setEntries'], function() {
    return exeWebPack(false);
});

/**
 * スクリプト監視タスク
 */
gulp.task('watchScript',['_setEntries'], function() {
    return exeWebPack(true);
});
<|endoftext|>