import Ember from 'ember';
import DS from 'ember-data';

export default DS.RESTAdapter.extend({
  namespace: 'api/v1',
  pathForType: function(type) {
    return Ember.String.underscore(type);
  }

  // handleResponse: function(status, headers, payload) {
  //   if (this.isSuccess(status, headers, payload)) {
  //     return payload;
  //   } else if (this.isInvalid(status, headers, payload)) {
  //     return new InvalidError(payload.errors);
  //   }

  //   let errors = this.normalizeErrorResponse(status, headers, payload);

  //   return new AdapterError(errors);
  // },

  // parseErrorResponse: function (responseText) {
  //   var json = responseText;
  //   console.log('parseErrorResponse');
  //   try {
  //     json = Ember.$.parseJSON(responseText);
  //   } catch (e) {}

  //   return json;
  // },

  // normalizeErrorResponse: function (status, headers, payload) {
  //   console.log('normalizeErrorResponse');
  //   if (payload && typeof payload === "object" && payload.errors) {
  //     return payload.errors;

  //   } else {
  //     return [{
  //       status: "" + status,
  //       title: "The backend responded with an error",
  //       details: "" + payload.message
  //     }];
  //   }
  // }

});

import Ember from 'ember';
import DS from 'ember-data';

export default DS.RESTAdapter.extend({
  namespace: 'api/v1',
  pathForType: function(type) {
    return Ember.String.underscore(type);
  },

  // NOTE: The default behavior of shouldReloadAll will change in Ember Data 2.0 to always return false when there is at least one "group" record in the store. If you would like to preserve the current behavior please override shouldReloadAll in your adapter:application and return true.
  shouldReloadAll: function () {
    return true;
  }

  // handleResponse: function(status, headers, payload) {
  //   if (this.isSuccess(status, headers, payload)) {
  //     return payload;
  //   } else if (this.isInvalid(status, headers, payload)) {
  //     return new InvalidError(payload.errors);
  //   }

  //   let errors = this.normalizeErrorResponse(status, headers, payload);

  //   return new AdapterError(errors);
  // },

  // parseErrorResponse: function (responseText) {
  //   var json = responseText;
  //   console.log('parseErrorResponse');
  //   try {
  //     json = Ember.$.parseJSON(responseText);
  //   } catch (e) {}

  //   return json;
  // },

  // normalizeErrorResponse: function (status, headers, payload) {
  //   console.log('normalizeErrorResponse');
  //   if (payload && typeof payload === "object" && payload.errors) {
  //     return payload.errors;

  //   } else {
  //     return [{
  //       status: "" + status,
  //       title: "The backend responded with an error",
  //       details: "" + payload.message
  //     }];
  //   }
  // }

});

Fix ember data shouldReloadAll deprecation


/**
 * Utility methods used when querying a site in order to discover its available
 * API endpoints
 *
 * @module autodiscovery
 */
'use strict';

const parseLinkHeader = require( 'parse-link-header' );

/**
 * Attempt to locate a `rel="https://api.w.org"` link relation header
 *
 * @method locateAPIRootHeader
 * @param {Object} response A response object with a link or headers property
 * @returns {String} The URL of the located API root
 */
function locateAPIRootHeader( response ) {
	// Extract & parse the response link headers
	const link = response.link || ( response.headers && response.headers.link );
	const headers = parseLinkHeader( link );

	// See https://developer.wordpress.org/rest-api/using-the-rest-api/discovery/
	const apiHeader = headers && headers[ 'https://api.w.org/' ];

	if ( apiHeader && apiHeader.url ) {
		return apiHeader.url;
	}

	throw new Error( 'No header link found with rel="https://api.w.org/"' );
}

module.exports = {
	locateAPIRootHeader: locateAPIRootHeader,
};

/**
 * Utility methods used when querying a site in order to discover its available
 * API endpoints
 *
 * @module autodiscovery
 */
'use strict';

const parseLinkHeader = require( 'parse-link-header' );

/**
 * Attempt to locate a `rel="https://api.w.org"` link relation header
 *
 * @method locateAPIRootHeader
 * @param {Object} response A response object with a link or headers property
 * @returns {String} The URL of the located API root
 */
function locateAPIRootHeader( response ) {
	// See https://developer.wordpress.org/rest-api/using-the-rest-api/discovery/
	const rel = 'https://api.w.org/';

	// Extract & parse the response link headers
	const link = response.link || ( response.headers && response.headers.link );
	const headers = parseLinkHeader( link );

	const apiHeader = headers && headers[ rel ];

	if ( apiHeader && apiHeader.url ) {
		return apiHeader.url;
	}

	throw new Error( `No header link found with rel="${ rel }"` );
}

module.exports = {
	locateAPIRootHeader: locateAPIRootHeader,
};

Reduce string duplication in autodisovery code


import initialState from './initialState';
import {
    BOARD_LIST_LOADED,
    BOARD_LIST_REQUESTED,
} from '../constants'

export default function (state=initialState.boardlist, action) {
    switch (action.type) {

        case BOARD_LIST_REQUESTED:
            return Object.assign({}, state, {
                isFetching: true,
                requestType: action.type  // for logging error to user...?
            })

        case BOARD_LIST_LOADED:
            return state[action.key] = action.payload

        default:
            return state
    }
}

import initialState from './initialState';
import {
    BOARD_LIST_LOADED,
    BOARD_LIST_REQUESTED,
} from '../constants'

export default function (state=initialState.boardlist, action) {
    switch (action.type) {

        case BOARD_LIST_REQUESTED:
            return Object.assign({}, state, {
                isFetching: true,
                requestType: action.type
            })

        case BOARD_LIST_LOADED:
            const newBoardlist = {}[action.key] = action.payload
            return Object.assign({}, state, newBoardlist)

        default:
            return state
    }
}

Fix mutated state in boardlist


'use strict'

const path = require('path')
const { DefinePlugin, ContextReplacementPlugin } = require('webpack')

const SRC_DIR = path.resolve(__dirname, '../src')

// See https://github.com/date-fns/date-fns/blob/master/docs/webpack.md
const supportedLocales = ['en', 'fr', 'es']
const regexpLocales = new RegExp(`/(${supportedLocales.join('|')})`)

module.exports = {
  resolve: {
    alias: {
      config: path.resolve(SRC_DIR, './config'),
      'redux-cozy-client': path.resolve(SRC_DIR, './lib/redux-cozy-client'),
      'cozy-ui/react': 'cozy-ui/transpiled/react'
    }
  },
  plugins: [
    new DefinePlugin({
      __PIWIK_SITEID__: 8,
      __PIWIK_DIMENSION_ID_APP__: 1,
      __PIWIK_TRACKER_URL__: JSON.stringify('https://piwik.cozycloud.cc')
    }),
    new ContextReplacementPlugin(/moment[\/\\]locale$/, regexpLocales),
    new ContextReplacementPlugin(/date-fns[\/\\]locale$/, regexpLocales),
    new ContextReplacementPlugin(/src[\/\\]locales/, regexpLocales),
  ]
}

'use strict'

const path = require('path')
const { DefinePlugin, ContextReplacementPlugin } = require('webpack')

const SRC_DIR = path.resolve(__dirname, '../src')

// See https://github.com/date-fns/date-fns/blob/master/docs/webpack.md
const supportedLocales = ['en', 'fr', 'es']
const regexpLocales = new RegExp(`/(${supportedLocales.join('|')})`)

module.exports = {
  resolve: {
    modules: [SRC_DIR, 'node_modules'],
    alias: {
      config: path.resolve(SRC_DIR, './config'),
      'redux-cozy-client': path.resolve(SRC_DIR, './lib/redux-cozy-client'),
      'cozy-ui/react': 'cozy-ui/transpiled/react'
    }
  },
  plugins: [
    new DefinePlugin({
      __PIWIK_SITEID__: 8,
      __PIWIK_DIMENSION_ID_APP__: 1,
      __PIWIK_TRACKER_URL__: JSON.stringify('https://piwik.cozycloud.cc')
    }),
    new ContextReplacementPlugin(/moment[\/\\]locale$/, regexpLocales),
    new ContextReplacementPlugin(/date-fns[\/\\]locale$/, regexpLocales),
    new ContextReplacementPlugin(/src[\/\\]locales/, regexpLocales)
  ]
}

Use relative resolve path for webpack


"use strict";

/* eslint no-undef:0 */
const { app, BrowserWindow, nativeImage } = require("electron");
const path = require("path");
const url = require("url");

let win;

let image = nativeImage.createFromPath(path.join(__dirname, "./img/icon.png"));
if (app.dock) {
  app.dock.setIcon(image);
}
function createWindow() {
  win = new BrowserWindow({
    width: 800,
    height: 600,
    icon: __dirname + "/img/icon.png",
    title: "Media Player",
    darkTheme: true,
    transparent: true,
    hasShadow: true,
    titleBarStyle: "hidden-inset"
  });
  win.setMenu(null);
  win.loadURL(url.format({
    pathname: path.join(__dirname, "./index.html"),
    protocol: "file:",
    slashes: true,
  }));
  win.on("closed", () => {
    win = null;
  });
}

app.on("ready", createWindow);

app.on("window-all-closed", () => app.quit());

app.on("activate", () => (win === null) ? createWindow() : 0);

"use strict";

/* eslint no-undef:0 */
const { app, BrowserWindow, nativeImage } = require("electron");
const path = require("path");
const url = require("url");

let win;

let image = nativeImage.createFromPath(path.join(__dirname, "./img/icon.png"));
if (app.dock) {
  app.dock.setIcon(image);
}
function createWindow() {
  win = new BrowserWindow({
    width: 800,
    height: 600,
    icon: __dirname + "/img/icon.png",
    title: "Media Player",
    darkTheme: true,
    hasShadow: true,
    titleBarStyle: "hidden-inset"
  });
  win.setMenu(null);
  win.loadURL(url.format({
    pathname: path.join(__dirname, "./index.html"),
    protocol: "file:",
    slashes: true,
  }));
  win.on("closed", () => {
    win = null;
  });
}

app.on("ready", createWindow);

app.on("window-all-closed", () => app.quit());

app.on("activate", () => (win === null) ? createWindow() : 0);

Remove transparency param for electron


const React = require('react')
const TextField = require('material-ui/TextField').default

const ModalOKCancel = require('./modal-ok-cancel')
const {dispatch, dispatcher} = require('../lib/dispatcher')

module.exports = class OpenTorrentAddressModal extends React.Component {
  render () {
    return (

Enter torrent address or magnet link

          <TextField
            className='control'
            ref={(c) => { this.torrentURL = c }}
            fullWidth
            onKeyDown={handleKeyDown.bind(this)} />

        <ModalOKCancel
          cancelText='CANCEL'
          onCancel={dispatcher('exitModal')}
          okText='OK'
          onOK={handleOK.bind(this)} />

    )
  }

  componentDidMount () {
    this.torrentURL.input.focus()
  }
}

function handleKeyDown (e) {
  if (e.which === 13) this.handleOK() /* hit Enter to submit */
}

function handleOK () {
  dispatch('exitModal')
  dispatch('addTorrent', this.torrentURL.input.value)
}

const React = require('react')
const TextField = require('material-ui/TextField').default

const ModalOKCancel = require('./modal-ok-cancel')
const {dispatch, dispatcher} = require('../lib/dispatcher')

