<commit_before>var fs = require('fs');
var path = require('path');
require('http').globalAgent.maxSockets = 20;

var mongo = require('mongodb');
var express = require('express');

var compression = require('compression')
var morgan = require('morgan');
var bodyParser = require('body-parser');
var multer = require('multer');
var lusca = require('lusca');
var favicon = require('serve-favicon');
var errorHandler = require('errorhandler');
var stylus = require('stylus');
var nib = require('nib');
var browserify = require('browserify');
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);

var _ = require('./utils.js');
var Parser = require('./parser.js');
var Evaluator = require('./evaluator.js');
var StreamInterface = require('./serverStreamInterface.js');
var Model = require('./model.js');
var ViewModel = require('./viewModel.js');
var Collection = require('./collection.js');
var Query = require('./query.js');
var DataInterface = require('./serverDataInterface.js');
var REST = require('./REST.js');

var ServerApplication = function(options) {
  // Create express app
  var expressApp = express();

  // Default options
  options = _.merge({
    mongoUrl: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://127.0.0.1:27017/declaire',
    viewsFolder: __dirname + '/../../../src/views/',
    npmPublic: ['/public']
  }, options);
  if(options.mongoDevUrl && expressApp.get('env') == 'development') {
    options.mongoUrl = options.mongoDevUrl;
  }

  // Logging
  expressApp.use(morgan('combined'));

  // Fix Safari caching bug
  expressApp.use(require('jumanji'));

  // Gzip compression
  expressApp.use(compression());

  // Mongo based sessions
  if(!process.env.SESSION_SECRET) console.warn("Warning: No SESSION_SECRET environment variable set!")
  expressApp.use(session({
    secret: process.env.SESSION_SECRET || 'devSecret',
    store: new MongoStore({url: options.mongoUrl}),
    saveUninitialized: true,
    resave: true
  }));

  // Prevent common vulnerabilities and attacks
  expressApp.use(lusca({
    // Cross site request forgery
    csrf: true,
    // Allow only images from other domains
    csp: {
      policy: {
        'default-src': "'self'",
        'img-src': '*'
      }
    },
    // Prevent clickjacking
    xframe: 'SAMEORIGIN',
    // Enforce HTTPS
    hsts: {maxAge: 31536000, includeSubDomains: true, preload: true},
    // Prevent cross site scripting
    xssProtection: true
  }));

  // Parse form data
  expressApp.use(bodyParser.json());
  expressApp.use(bodyParser.urlencoded({ extended: true }));

  // multipart/form-data
  expressApp.use(multer());

  // Compile Stylus stylesheets
  expressApp.use(stylus.middleware({
    src: __dirname + '/../../../',
    dest: __dirname + '/../../../public',
    compress: true,
    compile: function compile(str, path) {
      return stylus(str)
        .set('filename', path)
        .set('compress', true)
        .use(require('nib')())
        .import('nib');
    }
  }));

  // Serve public files
  var oneDay = 86400000;
  expressApp.use(express.static(__dirname + '/../../../public', {maxAge: oneDay}));
  _.each(options.npmPublic, function(folder) {
    expressApp.use('/' + folder, express.static(__dirname + '/../../../node_modules/' + folder, {maxAge: oneDay}));
  });

  // Serve favicon
  try { expressApp.use(favicon(__dirname + '/../public/favicon.png')) } catch(e) {
    console.error("Warning: Your application provides no icon!")
  }

  //XXX Remove this
  expressApp.get('/', function(req, res) {
    res.redirect('/pages/index');
  });

  // Package and minify JavaScript
  // Exchanges require calls to this very module with the client side implementation
  var bundle;
  var prepareBundle = function(cb) {
    if(bundle) return cb(bundle);
    process.stdout.write("Preparing Bundle...");
    // Use executed application as main script on the client as well
    var appPath = process.argv[1];
    var b = new browserify({debug: true});
    b.add(appPath);
    b.ignore('newrelic');
    b.ignore('express');
    b.ignore('connect');
    b.ignore('request');
    // Exchange require calls
    b.transform(require('aliasify'), {
      aliases: {
        "declaire": "./node_modules/declaire/src/clientAPI.js"
      },
      verbose: false
    });
    if(expressApp.get('env') == 'production') {
      b.plugin(require('minifyify'), {output: 'public/bundle.js.map', map: 'bundle.js.map'});
    }
    b.bundle(function(err, buf) {
      if(err) throw err;
      bundle = buf;
      cb(bundle);
    });
  };

  expressApp.get('/bundle.js', function(req, res) {
    res.setHeader('Content-Type', 'application/javascript');
    prepareBundle(function(bundle) {
      res.send(bundle);
    });
  });

  // Let New Relic measure uptime
  expressApp.get('/ping', function(req, res) { res.send('pong'); });

  // Inject bootstrapping script and bundle reference into head tag
  var injectScripts = function(layout) {
    var bootstrap = fs.readFileSync(__dirname + '/../../../node_modules/declaire/src/bootstrap.js', 'utf8');
    _.each(layout.children, function(node) {
      if(node.tag == 'head') {
        // Inject bootstrapping script
        var scriptTag = {
          type: 'HTMLTag',
          tag: 'script',
          children: [{
            type: 'Text',
            content: bootstrap
          }]
        };
        // node.children.push(scriptTag);
        // Inject bundle
        node.children.push({
          type: 'HTMLTag',
          tag: 'script',
          attributes: {
            src: {type: 'static', value: '/bundle.js'},
            async: {type: 'static', value: 'async'}
          },
          children: []
        });
        return false;
      }
    });
  };

  // Load and parse all templates in the views folder
  var parseTrees;
  var parseTemplates = function() {
    parseTrees = {};
    _.each(fs.readdirSync(options.viewsFolder), function(file) {
      if(path.extname(file) == '.dcl'){
        console.log("Parsing " + file);
        var fn = path.normalize(options.viewsFolder + file);
        try {
          var node = Parser.parseTemplate(fs.readFileSync(fn, 'utf8'));
          parseTrees[file] = node;
        } catch(e) {
          console.error( "Parse error: " + e.message + "\n  at " + fn + ":" + e.lineNum);
          throw e;
        }
      }
    });
    var layout = parseTrees['layout.dcl'];
    if(!layout) {
      console.error("ERROR: The main layout at " + path.normalize(options.viewsFolder + '/layout.dcl') + " could not be found!");
      process.exit(1);
    }
    injectScripts(layout);
  };
  parseTemplates();

  // Make parse trees available to client-side evaluator
  expressApp.get('/templates.json', function(req, res) {
    res.send(JSON.stringify(parseTrees));
  });

  // Save view model declarations for lookup in templates
  var viewModels = {};

  // Generic main model
  var MainModel = Model('_main', {_page: '/'});

  // Build an evaluator for the given URL
  var buildEvaluator = function(url) {
    // Create main model instance
    var mainModel = MainModel.create({_page: url});
    mainModel.set('_page', url);
    app.mainModel = mainModel;
    // Build evaluator for main layout
    var topNode = parseTrees['layout.dcl'];
    var evaluator = Evaluator(topNode, viewModels, parseTrees, StreamInterface());
    evaluator.baseScope.addLayer(mainModel);
    return evaluator;
  };

  // Render layout for the requested page
  expressApp.get('/pages/*', function(req, res) {
    res.setHeader('Content-Type', 'text/html');
    if(expressApp.get('env') == 'development') parseTemplates();
    var evaluator = buildEvaluator(req.url);
    // Stream chunks of rendered html
    evaluator.render().render(function(chunk) {
      // console.log(chunk);
      res.write(chunk.data);
      res.flush();
      if(chunk.eof) {
        res.end();
      }
    });
  });

  // Show stack traces in development
  if(expressApp.get('env') == 'development') {
    expressApp.use(errorHandler({dumpExceptions: true, showStack: true}));
  }

  var app = {
    // Export main model
    mainModel: MainModel.create(),

    // Register models and view models for use with this application
    use: function(model) {
      model.app = this;
      if(model.klass == 'ViewModel') {
        viewModels[model.name] = model;
      } else if(model.klass == 'Model') {
        var dataface = DataInterface(this, model.name);
        model.dataInterface = dataface;
        REST(model.name, expressApp, dataface).serveResource();
      }
      return model;
    },

    // Proxy model constructor
    Model: function(name, reference) {
      return this.use(Model(name, reference));
    },

    // Proxy view model constructor
    ViewModel: function(name, reference, constructor, postCb) {
      return this.use(ViewModel(name, reference, constructor, postCb));
    },

    // Proxy query constructor
    Query: function(modelOrCollection, query, options) {
      return this.use(Query(modelOrCollection, query, options));
    },

    // Connect to backend services, prepare bundle, call back
    init: function(cb) {
      var self = this;
      // Connect to database
      process.stdout.write("Connecting to database...");
      mongo.MongoClient.connect(options.mongoUrl, function(err, dbs) {
        if(err) throw err;
        console.log("done");
        self.db = dbs;
        // Mongo PubSub
        process.stdout.write("Preparing PubSub...");
        self.pubSub = require('./serverPublisher.js')(expressApp, self.db).init(function() {
          console.log("done");
          // start must be called by application code to listen for requests
          var start = function(cb) {
            var port = options.port || process.env.PORT || 3000;
            var server = expressApp.listen(port, function () {
              console.log('Listening on port ' + port);
              cb && cb();
            });
          };
          // Make sure we have a cached bundle ready before listening for requests
          prepareBundle(function() {
            console.log("done");
            cb(start, expressApp, self.db)
          });
        });
      });
    }
  };
  return app;
};

module.exports = ServerApplication;
<commit_msg>Make using socket.io from apps possible<commit_after>var fs = require('fs');
var path = require('path');
require('http').globalAgent.maxSockets = 20;

var mongo = require('mongodb');
var express = require('express');

var compression = require('compression')
var morgan = require('morgan');
var bodyParser = require('body-parser');
var multer = require('multer');
var lusca = require('lusca');
var favicon = require('serve-favicon');
var errorHandler = require('errorhandler');
var stylus = require('stylus');
var nib = require('nib');
var browserify = require('browserify');
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);

var _ = require('./utils.js');
var Parser = require('./parser.js');
var Evaluator = require('./evaluator.js');
var StreamInterface = require('./serverStreamInterface.js');
var Model = require('./model.js');
var ViewModel = require('./viewModel.js');
var Collection = require('./collection.js');
var Query = require('./query.js');
var DataInterface = require('./serverDataInterface.js');
var REST = require('./REST.js');

