<commit_before>module.exports = function (code, ast, opts) {
  var gen = new CodeGenerator(code, ast, opts);
  return gen.generate();
};

module.exports.CodeGenerator = CodeGenerator;

var sourceMap = require("source-map");
var assert    = require("assert");
var util      = require("./util");
var t         = require("./types");
var _         = require("lodash");

function CodeGenerator(code, ast, opts) {
  opts = opts || {}

  this.tabWidth = 2;
  this.code     = code;
  this.opts     = opts;
  this.ast      = ast;
  this.buf      = "";

  this.line    = 1;
  this.column  = 0;
  this._indent = 0;

  if (opts.sourceMap) {
    this.map = new sourceMap.SourceMapGenerator({
      file: opts.sourceMapName
    });

    this.map.setSourceContent(opts.sourceFileName, code);
  } else {
    this.map = null;
  }
}

CodeGenerator.prototype.mark = function (node, locType) {
  var loc = node.loc;
  if (!loc) return; // no location info

  var map = this.map;
  if (!map) return; // no source map

  map.addMapping({
    source: this.opts.sourceFileName,
    generated: {
      line: this.line,
      column: this.column
    },
    original: loc[locType]
  });
};

CodeGenerator.prototype.newline = function (removeLast) {
  if (!this.buf) return;
  if (removeLast) this.removeLastNewline();
  this.buf = this.buf.replace(/\n(\s+)$/, "\n");
  this._push("\n");
};

CodeGenerator.prototype.removeLastNewline = function () {
  if (this.isLast("\n")) {
    this.buf = this.buf.slice(0, -1);
    this.line--;
  }
};

CodeGenerator.prototype.semicolon = function () {
  this._push(";");
};

CodeGenerator.prototype.keyword = function (name) {
  this.push(name);
  this.push(" ");
};

CodeGenerator.prototype.push = function (str, noIndent) {
  if (this._indent && !noIndent && str !== "\n") {
    // we have an indent level and we aren't pushing a newline
    var indent = this.getIndent();

    // replace all newlines with newlines with the indentation
    str = str.replace(/\n/g, "\n" + indent);

    // we've got a newline before us so prepend on the indentation
    if (this.isLast("\n")) str = indent + str;
  }

  this._push(str);
};

CodeGenerator.prototype._push = function (str) {
  var self = this;

  _.each(str, function (cha) {
    if (cha === "\n") {
      self.line++;
      self.column = 0;
    } else {
      self.column++;
    }
  });

  this.buf += str;
};

CodeGenerator.prototype.isLast = function (cha) {
  return _.last(this.buf) === cha;
};

CodeGenerator.prototype.getIndent = function () {
  return util.repeat(this._indent * this.tabWidth);
};

CodeGenerator.prototype.indent = function () {
  this._indent++;
};

CodeGenerator.prototype.dedent = function () {
  this._indent--;
};

CodeGenerator.prototype.generate = function () {
  var ast = this.ast;

  this.print(ast);

  this.buf = this.buf.trimRight();

  var map = this.map;
  if (map) map = map.toJSON();

  return {
    map:  map,
    ast:  ast,
    code: this.buf
  };
};

CodeGenerator.prototype.buildPrint = function (parent) {
  var self = this;

  var print = function (node, opts) {
    return self.print(node, parent, opts);
  };

  print.sequence = function (nodes, opts) {
    return self.printSequence(print, nodes, opts);
  };

  return print;
};

CodeGenerator.prototype.printSequence = function (print, nodes, opts) {
  var tokens   = this.ast.tokens;

  var self = this;
  opts = opts || {};

  var needsNewlineBefore = function (node) {
    var startToken;
    var endToken;

    _.each(tokens, function (token, i) {
      // this is the token this node starts with
      if (node.start === token.start) {
        startToken = tokens[i - 1];
        endToken = token;
        return false;
      }
    });

    return self.hasWhitespaceBetween(startToken, endToken);
  };

  var needsNewlineAfter = function (node) {
    var startToken;
    var endToken;

    _.each(tokens, function (token, i) {
      // this is the token this node ends with
      if (node.end === token.end) {
        startToken = token;
        endToken = tokens[i + 1];
        return false;
      }
    });

    return self.hasWhitespaceBetween(startToken, endToken);
  };

  opts.print = function (node, i) {
    var needs = function (fn) {
      if (!self.opts.whitespace) return;

      if (node.start != null) {
        // user node
        if (!fn(node)) return;
      } else {
        // generated node
        if (!t.needsWhitespace(node)) return;
        if (self.isLast("{")) return;
        self.removeLastNewline();
      }

      self.newline();
    };

    print(node, node && {
      before: function () {
        needs(needsNewlineBefore);
      },

      after: function () {
        needs(needsNewlineAfter);
      }
    });
  };

  return this.printJoin(print, nodes, "\n", opts);
};

CodeGenerator.prototype.hasWhitespaceBetween = function (startToken, endToken) {
  if (!endToken) return false;

  var comments = this.ast.comments;

  var start = startToken ? startToken.end : 0;
  var end   = endToken.start;

  var sep = this.code.slice(start, end);

  var lines = 0;
  if (start > 0) lines--; // take off the current line

  // remove comments
  _.each(comments, function (comment) {
    // this comment is after the last token or befor ethe first
    if (comment.end > end || comment.start < start) return;

    var length = comment.end - comment.start;

    // compute the relative positions of the comment within the sliced node
    // string
    var startRelative = comment.start - start;
    var endRelative = comment.end - start;

    // remove the line this comment ends with
    if (comment.type === "Line") lines--;

    // remove comment
    sep = sep.slice(0, startRelative) + util.repeat(length) + sep.slice(endRelative);
  });

  // check if there was a newline between the two nodes
  lines += _.size(sep.match(/\n/g));
  return lines > 0;
};

CodeGenerator.prototype.print = function (node, parent, opts) {
  if (!node) return "";

  opts = opts || {};

  if (this[node.type]) {
    this.printLeadingComments(node);

    if (opts.before) opts.before();
    this.mark(node, "start");

    var needsParans = t.needsParans(node, parent);
    if (needsParans) this.push("(");

    this[node.type](node, this.buildPrint(node), parent);
    if (needsParans) this.push(")");

    this.mark(node, "end");
    if (opts.after) opts.after();

    this.printTrailingComments(node);
  } else {
    throw new ReferenceError("unknown node " + node.type + " " + JSON.stringify(node));
  }
};

CodeGenerator.prototype.generateComment = function (comment) {
  var val = comment.value;
  if (comment.type === "Line") {
    val = "//" + val + "\n";
  } else {
    val = "/*" + val + "*/\n";
  }
  return val;
};

CodeGenerator.prototype.printTrailingComments = function (node) {
  this._printComments(node.trailingComments);
};

CodeGenerator.prototype.printLeadingComments = function (node) {
  this._printComments(node.leadingComments);
};

CodeGenerator.prototype._printComments = function (comments) {
  if (!comments || !comments.length) return;

  var self = this;

  _.each(comments, function (comment, i) {
    // whitespace before
    if (self.hasWhitespaceBetween(comment, comments[i - 1])) {
      self.newline();
    }

    self.push(self.generateComment(comment));

    // whitespace after
    if (self.hasWhitespaceBetween(comment, comments[i + 1])) {
      self.newline();
    }
  });
};

CodeGenerator.prototype.printJoin = function (print, nodes, sep, opts) {
  opts = opts || {};
  sep  = sep || "\n";

  var self = this;
  var len  = nodes.length;

  if (opts.indent) self.indent();

  _.each(nodes, function (node, i) {
    if (opts.print) {
      opts.print(node, i);
    } else {
      print(node);
    }

    if (opts.iterator) {
      opts.iterator(node, i);
    }

    if (i < len - 1) {
      self.push(sep);
    }
  });

  if (opts.indent) self.dedent();
};

CodeGenerator.generators = {
  arrayComprehensions: require("./generators/array-comprehensions"),
  templateLiterals:    require("./generators/template-literals"),
  expressions:         require("./generators/expressions"),
  statements:          require("./generators/statements"),
  classes:             require("./generators/classes"),
  methods:             require("./generators/methods"),
  modules:             require("./generators/modules"),
  types:               require("./generators/types"),
  base:                require("./generators/base"),
  jsx:                 require("./generators/jsx")
};

_.each(CodeGenerator.generators, function (generator) {
  _.extend(CodeGenerator.prototype, generator);
});
<commit_msg>generator: add trim option to isLast<commit_after>module.exports = function (code, ast, opts) {
  var gen = new CodeGenerator(code, ast, opts);
  return gen.generate();
};

module.exports.CodeGenerator = CodeGenerator;

var sourceMap = require("source-map");
var assert    = require("assert");
var util      = require("./util");
var t         = require("./types");
var _         = require("lodash");

function CodeGenerator(code, ast, opts) {
  opts = opts || {}

  this.tabWidth = 2;
  this.code     = code;
  this.opts     = opts;
  this.ast      = ast;
  this.buf      = "";

  this.line    = 1;
  this.column  = 0;
  this._indent = 0;

  if (opts.sourceMap) {
    this.map = new sourceMap.SourceMapGenerator({
      file: opts.sourceMapName
    });

    this.map.setSourceContent(opts.sourceFileName, code);
  } else {
    this.map = null;
  }
}

CodeGenerator.prototype.mark = function (node, locType) {
  var loc = node.loc;
  if (!loc) return; // no location info

  var map = this.map;
  if (!map) return; // no source map

  map.addMapping({
    source: this.opts.sourceFileName,
    generated: {
      line: this.line,
      column: this.column
    },
    original: loc[locType]
  });
};

CodeGenerator.prototype.newline = function (removeLast) {
  if (!this.buf) return;
  if (removeLast) this.removeLastNewline();
  this.buf = this.buf.replace(/\n(\s+)$/, "\n");
  this._push("\n");
};

CodeGenerator.prototype.removeLastNewline = function () {
  if (this.isLast("\n")) {
    this.buf = this.buf.slice(0, -1);
    this.line--;
  }
};

CodeGenerator.prototype.semicolon = function () {
  this._push(";");
};

CodeGenerator.prototype.keyword = function (name) {
  this.push(name);
  this.push(" ");
};

CodeGenerator.prototype.push = function (str, noIndent) {
  if (this._indent && !noIndent && str !== "\n") {
    // we have an indent level and we aren't pushing a newline
    var indent = this.getIndent();

    // replace all newlines with newlines with the indentation
    str = str.replace(/\n/g, "\n" + indent);

    // we've got a newline before us so prepend on the indentation
    if (this.isLast("\n")) str = indent + str;
  }

  this._push(str);
};

CodeGenerator.prototype._push = function (str) {
  var self = this;

  _.each(str, function (cha) {
    if (cha === "\n") {
      self.line++;
      self.column = 0;
    } else {
      self.column++;
    }
  });

  this.buf += str;
};

CodeGenerator.prototype.isLast = function (cha, trimRight) {
  var buf = this.buf;
  if (trimRight) buf = buf.trimRight();
  return _.last(buf) === cha;
};

CodeGenerator.prototype.getIndent = function () {
  return util.repeat(this._indent * this.tabWidth);
};

CodeGenerator.prototype.indent = function () {
  this._indent++;
};

CodeGenerator.prototype.dedent = function () {
  this._indent--;
};

CodeGenerator.prototype.generate = function () {
  var ast = this.ast;

  this.print(ast);

  this.buf = this.buf.trimRight();

  var map = this.map;
  if (map) map = map.toJSON();

  return {
    map:  map,
    ast:  ast,
    code: this.buf
  };
};

CodeGenerator.prototype.buildPrint = function (parent) {
  var self = this;

  var print = function (node, opts) {
    return self.print(node, parent, opts);
  };

  print.sequence = function (nodes, opts) {
    return self.printSequence(print, nodes, opts);
  };

  return print;
};