module.exports = class OpenTorrentAddressModal extends React.Component {
  render () {
    return (

Enter torrent address or magnet link

          <TextField
            id='torrent-address-field'
            className='control'
            ref={(c) => { this.torrentURL = c }}
            fullWidth
            onKeyDown={handleKeyDown.bind(this)} />

        <ModalOKCancel
          cancelText='CANCEL'
          onCancel={dispatcher('exitModal')}
          okText='OK'
          onOK={handleOK.bind(this)} />

    )
  }

  componentDidMount () {
    this.torrentURL.input.focus()
  }
}

function handleKeyDown (e) {
  if (e.which === 13) handleOK.call(this) /* hit Enter to submit */
}

function handleOK () {
  dispatch('exitModal')
  dispatch('addTorrent', this.torrentURL.input.value)
}

Fix Open Torrent Address modal


var path = require('path')
var exec = require('child_process').exec
var chdir = require('chdir')
module.exports = function (config, cb) {
  if (!config.source) {
    cb(new Error('Source folder not provided'))
    return null
  }
  config.source = path.resolve(config.source)
  if (!config.dest) {
    config.dest = config.source
  } else {
    config.dest = path.resolve(config.dest)
  }
  if (!config.name) {
    config.name = path.basename(config.source)
  }
  chdir(config.source, function () {
    var zip_name = path.join(config.dest, config.name + '.zip')
    exec('zip -r ' + zip_name + ' ./', function(err, result) {
      if (err) {
        cb(err)
        return null
      }
      cb(null, zip_name)
    })
  })
}

var path = require('path')
var exec = require('child_process').exec
var chdir = require('chdir')
module.exports = function (config, cb) {
  if (!config.source) {
    cb(new Error('Source folder not provided'))
    return null
  }
  config.source = path.resolve(config.source)
  if (!config.dest) {
    config.dest = config.source
  } else {
    config.dest = path.resolve(config.dest)
  }
  if (!config.name) {
    config.name = path.basename(config.source)
  }
  chdir(config.source, function () {
    var zip_name = path.join(config.dest, config.name + '.zip')
    exec('zip -r ' + zip_name + ' ./', { maxBuffer: 1024 * 500 }, function (err, result) {
      if (err) {
        cb(err)
        return null
      }
      cb(null, zip_name)
    })
  })
}

Set maxBuffer when spawning child process


var Handlebars = require('handlebars');
var common = require('../lib/common');
var _ = require('lodash');

module.exports = function(reference, options) {
  if (!reference) {
    console.error("Cannot print null reference.");
    return '';
  }
  var model = common.resolveSchemaReference(reference, options.data.root);
  if (typeof model === 'object' && typeof model.properties === 'object')
    model = model.properties;
  var cloned = _.cloneDeep(model);
  Object.keys(cloned).forEach(function(propName) {
    var prop = cloned[propName];
    if (prop.type) {
      cloned[propName] = prop.type;
      if (prop.format) {
        cloned[propName] += ('(' + prop.format + ')');
      }
    }
  })
  if (options.hash.type == 'array')
    cloned = [cloned];
  var html = common.printSchema(cloned);
  return new Handlebars.SafeString(html);
};

var Handlebars = require('handlebars');
var common = require('../lib/common');
var _ = require('lodash');

module.exports = function(reference, options) {
  if (!reference) {
    console.error("Cannot print null reference.");
    return '';
  }
  var model = common.resolveSchemaReference(reference, options.data.root);
  if (typeof model === 'object' && typeof model.properties === 'object') {
    if (model['example']) {
      // Use the supplied example
      model = model.example;
      var cloned = _.cloneDeep(model);
    } else {
      // Create json object of keys : type info string
      model = model.properties;
      var cloned = _.cloneDeep(model);
      Object.keys(cloned).forEach(function(propName) {
        var prop = cloned[propName];
        if (prop.type) {
          cloned[propName] = prop.type;
          if (prop.format) {
            cloned[propName] += ('(' + prop.format + ')');
          }
        }
      })
    }
  }
  if (options.hash.type == 'array')
    cloned = [cloned];
  var html = common.printSchema(cloned);
  return new Handlebars.SafeString(html);
};

Use schema examples in 'request example'


function dataReduction(data, maxNum)
{
	var result = []
	for(var j=0, c=data.length; j<c; j++){
		var vals = []
		for(var i=0, num=data[j].length, step=Math.round(num/maxNum); i<num; i=i+step){
			vals.push( data[j][i] )
		}
		result.push(vals);
	}
	return result;
}

function setupChart(chartData, data, onCompletion)
{
	chartData["data"]=dataReduction(data, 30);
	if( onCompletion instanceof Function ) onCompletion();
}

function dataReduction(data, maxNum)
{
	if( data[0].length < maxNum ){
		return data;
	} else {
		var result = []
		for(var j=0, c=data.length; j<c; j++){
			var vals = []
			for(var i=0, num=data[j].length, step=num/maxNum; i<num; i=i+step){
				vals.push( data[j][Math.round(i)] )
			}
			result.push(vals);
		}
		return result;
	}
}

function setupChart(chartData, data, onCompletion)
{
	chartData["data"]=dataReduction(data, 30);
	if( onCompletion instanceof Function ) onCompletion();
}

Fix small num of data issue on PHP MQTT Dashboard


'use strict';

var _ = require('lodash');
var $ = require('jquery');

function render(container, options) {
  options = _.extend({
    countries: [],
    baseUrl: ''
  }, options);
  var ul = $('<ul>').addClass('list-country');
  _.each(options.countries, function(country) {
    var url = options.baseUrl + '?country=' + encodeURIComponent(country.code);
    $('<li>')
      .append(
        $('<a>').attr('href', url).text(country.name)
      )
      .appendTo(ul);
  });
  $(container).append(ul);
}

module.exports.render = render;

'use strict';

var _ = require('lodash');
var $ = require('jquery');

function render(container, options) {
  options = _.extend({
    countries: [],
    baseUrl: ''
  }, options);
  var ul = $('<ul>').addClass('list-country');
  _.each(options.countries, function(country) {
    var url = options.baseUrl + '?country=' + encodeURIComponent(country.code);
    $('<li>')
      .addClass(country.code == options.countryCode ? 'selected' : '')
      .append(
        $('<a>').attr('href', url).text(country.name)
      )
      .appendTo(ul);
  });
  $(container).append(ul);
}

module.exports.render = render;

Mark selected country in the country list


angular.module( 'gj.Form' ).directive( 'gjFormCurrencyInput', function( currencyFilter )
{
	var CURRENCY_REGEXP = /^[0-9]*(?:\.[0-9]{0,2})?$/;

	return {
		restrict: 'A',
		require: 'ngModel',
		link: function( scope, elem, attr, ngModel )
		{
			ngModel.$validators.currency = function( modelVal, viewVal )
			{
				if ( !ngModel.$valid ) {
					return true;
				}

				var val = modelVal || viewVal;
				return ngModel.$isEmpty( val ) || CURRENCY_REGEXP.test( val );
			};
		}
	};
} );

angular.module( 'gj.Form' ).directive( 'gjFormCurrencyInput', function( currencyFilter )
{
	var CURRENCY_REGEXP = /^[0-9]*(?:\.[0-9]{0,2})?$/;

	return {
		restrict: 'A',
		require: 'ngModel',
		link: function( scope, elem, attr, ngModel )
		{
			ngModel.$validators.currency = function( modelVal, viewVal )
			{
				var val = modelVal || viewVal;
				return ngModel.$isEmpty( val ) || CURRENCY_REGEXP.test( val );
			};
		}
	};
} );

Fix currency input when validating after typing multiple times.


// --
// Core.Agent.Admin.SysConfig.js - provides the special module functions for the AdminSysConfig
// Copyright (C) 2001-2010 OTRS AG, http://otrs.org/\n";
// --
// $Id: Core.Agent.Admin.SysConfig.js,v 1.1 2010-06-04 11:19:31 mn Exp $
// --
// This software comes with ABSOLUTELY NO WARRANTY. For details, see
// the enclosed file COPYING for license information (AGPL). If you
// did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
// --

"use strict";

var Core = Core || {};
Core.Agent = Core.Agent || {};
Core.Agent.Admin = Core.Agent.Admin || {};

/**
 * @namespace
 * @exports TargetNS as Core.Agent.Admin.SysConfig
 * @description
 *      This namespace contains the special module functions for the SysConfig module.
 */
Core.Agent.Admin.SysConfig = (function (TargetNS) {
    /**
     * @function
     * @return nothing
     *      This function initializes the special module functions
     */
    TargetNS.Init = function () {
        $('.AdminSysConfig h3 input:checkbox').click(function () {
            $(this).parent('h3').parent('fieldset').toggleClass('Invalid');
        });
    };

    return TargetNS;
}(Core.Agent.Admin.SysConfig || {}));

// --
// Core.Agent.Admin.SysConfig.js - provides the special module functions for the AdminSysConfig
// Copyright (C) 2001-2010 OTRS AG, http://otrs.org/\n";
// --
// $Id: Core.Agent.Admin.SysConfig.js,v 1.2 2010-06-22 11:24:49 mg Exp $
// --
// This software comes with ABSOLUTELY NO WARRANTY. For details, see
// the enclosed file COPYING for license information (AGPL). If you
// did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
// --

"use strict";

var Core = Core || {};
Core.Agent = Core.Agent || {};
Core.Agent.Admin = Core.Agent.Admin || {};

/**
 * @namespace
 * @exports TargetNS as Core.Agent.Admin.SysConfig
 * @description
 *      This namespace contains the special module functions for the SysConfig module.
 */
Core.Agent.Admin.SysConfig = (function (TargetNS) {
    /**
     * @function
     * @return nothing
     *      This function initializes the special module functions
     */
    TargetNS.Init = function () {
        $('#AdminSysConfig h3 input:checkbox').click(function () {
            $(this).parent('h3').parent('fieldset').toggleClass('Invalid');
        });
    };

    return TargetNS;
}(Core.Agent.Admin.SysConfig || {}));

Fix app specific JS for adminsysconfig.


var Bluebird = require('bluebird');

module.exports = issueRequest;

function issueRequest (request) {
    return Bluebird.resolve(request)
        .catch(function (err) {
            throw new Error('Error communicating with the webtask cluster: '
                + err.message);
        })
        .then(function (res) {
            if (res.error) throw createResponseError(res);

            // Api compatibility
            res.statusCode = res.status;

            return res;
        });
}

function createResponseError (res) {
    if (res.clientError) return new Error('Invalid request: '
        + res.body && res.body.message
            ? res.body.message
            : res.text);
    if (res.serverError) return new Error('Server error: '
        + res.body && res.body.message
            ? res.body.message
            : res.text);
}

var Bluebird = require('bluebird');

module.exports = issueRequest;

function issueRequest (request) {
    return Bluebird.resolve(request)
        .catch(normalizeResponseError)
        .then(function (res) {
            // Api compatibility
            res.statusCode = res.status;

            return res;
        });
}

function normalizeResponseError (err) {
    var error;
    var res = err.response;

    if (!res) {
        error = new Error(err.message);
    } else if (res.clientError) {
        error = new Error('Invalid request: '
            + res.body && res.body.message
                ? res.body.message
                : res.text);
    } else if (res.serverError) {
        error = new Error('Server error: '
            + res.body && res.body.message
                ? res.body.message
                : res.text);
    }

    Object.defineProperty(error, 'stack', { get: function () { return err.stack; }});

    error.statusCode = err.status || 500;

    return error;
}

Improve http request error reporting and metadata


