<commit_before>/**
 * Routes
 *
 * Sails uses a number of different strategies to route requests.
 * Here they are top-to-bottom, in order of precedence.
 *
 * For more information on routes, check out:
 * http://sailsjs.org/#documentation
 */

/**
 * (1) Core middleware
 *
 * Middleware included with `app.use` is run first, before the router
 */

/**
 * (2) Static routes
 *
 * This object routes static URLs to handler functions--
 * In most cases, these functions are actions inside of your controllers.
 * For convenience, you can also connect routes directly to views or external URLs.
 *
 */

module.exports.routes = {

  // By default, your root route (aka home page) points to a view
  // located at `views/home/index.ejs`
  //
  // (This would also work if you had a file at: `/views/home.ejs`)
  '/main.js': {
    controller: 'main',
    action: 'requireJSmain'
  },

  '/configs.js': {
    controller: 'main',
    action: 'getConfigsJS'
  },

  '/api/v1/translations.js': {
    controller: 'main',
    action: 'getTranslations'
  },

  '/': {
    controller: 'main',
    action: 'index'
    //view: 'home/index'
  },

  'get /links' : {
    controller: 'links',
    action: 'index'
  },

  'get /templates/:id?.ejs' : {
       controller: 'template',
       action: 'ejs'
  },
  /*
  'get /templates/:id?.html' : {
       controller: 'template',
       action: 'find'
  },

  'get /templates/:action/:id?.html' : {
       controller: 'template',
       action: 'find'
  },
  */
  // Standard RESTful routing

  //
  // find contact relationship status
  'get /api/v1/user/:contactId/contact': {
    controller    : 'contact',
    action        : 'findOneUserContact'
  },
  // request
  'post /api/v1/user/:contactId/contact-request': {
    controller    : 'contact',
    action        : 'requestContact'
  },
  // accept
  'post /api/v1/user/:contactId/contact-accept': {
    controller    : 'contact',
    action        : 'acceptContact'
  },
  // ignore
  'post /api/v1/user/:contactId/contact-ignore': {
    controller    : 'contact',
    action        : 'ignoreContact'
  },
  // delete contact relation
  'delete /api/v1/user/:contactId/contact/': {
    controller    : 'contact',
    action        : 'deleteContact'
  },

  // -- FOLLOW
  // get
  // example: /api/v1/follow/post/1/2?flagType=follow
  'get /api/v1/follow/:model/:modelId?': {
    controller    : 'FollowController',
    action        : 'isFollowing'
  },

  // create
  // example: /api/v1/flag/post/1/2?flagType=follow
  'post /api/v1/follow/:model/:modelId': {
    controller    : 'FollowController',
    action        : 'follow'
  },

  // delete
  // example: /api/v1/flag/post/1/2?flagType=follow
  'delete /api/v1/follow/:model/:modelId': {
    controller    : 'FollowController',
    action        : 'unFollow'
  },

  // -- FLAG

  // get
  // example: /api/v1/flag/post/1/2?flagType=follow
  'get /api/v1/flag/:model/:modelId?/:userId?': {
    controller    : 'FlagController',
    action        : 'getModelFlags'
  },

  // create
  // example: /api/v1/flag/post/1/2?flagType=follow
  'post /api/v1/flag/:model/:modelId': {
    controller    : 'FlagController',
    action        : 'flag'
  },

  // delete
  // example: /api/v1/flag/post/1/2?flagType=follow
  'delete /api/v1/flag/:model/:modelId': {
    controller    : 'FlagController',
    action        : 'unFlag'
  },

  // -- USERS

  // User Auth

  'get /api/v1/auth/callback/:access_token': {
    controller    : 'auth',
    action        : 'oauth2Callback'
  },

  '/auth/logout': {
    controller    : 'auth',
    action        : 'logOut'
  },

  'get /api/v1/images': {
    controller    : 'images',
    action        : 'list'
  },

  'get /api/v1/images/:name?': {
    controller    : 'images',
    action        : 'findOne'
  },

  // Image style thumbnail | medium | large
  'get /api/v1/images/:style(original|mini|thumbnail|medium|large)/:name': {
    controller    : 'images',
    action        : 'findOne'
  },

  'get /api/v1/images/:id/data': {
    controller    : 'images',
    action        : 'findOneReturnData'
  },

  'get /api/v1/images-crop/:id': {
    controller    : 'images',
    action        : 'cropImage'
  },

  'post /api/v1/images': {
    controller    : 'images',
    action        : 'createRecord'
  },

  //  -- MESSENGER

  'get /messenger/start': {
      controller    : 'message',
      action        : 'start'
  },

  'get /api/v1/contact': {
      controller    : 'ContactController',
      action        : 'getAllAuthenticatedUserContacts'
  },

  // TODO use sails.js blueprint for set routes
  'get /api/v1/message/:id?': {
      controller    : 'message',
      action        : 'list'
  },

  'post /api/v1/message': {
      controller    : 'message',
      action        : 'createRecord'
  },

  // Return a list of messages between authenticated user and :uid user
  'get /messenger/messages/with-user/:uid?': {
      controller    : 'message',
      action        : 'messagesWithUser'
  },

  // Return messages without toIds and roomIds
  'get /messenger/messages/public': {
      controller    : 'message',
      action        : 'getPublicMessages'
  },

  // Send a message to show writing status
  'post /messenger/user/writing': {
      controller    : 'message',
      action        : 'emitIamWriting'
  },

  // -- ROOMS

  // 'get /rooms/:id?': {
  //     controller    : 'rooms',
  //     action        : 'index'
  // },
  // 'post /rooms': {
  //     controller    : 'rooms',
  //     action        : 'create'
  // },
  // 'put /rooms/:id?': {
  //     controller    : 'rooms',
  //     action        : 'update'
  // },
  // 'delete /rooms/:id?': {
  //     controller    : 'rooms',
  //     action        : 'destroy'
  // },

  // // get users in one room
  // 'get /rooms/users/': {
  //     controller    : 'rooms',
  //     action        : 'usersGet'
  // },

  // add user in room
  'post /rooms/users/:id?': {
      controller    : 'rooms',
      action        : 'userAdd'
  },

  // remove user from room
  'delete /rooms/users/:id?': {
      controller    : 'rooms',
      action        : 'userRemove'
  },

  // - NOTIFICATION

  // get current user notification count
  'get /api/v1/current-user/notification-count': {
    controller    : 'notification',
    action        : 'getUnreadNotificationCount'
  },

  'post /api/v1/notify/mark-all-as-read': {
    controller    : 'notification',
    action        : 'markAllNotificationAsRead'
  },

  'post /api/v1/notify/:model/:modelId/mark-all-as-read': {
    controller    : 'notification',
    action        : 'markAllModelNotificationAsRead'
  },

  // -- POSTS
  // @todo check ir this route set is need
  'get /api/v1/post': {
    controller    : 'post',
    action        : 'list'
  },

  'get /api/v1/post/:id': {
      controller    : 'post',
      action        : 'findOneRecord'
  },

  // @todo check ir this route set is need
  'post /api/v1/post': {
    controller    : 'post',
    action        : 'createRecord'
  },

  // 'put /api/v1/post': {
  //   controller    : 'post',
  //   action        : 'updateRecord'
  // },

  // -- FILES

  'get /files': {
      controller    : 'files',
      action        : 'index'
  },

  'post /files': {
      controller    : 'files',
      action        : 'create'
  },

  // -- COMMENT

  'post /api/v1/comment': {
    controller    : 'comment',
    action        : 'createOneRecord'
  },

  'get /api/v1/comment/:id': {
    controller    : 'comment',
    action        : 'findOneRecord'
  },

  // -- ADMIN
  'get /admin/widgets': {
    controller    : 'main',
    action        : 'index'
  },

  'get /admin/roles': {
      controller    : 'roles',
      action        : 'index'
  },

  'post /admin/roles': {
      controller    : 'roles',
      action        : 'create'
  },

  'put /admin/roles/:id': {
      controller    : 'roles',
      action        : 'update'
  },

  'delete /admin/roles/:id': {
      controller    : 'roles',
      action        : 'delete'
  },

  // group routes
  'get /api/v1/group': {
      controller    : 'group',
      action        : 'list'
  },

  // -- Pub Sub
  //
  // subscribe from socket.io updates
  'post /api/v1/subscribe': {
      controller    : 'PubsubController',
      action        : 'subscribe'
  },
  // unsubscribe from socket.io updates
  'post /api/v1/unsubscribe': {
      controller    : 'PubsubController',
      action        : 'unsubscribe'
  }
};

/**
 * (3) Action blueprints
 * These routes can be disabled by setting (in `config/controllers.js`):
 * `module.exports.controllers.blueprints.actions = false`
 *
 * All of your controllers ' actions are automatically bound to a route.  For example:
 *   + If you have a controller, `FooController`:
 *     + its action `bar` is accessible at `/foo/bar`
 *     + its action `index` is accessible at `/foo/index`, and also `/foo`
 */

/**
 * (4) Shortcut CRUD blueprints
 *
 * These routes can be disabled by setting (in config/controllers.js)
 *      `module.exports.controllers.blueprints.shortcuts = false`
 *
 * If you have a model, `Foo`, and a controller, `FooController`,
 * you can access CRUD operations for that model at:
 *    /foo/find/:id?  ->  search lampshades using specified criteria or with id=:id
 *
 *    /foo/create   ->  create a lampshade using specified values
 *
 *    /foo/update/:id ->  update the lampshade with id=:id
 *
 *    /foo/destroy/:id  ->  delete lampshade with id=:id
 *
 */

/**
 * (5) REST blueprints
 *
 * These routes can be disabled by setting (in config/controllers.js)
 *    `module.exports.controllers.blueprints.rest = false`
 *
 * If you have a model, `Foo`, and a controller, `FooController`,
 * you can access CRUD operations for that model at:
 *
 *    get /foo/:id? ->  search lampshades using specified criteria or with id=:id
 *
 *    post /foo   -> create a lampshade using specified values
 *
 *    put /foo/:id  ->  update the lampshade with id=:id
 *
 *    delete /foo/:id ->  delete lampshade with id=:id
 *
 */

/**
 * (6) Static assets
 *
 * Flat files in your `assets` directory- (these are sometimes referred to as 'public')
 * If you have an image file at `/assets/images/foo.jpg`, it will be made available
 * automatically via the route:  `/images/foo.jpg`
 *
 */

/**
 * (7) 404 (not found) handler
 *
 * Finally, if nothing else matched, the default 404 handler is triggered.
 * See `config/404.js` to adjust your app's 404 logic.
 */

<commit_msg>added comment routes<commit_after>/**
 * Routes
 *
 * Sails uses a number of different strategies to route requests.
 * Here they are top-to-bottom, in order of precedence.
 *
 * For more information on routes, check out:
 * http://sailsjs.org/#documentation
 */

/**
 * (1) Core middleware
 *
 * Middleware included with `app.use` is run first, before the router
 */

/**
 * (2) Static routes
 *
 * This object routes static URLs to handler functions--
 * In most cases, these functions are actions inside of your controllers.
 * For convenience, you can also connect routes directly to views or external URLs.
 *
 */