CodeGenerator.prototype.printSequence = function (print, nodes, opts) {
  var tokens   = this.ast.tokens;

  var self = this;
  opts = opts || {};

  var needsNewlineBefore = function (node) {
    var startToken;
    var endToken;

    _.each(tokens, function (token, i) {
      // this is the token this node starts with
      if (node.start === token.start) {
        startToken = tokens[i - 1];
        endToken = token;
        return false;
      }
    });

    return self.hasWhitespaceBetween(startToken, endToken);
  };

  var needsNewlineAfter = function (node) {
    var startToken;
    var endToken;

    _.each(tokens, function (token, i) {
      // this is the token this node ends with
      if (node.end === token.end) {
        startToken = token;
        endToken = tokens[i + 1];
        return false;
      }
    });

    return self.hasWhitespaceBetween(startToken, endToken);
  };

  opts.print = function (node, i) {
    var needs = function (fn) {
      if (!self.opts.whitespace) return;

      if (node.start != null) {
        // user node
        if (!fn(node)) return;
      } else {
        // generated node
        if (!t.needsWhitespace(node)) return;
        if (self.isLast("{", true)) return;
      }

      self.newline();
    };

    print(node, node && {
      before: function () {
        needs(needsNewlineBefore);
      },

      after: function () {
        needs(needsNewlineAfter);
      }
    });
  };

  return this.printJoin(print, nodes, "\n", opts);
};

CodeGenerator.prototype.hasWhitespaceBetween = function (startToken, endToken) {
  if (!endToken) return false;

  var comments = this.ast.comments;

  var start = startToken ? startToken.end : 0;
  var end   = endToken.start;

  var sep = this.code.slice(start, end);

  var lines = 0;
  if (start > 0) lines--; // take off the current line

  // remove comments
  _.each(comments, function (comment) {
    // this comment is after the last token or befor ethe first
    if (comment.end > end || comment.start < start) return;

    var length = comment.end - comment.start;

    // compute the relative positions of the comment within the sliced node
    // string
    var startRelative = comment.start - start;
    var endRelative = comment.end - start;

    // remove the line this comment ends with
    if (comment.type === "Line") lines--;

    // remove comment
    sep = sep.slice(0, startRelative) + util.repeat(length) + sep.slice(endRelative);
  });

  // check if there was a newline between the two nodes
  lines += _.size(sep.match(/\n/g));
  return lines > 0;
};

CodeGenerator.prototype.print = function (node, parent, opts) {
  if (!node) return "";

  opts = opts || {};

  if (this[node.type]) {
    this.printLeadingComments(node);

    if (opts.before) opts.before();
    this.mark(node, "start");

    var needsParans = t.needsParans(node, parent);
    if (needsParans) this.push("(");

    this[node.type](node, this.buildPrint(node), parent);
    if (needsParans) this.push(")");

    this.mark(node, "end");
    if (opts.after) opts.after();

    this.printTrailingComments(node);
  } else {
    throw new ReferenceError("unknown node " + node.type + " " + JSON.stringify(node));
  }
};

CodeGenerator.prototype.generateComment = function (comment) {
  var val = comment.value;
  if (comment.type === "Line") {
    val = "//" + val + "\n";
  } else {
    val = "/*" + val + "*/\n";
  }
  return val;
};

CodeGenerator.prototype.printTrailingComments = function (node) {
  this._printComments(node.trailingComments);
};

CodeGenerator.prototype.printLeadingComments = function (node) {
  this._printComments(node.leadingComments);
};

CodeGenerator.prototype._printComments = function (comments) {
  if (!comments || !comments.length) return;

  var self = this;

  _.each(comments, function (comment, i) {
    // whitespace before
    if (self.hasWhitespaceBetween(comment, comments[i - 1])) {
      self.newline();
    }

    self.push(self.generateComment(comment));

    // whitespace after
    if (self.hasWhitespaceBetween(comment, comments[i + 1])) {
      self.newline();
    }
  });
};

CodeGenerator.prototype.printJoin = function (print, nodes, sep, opts) {
  opts = opts || {};
  sep  = sep || "\n";

  var self = this;
  var len  = nodes.length;

  if (opts.indent) self.indent();

  _.each(nodes, function (node, i) {
    if (opts.print) {
      opts.print(node, i);
    } else {
      print(node);
    }

    if (opts.iterator) {
      opts.iterator(node, i);
    }

    if (i < len - 1) {
      self.push(sep);
    }
  });

  if (opts.indent) self.dedent();
};

CodeGenerator.generators = {
  arrayComprehensions: require("./generators/array-comprehensions"),
  templateLiterals:    require("./generators/template-literals"),
  expressions:         require("./generators/expressions"),
  statements:          require("./generators/statements"),
  classes:             require("./generators/classes"),
  methods:             require("./generators/methods"),
  modules:             require("./generators/modules"),
  types:               require("./generators/types"),
  base:                require("./generators/base"),
  jsx:                 require("./generators/jsx")
};

_.each(CodeGenerator.generators, function (generator) {
  _.extend(CodeGenerator.prototype, generator);
});
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import Component from './component';
import path from 'path';

import asyncMap from 'greasebox/async-map';

import Locale from './locale';
import { LocaleLoadError } from './errors';

const isClient = typeof window !== 'undefined';

const CHILDROUTES = Symbol();
const COMPONENT = Symbol();
const COMPONENT_PATH = Symbol();
const LOCALE = Symbol();
const CTX = Symbol();

export default class Application {
  constructor(ctx) {
    this[CTX] = ctx;
    this[CHILDROUTES] = this.childRoutes.map(r => path.resolve(this.dirname, r));
    console.log(this[CHILDROUTES])
    this[COMPONENT_PATH] = path.resolve(this.dirname, this.component);
    this[LOCALE] = new Locale(ctx, this::processLocaleSetting());
    this[CTX] = {
      context: {
        ctx,
        locale: this[LOCALE]
      }
    };
  }
  get path() {
    return '/';
  }
  get childRoutes() {
    return [];
  }
  get component() {
    throw new Error('Application must define a relative path to component');
    return void 0;
  }
  get dirname() {
    throw new Error('Application must define dirname');
  }
  get locale() {
    return void 0;
  }

  title() {
    return void 0;
  }
  get routes() {

    return {
      path: this.path,
      getChildRoutes: async (location, cb) => {
        if(isClient) {
          cb(null, await asyncMap(this[CHILDROUTES], async r => {
            try {
              let ChildApp = await System.import(r);
              let child = new ChildApp(this[CTX].context.ctx);
              return child.routes;
            } catch (err) {
              return null;
            }

          }));
        } else {
          cb(null, this[CHILDROUTES].map(r => {
            let ChildApp = require(r);
            let child = new ChildApp(this[CTX].context.ctx);
            return child.routes;
          }))
        }
      },
      onEnter: async (nextState, replaceState, cb) => {
        try {
          await this[LOCALE].loadLocales();
        } catch (err) {
          if(!(err instanceof LocaleLoadError)) {
            err = new LocaleLoadError(err);
          }
          this[CTX].context.ctx.emit('error', err);
        }

        //title
        if(this.title !== Application.prototype.title) {
          this[CTX].context.ctx.pushTitle(this[CTX]::this.title());
        }
        if(typeof this.onEnter === 'function') {
          if(this.onEnter.length === 3) {
            await this[CTX]::this.onEnter(nextState, replaceState, cb);
          } else {
            await this[CTX]::this.onEnter(nextState, replaceState);
            cb();
          }
        } else {
          cb();
        }
      },
      onLeave: () => {
        //title
        if(this.title !== Application.prototype.title) {
          this[CTX].context.ctx.popTitle();
        }
        if(typeof this.onLeave === 'function') {
          this[CTX]::this.onLeave();
        }
      },
      getComponent: async (location, cb) => {
        let self = this;
        if(!this[COMPONENT]) {
          let Comp;
          if(isClient) {
            Comp = await System.import(this[COMPONENT_PATH]);
          } else {
            Comp = require(this[COMPONENT_PATH]);
          }

          //extends the Comp with contexts
          this[COMPONENT] = class K extends Component {
            static get contextTypes() {
              return {
                ctx: PropTypes.object,
                locale: PropTypes.func
              };
            }
            static get childContextTypes () {
              return {
                ctx: PropTypes.object,
                locale: PropTypes.func
              }
            }
            getChildContext() {
              return self[CTX].context;
            }
            render() {
              return (<Comp {...this.props}/>)
            }

          };

        }

        cb(null, this[COMPONENT]);
      }

    }
  }
}

function processLocaleSetting() {
  let settings = this.locale;
  if(settings) {
    settings.path = path.resolve(this.dirname, settings.path);
  }
  return settings;
}

//TODO:  onLeave handling
<commit_msg>remove debug log<commit_after>import React, { PropTypes } from 'react';
import Component from './component';
import path from 'path';

import asyncMap from 'greasebox/async-map';

import Locale from './locale';
import { LocaleLoadError } from './errors';

const isClient = typeof window !== 'undefined';

const CHILDROUTES = Symbol();
const COMPONENT = Symbol();
const COMPONENT_PATH = Symbol();
const LOCALE = Symbol();
const CTX = Symbol();

export default class Application {
  constructor(ctx) {
    this[CTX] = ctx;
    this[CHILDROUTES] = this.childRoutes.map(r => path.resolve(this.dirname, r));
    this[COMPONENT_PATH] = path.resolve(this.dirname, this.component);
    this[LOCALE] = new Locale(ctx, this::processLocaleSetting());
    this[CTX] = {
      context: {
        ctx,
        locale: this[LOCALE]
      }
    };
  }
  get path() {
    return '/';
  }
  get childRoutes() {
    return [];
  }
  get component() {
    throw new Error('Application must define a relative path to component');
    return void 0;
  }
  get dirname() {
    throw new Error('Application must define dirname');
  }
  get locale() {
    return void 0;
  }

  title() {
    return void 0;
  }
  get routes() {

    return {
      path: this.path,
      getChildRoutes: async (location, cb) => {
        if(isClient) {
          cb(null, await asyncMap(this[CHILDROUTES], async r => {
            try {
              let ChildApp = await System.import(r);
              let child = new ChildApp(this[CTX].context.ctx);
              return child.routes;
            } catch (err) {
              return null;
            }

          }));
        } else {
          cb(null, this[CHILDROUTES].map(r => {
            let ChildApp = require(r);
            let child = new ChildApp(this[CTX].context.ctx);
            return child.routes;
          }))
        }
      },
      onEnter: async (nextState, replaceState, cb) => {
        try {
          await this[LOCALE].loadLocales();
        } catch (err) {
          if(!(err instanceof LocaleLoadError)) {
            err = new LocaleLoadError(err);
          }
          this[CTX].context.ctx.emit('error', err);
        }

        //title
        if(this.title !== Application.prototype.title) {
          this[CTX].context.ctx.pushTitle(this[CTX]::this.title());
        }
        if(typeof this.onEnter === 'function') {
          if(this.onEnter.length === 3) {
            await this[CTX]::this.onEnter(nextState, replaceState, cb);
          } else {
            await this[CTX]::this.onEnter(nextState, replaceState);
            cb();
          }
        } else {
          cb();
        }
      },
      onLeave: () => {
        //title
        if(this.title !== Application.prototype.title) {
          this[CTX].context.ctx.popTitle();
        }
        if(typeof this.onLeave === 'function') {
          this[CTX]::this.onLeave();
        }
      },
      getComponent: async (location, cb) => {
        let self = this;
        if(!this[COMPONENT]) {
          let Comp;
          if(isClient) {
            Comp = await System.import(this[COMPONENT_PATH]);
          } else {
            Comp = require(this[COMPONENT_PATH]);
          }

          //extends the Comp with contexts
          this[COMPONENT] = class K extends Component {
            static get contextTypes() {
              return {
                ctx: PropTypes.object,
                locale: PropTypes.func
              };
            }
            static get childContextTypes () {
              return {
                ctx: PropTypes.object,
                locale: PropTypes.func
              }
            }
            getChildContext() {
              return self[CTX].context;
            }
            render() {
              return (<Comp {...this.props}/>)
            }

          };

        }

        cb(null, this[COMPONENT]);
      }

    }
  }
}