angular.module('dplaceMapDirective', [])
    .directive('dplaceMap', function() {
        function link(scope, element, attrs) {
            element.append("

");
            scope.map = $('#mapdiv').vectorMap({map: 'world_mill_en'}).vectorMap('get','mapObject');
            scope.addMarkers = function() {
                scope.map.removeAllMarkers();
                if(!scope.societies) {
                    return;
                }
                scope.societies.forEach(function(societyResult) {
                    var society = societyResult.society;
                    // Add a marker for each point
                    var marker = {latLng: society.location.coordinates.reverse(), name: society.name}
                    scope.map.addMarker(society.id, marker);
                });
            };

            // Update markers when societies change
            scope.$watchCollection('societies', function(oldvalue, newvalue) {
                scope.addMarkers();
            });

            scope.$on('mapTabActivated', function(event, args) {
                scope.map.setSize();
            });
        }

        return {
            restrict: 'E',
            scope: {
                societies: '='
            },
            link: link
        };
    });

angular.module('dplaceMapDirective', [])
    .directive('dplaceMap', function() {
        function link(scope, element, attrs) {
            element.append("

");
            scope.map = $('#mapdiv').vectorMap({
                map: 'world_mill_en',
                backgroundColor: 'white',
                regionStyle: {
                  initial: {
                    fill: '#428bca',
                    "fill-opacity": 1,
                    stroke: '#357ebd',
                    "stroke-width": 0,
                    "stroke-opacity": 1
                  },
                  hover: {
                    "fill-opacity": 0.8
                  },
                  selected: {
                    fill: 'yellow'
                  },
                  selectedHover: {
                  }
                }
            }).vectorMap('get','mapObject');
            scope.addMarkers = function() {
                scope.map.removeAllMarkers();
                if(!scope.societies) {
                    return;
                }
                scope.societies.forEach(function(societyResult) {
                    var society = societyResult.society;
                    // Add a marker for each point
                    var marker = {latLng: society.location.coordinates.reverse(), name: society.name}
                    scope.map.addMarker(society.id, marker);
                });
            };

            // Update markers when societies change
            scope.$watchCollection('societies', function(oldvalue, newvalue) {
                scope.addMarkers();
            });

            scope.$on('mapTabActivated', function(event, args) {
                scope.map.setSize();
            });
        }

        return {
            restrict: 'E',
            scope: {
                societies: '='
            },
            link: link
        };
    });

Tweak map styles to match theme


const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');

module.exports = {
	entry: path.join(__dirname, 'main-settings.js'),
	output: {
		path: path.resolve(__dirname, '../js'),
		publicPath: '/js/',
		filename: 'settings.js'
	},
	module: {
		rules: [
			{
				test: /davclient/,
				use: 'exports-loader?dav'
			},
			{
				test: /ical/,
				use: 'exports-loader?ICAL'
			},
			{
				test: /\.css$/,
				use: ['vue-style-loader', 'css-loader']
			},
			{
				test: /\.scss$/,
				use: ['vue-style-loader', 'css-loader', 'sass-loader']
			},
			{
				test: /\.vue$/,
				loader: 'vue-loader'
			},
			{
				test: /\.js$/,
				loader: 'babel-loader',
				exclude: /node_modules/
			},
			{
				test: /\.(png|jpg|gif)$/,
				loader: 'file-loader',
				options: {
					name: '[name].[ext]?[hash]'
				}
			},
			{
				test: /\.(svg)$/i,
				use: [
					{
						loader: 'url-loader'
					}
				]
			}
		]
	},
	plugins: [new VueLoaderPlugin()],
	resolve: {
		alias: {
			vue$: 'vue/dist/vue.esm.js',
			'@core': path.resolve('components/core')
		},
		extensions: ['*', '.js', '.vue', '.json'],
		symlinks: false
	}
};

const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');

module.exports = {
	entry: path.join(__dirname, 'main-settings.js'),
	output: {
		path: path.resolve(__dirname, '../js'),
		publicPath: '/js/',
		filename: 'settings.js'
	},
	module: {
		rules: [
			{
				test: /\.css$/,
				use: ['vue-style-loader', 'css-loader']
			},
			{
				test: /\.scss$/,
				use: ['vue-style-loader', 'css-loader', 'sass-loader']
			},
			{
				test: /\.vue$/,
				loader: 'vue-loader'
			},
			{
				test: /\.js$/,
				loader: 'babel-loader',
				exclude: /node_modules/
			},
			{
				test: /\.(png|jpg|gif)$/,
				loader: 'file-loader',
				options: {
					name: '[name].[ext]?[hash]'
				}
			},
			{
				test: /\.(svg)$/i,
				use: [
					{
						loader: 'url-loader'
					}
				]
			}
		]
	},
	plugins: [new VueLoaderPlugin()],
	resolve: {
		extensions: ['*', '.js', '.vue']
	}
};

Remove leftovers from copied webpack config


exports.BattlePokedex = {
	chansey: {
		inherit: true,
		abilities: {0:"Natural Cure",1:"Serene Grace"},
		prevo: ''
	},
	mrmime: {
		inherit: true,
		abilities: {0:"Swarm",1:"Technician"},
		prevo: ''
	},
	snorlax: {
		inherit: true,
		abilities: {0:"Immunity",1:"Thick Fat"},
		prevo: ''
	}
};

exports.BattlePokedex = {
	chansey: {
		inherit: true,
		abilities: {0:"Natural Cure",1:"Serene Grace"},
		prevo: ''
	},
	mrmime: {
		inherit: true,
		abilities: {0:"Soundproof",1:"Filter"},
		prevo: ''
	},
	snorlax: {
		inherit: true,
		abilities: {0:"Immunity",1:"Thick Fat"},
		prevo: ''
	}
};

Fix Mr. Mime abilities in Gen 3 Accidentally put Scyther's instead in 1d003cbaec


var rem = require('../..');
var read = require('read');
var clarinet = require('clarinet');

// Create Twitter API, prompting for key/secret.
var tw = rem.load('twitter', 1.0).prompt();

// Authenticate user via the console.
rem.console(tw, function (err, user) {
  user.stream('statuses/sample').get(function (err, stream) {
    // Pass the stream to a JSON parser and only print the tweets.
    stream.pipe(clarinet.createStream()).on('key', function (key) {
      if (key == 'text') {
        this.once('value', function (tweet) {
          console.log(String(tweet));
        })
      }
    });
  });
});

var rem = require('rem');
var read = require('read');
var clarinet = require('clarinet');

// Create Twitter API, prompting for key/secret.
var tw = rem.load('twitter', 1.0).prompt();

// Authenticate user via the console.
rem.console(tw, function (err, user) {

  // Pass the statuses/sample stream to a JSON parser and print only the tweets.
  user.stream('statuses/sample').get(function (err, stream) {
    stream.pipe(clarinet.createStream()).on('key', function (key) {
      if (key == 'text') {
        this.once('value', function (tweet) {
          console.log(String(tweet));
        })
      }
    });
  });
});

Improve example for twitter stream


var fs = require('fs');
var config = require('../config');

var schemaText = fs.readFileSync(config.schemapath);
var schema = JSON.parse(schemaText.toString());

schema.host = 'localhost';
schema.port = '3000'
schema.version = undefined;

var Api = require('../lib/api').Api;

var api = new Api({
	schema: schema,
	format: 'json',
	logger: require('../lib/logger')
});

var expect = require('chai').expect;

describe('api', function () {

	it('should get a release by id', function (done) {
		var releases = new api.Releases();
		releases.getDetails({ releaseId: 1192901 }, function (err, data) {
			expect(data.release.title).to.equal('Wasting Light');
			done();
		});
	});

	it('should handle bad xml from the api', function (done) {
		var releases = new api.Releases();
		releases.getDetails({ releaseId: 'error' }, function (err, data) {
			//Currently dies because xml2js never calls back..
			//https://github.com/Leonidas-from-XIV/node-xml2js/issues/51
			expect(err).to.not.equal(undefined);
			done();
		});
	});
});

var fs = require('fs');
var config = require('../config');

var schemaText = fs.readFileSync(config.schemapath);
var schema = JSON.parse(schemaText.toString());

schema.host = 'localhost';
schema.port = '3000'
schema.version = undefined;

var Api = require('../lib/api').Api;

var api = new Api({
	schema: schema,
	format: 'json',
	logger: require('../lib/logger')
});

var expect = require('chai').expect;

describe('api', function () {

	it('should get a release by id', function (done) {
		var releases = new api.Releases();
		releases.getDetails({ releaseId: 1192901 }, function (err, data) {
			expect(data.release.title).to.equal('Wasting Light');
			done();
		});
	});

	it('should handle bad xml from the api', function (done) {
		var releases = new api.Releases();
		releases.getDetails({ releaseId: 'error' }, function (err, data) {
			//Currently dies because xml2js never calls back..
			//https://github.com/Leonidas-from-XIV/node-xml2js/issues/51
			expect(err).to.not.equal(undefined);
			done();
		});
	});

	it('should handle missing resources from the api', function (done) {
		var releases = new api.Releases();
		releases.getDetails({ releaseId: 'missing' }, function (err, data) {
			expect(err).to.not.equal(undefined);
			expect(err.code).to.equal('2001');
			done();
		});
	});
});

Add test for api error response


import * as d3 from 'd3';
import { t } from '../util/locale';
import { modeBrowse } from '../modes/index';

export function uiSourceSwitch(context) {
    var keys;

    function click() {
        d3.event.preventDefault();

        if (context.history().hasChanges() &&
            !window.confirm(t('source_switch.lose_changes'))) return;

        var live = d3.select(this)
            .classed('live');

        context.connection()
            .switch(live ? keys[1] : keys[0]);

        context.enter(modeBrowse(context));
        context.flush();

        d3.select(this)
            .text(live ? t('source_switch.dev') : t('source_switch.live'))
            .classed('live', !live);
    }

    var sourceSwitch = function(selection) {
        selection
            .append('a')
            .attr('href', '#')
            .text(t('source_switch.live'))
            .classed('live', true)
            .attr('tabindex', -1)
            .on('click', click);
    };

    sourceSwitch.keys = function(_) {
        if (!arguments.length) return keys;
        keys = _;
        return sourceSwitch;
    };

    return sourceSwitch;
}

import * as d3 from 'd3';
import { t } from '../util/locale';
import { modeBrowse } from '../modes/index';

export function uiSourceSwitch(context) {
    var keys;

    function click() {
        d3.event.preventDefault();

        if (context.history().hasChanges() &&
            !window.confirm(t('source_switch.lose_changes'))) return;

        var live = d3.select(this)
            .classed('live');

        context.history().clearSaved();
        context.connection().switch(live ? keys[1] : keys[0]);
        context.enter(modeBrowse(context));
        context.flush();

        d3.select(this)
            .text(live ? t('source_switch.dev') : t('source_switch.live'))
            .classed('live', !live);
    }

    var sourceSwitch = function(selection) {
        selection
            .append('a')
            .attr('href', '#')
            .text(t('source_switch.live'))
            .classed('live', true)
            .attr('tabindex', -1)
            .on('click', click);
    };

    sourceSwitch.keys = function(_) {
        if (!arguments.length) return keys;
        keys = _;
        return sourceSwitch;
    };

    return sourceSwitch;
}

Clear history immediately when switching sources


'use strict';

var laralytics = {
  init: function(_api, _version) {

    // Object track with : screen size, mouse position, browser, all click event
    var payLoad = {};

    // Options of laralytics when DOM is loaded
    var options = {
      API : _api || '/laralytics',
      Version : _version || null,
    };

    payLoad.push({'Version':options.Version});
    console.log(payLoad);

    laralytics.sendPayload(payLoad, options);
  },

  sendPayload: function(_payLoad, _options) {

    var request = new XMLHttpRequest();
    request.open('POST', ''+ _options.API +'', true);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.setRequestHeader('X-XSRF-TOKEN', laralytics.getCookie('XSRF-TOKEN'));
    request.send(_payLoad);
  },

  getCookie: function(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)===' ') c = c.substring(1);
        if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
    }
    return "";
  },
};