module.exports.routes = {

  // By default, your root route (aka home page) points to a view
  // located at `views/home/index.ejs`
  //
  // (This would also work if you had a file at: `/views/home.ejs`)
  '/main.js': {
    controller: 'main',
    action: 'requireJSmain'
  },

  '/configs.js': {
    controller: 'main',
    action: 'getConfigsJS'
  },

  '/api/v1/translations.js': {
    controller: 'main',
    action: 'getTranslations'
  },

  '/': {
    controller: 'main',
    action: 'index'
    //view: 'home/index'
  },

  'get /links' : {
    controller: 'links',
    action: 'index'
  },

  'get /templates/:id?.ejs' : {
       controller: 'template',
       action: 'ejs'
  },
  /*
  'get /templates/:id?.html' : {
       controller: 'template',
       action: 'find'
  },

  'get /templates/:action/:id?.html' : {
       controller: 'template',
       action: 'find'
  },
  */
  // Standard RESTful routing

  //
  // find contact relationship status
  'get /api/v1/user/:contactId/contact': {
    controller    : 'contact',
    action        : 'findOneUserContact'
  },
  // request
  'post /api/v1/user/:contactId/contact-request': {
    controller    : 'contact',
    action        : 'requestContact'
  },
  // accept
  'post /api/v1/user/:contactId/contact-accept': {
    controller    : 'contact',
    action        : 'acceptContact'
  },
  // ignore
  'post /api/v1/user/:contactId/contact-ignore': {
    controller    : 'contact',
    action        : 'ignoreContact'
  },
  // delete contact relation
  'delete /api/v1/user/:contactId/contact/': {
    controller    : 'contact',
    action        : 'deleteContact'
  },

  // -- FOLLOW
  // get
  // example: /api/v1/follow/post/1/2?flagType=follow
  'get /api/v1/follow/:model/:modelId?': {
    controller    : 'FollowController',
    action        : 'isFollowing'
  },

  // create
  // example: /api/v1/flag/post/1/2?flagType=follow
  'post /api/v1/follow/:model/:modelId': {
    controller    : 'FollowController',
    action        : 'follow'
  },

  // delete
  // example: /api/v1/flag/post/1/2?flagType=follow
  'delete /api/v1/follow/:model/:modelId': {
    controller    : 'FollowController',
    action        : 'unFollow'
  },

  // -- FLAG

  // get
  // example: /api/v1/flag/post/1/2?flagType=follow
  'get /api/v1/flag/:model/:modelId?/:userId?': {
    controller    : 'FlagController',
    action        : 'getModelFlags'
  },

  // create
  // example: /api/v1/flag/post/1/2?flagType=follow
  'post /api/v1/flag/:model/:modelId': {
    controller    : 'FlagController',
    action        : 'flag'
  },

  // delete
  // example: /api/v1/flag/post/1/2?flagType=follow
  'delete /api/v1/flag/:model/:modelId': {
    controller    : 'FlagController',
    action        : 'unFlag'
  },

  // -- USERS

  // User Auth

  'get /api/v1/auth/callback/:access_token': {
    controller    : 'auth',
    action        : 'oauth2Callback'
  },

  '/auth/logout': {
    controller    : 'auth',
    action        : 'logOut'
  },

  'get /api/v1/images': {
    controller    : 'images',
    action        : 'list'
  },

  'get /api/v1/images/:name?': {
    controller    : 'images',
    action        : 'findOne'
  },

  // Image style thumbnail | medium | large
  'get /api/v1/images/:style(original|mini|thumbnail|medium|large)/:name': {
    controller    : 'images',
    action        : 'findOne'
  },

  'get /api/v1/images/:id/data': {
    controller    : 'images',
    action        : 'findOneReturnData'
  },

  'get /api/v1/images-crop/:id': {
    controller    : 'images',
    action        : 'cropImage'
  },

  'post /api/v1/images': {
    controller    : 'images',
    action        : 'createRecord'
  },

  //  -- MESSENGER

  'get /messenger/start': {
      controller    : 'message',
      action        : 'start'
  },

  'get /api/v1/contact': {
      controller    : 'ContactController',
      action        : 'getAllAuthenticatedUserContacts'
  },

  // TODO use sails.js blueprint for set routes
  'get /api/v1/message/:id?': {
      controller    : 'message',
      action        : 'list'
  },

  'post /api/v1/message': {
      controller    : 'message',
      action        : 'createRecord'
  },

  // Return a list of messages between authenticated user and :uid user
  'get /messenger/messages/with-user/:uid?': {
      controller    : 'message',
      action        : 'messagesWithUser'
  },

  // Return messages without toIds and roomIds
  'get /messenger/messages/public': {
      controller    : 'message',
      action        : 'getPublicMessages'
  },

  // Send a message to show writing status
  'post /messenger/user/writing': {
      controller    : 'message',
      action        : 'emitIamWriting'
  },

  // -- ROOMS

  // 'get /rooms/:id?': {
  //     controller    : 'rooms',
  //     action        : 'index'
  // },
  // 'post /rooms': {
  //     controller    : 'rooms',
  //     action        : 'create'
  // },
  // 'put /rooms/:id?': {
  //     controller    : 'rooms',
  //     action        : 'update'
  // },
  // 'delete /rooms/:id?': {
  //     controller    : 'rooms',
  //     action        : 'destroy'
  // },

  // // get users in one room
  // 'get /rooms/users/': {
  //     controller    : 'rooms',
  //     action        : 'usersGet'
  // },

  // add user in room
  'post /rooms/users/:id?': {
      controller    : 'rooms',
      action        : 'userAdd'
  },

  // remove user from room
  'delete /rooms/users/:id?': {
      controller    : 'rooms',
      action        : 'userRemove'
  },

  // - NOTIFICATION

  // get current user notification count
  'get /api/v1/current-user/notification-count': {
    controller    : 'notification',
    action        : 'getUnreadNotificationCount'
  },

  'post /api/v1/notify/mark-all-as-read': {
    controller    : 'notification',
    action        : 'markAllNotificationAsRead'
  },

  'post /api/v1/notify/:model/:modelId/mark-all-as-read': {
    controller    : 'notification',
    action        : 'markAllModelNotificationAsRead'
  },

  // -- POSTS
  // @todo check ir this route set is need
  'get /api/v1/post': {
    controller    : 'post',
    action        : 'list'
  },

  'get /api/v1/post/:id': {
      controller    : 'post',
      action        : 'findOneRecord'
  },

  // @todo check ir this route set is need
  'post /api/v1/post': {
    controller    : 'post',
    action        : 'createRecord'
  },

  // 'put /api/v1/post': {
  //   controller    : 'post',
  //   action        : 'updateRecord'
  // },

  // -- FILES

  'get /files': {
      controller    : 'files',
      action        : 'index'
  },

  'post /files': {
      controller    : 'files',
      action        : 'create'
  },

  // -- COMMENT

  'post /api/v1/comment': {
    controller    : 'comment',
    action        : 'createOneRecord'
  },

  'get /api/v1/comment/:id': {
    controller    : 'comment',
    action        : 'findOneRecord'
  },

  'get /api/v1/comment': {
    controller    : 'comment',
    action        : 'find'
  },

  'delete /api/v1/comment/:id': {
    controller    : 'comment',
    action        : 'destroyOneRecord'
  },

  'put /api/v1/comment/:id': {
    controller    : 'comment',
    action        : 'updateOneRecord'
  },

  // -- ADMIN
  'get /admin/widgets': {
    controller    : 'main',
    action        : 'index'
  },

  'get /admin/roles': {
      controller    : 'roles',
      action        : 'index'
  },

  'post /admin/roles': {
      controller    : 'roles',
      action        : 'create'
  },

  'put /admin/roles/:id': {
      controller    : 'roles',
      action        : 'update'
  },

  'delete /admin/roles/:id': {
      controller    : 'roles',
      action        : 'delete'
  },

  // group routes
  'get /api/v1/group': {
      controller    : 'group',
      action        : 'list'
  },

  // -- Pub Sub
  //
  // subscribe from socket.io updates
  'post /api/v1/subscribe': {
      controller    : 'PubsubController',
      action        : 'subscribe'
  },
  // unsubscribe from socket.io updates
  'post /api/v1/unsubscribe': {
      controller    : 'PubsubController',
      action        : 'unsubscribe'
  }
};

/**
 * (3) Action blueprints
 * These routes can be disabled by setting (in `config/controllers.js`):
 * `module.exports.controllers.blueprints.actions = false`
 *
 * All of your controllers ' actions are automatically bound to a route.  For example:
 *   + If you have a controller, `FooController`:
 *     + its action `bar` is accessible at `/foo/bar`
 *     + its action `index` is accessible at `/foo/index`, and also `/foo`
 */

/**
 * (4) Shortcut CRUD blueprints
 *
 * These routes can be disabled by setting (in config/controllers.js)
 *      `module.exports.controllers.blueprints.shortcuts = false`
 *
 * If you have a model, `Foo`, and a controller, `FooController`,
 * you can access CRUD operations for that model at:
 *    /foo/find/:id?  ->  search lampshades using specified criteria or with id=:id
 *
 *    /foo/create   ->  create a lampshade using specified values
 *
 *    /foo/update/:id ->  update the lampshade with id=:id
 *
 *    /foo/destroy/:id  ->  delete lampshade with id=:id
 *
 */

/**
 * (5) REST blueprints
 *
 * These routes can be disabled by setting (in config/controllers.js)
 *    `module.exports.controllers.blueprints.rest = false`
 *
 * If you have a model, `Foo`, and a controller, `FooController`,
 * you can access CRUD operations for that model at:
 *
 *    get /foo/:id? ->  search lampshades using specified criteria or with id=:id
 *
 *    post /foo   -> create a lampshade using specified values
 *
 *    put /foo/:id  ->  update the lampshade with id=:id
 *
 *    delete /foo/:id ->  delete lampshade with id=:id
 *
 */

/**
 * (6) Static assets
 *
 * Flat files in your `assets` directory- (these are sometimes referred to as 'public')
 * If you have an image file at `/assets/images/foo.jpg`, it will be made available
 * automatically via the route:  `/images/foo.jpg`
 *
 */

/**
 * (7) 404 (not found) handler
 *
 * Finally, if nothing else matched, the default 404 handler is triggered.
 * See `config/404.js` to adjust your app's 404 logic.
 */

<|endoftext|>


<commit_before>/*
 * jQuery doTimeout: Like setTimeout, but better! - v1.0 - 3/3/2010
 * http://benalman.com/projects/jquery-dotimeout-plugin/
 *
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 */
(function($){var a={},c="doTimeout",d=Array.prototype.slice;$[c]=function(){return b.apply(window,[0].concat(d.call(arguments)))};$.fn[c]=function(){var f=d.call(arguments),e=b.apply(this,[c+f[0]].concat(f));return typeof f[0]==="number"||typeof f[1]==="number"?this:e};function b(l){var m=this,h,k={},g=l?$.fn:$,n=arguments,i=4,f=n[1],j=n[2],p=n[3];if(typeof f!=="string"){i--;f=l=0;j=n[1];p=n[2]}if(l){h=m.eq(0);h.data(l,k=h.data(l)||{})}else{if(f){k=a[f]||(a[f]={})}}k.id&&clearTimeout(k.id);delete k.id;function e(){if(l){h.removeData(l)}else{if(f){delete a[f]}}}function o(){k.id=setTimeout(function(){k.fn()},j)}if(p){k.fn=function(q){if(typeof p==="string"){p=g[p]}p.apply(m,d.call(n,i))===true&&!q?o():e()};o()}else{if(k.fn){j===undefined?e():k.fn(j===false);return true}else{e()}}}})(jQuery);

// Making sure that console.log does not throw errors on Firefox + IE etc.
if (typeof console == "undefined") var console = { log: function() {} };

var DiscoJuice = {};

/*
 * Country codes available here http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
 */
DiscoJuice.Constants = {
	"Countries": {
		'CZ': 'Czech',
		'DK': 'Denmark',
		'FI': 'Finland',
		'FR': 'France',
		'DE': 'Germany',
		'GR': 'Greece',
		'HR': 'Croatia',
		'IE': 'Ireland',
		'IT': 'Italy',
		'HU': 'Hungary',
		'LU': 'Luxembourg',
		'NL': 'Netherlands',
		'NO': 'Norway',
		'PL': 'Poland',
		'PT': 'Portugal',
		'SI': 'Slovenia',
		'ES': 'Spain',
		'SE': 'Sweden',
		'CH': 'Switzerland',
		'TR': 'Turkey',
		'US': 'USA',
		'GB': 'UK',
		'XX': 'Experimental'
	},
	"Flags": {
		'CZ': 'cz.png',
		'DK': 'dk.png',
		'FI': 'fi.png',
		'FR': 'fr.png',
		'DE': 'de.png',
		'GR': 'gr.png',
		'HR': 'hr.png',
		'IE': 'ie.png',
		'IT': 'it.png',
		'HU': 'hu.png',
		'LU': 'lu.png',
		'NL': 'nl.png',
		'NO': 'no.png',
		'PL': 'pl.png',
		'PT': 'pt.png',
		'SI': 'si.png',
		'ES': 'es.png',
		'SE': 'se.png',
		'CH': 'ch.png',
		'TR': 'tr.png',
		'GB': 'gb.png',
		'US': 'us.png',
	}
};