var ServerApplication = function(options) {
  // Create express app
  var expressApp = express();

  // Default options
  options = _.merge({
    mongoUrl: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://127.0.0.1:27017/declaire',
    viewsFolder: __dirname + '/../../../src/views/',
    npmPublic: ['/public']
  }, options);
  if(options.mongoDevUrl && expressApp.get('env') == 'development') {
    options.mongoUrl = options.mongoDevUrl;
  }

  // Logging
  expressApp.use(morgan('combined'));

  // Fix Safari caching bug
  expressApp.use(require('jumanji'));

  // Gzip compression
  expressApp.use(compression());

  // Mongo based sessions
  if(!process.env.SESSION_SECRET) console.warn("Warning: No SESSION_SECRET environment variable set!")
  expressApp.use(session({
    secret: process.env.SESSION_SECRET || 'devSecret',
    store: new MongoStore({url: options.mongoUrl}),
    saveUninitialized: true,
    resave: true
  }));

  // Prevent common vulnerabilities and attacks
  expressApp.use(lusca({
    // Cross site request forgery
    csrf: true,
    // Allow only images from other domains
    csp: {
      policy: {
        // 'default-src': "'self'",
        'img-src': '*'
      }
    },
    // Prevent clickjacking
    xframe: 'SAMEORIGIN',
    // Enforce HTTPS
    hsts: {maxAge: 31536000, includeSubDomains: true, preload: true},
    // Prevent cross site scripting
    xssProtection: true
  }));

  // Parse form data
  expressApp.use(bodyParser.json());
  expressApp.use(bodyParser.urlencoded({ extended: true }));

  // multipart/form-data
  expressApp.use(multer());

  // Compile Stylus stylesheets
  expressApp.use(stylus.middleware({
    src: __dirname + '/../../../',
    dest: __dirname + '/../../../public',
    compress: true,
    compile: function compile(str, path) {
      return stylus(str)
        .set('filename', path)
        .set('compress', true)
        .use(require('nib')())
        .import('nib');
    }
  }));

  // Serve public files
  var oneDay = 86400000;
  expressApp.use(express.static(__dirname + '/../../../public', {maxAge: oneDay}));
  _.each(options.npmPublic, function(folder) {
    expressApp.use('/' + folder, express.static(__dirname + '/../../../node_modules/' + folder, {maxAge: oneDay}));
  });

  // Serve favicon
  try { expressApp.use(favicon(__dirname + '/../public/favicon.png')) } catch(e) {
    console.error("Warning: Your application provides no icon!")
  }

  //XXX Remove this
  expressApp.get('/', function(req, res) {
    res.redirect('/pages/index');
  });

  // Package and minify JavaScript
  // Exchanges require calls to this very module with the client side implementation
  var bundle;
  var prepareBundle = function(cb) {
    if(bundle) return cb(bundle);
    process.stdout.write("Preparing Bundle...");
    // Use executed application as main script on the client as well
    var appPath = process.argv[1];
    var b = new browserify({debug: true});
    b.add(appPath);
    b.ignore('newrelic');
    b.ignore('express');
    b.ignore('connect');
    b.ignore('request');
    b.ignore('socket.io');
    // Exchange require calls
    b.transform(require('aliasify'), {
      aliases: {
        "declaire": "./node_modules/declaire/src/clientAPI.js"
      },
      verbose: false
    });
    if(expressApp.get('env') == 'production') {
      b.plugin(require('minifyify'), {output: 'public/bundle.js.map', map: 'bundle.js.map'});
    }
    b.bundle(function(err, buf) {
      if(err) throw err;
      bundle = buf;
      cb(bundle);
    });
  };

  expressApp.get('/bundle.js', function(req, res) {
    res.setHeader('Content-Type', 'application/javascript');
    prepareBundle(function(bundle) {
      res.send(bundle);
    });
  });

  // Let New Relic measure uptime
  expressApp.get('/ping', function(req, res) { res.send('pong'); });

  // Inject bootstrapping script and bundle reference into head tag
  var injectScripts = function(layout) {
    var bootstrap = fs.readFileSync(__dirname + '/../../../node_modules/declaire/src/bootstrap.js', 'utf8');
    _.each(layout.children, function(node) {
      if(node.tag == 'head') {
        // Inject bootstrapping script
        var scriptTag = {
          type: 'HTMLTag',
          tag: 'script',
          children: [{
            type: 'Text',
            content: bootstrap
          }]
        };
        // node.children.push(scriptTag);
        // Inject bundle
        node.children.push({
          type: 'HTMLTag',
          tag: 'script',
          attributes: {
            src: {type: 'static', value: '/bundle.js'},
            async: {type: 'static', value: 'async'}
          },
          children: []
        });
        return false;
      }
    });
  };

  // Load and parse all templates in the views folder
  var parseTrees;
  var parseTemplates = function() {
    parseTrees = {};
    _.each(fs.readdirSync(options.viewsFolder), function(file) {
      if(path.extname(file) == '.dcl'){
        console.log("Parsing " + file);
        var fn = path.normalize(options.viewsFolder + file);
        try {
          var node = Parser.parseTemplate(fs.readFileSync(fn, 'utf8'));
          parseTrees[file] = node;
        } catch(e) {
          console.error( "Parse error: " + e.message + "\n  at " + fn + ":" + e.lineNum);
          throw e;
        }
      }
    });
    var layout = parseTrees['layout.dcl'];
    if(!layout) {
      console.error("ERROR: The main layout at " + path.normalize(options.viewsFolder + '/layout.dcl') + " could not be found!");
      process.exit(1);
    }
    injectScripts(layout);
  };
  parseTemplates();

  // Make parse trees available to client-side evaluator
  expressApp.get('/templates.json', function(req, res) {
    res.send(JSON.stringify(parseTrees));
  });

  // Save view model declarations for lookup in templates
  var viewModels = {};

  // Generic main model
  var MainModel = Model('_main', {_page: '/'});

  // Build an evaluator for the given URL
  var buildEvaluator = function(url) {
    // Create main model instance
    var mainModel = MainModel.create({_page: url});
    mainModel.set('_page', url);
    app.mainModel = mainModel;
    // Build evaluator for main layout
    var topNode = parseTrees['layout.dcl'];
    var evaluator = Evaluator(topNode, viewModels, parseTrees, StreamInterface());
    evaluator.baseScope.addLayer(mainModel);
    return evaluator;
  };

  // Render layout for the requested page
  expressApp.get('/pages/*', function(req, res) {
    res.setHeader('Content-Type', 'text/html');
    if(expressApp.get('env') == 'development') parseTemplates();
    var evaluator = buildEvaluator(req.url);
    // Stream chunks of rendered html
    evaluator.render().render(function(chunk) {
      // console.log(chunk);
      res.write(chunk.data);
      res.flush();
      if(chunk.eof) {
        res.end();
      }
    });
  });

  // Show stack traces in development
  if(expressApp.get('env') == 'development') {
    expressApp.use(errorHandler({dumpExceptions: true, showStack: true}));
  }

  var app = {
    // Export main model
    mainModel: MainModel.create(),

    // Register models and view models for use with this application
    use: function(model) {
      model.app = this;
      if(model.klass == 'ViewModel') {
        viewModels[model.name] = model;
      } else if(model.klass == 'Model') {
        var dataface = DataInterface(this, model.name);
        model.dataInterface = dataface;
        REST(model.name, expressApp, dataface).serveResource();
      }
      return model;
    },

    // Proxy model constructor
    Model: function(name, reference) {
      return this.use(Model(name, reference));
    },

    // Proxy view model constructor
    ViewModel: function(name, reference, constructor, postCb) {
      return this.use(ViewModel(name, reference, constructor, postCb));
    },

    // Proxy query constructor
    Query: function(modelOrCollection, query, options) {
      return this.use(Query(modelOrCollection, query, options));
    },

    // Connect to backend services, prepare bundle, call back
    init: function(cb) {
      var self = this;
      // Connect to database
      process.stdout.write("Connecting to database...");
      mongo.MongoClient.connect(options.mongoUrl, function(err, dbs) {
        if(err) throw err;
        console.log("done");
        self.db = dbs;
        // Mongo PubSub
        process.stdout.write("Preparing PubSub...");
        self.pubSub = require('./serverPublisher.js')(expressApp, self.db).init(function() {
          console.log("done");
          // start must be called by application code to listen for requests
          var start = function(cb) {
            var port = options.port || process.env.PORT || 3000;
            var server = expressApp.listen(port, function () {
              console.log('Listening on port ' + port);
              cb && cb(server);
            });
          };
          // Make sure we have a cached bundle ready before listening for requests
          prepareBundle(function() {
            console.log("done");
            cb(start, expressApp, self.db)
          });
        });
      });
    }
  };
  return app;
};

module.exports = ServerApplication;
<|endoftext|>


<commit_before>import moment from 'moment'
import 'moment/locale/th'
import 'moment/locale/en-au'

/**
 * @param {[string]}      date           | '2017-04-12T17:00:00.000Z' |
 * @return {[string]}     date           | '13 April 2017 12:00 AM' |
 */
// April 13, 2017 12:00 AM
const dateTimeFormat = date => moment( date )
// April 13, 2017
const dateFormat = date => dateTimeFormat( date ).format( 'LL' )
// Apr 13, 2017
const dateShortFormat = date => dateTimeFormat( date ).format( 'll' )
// 13 เมษายน 2560 เวลา 0:00
const thaiDateTimeFormat = date => moment( date ).add( 543, 'year' ).locale( 'th' )

// 13 เมษายน 2560
const thaiDateFormat = date => thaiDateTimeFormat( date ).format( 'LL' )
// 13 เม.ย. 2560
const thaiDateShortFormat = date => thaiDateTimeFormat( date ).format( 'll' )

const second = () => 10 * 100
const minute = () => 60 * second()
const hour = () => 60 * minute()

export {
  dateFormat,
  dateShortFormat,
  dateTimeFormat,
  minute,
  second,
  thaiDateFormat,
  thaiDateShortFormat,
  thaiDateTimeFormat,
  hour,
}
<commit_msg>📝 Update datetime function<commit_after>import moment from 'moment'
import 'moment/locale/th'
import 'moment/locale/en-au'

/**
 * @param {[string]}      date           | '2017-04-12T17:00:00.000Z' |
 * @return {[string]}     date           | '13 April 2017 12:00 AM' |
 */
