<commit_before>'use strict';

var assert = require('assert'),
	util = require('../../lib/util/util');

describe('util', function() {

	describe('#getContentType', function() {

		it('text/plain should be categorized as doc', function() {
			var result = util.getContentType('text/plain');
			assert.deepEqual(result, 'doc');
		});

		it('text/html should be categorized as doc', function() {
			var result = util.getContentType('text/html');
			assert.deepEqual(result, 'doc');
		});

		it('text/html; charset=utf-8 with charset should be categorized as doc', function() {
			var result = util.getContentType('text/html; charset=utf-8');
			assert.deepEqual(result, 'doc');
		});

		it('text/javascript should be categorized as js', function() {
			var result = util.getContentType('text/javascript');
			assert.deepEqual(result, 'js');
		});

		it('application/x-javascript; charset=utf-8 should be categorized as js', function() {
			var result = util.getContentType('application/x-javascript; charset=utf-8');
			assert.deepEqual(result, 'js');
		});

		it('text/css should be categorized as css', function() {
			var result = util.getContentType('text/css');
			assert.deepEqual(result, 'css');
		});

		it('image/png should be categorized as image', function() {
			var result = util.getContentType('image/png');
			assert.deepEqual(result, 'image');
		});

		it('image/jpg should be categorized as image', function() {
			var result = util.getContentType('image/jpg');
			assert.deepEqual(result, 'image');
		});

		it('image/gif should be categorized as image', function() {
			var result = util.getContentType('image/gif');
			assert.deepEqual(result, 'image');
		});

		it('image/x-icon should be categorized as image', function() {
			var result = util.getContentType('image/x-icon');
			assert.deepEqual(result, 'image');
		});

		it('image/svg+xml should be categorized as image', function() {
			var result = util.getContentType('image/svg+xml');
			assert.deepEqual(result, 'image');
		});

		it('image/webp should be categorized as image', function() {
			var result = util.getContentType('image/webp');
			assert.deepEqual(result, 'image');
		});

		it('application/font-woff should be categorized as font', function() {
			var result = util.getContentType('application/font-woff');
			assert.deepEqual(result, 'font');
		});

		it('application/font-sfnt should be categorized as font', function() {
			var result = util.getContentType('application/font-sfnt');
			assert.deepEqual(result, 'font');
		});

		it('application/x-font-opentype should be categorized as font', function() {
			var result = util.getContentType('application/x-font-opentype');
			assert.deepEqual(result, 'font');
		});

		it('application/x-font-ttf should be categorized as font', function() {
			var result = util.getContentType('application/x-font-ttf');
			assert.deepEqual(result, 'font');
		});

		it('application/x-shockwave-flash should be categorized as flash', function() {
			var result = util.getContentType('application/x-shockwave-flash');
			assert.deepEqual(result, 'flash');
		});

		it('application/my-own-type should be categorized as unkown', function() {
			var result = util.getContentType('application/my-own-type');
			assert.deepEqual(result, 'unknown');
		});

	});

	describe('#getGraphiteURLKey', function() {

		it('A domain without slash should return protocol.www_domain_com ', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io');
			assert.deepEqual(result, 'http.www_sitespeed_io.slash');
		});

		it('A https domain should start with https in the keys', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io');
			assert.deepEqual(result, 'https.www_sitespeed_io.slash');
		});

		it('A domain with a slash should return protocol.www_domain_com', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io/');
			assert.deepEqual(result, 'http.www_sitespeed_io.slash');
		});

		it('Many subdomains should keep all domains in the domain part of the key', function() {
			var result = util.getGraphiteURLKey('http://so.many.subdomains.sitespeed.io/hepp');
			assert.deepEqual(result, 'http.so_many_subdomains_sitespeed_io._hepp');
		});

		it('The path should be separated from the domain (ending without a slash)', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io/too/deep');
			assert.deepEqual(result, 'http.www_sitespeed_io._too_deep');
		});

		it('The path should be separated from the domain (ends with a slash)', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io/too/deep/');
			assert.deepEqual(result, 'http.www_sitespeed_io._too_deep_');
		});

		it('The path and files should be separated from the domain (when a file is in a folder)', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io/js/my.js');
			assert.deepEqual(result, 'http.www_sitespeed_io._js_my_js');
		});

		it('The path and files should be separated from the domain (when the file is in root)', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io/image.gif');
			assert.deepEqual(result, 'http.www_sitespeed_io._image_gif');
		});

		it('Should escape pipes that make graphite data retrieval problematic', function() {
			var result = util.getGraphiteURLKey('http://www.example.com/browse|ID|4.html');
			assert.deepEqual(result, 'http.www_example_com._browse_ID_4_html');
		});

		it('Should escape encoded pipe characters that make graphite data retrieval problematic', function() {
			var result = util.getGraphiteURLKey('http://www.example.com/browse%7CID%7C4.html');
			assert.deepEqual(result, 'http.www_example_com._browse_ID_4_html');
		});

		it('Should escape "+" that make graphite data retrieval problematic', function() {
			var result = util.getGraphiteURLKey('http://www.example.com/browse/hello+world');
			assert.deepEqual(result, 'http.www_example_com._browse_hello_world');
		});

		it('Should escape "," (comma) that makes graphite functions fail', function() {
			var result = util.getGraphiteURLKey('http://www.example.com/browse/hello,world');
			assert.deepEqual(result, 'http.www_example_com._browse_hello_world');
		});

	});
});
<commit_msg>adjust test to https closes #722<commit_after>'use strict';

var assert = require('assert'),
	util = require('../../lib/util/util');