DiscoJuice.Utils = {
	"log": function(string) {
		console.log(string);
		// opera.postError(string);
	},
	"options": function() {
		var options;
		return {
			"get": function (key, def) {
	//			DiscoJuice.log(options);
	//			DiscoJuice.log('Getting [' + key + '] default [' + def + '] val [' + options[key] + ']');
				if (!options) return def;
				if (!options[key]) return def;
				return options[key];
			},
			"set": function(opts) {
				options = opts;
			}
		}
	}(),

	/* Functions for setting, reading and erasing cookies */
	"createCookie": function(value, type) {
		var type = type || 'EntityID';
		var name = '_DiscoJuice_' + type;
		var days = 1825;
		if (days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		}
		else var expires = "";
		document.cookie = name+"="+escape(value)+expires+"; path=/";
	},
	"readCookie": function(type) {
		var type = type || 'EntityID';
		var name = '_DiscoJuice_' + type;
		var days = 1825;
		var nameEQ = name + "=";
		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,c.length);
			if (c.indexOf(nameEQ) == 0) return unescape(c.substring(nameEQ.length,c.length));
		}
		return null;
	},
	"eraseCookie": function (type) {
		var type = type || 'EntityID';
		var name = '_DiscoJuice_' + type;
		DiscoJuice.createCookie(name,"",-1);
	},
	/* ------ ------ ------ ------ ------ */

	/*
	 * Performs a search 'term' against an entity.
	 * If no match, return false.
	 * If match return the keyword that matches.
	 */
	"searchMatch": function(item, term) {
		if (item.title.toLowerCase().search(term.toLowerCase()) !== -1) return true;
		var key, i, keyword;

		if (item.keywords) {
			for(key in item.keywords) {
				keyword = item.keywords[key];
				for(i = 0; i < keyword.length; i++) {
					if (keyword[i].toLowerCase().search(term.toLowerCase()) !== -1) return keyword[i];
				}
			}
		}
		return false;
	},

	// calculate distance between two locations
	"calculateDistance": function (lat1, lon1, lat2, lon2) {
		var R = 6371; // km
		var dLat = this.toRad(lat2-lat1);
		var dLon = this.toRad(lon2-lon1);
		var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
				Math.cos(this.toRad(lat1)) * Math.cos(this.toRad(lat2)) *
				Math.sin(dLon/2) * Math.sin(dLon/2);
		var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
		var d = R * c;
		return d;
	},

	"toRad": function (deg) {
		return deg * Math.PI/180;
	}

};

/*
	Plugin for JQuery.
	*/
(function($) {
	$.fn.DiscoJuice = function(options) {
		return this.each(function() {
			DiscoJuice.Utils.options.set(options);

			DiscoJuice.Control.ui = DiscoJuice.UI;
			DiscoJuice.UI.control = DiscoJuice.Control;

			DiscoJuice.UI.enable(this);

		});
	};
})(jQuery);

<commit_msg>Allow updating options array from console<commit_after>/*
 * jQuery doTimeout: Like setTimeout, but better! - v1.0 - 3/3/2010
 * http://benalman.com/projects/jquery-dotimeout-plugin/
 *
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 */
(function($){var a={},c="doTimeout",d=Array.prototype.slice;$[c]=function(){return b.apply(window,[0].concat(d.call(arguments)))};$.fn[c]=function(){var f=d.call(arguments),e=b.apply(this,[c+f[0]].concat(f));return typeof f[0]==="number"||typeof f[1]==="number"?this:e};function b(l){var m=this,h,k={},g=l?$.fn:$,n=arguments,i=4,f=n[1],j=n[2],p=n[3];if(typeof f!=="string"){i--;f=l=0;j=n[1];p=n[2]}if(l){h=m.eq(0);h.data(l,k=h.data(l)||{})}else{if(f){k=a[f]||(a[f]={})}}k.id&&clearTimeout(k.id);delete k.id;function e(){if(l){h.removeData(l)}else{if(f){delete a[f]}}}function o(){k.id=setTimeout(function(){k.fn()},j)}if(p){k.fn=function(q){if(typeof p==="string"){p=g[p]}p.apply(m,d.call(n,i))===true&&!q?o():e()};o()}else{if(k.fn){j===undefined?e():k.fn(j===false);return true}else{e()}}}})(jQuery);

// Making sure that console.log does not throw errors on Firefox + IE etc.
if (typeof console == "undefined") var console = { log: function() {} };

var DiscoJuice = {};

/*
 * Country codes available here http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
 */
DiscoJuice.Constants = {
	"Countries": {
		'CZ': 'Czech',
		'DK': 'Denmark',
		'FI': 'Finland',
		'FR': 'France',
		'DE': 'Germany',
		'GR': 'Greece',
		'HR': 'Croatia',
		'IE': 'Ireland',
		'IT': 'Italy',
		'HU': 'Hungary',
		'LU': 'Luxembourg',
		'NL': 'Netherlands',
		'NO': 'Norway',
		'PL': 'Poland',
		'PT': 'Portugal',
		'SI': 'Slovenia',
		'ES': 'Spain',
		'SE': 'Sweden',
		'CH': 'Switzerland',
		'TR': 'Turkey',
		'US': 'USA',
		'GB': 'UK',
		'XX': 'Experimental'
	},
	"Flags": {
		'CZ': 'cz.png',
		'DK': 'dk.png',
		'FI': 'fi.png',
		'FR': 'fr.png',
		'DE': 'de.png',
		'GR': 'gr.png',
		'HR': 'hr.png',
		'IE': 'ie.png',
		'IT': 'it.png',
		'HU': 'hu.png',
		'LU': 'lu.png',
		'NL': 'nl.png',
		'NO': 'no.png',
		'PL': 'pl.png',
		'PT': 'pt.png',
		'SI': 'si.png',
		'ES': 'es.png',
		'SE': 'se.png',
		'CH': 'ch.png',
		'TR': 'tr.png',
		'GB': 'gb.png',
		'US': 'us.png',
	}
};

DiscoJuice.Utils = {
	"log": function(string) {
		console.log(string);
		// opera.postError(string);
	},
	"options": function() {
		var options;
		return {
			"get": function (key, def) {
	//			DiscoJuice.log(options);
	//			DiscoJuice.log('Getting [' + key + '] default [' + def + '] val [' + options[key] + ']');
				if (!options) return def;
				if (!options[key]) return def;
				return options[key];
			},
			"set": function(opts) {
				options = opts;
			},
			"update": function(key, value) {
				options[key] = value;
			}
		}
	}(),

	/* Functions for setting, reading and erasing cookies */
	"createCookie": function(value, type) {
		var type = type || 'EntityID';
		var name = '_DiscoJuice_' + type;
		var days = 1825;
		if (days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		}
		else var expires = "";
		document.cookie = name+"="+escape(value)+expires+"; path=/";
	},
	"readCookie": function(type) {
		var type = type || 'EntityID';
		var name = '_DiscoJuice_' + type;
		var days = 1825;
		var nameEQ = name + "=";
		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,c.length);
			if (c.indexOf(nameEQ) == 0) return unescape(c.substring(nameEQ.length,c.length));
		}
		return null;
	},
	"eraseCookie": function (type) {
		var type = type || 'EntityID';
		var name = '_DiscoJuice_' + type;
		DiscoJuice.createCookie(name,"",-1);
	},
	/* ------ ------ ------ ------ ------ */

	/*
	 * Performs a search 'term' against an entity.
	 * If no match, return false.
	 * If match return the keyword that matches.
	 */
	"searchMatch": function(item, term) {
		if (item.title.toLowerCase().search(term.toLowerCase()) !== -1) return true;
		var key, i, keyword;

		if (item.keywords) {
			for(key in item.keywords) {
				keyword = item.keywords[key];
				for(i = 0; i < keyword.length; i++) {
					if (keyword[i].toLowerCase().search(term.toLowerCase()) !== -1) return keyword[i];
				}
			}
		}
		return false;
	},

	// calculate distance between two locations
	"calculateDistance": function (lat1, lon1, lat2, lon2) {
		var R = 6371; // km
		var dLat = this.toRad(lat2-lat1);
		var dLon = this.toRad(lon2-lon1);
		var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
				Math.cos(this.toRad(lat1)) * Math.cos(this.toRad(lat2)) *
				Math.sin(dLon/2) * Math.sin(dLon/2);
		var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
		var d = R * c;
		return d;
	},

	"toRad": function (deg) {
		return deg * Math.PI/180;
	}

};

/*
	Plugin for JQuery.
	*/
(function($) {
	$.fn.DiscoJuice = function(options) {
		return this.each(function() {
			DiscoJuice.Utils.options.set(options);

			DiscoJuice.Control.ui = DiscoJuice.UI;
			DiscoJuice.UI.control = DiscoJuice.Control;

			DiscoJuice.UI.enable(this);

		});
	};
})(jQuery);

<|endoftext|>


<commit_before>"use strict";