function processLocaleSetting() {
  let settings = this.locale;
  if(settings) {
    settings.path = path.resolve(this.dirname, settings.path);
  }
  return settings;
}

//TODO:  onLeave handling
<|endoftext|>


<commit_before>import React from 'react'
import { View, Image } from 'react-native'
import {
	createStackNavigator,
	createBottomTabNavigator,
	createMaterialTopTabNavigator,
	createAppContainer
} from 'react-navigation'
import { MenuProvider } from 'react-native-popup-menu'
import { connect } from 'react-redux'
import { platformAndroid } from '../util/general'
import css from '../styles/css'
import COLOR from '../styles/ColorConstants'
import TabIcons from './TabIcons'
import NavigationService from './NavigationService'

// VIEWS
import Home from '../views/home/Home'
import OnboardingIntro from '../views/login/OnboardingIntro'
import OnboardingLogin from '../views/login/OnboardingLogin'
import SurfReport from '../views/weather/SurfReport'
import ShuttleStop from '../views/shuttle/ShuttleStop'
import DiningDetail from '../views/dining/DiningDetail'
import DiningNutrition from '../views/dining/DiningNutrition'
import EventDetail from '../views/events/EventDetail'
import NewsDetail from '../views/news/NewsDetail'
import Feedback from '../views/preferences/feedback/Feedback'
import Messaging from '../views/messaging/Messaging'
import Preferences from '../views/preferences/Preferences'
import Map from '../views/map/Map'
import DataListViewAll from '../views/common/DataListViewAll'
import SpecialEventsView from '../views/specialEvents/SpecialEventsView'
import SpecialEventsDetailView from '../views/specialEvents/SpecialEventsDetailView'
import SpecialEventsFilterListView from '../views/specialEvents/SpecialEventsFilterListView'
import ShuttleRoutesListView from '../views/shuttle/ShuttleRoutesListView'
import ShuttleStopsListView from '../views/shuttle/ShuttleStopsListView'
import ShuttleSavedListView from '../views/shuttle/ShuttleSavedListView'
import FullSchedule from '../views/schedule/FullScheduleListView'
import ParkingSpotType from '../views/parking/ParkingSpotType'
import ManageParkingLots from '../views/parking/ManageParkingLots'
import Notifications from '../views/preferences/notifications/Notifications'
import CardPreferences from '../views/preferences/card/CardPreferences'

const campusLogoImage = require('../assets/images/UCSanDiegoLogo-nav.png')

let TabNav

if (platformAndroid()) {
	TabNav = createMaterialTopTabNavigator(
		{
			Home: { screen: Home },
			Map: { screen: Map },
			Messaging: { screen: Messaging },
			Preferences: { screen: Preferences }
		},
		{
			tabBarOptions: {
				showLabel: false,
				showIcon: true,
				pressColor: COLOR.MGREY,
				indicatorStyle: { backgroundColor: COLOR.TRANSPARENT },
				style: css.tabBar,
			},
			defaultNavigationOptions: ({ navigation }) => ({
				tabBarIcon: ({ focused }) => {
					const { routeName } = navigation.state
					return <TabIcons title={routeName} focused={focused} />
				},
				swipeEnabled: false
			})
		}
	)
} else {
	TabNav = createBottomTabNavigator(
		{
			Home: { screen: Home },
			Map: { screen: Map },
			Messaging: { screen: Messaging },
			Preferences: { screen: Preferences }
		},
		{
			tabBarOptions: {
				showLabel: false,
				showIcon: true,
				pressColor: COLOR.MGREY,
				indicatorStyle: { backgroundColor: 'green' },
				style: css.tabBar,
			},
			defaultNavigationOptions: ({ navigation }) => ({
				tabBarIcon: ({ focused }) => {
					const { routeName } = navigation.state
					return <TabIcons title={routeName} focused={focused} />
				},
				swipeEnabled: false
			})
		}
	)
}

TabNav.navigationOptions = ({ navigation }) => {
	const { routeName } = navigation.state.routes[navigation.state.index]
	const headerTitle = ( routeName === 'Home') ? <Image source={campusLogoImage} style={css.navCampusLogoTitle} /> : routeName
	return { headerTitle }
}

const DummyView = () => (<View />) /* Workaround for misaligned title */

let MainStack = createStackNavigator(
	{
		MainTabs: { screen: TabNav },
		SurfReport: {
			screen: SurfReport,
			navigationOptions: {
				title: 'Surf Report',
				headerRight: (<DummyView />)
			}
		},
		NewsDetail: {
			screen: NewsDetail,
			navigationOptions: {
				title: 'News',
				headerRight: (<DummyView />)
			}
		},
		EventDetail: {
			screen: EventDetail,
			navigationOptions: {
				title: 'Events',
				headerRight: (<DummyView />)
			}
		},
		DiningDetail: {
			screen: DiningDetail,
			navigationOptions: {
				title: 'Dining',
				headerRight: (<DummyView />)
			}
		},
		DiningNutrition: {
			screen: DiningNutrition,
			navigationOptions: {
				title: 'Nutrition',
				headerRight: (<DummyView />)
			}
		},
		ShuttleStop: {
			screen: ShuttleStop,
			navigationOptions: {
				title: 'Shuttle',
				headerRight: (<DummyView />)
			}
		},
		ShuttleStopsListView: {
			screen: ShuttleStopsListView,
			navigationOptions: {
				title: 'Choose Stop',
				headerRight: (<DummyView />)
			}
		},
		ShuttleSavedListView: {
			screen: ShuttleSavedListView,
			navigationOptions: {
				title: 'Manage Stops',
				headerRight: (<DummyView />)
			}
		},
		ShuttleRoutesListView: {
			screen: ShuttleRoutesListView,
			navigationOptions: {
				title: 'Choose Route',
				headerRight: (<DummyView />)
			}
		},
		ParkingSpotType: {
			screen: ParkingSpotType,
			navigationOptions: {
				title: 'Spot Types',
				headerRight: (<DummyView />)
			}
		},
		ManageParkingLots: {
			screen: ManageParkingLots,
			navigationOptions: {
				title: 'Manage Lots',
				headerRight: (<DummyView />)
			}
		},
		SpecialEventsView: { screen: SpecialEventsView },
		SpecialEventsFilters: {
			screen: SpecialEventsFilterListView,
			navigationOptions: ({ navigation }) => {
				const { params } = navigation.state
				const { title } = params
				return {
					title,
					headerRight: (<DummyView />)
				}
			}
		},
		SpecialEventsDetailView: {
			screen: SpecialEventsDetailView,
			navigationOptions: ({ navigation }) => {
				const { params } = navigation.state
				const { title } = params
				return {
					title,
					headerRight: (<DummyView />)
				}
			}
		},
		FullSchedule: {
			screen: FullSchedule,
			navigationOptions: {
				title: 'Classes',
				headerRight: (<DummyView />)
			}
		},
		LoginScreen: {
			screen: OnboardingLogin,
			navigationOptions: { header: null }
		},
		Feedback: {
			screen: Feedback,
			navigationOptions: {
				title: 'Feedback'
			}
		},
		Notifications: {
			screen: Notifications,
			navigationOptions: {
				title: 'Notifications',
				headerRight: (<DummyView />)
			}
		},
		CardPreferences: {
			screen: CardPreferences,
			navigationOptions: {
				title: 'Cards',
				headerRight: (<DummyView />)
			}
		},
		DataListViewAll: {
			screen: DataListViewAll,
			navigationOptions: ({ navigation }) => {
				const { params } = navigation.state
				const { title } = params
				return {
					title,
					headerRight: (<DummyView />)
				}
			}
		}
	},
	{
		initialRouteName: 'MainTabs',
		defaultNavigationOptions: {
			headerStyle: css.nav,
			headerTitleStyle: css.navTitle,
			headerTintColor: COLOR.WHITE,

		},
		cardStyle: { backgroundColor: COLOR.LGREY2 }
	}
)

let OnboardingStack = createStackNavigator(
	{
		OnboardingIntro: {
			screen: OnboardingIntro,
			navigationOptions: { header: null }
		},
		OnboardingLogin: {
			screen: OnboardingLogin,
			navigationOptions: { header: null }
		},
	},
	{
		initialRouteName: 'OnboardingIntro',
		headerMode: 'none',
		cardStyle: { backgroundColor: COLOR.LGREY2 }
	},
)

MainStack = createAppContainer(MainStack)
OnboardingStack = createAppContainer(OnboardingStack)

const Router = ({ onBoardingViewed }) => (
	<MenuProvider>
		{
			(onBoardingViewed) ? (
				<MainStack ref={navigatorRef => NavigationService.setTopLevelNavigator(navigatorRef)} />
			) : (
				<OnboardingStack ref={navigatorRef => NavigationService.setTopLevelNavigator(navigatorRef)} />
			)
		}
	</MenuProvider>
)

const mapStateToProps = (state, props) => (
	{ onBoardingViewed: state.routes.onBoardingViewed }
)

export default connect(mapStateToProps)(Router)
<commit_msg>update router<commit_after>import React from 'react'
import { Image } from 'react-native'
import {
	createStackNavigator,
	createBottomTabNavigator,
	createMaterialTopTabNavigator,
	createAppContainer
} from 'react-navigation'
import { MenuProvider } from 'react-native-popup-menu'
import { connect } from 'react-redux'
import { platformAndroid } from '../util/general'
import css from '../styles/css'
import COLOR from '../styles/ColorConstants'
import TabIcons from './TabIcons'
import NavigationService from './NavigationService'

// VIEWS
import Home from '../views/home/Home'
import OnboardingIntro from '../views/login/OnboardingIntro'
import OnboardingLogin from '../views/login/OnboardingLogin'
import SurfReport from '../views/weather/SurfReport'
import ShuttleStop from '../views/shuttle/ShuttleStop'
import DiningDetail from '../views/dining/DiningDetail'
import DiningNutrition from '../views/dining/DiningNutrition'
import EventDetail from '../views/events/EventDetail'
import NewsDetail from '../views/news/NewsDetail'
import Feedback from '../views/preferences/feedback/Feedback'
import Messaging from '../views/messaging/Messaging'
import Preferences from '../views/preferences/Preferences'
import Map from '../views/map/Map'
import DataListViewAll from '../views/common/DataListViewAll'
import SpecialEventsView from '../views/specialEvents/SpecialEventsView'
import SpecialEventsDetailView from '../views/specialEvents/SpecialEventsDetailView'
import SpecialEventsFilterListView from '../views/specialEvents/SpecialEventsFilterListView'
import ShuttleRoutesListView from '../views/shuttle/ShuttleRoutesListView'
import ShuttleStopsListView from '../views/shuttle/ShuttleStopsListView'
import ShuttleSavedListView from '../views/shuttle/ShuttleSavedListView'
import FullSchedule from '../views/schedule/FullScheduleListView'
import ParkingSpotType from '../views/parking/ParkingSpotType'
import ManageParkingLots from '../views/parking/ManageParkingLots'
import Notifications from '../views/preferences/notifications/Notifications'
import CardPreferences from '../views/preferences/card/CardPreferences'

const campusLogoImage = require('../assets/images/UCSanDiegoLogo-nav.png')

const TabNavScreens = {
	Home: { screen: Home },
	Map: { screen: Map },
	Messaging: { screen: Messaging },
	Preferences: { screen: Preferences }
}