describe('util', function() {

	describe('#getContentType', function() {

		it('text/plain should be categorized as doc', function() {
			var result = util.getContentType('text/plain');
			assert.deepEqual(result, 'doc');
		});

		it('text/html should be categorized as doc', function() {
			var result = util.getContentType('text/html');
			assert.deepEqual(result, 'doc');
		});

		it('text/html; charset=utf-8 with charset should be categorized as doc', function() {
			var result = util.getContentType('text/html; charset=utf-8');
			assert.deepEqual(result, 'doc');
		});

		it('text/javascript should be categorized as js', function() {
			var result = util.getContentType('text/javascript');
			assert.deepEqual(result, 'js');
		});

		it('application/x-javascript; charset=utf-8 should be categorized as js', function() {
			var result = util.getContentType('application/x-javascript; charset=utf-8');
			assert.deepEqual(result, 'js');
		});

		it('text/css should be categorized as css', function() {
			var result = util.getContentType('text/css');
			assert.deepEqual(result, 'css');
		});

		it('image/png should be categorized as image', function() {
			var result = util.getContentType('image/png');
			assert.deepEqual(result, 'image');
		});

		it('image/jpg should be categorized as image', function() {
			var result = util.getContentType('image/jpg');
			assert.deepEqual(result, 'image');
		});

		it('image/gif should be categorized as image', function() {
			var result = util.getContentType('image/gif');
			assert.deepEqual(result, 'image');
		});

		it('image/x-icon should be categorized as image', function() {
			var result = util.getContentType('image/x-icon');
			assert.deepEqual(result, 'image');
		});

		it('image/svg+xml should be categorized as image', function() {
			var result = util.getContentType('image/svg+xml');
			assert.deepEqual(result, 'image');
		});

		it('image/webp should be categorized as image', function() {
			var result = util.getContentType('image/webp');
			assert.deepEqual(result, 'image');
		});

		it('application/font-woff should be categorized as font', function() {
			var result = util.getContentType('application/font-woff');
			assert.deepEqual(result, 'font');
		});

		it('application/font-sfnt should be categorized as font', function() {
			var result = util.getContentType('application/font-sfnt');
			assert.deepEqual(result, 'font');
		});

		it('application/x-font-opentype should be categorized as font', function() {
			var result = util.getContentType('application/x-font-opentype');
			assert.deepEqual(result, 'font');
		});

		it('application/x-font-ttf should be categorized as font', function() {
			var result = util.getContentType('application/x-font-ttf');
			assert.deepEqual(result, 'font');
		});

		it('application/x-shockwave-flash should be categorized as flash', function() {
			var result = util.getContentType('application/x-shockwave-flash');
			assert.deepEqual(result, 'flash');
		});

		it('application/my-own-type should be categorized as unkown', function() {
			var result = util.getContentType('application/my-own-type');
			assert.deepEqual(result, 'unknown');
		});

	});

	describe('#getGraphiteURLKey', function() {

		it('A domain without slash should return protocol.www_domain_com ', function() {
			var result = util.getGraphiteURLKey('http://www.sitespeed.io');
			assert.deepEqual(result, 'http.www_sitespeed_io.slash');
		});

		it('A https domain should start with https in the keys', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io');
			assert.deepEqual(result, 'https.www_sitespeed_io.slash');
		});

		it('A domain with a slash should return protocol.www_domain_com', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io/');
			assert.deepEqual(result, 'https.www_sitespeed_io.slash');
		});

		it('Many subdomains should keep all domains in the domain part of the key', function() {
			var result = util.getGraphiteURLKey('http://so.many.subdomains.sitespeed.io/hepp');
			assert.deepEqual(result, 'http.so_many_subdomains_sitespeed_io._hepp');
		});

		it('The path should be separated from the domain (ending without a slash)', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io/too/deep');
			assert.deepEqual(result, 'https.www_sitespeed_io._too_deep');
		});

		it('The path should be separated from the domain (ends with a slash)', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io/too/deep/');
			assert.deepEqual(result, 'https.www_sitespeed_io._too_deep_');
		});

		it('The path and files should be separated from the domain (when a file is in a folder)', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io/js/my.js');
			assert.deepEqual(result, 'https.www_sitespeed_io._js_my_js');
		});

		it('The path and files should be separated from the domain (when the file is in root)', function() {
			var result = util.getGraphiteURLKey('https://www.sitespeed.io/image.gif');
			assert.deepEqual(result, 'https.www_sitespeed_io._image_gif');
		});

		it('Should escape pipes that make graphite data retrieval problematic', function() {
			var result = util.getGraphiteURLKey('http://www.example.com/browse|ID|4.html');
			assert.deepEqual(result, 'http.www_example_com._browse_ID_4_html');
		});

		it('Should escape encoded pipe characters that make graphite data retrieval problematic', function() {
			var result = util.getGraphiteURLKey('http://www.example.com/browse%7CID%7C4.html');
			assert.deepEqual(result, 'http.www_example_com._browse_ID_4_html');
		});

		it('Should escape "+" that make graphite data retrieval problematic', function() {
			var result = util.getGraphiteURLKey('http://www.example.com/browse/hello+world');
			assert.deepEqual(result, 'http.www_example_com._browse_hello_world');
		});

		it('Should escape "," (comma) that makes graphite functions fail', function() {
			var result = util.getGraphiteURLKey('http://www.example.com/browse/hello,world');
			assert.deepEqual(result, 'http.www_example_com._browse_hello_world');
		});

	});
});
<|endoftext|>


<commit_before>var conf = require('../loop/config').conf;
var async = require('async');
var redis = require("redis");

var storage = conf.get("storage");
var utils = require("./utils");
var keysInformation = utils.keysInformation;
var dbInformation = utils.dbInformation;
var sget = utils.sget;
var args = process.argv.slice(2);

var verbose = args.indexOf('--verbose') !== -1;
var TWO_WEEKS = 3600 * 24 * 7 * 2;

if (storage.engine === "redis") {
  var options = storage.settings;
  var client = redis.createClient(
    options.port,
    options.host,
    options.options
  );
  if (options.db) client.select(options.db);

  keysInformation(client, '*', function(err, keysInfo) {
    if (err) throw err;

    console.log("Processing " + keysInfo.length + " keys");
    console.log("Looking for keys not used since : " + new Date(Date.now() - TWO_WEEKS * 1000).toLocaleDateString());

    var toDelete = [];

    keysInfo.forEach(function(key) {
      var lruDate = new Date(Date.now() - key.lru_seconds_idle * 1000).getTime();
      var now = Date.now();

      var delta = (now - lruDate) / 1000;

      if (delta > TWO_WEEKS) {
        toDelete.push(key.key);
      }

    });

    if (verbose) {
      console.log("Selected keys:");
      toDelete.forEach(function(key) {
        console.log("- " + key + " deleted");
      });
    }
    console.log(toDelete.length + " keys found.");

    if (toDelete.length > 0) {
      var entry = sget("Would you like to remove these keys? [y/N]");
      if (entry.toLowerCase().indexOf("y") === 0) {
        client.del(toDelete, function(err) {
          if (err) throw err;
          console.log(toDelete.length + " keys have been removed.");
          process.exit(0);
        });
        return;
      }
    }
    console.log("No key has been removed.");
    process.exit(0);
  });
}
<commit_msg>Display more information about the size to be removed.<commit_after>var conf = require('../loop/config').conf;
var async = require('async');
var redis = require("redis");

var storage = conf.get("storage");
var utils = require("./utils");
var keysInformation = utils.keysInformation;
var dbInformation = utils.dbInformation;
var sget = utils.sget;
var args = process.argv.slice(2);

var verbose = args.indexOf('--verbose') !== -1;
var TWO_WEEKS = 3600 * 24 * 7 * 2;

if (storage.engine === "redis") {
  var options = storage.settings;
  var client = redis.createClient(
    options.port,
    options.host,
    options.options
  );
  if (options.db) client.select(options.db);

  keysInformation(client, '*', function(err, keysInfo) {
    if (err) throw err;

    console.log("Processing " + keysInfo.length + " keys");
    console.log("Looking for keys not used since : " + new Date(Date.now() - TWO_WEEKS * 1000).toLocaleDateString());

    var toDelete = [];
    var freed = 0;

    keysInfo.forEach(function(key) {
      var lruDate = new Date(Date.now() - key.lru_seconds_idle * 1000).getTime();
      var now = Date.now();
      var size = parseInt(key.serializedlength, 10);

      var delta = (now - lruDate) / 1000;

      if (delta > TWO_WEEKS) {
        toDelete.push(key.key);
        freed = freed + size;
      }

    });

    if (verbose) {
      console.log("Selected keys:");
      toDelete.forEach(function(key) {
        console.log("- " + key + " deleted");
      });
    }
    console.log(toDelete.length + " keys found. (" + freed + " Bytes)");

    if (toDelete.length > 0) {
      var entry = sget("Would you like to remove these keys? [y/N]");
      if (entry.toLowerCase().indexOf("y") === 0) {
        client.del(toDelete, function(err) {
          if (err) throw err;
          console.log(toDelete.length + " keys have been removed. And " + freed + " Bytes freed.");
          process.exit(0);
        });
        return;
      }
    }
    console.log("No key has been removed.");
    process.exit(0);
  });
}
<|endoftext|>


<commit_before>define(['app','underscore','ionsound'], function(app,_) {
    app.directive('switchRealm', function() {
        return {
            restrict: 'EAC',
            replace: true,
            templateUrl: '/app/views/directives/switch-realm-directive.html',
            controller: ['$scope', '$location','realmConfiguration','realm',
                function($scope, $location, realmConfiguration, realm) {

                    console.log(realm);

                    $scope.realmList = [{identifier:'ABS', value:'ABS', message:'PRODUCTION'}
                                        ,{identifier:'ABS-DEV', value:'ABS-DEV', message:'DEVELOPMENT'},
                                        {identifier:'ABS-TRG', value:'ABS-TRG', message:'TRAINING'}]

                    $scope.currentRealm = function(){
                        var realmConfig = _.find(realmConfiguration,{host:$location.$$host});
                        return realmConfig.realm;
                    }

                    $scope.currentRealmMessage = function(){
                        var realmConfig = _.find(realmConfiguration,{host:$location.$$host});
                        return _.find($scope.realmList,{identifier:realmConfig.realm}).message;
                    }
                    $scope.switchRealm = function(){
                        var realmConfig = _.find(realmConfiguration,{host:$location.$$host});
                        realmConfig.realm = $scope.selectedRealm;
                        realm.value = realmConfig.realm;
                    }
                }]

        };
    });
});
<commit_msg>fix switch realm<commit_after>define(['app','underscore', '/app/services/app-config-service.js', 'ionsound'],
function(app,_) {
    app.directive('switchRealm', function() {
        return {
            restrict: 'EAC',
            replace: true,
            templateUrl: '/app/views/directives/switch-realm-directive.html',
            controller: ['$scope', '$location','appConfigService','realm',
                function($scope, $location, appConfigService, realm) {

                    console.log(realm);

                    $scope.realmList = [{identifier:'ABS', value:'ABS', message:'PRODUCTION'}
                                        ,{identifier:'ABS-DEV', value:'ABS-DEV', message:'DEVELOPMENT'},
                                        {identifier:'ABS-TRG', value:'ABS-TRG', message:'TRAINING'}]

                    $scope.currentRealm = function(){
                        return appConfigService.currentRealm;
                    }

                    $scope.currentRealmMessage = function(){

                        return _.find($scope.realmList,{identifier:appConfigService.currentRealm}).message;
                    }
                    $scope.switchRealm = function(){
                        appConfigService.setCurrentRealm($scope.selectedRealm);
                        appConfigService.currentRealm   = $scope.selectedRealm;
                        realm.value = appConfigService.currentRealm;
                    }
                }]

        };
    });
});
<|endoftext|>