(function($) {

	// Save the cursor position.
	var ranges = [];
	var saveSelection = function() {
		var sel = window.getSelection();
		ranges = [];
		if (sel.getRangeAt && sel.rangeCount) {
			for (let i = 0; i < sel.rangeCount; i++) {
				ranges.push(sel.getRangeAt(i));
			}
		}
	};

	// Insert content at cursor position.
	var insertContent = function(instance, content) {
		if (content.match(/<(audio|video)\b[^>]+>(<\/p>)?/)) {
			content = content + '

';
		}
		if (ranges.length) {
			var range = ranges[0];
			range.collapse(false);
			ranges = [];
		} else {
			var range = document.createRange();
			range.selectNodeContents(instance.get(0));
			range.collapse(false);
		}
		var sel = window.getSelection();
		sel.removeAllRanges();
		sel.addRange(range);
		if (String(navigator.userAgent).match(/Trident\/7/)) {
			range.insertNode(range.createContextualFragment(content));
			range.collapse(false);
		} else {
			document.execCommand('insertHTML', false, content);
		}
	};

	// Simplify HTML content by removing unnecessary tags.
	var simplifyContent = function(str) {
		str = String(str);
		str = str.replace(//gs, '');
		str = str.replace(/<\/?(\?xml|meta|link|font|span|style|script|noscript|frame|noframes|(?:st1|o):[a-z0-9]+)\b[^>]*?>/ig, '');
		str = str.replace(/(id|class|style|on(?:[a-z0-9]+)|Mso(?:[a-z0-9]+))="[^"]*"/ig, '');
		str = str.replace(/(<\/?)div(\W)/g, '$1p$2');
		return str;
	};

	// Convert YouTube links.
	var convertYouTube = function(str) {
		var regexp = /https?:\/\/(www\.youtube(?:-nocookie)?\.com\/(?:watch\?v=|v\/|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]+)\S*/g;
		var embed = '

';
		return String(str).replace(regexp, embed);
	};

	// Page load event handler.
	$(function() {
		$('.rx_simpleeditor').each(function() {

			// Load editor info.
			var editor = $(this);
			var editor_sequence = editor.data('editor-sequence');
			var content_key = editor.data('editor-content-key-name');
			var primary_key = editor.data('editor-primary-key-name');
			var insert_form = editor.closest('form');
			var content_input = insert_form.find('input,textarea').filter('[name=' + content_key + ']');
			var editor_height = editor.data('editor-height');
			if (editor_height) {
				editor.css('height', editor_height + 'px');
			}

			// Set editor sequence and other info to the form.
			insert_form[0].setAttribute('editor_sequence', editor_sequence);
			editorRelKeys[editor_sequence] = {};
			editorRelKeys[editor_sequence].primary = insert_form.find("input[name='" + primary_key + "']");
			editorRelKeys[editor_sequence].content = content_input;
			editorRelKeys[editor_sequence].func = editorGetContent;

			// Force
 as paragraph separator.
			document.execCommand('defaultParagraphSeparator', false, 'p');

			// Capture some simple keyboard shortcuts.
			editor.on('keydown', function(event) {
				if (!event.ctrlKey) {
					return;
				}
				var char = String.fromCharCode(event.which).toLowerCase();
				if (char === 'b') {
					document.execCommand('bold');
					event.preventDefault();
				}
				if (char === 'i') {
					document.execCommand('italic');
					event.preventDefault();
				}
				if (char === 'u') {
					document.execCommand('underline');
					event.preventDefault();
				}
			});

			// Save cursor position on moseup & keyup.
			editor.on('mouseup keyup', function() {
				saveSelection();
			});

			// Clean up pasted content.
			editor.on('paste', function(event) {
				var clipboard_data = (event.clipboardData || window.clipboardData || event.originalEvent.clipboardData);
				if (typeof clipboard_data !== 'undefined') {
					var content = clipboard_data.getData('text/html');
					if (content === '') {
						content = clipboard_data.getData('text');
					}
				} else {
					return;
				}
				content = convertYouTube(simplifyContent(content));
				insertContent(editor, content);
				event.preventDefault();
			});

			// Load existing content.
			if (content_input.size()) {
				editor.html(content_input.val());
			}

			// Copy edited content to the actual input element.
			editor.on('input blur mouseup keyup', function() {
				var content = simplifyContent(editor.html());
				content_input.val(content);
			});
		});
	});

	// Simulate CKEditor for file upload integration.
	window._getCkeInstance = function(editor_sequence) {
		var instance = $('#simpleeditor_instance_' + editor_sequence);
		return {
			getData: function() {
				return String(instance.html());
			},
			setData: function(content) {
				instance.html(content);
			},
			insertHtml: function(content) {
				insertContent(instance, content);
			}
		};
	};

})(jQuery);
<commit_msg>Fix #1361 always add at least one
 tag<commit_after>"use strict";

(function($) {

	// Save the cursor position.
	var ranges = [];
	var saveSelection = function() {
		var sel = window.getSelection();
		ranges = [];
		if (sel.getRangeAt && sel.rangeCount) {
			for (let i = 0; i < sel.rangeCount; i++) {
				ranges.push(sel.getRangeAt(i));
			}
		}
	};

	// Insert content at cursor position.
	var insertContent = function(instance, content) {
		if (content.match(/<(audio|video)\b[^>]+>(<\/p>)?/)) {
			content = content + '

';
		}
		if (ranges.length) {
			var range = ranges[0];
			range.collapse(false);
			ranges = [];
		} else {
			var range = document.createRange();
			range.selectNodeContents(instance.get(0));
			range.collapse(false);
		}
		var sel = window.getSelection();
		sel.removeAllRanges();
		sel.addRange(range);
		if (String(navigator.userAgent).match(/Trident\/7/)) {
			range.insertNode(range.createContextualFragment(content));
			range.collapse(false);
		} else {
			document.execCommand('insertHTML', false, content);
		}
	};

	// Simplify HTML content by removing unnecessary tags.
	var simplifyContent = function(str) {
		str = String(str);
		str = str.replace(//gs, '');
		str = str.replace(/<\/?(\?xml|meta|link|font|span|style|script|noscript|frame|noframes|(?:st1|o):[a-z0-9]+)\b[^>]*?>/ig, '');
		str = str.replace(/(id|class|style|on(?:[a-z0-9]+)|Mso(?:[a-z0-9]+))="[^"]*"/ig, '');
		str = str.replace(/(<\/?)div(\W)/g, '$1p$2');
		if (!str.match(/<\/?p>/)) {
			str = '
' + str + '
';
		}
		return str;
	};

	// Convert YouTube links.
	var convertYouTube = function(str) {
		var regexp = /https?:\/\/(www\.youtube(?:-nocookie)?\.com\/(?:watch\?v=|v\/|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]+)\S*/g;
		var embed = '

';
		return String(str).replace(regexp, embed);
	};

	// Page load event handler.
	$(function() {
		$('.rx_simpleeditor').each(function() {

			// Load editor info.
			var editor = $(this);
			var editor_sequence = editor.data('editor-sequence');
			var content_key = editor.data('editor-content-key-name');
			var primary_key = editor.data('editor-primary-key-name');
			var insert_form = editor.closest('form');
			var content_input = insert_form.find('input,textarea').filter('[name=' + content_key + ']');
			var editor_height = editor.data('editor-height');
			if (editor_height) {
				editor.css('height', editor_height + 'px');
			}

			// Set editor sequence and other info to the form.
			insert_form[0].setAttribute('editor_sequence', editor_sequence);
			editorRelKeys[editor_sequence] = {};
			editorRelKeys[editor_sequence].primary = insert_form.find("input[name='" + primary_key + "']");
			editorRelKeys[editor_sequence].content = content_input;
			editorRelKeys[editor_sequence].func = editorGetContent;

			// Force
 as paragraph separator.
			document.execCommand('defaultParagraphSeparator', false, 'p');

			// Capture some simple keyboard shortcuts.
			editor.on('keydown', function(event) {
				if (!event.ctrlKey) {
					return;
				}
				var char = String.fromCharCode(event.which).toLowerCase();
				if (char === 'b') {
					document.execCommand('bold');
					event.preventDefault();
				}
				if (char === 'i') {
					document.execCommand('italic');
					event.preventDefault();
				}
				if (char === 'u') {
					document.execCommand('underline');
					event.preventDefault();
				}
			});

			// Save cursor position on moseup & keyup.
			editor.on('mouseup keyup', function() {
				saveSelection();
			});

			// Clean up pasted content.
			editor.on('paste', function(event) {
				var clipboard_data = (event.clipboardData || window.clipboardData || event.originalEvent.clipboardData);
				if (typeof clipboard_data !== 'undefined') {
					var content = clipboard_data.getData('text/html');
					if (content === '') {
						content = clipboard_data.getData('text');
					}
				} else {
					return;
				}
				content = convertYouTube(simplifyContent(content));
				insertContent(editor, content);
				event.preventDefault();
			});

			// Load existing content.
			if (content_input.size()) {
				editor.html(content_input.val());
			}

			// Copy edited content to the actual input element.
			editor.on('input blur mouseup keyup', function() {
				var content = simplifyContent(editor.html());
				content_input.val(content);
			});
		});
	});

	// Simulate CKEditor for file upload integration.
	window._getCkeInstance = function(editor_sequence) {
		var instance = $('#simpleeditor_instance_' + editor_sequence);
		return {
			getData: function() {
				return String(instance.html());
			},
			setData: function(content) {
				instance.html(content);
			},
			insertHtml: function(content) {
				insertContent(instance, content);
			}
		};
	};

})(jQuery);
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * 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';

const NetworkRecorder = require('../../lib/network-recorder');
const emulation = require('../../lib/emulation');
const Element = require('../../lib/element');

const log = require('../../lib/log.js');

class Driver {

  constructor() {
    this.PAUSE_AFTER_LOAD = 500;
    this._traceEvents = [];
    this._traceCategories = Driver.traceCategories;
    this._eventEmitter = null;
  }

  static get traceCategories() {
    return [
      '-*', // exclude default
      'toplevel',
      'blink.console',
      'blink.user_timing',
      'benchmark',
      'devtools.timeline',
      'disabled-by-default-blink.debug.layout',
      'disabled-by-default-devtools.timeline',
      'disabled-by-default-devtools.timeline.frame',
      'disabled-by-default-devtools.timeline.stack',
      // 'disabled-by-default-v8.cpu_profile',  // these would include JS stack samples, but
      // 'disabled-by-default-v8.cpu_profile.hires', // will take the trace from 5MB -> 100MB
      'disabled-by-default-devtools.screenshot'
    ];
  }

  enableRuntimeEvents() {
    return this.sendCommand('Runtime.enable');
  }

  enableSecurityEvents() {
    return this.sendCommand('Security.enable');
  }

  /**
   * A simple formatting utility for event logging.
   * @param {string} prefix
   * @param {!Object} data A JSON-serializable object of event data to log.
   * @param {string=} level Optional logging level. Defaults to 'log'.
   */
  formattedLog(prefix, data, level) {
    const columns = (!process || process.browser) ? Infinity : process.stdout.columns;
    const maxLength = columns - data.method.length - prefix.length - 18;
    // IO.read blacklisted here to avoid logging megabytes of trace data
    const snippet = (data.params && data.method !== 'IO.read') ?
        JSON.stringify(data.params).substr(0, maxLength) : '';
    log[level ? level : 'log'](prefix, data.method, snippet);
  }

  /**
   * @return {!Promise<null>}
   */
  connect() {
    return Promise.reject(new Error('Not implemented'));
  }

  disconnect() {
    return Promise.reject(new Error('Not implemented'));
  }

  /**
   * Bind listeners for protocol events
   * @param {!string} eventName
   * @param {function(...)} cb
   */
  on(eventName, cb) {
    if (this._eventEmitter === null) {
      throw new Error('connect() must be called before attempting to listen to events.');
    }

    // log event listeners being bound
    this.formattedLog('listen for event =>', {method: eventName}, 'verbose');
    this._eventEmitter.on(eventName, cb);
  }

  /**
   * Bind a one-time listener for protocol events. Listener is removed once it
   * has been called.
   * @param {!string} eventName
   * @param {function(...)} cb
   */
  once(eventName, cb) {
    if (this._eventEmitter === null) {
      throw new Error('connect() must be called before attempting to listen to events.');
    }
    // log event listeners being bound
    this.formattedLog('listen once for event =>', {method: eventName}, 'verbose');
    this._eventEmitter.once(eventName, cb);
  }

  /**
   * Unbind event listeners
   * @param {!string} eventName
   * @param {function(...)} cb
   */
  off(eventName, cb) {
    if (this._eventEmitter === null) {
      throw new Error('connect() must be called before attempting to remove an event listener.');
    }

    this._eventEmitter.removeListener(eventName, cb);
  }

  /**
   * Call protocol methods
   * @return {!Promise}
   */
  sendCommand() {
    return Promise.reject(new Error('Not implemented'));
  }

  evaluateScriptOnLoad(scriptSource) {
    return this.sendCommand('Page.addScriptToEvaluateOnLoad', {
      scriptSource
    });
  }

  evaluateAsync(asyncExpression) {
    return new Promise((resolve, reject) => {
      let asyncTimeout;

      // Inject the call to capture inspection.
      const expression = `(function() {
        const __inspect = inspect;
        const __returnResults = function(results) {
          __inspect(JSON.stringify(results));
        };
        ${asyncExpression}
      })()`;

      const inspectHandler = value => {
        if (asyncTimeout !== undefined) {
          clearTimeout(asyncTimeout);
        }

        // If the returned object doesn't meet the expected pattern, bail with an undefined.
        if (value === undefined ||
            value.object === undefined ||
            value.object.value === undefined) {
          return resolve();
        }

        return resolve(JSON.parse(value.object.value));
      };

      // COMPAT: Chrome 52 is when Runtime.inspectRequested became available
      //   https://codereview.chromium.org/1866213002
      // Previously, a similar-looking Inspector.inspect event was available, but unfortunately
      // it will not fire in this scenario.
      this.once('Runtime.inspectRequested', inspectHandler);

      this.sendCommand('Runtime.evaluate', {
        expression,
        includeCommandLineAPI: true
      });

      // If this gets to 60s and it hasn't been resolved, reject the Promise.
      asyncTimeout = setTimeout(
        (_ => reject(new Error('The asynchronous expression exceeded the allotted time of 60s'))),
        60000
      );
    });
  }

  getSecurityState() {
    return new Promise((resolve, reject) => {
      this.once('Security.securityStateChanged', data => {
        this.sendCommand('Security.disable');
        resolve(data);
      });

      this.sendCommand('Security.enable');
    });
  }

  getServiceWorkerVersions() {
    return new Promise((resolve, reject) => {
      this.once('ServiceWorker.workerVersionUpdated', data => {
        this.sendCommand('ServiceWorker.disable');
        resolve(data);
      });

      this.sendCommand('ServiceWorker.enable');
    });
  }

  /**
   * If our main document URL redirects, we will update options.url accordingly
   * As such, options.url will always represent the post-redirected URL.
   * options.initialUrl is the pre-redirect URL that things started with
   */
  enableUrlUpdateIfRedirected(opts) {
    this._networkRecorder.on('requestloaded', redirectRequest => {
      // Quit if this is not a redirected request
      if (!redirectRequest.redirectSource) {
        return;
      }
      const earlierRequest = redirectRequest.redirectSource;
      if (earlierRequest.url === opts.url) {
        opts.url = redirectRequest.url;
      }
    });
  }

  /**
   * Navigate to the given URL. Use of this method directly isn't advised: if
   * the current page is already at the given URL, navigation will not occur and
   * so the returned promise will never resolve. See https://github.com/GoogleChrome/lighthouse/pull/185
   * for one possible workaround.
   * @param {string} url
   * @param {!Object} options
   * @return {!Promise}
   */
  gotoURL(url, options) {
    const waitForLoad = (options && options.waitForLoad) || false;
    const disableJavaScript = (options && options.disableJavaScript) || false;
    return this.sendCommand('Page.enable')
    .then(_ => this.sendCommand('Emulation.setScriptExecutionDisabled', {value: disableJavaScript}))
    .then(_ => this.sendCommand('Page.navigate', {url}))
    .then(_ => {
      return new Promise((resolve, reject) => {
        this.url = url;

        if (!waitForLoad) {
          return resolve();
        }

        this.once('Page.loadEventFired', response => {
          setTimeout(_ => {
            resolve(response);
          }, this.PAUSE_AFTER_LOAD);
        });
      });
    });
  }

  reloadForCleanStateIfNeeded() {
    return Promise.resolve();
  }

  /**
   * @param {string} selector Selector to find in the DOM
   * @return {!Promise<Element>} The found element, or null, resolved in a promise
   */
  querySelector(selector) {
    return this.sendCommand('DOM.getDocument')
      .then(result => result.root.nodeId)
      .then(nodeId => this.sendCommand('DOM.querySelector', {
        nodeId,
        selector
      }))
      .then(element => {
        if (element.nodeId === 0) {
          return null;
        }
        return new Element(element, this);
      });
  }

  beginTrace() {
    const tracingOpts = {
      categories: this._traceCategories.join(','),
      transferMode: 'ReturnAsStream',
      options: 'sampling-frequency=10000'  // 1000 is default and too slow.
    };

    return this.sendCommand('Page.enable')
      .then(_ => this.sendCommand('Tracing.start', tracingOpts));
  }

  endTrace() {
    return new Promise((resolve, reject) => {
      // When the tracing has ended this will fire with a stream handle.
      this.once('Tracing.tracingComplete', streamHandle => {
        this._readTraceFromStream(streamHandle)
            .then(traceContents => resolve(traceContents));
      });

      // Issue the command to stop tracing.
      this.sendCommand('Tracing.end');
    });
  }

  _readTraceFromStream(streamHandle) {
    return new Promise((resolve, reject) => {
      // COMPAT: We've found `result` not retaining its value in this scenario when it's
      // declared with `let`. Observed in Chrome 50 and 52. While investigating the V8 bug
      // further, we'll use a plain `var` declaration.
      var isEOF = false;
      var result = '';

      const readArguments = {
        handle: streamHandle.stream
      };

      const onChunkRead = response => {
        if (isEOF) {
          return;
        }

        result += response.data;

        if (response.eof) {
          isEOF = true;
          return resolve(JSON.parse(result));
        }

        return this.sendCommand('IO.read', readArguments).then(onChunkRead);
      };

      this.sendCommand('IO.read', readArguments).then(onChunkRead);
    });
  }

  beginNetworkCollect(opts) {
    return new Promise((resolve, reject) => {
      this._networkRecords = [];
      this._networkRecorder = new NetworkRecorder(this._networkRecords);
      this.enableUrlUpdateIfRedirected(opts);

      this.on('Network.requestWillBeSent', this._networkRecorder.onRequestWillBeSent);
      this.on('Network.requestServedFromCache', this._networkRecorder.onRequestServedFromCache);
      this.on('Network.responseReceived', this._networkRecorder.onResponseReceived);
      this.on('Network.dataReceived', this._networkRecorder.onDataReceived);
      this.on('Network.loadingFinished', this._networkRecorder.onLoadingFinished);
      this.on('Network.loadingFailed', this._networkRecorder.onLoadingFailed);
      this.on('Network.resourceChangedPriority', this._networkRecorder.onResourceChangedPriority);

      this.sendCommand('Network.enable').then(_ => {
        resolve();
      });
    });
  }

  endNetworkCollect() {
    return new Promise((resolve, reject) => {
      this.off('Network.requestWillBeSent', this._networkRecorder.onRequestWillBeSent);
      this.off('Network.requestServedFromCache', this._networkRecorder.onRequestServedFromCache);
      this.off('Network.responseReceived', this._networkRecorder.onResponseReceived);
      this.off('Network.dataReceived', this._networkRecorder.onDataReceived);
      this.off('Network.loadingFinished', this._networkRecorder.onLoadingFinished);
      this.off('Network.loadingFailed', this._networkRecorder.onLoadingFailed);
      this.off('Network.resourceChangedPriority', this._networkRecorder.onResourceChangedPriority);

      resolve(this._networkRecords);

      this._networkRecorder = null;
      this._networkRecords = [];
    });
  }

  beginEmulation() {
    return Promise.all([
      emulation.enableNexus5X(this),
      emulation.enableNetworkThrottling(this)
    ]);
  }

  /**
   * Emulate internet disconnection.
   * @return {!Promise}
   */
  goOffline() {
    return this.sendCommand('Network.enable').then(_ => emulation.goOffline(this));
  }

  /**
   * Enable internet connection, using emulated mobile settings if
   * `options.flags.mobile` is true.
   * @param {!Object} options
   * @return {!Promise}
   */
  goOnline(options) {
    return this.sendCommand('Network.enable').then(_ => {
      if (options.flags.mobile) {
        return emulation.enableNetworkThrottling(this);
      }

      return emulation.disableNetworkThrottling(this);
    });
  }

  cleanAndDisableBrowserCaches() {
    return Promise.all([
      this.clearBrowserCache(),
      this.disableBrowserCache()
    ]);
  }

  clearBrowserCache() {
    return this.sendCommand('Network.clearBrowserCache');
  }

  disableBrowserCache() {
    return this.sendCommand('Network.setCacheDisabled', {cacheDisabled: true});
  }

  forceUpdateServiceWorkers() {
    // COMPAT: This command will trigger this registrationId error in Chrome 50 (51 undetermined):
    //   "{"code":-32602,"message":"Missing or invalid 'registrationId' parameter"}"
    return this.sendCommand('ServiceWorker.setForceUpdateOnPageLoad', {
      forceUpdateOnPageLoad: true
    });
  }
}

module.exports = Driver;

<commit_msg>Add netlog to get detailed network activity.<commit_after>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * 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';

const NetworkRecorder = require('../../lib/network-recorder');
const emulation = require('../../lib/emulation');
const Element = require('../../lib/element');

const log = require('../../lib/log.js');

class Driver {

  constructor() {
    this.PAUSE_AFTER_LOAD = 500;
    this._traceEvents = [];
    this._traceCategories = Driver.traceCategories;
    this._eventEmitter = null;
  }

  static get traceCategories() {
    return [
      '-*', // exclude default
      'toplevel',
      'blink.console',
      'blink.user_timing',
      'benchmark',
      'netlog',
      'devtools.timeline',
      'disabled-by-default-blink.debug.layout',
      'disabled-by-default-devtools.timeline',
      'disabled-by-default-devtools.timeline.frame',
      'disabled-by-default-devtools.timeline.stack',
      // 'disabled-by-default-v8.cpu_profile',  // these would include JS stack samples, but
      // 'disabled-by-default-v8.cpu_profile.hires', // will take the trace from 5MB -> 100MB
      'disabled-by-default-devtools.screenshot'
    ];
  }

  enableRuntimeEvents() {
    return this.sendCommand('Runtime.enable');
  }

  enableSecurityEvents() {
    return this.sendCommand('Security.enable');
  }

  /**
   * A simple formatting utility for event logging.
   * @param {string} prefix
   * @param {!Object} data A JSON-serializable object of event data to log.
   * @param {string=} level Optional logging level. Defaults to 'log'.
   */
  formattedLog(prefix, data, level) {
    const columns = (!process || process.browser) ? Infinity : process.stdout.columns;
    const maxLength = columns - data.method.length - prefix.length - 18;
    // IO.read blacklisted here to avoid logging megabytes of trace data
    const snippet = (data.params && data.method !== 'IO.read') ?
        JSON.stringify(data.params).substr(0, maxLength) : '';
    log[level ? level : 'log'](prefix, data.method, snippet);
  }

  /**
   * @return {!Promise<null>}
   */
  connect() {
    return Promise.reject(new Error('Not implemented'));
  }

  disconnect() {
    return Promise.reject(new Error('Not implemented'));
  }

  /**
   * Bind listeners for protocol events
   * @param {!string} eventName
   * @param {function(...)} cb
   */
  on(eventName, cb) {
    if (this._eventEmitter === null) {
      throw new Error('connect() must be called before attempting to listen to events.');
    }

    // log event listeners being bound
    this.formattedLog('listen for event =>', {method: eventName}, 'verbose');
    this._eventEmitter.on(eventName, cb);
  }

  /**
   * Bind a one-time listener for protocol events. Listener is removed once it
   * has been called.
   * @param {!string} eventName
   * @param {function(...)} cb
   */
  once(eventName, cb) {
    if (this._eventEmitter === null) {
      throw new Error('connect() must be called before attempting to listen to events.');
    }
    // log event listeners being bound
    this.formattedLog('listen once for event =>', {method: eventName}, 'verbose');
    this._eventEmitter.once(eventName, cb);
  }

  /**
   * Unbind event listeners
   * @param {!string} eventName
   * @param {function(...)} cb
   */
  off(eventName, cb) {
    if (this._eventEmitter === null) {
      throw new Error('connect() must be called before attempting to remove an event listener.');
    }

    this._eventEmitter.removeListener(eventName, cb);
  }

  /**
   * Call protocol methods
   * @return {!Promise}
   */
  sendCommand() {
    return Promise.reject(new Error('Not implemented'));
  }

  evaluateScriptOnLoad(scriptSource) {
    return this.sendCommand('Page.addScriptToEvaluateOnLoad', {
      scriptSource
    });
  }

  evaluateAsync(asyncExpression) {
    return new Promise((resolve, reject) => {
      let asyncTimeout;

      // Inject the call to capture inspection.
      const expression = `(function() {
        const __inspect = inspect;
        const __returnResults = function(results) {
          __inspect(JSON.stringify(results));
        };
        ${asyncExpression}
      })()`;

      const inspectHandler = value => {
        if (asyncTimeout !== undefined) {
          clearTimeout(asyncTimeout);
        }

        // If the returned object doesn't meet the expected pattern, bail with an undefined.
        if (value === undefined ||
            value.object === undefined ||
            value.object.value === undefined) {
          return resolve();
        }

        return resolve(JSON.parse(value.object.value));
      };

      // COMPAT: Chrome 52 is when Runtime.inspectRequested became available
      //   https://codereview.chromium.org/1866213002
      // Previously, a similar-looking Inspector.inspect event was available, but unfortunately
      // it will not fire in this scenario.
      this.once('Runtime.inspectRequested', inspectHandler);

      this.sendCommand('Runtime.evaluate', {
        expression,
        includeCommandLineAPI: true
      });

      // If this gets to 60s and it hasn't been resolved, reject the Promise.
      asyncTimeout = setTimeout(
        (_ => reject(new Error('The asynchronous expression exceeded the allotted time of 60s'))),
        60000
      );
    });
  }

  getSecurityState() {
    return new Promise((resolve, reject) => {
      this.once('Security.securityStateChanged', data => {
        this.sendCommand('Security.disable');
        resolve(data);
      });

      this.sendCommand('Security.enable');
    });
  }

  getServiceWorkerVersions() {
    return new Promise((resolve, reject) => {
      this.once('ServiceWorker.workerVersionUpdated', data => {
        this.sendCommand('ServiceWorker.disable');
        resolve(data);
      });

      this.sendCommand('ServiceWorker.enable');
    });
  }

  /**
   * If our main document URL redirects, we will update options.url accordingly
   * As such, options.url will always represent the post-redirected URL.
   * options.initialUrl is the pre-redirect URL that things started with
   */
  enableUrlUpdateIfRedirected(opts) {
    this._networkRecorder.on('requestloaded', redirectRequest => {
      // Quit if this is not a redirected request
      if (!redirectRequest.redirectSource) {
        return;
      }
      const earlierRequest = redirectRequest.redirectSource;
      if (earlierRequest.url === opts.url) {
        opts.url = redirectRequest.url;
      }
    });
  }

  /**
   * Navigate to the given URL. Use of this method directly isn't advised: if
   * the current page is already at the given URL, navigation will not occur and
   * so the returned promise will never resolve. See https://github.com/GoogleChrome/lighthouse/pull/185
   * for one possible workaround.
   * @param {string} url
   * @param {!Object} options
   * @return {!Promise}
   */
  gotoURL(url, options) {
    const waitForLoad = (options && options.waitForLoad) || false;
    const disableJavaScript = (options && options.disableJavaScript) || false;
    return this.sendCommand('Page.enable')
    .then(_ => this.sendCommand('Emulation.setScriptExecutionDisabled', {value: disableJavaScript}))
    .then(_ => this.sendCommand('Page.navigate', {url}))
    .then(_ => {
      return new Promise((resolve, reject) => {
        this.url = url;

        if (!waitForLoad) {
          return resolve();
        }

        this.once('Page.loadEventFired', response => {
          setTimeout(_ => {
            resolve(response);
          }, this.PAUSE_AFTER_LOAD);
        });
      });
    });
  }

  reloadForCleanStateIfNeeded() {
    return Promise.resolve();
  }

  /**
   * @param {string} selector Selector to find in the DOM
   * @return {!Promise<Element>} The found element, or null, resolved in a promise
   */
  querySelector(selector) {
    return this.sendCommand('DOM.getDocument')
      .then(result => result.root.nodeId)
      .then(nodeId => this.sendCommand('DOM.querySelector', {
        nodeId,
        selector
      }))
      .then(element => {
        if (element.nodeId === 0) {
          return null;
        }
        return new Element(element, this);
      });
  }

  beginTrace() {
    const tracingOpts = {
      categories: this._traceCategories.join(','),
      transferMode: 'ReturnAsStream',
      options: 'sampling-frequency=10000'  // 1000 is default and too slow.
    };

    return this.sendCommand('Page.enable')
      .then(_ => this.sendCommand('Tracing.start', tracingOpts));
  }

  endTrace() {
    return new Promise((resolve, reject) => {
      // When the tracing has ended this will fire with a stream handle.
      this.once('Tracing.tracingComplete', streamHandle => {
        this._readTraceFromStream(streamHandle)
            .then(traceContents => resolve(traceContents));
      });

      // Issue the command to stop tracing.
      this.sendCommand('Tracing.end');
    });
  }

  _readTraceFromStream(streamHandle) {
    return new Promise((resolve, reject) => {
      // COMPAT: We've found `result` not retaining its value in this scenario when it's
      // declared with `let`. Observed in Chrome 50 and 52. While investigating the V8 bug
      // further, we'll use a plain `var` declaration.
      var isEOF = false;
      var result = '';

      const readArguments = {
        handle: streamHandle.stream
      };

      const onChunkRead = response => {
        if (isEOF) {
          return;
        }

        result += response.data;

        if (response.eof) {
          isEOF = true;
          return resolve(JSON.parse(result));
        }

        return this.sendCommand('IO.read', readArguments).then(onChunkRead);
      };

      this.sendCommand('IO.read', readArguments).then(onChunkRead);
    });
  }

  beginNetworkCollect(opts) {
    return new Promise((resolve, reject) => {
      this._networkRecords = [];
      this._networkRecorder = new NetworkRecorder(this._networkRecords);
      this.enableUrlUpdateIfRedirected(opts);

      this.on('Network.requestWillBeSent', this._networkRecorder.onRequestWillBeSent);
      this.on('Network.requestServedFromCache', this._networkRecorder.onRequestServedFromCache);
      this.on('Network.responseReceived', this._networkRecorder.onResponseReceived);
      this.on('Network.dataReceived', this._networkRecorder.onDataReceived);
      this.on('Network.loadingFinished', this._networkRecorder.onLoadingFinished);
      this.on('Network.loadingFailed', this._networkRecorder.onLoadingFailed);
      this.on('Network.resourceChangedPriority', this._networkRecorder.onResourceChangedPriority);

      this.sendCommand('Network.enable').then(_ => {
        resolve();
      });
    });
  }

  endNetworkCollect() {
    return new Promise((resolve, reject) => {
      this.off('Network.requestWillBeSent', this._networkRecorder.onRequestWillBeSent);
      this.off('Network.requestServedFromCache', this._networkRecorder.onRequestServedFromCache);
      this.off('Network.responseReceived', this._networkRecorder.onResponseReceived);
      this.off('Network.dataReceived', this._networkRecorder.onDataReceived);
      this.off('Network.loadingFinished', this._networkRecorder.onLoadingFinished);
      this.off('Network.loadingFailed', this._networkRecorder.onLoadingFailed);
      this.off('Network.resourceChangedPriority', this._networkRecorder.onResourceChangedPriority);

      resolve(this._networkRecords);

      this._networkRecorder = null;
      this._networkRecords = [];
    });
  }

  beginEmulation() {
    return Promise.all([
      emulation.enableNexus5X(this),
      emulation.enableNetworkThrottling(this)
    ]);
  }

  /**
   * Emulate internet disconnection.
   * @return {!Promise}
   */
  goOffline() {
    return this.sendCommand('Network.enable').then(_ => emulation.goOffline(this));
  }

  /**
   * Enable internet connection, using emulated mobile settings if
   * `options.flags.mobile` is true.
   * @param {!Object} options
   * @return {!Promise}
   */
  goOnline(options) {
    return this.sendCommand('Network.enable').then(_ => {
      if (options.flags.mobile) {
        return emulation.enableNetworkThrottling(this);
      }

      return emulation.disableNetworkThrottling(this);
    });
  }

  cleanAndDisableBrowserCaches() {
    return Promise.all([
      this.clearBrowserCache(),
      this.disableBrowserCache()
    ]);
  }

  clearBrowserCache() {
    return this.sendCommand('Network.clearBrowserCache');
  }

  disableBrowserCache() {
    return this.sendCommand('Network.setCacheDisabled', {cacheDisabled: true});
  }

  forceUpdateServiceWorkers() {
    // COMPAT: This command will trigger this registrationId error in Chrome 50 (51 undetermined):
    //   "{"code":-32602,"message":"Missing or invalid 'registrationId' parameter"}"
    return this.sendCommand('ServiceWorker.setForceUpdateOnPageLoad', {
      forceUpdateOnPageLoad: true
    });
  }
}

module.exports = Driver;

<|endoftext|>


<commit_before>'use strict';

var comments = ['Only one right. Grandma level.', 'Two right. Poser level.', 'Mid-level knowledge.', 'Your audiophile skills are strong', 'Wow! Perfect Score! You are a music junkie!'];

var score = 2;

if(score === 0) {
  var zeroComment = document.getElementById('zero_score_text');
  zeroComment.textContent = ('You got zero correct answers. Come to r&d immediately!');
} else {
  for (var i = 1; i <= score; i++) {
    var tableCell = document.getElementById('score' + [i]);
    tableCell.setAttribute('id', 'filledIn');
  }
  var tableComment = document.getElementById('status' + [score]);
  tableComment.textContent = comments[score - 1];

  if (score === 5) {
    var paraText = document.getElementById('congrats');
    paraText.textContent = ('Congratulations! You get a free record voucher!');
  } else {
    var paraOther = document.getElementById('results_text');
    paraOther.textContent = ('Thanks for playing!');
  }
};

<commit_msg>added local storage to resulst.js<commit_after>'use strict';

var comments = ['Only one right. Grandma level.', 'Two right. Poser level.', 'Mid-level knowledge.', 'Your audiophile skills are strong', 'Wow! Perfect Score! You are a music junkie!'];

// var score = 2;
loadHandler();
if(loadScore === 0) {
  var zeroComment = document.getElementById('zero_score_text');
  zeroComment.textContent = ('You got zero correct answers. Come to r&d immediately!');
} else {
  for (var i = 1; i <= loadScore; i++) {
    var tableCell = document.getElementById('score' + [i]);
    tableCell.setAttribute('id', 'filledIn');
  }
  var tableComment = document.getElementById('status' + [loadScore]);
  tableComment.textContent = comments[loadScore - 1];

  if (loadScore === 5) {
    var paraText = document.getElementById('congrats');
    paraText.textContent = ('Congratulations! You get a free record voucher!');
  } else {
    var paraOther = document.getElementById('results_text');
    paraOther.textContent = ('Thanks for playing!');
  }
};

<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular
    .module('idioms')
    .run(menuConfig);

  menuConfig.$inject = ['Menus'];

  function menuConfig(Menus) {
    Menus.addMenuItem('topbar', {
      title: 'Idioms',
      state: 'idioms',
      type: 'dropdown',
      roles: ['*']
    });

    // Add the dropdown list item
    Menus.addSubMenuItem('topbar', 'idioms', {
      title: 'List Idioms',
      state: 'idioms.list'
    });

    // Add the dropdown create item
    Menus.addSubMenuItem('topbar', 'idioms', {
      title: 'Create Idiom',
      state: 'idioms.create',
      roles: ['user', 'admin']
    });
  }
})();<commit_msg>D003 - Idiom search menu should only visible for logged in users<commit_after>(function() {
  'use strict';

  angular
    .module('idioms')
    .run(menuConfig);

  menuConfig.$inject = ['Menus'];

  function menuConfig(Menus) {
    Menus.addMenuItem('topbar', {
      title: 'Idioms',
      state: 'idioms',
      type: 'dropdown',
      roles: ['user', 'admin']
    });

    // Add the dropdown list item
    Menus.addSubMenuItem('topbar', 'idioms', {
      title: 'List Idioms',
      state: 'idioms.list',
      roles: ['user', 'admin']
    });

    // Add the dropdown create item
    Menus.addSubMenuItem('topbar', 'idioms', {
      title: 'Create Idiom',
      state: 'idioms.create',
      roles: ['user', 'admin']
    });
  }
})();<|endoftext|>