const TabNavSetup = {
	tabBarOptions: {
		showLabel: false,
		showIcon: true,
		pressColor: COLOR.MGREY,
		indicatorStyle: { backgroundColor: platformAndroid() ? COLOR.PRIMARY : COLOR.TRANSPARENT },
		style: css.tabBar,
	},
	defaultNavigationOptions: ({ navigation }) => ({
		tabBarIcon: ({ focused }) => {
			const { routeName } = navigation.state
			return <TabIcons title={routeName} focused={focused} />
		},
		swipeEnabled: false
	})
}

let TabNav
if (platformAndroid()) {
	TabNav = createMaterialTopTabNavigator(TabNavScreens, TabNavSetup)
} else {
	TabNav = createBottomTabNavigator(TabNavScreens, TabNavSetup)
}

TabNav.navigationOptions = ({ navigation }) => {
	const { routeName } = navigation.state.routes[navigation.state.index]
	const headerTitle = ( routeName === 'Home') ? <Image source={campusLogoImage} style={css.navCampusLogoTitle} /> : routeName
	return { headerTitle }
}

let MainStack = createStackNavigator(
	{
		MainTabs: { screen: TabNav },
		SurfReport: {
			screen: SurfReport,
			navigationOptions: {
				title: 'Surf Report'
			}
		},
		NewsDetail: {
			screen: NewsDetail,
			navigationOptions: {
				title: 'News',
			}
		},
		EventDetail: {
			screen: EventDetail,
			navigationOptions: {
				title: 'Events',
			}
		},
		DiningDetail: {
			screen: DiningDetail,
			navigationOptions: {
				title: 'Dining',
			}
		},
		DiningNutrition: {
			screen: DiningNutrition,
			navigationOptions: {
				title: 'Nutrition',
			}
		},
		ShuttleStop: {
			screen: ShuttleStop,
			navigationOptions: {
				title: 'Shuttle',
			}
		},
		ShuttleStopsListView: {
			screen: ShuttleStopsListView,
			navigationOptions: {
				title: 'Choose Stop',
			}
		},
		ShuttleSavedListView: {
			screen: ShuttleSavedListView,
			navigationOptions: {
				title: 'Manage Stops',
			}
		},
		ShuttleRoutesListView: {
			screen: ShuttleRoutesListView,
			navigationOptions: {
				title: 'Choose Route',
			}
		},
		ParkingSpotType: {
			screen: ParkingSpotType,
			navigationOptions: {
				title: 'Spot Types',
			}
		},
		ManageParkingLots: {
			screen: ManageParkingLots,
			navigationOptions: {
				title: 'Manage Lots',
			}
		},
		SpecialEventsView: { screen: SpecialEventsView },
		SpecialEventsFilters: {
			screen: SpecialEventsFilterListView,
			navigationOptions: ({ navigation }) => {
				const { params } = navigation.state
				const { title } = params
				return {
					title,
				}
			}
		},
		SpecialEventsDetailView: {
			screen: SpecialEventsDetailView,
			navigationOptions: ({ navigation }) => {
				const { params } = navigation.state
				const { title } = params
				return {
					title,
				}
			}
		},
		FullSchedule: {
			screen: FullSchedule,
			navigationOptions: {
				title: 'Classes',
			}
		},
		LoginScreen: {
			screen: OnboardingLogin,
			navigationOptions: { header: null }
		},
		Feedback: {
			screen: Feedback,
			navigationOptions: {
				title: 'Feedback'
			}
		},
		Notifications: {
			screen: Notifications,
			navigationOptions: {
				title: 'Notifications',
			}
		},
		CardPreferences: {
			screen: CardPreferences,
			navigationOptions: {
				title: 'Cards',
			}
		},
		DataListViewAll: {
			screen: DataListViewAll,
			navigationOptions: ({ navigation }) => {
				const { params } = navigation.state
				const { title } = params
				return { title }
			}
		}
	},
	{
		initialRouteName: 'MainTabs',
		defaultNavigationOptions: {
			headerStyle: css.nav,
			headerTitleStyle: css.navTitle,
			headerTintColor: COLOR.WHITE,
		},
		headerLayoutPreset: 'center',
		cardStyle: { backgroundColor: COLOR.LGREY2 }
	}
)

let OnboardingStack = createStackNavigator(
	{
		OnboardingIntro: {
			screen: OnboardingIntro,
			navigationOptions: { header: null }
		},
		OnboardingLogin: {
			screen: OnboardingLogin,
			navigationOptions: { header: null }
		},
	},
	{
		initialRouteName: 'OnboardingIntro',
		headerMode: 'none',
		cardStyle: { backgroundColor: COLOR.LGREY2 }
	},
)

MainStack = createAppContainer(MainStack)
OnboardingStack = createAppContainer(OnboardingStack)

const Router = ({ onBoardingViewed }) => {
	if (onBoardingViewed) {
		return (
			<MenuProvider>
				<MainStack ref={navigatorRef => NavigationService.setTopLevelNavigator(navigatorRef)} />
			</MenuProvider>
		)
	} else {
		return (
			<OnboardingStack ref={navigatorRef => NavigationService.setTopLevelNavigator(navigatorRef)} />
		)
	}
}

const mapStateToProps = (state, props) => (
	{ onBoardingViewed: state.routes.onBoardingViewed }
)

export default connect(mapStateToProps)(Router)
<|endoftext|>


<commit_before>const fs = require('fs');
const async = require('async');
const aws = require('aws-sdk');
const s3 = new aws.S3();

function uploadFile(file, callback) {
  fs.readFile('./build/' + file, function (err, data) {
    if (err) {
      console.log('Error reading file');
      console.log(err);
      callback(err);
    } else {
      const base64data = new Buffer(data, 'binary');
      const params = {
        Bucket: 'ez-react-boilerplate',
        Key: file,
        Body: base64data
      };
      const split = file.split('.');
      const last = split[split.length - 1];
      if (last === '.htaccess') {
        params.ContentType = 'binary/octet-stream'
      } else if (last === 'js') {
        params.ContentType = 'application/javascript'
      } else if (last === 'jpg') {
        params.ContentType = 'image/jpeg'
      } else if (last === 'ico') {
        params.ContentType = 'image/x-icon'
      } else if (last === 'html') {
        params.ContentType = 'text/html'
      } else if (last === 'json') {
        params.ContentType = 'application/json'
      }
      s3.putObject(params, function (err, data) {
        if (err) {
          console.log('Oh, Snap');
          console.log(err);
          callback(err);
        } else {
          console.log('Uploaded ' + file);
          callback();
        }
      })
    }
  })
}
async.series([
    function (cb) {
      console.log('Cleaning s3 bucket...');
      const params = {
        Bucket: 'ez-react-boilerplate'
      };
      s3.listObjects(params, function (err, data) {
        console.log(data);
        async.forEach(data.Contents, function (file, callback) {
          console.log('Deleting ' + file.Key);
          const p = {
            Bucket: 'ez-react-boilerplate',
            Key: file.Key
          };
          s3.deleteObject(p, function (err, data) {
            if (err) {
              console.log('Error ' + err);
              callback(err);
            } else {
              callback();
            }
          })
        }, function (err) {
          console.log('Done deleting...');
          cb();
        });
      })
    },
    function (cb) {
      console.log('Uploading files to s3...');
      fs.readdir('./build', (err, files) => {
        async.forEach(files, function (file, cb) {
          console.log('Working on file: ' + file);
          uploadFile(file, cb);
        }, function (err) {
          console.log('DONE!');
        })
      });
    }
  ],
  function (err) {
    console.log('DONE!');
  });
<commit_msg>fix to upload script<commit_after>const fs = require('fs');
const async = require('async');
const aws = require('aws-sdk');
const s3 = new aws.S3();

function uploadFile(file, callback) {
  fs.readFile('./build/' + file, function (err, data) {
    if (err) {
      console.log('Error reading file');
      console.log(err);
      callback(err);
    } else {
      const base64data = new Buffer(data, 'binary');
      const params = {
        Bucket: 'ez-react-boilerplate',
        Key: file,
        Body: base64data
      };
      const split = file.split('.');
      const last = split[split.length - 1];
      if (last === '.htaccess') {
        params.ContentType = 'binary/octet-stream'
      } else if (last === 'js') {
        params.ContentType = 'application/javascript'
      } else if (last === 'jpg') {
        params.ContentType = 'image/jpeg'
      } else if (last === 'ico') {
        params.ContentType = 'image/x-icon'
      } else if (last === 'html') {
        params.ContentType = 'text/html'
      } else if (last === 'json') {
        params.ContentType = 'application/json'
      }
      s3.putObject(params, function (err, data) {
        if (err) {
          console.log('Oh, Snap');
          console.log(err);
          callback(err);
        } else {
          console.log('Uploaded ' + file);
          callback();
        }
      })
    }
  })
}
async.series([
    function (cb) {
      console.log('Cleaning s3 bucket...');
      const params = {
        Bucket: 'ez-react-boilerplate'
      };
      s3.listObjects(params, function (err, data) {
        console.log(data);
        if (data.Contents) {
          async.forEach(data.Contents, function (file, callback) {
            console.log('Deleting ' + file.Key);
            const p = {
              Bucket: 'ez-react-boilerplate',
              Key: file.Key
            };
            s3.deleteObject(p, function (err, data) {
              if (err) {
                console.log('Error ' + err);
                callback(err);
              } else {
                callback();
              }
            })
          }, function (err) {
            console.log('Done deleting...');
            cb();
          });
        } else {
          console.log('Nothing to delete...');
          cb();
        }
      })
    },
    function (cb) {
      console.log('Uploading files to s3...');
      fs.readdir('./build', (err, files) => {
        async.forEach(files, function (file, cb) {
          console.log('Working on file: ' + file);
          uploadFile(file, cb);
        }, function (err) {
          console.log('DONE!');
        })
      });
    }
  ],
  function (err) {
    console.log('DONE!');
  });
<|endoftext|>


<commit_before>/**
 * @overview Generates a pdf in a new window.
 */