laralytics.init();
//# sourceMappingURL=laralytics.js.map

'use strict';

var laralytics = {
  init: function(_api, _version) {

    // Object track with : screen size, mouse position, browser, all click event
    var payLoad = {};

    // Options of laralytics when DOM is loaded
    var options = {
      API : _api || '/laralytics',
      Version : _version || null,
    };

    payLoad.push({'Version':options.Version});
    console.log(payLoad);

    laralytics.sendPayload(payLoad, options);
  },

  sendPayload: function(_payLoad, _options) {

    var request = new XMLHttpRequest();
    request.open('POST', ''+ _options.API +'', true);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.setRequestHeader('X-XSRF-TOKEN', decodeURIComponent(laralytics.getCookie('XSRF-TOKEN')));
    request.send(_payLoad);
  },

  getCookie: function(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)===' ') c = c.substring(1);
        if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
    }
    return "";
  },
};

laralytics.init();
//# sourceMappingURL=laralytics.js.map

Add decodeUriComponent on XSRF-TOKEN cookie before setting the X-XSRF-TOKEN header


// Polyfills
if(MouseEvent === undefined) {
    function MouseEvent(eventType, params) {
        params = params || { bubbles: false, cancelable: false };
        var mouseEvent = document.createEvent('MouseEvent');
        mouseEvent.initMouseEvent(eventType, params.bubbles, params.cancelable, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);

        return mouseEvent;
    }
}

function simulateMouseDown(element) {
    var ev = new MouseEvent("mousedown", {
        bubbles: true,
        cancelable: true,
        view: window
    });
    element.dispatchEvent(ev);
}

var prefetch;

describe('Prefetch', function() {
    describe('#hooks()', function() {

        var el = document.createElement("a");
        el.id = "myLink";
        el.href = "localhost";
        el.innerHTML = "Click me";
        document.body.appendChild(el);

        prefetch = new Prefetch();

        it("shouldn't create any link when no hyperlink have been clicked", function(done) {
            var links = document.querySelectorAll("link[rel=prefetch]");

            expect(links.length).to.equal(0);
            done();
        });

        it('should create a link tag when the hyperlink is been clicked', function(done) {
            var myLink = document.getElementById("myLink");

            simulateMouseDown(myLink);

            setTimeout(function() {
                var links = document.querySelectorAll("link[rel=prefetch]");

                expect(links.length).to.equal(1);
                done();

            }, 5);
        });
    });
});

// Polyfill MouseEvent for PhantomJS
if(MouseEvent === undefined) {
    function MouseEvent(eventType, params) {
        params = params || { bubbles: false, cancelable: false };
        var mouseEvent = document.createEvent('MouseEvent');
        mouseEvent.initMouseEvent(eventType, params.bubbles, params.cancelable, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);

        return mouseEvent;
    }
}

function simulateMouseDown(element) {
    var ev = new MouseEvent("mousedown", {
        bubbles: true,
        cancelable: true,
        view: window
    });
    element.dispatchEvent(ev);
}

describe('Prefetch', function() {
    describe('#hooks()', function() {

        var el = document.createElement("a");
        el.id = "myLink";
        el.href = "http://localhost";
        el.innerHTML = "Click me";
        document.body.appendChild(el);

        var prefetch = new Prefetch();

        it("shouldn't create any link when no hyperlink have been clicked", function(done) {
            var links = document.querySelectorAll("link[rel=prefetch]");

            expect(links.length).to.equal(0);
            done();
        });

        it('should create a link tag when the hyperlink is been clicked', function(done) {
            var myLink = document.getElementById("myLink");

            simulateMouseDown(myLink);

            setTimeout(function() {
                var links = document.querySelectorAll("link[rel=prefetch]");

                expect(links.length).to.equal(1);
                expect(links[0].href).to.equal(el.href);
                done();

            }, 5);
        });
    });
});

Add a assertion to test the href of the link


'use strict'

import React from 'react'
import SvgIcon from '../../components/svg-icon'

const FormSearch = () => (
  <div className='search'>
    <input
      className='form-control'
      type='search'
      placeholder='Busque por palavras chaves' />

    <button className='search-btn' type='submit' role='button'>
      <SvgIcon id='search' label='Search' />
    </button>
  </div>
)

export default FormSearch

'use strict'

import React, { PropTypes } from 'react'
import SvgIcon from '../../components/svg-icon'

const FormSearch = ({ searchField, handleChangeText }) => (
  <div className='search'>
    <input
      className='form-control'
      type='search'
      placeholder='Busque por palavras chaves'
      value={searchField}
      onChange={handleChangeText} />

    <button className='search-btn' type='submit' role='button'>
      <SvgIcon id='search' label='Search' />
    </button>
  </div>
)

FormSearch.propTypes = {
  searchField: PropTypes.string.isRequired,
  handleChangeText: PropTypes.func.isRequired
}

export default FormSearch

Add function to search by text


const Joi = require('@hapi/joi')

module.exports = Joi.object().pattern(/^/, Joi.array().items(Joi.string()))

const Joi = require('@hapi/joi')

module.exports = Joi.object().pattern(/^/, Joi.alternatives(
  Joi.string().valid(''),
  Joi.array().items(Joi.string())
))

Allow empty string for filter schema for deletions


// @flow

import React, { Component } from 'react';
import type { ElementProps } from 'react';

import { Provider, Subscribe } from 'unstated';
import AccordionContainer from '../AccordionContainer/AccordionContainer';
import Accordion from './accordion';

type AccordionWrapperProps = ElementProps<'div'> & {
    accordion: boolean,
    onChange: Function,
};

const defaultProps: AccordionWrapperProps = {
    accordion: true,
    onChange: () => {},
    className: 'accordion',
    children: null,
};

class AccordionWrapper extends Component<AccordionWrapperProps> {
    accordionStore = new AccordionContainer();

    static defaultProps = defaultProps;

    componentDidMount() {
        this.accordionStore.setAccordion(this.props.accordion);
        this.accordionStore.setOnChange(this.props.onChange);
    }

    componentDidUpdate() {
        this.accordionStore.setAccordion(this.props.accordion);
        this.accordionStore.setOnChange(this.props.onChange);
    }

    render() {
        const { accordion, onChange, ...rest } = this.props;
        return (
            <Provider inject={[this.accordionStore]}>
                <Subscribe to={[AccordionContainer]}>
                    {accordionStore => (
                        <Accordion
                            accordion={accordionStore.state.accordion}
                            {...rest}
                        />
                    )}
                </Subscribe>
            </Provider>
        );
    }
}

export default AccordionWrapper;

// @flow

import React, { Component } from 'react';
import type { ElementProps } from 'react';

import { Provider, Subscribe } from 'unstated';
import AccordionContainer from '../AccordionContainer/AccordionContainer';
import Accordion from './accordion';

type AccordionWrapperProps = ElementProps<'div'> & {
    accordion: boolean,
    onChange: Function,
};

const defaultProps: AccordionWrapperProps = {
    accordion: true,
    onChange: () => {},
    className: 'accordion',
    children: null,
};

class AccordionWrapper extends Component<AccordionWrapperProps> {
    accordionStore = new AccordionContainer({
        accordion: this.props.accordion,
        onChange: this.props.onChange,
    });

    static defaultProps = defaultProps;

    componentDidMount() {
        this.accordionStore.setAccordion(this.props.accordion);
        this.accordionStore.setOnChange(this.props.onChange);
    }

    componentDidUpdate() {
        this.accordionStore.setAccordion(this.props.accordion);
        this.accordionStore.setOnChange(this.props.onChange);
    }

    render() {
        const { accordion, onChange, ...rest } = this.props;
        return (
            <Provider inject={[this.accordionStore]}>
                <Subscribe to={[AccordionContainer]}>
                    {accordionStore => (
                        <Accordion
                            accordion={accordionStore.state.accordion}
                            {...rest}
                        />
                    )}
                </Subscribe>
            </Provider>
        );
    }
}

export default AccordionWrapper;

Fix AccordionWrapper initialization by passing initial 'accordion' and 'onChange' props to the container constructor.


var get = Ember.get,
    set = Ember.set;

Ember.S3Uploader = Ember.Uploader.extend({
  /**
    Url used to request a signed upload url

    @property url
  */
  url: '/sign',

  upload: function(file) {
    var self = this;

    set(this, 'isUploading', true);

    return this.sign(file).then(function(json) {
      var url = "http://" + json.bucket + ".s3.amazonaws.com";
      var data = self.setupFormData(file, json);

      return self.ajax(url, data);
    }).then(function(respData) {
      self.didUpload(respData);
      return respData;
    });
  },

  sign: function(file) {
    var settings = {
      url: get(this, 'url'),
      type: 'GET',
      contentType: 'json',
      data: {
        name: file.name
      }
    };

    return this._ajax(settings);
  }
});

var get = Ember.get,
    set = Ember.set;

Ember.S3Uploader = Ember.Uploader.extend({
  /**
    Url used to request a signed upload url

    @property url
  */
  url: '/sign',

  upload: function(file) {
    var self = this;

    set(this, 'isUploading', true);

    return this.sign(file).then(function(json) {
      var url = "http://" + json.bucket + ".s3.amazonaws.com";
      var data = self.setupFormData(file, json);

      return self.ajax(url, data);
    }).then(function(respData) {
      self.didUpload(respData);
      return respData;
    });
  },

  sign: function(file) {
    var settings = {
      url: get(this, 'url'),
      type: 'GET',
      contentType: 'json',
      data: {
        name: file.name,
        type: file.type,
        size: file.size
      }
    };

    return this._ajax(settings);
  }
});

Add file type and size to S3 sign function data


import express from 'express';
import UserController from '../controllers/UserController';

const userRouter = express.Router();
userRouter.post('/api/user/signup', UserController.createUser());
userRouter.post('/api/user/signin', [
  UserController.validateRequest(),
  UserController.authenticateUser()
]);
userRouter.use('/api', [
  UserController.getClientAuthToken(),
  UserController.authorizeUser()
]);
userRouter.put('/api/user', UserController.updateUser());
userRouter.delete('/api/user', UserController.deleteUser());
userRouter.get('/api/user/groups', UserController.getUserGroups());

export default userRouter;

import express from 'express';
import UserController from '../controllers/UserController';

const userRouter = express.Router();
userRouter.post('/api/user/signup', UserController.createUser());
userRouter.post('/api/user/signin', [
  UserController.validateRequest(),
  UserController.authenticateUser()
]);
userRouter.use('/api', [
  UserController.getClientAuthToken(),
  UserController.authorizeUser()
]);
userRouter.get('/api/user/:id', UserController.getUser());
userRouter.put('/api/user', UserController.updateUser());
userRouter.delete('/api/user', UserController.deleteUser());
userRouter.get('/api/user/groups', UserController.getUserGroups());

export default userRouter;

Add getUser endpoint to fetch a user


import Ember from 'ember';
import { translationMacro as t } from "ember-i18n";