<commit_before>import React from 'react'
import graphqlApi from '../graphql-api'
import lodash from 'lodash'
import MessagesContainer from './messages-container'
import DropdownButton from './dropdown-button'

export default class Group extends React.Component {
  state = {
    group: null,
    services: []
  }

  componentWillMount = async () => {
    const query = `{ group(name: "${this.props.name}") {
        name
        serviceAccessRules {
          service {
            id
            displayName
            roles
          }
          accessRules {
            asset
            role
          }
        }
      }
      services {
        id
        displayName
        roles
      }
    }`
    const response = await graphqlApi.request(query)

    this.setState(response.data)
  }

  removeService = (serviceId) => {
    const group = this.state.group
    lodash.remove(group.serviceAccessRules, (sar) => sar.service.id === serviceId)
    this.save(group)
  }

  isRoleEnabled = (role, accessRules) => {
    return !!lodash.find(accessRules, (rule) => rule.asset === '*' && (rule.role === role))
  }

  onRoleClicked = (event, role, serviceId) => {
    event.target.blur()
    const group = this.state.group
    const serviceAccessRule = lodash.find(group.serviceAccessRules, (sar) => sar.service.id === serviceId)
    const accessRules = serviceAccessRule.accessRules

    if (this.isRoleEnabled(role, accessRules)) {
      lodash.remove(accessRules, (rule) => rule.role === role)
    } else {
      accessRules.push({asset: '*', role: role})
    }

    this.save(group)
  }