<commit_before>const path = require('path')
const chalk = require('chalk')
const ora = require('ora')
const rollup = require('rollup')
const babel = require('rollup-plugin-babel')
const cjs = require('rollup-plugin-commonjs')
const nodeResolve = require('rollup-plugin-node-resolve')
const replace = require('rollup-plugin-re')
const vue = require('rollup-plugin-vue').default
const uglify = require('rollup-plugin-uglify').uglify
const sass = require('./rollup/sass')
const notifier = require('node-notifier')
const argv = require('yargs').argv
const utils = require('./utils')
const config = require('./config')

process.env.NODE_ENV = 'production'

const formats = argv.format
  ? argv.format.split(',').map(s => s.trim())
  : ['es', 'cjs', 'umd']

const srcPath = utils.resolve('src')
// form list of all packages to bundle
getAllPackages()
  .then(packages => {
    // traverse all provided formats
    return formats.reduce((prev, format) => {
      return prev.then(() => {
        if (format === 'umd') {
          packages = packages.slice(0, 1)
          packages[0].entry = config.umdEntry
        }
        // bundle each package in provided format
        return packages.reduce((prev, package) => {
          return prev.then(() => makeBundle(bundleOptions(format, package, process.env.NODE_ENV)))
        }, Promise.resolve())
      })
    }, Promise.resolve())
  })
  .then(() => {
    notifier.notify({
      title: config.fullname,
      message: 'All done!',
    })
  })
  .catch(err => {
    console.log(chalk.red(err.stack))
    process.exit(1)
  })

/********************************************************/
/* HELPERS                                              */
/********************************************************/
function getAllPackages () {
  const packages = [
    // main package
    {
      entry: config.entry,
      jsName: 'index',
      cssName: 'style',
      globName: config.fullname,
      amdName: config.name,
    },
  ]

  return Promise.all([
    packagesFromPath(utils.resolve('src/component'), utils.resolve('src/component')),
    packagesFromPath(utils.resolve('src/mixin'), srcPath),
    packagesFromPath(utils.resolve('src/ol-ext'), srcPath),
    packagesFromPath(utils.resolve('src/rx-ext'), srcPath),
    packagesFromPath(utils.resolve('src/util'), srcPath),
  ]).then(otherPackages => {
    return packages.concat(otherPackages.reduce((all, packages) => all.concat(packages), []))
  })
}

function packagesFromPath (searchPath, basePath = srcPath) {
  return utils.readDir(searchPath)
    .then(entries => entries.reduce((packages, entry) => {
      return packages.concat(entryToPackage(entry, basePath))
    }, []))
}

function entryToPackage (entry, basePath = srcPath) {
  let entryPath = entry.path
  if (!/\.js$/i.test(entryPath)) {
    entryPath = path.join(entry.path, 'index.js')
  }
  let jsName = path.relative(basePath, entryPath.replace(/\.js$/i, ''))
  let pkgName = jsName.replace(/\/index$/i, '')

  return {
    entry: entryPath,
    jsName,
    pkgName,
  }
}

function bundleOptions (format, package, env = 'development') {
  let options = Object.assign({}, package, {
    outputPath: config.outputPath,
    input: {
      input: package.entry,
    },
    output: {
      format,
      banner: config.banner,
      name: package.globName,
      amd: package.amdName ? {
        id: package.amdName,
      } : undefined,
    },
    format,
    env,
    // used before commonjs resolve
    replaces: Object.assign({
      '@import ~': '@import ',
      '@import "~': '@import "',
    }, config.replaces),
    // defines: {
    //   IS_STANDALONE: false,
    // },
  })

  // es/cjs external resolver
  const external = (id, parentId) => {
    if (!parentId) {
      return false
    }
    if (/\.(sass|vue)$/i.test(id)) {
      return false
    }
    // embeddable
    const embeddableRegExp = /(\.\/|src\/)(install)/i
    if (embeddableRegExp.test(id)) {
      return false
    }
    // check internal component imports
    const componentsRegExp = /component\/.*/i
    return !(
      componentsRegExp.test(parentId) && (
        id.slice(0, 2) === './' ||
        id.match(/\.vue\?rollup-plugin-vue/i) ||
        componentsRegExp.test(id) &&
        path.basename(path.dirname(id)) === path.basename(path.dirname(parentId))
      )
    )
  }
  // es/cjs path replacements in 2 phases
  const patterns = [
    [
      // component/**/* -> **/* replacement
      {
        test: /'(\.{1,2})\/component\/([^']*)'/ig,
        replace: (m1, m2, m3) => `'${m2}/${m3}'`,
      },
      // mixin/util/ol-ext/rx-ext path inside component replacement
      {
        include: [
          'src/component/**/*',
        ],
        test: /'(?:\.{2}\/){2}((?:mixin|ol-ext|rx-ext|util)\/[^']*)'/ig,
        replace: (m1, m2) => `'../${m2}'`,
      },
    ],
  ]

  switch (format) {
    case 'umd':
      options.jsName += '.' + format
      options.cssName = undefined
      options.output.globals = {
        vue: 'Vue',
        openlayers: 'ol',
      }
      options.input.external = ['vue', 'openlayers']
      options.replaces['process.env.NODE_ENV'] = `'${env}'`
      options.minify = true
      // process.env.BABEL_ENV = 'es5-production'
      // options.defines.IS_STANDALONE = true
      break
    case 'cjs':
      options.input.external = external
      options.patterns = patterns
      // process.env.BABEL_ENV = 'es5-production'
      break
    case 'es':
      options.input.external = external
      options.patterns = patterns
      // options.outputPath = path.join(options.outputPath, '_esm')
      // options.cssName = undefined
      break
  }

  return options
}

