From f317f95a7a1fed2c4f490eef58b2fce834762335 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Sat, 1 Sep 2018 06:25:23 +0200 Subject: [PATCH 01/19] Show offline Activities and smaller menu for offline activities --- app/views/view/data.jade | 7 ++++--- app/views/view/data/menu.jade | 4 ++-- app/views/view/home.jade | 7 ++++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/views/view/data.jade b/app/views/view/data.jade index 03d22c5..15d136b 100644 --- a/app/views/view/data.jade +++ b/app/views/view/data.jade @@ -32,10 +32,11 @@ a(href="#", editable-text="activity.name" onaftersave="changeActivityName()") Activity {{ activity.name }} a(ng-if='isStudent()') Activity {{ activity.name }} span(ng-if='isTeacher()' style='float: right; margin-top: 5px; font-size: 0.70em;') - button.btn-success(ng-if='activityState() == 2' ng-click='endActivity()') Opened - button.btn-warning(ng-if='activityState() == 0' ng-click='startActivity()') Closed - button.btn-info(ng-if='activityState() == 1') Loading  + button.btn-success(ng-if='activityState() == 2 && isOnlineActivityParam(activity)' ng-click='endActivity()') Opened + button.btn-warning(ng-if='activityState() == 0 && isOnlineActivityParam(activity)' ng-click='startActivity()') Closed + button.btn-info(ng-if='activityState() == 1 && isOnlineActivityParam(activity)') Loading span.fa.fa-refresh.fa-spin + p.btn-info(ng-if='isOfflineActivityParam(activity)') Offline Activity .panel-body.tabled(ng-if='game && version' style='padding-top: 0px') block dataMenu .row.row-tabled diff --git a/app/views/view/data/menu.jade b/app/views/view/data/menu.jade index 1aa571f..088509b 100644 --- a/app/views/view/data/menu.jade +++ b/app/views/view/data/menu.jade @@ -20,11 +20,11 @@ ul.nav span.left-menu-item(href="#info", role="tab", data-toggle="tab", ng-click="view = 'info'") span.glyphicon.glyphicon-info-sign.right20 | Information - li(ng-if='isTeacher()') + li(ng-if='isTeacher() && isOnlineActivity()') span.left-menu-item(href="#participants", role="tab", data-toggle="tab", ng-click="view = 'participants'") span.glyphicon.glyphicon-apple.right20 | Participants - li + li(ng-if='isDeveloper() || isOnlineActivity()') span.left-menu-item(href="#attempts", role="tab", data-toggle="tab", ng-click="view = 'attempts'") span.glyphicon.glyphicon-tasks.right20 | Attempts diff --git a/app/views/view/home.jade b/app/views/view/home.jade index 3073a0c..f5f29da 100644 --- a/app/views/view/home.jade +++ b/app/views/view/home.jade @@ -60,10 +60,11 @@ a(ng-href='#', ng-click='goToClass(getClassById(localactivity.classId))') {{ getClassById(localactivity.classId).name }} td {{localactivity._id | prettyDateId }} td(ng-if='isTeacher()') - button.btn-success(ng-if='activityState() == 2' ng-click='endActivity()') Opened - button.btn-warning(ng-if='activityState() == 0' ng-click='startActivity()') Closed - button.btn-info(ng-if='activityState() == 1') Loading + button.btn-success(ng-if='activityState() == 2 && isOnlineActivityParam(localactivity)' ng-click='endActivity()') Opened + button.btn-warning(ng-if='activityState() == 0 && isOnlineActivityParam(localactivity)' ng-click='startActivity()') Closed + button.btn-info(ng-if='activityState() == 1 && isOnlineActivityParam(localactivity)') Loading span.fa.fa-refresh.fa-spin + p.btn-info(ng-if='isOfflineActivityParam(localactivity)') Offline Activity td(ng-if='isTeacher()') a(ng-click='deleteActivity(localactivity)') span.glyphicon.glyphicon-remove-sign From 795f920b2e96e425ec795e5f3194803f6c64eea1 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Sat, 1 Sep 2018 06:25:56 +0200 Subject: [PATCH 02/19] Class activity Displays modal when creating an activity --- app/public/js/controllers/activity-list.js | 8 +++++++ app/public/js/controllers/app.js | 16 +++++++++++++ app/views/view/classactivity.jade | 26 ++++++++++++++++++---- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/app/public/js/controllers/activity-list.js b/app/public/js/controllers/activity-list.js index d79146c..bec47e8 100644 --- a/app/public/js/controllers/activity-list.js +++ b/app/public/js/controllers/activity-list.js @@ -126,6 +126,14 @@ angular.module('activitiesApp', ['ngStorage', 'services']) activity.gameId = gameId; activity.versionId = versionId; activity.classId = classId; + + if ($('#offline').is(":checked")) { + activity.offline = true; + activity.allowAnonymous = true; + } else { + activity.offline = false; + activity.allowAnonymous = false; + } activity.$save().then(function() { $http.get(CONSTANTS.PROXY + '/kibana/visualization/list/tch/' + gameId) .success(function (data) { diff --git a/app/public/js/controllers/app.js b/app/public/js/controllers/app.js index 4d0b320..fa9c62c 100644 --- a/app/public/js/controllers/app.js +++ b/app/public/js/controllers/app.js @@ -139,6 +139,22 @@ angular.module('myApp', [ return Role.isTeacher(); }; + $scope.isOfflineActivity = function () { + return $scope.isOfflineActivityParam($scope.selectedActivity); + }; + + $scope.isOnlineActivity = function () { + return $scope.isOnlineActivityParam($scope.selectedActivity); + }; + + $scope.isOfflineActivityParam = function (activity) { + return activity && activity.offline; + }; + + $scope.isOnlineActivityParam = function (activity) { + return activity && !activity.offline; + }; + $scope.isDeveloper = function () { return Role.isDeveloper(); }; diff --git a/app/views/view/classactivity.jade b/app/views/view/classactivity.jade index a4b5942..e36771c 100644 --- a/app/views/view/classactivity.jade +++ b/app/views/view/classactivity.jade @@ -13,6 +13,23 @@ limitations under the License. .container.theme-showcase(ng-if='selectedClass' ng-controller='ClassCtrl' ng-attr-classid='{{ selectedClass._id }}') div(ng-controller='ActivityListCtrl', ng-attr-classid='{{ class._id }}' ng-class='(isTeacher() ? "col-md-8" : "col-md-12")') + #normalModal(class="modal fade") + div(class="modal-dialog") + div(class="modal-content") + div(class="modal-header") + button(type="button" class="close" data-dismiss="modal" aria-hidden="true") × + h4(class="modal-title") What type of activity do you want to create? + div(class="modal-body") + .container + .row + input(id= "online" type="radio", name="symbol" value="online" checked) + = " online" + .row + input(id= "offline" type="radio", name="symbol" value="offline") + = " offline" + div(class="modal-footer") + button(type="button" class="btn btn-default" data-dismiss="modal") Close + button(type="button" ng-click="createActivity()" class="btn btn-primary") Submit .panel.panel-default .panel-heading h1(ng-if='isTeacher()') @@ -28,7 +45,7 @@ label Game: select.form-control(ng-model='activity.gameId') option(ng-repeat='game in games' value='{{ game._id }}') {{ game.title }} - a.btn.btn-primary(type='button', ng-click='createActivity()') + a.btn.btn-primary(type='button', data-toggle="modal" href="#normalModal" class="btn btn-default") span.glyphicon.glyphicon-plus.right10 | New activity p.btn-danger {{activityCreatedError}} @@ -53,10 +70,11 @@ a(ng-href='#', ng-click='goToGame(getGameById(activity.gameId))') {{ getGameById(activity.gameId).title }} td {{activity._id | prettyDateId }} td(ng-if='isTeacher()', ng-controller='ActivityCtrl' lite activity='{{ activity }}') - button.btn-success(ng-if='activityState() == 2' ng-click='endActivity()') Opened - button.btn-warning(ng-if='activityState() == 0' ng-click='startActivity()') Closed - button.btn-info(ng-if='activityState() == 1') Loading + button.btn-success(ng-if='activityState() == 2 && isOnlineActivityParam(activity)' ng-click='endActivity()') Opened + button.btn-warning(ng-if='activityState() == 0 && isOnlineActivityParam(activity)' ng-click='startActivity()') Closed + button.btn-info(ng-if='activityState() == 1 && isOnlineActivityParam(activity)') Loading span.fa.fa-refresh.fa-spin + p.btn-info(ng-if='isOfflineActivityParam(activity)') Offline Activity td(ng-if='isTeacher()') a(ng-click='deleteActivity(activity)') span.glyphicon.glyphicon-remove-sign From 0cee529c99a252a1451d4007579a43f321403e64 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Sat, 1 Sep 2018 06:26:18 +0200 Subject: [PATCH 03/19] View and controller for uploading CSV files as traces files --- app/public/js/controllers/activity-list.js | 2 +- app/public/js/controllers/activity.js | 113 +++++++++++++++++---- app/views/view/data/information.jade | 27 ++++- 3 files changed, 123 insertions(+), 19 deletions(-) diff --git a/app/public/js/controllers/activity-list.js b/app/public/js/controllers/activity-list.js index bec47e8..40e2ca4 100644 --- a/app/public/js/controllers/activity-list.js +++ b/app/public/js/controllers/activity-list.js @@ -127,7 +127,7 @@ angular.module('activitiesApp', ['ngStorage', 'services']) activity.versionId = versionId; activity.classId = classId; - if ($('#offline').is(":checked")) { + if ($('#offline').is(':checked')) { activity.offline = true; activity.allowAnonymous = true; } else { diff --git a/app/public/js/controllers/activity.js b/app/public/js/controllers/activity.js index 7903f8a..bbdb774 100644 --- a/app/public/js/controllers/activity.js +++ b/app/public/js/controllers/activity.js @@ -19,7 +19,7 @@ 'use strict'; angular.module('activityApp', ['myApp', 'ngStorage', 'services']) - .factory('_', ['$window', function($window) { + .factory('_', ['$window', function ($window) { return $window._; }]) .config(['$locationProvider', @@ -33,6 +33,20 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) new ColumnProgress(angular.element(element).children('.score-marker')[0], scope.result.score); }; }) + .directive('fileModel', ['$parse', function ($parse) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + var model = $parse(attrs.fileModel); + var modelSetter = model.assign; + element.bind('change', function () { + scope.$apply(function () { + modelSetter(scope, element[0].files[0]); + }); + }); + } + }; + }]) .controller('ActivityCtrl', ['$rootScope', '$scope', '$attrs', '$location', '$http', 'Activities', 'Classes', '_', 'Results', 'Versions', 'Groups', 'Groupings', '$sce', '$interval', 'Role', 'CONSTANTS', function ($rootScope, $scope, $attrs, $location, $http, Activities, Classes, _, Results, @@ -43,8 +57,8 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) var groupingsReady = false; var classReady = false; $scope.class = {}; - var onSetActivity = function() { - Classes.get({classId: $scope.activity.classId}).$promise.then(function(c) { + var onSetActivity = function () { + Classes.get({classId: $scope.activity.classId}).$promise.then(function (c) { classReady = true; $scope.class = c; if ($scope.activity.groupings && $scope.activity.groupings.length > 0) { @@ -93,7 +107,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) }; var updateGroups = function () { - var route = CONSTANTS.PROXY + '/classes/' + $scope.class._id + '/groups'; + var route = CONSTANTS.PROXY + '/classes/' + $scope.class._id + '/groups'; $http.get(route).success(function (data) { $scope.classGroups = data; }).error(function (data, status) { @@ -112,24 +126,26 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) }); }; - $scope.$on('$destroy', function() { + $scope.$on('$destroy', function () { if (refresh) { $interval.cancel(refresh); } }); - $attrs.$observe('activityid', function() { + $attrs.$observe('activityid', function () { $scope.activity = Activities.get({activityId: $attrs.activityid}, onSetActivity); + updateOfflineTraces(); }); - $attrs.$observe('activity', function() { + $attrs.$observe('activity', function () { groupsReady = false; groupingsReady = false; classReady = false; $scope.activity = JSON.parse($attrs.activity); - Activities.get({activityId: $scope.activity._id}).$promise.then(function(a) { + Activities.get({activityId: $scope.activity._id}).$promise.then(function (a) { $scope.activity = a; onSetActivity(); + updateOfflineTraces(); }); }); @@ -252,6 +268,68 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) $scope.iframeDashboardUrl = dashboardLink(); }; + + function updateOfflineTraces() { + if ($scope.activity) { + $http.get(CONSTANTS.PROXY + '/offlinetraces/' + $scope.activity._id, { + transformRequest: angular.identity, + headers: { + 'Content-Type': undefined, + enctype: 'multipart/form-data' + } + }).then(function successCallback(response) { + // This callback will be called asynchronously + // when the response is available + + // Check if the version has an analysis uploaded + + $scope.offlinetraces = response.data; + console.log('offline tracess!!'); + console.info($scope.offlinetraces); + }, function errorCallback(response) { + // Called asynchronously if an error occurs + // or server returns response with an error status. + console.error('Error on get /offlinetraces/' + $scope.activity._id + ' ' + + JSON.stringify(response, null, ' ')); + + // Check if the version has an analysis uploaded + }); + } + } + + function upload(file) { + var formData = new FormData(); + formData.append('offlinetraces', file); + $http.post(CONSTANTS.PROXY + '/offlinetraces/' + $scope.activity._id, formData, { + transformRequest: angular.identity, + headers: { + 'Content-Type': undefined, + enctype: 'multipart/form-data' + } + }).then(function successCallback(response) { + // This callback will be called asynchronously + // when the response is available + + // Check if the version has an analysis uploaded + updateOfflineTraces(); + }, function errorCallback(response) { + // Called asynchronously if an error occurs + // or server returns response with an error status. + console.error('Error on post /offlinetraces/' + $scope.activity._id + ' ' + + JSON.stringify(response, null, ' ')); + + // Check if the version has an analysis uploaded + }); + } + + $scope.myFile = undefined; + $scope.uploadTracesFile = function () { + if ($scope.myFile) { + console.log('upload 3 ' + $scope.myFile); + upload($scope.myFile); + } + }; + // Anonymous $scope.anonymous = 'btn-default'; @@ -278,7 +356,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) return !$scope.isUsingGroupings() && $scope.activity.groups && $scope.activity.groups.length > 0; }; - $scope.unlockGroups = function() { + $scope.unlockGroups = function () { var route = CONSTANTS.PROXY + '/activities/' + $scope.activity._id + '/remove'; if ($scope.unlockedGroupings) { $http.put(route, {groupings: $scope.activity.groupings}).success(function (data) { @@ -302,7 +380,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) } }; - $scope.unlockGroupings = function() { + $scope.unlockGroupings = function () { var route = CONSTANTS.PROXY + '/activities/' + $scope.activity._id + '/remove'; if ($scope.unlockedGroups) { $http.put(route, {groups: $scope.activity.groups}).success(function (data) { @@ -356,7 +434,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) $scope.selectedGroup = undefined; }; - $scope.getGroupThClass = function(group) { + $scope.getGroupThClass = function (group) { if ($scope.selectedGroup && $scope.selectedGroup._id === group._id) { return 'bg-success'; } @@ -366,7 +444,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) return ''; }; - $scope.getUserThClass = function(usr, role) { + $scope.getUserThClass = function (usr, role) { if ($scope.selectedGroup && $scope.isInSelectedGroup(usr, role)) { return 'bg-success'; } @@ -426,7 +504,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) // Name $scope.changeActivityName = function () { - $scope.activity.$update(function() { + $scope.activity.$update(function () { $rootScope.$broadcast('refreshClasses'); }); }; @@ -450,14 +528,15 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) return $scope.activity.start && !$scope.activity.end ? 2 : 0; }; - $scope.$on('refreshActivity', function(evt, activity) { + $scope.$on('refreshActivity', function (evt, activity) { if ($scope.activity._id === activity._id) { $scope.activity = activity; + updateOfflineTraces(); console.log('Activity updated'); } }); - var finishEvent = function(activity) { + var finishEvent = function (activity) { $scope.activity = activity; $rootScope.$broadcast('refreshActivity', $scope.activity); }; @@ -471,7 +550,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) console.error(error); $.notify('Error while opening the activity:
If the session was recently closed it ' + 'might need to be cleaned by the system.
Please try again in a few seconds.', { - offset: { x: 10, y: 65 }, + offset: {x: 10, y: 65}, type: 'danger'// jscs:ignore requireCamelCaseOrUpperCaseIdentifiers }); $rootScope.$broadcast('refreshActivity', $scope.activity); @@ -486,7 +565,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) $scope.activity.$event({event: 'end'}).$promise.then(finishEvent).fail(function (error) { console.error(error); $.notify('Error while closing the activity:
Please try again in a few seconds.', { - offset: { x: 10, y: 65 }, + offset: {x: 10, y: 65}, type: 'danger'// jscs:ignore requireCamelCaseOrUpperCaseIdentifiers }); $rootScope.$broadcast('refreshActivity', $scope.activity); diff --git a/app/views/view/data/information.jade b/app/views/view/data/information.jade index ff891e7..b80910e 100644 --- a/app/views/view/data/information.jade +++ b/app/views/view/data/information.jade @@ -17,7 +17,7 @@ .container-fluid.theme-showcase h1 Information - .row + .row(ng-if='!isOfflineActivity()') .col-xs-12 | Game link: a(href='{{ game.link }}') {{ game.link }} @@ -25,6 +25,31 @@ | Tracking code: kbd.left10(ng-if='isDeveloper()') {{ version.trackingCode }} kbd.left10(ng-if='isTeacher()') {{ activity.trackingCode }} + .row(ng-if='isTeacher() && isOfflineActivity()') + hr + .col-xs-12(ng-controller='ActivityCtrl') + label Select a CSV traces file: + input(type="file" file-model="myFile") + button.btn.btn-primary.top5(type='submit', ng-click='uploadTracesFile()') Upload trace file + .row + .col-md-12 + table.table.table-hover + thead + tr + th Trace file + th Time uploaded + th Author + tbody + tr(ng-if='!offlinetraces || offlinetraces.length === 0') + td(colspan=6) + div.alert.alert-warning(style='margin-bottom: 0px') No trace files found + tr(ng-repeat='tracefile in offlinetraces') + td + label {{tracefile.name}} + td + label {{tracefile._id | prettyDateId }} + td + label {{tracefile.author }} .row(ng-if='isDeveloper()') hr .col-xs-12 From 9cf0b8f552cf2f900385bf1e0f7062a0554dae47 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Sun, 2 Sep 2018 05:56:41 +0200 Subject: [PATCH 04/19] Modal actiity type dialog added to homepage --- app/public/js/controllers/activity-list.js | 3 ++- app/views/view/classactivity.jade | 15 +++++++++------ app/views/view/home.jade | 22 +++++++++++++++++++++- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/app/public/js/controllers/activity-list.js b/app/public/js/controllers/activity-list.js index 40e2ca4..a86657b 100644 --- a/app/public/js/controllers/activity-list.js +++ b/app/public/js/controllers/activity-list.js @@ -120,6 +120,7 @@ angular.module('activitiesApp', ['ngStorage', 'services']) }; + $scope.offline = false; var doCreateActivity = function(activityName, gameId, versionId, classId) { var activity = new Activities(); activity.name = activityName; @@ -127,7 +128,7 @@ angular.module('activitiesApp', ['ngStorage', 'services']) activity.versionId = versionId; activity.classId = classId; - if ($('#offline').is(':checked')) { + if ($scope.offline) { activity.offline = true; activity.allowAnonymous = true; } else { diff --git a/app/views/view/classactivity.jade b/app/views/view/classactivity.jade index e36771c..a2c307f 100644 --- a/app/views/view/classactivity.jade +++ b/app/views/view/classactivity.jade @@ -21,12 +21,15 @@ h4(class="modal-title") What type of activity do you want to create? div(class="modal-body") .container - .row - input(id= "online" type="radio", name="symbol" value="online" checked) - = " online" - .row - input(id= "offline" type="radio", name="symbol" value="offline") - = " offline" + .row.form-group + button.btn-default.role-button.col-sm-2(ng-click='offline = false' ng-class="{'active': offline==='false'}") + i.fa.fa-cloud.fa-5x + br + label online + button.btn-primary.role-button.col-sm-2(ng-click='offline = true' ng-class="{'active': offline==='true'}") + i.fa.fa-code.fa-5x + br + label Offline div(class="modal-footer") button(type="button" class="btn btn-default" data-dismiss="modal") Close button(type="button" ng-click="createActivity()" class="btn btn-primary") Submit diff --git a/app/views/view/home.jade b/app/views/view/home.jade index f5f29da..68dd812 100644 --- a/app/views/view/home.jade +++ b/app/views/view/home.jade @@ -19,6 +19,26 @@ .theme-showcase(ng-if='!isDeveloper()').col-md-12 //- Activities .panel.panel-default(ng-controller='ActivityListCtrl', ng-init='init()') + #normalModal(class="modal fade") + div(class="modal-dialog") + div(class="modal-content") + div(class="modal-header") + button(type="button" class="close" data-dismiss="modal" aria-hidden="true") × + h4(class="modal-title") What type of activity do you want to create? + div(class="modal-body") + .container + .row.form-group + button.btn-default.role-button.col-sm-2(ng-click='offline = false' ng-class="{'active': offline==='false'}") + i.fa.fa-cloud.fa-5x + br + label online + button.btn-primary.role-button.col-sm-2(ng-click='offline = true' ng-class="{'active': offline==='true'}") + i.fa.fa-code.fa-5x + br + label Offline + div(class="modal-footer") + button(type="button" class="btn btn-default" data-dismiss="modal") Close + button(type="button" ng-click="createActivity()" class="btn btn-primary") Submit .panel-heading My Activities .panel-body .panel.panel-primary(ng-if='isTeacher()') @@ -32,7 +52,7 @@ label Class: select.form-control(ng-model='activity.classId') option(ng-repeat='class in classes' value='{{ class._id }}') {{ class.name }} - a.btn.btn-primary(type='button', ng-click='createActivity()') + a.btn.btn-primary(type='button' data-toggle="modal" href="#normalModal" class="btn btn-default") span.glyphicon.glyphicon-plus.right10 | New activity p.btn-danger {{activityCreatedError}} From 39c56fe79f3b9304fa68b82c3de53f6f14b062e0 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Fri, 14 Sep 2018 17:53:34 +0200 Subject: [PATCH 05/19] Improve modal (activity creation) and modal height --- app/public/css/app.css | 15 +++++++++++++++ app/views/view/home.jade | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/public/css/app.css b/app/public/css/app.css index 9fbc3bb..81ca9c0 100644 --- a/app/public/css/app.css +++ b/app/public/css/app.css @@ -4,6 +4,21 @@ html, body { height:100vh; } +.modal-dialog-full { + width: 98%; + height: 92%; + padding: 0; +} + +.modal-content-full { + margin-bottom: 10px; +} + +.btn-space { + margin-right: 10px; + margin-left: 10px; +} + .left-menu { padding-left: 0px; padding-right: 0px; diff --git a/app/views/view/home.jade b/app/views/view/home.jade index 68dd812..9b8a412 100644 --- a/app/views/view/home.jade +++ b/app/views/view/home.jade @@ -38,7 +38,7 @@ label Offline div(class="modal-footer") button(type="button" class="btn btn-default" data-dismiss="modal") Close - button(type="button" ng-click="createActivity()" class="btn btn-primary") Submit + button(type="button" ng-click="createActivity()" data-dismiss="modal" class="btn btn-primary") Submit .panel-heading My Activities .panel-body .panel.panel-primary(ng-if='isTeacher()') From 65c5e177120500db38c99c2e578d60fc364a8fc7 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Fri, 14 Sep 2018 17:54:02 +0200 Subject: [PATCH 06/19] ClassActivity View fixed irregular bugs --- app/views/view/classactivity.jade | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/app/views/view/classactivity.jade b/app/views/view/classactivity.jade index a2c307f..5862928 100644 --- a/app/views/view/classactivity.jade +++ b/app/views/view/classactivity.jade @@ -12,6 +12,15 @@ See the License for the specific language governing permissions and limitations under the License. .container.theme-showcase(ng-if='selectedClass' ng-controller='ClassCtrl' ng-attr-classid='{{ selectedClass._id }}') + #dashboardModal(class="modal fade") + div.modal-dialog-full(class="modal-dialog") + div.modal-content-full(class="modal-content") + div(class="modal-header") + button(type="button" class="close" data-dismiss="modal" aria-hidden="true") × + h4(class="modal-title") Class dashboard displaying activities visualizations + div(class="modal-body ") + iframe#dashboardIframe.no-border(ng-src = "{{dashboardLink}}" scrolling="no" width="100%" height="100%") + script(src='./js/iresizer.js') div(ng-controller='ActivityListCtrl', ng-attr-classid='{{ class._id }}' ng-class='(isTeacher() ? "col-md-8" : "col-md-12")') #normalModal(class="modal fade") div(class="modal-dialog") @@ -32,12 +41,16 @@ label Offline div(class="modal-footer") button(type="button" class="btn btn-default" data-dismiss="modal") Close - button(type="button" ng-click="createActivity()" class="btn btn-primary") Submit + button(type="button" ng-click="createActivity()" data-dismiss="modal" class="btn btn-primary") Submit .panel.panel-default .panel-heading - h1(ng-if='isTeacher()') - a(href="#", editable-text="class.name" onaftersave="changeName()") Class {{ class.name }} - h1(ng-if='!isTeacher()') Class {{ class.name }} + .row + h1(ng-if='isTeacher()') + a.btn-space(href="#", editable-text="class.name" onaftersave="changeName()") Class {{ class.name }} + button.btn.btn-primary.btn-space(data-toggle="modal" href="#dashboardModal") Dashboard + button.btn.btn-primary.btn-space + i.fa.fa-external-link(ng-click='popDashboard()') + h1(ng-if='!isTeacher()') Class {{ class.name }} .panel-body .panel.panel-primary(ng-if='isTeacher()') @@ -48,11 +61,12 @@ label Game: select.form-control(ng-model='activity.gameId') option(ng-repeat='game in games' value='{{ game._id }}') {{ game.title }} - a.btn.btn-primary(type='button', data-toggle="modal" href="#normalModal" class="btn btn-default") + a.btn.btn-primary.btn-space(type='button', data-toggle="modal" href="#normalModal" class="btn btn-default") span.glyphicon.glyphicon-plus.right10 | New activity p.btn-danger {{activityCreatedError}} p.btn-danger {{activityOpenedError}} + p.btn-danger {{activityOpenedError}} table.table.table-hover thead tr @@ -359,4 +373,4 @@ span.glyphicon(ng-class='$scope.class.groupings.indexOf(grouping._id)===-1 ? "glyphicon-unchecked" : "glyphicon-saved"') td a(ng-click='$scope.removeGrouping(grouping)') -span.glyphicon.glyphicon-remove-sign \ No newline at end of file + span.glyphicon.glyphicon-remove-sign \ No newline at end of file From 03dfe0eceb11ecd67b53f94e312cfd0e9bcd809a Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Fri, 14 Sep 2018 17:54:26 +0200 Subject: [PATCH 07/19] Dashboard link 3 weeks timeframe --- app/public/js/controllers/class-list.js | 119 +++++++++++++++++++----- 1 file changed, 97 insertions(+), 22 deletions(-) diff --git a/app/public/js/controllers/class-list.js b/app/public/js/controllers/class-list.js index a8881ef..bfe9bb3 100644 --- a/app/public/js/controllers/class-list.js +++ b/app/public/js/controllers/class-list.js @@ -19,7 +19,8 @@ 'use strict'; angular.module('classesApp', ['ngStorage', 'services']) - .controller('ClassListCtrl', ['$scope', '$rootScope', '$location', '$http', 'Classes', 'Courses', '$timeout', 'CONSTANTS', + .controller('ClassListCtrl', ['$scope', '$rootScope', '$location', '$http', 'Classes', 'Courses', + '$timeout', 'CONSTANTS', function ($scope, $rootScope, $location, $http, Classes, Courses, $timeout, CONSTANTS) { $scope.activity = {}; $scope.courseId = {}; @@ -30,19 +31,19 @@ angular.module('classesApp', ['ngStorage', 'services']) $scope.editBoxCourse = {}; $scope.coursesTitles = {}; - $scope.goToClass = function(c) { - $rootScope.$broadcast('selectClass', { class: c}); + $scope.goToClass = function (c) { + $rootScope.$broadcast('selectClass', {class: c}); }; var getClasses = function () { - Classes.my().$promise.then(function(classes) { + Classes.my().$promise.then(function (classes) { $scope.classes = classes; refreshCoursesTitles(); }); }; var getCourses = function () { - $scope.courses = Courses.all().$promise.then(function(courses) { + $scope.courses = Courses.all().$promise.then(function (courses) { $scope.courses = courses; $scope.courses.unshift({_id: 'NEW', title: 'New Course'}); $scope.courses.unshift({title: 'No Course'}); @@ -54,7 +55,7 @@ angular.module('classesApp', ['ngStorage', 'services']) getCourses(); $scope.loading = false; - var refreshCoursesTitles = function() { + var refreshCoursesTitles = function () { if ($scope.courses && $scope.classes) { $scope.classes.forEach(function (cl) { $scope.coursesTitles[cl.courseId] = 'No Course'; @@ -73,22 +74,96 @@ angular.module('classesApp', ['ngStorage', 'services']) $scope.createClass = function () { var c = new Classes(); c.name = $scope.class.name ? $scope.class.name : 'New class'; - c.$save().then(function() { + c.$save().then(function () { $rootScope.$broadcast('refreshClasses'); - $scope.goToClass(c); + + $http.get(CONSTANTS.PROXY + '/kibana/classvis/') + .success(function (data) { + var panels = []; + var uiStates = {}; + + // Add index + + $http.post(CONSTANTS.PROXY + '/kibana/classindex/' + c._id, {}) + .success(function (data) { + + }).error(function (data, status) { + console.error('Error on post /kibana/classindex/' + c._id + ' ' + + JSON.stringify(data) + ', status: ' + status); + }); + + + // Add dashboard + var numPan = 1; + if (data.length > 0) { + data.forEach(function (visualization) { + $http.post(CONSTANTS.PROXY + '/kibana/visualization/class/' + c._id, visualization).success(function (result) { + console.log('updated visualization'); + console.info(visualization); + console.log('result'); + console.info(result); + panels.push('{\"id\":\"' + result._id + + '\",\"type\":\"visualization\",\"panelIndex\":' + numPan + ',' + + '\"size_x\":6,\"size_y\":4,\"col\":' + (1 + (numPan - 1 % 2)) + ',\"row\":' + + (numPan + 1 / 2) + '}'); + uiStates['P-' + numPan] = {vis: {legendOpen: false}}; + numPan++; + + if (numPan > data.length) { + var dashboard = { + title: 'dashboard_' + c._id, + hits: 0, + description: '', + panelsJSON: '[' + panels.toString() + ']', + optionsJSON: '{"darkTheme":false}', + uiStateJSON: JSON.stringify(uiStates), + version: 1, + timeRestore: true, + timeTo: 'now', + timeFrom: 'now-12w', + refreshInterval: { + display: '60 seconds', + pause: false, + section: 1, + value: 60000 + }, + kibanaSavedObjectMeta: { + searchSourceJSON: '{"filter":[{"query":{"query_string":{"query":"*","analyze_wildcard":true}}}]}' + } + }; + $http.post(CONSTANTS.PROXY + '/kibana/dashboard/class/' + c._id, dashboard) + .success(function (data) { + $scope.goToClass(c); + }).error(function (data, status) { + console.error('Error on post /kibana/dashboard/class/' + c._id + ' ' + + JSON.stringify(data) + ', status: ' + status); + }); + } + }).error(function (data, status) { + console.error('Error on post /kibana/visualization/class/' + c._id + ' ' + + JSON.stringify(data) + ', status: ' + status); + }); + }); + } else { + $scope.goToClass(c); + } + }).error(function (data, status) { + console.error('Error on get /kibana/classvis/' + + JSON.stringify(data) + ', status: ' + status); + }); }); }; - $scope.editBox = function(classObj) { + $scope.editBox = function (classObj) { return $scope.editBoxCourse[classObj._id]; }; - $scope.showSelectBox = function(classObj) { + $scope.showSelectBox = function (classObj) { return $scope.editCourse[classObj._id]; }; $scope.editCourseClass = function (classObj) { - Object.keys($scope.editCourse).forEach(function(key) { + Object.keys($scope.editCourse).forEach(function (key) { $scope.editCourse[key] = false; $scope.editBoxCourse[classObj._id] = false; }); @@ -100,7 +175,7 @@ angular.module('classesApp', ['ngStorage', 'services']) if (courseId === 'NEW') { if ($scope.newCourse.newName) { $http.post(CONSTANTS.PROXY + '/courses', {title: $scope.newCourse.newName}) - .success(function(data) { + .success(function (data) { $http.put(CONSTANTS.PROXY + '/classes/' + classObj._id, {courseId: data._id}) .success(function () { getClasses(); @@ -109,14 +184,14 @@ angular.module('classesApp', ['ngStorage', 'services']) JSON.stringify(data) + ', status: ' + status); }); }).error(function (data, status) { - console.error('Error on put /classes/' + classObj._id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }).finally(function () { - $scope.editBoxCourse[classObj._id] = false; - $scope.editCourse[classObj._id] = false; - $scope.newCourse = {}; - getCourses(); - }); + console.error('Error on put /classes/' + classObj._id + ' ' + + JSON.stringify(data) + ', status: ' + status); + }).finally(function () { + $scope.editBoxCourse[classObj._id] = false; + $scope.editCourse[classObj._id] = false; + $scope.newCourse = {}; + getCourses(); + }); } else { $scope.editBoxCourse[classObj._id] = true; } @@ -138,8 +213,8 @@ angular.module('classesApp', ['ngStorage', 'services']) }; $scope.deleteClass = function (classObj) { - classObj.$remove().then(function() { - $timeout(function() { + classObj.$remove().then(function () { + $timeout(function () { $rootScope.$broadcast('refreshClasses'); }, 20); }); From d537cc15dd435d0c529f9295724c194819425e60 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Fri, 14 Sep 2018 17:54:56 +0200 Subject: [PATCH 08/19] DashboardLink for class dashboard set up --- app/public/js/controllers/activity-list.js | 46 +++++++++------- app/public/js/controllers/class.js | 62 ++++++++++++++++------ 2 files changed, 74 insertions(+), 34 deletions(-) diff --git a/app/public/js/controllers/activity-list.js b/app/public/js/controllers/activity-list.js index a86657b..3909485 100644 --- a/app/public/js/controllers/activity-list.js +++ b/app/public/js/controllers/activity-list.js @@ -20,7 +20,7 @@ angular.module('activitiesApp', ['ngStorage', 'services']) .controller('ActivityListCtrl', ['$rootScope', '$scope', '$attrs', '$interpolate', '$http', 'Activities', 'Games', 'Versions', 'Classes', 'CONSTANTS', - function ($rootScope, $scope, $attrs, $interpolate, $http, Activities, Games, Versions, Classes, CONSTANTS) { + function ($rootScope, $scope, $attrs, $interpolate, $http, Activities, Games, Versions, Classes, CONSTANTS) { $scope.activityOpenedError = ''; $scope.activityCreatedError = ''; @@ -49,19 +49,19 @@ angular.module('activitiesApp', ['ngStorage', 'services']) loadAll(); } - $attrs.$observe('classid', function() { + $attrs.$observe('classid', function () { if ($attrs.classid) { loadByClass($attrs.classid); } }); - $attrs.$observe('gameid', function() { + $attrs.$observe('gameid', function () { if ($attrs.gameid && $attrs.versionid) { loadByGameAndVersion($attrs.gameid, $attrs.versionid); } }); - $attrs.$observe('versionid', function() { + $attrs.$observe('versionid', function () { if ($attrs.gameid && $attrs.versionid) { loadByGameAndVersion($attrs.gameid, $attrs.versionid); } @@ -69,21 +69,29 @@ angular.module('activitiesApp', ['ngStorage', 'services']) $scope.$on('refreshClasses', function () { Classes.my().$promise - .then(function(classes) { $scope.classes = classes; }) - .then(function() { - Activities.my().$promise.then(function(activities) { + .then(function (classes) { + $scope.classes = classes; + }) + .then(function () { + Activities.my().$promise.then(function (activities) { $scope.activities = activities; }); }); }); $scope.$on('refreshGames', function () { - Games.public().$promise.then(function(games) { $scope.games = games; }); - Activities.my().$promise.then(function(activities) { $scope.activities = activities; }); + Games.public().$promise.then(function (games) { + $scope.games = games; + }); + Activities.my().$promise.then(function (activities) { + $scope.activities = activities; + }); }); $scope.$on('refreshActivities', function () { - Activities.my().$promise.then(function(activities) { $scope.activities = activities; }); + Activities.my().$promise.then(function (activities) { + $scope.activities = activities; + }); }); @@ -107,7 +115,7 @@ angular.module('activitiesApp', ['ngStorage', 'services']) } if (!versionId) { - Versions.forGame({gameId: gameId}).$promise.then(function(versions) { + Versions.forGame({gameId: gameId}).$promise.then(function (versions) { if (versions && versions.length > 0 && versions[0]._id) { doCreateActivity(activityName, gameId, versions[0]._id, classId); } else { @@ -121,7 +129,7 @@ angular.module('activitiesApp', ['ngStorage', 'services']) }; $scope.offline = false; - var doCreateActivity = function(activityName, gameId, versionId, classId) { + var doCreateActivity = function (activityName, gameId, versionId, classId) { var activity = new Activities(); activity.name = activityName; activity.gameId = gameId; @@ -135,7 +143,7 @@ angular.module('activitiesApp', ['ngStorage', 'services']) activity.offline = false; activity.allowAnonymous = false; } - activity.$save().then(function() { + activity.$save().then(function () { $http.get(CONSTANTS.PROXY + '/kibana/visualization/list/tch/' + gameId) .success(function (data) { var panels = []; @@ -190,9 +198,9 @@ angular.module('activitiesApp', ['ngStorage', 'services']) $scope.goToActivity(activity); $rootScope.$broadcast('refreshActivities'); }).error(function (data, status) { - console.error('Error on post /kibana/dashboard/activity/' + activity._id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); + console.error('Error on post /kibana/dashboard/activity/' + activity._id + ' ' + + JSON.stringify(data) + ', status: ' + status); + }); } }).error(function (data, status) { console.error('Error on post /kibana/visualization/activity/' + visualizationId + '/' + activity._id + ' ' + @@ -212,13 +220,13 @@ angular.module('activitiesApp', ['ngStorage', 'services']) $scope.deleteActivity = function (activityObj) { if (activityObj) { - activityObj.$remove().then(function() { + activityObj.$remove().then(function () { $rootScope.$broadcast('refreshActivities'); }); } }; - $scope.getClassById = function(_id) { + $scope.getClassById = function (_id) { var r = null; if ($scope.classes) { $scope.classes.forEach(function (c) { @@ -230,7 +238,7 @@ angular.module('activitiesApp', ['ngStorage', 'services']) return r; }; - $scope.getGameById = function(_id) { + $scope.getGameById = function (_id) { var r = null; if ($scope.games) { $scope.games.forEach(function (g) { diff --git a/app/public/js/controllers/class.js b/app/public/js/controllers/class.js index 1694afe..8db14c5 100644 --- a/app/public/js/controllers/class.js +++ b/app/public/js/controllers/class.js @@ -19,12 +19,24 @@ 'use strict'; angular.module('classApp', ['ngStorage', 'services', 'ngAnimate', 'ngSanitize', 'ui.bootstrap']) - .controller('ClassCtrl', ['$rootScope', '$scope', '$attrs', '$location', '$http', '$uibModal', 'Classes', 'Groups', 'Groupings', 'CONSTANTS', - function ($rootScope, $scope, $attrs, $location, $http, $uibModal, Classes, Groups, Groupings, CONSTANTS) { + .controller('ClassCtrl', ['$rootScope', '$scope', '$attrs', '$sce', '$location', '$http', + '$uibModal', 'Classes', 'Groups', 'Groupings', 'CONSTANTS', '$window', + function ($rootScope, $scope, $attrs, $sce, $location, $http, $uibModal, Classes, Groups, Groupings, CONSTANTS, $window) { var groupsReady = false; var groupingsReady = false; var classReady = false; - var onSetClass = function() { + + $scope.dashboardLink = ''; + + + $scope.$watch('dashboardLink', function (newValue, oldValue) { + var iframeObj = document.getElementById('dashboardIframe'); + if (iframeObj) { + iframeObj.src = newValue; + iframeObj.contentWindow.location.reload(); + } + }); + var onSetClass = function () { if (!$scope.class) { throw new Error('No class for ClassCtrl'); } else { @@ -38,31 +50,51 @@ angular.module('classApp', ['ngStorage', 'services', 'ngAnimate', 'ngSanitize', $scope.lti.secret = data[0].secret; } }); + $scope.dashboardLink = $scope.getDashboardLink(); } }; - var onReadyGroups = function() { + $scope.getDashboardLink = function () { + var url = CONSTANTS.KIBANA + '/app/kibana#/dashboard/dashboard_' + + $scope.class._id + '?embed=true_g=(refreshInterval:(display:\'5%60seconds\',' + + 'pause:!f,section:1,value:60000),time:(from:now-1000h,mode:quick,to:now))'; + if (url.startsWith('localhost')) { + url = 'http://' + url; + } + + if (url.startsWith('localhost')) { + url = 'http://' + url; + } + + return $sce.trustAsResourceUrl(url); + }; + + $scope.popDashboard = function () { + $window.open($scope.getDashboardLink()); + }; + + var onReadyGroups = function () { groupsReady = true; if (groupsReady && groupingsReady && classReady) { onReadyParticipants(); } }; - var onReadyGroupings = function() { + var onReadyGroupings = function () { groupingsReady = true; if (groupsReady && groupingsReady && classReady) { onReadyParticipants(); } }; - var onReadyParticipants = function() { + var onReadyParticipants = function () { $scope.participants = {teachers: [], assistants: [], students: []}; if ($scope.isUsingGroupings()) { - $scope.class.groupings.forEach(function(groupingId) { + $scope.class.groupings.forEach(function (groupingId) { addParticipantsFromGroupingId(groupingId); }); } else if ($scope.isUsingGroups()) { - $scope.class.groups.forEach(function(groupId) { + $scope.class.groups.forEach(function (groupId) { addParticipantsFromGroupId(groupId); }); } else { @@ -70,7 +102,7 @@ angular.module('classApp', ['ngStorage', 'services', 'ngAnimate', 'ngSanitize', } }; - var getClassInfo = function() { + var getClassInfo = function () { groupsReady = false; groupingsReady = false; classReady = false; @@ -79,7 +111,7 @@ angular.module('classApp', ['ngStorage', 'services', 'ngAnimate', 'ngSanitize', $scope.groupings = Groupings.get({classId: $attrs.classid}, onReadyGroupings); }; - var addParticipantsFromGroupingId = function(groupingId) { + var addParticipantsFromGroupingId = function (groupingId) { for (var i = 0; i < $scope.groupings.length; i++) { if (groupingId === $scope.groupings[i]._id) { for (var j = 0; j < $scope.groupings[i].groups.length; j++) { @@ -90,7 +122,7 @@ angular.module('classApp', ['ngStorage', 'services', 'ngAnimate', 'ngSanitize', } }; - var addParticipantsFromGroupId = function(groupId) { + var addParticipantsFromGroupId = function (groupId) { for (var i = 0; i < $scope.groups.length; i++) { if (groupId === $scope.groups[i]._id) { pushUsrFromGroupToParticipants($scope.groups[i], 'teachers'); @@ -101,7 +133,7 @@ angular.module('classApp', ['ngStorage', 'services', 'ngAnimate', 'ngSanitize', } }; - var pushUsrFromGroupToParticipants = function(group, role) { + var pushUsrFromGroupToParticipants = function (group, role) { group.participants[role].forEach(function (usr) { if ($scope.participants[role].indexOf(usr) === -1) { $scope.participants[role].push(usr); @@ -116,9 +148,9 @@ angular.module('classApp', ['ngStorage', 'services', 'ngAnimate', 'ngSanitize', getClassInfo(); }); - $attrs.$observe('forclass', function() { + $attrs.$observe('forclass', function () { $scope.class = JSON.parse($attrs.forclass); - Classes.get({classId: $scope.class._id}).$promise.then(function(c) { + Classes.get({classId: $scope.class._id}).$promise.then(function (c) { $scope.class = c; }); onSetClass(); @@ -156,7 +188,7 @@ angular.module('classApp', ['ngStorage', 'services', 'ngAnimate', 'ngSanitize', // Class $scope.changeName = function () { - $scope.class.$update(function() { + $scope.class.$update(function () { $rootScope.$broadcast('refreshClasses'); }); }; From 9bdb0e648013f22f10429178c056705f4e62b2cd Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Wed, 3 Oct 2018 15:14:35 +0200 Subject: [PATCH 09/19] Removed comments --- app/public/js/controllers/activity.js | 12 +----------- app/public/js/controllers/game.js | 3 --- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/app/public/js/controllers/activity.js b/app/public/js/controllers/activity.js index bbdb774..4114401 100644 --- a/app/public/js/controllers/activity.js +++ b/app/public/js/controllers/activity.js @@ -281,18 +281,12 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) // This callback will be called asynchronously // when the response is available - // Check if the version has an analysis uploaded - $scope.offlinetraces = response.data; - console.log('offline tracess!!'); - console.info($scope.offlinetraces); }, function errorCallback(response) { // Called asynchronously if an error occurs // or server returns response with an error status. console.error('Error on get /offlinetraces/' + $scope.activity._id + ' ' + JSON.stringify(response, null, ' ')); - - // Check if the version has an analysis uploaded }); } } @@ -309,16 +303,12 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) }).then(function successCallback(response) { // This callback will be called asynchronously // when the response is available - - // Check if the version has an analysis uploaded updateOfflineTraces(); }, function errorCallback(response) { // Called asynchronously if an error occurs // or server returns response with an error status. console.error('Error on post /offlinetraces/' + $scope.activity._id + ' ' + JSON.stringify(response, null, ' ')); - - // Check if the version has an analysis uploaded }); } @@ -392,7 +382,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) }); } if ($scope.unlockedGroupings) { - $scope.put(route, {groupings: $scope.activity.groupings}).success(function (data) { + $http.put(route, {groupings: $scope.activity.groupings}).success(function (data) { $scope.activity = data; $scope.unlockedGroupings = false; }).error(function (data, status) { diff --git a/app/public/js/controllers/game.js b/app/public/js/controllers/game.js index e701205..47ac30c 100644 --- a/app/public/js/controllers/game.js +++ b/app/public/js/controllers/game.js @@ -25,9 +25,6 @@ angular.module('gameApp', ['ngStorage', 'services', 'ngFileUpload']) var gameId, versionId; var load = function(gameId, versionId) { var afterLoad = function() { - if ($scope.game && $scope.version) { - console.log('loaded'); - } }; Games.get({gameId: gameId}).$promise.then(function(game) { $scope.game = game; From e86c57479f7cc03687bb5e2018976d4b0c5e7018 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Wed, 3 Oct 2018 15:40:32 +0200 Subject: [PATCH 10/19] Removes offline activity modal -> checkbox --- app/public/css/app.css | 41 ++++++++++++++++++++++ app/public/js/controllers/activity-list.js | 6 ++-- app/views/view/classactivity.jade | 28 ++++----------- app/views/view/gameactivity.jade | 13 +++++-- app/views/view/home.jade | 28 ++++----------- 5 files changed, 69 insertions(+), 47 deletions(-) diff --git a/app/public/css/app.css b/app/public/css/app.css index 81ca9c0..982d95d 100644 --- a/app/public/css/app.css +++ b/app/public/css/app.css @@ -121,3 +121,44 @@ html, body { .warning-alert-table tr td:nth-child(3){ background-color: #ffef8f; text-align: center; cursor: pointer; } + +.checkbox label:after { + content: ''; + display: table; + clear: both; +} + +.checkbox .cr { + position: relative; + display: inline-block; + border: 1px solid #a9a9a9; + border-radius: .25em; + width: 1.3em; + height: 1.3em; + float: left; + margin-right: .5em; +} + +.checkbox .cr .cr-icon { + position: absolute; + font-size: .8em; + line-height: 0; + top: 50%; + left: 15%; +} + +.checkbox label input[type="checkbox"] { + display: none; +} + +.checkbox label input[type="checkbox"]+.cr>.cr-icon { + opacity: 0; +} + +.checkbox label input[type="checkbox"]:checked+.cr>.cr-icon { + opacity: 1; +} + +.checkbox label input[type="checkbox"]:disabled+.cr { + opacity: .5; +} \ No newline at end of file diff --git a/app/public/js/controllers/activity-list.js b/app/public/js/controllers/activity-list.js index 3909485..30b25fd 100644 --- a/app/public/js/controllers/activity-list.js +++ b/app/public/js/controllers/activity-list.js @@ -128,7 +128,9 @@ angular.module('activitiesApp', ['ngStorage', 'services']) }; - $scope.offline = false; + $scope.type = { + offline: false + }; var doCreateActivity = function (activityName, gameId, versionId, classId) { var activity = new Activities(); activity.name = activityName; @@ -136,7 +138,7 @@ angular.module('activitiesApp', ['ngStorage', 'services']) activity.versionId = versionId; activity.classId = classId; - if ($scope.offline) { + if ($scope.type.offline) { activity.offline = true; activity.allowAnonymous = true; } else { diff --git a/app/views/view/classactivity.jade b/app/views/view/classactivity.jade index 5862928..a7eb682 100644 --- a/app/views/view/classactivity.jade +++ b/app/views/view/classactivity.jade @@ -22,26 +22,6 @@ iframe#dashboardIframe.no-border(ng-src = "{{dashboardLink}}" scrolling="no" width="100%" height="100%") script(src='./js/iresizer.js') div(ng-controller='ActivityListCtrl', ng-attr-classid='{{ class._id }}' ng-class='(isTeacher() ? "col-md-8" : "col-md-12")') - #normalModal(class="modal fade") - div(class="modal-dialog") - div(class="modal-content") - div(class="modal-header") - button(type="button" class="close" data-dismiss="modal" aria-hidden="true") × - h4(class="modal-title") What type of activity do you want to create? - div(class="modal-body") - .container - .row.form-group - button.btn-default.role-button.col-sm-2(ng-click='offline = false' ng-class="{'active': offline==='false'}") - i.fa.fa-cloud.fa-5x - br - label online - button.btn-primary.role-button.col-sm-2(ng-click='offline = true' ng-class="{'active': offline==='true'}") - i.fa.fa-code.fa-5x - br - label Offline - div(class="modal-footer") - button(type="button" class="btn btn-default" data-dismiss="modal") Close - button(type="button" ng-click="createActivity()" data-dismiss="modal" class="btn btn-primary") Submit .panel.panel-default .panel-heading .row @@ -61,9 +41,15 @@ label Game: select.form-control(ng-model='activity.gameId') option(ng-repeat='game in games' value='{{ game._id }}') {{ game.title }} - a.btn.btn-primary.btn-space(type='button', data-toggle="modal" href="#normalModal" class="btn btn-default") + a.btn.btn-primary.btn-space(type='button', ng-click="createActivity()" class="btn btn-default") span.glyphicon.glyphicon-plus.right10 | New activity + .checkbox(style="display: inline-block") + label + input(type='checkbox' ng-model='type.offline') + span.cr + i.cr-icon.glyphicon.glyphicon-ok + | Offline activity p.btn-danger {{activityCreatedError}} p.btn-danger {{activityOpenedError}} p.btn-danger {{activityOpenedError}} diff --git a/app/views/view/gameactivity.jade b/app/views/view/gameactivity.jade index dc4cda1..93bfb17 100644 --- a/app/views/view/gameactivity.jade +++ b/app/views/view/gameactivity.jade @@ -34,6 +34,12 @@ a.btn.btn-primary(type='button', ng-click='createActivity()') span.glyphicon.glyphicon-plus.right10 | New activity + .checkbox(style="display: inline-block") + label + input(type='checkbox' ng-model='type.offline') + span.cr + i.cr-icon.glyphicon.glyphicon-ok + | Offline activity p.btn-danger {{activityCreatedError}} p.btn-danger {{activityOpenedError}} table.table.table-hover @@ -56,10 +62,11 @@ a(ng-href='#', ng-click='goToClass(getClassById(activity.classId))') {{ getClassById(activity.classId).name }} td {{activity._id | prettyDateId }} td(ng-if='isTeacher()') - button.btn-success(ng-if='activityState() == 2' ng-click='endActivity()') Opened - button.btn-warning(ng-if='activityState() == 0' ng-click='startActivity()') Closed - button.btn-info(ng-if='activityState() == 1') Loading + button.btn-success(ng-if='activityState() == 2 && isOnlineActivityParam(activity)' ng-click='endActivity()') Opened + button.btn-warning(ng-if='activityState() == 0 && isOnlineActivityParam(activity)' ng-click='startActivity()') Closed + button.btn-info(ng-if='activityState() == 1 && isOnlineActivityParam(activity)') Loading span.fa.fa-refresh.fa-spin + p.btn-info(ng-if='isOfflineActivityParam(activity)') Offline Activity td(ng-if='isTeacher()') a(ng-click='deleteActivity(activity)') span.glyphicon.glyphicon-remove-sign \ No newline at end of file diff --git a/app/views/view/home.jade b/app/views/view/home.jade index 9b8a412..69f8deb 100644 --- a/app/views/view/home.jade +++ b/app/views/view/home.jade @@ -19,26 +19,6 @@ .theme-showcase(ng-if='!isDeveloper()').col-md-12 //- Activities .panel.panel-default(ng-controller='ActivityListCtrl', ng-init='init()') - #normalModal(class="modal fade") - div(class="modal-dialog") - div(class="modal-content") - div(class="modal-header") - button(type="button" class="close" data-dismiss="modal" aria-hidden="true") × - h4(class="modal-title") What type of activity do you want to create? - div(class="modal-body") - .container - .row.form-group - button.btn-default.role-button.col-sm-2(ng-click='offline = false' ng-class="{'active': offline==='false'}") - i.fa.fa-cloud.fa-5x - br - label online - button.btn-primary.role-button.col-sm-2(ng-click='offline = true' ng-class="{'active': offline==='true'}") - i.fa.fa-code.fa-5x - br - label Offline - div(class="modal-footer") - button(type="button" class="btn btn-default" data-dismiss="modal") Close - button(type="button" ng-click="createActivity()" data-dismiss="modal" class="btn btn-primary") Submit .panel-heading My Activities .panel-body .panel.panel-primary(ng-if='isTeacher()') @@ -52,9 +32,15 @@ label Class: select.form-control(ng-model='activity.classId') option(ng-repeat='class in classes' value='{{ class._id }}') {{ class.name }} - a.btn.btn-primary(type='button' data-toggle="modal" href="#normalModal" class="btn btn-default") + a.btn.btn-primary(type='button' ng-click="createActivity()" class="btn btn-default") span.glyphicon.glyphicon-plus.right10 | New activity + .checkbox(style="display: inline-block") + label + input(type='checkbox' ng-model='type.offline') + span.cr + i.cr-icon.glyphicon.glyphicon-ok + | Offline activity p.btn-danger {{activityCreatedError}} p.btn-danger {{activityOpenedError}} table.table.table-hover From 3e5aae6563441f2420d837b47a90dd75f5562ca1 Mon Sep 17 00:00:00 2001 From: Victorma Perez Colado Date: Thu, 4 Oct 2018 15:11:45 +0200 Subject: [PATCH 11/19] Added ui blocking --- .bowerrc | 3 +- app/public/js/controllers/activity-list.js | 79 +- app/public/js/controllers/app.js | 9 +- app/public/js/controllers/class-list.js | 6 +- app/public/js/controllers/game-list.js | 6 +- app/public/js/services.js | 1 + app/views/layout.jade | 2 + bower.json | 1 + package-lock.json | 3029 ++++++++++++++++++++ 9 files changed, 3055 insertions(+), 81 deletions(-) create mode 100644 package-lock.json diff --git a/.bowerrc b/.bowerrc index 5f348ca..08bfe40 100644 --- a/.bowerrc +++ b/.bowerrc @@ -1,4 +1,5 @@ { "directory": "app/public/bower", - "interactive": false + "interactive": false, + "registry": "https://registry.bower.io" } \ No newline at end of file diff --git a/app/public/js/controllers/activity-list.js b/app/public/js/controllers/activity-list.js index 30b25fd..ef03e2b 100644 --- a/app/public/js/controllers/activity-list.js +++ b/app/public/js/controllers/activity-list.js @@ -19,8 +19,8 @@ 'use strict'; angular.module('activitiesApp', ['ngStorage', 'services']) - .controller('ActivityListCtrl', ['$rootScope', '$scope', '$attrs', '$interpolate', '$http', 'Activities', 'Games', 'Versions', 'Classes', 'CONSTANTS', - function ($rootScope, $scope, $attrs, $interpolate, $http, Activities, Games, Versions, Classes, CONSTANTS) { + .controller('ActivityListCtrl', ['$rootScope', '$scope', '$attrs', '$interpolate', '$http', 'Activities', 'Games', 'Versions', 'Classes', 'blockUI', 'CONSTANTS', + function ($rootScope, $scope, $attrs, $interpolate, $http, Activities, Games, Versions, Classes, blockUI, CONSTANTS) { $scope.activityOpenedError = ''; $scope.activityCreatedError = ''; @@ -145,78 +145,11 @@ angular.module('activitiesApp', ['ngStorage', 'services']) activity.offline = false; activity.allowAnonymous = false; } + blockUI.start(); activity.$save().then(function () { - $http.get(CONSTANTS.PROXY + '/kibana/visualization/list/tch/' + gameId) - .success(function (data) { - var panels = []; - var uiStates = {}; - - // Add index - $http.post(CONSTANTS.PROXY + '/kibana/index/' + gameId + '/' + activity._id, {}) - .success(function (data) { - - }).error(function (data, status) { - console.error('Error on post /kibana/index/' + gameId + '/' + activity._id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - - // Add dashboard - var numPan = 1; - if (data.length > 0) { - data.forEach(function (visualizationId) { - $http.post(CONSTANTS.PROXY + '/kibana/visualization/activity/' + gameId + - '/' + visualizationId + '/' + activity._id, {}).success(function (result) { - panels.push('{\"id\":\"' + visualizationId + '_' + activity._id + - '\",\"type\":\"visualization\",\"panelIndex\":' + numPan + ',' + - '\"size_x\":6,\"size_y\":4,\"col\":' + (1 + (numPan - 1 % 2)) + ',\"row\":' + - (numPan + 1 / 2) + '}'); - uiStates['P-' + numPan] = {vis: {legendOpen: false}}; - numPan++; - - if (numPan > data.length) { - var dashboard = { - title: 'dashboard_' + activity._id, - hits: 0, - description: '', - panelsJSON: '[' + panels.toString() + ']', - optionsJSON: '{"darkTheme":false}', - uiStateJSON: JSON.stringify(uiStates), - version: 1, - timeRestore: true, - timeTo: 'now', - timeFrom: 'now-1h', - refreshInterval: { - display: '5 seconds', - pause: false, - section: 1, - value: 5000 - }, - kibanaSavedObjectMeta: { - searchSourceJSON: '{"filter":[{"query":{"query_string":{"query":"*","analyze_wildcard":true}}}]}' - } - }; - $http.post(CONSTANTS.PROXY + '/kibana/dashboard/activity/' + activity._id, dashboard) - .success(function (data) { - $scope.goToActivity(activity); - $rootScope.$broadcast('refreshActivities'); - }).error(function (data, status) { - console.error('Error on post /kibana/dashboard/activity/' + activity._id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - } - }).error(function (data, status) { - console.error('Error on post /kibana/visualization/activity/' + visualizationId + '/' + activity._id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - }); - } else { - $scope.goToActivity(activity); - $rootScope.$broadcast('refreshActivities'); - } - }).error(function (data, status) { - console.error('Error on post /kibana/visualization/list/' + gameId + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); + $scope.goToActivity(activity); + $rootScope.$broadcast('refreshActivities'); + blockUI.stop(); }); }; diff --git a/app/public/js/controllers/app.js b/app/public/js/controllers/app.js index fa9c62c..e061045 100644 --- a/app/public/js/controllers/app.js +++ b/app/public/js/controllers/app.js @@ -22,7 +22,7 @@ angular.module('myApp', [ 'ngRoute', 'toolbarApp', 'signupApp', 'loginApp', 'loginPluginApp', 'classApp', 'participantsApp', 'classesApp', 'activitiesApp', 'activityApp', 'gameApp', 'analysisApp', 'kibanaApp', 'gamesApp', 'activityApp', 'analyticsApp', 'devVisualizatorApp', - 'services', 'xeditable', 'env-vars', 'ui.router' + 'services', 'xeditable', 'env-vars', 'ui.router', 'blockUI' ]).run(function (editableOptions, $localStorage, $cookies) { editableOptions.theme = 'bs3'; if ($localStorage.user) { @@ -73,8 +73,8 @@ angular.module('myApp', [ } }; } -]).config(['$routeProvider', '$httpProvider', '$locationProvider', '$stateProvider', - function ($routeProvider, $httpProvider, $locationProvider, $stateProvider) { +]).config(['$routeProvider', '$httpProvider', '$locationProvider', '$stateProvider', 'blockUIConfig', + function ($routeProvider, $httpProvider, $locationProvider, $stateProvider, blockUIConfig) { $httpProvider.interceptors.push('httpRequestInterceptor'); $locationProvider.html5Mode({enabled: true, requireBase: false}); @@ -114,6 +114,9 @@ angular.module('myApp', [ url: '/game', templateUrl: 'view/gameactivity' }); + + blockUIConfig.autoBlock = false; + blockUIConfig.message = 'Please wait...'; } ]).controller('AppCtrl', ['$rootScope', '$scope', '$location', '$http', '$timeout', '$localStorage', '$window', 'Games', 'Classes', 'Activities', 'Versions', 'Analysis', 'Role', 'CONSTANTS', 'QueryParams', diff --git a/app/public/js/controllers/class-list.js b/app/public/js/controllers/class-list.js index bfe9bb3..c870703 100644 --- a/app/public/js/controllers/class-list.js +++ b/app/public/js/controllers/class-list.js @@ -20,8 +20,8 @@ angular.module('classesApp', ['ngStorage', 'services']) .controller('ClassListCtrl', ['$scope', '$rootScope', '$location', '$http', 'Classes', 'Courses', - '$timeout', 'CONSTANTS', - function ($scope, $rootScope, $location, $http, Classes, Courses, $timeout, CONSTANTS) { + '$timeout', 'blockUI', 'CONSTANTS', + function ($scope, $rootScope, $location, $http, Classes, Courses, $timeout, blockUI, CONSTANTS) { $scope.activity = {}; $scope.courseId = {}; $scope.class = {}; @@ -74,6 +74,7 @@ angular.module('classesApp', ['ngStorage', 'services']) $scope.createClass = function () { var c = new Classes(); c.name = $scope.class.name ? $scope.class.name : 'New class'; + blockUI.start(); c.$save().then(function () { $rootScope.$broadcast('refreshClasses'); @@ -134,6 +135,7 @@ angular.module('classesApp', ['ngStorage', 'services']) $http.post(CONSTANTS.PROXY + '/kibana/dashboard/class/' + c._id, dashboard) .success(function (data) { $scope.goToClass(c); + blockUI.stop(); }).error(function (data, status) { console.error('Error on post /kibana/dashboard/class/' + c._id + ' ' + JSON.stringify(data) + ', status: ' + status); diff --git a/app/public/js/controllers/game-list.js b/app/public/js/controllers/game-list.js index 55036b9..1639b68 100644 --- a/app/public/js/controllers/game-list.js +++ b/app/public/js/controllers/game-list.js @@ -19,8 +19,8 @@ 'use strict'; angular.module('gamesApp', ['ngStorage', 'services', 'myApp']) - .controller('GameListCtrl', ['$scope', '$rootScope', '$http', '$window', 'Games', 'Versions', 'Role', 'CONSTANTS', - function ($scope, $rootScope, $http, $window, Games, Versions, Role, CONSTANTS) { + .controller('GameListCtrl', ['$scope', '$rootScope', '$http', '$window', 'Games', 'Versions', 'Role', 'blockUI', 'CONSTANTS', + function ($scope, $rootScope, $http, $window, Games, Versions, Role, blockUI, CONSTANTS) { $scope.game = {}; @@ -42,6 +42,7 @@ angular.module('gamesApp', ['ngStorage', 'services', 'myApp']) $scope.createGame = function () { var game = new Games(); game.title = $scope.game.gameTitle ? $scope.game.gameTitle : 'new game'; + blockUI.start(); game.$save().then(function (game) { var version = new Versions(); version.gameId = game._id; @@ -72,6 +73,7 @@ angular.module('gamesApp', ['ngStorage', 'services', 'myApp']) visJSON).success(function(data) { $rootScope.$broadcast('refreshGames'); $scope.goToGame(data); + blockUI.stop(); }).error(function (data, status) { console.error('Error on post /kibana/visualization/list/' + game._id + ' ' + JSON.stringify(data) + ', status: ' + status); diff --git a/app/public/js/services.js b/app/public/js/services.js index 9333bcb..a3e22a6 100644 --- a/app/public/js/services.js +++ b/app/public/js/services.js @@ -124,6 +124,7 @@ services.factory('Activities', ['$resource', 'CONSTANTS', gameId: '@gameId', username: '@username' }, { + save: { method: 'POST', url: CONSTANTS.PROXY + '/activities/bundle' }, my: { method: 'GET', isArray: true, url: CONSTANTS.PROXY + '/activities/my' }, forClass: { method: 'GET', isArray: true, url: CONSTANTS.PROXY + '/classes/:classId/activities/my' }, forGame: { method: 'GET', isArray: true, url: CONSTANTS.PROXY + '/games/:gameId/versions/:versionId/activities/my' }, diff --git a/app/views/layout.jade b/app/views/layout.jade index c8ccf71..6e1bdac 100644 --- a/app/views/layout.jade +++ b/app/views/layout.jade @@ -30,6 +30,7 @@ html link(href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css', rel='stylesheet') link(href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css', rel='stylesheet') link(href='bower/animate.css/animate.css', rel='stylesheet') + link(href='bower/angular-block-ui/dist/angular-block-ui.css', rel='stylesheet') // Custom Fonts link(href='https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css', rel='stylesheet') link(rel='stylesheet' href='css/nv.d3.css') @@ -57,6 +58,7 @@ html script(src="bower/checklist-model/checklist-model.js") script(src="bower/ngstorage/ngStorage.min.js") script(src="bower/angular-animate/angular-animate.min.js") + script(src="bower/angular-block-ui/dist/angular-block-ui.js") script(src="bower/angular-sanitize/angular-sanitize.min.js") script(src="bower/ng-file-upload/ng-file-upload.js") script(src="bower/d3/d3.min.js") diff --git a/bower.json b/bower.json index 3a9e13f..597c499 100644 --- a/bower.json +++ b/bower.json @@ -15,6 +15,7 @@ "angular-bootstrap": "2.1.4", "angular-ui-router": "^1.0.3", "angular-ui-bootstrap": "^2.5.6", + "angular-block-ui": "0.2.2", "ng-file-upload": "12.2.13", "ngstorage" : "0.3.11", "bootstrap": "3.3.7", diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..17f5562 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3029 @@ +{ + "name": "Learning-Frontend", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "JSV": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", + "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=", + "dev": true + }, + "accepts": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", + "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=" + }, + "acorn-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", + "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", + "requires": { + "acorn": "2.7.0" + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "asap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", + "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.5", + "to-fast-properties": "1.0.3" + }, + "dependencies": { + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha1-maktZcAnLevoyWtgV7yPv6O+1RE=", + "dev": true + } + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "basic-auth": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz", + "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.15" + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "character-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz", + "integrity": "sha1-wN3kqxgnE7kZuXCVmhI+zBow/NY=" + }, + "clean-css": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "requires": { + "commander": "2.8.1", + "source-map": "0.4.4" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": "1.0.1" + } + } + } + }, + "cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "7.1.2" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "dev": true, + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + } + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "coffee-script": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=", + "dev": true + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", + "integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0=" + }, + "comment-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.3.2.tgz", + "integrity": "sha1-PAPwd2uGo239mgosl8YwfzMggv4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constantinople": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.0.2.tgz", + "integrity": "sha1-S5RdmTeQe82Y7ldRIsOBdRZUQUE=", + "requires": { + "acorn": "2.7.0" + } + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "cookiejar": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.1.tgz", + "integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o=", + "dev": true + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "coveralls": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.0.tgz", + "integrity": "sha1-Iu9zAzBTgIDSm4wVHckUav3oipk=", + "dev": true, + "requires": { + "js-yaml": "3.10.0", + "lcov-parse": "0.0.10", + "log-driver": "1.2.5", + "minimist": "1.2.0", + "request": "2.83.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "dev": true, + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "css": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz", + "integrity": "sha1-k4aBHKgrzMnuf7WnMrHioxfIo+c=", + "requires": { + "css-parse": "1.0.4", + "css-stringify": "1.0.5" + } + }, + "css-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz", + "integrity": "sha1-OLBQP7+dqfVOnB29pg4UXHcRe90=" + }, + "css-stringify": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz", + "integrity": "sha1-sNBClG2ylTu50pKQCmy19tASIDE=" + }, + "cst": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/cst/-/cst-0.1.6.tgz", + "integrity": "sha1-Or7wLpYFpAN0EVwNsWn3gpjebU4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "source-map-support": "0.4.18" + } + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "1.0.2-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha1-qoVnpu7QPFMfyJ0/cRzQ5SWd7HU=", + "dev": true + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=" + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "express": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.14.1.tgz", + "integrity": "sha1-ZGwjf3ZvFIwhIK/wc4F7nk1+DTM=", + "requires": { + "accepts": "1.3.4", + "array-flatten": "1.1.1", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.2.0", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.7.0", + "finalhandler": "0.5.1", + "fresh": "0.3.0", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "1.1.5", + "qs": "6.2.0", + "range-parser": "1.2.0", + "send": "0.14.2", + "serve-static": "1.11.2", + "type-is": "1.6.15", + "utils-merge": "1.0.0", + "vary": "1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "qs": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz", + "integrity": "sha1-O3hIwDwt7OaalSKw+ujEEm10Xzs=" + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", + "dev": true + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "finalhandler": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.1.tgz", + "integrity": "sha1-LEANjUUwk1vCMlScX6OF7Afeb80=", + "requires": { + "debug": "2.2.0", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "statuses": "1.3.1", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + } + } + }, + "findup-sync": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "dev": true, + "requires": { + "glob": "3.2.11", + "lodash": "2.4.2" + }, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + } + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "formidable": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz", + "integrity": "sha1-lriIb3w8NQi5Mta9cMTTqI818ak=", + "dev": true + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha1-GSa6kM8+3+KttJJ/WIC8IsZseQ8=", + "dev": true + }, + "grunt": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", + "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=", + "dev": true, + "requires": { + "async": "0.1.22", + "coffee-script": "1.3.3", + "colors": "0.6.2", + "dateformat": "1.0.2-1.2.3", + "eventemitter2": "0.4.14", + "exit": "0.1.2", + "findup-sync": "0.1.3", + "getobject": "0.1.0", + "glob": "3.1.21", + "grunt-legacy-log": "0.1.3", + "grunt-legacy-util": "0.2.0", + "hooker": "0.2.3", + "iconv-lite": "0.2.11", + "js-yaml": "2.0.5", + "lodash": "0.9.2", + "minimatch": "0.2.14", + "nopt": "1.0.10", + "rimraf": "2.2.8", + "underscore.string": "2.2.1", + "which": "1.0.9" + }, + "dependencies": { + "argparse": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", + "dev": true, + "requires": { + "underscore": "1.7.0", + "underscore.string": "2.4.0" + }, + "dependencies": { + "underscore.string": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", + "dev": true + } + } + }, + "async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "iconv-lite": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=", + "dev": true + }, + "js-yaml": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "dev": true, + "requires": { + "argparse": "0.1.16", + "esprima": "1.0.4" + } + } + } + }, + "grunt-contrib-clean": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.1.0.tgz", + "integrity": "sha1-Vkq/LQN4qYOhW54/MO51tzjEBjg=", + "dev": true, + "requires": { + "async": "1.5.2", + "rimraf": "2.6.2" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "dev": true, + "requires": { + "glob": "7.1.2" + } + } + } + }, + "grunt-legacy-log": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", + "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=", + "dev": true, + "requires": { + "colors": "0.6.2", + "grunt-legacy-log-utils": "0.1.1", + "hooker": "0.2.3", + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-log-utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz", + "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=", + "dev": true, + "requires": { + "colors": "0.6.2", + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-util": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz", + "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=", + "dev": true, + "requires": { + "async": "0.1.22", + "exit": "0.1.2", + "getobject": "0.1.0", + "hooker": "0.2.3", + "lodash": "0.9.2", + "underscore.string": "2.2.1", + "which": "1.0.9" + }, + "dependencies": { + "async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true + } + } + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", + "dev": true, + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=", + "dev": true + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.3.0", + "domutils": "1.5.1", + "entities": "1.0.0", + "readable-stream": "1.1.14" + } + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.4.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "i": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.6.tgz", + "integrity": "sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherit": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/inherit/-/inherit-2.2.6.tgz", + "integrity": "sha1-8WFLBshUToEo5CKchjR9tzrZeI0=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", + "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=" + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.10.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" + }, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "jade": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/jade/-/jade-1.11.0.tgz", + "integrity": "sha1-nIDlOMEtP7lcjZu5VZ+gzAQEBf0=", + "requires": { + "character-parser": "1.2.1", + "clean-css": "3.4.28", + "commander": "2.6.0", + "constantinople": "3.0.2", + "jstransformer": "0.0.2", + "mkdirp": "0.5.1", + "transformers": "2.1.0", + "uglify-js": "2.8.29", + "void-elements": "2.0.1", + "with": "4.0.3" + } + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jscs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/jscs/-/jscs-3.0.3.tgz", + "integrity": "sha1-zERdGRZNlX5pw3GbK1ie9JGSqTQ=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-table": "0.3.1", + "commander": "2.9.0", + "cst": "0.1.6", + "estraverse": "4.2.0", + "exit": "0.1.2", + "glob": "5.0.15", + "htmlparser2": "3.8.3", + "js-yaml": "3.4.6", + "jscs-jsdoc": "2.0.0", + "jscs-preset-wikimedia": "1.0.0", + "jsonlint": "1.6.2", + "lodash": "3.10.1", + "minimatch": "3.0.4", + "natural-compare": "1.2.2", + "pathval": "0.1.1", + "prompt": "0.2.14", + "reserved-words": "0.1.2", + "resolve": "1.1.7", + "strip-bom": "2.0.0", + "strip-json-comments": "1.0.4", + "to-double-quotes": "2.0.0", + "to-single-quotes": "2.0.1", + "vow": "0.4.17", + "vow-fs": "0.3.6", + "xmlbuilder": "3.1.0" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "js-yaml": { + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.4.6.tgz", + "integrity": "sha1-a+GyP2JJ9T0pM3D9TRqqY84bTrA=", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "2.7.3", + "inherit": "2.2.6" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "jscs-jsdoc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jscs-jsdoc/-/jscs-jsdoc-2.0.0.tgz", + "integrity": "sha1-9T684CmqMSW9iCkLpQ1k1FEKSHE=", + "dev": true, + "requires": { + "comment-parser": "0.3.2", + "jsdoctypeparser": "1.2.0" + } + }, + "jscs-preset-wikimedia": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jscs-preset-wikimedia/-/jscs-preset-wikimedia-1.0.0.tgz", + "integrity": "sha1-//VjNCA4/C6IJre7cwnDrjQG/H4=", + "dev": true + }, + "jsdoctypeparser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-1.2.0.tgz", + "integrity": "sha1-597cFToRhJ/8UUEUSuhqfvDCU5I=", + "dev": true, + "requires": { + "lodash": "3.10.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "jshint": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.5.tgz", + "integrity": "sha1-HnJSkVzmgbQIJ+4UJIxG006apiw=", + "dev": true, + "requires": { + "cli": "1.0.1", + "console-browserify": "1.1.0", + "exit": "0.1.2", + "htmlparser2": "3.8.3", + "lodash": "3.7.0", + "minimatch": "3.0.4", + "shelljs": "0.3.0", + "strip-json-comments": "1.0.4" + }, + "dependencies": { + "lodash": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz", + "integrity": "sha1-Nni9irmVBXwHreg27S7wh9qBHUU=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonlint": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.2.tgz", + "integrity": "sha1-VzcEUIX1XrRVxosf9OvAG9UOiDA=", + "dev": true, + "requires": { + "JSV": "4.0.2", + "nomnom": "1.8.1" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jstransformer": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-0.0.2.tgz", + "integrity": "sha1-eq4pqQPRls+glz2IXT5HlH7Ndqs=", + "requires": { + "is-promise": "2.1.0", + "promise": "6.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcov-parse": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "lodash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + }, + "log-driver": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.0.0.tgz", + "integrity": "sha1-zMrJiLC8VHcRnLoOQ9569tatj04=", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha1-iD992rwWUUKyphQn8zUt7RldGj4=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "morgan": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", + "integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=", + "requires": { + "basic-auth": "2.0.0", + "debug": "2.6.9", + "depd": "1.1.2", + "on-finished": "2.3.0", + "on-headers": "1.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "natural-compare": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.2.2.tgz", + "integrity": "sha1-H5bWDjFBysG20FZTzg2urHY69qo=", + "dev": true + }, + "ncp": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "dev": true, + "requires": { + "chalk": "0.4.0", + "underscore": "1.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true, + "requires": { + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", + "dev": true + }, + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "requires": { + "wordwrap": "0.0.3" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "pathval": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-0.1.1.tgz", + "integrity": "sha1-CPkRzcqczllCiA2ngXvAtyO2bYI=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pkginfo": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", + "integrity": "sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "promise": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz", + "integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=", + "requires": { + "asap": "1.0.0" + } + }, + "prompt": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-0.2.14.tgz", + "integrity": "sha1-V3VPZPVD/XsIRXB8gY7OYY8F/9w=", + "dev": true, + "requires": { + "pkginfo": "0.4.1", + "read": "1.0.7", + "revalidator": "0.1.8", + "utile": "0.2.1", + "winston": "0.8.3" + } + }, + "promptly": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-3.0.3.tgz", + "integrity": "sha1-4Xj3Iuc9gsYNAZRiBEvM/dmHL0I=", + "dev": true, + "requires": { + "pify": "3.0.0", + "read": "1.0.7" + } + }, + "proxy-addr": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", + "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.4.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + } + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "requires": { + "mute-stream": "0.0.7" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", + "dev": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "reserved-words": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz", + "integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "revalidator": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" + }, + "send": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.14.2.tgz", + "integrity": "sha1-ObBDiz9RC+Xcb2Z6EfcWiTaM3u8=", + "requires": { + "debug": "2.2.0", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.7.0", + "fresh": "0.3.0", + "http-errors": "1.5.1", + "mime": "1.3.4", + "ms": "0.7.2", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + }, + "dependencies": { + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + } + } + }, + "http-errors": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", + "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=", + "requires": { + "inherits": "2.0.3", + "setprototypeof": "1.0.2", + "statuses": "1.3.1" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + }, + "setprototypeof": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz", + "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=" + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + } + } + }, + "serve-static": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.2.tgz", + "integrity": "sha1-LPmIm9RDWjIMw2iVyapXvWYuasc=", + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.14.2" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + }, + "shelljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", + "dev": true + }, + "should": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.1.tgz", + "integrity": "sha1-hObr+7FFx54K5CMHsls/YtyvV04=", + "dev": true, + "requires": { + "should-equal": "2.0.0", + "should-format": "3.0.3", + "should-type": "1.4.0", + "should-type-adaptors": "1.1.0", + "should-util": "1.0.0" + } + }, + "should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha1-YHLPgwRzYIZ+aOmLCdcRQ9BO4MM=", + "dev": true, + "requires": { + "should-type": "1.4.0" + } + }, + "should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dev": true, + "requires": { + "should-type": "1.4.0", + "should-type-adaptors": "1.1.0" + } + }, + "should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "dev": true + }, + "should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha1-QB5/M7VTMDOUTVzYvytlAneS4no=", + "dev": true, + "requires": { + "should-type": "1.4.0", + "should-util": "1.0.0" + } + }, + "should-util": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz", + "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "superagent": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", + "integrity": "sha1-5KEbnQR/fT7+s7vlNtnsACHRZAM=", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "cookiejar": "2.1.1", + "debug": "3.1.0", + "extend": "3.0.1", + "form-data": "2.3.1", + "formidable": "1.1.1", + "methods": "1.1.2", + "mime": "1.6.0", + "qs": "6.5.1", + "readable-stream": "2.3.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "supertest": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.0.0.tgz", + "integrity": "sha1-jUu2j9GDDuBwM7HFpamkAhyWUpY=", + "dev": true, + "requires": { + "methods": "1.1.2", + "superagent": "3.8.2" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + }, + "to-double-quotes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-double-quotes/-/to-double-quotes-2.0.0.tgz", + "integrity": "sha1-qvIx1vqUiUn4GTAburRITYWI5Kc=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-single-quotes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/to-single-quotes/-/to-single-quotes-2.0.1.tgz", + "integrity": "sha1-fMKRUfD18sQZRvEZ9ZMv5VQXASU=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "transformers": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz", + "integrity": "sha1-XSPLNVYd2F3Gf7hIIwm0fVPM6ac=", + "requires": { + "css": "1.0.8", + "promise": "2.0.0", + "uglify-js": "2.2.5" + }, + "dependencies": { + "is-promise": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", + "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=" + }, + "promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz", + "integrity": "sha1-RmSKqdYFr10ucMMCS/WUNtoCuA4=", + "requires": { + "is-promise": "1.0.1" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "requires": { + "amdefine": "1.0.1" + } + }, + "uglify-js": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "requires": { + "optimist": "0.3.7", + "source-map": "0.1.43" + } + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.17" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "underscore.string": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", + "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utile": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", + "integrity": "sha1-kwyI6ZCY1iIINMNWy9mncFItkNc=", + "dev": true, + "requires": { + "async": "0.2.10", + "deep-equal": "1.0.1", + "i": "0.3.6", + "mkdirp": "0.5.1", + "ncp": "0.4.2", + "rimraf": "2.2.8" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha1-EsUou51Y0LkmXZovbw/ovhf/HxQ=", + "dev": true + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" + }, + "vow": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/vow/-/vow-0.4.17.tgz", + "integrity": "sha1-sW4I+uWMUvPrxodfJEGyapJoKQQ=", + "dev": true + }, + "vow-fs": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/vow-fs/-/vow-fs-0.3.6.tgz", + "integrity": "sha1-LUxZviLivyYY3fWXq0uqkjvnIA0=", + "dev": true, + "requires": { + "glob": "7.1.2", + "uuid": "2.0.3", + "vow": "0.4.17", + "vow-queue": "0.4.3" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + } + } + }, + "vow-queue": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/vow-queue/-/vow-queue-0.4.3.tgz", + "integrity": "sha1-S6j2S1bpISwNvlfxQFruvVTM540=", + "dev": true, + "requires": { + "vow": "0.4.17" + } + }, + "which": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "winston": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz", + "integrity": "sha1-ZLar9M0Brcrv1QCTk7HY6L7BnbA=", + "dev": true, + "requires": { + "async": "0.2.10", + "colors": "0.6.2", + "cycle": "1.0.3", + "eyes": "0.1.8", + "isstream": "0.1.2", + "pkginfo": "0.3.1", + "stack-trace": "0.0.10" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "pkginfo": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", + "dev": true + } + } + }, + "with": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/with/-/with-4.0.3.tgz", + "integrity": "sha1-7v0VTp550sjTQXtkeo8U2f7M4U4=", + "requires": { + "acorn": "1.2.2", + "acorn-globals": "1.0.9" + }, + "dependencies": { + "acorn": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", + "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ=" + } + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xmlbuilder": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-3.1.0.tgz", + "integrity": "sha1-LIaIjy1OrehQ+jjKf3Ij9yCVFuE=", + "dev": true, + "requires": { + "lodash": "3.10.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } +} From 9fcf56191f43a1c4b3422cb1b47cce30ae961d72 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Thu, 11 Oct 2018 15:29:30 +0200 Subject: [PATCH 12/19] Fixes checkbox style and travis tests --- app/public/js/controllers/activity-list.js | 3 ++- app/views/view/data/config.jade | 5 +++-- app/views/view/data/participants.jade | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/public/js/controllers/activity-list.js b/app/public/js/controllers/activity-list.js index ef03e2b..0ab7bef 100644 --- a/app/public/js/controllers/activity-list.js +++ b/app/public/js/controllers/activity-list.js @@ -19,7 +19,8 @@ 'use strict'; angular.module('activitiesApp', ['ngStorage', 'services']) - .controller('ActivityListCtrl', ['$rootScope', '$scope', '$attrs', '$interpolate', '$http', 'Activities', 'Games', 'Versions', 'Classes', 'blockUI', 'CONSTANTS', + .controller('ActivityListCtrl', ['$rootScope', '$scope', '$attrs', '$interpolate', '$http', 'Activities', + 'Games', 'Versions', 'Classes', 'blockUI', 'CONSTANTS', function ($rootScope, $scope, $attrs, $interpolate, $http, Activities, Games, Versions, Classes, blockUI, CONSTANTS) { $scope.activityOpenedError = ''; diff --git a/app/views/view/data/config.jade b/app/views/view/data/config.jade index cc5d42e..b99898b 100644 --- a/app/views/view/data/config.jade +++ b/app/views/view/data/config.jade @@ -19,11 +19,12 @@ h1 Alerts & Warnings Setup a(href="#", editable-text="game.link" onaftersave="changeGameLink()") Link: {{ game.link }} .row .col-md-8 - .checkbox + .checkbox(style="display: inline-block") label input(type="checkbox" ng-change='publicGame()' ng-model='game.public') + span.cr + i.cr-icon.glyphicon.glyphicon-ok | Public game - br .row.top10 .col-sm-12 h4 Activity information diff --git a/app/views/view/data/participants.jade b/app/views/view/data/participants.jade index 780fc44..be36916 100644 --- a/app/views/view/data/participants.jade +++ b/app/views/view/data/participants.jade @@ -19,9 +19,11 @@ h1 Participants .row .col-md-12 - .checkbox + .checkbox(style="display: inline-block") label input(type="checkbox" ng-change='allowAnonymous()' ng-model='activity.allowAnonymous') + span.cr + i.cr-icon.glyphicon.glyphicon-ok | Allow anonymous users br div.modal-header.row From e975063877dc000112a79bb337294a70dd729284 Mon Sep 17 00:00:00 2001 From: Victorma Perez Colado Date: Tue, 16 Oct 2018 21:05:34 +0200 Subject: [PATCH 13/19] Bundle for classes and activities --- app/public/js/controllers/activity-list.js | 3 +- app/public/js/controllers/class-list.js | 78 +----------------- app/public/js/controllers/devVisualizator.js | 83 ++------------------ app/public/js/controllers/game-list.js | 54 +------------ app/public/js/services.js | 2 + app/views/view/data/dev-visualization.jade | 4 +- 6 files changed, 19 insertions(+), 205 deletions(-) diff --git a/app/public/js/controllers/activity-list.js b/app/public/js/controllers/activity-list.js index 0ab7bef..8338e81 100644 --- a/app/public/js/controllers/activity-list.js +++ b/app/public/js/controllers/activity-list.js @@ -21,7 +21,8 @@ angular.module('activitiesApp', ['ngStorage', 'services']) .controller('ActivityListCtrl', ['$rootScope', '$scope', '$attrs', '$interpolate', '$http', 'Activities', 'Games', 'Versions', 'Classes', 'blockUI', 'CONSTANTS', - function ($rootScope, $scope, $attrs, $interpolate, $http, Activities, Games, Versions, Classes, blockUI, CONSTANTS) { + function ($rootScope, $scope, $attrs, $interpolate, $http, Activities, Games, Versions, Classes, + blockUI, CONSTANTS) { $scope.activityOpenedError = ''; $scope.activityCreatedError = ''; diff --git a/app/public/js/controllers/class-list.js b/app/public/js/controllers/class-list.js index c870703..e500195 100644 --- a/app/public/js/controllers/class-list.js +++ b/app/public/js/controllers/class-list.js @@ -77,82 +77,8 @@ angular.module('classesApp', ['ngStorage', 'services']) blockUI.start(); c.$save().then(function () { $rootScope.$broadcast('refreshClasses'); - - $http.get(CONSTANTS.PROXY + '/kibana/classvis/') - .success(function (data) { - var panels = []; - var uiStates = {}; - - // Add index - - $http.post(CONSTANTS.PROXY + '/kibana/classindex/' + c._id, {}) - .success(function (data) { - - }).error(function (data, status) { - console.error('Error on post /kibana/classindex/' + c._id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - - - // Add dashboard - var numPan = 1; - if (data.length > 0) { - data.forEach(function (visualization) { - $http.post(CONSTANTS.PROXY + '/kibana/visualization/class/' + c._id, visualization).success(function (result) { - console.log('updated visualization'); - console.info(visualization); - console.log('result'); - console.info(result); - panels.push('{\"id\":\"' + result._id + - '\",\"type\":\"visualization\",\"panelIndex\":' + numPan + ',' + - '\"size_x\":6,\"size_y\":4,\"col\":' + (1 + (numPan - 1 % 2)) + ',\"row\":' + - (numPan + 1 / 2) + '}'); - uiStates['P-' + numPan] = {vis: {legendOpen: false}}; - numPan++; - - if (numPan > data.length) { - var dashboard = { - title: 'dashboard_' + c._id, - hits: 0, - description: '', - panelsJSON: '[' + panels.toString() + ']', - optionsJSON: '{"darkTheme":false}', - uiStateJSON: JSON.stringify(uiStates), - version: 1, - timeRestore: true, - timeTo: 'now', - timeFrom: 'now-12w', - refreshInterval: { - display: '60 seconds', - pause: false, - section: 1, - value: 60000 - }, - kibanaSavedObjectMeta: { - searchSourceJSON: '{"filter":[{"query":{"query_string":{"query":"*","analyze_wildcard":true}}}]}' - } - }; - $http.post(CONSTANTS.PROXY + '/kibana/dashboard/class/' + c._id, dashboard) - .success(function (data) { - $scope.goToClass(c); - blockUI.stop(); - }).error(function (data, status) { - console.error('Error on post /kibana/dashboard/class/' + c._id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - } - }).error(function (data, status) { - console.error('Error on post /kibana/visualization/class/' + c._id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - }); - } else { - $scope.goToClass(c); - } - }).error(function (data, status) { - console.error('Error on get /kibana/classvis/' + - JSON.stringify(data) + ', status: ' + status); - }); + $scope.goToClass(c); + blockUI.stop(); }); }; diff --git a/app/public/js/controllers/devVisualizator.js b/app/public/js/controllers/devVisualizator.js index 535785e..bf28292 100644 --- a/app/public/js/controllers/devVisualizator.js +++ b/app/public/js/controllers/devVisualizator.js @@ -24,96 +24,29 @@ angular.module('devVisualizatorApp', ['ngStorage', 'services']) function ($scope, $location, $http, $window, $localStorage, Games, Versions, Role, CONSTANTS, $sce, QueryParams) { $scope.$storage = $localStorage; + console.log('isDeveloper'); $scope.isDeveloper = function () { + console.log('isDeveloper'); return Role.isDeveloper(); }; var versionId = QueryParams.getQueryParam('version'); $scope.gameId = QueryParams.getQueryParam('game'); - $scope.showVisualization = function () { - versionId = QueryParams.getQueryParam('version'); - $scope.gameId = QueryParams.getQueryParam('game'); - - $http.get(CONSTANTS.PROXY + '/kibana/visualization/list/dev/' + $scope.gameId) - .success(function(data) { - - var panels = []; - var uiStates = {}; - - // Add index - $http.post(CONSTANTS.PROXY + '/kibana/index/' + $scope.gameId + '/' + versionId, {}) - .success(function(data) { - - }).error(function (data, status) { - console.error('Error on post /kibana/index/' + $scope.gameId + '/' + versionId + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - - // Add dashboard - var numPan = 1; - data.forEach(function (visualizationId) { - - $http.post(CONSTANTS.PROXY + '/kibana/visualization/activity/' + $scope.gameId + '/' + visualizationId + '/' + versionId, - {}).success(function(result) { - panels.push('{\"id\":\"' + visualizationId + '_' + versionId + - '\",\"type\":\"visualization\",\"panelIndex\":' + numPan + ',' + - '\"size_x\":6,\"size_y\":4,\"col\":' + (1 + (numPan - 1 % 2)) + ',\"row\":' + - (numPan + 1 / 2) + '}'); - uiStates['P-' + numPan] = {vis: {legendOpen: false}}; - numPan++; - - if (numPan > data.length) { - var dashboard = { - title: 'dashboard_' + versionId, - hits: 0, - description: '', - panelsJSON: '[' + panels.toString() + ']', - optionsJSON: '{"darkTheme":false}', - uiStateJSON: JSON.stringify(uiStates), - version: 1, - timeRestore: true, - timeTo: 'now', - timeFrom: 'now-7d', - refreshInterval: { - display: '10 seconds', - pause: false, - section: 1, - value: 10000 - }, - kibanaSavedObjectMeta: { - searchSourceJSON: '{"filter":[{"query":{"query_string":{"query":"*","analyze_wildcard":true}}}]}' - } - }; - $http.post(CONSTANTS.PROXY + '/kibana/dashboard/activity/' + versionId, dashboard) - .success(function(data) { - $scope.dashboardLink = getDashboardLink(); - }).error(function (data, status) { - console.error('Error on post /kibana/dashboard/activity/' + versionId + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - } - }).error(function (data, status) { - console.error('Error on post /kibana/visualization/activity/' + visualizationId + '/' + versionId + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - }); - }).error(function (data, status) { - console.error('Error on post /kibana/visualization/list/' + $scope.gameId + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - }; - var getDashboardLink = function() { var url = CONSTANTS.KIBANA + '/app/kibana#/dashboard/dashboard_' + - QueryParams.getQueryParam('version') + '?embed=true_g=(refreshInterval:(display:\'5%20seconds\',' + + versionId + '?embed=true_g=(refreshInterval:(display:\'5%20seconds\',' + 'pause:!f,section:1,value:5000),time:(from:now-1h,mode:quick,to:now))'; if (url.startsWith('localhost')) { url = 'http://' + url; } - document.getElementById('dashboardIframe').contentWindow.location.reload(); return $sce.trustAsResourceUrl(url); }; + $scope.initDashboard = function () { + $scope.dashboardLink = getDashboardLink(); + document.getElementById('dashboardIframe').contentWindow.location.reload(); + }; + } ]); \ No newline at end of file diff --git a/app/public/js/controllers/game-list.js b/app/public/js/controllers/game-list.js index 1639b68..6bd9ce0 100644 --- a/app/public/js/controllers/game-list.js +++ b/app/public/js/controllers/game-list.js @@ -44,57 +44,9 @@ angular.module('gamesApp', ['ngStorage', 'services', 'myApp']) game.title = $scope.game.gameTitle ? $scope.game.gameTitle : 'new game'; blockUI.start(); game.$save().then(function (game) { - var version = new Versions(); - version.gameId = game._id; - version.$save(function () { - $http.get(CONSTANTS.PROXY + '/kibana/templates/index/defaultIndex') - .success(function(data) { - $http.post(CONSTANTS.PROXY + '/kibana/templates/index/' + game._id, data._source).success(function (data) { - $http.get(CONSTANTS.PROXY + '/kibana/templates/_default_') - .success(function(data) { - var count = 0; - var selectedVisualizationTch = []; - var selectedVisualizationDev = []; - data.forEach(function (visualization) { - $http.post(CONSTANTS.PROXY + '/kibana/visualization/game/' + game._id + '/' + visualization.id, {}) - .success(function() { - if (visualization.isTeacher) { - selectedVisualizationTch.push(visualization.id); - } - if (visualization.isDeveloper) { - selectedVisualizationDev.push(visualization.id); - } - count++; - if (count >= data.length) { - var visJSON = {}; - visJSON.visualizationsDev = selectedVisualizationDev; - visJSON.visualizationsTch = selectedVisualizationTch; - $http.post(CONSTANTS.PROXY + '/kibana/visualization/list/' + game._id, - visJSON).success(function(data) { - $rootScope.$broadcast('refreshGames'); - $scope.goToGame(data); - blockUI.stop(); - }).error(function (data, status) { - console.error('Error on post /kibana/visualization/list/' + game._id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - } - }).error(function (data, status) { - console.error('Error on post /kibana/visualization/game/' + game._id + '/' + visualization.id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - }); - - }).error(function (data, status) { - $scope.defaultList = []; - }); - }).error(function (data, status) { - console.error('Error on post /kibana/templates/index/' + game._id + ' ' + - JSON.stringify(data) + ', status: ' + status); - }); - }).error(function (data, status) { - }); - }); + $rootScope.$broadcast('refreshGames'); + $scope.goToGame(game); + blockUI.stop(); }); }; diff --git a/app/public/js/services.js b/app/public/js/services.js index a3e22a6..5c00fa3 100644 --- a/app/public/js/services.js +++ b/app/public/js/services.js @@ -23,6 +23,7 @@ var services = angular.module('services', ['ngResource', 'ngStorage']); services.factory('Games', ['$resource', 'CONSTANTS', function ($resource, CONSTANTS) { return $resource(CONSTANTS.PROXY + '/games/:gameId', { gameId: '@_id' }, { + save: { method: 'POST', url: CONSTANTS.PROXY + '/games/bundle' }, my: { method: 'GET', isArray: true , url: CONSTANTS.PROXY + '/games/my' }, public: { method: 'GET', isArray: true , url: CONSTANTS.PROXY + '/games/public' }, update: { @@ -80,6 +81,7 @@ services.factory('Classes', ['$resource', 'CONSTANTS', return $resource(CONSTANTS.PROXY + '/classes/:classId', { classId: '@_id' }, { + save: { method: 'POST', url: CONSTANTS.PROXY + '/classes/bundle' }, my: { method: 'GET', isArray: true, url: CONSTANTS.PROXY + '/classes/my' }, update: { method: 'PUT', diff --git a/app/views/view/data/dev-visualization.jade b/app/views/view/data/dev-visualization.jade index e3d2bd7..274bf21 100644 --- a/app/views/view/data/dev-visualization.jade +++ b/app/views/view/data/dev-visualization.jade @@ -16,6 +16,6 @@ limitations under the License. h1(ng-controller='DevVisualizatorCtrl') Developer Visualizations - .row(ng-if="isDeveloper()" data-ng-init='showVisualization()') - iframe#dashboardIframe.no-border.top10(src = "{{dashboardLink}}" width="100%") + .row(ng-if="isDeveloper()") + iframe#dashboardIframe.no-border.top10(ng-init='initDashboard()' src="{{dashboardLink}}" width="100%") script(src='./js/iresizer.js') \ No newline at end of file From e845533be870fd21a1a3be076564b96209185516 Mon Sep 17 00:00:00 2001 From: gorco Date: Wed, 24 Oct 2018 18:59:47 +0200 Subject: [PATCH 14/19] Fixed remove group and error when register a new user that already exist --- app/public/js/controllers/app.js | 1 + app/public/js/controllers/participantsConf.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/public/js/controllers/app.js b/app/public/js/controllers/app.js index e061045..3e9d9a4 100644 --- a/app/public/js/controllers/app.js +++ b/app/public/js/controllers/app.js @@ -66,6 +66,7 @@ angular.module('myApp', [ function ($localStorage) { return { request: function (config) { + config.headers.Accept = 'application/json'; if ($localStorage.user) { config.headers.Authorization = 'Bearer ' + $localStorage.user.token; } diff --git a/app/public/js/controllers/participantsConf.js b/app/public/js/controllers/participantsConf.js index 8d17a02..d1ccc43 100644 --- a/app/public/js/controllers/participantsConf.js +++ b/app/public/js/controllers/participantsConf.js @@ -11,7 +11,7 @@ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * WITHOUT WARRANTIES OR ñDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ @@ -350,7 +350,7 @@ angular.module('participantsApp', []) }; $ctrl.removeGroup = function (group) { - if ($ctrl.group.name && $ctrl.group.name.trim() !== '') { + if (group.name && group.name.trim() !== '') { var route = CONSTANTS.PROXY + '/classes/groups/' + group._id; $http.delete(route).success(function (data) { updateGroups(); @@ -392,7 +392,7 @@ angular.module('participantsApp', []) }; $ctrl.removeGrouping = function (grouping) { - if ($ctrl.grouping.name && $ctrl.grouping.name.trim() !== '') { + if (grouping.name && grouping.name.trim() !== '') { var route = CONSTANTS.PROXY + '/classes/groupings/' + grouping._id; $http.delete(route).success(function (data) { updateGroupings(); From 88e271a93a6cea2ac8d885ca4c522959e7159645 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Fri, 26 Oct 2018 13:18:44 +0200 Subject: [PATCH 15/19] Fixed Offline Activity petition, only when is Offline --- app/public/js/controllers/activity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/public/js/controllers/activity.js b/app/public/js/controllers/activity.js index 4114401..a543dc0 100644 --- a/app/public/js/controllers/activity.js +++ b/app/public/js/controllers/activity.js @@ -270,7 +270,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) function updateOfflineTraces() { - if ($scope.activity) { + if ($scope.activity && $scope.activity.offline) { $http.get(CONSTANTS.PROXY + '/offlinetraces/' + $scope.activity._id, { transformRequest: angular.identity, headers: { From 96b43ca5437206f1cca83bff81d51359ece92fd2 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Fri, 26 Oct 2018 13:23:55 +0200 Subject: [PATCH 16/19] Don't show attempts view for the devewloper --- app/views/view/data/menu.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/view/data/menu.jade b/app/views/view/data/menu.jade index 088509b..12dbf4a 100644 --- a/app/views/view/data/menu.jade +++ b/app/views/view/data/menu.jade @@ -24,7 +24,7 @@ ul.nav span.left-menu-item(href="#participants", role="tab", data-toggle="tab", ng-click="view = 'participants'") span.glyphicon.glyphicon-apple.right20 | Participants - li(ng-if='isDeveloper() || isOnlineActivity()') + li(ng-if='isOnlineActivity()') span.left-menu-item(href="#attempts", role="tab", data-toggle="tab", ng-click="view = 'attempts'") span.glyphicon.glyphicon-tasks.right20 | Attempts From 4ebf2b0516ebceacf6831f366adad7d814c442d8 Mon Sep 17 00:00:00 2001 From: gorco Date: Mon, 29 Oct 2018 18:38:13 +0100 Subject: [PATCH 17/19] Fixed user filter --- app/public/js/controllers/activity.js | 17 +++++++---------- app/public/js/controllers/devVisualizator.js | 2 -- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/app/public/js/controllers/activity.js b/app/public/js/controllers/activity.js index a543dc0..2c5fbe6 100644 --- a/app/public/js/controllers/activity.js +++ b/app/public/js/controllers/activity.js @@ -172,22 +172,22 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) var filter = {}; if (userName) { - filter.name = userName; + filter['out.name'] = userName; } else if ($scope.player) { - filter.name = $scope.player.name; + filter['out.name'] = $scope.player.name; } if (attempt) { - filter.session = attempt; + filter['out.session'] = attempt; } else if ($scope.attempt) { - filter.session = $scope.attempt.number; + filter['out.session'] = $scope.attempt.number; } - if (filter.length > 0) { + if (Object.keys(filter).length > 0 ) { var props = []; for (var key in filter) { if (filter.hasOwnProperty(key)) { - props.push(key + ': ' + filter[key]); + props.push(key + ':' + filter[key]); } } url += '&_a=(filters:!(),options:(darkTheme:!f),query:(query_string:(analyze_wildcard:!t,query:\'' + props.join(',') + '\')))'; @@ -196,7 +196,6 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) if (url.startsWith('localhost')) { url = 'http://' + url; } - return $sce.trustAsResourceUrl(url); }; @@ -245,7 +244,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) $scope.viewPlayer = function (result) { $scope.player = result; $scope.attempt = null; - $scope.iframeDashboardUrl = dashboardLink(); + $scope.iframeDashboardUrl = dashboardLink(result.name); }; $scope.viewAttempt = function (gameplay, attempt) { @@ -315,7 +314,6 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) $scope.myFile = undefined; $scope.uploadTracesFile = function () { if ($scope.myFile) { - console.log('upload 3 ' + $scope.myFile); upload($scope.myFile); } }; @@ -522,7 +520,6 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) if ($scope.activity._id === activity._id) { $scope.activity = activity; updateOfflineTraces(); - console.log('Activity updated'); } }); diff --git a/app/public/js/controllers/devVisualizator.js b/app/public/js/controllers/devVisualizator.js index bf28292..81b62e2 100644 --- a/app/public/js/controllers/devVisualizator.js +++ b/app/public/js/controllers/devVisualizator.js @@ -24,9 +24,7 @@ angular.module('devVisualizatorApp', ['ngStorage', 'services']) function ($scope, $location, $http, $window, $localStorage, Games, Versions, Role, CONSTANTS, $sce, QueryParams) { $scope.$storage = $localStorage; - console.log('isDeveloper'); $scope.isDeveloper = function () { - console.log('isDeveloper'); return Role.isDeveloper(); }; From 77212dee3b180ac6095aef6a609de20f564abcb9 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Tue, 30 Oct 2018 18:31:34 +0100 Subject: [PATCH 18/19] Traces File Fix --- app/public/js/controllers/activity.js | 16 +++++++++------- app/views/view/data/information.jade | 4 ++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/public/js/controllers/activity.js b/app/public/js/controllers/activity.js index 2c5fbe6..0b91f12 100644 --- a/app/public/js/controllers/activity.js +++ b/app/public/js/controllers/activity.js @@ -33,15 +33,15 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) new ColumnProgress(angular.element(element).children('.score-marker')[0], scope.result.score); }; }) - .directive('fileModel', ['$parse', function ($parse) { + .directive('fileModel', ['$parse', '$rootScope', function ($parse, $rootScope) { return { restrict: 'A', link: function (scope, element, attrs) { var model = $parse(attrs.fileModel); var modelSetter = model.assign; element.bind('change', function () { - scope.$apply(function () { - modelSetter(scope, element[0].files[0]); + $rootScope.$apply(function () { + modelSetter($rootScope, element[0].files[0]); }); }); } @@ -183,7 +183,7 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) filter['out.session'] = $scope.attempt.number; } - if (Object.keys(filter).length > 0 ) { + if (Object.keys(filter).length > 0) { var props = []; for (var key in filter) { if (filter.hasOwnProperty(key)) { @@ -311,10 +311,12 @@ angular.module('activityApp', ['myApp', 'ngStorage', 'services']) }); } - $scope.myFile = undefined; + $rootScope.tracesFile = undefined; $scope.uploadTracesFile = function () { - if ($scope.myFile) { - upload($scope.myFile); + console.log('aaaaaaaaaa'); + if ($rootScope.tracesFile) { + console.log('bbbbbbbb'); + upload($rootScope.tracesFile); } }; diff --git a/app/views/view/data/information.jade b/app/views/view/data/information.jade index b80910e..7a07502 100644 --- a/app/views/view/data/information.jade +++ b/app/views/view/data/information.jade @@ -27,9 +27,9 @@ kbd.left10(ng-if='isTeacher()') {{ activity.trackingCode }} .row(ng-if='isTeacher() && isOfflineActivity()') hr - .col-xs-12(ng-controller='ActivityCtrl') + .col-xs-12 label Select a CSV traces file: - input(type="file" file-model="myFile") + input(type="file" file-model="tracesFile") button.btn.btn-primary.top5(type='submit', ng-click='uploadTracesFile()') Upload trace file .row .col-md-12 From 2792018095a5ef2db11ebc39742c7cb46b8b5054 Mon Sep 17 00:00:00 2001 From: RotaruDan Date: Tue, 30 Oct 2018 19:55:56 +0100 Subject: [PATCH 19/19] Priority of the menu changed to show Realtime First --- app/views/view/data.jade | 10 ++++----- app/views/view/data/dev-visualization.jade | 4 ++-- app/views/view/data/menu.jade | 24 +++++++++++----------- app/views/view/data/realtime/realtime.jade | 8 ++++---- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/app/views/view/data.jade b/app/views/view/data.jade index 15d136b..1578ef1 100644 --- a/app/views/view/data.jade +++ b/app/views/view/data.jade @@ -43,10 +43,12 @@ .col-xs-3.col-md-2.left-menu include data/menu .col-xs-9.col-md-10.tab-content.table-cell - #info.tab-pane.active - include data/information - #realtime.tab-pane + #realtime.tab-pane.active include data/realtime/realtime + #dev-visualization.tab-pane.active + include data/dev-visualization + #info.tab-pane + include data/information #participants.tab-pane include data/participants #attempts.tab-pane @@ -55,8 +57,6 @@ include data/config #analysis.tab-pane include data/analysis - #dev-visualization.tab-pane - include data/dev-visualization #game-analytics.tab-pane include data/game-analytics .panel.panel-default(ng-if='!isDeveloper() && selectedActivity' ng-controller='ActivityCtrl' activity='{{ selectedActivity }}' style='width=100%') diff --git a/app/views/view/data/dev-visualization.jade b/app/views/view/data/dev-visualization.jade index 274bf21..914e69a 100644 --- a/app/views/view/data/dev-visualization.jade +++ b/app/views/view/data/dev-visualization.jade @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. -h1(ng-controller='DevVisualizatorCtrl') Developer Visualizations - .row(ng-if="isDeveloper()") +h1(ng-if="isDeveloper()" ng-controller='DevVisualizatorCtrl') Developer Visualizations + .row iframe#dashboardIframe.no-border.top10(ng-init='initDashboard()' src="{{dashboardLink}}" width="100%") script(src='./js/iresizer.js') \ No newline at end of file diff --git a/app/views/view/data/menu.jade b/app/views/view/data/menu.jade index 12dbf4a..ae740d6 100644 --- a/app/views/view/data/menu.jade +++ b/app/views/view/data/menu.jade @@ -16,7 +16,17 @@ limitations under the License. ul.nav - li.active + li(ng-if='isTeacher() || isStudent()').active + span.left-menu-item(href="#realtime", role="tab", data-toggle="tab", ng-click="view = 'realtime'") + span.glyphicon.glyphicon-dashboard.right20 + | Real Time + li(ng-if='isDeveloper()').active + span.left-menu-item(href="#dev-visualization", role="tab", data-toggle="tab", ng-click="view = 'dev-visualization'") + span.glyphicon.glyphicon-dashboard.right20 + div.in-line Developer + br + | Visualizations + li span.left-menu-item(href="#info", role="tab", data-toggle="tab", ng-click="view = 'info'") span.glyphicon.glyphicon-info-sign.right20 | Information @@ -24,14 +34,10 @@ ul.nav span.left-menu-item(href="#participants", role="tab", data-toggle="tab", ng-click="view = 'participants'") span.glyphicon.glyphicon-apple.right20 | Participants - li(ng-if='isOnlineActivity()') + li span.left-menu-item(href="#attempts", role="tab", data-toggle="tab", ng-click="view = 'attempts'") span.glyphicon.glyphicon-tasks.right20 | Attempts - li(ng-if='isTeacher() || isStudent()') - span.left-menu-item(href="#realtime", role="tab", data-toggle="tab", ng-click="view = 'realtime'") - span.glyphicon.glyphicon-dashboard.right20 - | Real Time li(ng-if='isDeveloper() && showLrs' ng-controller='AnalyticsCtrl') span.left-menu-item(href="#game-analytics", role="tab", data-toggle="tab", ng-click="view = 'game-analytics'; getStatements()") span.fa.fa-bar-chart.right20 @@ -46,10 +52,4 @@ ul.nav span.left-menu-item(href="#analysis", role="tab", data-toggle="tab", ng-click="view = 'analysis'") span.glyphicon.glyphicon-cog.right20 | Analytics Setup - li(ng-if='isDeveloper()') - span.left-menu-item(href="#dev-visualization", role="tab", data-toggle="tab", ng-click="view = 'dev-visualization'") - span.glyphicon.glyphicon-dashboard.right20 - div.in-line Developer - br - | Visualizations diff --git a/app/views/view/data/realtime/realtime.jade b/app/views/view/data/realtime/realtime.jade index c1d898c..0305efe 100644 --- a/app/views/view/data/realtime/realtime.jade +++ b/app/views/view/data/realtime/realtime.jade @@ -15,9 +15,9 @@ See the License for the specific language governing permissions and limitations under the License. -link(rel="stylesheet", href="css/realtime.css") -.container-fluid.theme-showcase.height100(role="tabpanel" style="position:relative") - .row(ng-if="isTeacher()") +link(rel="stylesheet" href="css/realtime.css") +.container-fluid.theme-showcase.height100(ng-if="isTeacher()" role="tabpanel" style="position:relative") + .row h1(ng-if="results.length > 0") Alerts & Warnings .row(ng-show="player") .col-xs-12 @@ -69,7 +69,7 @@ link(rel="stylesheet", href="css/realtime.css") span.glyphicon.glyphicon-remove-sign .col-md-12 h1 Visualizations - iframe#dashboardIframe.no-border(ng-src = "{{iframeDashboardUrl}}" scrolling="no" width="100%") + iframe#dashboardIframe.no-border(ng-src = "{{iframeDashboardUrl}}" scrolling="no" width="100%" height="100%") .row(ng-if="isStudent()") .col-md-12 h1 Visualizations