  mapGroupToMutation = (group) => {
    return `mutation { setGroupAccessRules(
        name:"${group.name}",
        serviceAccessRules:[${group.serviceAccessRules.map(this.mapServiceAccessRuleToMutation).join(',')}]
      )
    }`
  }

  mapServiceAccessRuleToMutation = (serviceAccessRule) => {
    return `{
      serviceId:"${serviceAccessRule.service.id}",
      accessRules: [${serviceAccessRule.accessRules.map(this.mapAccessRuleToMutation).join(',')}]
    }`
  }

  mapAccessRuleToMutation = (accessRule) => {
    return `{
      asset: "${accessRule.asset}",
      role: "${accessRule.role}"
    }`
  }

  serviceOptions = () => {
    const servicesWithoutAccessRules = this.state.services.filter((service) => {
      const hasAccessRule = !!lodash.find(this.state.group.serviceAccessRules, (sar) => sar.service.id === service.id)
      return !hasAccessRule
    })
    return servicesWithoutAccessRules.map((s) => {
      return { text: s.displayName, value: s.id }
    })
  }

  addService = (serviceId) => {
    const group = this.state.group
    const service = lodash.find(this.state.services, (s) => s.id === serviceId)
    const serviceAccessRule = {
      service,
      accessRules: service.roles.map((r) => {
        return {
          asset: '*',
          role: r
        }
      })
    }
    group.serviceAccessRules.push(serviceAccessRule)
    this.save(group)
  }