function makeBundle (options = {}) {
  let stylesPromise = Promise.resolve([])

  const plugins = [
    // compile-time variables replace
    replace({
      sourceMap: true,
      include: [
        'src/**/*',
      ],
      replaces: options.replaces,
      defines: options.defines,
    }),
    vue({
      sourceMap: true,
      css: false,
    }),
    sass({
      sass: {
        indentedSyntax: true,
        includePaths: [
          utils.resolve('src'),
          utils.resolve('src/sass'),
          utils.resolve('node_modules'),
        ],
      },
      output: styles => {
        stylesPromise = Promise.resolve(styles || [])
      },
    }),
    babel({
      runtimeHelpers: true,
      sourceMap: true,
      include: [
        'src/**/*',
        'node_modules/ol-tilecache/**/*',
        'node_modules/rxjs/_esm2015/**/*',
        'node_modules/lodash-es/**/*',
      ],
      extensions: ['.js', '.jsx', '.es6', '.es', '.mjs', '.vue'],
    }),
    nodeResolve({
      main: true,
      module: true,
      jsnext: true,
      browser: true,
    }),
    cjs(),
    // paths replace
    ...(
      options.patterns
        ? options.patterns.map(patterns => replace({
          include: [
            'src/**/*',
          ],
          sourceMap: true,
          patterns,
        }))
        : []
    ),
  ]

  if (options.minify) {
    // options.jsName += '.min'
    // if (options.cssName) {
    //   options.cssName += '.min'
    // }

    plugins.push(
      uglify({
        mangle: true,
        sourcemap: true,
        compress: {
          warnings: false,
        },
        output: {
          comments: (node, comment) => {
            let text = comment.value
            let type = comment.type
            if (type === 'comment2') {
              // multiline comment
              return /@preserve|@license|@cc_on/i.test(text)
            }
          },
        },
      })
    )
  }

  const jsOutputPath = path.join(options.outputPath, options.jsName) + '.js'
  const cssOutputPath = options.cssName
    ? path.join(options.outputPath, options.cssName) + '.css'
    : undefined

  const spinner = ora(chalk.bold.blue(`making ${options.format} ${options.jsName} bundle...`)).start()

  // prepare rollup bundler
  return rollup.rollup(Object.assign({}, options.input, {
    plugins,
  })).then(bundle => {
    // generate bundle
    return bundle.generate(Object.assign({}, options.output, {
      sourcemap: true,
      sourcemapFile: jsOutputPath,
    }))
  }).then(js => {
    // concatenate all styles from Sass and Vue files
    if (!cssOutputPath) {
      return {js, css: undefined}
    }

    return stylesPromise.then(styles => {
      const files = styles.reduce((all, css) => {
        if (!css.code) return all

        return all.concat(Object.assign(css, {
          sourcesRelativeTo: css.id,
        }))
      }, [])

      const css = utils.concatFiles(files, cssOutputPath, options.output.banner)

      return utils.postcssProcess(css, options.minify)
    }).then(css => ({ js, css }))
  }).then(({ js, css }) => {
    // write js / css bundles to output path
    return Promise.all([
      utils.writeFile(jsOutputPath, js.code),
      utils.writeFile(jsOutputPath + '.map', JSON.stringify(js.map)),
      css && utils.writeFile(cssOutputPath, css.code),
      css && utils.writeFile(cssOutputPath + '.map', JSON.stringify(css.map)),
    ])
  }).then(([jsSrc, jsMap, cssSrc, cssMap]) => {
    // output results
    spinner.succeed(chalk.green(`bundle ${options.format} ${options.jsName} was created successfully`))

    console.log(jsSrc.path, chalk.gray(jsSrc.size))
    console.log(jsMap.path, chalk.gray(jsMap.size))
    cssSrc && console.log(cssSrc.path, chalk.gray(cssSrc.size))
    cssMap && console.log(cssMap.path, chalk.gray(cssMap.size))
  }).catch(err => {
    spinner.fail(chalk.red(`bundle ${options.jsName} could not be created`))
    throw err
  })
}
<commit_msg>fix rollup build: improve external regex<commit_after>const path = require('path')
const chalk = require('chalk')
const ora = require('ora')
const rollup = require('rollup')
const babel = require('rollup-plugin-babel')
const cjs = require('rollup-plugin-commonjs')
const nodeResolve = require('rollup-plugin-node-resolve')
const replace = require('rollup-plugin-re')
const vue = require('rollup-plugin-vue').default
const uglify = require('rollup-plugin-uglify').uglify
const sass = require('./rollup/sass')
const notifier = require('node-notifier')
const argv = require('yargs').argv
const utils = require('./utils')
const config = require('./config')

process.env.NODE_ENV = 'production'

const formats = argv.format
  ? argv.format.split(',').map(s => s.trim())
  : ['es', 'cjs', 'umd']

const srcPath = utils.resolve('src')
// form list of all packages to bundle
getAllPackages()
  .then(packages => {
    // traverse all provided formats
    return formats.reduce((prev, format) => {
      return prev.then(() => {
        if (format === 'umd') {
          packages = packages.slice(0, 1)
          packages[0].entry = config.umdEntry
        }
        // bundle each package in provided format
        return packages.reduce((prev, package) => {
          return prev.then(() => makeBundle(bundleOptions(format, package, process.env.NODE_ENV)))
        }, Promise.resolve())
      })
    }, Promise.resolve())
  })
  .then(() => {
    notifier.notify({
      title: config.fullname,
      message: 'All done!',
    })
  })
  .catch(err => {
    console.log(chalk.red(err.stack))
    process.exit(1)
  })

/********************************************************/
/* HELPERS                                              */
/********************************************************/
function getAllPackages () {
  const packages = [
    // main package
    {
      entry: config.entry,
      jsName: 'index',
      cssName: 'style',
      globName: config.fullname,
      amdName: config.name,
    },
  ]

  return Promise.all([
    packagesFromPath(utils.resolve('src/component'), utils.resolve('src/component')),
    packagesFromPath(utils.resolve('src/mixin'), srcPath),
    packagesFromPath(utils.resolve('src/ol-ext'), srcPath),
    packagesFromPath(utils.resolve('src/rx-ext'), srcPath),
    packagesFromPath(utils.resolve('src/util'), srcPath),
  ]).then(otherPackages => {
    return packages.concat(otherPackages.reduce((all, packages) => all.concat(packages), []))
  })
}

function packagesFromPath (searchPath, basePath = srcPath) {
  return utils.readDir(searchPath)
    .then(entries => entries.reduce((packages, entry) => {
      return packages.concat(entryToPackage(entry, basePath))
    }, []))
}

function entryToPackage (entry, basePath = srcPath) {
  let entryPath = entry.path
  if (!/\.js$/i.test(entryPath)) {
    entryPath = path.join(entry.path, 'index.js')
  }
  let jsName = path.relative(basePath, entryPath.replace(/\.js$/i, ''))
  let pkgName = jsName.replace(/\/index$/i, '')

  return {
    entry: entryPath,
    jsName,
    pkgName,
  }
}

function bundleOptions (format, package, env = 'development') {
  let options = Object.assign({}, package, {
    outputPath: config.outputPath,
    input: {
      input: package.entry,
    },
    output: {
      format,
      banner: config.banner,
      name: package.globName,
      amd: package.amdName ? {
        id: package.amdName,
      } : undefined,
    },
    format,
    env,
    // used before commonjs resolve
    replaces: Object.assign({
      '@import ~': '@import ',
      '@import "~': '@import "',
    }, config.replaces),
    // defines: {
    //   IS_STANDALONE: false,
    // },
  })

  // es/cjs external resolver
  const external = (id, parentId) => {
    if (!parentId) {
      return false
    }
    if (/\.(sass|vue)$/i.test(id)) {
      return false
    }
    // embeddable
    const embeddableRegExp = /(\.\/|src\/)(install)/i
    if (embeddableRegExp.test(id)) {
      return false
    }
    // check internal component imports
    const componentsRegExp = /component\/.*/i
    return !(
      componentsRegExp.test(parentId) && (
        id.slice(0, 2) === './' ||
        id.match(/\.vue\?rollup-plugin-vue/i) ||
        componentsRegExp.test(id) &&
        path.basename(path.dirname(id)) === path.basename(path.dirname(parentId))
      )
    )
  }
  // es/cjs path replacements in 2 phases
  const patterns = [
    [
      // component/**/* -> **/* replacement
      {
        test: /'(\.{1,2})\/component\/([^']*)'/ig,
        replace: (m1, m2, m3) => `'${m2}/${m3}'`,
      },
      // mixin/util/ol-ext/rx-ext path inside component replacement
      {
        include: [
          'src/component/**/*',
        ],
        test: /'(?:\.{2}\/){2}((?:mixin|ol-ext|rx-ext|util)[^']*)'/ig,
        replace: (m1, m2) => `'../${m2}'`,
      },
    ],
  ]

  switch (format) {
    case 'umd':
      options.jsName += '.' + format
      options.cssName = undefined
      options.output.globals = {
        vue: 'Vue',
        openlayers: 'ol',
      }
      options.input.external = ['vue', 'openlayers']
      options.replaces['process.env.NODE_ENV'] = `'${env}'`
      options.minify = true
      // process.env.BABEL_ENV = 'es5-production'
      // options.defines.IS_STANDALONE = true
      break
    case 'cjs':
      options.input.external = external
      options.patterns = patterns
      // process.env.BABEL_ENV = 'es5-production'
      break
    case 'es':
      options.input.external = external
      options.patterns = patterns
      // options.outputPath = path.join(options.outputPath, '_esm')
      // options.cssName = undefined
      break
  }

  return options
}