export default Ember.Controller.extend({

  i18n: Ember.inject.service(),
  delivery: Ember.computed.alias("deliveryController.model"),
  user: Ember.computed.alias('delivery.offer.createdBy'),
  selectedTerritory: null,
  selectedDistrict: null,

  initSelectedTerritories: Ember.on('init', function() {
    if(this.get("selectedDistrict") === null) {
      this.set("selectedTerritory", this.get("user.address.district.territory"));
      this.set("selectedDistrict", this.get("user.address.district"));
    }
  }),

  territoriesPrompt: t("all"),
  destrictPrompt: t("delivery.select_district"),

  territories: Ember.computed(function(){
    return this.store.peekAll('territory');
  }),

  districtsByTerritory: Ember.computed('selectedTerritory', function(){
    if(this.selectedTerritory && this.selectedTerritory.id) {
      return this.selectedTerritory.get('districts').sortBy('name');
    } else {
      return this.store.peekAll('district').sortBy('name');
    }
  })
});

import Ember from "ember";
import { translationMacro as t } from "ember-i18n";

export default Ember.Controller.extend({
  i18n: Ember.inject.service(),
  delivery: Ember.computed.alias("deliveryController.model"),
  user: Ember.computed.alias("delivery.offer.createdBy"),
  selectedTerritory: null,
  selectedDistrict: null,

  initSelectedTerritories: Ember.on("init", function() {
    if (this.get("selectedDistrict") === null) {
      this.set(
        "selectedTerritory",
        this.get("user.address.district.territory")
      );
      this.set("selectedDistrict", this.get("user.address.district"));
    }
  }),

  territoriesPrompt: t("all"),
  destrictPrompt: t("delivery.select_district"),

  territories: Ember.computed(function() {
    return this.store.peekAll("territory");
  }),

  districtsByTerritory: Ember.computed("selectedTerritory", function() {
    if (this.selectedTerritory && this.selectedTerritory.id) {
      return this.selectedTerritory.get("districts").sortBy("name");
    } else {
      return this.store.peekAll("district").sortBy("name");
    }
  }),

  actions: {
    onTerritoryChange(value) {
      this.set("selectedTerritory", value);
      this.set(
        "selectedDistrict",
        this.selectedTerritory.get("districts").sortBy("name").firstObject
      );
    }
  }
});

Initialize district on territory change


import { map } from 'substance'

export default class DynamicCollection {
  constructor (api, type) {
    this._api = api
    this._type = type
  }

  getItems () {
    const api = this._api
    const doc = api._getDocument()
    const index = doc.getIndex('type')
    const nodesById = index.get(this._type)
    const items = map(nodesById, node => {
      return api._getModelForNode(node)
    })
    return items
  }

  addItem () {
    console.error('TODO: should we implement DynamicCollection.addItem()?')
  }
}

import { map } from 'substance'

export default class DynamicCollection {
  constructor (api, type) {
    this._api = api
    this._type = type
  }

  getItems () {
    const api = this._api
    const doc = api._getDocument()
    const index = doc.getIndex('type')
    const nodesById = index.get(this._type)
    const items = map(nodesById, node => {
      return api._getModelForNode(node)
    })
    return items
  }

  addItem (item) {
    const api = this._api
    const model = api._addModel(item)
    return model
  }

  removeItem (item) {
    const api = this._api
    const model = api._removeModel(item)
    return model
  }
}

Add and remove items from dynamic collection.


var sideex_wait = {
    next_command_wait: false,
    done: true
};

var sideex_testCase = {
    count: 0
};

var sideex_testSuite = {
    count: 0
};

function clean_panel() {
    document.getElementById("records-grid").innerHTML = "";
    document.getElementById("command-command").value = "";
    document.getElementById("command-target").value = "";
    document.getElementById("command-target-list").innerHTML = "";
    document.getElementById("command-value").value = "";
}

var sideex_wait = {
    next_command_wait: false,
    done: true
};

var sideex_testCase = {
    count: 0
};

var sideex_testSuite = {
    count: 0
};

function clean_panel() {
    document.getElementById("records-grid").innerHTML = "";
    document.getElementById("command-command").value = "";
    document.getElementById("command-target").value = "";
    document.getElementById("command-target-list").innerHTML = "";
    document.getElementById("target-dropdown").innerHTML = "";
    document.getElementById("command-value").value = "";
}

Clean target dropdown in clean_panel()


const { next } = require('hooter/effects')
const normalizeCommands = require('./normalizeCommands')

module.exports = function executePlugin(lifecycle) {
  function executeOne(command, context) {
    let { outputName, options } = command
    let handlerOptions = {}

    if (!outputName) {
      throw new Error('Commands must have an output name in the end of "execute.one"')
    }

    if (options) {
      options.forEach((option) => {
        if (!option.outputName) {
          throw new Error('All options must have an output name in the end of "execute.one"')
        }

        handlerOptions[option.outputName] = option.value
      })
    }

    return lifecycle.toot(
      'execute.handle', outputName, handlerOptions, context
    )
  }

  function* executeBatch(commands) {
    let context

    for (let i = 0; i < commands.length; i++) {
      context = yield lifecycle.tootWith(
        'execute.one', executeOne, commands[i], context
      )
    }

    return context
  }

  let config

  lifecycle.hook('start', function* (_config) {
    config = yield next(_config)
    return config
  })

  lifecycle.hookEnd('execute', (commands) => {
    if (!Array.isArray(commands) || commands.length === 0) {
      throw new Error('The first argument of execute must be an array of commands')
    }

    commands = normalizeCommands(commands, config)
    return lifecycle.tootWith('execute.batch', executeBatch, commands)
  })
}

const { next, toot, tootWith } = require('hooter/effects')
const normalizeCommands = require('./normalizeCommands')

module.exports = function executePlugin(lifecycle) {
  function* executeOne(command, context) {
    let { outputName, options } = command
    let handlerOptions = {}

    if (!outputName) {
      throw new Error('Commands must have an output name in the end of "execute.one"')
    }

    if (options) {
      options.forEach((option) => {
        if (!option.outputName) {
          throw new Error('All options must have an output name in the end of "execute.one"')
        }

        handlerOptions[option.outputName] = option.value
      })
    }

    return yield toot('execute.handle', outputName, handlerOptions, context)
  }

  function* executeBatch(commands) {
    let context

    for (let i = 0; i < commands.length; i++) {
      context = yield tootWith('execute.one', executeOne, commands[i], context)
    }

    return context
  }

  let config

  lifecycle.hook('start', function* (_config) {
    config = yield next(_config)
    return config
  })

  lifecycle.hookEnd('execute', function* (commands) {
    if (!Array.isArray(commands) || commands.length === 0) {
      throw new Error('The first argument of execute must be an array of commands')
    }

    commands = normalizeCommands(commands, config)
    return yield tootWith('execute.batch', executeBatch, commands)
  })
}

Use the toot effects in "execute"


module.exports = function authorize (authApi) {
    return function authorizeMiddleware (req, res, next) {
        req.profiler.done('req2params.setup');

        authApi.authorize(req, res, (err, authorized) => {
            req.profiler.done('authorize');
            if (err) {
                return next(err);
            }

            if(!authorized) {
                err = new Error("Sorry, you are unauthorized (permission denied)");
                err.http_status = 403;
                return next(err);
            }

            return next();
        });
    };
};

module.exports = function authorize (authApi) {
    return function authorizeMiddleware (req, res, next) {
        authApi.authorize(req, res, (err, authorized) => {
            req.profiler.done('authorize');
            if (err) {
                return next(err);
            }

            if(!authorized) {
                err = new Error("Sorry, you are unauthorized (permission denied)");
                err.http_status = 403;
                return next(err);
            }

            return next();
        });
    };
};

Remove bad use of profiling step


/* eslint global-require: 0 */
module.exports = {
  Provider: {
    Gmail: 'gmail',
    IMAP: 'imap',
  },
  Imap: require('imap'),
  Errors: require('./src/errors'),
  IMAPErrors: require('./src/imap-errors'),
  SMTPErrors: require('./src/smtp-errors'),
  loadModels: require('./src/load-models'),
  AuthHelpers: require('./src/auth-helpers'),
  PromiseUtils: require('./src/promise-utils'),
  DatabaseTypes: require('./src/database-types'),
  IMAPConnection: require('./src/imap-connection').default,
  IMAPConnectionPool: require('./src/imap-connection-pool'),
  SendmailClient: require('./src/sendmail-client'),
  DeltaStreamBuilder: require('./src/delta-stream-builder'),
  HookTransactionLog: require('./src/hook-transaction-log'),
  HookIncrementVersionOnSave: require('./src/hook-increment-version-on-save'),
  BackoffScheduler: require('./src/backoff-schedulers').BackoffScheduler,
  ExponentialBackoffScheduler: require('./src/backoff-schedulers').ExponentialBackoffScheduler,
  CommonProviderSettings: require('imap-provider-settings').CommonProviderSettings,
  MetricsReporter: require('./src/metrics-reporter').default,
  MessageUtils: require('./src/message-utils'),
  ModelUtils: require('./src/model-utils'),
  executeJasmine: require('./spec/jasmine/execute').default,
  StringUtils: require('./src/string-utils'),
  TLSUtils: require('./src/tls-utils'),
  DBUtils: require('./src/db-utils'),
}

/* eslint global-require: 0 */
module.exports = {
  Provider: {
    Gmail: 'gmail',
    IMAP: 'imap',
  },
  Imap: require('imap'),
  Errors: require('./src/errors'),
  IMAPErrors: require('./src/imap-errors'),
  SMTPErrors: require('./src/smtp-errors'),
  loadModels: require('./src/load-models'),
  AuthHelpers: require('./src/auth-helpers'),
  PromiseUtils: require('./src/promise-utils'),
  DatabaseTypes: require('./src/database-types'),
  IMAPConnection: require('./src/imap-connection').default,
  IMAPConnectionPool: require('./src/imap-connection-pool'),
  SendmailClient: require('./src/sendmail-client'),
  DeltaStreamBuilder: require('./src/delta-stream-builder'),
  HookTransactionLog: require('./src/hook-transaction-log'),
  HookIncrementVersionOnSave: require('./src/hook-increment-version-on-save'),
  BackoffScheduler: require('./src/backoff-schedulers').BackoffScheduler,
  ExponentialBackoffScheduler: require('./src/backoff-schedulers').ExponentialBackoffScheduler,
  CommonProviderSettings: require('imap-provider-settings').CommonProviderSettings,
  MetricsReporter: require('./src/metrics-reporter').default,
  MessageUtils: require('./src/message-utils'),
  ModelUtils: require('./src/model-utils').default,
  executeJasmine: require('./spec/jasmine/execute').default,
  StringUtils: require('./src/string-utils'),
  TLSUtils: require('./src/tls-utils'),
  DBUtils: require('./src/db-utils'),
}

Add missing .default to require


window.GenericActivityView = Backbone.View.extend({
  tagName: "div",
  className: "activity-block",

  initialize: function(options) {
    this.useTemplate("activities", "_generic_activity");
  },

  render: function() {
    $(this.el).html( Mustache.to_html(this.tmpl, this.model.toJSON()) );
    $('#facts_for_channel').append($(this.el));
    return this;
  },

  clickHandler: function(e) {
    document.location.href = this.model.url();
  }
});

ActivityAddedEvidenceView = GenericActivityView.extend({});
ActivityAddedSubchannelView = GenericActivityView.extend({});
ActivityWasFollowedView = GenericActivityView.extend({});