export default
function create(data) {
    const doc = new jsPDF(),
          SHIPMENTS = data.shipments,
          COMPANY = data.company,
          START_DATE = new Date(data.start),
          END_DATE = new Date(data.end),
          LEFT_MARGIN = 20,
          DEFAULT_FONT_SIZE = 11,
          TABLE_HEADERS = ["頁","進貨日期","材料名稱","料號","需求量","需求單位"],
          TABLE_KEYS = ["refPage","date","product","pn","amount","dept"],
          TABLE_X_POS = [],
          THIN_LINE = 0.1,
          THICK_LINE = 0.6,
          TABLE_START_Y = 30;

    // Create TABLE_X_POS positions based on desired spacing.
    [0, 10, 25, 40, 45, 25].reduce((a,b,i) => TABLE_X_POS[i] = a+b, LEFT_MARGIN);

    let posY,
        pageNo = 1;

    // Check data for problems
    if (SHIPMENTS.length === 0) {
        alert("No data for that time period.\n找不到時期資料.");
        return;
    }

    let productOrder = JSON.parse(window.localStorage.getItem("productOrder")) || [];
    productOrder = productOrder.map(each => each.pn);

    // Document settings
    doc.setFont('Times', 'Roman');
    doc.setProperties({
        title: 'Shipment Report',
        subject: 'Shipment Report',
        author: 'Taimau Chemicals',
        keywords: 'jsPDF',
        creator: 'PDF Automation by Jay W Johnson'
    });
    doc.setDrawColor(180);  // Gray lines

    // Add method for printing Chinese characters.
    doc.altText = nonASCIItext;

    /**
     * Writes the table header to document at indicated position.
     * @param   {number} y Desired print position for next line.
     * @returns {number} Next print position after writing table header
     */
    function printTableHeader(y) {
        TABLE_X_POS.forEach((x,i) => doc.altText(x, y, TABLE_HEADERS[i], DEFAULT_FONT_SIZE));

        doc.setLineWidth(THICK_LINE);
        doc.line(20, y+1, 190, y+1);
        doc.setLineWidth(THIN_LINE);
        y += 5;

        return y;
    }

    /**
     * Returns a Taiwan year date string for printing.
     * @param   {object} date Date object
     * @returns {string} Formatted date string with Taiwan year (e.g. "105 / 2 / 14").
     */
    function taiwanDateFormat(date) {
        return `${date.getFullYear()-1911} / ${date.getMonth()+1} / ${date.getDate()}`;
    }

    /**
     * Writes the company name and time period at top and page number at bottom.
     */
    function printHeadFoot() {
        doc.altText(15, 15, COMPANY, 18);
        doc.altText(15, 20, taiwanDateFormat(START_DATE) +
                    " ~ " + taiwanDateFormat(END_DATE), 12);
        doc.altText(78, 15, "台茂槽車進貨需求確認單", 14);
        doc.altText(104, 290, pageNo++, DEFAULT_FONT_SIZE);
    }

    function calcSummaryData() {
        const units = Object.keys(
            d3.nest()
            .key(d => d.unit)
            .rollup(array => null)
            .map(SHIPMENTS)
        );

        // Nest by product number (pn)
        const pnData = d3.nest()
            .key(d => d.pn)
            .rollup(array => Object.assign(
                {product: array[0].product, pn: array[0].pn},
                d3.nest().key(d => d.unit)
                .rollup(a => d3.sum(a, d => d.amount)).map(array)
            ))
            .map(SHIPMENTS);

        // Convert object to array.
        const pnDataArray = Object.keys(pnData).map(key => pnData[key]);

        return [units, pnDataArray];
    }

    // Temporarily store recent refPage and shipment.
    let refPage = undefined;
    let shipment = undefined;

    // Print 1st header/footer
    printHeadFoot();

    // Print product summary table header
    const UNIT_AMT_SPACING = 15;
    const [unitNames, pnData] = calcSummaryData();
    posY = TABLE_START_Y;  // START POSITION for data tables
    doc.altText(LEFT_MARGIN, posY, "PRODUCT SUMMARY", DEFAULT_FONT_SIZE+3);
    posY += 6;
    doc.altText(LEFT_MARGIN, posY, "材料名稱", DEFAULT_FONT_SIZE);
    doc.altText(LEFT_MARGIN+30, posY, "料號", DEFAULT_FONT_SIZE);
    let ui;
    for (ui=0; ui<unitNames.length; ui++) {
//        doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, unitNames[ui], DEFAULT_FONT_SIZE);
    }
    // Show totals if more then one unit is shown.
//    if (unitNames.length > 1) {
    ui = 0;
    if (ui === 0) {
        doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, "總額", DEFAULT_FONT_SIZE);
    }
    doc.setLineWidth(THICK_LINE);
    doc.line(20, posY+1, 190, posY+1);

    // Print product summary table rows
    doc.setLineWidth(THIN_LINE);
    const dataPNs = pnData.map(each => each.pn);

    for (let poi in productOrder) {
        const pn = productOrder[poi];

        if (!pn) {
            posY += 5;
        } else if (dataPNs.indexOf(pn) >= 0) {
            posY += 5;
            let i = dataPNs.indexOf(pn);
            doc.altText(LEFT_MARGIN, posY, pnData[i].product, DEFAULT_FONT_SIZE);
            doc.altText(LEFT_MARGIN+30, posY, pnData[i].pn, DEFAULT_FONT_SIZE-2);
            let allUnitsTotal = 0;
            let ui;
            /**
             * Per unit breakdown not wanted. Skipping for now.
             */
            for (ui=0; ui<unitNames.length; ui++) {
                const UNIT = unitNames[ui];
//                doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, pnData[i][UNIT] || "", DEFAULT_FONT_SIZE);
                allUnitsTotal += pnData[i][UNIT] || 0;
            }
            ui = 0;
            // Show totals if more then one unit is shown.
//            if (unitNames.length > 1) {
            if (ui === 0) {
                doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, `${allUnitsTotal}`, DEFAULT_FONT_SIZE);
            }
        }
    }
    for (let each of pnData) {
        if (productOrder.indexOf(each.pn) >= 0) { continue; }

        posY += 5;
        doc.altText(LEFT_MARGIN, posY, each.product, DEFAULT_FONT_SIZE);
        doc.altText(LEFT_MARGIN+30, posY, each.pn, DEFAULT_FONT_SIZE-2);
        let allUnitsTotal = 0;
        let ui;
        for (ui=0; ui<unitNames.length; ui++) {
            const UNIT = unitNames[ui];
//            doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, each[UNIT] || "", DEFAULT_FONT_SIZE);
            allUnitsTotal += each[UNIT] || 0;
        }
        // Show totals if more then one unit is shown.
//        if (unitNames.length > 1) {
        ui = 0;
        if (ui === 0) {
            doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, `${allUnitsTotal}`, DEFAULT_FONT_SIZE);
        }
    }

    // Print shipments table
    posY += 12;
    doc.altText(LEFT_MARGIN, posY, "SHIPMENTS", DEFAULT_FONT_SIZE+3);
    posY += 6;
    doc.setLineWidth(THIN_LINE);
    posY = printTableHeader(posY);
    for (let i=0; i<SHIPMENTS.length; i++) {
        shipment = SHIPMENTS[i];

        // NEW PAGE when reaching end. Leave space for summary
        if (posY > 275) {
            doc.addPage();
            printHeadFoot();
            posY = printTableHeader(TABLE_START_Y);
        }

        if (shipment.refPage !== refPage) {
            doc.altText(TABLE_X_POS[0], posY, shipment.refPage, DEFAULT_FONT_SIZE-1);
            refPage = shipment.refPage;
            doc.line(20, posY+1-5, 190, posY+1-5);
        }
        const date = new Date(shipment.date);
        doc.altText(TABLE_X_POS[1], posY, `${date.getMonth()+1} / ${date.getDate()}`, DEFAULT_FONT_SIZE-1);
        doc.altText(TABLE_X_POS[2], posY, shipment[TABLE_KEYS[2]], DEFAULT_FONT_SIZE-1);
        doc.setTextColor(100);
        doc.altText(TABLE_X_POS[3], posY, shipment[TABLE_KEYS[3]], DEFAULT_FONT_SIZE-2);
        doc.setTextColor(0);
        doc.altText(TABLE_X_POS[4], posY, shipment[TABLE_KEYS[4]], DEFAULT_FONT_SIZE-1);
        doc.altText(TABLE_X_POS[5], posY, `${shipment.dept} ${shipment.unit}`, DEFAULT_FONT_SIZE-1);
        posY+= 5;
    }

    doc.output('dataurlnewwindow');
}
<commit_msg>PDF Ref Page format fix<commit_after>/**
 * @overview Generates a pdf in a new window.
 */

export default
function create(data) {
    const doc = new jsPDF(),
          SHIPMENTS = data.shipments,
          COMPANY = data.company,
          START_DATE = new Date(data.start),
          END_DATE = new Date(data.end),
          LEFT_MARGIN = 20,
          DEFAULT_FONT_SIZE = 11,
          TABLE_HEADERS = ["頁","進貨日期","材料名稱","料號","需求量","需求單位"],
          TABLE_KEYS = ["refPage","date","product","pn","amount","dept"],
          TABLE_X_POS = [],
          THIN_LINE = 0.1,
          THICK_LINE = 0.6,
          TABLE_START_Y = 30;

    // Create TABLE_X_POS positions based on desired spacing.
    [0, 10, 25, 40, 45, 25].reduce((a,b,i) => TABLE_X_POS[i] = a+b, LEFT_MARGIN);

    let posY,
        pageNo = 1;

    // Check data for problems
    if (SHIPMENTS.length === 0) {
        alert("No data for that time period.\n找不到時期資料.");
        return;
    }

    let productOrder = JSON.parse(window.localStorage.getItem("productOrder")) || [];
    productOrder = productOrder.map(each => each.pn);

    // Document settings
    doc.setFont('Times', 'Roman');
    doc.setProperties({
        title: 'Shipment Report',
        subject: 'Shipment Report',
        author: 'Taimau Chemicals',
        keywords: 'jsPDF',
        creator: 'PDF Automation by Jay W Johnson'
    });
    doc.setDrawColor(180);  // Gray lines

    // Add method for printing Chinese characters.
    doc.altText = nonASCIItext;

    /**
     * Writes the table header to document at indicated position.
     * @param   {number} y Desired print position for next line.
     * @returns {number} Next print position after writing table header
     */
    function printTableHeader(y) {
        TABLE_X_POS.forEach((x,i) => doc.altText(x, y, TABLE_HEADERS[i], DEFAULT_FONT_SIZE));

        doc.setLineWidth(THICK_LINE);
        doc.line(20, y+1, 190, y+1);
        doc.setLineWidth(THIN_LINE);
        y += 5;

        return y;
    }

    /**
     * Returns a Taiwan year date string for printing.
     * @param   {object} date Date object
     * @returns {string} Formatted date string with Taiwan year (e.g. "105 / 2 / 14").
     */
    function taiwanDateFormat(date) {
        return `${date.getFullYear()-1911} / ${date.getMonth()+1} / ${date.getDate()}`;
    }

    /**
     * Writes the company name and time period at top and page number at bottom.
     */
    function printHeadFoot() {
        doc.altText(15, 15, COMPANY, 18);
        doc.altText(15, 20, taiwanDateFormat(START_DATE) +
                    " ~ " + taiwanDateFormat(END_DATE), 12);
        doc.altText(78, 15, "台茂槽車進貨需求確認單", 14);
        doc.altText(104, 290, pageNo++, DEFAULT_FONT_SIZE);
    }

    function calcSummaryData() {
        const units = Object.keys(
            d3.nest()
            .key(d => d.unit)
            .rollup(array => null)
            .map(SHIPMENTS)
        );

        // Nest by product number (pn)
        const pnData = d3.nest()
            .key(d => d.pn)
            .rollup(array => Object.assign(
                {product: array[0].product, pn: array[0].pn},
                d3.nest().key(d => d.unit)
                .rollup(a => d3.sum(a, d => d.amount)).map(array)
            ))
            .map(SHIPMENTS);

        // Convert object to array.
        const pnDataArray = Object.keys(pnData).map(key => pnData[key]);

        return [units, pnDataArray];
    }

    // Temporarily store recent refPage and shipment.
    let refPage = undefined;
    let shipment = undefined;

    // Print 1st header/footer
    printHeadFoot();

    // Print product summary table header
    const UNIT_AMT_SPACING = 15;
    const [unitNames, pnData] = calcSummaryData();
    posY = TABLE_START_Y;  // START POSITION for data tables
    doc.altText(LEFT_MARGIN, posY, "PRODUCT SUMMARY", DEFAULT_FONT_SIZE+3);
    posY += 6;
    doc.altText(LEFT_MARGIN, posY, "材料名稱", DEFAULT_FONT_SIZE);
    doc.altText(LEFT_MARGIN+30, posY, "料號", DEFAULT_FONT_SIZE);
    let ui;
    for (ui=0; ui<unitNames.length; ui++) {
//        doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, unitNames[ui], DEFAULT_FONT_SIZE);
    }
    // Show totals if more then one unit is shown.
//    if (unitNames.length > 1) {
    ui = 0;
    if (ui === 0) {
        doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, "總額", DEFAULT_FONT_SIZE);
    }
    doc.setLineWidth(THICK_LINE);
    doc.line(20, posY+1, 190, posY+1);

    // Print product summary table rows
    doc.setLineWidth(THIN_LINE);
    const dataPNs = pnData.map(each => each.pn);

    for (let poi in productOrder) {
        const pn = productOrder[poi];

        if (!pn) {
            posY += 5;
        } else if (dataPNs.indexOf(pn) >= 0) {
            posY += 5;
            let i = dataPNs.indexOf(pn);
            doc.altText(LEFT_MARGIN, posY, pnData[i].product, DEFAULT_FONT_SIZE);
            doc.altText(LEFT_MARGIN+30, posY, pnData[i].pn, DEFAULT_FONT_SIZE-2);
            let allUnitsTotal = 0;
            let ui;
            /**
             * Per unit breakdown not wanted. Skipping for now.
             */
            for (ui=0; ui<unitNames.length; ui++) {
                const UNIT = unitNames[ui];
//                doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, pnData[i][UNIT] || "", DEFAULT_FONT_SIZE);
                allUnitsTotal += pnData[i][UNIT] || 0;
            }
            ui = 0;
            // Show totals if more then one unit is shown.
//            if (unitNames.length > 1) {
            if (ui === 0) {
                doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, `${allUnitsTotal}`, DEFAULT_FONT_SIZE);
            }
        }
    }
    for (let each of pnData) {
        if (productOrder.indexOf(each.pn) >= 0) { continue; }

        posY += 5;
        doc.altText(LEFT_MARGIN, posY, each.product, DEFAULT_FONT_SIZE);
        doc.altText(LEFT_MARGIN+30, posY, each.pn, DEFAULT_FONT_SIZE-2);
        let allUnitsTotal = 0;
        let ui;
        for (ui=0; ui<unitNames.length; ui++) {
            const UNIT = unitNames[ui];
//            doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, each[UNIT] || "", DEFAULT_FONT_SIZE);
            allUnitsTotal += each[UNIT] || 0;
        }
        // Show totals if more then one unit is shown.
//        if (unitNames.length > 1) {
        ui = 0;
        if (ui === 0) {
            doc.altText(LEFT_MARGIN+65+UNIT_AMT_SPACING*ui, posY, `${allUnitsTotal}`, DEFAULT_FONT_SIZE);
        }
    }

    // Print shipments table
    posY += 12;
    doc.altText(LEFT_MARGIN, posY, "SHIPMENTS", DEFAULT_FONT_SIZE+3);
    posY += 6;
    doc.setLineWidth(THIN_LINE);
    posY = printTableHeader(posY);
    for (let i=0; i<SHIPMENTS.length; i++) {
        shipment = SHIPMENTS[i];

        // NEW PAGE when reaching end. Leave space for summary
        if (posY > 275) {
            doc.addPage();
            printHeadFoot();
            posY = printTableHeader(TABLE_START_Y);
        }

        if (shipment.refPage !== refPage) {
            doc.altText(TABLE_X_POS[0], posY, String(shipment.refPage).split(".").map(ea => Number(ea)).join("-"), DEFAULT_FONT_SIZE-1);
            refPage = shipment.refPage;
            doc.line(20, posY+1-5, 190, posY+1-5);
        }
        const date = new Date(shipment.date);
        doc.altText(TABLE_X_POS[1], posY, `${date.getMonth()+1} / ${date.getDate()}`, DEFAULT_FONT_SIZE-1);
        doc.altText(TABLE_X_POS[2], posY, shipment[TABLE_KEYS[2]], DEFAULT_FONT_SIZE-1);
        doc.setTextColor(100);
        doc.altText(TABLE_X_POS[3], posY, shipment[TABLE_KEYS[3]], DEFAULT_FONT_SIZE-2);
        doc.setTextColor(0);
        doc.altText(TABLE_X_POS[4], posY, shipment[TABLE_KEYS[4]], DEFAULT_FONT_SIZE-1);
        doc.altText(TABLE_X_POS[5], posY, `${shipment.dept} ${shipment.unit}`, DEFAULT_FONT_SIZE-1);
        posY+= 5;
    }

    doc.output('dataurlnewwindow');
}
<|endoftext|>