function makeBundle (options = {}) {
  let stylesPromise = Promise.resolve([])

  const plugins = [
    // compile-time variables replace
    replace({
      sourceMap: true,
      include: [
        'src/**/*',
      ],
      replaces: options.replaces,
      defines: options.defines,
    }),
    vue({
      sourceMap: true,
      css: false,
    }),
    sass({
      sass: {
        indentedSyntax: true,
        includePaths: [
          utils.resolve('src'),
          utils.resolve('src/sass'),
          utils.resolve('node_modules'),
        ],
      },
      output: styles => {
        stylesPromise = Promise.resolve(styles || [])
      },
    }),
    babel({
      runtimeHelpers: true,
      sourceMap: true,
      include: [
        'src/**/*',
        'node_modules/ol-tilecache/**/*',
        'node_modules/rxjs/_esm2015/**/*',
        'node_modules/lodash-es/**/*',
      ],
      extensions: ['.js', '.jsx', '.es6', '.es', '.mjs', '.vue'],
    }),
    nodeResolve({
      main: true,
      module: true,
      jsnext: true,
      browser: true,
    }),
    cjs(),
    // paths replace
    ...(
      options.patterns
        ? options.patterns.map(patterns => replace({
          include: [
            'src/**/*',
          ],
          sourceMap: true,
          patterns,
        }))
        : []
    ),
  ]

  if (options.minify) {
    // options.jsName += '.min'
    // if (options.cssName) {
    //   options.cssName += '.min'
    // }

    plugins.push(
      uglify({
        mangle: true,
        sourcemap: true,
        compress: {
          warnings: false,
        },
        output: {
          comments: (node, comment) => {
            let text = comment.value
            let type = comment.type
            if (type === 'comment2') {
              // multiline comment
              return /@preserve|@license|@cc_on/i.test(text)
            }
          },
        },
      })
    )
  }

  const jsOutputPath = path.join(options.outputPath, options.jsName) + '.js'
  const cssOutputPath = options.cssName
    ? path.join(options.outputPath, options.cssName) + '.css'
    : undefined

  const spinner = ora(chalk.bold.blue(`making ${options.format} ${options.jsName} bundle...`)).start()

  // prepare rollup bundler
  return rollup.rollup(Object.assign({}, options.input, {
    plugins,
  })).then(bundle => {
    // generate bundle
    return bundle.generate(Object.assign({}, options.output, {
      sourcemap: true,
      sourcemapFile: jsOutputPath,
    }))
  }).then(js => {
    // concatenate all styles from Sass and Vue files
    if (!cssOutputPath) {
      return {js, css: undefined}
    }

    return stylesPromise.then(styles => {
      const files = styles.reduce((all, css) => {
        if (!css.code) return all

        return all.concat(Object.assign(css, {
          sourcesRelativeTo: css.id,
        }))
      }, [])

      const css = utils.concatFiles(files, cssOutputPath, options.output.banner)

      return utils.postcssProcess(css, options.minify)
    }).then(css => ({ js, css }))
  }).then(({ js, css }) => {
    // write js / css bundles to output path
    return Promise.all([
      utils.writeFile(jsOutputPath, js.code),
      utils.writeFile(jsOutputPath + '.map', JSON.stringify(js.map)),
      css && utils.writeFile(cssOutputPath, css.code),
      css && utils.writeFile(cssOutputPath + '.map', JSON.stringify(css.map)),
    ])
  }).then(([jsSrc, jsMap, cssSrc, cssMap]) => {
    // output results
    spinner.succeed(chalk.green(`bundle ${options.format} ${options.jsName} was created successfully`))

    console.log(jsSrc.path, chalk.gray(jsSrc.size))
    console.log(jsMap.path, chalk.gray(jsMap.size))
    cssSrc && console.log(cssSrc.path, chalk.gray(cssSrc.size))
    cssMap && console.log(cssMap.path, chalk.gray(cssMap.size))
  }).catch(err => {
    spinner.fail(chalk.red(`bundle ${options.jsName} could not be created`))
    throw err
  })
}
<|endoftext|>


<commit_before>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-present Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import {
  Button,
  Glyphicon,
  DropdownButton,
  MenuItem,
  Form,
  FormControl,
  ControlLabel,
  FormGroup,
  Col,
  Table,
} from 'react-bootstrap';
import PropTypes from 'prop-types';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import * as moment from 'moment';
import TextEditor from '../../components/TextEditor';
import StudyEntityView from '../../components/StudyEntityView';
import s from './StudyEntity.css';

class StudyEntity extends React.Component {
  static contextTypes = {
    store: PropTypes.any.isRequired,
    fetch: PropTypes.func.isRequired,
  };
  static propTypes = {
    course: PropTypes.shape({
      id: PropTypes.string.isRequired,
      title: PropTypes.string.isRequired,
    }).isRequired,
    studyEntity: PropTypes.shape({
      id: PropTypes.string,
      title: PropTypes.string,
      body: PropTypes.string,
    }).isRequired,
  };

  constructor(props) {
    super(props);
    this.state = {
      editMode: false,
      title: this.props.studyEntity.title,
      body: this.props.studyEntity.body,
      answerId: null,
      mark: 0,
      comment: '',
      answer: {},
      role: '',
    };
    this.switchMode = this.switchMode.bind(this);
    this.changeTitle = this.changeTitle.bind(this);
    this.changeBody = this.changeBody.bind(this);
    this.changeAnswer = this.changeAnswer.bind(this);
    this.saveAnswer = this.saveAnswer.bind(this);
    this.save = this.save.bind(this);
    this.addMark = this.addMark.bind(this);
    this.changeMark = this.changeMark.bind(this);
    this.changeComment = this.changeComment.bind(this);
    this.cancel = this.cancel.bind(this);
    this.selectAnswer = this.selectAnswer.bind(this);
  }

  componentWillMount() {
    if (this.context.store.getState().user) {
      this.retrieveAnswer();
      this.setUserRole();
    }
  }

  getValidationState() {
    const { mark } = this.state;
    if (mark <= 100 && mark >= 0) return 'success';
    return 'error';
  }

  getUserRole() {
    return this.state.role;
  }