window.ActivityView = function(opts) {
  if (opts.model.get("action") === "added_evidence") {
    return new ActivityAddedEvidenceView(opts);
  } else if (opts.model.get("action") === "added_subchannel") {
    return new ActivityAddedSubchannelView(opts);
  } else if (opts.model.get("action") === "was_followed") {
    return new ActivityWasFollowedView(opts);
  } else {
    return new GenericActivityView(opts);
  }
};

window.GenericActivityView = Backbone.View.extend({
  tagName: "div",
  className: "activity-block",

  initialize: function(options) {
    this.useTemplate("activities", "_generic_activity");
  },

  render: function() {
    $(this.el).html( Mustache.to_html(this.tmpl, this.model.toJSON()) );
    $('#facts_for_channel').append($(this.el));
    return this;
  },

  clickHandler: function(e) {
    document.location.href = this.model.url();
  }
});

ActivityAddedEvidenceView = GenericActivityView.extend({});
ActivityAddedSubchannelView = GenericActivityView.extend({
  initialize: function(options) {
    this.useTemplate("activities", "_added_subchannel_activity");
  }
});
ActivityWasFollowedView = GenericActivityView.extend({});

window.ActivityView = function(opts) {
  if (opts.model.get("action") === "added_evidence") {
    return new ActivityAddedEvidenceView(opts);
  } else if (opts.model.get("action") === "added_subchannel") {
    return new ActivityAddedSubchannelView(opts);
  } else if (opts.model.get("action") === "was_followed") {
    return new ActivityWasFollowedView(opts);
  } else {
    return new GenericActivityView(opts);
  }
};

Use the added_subchannel_activity template for this activity


var config = require('../src/config/config')
var client = require('mongodb').MongoClient
var fs = require('fs-extra')

client.connect(config.database.host+'vegodev', function(err, db){
  if (err) throw err

  //Drop vegodev database if it exists
  db.dropDatabase(function(err, result) {

    var adminDb = db.admin()
    //Get a fresh copy
    adminDb.command({
      copydb: 1,
      fromdb: 'vegosvar',
      todb: 'vegodev'

    }, function(err, result) {
      if (err) throw err
      if(result.ok) {
        console.log('Database copied successfully')
      }

      //Copy uploads folder
      var source = '/var/www/beta.vegosvar.se/uploads'
      var destination = '/var/www/dev.vegosvar.se/src/uploads'

      //assume this directory has a lot of files and folders
      fs.emptyDir(destination, function (err) {
        if (err) throw err
        fs.copy(source, destination, function (err) {
          if (err) throw err

          console.log('Uploads folder copied successfully')

          db.close()
        })
      })
    })
  })
})

var config = require('../src/config/config')
var client = require('mongodb').MongoClient
var fs = require('fs-extra')

client.connect(config.database.host+'vegodev', function(err, db){
  if (err) throw err

  //Drop vegodev database if it exists
  db.dropDatabase(function(err, result) {

    var adminDb = db.admin()
    //Get a fresh copy
    adminDb.command({
      copydb: 1,
      fromdb: 'vegosvar',
      todb: 'vegodev'

    }, function(err, result) {
      if (err) throw err
      if(result.ok) {
        console.log('Database copied successfully')
      }

      //Copy uploads folder
      var source = '/var/www/beta.vegosvar.se/src/uploads'
      var destination = '/var/www/dev.vegosvar.se/src/uploads'

      //assume this directory has a lot of files and folders
      fs.emptyDir(destination, function (err) {
        if (err) throw err
        fs.copy(source, destination, function (err) {
          if (err) throw err

          console.log('Uploads folder copied successfully')

          db.close()
        })
      })
    })
  })
})

Fix paths now that master is running with new structure


class PdfkiwiError extends Error {
    constructor(message, code, status) {
        super(message);

        const hasValidCode = code !== null && code !== undefined;
        Object.defineProperty(this, 'message', {
            configurable : true,
            enumerable   : false,
            value        : hasValidCode ? `${code}: ${message}` : message,
            writable     : true
        });

        Object.defineProperty(this, 'name', {
            configurable : true,
            enumerable   : false,
            value        : this.constructor.name,
            writable     : true
        });

        Object.defineProperty(this, 'code', {
            configurable : true,
            enumerable   : false,
            value        : code,
            writable     : true
        });

        Object.defineProperty(this, 'status', {
            configurable : true,
            enumerable   : false,
            value        : status,
            writable     : true
        });
    }
}

module.exports = PdfkiwiError;

class PdfkiwiError extends Error {
    constructor(message, code, status) {
        super(message);

        const hasValidCode = code !== null && code !== undefined;
        Object.defineProperty(this, 'message', {
            configurable : true,
            enumerable   : false,
            value        : hasValidCode ? `${code}: ${message}` : message,
            writable     : true
        });

        Object.defineProperty(this, 'name', {
            configurable : true,
            enumerable   : false,
            value        : this.constructor.name,
            writable     : true
        });

        Object.defineProperty(this, 'code', {
            configurable : true,
            enumerable   : false,
            value        : code,
            writable     : true
        });

        Object.defineProperty(this, 'status', {
            configurable : true,
            enumerable   : false,
            value        : status,
            writable     : true
        });

        // eslint-disable-next-line no-prototype-builtins
        if (Error.hasOwnProperty('captureStackTrace')) {
            Error.captureStackTrace(this, this.constructor);
            return;
        }

        Object.defineProperty(this, 'stack', {
            configurable : true,
            enumerable   : false,
            value        : (new Error(message)).stack,
            writable     : true
        });
    }
}

module.exports = PdfkiwiError;

Improve the stack returned from PdfkiwiError


angular.module('igTruncate', []).filter('truncate', function (){
  return function (text, length, end){
    if (text !== undefined){
      if (isNaN(length)){
        length = 10;
      }

      if (end === undefined){
        end = "...";
      }

      if (text.length <= length || text.length - end.length <= length){
        return text;
      }else{
        return String(text).substring(0, length - end.length) + end;
      }
    }
  };
});

angular.module('igTruncate', []).filter('truncate', function (){
  return function (text, length, end){
    if (text !== undefined){
      if (isNaN(length)){
        length = 10;
      }

      end = end || "...";

      if (text.length <= length || text.length - end.length <= length){
        return text;
      }else{
        return String(text).substring(0, length - end.length) + end;
      }
    }
  };
});

Simplify default for end variable.


'use strict';

import os from 'os';

export const HEADER = `// @flow
/* This file is automatically generated by css-modules-flow-types */`;

export default function printFlowDefinition(tokensArray, indent = '  ') {
  const props = tokensArray
    .sort()
    .map(key => `${indent}+'${key}': string;`)
    .join(os.EOL);

  return `${HEADER}
declare module.exports: {|
${props}
|};
`;
}

'use strict';

import os from 'os';

export const HEADER = `// @flow strict
/* This file is automatically generated by css-modules-flow-types */`;

export default function printFlowDefinition(tokensArray, indent = '  ') {
  const props = tokensArray
    .sort()
    .map(key => `${indent}+'${key}': string;`)
    .join(os.EOL);

  return `${HEADER}
declare module.exports: {|
${props}
|};
`;
}

Change header to 'flow strict'


// Static file helpers

import { canUseDOM } from 'react/lib/ExecutionEnvironment';

const os = require('os');

const PRODUCTION_STATIC_ROOT = 'http://static.tonikarttunen.com/static/';
const DEVELOPMENT_STATIC_ROOT = 'http://127.0.0.1:8888/';

const getStaticRootUrl = () => {
  if (canUseDOM) {
    const HOST_BASE_URL =
    window.location.origin || /* Modern browsers */
    window.location.protocol + '//' + window.location.hostname +
    (window.location.port ? ':' + window.location.port : ''); /* IE */

    return (HOST_BASE_URL.includes('tonikarttunen.com') ?
      PRODUCTION_STATIC_ROOT :
      DEVELOPMENT_STATIC_ROOT);
  } else {
    return (os.hostname().includes('tonikarttunen.com') ?
      PRODUCTION_STATIC_ROOT :
      DEVELOPMENT_STATIC_ROOT);
  }
};

export default {
  PRODUCTION_STATIC_ROOT: PRODUCTION_STATIC_ROOT,

  DEVELOPMENT_STATIC_ROOT: DEVELOPMENT_STATIC_ROOT,

  staticPath: (path) => {
    return getStaticRootUrl() + path;
  }
};

// Static file helpers

import { canUseDOM } from 'react/lib/ExecutionEnvironment';

const PRODUCTION_STATIC_ROOT = 'http://static.tonikarttunen.com/static/';
const DEVELOPMENT_STATIC_ROOT = 'http://127.0.0.1:8888/';

const getStaticRootUrl = () => {
  if (canUseDOM) {
    const HOST_BASE_URL =
    window.location.origin || /* Modern browsers */
    window.location.protocol + '//' + window.location.hostname +
    (window.location.port ? ':' + window.location.port : ''); /* IE */

    return (HOST_BASE_URL.includes('tonikarttunen.com') ?
      PRODUCTION_STATIC_ROOT :
      DEVELOPMENT_STATIC_ROOT);
  } else {
    const DEVELOPMENT = process.env.NODE_ENV !== 'production';
    return DEVELOPMENT ? DEVELOPMENT_STATIC_ROOT : PRODUCTION_STATIC_ROOT;
  }
};

export default {
  PRODUCTION_STATIC_ROOT: PRODUCTION_STATIC_ROOT,

  DEVELOPMENT_STATIC_ROOT: DEVELOPMENT_STATIC_ROOT,

  staticPath: (path) => {
    return getStaticRootUrl() + path;
  }
};

Fix static path in production


module.exports = (function() {
  var config = require('config');
  var mongoose = require('mongoose');

  var db = mongoose.connection;
  var schemas = {};

  var eventSchema = new mongoose.Schema({
    'category': String,
    'coordinates': {
      'latitude': Number,
      'longitude': Number
    },
    'name': String,
    'original_id': String,
    'url': String
  });

  var locationSchema = new mongoose.Schema({
    'category': String,
    'location': {
      'latitude': Number,
      'longitude': Number
    }
  });

  schemas.Event = mongoose.model('Event', eventSchema);
  schemas.Location = mongoose.model('Location', locationSchema);

  mongoose.connect(config.get('mongo').url);

  return {
    db: db,
    schemas: schemas
  };
}());

module.exports = (function() {
  var config = require('config');
  var mongoose = require('mongoose');

  var db = mongoose.connection;
  var schemas = {};

  var eventSchema = new mongoose.Schema({
    'category': String,
    'coordinates': {
      'latitude': Number,
      'longitude': Number
    },
    'name': String,
    'original_id': String,
    'url': String
  });

  var locationSchema = new mongoose.Schema({
    'category': String,
    'coordinates': {
      'latitude': Number,
      'longitude': Number
    }
  });

  schemas.Event = mongoose.model('Event', eventSchema);
  schemas.Location = mongoose.model('Location', locationSchema);

  mongoose.connect(config.get('mongo').url);

  return {
    db: db,
    schemas: schemas
  };
}());

Fix location coordinate field naming


// app/models/course.js
// load the things we need
let mongoose = require('mongoose');
let User = require('./user');

// define the schema for our user model
let courseSchema = mongoose.Schema({
	courseName: String,
	courseKey: String,
	teacher: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
	valid: {type: Boolean, default: true},
	timestamp: {type: Date, default: Date.now}
});

courseSchema.pre('save', function (next) {
	this.timestamp = new Date();
	next();
});