  save = async (group) => {
    const query = this.mapGroupToMutation(group)
    let response = await graphqlApi.request(query)

    if (response.error) {
      this.messagesContainer.push({
        title: 'Error Saving Group',
        body: response.error.message
      })
    } else {
      this.setState({ group: group })
    }
  }

  render () {
    const servicesWithoutAccessRules = this.state.services.filter((service) => {
      const hasAccessRule = !!lodash.find(this.state.group.serviceAccessRules, (sar) => sar.service.id === service.id)
      return !hasAccessRule
    })
    const serviceOptions = servicesWithoutAccessRules.map((s) => {
      return { text: s.displayName, value: s.id }
    })

    return (

{this.props.name}

        { this.state.group &&

            { serviceOptions.length > 0 &&
              <DropdownButton className='is-pulled-right'
                title='Add Service'
                options={serviceOptions}
                onValueSelected={this.addService} />
            }

Access Rules

                  Service
                  Roles
                  Options

                {
                  this.state.group.serviceAccessRules.map((serviceAccessRule) => (

                      {serviceAccessRule.service.displayName}

                          {serviceAccessRule.service.roles.map((role) => (

                              <button
                                className={`button is-primary ${this.isRoleEnabled(role, serviceAccessRule.accessRules) ? '' : 'is-outlined'}`}
                                onClick={(e) => this.onRoleClicked(e, role, serviceAccessRule.service.id)}>
                                {role}
                              </button>

                          ))}

                            <button className='button is-small is-danger'
                              onClick={() => this.removeService(serviceAccessRule.service.id)}>
                              Remove Service
                            </button>

                  ))
                }

        }
        <MessagesContainer ref={(container) => { this.messagesContainer = container }} />

    )
  }
}
<commit_msg>filter out unconfigured services from group edit page<commit_after>import React from 'react'
import graphqlApi from '../graphql-api'
import lodash from 'lodash'
import MessagesContainer from './messages-container'
import DropdownButton from './dropdown-button'

export default class Group extends React.Component {
  state = {
    group: null,
    services: []
  }

  componentWillMount = async () => {
    const query = `{ group(name: "${this.props.name}") {
        name
        serviceAccessRules {
          service {
            id
            displayName
            roles
          }
          accessRules {
            asset
            role
          }
        }
      }
      services(isConfigured: true) {
        id
        displayName
        roles
      }
    }`
    const response = await graphqlApi.request(query)

    this.setState(response.data)
  }

  removeService = (serviceId) => {
    const group = this.state.group
    lodash.remove(group.serviceAccessRules, (sar) => sar.service.id === serviceId)
    this.save(group)
  }

  isRoleEnabled = (role, accessRules) => {
    return !!lodash.find(accessRules, (rule) => rule.asset === '*' && (rule.role === role))
  }

  onRoleClicked = (event, role, serviceId) => {
    event.target.blur()
    const group = this.state.group
    const serviceAccessRule = lodash.find(group.serviceAccessRules, (sar) => sar.service.id === serviceId)
    const accessRules = serviceAccessRule.accessRules

    if (this.isRoleEnabled(role, accessRules)) {
      lodash.remove(accessRules, (rule) => rule.role === role)
    } else {
      accessRules.push({asset: '*', role: role})
    }

    this.save(group)
  }

  mapGroupToMutation = (group) => {
    return `mutation { setGroupAccessRules(
        name:"${group.name}",
        serviceAccessRules:[${group.serviceAccessRules.map(this.mapServiceAccessRuleToMutation).join(',')}]
      )
    }`
  }

  mapServiceAccessRuleToMutation = (serviceAccessRule) => {
    return `{
      serviceId:"${serviceAccessRule.service.id}",
      accessRules: [${serviceAccessRule.accessRules.map(this.mapAccessRuleToMutation).join(',')}]
    }`
  }

  mapAccessRuleToMutation = (accessRule) => {
    return `{
      asset: "${accessRule.asset}",
      role: "${accessRule.role}"
    }`
  }

  serviceOptions = () => {
    const servicesWithoutAccessRules = this.state.services.filter((service) => {
      const hasAccessRule = !!lodash.find(this.state.group.serviceAccessRules, (sar) => sar.service.id === service.id)
      return !hasAccessRule
    })
    return servicesWithoutAccessRules.map((s) => {
      return { text: s.displayName, value: s.id }
    })
  }

  addService = (serviceId) => {
    const group = this.state.group
    const service = lodash.find(this.state.services, (s) => s.id === serviceId)
    const serviceAccessRule = {
      service,
      accessRules: service.roles.map((r) => {
        return {
          asset: '*',
          role: r
        }
      })
    }
    group.serviceAccessRules.push(serviceAccessRule)
    this.save(group)
  }

  save = async (group) => {
    const query = this.mapGroupToMutation(group)
    let response = await graphqlApi.request(query)

    if (response.error) {
      this.messagesContainer.push({
        title: 'Error Saving Group',
        body: response.error.message
      })
    } else {
      this.setState({ group: group })
    }
  }