  async setUserRole() {
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `query getUserRole(
          $courseIds: [String],
          $userId: [String]
        ){
          courses(ids: $courseIds, userId: $userId){
            users {
                role,
              }
          }
        }`,
        variables: {
          courseIds: [this.props.course.id],
        },
      }),
    });
    const { data } = await resp.json();
    if (data !== null) {
      this.setState({
        role: data.courses[0].users[0].role,
      });
    }
  }

  changeTitle(event) {
    this.setState({ title: event.target.value });
  }

  changeBody(val) {
    this.setState({ body: val });
  }

  changeMark(event) {
    this.setState({ mark: event.target.value });
  }

  changeComment(event) {
    this.setState({ comment: event.target.value });
  }

  changeAnswer(val) {
    this.setState({ answer: val });
  }

  async saveAnswer() {
    if (this.state.answerId) {
      await this.context.fetch('/graphql', {
        body: JSON.stringify({
          query: `mutation update(
            $body: String,
            $id: String
          ){
            updateAnswer(
              body: $body,
              id: $id
            ){
              id
            }
          }`,
          variables: {
            body: JSON.stringify(this.state.answer),
            id: this.state.answerId,
          },
        }),
      });
    } else {
      await this.context.fetch('/graphql', {
        body: JSON.stringify({
          query: `mutation add(
            $body: String,
            $courseId: String,
            $userId: String,
            $studyEntityId: String
          ){
            addAnswer(
              body: $body,
              courseId: $courseId,
              userId: $userId,
              studyEntityId: $studyEntityId
            ){
              id
            }
          }`,
          variables: {
            body: JSON.stringify(this.state.answer),
            courseId: this.props.course.id,
            userId: this.context.store.getState().user.id,
            studyEntityId: this.props.studyEntity.id,
          },
        }),
      });
    }
  }

  switchMode() {
    this.setState({ editMode: !this.state.editMode });
  }

  async save() {
    await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `mutation create($title: String, $id: String, $body: String) {
          updateStudyEntity(
            title: $title,
            id: $id,
            body: $body,
          ){
            id,title
          }
        }`,
        variables: {
          title: this.state.title,
          id: this.props.studyEntity.id,
          body: this.state.body,
        },
      }),
    });
    this.switchMode();
  }

  cancel() {
    // TODO: change cancel bahaviour when user save values once
    this.setState({
      editMode: false,
      title: this.props.studyEntity.title,
      body: this.props.studyEntity.body,
    });
  }

  async addMark() {
    await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `mutation addMark($mark: Float, $comment: String, $answerId: String, $authorId: String) {
          addMark(
            mark: $mark,
            comment: $comment,
            answerId: $answerId,
            authorId: $authorId,
          ) {
            id
          }
        }`,
        variables: {
          mark: this.state.mark,
          comment: this.state.comment,
          answerId: this.state.answerId,
          authorId: this.context.store.getState().user.id,
        },
      }),
    });
    /* this.setState({
      mark: '',
      comment: '',
    }); */
  }

  async retrieveAnswer() {
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `query retrieveAnswers (
          $userIds: [String]
          $studyEntityIds: [String]
          $courseIds: [String]
        ){
          answers(
            userIds: $userIds,
            studyEntityIds: $studyEntityIds,
            courseIds: $courseIds
          ){
            id, body, marks {
              id, mark, comment, createdAt
            },
            user {
              id, profile {
                displayName
              }
            },
            createdAt
          }
        }`,
        variables: {
          userIds: !this.context.store.getState().user.isAdmin
            ? [this.context.store.getState().user.id]
            : null,
          studyEntityIds: [this.props.studyEntity.id],
          courseIds: [this.props.course.id],
        },
      }),
    });
    const { data } = await resp.json();
    if (data && data.answers && data.answers.length) {
      const answerCur = 0;
      this.setState({
        answers: data.answers.map(answer => {
          const ans = answer;
          ans.body = JSON.parse(answer.body);
          return ans;
        }),
        answerId: data.answers[answerCur].id,
        answer: data.answers[answerCur].body,
        answerCur,
      });
    }
  }

  selectAnswer(eventKey) {
    const answerCur = parseInt(eventKey, 10);
    this.setState({
      answerCur,
      answer: this.state.answers[answerCur].body,
      answerId: this.state.answers[answerCur].id,
    });
  }

  render() {
    let bodyComponent;
    let headerComponent;
    if (this.state.editMode) {
      bodyComponent = (
        <TextEditor value={this.state.body} onChange={this.changeBody} />
      );
      headerComponent = (

          <input
            value={this.state.title}
            type="text"
            onChange={this.changeTitle}
          />
          <Button onClick={this.save}>
            <Glyphicon glyph="ok" />
          </Button>
          <Button onClick={this.cancel}>
            <Glyphicon glyph="remove" />
          </Button>

      );
    } else {
      bodyComponent = (

          <StudyEntityView
            answerId={this.state.answerId}
            value={this.state.answer}
            body={this.state.body}
            onChange={this.changeAnswer}
          />
          {this.context.store.getState().user ? (
            <Button onClick={this.saveAnswer}>Save</Button>
          ) : (
            undefined
          )}

      );
      headerComponent = (

          {this.state.title}
          {this.getUserRole === 'teacher' ? (
            <Button onClick={this.switchMode}>
              <Glyphicon glyph="pencil" />
            </Button>
          ) : null}

      );
    }
    const { user } = this.context.store.getState();
    let answerChooser;
    let markView;
    if (user && user.isAdmin && this.state.answers) {
      const answerTitle = answer =>
        `${answer.user.profile.displayName} ${answer.createdAt}`;
      const answers = this.state.answers.map((answer, i) => (
        <MenuItem
          key={answer.id}
          eventKey={i}
          active={i === this.state.answerCur}
        >
          {answerTitle(answer)}
        </MenuItem>
      ));
      answerChooser = (
        <DropdownButton
          id="answer_chooser"
          title={answerTitle(this.state.answers[this.state.answerCur])}
          onSelect={this.selectAnswer}
        >
          {answers}
        </DropdownButton>
      );
      const marks = this.state.answers[this.state.answerCur].marks.map(
        (mark, i) => (

            {i + 1}
            {mark.mark}
            {mark.comment}

              {moment(mark.createdAt).fromNow()} ({moment(
                mark.createdAt,
              ).format('llll')})

        ),
      );
      markView = (

Marks list

                N
                Mark
                Comment
                Date

{marks}

          {/* Form for setting marks and making a comment */}
          <Form horizontal>
            <FormGroup controlId="Comment">
              <Col sm={10}>
                <FormControl
                  type="text"
                  placeholder="Comment"
                  value={this.state.comment}
                  onChange={this.changeComment}
                />
              </Col>
            </FormGroup>
            <ControlLabel>Set mark</ControlLabel>
            <FormGroup
              controlId="Mark"
              validationState={this.getValidationState()}
            >
              <Col sm={2}>
                <FormControl
                  type="number"
                  placeholder="Mark"
                  value={this.state.mark}
                  onChange={this.changeMark}
                />
              </Col>
              <Col sm={2}>
                {this.getValidationState() === 'success' ? (
                  <Button onClick={this.addMark}>
                    <Glyphicon glyph="ok" />
                  </Button>
                ) : null}
              </Col>
            </FormGroup>
          </Form>

      );
    }

    return (

            {this.props.course.title}/{headerComponent}
            {answerChooser}

          {bodyComponent}
          {markView}

    );
  }
}

export default withStyles(s)(StudyEntity);
<commit_msg>fix setUserRole in studyEntity<commit_after>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-present Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import {
  Button,
  Glyphicon,
  DropdownButton,
  MenuItem,
  Form,
  FormControl,
  ControlLabel,
  FormGroup,
  Col,
  Table,
} from 'react-bootstrap';
import _ from 'lodash';
import PropTypes from 'prop-types';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import * as moment from 'moment';
import TextEditor from '../../components/TextEditor';
import StudyEntityView from '../../components/StudyEntityView';
import s from './StudyEntity.css';

class StudyEntity extends React.Component {
  static contextTypes = {
    store: PropTypes.any.isRequired,
    fetch: PropTypes.func.isRequired,
  };
  static propTypes = {
    course: PropTypes.shape({
      id: PropTypes.string.isRequired,
      title: PropTypes.string.isRequired,
    }).isRequired,
    studyEntity: PropTypes.shape({
      id: PropTypes.string,
      title: PropTypes.string,
      body: PropTypes.string,
    }).isRequired,
  };

  constructor(props) {
    super(props);
    this.state = {
      editMode: false,
      title: this.props.studyEntity.title,
      body: this.props.studyEntity.body,
      answerId: null,
      mark: 0,
      comment: '',
      answer: {},
      role: '',
    };
    this.switchMode = this.switchMode.bind(this);
    this.changeTitle = this.changeTitle.bind(this);
    this.changeBody = this.changeBody.bind(this);
    this.changeAnswer = this.changeAnswer.bind(this);
    this.saveAnswer = this.saveAnswer.bind(this);
    this.save = this.save.bind(this);
    this.addMark = this.addMark.bind(this);
    this.changeMark = this.changeMark.bind(this);
    this.changeComment = this.changeComment.bind(this);
    this.cancel = this.cancel.bind(this);
    this.selectAnswer = this.selectAnswer.bind(this);
  }

  componentWillMount() {
    if (this.context.store.getState().user) {
      this.retrieveAnswer();
      this.setUserRole();
    }
  }

  getValidationState() {
    const { mark } = this.state;
    if (mark <= 100 && mark >= 0) return 'success';
    return 'error';
  }

  getUserRole() {
    return this.state.role;
  }