courseSchema.statics.taughtBy = function taughtBy(uid) {
	let Course = this;
	return Course.find({teacher: uid, valid: true}).sort('courseName');
};

courseSchema.statics.verifyCourseTaughtBy = function verifyCourseTaughtBy(cid, uid) {
	return this.find({_id: cid, teacher: uid, valid: true})
		.countDocuments()
		.then(function(count) {
			if (count <= 0) throw new Error('Teacher does not teach class!');
		});
};

// Generate a random 6-7 character key
courseSchema.statics.generateCourseKey = function generateCourseKey() {
	return (Math.floor(Math.random() * 1000000000) + parseInt(Date.now() / 1000)).toString(36).toUpperCase().substring(0, 6);
};

// create the model for users and expose it to our app
module.exports = {
	model: mongoose.model('Course', courseSchema)
};

// app/models/course.js
// load the things we need
const mongoose = require('mongoose');
const randomstring = require("randomstring");

// define the schema for our user model
const courseSchema = mongoose.Schema({
	courseName: String,
	courseKey: String,
	teacher: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
	valid: {type: Boolean, default: true},
	timestamp: {type: Date, default: Date.now}
});

courseSchema.pre('save', function (next) {
	this.timestamp = new Date();
	next();
});

courseSchema.statics.taughtBy = function taughtBy(uid) {
	let Course = this;
	return Course.find({teacher: uid, valid: true}).sort('courseName');
};

courseSchema.statics.verifyCourseTaughtBy = function verifyCourseTaughtBy(cid, uid) {
	return this.find({_id: cid, teacher: uid, valid: true})
		.countDocuments()
		.then(function(count) {
			if (count <= 0) throw new Error('Teacher does not teach class!');
		});
};

// Generate a random 6 character key
courseSchema.statics.generateCourseKey = () => randomstring.generate(6);

// create the model for users and expose it to our app
module.exports = {
	model: mongoose.model('Course', courseSchema)
};

Convert generateCourseKey to use randomstring module


var models = require('../models');

exports.addtime = function(req, res) {
	// get a random palette from the top ones
	console.log("Javascript linked!");
	var activityToUpdate = req.query.activity;
	var conditions = {"activity": activityToUpdate};
	var newTime = req.query.time;
	var update = {$inc:{"hours": newTime}};
	var options = {multi: false};
	models.Activity.update(conditions, update, options, afterUpdating);
	/*models.Activity
		.find({"activity": req.query.activity})
		.update({"hours": hours + req.query.time})
		.exec(afterUpdating);*/
	//not sure what was going on with result before...?
	function afterUpdating(err){
		if (err) res.send(500);
		res.send();
	}

}

var models = require('../models');

exports.addtime = function(req, res) {
	// get a random palette from the top ones
	var result = { "message": "" , "activity": "" , "hours": 0, "goal": 0} ;

	console.log("Javascript linked!");
	var activityToUpdate = req.query.activity;
	var conditions = {"activity": activityToUpdate};
	var newTime = req.query.time;
	var update = {$inc:{"hours": newTime}};
	var options = {multi: false};
	models.Activity.update(conditions, update, options, afterUpdating);
	/*models.Activity
		.find({"activity": req.query.activity})
		.update({"hours": hours + req.query.time})
		.exec(afterUpdating);*/
	//not sure what was going on with result before...?
	function afterUpdating(err){
		if (err) res.send(500);

	}
	result['message'] = "Time added!"
	result['activity'] = activityToUpdate;
	models.Activity.find({"activity": activityToUpdate}).exec(afterQuery);
	function afterQuery(err, activity) {
		if (err) res.send(500);
		var newHours = activity[0].hours;
		var goal = activity[0].goal;
		console.log(newHours + " " + goal);
		result['hours'] = newHours;
		result['goal'] = goal;
		res.json(result);
	}

}

Add time now works and refreshed the page content!


const {
  UtilsParsingError,
  UtilsRuntimeError,
} = require('./UtilsErrors');
const {
  RequestRuntimeError,
} = require('../../Request/RequestErrors');

function currencyConvertParse(json) {
  try {
    json = json['util:CurrencyConversion'].map(curr => ({
      from: curr.From,
      to: curr.To,
      rate: parseFloat(curr.BankSellingRate),
    }));
  } catch (e) {
    throw new UtilsParsingError(json);
  }

  return json;
}

function dataTypeParse(json) {
  try {
    json = json['util:ReferenceDataItem'];
  } catch (e) {
    throw new UtilsParsingError(json);
  }

  return json;
}

const errorHandler = function (rsp) {
  let errorInfo;
  let code;
  try {
    errorInfo = rsp.detail[`common_${this.uapi_version}:ErrorInfo`];
    code = errorInfo[`common_${this.uapi_version}:Code`];
  } catch (err) {
    throw new RequestRuntimeError.UnhandledError(null, new UtilsRuntimeError(rsp));
  }
  switch (code) {
    default:
      throw new RequestRuntimeError.UnhandledError(null, new UtilsRuntimeError(rsp));
  }
};

module.exports = {
  UTILS_ERROR: errorHandler,
  CURRENCY_CONVERSION: currencyConvertParse,
  REFERENCE_DATATYPE: dataTypeParse,
};

const {
  UtilsParsingError,
  UtilsRuntimeError,
} = require('./UtilsErrors');
const {
  RequestRuntimeError,
} = require('../../Request/RequestErrors');

function currencyConvertParse(json) {
  try {
    json = json['util:CurrencyConversion'].map(curr => ({
      from: curr.From,
      to: curr.To,
      rate: parseFloat(curr.BankSellingRate),
    }));
  } catch (e) {
    throw new UtilsParsingError(json);
  }

  return json;
}

function dataTypeParse(json) {
  return json['util:ReferenceDataItem'];
}

const errorHandler = function (rsp) {
  let errorInfo;
  let code;
  try {
    errorInfo = rsp.detail[`common_${this.uapi_version}:ErrorInfo`];
    code = errorInfo[`common_${this.uapi_version}:Code`];
  } catch (err) {
    throw new RequestRuntimeError.UnhandledError(null, new UtilsRuntimeError(rsp));
  }
  switch (code) {
    default:
      throw new RequestRuntimeError.UnhandledError(null, new UtilsRuntimeError(rsp));
  }
};

module.exports = {
  UTILS_ERROR: errorHandler,
  CURRENCY_CONVERSION: currencyConvertParse,
  REFERENCE_DATATYPE: dataTypeParse,
};

Revert "Added a validation into the parser"


(function() {

    describe('awesome-app.search module', function() {
        var $controller,
            $scope,
            SearchService,
            $rootScope,
            controller,
            element;

        beforeEach(function() {
            module('awesome-app.search');

            inject(function(_$controller_, _SearchService_, _$rootScope_, _$compile_, _$templateCache_) {
                $controller = _$controller_;
                SearchService = _SearchService_;
                $rootScope = _$rootScope_;
            });

            $scope = $rootScope.$new();
            $scope.$on = function() {};
            controller = $controller('SearchCtrl', {$scope: $scope});
        });

        describe('search controller tests', function(){
           it('should call getTypeaheadData', function() {
               spyOn(SearchService, 'getTypeaheadData')
                   .and.returnValue({then: function() {}});

               $scope.getTypeaheadData();

               expect(SearchService.getTypeaheadData).toHaveBeenCalled();
           });

            it('should emit event with teamMembers', function() {
                spyOn($scope, '$emit');
                $scope.teamMembers = [];

                $scope.refreshTeamList();

                expect($scope.$emit).toHaveBeenCalledWith('saveTeamMembers', $scope.teamMembers);
            });

            it('should remove teamMember', function() {
                $scope.teamMembers = [
                    {
                        name: 'Ross Gellar'
                    },
                    {
                        name: 'Chandler Bing'
                    }
                ];

                $scope.removeTeamMember(0);

                expect($scope.teamMembers).toEqual([{name: 'Chandler Bing'}]);
            });
        });
    });
})();

(function() {

    describe('awesome-app.search module', function() {
        var $controller,
            $scope,
            SearchService,
            $rootScope,
            controller;

        beforeEach(function() {
            module('awesome-app.search');

            inject(function(_$controller_, _SearchService_, _$rootScope_) {
                $controller = _$controller_;
                SearchService = _SearchService_;
                $rootScope = _$rootScope_;
            });

            $scope = $rootScope.$new();
            $scope.$on = function() {};
            controller = $controller('SearchCtrl', {$scope: $scope});
        });

        describe('search controller tests', function(){
           it('should call getTypeaheadData', function() {
               spyOn(SearchService, 'getTypeaheadData')
                   .and.returnValue({then: function() {}});

               $scope.getTypeaheadData();

               expect(SearchService.getTypeaheadData).toHaveBeenCalled();
           });

            it('should emit event with teamMembers', function() {
                spyOn($scope, '$emit');
                $scope.teamMembers = [];

                $scope.refreshTeamList();

                expect($scope.$emit).toHaveBeenCalledWith('saveTeamMembers', $scope.teamMembers);
            });

            it('should remove teamMember', function() {
                $scope.teamMembers = [
                    {
                        name: 'Ross Gellar'
                    },
                    {
                        name: 'Chandler Bing'
                    }
                ];

                $scope.removeTeamMember(0);

                expect($scope.teamMembers).toEqual([{name: 'Chandler Bing'}]);
            });
        });
    });
})();

Remove unnecessary commented out lines


/**

 Copyright 2015 Covistra Technologies Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
"use strict";

var P = require('bluebird'),
    Calibrate = require('calibrate'),
    _ = require('lodash');

module.exports = function(server) {
    var SystemStatus = server.plugins['system'].SystemStatus;

    function handler(req, reply) {
        server.log(['plugin', 'users', 'debug'], "Handling system status");
        SystemStatus.reportSystemStatus().catch(Calibrate.error).then(reply);
    }

    return {
        method: 'GET',
        path: '/status',
        handler: handler,
        config: {
            tags: ['api']
        }
    };
};

/**

 Copyright 2015 Covistra Technologies Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
"use strict";

var P = require('bluebird'),
    Calibrate = require('calibrate'),
    _ = require('lodash');

module.exports = function(server) {
    var SystemStatus = server.plugins['covistra-system'].SystemStatus;

    function handler(req, reply) {
        server.log(['plugin', 'users', 'debug'], "Handling system status");
        SystemStatus.reportSystemStatus().catch(Calibrate.error).then(reply);
    }

    return {
        method: 'GET',
        path: '/status',
        handler: handler,
        config: {
            tags: ['api']
        }
    };
};

Adjust plugin references to new covistra-system name


/**
 * @requires javelin-install
 * @provides javelin-typeahead-normalizer
 * @javelin
 */

/**
 * @group control
 */
JX.install('TypeaheadNormalizer', {
  statics : {
    normalize : function(str) {
      return ('' + str)
        .toLowerCase()
        .replace(/[^a-z0-9 ]/g, '')
        .replace(/ +/g, ' ')
        .replace(/^\s*|\s*$/g, '');
    }
  }
});

/**
 * @requires javelin-install
 * @provides javelin-typeahead-normalizer
 * @javelin
 */

/**
 * @group control
 */
JX.install('TypeaheadNormalizer', {
  statics : {
    /**
     * Normalizes a string by lowercasing it and stripping out extra spaces
     * and punctuation.
     *
     * @param string
     * @return string Normalized string.
     */
    normalize : function(str) {
      return ('' + str)
        .toLocaleLowerCase()
        .replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g, '')
        .replace(/ +/g, ' ')
        .replace(/^\s*|\s*$/g, '');
    }
  }
});