// April 13, 2017 12:00 AM
const dateTimeFormat = date => moment( date )
// April 13, 2017
const dateFormat = date => dateTimeFormat( date ).format( 'LL' )
// Apr 13, 2017
const dateShortFormat = date => dateTimeFormat( date ).format( 'll' )
// 13 เมษายน 2560 เวลา 0:00
const thaiDateTimeFormat = date => moment( date ).add( 543, 'year' ).locale( 'th' )
// วันที่ 13 เมษายน 2560
const thaiDateFormat = ( date, prefix = 'วันที่' ) =>
  `${ prefix } ${ thaiDateTimeFormat( date ).format( 'LL' ) }`
// 13 เม.ย. 2560
const thaiDateShortFormat = date => thaiDateTimeFormat( date ).format( 'll' )

const second = () => 10 * 100
const minute = () => 60 * second()
const hour = () => 60 * minute()

export {
  dateFormat,
  dateShortFormat,
  dateTimeFormat,
  minute,
  second,
  thaiDateFormat,
  thaiDateShortFormat,
  thaiDateTimeFormat,
  hour,
}
<|endoftext|>


<commit_before>import BaseLfo from '../core/BaseLfo';

const worker = `
var _separateArrays = false;
var _data = [];
var _separateArraysData = { time: [], data: [] };

function init() {
  _data.length = 0;
  _separateArraysData.time.length = 0;
  _separateArraysData.data.length = 0;
}

function process(time, data) {
  if (_separateArrays) {
    _separateArraysData.time.push(time);
    _separateArraysData.data.push(data);
  } else {
    var datum = { time: time, data: data };
    _data.push(datum);
  }
}

self.addEventListener('message', function(e) {
  switch (e.data.command) {
    case 'init':
      _separateArrays = e.data.separateArrays;
      init();
      break;
    case 'process':
      var time = e.data.time;
      var data = new Float32Array(e.data.buffer);
      process(time, data);
      break;
    case 'stop':
      var data = _separateArrays ? _separateArraysData : _data;
      self.postMessage({ data: data });
      init();
      break;
  }
});
`;

const definitions = {
  separateArrays: {
    type: 'boolean',
    default: false,
    constant: true,
  },
};

/**
 * Record arbitrary data from a graph.
 *
 * @param {Object} options - Override default parameters.
 * @param {Boolean} [options.separateArrays] - Format of the retrieved values:
 *  - when `false`, format is [{ time, data }, { time, data }, ...]
 *  - when `true`, format is { time: [...], data: [...] }
 *
 * @todo - handle WebWorker to be node compliant.
 *
 * @memberof module:sink
 *
 * @example
 * import * as lfo from 'waves-lfo';
 *
 * const eventIn = new EventIn({
 *   frameType: 'vector',
 *   frameSize: 2,
 *   frameRate: 0,
 * });
 *
 * const recorder = new DataRecorder();
 *
 * eventIn.connect(recorder);
 * eventIn.start();
 * recorder.start();
 */
class DataRecorder extends BaseLfo {
  constructor(options = {}) {
    super(definitions, options);

    /**
     * Define is the node is currently recording or not.
     *
     * @type {Boolean}
     * @name isRecording
     * @instance
     * @memberof module:sink.SignalRecorder
     */
    this.isRecording = false;

    // init worker
    const blob = new Blob([worker], { type: 'text/javascript' });
    this.worker = new Worker(window.URL.createObjectURL(blob));
  }

  /** @private */
  processStreamParams(prevStreamParams) {
    this.prepareStreamParams(prevStreamParams);

    this.worker.postMessage({
      command: 'init',
      separateArrays: this.params.get('separateArrays'),
    });

    this.propagateStreamParams();
  }

  /**
   * Start recording.
   */
  start() {
    this.isRecording = true;
  }

  /**
   * Stop recording and trigger the fulfillment of the promise returned by the
   * `retrieve` method.
   */
  stop() {
    if (this.isRecording) {
      this.worker.postMessage({ command: 'stop' });
      this.isRecording = false;
    }
  }

  /** @private */
  finalizeStream() {
    this.stop();
  }

  /** @private */
  processSignal(frame) {
    if (this.isRecording)
      this._sendFrame(frame);
  }

  /** @private */
  processVector(frame) {
    if (this.isRecording)
      this._sendFrame(frame);
  }

  /** @private */
  _sendFrame(frame) {
    this.frame.data = new Float32Array(frame.data);
    const buffer = this.frame.data.buffer;

    this.worker.postMessage({
      command: 'process',
      time: frame.time,
      buffer: buffer,
    }, [buffer]);
  }

  /**
   * Retrieve a promise that will be fulfilled when `stop` is called.
   *
   * @return {Promise<Array>}
   */
  retrieve() {
    return new Promise((resolve, reject) => {
      const callback = (e) => {
        this._started = false;

        this.worker.removeEventListener('message', callback, false);
        resolve(e.data.data);
      };

      this.worker.addEventListener('message', callback, false);
    });
  }
}

export default DataRecorder;

<commit_msg>updated example<commit_after>import BaseLfo from '../core/BaseLfo';

const worker = `
var _separateArrays = false;
var _data = [];
var _separateArraysData = { time: [], data: [] };

function init() {
  _data.length = 0;
  _separateArraysData.time.length = 0;
  _separateArraysData.data.length = 0;
}

function process(time, data) {
  if (_separateArrays) {
    _separateArraysData.time.push(time);
    _separateArraysData.data.push(data);
  } else {
    var datum = { time: time, data: data };
    _data.push(datum);
  }
}

self.addEventListener('message', function(e) {
  switch (e.data.command) {
    case 'init':
      _separateArrays = e.data.separateArrays;
      init();
      break;
    case 'process':
      var time = e.data.time;
      var data = new Float32Array(e.data.buffer);
      process(time, data);
      break;
    case 'stop':
      var data = _separateArrays ? _separateArraysData : _data;
      self.postMessage({ data: data });
      init();
      break;
  }
});
`;

const definitions = {
  separateArrays: {
    type: 'boolean',
    default: false,
    constant: true,
  },
};

/**
 * Record arbitrary data from a graph.
 *
 * @param {Object} options - Override default parameters.
 * @param {Boolean} [options.separateArrays] - Format of the retrieved values:
 *  - when `false`, format is [{ time, data }, { time, data }, ...]
 *  - when `true`, format is { time: [...], data: [...] }
 *
 * @todo - handle WebWorker to be node compliant.
 *
 * @memberof module:sink
 *
 * @example
 * import * as lfo from 'waves-lfo';
 *
 * const eventIn = new lfo.source.EventIn({
 *  frameType: 'vector',
 *  frameSize: 2,
 *  frameRate: 0,
 * });
 *
 * const recorder = new lfo.sink.DataRecorder();
 *
 * eventIn.connect(recorder);
 * eventIn.start();
 * recorder.start();
 *
 * recorder.retrieve()
 *  .then((result) => console.log(result))
 *  .catch((err) => console.error(err.stack));
 *
 * eventIn.process(0, [0, 1]);
 * eventIn.process(1, [1, 2]);
 *
 * recorder.stop();
 * > [{ time: 0, data: [0, 1] }, { time: 1, data: [1, 2] }];
 */
class DataRecorder extends BaseLfo {
  constructor(options = {}) {
    super(definitions, options);

    /**
     * Define is the node is currently recording or not.
     *
     * @type {Boolean}
     * @name isRecording
     * @instance
     * @memberof module:sink.SignalRecorder
     */
    this.isRecording = false;

    // init worker
    const blob = new Blob([worker], { type: 'text/javascript' });
    this.worker = new Worker(window.URL.createObjectURL(blob));
  }

  /** @private */
  processStreamParams(prevStreamParams) {
    this.prepareStreamParams(prevStreamParams);

    this.worker.postMessage({
      command: 'init',
      separateArrays: this.params.get('separateArrays'),
    });

    this.propagateStreamParams();
  }

  /**
   * Start recording.
   */
  start() {
    this.isRecording = true;
  }

  /**
   * Stop recording and trigger the fulfillment of the promise returned by the
   * `retrieve` method.
   */
  stop() {
    if (this.isRecording) {
      this.worker.postMessage({ command: 'stop' });
      this.isRecording = false;
    }
  }

  /** @private */
  finalizeStream() {
    this.stop();
  }

  /** @private */
  processSignal(frame) {
    if (this.isRecording)
      this._sendFrame(frame);
  }

  /** @private */
  processVector(frame) {
    if (this.isRecording)
      this._sendFrame(frame);
  }

  /** @private */
  _sendFrame(frame) {
    this.frame.data = new Float32Array(frame.data);
    const buffer = this.frame.data.buffer;

    this.worker.postMessage({
      command: 'process',
      time: frame.time,
      buffer: buffer,
    }, [buffer]);
  }

  /**
   * Retrieve a promise that will be fulfilled when `stop` is called.
   *
   * @return {Promise<Array>}
   */
  retrieve() {
    return new Promise((resolve, reject) => {
      const callback = (e) => {
        this._started = false;

        this.worker.removeEventListener('message', callback, false);
        resolve(e.data.data);
      };

      this.worker.addEventListener('message', callback, false);
    });
  }
}

export default DataRecorder;

<|endoftext|>


<commit_before>require('coffeescript/register') /* so we can require coffeescript */
require('coffee-cache')  /* so coffeescript doesn't get recompiled every time we require it */

if not process.env.SMC?
    process.env.SMC = path.join(process.env.HOME, '.smc')

exports.local_hub      = require('./local_hub.coffee')
exports.console_server = require('./console_server.coffee')
<commit_msg>lgtm found this -- https://lgtm.com/projects/g/sagemathinc/cocalc/snapshot/bb021b94cb910309f5cb4f6de38cd64e0fa11190/files/src/smc-project/index.js?sort=name&dir=ASC&mode=heatmap#x4883b628575f574e:1<commit_after>require("coffeescript/register"); /* so we can require coffeescript */
require("coffee-cache"); /* so coffeescript doesn't get recompiled every time we require it */

if (!process.env.SMC) {
  process.env.SMC = path.join(process.env.HOME, ".smc");
}

exports.local_hub = require("./local_hub.coffee");
exports.console_server = require("./console_server.coffee");
<|endoftext|>


<commit_before>'use strict';

angular.module('mol.controllers',[]);