  async setUserRole() {
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `query getUserRole(
          $courseIds: [String],
          $userId: [String]
        ){
          courses(ids: $courseIds, userId: $userId){
            users {
                role,
              }
          }
        }`,
        variables: {
          courseIds: [this.props.course.id],
        },
      }),
    });
    const { data } = await resp.json();
    if (_.get(data, 'courses[0].users[0]')) {
      this.setState({
        role: data.courses[0].users[0].role,
      });
    }
  }

  changeTitle(event) {
    this.setState({ title: event.target.value });
  }

  changeBody(val) {
    this.setState({ body: val });
  }

  changeMark(event) {
    this.setState({ mark: event.target.value });
  }

  changeComment(event) {
    this.setState({ comment: event.target.value });
  }

  changeAnswer(val) {
    this.setState({ answer: val });
  }

  async saveAnswer() {
    if (this.state.answerId) {
      await this.context.fetch('/graphql', {
        body: JSON.stringify({
          query: `mutation update(
            $body: String,
            $id: String
          ){
            updateAnswer(
              body: $body,
              id: $id
            ){
              id
            }
          }`,
          variables: {
            body: JSON.stringify(this.state.answer),
            id: this.state.answerId,
          },
        }),
      });
    } else {
      await this.context.fetch('/graphql', {
        body: JSON.stringify({
          query: `mutation add(
            $body: String,
            $courseId: String,
            $userId: String,
            $studyEntityId: String
          ){
            addAnswer(
              body: $body,
              courseId: $courseId,
              userId: $userId,
              studyEntityId: $studyEntityId
            ){
              id
            }
          }`,
          variables: {
            body: JSON.stringify(this.state.answer),
            courseId: this.props.course.id,
            userId: this.context.store.getState().user.id,
            studyEntityId: this.props.studyEntity.id,
          },
        }),
      });
    }
  }

  switchMode() {
    this.setState({ editMode: !this.state.editMode });
  }

  async save() {
    await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `mutation create($title: String, $id: String, $body: String) {
          updateStudyEntity(
            title: $title,
            id: $id,
            body: $body,
          ){
            id,title
          }
        }`,
        variables: {
          title: this.state.title,
          id: this.props.studyEntity.id,
          body: this.state.body,
        },
      }),
    });
    this.switchMode();
  }

  cancel() {
    // TODO: change cancel bahaviour when user save values once
    this.setState({
      editMode: false,
      title: this.props.studyEntity.title,
      body: this.props.studyEntity.body,
    });
  }

  async addMark() {
    await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `mutation addMark($mark: Float, $comment: String, $answerId: String, $authorId: String) {
          addMark(
            mark: $mark,
            comment: $comment,
            answerId: $answerId,
            authorId: $authorId,
          ) {
            id
          }
        }`,
        variables: {
          mark: this.state.mark,
          comment: this.state.comment,
          answerId: this.state.answerId,
          authorId: this.context.store.getState().user.id,
        },
      }),
    });
    /* this.setState({
      mark: '',
      comment: '',
    }); */
  }

  async retrieveAnswer() {
    const resp = await this.context.fetch('/graphql', {
      body: JSON.stringify({
        query: `query retrieveAnswers (
          $userIds: [String]
          $studyEntityIds: [String]
          $courseIds: [String]
        ){
          answers(
            userIds: $userIds,
            studyEntityIds: $studyEntityIds,
            courseIds: $courseIds
          ){
            id, body, marks {
              id, mark, comment, createdAt
            },
            user {
              id, profile {
                displayName
              }
            },
            createdAt
          }
        }`,
        variables: {
          userIds: !this.context.store.getState().user.isAdmin
            ? [this.context.store.getState().user.id]
            : null,
          studyEntityIds: [this.props.studyEntity.id],
          courseIds: [this.props.course.id],
        },
      }),
    });
    const { data } = await resp.json();
    if (data && data.answers && data.answers.length) {
      const answerCur = 0;
      this.setState({
        answers: data.answers.map(answer => {
          const ans = answer;
          ans.body = JSON.parse(answer.body);
          return ans;
        }),
        answerId: data.answers[answerCur].id,
        answer: data.answers[answerCur].body,
        answerCur,
      });
    }
  }

  selectAnswer(eventKey) {
    const answerCur = parseInt(eventKey, 10);
    this.setState({
      answerCur,
      answer: this.state.answers[answerCur].body,
      answerId: this.state.answers[answerCur].id,
    });
  }

  render() {
    let bodyComponent;
    let headerComponent;
    if (this.state.editMode) {
      bodyComponent = (
        <TextEditor value={this.state.body} onChange={this.changeBody} />
      );
      headerComponent = (

          <input
            value={this.state.title}
            type="text"
            onChange={this.changeTitle}
          />
          <Button onClick={this.save}>
            <Glyphicon glyph="ok" />
          </Button>
          <Button onClick={this.cancel}>
            <Glyphicon glyph="remove" />
          </Button>

      );
    } else {
      bodyComponent = (

          <StudyEntityView
            answerId={this.state.answerId}
            value={this.state.answer}
            body={this.state.body}
            onChange={this.changeAnswer}
          />
          {this.context.store.getState().user ? (
            <Button onClick={this.saveAnswer}>Save</Button>
          ) : (
            undefined
          )}

      );
      headerComponent = (

          {this.state.title}
          {this.getUserRole === 'teacher' ? (
            <Button onClick={this.switchMode}>
              <Glyphicon glyph="pencil" />
            </Button>
          ) : null}

      );
    }
    const { user } = this.context.store.getState();
    let answerChooser;
    let markView;
    if (user && user.isAdmin && this.state.answers) {
      const answerTitle = answer =>
        `${answer.user.profile.displayName} ${answer.createdAt}`;
      const answers = this.state.answers.map((answer, i) => (
        <MenuItem
          key={answer.id}
          eventKey={i}
          active={i === this.state.answerCur}
        >
          {answerTitle(answer)}
        </MenuItem>
      ));
      answerChooser = (
        <DropdownButton
          id="answer_chooser"
          title={answerTitle(this.state.answers[this.state.answerCur])}
          onSelect={this.selectAnswer}
        >
          {answers}
        </DropdownButton>
      );
      const marks = this.state.answers[this.state.answerCur].marks.map(
        (mark, i) => (

            {i + 1}
            {mark.mark}
            {mark.comment}

              {moment(mark.createdAt).fromNow()} ({moment(
                mark.createdAt,
              ).format('llll')})

        ),
      );
      markView = (

Marks list

                N
                Mark
                Comment
                Date

{marks}

          {/* Form for setting marks and making a comment */}
          <Form horizontal>
            <FormGroup controlId="Comment">
              <Col sm={10}>
                <FormControl
                  type="text"
                  placeholder="Comment"
                  value={this.state.comment}
                  onChange={this.changeComment}
                />
              </Col>
            </FormGroup>
            <ControlLabel>Set mark</ControlLabel>
            <FormGroup
              controlId="Mark"
              validationState={this.getValidationState()}
            >
              <Col sm={2}>
                <FormControl
                  type="number"
                  placeholder="Mark"
                  value={this.state.mark}
                  onChange={this.changeMark}
                />
              </Col>
              <Col sm={2}>
                {this.getValidationState() === 'success' ? (
                  <Button onClick={this.addMark}>
                    <Glyphicon glyph="ok" />
                  </Button>
                ) : null}
              </Col>
            </FormGroup>
          </Form>

      );
    }

    return (

            {this.props.course.title}/{headerComponent}
            {answerChooser}

          {bodyComponent}
          {markView}

    );
  }
}

export default withStyles(s)(StudyEntity);
<|endoftext|>


<commit_before>module.exports = {
    all: {
        options: {
            sourceMap: true,
            sourceMapIncludeSources: true,
        },
        files: [
            {dest: global.dist + '/js/binary.min.js', src: global.dist + '/js/binary.js'},
            {dest: global.dist + '/js/binary_pack.min.js', src: global.dist + '/js/binary_pack.js'}
        ]
    }
};
<commit_msg>Removed binary_pack from uglify<commit_after>module.exports = {
    all: {
        options: {
            sourceMap: true,
            sourceMapIncludeSources: true,
        },
        files: [
            {dest: global.dist + '/js/binary.min.js', src: global.dist + '/js/binary.js'}
        ]
    }
};
<|endoftext|>