Use Punctuation Blacklist for Typeahead Normalizer


import { connection, UserModel, GroupModel } from './models';

/**
 * The User class
 * @author Babatunde Adeyemi <tundewrites@gmail.com>
 * @class
 */
class PostIt {

  /**
   * Initializes the database connection
   * Initializes the database models
   * @constructor
   */
  constructor() {
    this.UserModel = UserModel;
    this.GroupModel = GroupModel;
  }

  /**
   * Registers new user's info to database
   * @param {string} firstName - User's first name
   * @param {string} lastName - User's last name
   * @param {string} email - User's email
   * @param {string} phone - User's phone
   * @param {string} password - User's password
   * @returns {Promise} - returns a Bluebird JS Promise
   */
  registerUser(firstName, lastName, email, phone, password) {
    return connection.sync().then(() =>
      this.UserModel.create({
        firstName,
        lastName,
        email,
        phone,
        password
      })
    );
  }
}

export default PostIt;

import { connection, UserModel, GroupModel } from './models';

/**
 * The User class
 * @author Babatunde Adeyemi <tundewrites@gmail.com>
 * @class
 */
class PostIt {

  /**
   * Initializes the database connection
   * Initializes the database models
   * @constructor
   */
  constructor() {
    this.UserModel = UserModel;
    this.GroupModel = GroupModel;
  }

  /**
   * Registers new user's info to database
   * @param {string} firstName - User's first name
   * @param {string} lastName - User's last name
   * @param {string} email - User's email
   * @param {string} phone - User's phone
   * @param {string} password - User's password
   * @returns {Promise} - returns a Bluebird JS Promise
   */
  registerUser(firstName, lastName, email, phone, password) {
    return connection.sync().then(() =>
      this.UserModel.create({
        firstName,
        lastName,
        email,
        phone,
        password
      })
    );
  }

  /**
   * Fetches user's details
   * @param {string} email - Signin email address
   * @param {*} password - Signin password
   * @returns {promise} - returns a Bluebird JS Promise
   */
  logUserIn(email) {
    return this.UserModel.findOne({
      where: {
        email
      }
    });
  }
}

export default PostIt;

Add login method to PostIt class


angular.module('fantastiq.components')
  .directive('menuButton', function () {
    return {
      scope: {},
      replace: true,
      controller: 'MenuButtonController',
      controllerAs: 'menu',
      template: '<md-button hide-gt-md ng-click="menu.toggle()" class="md-icon-button"><md-icon>menu</md-icon></md-button>'
    };
  })
  .controller('MenuButtonController', function ($mdSidenav) {
    this.toggle = function () {
      $mdSidenav('left').toggle();
    };
  });

angular.module('fantastiq.components')
  .directive('menuButton', function () {
    return {
      controller: 'MenuButtonController',
      controllerAs: 'menu',
      template: '<md-button hide-gt-md ng-click="menu.toggle()" class="md-icon-button"><md-icon>menu</md-icon></md-button>'
    };
  })
  .controller('MenuButtonController', function ($mdSidenav) {
    this.toggle = function () {
      $mdSidenav('left').toggle();
    };
  });

Clean up menu button a bit


var assert = require('assert');
var request = require('supertest');
var exec = require('child_process').exec;

var application = require(__dirname + '/server.js');

describe('server', function () {
    before(function () {
        application.listen();
    });

    after(function () {
        application.close();
    });

    describe('Array', function () {
        describe('#indexOf()', function () {
            it('should return -1 when the value is not present', function () {
                assert.equal(-1, [1, 2, 3].indexOf(5));
                assert.equal(-1, [1, 2, 3].indexOf(0));
            });
        });

        describe('#indexOf()', function () {
            it('should return -1 when the value is not present', function () {
                assert.equal(-1, [1, 2, 3].indexOf(5));
            });
        });

        describe('GET /', function() {
            it('respond with json', function(done) {
                request(application.app)
                    .get('/')
                    .set('Accept', 'application/json')
                    .expect('Content-Type', /html/)
                    .expect(200, done);
            });
        });

        describe('Run Abao', function() {
            it('respond with json', function(done) {
                this.timeout(15000);
                exec('node node_modules/.bin/abao ./raml/api.raml --server http://localhost:3000/api', function (err, stdout) {
                    console.log(stdout);
                    done();
                });
            });
        });
    });
});

var assert = require('assert');
var request = require('supertest');
var exec = require('child_process').exec;

var application = require(__dirname + '/server.js');

describe('server', function () {
    before(function () {
        application.listen();
    });

    after(function () {
        application.close();
    });

    describe('Array', function () {
        describe('#indexOf()', function () {
            it('should return -1 when the value is not present', function () {
                assert.equal(-1, [1, 2, 3].indexOf(5));
                assert.equal(-1, [1, 2, 3].indexOf(0));
            });
        });

        describe('#indexOf()', function () {
            it('should return -1 when the value is not present', function () {
                assert.equal(-1, [1, 2, 3].indexOf(5));
            });
        });

        describe('GET /', function() {
            it('respond with json', function(done) {
                request(application.app)
                    .get('/')
                    .set('Accept', 'application/json')
                    .expect('Content-Type', /html/)
                    .expect(200, done);
            });
        });

        describe('Run Abao', function() {
            it('respond with json', function(done) {
                this.timeout(15000);
                exec('node node_modules/.bin/abao ./raml/api.raml --server http://localhost:3000/api', function (err, stdout) {
                    console.log(err);
                    console.log(stdout);
                    done();
                });
            });
        });
    });
});

Add error output to testreport.


const gulp = require("gulp");
const lkpm = require('lkpm');
const path = require('path');

var taskExporter = new lkpm.TaskExporter({
    moduleBase: __dirname,
    javaSrcRoots: [path.join(__dirname, 'src', 'java')]
}, gulp);

taskExporter.exportTasks();

const gulp = require("gulp");
const lkpm = require('lkpm');
const path = require('path');

var taskExporter = new lkpm.TaskExporter({
    moduleBase: __dirname,
    javaSrcRoots: [path.join(__dirname, 'src', 'java'), path.join(__dirname, 'gen-src', 'java-jooq')]
}, gulp);

taskExporter.exportTasks();

Add generated source to build.


import ActionTypes from '../constants/ActionTypes';
import BaseStore from './BaseStore';

class LocaleStore extends BaseStore {

    constructor() {
        super();
        this.subscribe(() => this._registerToActions.bind(this));
        this._locale = 'en';
        let locale = localStorage.getItem('locale');
        if (locale) {
            this._locale = locale;
        } else if (navigator.languages.length > 0) {
            let locale = navigator.languages[0];
            if (locale.startsWith('es')) {
                this._locale = 'es';
            }
        } else if (navigator.language) {
            if (navigator.language.startsWith('es')) {
                this._locale = 'es';
            }
        }
    }

    _registerToActions(action) {

        switch (action.type) {

            case ActionTypes.CHANGE_LOCALE:
                this._locale = action.locale;
                localStorage.setItem('locale', this._locale);
                this.emitChange();
                break;

            default:
                break;
        }
    }

    get locale() {
        return this._locale;
    }

}

export default new LocaleStore();

import ActionTypes from '../constants/ActionTypes';
import BaseStore from './BaseStore';

class LocaleStore extends BaseStore {

    constructor() {
        super();
        this.subscribe(() => this._registerToActions.bind(this));
        this._locale = 'en';
        let locale = localStorage.getItem('locale');
        if (locale) {
            this._locale = locale;
        } else if (navigator.languages && navigator.languages.length > 0) {
            let locale = navigator.languages[0];
            if (locale.startsWith('es')) {
                this._locale = 'es';
            }
        } else if (navigator.language) {
            if (navigator.language.startsWith('es')) {
                this._locale = 'es';
            }
        }
    }

    _registerToActions(action) {

        switch (action.type) {

            case ActionTypes.CHANGE_LOCALE:
                this._locale = action.locale;
                localStorage.setItem('locale', this._locale);
                this.emitChange();
                break;

            default:
                break;
        }
    }

    get locale() {
        return this._locale;
    }

}

export default new LocaleStore();

Fix navigator.languages not supported in IE and Safari


import { shallow } from 'enzyme';
import React from 'react';
import assert from 'assert';
import tasks from './';

for (const key in tasks) {
  const TaskComponent = tasks[key];
  describe('Task ' + key, function() {
    let wrapper;

    it('should render with default props', function() {
      wrapper = shallow(<TaskComponent />);
    });

    it('should update on annotation change', function() {
      wrapper = shallow(<TaskComponent />);
      let annotation = TaskComponent.getDefaultAnnotation(tasks[key])
      wrapper.setProps({annotation});
    });
  });
}

import { shallow } from 'enzyme';
import React from 'react';
import assert from 'assert';
import tasks from './';
import { workflow } from '../../pages/dev-classifier/mock-data';

for (const key in workflow.tasks) {
  const task = workflow.tasks[key];
  const TaskComponent = tasks[task.type];
  describe('Task ' + task.type, function() {
    let wrapper;

    it('should render with default props', function() {
      wrapper = shallow(<TaskComponent />);
    });

    it('should update on annotation change', function() {
      wrapper = shallow(<TaskComponent />);
      let annotation = TaskComponent.getDefaultAnnotation(task, workflow, tasks);
      wrapper.setProps({annotation});
    });
  });
}

Use mock task data for generic task tests Update getDefaultAnnotation to use the method signature from the combo task.


//  Copyright (c) 2014 Readium Foundation and/or its licensees. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met:
//  1. Redistributions of source code must retain the above copyright notice, this
//  list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright notice,
//  this list of conditions and the following disclaimer in the documentation and/or
//  other materials provided with the distribution.
//  3. Neither the name of the organization nor the names of its contributors may be
//  used to endorse or promote products derived from this software without specific
//  prior written permission.

window.process = {};

window.process._RJS_baseUrl = function(n)
{
    return "..";
};

window.process._RJS_rootDir = function(n)
{
    if (n == 3) return ".";
    if (n == 2) return "readium-js";
    if (n == 1) return "readium-js/readium-shared-js";
    if (n == 0) return "readium-js/readium-shared-js/readium-cfi-js";
};

window.process._RJS_isBrowser = true;

require.config({

    paths:
    {
        "version":
            process._RJS_rootDir(3) + '/dev/version'
    }
});

//  Copyright (c) 2014 Readium Foundation and/or its licensees. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met:
//  1. Redistributions of source code must retain the above copyright notice, this
//  list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright notice,
//  this list of conditions and the following disclaimer in the documentation and/or
//  other materials provided with the distribution.
//  3. Neither the name of the organization nor the names of its contributors may be
//  used to endorse or promote products derived from this software without specific
//  prior written permission.

window.process = {};

window.process._RJS_baseUrl = function(n)
{
    return "..";
};

window.process._RJS_rootDir = function(n)
{
    if (n == 3) return ".";
    if (n == 2) return "readium-js";
    if (n == 1) return "readium-js/readium-shared-js";
    if (n == 0) return "readium-js/readium-shared-js/readium-cfi-js";
};

// Used in readium-build-tools/pluginsConfigMaker
// and readium_shared_js/globalsSetup.
// Flag as not optimized by r.js
window._RJS_isBrowser = true;

require.config({

    paths:
    {
        "version":
            process._RJS_rootDir(3) + '/dev/version'
    }
});

Introduce a new way to `require` plugins when using RequireJS (dev mode). This is to fix an issue with timing that existed previously.