<commit_before>/* global AFRAME */

/**
 * Component that listens to an event, fades out an entity, swaps the texture, and fades it
 * back in.
 */
AFRAME.registerComponent('set-image', {
  schema: {
    on: {type: 'string'},
    target: {type: 'selector'},
    src: {type: 'string'},
    dur: {type: 'number', default: 300}
  },

  init: function () {
    var data = this.data;
    var el = this.el;

    this.setupFadeAnimation();

    el.addEventListener(data.on, function () {
      // Fade out image.
      data.target.emit('set-image-fade');
      // Wait for fade to complete.
      setTimeout(function () {
        // Set image.
        data.target.setAttribute('material', 'src', data.src);
      }, data.dur);
    });
  },

  /**
   * Setup fade-in + fade-out.
   */
  setupFadeAnimation: function () {
    var data = this.data;
    var targetEl = this.data.target;

    // Only set up once.
    if (targetEl.dataset.setImageFadeSetup) { return; }
    targetEl.dataset.setImageFadeSetup = true;

    // Create animation.
    targetEl.setAttribute('animation__fade', {
      property: 'material.color',
      startEvents: 'set-image-fade',
      dir: 'alternate',
      dur: data.dur,
      from: '#FFF',
      to: '#000'
    });
  }
});
<commit_msg>Delete set-image.js<commit_after><|endoftext|>


<commit_before>/*global SpritzLoginDialog, $, SpritzSettings */

enyo.kind({
    name: "SpritzLoginDialog",
    kind: "onyx.Popup",
    style: "text-align: center; width: 80%; z-index: 130; margin: 4% 9%; height: 90%;",
    scrim: true,
    modal: true,
    autoDismiss: true,
    floating: true,
    centered: true,
    showTransitions: true,
    apiRoot: "https://api.spritzinc.com/api-server/v1/",
    components: [
//        {
//            kind: "enyo.Scroller",
//            classe: "enyo-fill",
//            components: [
        {
            kind: "enyo.FittableRows",
            classes: "enyo-fill",
            components: [
                {
                    name: "message",
                    content: "Loging in to spritz. Please log in to spritz in new window and copy result and paste it below."
                },
                {
                    classes: "enyo-fill",
                    fit: true,
                    name: "webView",
                    tag: "iframe",
                    attributes: {sandbox: "allow-scripts allow-forms allow-same-origin"},
                    onload: "webviewLoaded"
                },
                {
                    kind: "onyx.InputDecorator",
                    style: "display: block; width: 90%; margin: 10px auto;",
                    components: [
                        {
                            classes: "enyo-fill",
                            name: "resultEntry",
                            kind: "onyx.Input",
                            placeholder: "Paste result here"
                        }
                    ]
                },
                {
                    style: "display: block; margin: 10px auto;",
                    kind: "onyx.Button",
                    content: "Finish Auth",
                    name: "finishBtn",
                    ontap: "doFinish"
                },
                {
                    style: "display: block; margin: 10px auto;",
                    kind: "onyx.Button",
                    content: "Retry",
                    name: "retryBtn",
                    ontap: "doRetry"
                }
            ]
        }
//            ]
//        }
    ],
    published: {
        loginResult: false
    },
    doFinish: function () {
        var auth = this.$.resultEntry.getValue();
        if (auth) {
            this.loginResult = auth;
            SpritzClient.setAuthResponse(auth);
            //moboreader.Spritz.init();
            this.hide();
        }
    },
    doRetry: function () {
        var url = this.apiRoot + "oauth/authorize?" +
            //c=Spritz_JSSDK_1.2.2
            "c=" + encodeURIComponent(SPRITZ.client.VersionInfo.name + "_" + SPRITZ.client.VersionInfo.version) + "&" +
            //response_type=token
            "response_type=token&" +
            //client_id= ....
            "client_id=" + SpritzSettings.clientId + "&" +
            //redirect_uri=...
            "redirect_uri=" + encodeURIComponent(SpritzSettings.redirectUri);
        this.log("Setting src to " + url);
        this.$.webView.setSrc(url);
        //SpritzClient.userLogin();
    },
    webviewLoaded: function () {
        var title = this.$.webView.node.contentDocument.title;
        this.log("Got new title: ", title);
        if (title.indexOf("token: ") === 0) {
            var auth = title.substr(7);
            this.log("Got token: " + auth);
            SpritzClient.setAuthResponse(auth);
        }
    }
});

