diff --git a/.eslintrc b/.eslintrc
index 5e9e1216..b8473ad0 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -13,6 +13,7 @@
"commonjs": true,
"node": false
},
+ "plugins": ["jsdoc"],
"globals": {
"$": false
},
@@ -45,12 +46,6 @@
"no-unexpected-multiline": 1,
"no-unreachable": 2,
"use-isnan": 1,
- "valid-jsdoc": [1, {
- "requireReturn": false,
- "requireReturnType": false,
- "requireParamDescription": false,
- "requireReturnDescription": false
- }],
"valid-typeof": 2,
"accessor-pairs": 2,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd1572ba..f5d379f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,11 @@
+
+### 2.11.0
+
+### Features
+- login.js now supports multifactor authentication. See ```src/components/login/index.html``` for the necessary HTML components that must be on the login page.
+
+### 2.10.0
### Features
- Added a `keepOnline` flag to Presence Service.
diff --git a/dist/components/assignment/assignment.min.js.map b/dist/components/assignment/assignment.min.js.map
index 3a795486..fffd6935 100644
--- a/dist/components/assignment/assignment.min.js.map
+++ b/dist/components/assignment/assignment.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["webpack:///assignment.min.js","webpack:///webpack/bootstrap 5b36529e33521661d9bd","webpack:///./src/util/inherit.js","webpack:///./src/components/assignment/js/service-locator.js","webpack:///./src/components/assignment/js/base-model.js","webpack:///./src/components/assignment/js/defaults.js","webpack:///./src/components/assignment/js/user-model.js","webpack:///./src/components/assignment/js/base-collection.js","webpack:///./src/components/assignment/js/index.js","webpack:///./src/components/assignment/js/assignment.js","webpack:///./src/components/assignment/js/users-collection.js","webpack:///./src/components/assignment/js/worlds-collection.js","webpack:///./src/components/assignment/js/world-model.js","webpack:///./src/components/assignment/js/project-model.js","webpack:///./src/components/assignment/js/assignment-row.js","webpack:///./src/util/ajax-queue.js"],"names":["modules","__webpack_require__","moduleId","installedModules","exports","module","i","l","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","n","__esModule","object","property","prototype","hasOwnProperty","p","s","inherit","C","P","F","__super","constructor","extend","dest","obj","Array","slice","arguments","current","j","length","key","base","props","staticProps","parent","child","apply","this","env","cache","worldApi","service","World","memberApi","Member","_","pick","userApi","User","BaseModel","attr","options","defaults","result","_data","set","initialize","val","attrs","remove","collection","toJSON","keys","account","project","group","groupId","token","server","host","protocol","merge","classFrom","Base","serviceLocator","world","role","active","isWorldComplete","firstName","lastName","makeActive","params","userId","original","makeUserActive","fail","bind","makeInactive","makeUserInactive","BaseCollection","models","_models","idAttribute","create","model","reset","_this","concat","forEach","push","sort","sortFn","a","b","getById","id","_this2","find","each","cb","ctx","all","every","invoke","fn","filter","size","map","pluck","field","App","window","forio","MultiplayerAssignmentComponent","setEnvironment","omit","UsersCollection","WorldsCollection","ProjectModel","AssignemntRow","default","AjaxQueue","Assignment","el","$","$el","partialRight","users","worlds","bindAll","bindEvents","on","saveEdit","toggleControlls","selectAll","usassignSelected","autoAssignAll","load","join","setUsersCollection","joinUsers","render","when","fetch","then","updateControls","_showUpdating","maxUsers","_hideUpdating","getSelectedIds","data","findRowViews","ids","rowViews","unassignUsers","dtd","Deferred","done","resolve","queue","user","add","partial","updateUser","execute","promise","e","preventDefault","makeUsersInactive","rows","view","empty","sortTable","renderTable","getTableParams","mult","direction","nameDirection","userNameDirection","prop","an","bn","localeCompare","header","arrowDir","arrow","append","query","location","search","substr","split","q","_this3","u","updateControlsForSelection","updateAutoAssignButton","updateStatus","incompleteWorlds","getIncompleteWorldsCount","unassignedUsers","getUnassignedUsersCount","totalWorlds","usersText","worldsText","text","addClass","removeClass","numSelected","isDynamicAssignment","hasRoles","hide","show","allUsersAssigned","target","checked","total","removeAttr","css","opacity","Model","aw","toLowerCase","bw","am","manager","AuthManager","session","getCurrentUserSessionInfo","auth_token","ajaxSetup","headers","Authorization","me","splitIdChunks","userIds","idGroups","splice","loadUsersInfo","nonFacAndActive","endUsers","members","endUserIds","chunkedUsers","chunkedPromises","userGroups","reduce","acc","userGroup","getGroupDetails","reject","UserModel","doneFn","after","autoAssign","parse","w","worldName","prevWorld","getWorldByUser","curWorld","getOrCreateWorld","removeUser","addUser","getWordByName","Error","getWorldByUserId","getWorldNames","getNextWorldName","properNames","test","lastWorld","numWorld","match","num","places","zeros","digits","toString","needed","usersCollection","usersHash","isComplete","index","list","_worldApi","updateConfig","userObj","save","checkWorld","delete","mapUsers","res","createWorld","addUsers","savedUsers","isNew","roles","getProjectSettings","settings","__webpack_exports__","value","userRowTemplate","trim","AssignmentRow","template","editTemplate","editUserRowTemplate","setEditMode","cancelEdit","off","animate","height","duration","complete","removeEditMode","updateData","trigger","templ","vm","optionalRoles","newWorld","html","context","next","shift"],"mappings":"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","file":"assignment.min.js","sourcesContent":["/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 6);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/**\n/* Inherit from a class (using prototype borrowing)\n*/\n\n\nfunction inherit(C, P) {\n var F = function () {};\n F.prototype = P.prototype;\n C.prototype = new F();\n C.__super = P.prototype;\n C.prototype.constructor = C;\n}\n\n/**\n* Shallow copy of an object\n* @param {Object} dest object to extend\n* @return {Object} extended object\n*/\nvar extend = function (dest /*, var_args*/) {\n var obj = Array.prototype.slice.call(arguments, 1);\n var current;\n for (var j = 0; j < obj.length; j++) {\n if (!(current = obj[j])) {\n //eslint-disable-line\n continue;\n }\n\n // do not wrap inner in dest.hasOwnProperty or bad things will happen\n for (var key in current) {\n //eslint-disable-line\n dest[key] = current[key];\n }\n }\n\n return dest;\n};\n\nmodule.exports = function (base, props, staticProps) {\n var parent = base;\n var child;\n\n child = props && props.hasOwnProperty('constructor') ? props.constructor : function () {\n return parent.apply(this, arguments);\n };\n\n // add static properties to the child constructor function\n extend(child, parent, staticProps);\n\n // associate prototype chain\n inherit(child, parent);\n\n // add instance properties\n if (props) {\n extend(child.prototype, props);\n }\n\n // done\n return child;\n};\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar env = __webpack_require__(3);\n\nvar cache = {};\n\nmodule.exports = {\n worldApi: function () {\n if (!cache.worldApi) {\n cache.worldApi = new F.service.World(env.get());\n }\n return cache.worldApi;\n },\n\n memberApi: function () {\n if (!cache.memberApi) {\n cache.memberApi = new F.service.Member(_.pick(env.get(), ['groupId', 'server']));\n }\n\n return cache.memberApi;\n },\n\n userApi: function () {\n if (!cache.userApi) {\n cache.userApi = new F.service.User(_.pick(env.get(), ['account', 'server']));\n }\n\n return cache.userApi;\n }\n};\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar BaseModel = function (attr, options) {\n attr = _.defaults({}, attr, _.result(this, 'defaults'));\n this._data = {};\n this.set(attr, options);\n this.initialize.apply(this, arguments);\n};\n\n_.extend(BaseModel.prototype, {\n initialize: function (attr, options) {},\n\n set: function (key, val, options) {\n if (key === null) {\n return this;\n }\n\n var attrs;\n if (typeof key === 'object') {\n attrs = key;\n options = val;\n } else {\n (attrs = {})[key] = val;\n }\n\n options = options || {};\n\n _.extend(this._data, attrs);\n\n return this;\n },\n\n get: function (key, options) {\n return this._data[key];\n },\n\n remove: function () {\n if (this.collection) {\n this.collection.remove(this);\n }\n\n return this;\n },\n\n toJSON: function () {\n return this._data;\n },\n\n pick: function (keys) {\n return _.pick(this._data, keys);\n }\n\n});\n\nmodule.exports = BaseModel;\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar env = {\n account: '',\n project: '',\n group: '',\n groupId: '',\n token: '',\n server: {\n host: 'api.forio.com',\n protocol: 'https'\n }\n};\n\nmodule.exports = {\n set: function (options) {\n env = _.merge(env, options);\n },\n\n get: function () {\n return env;\n }\n};\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar classFrom = __webpack_require__(0);\nvar Base = __webpack_require__(2);\nvar serviceLocator = __webpack_require__(1);\n\nmodule.exports = classFrom(Base, {\n defaults: {\n world: '',\n role: '',\n active: true,\n isWorldComplete: true,\n firstName: '',\n lastName: ''\n },\n\n makeActive: function () {\n var memberApi = serviceLocator.memberApi();\n var params = {\n userId: this.get('id'),\n groupId: this.get('groupId')\n };\n\n var original = this.get('active');\n this.set('active', true);\n\n return memberApi.makeUserActive(params).fail(function () {\n // revert the change\n this.set('active', original);\n }.bind(this));\n },\n\n makeInactive: function () {\n var memberApi = serviceLocator.memberApi();\n var params = {\n userId: this.get('id'),\n groupId: this.get('groupId')\n };\n\n var original = this.get('active');\n this.set('active', false);\n\n return memberApi.makeUserInactive(params).fail(function () {\n // revert the change\n this.set('active', original);\n }.bind(this));\n }\n\n});\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar BaseCollection = function (models, options) {\n this._models = [];\n this.options = options;\n this.initialize.apply(this, arguments);\n};\n\n_.extend(BaseCollection.prototype, {\n idAttribute: 'id',\n\n initialize: function (models, options) {},\n\n create: function (attr, options) {\n var m = new this.model(attr, options);\n this.set(m);\n return m;\n },\n\n reset: function (models, options) {\n this._models.length = 0;\n this.set(models);\n },\n\n remove: function (model) {\n _.remove(this._models, function (m) {\n return m === model;\n });\n\n delete model.collection;\n\n return model;\n },\n\n set: function (models) {\n var _this = this;\n\n if (!models) {\n return;\n }\n\n models = [].concat(models);\n\n if (!models.length) {\n return;\n }\n\n models.forEach(function (m) {\n if (!(m instanceof _this.model)) {\n m = new _this.model(m);\n }\n m.collection = _this;\n _this._models.push(m);\n });\n\n this.sort();\n\n return models;\n },\n\n sortFn: function (a, b) {\n return b._data[this.idAttribute] - a._data[this.idAttribute];\n },\n\n sort: function () {\n this._models = this._models.sort(this.sortFn.bind(this));\n\n return this._models;\n },\n\n getById: function (id) {\n var _this2 = this;\n\n return _.find(this._models, function (m) {\n return m.get(_this2.idAttribute) === id;\n });\n },\n\n each: function (cb, ctx) {\n return _.each(this._models, cb, ctx || this);\n },\n\n all: function (cb, ctx) {\n return _.every(this._models, cb, ctx || this);\n },\n\n toJSON: function () {\n return _.invoke(this._models, 'toJSON');\n },\n\n find: function (fn) {\n return _.find(this._models, fn);\n },\n\n filter: function (fn) {\n return _.filter(this._models, fn);\n },\n\n size: function () {\n return this._models.length;\n },\n\n map: function (fn, ctx) {\n return _.map(this._models, function (model) {\n return fn.call(ctx, model.toJSON());\n });\n },\n\n pluck: function (field) {\n return this.map(function (m) {\n return m[field];\n });\n }\n\n});\n\nmodule.exports = BaseCollection;\n\n/***/ }),\n/* 6 */\n/***/ (function(module, exports, __webpack_require__) {\n\n(function () {\n var App = __webpack_require__(7);\n\n window.forio = window.forio || {};\n window.forio.MultiplayerAssignmentComponent = App;\n})();\n\n/***/ }),\n/* 7 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar UsersCollection = __webpack_require__(8);\nvar WorldsCollection = __webpack_require__(9);\nvar ProjectModel = __webpack_require__(11);\nvar AssignemntRow = __webpack_require__(12).default;\nvar env = __webpack_require__(3);\nvar AjaxQueue = __webpack_require__(13);\n\nfunction setEnvironment(options) {\n env.set(_.omit(options, 'el'));\n}\n\nvar Assignment = function (options) {\n setEnvironment(options);\n this.initialize(options);\n};\n\nAssignment.prototype = {\n\n initialize: function (options) {\n this.el = typeof options.el === 'string' ? $(options.el)[0] : options.el;\n this.$el = $(this.el);\n this.$ = _.partialRight($, this.el);\n\n this.users = new UsersCollection();\n this.worlds = new WorldsCollection();\n this.project = new ProjectModel();\n\n _.bindAll(this, ['render', 'renderTable', 'toggleControlls', 'saveEdit', 'selectAll', 'usassignSelected', '_showUpdating', '_hideUpdating', 'autoAssignAll', 'makeUserInactive']);\n\n this.bindEvents();\n },\n\n bindEvents: function () {\n this.$el.on('update', 'tr', this.saveEdit);\n this.$el.on('click', 'input:checkbox:not(#select-all)', this.toggleControlls);\n this.$el.on('click', '#select-all', this.selectAll);\n this.$el.on('click', '.unassign-user', this.usassignSelected);\n this.$el.on('click', '.auto-assign-all', this.autoAssignAll);\n this.$el.on('click', '.make-user-inactive', this.makeUserInactive);\n },\n\n load: function () {\n var join = function () {\n this.worlds.setUsersCollection(this.users);\n this.worlds.joinUsers();\n this.render();\n }.bind(this);\n\n return $.when(this.worlds.fetch(), this.users.fetch(), this.project.fetch()).then(join);\n },\n\n saveEdit: function () {\n this.worlds.fetch().then(function () {\n this.worlds.joinUsers();\n this.render();\n this.updateControls();\n }.bind(this));\n },\n\n autoAssignAll: function () {\n this._showUpdating();\n var maxUsers = +this.$('#max-users').val();\n return this.worlds.autoAssignAll({ maxUsers: maxUsers }).then(this._hideUpdating).fail(this._hideUpdating).then(function () {\n this.worlds.joinUsers();\n this.render();\n }.bind(this));\n },\n\n getSelectedIds: function () {\n return this.$('tbody :checkbox:checked').map(function () {\n return $(this).data('id');\n }).get();\n },\n\n findRowViews: function (ids) {\n var _this = this;\n\n return ids.map(function (id) {\n return _this.rowViews[id];\n });\n },\n\n unassignUsers: function (ids) {\n var _this2 = this;\n\n var dtd = $.Deferred();\n var done = function () {\n dtd.resolve();\n };\n\n // for now we need to sequence the calls to unassign users from worlds\n var queue = new AjaxQueue();\n\n ids.forEach(function (userId) {\n var user = _this2.users.getById(userId);\n user.set('world', '');\n user.set('role', '');\n queue.add(_.partial(_.bind(_this2.worlds.updateUser, _this2.worlds), user));\n });\n\n queue.execute(this).then(done);\n\n return dtd.promise();\n },\n\n usassignSelected: function (e) {\n e.preventDefault();\n\n var ids = this.getSelectedIds();\n\n var done = function () {\n this.worlds.fetch().then(function () {\n this.worlds.joinUsers();\n this._hideUpdating();\n this.render();\n }.bind(this));\n }.bind(this);\n\n this._showUpdating();\n\n return this.unassignUsers(ids).then(done);\n },\n\n makeUserInactive: function (e) {\n e.preventDefault();\n var ids = this.getSelectedIds();\n var done = function () {\n this.toggleControlls();\n }.bind(this);\n\n var makeUsersInactive = function () {\n var rows = this.findRowViews(ids);\n // for now we need to sequence the calls to patch the users\n // since the API can only operate on one call per group at a time\n var queue = new AjaxQueue();\n rows.forEach(function (view) {\n var user = view.model;\n queue.add(function () {\n return view.makeInactive().then(function () {\n user.remove();\n view.remove();\n });\n });\n });\n\n queue.execute(this).then(done);\n }.bind(this);\n\n return this.unassignUsers(ids).then(makeUsersInactive);\n },\n\n render: function () {\n this.$('table tbody').empty();\n this.sortTable();\n this.renderTable();\n this.toggleControlls();\n },\n\n sortTable: function () {\n // get the sort params and sort if necessary\n var params = this.getTableParams();\n\n var mult = params.hasOwnProperty('direction') && params.direction === 'desc' ? -1 : 1;\n var nameDirection = params.hasOwnProperty('sort') && params.sort === 'name' && mult > 0 ? 'desc' : 'asc';\n var userNameDirection = params.hasOwnProperty('sort') && params.sort === 'userName' && mult > 0 ? 'desc' : 'asc';\n this.$('table .header-name a').prop('href', '?sort=name&direction=' + nameDirection);\n this.$('table .header-username a').prop('href', '?sort=userName&direction=' + userNameDirection);\n\n if (params.hasOwnProperty('sort')) {\n this.users.sortFn = function (a, b) {\n var an = a.get(params.sort) || '';\n var bn = b.get(params.sort) || '';\n if (params.sort === 'name') {\n an = a.get('firstName') + a.get('lastName');\n bn = b.get('firstName') + b.get('lastName');\n }\n return mult * an.localeCompare(bn);\n };\n this.users.sort();\n\n var header = params.sort === 'name' ? this.$('table .header-name') : this.$('table .header-username');\n var arrowDir = mult > 0 ? 'caret-up' : 'caret-down';\n var arrow = this.$('');\n header.append(arrow);\n }\n },\n\n getTableParams: function () {\n var query = location.search !== '' ? location.search.substr(1).split('&') : [];\n var params = {};\n for (var i = 0; i < query.length; i++) {\n var q = query[i].split('=');\n params[q[0]] = q[1];\n }\n return params;\n },\n\n renderTable: function () {\n var _this3 = this;\n\n this.rowViews = {};\n var rows = [];\n this.users.each(function (u) {\n var view = new AssignemntRow({ model: u, worlds: _this3.worlds, project: _this3.project });\n _this3.rowViews[u.get('id')] = view;\n rows.push(view.render().el);\n });\n\n this.$('table tbody').append(rows);\n },\n\n updateControls: function () {\n this.updateControlsForSelection();\n this.updateAutoAssignButton();\n this.updateStatus();\n },\n\n updateStatus: function () {\n var incompleteWorlds = this.worlds.getIncompleteWorldsCount();\n var unassignedUsers = this.users.getUnassignedUsersCount();\n var totalWorlds = this.worlds.size();\n\n var usersText = 'All users have been assigned.';\n if (unassignedUsers) {\n usersText = unassignedUsers === 1 ? '1 user needs assignment.' : unassignedUsers + ' users need assignment.';\n }\n var worldsText = 'All worlds are complete.';\n if (!totalWorlds) {\n worldsText = 'No worlds have been created.';\n } else if (incompleteWorlds) {\n worldsText = incompleteWorlds === 1 ? '1 incomplete world needs attention.' : incompleteWorlds + ' incomplete worlds need attention.';\n }\n\n this.$('#users-status .text').text(usersText);\n this.$('#worlds-status .text').text(worldsText);\n\n if (unassignedUsers) {\n this.$('#users-status').addClass('incomplete');\n } else {\n this.$('#users-status').removeClass('incomplete');\n }\n\n if (incompleteWorlds || !totalWorlds) {\n this.$('#worlds-status').addClass('incomplete');\n } else {\n this.$('#worlds-status').removeClass('incomplete');\n }\n\n this.$('.status-widget').addClass('visible');\n },\n\n updateControlsForSelection: function () {\n var numSelected = this.$('tbody :checkbox:checked').length;\n this.$('.component.controls')[numSelected ? 'addClass' : 'removeClass']('visible');\n },\n\n updateAutoAssignButton: function () {\n\n if (this.project.isDynamicAssignment()) {\n var hasRoles = this.project.hasRoles();\n this.$('.table-controls .single').hide();\n this.$('.table-controls .dynamic').show();\n this.$('.table-controls .dynamic-no-roles-text')[hasRoles ? 'hide' : 'show']();\n this.$('.table-controls .no-roles')[hasRoles ? 'hide' : 'show']();\n } else {\n this.$('.table-controls .dynamic').hide();\n this.$('.table-controls .dynamic-no-roles-text').hide();\n this.$('.table-controls .single').show();\n this.$('.table-controls .no-roles').show();\n }\n\n if (this.users.allUsersAssigned()) {\n this.$('.table-controls').removeClass('visible');\n } else {\n this.$('.table-controls').addClass('visible');\n }\n },\n\n selectAll: function (e) {\n this.$('tbody :checkbox').prop('checked', e.target.checked);\n this.updateControls();\n },\n\n toggleControlls: function (e) {\n var total = this.$('tbody :checkbox');\n var checked = this.$('tbody :checkbox:checked');\n\n if (total.length === checked.length) {\n this.$('#select-all').attr('checked', 'checked');\n } else {\n this.$('#select-all').removeAttr('checked');\n }\n\n this.updateControls();\n },\n\n _showUpdating: function () {\n this.$el.css({ opacity: 0.4 });\n },\n\n _hideUpdating: function () {\n this.$el.css({ opacity: 1 });\n }\n\n};\n\nmodule.exports = Assignment;\n\n/***/ }),\n/* 8 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar classFrom = __webpack_require__(0);\n\nvar Model = __webpack_require__(4);\nvar Base = __webpack_require__(5);\nvar env = __webpack_require__(3);\nvar serviceLocator = __webpack_require__(1);\n\nmodule.exports = classFrom(Base, {\n model: Model,\n\n sortFn: function (a, b) {\n var aw = a.get('world').toLowerCase();\n var bw = b.get('world').toLowerCase();\n if (aw !== bw) {\n return aw < bw ? -1 : 1;\n }\n\n return b.get('userName') > a.get('userName') ? -1 : 1;\n },\n\n initialize: function () {\n var am = new F.manager.AuthManager();\n var session = am.getCurrentUserSessionInfo();\n var token = session.auth_token;\n if (token) {\n $.ajaxSetup({\n headers: {\n Authorization: 'Bearer ' + token\n }\n });\n }\n },\n\n allUsersAssigned: function () {\n return this.all(function (u) {\n return !!u.get('world');\n });\n },\n\n getUnassignedUsersCount: function () {\n return this.filter(function (u) {\n return !u.get('world');\n }).length;\n },\n\n fetch: function () {\n var dtd = $.Deferred();\n var me = this;\n var groupId = env.get().groupId;\n\n var getGroupUsers = function () {\n var memberApi = serviceLocator.memberApi();\n var userApi = serviceLocator.userApi();\n\n var loadGroupMembers = function () {\n return memberApi.getGroupDetails();\n };\n\n var splitIdChunks = function (userIds) {\n var idGroupSize = 100;\n var idGroups = [];\n while (userIds.length >= idGroupSize) {\n idGroups.push(userIds.splice(0, idGroupSize));\n }\n\n if (userIds.length) {\n idGroups.push(userIds);\n }\n\n return idGroups;\n };\n\n var loadUsersInfo = function (group) {\n var nonFacAndActive = function (u) {\n return u.active && u.role !== 'facilitator';\n };\n var endUsers = group.members.filter(function (m) {\n return nonFacAndActive(m);\n });\n var endUserIds = endUsers.map(function (u) {\n return u.userId;\n });\n var chunkedUsers = splitIdChunks(endUserIds);\n var chunkedPromises = chunkedUsers.map(function (users) {\n return userApi.get({ id: users });\n });\n return $.when.apply($, chunkedPromises).then(function (userGroups) {\n var totalUsers = userGroups.reduce(function (acc, userGroup) {\n return acc.concat(userGroup);\n }, []);\n\n return totalUsers;\n });\n };\n\n return loadGroupMembers().then(loadUsersInfo).fail(dtd.reject);\n };\n\n getGroupUsers().then(function (users) {\n users = users.map(function (u) {\n return $.extend(u, { groupId: groupId });\n });\n me.set(users);\n dtd.resolve(users);\n });\n\n return dtd.promise();\n }\n\n});\n\n/***/ }),\n/* 9 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar classFrom = __webpack_require__(0);\nvar Model = __webpack_require__(10);\nvar UserModel = __webpack_require__(4);\nvar serviceLocator = __webpack_require__(1);\n\nvar Base = __webpack_require__(5);\nvar __super = Base.prototype;\n\nvar doneFn = function (dtd, after) {\n return _.after(after, dtd.resolve);\n};\n\nvar worldApi;\n\nmodule.exports = classFrom(Base, {\n model: Model,\n\n initialize: function () {\n __super.initialize.apply(this, arguments);\n worldApi = serviceLocator.worldApi();\n },\n\n autoAssignAll: function (options) {\n return worldApi.autoAssign(options).then(function (worlds) {\n this.reset(this.parse(worlds));\n }.bind(this));\n },\n\n getIncompleteWorldsCount: function () {\n return this.filter(function (w) {\n return !w.get('complete');\n }).length;\n },\n\n updateUser: function (user) {\n var worldName = user.get('world');\n var dtd = $.Deferred();\n var prevWorld = this.getWorldByUser(user);\n var curWorld = this.getOrCreateWorld(worldName);\n var done = doneFn(dtd, 1);\n\n // check if there's anything to do\n if (!prevWorld && !curWorld) {\n return dtd.resolve().promise();\n }\n\n if (prevWorld && curWorld && prevWorld.get('id') === curWorld.get('id')) {\n //worlds are the same, but role changed\n return curWorld.updateUser(user);\n }\n if (prevWorld) {\n prevWorld.removeUser(user).then(function () {\n if (curWorld) {\n return curWorld.addUser(user);\n }\n }).then(done);\n } else if (curWorld) {\n curWorld.addUser(user).then(done);\n }\n\n return dtd.promise();\n },\n\n getOrCreateWorld: function (worldName) {\n if (!worldName) {\n return;\n }\n\n var world = this.getWordByName(worldName);\n\n if (!world) {\n world = this.create({ name: worldName });\n }\n\n return world;\n },\n\n getWordByName: function (worldName) {\n return this.find(function (world) {\n return world.get('name') === worldName;\n });\n },\n\n getWorldByUser: function (user) {\n if (!user.get) {\n throw new Error('getWorldByUser expectes a model (' + user + ')');\n }\n\n var id = user.get('id');\n return this.getWorldByUserId(id);\n },\n\n getWorldByUserId: function (userId) {\n return this.find(function (world) {\n return _.find(world.get('users'), function (u) {\n return u.get('id') === userId;\n });\n });\n },\n\n getWorldNames: function () {\n return this.pluck('name').sort();\n },\n\n getNextWorldName: function () {\n var pad = function (num, places) {\n var zeros = '000000000000000000';\n var digits = num.toString().length;\n var needed = places - digits;\n return zeros.substr(0, needed) + num;\n };\n\n var worlds = this.getWorldNames();\n\n if (!worlds.length) {\n return 'World001';\n }\n\n var properNames = _.filter(worlds, function (w) {\n return (/World\\d\\d\\d/.test(w)\n );\n }).sort();\n var lastWorld = properNames[properNames.length - 1];\n var numWorld = +lastWorld.match(/World(\\d\\d\\d)/)[1];\n var placesToPad = 3;\n return 'World' + pad(numWorld + 1, placesToPad);\n },\n\n setUsersCollection: function (usersCollection) {\n this.usersCollection = usersCollection;\n },\n\n joinUsers: function () {\n var usersHash = {};\n var usersCollection = this.usersCollection;\n usersCollection.each(function (u) {\n u.set({ isWorldComplete: true });\n return usersHash[u.get('id')] = u;\n });\n\n this.each(function (w, i) {\n var name = w.get('name');\n var isComplete = w.get('complete');\n w.set({ index: i, name: name || i + 1 + '' });\n _.each(w.get('users'), function (u) {\n if (usersHash[u.get('userId')]) {\n usersHash[u.get('userId')].set({ world: name, role: u.get('role'), isWorldComplete: isComplete });\n }\n });\n });\n\n usersCollection.sort();\n },\n\n fetch: function () {\n return worldApi.list().then(function (worlds) {\n this.reset(this.parse(worlds));\n }.bind(this));\n },\n\n parse: function (worlds) {\n if (worlds.length) {\n worlds = _.map(worlds, function (w) {\n var users = _.map(w.users, function (u) {\n // in the world api users Ids comes as userId\n // make sure we add it as id so we can use the\n // same code to access models that come from the\n // member/local api as with the world api\n u.id = u.userId;\n return new UserModel(u);\n });\n\n w.users = users;\n\n return w;\n });\n }\n\n return worlds;\n }\n});\n\n/***/ }),\n/* 10 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar serviceLocator = __webpack_require__(1);\nvar classFrom = __webpack_require__(0);\nvar Base = __webpack_require__(2);\nvar __super = Base.prototype;\n\nmodule.exports = classFrom(Base, {\n\n defaults: {\n users: null,\n model: 'model.eqn'\n },\n\n initialize: function () {\n __super.initialize.apply(this, arguments);\n\n this._data.users = this._data.users || [];\n\n this._worldApi = serviceLocator.worldApi();\n\n var id = this.get('id');\n if (id) {\n this._worldApi.updateConfig({ filter: id });\n }\n },\n\n updateUser: function (user) {\n if (!user) {\n throw new Error('updateUser: No user passed to update');\n }\n var userObj = user.toJSON();\n userObj.userId = userObj.id;\n return this._worldApi.updateUser(userObj, { id: this.get('id') });\n },\n\n addUser: function (user) {\n var users = this.get('users');\n users.push(user);\n\n return this.save();\n },\n\n removeUser: function (user) {\n var id = this.get('id');\n var checkWorld = function () {\n if (!this.get('users').length) {\n this.remove();\n return this._worldApi.updateConfig({ filter: id }).delete();\n }\n }.bind(this);\n\n _.remove(this.get('users'), function (u) {\n return u.get('id') === user.get('id');\n });\n\n return this._worldApi.updateConfig({ filter: id }).removeUser({ userId: user.get('id') }).then(checkWorld);\n },\n\n save: function () {\n var me = this;\n var mapUsers = function () {\n return _.map(this.get('users'), function (u) {\n var res = { userId: u.get('id') };\n var role = u.get('role');\n\n if (role) {\n res.role = role;\n }\n\n return res;\n });\n }.bind(this);\n\n var createWorld = _.partial(this._worldApi.create, this.pick(['model', 'name', 'minUsers']));\n var addUsers = _.partial(me._worldApi.addUsers, mapUsers(), { filter: me.get('id') });\n var savedUsers = this.get('users');\n if (this.isNew()) {\n // we need to create the world in the API and then add the users\n return createWorld().then(function (world) {\n me.set(world);\n me._worldApi.updateConfig({ filter: world.id });\n }).then(addUsers).then(function (users) {\n // since we re-set the world, re-set the users\n me.set('users', savedUsers);\n });\n } else {\n // the world is already created just add the users\n return addUsers();\n }\n },\n\n isNew: function () {\n return !this.get('lastModified');\n }\n\n});\n\n/***/ }),\n/* 11 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar serviceLocator = __webpack_require__(1);\n\nvar classFrom = __webpack_require__(0);\nvar Base = __webpack_require__(2);\n// var __super = Base.prototype;\n\nmodule.exports = classFrom(Base, {\n\n isDynamicAssignment: function () {\n return this.get('worlds') === 'dynamic';\n },\n\n hasRoles: function () {\n var roles = this.get('roles');\n return roles && !!roles.length;\n },\n\n fetch: function () {\n var api = serviceLocator.worldApi();\n\n return api.getProjectSettings().then(function (settings) {\n this.set(settings);\n }.bind(this));\n }\n});\n\n/***/ }),\n/* 12 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\nvar userRowTemplate = '\\n
\" | \\n <%= !isWorldComplete ? \\'\\' : \\'\\' %> | \\n <%= world %> | \\n <%= role %> | \\n <%= lastName %> | \\n <%= userName %> | \\n <%= !world ? \\'\\' : \\'\\' %> | \\n | \\n'.trim();\nvar editUserRowTemplate = '\\n \" | \\n | \\n \\n \\n | \\n \\n \\n | \\n <%= lastName %> | \\n <%= userName %> | \\n <%= !world ? \\'\\' : \\'\\' %> | \\n \\n \\n \\n | \\n';\n\nvar AssignmentRow = function (options) {\n this.$el = $('');\n this.el = this.$el[0];\n this.$ = _.partialRight($, this.$el);\n\n this.model = options.model;\n this.options = options;\n this.worlds = options.worlds;\n this.project = options.project;\n\n _.bindAll(this, ['setEditMode', 'removeEditMode', 'saveEdit', 'cancelEdit', 'updateData']);\n\n this.bindEvents();\n};\n\n_.extend(AssignmentRow.prototype, {\n\n template: _.template(userRowTemplate),\n editTemplate: _.template(editUserRowTemplate),\n\n bindEvents: function () {\n this.$el.on('click', 'button.edit', this.setEditMode);\n this.$el.on('click', 'button.save', this.saveEdit);\n this.$el.on('click', 'button.cancel', this.cancelEdit);\n },\n\n remove: function () {\n this.$el.off('click', null, null);\n // this only gives a delay to remove the tr\n // animation of height of the tr does not work\n this.$(':checkbox').attr('checked', false);\n this.$el.css({ opacity: 0.3 }).animate({ height: 0 }, {\n duration: 300,\n complete: function () {\n this.remove();\n }\n });\n },\n\n makeInactive: function () {\n return this.model.makeInactive();\n },\n\n setEditMode: function () {\n this.model.set('edit-mode', true);\n this.render();\n },\n\n removeEditMode: function () {\n this.model.set('edit-mode', false);\n this.render();\n },\n\n saveEdit: function () {\n var me = this;\n this.updateData();\n this.worlds.updateUser(this.model).then(function () {\n me.removeEditMode();\n me.$el.trigger('update', me);\n });\n },\n\n cancelEdit: function () {\n this.removeEditMode();\n },\n\n render: function () {\n var templ = this.model.get('edit-mode') ? this.editTemplate : this.template;\n var vm = _.extend({\n roles: this.project.get('roles'),\n optionalRoles: this.project.get('optionalRoles'),\n worlds: this.worlds.getWorldNames(),\n newWorld: this.worlds.getNextWorldName()\n }, this.model.toJSON());\n\n this.$el.html(templ(vm));\n\n return this;\n },\n\n updateData: function () {\n var me = this;\n this.$('[data-field]').each(function () {\n var el = $(this);\n var field = el.data('field');\n var val = el.val();\n\n me.model.set(field, val);\n });\n }\n});\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (AssignmentRow);\n\n/***/ }),\n/* 13 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n/**\n* Utility class to make ajax calls sequencial\n*/\n\nfunction AjaxQueue() {\n this.queue = [];\n}\n\n$.extend(AjaxQueue.prototype, {\n add: function (fn) {\n return this.queue.push(fn);\n },\n\n execute: function (context) {\n var dtd = $.Deferred();\n var me = this;\n context = context || this;\n\n function next() {\n if (me.queue.length) {\n var fn = me.queue.shift();\n\n fn.call(context).then(next).fail(dtd.reject);\n } else {\n dtd.resolve();\n }\n }\n\n next();\n\n return dtd.promise();\n }\n});\n\nmodule.exports = AjaxQueue;\n\n/***/ })\n/******/ ]);\n\n\n// WEBPACK FOOTER //\n// assignment.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 6);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 5b36529e33521661d9bd","/**\n/* Inherit from a class (using prototype borrowing)\n*/\n'use strict';\n\nfunction inherit(C, P) {\n var F = function () {};\n F.prototype = P.prototype;\n C.prototype = new F();\n C.__super = P.prototype;\n C.prototype.constructor = C;\n}\n\n/**\n* Shallow copy of an object\n* @param {Object} dest object to extend\n* @return {Object} extended object\n*/\nvar extend = function (dest /*, var_args*/) {\n var obj = Array.prototype.slice.call(arguments, 1);\n var current;\n for (var j = 0; j < obj.length; j++) {\n if (!(current = obj[j])) { //eslint-disable-line\n continue;\n }\n\n // do not wrap inner in dest.hasOwnProperty or bad things will happen\n for (var key in current) { //eslint-disable-line\n dest[key] = current[key];\n }\n }\n\n return dest;\n};\n\nmodule.exports = function (base, props, staticProps) {\n var parent = base;\n var child;\n\n child = props && props.hasOwnProperty('constructor') ? props.constructor : function () { return parent.apply(this, arguments); };\n\n // add static properties to the child constructor function\n extend(child, parent, staticProps);\n\n // associate prototype chain\n inherit(child, parent);\n\n // add instance properties\n if (props) {\n extend(child.prototype, props);\n }\n\n // done\n return child;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./src/util/inherit.js","'use strict';\n\nvar env = require('./defaults.js');\n\nvar cache = {};\n\nmodule.exports = {\n worldApi: function () {\n if (!cache.worldApi) {\n cache.worldApi = new F.service.World(env.get());\n }\n return cache.worldApi;\n },\n\n memberApi: function () {\n if (!cache.memberApi) {\n cache.memberApi = new F.service.Member(_.pick(env.get(), ['groupId', 'server']));\n }\n\n return cache.memberApi;\n },\n\n userApi: function () {\n if (!cache.userApi) {\n cache.userApi = new F.service.User(_.pick(env.get(), ['account', 'server']));\n }\n\n return cache.userApi;\n }\n};\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/service-locator.js","'use strict';\n\n\nvar BaseModel = function (attr, options) {\n attr = _.defaults({}, attr, _.result(this, 'defaults'));\n this._data = {};\n this.set(attr, options);\n this.initialize.apply(this, arguments);\n};\n\n_.extend(BaseModel.prototype, {\n initialize: function (attr, options) {\n\n },\n\n set: function (key, val, options) {\n if (key === null) {\n return this;\n }\n\n var attrs;\n if (typeof key === 'object') {\n attrs = key;\n options = val;\n } else {\n (attrs = {})[key] = val;\n }\n\n options = options || {};\n\n _.extend(this._data, attrs);\n\n return this;\n },\n\n get: function (key, options) {\n return this._data[key];\n },\n\n remove: function () {\n if (this.collection) {\n this.collection.remove(this);\n }\n\n return this;\n },\n\n toJSON: function () {\n return this._data;\n },\n\n pick: function (keys) {\n return _.pick(this._data, keys);\n }\n\n});\n\nmodule.exports = BaseModel;\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/base-model.js","'use strict';\n\nvar env = {\n account: '',\n project: '',\n group: '',\n groupId: '',\n token: '',\n server: {\n host: 'api.forio.com',\n protocol: 'https'\n }\n};\n\nmodule.exports = {\n set: function (options) {\n env = _.merge(env, options);\n },\n\n get: function () {\n return env;\n }\n};\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/defaults.js","'use strict';\n\nvar classFrom = require('../../../util/inherit');\nvar Base = require('./base-model');\nvar serviceLocator = require('./service-locator');\n\n\nmodule.exports = classFrom(Base, {\n defaults: {\n world: '',\n role: '',\n active: true,\n isWorldComplete: true,\n firstName: '',\n lastName: ''\n },\n\n makeActive: function () {\n var memberApi = serviceLocator.memberApi();\n var params = {\n userId: this.get('id'),\n groupId: this.get('groupId')\n };\n\n var original = this.get('active');\n this.set('active', true);\n\n return memberApi.makeUserActive(params)\n .fail(function () {\n // revert the change\n this.set('active', original);\n }.bind(this));\n },\n\n makeInactive: function () {\n var memberApi = serviceLocator.memberApi();\n var params = {\n userId: this.get('id'),\n groupId: this.get('groupId')\n };\n\n var original = this.get('active');\n this.set('active', false);\n\n return memberApi.makeUserInactive(params)\n .fail(function () {\n // revert the change\n this.set('active', original);\n }.bind(this));\n }\n\n});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/user-model.js","'use strict';\n\nvar BaseCollection = function (models, options) {\n this._models = [];\n this.options = options;\n this.initialize.apply(this, arguments);\n};\n\n_.extend(BaseCollection.prototype, {\n idAttribute: 'id',\n\n initialize: function (models, options) {\n },\n\n create: function (attr, options) {\n var m = new this.model(attr, options);\n this.set(m);\n return m;\n },\n\n reset: function (models, options) {\n this._models.length = 0;\n this.set(models);\n },\n\n remove: function (model) {\n _.remove(this._models, function (m) {\n return m === model;\n });\n\n delete model.collection;\n\n return model;\n },\n\n set: function (models) {\n if (!models) {\n return;\n }\n\n models = [].concat(models);\n\n if (!models.length) {\n return;\n }\n\n models.forEach((m)=> {\n if (!(m instanceof this.model)) {\n m = new this.model(m);\n }\n m.collection = this;\n this._models.push(m);\n });\n\n this.sort();\n\n return models;\n },\n\n sortFn: function (a, b) {\n return b._data[this.idAttribute] - a._data[this.idAttribute];\n },\n\n sort: function () {\n this._models = this._models.sort(this.sortFn.bind(this));\n\n return this._models;\n },\n\n getById: function (id) {\n return _.find(this._models, (m)=> {\n return m.get(this.idAttribute) === id;\n });\n },\n\n each: function (cb, ctx) {\n return _.each(this._models, cb, ctx || this);\n },\n\n all: function (cb, ctx) {\n return _.every(this._models, cb, ctx || this);\n },\n\n toJSON: function () {\n return _.invoke(this._models, 'toJSON');\n },\n\n find: function (fn) {\n return _.find(this._models, fn);\n },\n\n filter: function (fn) {\n return _.filter(this._models, fn);\n },\n\n size: function () {\n return this._models.length;\n },\n\n map: function (fn, ctx) {\n return _.map(this._models, function (model) {\n return fn.call(ctx, model.toJSON());\n });\n },\n\n pluck: function (field) {\n return this.map(function (m) {\n return m[field];\n });\n }\n\n});\n\nmodule.exports = BaseCollection;\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/base-collection.js","(function () {\n var App = require('./assignment.js');\n\n window.forio = window.forio || {};\n window.forio.MultiplayerAssignmentComponent = App;\n}());\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/index.js","'use strict';\n\nvar UsersCollection = require('./users-collection');\nvar WorldsCollection = require('./worlds-collection');\nvar ProjectModel = require('./project-model');\nvar AssignemntRow = require('./assignment-row').default;\nvar env = require('./defaults');\nvar AjaxQueue = require('../../../util/ajax-queue');\n\nfunction setEnvironment(options) {\n env.set(_.omit(options, 'el'));\n}\n\nvar Assignment = function (options) {\n setEnvironment(options);\n this.initialize(options);\n};\n\nAssignment.prototype = {\n\n initialize: function (options) {\n this.el = typeof options.el === 'string' ? $(options.el)[0] : options.el;\n this.$el = $(this.el);\n this.$ = _.partialRight($, this.el);\n\n this.users = new UsersCollection();\n this.worlds = new WorldsCollection();\n this.project = new ProjectModel();\n\n _.bindAll(this, ['render', 'renderTable', 'toggleControlls', 'saveEdit', 'selectAll', 'usassignSelected', '_showUpdating', '_hideUpdating', 'autoAssignAll', 'makeUserInactive']);\n\n this.bindEvents();\n },\n\n bindEvents: function () {\n this.$el.on('update', 'tr', this.saveEdit);\n this.$el.on('click', 'input:checkbox:not(#select-all)', this.toggleControlls);\n this.$el.on('click', '#select-all', this.selectAll);\n this.$el.on('click', '.unassign-user', this.usassignSelected);\n this.$el.on('click', '.auto-assign-all', this.autoAssignAll);\n this.$el.on('click', '.make-user-inactive', this.makeUserInactive);\n },\n\n load: function () {\n var join = function () {\n this.worlds.setUsersCollection(this.users);\n this.worlds.joinUsers();\n this.render();\n }.bind(this);\n\n return $.when(\n this.worlds.fetch(),\n this.users.fetch(),\n this.project.fetch()\n ).then(join);\n },\n\n saveEdit: function () {\n this.worlds.fetch()\n .then(function () {\n this.worlds.joinUsers();\n this.render();\n this.updateControls();\n }.bind(this));\n },\n\n autoAssignAll: function () {\n this._showUpdating();\n var maxUsers = +this.$('#max-users').val();\n return this.worlds.autoAssignAll({ maxUsers: maxUsers })\n .then(this._hideUpdating)\n .fail(this._hideUpdating)\n .then(function () {\n this.worlds.joinUsers();\n this.render();\n }.bind(this));\n },\n\n getSelectedIds: function () {\n return this.$('tbody :checkbox:checked').map(function () {\n return $(this).data('id');\n }).get();\n },\n\n findRowViews: function (ids) {\n return ids.map((id)=> {\n return this.rowViews[id];\n });\n },\n\n unassignUsers: function (ids) {\n var dtd = $.Deferred();\n var done = function () {\n dtd.resolve();\n };\n\n // for now we need to sequence the calls to unassign users from worlds\n var queue = new AjaxQueue();\n\n ids.forEach((userId)=> {\n var user = this.users.getById(userId);\n user.set('world', '');\n user.set('role', '');\n queue.add(_.partial(_.bind(this.worlds.updateUser, this.worlds), user));\n });\n\n queue.execute(this).then(done);\n\n return dtd.promise();\n },\n\n usassignSelected: function (e) {\n e.preventDefault();\n\n var ids = this.getSelectedIds();\n\n var done = function () {\n this.worlds.fetch().then(function () {\n this.worlds.joinUsers();\n this._hideUpdating();\n this.render();\n\n }.bind(this));\n }.bind(this);\n\n this._showUpdating();\n\n return this.unassignUsers(ids).then(done);\n },\n\n makeUserInactive: function (e) {\n e.preventDefault();\n var ids = this.getSelectedIds();\n var done = function () {\n this.toggleControlls();\n }.bind(this);\n\n var makeUsersInactive = function () {\n var rows = this.findRowViews(ids);\n // for now we need to sequence the calls to patch the users\n // since the API can only operate on one call per group at a time\n var queue = new AjaxQueue();\n rows.forEach((view)=> {\n var user = view.model;\n queue.add(function () {\n return view.makeInactive()\n .then(function () {\n user.remove();\n view.remove();\n });\n });\n\n });\n\n queue.execute(this).then(done);\n }.bind(this);\n\n return this.unassignUsers(ids)\n .then(makeUsersInactive);\n\n\n },\n\n render: function () {\n this.$('table tbody').empty();\n this.sortTable();\n this.renderTable();\n this.toggleControlls();\n },\n\n sortTable: function () {\n // get the sort params and sort if necessary\n var params = this.getTableParams();\n\n var mult = params.hasOwnProperty('direction') && params.direction === 'desc' ? -1 : 1;\n var nameDirection = params.hasOwnProperty('sort') && params.sort === 'name' && mult > 0 ? 'desc' : 'asc';\n var userNameDirection = params.hasOwnProperty('sort') && params.sort === 'userName' && mult > 0 ? 'desc' : 'asc';\n this.$('table .header-name a').prop('href', '?sort=name&direction=' + nameDirection);\n this.$('table .header-username a').prop('href', '?sort=userName&direction=' + userNameDirection);\n\n if (params.hasOwnProperty('sort')) {\n this.users.sortFn = function (a, b) {\n var an = (a.get(params.sort) || '');\n var bn = (b.get(params.sort) || '');\n if (params.sort === 'name') {\n an = (a.get('firstName') + a.get('lastName'));\n bn = (b.get('firstName') + b.get('lastName'));\n }\n return mult * an.localeCompare(bn);\n };\n this.users.sort();\n\n var header = params.sort === 'name' ? this.$('table .header-name') : this.$('table .header-username');\n var arrowDir = mult > 0 ? 'caret-up' : 'caret-down';\n var arrow = this.$('');\n header.append(arrow);\n }\n },\n\n getTableParams: function () {\n var query = location.search !== '' ? location.search.substr(1).split('&') : [];\n var params = {};\n for (var i = 0; i < query.length; i++) {\n var q = query[i].split('=');\n params[q[0]] = q[1];\n }\n return params;\n },\n\n renderTable: function () {\n this.rowViews = {};\n var rows = [];\n this.users.each((u)=> {\n var view = new AssignemntRow({ model: u, worlds: this.worlds, project: this.project });\n this.rowViews[u.get('id')] = view;\n rows.push(view.render().el);\n });\n\n this.$('table tbody').append(rows);\n },\n\n\n updateControls: function () {\n this.updateControlsForSelection();\n this.updateAutoAssignButton();\n this.updateStatus();\n },\n\n updateStatus: function () {\n var incompleteWorlds = this.worlds.getIncompleteWorldsCount();\n var unassignedUsers = this.users.getUnassignedUsersCount();\n var totalWorlds = this.worlds.size();\n\n var usersText = 'All users have been assigned.';\n if (unassignedUsers) {\n usersText = unassignedUsers === 1 ? '1 user needs assignment.' : unassignedUsers + ' users need assignment.';\n }\n var worldsText = 'All worlds are complete.';\n if (!totalWorlds) {\n worldsText = 'No worlds have been created.';\n } else if (incompleteWorlds) {\n worldsText = incompleteWorlds === 1 ? '1 incomplete world needs attention.' : incompleteWorlds + ' incomplete worlds need attention.';\n }\n\n this.$('#users-status .text').text(usersText);\n this.$('#worlds-status .text').text(worldsText);\n\n if (unassignedUsers) {\n this.$('#users-status').addClass('incomplete');\n } else {\n this.$('#users-status').removeClass('incomplete');\n }\n\n if (incompleteWorlds || !totalWorlds) {\n this.$('#worlds-status').addClass('incomplete');\n } else {\n this.$('#worlds-status').removeClass('incomplete');\n }\n\n this.$('.status-widget').addClass('visible');\n },\n\n updateControlsForSelection: function () {\n var numSelected = this.$('tbody :checkbox:checked').length;\n this.$('.component.controls')[numSelected ? 'addClass' : 'removeClass']('visible');\n },\n\n updateAutoAssignButton: function () {\n\n if (this.project.isDynamicAssignment()) {\n var hasRoles = this.project.hasRoles();\n this.$('.table-controls .single').hide();\n this.$('.table-controls .dynamic').show();\n this.$('.table-controls .dynamic-no-roles-text')[hasRoles ? 'hide' : 'show']();\n this.$('.table-controls .no-roles')[hasRoles ? 'hide' : 'show']();\n } else {\n this.$('.table-controls .dynamic').hide();\n this.$('.table-controls .dynamic-no-roles-text').hide();\n this.$('.table-controls .single').show();\n this.$('.table-controls .no-roles').show();\n\n }\n\n if (this.users.allUsersAssigned()) {\n this.$('.table-controls').removeClass('visible');\n } else {\n this.$('.table-controls').addClass('visible');\n }\n },\n\n selectAll: function (e) {\n this.$('tbody :checkbox').prop('checked', e.target.checked);\n this.updateControls();\n },\n\n toggleControlls: function (e) {\n var total = this.$('tbody :checkbox');\n var checked = this.$('tbody :checkbox:checked');\n\n if (total.length === checked.length) {\n this.$('#select-all').attr('checked', 'checked');\n } else {\n this.$('#select-all').removeAttr('checked');\n }\n\n this.updateControls();\n },\n\n _showUpdating: function () {\n this.$el.css({ opacity: 0.4 });\n },\n\n _hideUpdating: function () {\n this.$el.css({ opacity: 1 });\n }\n\n};\n\nmodule.exports = Assignment;\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/assignment.js","'use strict';\n\nvar classFrom = require('../../../util/inherit');\n\nvar Model = require('./user-model');\nvar Base = require('./base-collection');\nvar env = require('./defaults');\nvar serviceLocator = require('./service-locator');\n\n\nmodule.exports = classFrom(Base, {\n model: Model,\n\n sortFn: function (a, b) {\n var aw = a.get('world').toLowerCase();\n var bw = b.get('world').toLowerCase();\n if (aw !== bw) {\n return aw < bw ? -1 : 1;\n }\n\n return b.get('userName') > a.get('userName') ? -1 : 1;\n },\n\n initialize: function () {\n const am = new F.manager.AuthManager();\n const session = am.getCurrentUserSessionInfo();\n const token = session.auth_token;\n if (token) {\n $.ajaxSetup({\n headers: {\n Authorization: 'Bearer ' + token\n }\n });\n }\n },\n\n allUsersAssigned: function () {\n return this.all(function (u) {\n return !!u.get('world');\n });\n },\n\n getUnassignedUsersCount: function () {\n return this.filter(function (u) {\n return !u.get('world');\n }).length;\n },\n\n fetch: function () {\n var dtd = $.Deferred();\n var me = this;\n var groupId = env.get().groupId;\n\n var getGroupUsers = function () {\n var memberApi = serviceLocator.memberApi();\n var userApi = serviceLocator.userApi();\n\n var loadGroupMembers = function () {\n return memberApi.getGroupDetails();\n };\n\n var splitIdChunks = function (userIds) {\n var idGroupSize = 100;\n var idGroups = [];\n while (userIds.length >= idGroupSize) {\n idGroups.push(userIds.splice(0, idGroupSize));\n }\n\n if (userIds.length) {\n idGroups.push(userIds);\n }\n\n return idGroups;\n };\n\n var loadUsersInfo = function (group) {\n var nonFacAndActive = function (u) { return u.active && u.role !== 'facilitator'; };\n const endUsers = group.members.filter((m)=> nonFacAndActive(m));\n const endUserIds = endUsers.map((u)=> u.userId);\n var chunkedUsers = splitIdChunks(endUserIds);\n var chunkedPromises = chunkedUsers.map(function (users) {\n return userApi.get({ id: users });\n });\n return $.when.apply($, chunkedPromises).then(function (userGroups) {\n var totalUsers = userGroups.reduce(function (acc, userGroup) {\n return acc.concat(userGroup);\n }, []);\n\n return totalUsers;\n });\n };\n\n return loadGroupMembers()\n .then(loadUsersInfo)\n .fail(dtd.reject);\n };\n\n getGroupUsers()\n .then(function (users) {\n users = users.map(function (u) { return $.extend(u, { groupId: groupId }); });\n me.set(users);\n dtd.resolve(users);\n });\n\n return dtd.promise();\n }\n\n});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/users-collection.js","'use strict';\n\nvar classFrom = require('../../../util/inherit');\nvar Model = require('./world-model');\nvar UserModel = require('./user-model');\nvar serviceLocator = require('./service-locator');\n\nvar Base = require('./base-collection');\nvar __super = Base.prototype;\n\nvar doneFn = function (dtd, after) {\n return _.after(after, dtd.resolve);\n};\n\nvar worldApi;\n\nmodule.exports = classFrom(Base, {\n model: Model,\n\n initialize: function () {\n __super.initialize.apply(this, arguments);\n worldApi = serviceLocator.worldApi();\n },\n\n autoAssignAll: function (options) {\n return worldApi.autoAssign(options)\n .then(function (worlds) {\n this.reset(this.parse(worlds));\n }.bind(this));\n },\n\n getIncompleteWorldsCount: function () {\n return this.filter(function (w) {\n return !w.get('complete');\n }).length;\n },\n\n updateUser: function (user) {\n var worldName = user.get('world');\n var dtd = $.Deferred();\n var prevWorld = this.getWorldByUser(user);\n var curWorld = this.getOrCreateWorld(worldName);\n var done = doneFn(dtd, 1);\n\n // check if there's anything to do\n if (!prevWorld && !curWorld) {\n return dtd.resolve().promise();\n }\n\n if (prevWorld && curWorld && prevWorld.get('id') === curWorld.get('id')) {\n //worlds are the same, but role changed\n return curWorld.updateUser(user);\n }\n if (prevWorld) {\n prevWorld.removeUser(user)\n .then(function () {\n if (curWorld) {\n return curWorld.addUser(user);\n }\n })\n .then(done);\n } else if (curWorld) {\n curWorld.addUser(user)\n .then(done);\n }\n\n return dtd.promise();\n },\n\n getOrCreateWorld: function (worldName) {\n if (!worldName) {\n return;\n }\n\n var world = this.getWordByName(worldName);\n\n if (!world) {\n world = this.create({ name: worldName });\n }\n\n return world;\n },\n\n getWordByName: function (worldName) {\n return this.find(function (world) {\n return world.get('name') === worldName;\n });\n },\n\n getWorldByUser: function (user) {\n if (!user.get) {\n throw new Error('getWorldByUser expectes a model (' + user + ')');\n }\n\n var id = user.get('id');\n return this.getWorldByUserId(id);\n },\n\n getWorldByUserId: function (userId) {\n return this.find(function (world) {\n return _.find(world.get('users'), function (u) {\n return u.get('id') === userId;\n });\n });\n },\n\n getWorldNames: function () {\n return this.pluck('name').sort();\n },\n\n getNextWorldName: function () {\n var pad = function (num, places) {\n var zeros = '000000000000000000';\n var digits = num.toString().length;\n var needed = places - digits;\n return zeros.substr(0, needed) + num;\n };\n\n var worlds = this.getWorldNames();\n\n if (!worlds.length) {\n return 'World001';\n }\n\n var properNames = _.filter(worlds, function (w) { return (/World\\d\\d\\d/).test(w); }).sort();\n var lastWorld = properNames[properNames.length - 1];\n var numWorld = +lastWorld.match(/World(\\d\\d\\d)/)[1];\n var placesToPad = 3;\n return 'World' + pad(numWorld + 1, placesToPad);\n },\n\n setUsersCollection: function (usersCollection) {\n this.usersCollection = usersCollection;\n },\n\n joinUsers: function () {\n var usersHash = {};\n var usersCollection = this.usersCollection;\n usersCollection.each(function (u) {\n u.set({ isWorldComplete: true });\n return (usersHash[u.get('id')] = u);\n });\n\n this.each((w, i)=> {\n var name = w.get('name');\n var isComplete = w.get('complete');\n w.set({ index: i, name: name || (i + 1) + '' });\n _.each(w.get('users'), function (u) {\n if (usersHash[u.get('userId')]) {\n usersHash[u.get('userId')].set({ world: name, role: u.get('role'), isWorldComplete: isComplete });\n }\n });\n });\n\n usersCollection.sort();\n },\n\n fetch: function () {\n return worldApi.list()\n .then(function (worlds) {\n this.reset(this.parse(worlds));\n }.bind(this));\n },\n\n parse: function (worlds) {\n if (worlds.length) {\n worlds = _.map(worlds, function (w) {\n var users = _.map(w.users, function (u) {\n // in the world api users Ids comes as userId\n // make sure we add it as id so we can use the\n // same code to access models that come from the\n // member/local api as with the world api\n u.id = u.userId;\n return new UserModel(u);\n });\n\n w.users = users;\n\n return w;\n });\n }\n\n return worlds;\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/worlds-collection.js","'use strict';\nvar serviceLocator = require('./service-locator');\nvar classFrom = require('../../../util/inherit');\nvar Base = require('./base-model');\nvar __super = Base.prototype;\n\nmodule.exports = classFrom(Base, {\n\n defaults: {\n users: null,\n model: 'model.eqn'\n },\n\n initialize: function () {\n __super.initialize.apply(this, arguments);\n\n this._data.users = this._data.users || [];\n\n this._worldApi = serviceLocator.worldApi();\n\n var id = this.get('id');\n if (id) {\n this._worldApi.updateConfig({ filter: id });\n }\n },\n\n updateUser: function (user) {\n if (!user) {\n throw new Error('updateUser: No user passed to update');\n }\n const userObj = user.toJSON();\n userObj.userId = userObj.id;\n return this._worldApi.updateUser(userObj, { id: this.get('id') });\n },\n\n addUser: function (user) {\n var users = this.get('users');\n users.push(user);\n\n return this.save();\n },\n\n removeUser: function (user) {\n var id = this.get('id');\n var checkWorld = function () {\n if (!this.get('users').length) {\n this.remove();\n return this._worldApi.updateConfig({ filter: id }).delete();\n }\n }.bind(this);\n\n _.remove(this.get('users'), function (u) {\n return u.get('id') === user.get('id');\n });\n\n return this._worldApi\n .updateConfig({ filter: id })\n .removeUser({ userId: user.get('id') })\n .then(checkWorld);\n },\n\n save: function () {\n var me = this;\n var mapUsers = function () {\n return _.map(this.get('users'), function (u) {\n var res = { userId: u.get('id') };\n var role = u.get('role');\n\n if (role) {\n res.role = role;\n }\n\n return res;\n });\n }.bind(this);\n\n var createWorld = _.partial(this._worldApi.create, this.pick(['model', 'name', 'minUsers']));\n var addUsers = _.partial(me._worldApi.addUsers, mapUsers(), { filter: me.get('id') });\n var savedUsers = this.get('users');\n if (this.isNew()) {\n // we need to create the world in the API and then add the users\n return createWorld()\n .then(function (world) {\n me.set(world);\n me._worldApi.updateConfig({ filter: world.id });\n })\n .then(addUsers)\n .then(function (users) {\n // since we re-set the world, re-set the users\n me.set('users', savedUsers);\n });\n } else {\n // the world is already created just add the users\n return addUsers();\n }\n },\n\n isNew: function () {\n return !this.get('lastModified');\n }\n\n});\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/world-model.js","'use strict';\n\nvar serviceLocator = require('./service-locator');\n\nvar classFrom = require('../../../util/inherit');\nvar Base = require('./base-model');\n// var __super = Base.prototype;\n\nmodule.exports = classFrom(Base, {\n\n isDynamicAssignment: function () {\n return this.get('worlds') === 'dynamic';\n },\n\n hasRoles: function () {\n var roles = this.get('roles');\n return roles && !!roles.length;\n },\n\n fetch: function () {\n var api = serviceLocator.worldApi();\n\n return api.getProjectSettings().then(function (settings) {\n this.set(settings);\n }.bind(this));\n }\n});\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/project-model.js","const userRowTemplate = `\n \" | \n <%= !isWorldComplete ? '' : '' %> | \n <%= world %> | \n <%= role %> | \n <%= lastName %> | \n <%= userName %> | \n <%= !world ? '' : '' %> | \n | \n`.trim();\nconst editUserRowTemplate = `\n \" | \n | \n \n \n | \n \n \n | \n <%= lastName %> | \n <%= userName %> | \n <%= !world ? '' : '' %> | \n \n \n \n | \n`;\n\nvar AssignmentRow = function (options) {\n this.$el = $('
');\n this.el = this.$el[0];\n this.$ = _.partialRight($, this.$el);\n\n this.model = options.model;\n this.options = options;\n this.worlds = options.worlds;\n this.project = options.project;\n\n _.bindAll(this, ['setEditMode', 'removeEditMode', 'saveEdit', 'cancelEdit', 'updateData']);\n\n this.bindEvents();\n\n};\n\n_.extend(AssignmentRow.prototype, {\n\n template: _.template(userRowTemplate),\n editTemplate: _.template(editUserRowTemplate),\n\n bindEvents: function () {\n this.$el.on('click', 'button.edit', this.setEditMode);\n this.$el.on('click', 'button.save', this.saveEdit);\n this.$el.on('click', 'button.cancel', this.cancelEdit);\n },\n\n remove: function () {\n this.$el.off('click', null, null);\n // this only gives a delay to remove the tr\n // animation of height of the tr does not work\n this.$(':checkbox').attr('checked', false);\n this.$el\n .css({ opacity: 0.3 })\n .animate({ height: 0 }, {\n duration: 300,\n complete: function () {\n this.remove();\n }\n });\n },\n\n makeInactive: function () {\n return this.model.makeInactive();\n },\n\n setEditMode: function () {\n this.model.set('edit-mode', true);\n this.render();\n },\n\n removeEditMode: function () {\n this.model.set('edit-mode', false);\n this.render();\n },\n\n saveEdit: function () {\n var me = this;\n this.updateData();\n this.worlds\n .updateUser(this.model)\n .then(function () {\n me.removeEditMode();\n me.$el.trigger('update', me);\n });\n },\n\n cancelEdit: function () {\n this.removeEditMode();\n },\n\n render: function () {\n var templ = this.model.get('edit-mode') ? this.editTemplate : this.template;\n var vm = _.extend({\n roles: this.project.get('roles'),\n optionalRoles: this.project.get('optionalRoles'),\n worlds: this.worlds.getWorldNames(),\n newWorld: this.worlds.getNextWorldName()\n }, this.model.toJSON());\n\n this.$el.html(templ(vm));\n\n return this;\n },\n\n updateData: function () {\n var me = this;\n this.$('[data-field]').each(function () {\n var el = $(this);\n var field = el.data('field');\n var val = el.val();\n\n me.model.set(field, val);\n });\n }\n});\n\n\nexport default AssignmentRow;\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/assignment-row.js","'use strict';\n\n/**\n* Utility class to make ajax calls sequencial\n*/\nfunction AjaxQueue() {\n this.queue = [];\n}\n\n$.extend(AjaxQueue.prototype, {\n add: function (fn) {\n return this.queue.push(fn);\n },\n\n execute: function (context) {\n var dtd = $.Deferred();\n var me = this;\n context = context || this;\n\n function next() {\n if (me.queue.length) {\n var fn = me.queue.shift();\n\n fn.call(context)\n .then(next)\n .fail(dtd.reject);\n } else {\n dtd.resolve();\n }\n }\n\n next();\n\n return dtd.promise();\n }\n});\n\n\nmodule.exports = AjaxQueue;\n\n\n// WEBPACK FOOTER //\n// ./src/util/ajax-queue.js"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"sources":["webpack:///assignment.min.js","webpack:///webpack/bootstrap 5b36529e33521661d9bd","webpack:///./src/util/inherit.js","webpack:///./src/components/assignment/js/service-locator.js","webpack:///./src/components/assignment/js/base-model.js","webpack:///./src/components/assignment/js/defaults.js","webpack:///./src/components/assignment/js/user-model.js","webpack:///./src/components/assignment/js/base-collection.js","webpack:///./src/components/assignment/js/index.js","webpack:///./src/components/assignment/js/assignment.js","webpack:///./src/components/assignment/js/users-collection.js","webpack:///./src/components/assignment/js/worlds-collection.js","webpack:///./src/components/assignment/js/world-model.js","webpack:///./src/components/assignment/js/project-model.js","webpack:///./src/components/assignment/js/assignment-row.js","webpack:///./src/util/ajax-queue.js"],"names":["modules","__webpack_require__","moduleId","installedModules","exports","module","i","l","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","n","__esModule","object","property","prototype","hasOwnProperty","p","s","inherit","C","P","F","__super","constructor","extend","dest","obj","Array","slice","arguments","current","j","length","key","base","props","staticProps","parent","child","apply","this","env","require","cache","worldApi","service","World","memberApi","Member","_","pick","userApi","User","BaseModel","attr","options","defaults","result","_data","set","initialize","val","attrs","remove","collection","toJSON","keys","account","project","group","groupId","token","server","host","protocol","merge","classFrom","Base","serviceLocator","world","role","active","isWorldComplete","firstName","lastName","makeActive","params","userId","original","makeUserActive","fail","bind","makeInactive","makeUserInactive","BaseCollection","models","_models","idAttribute","create","model","reset","_this","concat","forEach","push","sort","sortFn","a","b","getById","id","_this2","find","each","cb","ctx","all","every","invoke","fn","filter","size","map","pluck","field","App","window","forio","MultiplayerAssignmentComponent","setEnvironment","omit","UsersCollection","WorldsCollection","ProjectModel","AssignemntRow","default","AjaxQueue","Assignment","el","$","$el","partialRight","users","worlds","bindAll","bindEvents","on","saveEdit","toggleControlls","selectAll","usassignSelected","autoAssignAll","load","join","setUsersCollection","joinUsers","render","when","fetch","then","updateControls","_showUpdating","maxUsers","_hideUpdating","getSelectedIds","data","findRowViews","ids","rowViews","unassignUsers","dtd","Deferred","done","resolve","queue","user","add","partial","updateUser","execute","promise","e","preventDefault","makeUsersInactive","rows","view","empty","sortTable","renderTable","getTableParams","mult","direction","nameDirection","userNameDirection","prop","an","bn","localeCompare","header","arrowDir","arrow","append","query","location","search","substr","split","q","_this3","u","updateControlsForSelection","updateAutoAssignButton","updateStatus","incompleteWorlds","getIncompleteWorldsCount","unassignedUsers","getUnassignedUsersCount","totalWorlds","usersText","worldsText","text","addClass","removeClass","numSelected","isDynamicAssignment","hasRoles","hide","show","allUsersAssigned","target","checked","total","removeAttr","css","opacity","Model","aw","toLowerCase","bw","am","manager","AuthManager","session","getCurrentUserSessionInfo","auth_token","ajaxSetup","headers","Authorization","me","splitIdChunks","userIds","idGroups","splice","loadUsersInfo","nonFacAndActive","endUsers","members","endUserIds","chunkedUsers","chunkedPromises","userGroups","reduce","acc","userGroup","getGroupDetails","reject","UserModel","doneFn","after","autoAssign","parse","w","worldName","prevWorld","getWorldByUser","curWorld","getOrCreateWorld","removeUser","addUser","getWordByName","Error","getWorldByUserId","getWorldNames","getNextWorldName","properNames","test","lastWorld","numWorld","match","num","places","zeros","digits","toString","needed","usersCollection","usersHash","isComplete","index","list","_worldApi","updateConfig","userObj","save","checkWorld","delete","mapUsers","res","createWorld","addUsers","savedUsers","isNew","roles","getProjectSettings","settings","__webpack_exports__","value","userRowTemplate","trim","AssignmentRow","template","editTemplate","editUserRowTemplate","setEditMode","cancelEdit","off","animate","height","duration","complete","removeEditMode","updateData","trigger","templ","vm","optionalRoles","newWorld","html","context","next","shift"],"mappings":"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","file":"assignment.min.js","sourcesContent":["/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 6);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/**\n/* Inherit from a class (using prototype borrowing)\n*/\n\n\nfunction inherit(C, P) {\n var F = function () {};\n F.prototype = P.prototype;\n C.prototype = new F();\n C.__super = P.prototype;\n C.prototype.constructor = C;\n}\n\n/**\n* Shallow copy of an object\n* @param {Object} dest object to extend\n* @return {Object} extended object\n*/\nvar extend = function (dest /*, var_args*/) {\n var obj = Array.prototype.slice.call(arguments, 1);\n var current;\n for (var j = 0; j < obj.length; j++) {\n if (!(current = obj[j])) {\n //eslint-disable-line\n continue;\n }\n\n // do not wrap inner in dest.hasOwnProperty or bad things will happen\n for (var key in current) {\n //eslint-disable-line\n dest[key] = current[key];\n }\n }\n\n return dest;\n};\n\nmodule.exports = function (base, props, staticProps) {\n var parent = base;\n var child;\n\n child = props && props.hasOwnProperty('constructor') ? props.constructor : function () {\n return parent.apply(this, arguments);\n };\n\n // add static properties to the child constructor function\n extend(child, parent, staticProps);\n\n // associate prototype chain\n inherit(child, parent);\n\n // add instance properties\n if (props) {\n extend(child.prototype, props);\n }\n\n // done\n return child;\n};\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar env = __webpack_require__(3);\n\nvar cache = {};\n\nmodule.exports = {\n worldApi: function () {\n if (!cache.worldApi) {\n cache.worldApi = new F.service.World(env.get());\n }\n return cache.worldApi;\n },\n\n memberApi: function () {\n if (!cache.memberApi) {\n cache.memberApi = new F.service.Member(_.pick(env.get(), ['groupId', 'server']));\n }\n\n return cache.memberApi;\n },\n\n userApi: function () {\n if (!cache.userApi) {\n cache.userApi = new F.service.User(_.pick(env.get(), ['account', 'server']));\n }\n\n return cache.userApi;\n }\n};\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar BaseModel = function (attr, options) {\n attr = _.defaults({}, attr, _.result(this, 'defaults'));\n this._data = {};\n this.set(attr, options);\n this.initialize.apply(this, arguments);\n};\n\n_.extend(BaseModel.prototype, {\n initialize: function (attr, options) {},\n\n set: function (key, val, options) {\n if (key === null) {\n return this;\n }\n\n var attrs;\n if (typeof key === 'object') {\n attrs = key;\n options = val;\n } else {\n (attrs = {})[key] = val;\n }\n\n options = options || {};\n\n _.extend(this._data, attrs);\n\n return this;\n },\n\n get: function (key, options) {\n return this._data[key];\n },\n\n remove: function () {\n if (this.collection) {\n this.collection.remove(this);\n }\n\n return this;\n },\n\n toJSON: function () {\n return this._data;\n },\n\n pick: function (keys) {\n return _.pick(this._data, keys);\n }\n\n});\n\nmodule.exports = BaseModel;\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar env = {\n account: '',\n project: '',\n group: '',\n groupId: '',\n token: '',\n server: {\n host: 'api.forio.com',\n protocol: 'https'\n }\n};\n\nmodule.exports = {\n set: function (options) {\n env = _.merge(env, options);\n },\n\n get: function () {\n return env;\n }\n};\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar classFrom = __webpack_require__(0);\nvar Base = __webpack_require__(2);\nvar serviceLocator = __webpack_require__(1);\n\nmodule.exports = classFrom(Base, {\n defaults: {\n world: '',\n role: '',\n active: true,\n isWorldComplete: true,\n firstName: '',\n lastName: ''\n },\n\n makeActive: function () {\n var memberApi = serviceLocator.memberApi();\n var params = {\n userId: this.get('id'),\n groupId: this.get('groupId')\n };\n\n var original = this.get('active');\n this.set('active', true);\n\n return memberApi.makeUserActive(params).fail(function () {\n // revert the change\n this.set('active', original);\n }.bind(this));\n },\n\n makeInactive: function () {\n var memberApi = serviceLocator.memberApi();\n var params = {\n userId: this.get('id'),\n groupId: this.get('groupId')\n };\n\n var original = this.get('active');\n this.set('active', false);\n\n return memberApi.makeUserInactive(params).fail(function () {\n // revert the change\n this.set('active', original);\n }.bind(this));\n }\n\n});\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar BaseCollection = function (models, options) {\n this._models = [];\n this.options = options;\n this.initialize.apply(this, arguments);\n};\n\n_.extend(BaseCollection.prototype, {\n idAttribute: 'id',\n\n initialize: function (models, options) {},\n\n create: function (attr, options) {\n var m = new this.model(attr, options);\n this.set(m);\n return m;\n },\n\n reset: function (models, options) {\n this._models.length = 0;\n this.set(models);\n },\n\n remove: function (model) {\n _.remove(this._models, function (m) {\n return m === model;\n });\n\n delete model.collection;\n\n return model;\n },\n\n set: function (models) {\n var _this = this;\n\n if (!models) {\n return;\n }\n\n models = [].concat(models);\n\n if (!models.length) {\n return;\n }\n\n models.forEach(function (m) {\n if (!(m instanceof _this.model)) {\n m = new _this.model(m);\n }\n m.collection = _this;\n _this._models.push(m);\n });\n\n this.sort();\n\n return models;\n },\n\n sortFn: function (a, b) {\n return b._data[this.idAttribute] - a._data[this.idAttribute];\n },\n\n sort: function () {\n this._models = this._models.sort(this.sortFn.bind(this));\n\n return this._models;\n },\n\n getById: function (id) {\n var _this2 = this;\n\n return _.find(this._models, function (m) {\n return m.get(_this2.idAttribute) === id;\n });\n },\n\n each: function (cb, ctx) {\n return _.each(this._models, cb, ctx || this);\n },\n\n all: function (cb, ctx) {\n return _.every(this._models, cb, ctx || this);\n },\n\n toJSON: function () {\n return _.invoke(this._models, 'toJSON');\n },\n\n find: function (fn) {\n return _.find(this._models, fn);\n },\n\n filter: function (fn) {\n return _.filter(this._models, fn);\n },\n\n size: function () {\n return this._models.length;\n },\n\n map: function (fn, ctx) {\n return _.map(this._models, function (model) {\n return fn.call(ctx, model.toJSON());\n });\n },\n\n pluck: function (field) {\n return this.map(function (m) {\n return m[field];\n });\n }\n\n});\n\nmodule.exports = BaseCollection;\n\n/***/ }),\n/* 6 */\n/***/ (function(module, exports, __webpack_require__) {\n\n(function () {\n var App = __webpack_require__(7);\n\n window.forio = window.forio || {};\n window.forio.MultiplayerAssignmentComponent = App;\n})();\n\n/***/ }),\n/* 7 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar UsersCollection = __webpack_require__(8);\nvar WorldsCollection = __webpack_require__(9);\nvar ProjectModel = __webpack_require__(11);\nvar AssignemntRow = __webpack_require__(12).default;\nvar env = __webpack_require__(3);\nvar AjaxQueue = __webpack_require__(13);\n\nfunction setEnvironment(options) {\n env.set(_.omit(options, 'el'));\n}\n\nvar Assignment = function (options) {\n setEnvironment(options);\n this.initialize(options);\n};\n\nAssignment.prototype = {\n\n initialize: function (options) {\n this.el = typeof options.el === 'string' ? $(options.el)[0] : options.el;\n this.$el = $(this.el);\n this.$ = _.partialRight($, this.el);\n\n this.users = new UsersCollection();\n this.worlds = new WorldsCollection();\n this.project = new ProjectModel();\n\n _.bindAll(this, ['render', 'renderTable', 'toggleControlls', 'saveEdit', 'selectAll', 'usassignSelected', '_showUpdating', '_hideUpdating', 'autoAssignAll', 'makeUserInactive']);\n\n this.bindEvents();\n },\n\n bindEvents: function () {\n this.$el.on('update', 'tr', this.saveEdit);\n this.$el.on('click', 'input:checkbox:not(#select-all)', this.toggleControlls);\n this.$el.on('click', '#select-all', this.selectAll);\n this.$el.on('click', '.unassign-user', this.usassignSelected);\n this.$el.on('click', '.auto-assign-all', this.autoAssignAll);\n this.$el.on('click', '.make-user-inactive', this.makeUserInactive);\n },\n\n load: function () {\n var join = function () {\n this.worlds.setUsersCollection(this.users);\n this.worlds.joinUsers();\n this.render();\n }.bind(this);\n\n return $.when(this.worlds.fetch(), this.users.fetch(), this.project.fetch()).then(join);\n },\n\n saveEdit: function () {\n this.worlds.fetch().then(function () {\n this.worlds.joinUsers();\n this.render();\n this.updateControls();\n }.bind(this));\n },\n\n autoAssignAll: function () {\n this._showUpdating();\n var maxUsers = +this.$('#max-users').val();\n return this.worlds.autoAssignAll({ maxUsers: maxUsers }).then(this._hideUpdating).fail(this._hideUpdating).then(function () {\n this.worlds.joinUsers();\n this.render();\n }.bind(this));\n },\n\n getSelectedIds: function () {\n return this.$('tbody :checkbox:checked').map(function () {\n return $(this).data('id');\n }).get();\n },\n\n findRowViews: function (ids) {\n var _this = this;\n\n return ids.map(function (id) {\n return _this.rowViews[id];\n });\n },\n\n unassignUsers: function (ids) {\n var _this2 = this;\n\n var dtd = $.Deferred();\n var done = function () {\n dtd.resolve();\n };\n\n // for now we need to sequence the calls to unassign users from worlds\n var queue = new AjaxQueue();\n\n ids.forEach(function (userId) {\n var user = _this2.users.getById(userId);\n user.set('world', '');\n user.set('role', '');\n queue.add(_.partial(_.bind(_this2.worlds.updateUser, _this2.worlds), user));\n });\n\n queue.execute(this).then(done);\n\n return dtd.promise();\n },\n\n usassignSelected: function (e) {\n e.preventDefault();\n\n var ids = this.getSelectedIds();\n\n var done = function () {\n this.worlds.fetch().then(function () {\n this.worlds.joinUsers();\n this._hideUpdating();\n this.render();\n }.bind(this));\n }.bind(this);\n\n this._showUpdating();\n\n return this.unassignUsers(ids).then(done);\n },\n\n makeUserInactive: function (e) {\n e.preventDefault();\n var ids = this.getSelectedIds();\n var done = function () {\n this.toggleControlls();\n }.bind(this);\n\n var makeUsersInactive = function () {\n var rows = this.findRowViews(ids);\n // for now we need to sequence the calls to patch the users\n // since the API can only operate on one call per group at a time\n var queue = new AjaxQueue();\n rows.forEach(function (view) {\n var user = view.model;\n queue.add(function () {\n return view.makeInactive().then(function () {\n user.remove();\n view.remove();\n });\n });\n });\n\n queue.execute(this).then(done);\n }.bind(this);\n\n return this.unassignUsers(ids).then(makeUsersInactive);\n },\n\n render: function () {\n this.$('table tbody').empty();\n this.sortTable();\n this.renderTable();\n this.toggleControlls();\n },\n\n sortTable: function () {\n // get the sort params and sort if necessary\n var params = this.getTableParams();\n\n var mult = params.hasOwnProperty('direction') && params.direction === 'desc' ? -1 : 1;\n var nameDirection = params.hasOwnProperty('sort') && params.sort === 'name' && mult > 0 ? 'desc' : 'asc';\n var userNameDirection = params.hasOwnProperty('sort') && params.sort === 'userName' && mult > 0 ? 'desc' : 'asc';\n this.$('table .header-name a').prop('href', '?sort=name&direction=' + nameDirection);\n this.$('table .header-username a').prop('href', '?sort=userName&direction=' + userNameDirection);\n\n if (params.hasOwnProperty('sort')) {\n this.users.sortFn = function (a, b) {\n var an = a.get(params.sort) || '';\n var bn = b.get(params.sort) || '';\n if (params.sort === 'name') {\n an = a.get('firstName') + a.get('lastName');\n bn = b.get('firstName') + b.get('lastName');\n }\n return mult * an.localeCompare(bn);\n };\n this.users.sort();\n\n var header = params.sort === 'name' ? this.$('table .header-name') : this.$('table .header-username');\n var arrowDir = mult > 0 ? 'caret-up' : 'caret-down';\n var arrow = this.$('');\n header.append(arrow);\n }\n },\n\n getTableParams: function () {\n var query = location.search !== '' ? location.search.substr(1).split('&') : [];\n var params = {};\n for (var i = 0; i < query.length; i++) {\n var q = query[i].split('=');\n params[q[0]] = q[1];\n }\n return params;\n },\n\n renderTable: function () {\n var _this3 = this;\n\n this.rowViews = {};\n var rows = [];\n this.users.each(function (u) {\n var view = new AssignemntRow({ model: u, worlds: _this3.worlds, project: _this3.project });\n _this3.rowViews[u.get('id')] = view;\n rows.push(view.render().el);\n });\n\n this.$('table tbody').append(rows);\n },\n\n updateControls: function () {\n this.updateControlsForSelection();\n this.updateAutoAssignButton();\n this.updateStatus();\n },\n\n updateStatus: function () {\n var incompleteWorlds = this.worlds.getIncompleteWorldsCount();\n var unassignedUsers = this.users.getUnassignedUsersCount();\n var totalWorlds = this.worlds.size();\n\n var usersText = 'All users have been assigned.';\n if (unassignedUsers) {\n usersText = unassignedUsers === 1 ? '1 user needs assignment.' : unassignedUsers + ' users need assignment.';\n }\n var worldsText = 'All worlds are complete.';\n if (!totalWorlds) {\n worldsText = 'No worlds have been created.';\n } else if (incompleteWorlds) {\n worldsText = incompleteWorlds === 1 ? '1 incomplete world needs attention.' : incompleteWorlds + ' incomplete worlds need attention.';\n }\n\n this.$('#users-status .text').text(usersText);\n this.$('#worlds-status .text').text(worldsText);\n\n if (unassignedUsers) {\n this.$('#users-status').addClass('incomplete');\n } else {\n this.$('#users-status').removeClass('incomplete');\n }\n\n if (incompleteWorlds || !totalWorlds) {\n this.$('#worlds-status').addClass('incomplete');\n } else {\n this.$('#worlds-status').removeClass('incomplete');\n }\n\n this.$('.status-widget').addClass('visible');\n },\n\n updateControlsForSelection: function () {\n var numSelected = this.$('tbody :checkbox:checked').length;\n this.$('.component.controls')[numSelected ? 'addClass' : 'removeClass']('visible');\n },\n\n updateAutoAssignButton: function () {\n\n if (this.project.isDynamicAssignment()) {\n var hasRoles = this.project.hasRoles();\n this.$('.table-controls .single').hide();\n this.$('.table-controls .dynamic').show();\n this.$('.table-controls .dynamic-no-roles-text')[hasRoles ? 'hide' : 'show']();\n this.$('.table-controls .no-roles')[hasRoles ? 'hide' : 'show']();\n } else {\n this.$('.table-controls .dynamic').hide();\n this.$('.table-controls .dynamic-no-roles-text').hide();\n this.$('.table-controls .single').show();\n this.$('.table-controls .no-roles').show();\n }\n\n if (this.users.allUsersAssigned()) {\n this.$('.table-controls').removeClass('visible');\n } else {\n this.$('.table-controls').addClass('visible');\n }\n },\n\n selectAll: function (e) {\n this.$('tbody :checkbox').prop('checked', e.target.checked);\n this.updateControls();\n },\n\n toggleControlls: function (e) {\n var total = this.$('tbody :checkbox');\n var checked = this.$('tbody :checkbox:checked');\n\n if (total.length === checked.length) {\n this.$('#select-all').attr('checked', 'checked');\n } else {\n this.$('#select-all').removeAttr('checked');\n }\n\n this.updateControls();\n },\n\n _showUpdating: function () {\n this.$el.css({ opacity: 0.4 });\n },\n\n _hideUpdating: function () {\n this.$el.css({ opacity: 1 });\n }\n\n};\n\nmodule.exports = Assignment;\n\n/***/ }),\n/* 8 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar classFrom = __webpack_require__(0);\n\nvar Model = __webpack_require__(4);\nvar Base = __webpack_require__(5);\nvar env = __webpack_require__(3);\nvar serviceLocator = __webpack_require__(1);\n\nmodule.exports = classFrom(Base, {\n model: Model,\n\n sortFn: function (a, b) {\n var aw = a.get('world').toLowerCase();\n var bw = b.get('world').toLowerCase();\n if (aw !== bw) {\n return aw < bw ? -1 : 1;\n }\n\n return b.get('userName') > a.get('userName') ? -1 : 1;\n },\n\n initialize: function () {\n var am = new F.manager.AuthManager();\n var session = am.getCurrentUserSessionInfo();\n var token = session.auth_token;\n if (token) {\n $.ajaxSetup({\n headers: {\n Authorization: 'Bearer ' + token\n }\n });\n }\n },\n\n allUsersAssigned: function () {\n return this.all(function (u) {\n return !!u.get('world');\n });\n },\n\n getUnassignedUsersCount: function () {\n return this.filter(function (u) {\n return !u.get('world');\n }).length;\n },\n\n fetch: function () {\n var dtd = $.Deferred();\n var me = this;\n var groupId = env.get().groupId;\n\n var getGroupUsers = function () {\n var memberApi = serviceLocator.memberApi();\n var userApi = serviceLocator.userApi();\n\n var loadGroupMembers = function () {\n return memberApi.getGroupDetails();\n };\n\n var splitIdChunks = function (userIds) {\n var idGroupSize = 100;\n var idGroups = [];\n while (userIds.length >= idGroupSize) {\n idGroups.push(userIds.splice(0, idGroupSize));\n }\n\n if (userIds.length) {\n idGroups.push(userIds);\n }\n\n return idGroups;\n };\n\n var loadUsersInfo = function (group) {\n var nonFacAndActive = function (u) {\n return u.active && u.role !== 'facilitator';\n };\n var endUsers = group.members.filter(function (m) {\n return nonFacAndActive(m);\n });\n var endUserIds = endUsers.map(function (u) {\n return u.userId;\n });\n var chunkedUsers = splitIdChunks(endUserIds);\n var chunkedPromises = chunkedUsers.map(function (users) {\n return userApi.get({ id: users });\n });\n return $.when.apply($, chunkedPromises).then(function (userGroups) {\n var totalUsers = userGroups.reduce(function (acc, userGroup) {\n return acc.concat(userGroup);\n }, []);\n\n return totalUsers;\n });\n };\n\n return loadGroupMembers().then(loadUsersInfo).fail(dtd.reject);\n };\n\n getGroupUsers().then(function (users) {\n users = users.map(function (u) {\n return $.extend(u, { groupId: groupId });\n });\n me.set(users);\n dtd.resolve(users);\n });\n\n return dtd.promise();\n }\n\n});\n\n/***/ }),\n/* 9 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar classFrom = __webpack_require__(0);\nvar Model = __webpack_require__(10);\nvar UserModel = __webpack_require__(4);\nvar serviceLocator = __webpack_require__(1);\n\nvar Base = __webpack_require__(5);\nvar __super = Base.prototype;\n\nvar doneFn = function (dtd, after) {\n return _.after(after, dtd.resolve);\n};\n\nvar worldApi;\n\nmodule.exports = classFrom(Base, {\n model: Model,\n\n initialize: function () {\n __super.initialize.apply(this, arguments);\n worldApi = serviceLocator.worldApi();\n },\n\n autoAssignAll: function (options) {\n return worldApi.autoAssign(options).then(function (worlds) {\n this.reset(this.parse(worlds));\n }.bind(this));\n },\n\n getIncompleteWorldsCount: function () {\n return this.filter(function (w) {\n return !w.get('complete');\n }).length;\n },\n\n updateUser: function (user) {\n var worldName = user.get('world');\n var dtd = $.Deferred();\n var prevWorld = this.getWorldByUser(user);\n var curWorld = this.getOrCreateWorld(worldName);\n var done = doneFn(dtd, 1);\n\n // check if there's anything to do\n if (!prevWorld && !curWorld) {\n return dtd.resolve().promise();\n }\n\n if (prevWorld && curWorld && prevWorld.get('id') === curWorld.get('id')) {\n //worlds are the same, but role changed\n return curWorld.updateUser(user);\n }\n if (prevWorld) {\n prevWorld.removeUser(user).then(function () {\n if (curWorld) {\n return curWorld.addUser(user);\n }\n }).then(done);\n } else if (curWorld) {\n curWorld.addUser(user).then(done);\n }\n\n return dtd.promise();\n },\n\n getOrCreateWorld: function (worldName) {\n if (!worldName) {\n return;\n }\n\n var world = this.getWordByName(worldName);\n\n if (!world) {\n world = this.create({ name: worldName });\n }\n\n return world;\n },\n\n getWordByName: function (worldName) {\n return this.find(function (world) {\n return world.get('name') === worldName;\n });\n },\n\n getWorldByUser: function (user) {\n if (!user.get) {\n throw new Error('getWorldByUser expectes a model (' + user + ')');\n }\n\n var id = user.get('id');\n return this.getWorldByUserId(id);\n },\n\n getWorldByUserId: function (userId) {\n return this.find(function (world) {\n return _.find(world.get('users'), function (u) {\n return u.get('id') === userId;\n });\n });\n },\n\n getWorldNames: function () {\n return this.pluck('name').sort();\n },\n\n getNextWorldName: function () {\n var pad = function (num, places) {\n var zeros = '000000000000000000';\n var digits = num.toString().length;\n var needed = places - digits;\n return zeros.substr(0, needed) + num;\n };\n\n var worlds = this.getWorldNames();\n\n if (!worlds.length) {\n return 'World001';\n }\n\n var properNames = _.filter(worlds, function (w) {\n return (/World\\d\\d\\d/.test(w)\n );\n }).sort();\n var lastWorld = properNames[properNames.length - 1];\n var numWorld = +lastWorld.match(/World(\\d\\d\\d)/)[1];\n var placesToPad = 3;\n return 'World' + pad(numWorld + 1, placesToPad);\n },\n\n setUsersCollection: function (usersCollection) {\n this.usersCollection = usersCollection;\n },\n\n joinUsers: function () {\n var usersHash = {};\n var usersCollection = this.usersCollection;\n usersCollection.each(function (u) {\n u.set({ isWorldComplete: true });\n return usersHash[u.get('id')] = u;\n });\n\n this.each(function (w, i) {\n var name = w.get('name');\n var isComplete = w.get('complete');\n w.set({ index: i, name: name || i + 1 + '' });\n _.each(w.get('users'), function (u) {\n if (usersHash[u.get('userId')]) {\n usersHash[u.get('userId')].set({ world: name, role: u.get('role'), isWorldComplete: isComplete });\n }\n });\n });\n\n usersCollection.sort();\n },\n\n fetch: function () {\n return worldApi.list().then(function (worlds) {\n this.reset(this.parse(worlds));\n }.bind(this));\n },\n\n parse: function (worlds) {\n if (worlds.length) {\n worlds = _.map(worlds, function (w) {\n var users = _.map(w.users, function (u) {\n // in the world api users Ids comes as userId\n // make sure we add it as id so we can use the\n // same code to access models that come from the\n // member/local api as with the world api\n u.id = u.userId;\n return new UserModel(u);\n });\n\n w.users = users;\n\n return w;\n });\n }\n\n return worlds;\n }\n});\n\n/***/ }),\n/* 10 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar serviceLocator = __webpack_require__(1);\nvar classFrom = __webpack_require__(0);\nvar Base = __webpack_require__(2);\nvar __super = Base.prototype;\n\nmodule.exports = classFrom(Base, {\n\n defaults: {\n users: null,\n model: 'model.eqn'\n },\n\n initialize: function () {\n __super.initialize.apply(this, arguments);\n\n this._data.users = this._data.users || [];\n\n this._worldApi = serviceLocator.worldApi();\n\n var id = this.get('id');\n if (id) {\n this._worldApi.updateConfig({ filter: id });\n }\n },\n\n updateUser: function (user) {\n if (!user) {\n throw new Error('updateUser: No user passed to update');\n }\n var userObj = user.toJSON();\n userObj.userId = userObj.id;\n return this._worldApi.updateUser(userObj, { id: this.get('id') });\n },\n\n addUser: function (user) {\n var users = this.get('users');\n users.push(user);\n\n return this.save();\n },\n\n removeUser: function (user) {\n var id = this.get('id');\n var checkWorld = function () {\n if (!this.get('users').length) {\n this.remove();\n return this._worldApi.updateConfig({ filter: id }).delete();\n }\n }.bind(this);\n\n _.remove(this.get('users'), function (u) {\n return u.get('id') === user.get('id');\n });\n\n return this._worldApi.updateConfig({ filter: id }).removeUser({ userId: user.get('id') }).then(checkWorld);\n },\n\n save: function () {\n var me = this;\n var mapUsers = function () {\n return _.map(this.get('users'), function (u) {\n var res = { userId: u.get('id') };\n var role = u.get('role');\n\n if (role) {\n res.role = role;\n }\n\n return res;\n });\n }.bind(this);\n\n var createWorld = _.partial(this._worldApi.create, this.pick(['model', 'name', 'minUsers']));\n var addUsers = _.partial(me._worldApi.addUsers, mapUsers(), { filter: me.get('id') });\n var savedUsers = this.get('users');\n if (this.isNew()) {\n // we need to create the world in the API and then add the users\n return createWorld().then(function (world) {\n me.set(world);\n me._worldApi.updateConfig({ filter: world.id });\n }).then(addUsers).then(function (users) {\n // since we re-set the world, re-set the users\n me.set('users', savedUsers);\n });\n } else {\n // the world is already created just add the users\n return addUsers();\n }\n },\n\n isNew: function () {\n return !this.get('lastModified');\n }\n\n});\n\n/***/ }),\n/* 11 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar serviceLocator = __webpack_require__(1);\n\nvar classFrom = __webpack_require__(0);\nvar Base = __webpack_require__(2);\n// var __super = Base.prototype;\n\nmodule.exports = classFrom(Base, {\n\n isDynamicAssignment: function () {\n return this.get('worlds') === 'dynamic';\n },\n\n hasRoles: function () {\n var roles = this.get('roles');\n return roles && !!roles.length;\n },\n\n fetch: function () {\n var api = serviceLocator.worldApi();\n\n return api.getProjectSettings().then(function (settings) {\n this.set(settings);\n }.bind(this));\n }\n});\n\n/***/ }),\n/* 12 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\nvar userRowTemplate = '\\n \" | \\n <%= !isWorldComplete ? \\'\\' : \\'\\' %> | \\n <%= world %> | \\n <%= role %> | \\n <%= lastName %> | \\n <%= userName %> | \\n <%= !world ? \\'\\' : \\'\\' %> | \\n | \\n'.trim();\nvar editUserRowTemplate = '\\n \" | \\n | \\n \\n \\n | \\n \\n \\n | \\n <%= lastName %> | \\n <%= userName %> | \\n <%= !world ? \\'\\' : \\'\\' %> | \\n \\n \\n \\n | \\n';\n\nvar AssignmentRow = function (options) {\n this.$el = $('
');\n this.el = this.$el[0];\n this.$ = _.partialRight($, this.$el);\n\n this.model = options.model;\n this.options = options;\n this.worlds = options.worlds;\n this.project = options.project;\n\n _.bindAll(this, ['setEditMode', 'removeEditMode', 'saveEdit', 'cancelEdit', 'updateData']);\n\n this.bindEvents();\n};\n\n_.extend(AssignmentRow.prototype, {\n\n template: _.template(userRowTemplate),\n editTemplate: _.template(editUserRowTemplate),\n\n bindEvents: function () {\n this.$el.on('click', 'button.edit', this.setEditMode);\n this.$el.on('click', 'button.save', this.saveEdit);\n this.$el.on('click', 'button.cancel', this.cancelEdit);\n },\n\n remove: function () {\n this.$el.off('click', null, null);\n // this only gives a delay to remove the tr\n // animation of height of the tr does not work\n this.$(':checkbox').attr('checked', false);\n this.$el.css({ opacity: 0.3 }).animate({ height: 0 }, {\n duration: 300,\n complete: function () {\n this.remove();\n }\n });\n },\n\n makeInactive: function () {\n return this.model.makeInactive();\n },\n\n setEditMode: function () {\n this.model.set('edit-mode', true);\n this.render();\n },\n\n removeEditMode: function () {\n this.model.set('edit-mode', false);\n this.render();\n },\n\n saveEdit: function () {\n var me = this;\n this.updateData();\n this.worlds.updateUser(this.model).then(function () {\n me.removeEditMode();\n me.$el.trigger('update', me);\n });\n },\n\n cancelEdit: function () {\n this.removeEditMode();\n },\n\n render: function () {\n var templ = this.model.get('edit-mode') ? this.editTemplate : this.template;\n var vm = _.extend({\n roles: this.project.get('roles'),\n optionalRoles: this.project.get('optionalRoles'),\n worlds: this.worlds.getWorldNames(),\n newWorld: this.worlds.getNextWorldName()\n }, this.model.toJSON());\n\n this.$el.html(templ(vm));\n\n return this;\n },\n\n updateData: function () {\n var me = this;\n this.$('[data-field]').each(function () {\n var el = $(this);\n var field = el.data('field');\n var val = el.val();\n\n me.model.set(field, val);\n });\n }\n});\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (AssignmentRow);\n\n/***/ }),\n/* 13 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n/**\n* Utility class to make ajax calls sequencial\n*/\n\nfunction AjaxQueue() {\n this.queue = [];\n}\n\n$.extend(AjaxQueue.prototype, {\n add: function (fn) {\n return this.queue.push(fn);\n },\n\n execute: function (context) {\n var dtd = $.Deferred();\n var me = this;\n context = context || this;\n\n function next() {\n if (me.queue.length) {\n var fn = me.queue.shift();\n\n fn.call(context).then(next).fail(dtd.reject);\n } else {\n dtd.resolve();\n }\n }\n\n next();\n\n return dtd.promise();\n }\n});\n\nmodule.exports = AjaxQueue;\n\n/***/ })\n/******/ ]);\n\n\n// WEBPACK FOOTER //\n// assignment.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 6);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 5b36529e33521661d9bd","/**\n/* Inherit from a class (using prototype borrowing)\n*/\n'use strict';\n\nfunction inherit(C, P) {\n var F = function () {};\n F.prototype = P.prototype;\n C.prototype = new F();\n C.__super = P.prototype;\n C.prototype.constructor = C;\n}\n\n/**\n* Shallow copy of an object\n* @param {Object} dest object to extend\n* @return {Object} extended object\n*/\nvar extend = function (dest /*, var_args*/) {\n var obj = Array.prototype.slice.call(arguments, 1);\n var current;\n for (var j = 0; j < obj.length; j++) {\n if (!(current = obj[j])) { //eslint-disable-line\n continue;\n }\n\n // do not wrap inner in dest.hasOwnProperty or bad things will happen\n for (var key in current) { //eslint-disable-line\n dest[key] = current[key];\n }\n }\n\n return dest;\n};\n\nmodule.exports = function (base, props, staticProps) {\n var parent = base;\n var child;\n\n child = props && props.hasOwnProperty('constructor') ? props.constructor : function () { return parent.apply(this, arguments); };\n\n // add static properties to the child constructor function\n extend(child, parent, staticProps);\n\n // associate prototype chain\n inherit(child, parent);\n\n // add instance properties\n if (props) {\n extend(child.prototype, props);\n }\n\n // done\n return child;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./src/util/inherit.js","'use strict';\n\nvar env = require('./defaults.js');\n\nvar cache = {};\n\nmodule.exports = {\n worldApi: function () {\n if (!cache.worldApi) {\n cache.worldApi = new F.service.World(env.get());\n }\n return cache.worldApi;\n },\n\n memberApi: function () {\n if (!cache.memberApi) {\n cache.memberApi = new F.service.Member(_.pick(env.get(), ['groupId', 'server']));\n }\n\n return cache.memberApi;\n },\n\n userApi: function () {\n if (!cache.userApi) {\n cache.userApi = new F.service.User(_.pick(env.get(), ['account', 'server']));\n }\n\n return cache.userApi;\n }\n};\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/service-locator.js","'use strict';\n\n\nvar BaseModel = function (attr, options) {\n attr = _.defaults({}, attr, _.result(this, 'defaults'));\n this._data = {};\n this.set(attr, options);\n this.initialize.apply(this, arguments);\n};\n\n_.extend(BaseModel.prototype, {\n initialize: function (attr, options) {\n\n },\n\n set: function (key, val, options) {\n if (key === null) {\n return this;\n }\n\n var attrs;\n if (typeof key === 'object') {\n attrs = key;\n options = val;\n } else {\n (attrs = {})[key] = val;\n }\n\n options = options || {};\n\n _.extend(this._data, attrs);\n\n return this;\n },\n\n get: function (key, options) {\n return this._data[key];\n },\n\n remove: function () {\n if (this.collection) {\n this.collection.remove(this);\n }\n\n return this;\n },\n\n toJSON: function () {\n return this._data;\n },\n\n pick: function (keys) {\n return _.pick(this._data, keys);\n }\n\n});\n\nmodule.exports = BaseModel;\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/base-model.js","'use strict';\n\nvar env = {\n account: '',\n project: '',\n group: '',\n groupId: '',\n token: '',\n server: {\n host: 'api.forio.com',\n protocol: 'https'\n }\n};\n\nmodule.exports = {\n set: function (options) {\n env = _.merge(env, options);\n },\n\n get: function () {\n return env;\n }\n};\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/defaults.js","'use strict';\n\nvar classFrom = require('../../../util/inherit');\nvar Base = require('./base-model');\nvar serviceLocator = require('./service-locator');\n\n\nmodule.exports = classFrom(Base, {\n defaults: {\n world: '',\n role: '',\n active: true,\n isWorldComplete: true,\n firstName: '',\n lastName: ''\n },\n\n makeActive: function () {\n var memberApi = serviceLocator.memberApi();\n var params = {\n userId: this.get('id'),\n groupId: this.get('groupId')\n };\n\n var original = this.get('active');\n this.set('active', true);\n\n return memberApi.makeUserActive(params)\n .fail(function () {\n // revert the change\n this.set('active', original);\n }.bind(this));\n },\n\n makeInactive: function () {\n var memberApi = serviceLocator.memberApi();\n var params = {\n userId: this.get('id'),\n groupId: this.get('groupId')\n };\n\n var original = this.get('active');\n this.set('active', false);\n\n return memberApi.makeUserInactive(params)\n .fail(function () {\n // revert the change\n this.set('active', original);\n }.bind(this));\n }\n\n});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/user-model.js","'use strict';\n\nvar BaseCollection = function (models, options) {\n this._models = [];\n this.options = options;\n this.initialize.apply(this, arguments);\n};\n\n_.extend(BaseCollection.prototype, {\n idAttribute: 'id',\n\n initialize: function (models, options) {\n },\n\n create: function (attr, options) {\n var m = new this.model(attr, options);\n this.set(m);\n return m;\n },\n\n reset: function (models, options) {\n this._models.length = 0;\n this.set(models);\n },\n\n remove: function (model) {\n _.remove(this._models, function (m) {\n return m === model;\n });\n\n delete model.collection;\n\n return model;\n },\n\n set: function (models) {\n if (!models) {\n return;\n }\n\n models = [].concat(models);\n\n if (!models.length) {\n return;\n }\n\n models.forEach((m)=> {\n if (!(m instanceof this.model)) {\n m = new this.model(m);\n }\n m.collection = this;\n this._models.push(m);\n });\n\n this.sort();\n\n return models;\n },\n\n sortFn: function (a, b) {\n return b._data[this.idAttribute] - a._data[this.idAttribute];\n },\n\n sort: function () {\n this._models = this._models.sort(this.sortFn.bind(this));\n\n return this._models;\n },\n\n getById: function (id) {\n return _.find(this._models, (m)=> {\n return m.get(this.idAttribute) === id;\n });\n },\n\n each: function (cb, ctx) {\n return _.each(this._models, cb, ctx || this);\n },\n\n all: function (cb, ctx) {\n return _.every(this._models, cb, ctx || this);\n },\n\n toJSON: function () {\n return _.invoke(this._models, 'toJSON');\n },\n\n find: function (fn) {\n return _.find(this._models, fn);\n },\n\n filter: function (fn) {\n return _.filter(this._models, fn);\n },\n\n size: function () {\n return this._models.length;\n },\n\n map: function (fn, ctx) {\n return _.map(this._models, function (model) {\n return fn.call(ctx, model.toJSON());\n });\n },\n\n pluck: function (field) {\n return this.map(function (m) {\n return m[field];\n });\n }\n\n});\n\nmodule.exports = BaseCollection;\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/base-collection.js","(function () {\n var App = require('./assignment.js');\n\n window.forio = window.forio || {};\n window.forio.MultiplayerAssignmentComponent = App;\n}());\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/index.js","'use strict';\n\nvar UsersCollection = require('./users-collection');\nvar WorldsCollection = require('./worlds-collection');\nvar ProjectModel = require('./project-model');\nvar AssignemntRow = require('./assignment-row').default;\nvar env = require('./defaults');\nvar AjaxQueue = require('../../../util/ajax-queue');\n\nfunction setEnvironment(options) {\n env.set(_.omit(options, 'el'));\n}\n\nvar Assignment = function (options) {\n setEnvironment(options);\n this.initialize(options);\n};\n\nAssignment.prototype = {\n\n initialize: function (options) {\n this.el = typeof options.el === 'string' ? $(options.el)[0] : options.el;\n this.$el = $(this.el);\n this.$ = _.partialRight($, this.el);\n\n this.users = new UsersCollection();\n this.worlds = new WorldsCollection();\n this.project = new ProjectModel();\n\n _.bindAll(this, ['render', 'renderTable', 'toggleControlls', 'saveEdit', 'selectAll', 'usassignSelected', '_showUpdating', '_hideUpdating', 'autoAssignAll', 'makeUserInactive']);\n\n this.bindEvents();\n },\n\n bindEvents: function () {\n this.$el.on('update', 'tr', this.saveEdit);\n this.$el.on('click', 'input:checkbox:not(#select-all)', this.toggleControlls);\n this.$el.on('click', '#select-all', this.selectAll);\n this.$el.on('click', '.unassign-user', this.usassignSelected);\n this.$el.on('click', '.auto-assign-all', this.autoAssignAll);\n this.$el.on('click', '.make-user-inactive', this.makeUserInactive);\n },\n\n load: function () {\n var join = function () {\n this.worlds.setUsersCollection(this.users);\n this.worlds.joinUsers();\n this.render();\n }.bind(this);\n\n return $.when(\n this.worlds.fetch(),\n this.users.fetch(),\n this.project.fetch()\n ).then(join);\n },\n\n saveEdit: function () {\n this.worlds.fetch()\n .then(function () {\n this.worlds.joinUsers();\n this.render();\n this.updateControls();\n }.bind(this));\n },\n\n autoAssignAll: function () {\n this._showUpdating();\n var maxUsers = +this.$('#max-users').val();\n return this.worlds.autoAssignAll({ maxUsers: maxUsers })\n .then(this._hideUpdating)\n .fail(this._hideUpdating)\n .then(function () {\n this.worlds.joinUsers();\n this.render();\n }.bind(this));\n },\n\n getSelectedIds: function () {\n return this.$('tbody :checkbox:checked').map(function () {\n return $(this).data('id');\n }).get();\n },\n\n findRowViews: function (ids) {\n return ids.map((id)=> {\n return this.rowViews[id];\n });\n },\n\n unassignUsers: function (ids) {\n var dtd = $.Deferred();\n var done = function () {\n dtd.resolve();\n };\n\n // for now we need to sequence the calls to unassign users from worlds\n var queue = new AjaxQueue();\n\n ids.forEach((userId)=> {\n var user = this.users.getById(userId);\n user.set('world', '');\n user.set('role', '');\n queue.add(_.partial(_.bind(this.worlds.updateUser, this.worlds), user));\n });\n\n queue.execute(this).then(done);\n\n return dtd.promise();\n },\n\n usassignSelected: function (e) {\n e.preventDefault();\n\n var ids = this.getSelectedIds();\n\n var done = function () {\n this.worlds.fetch().then(function () {\n this.worlds.joinUsers();\n this._hideUpdating();\n this.render();\n\n }.bind(this));\n }.bind(this);\n\n this._showUpdating();\n\n return this.unassignUsers(ids).then(done);\n },\n\n makeUserInactive: function (e) {\n e.preventDefault();\n var ids = this.getSelectedIds();\n var done = function () {\n this.toggleControlls();\n }.bind(this);\n\n var makeUsersInactive = function () {\n var rows = this.findRowViews(ids);\n // for now we need to sequence the calls to patch the users\n // since the API can only operate on one call per group at a time\n var queue = new AjaxQueue();\n rows.forEach((view)=> {\n var user = view.model;\n queue.add(function () {\n return view.makeInactive()\n .then(function () {\n user.remove();\n view.remove();\n });\n });\n\n });\n\n queue.execute(this).then(done);\n }.bind(this);\n\n return this.unassignUsers(ids)\n .then(makeUsersInactive);\n\n\n },\n\n render: function () {\n this.$('table tbody').empty();\n this.sortTable();\n this.renderTable();\n this.toggleControlls();\n },\n\n sortTable: function () {\n // get the sort params and sort if necessary\n var params = this.getTableParams();\n\n var mult = params.hasOwnProperty('direction') && params.direction === 'desc' ? -1 : 1;\n var nameDirection = params.hasOwnProperty('sort') && params.sort === 'name' && mult > 0 ? 'desc' : 'asc';\n var userNameDirection = params.hasOwnProperty('sort') && params.sort === 'userName' && mult > 0 ? 'desc' : 'asc';\n this.$('table .header-name a').prop('href', '?sort=name&direction=' + nameDirection);\n this.$('table .header-username a').prop('href', '?sort=userName&direction=' + userNameDirection);\n\n if (params.hasOwnProperty('sort')) {\n this.users.sortFn = function (a, b) {\n var an = (a.get(params.sort) || '');\n var bn = (b.get(params.sort) || '');\n if (params.sort === 'name') {\n an = (a.get('firstName') + a.get('lastName'));\n bn = (b.get('firstName') + b.get('lastName'));\n }\n return mult * an.localeCompare(bn);\n };\n this.users.sort();\n\n var header = params.sort === 'name' ? this.$('table .header-name') : this.$('table .header-username');\n var arrowDir = mult > 0 ? 'caret-up' : 'caret-down';\n var arrow = this.$('');\n header.append(arrow);\n }\n },\n\n getTableParams: function () {\n var query = location.search !== '' ? location.search.substr(1).split('&') : [];\n var params = {};\n for (var i = 0; i < query.length; i++) {\n var q = query[i].split('=');\n params[q[0]] = q[1];\n }\n return params;\n },\n\n renderTable: function () {\n this.rowViews = {};\n var rows = [];\n this.users.each((u)=> {\n var view = new AssignemntRow({ model: u, worlds: this.worlds, project: this.project });\n this.rowViews[u.get('id')] = view;\n rows.push(view.render().el);\n });\n\n this.$('table tbody').append(rows);\n },\n\n\n updateControls: function () {\n this.updateControlsForSelection();\n this.updateAutoAssignButton();\n this.updateStatus();\n },\n\n updateStatus: function () {\n var incompleteWorlds = this.worlds.getIncompleteWorldsCount();\n var unassignedUsers = this.users.getUnassignedUsersCount();\n var totalWorlds = this.worlds.size();\n\n var usersText = 'All users have been assigned.';\n if (unassignedUsers) {\n usersText = unassignedUsers === 1 ? '1 user needs assignment.' : unassignedUsers + ' users need assignment.';\n }\n var worldsText = 'All worlds are complete.';\n if (!totalWorlds) {\n worldsText = 'No worlds have been created.';\n } else if (incompleteWorlds) {\n worldsText = incompleteWorlds === 1 ? '1 incomplete world needs attention.' : incompleteWorlds + ' incomplete worlds need attention.';\n }\n\n this.$('#users-status .text').text(usersText);\n this.$('#worlds-status .text').text(worldsText);\n\n if (unassignedUsers) {\n this.$('#users-status').addClass('incomplete');\n } else {\n this.$('#users-status').removeClass('incomplete');\n }\n\n if (incompleteWorlds || !totalWorlds) {\n this.$('#worlds-status').addClass('incomplete');\n } else {\n this.$('#worlds-status').removeClass('incomplete');\n }\n\n this.$('.status-widget').addClass('visible');\n },\n\n updateControlsForSelection: function () {\n var numSelected = this.$('tbody :checkbox:checked').length;\n this.$('.component.controls')[numSelected ? 'addClass' : 'removeClass']('visible');\n },\n\n updateAutoAssignButton: function () {\n\n if (this.project.isDynamicAssignment()) {\n var hasRoles = this.project.hasRoles();\n this.$('.table-controls .single').hide();\n this.$('.table-controls .dynamic').show();\n this.$('.table-controls .dynamic-no-roles-text')[hasRoles ? 'hide' : 'show']();\n this.$('.table-controls .no-roles')[hasRoles ? 'hide' : 'show']();\n } else {\n this.$('.table-controls .dynamic').hide();\n this.$('.table-controls .dynamic-no-roles-text').hide();\n this.$('.table-controls .single').show();\n this.$('.table-controls .no-roles').show();\n\n }\n\n if (this.users.allUsersAssigned()) {\n this.$('.table-controls').removeClass('visible');\n } else {\n this.$('.table-controls').addClass('visible');\n }\n },\n\n selectAll: function (e) {\n this.$('tbody :checkbox').prop('checked', e.target.checked);\n this.updateControls();\n },\n\n toggleControlls: function (e) {\n var total = this.$('tbody :checkbox');\n var checked = this.$('tbody :checkbox:checked');\n\n if (total.length === checked.length) {\n this.$('#select-all').attr('checked', 'checked');\n } else {\n this.$('#select-all').removeAttr('checked');\n }\n\n this.updateControls();\n },\n\n _showUpdating: function () {\n this.$el.css({ opacity: 0.4 });\n },\n\n _hideUpdating: function () {\n this.$el.css({ opacity: 1 });\n }\n\n};\n\nmodule.exports = Assignment;\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/assignment.js","'use strict';\n\nvar classFrom = require('../../../util/inherit');\n\nvar Model = require('./user-model');\nvar Base = require('./base-collection');\nvar env = require('./defaults');\nvar serviceLocator = require('./service-locator');\n\n\nmodule.exports = classFrom(Base, {\n model: Model,\n\n sortFn: function (a, b) {\n var aw = a.get('world').toLowerCase();\n var bw = b.get('world').toLowerCase();\n if (aw !== bw) {\n return aw < bw ? -1 : 1;\n }\n\n return b.get('userName') > a.get('userName') ? -1 : 1;\n },\n\n initialize: function () {\n const am = new F.manager.AuthManager();\n const session = am.getCurrentUserSessionInfo();\n const token = session.auth_token;\n if (token) {\n $.ajaxSetup({\n headers: {\n Authorization: 'Bearer ' + token\n }\n });\n }\n },\n\n allUsersAssigned: function () {\n return this.all(function (u) {\n return !!u.get('world');\n });\n },\n\n getUnassignedUsersCount: function () {\n return this.filter(function (u) {\n return !u.get('world');\n }).length;\n },\n\n fetch: function () {\n var dtd = $.Deferred();\n var me = this;\n var groupId = env.get().groupId;\n\n var getGroupUsers = function () {\n var memberApi = serviceLocator.memberApi();\n var userApi = serviceLocator.userApi();\n\n var loadGroupMembers = function () {\n return memberApi.getGroupDetails();\n };\n\n var splitIdChunks = function (userIds) {\n var idGroupSize = 100;\n var idGroups = [];\n while (userIds.length >= idGroupSize) {\n idGroups.push(userIds.splice(0, idGroupSize));\n }\n\n if (userIds.length) {\n idGroups.push(userIds);\n }\n\n return idGroups;\n };\n\n var loadUsersInfo = function (group) {\n var nonFacAndActive = function (u) { return u.active && u.role !== 'facilitator'; };\n const endUsers = group.members.filter((m)=> nonFacAndActive(m));\n const endUserIds = endUsers.map((u)=> u.userId);\n var chunkedUsers = splitIdChunks(endUserIds);\n var chunkedPromises = chunkedUsers.map(function (users) {\n return userApi.get({ id: users });\n });\n return $.when.apply($, chunkedPromises).then(function (userGroups) {\n var totalUsers = userGroups.reduce(function (acc, userGroup) {\n return acc.concat(userGroup);\n }, []);\n\n return totalUsers;\n });\n };\n\n return loadGroupMembers()\n .then(loadUsersInfo)\n .fail(dtd.reject);\n };\n\n getGroupUsers()\n .then(function (users) {\n users = users.map(function (u) { return $.extend(u, { groupId: groupId }); });\n me.set(users);\n dtd.resolve(users);\n });\n\n return dtd.promise();\n }\n\n});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/users-collection.js","'use strict';\n\nvar classFrom = require('../../../util/inherit');\nvar Model = require('./world-model');\nvar UserModel = require('./user-model');\nvar serviceLocator = require('./service-locator');\n\nvar Base = require('./base-collection');\nvar __super = Base.prototype;\n\nvar doneFn = function (dtd, after) {\n return _.after(after, dtd.resolve);\n};\n\nvar worldApi;\n\nmodule.exports = classFrom(Base, {\n model: Model,\n\n initialize: function () {\n __super.initialize.apply(this, arguments);\n worldApi = serviceLocator.worldApi();\n },\n\n autoAssignAll: function (options) {\n return worldApi.autoAssign(options)\n .then(function (worlds) {\n this.reset(this.parse(worlds));\n }.bind(this));\n },\n\n getIncompleteWorldsCount: function () {\n return this.filter(function (w) {\n return !w.get('complete');\n }).length;\n },\n\n updateUser: function (user) {\n var worldName = user.get('world');\n var dtd = $.Deferred();\n var prevWorld = this.getWorldByUser(user);\n var curWorld = this.getOrCreateWorld(worldName);\n var done = doneFn(dtd, 1);\n\n // check if there's anything to do\n if (!prevWorld && !curWorld) {\n return dtd.resolve().promise();\n }\n\n if (prevWorld && curWorld && prevWorld.get('id') === curWorld.get('id')) {\n //worlds are the same, but role changed\n return curWorld.updateUser(user);\n }\n if (prevWorld) {\n prevWorld.removeUser(user)\n .then(function () {\n if (curWorld) {\n return curWorld.addUser(user);\n }\n })\n .then(done);\n } else if (curWorld) {\n curWorld.addUser(user)\n .then(done);\n }\n\n return dtd.promise();\n },\n\n getOrCreateWorld: function (worldName) {\n if (!worldName) {\n return;\n }\n\n var world = this.getWordByName(worldName);\n\n if (!world) {\n world = this.create({ name: worldName });\n }\n\n return world;\n },\n\n getWordByName: function (worldName) {\n return this.find(function (world) {\n return world.get('name') === worldName;\n });\n },\n\n getWorldByUser: function (user) {\n if (!user.get) {\n throw new Error('getWorldByUser expectes a model (' + user + ')');\n }\n\n var id = user.get('id');\n return this.getWorldByUserId(id);\n },\n\n getWorldByUserId: function (userId) {\n return this.find(function (world) {\n return _.find(world.get('users'), function (u) {\n return u.get('id') === userId;\n });\n });\n },\n\n getWorldNames: function () {\n return this.pluck('name').sort();\n },\n\n getNextWorldName: function () {\n var pad = function (num, places) {\n var zeros = '000000000000000000';\n var digits = num.toString().length;\n var needed = places - digits;\n return zeros.substr(0, needed) + num;\n };\n\n var worlds = this.getWorldNames();\n\n if (!worlds.length) {\n return 'World001';\n }\n\n var properNames = _.filter(worlds, function (w) { return (/World\\d\\d\\d/).test(w); }).sort();\n var lastWorld = properNames[properNames.length - 1];\n var numWorld = +lastWorld.match(/World(\\d\\d\\d)/)[1];\n var placesToPad = 3;\n return 'World' + pad(numWorld + 1, placesToPad);\n },\n\n setUsersCollection: function (usersCollection) {\n this.usersCollection = usersCollection;\n },\n\n joinUsers: function () {\n var usersHash = {};\n var usersCollection = this.usersCollection;\n usersCollection.each(function (u) {\n u.set({ isWorldComplete: true });\n return (usersHash[u.get('id')] = u);\n });\n\n this.each((w, i)=> {\n var name = w.get('name');\n var isComplete = w.get('complete');\n w.set({ index: i, name: name || (i + 1) + '' });\n _.each(w.get('users'), function (u) {\n if (usersHash[u.get('userId')]) {\n usersHash[u.get('userId')].set({ world: name, role: u.get('role'), isWorldComplete: isComplete });\n }\n });\n });\n\n usersCollection.sort();\n },\n\n fetch: function () {\n return worldApi.list()\n .then(function (worlds) {\n this.reset(this.parse(worlds));\n }.bind(this));\n },\n\n parse: function (worlds) {\n if (worlds.length) {\n worlds = _.map(worlds, function (w) {\n var users = _.map(w.users, function (u) {\n // in the world api users Ids comes as userId\n // make sure we add it as id so we can use the\n // same code to access models that come from the\n // member/local api as with the world api\n u.id = u.userId;\n return new UserModel(u);\n });\n\n w.users = users;\n\n return w;\n });\n }\n\n return worlds;\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/worlds-collection.js","'use strict';\nvar serviceLocator = require('./service-locator');\nvar classFrom = require('../../../util/inherit');\nvar Base = require('./base-model');\nvar __super = Base.prototype;\n\nmodule.exports = classFrom(Base, {\n\n defaults: {\n users: null,\n model: 'model.eqn'\n },\n\n initialize: function () {\n __super.initialize.apply(this, arguments);\n\n this._data.users = this._data.users || [];\n\n this._worldApi = serviceLocator.worldApi();\n\n var id = this.get('id');\n if (id) {\n this._worldApi.updateConfig({ filter: id });\n }\n },\n\n updateUser: function (user) {\n if (!user) {\n throw new Error('updateUser: No user passed to update');\n }\n const userObj = user.toJSON();\n userObj.userId = userObj.id;\n return this._worldApi.updateUser(userObj, { id: this.get('id') });\n },\n\n addUser: function (user) {\n var users = this.get('users');\n users.push(user);\n\n return this.save();\n },\n\n removeUser: function (user) {\n var id = this.get('id');\n var checkWorld = function () {\n if (!this.get('users').length) {\n this.remove();\n return this._worldApi.updateConfig({ filter: id }).delete();\n }\n }.bind(this);\n\n _.remove(this.get('users'), function (u) {\n return u.get('id') === user.get('id');\n });\n\n return this._worldApi\n .updateConfig({ filter: id })\n .removeUser({ userId: user.get('id') })\n .then(checkWorld);\n },\n\n save: function () {\n var me = this;\n var mapUsers = function () {\n return _.map(this.get('users'), function (u) {\n var res = { userId: u.get('id') };\n var role = u.get('role');\n\n if (role) {\n res.role = role;\n }\n\n return res;\n });\n }.bind(this);\n\n var createWorld = _.partial(this._worldApi.create, this.pick(['model', 'name', 'minUsers']));\n var addUsers = _.partial(me._worldApi.addUsers, mapUsers(), { filter: me.get('id') });\n var savedUsers = this.get('users');\n if (this.isNew()) {\n // we need to create the world in the API and then add the users\n return createWorld()\n .then(function (world) {\n me.set(world);\n me._worldApi.updateConfig({ filter: world.id });\n })\n .then(addUsers)\n .then(function (users) {\n // since we re-set the world, re-set the users\n me.set('users', savedUsers);\n });\n } else {\n // the world is already created just add the users\n return addUsers();\n }\n },\n\n isNew: function () {\n return !this.get('lastModified');\n }\n\n});\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/world-model.js","'use strict';\n\nvar serviceLocator = require('./service-locator');\n\nvar classFrom = require('../../../util/inherit');\nvar Base = require('./base-model');\n// var __super = Base.prototype;\n\nmodule.exports = classFrom(Base, {\n\n isDynamicAssignment: function () {\n return this.get('worlds') === 'dynamic';\n },\n\n hasRoles: function () {\n var roles = this.get('roles');\n return roles && !!roles.length;\n },\n\n fetch: function () {\n var api = serviceLocator.worldApi();\n\n return api.getProjectSettings().then(function (settings) {\n this.set(settings);\n }.bind(this));\n }\n});\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/project-model.js","const userRowTemplate = `\n \" | \n <%= !isWorldComplete ? '' : '' %> | \n <%= world %> | \n <%= role %> | \n <%= lastName %> | \n <%= userName %> | \n <%= !world ? '' : '' %> | \n | \n`.trim();\nconst editUserRowTemplate = `\n \" | \n | \n \n \n | \n \n \n | \n <%= lastName %> | \n <%= userName %> | \n <%= !world ? '' : '' %> | \n \n \n \n | \n`;\n\nvar AssignmentRow = function (options) {\n this.$el = $('
');\n this.el = this.$el[0];\n this.$ = _.partialRight($, this.$el);\n\n this.model = options.model;\n this.options = options;\n this.worlds = options.worlds;\n this.project = options.project;\n\n _.bindAll(this, ['setEditMode', 'removeEditMode', 'saveEdit', 'cancelEdit', 'updateData']);\n\n this.bindEvents();\n\n};\n\n_.extend(AssignmentRow.prototype, {\n\n template: _.template(userRowTemplate),\n editTemplate: _.template(editUserRowTemplate),\n\n bindEvents: function () {\n this.$el.on('click', 'button.edit', this.setEditMode);\n this.$el.on('click', 'button.save', this.saveEdit);\n this.$el.on('click', 'button.cancel', this.cancelEdit);\n },\n\n remove: function () {\n this.$el.off('click', null, null);\n // this only gives a delay to remove the tr\n // animation of height of the tr does not work\n this.$(':checkbox').attr('checked', false);\n this.$el\n .css({ opacity: 0.3 })\n .animate({ height: 0 }, {\n duration: 300,\n complete: function () {\n this.remove();\n }\n });\n },\n\n makeInactive: function () {\n return this.model.makeInactive();\n },\n\n setEditMode: function () {\n this.model.set('edit-mode', true);\n this.render();\n },\n\n removeEditMode: function () {\n this.model.set('edit-mode', false);\n this.render();\n },\n\n saveEdit: function () {\n var me = this;\n this.updateData();\n this.worlds\n .updateUser(this.model)\n .then(function () {\n me.removeEditMode();\n me.$el.trigger('update', me);\n });\n },\n\n cancelEdit: function () {\n this.removeEditMode();\n },\n\n render: function () {\n var templ = this.model.get('edit-mode') ? this.editTemplate : this.template;\n var vm = _.extend({\n roles: this.project.get('roles'),\n optionalRoles: this.project.get('optionalRoles'),\n worlds: this.worlds.getWorldNames(),\n newWorld: this.worlds.getNextWorldName()\n }, this.model.toJSON());\n\n this.$el.html(templ(vm));\n\n return this;\n },\n\n updateData: function () {\n var me = this;\n this.$('[data-field]').each(function () {\n var el = $(this);\n var field = el.data('field');\n var val = el.val();\n\n me.model.set(field, val);\n });\n }\n});\n\n\nexport default AssignmentRow;\n\n\n// WEBPACK FOOTER //\n// ./src/components/assignment/js/assignment-row.js","'use strict';\n\n/**\n* Utility class to make ajax calls sequencial\n*/\nfunction AjaxQueue() {\n this.queue = [];\n}\n\n$.extend(AjaxQueue.prototype, {\n add: function (fn) {\n return this.queue.push(fn);\n },\n\n execute: function (context) {\n var dtd = $.Deferred();\n var me = this;\n context = context || this;\n\n function next() {\n if (me.queue.length) {\n var fn = me.queue.shift();\n\n fn.call(context)\n .then(next)\n .fail(dtd.reject);\n } else {\n dtd.resolve();\n }\n }\n\n next();\n\n return dtd.promise();\n }\n});\n\n\nmodule.exports = AjaxQueue;\n\n\n// WEBPACK FOOTER //\n// ./src/util/ajax-queue.js"],"sourceRoot":""}
\ No newline at end of file
diff --git a/dist/components/login/index.html b/dist/components/login/index.html
index 445f7a6a..5d30f7c8 100644
--- a/dist/components/login/index.html
+++ b/dist/components/login/index.html
@@ -35,13 +35,20 @@
Please Login to this Simulation
-
+
-
+
+
diff --git a/dist/components/login/login.css b/dist/components/login/login.css
index e467bbb3..f0f61a3a 100644
--- a/dist/components/login/login.css
+++ b/dist/components/login/login.css
@@ -282,3 +282,10 @@ body {
background-position: 50%;
}
+
+.error-text {
+ display: none;
+}
+.has-error .error-text {
+ display: block;
+}
\ No newline at end of file
diff --git a/dist/components/login/login.js b/dist/components/login/login.js
index d0660179..c9b87769 100644
--- a/dist/components/login/login.js
+++ b/dist/components/login/login.js
@@ -23,7 +23,7 @@ $(function () {
select.find('[value!=""]').remove();
$.each(groups, function () {
$('