angular.module('mol.datasets', [
  'ui.router',
  'ui-leaflet',
  'angular-loading-bar',
  'angular.filter',
  'ngResource',
  'ngSanitize',
  'ngCookies',
  'ngAnimate',
  'ui.bootstrap',
  'mol.facets',
  'mol.api',
  'mol.services',
  'mol.loading-indicator',
  'mol.controllers'
])
.config(['cfpLoadingBarProvider', function(cfpLoadingBarProvider) {
    cfpLoadingBarProvider.includeSpinner = false;
    cfpLoadingBarProvider.includeBar = false;
    cfpLoadingBarProvider.latencyThreshold = 500;
  }])
.config(['$httpProvider', '$locationProvider', '$sceDelegateProvider', '$urlRouterProvider', '$stateProvider',
            function($httpProvider, $locationProvider, $sceDelegateProvider, $urlRouterProvider, $stateProvider) {
  $httpProvider.defaults.useXDomain = true;
  $httpProvider.defaults.withCredentials = true;
  $locationProvider.html5Mode(true);
  $sceDelegateProvider.resourceUrlWhitelist([
    'self',
    'http:*//localhost**',
    'http*://127.0.0.1:9001/**',
    'http*://*mol.org/**',
    'http://mol.org/**',
    'https://mol.org/**',
    'http*://api.mol.org/1.0/datasets/**',
    'http*://api.mol.org/1.0/datasets/**',
    'http*://mapoflife.github.io/**',
  ]);
  $urlRouterProvider.otherwise('/');
  $stateProvider
    .state(
      'datasets', {
        abstract: true,
        views: {
          '': {
            templateUrl: 'static/app/layouts/base.html',
            controller: 'molDatasetsCtrl'
          }
        }
      }
    )
    .state(
      'datasets.all', {
        abstract: true,
        title: 'Datasets Info',
        views: {
          '': {
            templateUrl: 'static/app/layouts/sidebar.html'
          },
          'sidebar@datasets.all': {
            templateUrl: 'static/app/views/sidebar.html'
          },
          'content@datasets.all': {
            templateUrl: 'static/app/layouts/content.html'
          }
        },
        url: '/'
      }
    )
    .state(
      'datasets.all.map', {
        views: {
          'map@datasets.all': {
            templateUrl: 'static/app/views/map/main.html',
            controller: 'molDatasetsMapCtrl'
          }
        },
        url: 'map'
      }
    )
    .state(
      'datasets.all.list', {
        views: {
          'info-pane@datasets.all': {
            templateUrl: 'static/app/views/table/main.html'
          }
        },
        url: 'list'
      }
    )
    .state(
      'datasets.all.both', {
        views: {
          'map@datasets.all': {
            templateUrl: 'static/app/views/map/main.html',
            controller: 'molDatasetsMapCtrl'
          },
          'info-pane@datasets.all': {
            templateUrl: 'static/app/views/table/main.html'
          }
        },
        url: ''
      }
    )
    .state(
      'datasets.info', {
        abstract: true,
        title: 'Dataset Info',
        views: {
          '': {
            templateUrl: 'static/app/layouts/basic.html'
          },
          'content@datasets.info': {
            templateUrl: 'static/app/layouts/content.html'
          },
        },
        url: '/:dataset'
      }
    )
    .state(
      'datasets.info.map', {
        views: {
          'map@datasets.info': {
            templateUrl: 'static/app/views/map/main.html',
            controller: 'molDatasetsMapCtrl'
          },
        },
        url: '/map'
      }
    )
    .state(
      'datasets.info.info', {
        views: {
          'info-pane@datasets.info': {
            templateUrl: 'static/app/views/info/info.html',
            controller: 'molDatasetsInfoCtrl'
          }
        },
        url: '/info'
      }
    )
    .state(
      'datasets.info.both', {
        views: {
          'map@datasets.info': {
            templateUrl: 'static/app/views/map/main.html',
            controller: 'molDatasetsMapCtrl'
          },
          'info-pane@datasets.info': {
            templateUrl: 'static/app/views/info/info.html',
            controller: 'molDatasetsInfoCtrl'
          }
        },
        url: ''
      }
    );
    $locationProvider.html5Mode(true);
}])
<commit_msg> Updating domain white-list #43<commit_after>'use strict';

angular.module('mol.controllers',[]);

angular.module('mol.datasets', [
  'ui.router',
  'ui-leaflet',
  'angular-loading-bar',
  'angular.filter',
  'ngResource',
  'ngSanitize',
  'ngCookies',
  'ngAnimate',
  'ui.bootstrap',
  'mol.facets',
  'mol.api',
  'mol.services',
  'mol.loading-indicator',
  'mol.controllers'
])
.config(['cfpLoadingBarProvider', function(cfpLoadingBarProvider) {
    cfpLoadingBarProvider.includeSpinner = false;
    cfpLoadingBarProvider.includeBar = false;
    cfpLoadingBarProvider.latencyThreshold = 500;
  }])
.config(['$httpProvider', '$locationProvider', '$sceDelegateProvider', '$urlRouterProvider', '$stateProvider',
            function($httpProvider, $locationProvider, $sceDelegateProvider, $urlRouterProvider, $stateProvider) {
  $httpProvider.defaults.useXDomain = true;
  $httpProvider.defaults.withCredentials = true;
  $locationProvider.html5Mode(true);
  $sceDelegateProvider.resourceUrlWhitelist([
    'self',
    'http:*//localhost**',
    'http*://127.0.0.1:9001/**',
    'http*://*mol.org/**',
    'http://mol.org',
    'https://mol.org',
    'http*://api.mol.org/1.0/datasets/**',
    'http*://api.mol.org/1.0/datasets/**',
    'http*://mapoflife.github.io/**',
  ]);
  $urlRouterProvider.otherwise('/');
  $stateProvider
    .state(
      'datasets', {
        abstract: true,
        views: {
          '': {
            templateUrl: 'static/app/layouts/base.html',
            controller: 'molDatasetsCtrl'
          }
        }
      }
    )
    .state(
      'datasets.all', {
        abstract: true,
        title: 'Datasets Info',
        views: {
          '': {
            templateUrl: 'static/app/layouts/sidebar.html'
          },
          'sidebar@datasets.all': {
            templateUrl: 'static/app/views/sidebar.html'
          },
          'content@datasets.all': {
            templateUrl: 'static/app/layouts/content.html'
          }
        },
        url: '/'
      }
    )
    .state(
      'datasets.all.map', {
        views: {
          'map@datasets.all': {
            templateUrl: 'static/app/views/map/main.html',
            controller: 'molDatasetsMapCtrl'
          }
        },
        url: 'map'
      }
    )
    .state(
      'datasets.all.list', {
        views: {
          'info-pane@datasets.all': {
            templateUrl: 'static/app/views/table/main.html'
          }
        },
        url: 'list'
      }
    )
    .state(
      'datasets.all.both', {
        views: {
          'map@datasets.all': {
            templateUrl: 'static/app/views/map/main.html',
            controller: 'molDatasetsMapCtrl'
          },
          'info-pane@datasets.all': {
            templateUrl: 'static/app/views/table/main.html'
          }
        },
        url: ''
      }
    )
    .state(
      'datasets.info', {
        abstract: true,
        title: 'Dataset Info',
        views: {
          '': {
            templateUrl: 'static/app/layouts/basic.html'
          },
          'content@datasets.info': {
            templateUrl: 'static/app/layouts/content.html'
          },
        },
        url: '/:dataset'
      }
    )
    .state(
      'datasets.info.map', {
        views: {
          'map@datasets.info': {
            templateUrl: 'static/app/views/map/main.html',
            controller: 'molDatasetsMapCtrl'
          },
        },
        url: '/map'
      }
    )
    .state(
      'datasets.info.info', {
        views: {
          'info-pane@datasets.info': {
            templateUrl: 'static/app/views/info/info.html',
            controller: 'molDatasetsInfoCtrl'
          }
        },
        url: '/info'
      }
    )
    .state(
      'datasets.info.both', {
        views: {
          'map@datasets.info': {
            templateUrl: 'static/app/views/map/main.html',
            controller: 'molDatasetsMapCtrl'
          },
          'info-pane@datasets.info': {
            templateUrl: 'static/app/views/info/info.html',
            controller: 'molDatasetsInfoCtrl'
          }
        },
        url: ''
      }
    );
    $locationProvider.html5Mode(true);
}])
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import Highlight from 'react-syntax-highlight';
import Note from '../Note';

class OnYourOwn extends Component {
  render() {
    return(

19. On your own

In the next workshop, we will be create a Redux store to house our apps state and wire up the APIs to retreive real data and make out bar finder come alive!

Home Work

Customize the app and clean up any style tweaks you want to make before next time.

Learn about Redux, we will use it to manage all of our state and date within our app - http://redux.js.org/

We will also be using the fetch method to get our data, check out the details here - Using Fetch - MDN

Solution

You can find the solution from this workshop here: react-native-barfinder

    );
  }
}

export default OnYourOwn;
<commit_msg>updates<commit_after>import React, {Component} from 'react';
import Highlight from 'react-syntax-highlight';
import Note from '../Note';

class OnYourOwn extends Component {
  render() {
    return(

19. On your own

In the next workshop, we will be create a Redux store to house our apps state and wire up the APIs to retreive real data and make out bar finder come alive!

Home Work

Customize the app and clean up any style tweaks you want to make before next time.

Learn about Redux, we will use it to manage all of our state and date within our app - http://redux.js.org/

We will also be using the fetch method to get our data, check out the details here - Using Fetch - MDN

Solution

You can find the solution from this workshop here: react-native-workshop-3-solution

    );
  }
}

export default OnYourOwn;
<|endoftext|>


<commit_before>export default {
  dom: null, // canvas dom
  renderer: null, // 渲染器
  scene: null, // 当前场景
  camera: null, // 主摄像机
  group: null, // 三维对象组
  target: null, // 当前选中的三维对象
  ray: null, // 射线
  tick: null, // 渲染辅助标记
  /**
   * 动态方法委托
   */
  resetCamera: null,
  rendererDelegation: [], // 渲染过程委托
}
<commit_msg>清楚不需要的state<commit_after>export default {
  dom: null, // canvas dom
  renderer: null, // 渲染器
  scene: null, // 当前场景
  camera: null, // 主摄像机
  group: null, // 三维对象组
  target: null, // 当前选中的三维对象
  ray: null, // 射线
  tick: null, // 渲染辅助标记
  rendererDelegation: [], // 渲染过程委托
}
<|endoftext|>