enyo.singleton({
    name: "moboreader.Spritz",

    published: {
        wordCompleted: 0,
        totalWords: 0,
        running: false,
        numDownloading: 0,
        available: false,
        username: "Login"
    },
    bindings: [
        { from: "^.moboreader.Prefs.useSpritz", to: ".available" }
    ],
    dlCounter: 0,
    initialized: false,

    availableChanged: function () {
        this.log("Need to activate Spritz: ", moboreader.Prefs.useSpritz);
        if (moboreader.Prefs.useSpritz) {
            if (window.$ === undefined && !this.loadingJQuery) {
                //load jquery
                this.loadScript("jquery-2.1.0.min.js");
                this.loadingJQuery = true;
            }
            if (window.SpritzClient === undefined && !this.loadingSpritz) {
                if (window.$) {
                    //load spritz
                    this.loadScript("spritz.1.2.2.min.js", "spritzjs");
                    this.loadingSpritz = true;
                } else {
                    this.log("Delaying spritz loading until jquery is ready.");
                    setTimeout(this.availableChanged.bind(this), 100);
                }
            }
        }
    },

    login: function () {
        /*if (popupWindow) {
            SpritzClient.userLogin();
        }*/
        if (SpritzClient.isUserLoggedIn()) {
            SpritzClient.userLogout();
        } else {
            this.dialog = new SpritzLoginDialog();
            this.dialog.show();
            this.dialog.doRetry();
        }
    },

    loadScript: function (name, id) {
        this.log("Loading ", name);
        var head = document.getElementsByTagName("head")[0],
            script = document.createElement("script");
        script.type = "text/javascript";
        script.charset = "utf-8";
        script.src = "assets/jslibraries/" + name;
        if (id) {
            script.id = id;
        }
        head.appendChild(script);
    },

    init: function () {
        var node = $("#spritzer"),
            options = {
                defaultSpeed: 500,
                speedItems: [250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900,  950, 1000],
                redicleWidth: node.width() - 30,

                // These must correspond to controlTitles below
                controlButtons: ["rewind", "back", "pauseplay", "forward"],

                header: {
                    close: false,
                    login: false
                },
                controlTitles: {
                    pause: "Pause",
                    play: "Play",
                    rewind: "Back to beginning",
                    back: "Previous sentence",
                    forware: "Next sentence"
                },
                placeholder: {
                    startText: "Tap to spritz",
                    endText: "Tap to close spritz dialog."
                }
            };

        SPRITZ.utils.debugLevel = 10000000; //make spritz talk to us :)
        if (this.initialized) {
            this.spritzController.detach();
            delete this.spritzController;
        }

        this.spritzController = new SPRITZ.spritzinc.SpritzerController(options);
        this.spritzController.attach(node);
        this.spritzController.setProgressReporter(this.bindSafely("receiveProgress"));

        this.initialized = true;
        this.setUsername(SpritzClient.getUserName() || "Login");

        //if (!SpritzClient.isUserLoggedIn()) {
            //this.login();
        var btn = document.getElementsByClassName("spritzer-login-btn")[0];
        if (btn) {
            btn.addEventListener("click", function () { this.login(false); }.bind(this));
        }
        //}

        setInterval(function () {
            this.setRunning(this.isRunning());
        }.bind(this), 100);
    },

    resetArticle: function (articleModel) {
        articleModel.spritzOk = false;
        delete articleModel.spritzModel;
        delete articleModel.spritzModelPersist;
    },

    receiveProgress: function (completed, total) {
        this.setWordCompleted(completed);
        this.setTotalWords(total);
    },

    start: function (articleModel, restart) {
        var spritzModel;

        if (!this.initialized) {
            this.init();
        }

        if (articleModel.spritzOk && articleModel.spritzModel) {
            spritzModel = articleModel.spritzModel;
        } else if (articleModel.spritzModelPersist) {
            articleModel.spritzModel = this.restoreSpritzModel(articleModel.spritzModelPersist);
            articleModel.spritzOk = true;
            spritzModel = articleModel.spritzModel;
            spritzModel.reset();
        } else {
            this.log("Need to download spritz model from ", articleModel.attributes.url);
            if (articleModel.spritzDownloading >= 0) {
                return articleModel.spritzDownloading;
            } else {
                return this.downloadSpritzModel(articleModel);
            }
        }

        if (restart) {
            spritzModel.reset();
        }
        this.spritzController.startSpritzing(spritzModel);
        this.pause();

        return -1;
    },
    stop: function () {
        this.spritzController.stopSpritzing();
    },

    pause: function () {
        this.spritzController.pauseSpritzing();
    },
    resume: function () {
        this.spritzController.resumeSpritzing();
    },

    setWpm: function (wpm) {
        if (!this.spritzController.setSpeed(wpm)) {
            this.spritzController.setSpeed(SPRITZ.constants.Constants.MAX_SPEED);
        }
        return this.spritzController.getSpeed();
    },

    isRunning: function () {
        return this.spritzController.spritzPanel.isRunning();
    },
    isComplete: function () {
        return this.spritzController.spritzPanel.isCompleted();
    },

    downloadSpritzModel: function (articleModel, webContent) {
        if (!webContent) {
            if (articleModel.get) {
                webContent = articleModel.get("content");
            } else {
                webContent = articleModel.content;
            }
        }
        this.dlCounter += 1;
        this.setNumDownloading(this.numDownloading + 1);
        articleModel.spritzDownloading = this.dlCounter;

        if (!webContent) {
            var url;
            if (articleModel.get) {
                url = articleModel.get("url");
            } else {
                url = articleModel.url;
            }
            SpritzClient.fetchContents(url,
                                       this.bindSafely("fetchSuccess", articleModel, this.dlCounter, webContent),
                                       this.bindSafely("fetchError", articleModel, this.dlCounter, webContent));
        } else {
            var locale = webContent,
                start = locale.indexOf("lang=\"") + 6,
                end = locale.indexOf("\"", start),
                tmpNode = document.createElement("div"),
                text = "";

            if (start >= 0 && end >= 0 && end > start) {
                locale = locale.substring(start, end);
                this.log("Extracted locale: ", locale);
            } else {
                locale = "en";
                this.error("Could not extract locale.");
            }

            //now get rid of HTML:
            tmpNode.innerHTML = webContent;
            text = tmpNode.innerText;

            SpritzClient.spritzify(text, locale,
                                   this.bindSafely("fetchSuccess", articleModel, this.dlCounter, webContent),
                                   this.bindSafely("fetchError", articleModel, this.dlCounter, webContent));
        }

        return this.dlCounter;
    },
    fetchSuccess: function (articleModel, dlId, webContent, result) {
        this.log("Got spritzData: ", result);
        if (!articleModel.attributes || !articleModel.previous) {
            this.log("Article was already destroyed.");
        } else {
            articleModel.spritzModel = result;
            articleModel.spritzOk = true;
        }
        delete articleModel.spritzDownloading;

        var spritzPersist = this.storeSpritzModel(result);

        enyo.Signals.send("onArticleDownloaded", {
            id: !!articleModel.get ? articleModel.get(articleModel.primaryKey) : articleModel.item_id,
            content: {
                web: webContent,
                spritz: spritzPersist
            },
            model: articleModel
        });

        enyo.Signals.send("onSpritzDL", {id: dlId, success: true});
        this.setNumDownloading(this.numDownloading - 1);
    },
    fetchError: function (articleModel, dlId) {
        this.log("Error fetching: ", (articleModel.get ? articleModel.get("url") : articleModel.url));
        enyo.Signals.send("onSpritzDL", {id: dlId, success: false});
        this.setNumDownloading(this.numDownloading - 1);
        delete articleModel.spritzDownloading;

        enyo.Signals.send("onArticleDownloaded", {
            id: !!articleModel.get ? articleModel.get(articleModel.primaryKey) : articleModel.item_id,
            content: {},
            model: articleModel
        });
    },

    storeSpritzModel: function (spritzModel) {
        var obj = {
            contentVersion: spritzModel.getContentVersionId(),
            words: spritzModel.getWords(),
            duration: spritzModel.getDuration(),
            locale: spritzModel.getLocale(),
            version: spritzModel.getVersion(),
            wordCount: spritzModel.getWordCount()
        };

        this.log("Created object: ", obj, " from ", spritzModel);

        return obj;
    },
    restoreSpritzModel: function (obj) {
        var words = [];
        obj.words.forEach(function (word, index) {
            words[index] = new SPRITZ.model.TimedWord(word.word, word.orp, word.multiplier, word.position, word.flags);
        });

        return new SPRITZ.model.SpritzText(obj.contentVersion, words, obj.duration, obj.locale, obj.version, obj.wordCount);
    }
});
<commit_msg>reworked spritz login to use iframe<commit_after>/*global SpritzLoginDialog, $, SpritzSettings */

enyo.kind({
    name: "SpritzLoginDialog",
    kind: "onyx.Popup",
    style: "text-align: center; width: 80%; z-index: 130; margin: 4% 9%; height: 90%;",
    scrim: true,
    modal: true,
    autoDismiss: true,
    floating: true,
    centered: true,
    showTransitions: true,
    apiRoot: "https://api.spritzinc.com/api-server/v1/",
    components: [
//        {
//            kind: "enyo.Scroller",
//            classe: "enyo-fill",
//            components: [
        {
            kind: "enyo.FittableRows",
            classes: "enyo-fill",
            components: [
                {
                    name: "message",
                    content: "Loging in to spritz. Please log in to spritz in new window and copy result and paste it below."
                },
                {
                    classes: "enyo-fill",
                    fit: true,
                    name: "webView",
                    tag: "iframe",
                    attributes: {sandbox: "allow-scripts allow-forms allow-same-origin"}
                },
                {
                    style: "display: block; margin: 10px auto;",
                    kind: "onyx.Button",
                    content: "Retry",
                    name: "retryBtn",
                    ontap: "doRetry"
                }
            ]
        }
//            ]
//        }
    ],
    doRetry: function () {
        function addListener() {
            if (that.$.webView.eventNode) {
                that.$.webView.eventNode.onload = that.bindSafely("webviewLoaded");
            } else {
                that.log("Need to retry binding.");
                setTimeout(addListener, 10);
            }
        }

        var url = this.apiRoot + "oauth/authorize?" +
            //c=Spritz_JSSDK_1.2.2
            "c=" + encodeURIComponent(SPRITZ.client.VersionInfo.name + "_" + SPRITZ.client.VersionInfo.version) + "&" +
            //response_type=token
            "response_type=token&" +
            //client_id= ....
            "client_id=" + SpritzSettings.clientId + "&" +
            //redirect_uri=...
            "redirect_uri=" + encodeURIComponent(SpritzSettings.redirectUri), that = this;
        this.log("Setting src to " + url);
        this.$.webView.setSrc(url);
        addListener();
    },
    webviewLoaded: function () {
        this.log("WebView loaded!");
        var title = this.$.webView.node.contentDocument.title, auth;
        this.log("Got new title: ", title);
        if (title.indexOf("token: ") === 0) {
            auth = title.substr(7);
            this.log("Got token: " + auth);
            SpritzClient.setAuthResponse(auth, moboreader.Spritz.updateUsername.bind(moboreader.Spritz));
            this.hide();
        }
    }
});

enyo.singleton({
    name: "moboreader.Spritz",

    published: {
        wordCompleted: 0,
        totalWords: 0,
        running: false,
        numDownloading: 0,
        available: false,
        username: "Login"
    },
    bindings: [
        { from: "^.moboreader.Prefs.useSpritz", to: ".available" }
    ],
    dlCounter: 0,
    initialized: false,

    availableChanged: function () {
        this.log("Need to activate Spritz: ", moboreader.Prefs.useSpritz);
        if (moboreader.Prefs.useSpritz) {
            if (window.$ === undefined && !this.loadingJQuery) {
                //load jquery
                this.loadScript("jquery-2.1.0.min.js");
                this.loadingJQuery = true;
            }
            if (window.SpritzClient === undefined && !this.loadingSpritz) {
                if (window.$) {
                    //load spritz
                    this.loadScript("spritz.1.2.2.min.js", "spritzjs");
                    this.loadingSpritz = true;
                } else {
                    this.log("Delaying spritz loading until jquery is ready.");
                    setTimeout(this.availableChanged.bind(this), 100);
                }
            }
        }
    },

    login: function () {
        if (SpritzClient.isUserLoggedIn()) {
            SpritzClient.userLogout();
        } else {
            SpritzClient.userLogout(); //sometimes spritz does not recognize a user to be logged in.
            this.dialog = new SpritzLoginDialog();
            this.dialog.show();
            this.dialog.doRetry();
        }
    },

    loadScript: function (name, id) {
        this.log("Loading ", name);
        var head = document.getElementsByTagName("head")[0],
            script = document.createElement("script");
        script.type = "text/javascript";
        script.charset = "utf-8";
        script.src = "assets/jslibraries/" + name;
        if (id) {
            script.id = id;
        }
        head.appendChild(script);
    },

    updateUsername: function () {
        this.log("Updating username to " + SpritzClient.getUserName());
        this.setUsername(SpritzClient.getUserName() || "Login");
    },

    init: function () {
        var node = $("#spritzer"),
            options = {
                defaultSpeed: 500,
                speedItems: [250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900,  950, 1000],
                redicleWidth: node.width() - 30,

                // These must correspond to controlTitles below
                controlButtons: ["rewind", "back", "pauseplay", "forward"],

                header: {
                    close: false,
                    login: false
                },
                controlTitles: {
                    pause: "Pause",
                    play: "Play",
                    rewind: "Back to beginning",
                    back: "Previous sentence",
                    forware: "Next sentence"
                },
                placeholder: {
                    startText: "Tap to spritz",
                    endText: "Tap to close spritz dialog."
                }
            };

        SPRITZ.utils.debugLevel = 10000000; //make spritz talk to us :)
        if (this.initialized) {
            this.spritzController.detach();
            delete this.spritzController;
        }

        this.spritzController = new SPRITZ.spritzinc.SpritzerController(options);
        this.spritzController.attach(node);
        this.spritzController.setProgressReporter(this.bindSafely("receiveProgress"));
        SpritzClient.registerLoginCallback(this.bindSafely("updateUsername"));
        SpritzClient.logoutCallback = this.bindSafely("updateUsername");

        this.initialized = true;
        this.updateUsername();

        setInterval(function () {
            this.setRunning(this.isRunning());
        }.bind(this), 100);
    },

    resetArticle: function (articleModel) {
        articleModel.spritzOk = false;
        delete articleModel.spritzModel;
        delete articleModel.spritzModelPersist;
    },

    receiveProgress: function (completed, total) {
        this.setWordCompleted(completed);
        this.setTotalWords(total);
    },

    start: function (articleModel, restart) {
        var spritzModel;

        if (!this.initialized) {
            this.init();
        }

        if (articleModel.spritzOk && articleModel.spritzModel) {
            spritzModel = articleModel.spritzModel;
        } else if (articleModel.spritzModelPersist) {
            articleModel.spritzModel = this.restoreSpritzModel(articleModel.spritzModelPersist);
            articleModel.spritzOk = true;
            spritzModel = articleModel.spritzModel;
            spritzModel.reset();
        } else {
            this.log("Need to download spritz model from ", articleModel.attributes.url);
            if (articleModel.spritzDownloading >= 0) {
                return articleModel.spritzDownloading;
            } else {
                return this.downloadSpritzModel(articleModel);
            }
        }

        if (restart) {
            spritzModel.reset();
        }
        this.spritzController.startSpritzing(spritzModel);
        this.pause();

        return -1;
    },
    stop: function () {
        this.spritzController.stopSpritzing();
    },

    pause: function () {
        this.spritzController.pauseSpritzing();
    },
    resume: function () {
        this.spritzController.resumeSpritzing();
    },

    setWpm: function (wpm) {
        if (!this.spritzController.setSpeed(wpm)) {
            this.spritzController.setSpeed(SPRITZ.constants.Constants.MAX_SPEED);
        }
        return this.spritzController.getSpeed();
    },

    isRunning: function () {
        return this.spritzController.spritzPanel.isRunning();
    },
    isComplete: function () {
        return this.spritzController.spritzPanel.isCompleted();
    },

    downloadSpritzModel: function (articleModel, webContent) {
        if (!webContent) {
            if (articleModel.get) {
                webContent = articleModel.get("content");
            } else {
                webContent = articleModel.content;
            }
        }
        this.dlCounter += 1;
        this.setNumDownloading(this.numDownloading + 1);
        articleModel.spritzDownloading = this.dlCounter;

        if (!webContent) {
            var url;
            if (articleModel.get) {
                url = articleModel.get("url");
            } else {
                url = articleModel.url;
            }
            SpritzClient.fetchContents(url,
                                       this.bindSafely("fetchSuccess", articleModel, this.dlCounter, webContent),
                                       this.bindSafely("fetchError", articleModel, this.dlCounter, webContent));
        } else {
            var locale = webContent,
                start = locale.indexOf("lang=\"") + 6,
                end = locale.indexOf("\"", start),
                tmpNode = document.createElement("div"),
                text = "";

            if (start >= 0 && end >= 0 && end > start) {
                locale = locale.substring(start, end);
                this.log("Extracted locale: ", locale);
            } else {
                locale = "en";
                this.error("Could not extract locale.");
            }

            //now get rid of HTML:
            tmpNode.innerHTML = webContent;
            text = tmpNode.innerText;

            SpritzClient.spritzify(text, locale,
                                   this.bindSafely("fetchSuccess", articleModel, this.dlCounter, webContent),
                                   this.bindSafely("fetchError", articleModel, this.dlCounter, webContent));
        }

        return this.dlCounter;
    },
    fetchSuccess: function (articleModel, dlId, webContent, result) {
        this.log("Got spritzData: ", result);
        if (!articleModel.attributes || !articleModel.previous) {
            this.log("Article was already destroyed.");
        } else {
            articleModel.spritzModel = result;
            articleModel.spritzOk = true;
        }
        delete articleModel.spritzDownloading;

        var spritzPersist = this.storeSpritzModel(result);

        enyo.Signals.send("onArticleDownloaded", {
            id: !!articleModel.get ? articleModel.get(articleModel.primaryKey) : articleModel.item_id,
            content: {
                web: webContent,
                spritz: spritzPersist
            },
            model: articleModel
        });

        enyo.Signals.send("onSpritzDL", {id: dlId, success: true});
        this.setNumDownloading(this.numDownloading - 1);
    },
    fetchError: function (articleModel, dlId) {
        this.log("Error fetching: ", (articleModel.get ? articleModel.get("url") : articleModel.url));
        enyo.Signals.send("onSpritzDL", {id: dlId, success: false});
        this.setNumDownloading(this.numDownloading - 1);
        delete articleModel.spritzDownloading;

        enyo.Signals.send("onArticleDownloaded", {
            id: !!articleModel.get ? articleModel.get(articleModel.primaryKey) : articleModel.item_id,
            content: {},
            model: articleModel
        });
    },

    storeSpritzModel: function (spritzModel) {
        var obj = {
            contentVersion: spritzModel.getContentVersionId(),
            words: spritzModel.getWords(),
            duration: spritzModel.getDuration(),
            locale: spritzModel.getLocale(),
            version: spritzModel.getVersion(),
            wordCount: spritzModel.getWordCount()
        };

        this.log("Created object: ", obj, " from ", spritzModel);

        return obj;
    },
    restoreSpritzModel: function (obj) {
        var words = [];
        obj.words.forEach(function (word, index) {
            words[index] = new SPRITZ.model.TimedWord(word.word, word.orp, word.multiplier, word.position, word.flags);
        });

        return new SPRITZ.model.SpritzText(obj.contentVersion, words, obj.duration, obj.locale, obj.version, obj.wordCount);
    }
});
<|endoftext|>