  render () {
    const servicesWithoutAccessRules = this.state.services.filter((service) => {
      const hasAccessRule = !!lodash.find(this.state.group.serviceAccessRules, (sar) => sar.service.id === service.id)
      return !hasAccessRule
    })
    const serviceOptions = servicesWithoutAccessRules.map((s) => {
      return { text: s.displayName, value: s.id }
    })

    return (

{this.props.name}

        { this.state.group &&

            { serviceOptions.length > 0 &&
              <DropdownButton className='is-pulled-right'
                title='Add Service'
                options={serviceOptions}
                onValueSelected={this.addService} />
            }

Access Rules

                  Service
                  Roles
                  Options

                {
                  this.state.group.serviceAccessRules.map((serviceAccessRule) => (

                      {serviceAccessRule.service.displayName}

                          {serviceAccessRule.service.roles.map((role) => (

                              <button
                                className={`button is-primary ${this.isRoleEnabled(role, serviceAccessRule.accessRules) ? '' : 'is-outlined'}`}
                                onClick={(e) => this.onRoleClicked(e, role, serviceAccessRule.service.id)}>
                                {role}
                              </button>

                          ))}

                            <button className='button is-small is-danger'
                              onClick={() => this.removeService(serviceAccessRule.service.id)}>
                              Remove Service
                            </button>

                  ))
                }

        }
        <MessagesContainer ref={(container) => { this.messagesContainer = container }} />

    )
  }
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

/**
 * Option Schema
 */
var OptionSchema = new Schema({
  name: {
    type: String,
    default: '',
    required: 'Please fill Option name',
    trim: true
  },
  created: {
    type: Date,
    default: Date.now
  },
  user: {
    type: Schema.ObjectId,
    ref: 'User'
  }
});

mongoose.model('Option', OptionSchema);
<commit_msg>Commited from lenh at 2017年 6月 15日 木曜日 09:31:42<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

/**
 * Option Schema
 */
var OptionSchema = new Schema({
  title: {
    type: String,
    default: '',
    required: 'Please fill Option title',
    trim: true
  },
  body: {
    type: String,
    default: '',
    required: 'Please fill Option body',
    trim: true
  },
  name: {
    type: String,
    default: '',
    required: 'Please fill Option name',
    trim: true
  },
  created: {
    type: Date,
    default: Date.now
  },
  user: {
    type: Schema.ObjectId,
    ref: 'User'
  }
});

mongoose.model('Option', OptionSchema);
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
'use strict';

const querystring = require('querystring');
const url = require('url');

/**
 * Attaches a WebSocket based connection to the Packager to expose
 * Hot Module Replacement updates to the simulator.
 */
function attachHMRServer({httpServer, path, packagerServer}) {
  let client = null;

  function disconnect() {
    client = null;
    packagerServer.setHMRFileChangeListener(null);
  }

  // Returns a promise with the full list of dependencies and the shallow
  // dependencies each file on the dependency list has for the give platform
  // and entry file.
  function getDependencies(platform, bundleEntry) {
    return packagerServer.getDependencies({
      platform: platform,
      dev: true,
      entryFile: bundleEntry,
    }).then(response => {
      // for each dependency builds the object:
      // `{path: '/a/b/c.js', deps: ['modA', 'modB', ...]}`
      return Promise.all(Object.values(response.dependencies).map(dep => {
        return dep.getName().then(depName => {
          if (dep.isAsset() || dep.isAsset_DEPRECATED() || dep.isJSON()) {
            return Promise.resolve({path: dep.path, deps: []});
          }
          return packagerServer.getShallowDependencies(dep.path)
            .then(deps => {
              return {
                path: dep.path,
                name: depName,
                deps,
              };
            });
        });
      }))
      .then(deps => {
        // list with all the dependencies' filenames the bundle entry has
        const dependenciesCache = response.dependencies.map(dep => dep.path);

        // map from module name to path
        const moduleToFilenameCache = Object.create(null);
        deps.forEach(dep => moduleToFilenameCache[dep.name] = dep.path);

        // map that indicates the shallow dependency each file included on the
        // bundle has
        const shallowDependencies = Object.create(null);
        deps.forEach(dep => shallowDependencies[dep.path] = dep.deps);

        // map from module name to the modules' dependencies the bundle entry
        // has
        const dependenciesModulesCache = Object.create(null);
        return Promise.all(response.dependencies.map(dep => {
          return dep.getName().then(depName => {
            dependenciesModulesCache[depName] = dep;
          });
        })).then(() => {
          return {
            dependenciesCache,
            dependenciesModulesCache,
            shallowDependencies,
          };
        });
      });
    });
  }

  const WebSocketServer = require('ws').Server;
  const wss = new WebSocketServer({
    server: httpServer,
    path: path,
  });

  console.log('[Hot Module Replacement] Server listening on', path);
  wss.on('connection', ws => {
    console.log('[Hot Module Replacement] Client connected');
    const params = querystring.parse(url.parse(ws.upgradeReq.url).query);

    getDependencies(params.platform, params.bundleEntry)
      .then(({
        dependenciesCache,
        dependenciesModulesCache,
        shallowDependencies,
      }) => {
        client = {
          ws,
          platform: params.platform,
          bundleEntry: params.bundleEntry,
          dependenciesCache,
          dependenciesModulesCache,
          shallowDependencies,
        };

        packagerServer.setHMRFileChangeListener(filename => {
          if (!client) {
            return;
          }

          return packagerServer.getShallowDependencies(filename)
            .then(deps => {
              // if the file dependencies have change we need to invalidate the
              // dependencies caches because the list of files we need to send
              // to the client may have changed
              const oldDependencies = client.shallowDependencies[filename];
              if (arrayEquals(deps, oldDependencies)) {
                return [packagerServer.getModuleForPath(filename)];
              }

              // if there're new dependencies compare the full list of
              // dependencies we used to have with the one we now have
              return getDependencies(client.platform, client.bundleEntry)
                .then(({
                  dependenciesCache,
                  dependenciesModulesCache,
                  shallowDependencies,
                }) => {
                  // build list of modules for which we'll send HMR updates
                  const modulesToUpdate = [];
                  Object.keys(dependenciesModulesCache).forEach(module => {
                    if (!client.dependenciesModulesCache[module]) {
                      modulesToUpdate.push(dependenciesModulesCache[module]);
                    }
                  });

                  // invalidate caches
                  client.dependenciesCache = dependenciesCache;
                  client.dependenciesModulesCache = dependenciesModulesCache;
                  client.shallowDependencies = shallowDependencies;

                  return modulesToUpdate;
                });
            })
            .then(modulesToUpdate => {
              // make sure the file was modified is part of the bundle
              if (!client.shallowDependencies[filename]) {
                return;
              }

              return packagerServer.buildBundleForHMR({
                entryFile: client.bundleEntry,
                platform: client.platform,
                modules: modulesToUpdate,
              });
            })
            .then(bundle => {
              if (bundle) {
                client.ws.send(bundle);
              }
            })
            .done();
        });

        client.ws.on('error', e => {
          console.error('[Hot Module Replacement] Unexpected error', e);
          disconnect();
        });

        client.ws.on('close', () => disconnect());
      })
    .done();
  });
}

function arrayEquals(arrayA, arrayB) {
  arrayA = arrayA || [];
  arrayB = arrayB || [];
  return (
    arrayA.length === arrayB.length &&
    arrayA.every((element, index) => {
      return element === arrayB[index];
    })
  );
}

module.exports = attachHMRServer;
<commit_msg>Make sure client is still connected while computing HMR update<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
'use strict';

const querystring = require('querystring');
const url = require('url');

/**
 * Attaches a WebSocket based connection to the Packager to expose
 * Hot Module Replacement updates to the simulator.
 */
function attachHMRServer({httpServer, path, packagerServer}) {
  let client = null;

  function disconnect() {
    client = null;
    packagerServer.setHMRFileChangeListener(null);
  }

  // Returns a promise with the full list of dependencies and the shallow
  // dependencies each file on the dependency list has for the give platform
  // and entry file.
  function getDependencies(platform, bundleEntry) {
    return packagerServer.getDependencies({
      platform: platform,
      dev: true,
      entryFile: bundleEntry,
    }).then(response => {
      // for each dependency builds the object:
      // `{path: '/a/b/c.js', deps: ['modA', 'modB', ...]}`
      return Promise.all(Object.values(response.dependencies).map(dep => {
        return dep.getName().then(depName => {
          if (dep.isAsset() || dep.isAsset_DEPRECATED() || dep.isJSON()) {
            return Promise.resolve({path: dep.path, deps: []});
          }
          return packagerServer.getShallowDependencies(dep.path)
            .then(deps => {
              return {
                path: dep.path,
                name: depName,
                deps,
              };
            });
        });
      }))
      .then(deps => {
        // list with all the dependencies' filenames the bundle entry has
        const dependenciesCache = response.dependencies.map(dep => dep.path);

        // map from module name to path
        const moduleToFilenameCache = Object.create(null);
        deps.forEach(dep => moduleToFilenameCache[dep.name] = dep.path);

        // map that indicates the shallow dependency each file included on the
        // bundle has
        const shallowDependencies = Object.create(null);
        deps.forEach(dep => shallowDependencies[dep.path] = dep.deps);

        // map from module name to the modules' dependencies the bundle entry
        // has
        const dependenciesModulesCache = Object.create(null);
        return Promise.all(response.dependencies.map(dep => {
          return dep.getName().then(depName => {
            dependenciesModulesCache[depName] = dep;
          });
        })).then(() => {
          return {
            dependenciesCache,
            dependenciesModulesCache,
            shallowDependencies,
          };
        });
      });
    });
  }

  const WebSocketServer = require('ws').Server;
  const wss = new WebSocketServer({
    server: httpServer,
    path: path,
  });

  console.log('[Hot Module Replacement] Server listening on', path);
  wss.on('connection', ws => {
    console.log('[Hot Module Replacement] Client connected');
    const params = querystring.parse(url.parse(ws.upgradeReq.url).query);

    getDependencies(params.platform, params.bundleEntry)
      .then(({
        dependenciesCache,
        dependenciesModulesCache,
        shallowDependencies,
      }) => {
        client = {
          ws,
          platform: params.platform,
          bundleEntry: params.bundleEntry,
          dependenciesCache,
          dependenciesModulesCache,
          shallowDependencies,
        };

        packagerServer.setHMRFileChangeListener(filename => {
          if (!client) {
            return;
          }

          return packagerServer.getShallowDependencies(filename)
            .then(deps => {
              if (!client) {
                return [];
              }

              // if the file dependencies have change we need to invalidate the
              // dependencies caches because the list of files we need to send
              // to the client may have changed
              const oldDependencies = client.shallowDependencies[filename];
              if (arrayEquals(deps, oldDependencies)) {
                return [packagerServer.getModuleForPath(filename)];
              }

              // if there're new dependencies compare the full list of
              // dependencies we used to have with the one we now have
              return getDependencies(client.platform, client.bundleEntry)
                .then(({
                  dependenciesCache,
                  dependenciesModulesCache,
                  shallowDependencies,
                }) => {
                  if (!client) {
                    return [];
                  }

                  // build list of modules for which we'll send HMR updates
                  const modulesToUpdate = [];
                  Object.keys(dependenciesModulesCache).forEach(module => {
                    if (!client.dependenciesModulesCache[module]) {
                      modulesToUpdate.push(dependenciesModulesCache[module]);
                    }
                  });

                  // invalidate caches
                  client.dependenciesCache = dependenciesCache;
                  client.dependenciesModulesCache = dependenciesModulesCache;
                  client.shallowDependencies = shallowDependencies;

                  return modulesToUpdate;
                });
            })
            .then(modulesToUpdate => {
              if (!client) {
                return;
              }

              // make sure the file was modified is part of the bundle
              if (!client.shallowDependencies[filename]) {
                return;
              }

              return packagerServer.buildBundleForHMR({
                entryFile: client.bundleEntry,
                platform: client.platform,
                modules: modulesToUpdate,
              });
            })
            .then(bundle => {
              if (!client) {
                return;
              }

              // check we actually want to send an HMR update
              if (bundle) {
                client.ws.send(bundle);
              }
            })
            .done();
        });

        client.ws.on('error', e => {
          console.error('[Hot Module Replacement] Unexpected error', e);
          disconnect();
        });

        client.ws.on('close', () => disconnect());
      })
    .done();
  });
}

function arrayEquals(arrayA, arrayB) {
  arrayA = arrayA || [];
  arrayB = arrayB || [];
  return (
    arrayA.length === arrayB.length &&
    arrayA.every((element, index) => {
      return element === arrayB[index];
    })
  );
}

module.exports = attachHMRServer;
<|endoftext|>


<commit_before>/* eslint-disable react/prop-types */
/* eslint-disable no-unused-vars */
/* eslint-disable react/forbid-prop-types */
/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2018
 */

import React, { useState } from 'react';
import { View, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import { VictoryChart, VictoryBar, VictoryAxis } from 'victory-native';
import { APP_FONT_FAMILY, GREY, LIGHT_GREY, DARK_GREY, SUSSOL_ORANGE } from '../../globalStyles';

export const ReportTable = ({ title, type, data }) => {
  const [dimensions, setDimensions] = useState({ height: null, width: null });
  const { height, width } = dimensions;

  // Victory Native sizes are set using absolute values. Parents dimensions are used to
  // calculate relative values for width and height for each chart.
  const onLayout = event => {
    const newDimensionsObj = {
      height: event.nativeEvent.layout.width,
      width: event.nativeEvent.layout.height,
    };
    setDimensions(newDimensionsObj);
  };

  const { padTop, padBottom, padLeft, padRight, padDomain, style } = victoryStyles.barChart;

  const padding = {
    top: height * padTop,
    bottom: height * padBottom,
    left: width * padLeft,
    right: width * padRight,
  };

  const chartDimensions = width * (1 - (padLeft + padRight));
  const domainPadding = chartDimensions * padDomain;

  const { rows, header } = data;

  return (
    <View style={localStyles.ChartContainer} onLayout={onLayout}>
      <ReportTable rows={rows} headers={header} />;
    </View>
  );
};

ReportTable.propTypes = {
  title: PropTypes.string.isRequired,
  type: PropTypes.string.isRequired,
  data: PropTypes.array.isRequired,
};

const localStyles = StyleSheet.create({
  ChartContainer: {
    width: '75%',
    minHeight: '100%',
    backgroundColor: 'white',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const victoryStyles = {
  axisX: {
    fixLabelOverlap: true,
    style: {
      axis: { stroke: LIGHT_GREY },
      ticks: { stroke: DARK_GREY },
      tickLabels: { fontFamily: APP_FONT_FAMILY, fill: GREY, textAnchor: 'end', angle: -45 },
    },
  },
  axisY: {
    fixLabelOverlap: false,
    style: {
      axis: { stroke: LIGHT_GREY },
      ticks: { stroke: DARK_GREY },
      tickLabels: { fontFamily: APP_FONT_FAMILY, fill: GREY },
    },
  },
  barChart: {
    padTop: 0.1,
    padBottom: 0.15,
    padLeft: 0.1,
    padRight: 0.05,
    padDomain: 0.05,
    style: { data: { fill: SUSSOL_ORANGE } },
  },
};
<commit_msg>Create component ReportTable<commit_after>/* eslint-disable react/prop-types */
/* eslint-disable react/forbid-prop-types */
/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2018
 */

import React from 'react';
import { StyleSheet, FlatList, View } from 'react-native';
import PropTypes from 'prop-types';
import { LIGHT_GREY } from '../../globalStyles';
import { ReportRow } from './ReportRow';

export const ReportTable = ({ rows, header }) => {
  const renderItem = ({ item, index }) => <ReportRow rowData={item} rowIndex={index} />;

  const renderHeader = () => <ReportRow rowData={header} isHeader rowIndex={0} />;

  // TODO: KeyExtractor should be altered to not use the index.
  return (
    <View style={localStyles.container}>
      {renderHeader()}
      <FlatList data={rows} renderItem={renderItem} keyExtractor={(_, index) => `${index}`} />
    </View>
  );
};

ReportTable.propTypes = {
  header: PropTypes.array.isRequired,
  rows: PropTypes.array.isRequired,
};

const localStyles = StyleSheet.create({
  container: {
    backgroundColor: LIGHT_GREY,
  },
});
<|endoftext|>