<commit_before>import { applyMiddleware, compose, createStore } from 'redux';
import { persistStore, autoRehydrate } from 'redux-persist';
import createSagaMiddleware from 'redux-saga';
import { browserHistory } from 'react-router';
import makeRootReducer from './reducers';
import { updateLocation } from './location';
import createWSMiddleware from '../modules/ws/middleware';
import { WS_PREFIX } from '../modules/ws/constants';
import rootSaga from './sagas';

// Set the websocket options
const webSocketOptions = {
  hostname: 'outflow.local',
  port: 80,
  path: '/ws',
  autoreconnect: true,
  perMessageDeflate: true,
};

export default (initialState = {}) => {
  const wsMiddleware = createWSMiddleware(WS_PREFIX, webSocketOptions);
  const sagaMiddleware = createSagaMiddleware();
  const middleware = [wsMiddleware, sagaMiddleware];
  const enhancers = [autoRehydrate()];
  let composeEnhancers = compose;

  // Load redux dev tools
  if (__DEV__) {
    const composeWithDevToolsExtension = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
    if (typeof composeWithDevToolsExtension === 'function') {
      composeEnhancers = composeWithDevToolsExtension;
    }
  }

  // Store Instantiation and HMR Setup
  const store = createStore(
    makeRootReducer(),
    initialState,
    composeEnhancers(
      applyMiddleware(...middleware),
      ...enhancers
    )
  );
  persistStore(store);
  store.asyncReducers = {};
  sagaMiddleware.run(rootSaga);

  // To unsubscribe, invoke `store.unsubscribeHistory()` anytime
  store.unsubscribeHistory = browserHistory.listen(updateLocation(store));

  if (module.hot) {
    module.hot.accept('./reducers', () => {
      const reducers = require('./reducers').default;
      store.replaceReducer(reducers(store.asyncReducers));
    });
  }

  return store;
}
<commit_msg>Remove hard coded ws URL<commit_after>import { applyMiddleware, compose, createStore } from 'redux';
import { persistStore, autoRehydrate } from 'redux-persist';
import createSagaMiddleware from 'redux-saga';
import { browserHistory } from 'react-router';
import makeRootReducer from './reducers';
import { updateLocation } from './location';
import createWSMiddleware from '../modules/ws/middleware';
import { WS_PREFIX } from '../modules/ws/constants';
import rootSaga from './sagas';

// Set the websocket options
const hostname = window.location.hostname.indexOf('localhost') ? 'outflow.local' : window.location.hostname;
const webSocketOptions = {
  hostname,
  port: 80,
  path: '/ws',
  autoreconnect: true,
  perMessageDeflate: true,
};

export default (initialState = {}) => {
  const wsMiddleware = createWSMiddleware(WS_PREFIX, webSocketOptions);
  const sagaMiddleware = createSagaMiddleware();
  const middleware = [wsMiddleware, sagaMiddleware];
  const enhancers = [autoRehydrate()];
  let composeEnhancers = compose;

  // Load redux dev tools
  if (__DEV__) {
    const composeWithDevToolsExtension = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
    if (typeof composeWithDevToolsExtension === 'function') {
      composeEnhancers = composeWithDevToolsExtension;
    }
  }

  // Store Instantiation and HMR Setup
  const store = createStore(
    makeRootReducer(),
    initialState,
    composeEnhancers(
      applyMiddleware(...middleware),
      ...enhancers
    )
  );
  persistStore(store);
  store.asyncReducers = {};
  sagaMiddleware.run(rootSaga);

  // To unsubscribe, invoke `store.unsubscribeHistory()` anytime
  store.unsubscribeHistory = browserHistory.listen(updateLocation(store));

  if (module.hot) {
    module.hot.accept('./reducers', () => {
      const reducers = require('./reducers').default;
      store.replaceReducer(reducers(store.asyncReducers));
    });
  }

  return store;
}
<|endoftext|>


<commit_before>import store from '../store'

const initialState = {
  appMode: 'full',
  navigationMode: 'forward',
  isRouterEnabled: false,
  router: {},
  history: [],
  backwardNavigation: false,
  componentList: {},
  goBackView: '',
  diameters: {},
  usePercentSizes: false,
  percentSizes: {
    xxl: 30,
    xl: 20,
    l: 16,
    m: 8,
    s: 6,
    xs: 4,
    xxs: 2
  },
  minSizesInPixels: {
    xxl: 180,
    xl: 150,
    l: 100,
    m: 80,
    s: 50,
    xs: 30,
    xxs: 20
  },
  appStyle: {
    theme: 'theme-black',
    mode: 'mode-dark',
    shape: 'circle'
  },
  currentPage: 0,
  items: [],
  pages: [],
  params: {},
  debug: false
}
const app = {
  getAppMode () {
    return store.state.appMode
  },
  isUsingPercentSizes () {
    return store.state.usePercentSizes
  },
  resetConfig () {
    store.state = initialState
  },
  config (config) {
    // debug
    if (typeof config.debug === 'boolean' && store.state.debug) store.state.debug = config.debug && store.actions.setLog('- Debug enabled')
    // App mode
    if (config.mode === 'full' || config.mode === 'mixed') store.state.appMode = config.mode && store.actions.setLog('- Mode: ' + config.mode)
    // Percent Sizes
    if (typeof config.usePercentSizes === 'boolean' && config.usePercentSizes) store.state.usePercentSizes = config.usePercentSizes && store.actions.setLog('- Percent sizes ON')
    //
    if (config.percentSizes) store.state.percentSizes = config.percentSizes && store.actions.setLog('- Component percentSizes: ' + JSON.stringify(config.percentSizes))
    //
    if (config.minSizesInPixels) store.state.minSizesInPixels = config.minSizesInPixels && store.actions.setLog('- Component minSizesInPixels: ' + JSON.stringify(config.minSizesInPixels))
    // Theme
    if (config.style && config.style.theme) store.state.appStyle.theme = 'theme-' + config.style.theme && store.actions.setLog('- Theme: ' + config.style.theme)
    // Style Mode
    if (config.style && config.style.mode) store.state.appStyle.mode = 'mode-' + config.style.mode && store.actions.setLog('- Theme mode: ' + config.style.mode)
    // Style shape
    if (config.style && config.style.shape) store.state.appStyle.shape = config.style.shape && store.actions.setLog('- Theme shape: ' + config.style.shape)
    if (config.router) {
      store.state.router = config.router
      store.state.isRouterEnabled = true
      store.actions.setRouterHooks()
      store.actions.setLog('- VueRouter enabled')
      store.actions.setView({
        name: store.state.router.currentRoute.name,
        params: store.state.router.currentRoute.params
      })
      if (store.actions.getAppMode() === 'mixed') store.actions.setLog('You should not use VueRouter when Zircle is in mixed mode.', 'warn')
    }
  }
}
export default app
<commit_msg>perf: optimize code<commit_after>import store from '../store'

const initialState = {
  appMode: 'full',
  navigationMode: 'forward',
  isRouterEnabled: false,
  router: {},
  history: [],
  backwardNavigation: false,
  componentList: {},
  goBackView: '',
  diameters: {},
  usePercentSizes: false,
  percentSizes: {
    xxl: 30,
    xl: 20,
    l: 16,
    m: 8,
    s: 6,
    xs: 4,
    xxs: 2
  },
  minSizesInPixels: {
    xxl: 180,
    xl: 150,
    l: 100,
    m: 80,
    s: 50,
    xs: 30,
    xxs: 20
  },
  appStyle: {
    theme: 'theme-black',
    mode: 'mode-dark',
    shape: 'circle'
  },
  currentPage: 0,
  items: [],
  pages: [],
  params: {},
  debug: false
}
const app = {
  getAppMode () {
    return store.state.appMode
  },
  isUsingPercentSizes () {
    return store.state.usePercentSizes
  },
  resetConfig () {
    store.state = initialState
  },
  config (config) {
    if (typeof config.debug === 'boolean') store.state.debug = config.debug
    if (store.state.debug === true) store.actions.setLog('- Debug enabled')
    if (config.mode === 'full' || config.mode === 'mixed') {
      store.state.appMode = config.mode
      store.actions.setLog('- Mode: ' + config.mode)
    }
    if (typeof config.usePercentSizes === 'boolean') {
      store.state.usePercentSizes = config.usePercentSizes
      store.actions.setLog(`- Percent sizes ${config.usePercentSizes ? 'ON' : 'OFF'}`)
    }
    if (config.percentSizes) {
      store.state.percentSizes = config.percentSizes
      store.actions.setLog('- Component percentSizes: ' + JSON.stringify(config.percentSizes))
    }
    if (config.minSizesInPixels) {
      store.state.minSizesInPixels = config.minSizesInPixels
      store.actions.setLog('- Component minSizesInPixels: ' + JSON.stringify(config.minSizesInPixels))
    }
    if (config.style && config.style.theme) {
      store.state.appStyle.theme = 'theme-' + config.style.theme
      store.actions.setLog('- Theme: ' + config.style.theme)
    }
    if (config.style && config.style.mode) {
      store.state.appStyle.mode = 'mode-' + config.style.mode
      store.actions.setLog('- Theme mode: ' + config.style.mode)
    }
    if (config.style && config.style.shape) {
      store.state.appStyle.shape = config.style.shape
      store.actions.setLog('- Theme shape: ' + config.style.shape)
    }
    if (config.router) {
      store.state.router = config.router
      store.state.isRouterEnabled = true
      store.actions.setRouterHooks()
      store.actions.setLog('- VueRouter enabled')
      store.actions.setView({
        name: store.state.router.currentRoute.name,
        params: store.state.router.currentRoute.params
      })
      if (store.actions.getAppMode() === 'mixed') store.actions.setLog('You should not use VueRouter when Zircle is in mixed mode.', 'warn')
    }
  }
}
export default app
<|endoftext|>


<commit_before>const path = require('path')
const Base = require('./Base.js')
const PatronModel = require('../../models/Patron.js')
const getConfig = require('../../config.js').get

class Patron extends Base {
  constructor (data, _saved) {
    super(data, _saved)

    // _id is patron member ID
    if (!this._id) {
      throw new TypeError('_id is undefined')
    }

    /**
     * @type {string}
     */
    this.status = this.getField('status')

    /**
     * @type {string}
     */
    this.lastCharge = this.getField('lastCharge')

    /**
     * @type {number}
     */
    this.pledgeLifetime = this.getField('pledgeLifetime')
    if (this.pledgeLifetime === undefined) {
      throw new TypeError('pledgeLifetime is undefined')
    }

    /**
     * @type {number}
     */
    this.pledge = this.getField('pledge')
    if (this.pledge === undefined) {
      throw new TypeError('pledge is undefined')
    }

    /**
     * @type {string}
     */
    this.discord = this.getField('discord')

    /**
     * @type {string}
     */
    this.name = this.getField('name')

    /**
     * @type {string}
     */
    this.email = this.getField('email')
  }