<commit_before>/**
 * THIS IS THE ENTRY POINT FOR THE CLIENT, JUST LIKE server.js IS THE ENTRY POINT FOR THE SERVER.
 */
import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import { ConnectedRouter } from 'react-router-redux';
import { renderRoutes } from 'react-router-config';
import { trigger } from 'redial';
import createBrowserHistory from 'history/createBrowserHistory';
import Loadable from 'react-loadable';
import { AppContainer as HotEnabler } from 'react-hot-loader';
import { getStoredState } from 'redux-persist';
import localForage from 'localforage';
import { socket, createApp } from 'app';
import createStore from 'redux/create';
import apiClient from 'helpers/apiClient';
import routes from 'routes';
import isOnline from 'utils/isOnline';
import asyncMatchRoutes from 'utils/asyncMatchRoutes';
import { ReduxAsyncConnect, Provider } from 'components';

const persistConfig = {
  key: 'primary',
  storage: localForage,
  whitelist: ['auth', 'info', 'chat']
};

const dest = document.getElementById('content');

const app = createApp();
const restApp = createApp('rest');
const client = apiClient();
const providers = { app, restApp, client };

function initSocket() {
  socket.on('news', data => {
    console.log(data);
    socket.emit('my other event', { my: 'data from client' });
  });
  socket.on('msg', data => {
    console.log(data);
  });

  return socket;
}

global.socket = initSocket();

(async () => {
  const storedData = await getStoredState(persistConfig);
  const online = await (window.__data ? true : isOnline());

  if (online) {
    socket.open();
    await app.authenticate().catch(() => null);
  }

  const history = createBrowserHistory();
  const data = !online ? { ...storedData, ...window.__data, online } : { ...window.__data, online };
  const store = createStore({
    history,
    data,
    helpers: providers,
    persistConfig
  });

  const hydrate = async _routes => {
    const { components, match, params } = await asyncMatchRoutes(_routes, history.location.pathname);
    const triggerLocals = {
      ...providers,
      store,
      match,
      params,
      history,
      location: history.location
    };

    await trigger('fetch', components, triggerLocals);
    await trigger('defer', components, triggerLocals);

    ReactDOM.hydrate(
      <HotEnabler>
        <Provider store={store} {...providers}>
          <ConnectedRouter history={history}>
            <ReduxAsyncConnect routes={_routes} store={store} helpers={providers}>
              {renderRoutes(_routes)}
            </ReduxAsyncConnect>
          </ConnectedRouter>
        </Provider>
      </HotEnabler>,
      dest
    );
  };

  await Loadable.preloadReady();

  await hydrate(routes);

  if (module.hot) {
    module.hot.accept('./routes', () => {
      const nextRoutes = require('./routes');
      hydrate(nextRoutes).catch(err => {
        console.error('Error on routes reload:', err);
      });
    });
  }

  if (process.env.NODE_ENV !== 'production') {
    window.React = React; // enable debugger

    if (!dest || !dest.firstChild || !dest.firstChild.attributes || !dest.firstChild.attributes['data-reactroot']) {
      console.error('Server-side React render was discarded.\n' +
          'Make sure that your initial render does not contain any client-side code.');
    }
  }

  if (__DEVTOOLS__ && !window.devToolsExtension) {
    const devToolsDest = document.createElement('div');
    window.document.body.insertBefore(devToolsDest, null);
    const DevTools = require('./containers/DevTools/DevTools');
    ReactDOM.hydrate(
      <Provider store={store}>
        <DevTools />
      </Provider>,
      devToolsDest
    );
  }

  if (online && !__DEVELOPMENT__ && 'serviceWorker' in navigator) {
    window.addEventListener('load', async () => {
      try {
        await navigator.serviceWorker.register('/dist/service-worker.js', { scope: '/' });
        console.log('Service worker registered!');
      } catch (error) {
        console.log('Error registering service worker: ', error);
      }

      await navigator.serviceWorker.ready;
      console.log('Service Worker Ready');
    });
  }
})();
<commit_msg>use React.render instead of React.hydrate on client<commit_after>/**
 * THIS IS THE ENTRY POINT FOR THE CLIENT, JUST LIKE server.js IS THE ENTRY POINT FOR THE SERVER.
 */
import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import { ConnectedRouter } from 'react-router-redux';
import { renderRoutes } from 'react-router-config';
import { trigger } from 'redial';
import createBrowserHistory from 'history/createBrowserHistory';
import Loadable from 'react-loadable';
import { AppContainer as HotEnabler } from 'react-hot-loader';
import { getStoredState } from 'redux-persist';
import localForage from 'localforage';
import { socket, createApp } from 'app';
import createStore from 'redux/create';
import apiClient from 'helpers/apiClient';
import routes from 'routes';
import isOnline from 'utils/isOnline';
import asyncMatchRoutes from 'utils/asyncMatchRoutes';
import { ReduxAsyncConnect, Provider } from 'components';

const persistConfig = {
  key: 'primary',
  storage: localForage,
  whitelist: ['auth', 'info', 'chat']
};

const dest = document.getElementById('content');

const app = createApp();
const restApp = createApp('rest');
const client = apiClient();
const providers = { app, restApp, client };

function initSocket() {
  socket.on('news', data => {
    console.log(data);
    socket.emit('my other event', { my: 'data from client' });
  });
  socket.on('msg', data => {
    console.log(data);
  });

  return socket;
}

global.socket = initSocket();

(async () => {
  const storedData = await getStoredState(persistConfig);
  const online = await (window.__data ? true : isOnline());

  if (online) {
    socket.open();
    await app.authenticate().catch(() => null);
  }

  const history = createBrowserHistory();
  const data = !online ? { ...storedData, ...window.__data, online } : { ...window.__data, online };
  const store = createStore({
    history,
    data,
    helpers: providers,
    persistConfig
  });

  const hydrate = async _routes => {
    const { components, match, params } = await asyncMatchRoutes(_routes, history.location.pathname);
    const triggerLocals = {
      ...providers,
      store,
      match,
      params,
      history,
      location: history.location
    };

    await trigger('fetch', components, triggerLocals);
    await trigger('defer', components, triggerLocals);

    ReactDOM.render(
      <HotEnabler>
        <Provider store={store} {...providers}>
          <ConnectedRouter history={history}>
            <ReduxAsyncConnect routes={_routes} store={store} helpers={providers}>
              {renderRoutes(_routes)}
            </ReduxAsyncConnect>
          </ConnectedRouter>
        </Provider>
      </HotEnabler>,
      dest
    );
  };

  await Loadable.preloadReady();

  await hydrate(routes);

  if (module.hot) {
    module.hot.accept('./routes', () => {
      const nextRoutes = require('./routes');
      hydrate(nextRoutes).catch(err => {
        console.error('Error on routes reload:', err);
      });
    });
  }

  if (process.env.NODE_ENV !== 'production') {
    window.React = React; // enable debugger

    if (!dest || !dest.firstChild || !dest.firstChild.attributes || !dest.firstChild.attributes['data-reactroot']) {
      console.error('Server-side React render was discarded.\n' +
          'Make sure that your initial render does not contain any client-side code.');
    }
  }

  if (__DEVTOOLS__ && !window.devToolsExtension) {
    const devToolsDest = document.createElement('div');
    window.document.body.insertBefore(devToolsDest, null);
    const DevTools = require('./containers/DevTools/DevTools');
    ReactDOM.hydrate(
      <Provider store={store}>
        <DevTools />
      </Provider>,
      devToolsDest
    );
  }

  if (online && !__DEVELOPMENT__ && 'serviceWorker' in navigator) {
    window.addEventListener('load', async () => {
      try {
        await navigator.serviceWorker.register('/dist/service-worker.js', { scope: '/' });
        console.log('Service worker registered!');
      } catch (error) {
        console.log('Error registering service worker: ', error);
      }

      await navigator.serviceWorker.ready;
      console.log('Service Worker Ready');
    });
  }
})();
<|endoftext|>


<commit_before><commit_msg>Begin Item Object Model system<commit_after><|endoftext|>