<commit_before>(function() {
	IssueTrackingSystem.controller('User', ['$scope', '$location', 'authentication', '$sessionStorage',
			function ($scope, $location, authentication, $sessionStorage) {

				$scope.loginUserInSystem = function (user) {
					authentication.loginUser(user)
						.then(function (loggedUser) {
							$sessionStorage.isAuthenticated = true;
							$sessionStorage.access_token = loggedUser.access_token;
							$sessionStorage.token_type = loggedUser.token_type;
							$sessionStorage.user = loggedUser.userName;
							$location.path('/');
						})
				};

				$scope.registerUserInSystem = function (user) {
					authentication.registerUser(user)
						.then(function (registeredUser) {
							console.log(registeredUser);
						})

				}

	}]);
})();<commit_msg>complete logout function<commit_after>(function() {
	IssueTrackingSystem.controller('User', ['$scope', '$location', 'authentication', '$sessionStorage',
			function ($scope, $location, authentication, $sessionStorage) {

				$scope.loginUserInSystem = function (user) {
					authentication.loginUser(user)
						.then(function (loggedUser) {
							$sessionStorage.isAuthenticated = true;
							$sessionStorage.access_token = loggedUser.access_token;
							$sessionStorage.token_type = loggedUser.token_type;
							$sessionStorage.user = loggedUser.userName;
							$location.path('/');
						})
				};

				$scope.registerUserInSystem = function (user) {
					authentication.registerUser(user)
						.then(function (registeredUser) {
							console.log(registeredUser);
						})

				};

				$scope.logoutUser = function () {
					delete $sessionStorage.access_token;
					delete $sessionStorage.token_type;
					delete $sessionStorage.user;
					$sessionStorage.isAuthenticated = false;
					$location.path('/login');
				}

	}]);
})();<|endoftext|>


<commit_before>var _ = require('lodash');

var React = require('react');

var MessagesSection = require('./dialog/MessagesSection.react');
var ComposeSection = require('./dialog/ComposeSection.react');

var DialogStore = require('../stores/DialogStore');
var MessageStore = require('../stores/MessageStore');

var _renderMessagesStep = 100;
var _renderMessagesCount = 100;

var getStateFromStores = function() {
  var messages = MessageStore.getAll();

  var messagesToRender;

  if (messages.length > _renderMessagesCount) {
    messagesToRender = messages.slice(messages.length - _renderMessagesCount);
  } else {
    messagesToRender = messages;
  }

  return({
    dialog: DialogStore.getSelectedDialog(),
    messages: messages,
    messagesToRender: messagesToRender
  });
};

var _lastScrolledFromBottom = 0;

var DialogSection = React.createClass({
  getInitialState: function() {
    return(getStateFromStores());
  },

  componentDidMount: function() {
    DialogStore.addSelectListener(this._onChange);
    MessageStore.addChangeListener(this._onChange);
  },

  componentWillUnmount: function() {
    MessageStore.removeChangeListener(this._onChange);
    DialogStore.removeSelectListener(this._onChange);
  },

  componentDidUpdate: function() {
    this._fixScroll()
  },

  render: function() {
    if (this.state.dialog) {
      return (

          <MessagesSection peer={this.state.dialog.peer.peer}
                           messages={this.state.messagesToRender}
                           ref="MessagesSection"/>
          <ComposeSection dialog={this.state.dialog}/>

      )
    } else {
      return(

      )
    }
  },

  _fixScroll: function() {
    var node = this.refs.MessagesSection.getDOMNode();
    node.scrollTop = node.scrollHeight - _lastScrolledFromBottom;
  },

  _onChange: _.debounce(function() {
    this.setState(getStateFromStores());
  }, 10, {maxWait: 50, leading: true}),

  _onScroll: _.debounce(function() {
    var node = this.refs.MessagesSection.getDOMNode();

    var scrollTop = node.scrollTop;
    _lastScrolledFromBottom = node.scrollHeight - scrollTop;

    if (node.scrollTop == 0) {
      if (this.state.messages.length > this.state.messagesToRender.length) {
        _renderMessagesCount += _renderMessagesStep;

        if (_renderMessagesCount > this.state.messages.length) {
          _renderMessagesCount = this.state.messages.length;
        }

        this.setState(getStateFromStores());
      }
    }
  }, 10)
});

module.exports = DialogSection;
<commit_msg>perf(web): way faster messages rendering<commit_after>var _ = require('lodash');

var React = require('react');

var MessagesSection = require('./dialog/MessagesSection.react');
var ComposeSection = require('./dialog/ComposeSection.react');

var DialogStore = require('../stores/DialogStore');
var MessageStore = require('../stores/MessageStore');

var _renderMessagesStep = 20;
var _renderMessagesCount = 10;

var getStateFromStores = function() {
  var messages = MessageStore.getAll();

  var messagesToRender;

  if (messages.length > _renderMessagesCount) {
    messagesToRender = messages.slice(messages.length - _renderMessagesCount);
  } else {
    messagesToRender = messages;
  }

  return({
    dialog: DialogStore.getSelectedDialog(),
    messages: messages,
    messagesToRender: messagesToRender
  });
};

var _lastScrolledFromBottom = 0;

var DialogSection = React.createClass({
  getInitialState: function() {
    return(getStateFromStores());
  },

  componentDidMount: function() {
    DialogStore.addSelectListener(this._onChange);
    MessageStore.addChangeListener(this._onChange);
  },

  componentWillUnmount: function() {
    MessageStore.removeChangeListener(this._onChange);
    DialogStore.removeSelectListener(this._onChange);
  },

  componentDidUpdate: function() {
    this._fixScroll();
    this._loadMessagesByScroll();
  },

  render: function() {
    if (this.state.dialog) {
      return (

          <MessagesSection peer={this.state.dialog.peer.peer}
                           messages={this.state.messagesToRender}
                           ref="MessagesSection"/>
          <ComposeSection dialog={this.state.dialog}/>

      )
    } else {
      return(

      )
    }
  },

  _fixScroll: function() {
    var node = this.refs.MessagesSection.getDOMNode();
    node.scrollTop = node.scrollHeight - _lastScrolledFromBottom;
  },

  _onChange: _.debounce(function() {
    this.setState(getStateFromStores());
  }, 10, {maxWait: 50, leading: true}),

  _loadMessagesByScroll: _.debounce(function() {
    var node = this.refs.MessagesSection.getDOMNode();

    var scrollTop = node.scrollTop;
    _lastScrolledFromBottom = node.scrollHeight - scrollTop;

    if (node.scrollTop == 0) {
      if (this.state.messages.length > this.state.messagesToRender.length) {
        _renderMessagesCount += _renderMessagesStep;

        if (_renderMessagesCount > this.state.messages.length) {
          _renderMessagesCount = this.state.messages.length;
        }

        this.setState(getStateFromStores());
      }
    }
  }, 10)
});

module.exports = DialogSection;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';

// Component styles
import 'style!./styles/Items.scss';
let styles = require('./styles/Items.scss').locals.styles;

// Actions
import { add, del } from '../../actions';

class Items extends Component {
  constructor() {
    super();
  }
  componentDidMount() {
    React.findDOMNode(this.refs.text).value = 'test';
  }
  render() {
    const { dispatch, items } = this.props;
    let _addClick = () => {
      this.props.dispatch(add(React.findDOMNode(this.refs.text).value));
    }
    return (
      <div className={ `${ styles }`} >
        <For each='item' of={ items }>

{ item }

        </For>

          <input type='text' className='form-control' ref='text' />

          <button className='btn btn-default' onClick={ () => _addClick() }>add</button>
          {' '}
          <button className='btn btn-default' onClick={ () => dispatch(del()) }>delete</button>

    );
  }
}

let select = (state) => {
  return {
    items: state.items
  };
}

export default connect(select)(Items);
<commit_msg>example "if"<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';

// Component styles
import 'style!./styles/Items.scss';
let styles = require('./styles/Items.scss').locals.styles;

// Actions
import { add, del } from '../../actions';

class Items extends Component {
  constructor() {
    super();
  }
  componentDidMount() {
    React.findDOMNode(this.refs.text).value = 'test';
  }
  render() {
    const { dispatch, items } = this.props;
    let _addClick = () => {
      this.props.dispatch(add(React.findDOMNode(this.refs.text).value));
    }
    return (
      <div className={ `${ styles }`} >
        <If condition={ !items.length }>
          Array is empty
        </If>
        <For each='item' of={ items }>

{ item }

        </For>

          <input type='text' className='form-control' ref='text' />

          <button className='btn btn-default' onClick={ () => _addClick() }>add</button>
          {' '}
          <button className='btn btn-default' onClick={ () => dispatch(del()) }>delete</button>

    );
  }
}

let select = (state) => {
  return {
    items: state.items
  };
}

export default connect(select)(Items);
<|endoftext|>