  static async refresh () {
    const filePath = path.join(path.resolve(), 'settings', 'api.js')
    return require(filePath)()
  }

  toObject () {
    return {
      _id: this._id,
      status: this.status,
      lastCharge: this.lastCharge,
      pledgeLifetime: this.pledgeLifetime,
      pledge: this.pledge,
      discord: this.discord,
      name: this.name,
      email: this.email
    }
  }

  /**
   * @returns {boolean}
   */
  isActive () {
    const active = this.status === Patron.STATUS.ACTIVE
    if (active) {
      return true
    }
    const declined = this.status === Patron.STATUS.DECLINED
    if (!declined || !this.lastCharge) {
      return false
    }
    const now = new Date(new Date().toUTCString())
    const last = new Date(this.lastCharge)
    const diffTime = Math.abs(last - now)
    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
    return diffDays < 4
  }

  /**
   * @returns {number}
   */
  determineMaxFeeds () {
    const config = getConfig()
    if (!this.isActive()) {
      return config.feeds.max
    }
    if (this.pledge >= 2000) {
      return 140
    }
    if (this.pledge >= 1000) {
      return 70
    }
    if (this.pledge >= 500) {
      return 35
    }
    if (this.pledge >= 250) {
      return 15
    }
    return config.feeds.max
  }

  /**
   * @returns {number}
   */
  determineMaxGuilds () {
    if (!this.isActive()) {
      return 1
    }
    if (this.pledgeLifetime >= 2500) {
      return 4
    }
    if (this.pledgeLifetime >= 1500) {
      return 3
    }
    if (this.pledgeLifetime >= 500) {
      return 2
    }
    return 1
  }

  /**
   * @returns {number}
   */
  determineWebhook () {
    if (!this.isActive()) {
      return false
    } else {
      return this.pledge >= 100
    }
  }

  static get STATUS () {
    return {
      ACTIVE: 'active_patron',
      FORMER: 'former_patron',
      DECLINED: 'declined_patron'
    }
  }

  static get Model () {
    return PatronModel.Model
  }
}

module.exports = Patron
<commit_msg>Add pledge tier<commit_after>const path = require('path')
const Base = require('./Base.js')
const PatronModel = require('../../models/Patron.js')
const getConfig = require('../../config.js').get

class Patron extends Base {
  constructor (data, _saved) {
    super(data, _saved)

    // _id is patron member ID
    if (!this._id) {
      throw new TypeError('_id is undefined')
    }

    /**
     * @type {string}
     */
    this.status = this.getField('status')

    /**
     * @type {string}
     */
    this.lastCharge = this.getField('lastCharge')

    /**
     * @type {number}
     */
    this.pledgeLifetime = this.getField('pledgeLifetime')
    if (this.pledgeLifetime === undefined) {
      throw new TypeError('pledgeLifetime is undefined')
    }

    /**
     * @type {number}
     */
    this.pledge = this.getField('pledge')
    if (this.pledge === undefined) {
      throw new TypeError('pledge is undefined')
    }

    /**
     * @type {string}
     */
    this.discord = this.getField('discord')

    /**
     * @type {string}
     */
    this.name = this.getField('name')

    /**
     * @type {string}
     */
    this.email = this.getField('email')
  }

  static async refresh () {
    const filePath = path.join(path.resolve(), 'settings', 'api.js')
    return require(filePath)()
  }

  toObject () {
    return {
      _id: this._id,
      status: this.status,
      lastCharge: this.lastCharge,
      pledgeLifetime: this.pledgeLifetime,
      pledge: this.pledge,
      discord: this.discord,
      name: this.name,
      email: this.email
    }
  }

  /**
   * @returns {boolean}
   */
  isActive () {
    const active = this.status === Patron.STATUS.ACTIVE
    if (active) {
      return true
    }
    const declined = this.status === Patron.STATUS.DECLINED
    if (!declined || !this.lastCharge) {
      return false
    }
    const now = new Date(new Date().toUTCString())
    const last = new Date(this.lastCharge)
    const diffTime = Math.abs(last - now)
    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
    return diffDays < 4
  }

  /**
   * @returns {number}
   */
  determineMaxFeeds () {
    const config = getConfig()
    if (!this.isActive()) {
      return config.feeds.max
    }
    if (this.pledge >= 2000) {
      return 140
    }
    if (this.pledge > 1500) {
      return 105
    }
    if (this.pledge >= 1000) {
      return 70
    }
    if (this.pledge >= 500) {
      return 35
    }
    if (this.pledge >= 250) {
      return 15
    }
    return config.feeds.max
  }

  /**
   * @returns {number}
   */
  determineMaxGuilds () {
    if (!this.isActive()) {
      return 1
    }
    if (this.pledgeLifetime >= 2500) {
      return 4
    }
    if (this.pledgeLifetime >= 1500) {
      return 3
    }
    if (this.pledgeLifetime >= 500) {
      return 2
    }
    return 1
  }

  /**
   * @returns {number}
   */
  determineWebhook () {
    if (!this.isActive()) {
      return false
    } else {
      return this.pledge >= 100
    }
  }

  static get STATUS () {
    return {
      ACTIVE: 'active_patron',
      FORMER: 'former_patron',
      DECLINED: 'declined_patron'
    }
  }

  static get Model () {
    return PatronModel.Model
  }
}

module.exports = Patron
<|endoftext|>


<commit_before>/**
 * [XMLvalidation evaluates an MODS XML file and ensures it meets standards set here: https://wiki.lib.utk.edu/display/DLP/UTK+Data+Dictionary]
 * @param {[String]} input [MODS XML filename]
 * @return {[Array]}       [Success] or [Filename, Error 1, Error 2, Error 3, ...]
 *
 */

var fs = require('fs');
var parser = require('xml2json');
var jp = require('jsonpath');
var status = [];
var filename = process.argv;
filename = String(filename[2]);

var modsIn = fs.readFileSync(filename, 'utf8');
var modsObj = parser.toJson(modsIn, options = {object: true});

var xmlValues = [];
// only testing for fields that are required and/or non-repeating
var xmlTargets = [0,   //collTitle (req if avail, non-repeating)
                  0,   //ms_arID (req if avail, non-repeating)
                  2,   //dateCreated*
                  1,   //dateIssued (optional, non-repeating)
                  1,   //digitalOrigin (req'd, non-repeating)
                  1,   //physicalDescription/extent (optional, non-repeating)
                  1,   //identifier[@type='filename'] (req'd, repeatable)
                  1,   //physicalDescription/form (req'd, repeatable)
                  1,   //physicalDescription/internetMediaType (req'd, non-repeating)
                  1,   //typeOfResource (req'd, non-repeating)
                  1,   //languageOfCataloging/languageTerm (req'd, non-repeating)
                  1,   //note[@type='ownership'] (optional, non-repeating)
                  1,   //recordInfo/recordOrigin (req'd, non-repeating)
                  1,   //recordInfo/recordContentSource (optional, non-repeating)
                  1,   //location/physicalLocation (req if avail, non-repeating)
                  1,   //rights! (required, non-repeating)
                  1,   //shelfLocator (optional, non-repeating)
                  1    //titleInfo/title (required, repeatable)

                 ];
var xmlErrors = ["XML: too many collection titles",
                 "XML: too many MS/AR numbers",
                 "XML: verify dateCreated values",
                 "XML: too many dateIssued elements",
                 "XML: problems with digitalOrigin",
                 "XML: too many extent elements",
                 "XML: please verify identifier[@type=\'filename\']",
                 "XML: too many form elements",
                 "XML: please verify internetMediaType",
                 "XML: please verify typeOfResource",
                 "XML: please verify languageOfCataloging/languageTerm",
                 "XML: please check the number of note[@type=\'ownership\']",
                 "XML: please check the number of recordOrigin elements",
                 "XML: please check the number of recordContentSource elements",
                 "XML: please check the number of location/physicalLocation elements",
                 "XML: please check the accessCondition element",
                 "XML: too many shelfLocator elements",
                 "XML: please add a titleInfo/title element"

                 ];

xmlValues[0] = jp.query(modsObj, '$.mods.relatedItem[?(@.displayLabel=="Collection")].titleInfo.title').length;
xmlValues[1] = jp.query(modsObj, '$.mods.relatedItem[?(@.displayLabel=="Collection")].identifier').length;
xmlValues[2] = jp.query(modsObj, '$.mods.originInfo.dateCreated.*').length;
xmlValues[3] = jp.query(modsObj, '$.mods.originInfo.dateIssued').length;
xmlValues[4] = jp.query(modsObj, '$.mods.physicalDescription.digitalOrigin').length;
xmlValues[5] = jp.query(modsObj, '$.mods.physicalDescription.extent').length;
xmlValues[6] = jp.query(modsObj, '$.mods.identifier[?(@.type=="filename")]').length;
xmlValues[7] = jp.query(modsObj, '$.mods.physicalDescription.form').length;
xmlValues[8] = jp.query(modsObj, '$.mods.physicalDescription.internetMediaType').length;
xmlValues[9] = jp.query(modsObj, '$.mods.typeOfResource').length;
xmlValues[10] = jp.query(modsObj, '$.mods.note[?(@.type=="ownership")]').length;
xmlValues[11] = jp.query(modsObj, '$.mods.recordInfo.recordOrigin').length;
xmlValues[12] = jp.query(modsObj, '$.mods.recordInfo.recordContentSource').length;
xmlValues[13] = jp.query(modsObj, '$.mods.location.physicalLocation').length;
xmlValues[14] = jp.query(modsObj, '$.mods.accessCondition').length;
xmlValues[15] = jp.query(modsObj, '$..shelfLocator').length;
xmlValues[16] = jp.query(modsObj, '$.mods.titleInfo[*].title').length

for(i=0; i < xmlValues.length; i++) {
  if(xmlValues[i]!=xmlTargets[i]) {
    console.log(`oops! Error Message: \"${xmlErrors[i]}\"\n ${xmlValues[i]} didn\'t match the expected value of ${xmlTargets[i]}`);
  }
}

// fileKey for mods/identifier[@local] comparisons and interacting with db
// should accommodate multiple identifier[@type='filename']s now; this takes the first
// TODO this should incorporate a simple adminDB formatting validity check
var fileID = jp.query(modsObj, '$.mods.identifier[?(@.type=="filename")]["$t"]');
var fileKey = String(fileID[0]).slice(0, -4);
console.log('fileID: ' + fileID);
console.log('fileKey: ' + fileKey);

// originInfo/dateCreated* test (required and repeatable)
// TODO should be at least 1 dateCreated w/ no keyDate
// dateCreated[no attributes] = 1 (required, repeatable)
// dateCreated[@keyDate][@point='start'] = 1 (req'd, non-repeating)
// dateCreated[@keyDate][@qualifier] <= 1 (optional, non-repeating)

// TODO identifier testing
// identifier[@type='filename'], [@type='local'], [@type='opac']
// identifier[@type='filename'] is the only req'd, all repeatable

// genre (optional and repeatable)
// host title relatedItem[@type='host']/titleInfo/title (optional and repeatable)

// language/languageTerm (optional, repeatable)
// recordInfo/languageOfCataloging (required, non-repeating)

// name/namePart (optional, repeatable)
// name[@authority] (optional, repeatable)
// name/namePart/role/roleTerm (req'd if available, repeatable)
// name[@type] (optional, repeatable)

// subjects (all optional, all repeatable)
// thumbnail (req'd if applicable, non-repeating)
// title_initial_article, titleInfo/nonSort: articles in the title element (req'd if applicable, repeatable)
// title_of_part, titleInfo/partName (req'd if applicable, repeatable)

startProcessing(filename, fileRead);

function startProcessing(file, callback) {
  fs.readFile(file, 'utf8', callback);
}

function fileRead(err, data) {
  var message;
  if (err) {
    message = 'Cannot read file';
  }
  else {
    message = 'Successfully read file';
  }
  //console.log('message :' + message);
  postResults(message, data);
}

function postResults(x, data) {
  switch(x) {
    case 'Cannot read file':
      console.log('CANNOT');
      break;
    case 'Successfully read file':
      //readMODS(data);
      return data;
      break;
  }
}
<commit_msg>fix missing xmlValues value<commit_after>/**
 * [XMLvalidation evaluates an MODS XML file and ensures it meets standards set here: https://wiki.lib.utk.edu/display/DLP/UTK+Data+Dictionary]
 * @param {[String]} input [MODS XML filename]
 * @return {[Array]}       [Success] or [Filename, Error 1, Error 2, Error 3, ...]
 *
 */

var fs = require('fs');
var parser = require('xml2json');
var jp = require('jsonpath');
var status = [];
var filename = process.argv;
filename = String(filename[2]);

var modsIn = fs.readFileSync(filename, 'utf8');
var modsObj = parser.toJson(modsIn, options = {object: true});

var xmlValues = [];
// only testing for fields that are required and/or non-repeating
var xmlTargets = [0,   //collTitle (req if avail, non-repeating)
                  0,   //ms_arID (req if avail, non-repeating)
                  2,   //dateCreated*
                  1,   //dateIssued (optional, non-repeating)
                  1,   //digitalOrigin (req'd, non-repeating)
                  1,   //physicalDescription/extent (optional, non-repeating)
                  1,   //identifier[@type='filename'] (req'd, repeatable)
                  1,   //physicalDescription/form (req'd, repeatable)
                  1,   //physicalDescription/internetMediaType (req'd, non-repeating)
                  1,   //typeOfResource (req'd, non-repeating)
                  1,   //languageOfCataloging/languageTerm (req'd, non-repeating)
                  1,   //note[@type='ownership'] (optional, non-repeating)
                  1,   //recordInfo/recordOrigin (req'd, non-repeating)
                  1,   //recordInfo/recordContentSource (optional, non-repeating)
                  1,   //location/physicalLocation (req if avail, non-repeating)
                  1,   //rights! (required, non-repeating)
                  1,   //shelfLocator (optional, non-repeating)
                  1    //titleInfo/title (required, repeatable)

                 ];
var xmlErrors = ["XML: too many collection titles",
                 "XML: too many MS/AR numbers",
                 "XML: verify dateCreated values",
                 "XML: too many dateIssued elements",
                 "XML: problems with digitalOrigin",
                 "XML: too many extent elements",
                 "XML: please verify identifier[@type=\'filename\']",
                 "XML: too many form elements",
                 "XML: please verify internetMediaType",
                 "XML: please verify typeOfResource",
                 "XML: please verify languageOfCataloging/languageTerm",
                 "XML: please check the number of note[@type=\'ownership\']",
                 "XML: please check the number of recordOrigin elements",
                 "XML: please check the number of recordContentSource elements",
                 "XML: please check the number of location/physicalLocation elements",
                 "XML: please check the accessCondition element",
                 "XML: too many shelfLocator elements",
                 "XML: please add a titleInfo/title element"

                 ];

xmlValues[0] = jp.query(modsObj, '$.mods.relatedItem[?(@.displayLabel=="Collection")].titleInfo.title').length;
xmlValues[1] = jp.query(modsObj, '$.mods.relatedItem[?(@.displayLabel=="Collection")].identifier').length;
xmlValues[2] = jp.query(modsObj, '$.mods.originInfo.dateCreated.*').length;
xmlValues[3] = jp.query(modsObj, '$.mods.originInfo.dateIssued').length;
xmlValues[4] = jp.query(modsObj, '$.mods.physicalDescription.digitalOrigin').length;
xmlValues[5] = jp.query(modsObj, '$.mods.physicalDescription.extent').length;
xmlValues[6] = jp.query(modsObj, '$.mods.identifier[?(@.type=="filename")]').length;
xmlValues[7] = jp.query(modsObj, '$.mods.physicalDescription.form').length;
xmlValues[8] = jp.query(modsObj, '$.mods.physicalDescription.internetMediaType').length;
xmlValues[9] = jp.query(modsObj, '$.mods.typeOfResource').length;
xmlValues[10] = jp.query(modsObj, '$.mods..languageOfCataloging.languageTerm').length;
xmlValues[11] = jp.query(modsObj, '$.mods.note[?(@.type=="ownership")]').length;
xmlValues[12] = jp.query(modsObj, '$.mods.recordInfo.recordOrigin').length;
xmlValues[13] = jp.query(modsObj, '$.mods.recordInfo.recordContentSource').length;
xmlValues[14] = jp.query(modsObj, '$.mods.location.physicalLocation').length;
xmlValues[15] = jp.query(modsObj, '$.mods.accessCondition').length;
xmlValues[16] = jp.query(modsObj, '$..shelfLocator').length;
xmlValues[17] = jp.query(modsObj, '$.mods.titleInfo[*].title').length;

console.log('xmlValues:  ' + xmlValues + ' length: ' + xmlValues.length);
console.log('xmlTargets: ' + xmlTargets + ' length: ' + xmlTargets.length);

for(i=0; i < xmlValues.length; i++) {
  if((i==0) && ((xmlValues[i]>(xmlTargets[i])+1))) {
    console.log(`XML: Collection titles: ${xmlValues[i]} didn\'t match the expected value of ${xmlTargets[i]}`);
  }
  if((i==1) && (xmlValues[i]>1)) {
    console.log(`XML: MS/AR identifier(s): ${xmlValues[i]} didn\'t match the expected value of ${xmlTargets[i]}`);
  }
  if((i==2) && (xmlValues[i]>xmlTargets[i])) {
    console.log(`XML: dateCreated error: ${xmlValues[i]} didn\'t match the expected value of ${xmlTargets[i]}`);
  }
  // else {
  //  if(xmlValues[i]!=xmlTargets[i]) {
  //    console.log(`oops! Error Message: \"${xmlErrors[i]}\"\n ${xmlValues[i]} didn\'t match the expected value of ${xmlTargets[i]}`);
  //  }
  //}
}

startProcessing(filename, fileRead);

function startProcessing(file, callback) {
  fs.readFile(file, 'utf8', callback);
}

function fileRead(err, data) {
  var message;
  if (err) {
    message = 'Cannot read file';
  }
  else {
    message = 'Successfully read file';
  }
  //console.log('message :' + message);
  postResults(message, data);
}

function postResults(x, data) {
  switch(x) {
    case 'Cannot read file':
      console.log('CANNOT');
      break;
    case 'Successfully read file':
      //readMODS(data);
      return data;
      break;
  }
}

// fileKey for mods/identifier[@local] comparisons and interacting with db
// should accommodate multiple identifier[@type='filename']s now; this takes the first
// TODO this should incorporate a simple adminDB formatting validity check
var fileID = jp.query(modsObj, '$.mods.identifier[?(@.type=="filename")]["$t"]');
var fileKey = String(fileID[0]).slice(0, -4);
console.log('fileID: ' + fileID);
console.log('fileKey: ' + fileKey);

// originInfo/dateCreated* test (required and repeatable)
// TODO should be at least 1 dateCreated w/ no keyDate
// dateCreated[no attributes] = 1 (required, repeatable)
// dateCreated[@keyDate][@point='start'] = 1 (req'd, non-repeating)
// dateCreated[@keyDate][@qualifier] <= 1 (optional, non-repeating)

// TODO identifier testing
// identifier[@type='filename'], [@type='local'], [@type='opac']
// identifier[@type='filename'] is the only req'd, all repeatable

// genre (optional and repeatable)
// host title relatedItem[@type='host']/titleInfo/title (optional and repeatable)

// language/languageTerm (optional, repeatable)
// recordInfo/languageOfCataloging (required, non-repeating)

// name/namePart (optional, repeatable)
// name[@authority] (optional, repeatable)
// name/namePart/role/roleTerm (req'd if available, repeatable)
// name[@type] (optional, repeatable)

// subjects (all optional, all repeatable)
// thumbnail (req'd if applicable, non-repeating)
// title_initial_article, titleInfo/nonSort: articles in the title element (req'd if applicable, repeatable)
// title_of_part, titleInfo/partName (req'd if applicable, repeatable)
<|endoftext|>


<commit_before>module.exports = (initialState) => (
  `
    <!DOCTYPE html>

        <meta charset="utf-8">
        <link href="/public/bundle.css" rel="stylesheet">
        <title>FCC Voting App</title>

  `
)
<commit_msg>build testing<commit_after>module.exports = (initialState) => (
  `
    <!DOCTYPE html>

        <meta charset="utf-8">
        <link href="/public/bundle.css" rel="stylesheet">
        <title>FCC Voting App</title>

${__dirname} ${process.cwd()}

  `
)
<|endoftext|>


<commit_before>import { invert, lighten, rgba } from 'khroma';

class Theme {
  constructor() {
    this.background = '#333';
    this.mainBkg = lighten('#1f2020', 15);
    this.secondBkg = 'calculated';
    this.mainContrastColor = 'lightgrey';
    this.darkTextColor = lighten(invert('#323D47'), 10);
    this.lineColor = 'calculated';
    this.border1 = '#81B1DB';
    this.border2 = rgba(255, 255, 255, 0.25);
    this.arrowheadColor = 'calculated';
    this.fontFamily = '"trebuchet ms", verdana, arial';
    this.fontSize = '16px';
    this.labelBackground = '#181818';
    this.textColor = '#ccc';
    /* Flowchart variables */

    this.nodeBkg = 'calculated';
    this.nodeBorder = 'calculated';
    this.clusterBkg = 'calculated';
    this.clusterBorder = 'calculated';
    this.defaultLinkColor = 'calculated';
    this.titleColor = '#F9FFFE';
    this.edgeLabelBackground = 'calculated';

    /* Sequence Diagram variables */

    this.actorBorder = 'calculated';
    this.actorBkg = 'calculated';
    this.actorTextColor = 'calculated';
    this.actorLineColor = 'calculated';
    this.signalColor = 'calculated';
    this.signalTextColor = 'calculated';
    this.labelBoxBkgColor = 'calculated';
    this.labelBoxBorderColor = 'calculated';
    this.labelTextColor = 'calculated';
    this.loopTextColor = 'calculated';
    this.noteBorderColor = 'calculated';
    this.noteBkgColor = '#fff5ad';
    this.noteTextColor = 'calculated';
    this.activationBorderColor = 'calculated';
    this.activationBkgColor = 'calculated';
    this.sequenceNumberColor = 'black';

    /* Gantt chart variables */

    this.sectionBkgColor = rgba(255, 255, 255, 30);
    this.altSectionBkgColor = 'white';
    this.sectionBkgColor2 = '#EAE8B9';
    this.taskBorderColor = rgba(255, 255, 255, 70);
    this.taskBkgColor = 'calculated';
    this.taskTextColor = 'calculated';
    this.taskTextLightColor = 'calculated';
    this.taskTextOutsideColor = 'calculated';
    this.taskTextClickableColor = '#003163';
    this.activeTaskBorderColor = rgba(255, 255, 255, 50);
    this.activeTaskBkgColor = '#81B1DB';
    this.gridColor = 'calculated';
    this.doneTaskBkgColor = 'calculated';
    this.doneTaskBorderColor = 'grey';
    this.critBorderColor = '#E83737';
    this.critBkgColor = '#E83737';
    this.taskTextDarkColor = 'calculated';
    this.todayLineColor = '#DB5757';

    /* state colors */
    this.labelColor = 'calculated';

    this.errorBkgColor = '#a44141';
    this.errorTextColor = '#ddd';
  }
  updateColors() {
    this.secondBkg = lighten(this.mainBkg, 16);
    this.lineColor = this.mainContrastColor;
    this.arrowheadColor = this.mainContrastColor;
    /* Flowchart variables */

    this.nodeBkg = this.mainBkg;
    this.nodeBorder = this.border1;
    this.clusterBkg = this.secondBkg;
    this.clusterBorder = this.border2;
    this.defaultLinkColor = this.lineColor;
    this.edgeLabelBackground = lighten(this.labelBackground, 25);

    /* Sequence Diagram variables */

    this.actorBorder = this.border1;
    this.actorBkg = this.mainBkg;
    this.actorTextColor = this.mainContrastColor;
    this.actorLineColor = this.mainContrastColor;
    this.signalColor = this.mainContrastColor;
    this.signalTextColor = this.mainContrastColor;
    this.labelBoxBkgColor = this.actorBkg;
    this.labelBoxBorderColor = this.actorBorder;
    this.labelTextColor = this.mainContrastColor;
    this.loopTextColor = this.mainContrastColor;
    this.noteBorderColor = this.border2;
    this.noteTextColor = this.mainBkg;
    this.activationBorderColor = this.border1;
    this.activationBkgColor = this.secondBkg;

    /* Gantt chart variables */

    this.taskBkgColor = this.mainBkg;
    this.taskTextColor = this.darkTextColor;
    this.taskTextLightColor = this.mainContrastColor;
    this.taskTextOutsideColor = this.taskTextLightColor;
    this.gridColor = this.mainContrastColor;
    this.doneTaskBkgColor = this.mainContrastColor;
    this.taskTextDarkColor = this.darkTextColor;

    /* state colors */
    this.labelColor = this.textColor;
  }
  calculate(overrides) {
    if (typeof overrides !== 'object') {
      // Calculate colors form base colors
      this.updateColors();
      return;
    }

    const keys = Object.keys(overrides);

    // Copy values from overrides, this is mainly for base colors
    keys.forEach(k => {
      this[k] = overrides[k];
    });

    // Calculate colors form base colors
    this.updateColors();
    // Copy values from overrides again in case of an override of derived value
    keys.forEach(k => {
      this[k] = overrides[k];
    });
  }
}

export const getThemeVariables = userOverrides => {
  const theme = new Theme();
  theme.calculate(userOverrides);
  return theme;
};
<commit_msg>#1542 Gantt tweaks<commit_after>import { invert, lighten, darken, rgba } from 'khroma';

class Theme {
  constructor() {
    this.background = '#333';
    this.mainBkg = '#1f2020';
    this.secondBkg = 'calculated';
    this.mainContrastColor = 'lightgrey';
    this.darkTextColor = lighten(invert('#323D47'), 10);
    this.lineColor = 'calculated';
    this.border1 = '#81B1DB';
    this.border2 = rgba(255, 255, 255, 0.25);
    this.arrowheadColor = 'calculated';
    this.fontFamily = '"trebuchet ms", verdana, arial';
    this.fontSize = '16px';
    this.labelBackground = '#181818';
    this.textColor = '#ccc';
    /* Flowchart variables */

    this.nodeBkg = 'calculated';
    this.nodeBorder = 'calculated';
    this.clusterBkg = 'calculated';
    this.clusterBorder = 'calculated';
    this.defaultLinkColor = 'calculated';
    this.titleColor = '#F9FFFE';
    this.edgeLabelBackground = 'calculated';

    /* Sequence Diagram variables */

    this.actorBorder = 'calculated';
    this.actorBkg = 'calculated';
    this.actorTextColor = 'calculated';
    this.actorLineColor = 'calculated';
    this.signalColor = 'calculated';
    this.signalTextColor = 'calculated';
    this.labelBoxBkgColor = 'calculated';
    this.labelBoxBorderColor = 'calculated';
    this.labelTextColor = 'calculated';
    this.loopTextColor = 'calculated';
    this.noteBorderColor = 'calculated';
    this.noteBkgColor = '#fff5ad';
    this.noteTextColor = 'calculated';
    this.activationBorderColor = 'calculated';
    this.activationBkgColor = 'calculated';
    this.sequenceNumberColor = 'black';

    /* Gantt chart variables */

    this.sectionBkgColor = darken('#EAE8D9', 30);
    this.altSectionBkgColor = 'calculated';
    this.sectionBkgColor2 = '#EAE8D9';
    this.taskBorderColor = rgba(255, 255, 255, 70);
    this.taskBkgColor = 'calculated';
    this.taskTextColor = 'calculated';
    this.taskTextLightColor = 'calculated';
    this.taskTextOutsideColor = 'calculated';
    this.taskTextClickableColor = '#003163';
    this.activeTaskBorderColor = rgba(255, 255, 255, 50);
    this.activeTaskBkgColor = '#81B1DB';
    this.gridColor = 'calculated';
    this.doneTaskBkgColor = 'calculated';
    this.doneTaskBorderColor = 'grey';
    this.critBorderColor = '#E83737';
    this.critBkgColor = '#E83737';
    this.taskTextDarkColor = 'calculated';
    this.todayLineColor = '#DB5757';

    /* state colors */
    this.labelColor = 'calculated';

    this.errorBkgColor = '#a44141';
    this.errorTextColor = '#ddd';
  }
  updateColors() {
    this.secondBkg = lighten(this.mainBkg, 16);
    this.lineColor = this.mainContrastColor;
    this.arrowheadColor = this.mainContrastColor;
    /* Flowchart variables */

    this.nodeBkg = this.mainBkg;
    this.nodeBorder = this.border1;
    this.clusterBkg = this.secondBkg;
    this.clusterBorder = this.border2;
    this.defaultLinkColor = this.lineColor;
    this.edgeLabelBackground = lighten(this.labelBackground, 25);

    /* Sequence Diagram variables */

    this.actorBorder = this.border1;
    this.actorBkg = this.mainBkg;
    this.actorTextColor = this.mainContrastColor;
    this.actorLineColor = this.mainContrastColor;
    this.signalColor = this.mainContrastColor;
    this.signalTextColor = this.mainContrastColor;
    this.labelBoxBkgColor = this.actorBkg;
    this.labelBoxBorderColor = this.actorBorder;
    this.labelTextColor = this.mainContrastColor;
    this.loopTextColor = this.mainContrastColor;
    this.noteBorderColor = this.border2;
    this.noteTextColor = this.mainBkg;
    this.activationBorderColor = this.border1;
    this.activationBkgColor = this.secondBkg;

    /* Gantt chart variables */

    this.altSectionBkgColor = this.background;
    this.taskBkgColor = lighten(this.mainBkg, 23);
    this.taskTextColor = this.darkTextColor;
    this.taskTextLightColor = this.mainContrastColor;
    this.taskTextOutsideColor = this.taskTextLightColor;
    this.gridColor = this.mainContrastColor;
    this.doneTaskBkgColor = this.mainContrastColor;
    this.taskTextDarkColor = this.darkTextColor;

    /* state colors */
    this.labelColor = this.textColor;
  }
  calculate(overrides) {
    if (typeof overrides !== 'object') {
      // Calculate colors form base colors
      this.updateColors();
      return;
    }

    const keys = Object.keys(overrides);

    // Copy values from overrides, this is mainly for base colors
    keys.forEach(k => {
      this[k] = overrides[k];
    });

    // Calculate colors form base colors
    this.updateColors();
    // Copy values from overrides again in case of an override of derived value
    keys.forEach(k => {
      this[k] = overrides[k];
    });
  }
}

export const getThemeVariables = userOverrides => {
  const theme = new Theme();
  theme.calculate(userOverrides);
  return theme;
};
<|endoftext|>