diff --git a/bigbluebutton-html5/.eslintignore b/bigbluebutton-html5/.eslintignore new file mode 100644 index 0000000000000000000000000000000000000000..9dce6fc290b961483e663a32585d2d15260332a1 --- /dev/null +++ b/bigbluebutton-html5/.eslintignore @@ -0,0 +1,2 @@ +tests/* +Gruntfile.js diff --git a/bigbluebutton-html5/.eslintrc.js b/bigbluebutton-html5/.eslintrc.js new file mode 100644 index 0000000000000000000000000000000000000000..a02fc91be907df47d4ee119e3294c49aafc3b346 --- /dev/null +++ b/bigbluebutton-html5/.eslintrc.js @@ -0,0 +1,22 @@ +module.exports = { + "extends": "airbnb", + "plugins": [ + "react", + "jsx-a11y", + "import", + ], + "env": { + "es6": true, + "node": true, + "browser": true, + "meteor": true, + }, + "rules": { + "no-underscore-dangle": 0, + "import/extensions": [2, "never"], + "import/no-absolute-path": 0, + "import/no-unresolved": 0, + "import/no-extraneous-dependencies": 1, + "react/prop-types": 1, + }, +}; diff --git a/bigbluebutton-html5/.jscsrc b/bigbluebutton-html5/.jscsrc deleted file mode 100755 index fb242fb301df8fa58a55b088ca59304336981145..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/.jscsrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "preset": "airbnb", - "maxErrors": null, // display all errors - "fileExtensions": [".js", ".jsx"], - "esnext": true -} diff --git a/bigbluebutton-html5/.meteor/versions b/bigbluebutton-html5/.meteor/versions index a89bd386636b42aa94570188d44de14c3920214c..798c412921945cb36fd803e96b4e68053049dee1 100644 --- a/bigbluebutton-html5/.meteor/versions +++ b/bigbluebutton-html5/.meteor/versions @@ -63,7 +63,7 @@ ordered-dict@1.0.9 promise@0.8.8 raix:eventemitter@0.1.3 random@1.0.10 -react-meteor-data@0.2.9 +react-meteor-data@0.2.11 reactive-dict@1.1.8 reactive-var@1.0.11 reload@1.1.11 diff --git a/bigbluebutton-html5/Gruntfile.js b/bigbluebutton-html5/Gruntfile.js index 96d8012b1b4a6a9f0f032f37bdf4eb2be5a05b39..2f389886c08f744ab007958dcbb1060dcbc1c255 100755 --- a/bigbluebutton-html5/Gruntfile.js +++ b/bigbluebutton-html5/Gruntfile.js @@ -1,28 +1,27 @@ /* jshint node: true */ -'use strict'; -module.exports = function (grunt) { +module.exports = function (grunt) { require('load-grunt-tasks')(grunt); // importing the Meteor settings: - var SHELL_CONFIG = require('./private/config/server/shell.yaml'); - var PROD_SHELL_CONFIG = require('./private/config/production/server/shell.yaml'); + const SHELL_CONFIG = require('./private/config/server/shell.yaml'); + const PROD_SHELL_CONFIG = require('./private/config/production/server/shell.yaml'); // root URL in development/production: - var rootURL = (SHELL_CONFIG.shell.rootURL == undefined) + const rootURL = (SHELL_CONFIG.shell.rootURL == undefined) ? 'http://127.0.0.1/html5client' : SHELL_CONFIG.shell.rootURL; // command line string containing the Meteor's home directory in production: - var prodHomeStr = (PROD_SHELL_CONFIG.shell.home == undefined) ? '' - : ('HOME=' + PROD_SHELL_CONFIG.shell.home + ' '); + const prodHomeStr = (PROD_SHELL_CONFIG.shell.home == undefined) ? '' + : (`HOME=${PROD_SHELL_CONFIG.shell.home} `); // final commands: - var METEOR_DEV_COMMAND = 'ROOT_URL=' + - rootURL + ' NODE_ENV=development' + ' meteor'; - var METEOR_PROD_COMMAND = prodHomeStr + 'ROOT_URL=' + - rootURL + ' NODE_ENV=production' + ' meteor'; + const METEOR_DEV_COMMAND = `ROOT_URL=${ + rootURL} NODE_ENV=development` + ' meteor'; + const METEOR_PROD_COMMAND = `${prodHomeStr}ROOT_URL=${ + rootURL} NODE_ENV=production` + ' meteor'; // configure Grunt grunt.initConfig({ @@ -88,13 +87,13 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-concurrent'); grunt.loadNpmTasks('grunt-newer'); - var mode = (grunt.option('mode') == 'production') ? 'production' : 'development'; + const mode = (grunt.option('mode') == 'production') ? 'production' : 'development'; // sets the default task to run JSCS first (forcing our way past warnings) and then start Meteor: - grunt.registerTask('default', ['force:newer:jscs:check', 'concurrent:meteor_watch_' + mode]); + grunt.registerTask('default', ['force:newer:jscs:check', `concurrent:meteor_watch_${mode}`]); // sets the autofix task to fix JSCS warning when possible and then start Meteor: - grunt.registerTask('autofix', ['force:newer:jscs:autofix', 'concurrent:meteor_watch_' + mode]); + grunt.registerTask('autofix', ['force:newer:jscs:autofix', `concurrent:meteor_watch_${mode}`]); // runs the linter task: grunt.registerTask('quicklint', ['force:jscs:check']); diff --git a/bigbluebutton-html5/imports/api/audio/client/bridge/base.js b/bigbluebutton-html5/imports/api/audio/client/bridge/base.js index b3bf86aa2e66f5c656b449c67e72deca015fdc35..58037d1e5340be2ccf2787d649456a226113b702 100644 --- a/bigbluebutton-html5/imports/api/audio/client/bridge/base.js +++ b/bigbluebutton-html5/imports/api/audio/client/bridge/base.js @@ -2,7 +2,7 @@ export default class BaseAudioBridge { constructor() { } - exitAudio () { + exitAudio() { } joinListenOnly() { diff --git a/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js b/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js index ab7a8a188d6acc79eb9cb1a33ed26fe13d8574c7..ad3e42d9f47abb6fe9a93dddbc86909e61803389 100644 --- a/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js +++ b/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js @@ -27,7 +27,7 @@ export default class SIPBridge extends BaseAudioBridge { exitAudio(isListenOnly, afterExitCall = () => {}) { // To be called when the hangup is confirmed const hangupCallback = function () { - console.log('Exited Voice Conference, listenOnly=' + isListenOnly); + console.log(`Exited Voice Conference, listenOnly=${isListenOnly}`); // notify BBB-apps we are leaving the call if we are in listen only mode if (isListenOnly) { @@ -60,10 +60,7 @@ export default class SIPBridge extends BaseAudioBridge { // try again periodically setTimeout(checkToHangupCall, MEDIA_CONFIG.WebRTCHangupRetryInterval); } - }) - - // automatically run function - (this, afterExitCall); + })(this, afterExitCall); return false; } @@ -103,22 +100,22 @@ export default class SIPBridge extends BaseAudioBridge { turn: this.userData.turns, }; - callIntoConference(extension, function (audio) { + callIntoConference(extension, (audio) => { switch (audio.status) { case 'failed': - let audioFailed = new CustomEvent('bbb.webrtc.failed', { - status: 'Failed', }); + const audioFailed = new CustomEvent('bbb.webrtc.failed', { + status: 'Failed' }); window.dispatchEvent(audioFailed); break; case 'mediafail': - let mediaFailed = new CustomEvent('bbb.webrtc.mediaFailed', { - status: 'MediaFailed', }); + const mediaFailed = new CustomEvent('bbb.webrtc.mediaFailed', { + status: 'MediaFailed' }); window.dispatchEvent(mediaFailed); break; case 'mediasuccess': case 'started': - let connected = new CustomEvent('bbb.webrtc.connected', { - status: 'started', }); + const connected = new CustomEvent('bbb.webrtc.connected', { + status: 'started' }); window.dispatchEvent(connected); break; } diff --git a/bigbluebutton-html5/imports/api/audio/client/manager/index.js b/bigbluebutton-html5/imports/api/audio/client/manager/index.js index 54f431f0928e38caabe8be8bcd3eb3f3018f97a8..8092a0931503676d1d658f988c937200984c602e 100644 --- a/bigbluebutton-html5/imports/api/audio/client/manager/index.js +++ b/bigbluebutton-html5/imports/api/audio/client/manager/index.js @@ -19,7 +19,7 @@ export default class AudioManager { this.microphoneLockEnforced = userData.microphoneLockEnforced; } - exitAudio () { + exitAudio() { this.bridge.exitAudio(this.isListenOnly); } diff --git a/bigbluebutton-html5/imports/api/breakouts/server/handlers/breakoutJoinURL.js b/bigbluebutton-html5/imports/api/breakouts/server/handlers/breakoutJoinURL.js index 0f54369b5f7fe5dada92e620d8c7a8363d1df287..a2248847276282f289211c65cd0346562cd0b1fe 100644 --- a/bigbluebutton-html5/imports/api/breakouts/server/handlers/breakoutJoinURL.js +++ b/bigbluebutton-html5/imports/api/breakouts/server/handlers/breakoutJoinURL.js @@ -6,7 +6,7 @@ import xml2js from 'xml2js'; import url from 'url'; const xmlParser = new xml2js.Parser(); -const getUrlParams = urlToParse => { +const getUrlParams = (urlToParse) => { const options = { parseQueryString: true }; const parsedUrl = url.parse(urlToParse, options); return parsedUrl.query; @@ -39,9 +39,9 @@ export default function handleBreakoutJoinURL({ payload }) { breakout = Breakouts.findOne(selector); const { response } = parsedXML; - let users = breakout.users; + const users = breakout.users; - let user = { + const user = { userId: payload.userId, urlParams: { meetingId: response.meeting_id[0], diff --git a/bigbluebutton-html5/imports/api/breakouts/server/handlers/breakoutStarted.js b/bigbluebutton-html5/imports/api/breakouts/server/handlers/breakoutStarted.js index 3d7c91983d5530948847abf1e7020c221913b011..97ef4b14b738ede01e8e5afdf966daf0c3fd65f8 100644 --- a/bigbluebutton-html5/imports/api/breakouts/server/handlers/breakoutStarted.js +++ b/bigbluebutton-html5/imports/api/breakouts/server/handlers/breakoutStarted.js @@ -19,7 +19,7 @@ export default function handleBreakoutRoomStarted({ payload }) { $set: { users: [], timeRemaining: Number(timeRemaining), - externalMeetingId: externalMeetingId, + externalMeetingId, }, }; @@ -29,7 +29,7 @@ export default function handleBreakoutRoomStarted({ payload }) { } if (numChanged) { - return Logger.info(`Updated timeRemaining and externalMeetingId ` + + return Logger.info('Updated timeRemaining and externalMeetingId ' + `for breakout id=${meetingId}`); } }; diff --git a/bigbluebutton-html5/imports/api/breakouts/server/handlers/updateTimeRemaining.js b/bigbluebutton-html5/imports/api/breakouts/server/handlers/updateTimeRemaining.js index 6c95c64b7fd37b831c83011900dc95ce08317446..88eaf05f3c5e5276003965035a5f095d73db12f7 100644 --- a/bigbluebutton-html5/imports/api/breakouts/server/handlers/updateTimeRemaining.js +++ b/bigbluebutton-html5/imports/api/breakouts/server/handlers/updateTimeRemaining.js @@ -17,7 +17,7 @@ export default function handleUpdateTimeRemaining({ payload }) { const modifier = { $set: { - timeRemaining: timeRemaining, + timeRemaining, }, }; @@ -31,7 +31,7 @@ export default function handleUpdateTimeRemaining({ payload }) { } if (numChanged) { - return Logger.info(`Updated breakout time remaining for breakouts ` + + return Logger.info('Updated breakout time remaining for breakouts ' + `where parentMeetingId=${meetingId}`); } }; diff --git a/bigbluebutton-html5/imports/api/breakouts/server/modifiers/addBreakout.js b/bigbluebutton-html5/imports/api/breakouts/server/modifiers/addBreakout.js index f6dfe451ff164e3e31daba8edaac950101a2aac1..7ef63a62cb68df81d712c108d6b8d1307f0fa631 100644 --- a/bigbluebutton-html5/imports/api/breakouts/server/modifiers/addBreakout.js +++ b/bigbluebutton-html5/imports/api/breakouts/server/modifiers/addBreakout.js @@ -39,4 +39,4 @@ export default function addBreakout(payload) { }; return Breakouts.upsert(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/breakouts/server/modifiers/clearBreakouts.js b/bigbluebutton-html5/imports/api/breakouts/server/modifiers/clearBreakouts.js index c16ce4ffdab6519145c3f18972fbda06f5162f9f..2da55e7db766d9cff2fe4cd7cd2f5cc398b320f8 100644 --- a/bigbluebutton-html5/imports/api/breakouts/server/modifiers/clearBreakouts.js +++ b/bigbluebutton-html5/imports/api/breakouts/server/modifiers/clearBreakouts.js @@ -16,5 +16,5 @@ export default function clearBreakouts(meetingId) { return Breakouts.remove(selector, cb); } - return Breakouts.remove({}, Logger.info(`Cleared Breakouts (all)`)); + return Breakouts.remove({}, Logger.info('Cleared Breakouts (all)')); } diff --git a/bigbluebutton-html5/imports/api/breakouts/server/publishers.js b/bigbluebutton-html5/imports/api/breakouts/server/publishers.js index ca40223dfc43b756457f69b3e5fd59916469b3d9..8d0d6ef65b7e45fda2b05aec1e21a2f315d53745 100644 --- a/bigbluebutton-html5/imports/api/breakouts/server/publishers.js +++ b/bigbluebutton-html5/imports/api/breakouts/server/publishers.js @@ -1,7 +1,7 @@ import Breakouts from '/imports/api/breakouts'; import { Meteor } from 'meteor/meteor'; -Meteor.publish('breakouts', credentials => { +Meteor.publish('breakouts', (credentials) => { const { meetingId, requesterUserId, diff --git a/bigbluebutton-html5/imports/api/captions/server/handlers/captionHistory.js b/bigbluebutton-html5/imports/api/captions/server/handlers/captionHistory.js index 9f6804494fc90d551437c6f7f0418620532de8ae..a7d1c750d94cce7300b21804452c063f516b8863 100644 --- a/bigbluebutton-html5/imports/api/captions/server/handlers/captionHistory.js +++ b/bigbluebutton-html5/imports/api/captions/server/handlers/captionHistory.js @@ -20,21 +20,23 @@ export default function handleCaptionHistory({ payload }) { check(meetingId, String); check(captionHistory, Object); - let captionsAdded = []; + const captionsAdded = []; _.each(captionHistory, (caption, locale) => { - let ownerId = caption[0]; + const ownerId = caption[0]; let captions = caption[1].slice(0); - let chunks = []; + const chunks = []; if (captions.length === 0) { chunks.push(''); - } else while (captions.length > 0) { - if (captions.length > CAPTION_CHUNK_LENGTH) { - chunks.push(captions.slice(0, CAPTION_CHUNK_LENGTH)); - captions = captions.slice(CAPTION_CHUNK_LENGTH); - } else { - chunks.push(captions); - captions = captions.slice(captions.length); + } else { + while (captions.length > 0) { + if (captions.length > CAPTION_CHUNK_LENGTH) { + chunks.push(captions.slice(0, CAPTION_CHUNK_LENGTH)); + captions = captions.slice(CAPTION_CHUNK_LENGTH); + } else { + chunks.push(captions); + captions = captions.slice(captions.length); + } } } @@ -47,7 +49,7 @@ export default function handleCaptionHistory({ payload }) { Captions.remove(selectorToRemove); chunks.forEach((captions, index) => { - let captionHistoryObject = { + const captionHistoryObject = { locale, ownerId, captions, @@ -57,8 +59,7 @@ export default function handleCaptionHistory({ payload }) { captionsAdded.push(addCaption(meetingId, locale, captionHistoryObject)); }); - }); return captionsAdded; -}; +} diff --git a/bigbluebutton-html5/imports/api/captions/server/handlers/captionOwnerUpdate.js b/bigbluebutton-html5/imports/api/captions/server/handlers/captionOwnerUpdate.js index eff8e4342753a0149aaa45c8934ef323cc4b5755..0932b482ddaa0bee12ffa72052b3b693103ab3a7 100644 --- a/bigbluebutton-html5/imports/api/captions/server/handlers/captionOwnerUpdate.js +++ b/bigbluebutton-html5/imports/api/captions/server/handlers/captionOwnerUpdate.js @@ -17,7 +17,7 @@ export default function handleCaptionOwnerUpdate({ payload }) { locale, }; - let modifier = { + const modifier = { $set: { 'captionHistory.ownerId': ownerId, }, @@ -47,4 +47,4 @@ export default function handleCaptionOwnerUpdate({ payload }) { }; return Captions.update(selector, modifier, { multi: true }, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/captions/server/handlers/captionUpdate.js b/bigbluebutton-html5/imports/api/captions/server/handlers/captionUpdate.js index eb7a4859efba1b5b67a952d96dc02d935b884bc4..cb252b01b7267bb505f4dc294989d2459d731d01 100644 --- a/bigbluebutton-html5/imports/api/captions/server/handlers/captionUpdate.js +++ b/bigbluebutton-html5/imports/api/captions/server/handlers/captionUpdate.js @@ -13,7 +13,7 @@ export default function handleCaptionUpdate({ payload }) { check(meetingId, String); check(locale, String); - let captionsObjects = Captions.find({ + const captionsObjects = Captions.find({ meetingId, locale, }, { @@ -23,35 +23,35 @@ export default function handleCaptionUpdate({ payload }) { }, }).fetch(); - let objectsToUpdate = []; + const objectsToUpdate = []; if (captionsObjects != null) { let startIndex; let endIndex; let length = 0; let current = captionsObjects[0]; - //looking for a start index and end index - //(end index only for the case when they are in the same block) + // looking for a start index and end index + // (end index only for the case when they are in the same block) while (current != null) { length += current.captionHistory.captions.length; - //if length is bigger than start index - we found our start index + // if length is bigger than start index - we found our start index if (length >= payload.start_index && startIndex == undefined) { - //check if it's a new character somewhere in the middle of captions text + // check if it's a new character somewhere in the middle of captions text if (length - 1 >= payload.start_index) { startIndex = payload.start_index - (length - current.captionHistory.captions.length); - //check to see if the end_index is in the same object as start_index + // check to see if the end_index is in the same object as start_index if (length - 1 >= payload.end_index) { endIndex = payload.end_index - (length - current.captionHistory.captions.length); - let _captions = current.captionHistory.captions; + const _captions = current.captionHistory.captions; current.captionHistory.captions = _captions.slice(0, startIndex) + payload.text + _captions.slice(endIndex); objectsToUpdate.push(current); break; - //end index is not in the same object as start_index, we will find it later + // end index is not in the same object as start_index, we will find it later } else { current.captionHistory.captions = current.captionHistory.captions.slice(0, startIndex) + payload.text; @@ -59,11 +59,10 @@ export default function handleCaptionUpdate({ payload }) { break; } - //separate case for appending new characters to the very end of the string + // separate case for appending new characters to the very end of the string } else if (current.captionHistory.next == null && length == payload.start_index && length == payload.start_index) { - startIndex = 1; endIndex = 1; current.captionHistory.captions += payload.text; @@ -74,23 +73,22 @@ export default function handleCaptionUpdate({ payload }) { current = captionsObjects[current.captionHistory.next]; } - //looking for end index here if it wasn't in the same object as start index + // looking for end index here if it wasn't in the same object as start index if (startIndex != undefined && endIndex == undefined) { current = captionsObjects[current.captionHistory.next]; while (current != null) { length += current.captionHistory.captions.length; - //check to see if the end_index is in the current object + // check to see if the end_index is in the current object if (length - 1 >= payload.end_index) { - endIndex = payload.end_index - (length - current.captionHistory.captions.length); current.captionHistory.captions = current.captionHistory.captions.slice(endIndex); objectsToUpdate.push(current); break; - //if end_index wasn't in the current object, that means this whole object was deleted - //initializing string to '' + // if end_index wasn't in the current object, that means this whole object was deleted + // initializing string to '' } else { current.captionHistory.captions = ''; objectsToUpdate.push(current); @@ -100,56 +98,55 @@ export default function handleCaptionUpdate({ payload }) { } } - //looking for the strings which exceed the limit and split them into multiple objects + // looking for the strings which exceed the limit and split them into multiple objects let maxIndex = captionsObjects.length - 1; for (i = 0; i < objectsToUpdate.length; i++) { if (objectsToUpdate[i].captionHistory.captions.length > CAPTION_CHUNK_LENGTH) { - //string is too large. Check if the next object exists and if it can - //accomodate the part of the string that exceeds the limits - let _nextIndex = objectsToUpdate[i].captionHistory.next; + // string is too large. Check if the next object exists and if it can + // accomodate the part of the string that exceeds the limits + const _nextIndex = objectsToUpdate[i].captionHistory.next; if (_nextIndex != null && captionsObjects[_nextIndex].captionHistory.captions.length < CAPTION_CHUNK_LENGTH) { + const extraString = objectsToUpdate[i].captionHistory.captions.slice(CAPTION_CHUNK_LENGTH); - let extraString = objectsToUpdate[i].captionHistory.captions.slice(CAPTION_CHUNK_LENGTH); - - //could assign it directly, but our linter complained + // could assign it directly, but our linter complained let _captions = objectsToUpdate[i].captionHistory.captions; _captions = _captions.slice(0, CAPTION_CHUNK_LENGTH); objectsToUpdate[i].captionHistory.captions = _captions; - //check to see if the next object was added to objectsToUpdate array + // check to see if the next object was added to objectsToUpdate array if (objectsToUpdate[i + 1] != null && objectsToUpdate[i].captionHistory.next == objectsToUpdate[i + 1].captionHistory.index) { objectsToUpdate[i + 1].captionHistory.captions = extraString + objectsToUpdate[i + 1].captionHistory.captions; - //next object wasn't added to objectsToUpdate array, adding it from captionsObjects array. + // next object wasn't added to objectsToUpdate array, adding it from captionsObjects array. } else { - let nextObj = captionsObjects[objectsToUpdate[i].captionHistory.next]; + const nextObj = captionsObjects[objectsToUpdate[i].captionHistory.next]; nextObj.captionHistory.captions = extraString + nextObj.captionHistory.captions; objectsToUpdate.push(nextObj); } - //next object was full already, so we create another and insert it in between them + // next object was full already, so we create another and insert it in between them } else { - //need to take a current object out of the objectsToUpdate and add it back after - //every other object, so that Captions collection could be updated in a proper order - let tempObj = objectsToUpdate.splice(i, 1); + // need to take a current object out of the objectsToUpdate and add it back after + // every other object, so that Captions collection could be updated in a proper order + const tempObj = objectsToUpdate.splice(i, 1); let extraString = tempObj[0].captionHistory.captions.slice(CAPTION_CHUNK_LENGTH); tempObj[0].captionHistory.captions = tempObj[0].captionHistory.captions.slice(0, CAPTION_CHUNK_LENGTH); maxIndex += 1; - let tempIndex = tempObj[0].captionHistory.next; + const tempIndex = tempObj[0].captionHistory.next; tempObj[0].captionHistory.next = maxIndex; while (extraString.length != 0) { - let entry = { - meetingId: meetingId, - locale: locale, + const entry = { + meetingId, + locale, captionHistory: { - locale: locale, + locale, ownerId: tempObj[0].captionHistory.ownerId, captions: extraString.slice(0, CAPTION_CHUNK_LENGTH), index: maxIndex, @@ -173,11 +170,11 @@ export default function handleCaptionUpdate({ payload }) { } } - let captionsAdded = []; - objectsToUpdate.forEach(entry => { + const captionsAdded = []; + objectsToUpdate.forEach((entry) => { const { _id, meetingId, locale, captionHistory } = entry; captionsAdded.push(addCaption(meetingId, locale, captionHistory, _id)); }); return captionsAdded; -}; +} diff --git a/bigbluebutton-html5/imports/api/captions/server/modifiers/addCaption.js b/bigbluebutton-html5/imports/api/captions/server/modifiers/addCaption.js index b848e779cab3e71b9886d787243276c38ab5bec8..86056d2492f38ecdd777d7143a8d039a87c630a2 100644 --- a/bigbluebutton-html5/imports/api/captions/server/modifiers/addCaption.js +++ b/bigbluebutton-html5/imports/api/captions/server/modifiers/addCaption.js @@ -18,13 +18,13 @@ export default function addCaption(meetingId, locale, captionHistory, id = false selector['captionHistory.index'] = captionHistory.index; } - let modifier = { + const modifier = { $set: { meetingId, locale, 'captionHistory.locale': locale, 'captionHistory.ownerId': captionHistory.ownerId, - 'captionHistory.captions':captionHistory.captions, + 'captionHistory.captions': captionHistory.captions, 'captionHistory.next': captionHistory.next, 'captionHistory.index': captionHistory.index, }, @@ -46,4 +46,4 @@ export default function addCaption(meetingId, locale, captionHistory, id = false }; return Captions.upsert(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/captions/server/modifiers/clearCaptions.js b/bigbluebutton-html5/imports/api/captions/server/modifiers/clearCaptions.js index 5427179324383cf2acc6e15421770843d27770b0..9d10d369cd3ff37cef465f99832ee8299eee3df6 100644 --- a/bigbluebutton-html5/imports/api/captions/server/modifiers/clearCaptions.js +++ b/bigbluebutton-html5/imports/api/captions/server/modifiers/clearCaptions.js @@ -3,8 +3,8 @@ import Logger from '/imports/startup/server/logger'; export default function clearCaptions(meetingId) { if (meetingId) { - return Captions.remove({ meetingId, }, Logger.info(`Cleared Captions (${meetingId})`)); + return Captions.remove({ meetingId }, Logger.info(`Cleared Captions (${meetingId})`)); } return Captions.remove({}, Logger.info('Cleared Captions (all)')); -}; +} diff --git a/bigbluebutton-html5/imports/api/captions/server/publishers.js b/bigbluebutton-html5/imports/api/captions/server/publishers.js index 901fb3e4f93e002161bab94b46efb4a0fb49b622..aad98874ec17beecd94d9effbb4c643fe52797ba 100644 --- a/bigbluebutton-html5/imports/api/captions/server/publishers.js +++ b/bigbluebutton-html5/imports/api/captions/server/publishers.js @@ -4,7 +4,7 @@ import { check } from 'meteor/check'; import Logger from '/imports/startup/server/logger'; import { isAllowedTo } from '/imports/startup/server/userPermissions'; -Meteor.publish('captions', function (credentials) { +Meteor.publish('captions', (credentials) => { // TODO: Some publishers have ACL and others dont // if (isAllowedTo('subscribeCaptions', credentials)) { // this.error(new Meteor.Error(402, "The user was not authorized to subscribe for 'captions'")); diff --git a/bigbluebutton-html5/imports/api/chat/server/handlers/chatHistory.js b/bigbluebutton-html5/imports/api/chat/server/handlers/chatHistory.js index 8fd0ed64d6fbe9696d81aa72eac4ad0e31986f8a..0a25355baefd78e49008c7e483e3565804148be8 100644 --- a/bigbluebutton-html5/imports/api/chat/server/handlers/chatHistory.js +++ b/bigbluebutton-html5/imports/api/chat/server/handlers/chatHistory.js @@ -14,11 +14,11 @@ export default function handleChatHistory({ payload }) { check(meetingId, String); check(chatHistory, Array); - let chatsAdded = []; + const chatsAdded = []; - chatHistory.forEach(message => { + chatHistory.forEach((message) => { chatsAdded.push(addChat(meetingId, message)); }); return chatsAdded; -}; +} diff --git a/bigbluebutton-html5/imports/api/chat/server/handlers/chatMessage.js b/bigbluebutton-html5/imports/api/chat/server/handlers/chatMessage.js index 74aec0f43b5042ccb5f982f6e087d0ebf19d33a5..6926b4fb2aa9837ea5b41b0f285e47fc94e718e1 100644 --- a/bigbluebutton-html5/imports/api/chat/server/handlers/chatMessage.js +++ b/bigbluebutton-html5/imports/api/chat/server/handlers/chatMessage.js @@ -14,4 +14,4 @@ export default function handleChatMessage({ payload, header }) { message.from_time = +(header.current_time); return addChat(meetingId, message); -}; +} diff --git a/bigbluebutton-html5/imports/api/chat/server/methods/sendChat.js b/bigbluebutton-html5/imports/api/chat/server/methods/sendChat.js index 5d56026ad6003151e0a3f5091e78eae5d71004fb..fdbf7f45ffe7af0450e88dd794268535e1ecc520 100755 --- a/bigbluebutton-html5/imports/api/chat/server/methods/sendChat.js +++ b/bigbluebutton-html5/imports/api/chat/server/methods/sendChat.js @@ -48,6 +48,8 @@ export default function sendChat(credentials, message) { let actionName = message.to_userid === requesterUserId ? 'chatSelf' : 'chatPrivate'; let eventName = 'send_private_chat_message'; + message.message = parseMessage(message.message); + if (message.chat_type === PUBLIC_CHAT_TYPE) { eventName = 'send_public_chat_message'; actionName = 'chatPublic'; @@ -55,14 +57,14 @@ export default function sendChat(credentials, message) { if (!isAllowedTo(actionName, credentials) && message.from_userid !== requesterUserId) { - throw new Meteor.Error('not-allowed', `You are not allowed to sendChat`); + throw new Meteor.Error('not-allowed', 'You are not allowed to sendChat'); } - let payload = { + const payload = { message, meeting_id: meetingId, requester_id: message.from_userid, }; return RedisPubSub.publish(CHANNEL, eventName, payload); -}; +} diff --git a/bigbluebutton-html5/imports/api/chat/server/modifiers/addChat.js b/bigbluebutton-html5/imports/api/chat/server/modifiers/addChat.js index b2effb91607a0c063ed70546f803c37683852c1c..bb6dd5b35602c23b2847a6cafc74de4e82818eaa 100755 --- a/bigbluebutton-html5/imports/api/chat/server/modifiers/addChat.js +++ b/bigbluebutton-html5/imports/api/chat/server/modifiers/addChat.js @@ -7,11 +7,11 @@ const parseMessage = (message) => { message = message || ''; // Replace \r and \n to <br/> - message = message.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + BREAK_LINE + '$2'); + message = message.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, `$1${BREAK_LINE}$2`); // Replace flash links to html valid ones - message = message.split(`<a href='event:`).join(`<a target="_blank" href='`); - message = message.split(`<a href="event:`).join(`<a target="_blank" href="`); + message = message.split('<a href=\'event:').join('<a target="_blank" href=\''); + message = message.split('<a href="event:').join('<a target="_blank" href="'); return message; }; @@ -67,4 +67,4 @@ export default function addChat(meetingId, message) { }; return Chat.upsert(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/chat/server/modifiers/clearChats.js b/bigbluebutton-html5/imports/api/chat/server/modifiers/clearChats.js index 8d1b5f01da43b0226e748909da5ce488b5f95ea9..98d319e8b50b273892f92350aa094df9a7ae2f03 100755 --- a/bigbluebutton-html5/imports/api/chat/server/modifiers/clearChats.js +++ b/bigbluebutton-html5/imports/api/chat/server/modifiers/clearChats.js @@ -3,8 +3,8 @@ import Logger from '/imports/startup/server/logger'; export default function clearChats(meetingId) { if (meetingId) { - return Chat.remove({ meetingId: meetingId, }, Logger.info(`Cleared Chats (${meetingId})`)); + return Chat.remove({ meetingId }, Logger.info(`Cleared Chats (${meetingId})`)); } return Chat.remove({}, Logger.info('Cleared Chats (all)')); -}; +} diff --git a/bigbluebutton-html5/imports/api/chat/server/modifiers/clearUserSystemMessages.js b/bigbluebutton-html5/imports/api/chat/server/modifiers/clearUserSystemMessages.js index e6adcec64e0cc403fad98d9805ddd2f58363eea1..081df4957f3f0d529a098c53c4d8e73608d6442f 100644 --- a/bigbluebutton-html5/imports/api/chat/server/modifiers/clearUserSystemMessages.js +++ b/bigbluebutton-html5/imports/api/chat/server/modifiers/clearUserSystemMessages.js @@ -10,7 +10,6 @@ import { BREAK_LINE } from '/imports/utils/lineEndings.js'; * @param {string} userId */ export default function clearUserSystemMessages(meetingId, userId) { - check(meetingId, String); check(userId, String); @@ -23,4 +22,4 @@ export default function clearUserSystemMessages(meetingId, userId) { }; return Chat.remove(selector, Logger.info(`Removing system messages from: (${userId})`)); -}; +} diff --git a/bigbluebutton-html5/imports/api/common/server/helpers.js b/bigbluebutton-html5/imports/api/common/server/helpers.js index f4947545796bd75c1367a676fc1f9d2fa08e0718..0d6100620c6fad1d75abda381977ca1c257b8117 100755 --- a/bigbluebutton-html5/imports/api/common/server/helpers.js +++ b/bigbluebutton-html5/imports/api/common/server/helpers.js @@ -10,21 +10,21 @@ export function appendMessageHeader(eventName, messageObj) { }; messageObj.header = header; return messageObj; -}; +} export const indexOf = [].indexOf || function (item) { - for (let i = 0, l = this.length; i < l; i++) { - if (i in this && this[i] === item) { - return i; - } + for (let i = 0, l = this.length; i < l; i++) { + if (i in this && this[i] === item) { + return i; } + } - return -1; - }; + return -1; +}; export function publish(channel, message) { return redisPubSub.publish(channel, message.header.name, message.payload, message.header); -}; +} // translate '\n' newline character and '\r' carriage // returns to '<br/>' breakline character for Flash diff --git a/bigbluebutton-html5/imports/api/cursor/server/handlers/cursorUpdate.js b/bigbluebutton-html5/imports/api/cursor/server/handlers/cursorUpdate.js index c14e2a7b9a620c6ae403f8de48ee3761d7a6f83d..215e0b811c414ab001698e52abad0edf8200ac31 100644 --- a/bigbluebutton-html5/imports/api/cursor/server/handlers/cursorUpdate.js +++ b/bigbluebutton-html5/imports/api/cursor/server/handlers/cursorUpdate.js @@ -12,4 +12,4 @@ export default function handleCursorUpdate({ payload }) { check(y, Number); return updateCursor(meetingId, x, y); -}; +} diff --git a/bigbluebutton-html5/imports/api/cursor/server/modifiers/clearCursor.js b/bigbluebutton-html5/imports/api/cursor/server/modifiers/clearCursor.js index 07fd887879d845ac448f0715af49d379e4557d9e..671d05814d10311e16c32c9765541aa7c31c81c1 100755 --- a/bigbluebutton-html5/imports/api/cursor/server/modifiers/clearCursor.js +++ b/bigbluebutton-html5/imports/api/cursor/server/modifiers/clearCursor.js @@ -7,4 +7,4 @@ export default function clearCursor(meetingId) { } return Cursor.remove({}, Logger.info('Cleared Cursor (all)')); -}; +} diff --git a/bigbluebutton-html5/imports/api/cursor/server/modifiers/initializeCursor.js b/bigbluebutton-html5/imports/api/cursor/server/modifiers/initializeCursor.js index 0b4c162e3cb39171b8d3aaa202ec30a17a42ab69..d356ff077c81e7ae44007c85b9cd86ad1136dd84 100755 --- a/bigbluebutton-html5/imports/api/cursor/server/modifiers/initializeCursor.js +++ b/bigbluebutton-html5/imports/api/cursor/server/modifiers/initializeCursor.js @@ -5,4 +5,4 @@ export default function initializeCursor(meetingId) { check(meetingId, String); return updateCursor(meetingId, 0, 0); -}; +} diff --git a/bigbluebutton-html5/imports/api/cursor/server/modifiers/updateCursor.js b/bigbluebutton-html5/imports/api/cursor/server/modifiers/updateCursor.js index 13928c2c5e5b618a609fa0dd48fe0d35de91d5b6..3b954fbc5018d86fbd18171f1d8a1f36c1806ba0 100755 --- a/bigbluebutton-html5/imports/api/cursor/server/modifiers/updateCursor.js +++ b/bigbluebutton-html5/imports/api/cursor/server/modifiers/updateCursor.js @@ -35,4 +35,4 @@ export default function updateCursor(meetingId, x = 0, y = 0) { }; return Cursor.upsert(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/deskshare/client/bridge/verto.js b/bigbluebutton-html5/imports/api/deskshare/client/bridge/verto.js index 23f54195478cbcf3a1360acffb321ad5faff1b58..18e9cfa645d179d8109c6a79da699e6204052230 100644 --- a/bigbluebutton-html5/imports/api/deskshare/client/bridge/verto.js +++ b/bigbluebutton-html5/imports/api/deskshare/client/bridge/verto.js @@ -1,12 +1,12 @@ import Users from '/imports/api/users'; import Auth from '/imports/ui/services/auth'; -import {getConferenceBridge} from './service'; +import { getConferenceBridge } from './service'; // TODO pass info in constructor instead of importing ^^ const createVertoUserName = () => { const userId = Auth.userID; const uName = Users.findOne({ userId }).user.name; - return 'FreeSWITCH User - ' + encodeURIComponent(uName); + return `FreeSWITCH User - ${encodeURIComponent(uName)}`; }; export default class VertoDeskshareBridge { diff --git a/bigbluebutton-html5/imports/api/deskshare/server/handlers/incomingDeskshareEvent.js b/bigbluebutton-html5/imports/api/deskshare/server/handlers/incomingDeskshareEvent.js index cce1019ff2a6ba234fc948297e706d62df1b2b32..2feea406b671fb4dc906d9935c1da70e7754c9e1 100755 --- a/bigbluebutton-html5/imports/api/deskshare/server/handlers/incomingDeskshareEvent.js +++ b/bigbluebutton-html5/imports/api/deskshare/server/handlers/incomingDeskshareEvent.js @@ -16,7 +16,7 @@ export default function incomingDeskshareEvent({ payload }) { const deskShareInfo = { vw: payload.vw, vh: payload.vh, - voiceBridge: voiceBridge, // payload.voice_bridge + voiceBridge, // payload.voice_bridge broadcasting: payload.broadcasting, }; modifyDeskshareStatus(meetingId, deskShareInfo); diff --git a/bigbluebutton-html5/imports/api/deskshare/server/modifiers/clearDeskshareCollection.js b/bigbluebutton-html5/imports/api/deskshare/server/modifiers/clearDeskshareCollection.js index 369d701505b3c6eb224aeaed65e55b38ef5da59b..dc7b7753223dfb3071081aa0c5e5f5603927eaa6 100755 --- a/bigbluebutton-html5/imports/api/deskshare/server/modifiers/clearDeskshareCollection.js +++ b/bigbluebutton-html5/imports/api/deskshare/server/modifiers/clearDeskshareCollection.js @@ -3,12 +3,12 @@ import { logger } from '/imports/startup/server/logger'; export function clearDeskshareCollection(meetingId) { if (meetingId != null) { - Deskshare.remove({ meetingId: meetingId }, function () { + Deskshare.remove({ meetingId }, function () { logger.info(`cleared Deskshare Collection (meetingId: ${this.meetingId}!)`); }); } else { - Deskshare.remove({}, function () { - logger.info(`cleared Deskshare Collection (all meetings)!`); + Deskshare.remove({}, () => { + logger.info('cleared Deskshare Collection (all meetings)!'); }); } } diff --git a/bigbluebutton-html5/imports/api/deskshare/server/modifiers/modifyDeskshareStatus.js b/bigbluebutton-html5/imports/api/deskshare/server/modifiers/modifyDeskshareStatus.js index 2d8ad3cf893085d4ab0e4c97d26b6192a1a01d1a..4fca0e2ca853895441b41530dc928b9199d4e6e2 100755 --- a/bigbluebutton-html5/imports/api/deskshare/server/modifiers/modifyDeskshareStatus.js +++ b/bigbluebutton-html5/imports/api/deskshare/server/modifiers/modifyDeskshareStatus.js @@ -7,18 +7,18 @@ import { check } from 'meteor/check'; export default function modifyDeskshareStatus(meetingId, deskshareInfo) { check(meetingId, String); - const presenter = Users.findOne({ meetingId, 'user.presenter': true }); + const presenter = Users.findOne({ meetingId, 'user.presenter': true }); check(presenter, Object); check(presenter.user.userid, String); const startedById = presenter.user.userid; - Deskshare.upsert({ meetingId: meetingId }, { $set: { + Deskshare.upsert({ meetingId }, { $set: { broadcasting: deskshareInfo.broadcasting, timestamp: 'now', vw: deskshareInfo.vw, vh: deskshareInfo.vh, voiceBridge: deskshareInfo.voiceBridge, startedBy: startedById, - }, }); + } }); } diff --git a/bigbluebutton-html5/imports/api/deskshare/server/publishers.js b/bigbluebutton-html5/imports/api/deskshare/server/publishers.js index 2c479cc1c9f218bed50f574df65a1c1ea5d6f692..94e4c27d885bfce33da23adf828eaff71186fa6c 100755 --- a/bigbluebutton-html5/imports/api/deskshare/server/publishers.js +++ b/bigbluebutton-html5/imports/api/deskshare/server/publishers.js @@ -1,8 +1,8 @@ import Deskshare from '/imports/api/deskshare'; import { logger } from '/imports/startup/server/logger'; -Meteor.publish('deskshare', function (credentials) { +Meteor.publish('deskshare', (credentials) => { const { meetingId } = credentials; logger.info(`publishing deskshare for ${meetingId}`); - return Deskshare.find({ meetingId: meetingId }); + return Deskshare.find({ meetingId }); }); diff --git a/bigbluebutton-html5/imports/api/log-client/server/methods/logClient.js b/bigbluebutton-html5/imports/api/log-client/server/methods/logClient.js index 23e7d29ba5298e41f02b1c94dd09e010f4b2d531..72e451a16b1fbf793a8f29fc4d2751dfdd43e54b 100644 --- a/bigbluebutton-html5/imports/api/log-client/server/methods/logClient.js +++ b/bigbluebutton-html5/imports/api/log-client/server/methods/logClient.js @@ -4,4 +4,4 @@ export default function logClient() { const args = Array.prototype.slice.call(arguments, 1); Logger.log(arguments[0], 'Client Log', args); -}; +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/getAllMeetings.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/getAllMeetings.js index 16b27d8f1bed64e823d474db5e8d9675ce07776a..53a73eb68d293b27f0c1728422ff79c29c432fd2 100644 --- a/bigbluebutton-html5/imports/api/meetings/server/handlers/getAllMeetings.js +++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/getAllMeetings.js @@ -27,10 +27,10 @@ export default function handleGetAllMettings({ payload }) { meetingsToRemove.forEach(meeting => removeMeeting(meeting.meetingId)); - let meetingsAdded = []; - meetings.forEach(meeting => { + const meetingsAdded = []; + meetings.forEach((meeting) => { meetingsAdded.push(addMeeting(meeting)); }); return meetingsAdded; -}; +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js index aa29050be74b07e7c02dd53c090a37fa458a3ecd..31c8c9753e6d3f20ca494d4e761e91c6e8855c4f 100644 --- a/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js +++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingCreation.js @@ -8,4 +8,4 @@ export default function handleMeetingCreation({ payload }) { check(meetingId, String); return addMeeting(payload); -}; +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingDestruction.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingDestruction.js index 3e5ca2a23eca48bf9d8964af8348646bab968f91..9df6355de5263fb016dd72b784ffe0f5d6356169 100644 --- a/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingDestruction.js +++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingDestruction.js @@ -8,4 +8,4 @@ export default function handleMeetingDestruction({ payload }) { check(meetingId, String); return removeMeeting(meetingId); -}; +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/permissionSettingsChange.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/permissionSettingsChange.js index 5e2ac30b538f7130ec311f36a14fd95ced1bf912..6cff920e8b7eb01476d9822ac987eeccfe2d8c87 100644 --- a/bigbluebutton-html5/imports/api/meetings/server/handlers/permissionSettingsChange.js +++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/permissionSettingsChange.js @@ -50,4 +50,4 @@ export default function handlePermissionSettingsChange({ payload }) { }; return Meetings.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/recordingStatusChange.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/recordingStatusChange.js index c555f61840dd7d03aa7a28610b46253d209c1903..29091b99d5ae5b768276bade87a9730543891763 100644 --- a/bigbluebutton-html5/imports/api/meetings/server/handlers/recordingStatusChange.js +++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/recordingStatusChange.js @@ -33,4 +33,4 @@ export default function handleRecordingStatusChange({ payload }) { }; return Meetings.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/stunTurnReply.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/stunTurnReply.js index 0816355f79158cc8c2c1baf5eb682751694442b9..7a075ab7278dedf7ca15489cafa7a97634ce9f14 100644 --- a/bigbluebutton-html5/imports/api/meetings/server/handlers/stunTurnReply.js +++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/stunTurnReply.js @@ -30,4 +30,4 @@ export default function handleStunTurnReply({ payload }) { }; return Meetings.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js b/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js index eb34b099f286406503eaea921c4ec5c3b6ed9f91..37aacb0a7dc39719856ef61ff1de8ddaaaa6a3b2 100755 --- a/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js +++ b/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js @@ -52,4 +52,4 @@ export default function addMeeting(meeting) { }; return Meetings.upsert(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/modifiers/clearMeetings.js b/bigbluebutton-html5/imports/api/meetings/server/modifiers/clearMeetings.js index 438cc4188f7bcf132402741cd2ecbf668060317c..c3b7ac218ee4a3fd68510bf45952c114ed4ac47d 100755 --- a/bigbluebutton-html5/imports/api/meetings/server/modifiers/clearMeetings.js +++ b/bigbluebutton-html5/imports/api/meetings/server/modifiers/clearMeetings.js @@ -26,4 +26,4 @@ export default function clearMeetings() { return Logger.info('Cleared Meetings (all)'); }); -}; +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/modifiers/removeMeeting.js b/bigbluebutton-html5/imports/api/meetings/server/modifiers/removeMeeting.js index 79608307ad93f7bbd7eb5350127925e43ad0d610..263848979214161aac0e7ceb0686238f40f276f2 100755 --- a/bigbluebutton-html5/imports/api/meetings/server/modifiers/removeMeeting.js +++ b/bigbluebutton-html5/imports/api/meetings/server/modifiers/removeMeeting.js @@ -38,4 +38,4 @@ export default function removeMeeting(meetingId) { }; return Meetings.remove(selector, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/polls/server/handlers/userVoted.js b/bigbluebutton-html5/imports/api/polls/server/handlers/userVoted.js index 29261be9082d48f8738c033bb9178e59e2a6f675..3ef150e5b84c9d323127e9180fafa79c477847f2 100644 --- a/bigbluebutton-html5/imports/api/polls/server/handlers/userVoted.js +++ b/bigbluebutton-html5/imports/api/polls/server/handlers/userVoted.js @@ -13,4 +13,4 @@ export default function userVoted({ payload }) { check(requesterId, String); return updateVotes(poll, meetingId, requesterId); -}; +} diff --git a/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js b/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js index 5f7f545e4f1bd5fffc6a79bd0fc8db8450db55cc..0517399dadf9bdc302ceb15fe2e6912559b5623b 100644 --- a/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js +++ b/bigbluebutton-html5/imports/api/polls/server/methods/publishVote.js @@ -4,20 +4,20 @@ import { check } from 'meteor/check'; import Polls from '/imports/api/polls'; import Logger from '/imports/startup/server/logger'; -export default function publishVote(credentials, pollId, pollAnswerId) { //TODO discuss location +export default function publishVote(credentials, pollId, pollAnswerId) { // TODO discuss location const REDIS_CONFIG = Meteor.settings.redis; const CHANNEL = REDIS_CONFIG.channels.toBBBApps.polling; const EVENT_NAME = 'vote_poll_user_request_message'; if (!isAllowedTo('subscribePoll', credentials)) { - throw new Meteor.Error('not-allowed', `You are not allowed to publishVote`); + throw new Meteor.Error('not-allowed', 'You are not allowed to publishVote'); } const { meetingId, requesterUserId, requesterToken } = credentials; const currentPoll = Polls.findOne({ users: requesterUserId, - meetingId: meetingId, + meetingId, 'poll.answers.id': pollAnswerId, 'poll.id': pollId, }); @@ -27,7 +27,7 @@ export default function publishVote(credentials, pollId, pollAnswerId) { //TODO check(pollAnswerId, Number); check(currentPoll.meetingId, String); - let payload = { + const payload = { meeting_id: currentPoll.meetingId, user_id: requesterUserId, poll_id: currentPoll.poll.id, @@ -37,7 +37,7 @@ export default function publishVote(credentials, pollId, pollAnswerId) { //TODO const selector = { users: requesterUserId, - meetingId: meetingId, + meetingId, 'poll.answers.id': pollAnswerId, }; diff --git a/bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js b/bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js index ea091c7b82dfcce584eb2bd7689125e098c84458..91eb5e8523ce8681a6039d2618aa630249a4d9ff 100644 --- a/bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js +++ b/bigbluebutton-html5/imports/api/polls/server/modifiers/addPoll.js @@ -10,7 +10,7 @@ export default function addPoll(meetingId, requesterId, poll) { check(meetingId, String); let selector = { - meetingId: meetingId, + meetingId, }; const options = { @@ -51,4 +51,4 @@ export default function addPoll(meetingId, requesterId, poll) { }; return Polls.upsert(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/polls/server/modifiers/clearPolls.js b/bigbluebutton-html5/imports/api/polls/server/modifiers/clearPolls.js index 7e4ea4a1ea7b2ecfa23788f817f0345522a07fcc..d614528ebf32449b050282a3aeca4348984c9d37 100644 --- a/bigbluebutton-html5/imports/api/polls/server/modifiers/clearPolls.js +++ b/bigbluebutton-html5/imports/api/polls/server/modifiers/clearPolls.js @@ -3,8 +3,8 @@ import Logger from '/imports/startup/server/logger'; export default function clearPolls(meetingId) { if (meetingId) { - return Polls.remove({ meetingId, }, Logger.info(`Cleared Polls (${meetingId})`)); + return Polls.remove({ meetingId }, Logger.info(`Cleared Polls (${meetingId})`)); } return Polls.remove({}, Logger.info('Cleared Polls (all)')); -}; +} diff --git a/bigbluebutton-html5/imports/api/polls/server/modifiers/removePoll.js b/bigbluebutton-html5/imports/api/polls/server/modifiers/removePoll.js index f5af42d8febab5cf649878a77f0cbde1ad8ff16c..8be3c489bd60b3d73dbbea4879d7d7847eb78c8f 100644 --- a/bigbluebutton-html5/imports/api/polls/server/modifiers/removePoll.js +++ b/bigbluebutton-html5/imports/api/polls/server/modifiers/removePoll.js @@ -22,4 +22,4 @@ export default function removePoll(meetingId, pollId) { }; return Polls.remove(selector, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/polls/server/modifiers/updateVotes.js b/bigbluebutton-html5/imports/api/polls/server/modifiers/updateVotes.js index 624556e22dea1fd9d3e18e110c8cf97576ed1515..d8d2e63bf255d2149c406c00baee92007e04aeaf 100644 --- a/bigbluebutton-html5/imports/api/polls/server/modifiers/updateVotes.js +++ b/bigbluebutton-html5/imports/api/polls/server/modifiers/updateVotes.js @@ -31,7 +31,7 @@ export default function updateVotes(poll, meetingId, requesterId) { $set: { requester: requesterId, poll: { - answers: answers, + answers, num_responders: numResponders, num_respondents: numRespondents, id, @@ -48,4 +48,4 @@ export default function updateVotes(poll, meetingId, requesterId) { }; return Polls.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/polls/server/publishers.js b/bigbluebutton-html5/imports/api/polls/server/publishers.js index 27098f6ca8d92ff511c32bed1fcd0561e1e37327..b60f3ef87930d8db375aabc851594a63cd0286d6 100644 --- a/bigbluebutton-html5/imports/api/polls/server/publishers.js +++ b/bigbluebutton-html5/imports/api/polls/server/publishers.js @@ -5,7 +5,7 @@ import { check } from 'meteor/check'; import { logger } from '/imports/startup/server/logger'; Meteor.publish('polls', function (credentials) { - //checking if it is allowed to see Poll Collection in general + // checking if it is allowed to see Poll Collection in general if (!isAllowedTo('subscribePoll', credentials)) { this.error(new Meteor.Error(402, "The user was not authorized to subscribe for 'polls'")); } @@ -17,7 +17,7 @@ Meteor.publish('polls', function (credentials) { check(requesterToken, String); const selector = { - meetingId: meetingId, + meetingId, users: requesterUserId, }; diff --git a/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationChange.js b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationChange.js index 3c1731aa1d3f4d4a3cee285a37791b9eb4537ef7..7e13d09eab4a1c8e88569b882dc5ad961803aeb7 100644 --- a/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationChange.js +++ b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationChange.js @@ -5,23 +5,23 @@ import Presentations from '/imports/api/presentations'; import addPresentation from '../modifiers/addPresentation'; const clearCurrentPresentation = (meetingId, presentationId) => { - let selector = { + const selector = { meetingId, presentationId: { $ne: presentationId }, 'presentation.current': true, }; - let modifier = { + const modifier = { $set: { 'presentation.current': false }, }; - let cb = (err, numChanged) => { + const cb = (err, numChanged) => { if (err) { return Logger.error(`Unsetting the current presentation: ${err}`); } if (numChanged) { - return Logger.info(`Unsetted as current presentation`); + return Logger.info('Unsetted as current presentation'); } }; @@ -41,4 +41,4 @@ export default function handlePresentationChange({ payload }) { } return addPresentation(meetingId, presentation); -}; +} diff --git a/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationInfoReply.js b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationInfoReply.js index 08e3fc9a2c9a59d447fa9caa2d4281e5a91632bd..33570031b741bfca3d13442183fe022c1bcab61b 100644 --- a/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationInfoReply.js +++ b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationInfoReply.js @@ -25,10 +25,10 @@ export default function handlePresentationInfoReply({ payload }) { presentationsToRemove.forEach(p => removePresentation(meetingId, p.presentation.id)); - let presentationsAdded = []; - presentations.forEach(presentation => { + const presentationsAdded = []; + presentations.forEach((presentation) => { presentationsAdded.push(addPresentation(meetingId, presentation)); }); return presentationsAdded; -}; +} diff --git a/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationRemove.js b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationRemove.js index ba589c6484ad4375e0a6d926ba736b15c8f309c2..f9d7a12af635aec59e126fc6b817cfc2f91d7e07 100644 --- a/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationRemove.js +++ b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationRemove.js @@ -11,4 +11,4 @@ export default function handlePresentationRemove({ payload }) { check(presentationId, String); return removePresentation(meetingId, presentationId); -}; +} diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/addPresentation.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/addPresentation.js index 74c3f79d73a6bf878db455918385b6423ca2d43a..1b78a7169a7f538b8f90092488c7804cf19d4c42 100755 --- a/bigbluebutton-html5/imports/api/presentations/server/modifiers/addPresentation.js +++ b/bigbluebutton-html5/imports/api/presentations/server/modifiers/addPresentation.js @@ -5,9 +5,9 @@ import Logger from '/imports/startup/server/logger'; import addSlide from '/imports/api/slides/server/modifiers/addSlide'; const addSlides = (meetingId, presentationId, slides) => { - let slidesAdded = []; + const slidesAdded = []; - slides.forEach(slide => { + slides.forEach((slide) => { slidesAdded.push(addSlide(meetingId, presentationId, slide)); }); @@ -50,4 +50,4 @@ export default function addPresentation(meetingId, presentation) { }; return Presentations.upsert(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/changeCurrentPresentation.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/changeCurrentPresentation.js index 8657e563aa397511e34c4c608b2ebf39fd0681b2..d89a5869dd2fcceeda64ff5f8d591e89cf81c8d3 100644 --- a/bigbluebutton-html5/imports/api/presentations/server/modifiers/changeCurrentPresentation.js +++ b/bigbluebutton-html5/imports/api/presentations/server/modifiers/changeCurrentPresentation.js @@ -19,7 +19,7 @@ export default function changeCurrentPresentation(meetingId, presentationId) { return Logger.error(`Unsetting the current presentation: ${err}`); } - return Logger.info(`Unsetted as current presentation`); + return Logger.info('Unsetted as current presentation'); }, }; @@ -50,4 +50,4 @@ export default function changeCurrentPresentation(meetingId, presentationId) { if (oldPresentation) { Presentations.update(oldPresentation._id, oldCurrent.modifier, oldCurrent.callback); } -}; +} diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/clearPresentations.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/clearPresentations.js index 4301e5185679553571e6c9010ab3e2f76cf22c4c..7c0832598c3b370e7bb7c51f49cb21a69d9a8481 100755 --- a/bigbluebutton-html5/imports/api/presentations/server/modifiers/clearPresentations.js +++ b/bigbluebutton-html5/imports/api/presentations/server/modifiers/clearPresentations.js @@ -3,9 +3,8 @@ import Logger from '/imports/startup/server/logger'; export default function clearPresentations(meetingId) { if (meetingId) { - return Presentations.remove({ meetingId: meetingId }, + return Presentations.remove({ meetingId }, Logger.info(`Cleared Presentations (${meetingId})`)); - } else { - return Presentations.remove({}, Logger.info('Cleared Presentations (all)')); } -}; + return Presentations.remove({}, Logger.info('Cleared Presentations (all)')); +} diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/removePresentation.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/removePresentation.js index d2729932f1306087fef2c9502c48f6d0efc70f43..15efcd0fc09229468c8c7f49a61746121aa7e5a8 100644 --- a/bigbluebutton-html5/imports/api/presentations/server/modifiers/removePresentation.js +++ b/bigbluebutton-html5/imports/api/presentations/server/modifiers/removePresentation.js @@ -25,4 +25,4 @@ export default function removePresentation(meetingId, presentationId) { }; return Presentations.remove(selector, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardCleared.js b/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardCleared.js index cd9f477688d3f17939417f98a3c674adced868be..79190c2b883e05be92d07cbfc83327601d0d2e8f 100644 --- a/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardCleared.js +++ b/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardCleared.js @@ -11,4 +11,4 @@ export default function handleWhiteboardCleared({ payload }) { check(whiteboardId, String); return clearShapesWhiteboard(meetingId, whiteboardId); -}; +} diff --git a/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardGetReply.js b/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardGetReply.js index 815868b99edbdb5d28cd2a45d1072aaa3a13d2ed..410b45ab6ae40ce287a874a1b93c4cfe96854481 100644 --- a/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardGetReply.js +++ b/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardGetReply.js @@ -25,11 +25,11 @@ export default function handleWhiteboardGetReply({ payload }) { shapesToRemove.forEach(s => removeShape(meetingId, s.shape.wb_id, s.shape.id)); - let shapesAdded = []; - shapes.forEach(shape => { - let whiteboardId = shape.wb_id; + const shapesAdded = []; + shapes.forEach((shape) => { + const whiteboardId = shape.wb_id; shapesAdded.push(addShape(meetingId, whiteboardId, shape)); }); return shapesAdded; -}; +} diff --git a/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardSend.js b/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardSend.js index 734ea794425d4ef2f20f07a7d7f083b11920b411..e9704bcf248c7b198f4a4b24e80a282b98a6f4d7 100644 --- a/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardSend.js +++ b/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardSend.js @@ -15,4 +15,4 @@ export default function handleWhiteboardSend({ payload }) { check(whiteboardId, String); return addShape(meetingId, whiteboardId, shape); -}; +} diff --git a/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardUndo.js b/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardUndo.js index 2ba4e1672e51d4a672a3f8e921821aed4433c7a0..fc857e8fc4dc99d00af279751307bf756c7578f9 100644 --- a/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardUndo.js +++ b/bigbluebutton-html5/imports/api/shapes/server/handlers/whiteboardUndo.js @@ -13,4 +13,4 @@ export default function handleWhiteboardUndo({ payload }) { check(shapeId, String); return removeShape(meetingId, whiteboardId, shapeId); -}; +} diff --git a/bigbluebutton-html5/imports/api/shapes/server/modifiers/addShape.js b/bigbluebutton-html5/imports/api/shapes/server/modifiers/addShape.js index 1e15472fe41a028cc74f51b00a52c55b92fc5ce0..7b8f38fb10372866b4efb4bcdc5072aa9b6e6672 100644 --- a/bigbluebutton-html5/imports/api/shapes/server/modifiers/addShape.js +++ b/bigbluebutton-html5/imports/api/shapes/server/modifiers/addShape.js @@ -15,7 +15,7 @@ export default function addShape(meetingId, whiteboardId, shape) { 'shape.id': shape.id, }; - let modifier = { + const modifier = { $set: { meetingId, whiteboardId, @@ -82,4 +82,4 @@ export default function addShape(meetingId, whiteboardId, shape) { }; return Shapes.upsert(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/shapes/server/modifiers/clearShapes.js b/bigbluebutton-html5/imports/api/shapes/server/modifiers/clearShapes.js index 8a0ab5de735f11fb19616daedc475df201e498a7..e8af0e4546eca3d5329be9b0875597f3c2aee669 100755 --- a/bigbluebutton-html5/imports/api/shapes/server/modifiers/clearShapes.js +++ b/bigbluebutton-html5/imports/api/shapes/server/modifiers/clearShapes.js @@ -3,8 +3,8 @@ import Logger from '/imports/startup/server/logger'; export default function clearShapes(meetingId) { if (meetingId) { - return Shapes.remove({ meetingId, }, Logger.info(`Cleared Shapes (${meetingId})`)); + return Shapes.remove({ meetingId }, Logger.info(`Cleared Shapes (${meetingId})`)); } return Shapes.remove({}, Logger.info('Cleared Shapes (all)')); -}; +} diff --git a/bigbluebutton-html5/imports/api/shapes/server/modifiers/clearShapesWhiteboard.js b/bigbluebutton-html5/imports/api/shapes/server/modifiers/clearShapesWhiteboard.js index e85eeac3119201fbd25d7fed88c7b3e38fb02583..79b89049947c0f9ab1434868e3fac3fb32a8d6ee 100644 --- a/bigbluebutton-html5/imports/api/shapes/server/modifiers/clearShapesWhiteboard.js +++ b/bigbluebutton-html5/imports/api/shapes/server/modifiers/clearShapesWhiteboard.js @@ -20,4 +20,4 @@ export default function clearShapesWhiteboard(meetingId, whiteboardId) { }; return Shapes.remove(selector, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/shapes/server/modifiers/removeShape.js b/bigbluebutton-html5/imports/api/shapes/server/modifiers/removeShape.js index bcd2f8052fcaac0c303c36b4bc92938aed5fd026..2f5ece18e7bb154e11ee938320d664184013657b 100644 --- a/bigbluebutton-html5/imports/api/shapes/server/modifiers/removeShape.js +++ b/bigbluebutton-html5/imports/api/shapes/server/modifiers/removeShape.js @@ -24,4 +24,4 @@ export default function removeShape(meetingId, whiteboardId, shapeId) { }; return Shapes.remove(selector, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/slides/server/handlers/slideChange.js b/bigbluebutton-html5/imports/api/slides/server/handlers/slideChange.js index dd24043b97d56543d8688c727d426a1b12153821..334aa9bfb917533ec03b01f6ed10cc8b5347bac9 100644 --- a/bigbluebutton-html5/imports/api/slides/server/handlers/slideChange.js +++ b/bigbluebutton-html5/imports/api/slides/server/handlers/slideChange.js @@ -13,4 +13,4 @@ export default function handleSlideChange({ payload }) { const presentationId = slideId.split('/')[0]; return changeCurrentSlide(meetingId, presentationId, slideId); -}; +} diff --git a/bigbluebutton-html5/imports/api/slides/server/handlers/slideResize.js b/bigbluebutton-html5/imports/api/slides/server/handlers/slideResize.js index 880d08daeba07c3c3a4b7a9fc4f672e547348134..21db8e6c7a4ea29a4072d0e348a70ac1a6171fb3 100644 --- a/bigbluebutton-html5/imports/api/slides/server/handlers/slideResize.js +++ b/bigbluebutton-html5/imports/api/slides/server/handlers/slideResize.js @@ -14,4 +14,4 @@ export default function handleSlideResize({ payload }) { const presentationId = slideId.split('/')[0]; return resizeSlide(meetingId, presentationId, slideId, slide); -}; +} diff --git a/bigbluebutton-html5/imports/api/slides/server/methods/switchSlide.js b/bigbluebutton-html5/imports/api/slides/server/methods/switchSlide.js index d366cce6f0952f64faf5abbe168fb768ed2d23db..17d16811eb927e40345b1897987a57563b6494af 100755 --- a/bigbluebutton-html5/imports/api/slides/server/methods/switchSlide.js +++ b/bigbluebutton-html5/imports/api/slides/server/methods/switchSlide.js @@ -19,7 +19,7 @@ export default function switchSlide(credentials, slideNumber) { check(slideNumber, Number); if (!isAllowedTo('switchSlide', credentials)) { - throw new Meteor.Error('not-allowed', `You are not allowed to switchSlide`); + throw new Meteor.Error('not-allowed', 'You are not allowed to switchSlide'); } const Presentation = Presentations.findOne({ @@ -29,7 +29,7 @@ export default function switchSlide(credentials, slideNumber) { if (!Presentation) { throw new Meteor.Error( - 'presentation-not-found', `You need a presentation to be able to switch slides`); + 'presentation-not-found', 'You need a presentation to be able to switch slides'); } const Slide = Slides.findOne({ @@ -43,10 +43,10 @@ export default function switchSlide(credentials, slideNumber) { 'slide-not-found', `Slide number ${slideNumber} not found in the current presentation`); } - let payload = { + const payload = { page: Slide.slide.id, meeting_id: meetingId, }; return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload); -}; +} diff --git a/bigbluebutton-html5/imports/api/slides/server/modifiers/addSlide.js b/bigbluebutton-html5/imports/api/slides/server/modifiers/addSlide.js index b14f9d5dc4a5684abbeea67ea52f358a5b325c8c..ed6ec611b70c1a2b5098a238442ea56db6c53673 100755 --- a/bigbluebutton-html5/imports/api/slides/server/modifiers/addSlide.js +++ b/bigbluebutton-html5/imports/api/slides/server/modifiers/addSlide.js @@ -11,7 +11,7 @@ const requestWhiteboardHistory = (meetingId, slideId) => { const CHANNEL = REDIS_CONFIG.channels.toBBBApps.whiteboard; const EVENT_NAME = 'request_whiteboard_annotation_history_request'; - let payload = { + const payload = { meeting_id: meetingId, requester_id: 'nodeJSapp', whiteboard_id: slideId, @@ -85,11 +85,11 @@ export default function addSlide(meetingId, presentationId, slide) { }) .catch(reason => Logger.error(`Error parsing image size. ${reason}. slide=${slide.id} uri=${imageUri}`)); -}; +} -const fetchImageSizes = (imageUri) => +const fetchImageSizes = imageUri => probe(imageUri) - .then(result => { + .then((result) => { if (!SUPPORTED_TYPES.includes(result.mime)) { throw `Invalid image type, received ${result.mime} expecting ${SUPPORTED_TYPES.join()}`; } @@ -99,7 +99,7 @@ const fetchImageSizes = (imageUri) => height: result.height, }; }) - .catch(reason => { + .catch((reason) => { Logger.error(`Error parsing image size. ${reason}. uri=${imageUri}`); return reason; }); diff --git a/bigbluebutton-html5/imports/api/slides/server/modifiers/changeCurrentSlide.js b/bigbluebutton-html5/imports/api/slides/server/modifiers/changeCurrentSlide.js index c022d5f042f3952aa34ca579088fad7dd3ea9472..f551ab0a2c68c584ee46365570be8f14d4df5dce 100755 --- a/bigbluebutton-html5/imports/api/slides/server/modifiers/changeCurrentSlide.js +++ b/bigbluebutton-html5/imports/api/slides/server/modifiers/changeCurrentSlide.js @@ -21,7 +21,7 @@ export default function changeCurrentSlide(meetingId, presentationId, slideId) { return Logger.error(`Unsetting the current slide: ${err}`); } - return Logger.info(`Unsetted the current slide`); + return Logger.info('Unsetted the current slide'); }, }; @@ -53,4 +53,4 @@ export default function changeCurrentSlide(meetingId, presentationId, slideId) { if (oldSlide) { Slides.update(oldSlide._id, oldCurrent.modifier, oldCurrent.callback); } -}; +} diff --git a/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlides.js b/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlides.js index c20dd62f2dca3a28a394b18a6e528aac5bbabd4f..6ca772b1ca3ff0312e684f0237db9c642496ffe2 100755 --- a/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlides.js +++ b/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlides.js @@ -7,4 +7,4 @@ export default function clearSlides(meetingId) { } return Slides.remove({}, Logger.info('Cleared Slides (all)')); -}; +} diff --git a/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesPresentation.js b/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesPresentation.js index e82923a0271f86383b39c326a479d5b5f94b090b..8f4247953c24bc06d3a268d418052eeb71f8a3c5 100644 --- a/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesPresentation.js +++ b/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesPresentation.js @@ -27,4 +27,4 @@ export default function clearSlidesPresentation(meetingId, presentationId) { }; return Slides.remove(selector, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/slides/server/modifiers/resizeSlide.js b/bigbluebutton-html5/imports/api/slides/server/modifiers/resizeSlide.js old mode 100644 new mode 100755 index 6eae4cdc3cd19399e626fff1cf8a7f408e12b00f..309320c125a000aac3bb9f0f10902de320863bb5 --- a/bigbluebutton-html5/imports/api/slides/server/modifiers/resizeSlide.js +++ b/bigbluebutton-html5/imports/api/slides/server/modifiers/resizeSlide.js @@ -1,4 +1,3 @@ -import probe from 'probe-image-size'; import { check } from 'meteor/check'; import Slides from '/imports/api/slides'; import Logger from '/imports/startup/server/logger'; @@ -35,4 +34,4 @@ export default function resizeSlide(meetingId, presentationId, slideId, slide) { }; return Slides.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/emojiStatus.js b/bigbluebutton-html5/imports/api/users/server/handlers/emojiStatus.js index f13c2d46451124ae1379947611b7fcb1429589a7..435399ba0c4d57b99cd8ac9032e54b71a5c091a6 100755 --- a/bigbluebutton-html5/imports/api/users/server/handlers/emojiStatus.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/emojiStatus.js @@ -29,11 +29,11 @@ export default function handleEmojiStatus({ payload }) { } if (numChanged) { - return Logger.info('Assigned user emoji status' - + status + ' id=' + userId + ' meeting=' + meetingId + return Logger.info(`Assigned user emoji status${ + status} id=${userId} meeting=${meetingId}`, ); } }; return Users.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/getUsers.js b/bigbluebutton-html5/imports/api/users/server/handlers/getUsers.js index 8fdbca484648027a6bfb46dd6d128f0472f5f734..6d92cb9dbdcc1297728b19b03ba9ba7ec307ef74 100644 --- a/bigbluebutton-html5/imports/api/users/server/handlers/getUsers.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/getUsers.js @@ -26,10 +26,10 @@ export default function handleGetUsers({ payload }) { usersToRemove.forEach(user => removeUser(meetingId, user.userId)); - let usersAdded = []; - users.forEach(user => { + const usersAdded = []; + users.forEach((user) => { usersAdded.push(addUser(meetingId, user)); }); return usersAdded; -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/kickUser.js b/bigbluebutton-html5/imports/api/users/server/handlers/kickUser.js index 16e61b442cb23480d6daa42bc2162543becfbc6d..b132f31742306ad1e952f8612fdbbc31a583dd8e 100644 --- a/bigbluebutton-html5/imports/api/users/server/handlers/kickUser.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/kickUser.js @@ -11,4 +11,4 @@ export default function handleKickUser({ payload }) { check(userId, String); return kickUser(meetingId, userId); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/listeningOnly.js b/bigbluebutton-html5/imports/api/users/server/handlers/listeningOnly.js index 63fa0c82f7994d68b0e43154d53e99372af8988f..4e70dc0cc26468d646a726561ef9e925d77b20b7 100644 --- a/bigbluebutton-html5/imports/api/users/server/handlers/listeningOnly.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/listeningOnly.js @@ -29,10 +29,10 @@ export default function handleListeningOnly({ payload }) { if (numChanged) { return Logger.info( - `Assigned listen only status '${listenOnly}' user=${userId} meeting=${meetingId}` + `Assigned listen only status '${listenOnly}' user=${userId} meeting=${meetingId}`, ); } }; return Users.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/lockedStatusChange.js b/bigbluebutton-html5/imports/api/users/server/handlers/lockedStatusChange.js index f439a9eb1a8fc7eff036e1b730356e889f83556b..df596642116bbf281d78bfbdc135a3194fd53257 100755 --- a/bigbluebutton-html5/imports/api/users/server/handlers/lockedStatusChange.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/lockedStatusChange.js @@ -21,7 +21,7 @@ export default function handleLockedStatusChange({ payload }) { const User = Users.findOne(selector); if (!User) { throw new Meteor.Error( - 'user-not-found', `You need a valid user to be able to set presenter`); + 'user-not-found', 'You need a valid user to be able to set presenter'); } const modifier = { @@ -41,7 +41,6 @@ export default function handleLockedStatusChange({ payload }) { && !User.user.voiceUser.muted && User.user.voiceUser.joined && isLocked) { - const credentials = { meetingId, requesterUserId: userId, @@ -56,4 +55,4 @@ export default function handleLockedStatusChange({ payload }) { }; return Users.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/presenterAssigned.js b/bigbluebutton-html5/imports/api/users/server/handlers/presenterAssigned.js index 9d4e1fe652383d375f0c82a1e3c0dbb89359d4d9..2099d54bc7b05047be38d7e12357b9596f23f234 100644 --- a/bigbluebutton-html5/imports/api/users/server/handlers/presenterAssigned.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/presenterAssigned.js @@ -32,7 +32,7 @@ export default function handlePresenterAssigned({ payload }) { }; return Users.update(selector, modifier, cb); -}; +} const unassignCurrentPresenter = (meetingId, newPresenterId) => { const selector = { diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/removeUser.js b/bigbluebutton-html5/imports/api/users/server/handlers/removeUser.js index a99e54cac78cd91c1aa3c8e9b3672f4559b6419c..e5bcf0005317121d75aedb74a9ddfb217ecc289b 100644 --- a/bigbluebutton-html5/imports/api/users/server/handlers/removeUser.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/removeUser.js @@ -11,4 +11,4 @@ export default function handleRemoveUser({ payload }) { check(userId, String); return removeUser(meetingId, userId); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/userJoined.js b/bigbluebutton-html5/imports/api/users/server/handlers/userJoined.js index 1ab2b64f85f57870d4d585e0e1b894a3cacfb084..70d18c03a8eb8a457a9cf6aa42067b934428b326 100644 --- a/bigbluebutton-html5/imports/api/users/server/handlers/userJoined.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/userJoined.js @@ -11,4 +11,4 @@ export default function handleUserJoined({ payload }) { check(user, Object); return addUser(meetingId, user); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/validateAuthToken.js b/bigbluebutton-html5/imports/api/users/server/handlers/validateAuthToken.js index b5ae1279ff70655100cc9b6ab880899e3e3fe3c7..cf646521c058cb97eddd6e94331d19e10470f018 100755 --- a/bigbluebutton-html5/imports/api/users/server/handlers/validateAuthToken.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/validateAuthToken.js @@ -45,14 +45,14 @@ export default function handleValidateAuthToken({ payload }) { addWelcomeChatMessage(meetingId, userId); } - return Logger.info('Validated auth token as ' + validStatus + - +' user=' + userId + ' meeting=' + meetingId + return Logger.info(`Validated auth token as ${validStatus + }${+' user='}${userId} meeting=${meetingId}`, ); } }; return Users.update(selector, modifier, cb); -}; +} const addWelcomeChatMessage = (meetingId, userId) => { const APP_CONFIG = Meteor.settings.public.app; @@ -60,7 +60,7 @@ const addWelcomeChatMessage = (meetingId, userId) => { const Meeting = Meetings.findOne({ meetingId }); - let welcomeMessage = APP_CONFIG.defaultWelcomeMessage + const welcomeMessage = APP_CONFIG.defaultWelcomeMessage .concat(APP_CONFIG.defaultWelcomeMessageFooter) .replace(/%%CONFNAME%%/, Meeting.meetingName); diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/voiceUpdate.js b/bigbluebutton-html5/imports/api/users/server/handlers/voiceUpdate.js index ab4e8c51711e150aac48b060900f0e8f7b9d413c..92a936385204dfff04699e287076695938487392 100644 --- a/bigbluebutton-html5/imports/api/users/server/handlers/voiceUpdate.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/voiceUpdate.js @@ -17,4 +17,4 @@ export default function handleVoiceUpdate({ payload }) { check(userId, String); return updateVoiceUser(meetingId, userId, voiceUser); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/methods/assignPresenter.js b/bigbluebutton-html5/imports/api/users/server/methods/assignPresenter.js index 4d6f2ff2a51b5d836fa86fe2059d2bdc411e53d4..d6b59a351168f3b67ea00fdfbd7c20a8c67186e7 100755 --- a/bigbluebutton-html5/imports/api/users/server/methods/assignPresenter.js +++ b/bigbluebutton-html5/imports/api/users/server/methods/assignPresenter.js @@ -17,7 +17,7 @@ export default function assignPresenter(credentials, userId) { check(userId, String); if (!isAllowedTo('setPresenter', credentials)) { - throw new Meteor.Error('not-allowed', `You are not allowed to setPresenter`); + throw new Meteor.Error('not-allowed', 'You are not allowed to setPresenter'); } const User = Users.findOne({ @@ -26,10 +26,10 @@ export default function assignPresenter(credentials, userId) { }); if (!User) { throw new Meteor.Error( - 'user-not-found', `You need a valid user to be able to set presenter`); + 'user-not-found', 'You need a valid user to be able to set presenter'); } - let payload = { + const payload = { new_presenter_id: userId, new_presenter_name: User.user.name, meeting_id: meetingId, @@ -40,4 +40,4 @@ export default function assignPresenter(credentials, userId) { requesterUserId}' from meeting '${meetingId}'`); return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/methods/kickUser.js b/bigbluebutton-html5/imports/api/users/server/methods/kickUser.js index 86f189f8a562500544de2dba93216e7e4b27f75b..31775075bcd26d63637d3ce108de46038e9eee7a 100755 --- a/bigbluebutton-html5/imports/api/users/server/methods/kickUser.js +++ b/bigbluebutton-html5/imports/api/users/server/methods/kickUser.js @@ -16,10 +16,10 @@ export default function kickUser(credentials, userId) { check(userId, String); if (!isAllowedTo('kickUser', credentials)) { - throw new Meteor.Error('not-allowed', `You are not allowed to kickUser`); + throw new Meteor.Error('not-allowed', 'You are not allowed to kickUser'); } - let payload = { + const payload = { userid: userId, ejected_by: requesterUserId, meeting_id: meetingId, @@ -28,4 +28,4 @@ export default function kickUser(credentials, userId) { Logger.verbose(`User '${userId}' was kicked by '${requesterUserId}' from meeting '${meetingId}'`); return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/methods/listenOnlyToggle.js b/bigbluebutton-html5/imports/api/users/server/methods/listenOnlyToggle.js index 2fbe1d0f76fd971ffd091e277ab7efeb2e7b776d..02d15266f50cd7f96f50e1878b8aaa5b28eb8b9a 100755 --- a/bigbluebutton-html5/imports/api/users/server/methods/listenOnlyToggle.js +++ b/bigbluebutton-html5/imports/api/users/server/methods/listenOnlyToggle.js @@ -16,24 +16,24 @@ export default function listenOnlyToggle(credentials, isJoining = true) { check(requesterUserId, String); check(isJoining, Boolean); - let EVENT_NAME = undefined; + let EVENT_NAME; if (isJoining) { EVENT_NAME = 'user_connected_to_global_audio'; if (!isAllowedTo('joinListenOnly', credentials)) { - throw new Meteor.Error('not-allowed', `You are not allowed to joinListenOnly`); + throw new Meteor.Error('not-allowed', 'You are not allowed to joinListenOnly'); } } else { EVENT_NAME = 'user_disconnected_from_global_audio'; if (!isAllowedTo('leaveListenOnly', credentials)) { - throw new Meteor.Error('not-allowed', `You are not allowed to leaveListenOnly`); + throw new Meteor.Error('not-allowed', 'You are not allowed to leaveListenOnly'); } } const Metting = Meetings.findOne({ meetingId }); if (!Metting) { throw new Meteor.Error( - 'metting-not-found', `You need a valid meeting to be able to toggle audio`); + 'metting-not-found', 'You need a valid meeting to be able to toggle audio'); } check(Metting.voiceConf, String); @@ -45,12 +45,12 @@ export default function listenOnlyToggle(credentials, isJoining = true) { if (!User) { throw new Meteor.Error( - 'user-not-found', `You need a valid user to be able to toggle audio`); + 'user-not-found', 'You need a valid user to be able to toggle audio'); } check(User.user.name, String); - let payload = { + const payload = { userid: requesterUserId, meeting_id: meetingId, voice_conf: Metting.voiceConf, @@ -61,4 +61,4 @@ export default function listenOnlyToggle(credentials, isJoining = true) { ? 'joined' : 'left'} global audio from meeting '${meetingId}'`); return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/methods/muteToggle.js b/bigbluebutton-html5/imports/api/users/server/methods/muteToggle.js index 2ca6d69141ac88003fb5a0caef776cf471ba98fb..2ce9ba3bfbdafd957c3e9363cea7b703ee581ad7 100755 --- a/bigbluebutton-html5/imports/api/users/server/methods/muteToggle.js +++ b/bigbluebutton-html5/imports/api/users/server/methods/muteToggle.js @@ -25,7 +25,7 @@ export default function muteToggle(credentials, userId, isMuted = true) { throw new Meteor.Error('not-allowed', `You are not allowed to ${action}`); } - let payload = { + const payload = { user_id: userId, meeting_id: meetingId, mute: isMuted, @@ -36,4 +36,4 @@ export default function muteToggle(credentials, userId, isMuted = true) { requesterUserId}' from meeting '${meetingId}'`); return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/methods/requestStunTurn.js b/bigbluebutton-html5/imports/api/users/server/methods/requestStunTurn.js index 6558d2692f927d12a9db4d100a2904990323ef8d..228d0b687df53e6c26257e8684517665daa600b2 100644 --- a/bigbluebutton-html5/imports/api/users/server/methods/requestStunTurn.js +++ b/bigbluebutton-html5/imports/api/users/server/methods/requestStunTurn.js @@ -11,7 +11,7 @@ export default function requestStunTurn(meetingId, requesterUserId) { check(meetingId, String); check(requesterUserId, String); - let payload = { + const payload = { meeting_id: meetingId, requester_id: requesterUserId, }; @@ -19,4 +19,4 @@ export default function requestStunTurn(meetingId, requesterUserId) { Logger.verbose(`User '${requesterUserId}' requested stun/turn from meeting '${meetingId}'`); return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/methods/setEmojiStatus.js b/bigbluebutton-html5/imports/api/users/server/methods/setEmojiStatus.js index f30f5a796ba5d1c9ea5dedd9b16a58d0013a875a..f4ef62af9879d67289fac63bbf5f25b665fb17c3 100755 --- a/bigbluebutton-html5/imports/api/users/server/methods/setEmojiStatus.js +++ b/bigbluebutton-html5/imports/api/users/server/methods/setEmojiStatus.js @@ -16,10 +16,10 @@ export default function setEmojiStatus(credentials, userId, status) { check(userId, String); if (!isAllowedTo('setEmojiStatus', credentials)) { - throw new Meteor.Error('not-allowed', `You are not allowed to setEmojiStatus`); + throw new Meteor.Error('not-allowed', 'You are not allowed to setEmojiStatus'); } - let payload = { + const payload = { emoji_status: status, userid: userId, meeting_id: meetingId, @@ -29,4 +29,4 @@ export default function setEmojiStatus(credentials, userId, status) { requesterUserId}' from meeting '${meetingId}'`); return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/methods/userLeaving.js b/bigbluebutton-html5/imports/api/users/server/methods/userLeaving.js index c1e3911a84b4b3c898d4ceaca5589298f27688d1..8f69b500e1f1ee748825c0138590b294f2f2fe80 100755 --- a/bigbluebutton-html5/imports/api/users/server/methods/userLeaving.js +++ b/bigbluebutton-html5/imports/api/users/server/methods/userLeaving.js @@ -60,11 +60,11 @@ export default function userLeaving(credentials, userId) { Users.update(selector, modifier, cb); } - let payload = { + const payload = { meeting_id: meetingId, userid: userId, }; Logger.verbose(`User '${requesterUserId}' left meeting '${meetingId}'`); return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/methods/userLogout.js b/bigbluebutton-html5/imports/api/users/server/methods/userLogout.js index 949e52e55af6f21187e31e154e919ea5f3af9acf..fd87d8e3e12ae0491946dd97baea5361a4907984 100755 --- a/bigbluebutton-html5/imports/api/users/server/methods/userLogout.js +++ b/bigbluebutton-html5/imports/api/users/server/methods/userLogout.js @@ -6,14 +6,14 @@ import userLeaving from './userLeaving'; export default function userLogout(credentials) { if (!isAllowedTo('logoutSelf', credentials)) { - throw new Meteor.Error('not-allowed', `You are not allowed to logoutSelf`); + throw new Meteor.Error('not-allowed', 'You are not allowed to logoutSelf'); } const { requesterUserId } = credentials; try { userLeaving(credentials, requesterUserId); - } catch(e) { + } catch (e) { Logger.error(`Exception while executing userLeaving: ${e}`); } -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/methods/validateAuthToken.js b/bigbluebutton-html5/imports/api/users/server/methods/validateAuthToken.js index b8ac498d7c2d0aced9cf92f67e7ce5a9bce96a6e..ff760b1b1b39c34de3272926eff2430c2b20729d 100755 --- a/bigbluebutton-html5/imports/api/users/server/methods/validateAuthToken.js +++ b/bigbluebutton-html5/imports/api/users/server/methods/validateAuthToken.js @@ -32,7 +32,7 @@ export default function validateAuthToken(credentials) { setConnectionStatus(meetingId, requesterUserId, ONLINE_CONNECTION_STATUS); } - let payload = { + const payload = { auth_token: requesterToken, userid: requesterUserId, meeting_id: meetingId, @@ -47,4 +47,4 @@ export default function validateAuthToken(credentials) { }' is trying to validate auth tokenfor meeting '${meetingId}'`); return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload, header); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js b/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js index 0b58b873b5af0650b902a71493d3cea508045ad5..dcd6d39db2a53dde94c0d6faec64726e0f9a788b 100644 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js @@ -24,7 +24,7 @@ export default function addUser(meetingId, user) { const ALLOW_HTML5_MODERATOR = APP_CONFIG.allowHTML5Moderator; // override moderator status of html5 client users, depending on a system flag - let dummyUser = Users.findOne(selector); + const dummyUser = Users.findOne(selector); if (dummyUser && dummyUser.clientType === 'HTML5' && user.role === ROLE_MODERATOR && @@ -82,4 +82,4 @@ export default function addUser(meetingId, user) { }; return Users.upsert(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/clearUsers.js b/bigbluebutton-html5/imports/api/users/server/modifiers/clearUsers.js index 6a37f791d418e7cfb59df37c80ed25f8d71a0dad..76f88e59fb19b09eda9f3ed9cb3d219bcee1330b 100755 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/clearUsers.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/clearUsers.js @@ -7,4 +7,4 @@ export default function clearUsers(meetingId) { } return Users.remove({}, Logger.info('Cleared Users (all)')); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/createDummyUser.js b/bigbluebutton-html5/imports/api/users/server/modifiers/createDummyUser.js index 4fcb9c71a280ff368a69f96ecfb42720bc6ea9a5..a292b1bf077b8924906ee02d5a2a9cd0fbde7ca7 100755 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/createDummyUser.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/createDummyUser.js @@ -10,7 +10,7 @@ export default function createDummyUser(meetingId, userId, authToken) { const User = Users.findOne({ meetingId, userId }); if (User) { - throw new Meteor.Error('existing-user', `Tried to create a dummy user for an existing user`); + throw new Meteor.Error('existing-user', 'Tried to create a dummy user for an existing user'); } const doc = { @@ -30,4 +30,4 @@ export default function createDummyUser(meetingId, userId, authToken) { }; return Users.insert(doc, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/kickUser.js b/bigbluebutton-html5/imports/api/users/server/modifiers/kickUser.js index 63dcfab1d065b1651e5c02cc63de2a0ef925730d..6c5e69dd4c65b87b6817744da9876c0aa634904a 100644 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/kickUser.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/kickUser.js @@ -40,4 +40,4 @@ export default function kickUser(meetingId, userId) { }; return Users.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/lockAllViewersMic.js b/bigbluebutton-html5/imports/api/users/server/modifiers/lockAllViewersMic.js index 6d595e612045cf7cdcb98b34388bb74422acce97..17e222619250195baa8fe9fec4dd452def236b8a 100755 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/lockAllViewersMic.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/lockAllViewersMic.js @@ -18,6 +18,6 @@ export default function lockAllViewersMic(meetingId) { muteToggle({ meetingId, requesterUserId: user.userId, - }, userId, true) + }, userId, true), ); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/removeUser.js b/bigbluebutton-html5/imports/api/users/server/modifiers/removeUser.js index 6a2912ace68c86ca858ebdb4a25417946d3605e8..3c0b485e2999e9973d8f7e0c9fb66e2bd660c985 100644 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/removeUser.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/removeUser.js @@ -43,4 +43,4 @@ export default function removeUser(meetingId, userId) { }; return Users.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/setConnectionStatus.js b/bigbluebutton-html5/imports/api/users/server/modifiers/setConnectionStatus.js index 36a4206c451c6f13e56130f317c2f68f5aecf5c4..1e969be0af21bfbeb9901eb1b7842ba97a428bfb 100755 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/setConnectionStatus.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/setConnectionStatus.js @@ -38,4 +38,4 @@ export default function setConnectionStatus(meetingId, userId, status = 'online' }; return Users.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/updateVoiceUser.js b/bigbluebutton-html5/imports/api/users/server/modifiers/updateVoiceUser.js index d94fa3a54e22fc71ebd95362ca1af2c0fdae1da3..2e9654459e9f77836af84658790f9dc716b3adc7 100755 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/updateVoiceUser.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/updateVoiceUser.js @@ -32,4 +32,4 @@ export default function updateVoiceUser(meetingId, userId, voiceUser) { }; return Users.update(selector, modifier, cb); -}; +} diff --git a/bigbluebutton-html5/imports/api/users/server/publishers.js b/bigbluebutton-html5/imports/api/users/server/publishers.js index a4207a7ca789cfc0dcc461b7d3d4e0cdc20cb1b9..43218ad248133c8cea02b10f0a03713612870d89 100644 --- a/bigbluebutton-html5/imports/api/users/server/publishers.js +++ b/bigbluebutton-html5/imports/api/users/server/publishers.js @@ -6,7 +6,7 @@ import { isAllowedTo } from '/imports/startup/server/userPermissions'; import userLeaving from './methods/userLeaving'; -Meteor.publish('current-user', function (credentials) { +Meteor.publish('current-user', (credentials) => { const { meetingId, requesterUserId, requesterToken } = credentials; check(meetingId, String); @@ -42,7 +42,7 @@ Meteor.publish('users', function (credentials) { this.onStop(() => { try { userLeaving(credentials, requesterUserId); - } catch(e) { + } catch (e) { Logger.error(`Exception while executing userLeaving: ${e}`); } }); diff --git a/bigbluebutton-html5/imports/startup/client/auth.js b/bigbluebutton-html5/imports/startup/client/auth.js index 5f09e2d164e5c67682577f7d5925ca74183b79d4..9f7ebd339488252124044dfa9b063627c20a31e9 100755 --- a/bigbluebutton-html5/imports/startup/client/auth.js +++ b/bigbluebutton-html5/imports/startup/client/auth.js @@ -14,21 +14,21 @@ export function joinRouteHandler(nextState, replace, callback) { Auth.set(meetingID, userID, authToken); replace({ pathname: '/' }); callback(); -}; +} export function logoutRouteHandler(nextState, replace, callback) { const { meetingID, userID, authToken } = nextState.params; Auth.logout() - .then(logoutURL => { + .then((logoutURL) => { window.location = logoutURL || window.location.origin; callback(); }) - .catch(reason => { + .catch((reason) => { replace({ pathname: '/error/500' }); callback(); }); -}; +} export function authenticatedRouteHandler(nextState, replace, callback) { const credentialsSnapshot = { @@ -45,7 +45,7 @@ export function authenticatedRouteHandler(nextState, replace, callback) { Auth.authenticate() .then(callback) - .catch(reason => { + .catch((reason) => { logClient('error', { error: reason, method: 'authenticatedRouteHandler', @@ -63,13 +63,12 @@ export function authenticatedRouteHandler(nextState, replace, callback) { replace({ pathname: `/error/${reason.error}` }); callback(); }); -}; +} function _addReconnectObservable() { let lastStatus = null; Tracker.autorun(() => { - lastStatus = updateStatus(Meteor.status(), lastStatus); if (shouldAuthenticate(Meteor.status(), lastStatus)) { diff --git a/bigbluebutton-html5/imports/startup/client/base.js b/bigbluebutton-html5/imports/startup/client/base.js index ad1fa4d66197910a5e813daf6dfe3cdae14ad1d7..8ce15e76df4743ed562de22eddc20da4cd33673d 100644 --- a/bigbluebutton-html5/imports/startup/client/base.js +++ b/bigbluebutton-html5/imports/startup/client/base.js @@ -53,7 +53,7 @@ class Base extends Component { return (<LoadingScreen>{loading}</LoadingScreen>); } - return (<AppContainer {...this.props} baseControls={stateControls}/>); + return (<AppContainer {...this.props} baseControls={stateControls} />); } render() { @@ -67,7 +67,7 @@ class Base extends Component { </IntlStartup> ); } -}; +} const SUBSCRIPTIONS_NAME = [ 'users', 'chat', 'cursor', 'deskshare', 'meetings', diff --git a/bigbluebutton-html5/imports/startup/client/intl.js b/bigbluebutton-html5/imports/startup/client/intl.js old mode 100644 new mode 100755 index 1c7ddaa0308a9bf82a88f909b45161d5abae1310..584818c9be3335bebc08feea646338f01800a624 --- a/bigbluebutton-html5/imports/startup/client/intl.js +++ b/bigbluebutton-html5/imports/startup/client/intl.js @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { IntlProvider } from 'react-intl'; const propTypes = { @@ -28,20 +29,19 @@ class IntlStartup extends Component { baseControls.updateLoadingState(true); fetch(url) - .then(response => { + .then((response) => { if (response.ok) { return response.json(); - } else { - this.setState({ appLocale: 'en' }); - return response.json(); } + this.setState({ appLocale: 'en' }); + return response.json(); }) - .then(messages => { + .then((messages) => { this.setState({ messages }, () => { baseControls.updateLoadingState(false); }); }) - .catch(reason => { + .catch((reason) => { baseControls.updateErrorState(reason); baseControls.updateLoadingState(false); }); @@ -65,7 +65,7 @@ class IntlStartup extends Component { </IntlProvider> ); } -}; +} export default IntlStartup; diff --git a/bigbluebutton-html5/imports/startup/client/routes.js b/bigbluebutton-html5/imports/startup/client/routes.js index 7f7d5b27b2a688a54425ab638c062f218d9b3edb..f7ffa37387bb28201a0266c3d409a4689f4d7227 100755 --- a/bigbluebutton-html5/imports/startup/client/routes.js +++ b/bigbluebutton-html5/imports/startup/client/routes.js @@ -16,18 +16,22 @@ const browserHistory = useRouterHistory(createHistory)({ export const renderRoutes = () => ( <Router history={browserHistory}> <Route path="/logout" onEnter={logoutRouteHandler} /> - <Route path="/join/:meetingID/:userID/:authToken" - component={LoadingScreen} onEnter={joinRouteHandler} /> + <Route + path="/join/:meetingID/:userID/:authToken" + component={LoadingScreen} onEnter={joinRouteHandler} + /> <Route path="/" component={Base} onEnter={authenticatedRouteHandler} > <IndexRoute components={{}} /> <Route name="users" path="users" components={{ userList: UserListContainer }} /> - <Route name="chat" path="users/chat/:chatID" components={{ - userList: UserListContainer, - chat: ChatContainer, - }} /> + <Route + name="chat" path="users/chat/:chatID" components={{ + userList: UserListContainer, + chat: ChatContainer, + }} + /> <Redirect from="users/chat" to="/users/chat/public" /> </Route> - <Route name="error" path="/error/:errorCode" component={Base}/> + <Route name="error" path="/error/:errorCode" component={Base} /> <Redirect from="*" to="/error/404" /> </Router> ); diff --git a/bigbluebutton-html5/imports/startup/server/index.js b/bigbluebutton-html5/imports/startup/server/index.js index 5c64b14063bcfc8ac9c8280cb1ee87526ac40dea..a3eb5c198fb1c41ac926fc4e39923ea0812011c7 100755 --- a/bigbluebutton-html5/imports/startup/server/index.js +++ b/bigbluebutton-html5/imports/startup/server/index.js @@ -12,7 +12,7 @@ Meteor.startup(() => { }); WebApp.connectHandlers.use('/check', (req, res, next) => { - let payload = { html5clientStatus: 'running' }; + const payload = { html5clientStatus: 'running' }; res.setHeader('Content-Type', 'application/json'); res.writeHead(200); @@ -21,23 +21,23 @@ WebApp.connectHandlers.use('/check', (req, res, next) => { WebApp.connectHandlers.use('/locale', (req, res) => { const APP_CONFIG = Meteor.settings.public.app; - let defaultLocale = APP_CONFIG.defaultLocale; - let localeRegion = req.query.locale.split('-'); + const defaultLocale = APP_CONFIG.defaultLocale; + const localeRegion = req.query.locale.split('-'); let messages = {}; - let locales = [defaultLocale, localeRegion[0]]; + const locales = [defaultLocale, localeRegion[0]]; let statusCode = 200; if (localeRegion.length > 1) { locales.push(`${localeRegion[0]}_${localeRegion[1].toUpperCase()}`); } - locales.forEach(locale => { + locales.forEach((locale) => { try { const data = Assets.getText(`locales/${locale}.json`); messages = Object.assign(messages, JSON.parse(data)); } catch (e) { - //Variant Also Negotiates Status-Code, to alert the client that we - //do not support the following lang. - //https://en.wikipedia.org/wiki/Content_negotiation + // Variant Also Negotiates Status-Code, to alert the client that we + // do not support the following lang. + // https://en.wikipedia.org/wiki/Content_negotiation statusCode = 506; } }); @@ -49,7 +49,7 @@ WebApp.connectHandlers.use('/locale', (req, res) => { WebApp.connectHandlers.use('/locales', (req, res) => { if (!availableLocales.length) { - locales.forEach(l => { + locales.forEach((l) => { try { Assets.absoluteFilePath(`locales/${l.locale}.json`); availableLocales.push(l); @@ -66,4 +66,4 @@ WebApp.connectHandlers.use('/locales', (req, res) => { export const eventEmitter = Redis.emitter; -export let redisPubSub = Redis; +export const redisPubSub = Redis; diff --git a/bigbluebutton-html5/imports/startup/server/logger.js b/bigbluebutton-html5/imports/startup/server/logger.js index d1ba3fd4ec6c24ee75bbff0f88a65c8c103e23f5..360c75656fed0ab71303ce0884d3c8676a564b74 100755 --- a/bigbluebutton-html5/imports/startup/server/logger.js +++ b/bigbluebutton-html5/imports/startup/server/logger.js @@ -1,10 +1,10 @@ import { Meteor } from 'meteor/meteor'; import Winston from 'winston'; -let Logger = new Winston.Logger(); +const Logger = new Winston.Logger(); Logger.configure({ - levels: { error: 0, warn: 1, info: 2, verbose: 3, debug: 4, }, + levels: { error: 0, warn: 1, info: 2, verbose: 3, debug: 4 }, colors: { error: 'red', warn: 'yellow', @@ -37,7 +37,7 @@ Meteor.startup(() => { } Logger.add(Winston.transports.File, { - filename: filename, + filename, prettyPrint: true, }); } @@ -45,4 +45,4 @@ Meteor.startup(() => { export default Logger; -export let logger = Logger; +export const logger = Logger; diff --git a/bigbluebutton-html5/imports/startup/server/redis.js b/bigbluebutton-html5/imports/startup/server/redis.js index 58bbac3b6ddffec0666e6bb5b5dc6ffb589812e3..256ec756746bd61c9db297f687957153b74ef904 100755 --- a/bigbluebutton-html5/imports/startup/server/redis.js +++ b/bigbluebutton-html5/imports/startup/server/redis.js @@ -41,18 +41,18 @@ class RedisPubSub { } publish(channel, eventName, payload = {}, header = {}) { - let message = { + const message = { header: Object.assign({ timestamp: new Date().getTime(), name: eventName, }, header), - payload: payload, + payload, }; this._debug(`Publishing ${eventName} to ${channel}`); return this.pub.publish(channel, JSON.stringify(message), (err, res) => { if (err) { - Logger.error(`Tried to publish to %s`, channel, message); + Logger.error('Tried to publish to %s', channel, message); } }); } @@ -75,13 +75,13 @@ class RedisPubSub { if (!messagesWeIgnore.includes(eventName)) { this._debug(`${eventName} added to queue`); - //Logger.info(`QUEUE | PROGRESS ${this.queue.progress()}% | LENGTH ${this.queue.length()}}`); + // Logger.info(`QUEUE | PROGRESS ${this.queue.progress()}% | LENGTH ${this.queue.length()}}`); return this.queue.add({ - pattern: pattern, - channel: channel, - eventName: eventName, - message: message, + pattern, + channel, + eventName, + message, }); } } @@ -95,11 +95,11 @@ class RedisPubSub { this._debug(`${eventName} emitted`); return this.emitter .emitAsync(eventName, message) - .then(_ => { + .then((_) => { this._debug(`${eventName} completed`); return next(); }) - .catch(reason => { + .catch((reason) => { this._debug(`${eventName} completed with error`); Logger.error(`${eventName}: ${reason}`); return next(); @@ -116,9 +116,9 @@ class RedisPubSub { Logger.info(message); } } -}; +} -let RedisPubSubSingleton = new RedisPubSub(); +const RedisPubSubSingleton = new RedisPubSub(); Meteor.startup(() => { const REDIS_CONFIG = Meteor.settings.redis; diff --git a/bigbluebutton-html5/imports/startup/server/userPermissions.js b/bigbluebutton-html5/imports/startup/server/userPermissions.js index d1e15611b58eb52159b0b1a25d11789f15c14c7e..035464f3e59a888fedf62a0fc2aba04f378030af 100755 --- a/bigbluebutton-html5/imports/startup/server/userPermissions.js +++ b/bigbluebutton-html5/imports/startup/server/userPermissions.js @@ -5,7 +5,7 @@ import { logger } from '/imports/startup/server/logger'; const presenter = { switchSlide: true, - //poll + // poll subscribePoll: true, subscribeAnswers: true, @@ -33,27 +33,27 @@ const moderator = { logoutSelf: true, - //subscribing + // subscribing subscribeUsers: true, subscribeChat: true, - //chat + // chat chatPublic: true, chatPrivate: true, - //poll + // poll subscribePoll: true, subscribeAnswers: false, - //emojis + // emojis setEmojiStatus: true, clearEmojiStatus: true, - //user control + // user control kickUser: true, setPresenter: true, - //captions + // captions subscribeCaptions: true, }; @@ -86,11 +86,11 @@ const viewer = function (meetingId, userId) { logoutSelf: true, - //subscribing + // subscribing subscribeUsers: true, subscribeChat: true, - //chat + // chat chatPublic: !((meeting = Meetings.findOne({ meetingId })) != null && meeting.roomLockSettings.disablePublicChat) || !((user = Users.findOne({ meetingId, userId })) != null && @@ -103,15 +103,15 @@ const viewer = function (meetingId, userId) { user.user.locked) || (user != null && user.user.presenter), - //poll + // poll subscribePoll: true, subscribeAnswers: false, - //emojis + // emojis setEmojiStatus: true, clearEmojiStatus: true, - //captions + // captions subscribeCaptions: true, }; }; @@ -165,9 +165,7 @@ export function isAllowedTo(action, credentials) { logger.debug(`attempt from userId=${userId} to perform:${action}, allowed=${result}`); return result; - } else { - logger.error(`FAILED due to permissions:${action} ${JSON.stringify(credentials)}`); - return false; } - -}; + logger.error(`FAILED due to permissions:${action} ${JSON.stringify(credentials)}`); + return false; +} diff --git a/bigbluebutton-html5/imports/ui/components/about/component.jsx b/bigbluebutton-html5/imports/ui/components/about/component.jsx index a6c3ba05cbbf2b63f5aa5a7e332350042a1ec220..a42a9bce7ee55e73c4a656855e52cc584a6df2aa 100755 --- a/bigbluebutton-html5/imports/ui/components/about/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/about/component.jsx @@ -44,12 +44,13 @@ class AboutComponent extends Component { dismiss={{ label: intl.formatMessage(intlMessages.dismissLabel), description: intl.formatMessage(intlMessages.dismissDesc), - }}> - {`${intl.formatMessage(intlMessages.copyright)} ${copyright}`} <br/> + }} + > + {`${intl.formatMessage(intlMessages.copyright)} ${copyright}`} <br /> {`${intl.formatMessage(intlMessages.version)} ${clientBuild}`} </Modal> ); } -}; +} export default injectIntl(AboutComponent); diff --git a/bigbluebutton-html5/imports/ui/components/about/container.jsx b/bigbluebutton-html5/imports/ui/components/about/container.jsx old mode 100644 new mode 100755 index a24f08c72703180a663ee5a4b781965c30c8e8f0..45c31b6085120ecc0f6eae9024fb199d560e1e69 --- a/bigbluebutton-html5/imports/ui/components/about/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/about/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import AboutComponent from './component'; @@ -24,6 +25,4 @@ const getClientBuildInfo = function () { }; }; -export default createContainer(function () { - return getClientBuildInfo(); -}, AboutContainer); +export default createContainer(() => getClientBuildInfo(), AboutContainer); diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx index bb40f78bb4131cc19b89524f9ccf7a099c9344cb..2106fe163b8979aabc68486ce5c0a82e9ef05bab 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import Button from '/imports/ui/components/button/component'; @@ -39,11 +40,11 @@ const intlMessages = defineMessages({ }, }); -const presentation = () => {console.log('Should show the uploader component');}; +const presentation = () => { console.log('Should show the uploader component'); }; -const polling = () => {console.log('Should initiate a polling');}; +const polling = () => { console.log('Should initiate a polling'); }; -const shareScreen = () => {console.log('Should start screen sharing');}; +const shareScreen = () => { console.log('Should start screen sharing'); }; class ActionsDropdown extends Component { constructor(props) { @@ -64,7 +65,7 @@ class ActionsDropdown extends Component { icon="add" color="primary" size="lg" - circle={true} + circle onClick={() => null} /> </DropdownTrigger> diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx index 7ca0f02ac63d1b2a21901351053a74f834b94d8d..31b73bb67719318aa38f1cfe07141de3a6a87a77 100644 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx @@ -16,7 +16,7 @@ export default class ActionsBar extends Component { return ( <div className={styles.actionsbar}> <div className={styles.left}> - <ActionsDropdown {...{ isUserPresenter }}/> + <ActionsDropdown {...{ isUserPresenter }} /> </div> <div className={styles.center}> <MuteAudioContainer /> @@ -24,7 +24,7 @@ export default class ActionsBar extends Component { handleJoinAudio={this.props.handleOpenJoinAudio} handleCloseAudio={this.props.handleExitAudio} /> - {/*<JoinVideo />*/} + {/* <JoinVideo />*/} <EmojiContainer /> </div> </div> diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx index d0fd3dc1e708accdbc263b49fde2709a6b93b201..9a19d36810b2a0c4098dca4581a42f0356cbbbaa 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx @@ -15,8 +15,9 @@ class ActionsBarContainer extends Component { render() { return ( <ActionsBar - {...this.props}> - {this.props.children} + {...this.props} + > + {this.props.children} </ActionsBar> ); } @@ -31,7 +32,7 @@ export default withModalMounter(createContainer(({ mountModal }) => { return { isUserPresenter: isPresenter, - handleExitAudio: handleExitAudio, - handleOpenJoinAudio: handleOpenJoinAudio, + handleExitAudio, + handleOpenJoinAudio, }; }, ActionsBarContainer)); diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/component.jsx index 867e350f97d2810494cbc99229269fdf0989ff6d..2ecc99ee2fadd9454d680f4c6826ddf9c51c4849 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import Button from '/imports/ui/components/button/component'; @@ -18,7 +19,6 @@ const propTypes = { class EmojiMenu extends Component { constructor(props) { super(props); - } render() { @@ -38,14 +38,15 @@ class EmojiMenu extends Component { aria-describedby="currentStatus" icon="hand" ghost={false} - circle={true} + circle hideLabel={false} color="primary" size="lg" // FIXME: Without onClick react proptypes keep warning // even after the DropdownTrigger inject an onClick handler - onClick={() => null}> + onClick={() => null} + > <div id="currentStatus" hidden> { intl.formatMessage(intlMessages.currentStatusDesc, { 0: userEmojiStatus }) diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/container.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/container.jsx index fe09bf78973cc0382ca9da58934b515287db30f1..47961f870a8c46fa498c0b9f0a339be03d558804 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import EmojiService from './service'; @@ -22,7 +23,7 @@ class EmojiContainer extends React.Component { } = this.props; return ( - <EmojiMenu userEmojiStatus={userEmojiStatus} actions={actions}/> + <EmojiMenu userEmojiStatus={userEmojiStatus} actions={actions} /> ); } } diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/service.js b/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/service.js index 0ed663967697f0558805ba260f79b4181a5d6eb2..519c01321875fc43f14207a1ba8a12e07e002a7c 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/service.js +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/emoji-menu/service.js @@ -2,8 +2,7 @@ import Auth from '/imports/ui/services/auth/index.js'; import Users from '/imports/api/users'; import { makeCall } from '/imports/ui/services/api/index.js'; -let getEmojiData = () => { - +const getEmojiData = () => { // Get userId and meetingId const credentials = Auth.credentials; const { requesterUserId: userId, meetingId } = credentials; @@ -15,8 +14,8 @@ let getEmojiData = () => { }).user.emoji_status; return { - userEmojiStatus: userEmojiStatus, - credentials: credentials, + userEmojiStatus, + credentials, }; }; diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/mute-button/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/mute-button/component.jsx index 9d68255bbeb114cd46a3fba39b49a3877fe3c9ee..be0d7190f7d1de9a95b905800689327ed1e94f4c 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/mute-button/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/mute-button/component.jsx @@ -30,9 +30,9 @@ class MuteAudio extends React.Component { const muteLabel = intl.formatMessage(intlMessages.muteLabel); const unmuteLabel = intl.formatMessage(intlMessages.unmuteLabel); - let label = !isMuted ? muteLabel : unmuteLabel; - let icon = !isMuted ? 'unmute' : 'mute'; - let tabIndex = !isInAudio ? -1 : 0; + const label = !isMuted ? muteLabel : unmuteLabel; + const icon = !isMuted ? 'unmute' : 'mute'; + const tabIndex = !isInAudio ? -1 : 0; let className = null; if (isInAudio && isTalking) { @@ -46,7 +46,7 @@ class MuteAudio extends React.Component { color={'primary'} icon={icon} size={'lg'} - circle={true} + circle className={className} tabIndex={tabIndex} /> diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/mute-button/container.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/mute-button/container.jsx index 36c25b62af440a806e0f1fbbcd15c465e05d9a40..18245671fec5c7661cc4644f3ba29d64070ccab2 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/mute-button/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/mute-button/container.jsx @@ -16,7 +16,7 @@ class MuteAudioContainer extends React.Component { export default createContainer((params) => { const userId = Auth.userID; - const user = Users.findOne({ userId: userId }).user; + const user = Users.findOne({ userId }).user; const isMuted = user.voiceUser.muted; const isInAudio = user.voiceUser.joined; const isTalking = user.voiceUser.talking; diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/service.js b/bigbluebutton-html5/imports/ui/components/actions-bar/service.js index 9249374326b469e27cd93802f0575b1682c116be..209e4ea3ace7fcc556454828db6415af25b91f18 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/service.js +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/service.js @@ -2,7 +2,7 @@ import React from 'react'; import Auth from '/imports/ui/services/auth/index.js'; import Users from '/imports/api/users'; -let isUserPresenter = () => Users.findOne({ +const isUserPresenter = () => Users.findOne({ userId: Auth.userID, }).user.presenter; diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/video-button/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/video-button/component.jsx index 21398df92ce26eb8153b6c120dcb674b855698a8..7c796ce6e771c110ced03c85b4b3ae7b04cb9c34 100644 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/video-button/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/video-button/component.jsx @@ -15,7 +15,7 @@ export default class JoinVideo extends React.Component { color={'primary'} icon={'video_off'} size={'lg'} - circle={true} + circle style={{ visibility: 'hidden' }} /> ); diff --git a/bigbluebutton-html5/imports/ui/components/app/component.jsx b/bigbluebutton-html5/imports/ui/components/app/component.jsx index 045325dd36d806d2c34313efa4290fb9f72e8d9c..d1c77ee64c54416eef6e53da600c84c786ce2bd8 100755 --- a/bigbluebutton-html5/imports/ui/components/app/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/app/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import _ from 'lodash'; @@ -99,7 +100,7 @@ class App extends Component { if (!userList) return; - let userListStyle = {}; + const userListStyle = {}; userListStyle[styles.compact] = compactUserList; userList = React.cloneElement(userList, { compact: compactUserList, @@ -108,8 +109,9 @@ class App extends Component { return ( <nav className={cx(styles.userList, userListStyle)} - aria-label={intl.formatMessage(intlMessages.userListLabel)}> - {userList} + aria-label={intl.formatMessage(intlMessages.userListLabel)} + > + {userList} </nav> ); } @@ -123,8 +125,9 @@ class App extends Component { <section className={styles.chat} role="region" - aria-label={intl.formatMessage(intlMessages.chatLabel)}> - {chat} + aria-label={intl.formatMessage(intlMessages.chatLabel)} + > + {chat} </section> ); } @@ -138,9 +141,10 @@ class App extends Component { <section className={styles.media} role="region" - aria-label={intl.formatMessage(intlMessages.mediaLabel)}> - {media} - {this.renderClosedCaption()} + aria-label={intl.formatMessage(intlMessages.mediaLabel)} + > + {media} + {this.renderClosedCaption()} </section> ); } @@ -154,8 +158,9 @@ class App extends Component { <section className={styles.actionsbar} role="region" - aria-label={intl.formatMessage(intlMessages.actionsbarLabel)}> - {actionsbar} + aria-label={intl.formatMessage(intlMessages.actionsbarLabel)} + > + {actionsbar} </section> ); } diff --git a/bigbluebutton-html5/imports/ui/components/app/container.jsx b/bigbluebutton-html5/imports/ui/components/app/container.jsx index 32c1799779706d6f106971cb92ac7f39b1b14d48..2c82bd97048112f9975a45077b4adaaefef20765 100755 --- a/bigbluebutton-html5/imports/ui/components/app/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/app/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes, cloneElement } from 'react'; +import React, { Component, cloneElement } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import { withRouter } from 'react-router'; import { defineMessages, injectIntl } from 'react-intl'; @@ -37,7 +38,7 @@ const intlMessages = defineMessages({ class AppContainer extends Component { render() { // inject location on the navbar container - let navbarWithLocation = cloneElement(this.props.navbar, { location: this.props.location }); + const navbarWithLocation = cloneElement(this.props.navbar, { location: this.props.location }); return ( <App {...this.props} navbar={navbarWithLocation}> @@ -45,36 +46,36 @@ class AppContainer extends Component { </App> ); } -}; +} export default withRouter(injectIntl(withModalMounter(createContainer(( { router, intl, mountModal, baseControls }) => { // Check if user is kicked out of the session - Users.find({ userId: Auth.userID }).observeChanges({ - changed(id, fields) { - if (fields.user && fields.user.kicked) { - Auth.clearCredentials() + Users.find({ userId: Auth.userID }).observeChanges({ + changed(id, fields) { + if (fields.user && fields.user.kicked) { + Auth.clearCredentials() .then(() => { router.push('/error/403'); baseControls.updateErrorState( intl.formatMessage(intlMessages.kickedMessage), ); }); - } - }, - }); + } + }, + }); // Close the widow when the current breakout room ends - Breakouts.find({ breakoutMeetingId: Auth.meetingID }).observeChanges({ - removed(old) { - Auth.clearCredentials().then(window.close); - }, - }); + Breakouts.find({ breakoutMeetingId: Auth.meetingID }).observeChanges({ + removed(old) { + Auth.clearCredentials().then(window.close); + }, + }); - return { - closedCaption: getCaptionsStatus() ? <ClosedCaptionsContainer /> : null, - fontSize: getFontSize(), - }; - }, AppContainer)))); + return { + closedCaption: getCaptionsStatus() ? <ClosedCaptionsContainer /> : null, + fontSize: getFontSize(), + }; +}, AppContainer)))); AppContainer.defaultProps = defaultProps; diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-menu/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-menu/component.jsx index f99f850075bd3d66e95a110c6f08db570ee9976d..2d6b33775ee218f3e38d627b7832f7e31448d952 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-menu/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-menu/component.jsx @@ -33,7 +33,7 @@ class JoinAudioOptions extends React.Component { color={'danger'} icon={'audio_off'} size={'lg'} - circle={true} + circle /> ); } @@ -45,7 +45,7 @@ class JoinAudioOptions extends React.Component { color={'primary'} icon={'audio_on'} size={'lg'} - circle={true} + circle /> ); } diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-modal/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-modal/component.jsx index 57dea15be52d5e1d3e72e6bf6183b73c193e228c..2685e511b49698d37e7a0a14c9eb0abaacf16c64 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-modal/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-modal/component.jsx @@ -19,8 +19,8 @@ export default class AudioModal extends React.Component { * initialized to 0 */ this.setState({ activeSubmenu: 0 }); - this.submenus.push({ componentName: JoinAudio, }); - this.submenus.push({ componentName: AudioSettings, }); + this.submenus.push({ componentName: JoinAudio }); + this.submenus.push({ componentName: AudioSettings }); } handleSubmenuChange(i) { @@ -30,7 +30,7 @@ export default class AudioModal extends React.Component { renderSubmenu(key) { const curr = this.state.activeSubmenu ? 0 : this.state.activeSubmenu; - let props = { + const props = { changeMenu: this.handleSubmenuChange.bind(this), JOIN_AUDIO: this.JOIN_AUDIO, AUDIO_SETTINGS: this.AUDIO_SETTINGS, @@ -39,7 +39,7 @@ export default class AudioModal extends React.Component { }; const Submenu = this.submenus[key].componentName; - return <Submenu {...props}/>; + return <Submenu {...props} />; } render() { @@ -51,4 +51,4 @@ export default class AudioModal extends React.Component { </ModalBase> ); } -}; +} diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-notification/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-notification/component.jsx index 7e5287ddd19c41a448f88c5ce6e010918919a07a..d0c3d1823f4e599bb3b2bb8cbe713407fc14578f 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-notification/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-notification/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import styles from './styles.scss'; import cx from 'classnames'; @@ -44,23 +45,24 @@ class AudioNotification extends Component { if (!color || !message) { return null; - } else { - return ( - <div - role="alert" - className={cx(styles.audioNotifications, styles[this.props.color])}> - {message} - <Button className={styles.closeBtn} - label={intl.formatMessage(intlMessages.closeLabel)} - icon={'close'} - size={'sm'} - circle={true} - hideLabel={true} - onClick={this.handleClose} - /> - </div> - ); } + return ( + <div + role="alert" + className={cx(styles.audioNotifications, styles[this.props.color])} + > + {message} + <Button + className={styles.closeBtn} + label={intl.formatMessage(intlMessages.closeLabel)} + icon={'close'} + size={'sm'} + circle + hideLabel + onClick={this.handleClose} + /> + </div> + ); } } diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-notification/container.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-notification/container.jsx index 8d2cea45e82da8f9065eea1ac5b9ddb08581f1ea..5e386ca1b3a60c6d780494f62e568f1db3050b26 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-notification/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-notification/container.jsx @@ -73,7 +73,7 @@ class AudioNotificationContainer extends Component { } export default injectIntl(createContainer(({ intl }) => { - let messages = {}; + const messages = {}; messages.audioFailure = intl.formatMessage(intlMessages.audioFailed); messages.mediaFailure = intl.formatMessage(intlMessages.mediaFailed); return messages; diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx index 8bff98de026fe88bcf650f60266553318c3d18bc..b7046fa92b15c6821ba03196509e36b5f52170fb 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx @@ -52,12 +52,13 @@ class AudioSettings extends React.Component { return ( <div> <div className={styles.topRow}> - <Button className={styles.backBtn} + <Button + className={styles.backBtn} label={intl.formatMessage(intlMessages.backLabel)} icon={'left_arrow'} size={'md'} color={'primary'} - ghost={true} + ghost onClick={this.chooseAudio} /> <div className={cx(styles.title, styles.chooseAudio)}> @@ -83,7 +84,8 @@ class AudioSettings extends React.Component { value={this.state.inputDeviceId} className={styles.select} kind="audioinput" - onChange={this.handleInputChange} /> + onChange={this.handleInputChange} + /> </div> </div> <div className={styles.col}> @@ -92,10 +94,11 @@ class AudioSettings extends React.Component { {intl.formatMessage(intlMessages.speakerSourceLabel)} </label> <DeviceSelector - value={this.state.outputDeviceId} - className={styles.select} - kind="audiooutput" - onChange={this.handleOutputChange} /> + value={this.state.outputDeviceId} + className={styles.select} + kind="audiooutput" + onChange={this.handleOutputChange} + /> </div> </div> </div> @@ -108,23 +111,24 @@ class AudioSettings extends React.Component { </label> <AudioStreamVolume deviceId={this.state.inputDeviceId} - className={styles.audioMeter} /> + className={styles.audioMeter} + /> </div> </div> <div className={styles.col}> <label className={styles.label}>Â </label> - <AudioTestContainer/> + <AudioTestContainer /> </div> </div> </div> <div className={styles.enterAudio}> - <EnterAudioContainer isFullAudio={true}/> + <EnterAudioContainer isFullAudio /> </div> </div> ); } -}; +} const intlMessages = defineMessages({ backLabel: { diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-stream-volume/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-stream-volume/component.jsx index b91b9edc92c70cde5786e3862b6eabeb62ec151c..0104cd50d5618886324c9ce843264d87cdc924b6 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-stream-volume/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-stream-volume/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { logClient } from '/imports/ui/services/api'; const propTypes = { @@ -59,7 +60,7 @@ class AudioStreamVolume extends Component { this.scriptProcessor.onaudioprocess = this.handleAudioProcess; this.source = null; - let constraints = { + const constraints = { audio: true, }; @@ -96,8 +97,8 @@ class AudioStreamVolume extends Component { const sum = input.reduce((a, b) => a + (b * b), 0); const instant = Math.sqrt(sum / input.length); - this.setState((prevState) => ({ - instant: instant, + this.setState(prevState => ({ + instant, slow: 0.75 * prevState.slow + 0.25 * instant, })); } @@ -122,7 +123,7 @@ class AudioStreamVolume extends Component { /> ); } -}; +} AudioStreamVolume.propTypes = propTypes; AudioStreamVolume.defaultProps = defaultProps; diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-test/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-test/component.jsx index 071e2d80bb896b1980cea23bdda5a01f4e94a693..33ace856628851727ace7c1b0e192c0e80c05e32 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-test/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-test/component.jsx @@ -14,7 +14,8 @@ class AudioTest extends React.Component { } = this.props; return ( - <Button className={styles.testAudioBtn} + <Button + className={styles.testAudioBtn} label={intl.formatMessage(intlMessages.playSoundLabel)} icon={'unmute'} size={'sm'} @@ -23,7 +24,7 @@ class AudioTest extends React.Component { /> ); } -}; +} const intlMessages = defineMessages({ playSoundLabel: { diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-test/container.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-test/container.jsx index a9c85b0a7fc93aaa24fbf20bdd7c8968a84b66a2..37420893afe78df3005acb3826e9ae1fb85dbd16 100644 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-test/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-test/container.jsx @@ -16,11 +16,9 @@ class AudioTestContainer extends Component { } } -export default createContainer(function () { - return { - handlePlayAudioSample: () => { - const snd = new Audio('resources/sounds/audioSample.mp3'); - snd.play(); - }, - }; -}, AudioTestContainer); +export default createContainer(() => ({ + handlePlayAudioSample: () => { + const snd = new Audio('resources/sounds/audioSample.mp3'); + snd.play(); + }, +}), AudioTestContainer); diff --git a/bigbluebutton-html5/imports/ui/components/audio/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/component.jsx index 3ca1802e5d62139f41e2bbfecccd480ef8de5749..978cbe9af0ead95e4fd69bf3aa5174e27ea7ace5 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/component.jsx @@ -7,6 +7,6 @@ export default class Audio extends Component { } render() { - return (<audio id="remote-media" autoPlay="autoplay"></audio>); + return (<audio id="remote-media" autoPlay="autoplay" />); } } diff --git a/bigbluebutton-html5/imports/ui/components/audio/device-selector/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/device-selector/component.jsx index a0b907349a63708a55eadf710623f8a2d88fcb92..b5166625edbec5727d659a9bb766c365bb5dfa54 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/device-selector/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/device-selector/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; const propTypes = { kind: PropTypes.oneOf(['audioinput', 'audiooutput', 'videoinput']), @@ -67,13 +68,15 @@ class DeviceSelector extends Component { {...props} value={value} onChange={this.handleSelectChange} - disabled={!options.length}> + disabled={!options.length} + > { options.length ? options.map((option, i) => ( <option key={i} - value={option.value}> + value={option.value} + > {option.label} </option> )) : @@ -82,7 +85,7 @@ class DeviceSelector extends Component { </select> ); } -}; +} DeviceSelector.propTypes = propTypes; DeviceSelector.defaultProps = defaultProps; diff --git a/bigbluebutton-html5/imports/ui/components/audio/enter-audio/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/enter-audio/component.jsx index 76cb12e4de44beb3b187c767cf8c9a573bc2fde2..a7338fc002a1eb1b9a857a3f52b7c32c2e316cbd 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/enter-audio/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/enter-audio/component.jsx @@ -23,7 +23,7 @@ class EnterAudio extends React.Component { </div> ); } -}; +} const intlMessages = defineMessages({ enterSessionLabel: { diff --git a/bigbluebutton-html5/imports/ui/components/audio/enter-audio/container.jsx b/bigbluebutton-html5/imports/ui/components/audio/enter-audio/container.jsx index a0fe3682bd549929a3c9f76596f8b30954e3c6b9..30a84bea882d683c03c822b1ceca7cfdcfb5a564 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/enter-audio/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/enter-audio/container.jsx @@ -15,7 +15,7 @@ class EnterAudioContainer extends Component { mountModal, } = this.props; - let handleJoin = () => { + const handleJoin = () => { mountModal(null); return isFullAudio ? AudioService.joinMicrophone() : AudioService.joinListenOnly(); }; diff --git a/bigbluebutton-html5/imports/ui/components/audio/join-audio/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/join-audio/component.jsx index e8ff3b6a1b3b03496e904121648136802fdbf859..c0ae66ce1a76df1fa7142b2b04bc2f1234c3dc3d 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/join-audio/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/join-audio/component.jsx @@ -51,11 +51,12 @@ class JoinAudio extends React.Component { return ( <div> <div className={styles.closeBtn}> - <Button className={styles.closeBtn} + <Button + className={styles.closeBtn} label={intl.formatMessage(intlMessages.closeLabel)} icon={'close'} size={'lg'} - hideLabel={true} + hideLabel onClick={this.handleClose} /> </div> @@ -64,20 +65,21 @@ class JoinAudio extends React.Component { {intl.formatMessage(intlMessages.audioChoiceLabel)} </div> <div className={styles.center}> - <Button className={styles.audioBtn} + <Button + className={styles.audioBtn} label={intl.formatMessage(intlMessages.microphoneLabel)} icon={'unmute'} - circle={true} + circle size={'jumbo'} onClick={this.openAudio} /> - <span className={styles.verticalLine}> - </span> - <Button className={styles.audioBtn} + <span className={styles.verticalLine} /> + <Button + className={styles.audioBtn} label={intl.formatMessage(intlMessages.listenOnlyLabel)} icon={'listen'} - circle={true} + circle size={'jumbo'} onClick={this.openListen} /> @@ -85,6 +87,6 @@ class JoinAudio extends React.Component { </div> ); } -}; +} export default withModalMounter(injectIntl(JoinAudio)); diff --git a/bigbluebutton-html5/imports/ui/components/audio/service.js b/bigbluebutton-html5/imports/ui/components/audio/service.js index 8a190d387a11ca81d5dc9a2641114c04e1b40cd0..99b27ca9c65351a953b97cf0a929e382e665f292 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/service.js +++ b/bigbluebutton-html5/imports/ui/components/audio/service.js @@ -6,13 +6,13 @@ import Auth from '/imports/ui/services/auth'; import AudioManager from '/imports/api/audio/client/manager'; -let audioManager = undefined; +let audioManager; const init = () => { const userId = Auth.userID; const User = Users.findOne({ userId }); const username = User.user.name; - const Meeting = Meetings.findOne(); //TODO test this with Breakouts + const Meeting = Meetings.findOne(); // TODO test this with Breakouts const turns = Meeting.turns; const stuns = Meeting.stuns; const voiceBridge = Meeting.voiceConf; @@ -30,9 +30,9 @@ const init = () => { audioManager = new AudioManager(userData); }; -let exitAudio = () => audioManager.exitAudio(); -let joinListenOnly = () => audioManager.joinAudio(true); -let joinMicrophone = () => audioManager.joinAudio(false); +const exitAudio = () => audioManager.exitAudio(); +const joinListenOnly = () => audioManager.joinAudio(true); +const joinMicrophone = () => audioManager.joinAudio(false); export default { init, diff --git a/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx b/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx index aa325e5b4aaf9c8f764dfee7c5b02e6e163d58f9..eb5ce8f7aae535e87aa1261792cdb502a1d5670a 100755 --- a/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx @@ -64,11 +64,12 @@ class BreakoutJoinConfirmation extends Component { dismiss={{ label: intl.formatMessage(intlMessages.dismissLabel), description: intl.formatMessage(intlMessages.dismissDesc), - }}> + }} + > {`${intl.formatMessage(intlMessages.message)} ${breakoutName}?`} </Modal> ); } -}; +} export default withModalMounter(injectIntl(BreakoutJoinConfirmation)); diff --git a/bigbluebutton-html5/imports/ui/components/button/base/component.jsx b/bigbluebutton-html5/imports/ui/components/button/base/component.jsx index eeeb064665ac32d256656f82546549c9dddb675e..122b155b7fcc749c867d60b7ff9afa180a913f1c 100755 --- a/bigbluebutton-html5/imports/ui/components/button/base/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/button/base/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; const propTypes = { /** @@ -92,7 +93,7 @@ export default class ButtonBase extends Component { } render() { - let Component = this.props.tagName; + const Component = this.props.tagName; const remainingProps = Object.assign({}, this.props); delete remainingProps.label; diff --git a/bigbluebutton-html5/imports/ui/components/button/component.jsx b/bigbluebutton-html5/imports/ui/components/button/component.jsx index c4f16c1efce238043b65398351cb48884d12c65d..3beb422516b6b4cb2bb931af1029200f9ff97160 100755 --- a/bigbluebutton-html5/imports/ui/components/button/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/button/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import BaseButton from './base/component'; import styles from './styles'; import cx from 'classnames'; diff --git a/bigbluebutton-html5/imports/ui/components/chat/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/component.jsx index 6c1cec82e9bb723415fa38b2ed420d569d87211c..2a1a879ea5bfdd65e540ac8546d185675e5d56ac 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/component.jsx @@ -35,6 +35,8 @@ class Chat extends Component { lastReadMessageTime, partnerIsLoggedOut, isChatLocked, + minMessageLength, + maxMessageLength, actions, intl, } = this.props; @@ -47,8 +49,9 @@ class Chat extends Component { <Link to="/users" role="button" - aria-label={intl.formatMessage(intlMessages.hideChatLabel, { 0: title })}> - <Icon iconName="left_arrow"/> {title} + aria-label={intl.formatMessage(intlMessages.hideChatLabel, { 0: title })} + > + <Icon iconName="left_arrow" /> {title} </Link> </div> <div className={styles.closeIcon}> @@ -58,8 +61,9 @@ class Chat extends Component { <Link to="/users" role="button" - aria-label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })}> - <Icon iconName="close" onClick={() => actions.handleClosePrivateChat(chatID)}/> + aria-label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })} + > + <Icon iconName="close" onClick={() => actions.handleClosePrivateChat(chatID)} /> </Link>) } </div> @@ -81,6 +85,8 @@ class Chat extends Component { chatAreaId={ELEMENT_ID} chatTitle={title} chatName={chatName} + minMessageLength={minMessageLength} + maxMessageLength={maxMessageLength} handleSendMessage={actions.handleSendMessage} /> </div> diff --git a/bigbluebutton-html5/imports/ui/components/chat/container.jsx b/bigbluebutton-html5/imports/ui/components/chat/container.jsx index e4705b2976db00564f20aa027d1b1e351e93f8c6..49a18fa75fe12dff833c7935b586e7ace45e0b98 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import { createContainer } from 'meteor/react-meteor-data'; @@ -51,7 +52,7 @@ export default injectIntl(createContainer(({ params, intl }) => { messages = ChatService.getPrivateMessages(chatID); } - let user = ChatService.getUser(chatID, '{{NAME}}'); + const user = ChatService.getUser(chatID, '{{NAME}}'); let partnerIsLoggedOut = false; @@ -59,22 +60,22 @@ export default injectIntl(createContainer(({ params, intl }) => { partnerIsLoggedOut = !user.isOnline; if (messages && chatID !== PUBLIC_CHAT_KEY) { - let userMessage = messages.find(m => m.sender !== null); - let user = ChatService.getUser(chatID, '{{NAME}}'); + const userMessage = messages.find(m => m.sender !== null); + const user = ChatService.getUser(chatID, '{{NAME}}'); title = intl.formatMessage(intlMessages.titlePrivate, { 0: user.name }); chatName = user.name; if (!user.isOnline) { - let time = Date.now(); - let id = `partner-disconnected-${time}`; - let messagePartnerLoggedOut = { + const time = Date.now(); + const id = `partner-disconnected-${time}`; + const messagePartnerLoggedOut = { id, content: [{ id, text: intl.formatMessage(intlMessages.partnerDisconnected, { 0: user.name }), time, - },], + }], time, sender: null, }; @@ -99,13 +100,14 @@ export default injectIntl(createContainer(({ params, intl }) => { partnerIsLoggedOut, isChatLocked, scrollPosition, + minMessageLength: CHAT_CONFIG.min_message_length, + maxMessageLength: CHAT_CONFIG.max_message_length, actions: { - handleClosePrivateChat: chatID => ChatService.closePrivateChat(chatID), - handleSendMessage: message => { + handleSendMessage: (message) => { ChatService.updateScrollPosition(chatID, null); - let sentMessage = ChatService.sendMessage(chatID, message); + return ChatService.sendMessage(chatID, message); }, handleScrollUpdate: position => ChatService.updateScrollPosition(chatID, position), diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx index 5fdbef7ee8990a75344aaa74ac7390a71899a19c..1d7318f79037154dcc9063b16b75b3066d7696bb 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import { findDOMNode } from 'react-dom'; import cx from 'classnames'; @@ -27,6 +28,12 @@ const messages = defineMessages({ id: 'app.chat.inputPlaceholder', description: 'Chat message input placeholder', }, + errorMinMessageLength: { + id: 'app.chat.errorMinMessageLength', + }, + errorMaxMessageLength: { + id: 'app.chat.errorMaxMessageLength', + }, }); class MessageForm extends Component { @@ -35,97 +42,123 @@ class MessageForm extends Component { this.state = { message: '', + error: '', + hasErrors: false, }; this.handleMessageChange = this.handleMessageChange.bind(this); this.handleMessageKeyDown = this.handleMessageKeyDown.bind(this); this.handleSubmit = this.handleSubmit.bind(this); - } handleMessageKeyDown(e) { - - //TODO Prevent send message pressing enter on mobile and/or virtual keyboard + // TODO Prevent send message pressing enter on mobile and/or virtual keyboard if (e.keyCode === 13 && !e.shiftKey) { e.preventDefault(); - let event = new Event('submit', { + const event = new Event('submit', { bubbles: true, cancelable: true, }); - this.refs.form.dispatchEvent(event); + this.form.dispatchEvent(event); } } handleMessageChange(e) { - this.setState({ message: e.target.value }); + const { intl } = this.props; + + const message = e.target.value; + let error = ''; + + const { minMessageLength, maxMessageLength } = this.props; + + if (message.length < minMessageLength) { + error = intl.formatMessage(messages.errorMinMessageLength, + { 0: minMessageLength - message.length }); + } + + if (message.length > maxMessageLength) { + error = intl.formatMessage(messages.errorMaxMessageLength, + { 0: message.length - maxMessageLength }); + } + + this.setState({ + message, + error, + }); } handleSubmit(e) { e.preventDefault(); - const { disabled } = this.props; + const { disabled, minMessageLength, maxMessageLength } = this.props; + let message = this.state.message.trim(); - if (disabled) { + if (disabled + || message.length === 0 + || message.length < minMessageLength + || message.length > maxMessageLength) { + this.setState({ hasErrors: true }); return false; } - let message = this.state.message.trim(); - // Sanitize. See: http://shebang.brandonmintern.com/foolproof-html-escaping-in-javascript/ - let div = document.createElement('div'); + const div = document.createElement('div'); div.appendChild(document.createTextNode(message)); message = div.innerHTML; - if (message) { - this.props.handleSendMessage(message); - } - - this.setState({ message: '' }); + return this.props.handleSendMessage(message) + .then(() => this.setState({ + message: '', + hasErrors: false, + })); } render() { - const { intl, chatTitle, chatName, disabled } = this.props; + const { intl, chatTitle, chatName, disabled, + minMessageLength, maxMessageLength } = this.props; + + const { hasErrors, error } = this.state; return ( <form - ref="form" + ref={(ref) => { this.form = ref; }} className={cx(this.props.className, styles.form)} - onSubmit={this.handleSubmit}> - { - // <MessageFormActions - // onClick={() => alert('Not supported yet...')} - // className={styles.actions} - // disabled={disabled} - // label={'More actions'} - // /> - } - <TextareaAutosize - className={styles.input} - id="message-input" - placeholder={intl.formatMessage(messages.inputPlaceholder, { 0: chatName })} - aria-controls={this.props.chatAreaId} - aria-label={intl.formatMessage(messages.inputLabel, { 0: chatTitle })} - autoCorrect="off" - autoComplete="off" - spellCheck="true" - disabled={disabled} - value={this.state.message} - onChange={this.handleMessageChange} - onKeyDown={this.handleMessageKeyDown} - /> - <Button - className={styles.sendButton} - aria-label={intl.formatMessage(messages.submitLabel)} - type="submit" - disabled={disabled} - label={intl.formatMessage(messages.submitLabel)} - hideLabel={true} - icon={'send'} - onClick={this.handleMessageKeyDown} - /> + onSubmit={this.handleSubmit} + > + <div className={styles.wrapper}> + <TextareaAutosize + className={styles.input} + id="message-input" + placeholder={intl.formatMessage(messages.inputPlaceholder, { 0: chatName })} + aria-controls={this.props.chatAreaId} + aria-label={intl.formatMessage(messages.inputLabel, { 0: chatTitle })} + aria-invalid={hasErrors ? 'true' : 'false'} + aria-describedby={hasErrors ? 'message-input-error' : null} + autoCorrect="off" + autoComplete="off" + spellCheck="true" + disabled={disabled} + value={this.state.message} + onChange={this.handleMessageChange} + onKeyDown={this.handleMessageKeyDown} + /> + <Button + className={styles.sendButton} + aria-label={intl.formatMessage(messages.submitLabel)} + type="submit" + disabled={disabled} + label={intl.formatMessage(messages.submitLabel)} + hideLabel + icon="send" + onClick={() => this.hangleMessageKeyDown} + /> + </div> + <div className={styles.info}> + { hasErrors ? <span id="message-input-error">{error}</span> : null } + </div> </form> ); } diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/message-form-actions/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-form/message-form-actions/component.jsx index 7ec85c71ac0637f1ce72058d9a54e5d1c1bd2cf2..ff0639d4f668bff250d7591243e59ec5f4fb8910 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/message-form/message-form-actions/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/message-form-actions/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import styles from './styles'; import Icon from '../../../icon/component'; @@ -24,7 +25,7 @@ export default class MessageFormActions extends BaseButton { </BaseButton> ); } -}; +} MessageFormActions.propTypes = propTypes; MessageFormActions.defaultProps = defaultProps; diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss index a75cdfd355095041e84ca7a8db4d728e932576ba..9fbc08f17b8aa5709df66a27c79dcf90e1027536 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss @@ -4,9 +4,14 @@ flex-grow: 0; flex-shrink: 0; align-self: flex-end; + width: 100%; + position: relative; + margin-bottom: -$sm-padding-x; +} + +.wrapper { display: flex; flex-direction: row; - width: 100%; } .actions { @@ -72,3 +77,14 @@ color: $color-gray-light; } } + +.info { + font-size: $font-size-base * .75; + color: $color-gray-light; + text-align: right; + padding: $border-size 0; + + &:before { + content: "\00a0"; // non-breaking space + } +} diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-list/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-list/component.jsx index 39db23b663c6731ef99b57c162f2c662ea1a9a10..63360a2b59d72989e786fa59fb13663ea1790031 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/message-list/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/message-list/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import _ from 'lodash'; import styles from './styles'; @@ -34,7 +35,7 @@ class MessageList extends Component { } scrollTo(position = null) { - const { scrollArea } = this.refs; + const { scrollArea } = this; if (position === null) { position = scrollArea.scrollHeight - scrollArea.clientHeight; @@ -45,7 +46,7 @@ class MessageList extends Component { handleScrollUpdate(position, target) { if (position !== null && position + target.offsetHeight === target.scrollHeight) { - position = null; //update with null so it keeps auto scrolling + position = null; // update with null so it keeps auto scrolling } this.props.handleScrollUpdate(position); @@ -56,7 +57,7 @@ class MessageList extends Component { if (!this.ticking) { window.requestAnimationFrame(() => { - let position = this.lastKnowScrollPosition; + const position = this.lastKnowScrollPosition; this.handleScrollUpdate(position, e.target); this.ticking = false; }); @@ -67,7 +68,7 @@ class MessageList extends Component { componentWillReceiveProps(nextProps) { if (this.props.chatId !== nextProps.chatId) { - const { scrollArea } = this.refs; + const { scrollArea } = this; this.handleScrollUpdate(scrollArea.scrollTop, scrollArea); } } @@ -78,12 +79,12 @@ class MessageList extends Component { return; } - const { scrollArea } = this.refs; + const { scrollArea } = this; - let position = scrollArea.scrollTop + scrollArea.offsetHeight; + const position = scrollArea.scrollTop + scrollArea.offsetHeight; - //Compare with <1 to account for the chance scrollArea.scrollTop is a float - //value in some browsers. + // Compare with <1 to account for the chance scrollArea.scrollTop is a float + // value in some browsers. this.shouldScrollBottom = position === scrollArea.scrollHeight || (scrollArea.scrollHeight - position < 1) || nextProps.scrollPosition === null; @@ -100,14 +101,14 @@ class MessageList extends Component { } componentDidMount() { - const { scrollArea } = this.refs; + const { scrollArea } = this; this.scrollTo(this.props.scrollPosition); scrollArea.addEventListener('scroll', this.handleScrollChange, false); } componentWillUnmount() { - const { scrollArea } = this.refs; + const { scrollArea } = this; this.handleScrollUpdate(scrollArea.scrollTop, scrollArea); scrollArea.removeEventListener('scroll', this.handleScrollChange, false); @@ -143,7 +144,7 @@ class MessageList extends Component { <div role="log" tabIndex="0" - ref="scrollArea" + ref={(ref) => { this.scrollArea = ref; }} id={this.props.id} className={styles.messageList} aria-live="polite" @@ -151,7 +152,7 @@ class MessageList extends Component { aria-relevant="additions" aria-label={intl.formatMessage(intlMessages.emptyLogLabel)} > - {messages.map((message) => ( + {messages.map(message => ( <MessageListItem handleReadMessage={this.props.handleReadMessage} className={styles.messageListItem} diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/component.jsx index 9faaac2a078f6207c1fbb4744ebce09e06b21225..41ffba4af9c8300a14c61e18a3428f7096cf14ee 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { FormattedTime } from 'react-intl'; import cx from 'classnames'; import _ from 'lodash'; @@ -47,7 +48,7 @@ export default class MessageListItem extends Component { handleMessageInViewport() { window.requestAnimationFrame(() => { - const node = this.refs.item; + const node = this.item; this.setState({ preventRender: !isElementInViewport(node) }); }); } @@ -55,7 +56,7 @@ export default class MessageListItem extends Component { componentDidMount() { const scrollArea = document.getElementById(this.props.chatAreaId); eventsToBeBound.forEach( - e => scrollArea.addEventListener(e, this.handleMessageInViewport, false) + e => scrollArea.addEventListener(e, this.handleMessageInViewport, false), ); this.handleMessageInViewport(); @@ -64,7 +65,7 @@ export default class MessageListItem extends Component { componentWillUnmount() { const scrollArea = document.getElementById(this.props.chatAreaId); eventsToBeBound.forEach( - e => scrollArea.removeEventListener(e, this.handleMessageInViewport, false) + e => scrollArea.removeEventListener(e, this.handleMessageInViewport, false), ); } @@ -101,8 +102,8 @@ export default class MessageListItem extends Component { } return ( - <div className={styles.item}> - <div className={styles.wrapper} ref="item"> + <div className={styles.item}> + <div className={styles.wrapper} ref={(ref) => { this.item = ref; }}> <div className={styles.avatar}> <UserAvatar user={user} /> </div> @@ -113,7 +114,7 @@ export default class MessageListItem extends Component { {user.isOnline ? null : <span className={styles.offline}>(offline)</span>} </div> <time className={styles.time} dateTime={dateTime}> - <FormattedTime value={dateTime}/> + <FormattedTime value={dateTime} /> </time> </div> <div className={styles.messages}> @@ -142,7 +143,7 @@ export default class MessageListItem extends Component { return ( <div className={cx(styles.item, styles.systemMessage)}> - <div className={styles.content} ref="item"> + <div className={styles.content} ref={(ref) => { this.item = ref; }}> <div className={styles.messages}> {messages.map((message, i) => ( <Message diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/message/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/message/component.jsx index f4a4c0485ecc58f67f54af3eca336437446128d9..d05b068038eac47111f695de095b63bcbb9a1e42 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/message/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/message-list/message-list-item/message/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import _ from 'lodash'; const propTypes = { @@ -39,13 +40,13 @@ export default class MessageListItem extends Component { handleMessageInViewport(e) { if (!this.ticking) { window.requestAnimationFrame(() => { - const node = this.refs.text; + const node = this.text; const scrollArea = document.getElementById(this.props.chatAreaId); if (isElementInViewport(node)) { this.props.handleReadMessage(this.props.time); eventsToBeBound.forEach( - e => scrollArea.removeEventListener(e, this.handleMessageInViewport) + e => scrollArea.removeEventListener(e, this.handleMessageInViewport), ); } @@ -61,14 +62,14 @@ export default class MessageListItem extends Component { return; } - const node = this.refs.text; + const node = this.text; if (isElementInViewport(node)) { this.props.handleReadMessage(this.props.time); } else { const scrollArea = document.getElementById(this.props.chatAreaId); eventsToBeBound.forEach( - e => scrollArea.addEventListener(e, this.handleMessageInViewport, false) + e => scrollArea.addEventListener(e, this.handleMessageInViewport, false), ); } } @@ -80,7 +81,7 @@ export default class MessageListItem extends Component { const scrollArea = document.getElementById(this.props.chatAreaId); eventsToBeBound.forEach( - e => scrollArea.removeEventListener(e, this.handleMessageInViewport, false) + e => scrollArea.removeEventListener(e, this.handleMessageInViewport, false), ); } @@ -92,7 +93,7 @@ export default class MessageListItem extends Component { return ( <p - ref="text" + ref={(ref) => { this.text = ref; }} dangerouslySetInnerHTML={{ __html: text }} className={this.props.className} /> diff --git a/bigbluebutton-html5/imports/ui/components/chat/notification/container.jsx b/bigbluebutton-html5/imports/ui/components/chat/notification/container.jsx old mode 100644 new mode 100755 index 92db45757e898cf58bf2484ee67612bce4b4d823..ff4b7886ec7a9dacba2c4db5cb91a66f07ef2e48 --- a/bigbluebutton-html5/imports/ui/components/chat/notification/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/notification/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import _ from 'lodash'; diff --git a/bigbluebutton-html5/imports/ui/components/chat/service.js b/bigbluebutton-html5/imports/ui/components/chat/service.js index 4f1a6fe6b54eef79020000c71b1bc5b7b56af85b..55e3d0aa2814144fc41ce691accf9d0ff3cc9ff4 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/service.js +++ b/bigbluebutton-html5/imports/ui/components/chat/service.js @@ -27,7 +27,7 @@ const CLOSED_CHAT_LIST_KEY = 'closedChatList'; /* TODO: Same map is done in the user-list/service we should share this someway */ -const mapUser = (user) => ({ +const mapUser = user => ({ id: user.userid, name: user.name, emoji: { @@ -48,10 +48,10 @@ const mapUser = (user) => ({ const mapMessage = (messagePayload) => { const { message } = messagePayload; - let mappedMessage = { + const mappedMessage = { id: messagePayload._id, content: messagePayload.content, - time: message.from_time, //+ message.from_tz_offset, + time: message.from_time, // + message.from_tz_offset, sender: null, }; @@ -63,8 +63,8 @@ const mapMessage = (messagePayload) => { }; const reduceMessages = (previous, current, index, array) => { - let lastMessage = previous[previous.length - 1]; - let currentPayload = current.message; + const lastMessage = previous[previous.length - 1]; + const currentPayload = current.message; current.content = []; current.content.push({ @@ -77,7 +77,7 @@ const reduceMessages = (previous, current, index, array) => { return previous.concat(current); } - let lastPayload = lastMessage.message; + const lastPayload = lastMessage.message; // Check if the last message is from the same user and time discrepancy // between the two messages exceeds window and then group current message @@ -87,9 +87,8 @@ const reduceMessages = (previous, current, index, array) => { && (currentPayload.from_time - lastPayload.from_time) <= GROUPING_MESSAGES_WINDOW) { lastMessage.content.push(current.content.pop()); return previous; - } else { - return previous.concat(current); } + return previous.concat(current); }; const getUser = (userID, userName) => { @@ -102,11 +101,11 @@ const getUser = (userID, userName) => { }; const getPublicMessages = () => { - let publicMessages = Chats.find({ + const publicMessages = Chats.find({ 'message.chat_type': { $in: [PUBLIC_CHAT_TYPE, SYSTEM_CHAT_TYPE] }, }, { - sort: ['message.from_time'], - }) + sort: ['message.from_time'], + }) .fetch(); return publicMessages @@ -115,15 +114,15 @@ const getPublicMessages = () => { }; const getPrivateMessages = (userID) => { - let messages = Chats.find({ + const messages = Chats.find({ 'message.chat_type': PRIVATE_CHAT_TYPE, $or: [ { 'message.to_userid': userID }, { 'message.from_userid': userID }, ], }, { - sort: ['message.from_time'], - }).fetch(); + sort: ['message.from_time'], + }).fetch(); return messages.reduce(reduceMessages, []).map(mapMessage); }; @@ -172,8 +171,8 @@ const sendMessage = (receiverID, message) => { * The server only really needs the message, from_userid, to_userid and from_lang */ - let messagePayload = { - message: message, + const messagePayload = { + message, chat_type: isPublic ? PUBLIC_CHAT_TYPE : PRIVATE_CHAT_TYPE, from_userid: sender.id, from_username: sender.name, @@ -185,27 +184,25 @@ const sendMessage = (receiverID, message) => { from_color: 0, }; - let currentClosedChats = Storage.getItem(CLOSED_CHAT_LIST_KEY); + const currentClosedChats = Storage.getItem(CLOSED_CHAT_LIST_KEY); // Remove the chat that user send messages from the session. if (_.indexOf(currentClosedChats, receiver.id) > -1) { Storage.setItem(CLOSED_CHAT_LIST_KEY, _.without(currentClosedChats, receiver.id)); } - makeCall('sendChat', messagePayload); - - return messagePayload; + return makeCall('sendChat', messagePayload); }; const getScrollPosition = (receiverID) => { - let scroll = ScrollCollection.findOne({ receiver: receiverID }) || { position: null }; + const scroll = ScrollCollection.findOne({ receiver: receiverID }) || { position: null }; return scroll.position; }; const updateScrollPosition = (receiverID, position) => ScrollCollection.upsert( { receiver: receiverID }, - { $set: { position: position } }, + { $set: { position } }, ); const updateUnreadMessage = (receiverID, timestamp) => { @@ -215,8 +212,7 @@ const updateUnreadMessage = (receiverID, timestamp) => { }; const closePrivateChat = (chatID) => { - - let currentClosedChats = Storage.getItem(CLOSED_CHAT_LIST_KEY) || []; + const currentClosedChats = Storage.getItem(CLOSED_CHAT_LIST_KEY) || []; if (_.indexOf(currentClosedChats, chatID) < 0) { currentClosedChats.push(chatID); diff --git a/bigbluebutton-html5/imports/ui/components/checkbox/component.jsx b/bigbluebutton-html5/imports/ui/components/checkbox/component.jsx index a801b18e19c1a52e486bd1cf3fccacd8da431043..bec0a5666257a6f705ef74a19e5341866e953a50 100755 --- a/bigbluebutton-html5/imports/ui/components/checkbox/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/checkbox/component.jsx @@ -1,5 +1,5 @@ -import React, { Component, PropTypes } from 'react'; - +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import Icon from '../icon/component'; import styles from './styles'; import cx from 'classnames'; @@ -17,22 +17,22 @@ export default class Checkbox extends Component { } render() { - - const { ariaLabel, ariaLabelledBy, ariaDesc, ariaDescribedBy, } = this.props; + const { ariaLabel, ariaLabelledBy, ariaDesc, ariaDescribedBy } = this.props; return ( <div className={styles.container}> <input - type='checkbox' + type="checkbox" onChange={this.handleChange} checked={this.props.checked} className={styles.input} aria-labelledby={ariaLabelledBy} - aria-describedby={ariaDescribedBy}/> + aria-describedby={ariaDescribedBy} + /> <div onClick={this.handleChange}> { this.props.checked ? - <Icon iconName='check' className={cx(styles.icon, styles.checked)}/> : - <Icon iconName='circle' className={styles.icon}/> + <Icon iconName="check" className={cx(styles.icon, styles.checked)} /> : + <Icon iconName="circle" className={styles.icon} /> } </div> <div id={ariaLabelledBy} hidden>{ariaLabel}</div> diff --git a/bigbluebutton-html5/imports/ui/components/closed-captions/component.jsx b/bigbluebutton-html5/imports/ui/components/closed-captions/component.jsx index facfc98b79f90ab11966332bcf8e0829e7f21c99..a4581c6c6f03335bd8c2160e3e15073be5fa74fb 100755 --- a/bigbluebutton-html5/imports/ui/components/closed-captions/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/closed-captions/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import styles from './styles.scss'; import { findDOMNode } from 'react-dom'; @@ -10,7 +11,7 @@ export default class ClosedCaptions extends React.Component { } renderCaptions(caption) { - let text = caption.captions; + const text = caption.captions; const captionStyles = { whiteSpace: 'pre-wrap', wordWrap: 'break-word', @@ -29,9 +30,8 @@ export default class ClosedCaptions extends React.Component { } componentWillUpdate() { - const { ccScrollArea } = this.refs; - const node = findDOMNode(ccScrollArea); + const node = findDOMNode(this.ccScrollArea); // number 4 is for the border // offset height includes the border, but scrollheight doesn't @@ -40,8 +40,7 @@ export default class ClosedCaptions extends React.Component { componentDidUpdate() { if (this.shouldScrollBottom) { - const { ccScrollArea } = this.refs; - const node = findDOMNode(ccScrollArea); + const node = findDOMNode(this.ccScrollArea); node.scrollTop = node.scrollHeight; } } @@ -56,13 +55,14 @@ export default class ClosedCaptions extends React.Component { return ( <div disabled className={styles.ccbox}> <div className={styles.title}> - <p> {locale ? locale : 'Locale is not selected'} </p> + <p> {locale || 'Locale is not selected'} </p> </div> <div - ref="ccScrollArea" + ref={(ref) => { this.ccScrollArea = ref; }} className={styles.frame} - style={{ background: backgroundColor }}> - {captions[locale] ? captions[locale].captions.map((caption) => ( + style={{ background: backgroundColor }} + > + {captions[locale] ? captions[locale].captions.map(caption => ( this.renderCaptions(caption) )) : null } </div> diff --git a/bigbluebutton-html5/imports/ui/components/closed-captions/container.jsx b/bigbluebutton-html5/imports/ui/components/closed-captions/container.jsx old mode 100644 new mode 100755 index 1ba92f1d8a89054160956b8e8b73ac971a75f764..a7ba7bf422e0b576938badc91f379c008438a05c --- a/bigbluebutton-html5/imports/ui/components/closed-captions/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/closed-captions/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import ClosedCaptionsService from './service.js'; import ClosedCaptions from './component'; @@ -17,6 +18,4 @@ class ClosedCaptionsContainer extends Component { } } -export default createContainer(function () { - return ClosedCaptionsService.getCCData(); -}, ClosedCaptionsContainer); +export default createContainer(() => ClosedCaptionsService.getCCData(), ClosedCaptionsContainer); diff --git a/bigbluebutton-html5/imports/ui/components/closed-captions/service.js b/bigbluebutton-html5/imports/ui/components/closed-captions/service.js index b4fc7e3dcc7a68c78c8660e481302e6e02182cf8..7a4c9fe37ab7b3f7a799d10b601eb8bb3fa3e088 100755 --- a/bigbluebutton-html5/imports/ui/components/closed-captions/service.js +++ b/bigbluebutton-html5/imports/ui/components/closed-captions/service.js @@ -2,29 +2,27 @@ import Captions from '/imports/api/captions'; import Auth from '/imports/ui/services/auth'; import Settings from '/imports/ui/services/settings'; -let getCCData = () => { +const getCCData = () => { const meetingID = Auth.meetingID; const ccSettings = Settings.cc; - let CCEnabled = ccSettings.enabled; + const CCEnabled = ccSettings.enabled; - //associative array that keeps locales with arrays of string objects related to those locales - let captions = []; + // associative array that keeps locales with arrays of string objects related to those locales + const captions = []; - //list of unique locales in the Captions Collection + // list of unique locales in the Captions Collection if (CCEnabled) { - let locales = _.uniq(Captions.find({}, { + const locales = _.uniq(Captions.find({}, { sort: { locale: 1 }, fields: { locale: true }, - }).fetch().map(function (obj) { - return obj.locale; - }), true); + }).fetch().map(obj => obj.locale), true); locales.forEach((locale) => { - let captionObjects = Captions.find({ + const captionObjects = Captions.find({ meetingId: meetingID, - locale: locale, + locale, }, { sort: { locale: 1, @@ -47,19 +45,19 @@ let getCCData = () => { }); } - //fetching settings for the captions - let selectedLocale = ccSettings.locale; - let ccFontFamily = ccSettings.fontFamily ? ccSettings.fontFamily : 'Arial'; - let ccFontSize = ccSettings.fontSize ? ccSettings.fontSize : 18; - let ccBackgroundColor = ccSettings.backgroundColor ? ccSettings.backgroundColor : '#f3f6f9'; - let ccFontColor = ccSettings.fontColor ? ccSettings.fontColor : '#000000'; + // fetching settings for the captions + const selectedLocale = ccSettings.locale; + const ccFontFamily = ccSettings.fontFamily ? ccSettings.fontFamily : 'Arial'; + const ccFontSize = ccSettings.fontSize ? ccSettings.fontSize : 18; + const ccBackgroundColor = ccSettings.backgroundColor ? ccSettings.backgroundColor : '#f3f6f9'; + const ccFontColor = ccSettings.fontColor ? ccSettings.fontColor : '#000000'; return { locale: selectedLocale, fontFamily: ccFontFamily, fontSize: ccFontSize, fontColor: ccFontColor, backgroundColor: ccBackgroundColor, - captions: captions, + captions, }; }; diff --git a/bigbluebutton-html5/imports/ui/components/closed-captions/styles.scss b/bigbluebutton-html5/imports/ui/components/closed-captions/styles.scss index 2aea8ed05882fdc4c9bb9fb4f0c557478b5aa2f4..0389830e35db3078a09eb3a66c36fda934f17ab8 100755 --- a/bigbluebutton-html5/imports/ui/components/closed-captions/styles.scss +++ b/bigbluebutton-html5/imports/ui/components/closed-captions/styles.scss @@ -7,6 +7,7 @@ height:100%; overflow-y: auto; overflow-x: hidden; + position:absolute; } .frame { @@ -14,7 +15,6 @@ height: calc(100% - 80px); margin: 20px; overflow: auto; - //if you change the thickness of the border //you should also change a corresponding value in the componentWillUpdate //otherwise auto-scrolling for closed-captions will break diff --git a/bigbluebutton-html5/imports/ui/components/deskshare/component.jsx b/bigbluebutton-html5/imports/ui/components/deskshare/component.jsx index a297efc74f1d77dd5f1b0b6af7bfa100792aff32..9b612e523bad58ee26268817e2a219fe8709d34d 100755 --- a/bigbluebutton-html5/imports/ui/components/deskshare/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/deskshare/component.jsx @@ -7,7 +7,7 @@ export default class DeskshareComponent extends React.Component { render() { return ( - <video id="deskshareVideo" style={{ height: '100%', width: '100%', }} /> + <video id="deskshareVideo" style={{ height: '100%', width: '100%' }} /> ); } -}; +} diff --git a/bigbluebutton-html5/imports/ui/components/deskshare/container.jsx b/bigbluebutton-html5/imports/ui/components/deskshare/container.jsx index 79bd8bad9a1763a781f36d198c6957f06930b904..636da36c6eb0f029da42ae732b29d9f3a57dccb2 100755 --- a/bigbluebutton-html5/imports/ui/components/deskshare/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/deskshare/container.jsx @@ -1,6 +1,6 @@ import React from 'react'; -import {isVideoBroadcasting, presenterDeskshareHasEnded, - presenterDeskshareHasStarted} from './service'; +import { isVideoBroadcasting, presenterDeskshareHasEnded, + presenterDeskshareHasStarted } from './service'; import { createContainer } from 'meteor/react-meteor-data'; import DeskshareComponent from './component'; diff --git a/bigbluebutton-html5/imports/ui/components/deskshare/service.js b/bigbluebutton-html5/imports/ui/components/deskshare/service.js index fa800ff953813afff85c4c7da0ede421151f9964..893288f021c522baf15652bd65e51d3a7fa1af10 100755 --- a/bigbluebutton-html5/imports/ui/components/deskshare/service.js +++ b/bigbluebutton-html5/imports/ui/components/deskshare/service.js @@ -21,14 +21,14 @@ function presenterDeskshareHasEnded() { // references a functiion in the global namespace inside verto_extension.js // that we load dynamically vertoBridge.vertoExitVideo(); -}; +} // if remote deskshare has been started connect and display the video stream function presenterDeskshareHasStarted() { // references a functiion in the global namespace inside verto_extension.js // that we load dynamically vertoBridge.vertoWatchVideo(); -}; +} export { isVideoBroadcasting, presenterDeskshareHasEnded, presenterDeskshareHasStarted, diff --git a/bigbluebutton-html5/imports/ui/components/dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/dropdown/component.jsx index 75bfa1792ce246140999b5986778d8a58e82e813..900b4820bdd16b8da883ddc532d85663276ef3a9 100755 --- a/bigbluebutton-html5/imports/ui/components/dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/dropdown/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { findDOMNode } from 'react-dom'; import styles from './styles'; import DropdownTrigger from './trigger/component'; @@ -7,7 +8,7 @@ import Button from '/imports/ui/components/button/component'; import cx from 'classnames'; import { defineMessages, injectIntl } from 'react-intl'; -const FOCUSABLE_CHILDREN = `[tabindex]:not([tabindex="-1"]), a, input, button`; +const FOCUSABLE_CHILDREN = '[tabindex]:not([tabindex="-1"]), a, input, button'; const intlMessages = defineMessages({ close: { @@ -25,8 +26,8 @@ const propTypes = { if (!children || children.length < 2) { return new Error( - 'Invalid prop `' + propName + '` supplied to' + - ' `' + componentName + '`. Validation failed.' + `Invalid prop \`${propName}\` supplied to` + + ` \`${componentName}\`. Validation failed.`, ); } @@ -35,15 +36,15 @@ const propTypes = { if (!trigger) { return new Error( - 'Invalid prop `' + propName + '` supplied to' + - ' `' + componentName + '`. Missing `DropdownTrigger`. Validation failed.' + `Invalid prop \`${propName}\` supplied to` + + ` \`${componentName}\`. Missing \`DropdownTrigger\`. Validation failed.`, ); } if (!content) { return new Error( - 'Invalid prop `' + propName + '` supplied to' + - ' `' + componentName + '`. Missing `DropdownContent`. Validation failed.' + `Invalid prop \`${propName}\` supplied to` + + ` \`${componentName}\`. Missing \`DropdownContent\`. Validation failed.`, ); } }, @@ -57,7 +58,7 @@ const defaultProps = { class Dropdown extends Component { constructor(props) { super(props); - this.state = { isOpen: false, }; + this.state = { isOpen: false }; this.handleShow = this.handleShow.bind(this); this.handleHide = this.handleHide.bind(this); this.handleStateCallback = this.handleStateCallback.bind(this); @@ -90,7 +91,6 @@ class Dropdown extends Component { } handleHide() { - const { removeEventListener } = window; removeEventListener('click', this.handleWindowClick, false); @@ -99,7 +99,7 @@ class Dropdown extends Component { this.setState({ isOpen: false }, this.handleStateCallback); if (autoFocus) { - const triggerElement = findDOMNode(this.refs.trigger); + const triggerElement = findDOMNode(this.trigger); triggerElement.focus(); } } @@ -134,14 +134,14 @@ class Dropdown extends Component { let content = children.find(x => x.type === DropdownContent); trigger = React.cloneElement(trigger, { - ref: 'trigger', + ref: (ref) => { this.trigger = ref; }, dropdownToggle: this.handleToggle, dropdownShow: this.handleShow, dropdownHide: this.handleHide, }); content = React.cloneElement(content, { - ref: 'content', + ref: (ref) => { this.content = ref; }, 'aria-expanded': this.state.isOpen, dropdownToggle: this.handleToggle, dropdownShow: this.handleShow, diff --git a/bigbluebutton-html5/imports/ui/components/dropdown/content/component.jsx b/bigbluebutton-html5/imports/ui/components/dropdown/content/component.jsx index 96e579e22111472611ef2dd1d229e64d2877c14c..70f2e4d6e8f8065384741047eb005599451ffb31 100755 --- a/bigbluebutton-html5/imports/ui/components/dropdown/content/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/dropdown/content/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes, Children, cloneElement } from 'react'; +import React, { Component, Children, cloneElement } from 'react'; +import PropTypes from 'prop-types'; import cx from 'classnames'; import styles from '../styles'; @@ -27,19 +28,20 @@ export default class DropdownContent extends Component { const { placement, className, children, style } = this.props; const { dropdownToggle, dropdownShow, dropdownHide } = this.props; - let placementName = placement.split(' ').join('-'); + const placementName = placement.split(' ').join('-'); const boundChildren = Children.map(children, child => cloneElement(child, { - dropdownToggle: dropdownToggle, - dropdownShow: dropdownShow, - dropdownHide: dropdownHide, + dropdownToggle, + dropdownShow, + dropdownHide, })); return ( <div style={style} aria-expanded={this.props['aria-expanded']} - className={cx(styles.content, styles[placementName], className)}> + className={cx(styles.content, styles[placementName], className)} + > <div className={styles.scrollable}> {boundChildren} </div> diff --git a/bigbluebutton-html5/imports/ui/components/dropdown/list/item/component.jsx b/bigbluebutton-html5/imports/ui/components/dropdown/list/item/component.jsx index bafc6884e326999e0ae4145f51d7d3f90e64533c..e2218bf463007de183a372e8d51ccdad214fca1d 100755 --- a/bigbluebutton-html5/imports/ui/components/dropdown/list/item/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/dropdown/list/item/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import styles from '../styles'; import _ from 'lodash'; import cx from 'classnames'; @@ -21,11 +22,11 @@ export default class DropdownListItem extends Component { } renderDefault() { - let children = []; - const { icon, label, } = this.props; + const children = []; + const { icon, label } = this.props; return [ - (icon ? <Icon iconName={icon} key="icon" className={styles.itemIcon}/> : null), + (icon ? <Icon iconName={icon} key="icon" className={styles.itemIcon} /> : null), (<span className={styles.itemLabel} key="label">{label}</span>), ]; } @@ -44,10 +45,10 @@ export default class DropdownListItem extends Component { aria-describedby={this.descID} className={cx(styles.item, className)} style={style} - role="menuitem"> + role="menuitem" + > { - children ? children - : this.renderDefault() + children || this.renderDefault() } { label ? @@ -60,7 +61,7 @@ export default class DropdownListItem extends Component { : null } </li> - ); + ); } } diff --git a/bigbluebutton-html5/imports/ui/components/dropdown/list/separator/component.jsx b/bigbluebutton-html5/imports/ui/components/dropdown/list/separator/component.jsx index d5c7a66a9257fb836b78da68fd5cb02557a3a8bc..cc8a9b1f677b788899e580a52c0961fdce416bf9 100755 --- a/bigbluebutton-html5/imports/ui/components/dropdown/list/separator/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/dropdown/list/separator/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import styles from '../styles'; import cx from 'classnames'; diff --git a/bigbluebutton-html5/imports/ui/components/dropdown/list/title/component.jsx b/bigbluebutton-html5/imports/ui/components/dropdown/list/title/component.jsx old mode 100644 new mode 100755 index 96500c1df1f8b3b6cbf6b8155a56301c449a589b..cf1b50aa5035134c6be8c6f07ff01020af34f20c --- a/bigbluebutton-html5/imports/ui/components/dropdown/list/title/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/dropdown/list/title/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import styles from '../styles'; const propTypes = { @@ -13,7 +14,7 @@ export default class DropdownListTitle extends Component { return ( <div> <li className={styles.title} aria-describedby="labelContext">{this.props.children}</li> - <div id="labelContext" aria-label={description}></div> + <div id="labelContext" aria-label={description} /> </div> ); } diff --git a/bigbluebutton-html5/imports/ui/components/dropdown/trigger/component.jsx b/bigbluebutton-html5/imports/ui/components/dropdown/trigger/component.jsx index 3ae9d01bded7f53541f827e25c9dcde17250be48..31edf45c7456596722ff8142fb33072061c74fa0 100755 --- a/bigbluebutton-html5/imports/ui/components/dropdown/trigger/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/dropdown/trigger/component.jsx @@ -1,11 +1,12 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { findDOMNode } from 'react-dom'; import cx from 'classnames'; import KEY_CODES from '/imports/utils/keyCodes'; const propTypes = { - children: React.PropTypes.element.isRequired, + children: PropTypes.element.isRequired, }; export default class DropdownTrigger extends Component { @@ -21,7 +22,7 @@ export default class DropdownTrigger extends Component { } handleKeyDown(event) { - const { dropdownShow, dropdownHide, } = this.props; + const { dropdownShow, dropdownHide } = this.props; if ([KEY_CODES.SPACE, KEY_CODES.ENTER].includes(event.which)) { event.preventDefault(); @@ -37,7 +38,6 @@ export default class DropdownTrigger extends Component { if (KEY_CODES.ESCAPE === event.which) { dropdownHide(); } - } render() { @@ -50,6 +50,7 @@ export default class DropdownTrigger extends Component { 'aria-haspopup': true, tabIndex: tabIndex, style: style, + className: cx(children.props.className, className), }); diff --git a/bigbluebutton-html5/imports/ui/components/error-screen/component.jsx b/bigbluebutton-html5/imports/ui/components/error-screen/component.jsx index 29cdd9e9016e5f285d8ec99acc61987d5647a8a9..7efe777b56346e1d02f3172b1e57b84771427398 100755 --- a/bigbluebutton-html5/imports/ui/components/error-screen/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/error-screen/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import Button from '/imports/ui/components/button/component'; @@ -67,7 +68,7 @@ class ErrorScreen extends Component { size={'sm'} onClick={this.onClick} label={intl.formatMessage(intlMessages.leave)} - /> + /> </div> </div> ); diff --git a/bigbluebutton-html5/imports/ui/components/icon/component.jsx b/bigbluebutton-html5/imports/ui/components/icon/component.jsx index dcff1b1ba41e923d51f64222c16bab5a9f896e39..b44a80f566cf2c89873cf086a0fe83ae2072a83c 100755 --- a/bigbluebutton-html5/imports/ui/components/icon/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/icon/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import cx from 'classnames'; const propTypes = { @@ -16,8 +17,8 @@ export default class Icon extends Component { return ( <i className={cx(className, [prependIconName, iconName].join(''))} - {...otherProps}> - </i> + {...otherProps} + /> ); } } diff --git a/bigbluebutton-html5/imports/ui/components/loading-screen/component.jsx b/bigbluebutton-html5/imports/ui/components/loading-screen/component.jsx index 1495106fba9ef24ae4d77a15dcc1fdd9eb953da3..a9045fc394ff25c935720fbf3df633bbf10656cd 100644 --- a/bigbluebutton-html5/imports/ui/components/loading-screen/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/loading-screen/component.jsx @@ -6,9 +6,9 @@ class LoadingScreen extends Component { return ( <div className={styles.background}> <div className={styles.spinner}> - <div className={styles.bounce1}></div> - <div className={styles.bounce2}></div> - <div className={styles.bounce3}></div> + <div className={styles.bounce1} /> + <div className={styles.bounce2} /> + <div className={styles.bounce3} /> </div> </div> ); diff --git a/bigbluebutton-html5/imports/ui/components/logout-confirmation/component.jsx b/bigbluebutton-html5/imports/ui/components/logout-confirmation/component.jsx index fb4b7b8f07ef39f1f2e4461714ff7414a5f4b332..daabff7f038bce6e6c87b51ed5df96407f2fd15d 100755 --- a/bigbluebutton-html5/imports/ui/components/logout-confirmation/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/logout-confirmation/component.jsx @@ -46,11 +46,12 @@ class LeaveConfirmation extends Component { callback: () => null, label: intl.formatMessage(intlMessages.dismissLabel), description: intl.formatMessage(intlMessages.dismissDesc), - }}> + }} + > {intl.formatMessage(intlMessages.message)} </Modal> ); } -}; +} export default withRouter(injectIntl(LeaveConfirmation)); diff --git a/bigbluebutton-html5/imports/ui/components/media/component.jsx b/bigbluebutton-html5/imports/ui/components/media/component.jsx index 77f5cbb6a6600a9cd67625a0885048ecaad271df..b0648d838d055733ffaa3c8c8bfab000f5b7dd49 100755 --- a/bigbluebutton-html5/imports/ui/components/media/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/media/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import styles from './styles.scss'; const propTypes = { diff --git a/bigbluebutton-html5/imports/ui/components/media/container.jsx b/bigbluebutton-html5/imports/ui/components/media/container.jsx index 117c20a0ba27c3431cedde3be3739acddc50df5c..484cd0eec31759536d23c4327ced3bc75e37a16a 100755 --- a/bigbluebutton-html5/imports/ui/components/media/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/media/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import Media from './component'; import MediaService from './service'; @@ -9,8 +10,8 @@ import DeskshareContainer from '../deskshare/container'; import DefaultContent from '../presentation/default-content/component'; const defaultProps = { - overlay: null, //<VideoDockContainer/>, - content: <PresentationAreaContainer/>, + overlay: null, // <VideoDockContainer/>, + content: <PresentationAreaContainer />, defaultContent: <DefaultContent />, }; @@ -20,7 +21,7 @@ class MediaContainer extends Component { const { overlay, content, defaultContent } = this.props; this.state = { - overlay: overlay, + overlay, content: this.props.current_presentation ? content : defaultContent, }; @@ -54,7 +55,7 @@ class MediaContainer extends Component { MediaContainer.defaultProps = defaultProps; export default createContainer(() => { - let data = {}; + const data = {}; data.currentPresentation = MediaService.getPresentationInfo(); data.content = <DefaultContent />; diff --git a/bigbluebutton-html5/imports/ui/components/media/service.js b/bigbluebutton-html5/imports/ui/components/media/service.js index 94a46c8bfbb823fddf85cc0a477a9bffe4a3dee4..9a3937a46a4767a430aa0bca0e768cb10fb96b80 100755 --- a/bigbluebutton-html5/imports/ui/components/media/service.js +++ b/bigbluebutton-html5/imports/ui/components/media/service.js @@ -2,14 +2,14 @@ import Presentations from '/imports/api/presentations'; import Slides from '/imports/api/slides'; import { isVideoBroadcasting } from '../deskshare/service'; -let getPresentationInfo = () => { +const getPresentationInfo = () => { let currentPresentation; currentPresentation = Presentations.findOne({ - 'presentation.current': true, - }); + 'presentation.current': true, + }); return { - current_presentation: (currentPresentation != null ? true : false), + current_presentation: (currentPresentation != null), }; }; diff --git a/bigbluebutton-html5/imports/ui/components/modal/base/component.jsx b/bigbluebutton-html5/imports/ui/components/modal/base/component.jsx index ef8670d5a1c842af0e6245b5debd5ec4cbbebe02..f5e9ddf522ff20093123088791a0b6d0c95aeef8 100755 --- a/bigbluebutton-html5/imports/ui/components/modal/base/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/modal/base/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import ReactModal from 'react-modal'; import styles from './styles.scss'; @@ -25,12 +26,12 @@ export default class ModalBase extends Component { </ReactModal> ); } -}; +} ModalBase.propTypes = propTypes; ModalBase.defaultProps = defaultProps; -export const withModalState = (ComponentToWrap) => +export const withModalState = ComponentToWrap => class ModalStateWrapper extends Component { constructor(props) { super(props); @@ -52,11 +53,11 @@ export const withModalState = (ComponentToWrap) => } render() { - return <ComponentToWrap + return (<ComponentToWrap {...this.props} modalHide={this.hide} modalShow={this.show} modalisOpen={this.state.isOpen} - />; + />); } }; diff --git a/bigbluebutton-html5/imports/ui/components/modal/container.jsx b/bigbluebutton-html5/imports/ui/components/modal/container.jsx index c8617cf0ff5bf58e07c698c0959314a7baea299a..beeed571db1a054b88d974f0325551824e57273b 100644 --- a/bigbluebutton-html5/imports/ui/components/modal/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/modal/container.jsx @@ -4,5 +4,5 @@ import { getModal } from './service'; export default createContainer( () => ({ modalComponent: getModal() }), - ({ modalComponent }) => modalComponent + ({ modalComponent }) => modalComponent, ); diff --git a/bigbluebutton-html5/imports/ui/components/modal/fullscreen/component.jsx b/bigbluebutton-html5/imports/ui/components/modal/fullscreen/component.jsx index 0d0c0986cb196652ad881067bd25cb848bd73ee0..2a2f97379e948294fc46a064259a2ff0765e8670 100755 --- a/bigbluebutton-html5/imports/ui/components/modal/fullscreen/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/modal/fullscreen/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import ModalBase, { withModalState } from '../base/component'; import Button from '/imports/ui/components/button/component'; import styles from './styles.scss'; diff --git a/bigbluebutton-html5/imports/ui/components/modal/service.js b/bigbluebutton-html5/imports/ui/components/modal/service.js index 5d68f5c363bbfbaf3ae921c31bcf3b5621167d31..0f676666c10078f23173663a8cdaf3ae6ec60895 100644 --- a/bigbluebutton-html5/imports/ui/components/modal/service.js +++ b/bigbluebutton-html5/imports/ui/components/modal/service.js @@ -1,9 +1,9 @@ import { Tracker } from 'meteor/tracker'; import React, { Component } from 'react'; -let currentModal = { +const currentModal = { component: null, - tracker: new Tracker.Dependency, + tracker: new Tracker.Dependency(), }; const showModal = (component) => { @@ -18,7 +18,7 @@ export const getModal = () => { return currentModal.component; }; -export const withModalMounter = (ComponentToWrap) => +export const withModalMounter = ComponentToWrap => class ModalMounterWrapper extends Component { constructor(props) { super(props); @@ -33,9 +33,9 @@ export const withModalMounter = (ComponentToWrap) => } render() { - return <ComponentToWrap + return (<ComponentToWrap {...this.props} mountModal={this.mount} - />; + />); } }; diff --git a/bigbluebutton-html5/imports/ui/components/modal/simple/component.jsx b/bigbluebutton-html5/imports/ui/components/modal/simple/component.jsx old mode 100644 new mode 100755 index 7a9f887d5fbfd2536527b09ee99d58ed12a670c8..d14e339a8554b8601053bf180a481890633fabff --- a/bigbluebutton-html5/imports/ui/components/modal/simple/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/modal/simple/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import ModalBase, { withModalState } from '../base/component'; import Button from '/imports/ui/components/button/component'; import styles from './styles.scss'; diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx index 44cfdd9d07efdd39c6d322cfa95926e879f00c17..62a1707d94c5a4c3606882c5d5a931fc8e52ed89 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import _ from 'lodash'; import cx from 'classnames'; import styles from './styles.scss'; @@ -40,8 +41,9 @@ const defaultProps = { const openBreakoutJoinConfirmation = (breakoutURL, breakoutName, mountModal) => mountModal(<BreakoutJoinConfirmation - breakoutURL={breakoutURL} - breakoutName={breakoutName}/>); + breakoutURL={breakoutURL} + breakoutName={breakoutName} + />); class NavBar extends Component { constructor(props) { @@ -76,7 +78,7 @@ class NavBar extends Component { render() { const { hasUnreadMessages, beingRecorded, isExpanded, intl } = this.props; - let toggleBtnClasses = {}; + const toggleBtnClasses = {}; toggleBtnClasses[styles.btn] = true; toggleBtnClasses[styles.btnWithNotificationDot] = hasUnreadMessages; @@ -85,9 +87,9 @@ class NavBar extends Component { <div className={styles.left}> <Button onClick={this.handleToggleUserList} - ghost={true} - circle={true} - hideLabel={true} + ghost + circle + hideLabel label={intl.formatMessage(intlMessages.toggleUserListLabel)} icon={'user'} className={cx(toggleBtnClasses)} @@ -96,11 +98,12 @@ class NavBar extends Component { /> <div id="newMessage" - aria-label={hasUnreadMessages ? intl.formatMessage(intlMessages.newMessages) : null}/> + aria-label={hasUnreadMessages ? intl.formatMessage(intlMessages.newMessages) : null} + /> </div> <div className={styles.center} role="banner"> {this.renderPresentationTitle()} - <RecordingIndicator beingRecorded={beingRecorded}/> + <RecordingIndicator beingRecorded={beingRecorded} /> </div> <div className={styles.right}> <SettingsDropdownContainer /> @@ -123,16 +126,15 @@ class NavBar extends Component { } return ( - <Dropdown - isOpen={this.state.isActionsOpen} - ref="dropdown"> + <Dropdown isOpen={this.state.isActionsOpen}> <DropdownTrigger> <h1 className={cx(styles.presentationTitle, styles.dropdownBreakout)}> - {presentationTitle} <Icon iconName='down-arrow'/> + {presentationTitle} <Icon iconName="down-arrow" /> </h1> </DropdownTrigger> <DropdownContent - placement="bottom"> + placement="bottom" + > <DropdownList> {breakouts.map(breakout => this.renderBreakoutItem(breakout))} </DropdownList> @@ -148,7 +150,7 @@ class NavBar extends Component { isBreakoutRoom, } = this.props; - breakouts.forEach(breakout => { + breakouts.forEach((breakout) => { if (!breakout.users) { return; } diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/container.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/container.jsx index c4de6ef3a1d25e894d9117014a250e91df5b1033..eedd273469b1a921adeee0ccecaa6afc28cebab5 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import { withRouter } from 'react-router'; import Meetings from '/imports/api/meetings'; @@ -27,13 +28,12 @@ class NavBarContainer extends Component { } export default withRouter(createContainer(({ location, router }) => { - let meetingTitle; let meetingRecorded; const meetingId = Auth.meetingID; const meetingObject = Meetings.findOne({ - meetingId: meetingId, + meetingId, }); if (meetingObject != null) { @@ -42,7 +42,7 @@ export default withRouter(createContainer(({ location, router }) => { } const checkUnreadMessages = () => { - let users = userListService.getUsers(); + const users = userListService.getUsers(); // 1.map every user id // 2.filter the user except the current user from the user array @@ -58,7 +58,7 @@ export default withRouter(createContainer(({ location, router }) => { const breakouts = Service.getBreakouts(); const currentUserId = Auth.userID; - let isExpanded = location.pathname.indexOf('/users') !== -1; + const isExpanded = location.pathname.indexOf('/users') !== -1; return { isExpanded, diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/recording-indicator/component.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/recording-indicator/component.jsx index c23cd33c1f18cecc861c4ec3ee6ffa8d57a58797..fe2b5949700b31e7cebf40dcb0f3412ea1628f92 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/recording-indicator/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/recording-indicator/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import styles from './styles.scss'; export default class RecordingIndicator extends Component { @@ -13,6 +14,6 @@ export default class RecordingIndicator extends Component { return null; } - return (<div className={styles.indicator}></div>); + return (<div className={styles.indicator} />); } -}; +} diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx index f4935b64d20deba22bb59ad32a8c2893112186ae..fd08eeee8749d80531172edd960bf5a4447af64d 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import cx from 'classnames'; import styles from '../styles'; @@ -110,9 +111,9 @@ class SettingsDropdown extends Component { <Button label={intl.formatMessage(intlMessages.optionsLabel)} icon="more" - ghost={true} - circle={true} - hideLabel={true} + ghost + circle + hideLabel className={cx(styles.btn, styles.btnSettings)} // FIXME: Without onClick react proptypes keep warning diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx index 8906f5679d94c8d647e75ecab1ddc9995488e669..ffb90d87578a04c3ac6e09d4bd488da8a1a58c23 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx @@ -49,7 +49,6 @@ export default class SettingsDropdownContainer extends Component { } render() { - const handleToggleFullscreen = Service.toggleFullScreen; const isFullScreen = this.state.isFullScreen; diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/service.js b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/service.js index 818a3ce62ec59b4c3c95f4cc310d84df596d4e3a..66eaee82f6d36935e397641b03751897a75d70e8 100644 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/service.js +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/service.js @@ -1,11 +1,10 @@ toggleFullScreen = () => { - let element = document.documentElement; + const element = document.documentElement; if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) { - if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozCancelFullScreen) { @@ -15,17 +14,15 @@ toggleFullScreen = () => { } // If the page is not currently fullscreen, make fullscreen - } else { - if (element.requestFullscreen) { - element.requestFullscreen(); - } else if (element.mozRequestFullScreen) { - element.mozRequestFullScreen(); - } else if (element.webkitRequestFullscreen) { - element.webkitRequestFullscreen(); - element.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); - } else if (element.msRequestFullscreen) { - element.msRequestFullscreen(); - } + } else if (element.requestFullscreen) { + element.requestFullscreen(); + } else if (element.mozRequestFullScreen) { + element.mozRequestFullScreen(); + } else if (element.webkitRequestFullscreen) { + element.webkitRequestFullscreen(); + element.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); + } else if (element.msRequestFullscreen) { + element.msRequestFullscreen(); } }; diff --git a/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx old mode 100644 new mode 100755 index 95133d8dec0223e0b64285de1ab6f09427367bc2..1886dd6ecc86b4496398ee2b221113bec22b3327 --- a/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/notifications-bar/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import styles from './styles.scss'; import cx from 'classnames'; @@ -25,7 +26,8 @@ export default class NotificationsBar extends Component { return ( <div role="alert" - className={cx(styles.notificationsBar, styles[color])}> + className={cx(styles.notificationsBar, styles[color])} + > {this.props.children} </div> ); diff --git a/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx b/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx index 6b38d1c875cf5094b1ef1749951e4555f544d147..3eb1a6c308b8c7cc81d87c7cd32e81ca3eabd2f8 100755 --- a/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/notifications-bar/container.jsx @@ -1,6 +1,7 @@ import { Meteor } from 'meteor/meteor'; import { createContainer } from 'meteor/react-meteor-data'; -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import _ from 'lodash'; import NavBarService from '../nav-bar/service'; @@ -73,8 +74,8 @@ class NotificationsBarContainer extends Component { let retrySeconds = 0; let timeRemaining = 0; -const retrySecondsDep = new Tracker.Dependency; -const timeRemainingDep = new Tracker.Dependency; +const retrySecondsDep = new Tracker.Dependency(); +const timeRemainingDep = new Tracker.Dependency(); let retryInterval = null; let timeRemainingInterval = null; @@ -122,7 +123,7 @@ const changeDocumentTitle = (sec) => { export default injectIntl(createContainer(({ intl }) => { const { status, connected, retryCount, retryTime } = Meteor.status(); - let data = {}; + const data = {}; if (!connected) { data.color = 'primary'; @@ -140,7 +141,7 @@ export default injectIntl(createContainer(({ intl }) => { retryInterval = startCounter(sec, setRetrySeconds, getRetrySeconds, retryInterval); data.message = intl.formatMessage( intlMessages.waitingMessage, - { 0: getRetrySeconds() } + { 0: getRetrySeconds() }, ); break; } @@ -170,7 +171,7 @@ export default injectIntl(createContainer(({ intl }) => { if (timeRemaining > 0) { data.message = intl.formatMessage( intlMessages.breakoutTimeRemaining, - { time: humanizeSeconds(timeRemaining) } + { time: humanizeSeconds(timeRemaining) }, ); } else { clearInterval(timeRemainingInterval); diff --git a/bigbluebutton-html5/imports/ui/components/polling/component.jsx b/bigbluebutton-html5/imports/ui/components/polling/component.jsx index ed342ed95e4a3e1af37917282fcf981fcececc8d..46f71aebfa1c8921f196cc1e5266ddc37b227452 100755 --- a/bigbluebutton-html5/imports/ui/components/polling/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/polling/component.jsx @@ -40,7 +40,7 @@ class PollingComponent extends React.Component { </p> </div> {poll.answers.map((pollAnswer, index) => - <div + (<div key={index} style={calculatedStyles} className={styles.pollButtonWrapper} @@ -66,11 +66,11 @@ class PollingComponent extends React.Component { > {`Select this option to vote for ${pollAnswer.key}`} </div> - </div> + </div>), )} </div> ); } -}; +} export default injectIntl(PollingComponent); diff --git a/bigbluebutton-html5/imports/ui/components/polling/container.jsx b/bigbluebutton-html5/imports/ui/components/polling/container.jsx index 922ba44a9851aa01678bac429e78500467497fef..a274295faf7ed3334352f19f29fb448c56483417 100755 --- a/bigbluebutton-html5/imports/ui/components/polling/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/polling/container.jsx @@ -7,9 +7,8 @@ class PollingContainer extends React.Component { render() { if (this.props.pollExists) { return <PollingComponent poll={this.props.poll} handleVote={this.props.handleVote} />; - } else { - return null; } + return null; } } diff --git a/bigbluebutton-html5/imports/ui/components/polling/service.js b/bigbluebutton-html5/imports/ui/components/polling/service.js index 1dc3678118f234e078334e4fcaa9efdf0a277b3b..6e084543a121ae81f0ce1d15a9e95c2aa404ffd0 100755 --- a/bigbluebutton-html5/imports/ui/components/polling/service.js +++ b/bigbluebutton-html5/imports/ui/components/polling/service.js @@ -1,8 +1,8 @@ import { makeCall } from '/imports/ui/services/api'; import Polls from '/imports/api/polls'; -let mapPolls = function () { - let poll = Polls.findOne({}); +const mapPolls = function () { + const poll = Polls.findOne({}); if (!poll) { return { pollExists: false }; } @@ -15,8 +15,8 @@ let mapPolls = function () { pollId: poll.poll.id, }, pollExists: true, - amIRequester: amIRequester, - handleVote: function (pollId, answerId) { + amIRequester, + handleVote(pollId, answerId) { makeCall('publishVote', pollId, answerId.id); }, }; diff --git a/bigbluebutton-html5/imports/ui/components/presentation/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/component.jsx index 3a0787884d7b1213f2b63ecd885823720da6d31d..6bd11413e159cd2e5afa5868346627698541929e 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/presentation/component.jsx @@ -1,10 +1,11 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import ShapeGroupContainer from '../whiteboard/shape-group/container.jsx'; import Cursor from './cursor/component.jsx'; import PresentationToolbarContainer from './presentation-toolbar/container.jsx'; import Slide from './slide/component.jsx'; import styles from './styles.scss'; -import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; +import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'; import PollingContainer from '/imports/ui/components/polling/container'; export default class PresentationArea extends React.Component { @@ -17,20 +18,20 @@ export default class PresentationArea extends React.Component { if (this.props.currentSlide) { slideObj = this.props.currentSlide.slide; - let x = -slideObj.x_offset * 2 * slideObj.width / 100; - let y = -slideObj.y_offset * 2 * slideObj.height / 100; - let viewBoxWidth = slideObj.width * slideObj.width_ratio / 100; - let viewBoxHeight = slideObj.height * slideObj.height_ratio / 100; + const x = -slideObj.x_offset * 2 * slideObj.width / 100; + const y = -slideObj.y_offset * 2 * slideObj.height / 100; + const viewBoxWidth = slideObj.width * slideObj.width_ratio / 100; + const viewBoxHeight = slideObj.height * slideObj.height_ratio / 100; return ( - <ReactCSSTransitionGroup - transitionName={ { + <CSSTransitionGroup + transitionName={{ enter: styles.enter, enterActive: styles.enterActive, appear: styles.appear, appearActive: styles.appearActive, - } } - transitionAppear={true} - transitionEnter={true} + }} + transitionAppear + transitionEnter transitionLeave={false} transitionAppearTimeout={400} transitionEnterTimeout={400} @@ -40,42 +41,41 @@ export default class PresentationArea extends React.Component { viewBox={`${x} ${y} ${viewBoxWidth} ${viewBoxHeight}`} version="1.1" - //it's supposed to be here in theory - //but now it's ignored by all the browsers and it's not supported by React - //xmlNS="http://www.w3.org/2000/svg" + // it's supposed to be here in theory + // but now it's ignored by all the browsers and it's not supported by React + // xmlNS="http://www.w3.org/2000/svg" className={styles.svgStyles} key={slideObj.id} > <defs> <clipPath id="viewBox"> - <rect x={x} y={y} width="100%" height="100%" fill="none"/> + <rect x={x} y={y} width="100%" height="100%" fill="none" /> </clipPath> </defs> <g clipPath="url(#viewBox)"> - <Slide id="slideComponent" currentSlide={this.props.currentSlide}/> + <Slide id="slideComponent" currentSlide={this.props.currentSlide} /> <ShapeGroupContainer - width = {slideObj.width} - height = {slideObj.height} - whiteboardId = {slideObj.id} + width={slideObj.width} + height={slideObj.height} + whiteboardId={slideObj.id} /> {this.props.cursor ? <Cursor - viewBoxWidth={viewBoxWidth} - viewBoxHeight={viewBoxHeight} - viewBoxX={x} - viewBoxY={y} - widthRatio={slideObj.width_ratio} - cursorX={this.props.cursor.x} - cursorY={this.props.cursor.y} + viewBoxWidth={viewBoxWidth} + viewBoxHeight={viewBoxHeight} + viewBoxX={x} + viewBoxY={y} + widthRatio={slideObj.width_ratio} + cursorX={this.props.cursor.x} + cursorY={this.props.cursor.y} /> : null } </g> </svg> - </ReactCSSTransitionGroup> + </CSSTransitionGroup> ); - } else { - return null; } + return null; } renderPresentationToolbar() { @@ -86,9 +86,8 @@ export default class PresentationArea extends React.Component { presentationId={this.props.currentSlide.presentationId} /> ); - } else { - return null; } + return null; } render() { diff --git a/bigbluebutton-html5/imports/ui/components/presentation/container.jsx b/bigbluebutton-html5/imports/ui/components/presentation/container.jsx index 6c1e04b2da6226c3b9e523d280f13df9ac1b1dd3..5b2d9375483fabc4c281945ba4de924aab706a5c 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/presentation/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import PresentationAreaService from './service'; import PresentationArea from './component'; diff --git a/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx index 6f843914778affa84afc398299386bb679b2671e..eb561711f96fd46f6993df5fdfba25dcb1d03d40 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx @@ -1,25 +1,26 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; const propTypes = { - //Width of the view box + // Width of the view box viewBoxWidth: PropTypes.number.isRequired, - //Height of the view box + // Height of the view box viewBoxHeight: PropTypes.number.isRequired, - //x Position of the view box + // x Position of the view box viewBoxX: PropTypes.number.isRequired, - //y Position of the view box + // y Position of the view box viewBoxY: PropTypes.number.isRequired, - //Slide to view box width ratio + // Slide to view box width ratio widthRatio: PropTypes.number.isRequired, - //Defines the cursor x position + // Defines the cursor x position cursorX: PropTypes.number.isRequired, - //Defines the cursor y position + // Defines the cursor y position cursorY: PropTypes.number.isRequired, /** @@ -58,12 +59,12 @@ export default class Cursor extends Component { radius, } = this.props; - //Adjust the x,y cursor position according to zoom - let cx = (cursorX * viewBoxWidth) + viewBoxX; - let cy = (cursorY * viewBoxHeight) + viewBoxY; + // Adjust the x,y cursor position according to zoom + const cx = (cursorX * viewBoxWidth) + viewBoxX; + const cy = (cursorY * viewBoxHeight) + viewBoxY; - //Adjust the radius of the cursor according to zoom - let finalRadius = radius * widthRatio / 100; + // Adjust the radius of the cursor according to zoom + const finalRadius = radius * widthRatio / 100; return ( <circle diff --git a/bigbluebutton-html5/imports/ui/components/presentation/default-content/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/default-content/component.jsx index 097b4a6e83683741d9a8fd5d5bd460c5e72a2b0d..0853098043e04234aad555024d7e18fe3f3f2b9e 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/default-content/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/presentation/default-content/component.jsx @@ -1,7 +1,8 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import styles from './styles.scss'; import { FormattedMessage, FormattedDate } from 'react-intl'; -import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; +import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'; import Button from '../../button/component'; export default class DefaultContent extends Component { @@ -11,13 +12,13 @@ export default class DefaultContent extends Component { render() { return ( - <ReactCSSTransitionGroup - transitionName={ { + <CSSTransitionGroup + transitionName={{ appear: styles.appear, appearActive: styles.appearActive, - } } - transitionAppear={true} - transitionEnter={true} + }} + transitionAppear + transitionEnter transitionLeave={false} transitionAppearTimeout={700} transitionEnterTimeout={0} @@ -34,11 +35,11 @@ export default class DefaultContent extends Component { defaultMessage="Welcome {0}! Your presentation will begin shortly..." values={{ 0: 'James Bond' }} /> - <br/> + <br /> Today is {' '}<FormattedDate value={Date.now()} /> - <br/> + <br /> Here is some button examples - <br/> + <br /> </p> <p> <Button @@ -81,25 +82,25 @@ export default class DefaultContent extends Component { <Button label={'Default'} onClick={this.handleClick} - ghost={true} + ghost /> <Button label={'Primary'} onClick={this.handleClick} color={'primary'} - ghost={true} + ghost /> <Button label={'Danger'} onClick={this.handleClick} color={'danger'} - ghost={true} + ghost /> <Button label={'Success'} onClick={this.handleClick} color={'success'} - ghost={true} + ghost /> </p> <p> @@ -113,22 +114,22 @@ export default class DefaultContent extends Component { onClick={this.handleClick} color={'primary'} icon={'add'} - ghost={true} + ghost /> <Button label={'Icon Right'} onClick={this.handleClick} color={'danger'} icon={'add'} - ghost={true} - iconRight={true} + ghost + iconRight /> <Button label={'Icon Right'} onClick={this.handleClick} color={'success'} icon={'add'} - iconRight={true} + iconRight /> </p> <p> @@ -137,8 +138,8 @@ export default class DefaultContent extends Component { onClick={this.handleClick} color={'primary'} icon={'unmute'} - ghost={true} - circle={true} + ghost + circle /> <Button label={'Large'} @@ -146,15 +147,15 @@ export default class DefaultContent extends Component { color={'danger'} icon={'unmute'} size={'lg'} - ghost={true} - circle={true} - /><br/> + ghost + circle + /><br /> <Button label={'Small'} onClick={this.handleClick} icon={'unmute'} size={'sm'} - circle={true} + circle /> <Button label={'Icon Right'} @@ -162,14 +163,14 @@ export default class DefaultContent extends Component { color={'success'} icon={'unmute'} size={'sm'} - iconRight={true} - circle={true} + iconRight + circle /> </p> </div> </div> </div> - </ReactCSSTransitionGroup> + </CSSTransitionGroup> ); } } diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx index 0b6efa7401b48e0bdec34d596a0db5531c3d60a2..c80a6f52194fc3f7c25976de7ccc97bddd40f088 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import styles from './styles.scss'; import Button from '/imports/ui/components/button/component'; import classNames from 'classnames'; @@ -37,7 +38,7 @@ class PresentationToolbar extends Component { renderSkipSlideOpts(numberOfSlides) { // Fill drop down menu with all the slides in presentation - let optionList = []; + const optionList = []; for (i = 1; i <= numberOfSlides; i++) { optionList.push( <option @@ -47,7 +48,7 @@ class PresentationToolbar extends Component { aria-controls="slideComponent" > Slide {i} - </option> + </option>, ); } @@ -66,22 +67,22 @@ class PresentationToolbar extends Component { <div id="presentationToolbarWrapper" className={styles.presentationToolbarWrapper}> {this.renderAriaLabelsDescs()} - {/*Previous Slide button*/} + {/* Previous Slide button*/} <Button role="button" aria-labelledby="prevSlideLabel" aria-describedby="prevSlideDescrip" aria-controls="skipSlide slideComponent" - disabled={currentSlideNum > 1 ? false : true} + disabled={!(currentSlideNum > 1)} color={'default'} icon={'left_arrow'} size={'md'} onClick={actions.previousSlideHandler} label={intl.formatMessage(intlMessages.previousSlideLabel)} - hideLabel={true} + hideLabel className={styles.prevSlide} /> - {/*Skip Slide drop down*/} + {/* Skip Slide drop down*/} <select id="skipSlide" role="listbox" @@ -96,22 +97,22 @@ class PresentationToolbar extends Component { > {this.renderSkipSlideOpts(numberOfSlides)} </select> - {/*Next Slide button*/} + {/* Next Slide button*/} <Button role="button" aria-labelledby="nextSlideLabel" aria-describedby="nextSlideDescrip" aria-controls="skipSlide slideComponent" - disabled={currentSlideNum < numberOfSlides ? false : true} + disabled={!(currentSlideNum < numberOfSlides)} color={'default'} icon={'right_arrow'} size={'md'} onClick={actions.nextSlideHandler} label={intl.formatMessage(intlMessages.nextSlideLabel)} - hideLabel={true} + hideLabel /> - {/*Fit to width button + {/* Fit to width button <Button role="button" aria-labelledby="fitWidthLabel" @@ -124,7 +125,7 @@ class PresentationToolbar extends Component { label={'Fit to Width'} hideLabel={true} />*/} - {/*Fit to screen button + {/* Fit to screen button <Button role="button" aria-labelledby="fitScreenLabel" @@ -137,7 +138,7 @@ class PresentationToolbar extends Component { label={'Fit to Screen'} hideLabel={true} />*/} - {/*Zoom slider + {/* Zoom slider <div className={classNames(styles.zoomWrapper, { [styles.zoomWrapperNoBorder]: true })} > @@ -161,13 +162,13 @@ class PresentationToolbar extends Component { <div className={styles.zoomMinMax}> 400% </div> </div>*/} </div> - ); + ); } renderAriaLabelsDescs() { return ( <div hidden > - {/*Previous Slide button aria*/} + {/* Previous Slide button aria*/} <div id="prevSlideLabel"> <FormattedMessage id="app.presentation.presentationToolbar.prevSlideLabel" @@ -182,7 +183,7 @@ class PresentationToolbar extends Component { defaultMessage="Change the presentation to the previous slide" /> </div> - {/*Next Slide button aria*/} + {/* Next Slide button aria*/} <div id="nextSlideLabel"> <FormattedMessage id="app.presentation.presentationToolbar.nextSlideLabel" @@ -197,7 +198,7 @@ class PresentationToolbar extends Component { defaultMessage="Change the presentation to the next slide" /> </div> - {/*Skip Slide drop down aria*/} + {/* Skip Slide drop down aria*/} <div id="skipSlideLabel"> <FormattedMessage id="app.presentation.presentationToolbar.skipSlideLabel" @@ -212,7 +213,7 @@ class PresentationToolbar extends Component { defaultMessage="Change the presentation to a specific slide" /> </div> - {/*Fit to width button aria*/} + {/* Fit to width button aria*/} <div id="fitWidthLabel"> <FormattedMessage id="app.presentation.presentationToolbar.fitWidthLabel" @@ -227,7 +228,7 @@ class PresentationToolbar extends Component { defaultMessage="Display the whole width of the slide" /> </div> - {/*Fit to screen button aria*/} + {/* Fit to screen button aria*/} <div id="fitScreenLabel"> <FormattedMessage id="app.presentation.presentationToolbar.fitScreenLabel" @@ -242,7 +243,7 @@ class PresentationToolbar extends Component { defaultMessage="Display the whole slide" /> </div> - {/*Zoom slider aria*/} + {/* Zoom slider aria*/} <div id="zoomLabel"> <FormattedMessage id="app.presentation.presentationToolbar.zoomLabel" diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/container.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/container.jsx index 306b1a4194520751b131ee5c948850f38329c94a..b48928f7f0817c5e61808b4cb8cc0b0de9664a71 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import PresentationToolbarService from './service'; @@ -41,9 +42,8 @@ class PresentationToolbarContainer extends React.Component { actions={actions} /> ); - } else { - return null; } + return null; } } @@ -63,7 +63,7 @@ export default createContainer((params) => { PresentationToolbarService.nextSlide(params.currentSlideNum, numberOfSlides), previousSlideHandler: () => PresentationToolbarService.previousSlide(params.currentSlideNum, numberOfSlides), - skipToSlideHandler: (event) => + skipToSlideHandler: event => PresentationToolbarService.skipToSlide(event), }, }; diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/service.js b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/service.js index 297c810a5b9a995f57495fb5858d686bc6b97f6e..75e2b3bf32a8421487bb8ad8da672a01acec5754 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/service.js +++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/service.js @@ -3,7 +3,7 @@ import Users from '/imports/api/users'; import Slides from '/imports/api/slides'; import { makeCall } from '/imports/ui/services/api/index.js'; -let getSlideData = (params) => { +const getSlideData = (params) => { const { currentSlideNum, presentationId } = params; // Get userId and meetingId @@ -12,8 +12,8 @@ let getSlideData = (params) => { // Find the user object of this specific meeting and userid const currentUser = Users.findOne({ - meetingId: meetingId, - userId: userId, + meetingId, + userId, }); let userIsPresenter; @@ -23,13 +23,13 @@ let getSlideData = (params) => { // Get total number of slides in this presentation const numberOfSlides = Slides.find({ - meetingId: meetingId, - presentationId: presentationId, + meetingId, + presentationId, }).fetch().length; return { - userIsPresenter: userIsPresenter, - numberOfSlides: numberOfSlides, + userIsPresenter, + numberOfSlides, }; }; diff --git a/bigbluebutton-html5/imports/ui/components/presentation/service.js b/bigbluebutton-html5/imports/ui/components/presentation/service.js index 48ddef1c12f2092ef30b97031b1d088d8796da77..dfb23e829894f2eb39d64adf66688bd772c1cab7 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/service.js +++ b/bigbluebutton-html5/imports/ui/components/presentation/service.js @@ -24,7 +24,7 @@ const getCurrentSlide = () => { const getCurrentCursor = () => Cursor.findOne({}); const isPresenter = () => { - const currentUser = Users.findOne({ userId: Auth.userID, }); + const currentUser = Users.findOne({ userId: Auth.userID }); if (currentUser && currentUser.user) { return currentUser.user.presenter; diff --git a/bigbluebutton-html5/imports/ui/components/presentation/slide/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/slide/component.jsx index 44015bb1774a02fc355cf7bd4753824f38ec86de..4e1e7d2d78567d356573f88125d7c077c1e18515 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/slide/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/presentation/slide/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; export default class Slide extends React.Component { constructor(props) { @@ -16,15 +17,14 @@ export default class Slide extends React.Component { width={this.props.currentSlide.slide.width} height={this.props.currentSlide.slide.height} fill="white" - > - </rect> - <image x="0" y="0" + /> + <image + x="0" y="0" width={this.props.currentSlide.slide.width} height={this.props.currentSlide.slide.height} xlinkHref={this.props.currentSlide.slide.img_uri} strokeWidth="0.8" - > - </image> + /> </g> : null } </g> diff --git a/bigbluebutton-html5/imports/ui/components/settings/component.jsx b/bigbluebutton-html5/imports/ui/components/settings/component.jsx index 9d040ee4ab48467b6aa978de241ba7ed06ede35c..a4e3b9b60e4e0fcf50859b7ac72ce354c4e2a759 100755 --- a/bigbluebutton-html5/imports/ui/components/settings/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/settings/component.jsx @@ -89,14 +89,14 @@ class Settings extends Component { } componentWillMount() { - this.props.availableLocales.then(locales => { + this.props.availableLocales.then((locales) => { this.setState({ availableLocales: locales }); }); } setHtmlFontSize(size) { document.getElementsByTagName('html')[0].style.fontSize = size; - }; + } render() { const intl = this.props.intl; @@ -118,14 +118,15 @@ class Settings extends Component { }), label: intl.formatMessage(intlMessages.CancelLabel), description: intl.formatMessage(intlMessages.CancelLabelDesc), - }}> - {this.renderModalContent()} + }} + > + {this.renderModalContent()} </Modal> ); } handleUpdateSettings(key, newSettings) { - let settings = this.state; + const settings = this.state; settings.current[key] = newSettings; this.setState(settings); } @@ -151,20 +152,20 @@ class Settings extends Component { > <TabList className={styles.tabList}> <Tab className={styles.tabSelector} aria-labelledby="appTab"> - <Icon iconName='application' className={styles.icon}/> + <Icon iconName="application" className={styles.icon} /> <span id="appTab">{intl.formatMessage(intlMessages.appTabLabel)}</span> </Tab> - {/*<Tab className={styles.tabSelector} aria-labelledby="videoTab">*/} - {/*<Icon iconName='video' className={styles.icon}/>*/} - {/*<span id="videoTab">{intl.formatMessage(intlMessages.videoTabLabel)}</span>*/} - {/*</Tab>*/} + {/* <Tab className={styles.tabSelector} aria-labelledby="videoTab">*/} + {/* <Icon iconName='video' className={styles.icon}/>*/} + {/* <span id="videoTab">{intl.formatMessage(intlMessages.videoTabLabel)}</span>*/} + {/* </Tab>*/} <Tab className={styles.tabSelector} aria-labelledby="ccTab"> - <Icon iconName='user' className={styles.icon}/> + <Icon iconName="user" className={styles.icon} /> <span id="ccTab">{intl.formatMessage(intlMessages.closecaptionTabLabel)}</span> </Tab> { isModerator ? <Tab className={styles.tabSelector} aria-labelledby="usersTab"> - <Icon iconName='user' className={styles.icon}/> + <Icon iconName="user" className={styles.icon} /> <span id="usersTab">{intl.formatMessage(intlMessages.usersTabLabel)}</span> </Tab> : null } @@ -174,25 +175,27 @@ class Settings extends Component { availableLocales={this.state.availableLocales} handleUpdateSettings={this.handleUpdateSettings} settings={this.state.current.application} - /> + /> </TabPanel> - {/*<TabPanel className={styles.tabPanel}>*/} - {/*<Video*/} - {/*handleUpdateSettings={this.handleUpdateSettings}*/} - {/*settings={this.state.current.video}*/} - {/*/>*/} - {/*</TabPanel>*/} + {/* <TabPanel className={styles.tabPanel}>*/} + {/* <Video*/} + {/* handleUpdateSettings={this.handleUpdateSettings}*/} + {/* settings={this.state.current.video}*/} + {/* />*/} + {/* </TabPanel>*/} <TabPanel className={styles.tabPanel}> <ClosedCaptions settings={this.state.current.cc} handleUpdateSettings={this.handleUpdateSettings} - locales={this.props.locales}/> + locales={this.props.locales} + /> </TabPanel> { isModerator ? <TabPanel className={styles.tabPanel}> <Participants settings={this.state.current.participants} - handleUpdateSettings={this.handleUpdateSettings}/> + handleUpdateSettings={this.handleUpdateSettings} + /> </TabPanel> : null } </Tabs> diff --git a/bigbluebutton-html5/imports/ui/components/settings/container.jsx b/bigbluebutton-html5/imports/ui/components/settings/container.jsx old mode 100644 new mode 100755 index 89ee8a6c263903cf9997253ead8f1a2c18b2c89e..b5ff6d69bfd58d33d4f6407b76f71136ea2e1b76 --- a/bigbluebutton-html5/imports/ui/components/settings/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/settings/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import Settings from './component'; import SettingsService from '/imports/ui/services/settings'; @@ -13,21 +14,19 @@ import { class SettingsContainer extends Component { render() { return ( - <Settings {...this.props}/> + <Settings {...this.props} /> ); } } -export default createContainer(function () { - return { - audio: SettingsService.audio, - video: SettingsService.video, - application: SettingsService.application, - cc: SettingsService.cc, - participants: SettingsService.participants, - updateSettings, - locales: getClosedCaptionLocales(), - availableLocales: getAvailableLocales(), - isModerator: getUserRoles() === 'MODERATOR', - }; -}, SettingsContainer); +export default createContainer(() => ({ + audio: SettingsService.audio, + video: SettingsService.video, + application: SettingsService.application, + cc: SettingsService.cc, + participants: SettingsService.participants, + updateSettings, + locales: getClosedCaptionLocales(), + availableLocales: getAvailableLocales(), + isModerator: getUserRoles() === 'MODERATOR', +}), SettingsContainer); diff --git a/bigbluebutton-html5/imports/ui/components/settings/service.js b/bigbluebutton-html5/imports/ui/components/settings/service.js index dbb617a49654ab936179a21a758d82bd4b096602..19d38a83c8eec4c2600f179a63079609042c2930 100644 --- a/bigbluebutton-html5/imports/ui/components/settings/service.js +++ b/bigbluebutton-html5/imports/ui/components/settings/service.js @@ -5,13 +5,11 @@ import _ from 'lodash'; import Settings from '/imports/ui/services/settings'; const getClosedCaptionLocales = () => { - //list of unique locales in the Captions Collection + // list of unique locales in the Captions Collection const locales = _.uniq(Captions.find({}, { sort: { locale: 1 }, fields: { locale: true }, - }).fetch().map(function (obj) { - return obj.locale; - }), true); + }).fetch().map(obj => obj.locale), true); return locales; }; diff --git a/bigbluebutton-html5/imports/ui/components/settings/submenus/application/component.jsx b/bigbluebutton-html5/imports/ui/components/settings/submenus/application/component.jsx index 2b61739df81145afa81242b7810dcc8e9e06ba70..8c2daab4080e19f6c016b475c7fd804ebf6e0170 100644 --- a/bigbluebutton-html5/imports/ui/components/settings/submenus/application/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/settings/submenus/application/component.jsx @@ -53,7 +53,7 @@ const intlMessages = defineMessages({ id: 'app.submenu.application.ariaLanguageLabel', description: 'aria label for locale change section', }, - languageOptionLabel: { + languageOptionLabel: { id: 'app.submenu.application.languageOptionLabel', description: 'default change language option when locales are available', }, @@ -74,17 +74,17 @@ class ApplicationMenu extends BaseMenu { } handleUpdateFontSize(size) { - let obj = this.state; + const obj = this.state; obj.settings.fontSize = size; this.handleUpdateSettings(this.state.settingsName, obj.settings); } setHtmlFontSize(size) { document.getElementsByTagName('html')[0].style.fontSize = size; - }; + } changeFontSize(size) { - let obj = this.state; + const obj = this.state; obj.settings.fontSize = size; this.setState(obj, () => { this.setHtmlFontSize(this.state.settings.fontSize); @@ -96,20 +96,20 @@ class ApplicationMenu extends BaseMenu { const currentFontSize = this.state.settings.fontSize; const availableFontSizes = this.props.fontSizes; const canIncreaseFontSize = availableFontSizes.indexOf(currentFontSize) < MAX_FONTSIZE; - let fs = (canIncreaseFontSize) ? availableFontSizes.indexOf(currentFontSize) + 1 : MAX_FONTSIZE; + const fs = (canIncreaseFontSize) ? availableFontSizes.indexOf(currentFontSize) + 1 : MAX_FONTSIZE; this.changeFontSize(availableFontSizes[fs]); - }; + } handleDecreaseFontSize() { const currentFontSize = this.state.settings.fontSize; const availableFontSizes = this.props.fontSizes; const canDecreaseFontSize = availableFontSizes.indexOf(currentFontSize) > MIN_FONTSIZE; - let fs = (canDecreaseFontSize) ? availableFontSizes.indexOf(currentFontSize) - 1 : MIN_FONTSIZE; + const fs = (canDecreaseFontSize) ? availableFontSizes.indexOf(currentFontSize) - 1 : MIN_FONTSIZE; this.changeFontSize(availableFontSizes[fs]); - }; + } handleSelectChange(fieldname, options, e) { - let obj = this.state; + const obj = this.state; obj.settings[fieldname] = e.target.value.toLowerCase().replace('_', '-'); this.handleUpdateSettings('application', obj.settings); } @@ -143,7 +143,8 @@ class ApplicationMenu extends BaseMenu { defaultChecked={this.state.settings.chatAudioNotifications} onChange={() => this.handleToggle('chatAudioNotifications')} ariaLabelledBy={'audioNotify'} - ariaLabel={intl.formatMessage(intlMessages.audioNotifyLabel)} /> + ariaLabel={intl.formatMessage(intlMessages.audioNotifyLabel)} + /> </div> </div> </div> @@ -162,7 +163,8 @@ class ApplicationMenu extends BaseMenu { defaultChecked={this.state.settings.chatPushNotifications} onChange={() => this.handleToggle('chatPushNotifications')} ariaLabelledBy={'pushNotify'} - ariaLabel={intl.formatMessage(intlMessages.pushNotifyLabel)}/> + ariaLabel={intl.formatMessage(intlMessages.pushNotifyLabel)} + /> </div> </div> </div> @@ -175,32 +177,35 @@ class ApplicationMenu extends BaseMenu { </div> </div> <div className={styles.col}> - <div className={cx(styles.formElement, styles.pullContentRight)} - aria-labelledby="changeLangLabel"> + <div + className={cx(styles.formElement, styles.pullContentRight)} + aria-labelledby="changeLangLabel" + > <select defaultValue={this.state.settings.locale} className={styles.select} - onChange={this.handleSelectChange.bind(this, 'locale', availableLocales)}> - <option disabled={true}> + onChange={this.handleSelectChange.bind(this, 'locale', availableLocales)} + > + <option disabled> { availableLocales && availableLocales.length ? intl.formatMessage(intlMessages.languageOptionLabel) : intl.formatMessage(intlMessages.noLocaleOptionLabel) } </option> - {availableLocales ? availableLocales.map((locale, index) => - <option key={index} value={locale.locale}> + {availableLocales ? availableLocales.map((locale, index) => + (<option key={index} value={locale.locale}> {locale.name} - </option> + </option>), ) : null } </select> </div> <div id="changeLangLabel" - aria-label={intl.formatMessage(intlMessages.ariaLanguageLabel)}> - </div> + aria-label={intl.formatMessage(intlMessages.ariaLanguageLabel)} + /> </div> </div> - <hr className={styles.separator}/> + <hr className={styles.separator} /> <div className={styles.row}> <div className={styles.col}> <div className={styles.formElement}> @@ -224,8 +229,8 @@ class ApplicationMenu extends BaseMenu { onClick={() => this.handleIncreaseFontSize()} color={'success'} icon={'add'} - circle={true} - hideLabel={true} + circle + hideLabel label={intl.formatMessage(intlMessages.increaseFontBtnLabel)} /> </div> @@ -234,8 +239,8 @@ class ApplicationMenu extends BaseMenu { onClick={() => this.handleDecreaseFontSize()} color={'success'} icon={'substract'} - circle={true} - hideLabel={true} + circle + hideLabel label={intl.formatMessage(intlMessages.decreaseFontBtnLabel)} /> </div> @@ -247,6 +252,6 @@ class ApplicationMenu extends BaseMenu { </div> ); } -}; +} export default injectIntl(ApplicationMenu); diff --git a/bigbluebutton-html5/imports/ui/components/settings/submenus/application/container.jsx b/bigbluebutton-html5/imports/ui/components/settings/submenus/application/container.jsx old mode 100644 new mode 100755 index a3c111ee8fde2ed543d9b374d692524a78217e2f..f90e513da4d5843ba352965a76375b8fba80b14c --- a/bigbluebutton-html5/imports/ui/components/settings/submenus/application/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/settings/submenus/application/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import Application from './component'; @@ -13,14 +14,12 @@ class ApplicationContainer extends Component { ); } } -export default createContainer(function () { - return { - fontSizes: [ - '12px', - '14px', - '16px', - '18px', - '20px', - ], - }; -}, ApplicationContainer); +export default createContainer(() => ({ + fontSizes: [ + '12px', + '14px', + '16px', + '18px', + '20px', + ], +}), ApplicationContainer); diff --git a/bigbluebutton-html5/imports/ui/components/settings/submenus/base/component.jsx b/bigbluebutton-html5/imports/ui/components/settings/submenus/base/component.jsx index fb105ff8b903b51d23aed7cf873984099c47d551..5098df29e72ade48c245c7ae5532835d0c20b8e2 100644 --- a/bigbluebutton-html5/imports/ui/components/settings/submenus/base/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/settings/submenus/base/component.jsx @@ -12,11 +12,11 @@ export default class BaseMenu extends React.Component { } handleToggle(key) { - let obj = this.state; + const obj = this.state; obj.settings[key] = !this.state.settings[key]; this.setState(obj, () => { this.handleUpdateSettings(this.state.settingsName, this.state.settings); }); } -}; +} diff --git a/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/component.jsx b/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/component.jsx index ae6f7a3899266cadc41c36c72d9425865931ac8b..58ef831be5fb23b4fe659daf63c0c98e58e798a9 100755 --- a/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/component.jsx @@ -7,18 +7,18 @@ import Checkbox from '/imports/ui/components/checkbox/component'; import { GithubPicker } from 'react-color'; import { defineMessages, injectIntl } from 'react-intl'; -//an array of font-families +// an array of font-families const FONT_FAMILIES = ['Arial', 'Calibri', 'Time New Roman', 'Sans-serif']; -//an array of different font-sizes +// an array of different font-sizes const FONT_SIZES = ['12px', '14px', '18px', '24px', '32px', '42px']; -//an array of colors for both background and text -const COLORS = [ - '#000000', '#7A7A7A', '#FF0000', '#FF8800', - '#88FF00', '#FFFFFF', '#00FFFF', '#0000FF', - '#8800FF', '#FF00FF', - ]; +// an array of colors for both background and text +const COLORS = [ + '#000000', '#7A7A7A', '#FF0000', '#FF8800', + '#88FF00', '#FFFFFF', '#00FFFF', '#0000FF', + '#8800FF', '#FF00FF', +]; const intlMessages = defineMessages({ closedCaptionsLabel: { @@ -92,30 +92,30 @@ class ClosedCaptionsMenu extends BaseMenu { }; } - //clickhandler, opens a selected color picker (supports both of them) + // clickhandler, opens a selected color picker (supports both of them) handleColorPickerClick(fieldname) { - let obj = {}; + const obj = {}; obj[fieldname] = !this.state[fieldname]; this.setState(obj); } - //closes color pickers + // closes color pickers handleCloseColorPicker() { this.setState({ displayBackgroundColorPicker: false, - displayFontColorPicker:false, + displayFontColorPicker: false, }); } handleSelectChange(fieldname, options, e) { - let obj = this.state; + const obj = this.state; obj.settings[fieldname] = options[e.target.value]; this.setState(obj); this.handleUpdateSettings('cc', obj.settings); } handleColorChange(fieldname, color) { - let obj = this.state; + const obj = this.state; obj.settings[fieldname] = color.hex; this.setState(obj); @@ -146,12 +146,13 @@ class ClosedCaptionsMenu extends BaseMenu { </div> <div className={styles.col}> <div className={cx(styles.formElement, styles.pullContentRight)} > - <Toggle - icons={false} - defaultChecked={this.state.settings.enabled} - onChange={() => this.handleToggle('enabled')} - ariaLabelledBy={'closedCaptions'} - ariaLabel={intl.formatMessage(intlMessages.closedCaptionsLabel)} /> + <Toggle + icons={false} + defaultChecked={this.state.settings.enabled} + onChange={() => this.handleToggle('enabled')} + ariaLabelledBy={'closedCaptions'} + ariaLabel={intl.formatMessage(intlMessages.closedCaptionsLabel)} + /> </div> </div> </div> @@ -172,7 +173,8 @@ class ClosedCaptionsMenu extends BaseMenu { onChange={() => this.handleToggle('takeOwnership')} checked={this.state.settings.takeOwnership} ariaLabelledBy={'takeOwnership'} - ariaLabel={intl.formatMessage(intlMessages.takeOwnershipLabel)}/> + ariaLabel={intl.formatMessage(intlMessages.takeOwnershipLabel)} + /> </div> </div> </div> @@ -188,11 +190,13 @@ class ClosedCaptionsMenu extends BaseMenu { <div className={styles.col}> <div className={cx(styles.formElement, styles.pullContentRight)} - aria-label={intl.formatMessage(intlMessages.languageLabel)}> + aria-label={intl.formatMessage(intlMessages.languageLabel)} + > <select defaultValue={locales ? locales.indexOf(this.state.settings.locale) : -1} className={styles.select} - onChange={this.handleSelectChange.bind(this, 'locale', this.props.locales)}> + onChange={this.handleSelectChange.bind(this, 'locale', this.props.locales)} + > <option> { this.props.locales && this.props.locales.length ? @@ -200,9 +204,9 @@ class ClosedCaptionsMenu extends BaseMenu { intl.formatMessage(intlMessages.noLocaleOptionLabel) } </option> {this.props.locales ? this.props.locales.map((locale, index) => - <option key={index} value={index}> + (<option key={index} value={index}> {locale} - </option> + </option>), ) : null } </select> </div> @@ -220,19 +224,21 @@ class ClosedCaptionsMenu extends BaseMenu { <div className={styles.col}> <div className={cx(styles.formElement, styles.pullContentRight)} - aria-label={intl.formatMessage(intlMessages.fontFamilyLabel)}> + aria-label={intl.formatMessage(intlMessages.fontFamilyLabel)} + > <select defaultValue={FONT_FAMILIES.indexOf(this.state.settings.fontFamily)} onChange={this.handleSelectChange.bind(this, 'fontFamily', FONT_FAMILIES)} - className={styles.select}> - <option value='-1' disabled> + className={styles.select} + > + <option value="-1" disabled> {intl.formatMessage(intlMessages.fontFamilyOptionLabel)} </option> { FONT_FAMILIES.map((family, index) => - <option key={index} value={index}> + (<option key={index} value={index}> {family} - </option> + </option>), ) } </select> @@ -251,22 +257,24 @@ class ClosedCaptionsMenu extends BaseMenu { <div className={styles.col}> <div className={cx(styles.formElement, styles.pullContentRight)} - aria-label={intl.formatMessage(intlMessages.fontSizeLabel)}> - <select - defaultValue={FONT_SIZES.indexOf(this.state.settings.fontSize)} - onChange={this.handleSelectChange.bind(this, 'fontSize', FONT_SIZES)} - className={styles.select}> - <option value='-1' disabled> - {intl.formatMessage(intlMessages.fontSizeOptionLabel)} - </option> - { + aria-label={intl.formatMessage(intlMessages.fontSizeLabel)} + > + <select + defaultValue={FONT_SIZES.indexOf(this.state.settings.fontSize)} + onChange={this.handleSelectChange.bind(this, 'fontSize', FONT_SIZES)} + className={styles.select} + > + <option value="-1" disabled> + {intl.formatMessage(intlMessages.fontSizeOptionLabel)} + </option> + { FONT_SIZES.map((size, index) => - <option key={index} value={index}> + (<option key={index} value={index}> {size} - </option> + </option>), ) } - </select> + </select> </div> </div> </div> @@ -282,24 +290,26 @@ class ClosedCaptionsMenu extends BaseMenu { <div className={styles.col}> <div className={cx(styles.formElement, styles.pullContentRight)} - aria-label={intl.formatMessage(intlMessages.backgroundColorLabel)}> + aria-label={intl.formatMessage(intlMessages.backgroundColorLabel)} + > <div - tabIndex='0' - className={ styles.swatch } + tabIndex="0" + className={styles.swatch} onClick={ this.handleColorPickerClick.bind(this, 'displayBackgroundColorPicker') - }> + } + > <div className={styles.swatchInner} - style={ { background: this.state.settings.backgroundColor } }> - </div> + style={{ background: this.state.settings.backgroundColor }} + /> </div> { this.state.displayBackgroundColorPicker ? <div className={styles.colorPickerPopover}> <div className={styles.colorPickerOverlay} - onClick={ this.handleCloseColorPicker.bind(this) }> - </div> + onClick={this.handleCloseColorPicker.bind(this)} + /> <GithubPicker onChange={this.handleColorChange.bind(this, 'backgroundColor')} color={this.state.settings.backgroundColor} @@ -324,23 +334,24 @@ class ClosedCaptionsMenu extends BaseMenu { <div className={styles.col}> <div className={cx(styles.formElement, styles.pullContentRight)} - aria-label={intl.formatMessage(intlMessages.fontColorLabel)}> + aria-label={intl.formatMessage(intlMessages.fontColorLabel)} + > <div - tabIndex='0' - className={ styles.swatch } - onClick={ this.handleColorPickerClick.bind(this, 'displayFontColorPicker') }> + tabIndex="0" + className={styles.swatch} + onClick={this.handleColorPickerClick.bind(this, 'displayFontColorPicker')} + > <div className={styles.swatchInner} - style={ { background: this.state.settings.fontColor } }> - </div> + style={{ background: this.state.settings.fontColor }} + /> </div> { this.state.displayFontColorPicker ? <div className={styles.colorPickerPopover}> <div className={styles.colorPickerOverlay} - onClick={ this.handleCloseColorPicker.bind(this) } - > - </div> + onClick={this.handleCloseColorPicker.bind(this)} + /> <GithubPicker onChange={this.handleColorChange.bind(this, 'fontColor')} color={this.state.settings.fontColor} @@ -355,8 +366,9 @@ class ClosedCaptionsMenu extends BaseMenu { </div> <div className={cx(styles.ccPreviewBox, styles.spacedLeft)} - role='presentation' - style={ { background: this.state.settings.backgroundColor } }> + role="presentation" + style={{ background: this.state.settings.backgroundColor }} + > <span style={this.getPreviewStyle()}> Etiam porta sem malesuada magna mollis euis-mod. Donec ullamcorper nulla non metus auctor fringilla. @@ -368,6 +380,6 @@ class ClosedCaptionsMenu extends BaseMenu { </div> ); } -}; +} export default injectIntl(ClosedCaptionsMenu); diff --git a/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/container.jsx b/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/container.jsx old mode 100644 new mode 100755 index 339cc0371ccd5ce6f482a7a3b52e110c37dde522..53979f92925a2f9ce234b53d1b678a879012e145 --- a/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import ClosedCaptionsMenu from './component'; import Service from './service'; @@ -13,6 +14,4 @@ class ClosedCaptionsMenuContainer extends Component { } } -export default createContainer(function () { - return Service.getClosedCaptionSettings(); -}, ClosedCaptionsMenuContainer); +export default createContainer(() => Service.getClosedCaptionSettings(), ClosedCaptionsMenuContainer); diff --git a/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/service.js b/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/service.js index 1d3dadbb1fe597e6c5843d11f9b744a55d76ff9e..264748636fdb858882d417b0abc02480397f901e 100644 --- a/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/service.js +++ b/bigbluebutton-html5/imports/ui/components/settings/submenus/closed-captions/service.js @@ -1,8 +1,8 @@ import Storage from '/imports/ui/services/storage/session'; getClosedCaptionSettings = () => { - let ccSettings = {}; - let ccEnabled = Storage.getItem('closedCaptions'); + const ccSettings = {}; + const ccEnabled = Storage.getItem('closedCaptions'); ccSettings.ccEnabled = !!ccEnabled; return ccSettings; diff --git a/bigbluebutton-html5/imports/ui/components/settings/submenus/participants/component.jsx b/bigbluebutton-html5/imports/ui/components/settings/submenus/participants/component.jsx index 0a9bc7beb4e1f3ce2e251f52bebc64104a3e2cfb..6302e7b1fe554479f00f21556c37cef5f97592d7 100755 --- a/bigbluebutton-html5/imports/ui/components/settings/submenus/participants/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/settings/submenus/participants/component.jsx @@ -101,7 +101,6 @@ class ApplicationMenu extends BaseMenu { } getLockItems() { - const { intl } = this.props; return [ @@ -149,7 +148,6 @@ class ApplicationMenu extends BaseMenu { } render() { - const { intl } = this.props; return ( @@ -168,13 +166,14 @@ class ApplicationMenu extends BaseMenu { </div> <div className={styles.col}> <div - className={cx(styles.formElement, styles.pullContentRight)}> - <Toggle - icons={false} - defaultChecked={this.state.settings.muteAll} - onChange={() => this.handleToggle('muteAll')} - ariaLabelledBy={'muteLabel'} - ariaLabel={intl.formatMessage(intlMessages.muteAllLabel)} + className={cx(styles.formElement, styles.pullContentRight)} + > + <Toggle + icons={false} + defaultChecked={this.state.settings.muteAll} + onChange={() => this.handleToggle('muteAll')} + ariaLabelledBy={'muteLabel'} + ariaLabel={intl.formatMessage(intlMessages.muteAllLabel)} /> </div> </div> @@ -189,24 +188,23 @@ class ApplicationMenu extends BaseMenu { </div> <div className={styles.col}> <div className={cx(styles.formElement, styles.pullContentRight)}> - <Toggle - icons={false} - defaultChecked={this.state.settings.lockAll} - onChange={() => this.handleToggle('lockAll')} - ariaLabelledBy={'lockLabel'} - ariaLabel={intl.formatMessage(intlMessages.lockAllLabel)} - /> + <Toggle + icons={false} + defaultChecked={this.state.settings.lockAll} + onChange={() => this.handleToggle('lockAll')} + ariaLabelledBy={'lockLabel'} + ariaLabel={intl.formatMessage(intlMessages.lockAllLabel)} + /> </div> </div> </div> - {this.getLockItems().map((item, i) => this.renderLockItem(item, i))} + {this.getLockItems().map((item, i) => this.renderLockItem(item, i))} </div> </div> ); } renderLockItem({ label, key, ariaLabel, ariaLabelledBy, ariaDesc, ariaDescribedBy }, i) { - return ( <div key={i} className={cx(styles.row, styles.spacedLeft)}> <div className={styles.col}> @@ -218,7 +216,8 @@ class ApplicationMenu extends BaseMenu { </div> <div className={styles.col}> <div - className={cx(styles.formElement, styles.pullContentRight)}> + className={cx(styles.formElement, styles.pullContentRight)} + > <Checkbox onChange={() => this.handleToggle(key)} checked={this.state.settings[key]} @@ -226,12 +225,12 @@ class ApplicationMenu extends BaseMenu { ariaLabelledBy={ariaLabelledBy} ariaDesc={ariaDesc} ariaDescribedBy={ariaDescribedBy} - /> + /> </div> </div> </div> ); } -}; +} export default injectIntl(ApplicationMenu); diff --git a/bigbluebutton-html5/imports/ui/components/settings/submenus/video/component.jsx b/bigbluebutton-html5/imports/ui/components/settings/submenus/video/component.jsx index 53f08e848ce21c24a910f2f9bb932fd277c2204d..d58aaf4a85cf1a7a11a9511093aa6585e04c7f81 100755 --- a/bigbluebutton-html5/imports/ui/components/settings/submenus/video/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/settings/submenus/video/component.jsx @@ -56,14 +56,16 @@ class VideoMenu extends BaseMenu { <div className={styles.col}> <div className={styles.formElement} - aria-label={intl.formatMessage(intlMessages.videoSourceLabel)}> + aria-label={intl.formatMessage(intlMessages.videoSourceLabel)} + > <label className={cx(styles.label, styles.labelSmall)}> {intl.formatMessage(intlMessages.videoSourceLabel)} </label> <select - defaultValue='-1' - className={styles.select}> - <option value='-1' disabled> + defaultValue="-1" + className={styles.select} + > + <option value="-1" disabled> {intl.formatMessage(intlMessages.videoOptionLabel)} </option> </select> @@ -72,14 +74,16 @@ class VideoMenu extends BaseMenu { <div className={styles.col}> <div className={styles.formElement} - aria-label={intl.formatMessage(intlMessages.videoQualityLabel)}> + aria-label={intl.formatMessage(intlMessages.videoQualityLabel)} + > <label className={cx(styles.label, styles.labelSmall)}> {intl.formatMessage(intlMessages.videoQualityLabel)} </label> <select - defaultValue='-1' - className={styles.select}> - <option value='-1' disabled> + defaultValue="-1" + className={styles.select} + > + <option value="-1" disabled> {intl.formatMessage(intlMessages.qualityOptionLabel)} </option> </select> @@ -96,12 +100,13 @@ class VideoMenu extends BaseMenu { </div> <div className={styles.col}> <div className={cx(styles.formElement, styles.pullContentRight)}> - <Toggle - icons={false} - defaultChecked={this.state.viewParticipantsWebcams} - onChange={() => this.handleToggle('viewParticipantsWebcams')} - ariaLabelledBy={'viewCamLabel'} - ariaLabel={intl.formatMessage(intlMessages.participantsCamLabel)} /> + <Toggle + icons={false} + defaultChecked={this.state.viewParticipantsWebcams} + onChange={() => this.handleToggle('viewParticipantsWebcams')} + ariaLabelledBy={'viewCamLabel'} + ariaLabel={intl.formatMessage(intlMessages.participantsCamLabel)} + /> </div> </div> </div> @@ -109,6 +114,6 @@ class VideoMenu extends BaseMenu { </div> ); } -}; +} export default injectIntl(VideoMenu); diff --git a/bigbluebutton-html5/imports/ui/components/switch/component.jsx b/bigbluebutton-html5/imports/ui/components/switch/component.jsx old mode 100644 new mode 100755 index 9e86014c252bc4ed621f08017737cd912ade6fb2..6cc7e3a4182e41cc380657ac3e5c3365fbc8b34f --- a/bigbluebutton-html5/imports/ui/components/switch/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/switch/component.jsx @@ -39,7 +39,6 @@ export default class Switch extends Toggle { <input {...inputProps} ref={ref => { this.input = ref; }} - onFocus={this.handleFocus} onBlur={this.handleBlur} className='react-toggle-screenreader-only' diff --git a/bigbluebutton-html5/imports/ui/components/user-avatar/color-generator.js b/bigbluebutton-html5/imports/ui/components/user-avatar/color-generator.js index d670179f6c03ff719d0116b1d451053c2e7db28d..302843ea832adb4942aae33607f7ae47e75ecd48 100755 --- a/bigbluebutton-html5/imports/ui/components/user-avatar/color-generator.js +++ b/bigbluebutton-html5/imports/ui/components/user-avatar/color-generator.js @@ -1,22 +1,22 @@ -//This is the code to generate the colors for the user avatar when no image is provided +// This is the code to generate the colors for the user avatar when no image is provided const stringToPastelColour = (str) => { str = str.trim().toLowerCase(); - let baseRed = 128; - let baseGreen = 128; - let baseBlue = 128; + const baseRed = 128; + const baseGreen = 128; + const baseBlue = 128; let seed = 0; for (let i = 0; i < str.length; seed = str.charCodeAt(i++) + ((seed << 5) - seed)); - let a = Math.abs((Math.sin(seed++) * 10000)) % 256; - let b = Math.abs((Math.sin(seed++) * 10000)) % 256; - let c = Math.abs((Math.sin(seed++) * 10000)) % 256; + const a = Math.abs((Math.sin(seed++) * 10000)) % 256; + const b = Math.abs((Math.sin(seed++) * 10000)) % 256; + const c = Math.abs((Math.sin(seed++) * 10000)) % 256; - //build colour - let red = Math.round((a + baseRed) / 2); - let green = Math.round((b + baseGreen) / 2); - let blue = Math.round((c + baseBlue) / 2); + // build colour + const red = Math.round((a + baseRed) / 2); + const green = Math.round((b + baseGreen) / 2); + const blue = Math.round((c + baseBlue) / 2); return { r: red, @@ -28,10 +28,10 @@ const stringToPastelColour = (str) => { // https://www.w3.org/TR/WCAG20/#relativeluminancedef // http://entropymine.com/imageworsener/srgbformula/ const relativeLuminance = (rgb) => { - let tmp = {}; + const tmp = {}; Object.keys(rgb).forEach((i) => { - let c = rgb[i] / 255; + const c = rgb[i] / 255; if (c <= 0.03928) { tmp[i] = c / 12.92; } else { @@ -53,7 +53,7 @@ const contrastRatio = (a, b) => { a = relativeLuminance(a); b = relativeLuminance(b); - //Arrange so a is lightest + // Arrange so a is lightest if (a < b) { c = a; a = b; @@ -77,20 +77,20 @@ const shadeColor = (rgb, amt) => { else if (g < 0) g = 0; return { - r: r, - g: g, - b: b, + r, + g, + b, }; }; const addShadeIfNoContrast = (rgb) => { - let base = { + const base = { r: 255, g: 255, b: 255, }; // white - let cr = contrastRatio(base, rgb); + const cr = contrastRatio(base, rgb); if (cr > 4.5) { return rgb; @@ -102,7 +102,7 @@ const addShadeIfNoContrast = (rgb) => { const getColor = (str) => { let rgb = stringToPastelColour(str); rgb = addShadeIfNoContrast(rgb); - return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')'; + return `rgb(${rgb.r},${rgb.g},${rgb.b})`; }; export default getColor; diff --git a/bigbluebutton-html5/imports/ui/components/user-avatar/component.jsx b/bigbluebutton-html5/imports/ui/components/user-avatar/component.jsx index bffd9d4e8e4d19027f74458c5e47a564877da90f..928a9d4a37d4919a6cd3763a75623d4f5eb67aca 100755 --- a/bigbluebutton-html5/imports/ui/components/user-avatar/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-avatar/component.jsx @@ -1,17 +1,18 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import Icon from '/imports/ui/components/icon/component'; import styles from './styles.scss'; import cx from 'classnames'; import generateColor from './color-generator'; const propTypes = { - user: React.PropTypes.shape({ - name: React.PropTypes.string.isRequired, - isPresenter: React.PropTypes.bool.isRequired, - isVoiceUser: React.PropTypes.bool.isRequired, - isModerator: React.PropTypes.bool.isRequired, - isOnline: React.PropTypes.bool.isRequired, - image: React.PropTypes.string, + user: PropTypes.shape({ + name: PropTypes.string.isRequired, + isPresenter: PropTypes.bool.isRequired, + isVoiceUser: PropTypes.bool.isRequired, + isModerator: PropTypes.bool.isRequired, + isOnline: PropTypes.bool.isRequired, + image: PropTypes.string, }).isRequired, }; @@ -26,14 +27,16 @@ export default class UserAvatar extends Component { const avatarColor = user.isOnline ? generateColor(user.name) : '#fff'; - let avatarStyles = { + const avatarStyles = { backgroundColor: avatarColor, boxShadow: user.isTalking ? `0 0 .5rem ${avatarColor}` : 'none', }; return ( - <div className={user.isOnline ? styles.userAvatar : styles.userLogout} - style={avatarStyles} aria-hidden="true"> + <div + className={user.isOnline ? styles.userAvatar : styles.userLogout} + style={avatarStyles} aria-hidden="true" + > <div> {this.renderAvatarContent()} </div> @@ -49,7 +52,7 @@ export default class UserAvatar extends Component { let content = <span aria-hidden="true">{user.name.slice(0, 2)}</span>; if (user.emoji.status !== 'none') { - let iconEmoji = undefined; + let iconEmoji; switch (user.emoji.status) { case 'thumbsUp': @@ -70,7 +73,7 @@ export default class UserAvatar extends Component { default: iconEmoji = user.emoji.status; } - content = <span aria-label={user.emoji.status}><Icon iconName={iconEmoji}/></span>; + content = <span aria-label={user.emoji.status}><Icon iconName={iconEmoji} /></span>; } return content; @@ -80,14 +83,13 @@ export default class UserAvatar extends Component { const user = this.props.user; let userStatus; - let userStatusClasses = {}; + const userStatusClasses = {}; userStatusClasses[styles.moderator] = user.isModerator; userStatusClasses[styles.presenter] = user.isPresenter; if (user.isModerator || user.isPresenter) { userStatus = ( - <span className={cx(styles.userStatus, userStatusClasses)}> - </span> + <span className={cx(styles.userStatus, userStatusClasses)} /> ); } @@ -98,14 +100,14 @@ export default class UserAvatar extends Component { const user = this.props.user; let userMediaStatus; - let userMediaClasses = {}; + const userMediaClasses = {}; userMediaClasses[styles.voiceOnly] = user.isListenOnly; userMediaClasses[styles.microphone] = user.isVoiceUser; if (user.isListenOnly || user.isVoiceUser) { userMediaStatus = ( <span className={cx(styles.userMediaStatus, userMediaClasses)}> - {user.isMuted ? <div className={styles.microphoneMuted}/> : null} + {user.isMuted ? <div className={styles.microphoneMuted} /> : null} </span> ); } diff --git a/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/component.jsx index f615401d42ced4eab231f8024c9f167ef73b9dce..4033113b2152f0aba73b64f7a3404fce3d787ed7 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/chat-list-item/component.jsx @@ -1,4 +1,5 @@ import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import UserAvatar from '/imports/ui/components/user-avatar/component'; import Icon from '/imports/ui/components/icon/component'; import styles from './styles.scss'; @@ -26,10 +27,10 @@ const CHAT_CONFIG = Meteor.settings.public.chat; const PRIVATE_CHAT_PATH = CHAT_CONFIG.path_route; const propTypes = { - chat: React.PropTypes.shape({ - id: React.PropTypes.string.isRequired, - name: React.PropTypes.string.isRequired, - unreadCounter: React.PropTypes.number.isRequired, + chat: PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + unreadCounter: PropTypes.number.isRequired, }).isRequired, }; @@ -48,9 +49,9 @@ class ChatListItem extends Component { const linkPath = [PRIVATE_CHAT_PATH, chat.id].join(''); const isCurrentChat = chat.id === openChat; - let isSingleMessage = chat.unreadCounter === 1; + const isSingleMessage = chat.unreadCounter === 1; - let linkClasses = {}; + const linkClasses = {}; linkClasses[styles.active] = isCurrentChat; if (chat.name === 'Public Chat') { @@ -58,41 +59,43 @@ class ChatListItem extends Component { } return ( - <Link - to={linkPath} - className={cx(styles.chatListItem, linkClasses)} - role="button" - aria-expanded={isCurrentChat} - tabIndex={tabIndex}> - <div className={styles.chatListItemLink}> - {chat.icon ? this.renderChatIcon() : this.renderChatAvatar()} - <div className={styles.chatName}> - {!compact ? <span className={styles.chatNameMain}>{chat.name}</span> : null } - </div> - {(chat.unreadCounter > 0) ? - <div - className={styles.unreadMessages} - aria-label={isSingleMessage + <Link + to={linkPath} + className={cx(styles.chatListItem, linkClasses)} + role="button" + aria-expanded={isCurrentChat} + tabIndex={tabIndex} + > + <div className={styles.chatListItemLink}> + {chat.icon ? this.renderChatIcon() : this.renderChatAvatar()} + <div className={styles.chatName}> + {!compact ? <span className={styles.chatNameMain}>{chat.name}</span> : null } + </div> + {(chat.unreadCounter > 0) ? + <div + className={styles.unreadMessages} + aria-label={isSingleMessage ? intl.formatMessage(intlMessages.unreadSingular, { 0: chat.unreadCounter }) - : intl.formatMessage(intlMessages.unreadPlural, { 0: chat.unreadCounter })}> - <div className={styles.unreadMessagesText} aria-hidden="true"> - {chat.unreadCounter} - </div> + : intl.formatMessage(intlMessages.unreadPlural, { 0: chat.unreadCounter })} + > + <div className={styles.unreadMessagesText} aria-hidden="true"> + {chat.unreadCounter} </div> + </div> : null} - </div> - </Link> + </div> + </Link> ); } renderChatAvatar() { - return <UserAvatar user={this.props.chat}/>; + return <UserAvatar user={this.props.chat} />; } renderChatIcon() { return ( <div className={styles.chatThumbnail}> - <Icon iconName={this.props.chat.icon} className={styles.actionIcon}/> + <Icon iconName={this.props.chat.icon} className={styles.actionIcon} /> </div> ); } diff --git a/bigbluebutton-html5/imports/ui/components/user-list/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/component.jsx index 6dc577205ecfeec062e40ddbaf072e4e3ff6e4b7..24701aa64b40472bb36d46a9afaaca80f72d19e1 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/component.jsx @@ -1,6 +1,7 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { withRouter } from 'react-router'; -import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; +import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'; import styles from './styles.scss'; import cx from 'classnames'; import { defineMessages, injectIntl } from 'react-intl'; @@ -127,9 +128,9 @@ class UserList extends Component { <div className={styles.header}> { !this.state.compact ? - <div className={styles.headerTitle} role="banner"> - {intl.formatMessage(intlMessages.participantsTitle)} - </div> : null + <div className={styles.headerTitle} role="banner"> + {intl.formatMessage(intlMessages.participantsTitle)} + </div> : null } </div> ); @@ -155,15 +156,16 @@ class UserList extends Component { <div className={styles.messages}> { !this.state.compact ? - <div className={styles.smallTitle} role="banner"> - {intl.formatMessage(intlMessages.messagesTitle)} - </div> : <hr className={styles.separator}></hr> + <div className={styles.smallTitle} role="banner"> + {intl.formatMessage(intlMessages.messagesTitle)} + </div> : <hr className={styles.separator} /> } <div tabIndex={0} className={styles.scrollableList} - ref={(r) => this._msgsList = r}> - <ReactCSSTransitionGroup + ref={(ref) => { this._msgsList = ref; }} + > + <CSSTransitionGroup transitionName={listTransition} transitionAppear={true} transitionEnter={true} @@ -172,18 +174,20 @@ class UserList extends Component { transitionEnterTimeout={0} transitionLeaveTimeout={0} component="div" - className={cx(styles.chatsList, styles.scrollableList)}> - <div ref={(r) => this._msgItems = r}> + className={cx(styles.chatsList, styles.scrollableList)} + > + <div ref={(ref) => { this._msgItems = ref; }}> {openChats.map(chat => ( <ChatListItem compact={this.state.compact} key={chat.id} openChat={openChat} chat={chat} - tabIndex={-1} /> + tabIndex={-1} + /> ))} </div> - </ReactCSSTransitionGroup> + </CSSTransitionGroup> </div> </div> ); @@ -236,16 +240,17 @@ class UserList extends Component { <div className={styles.participants}> { !this.state.compact ? - <div className={styles.smallTitle} role="banner"> - {intl.formatMessage(intlMessages.usersTitle)} + <div className={styles.smallTitle} role="banner"> + {intl.formatMessage(intlMessages.usersTitle)} ({users.length}) - </div> : <hr className={styles.separator}></hr> + </div> : <hr className={styles.separator} /> } <div className={styles.scrollableList} tabIndex={0} - ref={(r) => this._usersList = r}> - <ReactCSSTransitionGroup + ref={(ref) => { this._usersList = ref; }} + > + <CSSTransitionGroup transitionName={listTransition} transitionAppear={true} transitionEnter={true} @@ -254,22 +259,24 @@ class UserList extends Component { transitionEnterTimeout={0} transitionLeaveTimeout={0} component="div" - className={cx(styles.participantsList, styles.scrollableList)}> - <div ref={(r) => this._userItems = r}> + className={cx(styles.participantsList, styles.scrollableList)} + > + <div ref={(ref) => { this._userItems = ref; }}> { users.map(user => ( - <UserListItem - compact={this.state.compact} - key={user.id} - isBreakoutRoom={isBreakoutRoom} - user={user} - currentUser={currentUser} - userActions={userActions} - meeting={meeting} - />)) + <UserListItem + compact={this.state.compact} + key={user.id} + isBreakoutRoom={isBreakoutRoom} + user={user} + currentUser={currentUser} + userActions={userActions} + meeting={meeting} + /> + )) } </div> - </ReactCSSTransitionGroup> + </CSSTransitionGroup> </div> </div> ); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/container.jsx b/bigbluebutton-html5/imports/ui/components/user-list/container.jsx index a3433b154f06518a49cc05c81141aa0ad0ff1cd5..99e0b894727b365074a184946eb9e02f8de6298a 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/container.jsx @@ -31,7 +31,8 @@ class UserListContainer extends Component { openChat={openChat} isBreakoutRoom={isBreakoutRoom} makeCall={makeCall} - userActions={userActions}> + userActions={userActions} + > {children} </UserList> ); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/service.js b/bigbluebutton-html5/imports/ui/components/user-list/service.js index 3552b9c2d254506d8e997227d1d9b7afa752a95e..1ba864235f62587ffb0519290299cb1be95c4801 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/service.js +++ b/bigbluebutton-html5/imports/ui/components/user-list/service.js @@ -36,8 +36,8 @@ const mapUser = user => ({ isLocked: user.locked, }); -const mapOpenChats = chat => { - let currentUserId = Auth.userID; +const mapOpenChats = (chat) => { + const currentUserId = Auth.userID; return chat.message.from_userid !== currentUserId ? chat.message.from_userid : chat.message.to_userid; @@ -163,7 +163,7 @@ const userFindSorting = { }; const getUsers = () => { - let users = Users + const users = Users .find({ 'user.connection_status': 'online' }, userFindSorting) .fetch(); @@ -173,14 +173,13 @@ const getUsers = () => { .sort(sortUsers); }; -const getOpenChats = chatID => { - +const getOpenChats = (chatID) => { let openChats = Chat .find({ 'message.chat_type': PRIVATE_CHAT_TYPE }) .fetch() .map(mapOpenChats); - let currentUserId = Auth.userID; + const currentUserId = Auth.userID; if (chatID) { openChats.push(chatID); @@ -192,16 +191,15 @@ const getOpenChats = chatID => { .find({ 'user.userid': { $in: openChats } }) .map(u => u.user) .map(mapUser) - .map(op => { + .map((op) => { op.unreadCounter = UnreadMessages.count(op.id); return op; }); - let currentClosedChats = Storage.getItem(CLOSED_CHAT_LIST_KEY) || []; - let filteredChatList = []; + const currentClosedChats = Storage.getItem(CLOSED_CHAT_LIST_KEY) || []; + const filteredChatList = []; openChats.forEach((op) => { - // When a new private chat message is received, ensure the conversation view is restored. if (op.unreadCounter > 0) { if (_.indexOf(currentClosedChats, op.id) > -1) { @@ -231,8 +229,8 @@ const getOpenChats = chatID => { }; getCurrentUser = () => { - let currentUserId = Auth.userID; - let currentUser = Users.findOne({ 'user.userid': currentUserId }); + const currentUserId = Auth.userID; + const currentUser = Users.findOne({ 'user.userid': currentUserId }); return (currentUser) ? mapUser(currentUser.user) : null; }; diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-item/component.jsx index 42f77a869e0b9cf27ca664e0f47971c4787c9f90..cae9d882f8c25cd5d30a436fe234c7920721c095 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-item/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-item/component.jsx @@ -1,6 +1,6 @@ import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import UserAvatar from '/imports/ui/components/user-avatar/component'; -import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; import Icon from '/imports/ui/components/icon/component'; import { findDOMNode } from 'react-dom'; import { withRouter } from 'react-router'; @@ -18,19 +18,19 @@ import DropdownListSeparator from '/imports/ui/components/dropdown/list/separato import DropdownListTitle from '/imports/ui/components/dropdown/list/title/component'; const propTypes = { - user: React.PropTypes.shape({ - name: React.PropTypes.string.isRequired, - isPresenter: React.PropTypes.bool.isRequired, - isVoiceUser: React.PropTypes.bool.isRequired, - isModerator: React.PropTypes.bool.isRequired, - image: React.PropTypes.string, + user: PropTypes.shape({ + name: PropTypes.string.isRequired, + isPresenter: PropTypes.bool.isRequired, + isVoiceUser: PropTypes.bool.isRequired, + isModerator: PropTypes.bool.isRequired, + image: PropTypes.string, }).isRequired, - currentUser: React.PropTypes.shape({ - id: React.PropTypes.string.isRequired, + currentUser: PropTypes.shape({ + id: PropTypes.string.isRequired, }).isRequired, - userActions: React.PropTypes.shape(), + userActions: PropTypes.shape(), }; const defaultProps = { @@ -117,15 +117,15 @@ class UserListItem extends Component { } = userActions; const hasAuthority = currentUser.isModerator || user.isCurrent; - let allowedToChatPrivately = !user.isCurrent; - let allowedToMuteAudio = hasAuthority && user.isVoiceUser && user.isMuted; - let allowedToUnmuteAudio = hasAuthority && user.isVoiceUser && !user.isMuted; - let allowedToResetStatus = hasAuthority && user.emoji.status != 'none'; + const allowedToChatPrivately = !user.isCurrent; + const allowedToMuteAudio = hasAuthority && user.isVoiceUser && user.isMuted; + const allowedToUnmuteAudio = hasAuthority && user.isVoiceUser && !user.isMuted; + const allowedToResetStatus = hasAuthority && user.emoji.status != 'none'; // if currentUser is a moderator, allow kicking other users - let allowedToKick = currentUser.isModerator && !user.isCurrent && !isBreakoutRoom; + const allowedToKick = currentUser.isModerator && !user.isCurrent && !isBreakoutRoom; - let allowedToSetPresenter = + const allowedToSetPresenter = (currentUser.isModerator || currentUser.isPresenter) && !user.isPresenter; return _.compact([ @@ -154,7 +154,7 @@ class UserListItem extends Component { const scrollContainer = dropdown.parentElement.parentElement; - let nextState = { + const nextState = { dropdownVisible: true, }; @@ -238,7 +238,7 @@ class UserListItem extends Component { compact, } = this.props; - let userItemContentsStyle = {}; + const userItemContentsStyle = {}; userItemContentsStyle[styles.userItemContentsCompact] = compact; userItemContentsStyle[styles.active] = this.state.isActionsOpen; @@ -249,7 +249,7 @@ class UserListItem extends Component { let you = (user.isCurrent) ? intl.formatMessage(messages.you) : ''; - let presenter = (user.isPresenter) + const presenter = (user.isPresenter) ? intl.formatMessage(messages.presenter) : ''; @@ -259,9 +259,11 @@ class UserListItem extends Component { let actions = this.getAvailableActions(); let contents = ( + <div className={cx(styles.userListItem, userItemContentsStyle)} - aria-label={userAriaLabel}> + aria-label={userAriaLabel} + > <div className={styles.userItemContents} aria-hidden="true"> <UserAvatar user={user} /> {this.renderUserName()} @@ -275,7 +277,7 @@ class UserListItem extends Component { } const { dropdownOffset, dropdownDirection, dropdownVisible, } = this.state; - + return ( <Dropdown ref={(ref) => { this.dropdown = ref; }} @@ -296,7 +298,8 @@ class UserListItem extends Component { [dropdownDirection]: `${dropdownOffset}px`, }} className={styles.dropdownContent} - placement={`right ${dropdownDirection}`}> + placement={`right ${dropdownDirection}`} + > <DropdownList ref={(ref) => { this.list = ref; }} @@ -305,10 +308,11 @@ class UserListItem extends Component { { [ (<DropdownListTitle - description={intl.formatMessage(messages.menuTitleContext)} - key={_.uniqueId('dropdown-list-title')}> - {user.name} - </DropdownListTitle>), + description={intl.formatMessage(messages.menuTitleContext)} + key={_.uniqueId('dropdown-list-title')} + > + {user.name} + </DropdownListTitle>), (<DropdownListSeparator key={_.uniqueId('action-separator')} />), ].concat(actions) } @@ -324,8 +328,8 @@ class UserListItem extends Component { intl, } = this.props; - let actions = this.getAvailableActions(); - let contents = ( + const actions = this.getAvailableActions(); + const contents = ( <div className={styles.userItemContents}> <UserAvatar user={user} /> {this.renderUserName()} @@ -337,16 +341,17 @@ class UserListItem extends Component { return contents; } - const { dropdownOffset, dropdownDirection, dropdownVisible, } = this.state; + const { dropdownOffset, dropdownDirection, dropdownVisible } = this.state; return ( <Dropdown - ref="dropdown" + ref={(ref) => { this.dropdown = ref; }} isOpen={this.state.isActionsOpen} onShow={this.onActionsShow} onHide={this.onActionsHide} className={styles.dropdown} - autoFocus={false}> + autoFocus={false} + > <DropdownTrigger> {contents} </DropdownTrigger> @@ -356,16 +361,18 @@ class UserListItem extends Component { [dropdownDirection]: `${dropdownOffset}px`, }} className={styles.dropdownContent} - placement={`right ${dropdownDirection}`}> + placement={`right ${dropdownDirection}`} + > <DropdownList> { [ (<DropdownListTitle - description={intl.formatMessage(messages.menuTitleContext)} - key={_.uniqueId('dropdown-list-title')}> - {user.name} - </DropdownListTitle>), + description={intl.formatMessage(messages.menuTitleContext)} + key={_.uniqueId('dropdown-list-title')} + > + {user.name} + </DropdownListTitle>), (<DropdownListSeparator key={_.uniqueId('action-separator')} />), ].concat(actions) } @@ -402,7 +409,7 @@ class UserListItem extends Component { const { disablePrivateChat, disableCam, disableMic, - disablePublicChat, } = meeting.roomLockSettings; + disablePublicChat } = meeting.roomLockSettings; return ( <div className={styles.userName}> @@ -415,10 +422,10 @@ class UserListItem extends Component { || disableCam || disableMic || disablePublicChat)) ? - <span> {(user.isCurrent ? ' | ' : null)} - <Icon iconName='lock' /> - {intl.formatMessage(messages.locked)} - </span> : null} + <span> {(user.isCurrent ? ' | ' : null)} + <Icon iconName="lock" /> + {intl.formatMessage(messages.locked)} + </span> : null} </span> </div> ); @@ -444,7 +451,7 @@ class UserListItem extends Component { audioChatIcon = !user.isMuted ? 'unmute' : 'mute'; } - let audioIconClassnames = {}; + const audioIconClassnames = {}; audioIconClassnames[styles.userIconsContainer] = true; audioIconClassnames[styles.userIconGlowing] = user.isTalking; @@ -459,7 +466,7 @@ class UserListItem extends Component { { user.isSharingWebcam ? <span className={styles.userIconsContainer}> - <Icon iconName='video' /> + <Icon iconName="video" /> </span> : null } @@ -481,12 +488,13 @@ class UserListItem extends Component { } = this.props; const userAction = ( - <DropdownListItem key={_.uniqueId('action-item-')} + <DropdownListItem + key={_.uniqueId('action-item-')} icon={action.icon} label={action.label} defaultMessage={action.label} onClick={action.handler.bind(this, ...parameters)} - placeInTabOrder={true} + placeInTabOrder /> ); diff --git a/bigbluebutton-html5/imports/ui/components/video-dock/component.jsx b/bigbluebutton-html5/imports/ui/components/video-dock/component.jsx index 67be55d5da062c245fe5e1eb9f46c6ad9a1884c9..6c4a06f36634684dc97b2c7b7fdd9b11016fc647 100755 --- a/bigbluebutton-html5/imports/ui/components/video-dock/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/video-dock/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import styles from './styles.scss'; import { FormattedMessage, FormattedDate } from 'react-intl'; import DeskshareContainer from '/imports/ui/components/deskshare/container.jsx'; diff --git a/bigbluebutton-html5/imports/ui/components/video-dock/container.jsx b/bigbluebutton-html5/imports/ui/components/video-dock/container.jsx index fb2fb5f6b97c6f8bda439dd9d8990a594af5c7f0..dda70f9db6198bb8f62dcc701b5dea018a262d65 100755 --- a/bigbluebutton-html5/imports/ui/components/video-dock/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/video-dock/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import VideoDock from './component'; @@ -18,6 +19,6 @@ class VideoDockContainer extends Component { } export default createContainer(() => { - let data = {}; + const data = {}; return data; }, VideoDockContainer); diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shape-factory/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/shape-factory/component.jsx index 0645ef933900f61dbb5dde7b2903c1149c2c4af1..5ad2e3a752e09ead82204642a748c3318b0b5aa4 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shape-factory/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shape-factory/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import Ellipse from '../shapes/ellipse/component.jsx'; import Line from '../shapes/line/component.jsx'; import Poll from '../shapes/poll/component.jsx'; @@ -13,7 +14,7 @@ export default class WhiteboardShapeModel extends React.Component { } render() { - let Component = this.props.shapes[this.props.shape.shape_type]; + const Component = this.props.shapes[this.props.shape.shape_type]; if (Component != null) { return ( <Component @@ -24,11 +25,10 @@ export default class WhiteboardShapeModel extends React.Component { slideHeight={this.props.slideHeight} /> ); - } else { - return ( - <g></g> - ); } + return ( + <g /> + ); } } diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/component.jsx index e9fe7890104dcc30d93029b56225d9921cdff699..34ee4b75e0021368aaaec11ac6a80f5217377903 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/component.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import WhiteboardShapeModel from '../shape-factory/component'; const propTypes = { @@ -6,8 +7,8 @@ const propTypes = { width: PropTypes.number.isRequired, height: PropTypes.number.isRequired, - //array of shapes, optional - shapes: React.PropTypes.array, + // array of shapes, optional + shapes: PropTypes.array, }; export default class ShapeGroup extends React.Component { @@ -24,13 +25,13 @@ export default class ShapeGroup extends React.Component { return ( <g> - {shapes ? shapes.map((shape) => - <WhiteboardShapeModel + {shapes ? shapes.map(shape => + (<WhiteboardShapeModel shape={shape.shape} key={shape.shape.id} - slideWidth = {width} - slideHeight = {height} - /> + slideWidth={width} + slideHeight={height} + />), ) : null } </g> diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/container.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/container.jsx index dc3d226c139e6d5160ed547df23c854647978b68..c6a17ee6f4d9b303553f0b62d8ad71394dfdd9af 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/container.jsx @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { createContainer } from 'meteor/react-meteor-data'; import ShapeGroupService from './service'; @@ -12,8 +13,8 @@ const propTypes = { width: PropTypes.number.isRequired, height: PropTypes.number.isRequired, - //array of shapes, optional - shapes: React.PropTypes.array, + // array of shapes, optional + shapes: PropTypes.array, }; class ShapeGroupContainer extends React.Component { diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/service.js b/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/service.js index bc22b525c6792132060cd370721bdcbbc018de4c..83a5480a0f0922af8cd476d3590a493bfe051306 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/service.js +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shape-group/service.js @@ -1,13 +1,12 @@ import Shapes from '/imports/api/shapes'; const getCurrentShapes = (whiteboardId) => { - if (!whiteboardId) { return null; } return Shapes.find({ - whiteboardId: whiteboardId, + whiteboardId, }).fetch(); }; diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/ellipse/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/ellipse/component.jsx index cf6b623a85a62eddb6a28e0cedc654f1ebc3b873..00c189c732b6eee8a21836714d6149c4732c6ef2 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/ellipse/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/ellipse/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import ShapeHelpers from '../helpers.js'; export default class EllipseDrawComponent extends React.Component { @@ -7,33 +8,33 @@ export default class EllipseDrawComponent extends React.Component { } getCoordinates() { - //x1 and y1 - coordinates of the ellipse's top left corner - //x2 and y2 - coordinates of the ellipse's bottom right corner + // x1 and y1 - coordinates of the ellipse's top left corner + // x2 and y2 - coordinates of the ellipse's bottom right corner const x1 = this.props.shape.points[0]; const y1 = this.props.shape.points[1]; const x2 = this.props.shape.points[2]; const y2 = this.props.shape.points[3]; - //rx - horizontal radius - //ry - vertical radius - //cx and cy - coordinates of the ellipse's center + // rx - horizontal radius + // ry - vertical radius + // cx and cy - coordinates of the ellipse's center let rx = (x2 - x1) / 2; let ry = (y2 - y1) / 2; - let cx = (rx + x1) * this.props.slideWidth / 100; - let cy = (ry + y1) * this.props.slideHeight / 100; + const cx = (rx + x1) * this.props.slideWidth / 100; + const cy = (ry + y1) * this.props.slideHeight / 100; rx = Math.abs(rx / 100 * this.props.slideWidth); ry = Math.abs(ry / 100 * this.props.slideHeight); return { - cx: cx, - cy: cy, - rx: rx, - ry: ry, + cx, + cy, + rx, + ry, }; } render() { - let results = this.getCoordinates(); + const results = this.getCoordinates(); return ( <ellipse cx={results.cx} @@ -44,8 +45,7 @@ export default class EllipseDrawComponent extends React.Component { stroke={ShapeHelpers.formatColor(this.props.shape.color)} strokeWidth={this.props.shape.thickness} style={this.props.style} - > - </ellipse> + /> ); } } diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/helpers.js b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/helpers.js index b1be8de592baa220ef427c720fce99ddc80c2e94..3f9323264a790a298bea4a2011fc68d784b78be9 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/helpers.js +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/helpers.js @@ -2,12 +2,12 @@ const zoomStroke = (thickness, widthRatio, heightRatio) => { let ratio; - ratio = (widthRatio + heightRatio) / 2; + ratio = (widthRatio + heightRatio) / 2; return thickness * 100 / ratio; }; const formatColor = (color) => { - //let color = this.props.shape.shape.shape.color; + // let color = this.props.shape.shape.shape.color; if (!color) { color = '0'; // default value } diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/line/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/line/component.jsx index a52c649ad3b88acb84516c0c5fb9e862efbdb8fe..cc8bb21ebf28181f47c07b237fda9ba7ae78a37f 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/line/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/line/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import ShapeHelpers from '../helpers.js'; export default class LineDrawComponent extends React.Component { @@ -7,21 +8,21 @@ export default class LineDrawComponent extends React.Component { } getCoordinates() { - let x1 = this.props.shape.points[0] / 100 * this.props.slideWidth; - let y1 = this.props.shape.points[1] / 100 * this.props.slideHeight; - let x2 = this.props.shape.points[2] / 100 * this.props.slideWidth; - let y2 = this.props.shape.points[3] / 100 * this.props.slideHeight; + const x1 = this.props.shape.points[0] / 100 * this.props.slideWidth; + const y1 = this.props.shape.points[1] / 100 * this.props.slideHeight; + const x2 = this.props.shape.points[2] / 100 * this.props.slideWidth; + const y2 = this.props.shape.points[3] / 100 * this.props.slideHeight; return { - x1: x1, - y1: y1, - x2: x2, - y2: y2, + x1, + y1, + x2, + y2, }; } render() { - let results = this.getCoordinates(); + const results = this.getCoordinates(); return ( <line x1={results.x1} diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/pencil/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/pencil/component.jsx index ec58fdbc12a72e429dd27ac74584d45f770c99b4..3d8b850a95689c371d5ecd6efa30ccae554a4131 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/pencil/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/pencil/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import ShapeHelpers from '../helpers.js'; export default class PencilDrawComponent extends React.Component { @@ -9,13 +10,13 @@ export default class PencilDrawComponent extends React.Component { getCoordinates() { let i = 2; let path = ''; - let points = this.props.shape.points; + const points = this.props.shape.points; if (points && points.length >= 2) { - path = path + 'M' + (points[0] / 100 * this.props.slideWidth) + - ', ' + (points[1] / 100 * this.props.slideHeight); + path = `${path}M${points[0] / 100 * this.props.slideWidth + }, ${points[1] / 100 * this.props.slideHeight}`; while (i < points.length) { - path = path + ' L' + (points[i] / 100 * this.props.slideWidth) + - ', ' + (points[i + 1] / 100 * this.props.slideHeight); + path = `${path} L${points[i] / 100 * this.props.slideWidth + }, ${points[i + 1] / 100 * this.props.slideHeight}`; i += 2; } @@ -24,7 +25,7 @@ export default class PencilDrawComponent extends React.Component { } render() { - let path = this.getCoordinates(); + const path = this.getCoordinates(); return ( <path fill="none" @@ -33,8 +34,8 @@ export default class PencilDrawComponent extends React.Component { strokeWidth={this.props.shape.thickness} strokeLinejoin="round" strokeLinecap="round" - style={this.props.style}> - </path> + style={this.props.style} + /> ); } } diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/poll/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/poll/component.jsx index d5490c1e6dade5879653494fd0c11503322e058e..c4ef2bac5bae468422c78a2d4f2fcb453afc89d8 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/poll/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/poll/component.jsx @@ -1,5 +1,6 @@ -import React, { PropTypes } from 'react'; -import ReactDOM from 'react-dom'; +import React from 'react'; +import PropTypes from 'prop-types'; +import { findDOMNode } from 'react-dom'; import ShapeHelpers from '../helpers.js'; export default class PollDrawComponent extends React.Component { @@ -7,10 +8,10 @@ export default class PollDrawComponent extends React.Component { super(props); this.state = { - //flag indicating whether we need to continue calculating the sizes or display the shape + // flag indicating whether we need to continue calculating the sizes or display the shape prepareToDisplay: true, - //outer (white) rectangle's coordinates and sizes (calculated in componentWillMount) + // outer (white) rectangle's coordinates and sizes (calculated in componentWillMount) outerRect: { x: 0, y: 0, @@ -18,7 +19,7 @@ export default class PollDrawComponent extends React.Component { height: 0, }, - //inner rectangle's coordinates and sizes + // inner rectangle's coordinates and sizes innerRect: { x: 0, y: 0, @@ -28,22 +29,22 @@ export default class PollDrawComponent extends React.Component { thickness: 0, backgroundColor: '#ffffff', - //max line sizes + // max line sizes maxLineWidth: 0, maxLineHeight: 0, - //max widths of the keys (left) and percent (right) strings + // max widths of the keys (left) and percent (right) strings maxLeftWidth: 0, maxRightWidth: 0, - //these parameters are used in calculations before and while displaying the final result + // these parameters are used in calculations before and while displaying the final result votesTotal: 0, maxNumVotes: 0, textArray: [], maxDigitWidth: 0, maxDigitHeight: 0, - //start value used for font-size calculations + // start value used for font-size calculations calcFontSize: 50, currentLine: 0, lineToMeasure: [], @@ -52,31 +53,31 @@ export default class PollDrawComponent extends React.Component { } componentWillMount() { - //in this part we retrieve the props and perform initial calculations for the state - //calculating only the parts which have to be done just once and don't require - //rendering / rerendering the text objects - - //x1 and y1 - coordinates of the top left corner of the shape - //initial width and height are the width and height of the shape - //all the points are given as percentages of the slide - let x1 = this.props.shape.points[0]; - let y1 = this.props.shape.points[1]; - let initialWidth = this.props.shape.points[2]; - let initialHeight = this.props.shape.points[3]; - - //calculating the data for the outer rectangle - //0.001 is needed to accomodate bottom and right borders of the shape - let x = x1 / 100 * this.props.slideWidth; - let y = y1 / 100 * this.props.slideHeight; - let width = (initialWidth - 0.001) / 100 * this.props.slideWidth; - let height = (initialHeight - 0.001) / 100 * this.props.slideHeight; + // in this part we retrieve the props and perform initial calculations for the state + // calculating only the parts which have to be done just once and don't require + // rendering / rerendering the text objects + + // x1 and y1 - coordinates of the top left corner of the shape + // initial width and height are the width and height of the shape + // all the points are given as percentages of the slide + const x1 = this.props.shape.points[0]; + const y1 = this.props.shape.points[1]; + const initialWidth = this.props.shape.points[2]; + const initialHeight = this.props.shape.points[3]; + + // calculating the data for the outer rectangle + // 0.001 is needed to accomodate bottom and right borders of the shape + const x = x1 / 100 * this.props.slideWidth; + const y = y1 / 100 * this.props.slideHeight; + const width = (initialWidth - 0.001) / 100 * this.props.slideWidth; + const height = (initialHeight - 0.001) / 100 * this.props.slideHeight; let votesTotal = 0; let maxNumVotes = 0; - let textArray = []; + const textArray = []; - //counting the total number of votes, finding the biggest number of votes - this.props.shape.result.reduce(function (previousValue, currentValue, currentIndex, array) { + // counting the total number of votes, finding the biggest number of votes + this.props.shape.result.reduce((previousValue, currentValue, currentIndex, array) => { votesTotal = previousValue + currentValue.num_votes; if (maxNumVotes < currentValue.num_votes) { maxNumVotes = currentValue.num_votes; @@ -85,47 +86,47 @@ export default class PollDrawComponent extends React.Component { return votesTotal; }, 0); - //filling the textArray with data to display - //adding value of the iterator to each line needed to create unique - //keys while rendering at the end - let arrayLength = this.props.shape.result.length; + // filling the textArray with data to display + // adding value of the iterator to each line needed to create unique + // keys while rendering at the end + const arrayLength = this.props.shape.result.length; for (let i = 0; i < arrayLength; ++i) { - let _tempArray = []; - let _result = this.props.shape.result[i]; - _tempArray.push(_result.key, _result.num_votes + ''); + const _tempArray = []; + const _result = this.props.shape.result[i]; + _tempArray.push(_result.key, `${_result.num_votes}`); if (votesTotal === 0) { _tempArray.push('0%'); _tempArray.push(i); } else { percResult = _result.num_votes / votesTotal * 100; - _tempArray.push(Math.round(percResult) + '%'); + _tempArray.push(`${Math.round(percResult)}%`); _tempArray.push(i); } textArray.push(_tempArray); } - //calculating the data for the inner rectangle - let innerWidth = width * 0.95; - let innerHeight = height - width * 0.05; - let innerX = x + width * 0.025; - let innerY = y + width * 0.025; - let thickness = (width - innerWidth) / 10; + // calculating the data for the inner rectangle + const innerWidth = width * 0.95; + const innerHeight = height - width * 0.05; + const innerX = x + width * 0.025; + const innerY = y + width * 0.025; + const thickness = (width - innerWidth) / 10; - //calculating the maximum possible width and height of the each line - //25% of the height goes to the padding - let maxLineWidth = innerWidth / 3; - let maxLineHeight = innerHeight * 0.75 / textArray.length; + // calculating the maximum possible width and height of the each line + // 25% of the height goes to the padding + const maxLineWidth = innerWidth / 3; + const maxLineHeight = innerHeight * 0.75 / textArray.length; - let lineToMeasure = textArray[0]; + const lineToMeasure = textArray[0]; - //saving all the initial calculations in the state + // saving all the initial calculations in the state this.setState({ outerRect: { - x: x, - y: y, - width: width, - height: height, + x, + y, + width, + height, }, innerRect: { x: innerX, @@ -133,13 +134,13 @@ export default class PollDrawComponent extends React.Component { width: innerWidth, height: innerHeight, }, - thickness: thickness, - votesTotal: votesTotal, - maxNumVotes: maxNumVotes, - textArray: textArray, - maxLineWidth: maxLineWidth, - maxLineHeight: maxLineHeight, - lineToMeasure: lineToMeasure, + thickness, + votesTotal, + maxNumVotes, + textArray, + maxLineWidth, + maxLineHeight, + lineToMeasure, }); } @@ -154,19 +155,19 @@ export default class PollDrawComponent extends React.Component { } checkSizes() { - let maxLineWidth = this.state.maxLineWidth; + const maxLineWidth = this.state.maxLineWidth; let maxLineHeight = this.state.maxLineHeight; - //calculating the font size in this if / else block + // calculating the font size in this if / else block if (this.state.fontSizeDirection != 0) { - let key = `${this.props.shape.id}_key_${this.state.currentLine}`; - let votes = `${this.props.shape.id}_votes_${this.state.currentLine}`; - let percent = `${this.props.shape.id}_percent_${this.state.currentLine}`; - let keySizes = ReactDOM.findDOMNode(this.refs[key]).getBBox(); - let voteSizes = ReactDOM.findDOMNode(this.refs[votes]).getBBox(); - let percSizes = ReactDOM.findDOMNode(this.refs[percent]).getBBox(); - - //first check if we can still increase the font-size + const key = `${this.props.shape.id}_key_${this.state.currentLine}`; + const votes = `${this.props.shape.id}_votes_${this.state.currentLine}`; + const percent = `${this.props.shape.id}_percent_${this.state.currentLine}`; + const keySizes = findDOMNode(this[key]).getBBox(); + const voteSizes = findDOMNode(this[votes]).getBBox(); + const percSizes = findDOMNode(this[percent]).getBBox(); + + // first check if we can still increase the font-size if (this.state.fontSizeDirection == 1) { if (keySizes.width < maxLineWidth && keySizes.height < maxLineHeight && voteSizes.width < maxLineWidth && voteSizes.height < maxLineHeight && @@ -175,16 +176,14 @@ export default class PollDrawComponent extends React.Component { calcFontSize: this.state.calcFontSize + 1, }); - //we can't increase font-size anymore, start decreasing - } else { - return this.setState({ - fontSizeDirection: -1, - calcFontSize: this.state.calcFontSize - 1, - }); + // we can't increase font-size anymore, start decreasing } + return this.setState({ + fontSizeDirection: -1, + calcFontSize: this.state.calcFontSize - 1, + }); } else if (this.state.fontSizeDirection == -1) { - - //check if the font-size is still bigger than allowed + // check if the font-size is still bigger than allowed if (keySizes.width > maxLineWidth || keySizes.height > maxLineHeight || voteSizes.width > maxLineWidth || voteSizes.height > maxLineHeight || percSizes.width > maxLineWidth || percSizes.height > maxLineHeight) { @@ -192,37 +191,35 @@ export default class PollDrawComponent extends React.Component { calcFontSize: this.state.calcFontSize - 1, }); - //font size is fine for the current line, switch to the next line - //or finish with the font-size calculations if this we are at the end of the array - } else { - if (this.state.currentLine < this.state.textArray.length - 1) { - return this.setState({ - currentLine: this.state.currentLine + 1, - lineToMeasure: this.state.textArray[this.state.currentLine + 1], - }); - } else { - return this.setState({ - fontSizeDirection: 0, - currentLine: 0, - lineToMeasure: this.state.textArray[0], - }); - } + // font size is fine for the current line, switch to the next line + // or finish with the font-size calculations if this we are at the end of the array + } + if (this.state.currentLine < this.state.textArray.length - 1) { + return this.setState({ + currentLine: this.state.currentLine + 1, + lineToMeasure: this.state.textArray[this.state.currentLine + 1], + }); } + return this.setState({ + fontSizeDirection: 0, + currentLine: 0, + lineToMeasure: this.state.textArray[0], + }); } } - //next block is executed when we finally found a proper font size + // next block is executed when we finally found a proper font size - //finding the biggest width and height of the left and right strings, - //max real line height and max width value for 1 digit + // finding the biggest width and height of the left and right strings, + // max real line height and max width value for 1 digit let maxLeftWidth = 0; let maxRightWidth = 0; maxLineHeight = 0; for (let i = 0; i < this.state.textArray.length; ++i) { - let key = `${this.props.shape.id}_key_${i}`; - let percent = `${this.props.shape.id}_percent_${i}`; - let keySizes = ReactDOM.findDOMNode(this.refs[key]).getBBox(); - let percSizes = ReactDOM.findDOMNode(this.refs[percent]).getBBox(); + const key = `${this.props.shape.id}_key_${i}`; + const percent = `${this.props.shape.id}_percent_${i}`; + const keySizes = findDOMNode(this[key]).getBBox(); + const percSizes = findDOMNode(this[percent]).getBBox(); if (keySizes.width > maxLeftWidth) { maxLeftWidth = keySizes.width; @@ -241,62 +238,62 @@ export default class PollDrawComponent extends React.Component { } } - let digitRef = `${this.props.shape.id}_digit`; - let maxDigitWidth = ReactDOM.findDOMNode(this.refs[digitRef]).getBBox().width; - let maxDigitHeight = ReactDOM.findDOMNode(this.refs[digitRef]).getBBox().height; + const digitRef = `${this.props.shape.id}_digit`; + const maxDigitWidth = findDOMNode(this[digitRef]).getBBox().width; + const maxDigitHeight = findDOMNode(this[digitRef]).getBBox().height; this.setState({ - maxLeftWidth: maxLeftWidth, - maxRightWidth: maxRightWidth, - maxLineHeight: maxLineHeight, - maxDigitWidth: maxDigitWidth, - maxDigitHeight: maxDigitHeight, + maxLeftWidth, + maxRightWidth, + maxLineHeight, + maxDigitWidth, + maxDigitHeight, prepareToDisplay: false, }); } renderPoll() { - //********************************************************************************************* - //******************************************MAGIC NUMBER*************************************** - //There is no automatic vertical centering in SVG. - //To center the text element we have to move it down by the half of its height. - //But every text element has its own padding by default. The height we receive - //by calling getBBox() includes padding, but the anchor point doesn't consider it. - //This way the text element is moved down a little bit and we have to move it up a bit. + //* ******************************************************************************************** + //* *****************************************MAGIC NUMBER*************************************** + // There is no automatic vertical centering in SVG. + // To center the text element we have to move it down by the half of its height. + // But every text element has its own padding by default. The height we receive + // by calling getBBox() includes padding, but the anchor point doesn't consider it. + // This way the text element is moved down a little bit and we have to move it up a bit. // 1/6 of the maximum height of the digit seems to work fine. - //Oleksandr Zhurbenko. June 22, 2016 - let magicNumber = this.state.maxDigitHeight / 6; + // Oleksandr Zhurbenko. June 22, 2016 + const magicNumber = this.state.maxDigitHeight / 6; - //maximum height and width of the line bar - let maxBarWidth = this.state.innerRect.width * 0.9 - + // maximum height and width of the line bar + const maxBarWidth = this.state.innerRect.width * 0.9 - this.state.maxLeftWidth - this.state.maxRightWidth; - let barHeight = this.state.innerRect.height * 0.75 / this.state.textArray.length; + const barHeight = this.state.innerRect.height * 0.75 / this.state.textArray.length; - //Horizontal padding - let horizontalPadding = this.state.innerRect.width * 0.1 / 4; + // Horizontal padding + const horizontalPadding = this.state.innerRect.width * 0.1 / 4; - //Vertical padding - let verticalPadding = this.state.innerRect.height * 0.25 / (this.state.textArray.length + 1); + // Vertical padding + const verticalPadding = this.state.innerRect.height * 0.25 / (this.state.textArray.length + 1); - //Initial coordinates of the key column + // Initial coordinates of the key column let yLeft = this.state.innerRect.y + verticalPadding + barHeight / 2 - magicNumber; - let xLeft = this.state.innerRect.x + horizontalPadding + 1; + const xLeft = this.state.innerRect.x + horizontalPadding + 1; - //Initial coordinates of the line bar column - let xBar = this.state.innerRect.x + this.state.maxLeftWidth + horizontalPadding * 2; + // Initial coordinates of the line bar column + const xBar = this.state.innerRect.x + this.state.maxLeftWidth + horizontalPadding * 2; let yBar = this.state.innerRect.y + verticalPadding; - //Initial coordinates of the percentage column + // Initial coordinates of the percentage column let yRight = this.state.innerRect.y + verticalPadding + barHeight / 2 - magicNumber; - let xRight = this.state.innerRect.x + + const xRight = this.state.innerRect.x + horizontalPadding * 3 + this.state.maxLeftWidth + this.state.maxRightWidth + maxBarWidth + 1; let yNumVotes = this.state.innerRect.y + verticalPadding - magicNumber; - let extendedTextArray = []; + const extendedTextArray = []; for (let i = 0; i < this.state.textArray.length; i++) { if (this.state.maxNumVotes == 0 || this.props.shape.result[i].num_votes === 0) { barWidth = 1; @@ -304,13 +301,13 @@ export default class PollDrawComponent extends React.Component { barWidth = this.props.shape.result[i].num_votes / this.state.maxNumVotes * maxBarWidth; } - //coordinates and color of the text inside the line bar - //xNumVotesDefault and xNumVotesMovedRight are 2 different x coordinates for the text - //since if the line bar is too small then we place the number to the right of the bar - let xNumVotesDefault = this.state.innerRect.x + + // coordinates and color of the text inside the line bar + // xNumVotesDefault and xNumVotesMovedRight are 2 different x coordinates for the text + // since if the line bar is too small then we place the number to the right of the bar + const xNumVotesDefault = this.state.innerRect.x + this.state.maxLeftWidth + horizontalPadding * 2; - let xNumVotesMovedRight = xNumVotesDefault + + const xNumVotesMovedRight = xNumVotesDefault + barWidth / 2 + this.state.maxDigitWidth / 2; @@ -325,32 +322,32 @@ export default class PollDrawComponent extends React.Component { } extendedTextArray[i] = - { - key: `${this.props.shape.id}_${this.state.textArray[i][3]}`, - keyColumn: { - keyString: this.state.textArray[i][0], - xLeft: xLeft, - yLeft: yLeft, - }, - barColumn: { - votesString: this.state.textArray[i][1], - xBar: xBar, - yBar: yBar, - barWidth: barWidth, - barHeight: barHeight, - yNumVotes: yNumVotes, - xNumVotes: xNumVotes, - color: color, - numVotes: this.props.shape.result[i].num_votes, - }, - percentColumn: { - xRight: xRight, - yRight: yRight, - percentString: this.state.textArray[i][2], - }, - }; - - //changing the Y coordinate for all the objects + { + key: `${this.props.shape.id}_${this.state.textArray[i][3]}`, + keyColumn: { + keyString: this.state.textArray[i][0], + xLeft, + yLeft, + }, + barColumn: { + votesString: this.state.textArray[i][1], + xBar, + yBar, + barWidth, + barHeight, + yNumVotes, + xNumVotes, + color, + numVotes: this.props.shape.result[i].num_votes, + }, + percentColumn: { + xRight, + yRight, + percentString: this.state.textArray[i][2], + }, + }; + + // changing the Y coordinate for all the objects yBar = yBar + barHeight + verticalPadding; yLeft = yLeft + barHeight + verticalPadding; yRight = yRight + barHeight + verticalPadding; @@ -384,29 +381,28 @@ export default class PollDrawComponent extends React.Component { fontSize={this.state.calcFontSize} textAnchor="start" > - {extendedTextArray.map((line) => - <tspan + {extendedTextArray.map(line => + (<tspan x={line.keyColumn.xLeft} y={line.keyColumn.yLeft} dy={this.state.maxLineHeight / 2} key={`${line.key}_key`} > {line.keyColumn.keyString} - </tspan> + </tspan>), )} </text> - {extendedTextArray.map((line) => - <rect - key={`${line.key}_bar`} - x={line.barColumn.xBar} - y={line.barColumn.yBar} - width={line.barColumn.barWidth} - height={line.barColumn.barHeight} - stroke="#333333" - fill="#333333" - strokeWidth={this.state.thickness - 1} - > - </rect> + {extendedTextArray.map(line => + (<rect + key={`${line.key}_bar`} + x={line.barColumn.xBar} + y={line.barColumn.yBar} + width={line.barColumn.barWidth} + height={line.barColumn.barHeight} + stroke="#333333" + fill="#333333" + strokeWidth={this.state.thickness - 1} + />), )} <text x={this.state.innerRect.x} @@ -416,15 +412,15 @@ export default class PollDrawComponent extends React.Component { fontSize={this.state.calcFontSize} textAnchor="end" > - {extendedTextArray.map((line) => - <tspan + {extendedTextArray.map(line => + (<tspan x={line.percentColumn.xRight} y={line.percentColumn.yRight} dy={this.state.maxLineHeight / 2} key={`${line.key}_percent`} > {line.percentColumn.percentString} - </tspan> + </tspan>), )} </text> <text @@ -434,8 +430,8 @@ export default class PollDrawComponent extends React.Component { fontFamily="Arial" fontSize={this.state.calcFontSize} > - {extendedTextArray.map((line) => - <tspan + {extendedTextArray.map(line => + (<tspan x={line.barColumn.xNumVotes + line.barColumn.barWidth / 2} y={line.barColumn.yNumVotes + line.barColumn.barHeight / 2} dy={this.state.maxLineHeight / 2} @@ -443,7 +439,7 @@ export default class PollDrawComponent extends React.Component { fill={line.barColumn.color} > {line.barColumn.numVotes} - </tspan> + </tspan>), )} </text> </g> @@ -451,13 +447,13 @@ export default class PollDrawComponent extends React.Component { } renderLine(line) { - //this func just renders the strings for one line + // this func just renders the strings for one line return ( <g key={`${this.props.shape.id}_line_${line[3]}`}> <text fontFamily="Arial" fontSize={this.state.calcFontSize} - ref={`${this.props.shape.id}_key_${line[3]}`} + ref={(ref) => { this[`${this.props.shape.id}_key_${line[3]}`] = ref; }} > <tspan> {line[0]} @@ -466,7 +462,7 @@ export default class PollDrawComponent extends React.Component { <text fontFamily="Arial" fontSize={this.state.calcFontSize} - ref={`${this.props.shape.id}_votes_${line[3]}`} + ref={(ref) => { this[`${this.props.shape.id}_votes_${line[3]}`] = ref; }} > <tspan> {line[1]} @@ -475,7 +471,7 @@ export default class PollDrawComponent extends React.Component { <text fontFamily="Arial" fontSize={this.state.calcFontSize} - ref={`${this.props.shape.id}_percent_${line[3]}`} + ref={(ref) => { this[`${this.props.shape.id}_percent_${line[3]}`] = ref; }} > <tspan> {line[2]} @@ -486,29 +482,29 @@ export default class PollDrawComponent extends React.Component { } renderTestStrings() { - //check whether we need to render just one line (which means we still calculating the font-size) - //or if we finished with the font-size and we need to render all the strings in order to - //determine the maxHeight, maxWidth and maxDigitWidth + // check whether we need to render just one line (which means we still calculating the font-size) + // or if we finished with the font-size and we need to render all the strings in order to + // determine the maxHeight, maxWidth and maxDigitWidth if (this.state.fontSizeDirection != 0) { return this.renderLine(this.state.lineToMeasure); - } else { - return ( - <g> - {this.state.textArray.map((line) => - this.renderLine(line) - )} - <text - fontFamily="Arial" - fontSize={this.state.calcFontSize} - ref={`${this.props.shape.id}_digit`} - > - <tspan> - 0 - </tspan> - </text> - </g> - ); } + return ( + <g> + {this.state.textArray.map(line => + this.renderLine(line), + ) + } + <text + fontFamily="Arial" + fontSize={this.state.calcFontSize} + ref={(ref) => { this[`${this.props.shape.id}_digit`] = ref; }} + > + <tspan> + 0 + </tspan> + </text> + </g> + ); } render() { diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/rectangle/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/rectangle/component.jsx index 76c3d9363426f5eeaf78bdfff11263262ea986f9..1f96140c5122ee52f9a7e79cecbc8f1c763733ad 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/rectangle/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/rectangle/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import ShapeHelpers from '../helpers.js'; export default class RectangleDrawComponent extends React.Component { @@ -7,40 +8,40 @@ export default class RectangleDrawComponent extends React.Component { } getCoordinates() { - //x1 and y1 are the coordinates of the top left corner of the shape - //x2 and y2 are the coordinates of the bottom right corner of the shape + // x1 and y1 are the coordinates of the top left corner of the shape + // x2 and y2 are the coordinates of the bottom right corner of the shape let x1 = this.props.shape.points[0]; let y1 = this.props.shape.points[1]; let x2 = this.props.shape.points[2]; let y2 = this.props.shape.points[3]; - //Presenter pulled rectangle to the left + // Presenter pulled rectangle to the left if (x2 < x1) { x1 = this.props.shape.points[2]; x2 = this.props.shape.points[0]; } - //Presenter pulled Rectangle to the top + // Presenter pulled Rectangle to the top if (y2 < y1) { y1 = this.props.shape.points[3]; y2 = this.props.shape.points[1]; } - let x = x1 / 100 * this.props.slideWidth; - let y = y1 / 100 * this.props.slideHeight; - let width = (x2 - x1) / 100 * this.props.slideWidth; - let height = (y2 - y1) / 100 * this.props.slideHeight; + const x = x1 / 100 * this.props.slideWidth; + const y = y1 / 100 * this.props.slideHeight; + const width = (x2 - x1) / 100 * this.props.slideWidth; + const height = (y2 - y1) / 100 * this.props.slideHeight; return { - x: x, - y: y, - width: width, - height: height, + x, + y, + width, + height, }; } render() { - let results = this.getCoordinates(); + const results = this.getCoordinates(); return ( <rect x={results.x} @@ -53,8 +54,7 @@ export default class RectangleDrawComponent extends React.Component { stroke={ShapeHelpers.formatColor(this.props.shape.color)} strokeWidth={this.props.shape.thickness} style={this.props.style} - > - </rect> + /> ); } } diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/text/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/text/component.jsx index fb581a43729d7e848d05742dcf6a2e297702adb3..24618070892b8a75ff42af5f1b3c5d9e562d68e9 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/text/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/text/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import ShapeHelpers from '../helpers.js'; export default class TextDrawComponent extends React.Component { @@ -7,29 +8,29 @@ export default class TextDrawComponent extends React.Component { } getCoordinates() { - let x = this.props.shape.x / 100 * this.props.slideWidth; - let y = this.props.shape.y / 100 * this.props.slideHeight; - let width = this.props.shape.textBoxWidth / 100 * this.props.slideWidth; - let height = this.props.shape.textBoxHeight / 100 * this.props.slideHeight; - let fontColor = ShapeHelpers.formatColor(this.props.shape.fontColor); - let fontSize = this.props.shape.fontSize; - let calcedFontSize = this.props.shape.calcedFontSize / 100 * this.props.slideHeight; - let text = this.props.shape.text; + const x = this.props.shape.x / 100 * this.props.slideWidth; + const y = this.props.shape.y / 100 * this.props.slideHeight; + const width = this.props.shape.textBoxWidth / 100 * this.props.slideWidth; + const height = this.props.shape.textBoxHeight / 100 * this.props.slideHeight; + const fontColor = ShapeHelpers.formatColor(this.props.shape.fontColor); + const fontSize = this.props.shape.fontSize; + const calcedFontSize = this.props.shape.calcedFontSize / 100 * this.props.slideHeight; + const text = this.props.shape.text; return { - x: x, - y: y, - text: text, - width: width, - height: height, - fontSize: fontSize, - fontColor: fontColor, - calcedFontSize: calcedFontSize, + x, + y, + text, + width, + height, + fontSize, + fontColor, + calcedFontSize, }; } getStyles(results) { - let styles = { + const styles = { WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)', pointerEvents: 'none', fontStyle: 'normal', @@ -50,34 +51,34 @@ export default class TextDrawComponent extends React.Component { } render() { - let results = this.getCoordinates(); - let styles = this.getStyles(results); + const results = this.getCoordinates(); + const styles = this.getStyles(results); return ( - <g> - <clipPath id="c1"> - <rect + <g> + <clipPath id="c1"> + <rect + x={results.x} + y={results.y} + width={results.width} + height={results.height} + fill="purple" + strokeWidth="2" + /> + </clipPath> + + <foreignObject + clipPath="url(#c1)" x={results.x} y={results.y} width={results.width} height={results.height} - fill="purple" - strokeWidth="2" - /> - </clipPath> - - <foreignObject - clipPath="url(#c1)" - x={results.x} - y={results.y} - width={results.width} - height={results.height} - > - <p style={styles}> - {results.text} - </p> - </foreignObject> - </g> + > + <p style={styles}> + {results.text} + </p> + </foreignObject> + </g> ); } } diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/triangle/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/triangle/component.jsx index e22c27cbb638e2b54f54d76da281536c4f2d771d..a2f11cda2f35f3fb9e8de35a3baea9a61cdb9937 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/triangle/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/shapes/triangle/component.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import ShapeHelpers from '../helpers.js'; export default class TriangleDrawComponent extends React.Component { @@ -9,28 +10,28 @@ export default class TriangleDrawComponent extends React.Component { getCoordinates() { let path = ''; - //points[0] and points[1] are x and y coordinates of the top left corner of the shape obj - //points[2] and points[3] are x and y coordinates of the bottom right corner of the shape obj - let xBottomLeft = this.props.shape.points[0]; - let yBottomLeft = this.props.shape.points[3]; - let xBottomRight = this.props.shape.points[2]; - let yBottomRight = this.props.shape.points[3]; - let xTop = ((xBottomRight - xBottomLeft) / 2) + xBottomLeft; - let yTop = this.props.shape.points[1]; + // points[0] and points[1] are x and y coordinates of the top left corner of the shape obj + // points[2] and points[3] are x and y coordinates of the bottom right corner of the shape obj + const xBottomLeft = this.props.shape.points[0]; + const yBottomLeft = this.props.shape.points[3]; + const xBottomRight = this.props.shape.points[2]; + const yBottomRight = this.props.shape.points[3]; + const xTop = ((xBottomRight - xBottomLeft) / 2) + xBottomLeft; + const yTop = this.props.shape.points[1]; - path = path + 'M' + (xTop / 100 * this.props.slideWidth) + - ',' + (yTop / 100 * this.props.slideHeight) + - ',' + (xBottomLeft / 100 * this.props.slideWidth) + - ',' + (yBottomLeft / 100 * this.props.slideHeight) + - ',' + (xBottomRight / 100 * this.props.slideWidth) + - ',' + (yBottomRight / 100 * this.props.slideHeight) + - 'Z'; + path = `${path}M${xTop / 100 * this.props.slideWidth + },${yTop / 100 * this.props.slideHeight + },${xBottomLeft / 100 * this.props.slideWidth + },${yBottomLeft / 100 * this.props.slideHeight + },${xBottomRight / 100 * this.props.slideWidth + },${yBottomRight / 100 * this.props.slideHeight + }Z`; return path; } render() { - let path = this.getCoordinates(); + const path = this.getCoordinates(); return ( <path style={this.props.style} @@ -39,8 +40,7 @@ export default class TriangleDrawComponent extends React.Component { d={path} strokeWidth={this.props.shape.thickness} strokeLinejoin="round" - > - </path> + /> ); } } diff --git a/bigbluebutton-html5/imports/ui/services/api/index.js b/bigbluebutton-html5/imports/ui/services/api/index.js index e9b706a49521b524ee6ba93a52c3774fe6562539..e515180c21be10e0be3ad936e591cf7d1de7e54e 100755 --- a/bigbluebutton-html5/imports/ui/services/api/index.js +++ b/bigbluebutton-html5/imports/ui/services/api/index.js @@ -24,7 +24,7 @@ function makeCall(name, ...args) { resolve(result); }); }); -}; +} /** * Send the request to the server via Meteor.call and treat the error to a default callback. @@ -39,7 +39,7 @@ function call(name, ...args) { NotificationService.add({ notification: `Error while executing ${name}` }); throw e; }); -}; +} /** * Log the error to the client and to the server. @@ -70,9 +70,9 @@ function logClient() { Meteor.call('logClient', logTypeInformed ? args[0] : 'info', credentials, - outputLog + outputLog, ); -}; +} const API = { logClient, diff --git a/bigbluebutton-html5/imports/ui/services/auth/index.js b/bigbluebutton-html5/imports/ui/services/auth/index.js index e6f741608621cd08341d7c345215fd0d0d718bc5..cf8d69ccb48e908e1c3273e326eadf9372183361 100644 --- a/bigbluebutton-html5/imports/ui/services/auth/index.js +++ b/bigbluebutton-html5/imports/ui/services/auth/index.js @@ -15,7 +15,7 @@ class Auth { this._authToken = Storage.getItem('authToken'); this._loggedIn = { value: false, - tracker: new Tracker.Dependency, + tracker: new Tracker.Dependency(), }; } @@ -81,7 +81,7 @@ class Auth { this.loggedIn = false; return Promise.resolve(...arguments); - }; + } logout() { if (!this.loggedIn) { @@ -107,7 +107,7 @@ class Auth { } }); }); - }; + } authenticate(force) { if (this.loggedIn && !force) return Promise.resolve(); @@ -192,13 +192,13 @@ class Auth { } fetchLogoutUrl() { - const url = `/bigbluebutton/api/enter`; + const url = '/bigbluebutton/api/enter'; return fetch(url) .then(response => response.json()) .then(data => Promise.resolve(data.response.logoutURL)); } -}; +} -let AuthSingleton = new Auth(); +const AuthSingleton = new Auth(); export default AuthSingleton; diff --git a/bigbluebutton-html5/imports/ui/services/notification/index.js b/bigbluebutton-html5/imports/ui/services/notification/index.js index eb8f5534e89efe0bdfcc803d60a169dc60dc02b7..e2fc226ce493339909f6bf493b7099ad4fd9d7b0 100644 --- a/bigbluebutton-html5/imports/ui/services/notification/index.js +++ b/bigbluebutton-html5/imports/ui/services/notification/index.js @@ -1,6 +1,6 @@ import { check } from 'meteor/check'; -let collection = new Mongo.Collection(null); +const collection = new Mongo.Collection(null); function findById(notificationId) { check(notificationId, String); @@ -17,7 +17,7 @@ function remove(notificationId) { collection.remove({ notificationId }); } -const NotificationCollection = { findById, add, remove, }; +const NotificationCollection = { findById, add, remove }; export default NotificationCollection; diff --git a/bigbluebutton-html5/imports/ui/services/notification/notificationService.js b/bigbluebutton-html5/imports/ui/services/notification/notificationService.js index 09861c62ec26a894a6a3cb7d247e97008b20778f..85b8c2243e685f861d352d501440f4109cfb895e 100644 --- a/bigbluebutton-html5/imports/ui/services/notification/notificationService.js +++ b/bigbluebutton-html5/imports/ui/services/notification/notificationService.js @@ -6,36 +6,36 @@ class NotificationService { * Database to be transacted * @param {Object} database */ - constructor(database) { - this.database = database; - } + constructor(database) { + this.database = database; + } /** * @param {string} notificationID */ - get(notificationID) { - this.database.findById(notificationID); - } + get(notificationID) { + this.database.findById(notificationID); + } /** * @param {Object} notification */ - add(notification) { - this.database.add(notification); - } + add(notification) { + this.database.add(notification); + } /** * @param {string} notificationID */ - remove(notificationID) { - this.database.remove(notificationID); - } + remove(notificationID) { + this.database.remove(notificationID); + } } -let NotificationServiceSingleton = new NotificationService(db); +const NotificationServiceSingleton = new NotificationService(db); export { - NotificationService + NotificationService, }; export default NotificationServiceSingleton; diff --git a/bigbluebutton-html5/imports/ui/services/settings/index.js b/bigbluebutton-html5/imports/ui/services/settings/index.js index 05d3a9a4300bed8fd1c93ebd56ce67174d97ceb0..2e1303c47bb785bfbe8b4f83f33c13e69d21c9e1 100644 --- a/bigbluebutton-html5/imports/ui/services/settings/index.js +++ b/bigbluebutton-html5/imports/ui/services/settings/index.js @@ -11,10 +11,10 @@ const SETTINGS = [ class Settings { constructor(defaultValues = {}) { - SETTINGS.forEach(p => { + SETTINGS.forEach((p) => { const privateProp = `_${p}`; this[privateProp] = { - tracker: new Tracker.Dependency, + tracker: new Tracker.Dependency(), value: undefined, }; @@ -24,7 +24,7 @@ class Settings { return this[privateProp].value; }, - set: v => { + set: (v) => { this[privateProp].value = v; this[privateProp].tracker.changed(); }, @@ -36,16 +36,16 @@ class Settings { setDefault(defaultValues) { const savedSettings = {}; - SETTINGS.forEach(s => { + SETTINGS.forEach((s) => { savedSettings[s] = Storage.getItem(`settings_${s}`); }); - Object.keys(defaultValues).forEach(key => { + Object.keys(defaultValues).forEach((key) => { this[key] = _.extend(defaultValues[key], savedSettings[key]); }); this.save(); - }; + } save() { Object.keys(this).forEach(k => Storage.setItem(`settings${k}`, this[k].value)); diff --git a/bigbluebutton-html5/imports/ui/services/storage/local.js b/bigbluebutton-html5/imports/ui/services/storage/local.js index bab2c5afc9fa4d014d1d98c455e82f2771d5000d..efcdc266435145451cf8372a008480905abe05ce 100644 --- a/bigbluebutton-html5/imports/ui/services/storage/local.js +++ b/bigbluebutton-html5/imports/ui/services/storage/local.js @@ -1,5 +1,5 @@ import ReactiveStorage from './reactive'; -let _singleton = new ReactiveStorage(window.localStorage, 'BBB_'); +const _singleton = new ReactiveStorage(window.localStorage, 'BBB_'); export default _singleton; diff --git a/bigbluebutton-html5/imports/ui/services/storage/reactive.js b/bigbluebutton-html5/imports/ui/services/storage/reactive.js index 2d2174c3bf4e3104104f6d36517cf85816162b62..3155081e2118feadc047071113596d26c89d1446 100644 --- a/bigbluebutton-html5/imports/ui/services/storage/reactive.js +++ b/bigbluebutton-html5/imports/ui/services/storage/reactive.js @@ -6,7 +6,7 @@ import { EJSON } from 'meteor/ejson'; export default class StorageTracker { constructor(storage, prefix = '') { - if (!storage instanceof Storage) { + if (!(storage instanceof Storage)) { throw `Expecting a instanceof Storage recieve a '${storage.constructor.name}' instance`; } @@ -17,7 +17,7 @@ export default class StorageTracker { _ensureDeps(key) { if (!this._trackers[key]) { - this._trackers[key] = new Tracker.Dependency; + this._trackers[key] = new Tracker.Dependency(); } } @@ -31,7 +31,7 @@ export default class StorageTracker { } getItem(key) { - let prefixedKey = this._prefixedKey(key); + const prefixedKey = this._prefixedKey(key); this._ensureDeps(prefixedKey); this._trackers[prefixedKey].depend(); @@ -47,7 +47,7 @@ export default class StorageTracker { } setItem(key, value) { - let prefixedKey = this._prefixedKey(key); + const prefixedKey = this._prefixedKey(key); this._ensureDeps(prefixedKey); // let currentValue = this.getItem(prefixedKey); @@ -65,15 +65,15 @@ export default class StorageTracker { } removeItem(key) { - let prefixedKey = this._prefixedKey(key); + const prefixedKey = this._prefixedKey(key); this._storage.removeItem(prefixedKey); this._trackers[prefixedKey].changed(); delete this._trackers[prefixedKey]; } clear() { - Object.keys(this._trackers).forEach(key => { + Object.keys(this._trackers).forEach((key) => { this.removeItem(key); }); } -}; +} diff --git a/bigbluebutton-html5/imports/ui/services/storage/session.js b/bigbluebutton-html5/imports/ui/services/storage/session.js index c3bf0b2e5d5148e89e40564b61a1f6ed920169e4..ade20a01154dff9d231d6cf6b20b4e5e8cce9fa5 100644 --- a/bigbluebutton-html5/imports/ui/services/storage/session.js +++ b/bigbluebutton-html5/imports/ui/services/storage/session.js @@ -1,5 +1,5 @@ import ReactiveStorage from './reactive'; -let _singleton = new ReactiveStorage(window.sessionStorage, 'BBB_'); +const _singleton = new ReactiveStorage(window.sessionStorage, 'BBB_'); export default _singleton; diff --git a/bigbluebutton-html5/imports/ui/services/unread-messages/index.js b/bigbluebutton-html5/imports/ui/services/unread-messages/index.js index c4b00a9532f654f2fed2188aa39d575daf443fd5..88d4d70082773cc8bae56cfbba00a5c881c7298b 100755 --- a/bigbluebutton-html5/imports/ui/services/unread-messages/index.js +++ b/bigbluebutton-html5/imports/ui/services/unread-messages/index.js @@ -10,7 +10,7 @@ const STORAGE_KEY = CHAT_CONFIG.storage_key; class UnreadMessagesTracker { constructor() { - this._tracker = new Tracker.Dependency; + this._tracker = new Tracker.Dependency(); this._unreadChats = Storage.getItem('UNREAD_CHATS') || {}; } @@ -20,7 +20,7 @@ class UnreadMessagesTracker { } update(chatID, timestamp = 0) { - let currentValue = this.get(chatID); + const currentValue = this.get(chatID); if (currentValue < timestamp) { this._unreadChats[chatID] = timestamp; this._tracker.changed(); @@ -31,7 +31,7 @@ class UnreadMessagesTracker { } count(chatID) { - let filter = { + const filter = { 'message.from_time': { $gt: this.get(chatID), }, @@ -48,7 +48,7 @@ class UnreadMessagesTracker { return Chats.find(filter).count(); } -}; +} -let UnreadTrackerSingleton = new UnreadMessagesTracker(); +const UnreadTrackerSingleton = new UnreadMessagesTracker(); export default UnreadTrackerSingleton; diff --git a/bigbluebutton-html5/imports/ui/stylesheets/variables/typography.scss b/bigbluebutton-html5/imports/ui/stylesheets/variables/typography.scss index 4340296f1b03fb0796a4bbe2eacaa451d15d2b87..4cfc353281a56a4cc77a323579839637324d4ed9 100644 --- a/bigbluebutton-html5/imports/ui/stylesheets/variables/typography.scss +++ b/bigbluebutton-html5/imports/ui/stylesheets/variables/typography.scss @@ -8,7 +8,7 @@ $font-size-base: 1rem !default; $font-size-large: 1.25rem !default; $font-size-small: .875rem !default; -$line-height-base: 1.428571429 !default; // 20/14 +$line-height-base: 1.25 !default; // 20/16 $line-height-computed: floor(($font-size-base * $line-height-base)) !default; $headings-font-family: inherit !default; diff --git a/bigbluebutton-html5/imports/utils/humanizeSeconds.js b/bigbluebutton-html5/imports/utils/humanizeSeconds.js index cf88ee711ebebd0d678ab90d75758df9caa16d0d..1c81121865dc28d75ea92ad52faee5d9d30c110d 100644 --- a/bigbluebutton-html5/imports/utils/humanizeSeconds.js +++ b/bigbluebutton-html5/imports/utils/humanizeSeconds.js @@ -1,4 +1,4 @@ -const humanizeSeconds = time => { +const humanizeSeconds = (time) => { const minutes = Math.floor(time / 60); const seconds = time % 60; return [ diff --git a/bigbluebutton-html5/imports/utils/locales.js b/bigbluebutton-html5/imports/utils/locales.js index f04a1586b4ede866594723b6dd2d0a0ca7129c7c..6a66ee8be2ec5da0b7a29e4aba8e7cc24212bec0 100644 --- a/bigbluebutton-html5/imports/utils/locales.js +++ b/bigbluebutton-html5/imports/utils/locales.js @@ -1,5 +1,5 @@ const locales = [ - { + { locale: 'af_NA', name: 'Afrikaans (Namibia)', }, diff --git a/bigbluebutton-html5/imports/utils/mimeTypes.js b/bigbluebutton-html5/imports/utils/mimeTypes.js index 07bbe4b98f3ff5403877ee657e14efda474e1f25..763fe03ffd92a009724bd706f6661f88d153a47b 100644 --- a/bigbluebutton-html5/imports/utils/mimeTypes.js +++ b/bigbluebutton-html5/imports/utils/mimeTypes.js @@ -1,18 +1,18 @@ -export const XLS = 'application/vnd.ms-excel'; +export const XLS = 'application/vnd.ms-excel'; export const XLSX = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; -export const DOC = 'application/msword'; +export const DOC = 'application/msword'; export const DOCX = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; -export const PPT = 'application/vnd.ms-powerpoint'; +export const PPT = 'application/vnd.ms-powerpoint'; export const PPTX = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'; -export const ODT = 'application/vnd.oasis.opendocument.text'; -export const RTF = 'application/rtf'; -export const TXT = 'text/plain'; -export const ODS = 'application/vnd.oasis.opendocument.spreadsheet'; -export const ODP = 'application/vnd.oasis.opendocument.presentation'; -export const PDF = 'application/pdf'; +export const ODT = 'application/vnd.oasis.opendocument.text'; +export const RTF = 'application/rtf'; +export const TXT = 'text/plain'; +export const ODS = 'application/vnd.oasis.opendocument.spreadsheet'; +export const ODP = 'application/vnd.oasis.opendocument.presentation'; +export const PDF = 'application/pdf'; export const JPEG = 'image/jpeg'; -export const PNG = 'image/png'; -export const SVG = 'image/svg+xml'; +export const PNG = 'image/png'; +export const SVG = 'image/svg+xml'; export const UPLOAD_SUPORTED = [ XLS, diff --git a/bigbluebutton-html5/imports/utils/regex-weburl.js b/bigbluebutton-html5/imports/utils/regex-weburl.js index d7036c329f583b5975c7a2d463b041e4331c1c92..575f0134ca30e98f1426e56c42368221bb00e483 100755 --- a/bigbluebutton-html5/imports/utils/regex-weburl.js +++ b/bigbluebutton-html5/imports/utils/regex-weburl.js @@ -116,5 +116,5 @@ export default new RegExp( '(?::\\d{2,5})?' + // resource path - '(?:[/?#]\\S*)?', 'img' + '(?:[/?#]\\S*)?', 'img', ); diff --git a/bigbluebutton-html5/package-lock.json b/bigbluebutton-html5/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..fa7ef113bcbbfe53643de9ea887e3d9ba6dc06a9 --- /dev/null +++ b/bigbluebutton-html5/package-lock.json @@ -0,0 +1,3702 @@ +{ + "name": "bbb-html5-client", + "lockfileVersion": 1, + "dependencies": { + "abbrev": { + "version": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" + }, + "acorn": { + "version": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", + "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ=", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "align-text": { + "version": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true + }, + "alter": { + "version": "https://registry.npmjs.org/alter/-/alter-0.2.0.tgz", + "integrity": "sha1-x1iICGF1cgNKrmJICvJrHU0cs80=", + "dev": true + }, + "amdefine": { + "version": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz", + "integrity": "sha1-/RdHRwDLXMnCtwnwvp0jzjwZjDM=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", + "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=" + }, + "ansi-styles": { + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "any-promise": { + "version": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "aproba": { + "version": "https://registry.npmjs.org/aproba/-/aproba-1.0.4.tgz", + "integrity": "sha1-JxNoB3XnYUyLoYbAZdTi5S0QcsA=" + }, + "are-we-there-yet": { + "version": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz", + "integrity": "sha1-gORw6VoIR5T+GJkmLFZnxuiN4bM=" + }, + "argparse": { + "version": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", + "dev": true, + "dependencies": { + "underscore": { + "version": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "underscore.string": { + "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", + "dev": true + } + } + }, + "aria-query": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-0.5.0.tgz", + "integrity": "sha1-heMVLNjMW6sY2+1hzZxPzlT6ecM=", + "dev": true + }, + "array-differ": { + "version": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-find-index": { + "version": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.1.tgz", + "integrity": "sha1-C8Jd2slB7IpJauJY/UrBiAA+868=" + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true + }, + "array-index": { + "version": "https://registry.npmjs.org/array-index/-/array-index-1.0.0.tgz", + "integrity": "sha1-7FanSe4QPk4Ix5C5w1PfFgVbl/k=" + }, + "array-union": { + "version": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true + }, + "array-uniq": { + "version": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz", + "integrity": "sha1-UidltQw1EEkOUtfc/ghe+bqWlY8=" + }, + "asn1": { + "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + }, + "ast-traverse": { + "version": "https://registry.npmjs.org/ast-traverse/-/ast-traverse-0.1.1.tgz", + "integrity": "sha1-ac8rg4bxnc2hux4F1o/jWdiJfeY=", + "dev": true + }, + "ast-types": { + "version": "https://registry.npmjs.org/ast-types/-/ast-types-0.8.12.tgz", + "integrity": "sha1-oNkOQ1G7iHcWyD/WN+v4GK9K38w=", + "dev": true + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, + "async": { + "version": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "async-foreach": { + "version": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=" + }, + "autoprefixer": { + "version": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.1.1.tgz", + "integrity": "sha1-l7yFTH0Ll5+NZIneVHoNF/swf20=", + "dev": true + }, + "autosize": { + "version": "https://registry.npmjs.org/autosize/-/autosize-3.0.21.tgz", + "integrity": "sha1-8YL0DRd1fZeKE5pMnKQMTA5EhgM=" + }, + "aws-sign2": { + "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + }, + "aws4": { + "version": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz", + "integrity": "sha1-/efVKSRm0jDl7g9OA42d+qsI/GE=" + }, + "axobject-query": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-0.1.0.tgz", + "integrity": "sha1-YvWdvFnJ+SQnWco0mWDnov48NsA=", + "dev": true + }, + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "dependencies": { + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + } + } + }, + "babel-core": { + "version": "https://registry.npmjs.org/babel-core/-/babel-core-5.8.38.tgz", + "integrity": "sha1-H8ruedfmG3ULALjlT238nQr4ZVg=", + "dev": true, + "dependencies": { + "js-tokens": { + "version": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.1.tgz", + "integrity": "sha1-zENaXIuUrRWst5gxQPyAGCyJrq4=", + "dev": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true + }, + "path-exists": { + "version": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", + "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=", + "dev": true + }, + "repeating": { + "version": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", + "dev": true + } + } + }, + "babel-jscs": { + "version": "https://registry.npmjs.org/babel-jscs/-/babel-jscs-2.0.5.tgz", + "integrity": "sha1-CjRwRrSBRay8pW6MjtX3NrxU+dA=", + "dev": true, + "dependencies": { + "lodash.assign": { + "version": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", + "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", + "dev": true + } + } + }, + "babel-plugin-constant-folding": { + "version": "https://registry.npmjs.org/babel-plugin-constant-folding/-/babel-plugin-constant-folding-1.0.1.tgz", + "integrity": "sha1-g2HTZMmORJw2kr26Ue/whEKQqo4=", + "dev": true + }, + "babel-plugin-dead-code-elimination": { + "version": "https://registry.npmjs.org/babel-plugin-dead-code-elimination/-/babel-plugin-dead-code-elimination-1.0.2.tgz", + "integrity": "sha1-X3xFEnTc18zNv7s+C4XdKBIfD2U=", + "dev": true + }, + "babel-plugin-eval": { + "version": "https://registry.npmjs.org/babel-plugin-eval/-/babel-plugin-eval-1.0.1.tgz", + "integrity": "sha1-ovrtJc5r5preS/7CY/cBaRlZUNo=", + "dev": true + }, + "babel-plugin-inline-environment-variables": { + "version": "https://registry.npmjs.org/babel-plugin-inline-environment-variables/-/babel-plugin-inline-environment-variables-1.0.1.tgz", + "integrity": "sha1-H1jOkSB61qgmqL9kX6/mj/X+P/4=", + "dev": true + }, + "babel-plugin-jscript": { + "version": "https://registry.npmjs.org/babel-plugin-jscript/-/babel-plugin-jscript-1.0.4.tgz", + "integrity": "sha1-jzQsOCduh6R9X6CovT1etsytj8w=", + "dev": true + }, + "babel-plugin-member-expression-literals": { + "version": "https://registry.npmjs.org/babel-plugin-member-expression-literals/-/babel-plugin-member-expression-literals-1.0.1.tgz", + "integrity": "sha1-zF7bD6qNyScXDnTW0cAkQAIWJNM=", + "dev": true + }, + "babel-plugin-property-literals": { + "version": "https://registry.npmjs.org/babel-plugin-property-literals/-/babel-plugin-property-literals-1.0.1.tgz", + "integrity": "sha1-AlIwGQAZKYCxwRjv6kjOk6q4MzY=", + "dev": true + }, + "babel-plugin-proto-to-assign": { + "version": "https://registry.npmjs.org/babel-plugin-proto-to-assign/-/babel-plugin-proto-to-assign-1.0.4.tgz", + "integrity": "sha1-xJ56/QL1d7xNoF6i3wAiUM980SM=", + "dev": true, + "dependencies": { + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "babel-plugin-react-constant-elements": { + "version": "https://registry.npmjs.org/babel-plugin-react-constant-elements/-/babel-plugin-react-constant-elements-1.0.3.tgz", + "integrity": "sha1-lGc26DeEKcvDSdz/YvUcFDs041o=", + "dev": true + }, + "babel-plugin-react-display-name": { + "version": "https://registry.npmjs.org/babel-plugin-react-display-name/-/babel-plugin-react-display-name-1.0.3.tgz", + "integrity": "sha1-dU/jiSboQkpOexWrbqYTne4FFPw=", + "dev": true + }, + "babel-plugin-remove-console": { + "version": "https://registry.npmjs.org/babel-plugin-remove-console/-/babel-plugin-remove-console-1.0.1.tgz", + "integrity": "sha1-2PJFVsOgUAXUKqqv0neH9T/wE6c=", + "dev": true + }, + "babel-plugin-remove-debugger": { + "version": "https://registry.npmjs.org/babel-plugin-remove-debugger/-/babel-plugin-remove-debugger-1.0.1.tgz", + "integrity": "sha1-/S6jzWGkKK0fO5yJiC/0KT6MFMc=", + "dev": true + }, + "babel-plugin-runtime": { + "version": "https://registry.npmjs.org/babel-plugin-runtime/-/babel-plugin-runtime-1.0.7.tgz", + "integrity": "sha1-v3x9lm3Vbs1cF/ocslPJrLflSq8=", + "dev": true + }, + "babel-plugin-undeclared-variables-check": { + "version": "https://registry.npmjs.org/babel-plugin-undeclared-variables-check/-/babel-plugin-undeclared-variables-check-1.0.2.tgz", + "integrity": "sha1-XPGqU52BP/ZOmWQSkK9iCWX2Xe4=", + "dev": true + }, + "babel-plugin-undefined-to-void": { + "version": "https://registry.npmjs.org/babel-plugin-undefined-to-void/-/babel-plugin-undefined-to-void-1.1.6.tgz", + "integrity": "sha1-f1eO+LeN+uYAM4XYQXph7aBuL4E=", + "dev": true + }, + "babel-runtime": { + "version": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dependencies": { + "core-js": { + "version": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", + "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=" + } + } + }, + "babylon": { + "version": "https://registry.npmjs.org/babylon/-/babylon-5.8.38.tgz", + "integrity": "sha1-7JsSCxG/bM1Bc6GL8hfmC3mFn/0=", + "dev": true + }, + "balanced-match": { + "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + }, + "bindings": { + "version": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", + "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=" + }, + "bl": { + "version": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "dependencies": { + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=" + } + } + }, + "block-stream": { + "version": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=" + }, + "bluebird": { + "version": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz", + "integrity": "sha1-AkpVFylTCIV/FPkfEQb8O1VfRGs=", + "dev": true + }, + "body-parser": { + "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", + "dev": true, + "dependencies": { + "qs": { + "version": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", + "dev": true + } + } + }, + "boom": { + "version": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=" + }, + "brace-expansion": { + "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", + "integrity": "sha1-cZfX6qm4fmSDkOph/GbIRCdCDfk=" + }, + "breakable": { + "version": "https://registry.npmjs.org/breakable/-/breakable-1.0.0.tgz", + "integrity": "sha1-eEp5eRWjjq0nutRWtVcstLuqeME=", + "dev": true + }, + "browserslist": { + "version": "https://registry.npmjs.org/browserslist/-/browserslist-2.1.4.tgz", + "integrity": "sha1-zFJq9KExK30uBWU+VtDIq3DA4FM=", + "dev": true + }, + "buffer-shims": { + "version": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + }, + "builtin-modules": { + "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "bytes": { + "version": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelcase-keys": { + "version": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=" + }, + "caniuse-lite": { + "version": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000677.tgz", + "integrity": "sha1-QwkCM9SyxxkGV/lUVZg9lNJkuqo=", + "dev": true + }, + "capture-stack-trace": { + "version": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + }, + "caseless": { + "version": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" + }, + "center-align": { + "version": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true + }, + "chain-function": { + "version": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.0.tgz", + "integrity": "sha1-DUqzfn4Y6tC9xHuSB2QRjOWHM9w=" + }, + "chalk": { + "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=" + }, + "circular-json": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", + "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=", + "dev": true + }, + "classnames": { + "version": "https://registry.npmjs.org/classnames/-/classnames-2.2.5.tgz", + "integrity": "sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0=" + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true + }, + "cli-table": { + "version": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "dev": true + }, + "cli-width": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", + "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", + "dev": true + }, + "cliui": { + "version": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz", + "integrity": "sha1-9psZLT99keOC5Lcb3bd4eGGasMY=" + }, + "coffee-script": { + "version": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=", + "dev": true + }, + "colors": { + "version": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, + "combined-stream": { + "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=" + }, + "commander": { + "version": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=" + }, + "comment-parser": { + "version": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.3.1.tgz", + "integrity": "sha1-/WV6rIwUktMIyaYQD8m0nSQ1q6E=", + "dev": true + }, + "commoner": { + "version": "https://registry.npmjs.org/commoner/-/commoner-0.10.4.tgz", + "integrity": "sha1-mPMzPdOtOZWWuy04Sng7tyE9aPg=", + "dev": true + }, + "concat-map": { + "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "readable-stream": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.10.tgz", + "integrity": "sha512-HQEnnoV404e0EtwB9yNiuk2tJ+egeVC8Y9QBAxzDg8DBJt4BzRp+yQuIb/t3FIWkSTmIi+sgx7yVv/ZM0GNoqw==", + "dev": true + }, + "string_decoder": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz", + "integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=", + "dev": true + } + } + }, + "console-control-strings": { + "version": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "content-type": { + "version": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", + "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", + "dev": true + }, + "convert-source-map": { + "version": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.3.0.tgz", + "integrity": "sha1-6fPpxuJyjvwmdmlqcOs4L3MQamc=", + "dev": true + }, + "core-js": { + "version": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "core-util-is": { + "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-error-class": { + "version": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=" + }, + "create-react-class": { + "version": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.5.3.tgz", + "integrity": "sha1-+w98rnkznpoXnhlO9Gbvo5I4IP4=", + "dependencies": { + "js-tokens": { + "version": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=" + }, + "loose-envify": { + "version": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=" + }, + "object-assign": { + "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + } + } + }, + "cross-spawn": { + "version": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=" + }, + "cryptiles": { + "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=" + }, + "css-selector-tokenizer": { + "version": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", + "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", + "dev": true + }, + "cssesc": { + "version": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "currently-unhandled": { + "version": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=" + }, + "cycle": { + "version": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, + "d": { + "version": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=" + }, + "damerau-levenshtein": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", + "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=", + "dev": true + }, + "dashdash": { + "version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz", + "integrity": "sha1-KeSGxUGL8PNWA0qZPVFoajPoQUE=", + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "dateformat": { + "version": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=", + "dev": true + }, + "debug": { + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=" + }, + "decamelize": { + "version": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-equal": { + "version": "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 + }, + "deepmerge": { + "version": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.3.2.tgz", + "integrity": "sha1-FmNpFinU2/42T6EqKk8KqGqjoFA=" + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true + }, + "defined": { + "version": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "defs": { + "version": "https://registry.npmjs.org/defs/-/defs-1.1.1.tgz", + "integrity": "sha1-siYJ8sehG6ej2xFoBcE5scr/qdI=", + "dev": true, + "dependencies": { + "camelcase": { + "version": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true + }, + "esprima-fb": { + "version": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk=", + "dev": true + }, + "window-size": { + "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "dev": true + }, + "yargs": { + "version": "https://registry.npmjs.org/yargs/-/yargs-3.27.0.tgz", + "integrity": "sha1-ISBUaTFuk5Ex1Z8toMbX+YIh6kA=", + "dev": true + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true + }, + "delayed-stream": { + "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=", + "dev": true + }, + "detect-indent": { + "version": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz", + "integrity": "sha1-ncXl3bzu+DJXZLlFGwK8bVQIT3U=", + "dev": true, + "dependencies": { + "repeating": { + "version": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", + "dev": true + } + } + }, + "detective": { + "version": "https://registry.npmjs.org/detective/-/detective-4.3.1.tgz", + "integrity": "sha1-n7Bt0e6PDqTbzGB82jnZzh1Pcm8=", + "dev": true + }, + "doctrine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", + "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "dev": true + }, + "dom-helpers": { + "version": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.2.1.tgz", + "integrity": "sha1-MgPgf+0he9H0JLAZc1WC/Deyglo=" + }, + "dom-serializer": { + "version": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "dependencies": { + "domelementtype": { + "version": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + }, + "entities": { + "version": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + } + } + }, + "domelementtype": { + "version": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true + }, + "domutils": { + "version": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true + }, + "double-ended-queue": { + "version": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" + }, + "duplexer3": { + "version": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "duplexify": { + "version": "https://registry.npmjs.org/duplexify/-/duplexify-3.4.5.tgz", + "integrity": "sha1-Dn4oenda91O/V+bnt/IfGD9sOlM=", + "dev": true + }, + "ecc-jsbn": { + "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true + }, + "ee-first": { + "version": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.13.tgz", + "integrity": "sha1-GzperObgh7teJXoQCwy/6Bsokfw=", + "dev": true + }, + "element-class": { + "version": "https://registry.npmjs.org/element-class/-/element-class-0.2.2.tgz", + "integrity": "sha1-nTu9B2f5AT744cjr5yLBQCpgBQ4=" + }, + "emoji-regex": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.4.2.tgz", + "integrity": "sha1-owtv7jU9QG2Wz7n6dlvcgol+/24=", + "dev": true + }, + "encoding": { + "version": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=" + }, + "end-of-stream": { + "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", + "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=", + "dev": true + }, + "entities": { + "version": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "error-ex": { + "version": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz", + "integrity": "sha1-5ntD8+gsluo6WE/+4Ln8MyXYAtk=" + }, + "es-abstract": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz", + "integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=", + "dev": true + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true + }, + "es5-ext": { + "version": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz", + "integrity": "sha1-qoRkHU23a2Krul5F/YBey6sUAEc=" + }, + "es6-iterator": { + "version": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz", + "integrity": "sha1-vZaFZ9YWNeM8C4BydhPJy0sJa6w=" + }, + "es6-map": { + "version": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.4.tgz", + "integrity": "sha1-o0sUe+IkdzpNfagHJ5TO+jYyuJc=", + "dev": true + }, + "es6-set": { + "version": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.4.tgz", + "integrity": "sha1-lRa2dhwpZLkv9HlFYjOiR9xwfOg=", + "dev": true + }, + "es6-symbol": { + "version": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz", + "integrity": "sha1-lEgcZV56fK2C66gy2X1UM0ltf/o=" + }, + "es6-weak-map": { + "version": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.1.tgz", + "integrity": "sha1-DSu9iCfrX7S6j5f7/qUNQ9sh6oE=", + "dev": true + }, + "escape-string-regexp": { + "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escope": { + "version": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "dev": true, + "dependencies": { + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", + "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", + "dev": true + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-yaml": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz", + "integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=", + "dev": true + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true + } + } + }, + "eslint-config-airbnb": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-15.0.1.tgz", + "integrity": "sha1-e1GI5bfHS5ss5jn9Xh2rqP12Gu0=", + "dev": true + }, + "eslint-config-airbnb-base": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.2.0.tgz", + "integrity": "sha1-GancRIGib3CQRUXsBAEWh2AY+FM=", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", + "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", + "dev": true + }, + "eslint-module-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.0.0.tgz", + "integrity": "sha1-pvjCHZATWHWc3DXbrBmCrh7li84=", + "dev": true + }, + "eslint-plugin-import": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.3.0.tgz", + "integrity": "sha1-N8gB4K2g4pbL3yDD85OstbUq82s=", + "dev": true, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "eslint-plugin-jsx-a11y": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-5.0.3.tgz", + "integrity": "sha1-SpOfduwSUBBSiCMzG/lIzFczgLY=", + "dev": true + }, + "eslint-plugin-react": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.0.1.tgz", + "integrity": "sha1-54EH4eVZxuKxd4a7Z8LioBCtDS8=", + "dev": true + }, + "espree": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", + "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", + "dev": true, + "dependencies": { + "acorn": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=", + "dev": true + } + } + }, + "esprima": { + "version": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true + }, + "esrecurse": { + "version": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.1.0.tgz", + "integrity": "sha1-RxO2U2rffyrE8yfVWed1a/9kgiA=", + "dev": true, + "dependencies": { + "estraverse": { + "version": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz", + "integrity": "sha1-9srKcokzqFDvkGYdDheYK6RxEaI=", + "dev": true + } + } + }, + "estraverse": { + "version": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-emitter": { + "version": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.4.tgz", + "integrity": "sha1-jWPd+0z+H647MsomXExyAiIIC7U=", + "dev": true + }, + "eventemitter2": { + "version": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-2.1.3.tgz", + "integrity": "sha1-vXIB+FxZVIOA4eQ7P2pyhtTac0k=" + }, + "exenv": { + "version": "https://registry.npmjs.org/exenv/-/exenv-1.2.0.tgz", + "integrity": "sha1-ODXxJ6vwdb/ggtCu1EhAV8eOPIk=" + }, + "exit": { + "version": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "extend": { + "version": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=" + }, + "extsprintf": { + "version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" + }, + "eyes": { + "version": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, + "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 + }, + "fastparse": { + "version": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", + "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", + "dev": true + }, + "faye-websocket": { + "version": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true + }, + "fbjs": { + "version": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.9.tgz", + "integrity": "sha1-GAJH+9NH3MkARRe5BPhlQAoMjxQ=" + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true + }, + "find-up": { + "version": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=" + }, + "findup-sync": { + "version": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=" + }, + "flat-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", + "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", + "dev": true + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "forever-agent": { + "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz", + "integrity": "sha1-BaxrwiIntD5EYfSIFhVUaZ1Pi14=" + }, + "fs-readdir-recursive": { + "version": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-0.1.2.tgz", + "integrity": "sha1-MVtPuMHKW4xH3v7zGdBz2tNWgFk=", + "dev": true + }, + "fs.realpath": { + "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz", + "integrity": "sha1-YE6Kkv4m/9n2+uMDmdSYThqyKCI=" + }, + "function-bind": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", + "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", + "dev": true + }, + "gauge": { + "version": "https://registry.npmjs.org/gauge/-/gauge-2.6.0.tgz", + "integrity": "sha1-01MBrRjpaQK0dR3LvkD0IYuUKkY=" + }, + "gaze": { + "version": "https://registry.npmjs.org/gaze/-/gaze-1.1.1.tgz", + "integrity": "sha1-q4HVV9G1FfV1K9XxEX1vo8Tp20E=" + }, + "generate-function": { + "version": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" + }, + "generate-object-property": { + "version": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=" + }, + "get-caller-file": { + "version": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + }, + "get-stdin": { + "version": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "get-stream": { + "version": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "getobject": { + "version": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "getpass": { + "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=", + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=" + }, + "globals": { + "version": "https://registry.npmjs.org/globals/-/globals-6.4.1.tgz", + "integrity": "sha1-hJgDKzttHMge68X3lpDY/in6v08=", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "dependencies": { + "brace-expansion": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", + "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + } + } + }, + "globule": { + "version": "https://registry.npmjs.org/globule/-/globule-1.0.0.tgz", + "integrity": "sha1-8irrqszgK+SSRT6XnDrptpg/HGw=", + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=" + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.9.0.tgz", + "integrity": "sha1-TCDXQvA86F3HAODderm8q4Xm/BQ=" + } + } + }, + "got": { + "version": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=" + }, + "graceful-fs": { + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha1-UUw4dysxvuLgi+3CGgrrOr9UwZ4=" + }, + "graceful-readlink": { + "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "grunt": { + "version": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", + "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=", + "dev": true, + "dependencies": { + "async": { + "version": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true + }, + "colors": { + "version": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "eventemitter2": { + "version": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "findup-sync": { + "version": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "dev": true, + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true + } + } + }, + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "dependencies": { + "inherits": { + "version": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "iconv-lite": { + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=", + "dev": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + }, + "lru-cache": { + "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true + }, + "nopt": { + "version": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true + }, + "rimraf": { + "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "which": { + "version": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + } + } + }, + "grunt-cli": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=" + }, + "grunt-concurrent": { + "version": "https://registry.npmjs.org/grunt-concurrent/-/grunt-concurrent-2.2.1.tgz", + "integrity": "sha1-BjUjQjya99HWnDPIzP83KKQPhAU=", + "dev": true + }, + "grunt-contrib-watch": { + "version": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz", + "integrity": "sha1-hKGnodar0m7VaEE0lscxM+mQAY8=", + "dev": true, + "dependencies": { + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "grunt-force-task": { + "version": "https://registry.npmjs.org/grunt-force-task/-/grunt-force-task-2.0.0.tgz", + "integrity": "sha1-XJkD93QJYemBFz0cCCwYpdcwXUk=", + "dev": true + }, + "grunt-jscs": { + "version": "https://registry.npmjs.org/grunt-jscs/-/grunt-jscs-2.8.0.tgz", + "integrity": "sha1-nc81LFY6Mi2Adl/pIsLNoqRkzto=", + "dev": true, + "dependencies": { + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.6.1.tgz", + "integrity": "sha1-3wDBFkrSNrGDz8OIel6NOMxjy7w=", + "dev": true + } + } + }, + "grunt-known-options": { + "version": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz", + "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=" + }, + "grunt-legacy-log": { + "version": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", + "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=", + "dev": true, + "dependencies": { + "colors": { + "version": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-log-utils": { + "version": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz", + "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=", + "dev": true, + "dependencies": { + "colors": { + "version": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-util": { + "version": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz", + "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=", + "dev": true, + "dependencies": { + "async": { + "version": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + }, + "which": { + "version": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + } + } + }, + "grunt-newer": { + "version": "https://registry.npmjs.org/grunt-newer/-/grunt-newer-1.2.0.tgz", + "integrity": "sha1-d/geavt6grP5HBQTc2GZjViGaEE=", + "dev": true + }, + "grunt-shell": { + "version": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-1.2.1.tgz", + "integrity": "sha1-e3X16yF/X8NdmmrxiNAr4ui1pWU=", + "dev": true + }, + "har-validator": { + "version": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=" + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true + }, + "has-ansi": { + "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=" + }, + "has-color": { + "version": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" + }, + "has-flag": { + "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-unicode": { + "version": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hawk": { + "version": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=" + }, + "hiredis": { + "version": "https://registry.npmjs.org/hiredis/-/hiredis-0.5.0.tgz", + "integrity": "sha1-2wOpi+zXAD0TwmAEOs7s+s31m4c=" + }, + "history": { + "version": "https://registry.npmjs.org/history/-/history-3.3.0.tgz", + "integrity": "sha1-/O3M6PEpdTcVRdc1RhAzV5ptrpw=" + }, + "hoek": { + "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "hoist-non-react-statics": { + "version": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz", + "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=" + }, + "home-or-tmp": { + "version": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-1.0.0.tgz", + "integrity": "sha1-S58eQIAMPlDGwn94FnavzOcfOYU=", + "dev": true + }, + "hooker": { + "version": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "hosted-git-info": { + "version": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz", + "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=" + }, + "htmlparser2": { + "version": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "dependencies": { + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + } + } + }, + "http-errors": { + "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "dev": true + }, + "http-signature": { + "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=" + }, + "i": { + "version": "https://registry.npmjs.org/i/-/i-0.3.5.tgz", + "integrity": "sha1-HSuFQVjsgWkRPGy39raAHpniEdU=", + "dev": true + }, + "iconv-lite": { + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=" + }, + "icss-replace-symbols": { + "version": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "ignore": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", + "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "in-publish": { + "version": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=" + }, + "indent-string": { + "version": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=" + }, + "inflight": { + "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", + "integrity": "sha1-2zIEzVqd4ubNiQuFxuL2a89PYgo=" + }, + "inherit": { + "version": "https://registry.npmjs.org/inherit/-/inherit-2.2.5.tgz", + "integrity": "sha1-bHcVNMvC02DFWmdeKh029w2q8Yw=", + "dev": true + }, + "inherits": { + "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + }, + "interpret": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", + "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", + "dev": true + }, + "intl-format-cache": { + "version": "https://registry.npmjs.org/intl-format-cache/-/intl-format-cache-2.0.5.tgz", + "integrity": "sha1-tITO/Lk1PzdPJd44mjzuoa8Y18k=" + }, + "intl-messageformat": { + "version": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-1.3.0.tgz", + "integrity": "sha1-99kmre16OrGbLcYB79VOmaS9Tq4=" + }, + "intl-messageformat-parser": { + "version": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.2.0.tgz", + "integrity": "sha1-WQa3+VOrdHDg3IVJCXtki5kYkv8=" + }, + "intl-relativeformat": { + "version": "https://registry.npmjs.org/intl-relativeformat/-/intl-relativeformat-1.3.0.tgz", + "integrity": "sha1-iT3HB2/M04DPCRojAMOA+les5Fs=" + }, + "invariant": { + "version": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz", + "integrity": "sha1-sJcBBUdmjH4zcCjr6Bbr42yKjVQ=" + }, + "invert-kv": { + "version": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "is-arrayish": { + "version": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-buffer": { + "version": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz", + "integrity": "sha1-z8hszV3FpS+oBIkRHGkgxFfi2Ys=", + "dev": true + }, + "is-builtin-module": { + "version": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=" + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-finite": { + "version": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz", + "integrity": "sha1-ZDhgPq6+J5OUj/SkJi7I2z1iWXs=" + }, + "is-fullwidth-code-point": { + "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=" + }, + "is-integer": { + "version": "https://registry.npmjs.org/is-integer/-/is-integer-1.0.6.tgz", + "integrity": "sha1-UnOBn62ogNEj4awAqTjnFy3Y2V4=", + "dev": true + }, + "is-my-json-valid": { + "version": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz", + "integrity": "sha1-1Vd4qC/rawlj/0vhEdXRaE6JBwc=" + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true + }, + "is-property": { + "version": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "is-redirect": { + "version": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true + }, + "is-retry-allowed": { + "version": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-stream": { + "version": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-typedarray": { + "version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", + "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA=" + }, + "isomorphic-fetch": { + "version": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=" + }, + "isstream": { + "version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jodid25519": { + "version": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", + "optional": true + }, + "js-tokens": { + "version": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz", + "integrity": "sha1-FOVutoyPGpLEPVn1AU7CncIPKuE=" + }, + "js-yaml": { + "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "dev": true + }, + "jsbn": { + "version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz", + "integrity": "sha1-ZQmH2g3XT06/WhE3eiqi0nPpff0=", + "optional": true + }, + "jscs": { + "version": "https://registry.npmjs.org/jscs/-/jscs-2.11.0.tgz", + "integrity": "sha1-bhHvDKqgdzH53MKysn2OzuHdvLY=", + "dev": true, + "dependencies": { + "argparse": { + "version": "https://registry.npmjs.org/argparse/-/argparse-1.0.7.tgz", + "integrity": "sha1-wolQZIBVeBDxSovGLXoG9j7X+VE=", + "dev": true + }, + "esprima": { + "version": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "js-yaml": { + "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.4.6.tgz", + "integrity": "sha1-a+GyP2JJ9T0pM3D9TRqqY84bTrA=", + "dev": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "jscs-jsdoc": { + "version": "https://registry.npmjs.org/jscs-jsdoc/-/jscs-jsdoc-1.3.2.tgz", + "integrity": "sha1-HyyCtqtLl1JNqVj0a05WLgMF+ac=", + "dev": true + }, + "jscs-preset-wikimedia": { + "version": "https://registry.npmjs.org/jscs-preset-wikimedia/-/jscs-preset-wikimedia-1.0.0.tgz", + "integrity": "sha1-//VjNCA4/C6IJre7cwnDrjQG/H4=", + "dev": true + }, + "jsdoctypeparser": { + "version": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-1.2.0.tgz", + "integrity": "sha1-597cFToRhJ/8UUEUSuhqfvDCU5I=", + "dev": true, + "dependencies": { + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "jsesc": { + "version": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "json-schema": { + "version": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz", + "integrity": "sha1-UDVPGfYDkXxpX3C4Wvp3w7DyNQY=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true + }, + "json-stringify-safe": { + "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz", + "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonlint": { + "version": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.2.tgz", + "integrity": "sha1-VzcEUIX1XrRVxosf9OvAG9UOiDA=", + "dev": true + }, + "jsonpointer": { + "version": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz", + "integrity": "sha1-OvHdIP6FRjkQ1GmjheMwF9KgMNk=" + }, + "jsprim": { + "version": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.0.tgz", + "integrity": "sha1-zi4b74NSBLTzCZkoxgL4tq5hVlA=" + }, + "JSV": { + "version": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", + "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=", + "dev": true + }, + "jsx-ast-utils": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", + "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", + "dev": true + }, + "kind-of": { + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.4.tgz", + "integrity": "sha1-e47PGKThf4Jp1ztQHJ8jLJaIenQ=", + "dev": true + }, + "lazy-cache": { + "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lcid": { + "version": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=" + }, + "leven": { + "version": "https://registry.npmjs.org/leven/-/leven-1.0.2.tgz", + "integrity": "sha1-kUS27ryl8dBoAWnxpncNzqYLdcM=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true + }, + "livereload-js": { + "version": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", + "integrity": "sha1-bIclfmSKtHW8JOoldFftzB+NC8I=", + "dev": true + }, + "load-grunt-tasks": { + "version": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-3.4.1.tgz", + "integrity": "sha1-iDuT6r07HMvzZP3OscqJk/xlqKU=", + "dev": true + }, + "load-json-file": { + "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=" + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash._baseassign": { + "version": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true + }, + "lodash._basecopy": { + "version": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._bindcallback": { + "version": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "lodash._createassigner": { + "version": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", + "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", + "dev": true + }, + "lodash._getnative": { + "version": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.assign": { + "version": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "lodash.clonedeep": { + "version": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "lodash.cond": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", + "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", + "dev": true + }, + "lodash.isarguments": { + "version": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true + }, + "lodash.restparam": { + "version": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "longest": { + "version": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loose-envify": { + "version": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz", + "integrity": "sha1-aaZarT3lQs9O4PT+dOjjPHCcyw8=" + }, + "loud-rejection": { + "version": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=" + }, + "lowercase-keys": { + "version": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + }, + "lru-cache": { + "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", + "integrity": "sha1-E0OVXtry432bnn7nJB4nxLn7cr4=" + }, + "map-obj": { + "version": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, + "material-colors": { + "version": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.5.tgz", + "integrity": "sha1-UpJZPmdUyxvMK5gDDk4Najr8nqE=" + }, + "media-typer": { + "version": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "meow": { + "version": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=" + }, + "meteor-node-stubs": { + "version": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.2.11.tgz", + "integrity": "sha1-cV5Owc6IgkiylgThbQkiVrDLfjQ=", + "dependencies": { + "asn1.js": { + "version": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.0.tgz", + "integrity": "sha1-9xoSQ/PnnUbXsH1/v0gk7nOvBUo=" + }, + "assert": { + "version": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=" + }, + "balanced-match": { + "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + }, + "Base64": { + "version": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", + "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=" + }, + "base64-js": { + "version": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", + "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=" + }, + "bn.js": { + "version": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "brace-expansion": { + "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", + "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=" + }, + "brorand": { + "version": "https://registry.npmjs.org/brorand/-/brorand-1.0.6.tgz", + "integrity": "sha1-QChwa5FfkfezSaLgvzw3YDnSFuU=" + }, + "browserify-aes": { + "version": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz", + "integrity": "sha1-Xncl297x/Vkw1OurSFZ85FHEigo=" + }, + "browserify-cipher": { + "version": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=" + }, + "browserify-des": { + "version": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=" + }, + "browserify-rsa": { + "version": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=" + }, + "browserify-sign": { + "version": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.0.tgz", + "integrity": "sha1-EHc5EMPCBtVCCkaq2GlPgguFlo8=" + }, + "browserify-zlib": { + "version": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=" + }, + "buffer": { + "version": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=" + }, + "buffer-xor": { + "version": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "cipher-base": { + "version": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.3.tgz", + "integrity": "sha1-7qvxlEGc6QDaMBjCB9IS8qbfCgc=" + }, + "concat-map": { + "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-browserify": { + "version": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=" + }, + "constants-browserify": { + "version": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "create-ecdh": { + "version": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=" + }, + "create-hash": { + "version": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz", + "integrity": "sha1-USEAYte7dHn2xlu0GpIgix1hq60=" + }, + "create-hmac": { + "version": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.4.tgz", + "integrity": "sha1-0/tLolPriz9W456i+8uK90e9MXA=" + }, + "crypto-browserify": { + "version": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.0.tgz", + "integrity": "sha1-NlKgkGq5sqfgw85mpAjpV6JIVSI=" + }, + "date-now": { + "version": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + }, + "des.js": { + "version": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=" + }, + "diffie-hellman": { + "version": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=" + }, + "domain-browser": { + "version": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=" + }, + "elliptic": { + "version": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.2.tgz", + "integrity": "sha1-5MgeCCnPCmWrcOmYuCMnI7XBvEg=" + }, + "events": { + "version": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "evp_bytestokey": { + "version": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz", + "integrity": "sha1-SXtmrZ/vZc18CKYYCCS6FHa2blM=" + }, + "fs.realpath": { + "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=" + }, + "hash.js": { + "version": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz", + "integrity": "sha1-EzL/ABVsCg/92CNgE9B7d6BFFXM=" + }, + "http-browserify": { + "version": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz", + "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=" + }, + "https-browserify": { + "version": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=" + }, + "ieee754": { + "version": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + }, + "indexof": { + "version": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "inflight": { + "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" + }, + "inherits": { + "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "miller-rabin": { + "version": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.0.tgz", + "integrity": "sha1-SmL7HUKTPAVYOYL0xxb2+55sbT0=" + }, + "minimalistic-assert": { + "version": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" + }, + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=" + }, + "once": { + "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + }, + "os-browserify": { + "version": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", + "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=" + }, + "pako": { + "version": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + }, + "parse-asn1": { + "version": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.0.0.tgz", + "integrity": "sha1-NQYPbVAV03Yox3D04JGgtaJ4vCM=" + }, + "path-browserify": { + "version": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" + }, + "path-is-absolute": { + "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "pbkdf2": { + "version": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.9.tgz", + "integrity": "sha1-8sSyWmAAWLPDdzwIbDfbvuH/5pM=" + }, + "process": { + "version": "https://registry.npmjs.org/process/-/process-0.11.9.tgz", + "integrity": "sha1-e9WtIapiU+fahoImTx4R0RwDGME=" + }, + "process-nextick-args": { + "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "public-encrypt": { + "version": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=" + }, + "punycode": { + "version": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "querystring": { + "version": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "randombytes": { + "version": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.3.tgz", + "integrity": "sha1-Z0yZdgkBw8QRJ3GjHlIdw0nMCew=" + }, + "readable-stream": { + "version": "git+https://github.com/meteor/readable-stream.git#2e9112d7d31a2af6e0682db0e18679b1e5fd4694" + }, + "rimraf": { + "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=" + }, + "ripemd160": { + "version": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.1.tgz", + "integrity": "sha1-k6S71JQrxXS2mo+lfHHeEOzKfW4=" + }, + "safe-buffer": { + "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" + }, + "sha.js": { + "version": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz", + "integrity": "sha1-NwaMLEdra69ALRSknGf1l5IfY08=" + }, + "stream-browserify": { + "version": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=" + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz", + "integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=" + }, + "timers-browserify": { + "version": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=" + }, + "tty-browserify": { + "version": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "url": { + "version": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dependencies": { + "punycode": { + "version": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "util": { + "version": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=" + }, + "util-deprecate": { + "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "vm-browserify": { + "version": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=" + }, + "wrappy": { + "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + } + }, + "mime-db": { + "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz", + "integrity": "sha1-oxtAcK2uon1zLqMzdApk0OyaZlk=" + }, + "mime-types": { + "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", + "integrity": "sha1-wlnEcb2oCKhdbNGTtDCl+uRHOzw=" + }, + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=" + }, + "minimist": { + "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mkdirp": { + "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dependencies": { + "minimist": { + "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "ms": { + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "multimatch": { + "version": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "dev": true + }, + "mute-stream": { + "version": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.6.tgz", + "integrity": "sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s=", + "dev": true + }, + "nan": { + "version": "https://registry.npmjs.org/nan/-/nan-2.4.0.tgz", + "integrity": "sha1-+zxZ1F/k7/4hXwuJD4rfbrMtIjI=" + }, + "natural-compare": { + "version": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.2.2.tgz", + "integrity": "sha1-H5bWDjFBysG20FZTzg2urHY69qo=", + "dev": true + }, + "ncp": { + "version": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", + "dev": true + }, + "next-tick": { + "version": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "node-fetch": { + "version": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", + "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=" + }, + "node-gyp": { + "version": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.4.0.tgz", + "integrity": "sha1-3aVYOTs+y74kyea4cDxxGUxj+jY=", + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=" + } + } + }, + "node-sass": { + "version": "https://registry.npmjs.org/node-sass/-/node-sass-3.8.0.tgz", + "integrity": "sha1-7A+JrmYl4dmQ3H/3E7J16hXf7gU=", + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=" + } + } + }, + "node-uuid": { + "version": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", + "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=" + }, + "nomnom": { + "version": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true + }, + "chalk": { + "version": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true + }, + "strip-ansi": { + "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", + "dev": true + }, + "underscore": { + "version": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + } + } + }, + "nopt": { + "version": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=" + }, + "normalize-package-data": { + "version": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz", + "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=" + }, + "normalize-range": { + "version": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "npmlog": { + "version": "https://registry.npmjs.org/npmlog/-/npmlog-3.1.2.tgz", + "integrity": "sha1-LUb6h0M3r5SYovErtD2NC+SjaHM=" + }, + "num2fraction": { + "version": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz", + "integrity": "sha1-wCD1KcUoKt/dIz2R1LGBw9aG3Es=" + }, + "oauth-sign": { + "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "on-finished": { + "version": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true + }, + "once": { + "version": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=" + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "os-homedir": { + "version": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz", + "integrity": "sha1-DWK99EuRb9O73PLKsZGUj7CU8Ac=" + }, + "os-locale": { + "version": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=" + }, + "os-tmpdir": { + "version": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz", + "integrity": "sha1-6bQjoe2vR5iCVi6S7XHXdDoHG24=" + }, + "osenv": { + "version": "https://registry.npmjs.org/osenv/-/osenv-0.1.3.tgz", + "integrity": "sha1-g88FxtZFj8TVrGNi6jJdkvJ1Qhc=" + }, + "output-file-sync": { + "version": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true + }, + "pad-stream": { + "version": "https://registry.npmjs.org/pad-stream/-/pad-stream-1.2.0.tgz", + "integrity": "sha1-Yx3Mn3mBC3BZZeid7eps/w/B38k=", + "dev": true + }, + "parse-json": { + "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" + }, + "parseurl": { + "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", + "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", + "dev": true + }, + "path-array": { + "version": "https://registry.npmjs.org/path-array/-/path-array-1.0.1.tgz", + "integrity": "sha1-fi8PNfB6IBUSK4aLfqwOssT+wnE=" + }, + "path-exists": { + "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=" + }, + "path-is-absolute": { + "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", + "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-type": { + "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=" + }, + "pathval": { + "version": "https://registry.npmjs.org/pathval/-/pathval-0.1.1.tgz", + "integrity": "sha1-CPkRzcqczllCiA2ngXvAtyO2bYI=", + "dev": true + }, + "pify": { + "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=" + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true + }, + "pkg-up": { + "version": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", + "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", + "dev": true + }, + "pkginfo": { + "version": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", + "dev": true + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "postcss": { + "version": "https://registry.npmjs.org/postcss/-/postcss-6.0.1.tgz", + "integrity": "sha1-AA29H47vIXqjaLmiEsX8QLKo8/I=", + "dev": true, + "dependencies": { + "supports-color": { + "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true + } + } + }, + "postcss-modules-extract-imports": { + "version": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", + "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", + "dev": true + }, + "postcss-modules-local-by-default": { + "version": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "dev": true + }, + "postcss-modules-scope": { + "version": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "dev": true + }, + "postcss-modules-values": { + "version": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "dev": true + }, + "postcss-nested": { + "version": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-2.0.2.tgz", + "integrity": "sha1-84+tVH9cN0cWCuw7s0dFgZJSl0o=", + "dev": true + }, + "postcss-value-parser": { + "version": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", + "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 + }, + "prepend-http": { + "version": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "private": { + "version": "https://registry.npmjs.org/private/-/private-0.1.6.tgz", + "integrity": "sha1-VcapdtD5uvuZJIUTUP5HubX7t8E=", + "dev": true + }, + "probe-image-size": { + "version": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-3.0.0.tgz", + "integrity": "sha1-sZ7LpfTPRvga7+TDNWZmVdxTvwA=", + "dependencies": { + "inherits": { + "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "process-nextick-args": { + "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "promise": { + "version": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz", + "integrity": "sha1-SJZUxpJha4qlWwck+oCbt9tJxb8=" + }, + "prompt": { + "version": "https://registry.npmjs.org/prompt/-/prompt-0.2.14.tgz", + "integrity": "sha1-V3VPZPVD/XsIRXB8gY7OYY8F/9w=", + "dev": true, + "dependencies": { + "async": { + "version": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "colors": { + "version": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "winston": { + "version": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz", + "integrity": "sha1-ZLar9M0Brcrv1QCTk7HY6L7BnbA=", + "dev": true + } + } + }, + "prop-types": { + "version": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", + "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "dependencies": { + "js-tokens": { + "version": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=" + }, + "loose-envify": { + "version": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=" + } + } + }, + "pseudomap": { + "version": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "pump": { + "version": "https://registry.npmjs.org/pump/-/pump-1.0.1.tgz", + "integrity": "sha1-8fFAn7m9EIW721drQ7hOxLXq3Bo=", + "dev": true, + "dependencies": { + "end-of-stream": { + "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz", + "integrity": "sha1-6TUyWLqpEIll78QcsO+K3i88+wc=", + "dev": true + } + } + }, + "pumpify": { + "version": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.5.tgz", + "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=", + "dev": true + }, + "q": { + "version": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "qs": { + "version": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz", + "integrity": "sha1-zgPF/wk1vB2daanxTL0Y5WjWdiU=" + }, + "query-string": { + "version": "https://registry.npmjs.org/query-string/-/query-string-4.3.2.tgz", + "integrity": "sha1-7A/XZfWKUAMaOWjCQxOG+JR6XN0=" + }, + "raw-body": { + "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "dev": true, + "dependencies": { + "bytes": { + "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + } + } + }, + "react": { + "version": "https://registry.npmjs.org/react/-/react-15.5.4.tgz", + "integrity": "sha1-+oPrAVBqsjfNwcjDsc6o3gEr8Ec=" + }, + "react-autosize-textarea": { + "version": "https://registry.npmjs.org/react-autosize-textarea/-/react-autosize-textarea-0.4.3.tgz", + "integrity": "sha1-caoCmhJ4NS3IBYQf6ogCI8uZc3o=" + }, + "react-color": { + "version": "https://registry.npmjs.org/react-color/-/react-color-2.12.0.tgz", + "integrity": "sha1-VL+T5Ru43Cx2KCrBJ/hbNLhs1zQ=" + }, + "react-dom": { + "version": "https://registry.npmjs.org/react-dom/-/react-dom-15.5.4.tgz", + "integrity": "sha1-ugwoeG/VLtfk8hNf4CiNRirvk9o=" + }, + "react-intl": { + "version": "https://registry.npmjs.org/react-intl/-/react-intl-2.3.0.tgz", + "integrity": "sha1-4d9q9WZ/3wHL5KqyDhNyUeKuUUI=" + }, + "react-modal": { + "version": "https://registry.npmjs.org/react-modal/-/react-modal-1.7.7.tgz", + "integrity": "sha1-cCBfUcWHCMSHr/aBuj/teUbjkdk=" + }, + "react-router": { + "version": "https://registry.npmjs.org/react-router/-/react-router-3.0.2.tgz", + "integrity": "sha1-WhkVZniBDgHYGQH5wP72MoS4pRQ=" + }, + "react-tabs": { + "version": "https://registry.npmjs.org/react-tabs/-/react-tabs-1.0.0.tgz", + "integrity": "sha1-8VDJ+RAt1l28lKWg4eAZ1eOBSn8=" + }, + "react-toggle": { + "version": "https://registry.npmjs.org/react-toggle/-/react-toggle-4.0.1.tgz", + "integrity": "sha1-DoPoyU2UIy3r+iGpOP89KyEG7HI=" + }, + "react-transition-group": { + "version": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-1.1.3.tgz", + "integrity": "sha1-XgLPbkSoYzFP88aKDIJsLZ1wsiE=" + }, + "reactcss": { + "version": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.2.tgz", + "integrity": "sha1-QbDvQ+AdVIgDV8NLEawVMSCTUO8=" + }, + "read": { + "version": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true + }, + "read-pkg": { + "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=" + }, + "read-pkg-up": { + "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=" + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=" + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "dependencies": { + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + } + } + }, + "recast": { + "version": "https://registry.npmjs.org/recast/-/recast-0.10.33.tgz", + "integrity": "sha1-lCgI96oBbx+nFCxGHX5XBKqo1pc=", + "dev": true, + "dependencies": { + "esprima-fb": { + "version": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk=", + "dev": true + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true + }, + "redent": { + "version": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=" + }, + "redis": { + "version": "https://registry.npmjs.org/redis/-/redis-2.6.2.tgz", + "integrity": "sha1-fMqwVjATrGGefdhMZRK4HT2FJXk=" + }, + "redis-commands": { + "version": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.2.0.tgz", + "integrity": "sha1-SAjnoPyx02Cb7FbuzDUy2surmBw=" + }, + "redis-parser": { + "version": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.0.4.tgz", + "integrity": "sha1-cMu7PO+L9BoxU4iv4UkEplp6ECg=" + }, + "regenerate": { + "version": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.1.tgz", + "integrity": "sha1-AwAgOl0v3PiRFtzoQnXQEfWQPzM=", + "dev": true + }, + "regenerator": { + "version": "https://registry.npmjs.org/regenerator/-/regenerator-0.8.40.tgz", + "integrity": "sha1-oORXxY69uuV1yfjNdRJ+k3VkNdg=", + "dev": true, + "dependencies": { + "esprima-fb": { + "version": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk=", + "dev": true + } + } + }, + "regenerator-runtime": { + "version": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + }, + "regexpu": { + "version": "https://registry.npmjs.org/regexpu/-/regexpu-1.3.0.tgz", + "integrity": "sha1-5TTcmRqeWEYFDJjebX3UpVyeoW0=", + "dev": true, + "dependencies": { + "esprima": { + "version": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + } + } + }, + "regexpu-core": { + "version": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true + }, + "regjsgen": { + "version": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true + }, + "repeat-string": { + "version": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.5.4.tgz", + "integrity": "sha1-ZOwMkeD0tHX5DVtkNlHj5uW2wtU=", + "dev": true + }, + "repeating": { + "version": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=" + }, + "request": { + "version": "https://registry.npmjs.org/request/-/request-2.74.0.tgz", + "integrity": "sha1-dpPKdou7DqXIzgjAhKRe+gW4kqs=" + }, + "require-directory": { + "version": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + } + } + }, + "reserved-words": { + "version": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.1.tgz", + "integrity": "sha1-b3wV5eVhTFDalhYw2kat3IfAzvI=", + "dev": true + }, + "resolve": { + "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + }, + "resolve-from": { + "version": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", + "dev": true + }, + "resolve-pkg": { + "version": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-0.1.0.tgz", + "integrity": "sha1-AsyZNBDik2livZcWahsHfalyVTE=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true + }, + "revalidator": { + "version": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=", + "dev": true + }, + "right-align": { + "version": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true + }, + "rimraf": { + "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=" + } + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" + }, + "sass-graph": { + "version": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.1.2.tgz", + "integrity": "sha1-llEEviPoEDy35fcQ32WTWzF9pXs=", + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=" + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + } + } + }, + "sax": { + "version": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "semver": { + "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "set-blocking": { + "version": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setimmediate": { + "version": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "shebang-regex": { + "version": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelljs": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.7.tgz", + "integrity": "sha1-svXHfvlxSPS09uImguELuoZnz/E=", + "dev": true, + "dependencies": { + "brace-expansion": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", + "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + } + } + }, + "sigmund": { + "version": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz", + "integrity": "sha1-PAVDtl17T7xgts2UWT2b9DZzm+g=" + }, + "simple-fmt": { + "version": "https://registry.npmjs.org/simple-fmt/-/simple-fmt-0.1.0.tgz", + "integrity": "sha1-GRv1ZqWeZTBILLJatTtKjchcOms=", + "dev": true + }, + "simple-is": { + "version": "https://registry.npmjs.org/simple-is/-/simple-is-0.2.0.tgz", + "integrity": "sha1-Krt1qt453rXMgVzhDmGRFkhQuvA=", + "dev": true + }, + "slash": { + "version": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "sntp": { + "version": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=" + }, + "source-map": { + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + }, + "source-map-support": { + "version": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", + "integrity": "sha1-6lo5AKHByyUJagrozFwrSxDe09w=", + "dev": true, + "dependencies": { + "source-map": { + "version": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", + "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", + "dev": true + } + } + }, + "spdx-correct": { + "version": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=" + }, + "spdx-exceptions": { + "version": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-1.0.5.tgz", + "integrity": "sha1-nSGsTaS9tx0GD7dOWmdTHQMsu6Y=" + }, + "spdx-expression-parse": { + "version": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.2.tgz", + "integrity": "sha1-1SsUtelnB3FECvIlvLVjEirEUvY=" + }, + "spdx-license-ids": { + "version": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" + }, + "split2": { + "version": "https://registry.npmjs.org/split2/-/split2-1.1.1.tgz", + "integrity": "sha1-Fi2bGIZfAqsvKtlYVSLbm1TEgfk=", + "dev": true + }, + "sprintf-js": { + "version": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "https://registry.npmjs.org/sshpk/-/sshpk-1.9.2.tgz", + "integrity": "sha1-O0E1G7rVw03fS9gRmTfv7jGkZ2U=", + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "stable": { + "version": "https://registry.npmjs.org/stable/-/stable-0.1.5.tgz", + "integrity": "sha1-CCMvYMcy6YkHhLW+0HNPizKoh7k=", + "dev": true + }, + "stack-trace": { + "version": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=" + }, + "statuses": { + "version": "https://registry.npmjs.org/statuses/-/statuses-1.3.0.tgz", + "integrity": "sha1-jlV1jLIOdoLB9Pzo3KswvwHR4Ho=", + "dev": true + }, + "stream-parser": { + "version": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz", + "integrity": "sha1-FhhUhpRCACGhGC/wrxkRwSl2F3M=" + }, + "stream-shift": { + "version": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "strict-uri-encode": { + "version": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "string-width": { + "version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=" + }, + "stringmap": { + "version": "https://registry.npmjs.org/stringmap/-/stringmap-0.2.2.tgz", + "integrity": "sha1-VWwTeyWPlCuHdvWy71gqoGnX0bE=", + "dev": true + }, + "stringset": { + "version": "https://registry.npmjs.org/stringset/-/stringset-0.2.1.tgz", + "integrity": "sha1-7yWcTjSTRDd/zRyRPdLoSMnAQrU=", + "dev": true + }, + "stringstream": { + "version": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=" + }, + "strip-bom": { + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" + }, + "strip-indent": { + "version": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=" + }, + "strip-json-comments": { + "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "supports-color": { + "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "string-width": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz", + "integrity": "sha1-Y1xUNsxypuDDh87KJ41OLuxSaH4=", + "dev": true + } + } + }, + "tar": { + "version": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=" + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz", + "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true + } + } + }, + "timed-out": { + "version": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "tiny-lr": { + "version": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", + "dev": true, + "dependencies": { + "qs": { + "version": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", + "dev": true + } + } + }, + "tinycolor2": { + "version": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, + "to-double-quotes": { + "version": "https://registry.npmjs.org/to-double-quotes/-/to-double-quotes-2.0.0.tgz", + "integrity": "sha1-qvIx1vqUiUn4GTAburRITYWI5Kc=", + "dev": true + }, + "to-fast-properties": { + "version": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz", + "integrity": "sha1-8/XAw7pymafvmUJ+RGMyV63kMyA=", + "dev": true + }, + "to-single-quotes": { + "version": "https://registry.npmjs.org/to-single-quotes/-/to-single-quotes-2.0.1.tgz", + "integrity": "sha1-fMKRUfD18sQZRvEZ9ZMv5VQXASU=", + "dev": true + }, + "tough-cookie": { + "version": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.1.tgz", + "integrity": "sha1-mcd9+7fYBCSeiimdTLD9gf7wg/0=" + }, + "trim-newlines": { + "version": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "trim-right": { + "version": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "try-resolve": { + "version": "https://registry.npmjs.org/try-resolve/-/try-resolve-1.0.1.tgz", + "integrity": "sha1-z95vq9ctY+V5fPqrhzq76OcA6RI=", + "dev": true + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "tryor": { + "version": "https://registry.npmjs.org/tryor/-/tryor-0.1.2.tgz", + "integrity": "sha1-gUXkynyv9ArN48z5Rui4u3W0Fys=", + "dev": true + }, + "tunnel-agent": { + "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=" + }, + "tweetnacl": { + "version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz", + "integrity": "sha1-1ii1bzvMPVrnS6nUwacE3vWrS1Y=", + "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 + }, + "type-is": { + "version": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz", + "integrity": "sha1-boO6e8MM0zp7sLf7AHN6IIW/nQg=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "ua-parser-js": { + "version": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.12.tgz", + "integrity": "sha1-BMgamb3V3FImPqKdJMa/jUgYpLs=" + }, + "underscore.string": { + "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", + "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=", + "dev": true + }, + "unpipe": { + "version": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unzip-response": { + "version": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + }, + "url-parse-lax": { + "version": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=" + }, + "user-home": { + "version": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utile": { + "version": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", + "integrity": "sha1-kwyI6ZCY1iIINMNWy9mncFItkNc=", + "dev": true, + "dependencies": { + "async": { + "version": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, + "uuid": { + "version": "https://registry.npmjs.org/uuid/-/uuid-2.0.2.tgz", + "integrity": "sha1-SL1WmPBnfjx5AaHEbvFbFkN5RyY=", + "dev": true + }, + "validate-npm-package-license": { + "version": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=" + }, + "verror": { + "version": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=" + }, + "vow": { + "version": "https://registry.npmjs.org/vow/-/vow-0.4.12.tgz", + "integrity": "sha1-2kcsxgzzsIFHVWwPNw8sgFrktEk=", + "dev": true + }, + "vow-fs": { + "version": "https://registry.npmjs.org/vow-fs/-/vow-fs-0.3.6.tgz", + "integrity": "sha1-LUxZviLivyYY3fWXq0uqkjvnIA0=", + "dev": true, + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", + "dev": true + } + } + }, + "vow-queue": { + "version": "https://registry.npmjs.org/vow-queue/-/vow-queue-0.4.2.tgz", + "integrity": "sha1-5/4XFg4Vx8QYTRtmapvGThjjAYQ=", + "dev": true + }, + "warning": { + "version": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=" + }, + "websocket-driver": { + "version": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "dev": true + }, + "websocket-extensions": { + "version": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz", + "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=", + "dev": true + }, + "whatwg-fetch": { + "version": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", + "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" + }, + "which": { + "version": "https://registry.npmjs.org/which/-/which-1.2.10.tgz", + "integrity": "sha1-kc2b0HUTIkEbZZtA8FSyHelXqy0=" + }, + "which-module": { + "version": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "wide-align": { + "version": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz", + "integrity": "sha1-QO3egCpx/qHwcNo+YtzaLnrdlq0=" + }, + "window-size": { + "version": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" + }, + "winston": { + "version": "https://registry.npmjs.org/winston/-/winston-2.3.1.tgz", + "integrity": "sha1-C0hCDZeMAYBM8CMLZIhhWYIloRk=", + "dependencies": { + "async": { + "version": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + } + } + }, + "wordwrap": { + "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "wrap-ansi": { + "version": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.0.0.tgz", + "integrity": "sha1-fTD4+HP5pbvDpk2ryNF34HGuQm8=" + }, + "wrappy": { + "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true + }, + "xml2js": { + "version": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", + "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "xmlbuilder": { + "version": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", + "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=" + } + } + }, + "xmlbuilder": { + "version": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-3.1.0.tgz", + "integrity": "sha1-LIaIjy1OrehQ+jjKf3Ij9yCVFuE=", + "dev": true, + "dependencies": { + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "xtend": { + "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz", + "integrity": "sha1-MGxUODXwnuGkyyO3vOmrNByRzdQ=" + }, + "yargs": { + "version": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=" + }, + "yargs-parser": { + "version": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "dependencies": { + "camelcase": { + "version": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + } + } + } + } +} diff --git a/bigbluebutton-html5/package.json b/bigbluebutton-html5/package.json old mode 100755 new mode 100644 index 2832f312380f96e3cfe367e561f35fe02ac0241a..60c99a79d03e0df66482bfec991878503182c7ac --- a/bigbluebutton-html5/package.json +++ b/bigbluebutton-html5/package.json @@ -4,53 +4,61 @@ "scripts": { "start": "cd app;./start.sh", "preinstall": "npm install grunt-cli", - "test": "cd app;JASMINE_BROWSER=PhantomJS JASMINE_MIRROR_PORT=3000 meteor run --test", - "lint": "node_modules/jscs/bin/jscs *", - "autofix": "node_modules/jscs/bin/jscs * --fix" + "test": "wdio ./tests/webdriverio/wdio.conf.js", + "lint": "eslint . --ext .jsx,.js" }, "dependencies": { - "babel-runtime": "^6.18.0", + "babel-runtime": "^6.23.0", "classnames": "^2.2.5", "eventemitter2": "^2.1.3", - "grunt-cli": "~1.2.0", + "grunt-cli": "^1.2.0", "hiredis": "^0.5.0", "history": "~3.3.0", - "meteor-node-stubs": "^0.2.3", + "lodash": "~4.17.4", + "meteor-node-stubs": "^0.2.11", "node-sass": "~3.8.0", - "probe-image-size": "~2.1.1", - "react-addons-shallow-compare": "^15.4.2", - "react": "~15.4.2", - "react-addons-css-transition-group": "~15.4.2", - "react-addons-pure-render-mixin": "~15.4.2", - "react-autosize-textarea": "~0.3.2", - "react-color": "^2.11.1", - "react-dom": "~15.4.2", - "react-intl": "~2.1.3", - "react-modal": "~1.7.1", + "probe-image-size": "~3.0.0", + "prop-types": "~15.5.10", + "react": "~15.5.4", + "react-autosize-textarea": "~0.4.3", + "react-color": "^2.12.0", + "react-dom": "~15.5.4", + "react-intl": "~2.3.0", + "react-modal": "~1.7.7", "react-router": "~3.0.2", - "react-tabs": "^0.8.2", - "react-toggle": "^2.2.0", + "react-tabs": "~1.0.0", + "react-toggle": "~4.0.1", + "react-transition-group": "~1.1.3", "redis": "^2.6.2", "winston": "^2.3.1", - "xml2js": "^0.4.17", - "lodash": "~4.17.4" + "xml2js": "^0.4.17" }, "devDependencies": { - "autoprefixer": "^6.3.6", + "chai": "^3.5.0", + "autoprefixer": "^7.1.1", + "eslint": "~3.19.0", + "eslint-config-airbnb": "^15.0.1", + "eslint-config-airbnb-base": "~11.2.0", + "eslint-plugin-import": "~2.3.0", + "eslint-plugin-jsx-a11y": "^5.0.3", + "eslint-plugin-react": "^7.0.1", "grunt": "^0.4.5", "grunt-concurrent": "~2.2.1", "grunt-contrib-watch": "~1.0.0", "grunt-force-task": "~2.0.0", "grunt-jscs": "~2.8.0", + "grunt-newer": "~1.2.0", "grunt-shell": "~1.2.1", - "jscs": "~2.11.0", + "wdio-jasmine-framework": "^0.3.1", + "wdio-junit-reporter": "^0.3.0", + "wdio-spec-reporter": "^0.1.0", + "webdriverio": "^4.8.0", "load-grunt-tasks": "~3.4.1", - "grunt-newer": "~1.2.0", - "postcss-modules-extract-imports": "1.0.0", - "postcss-modules-local-by-default": "1.0.0", - "postcss-modules-scope": "1.0.0", - "postcss-modules-values": "1.1.1", - "postcss-nested": "1.0.0" + "postcss-modules-extract-imports": "1.1.0", + "postcss-modules-local-by-default": "1.2.0", + "postcss-modules-scope": "1.1.0", + "postcss-modules-values": "1.3.0", + "postcss-nested": "2.0.2" }, "cssModules": { "extensions": [ diff --git a/bigbluebutton-html5/private/config/public/chat.yaml b/bigbluebutton-html5/private/config/public/chat.yaml index 2ae01424b0deffc9b1b12cd6ae89b1d873c276d7..277ff5842daf1d2a7f2fb2b76ee0f354f5e6dc40 100755 --- a/bigbluebutton-html5/private/config/public/chat.yaml +++ b/bigbluebutton-html5/private/config/public/chat.yaml @@ -1,5 +1,7 @@ # Chat service configurations chat: + min_message_length: 1 + max_message_length: 5000 grouping_messages_window: 60000 # Chat types type_system: 'SYSTEM_MESSAGE' diff --git a/bigbluebutton-html5/start.sh b/bigbluebutton-html5/start.sh index 8da3cbeae88020387f309e7a3bc1f3abe0eda733..8a5827bb2a7233af7010038ce1589109fd8b5027 100755 --- a/bigbluebutton-html5/start.sh +++ b/bigbluebutton-html5/start.sh @@ -3,5 +3,5 @@ # Change to start meteor in production or development mode ENVIRONMENT_TYPE=development -JASMINE_SERVER_UNIT=0 JASMINE_SERVER_INTEGRATION=0 JASMINE_CLIENT_INTEGRATION=0 JASMINE_BROWSER=PhantomJS JASMINE_MIRROR_PORT=3000 ROOT_URL=http://127.0.0.1/html5client NODE_ENV=$ENVIRONMENT_TYPE meteor +ROOT_URL=http://127.0.0.1/html5client NODE_ENV=$ENVIRONMENT_TYPE meteor diff --git a/bigbluebutton-html5/tests/jasmine/client/integration/templates/usersList/usersListSpec.js b/bigbluebutton-html5/tests/jasmine/client/integration/templates/usersList/usersListSpec.js deleted file mode 100755 index 45ca596a49bc74763099c3d86001857cc05643a4..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/tests/jasmine/client/integration/templates/usersList/usersListSpec.js +++ /dev/null @@ -1,266 +0,0 @@ -var emptyUsersCollection = function () { - Users.find().map(function (item) { - Users.remove({ _id: item._id }); - }); -}; - -var renderUsersListTemplate = function () { - var div = document.createElement('div'); - var data = {}; - data.id = 'users'; - data.name = 'usersList'; - var comp = Blaze.renderWithData(Template.usersList, data); // loading data is optional - Blaze.insert(comp, div); - return div; -}; - -// TODO: try to use Meteor methods instead -var removeUserFromCollection = function (id) { - Users.find().map(function (item) { - if (item.userId == id) Users.remove({ _id: item._id }); - }); -}; - -// TODO: try to start with calling the app's methods instead of modifying the collection -describe('usersList template', function () { - beforeEach(function () { - emptyUsersCollection(); - }); - - it('should have no users when we start with an empty Users collection', function () { - var div = renderUsersListTemplate(); - - expect($(div).find('.userNameEntry')[0]).not.toBeDefined(); - }); - - it('should not display presenter icon next to a non-presenter user', function () { - var document1 = { - meetingId: 'meeting001', - userId: 'user001', - user: { - presenter: false, - }, - }; - Users.insert(document1); - var div = renderUsersListTemplate(); - - expect($(div).find('.glyphicon-picture')[0]).not.toBeDefined(); - }); - - it("should display presenter icon next to the presenter's username", function () { - var document1 = { - meetingId: 'meeting001', - userId: 'user001', - user: { - presenter: true, - }, - }; - Users.insert(document1); - var div = renderUsersListTemplate(); - - expect($(div).find('.glyphicon-picture')[0]).toBeDefined(); - }); - - it('should display usernames correctly', function () { - var document1 = { - meetingId: 'meeting001', - userId: 'user001', - user: { - name: 'Maxim', - }, - }; - Users.insert(document1); - var div = renderUsersListTemplate(); - - expect($(div).find('.userNameEntry').html().trim()).toEqual('Maxim'); - }); - - it('should display all the users in chat (correct number)', function () { - var document1 = { - meetingId: 'meeting001', - userId: 'user001', - user: { - name: 'Maxim', - }, - }; - var document2 = { - meetingId: 'meeting001', - userId: 'user002', - user: { - name: 'Anton', - }, - }; - var document3 = { - meetingId: 'meeting001', - userId: 'user003', - user: { - name: 'Danny', - }, - }; - - Users.insert(document1); - Users.insert(document2); - Users.insert(document3); - var div = renderUsersListTemplate(); - - expect($(div).find('.userNameEntry').size()).toEqual(3); - }); - - it( - 'should be able to reactively handle new and logged-out users ' + - '(1 user -> 3 users -> 4 users -> 2 users -> 5 users)', function () { - var document1 = { - meetingId: 'meeting001', - userId: 'user001', - user: { - name: 'Maxim', - }, - }; - var document2 = { - meetingId: 'meeting001', - userId: 'user002', - user: { - name: 'Anton', - }, - }; - var document3 = { - meetingId: 'meeting001', - userId: 'user003', - user: { - name: 'Danny', - }, - }; - var document4 = { - meetingId: 'meeting001', - userId: 'user004', - user: { - name: 'Chad', - }, - }; - var document5 = { - meetingId: 'meeting001', - userId: 'user005', - user: { - name: 'Fardad', - }, - }; - var document6 = { - meetingId: 'meeting001', - userId: 'user006', - user: { - name: 'Adam', - }, - }; - var document7 = { - meetingId: 'meeting001', - userId: 'user007', - user: { - name: 'Gary', - }, - }; - - Users.insert(document1); - var div = renderUsersListTemplate(); - - expect($(div).find('.userNameEntry').size()).toEqual(1); - expect($(div).find('.userNameEntry:eq(0)').html().trim()).toEqual('Maxim'); - - Users.insert(document2); - Users.insert(document3); - - expect($(div).find('.userNameEntry').size()).toEqual(3); - expect($(div).find('.userNameEntry:eq(0)').html().trim()).toEqual('Maxim'); - expect($(div).find('.userNameEntry:eq(1)').html().trim()).toEqual('Anton'); - expect($(div).find('.userNameEntry:eq(2)').html().trim()).toEqual('Danny'); - - Users.insert(document4); - - expect($(div).find('.userNameEntry').size()).toEqual(4); - expect($(div).find('.userNameEntry:eq(0)').html().trim()).toEqual('Maxim'); - expect($(div).find('.userNameEntry:eq(1)').html().trim()).toEqual('Anton'); - expect($(div).find('.userNameEntry:eq(2)').html().trim()).toEqual('Danny'); - expect($(div).find('.userNameEntry:eq(3)').html().trim()).toEqual('Chad'); - - removeUserFromCollection('user002'); - removeUserFromCollection('user004'); - - expect($(div).find('.userNameEntry').size()).toEqual(2); - expect($(div).find('.userNameEntry:eq(0)').html().trim()).toEqual('Maxim'); - expect($(div).find('.userNameEntry:eq(1)').html().trim()).toEqual('Danny'); - - Users.insert(document5); - Users.insert(document6); - Users.insert(document7); - - expect($(div).find('.userNameEntry:eq(0)').html().trim()).toEqual('Maxim'); - expect($(div).find('.userNameEntry:eq(1)').html().trim()).toEqual('Danny'); - expect($(div).find('.userNameEntry:eq(2)').html().trim()).toEqual('Fardad'); - expect($(div).find('.userNameEntry:eq(3)').html().trim()).toEqual('Adam'); - expect($(div).find('.userNameEntry:eq(4)').html().trim()).toEqual('Gary'); - }); - - it('should display usernames in the correct order', function () { - var document1 = { - meetingId: 'meeting001', - userId: 'user001', - user: { - name: 'Maxim', - }, - }; - var document2 = { - meetingId: 'meeting001', - userId: 'user002', - user: { - name: 'Anton', - }, - }; - var document3 = { - meetingId: 'meeting001', - userId: 'user003', - user: { - name: 'Danny', - }, - }; - - Users.insert(document1); - Users.insert(document2); - Users.insert(document3); - var div = renderUsersListTemplate(); - - expect($(div).find('.userNameEntry:eq(0)').html().trim()).toEqual('Maxim'); - expect($(div).find('.userNameEntry:eq(1)').html().trim()).toEqual('Anton'); - expect($(div).find('.userNameEntry:eq(2)').html().trim()).toEqual('Danny'); - }); - - it('should handle listen-only users properly', function () { - var document1 = { - meetingId: 'meeting001', - userId: 'user001', - user: { - name: 'Maxim', - }, - }; - var document2 = { - meetingId: 'meeting001', - userId: 'user002', - user: { - name: 'Anton', - listenOnly: true, - }, - }; - var document3 = { - meetingId: 'meeting001', - userId: 'user003', - user: { - name: 'Danny', - }, - }; - - Users.insert(document1); - Users.insert(document2); - Users.insert(document3); - var div = renderUsersListTemplate(); - - expect($(div).find('.glyphicon-headphones')).toBeDefined(); - }); -}); diff --git a/bigbluebutton-html5/tests/jasmine/client/integration/templates/whiteboard/whiteboardSpec.js b/bigbluebutton-html5/tests/jasmine/client/integration/templates/whiteboard/whiteboardSpec.js deleted file mode 100755 index 4275cd7de0b03500def2db82d2b53968ba8368e8..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/tests/jasmine/client/integration/templates/whiteboard/whiteboardSpec.js +++ /dev/null @@ -1,95 +0,0 @@ -var emptyMeetingsCollection = function () { - Meetings.find().map(function (item) { - Meetings.remove({ _id: item._id }); - }); -}; - -var emptyPresentationsCollection = function () { - Presentations.find().map(function (item) { - Presentations.remove({ _id: item._id }); - }); -}; - -var emptySlidesCollection = function () { - Slides.find().map(function (item) { - Slides.remove({ _id: item._id }); - }); -}; - -var emptyShapesCollection = function () { - Shapes.find().map(function (item) { - Shapes.remove({ _id: item._id }); - }); -}; - -var renderWhiteboardTemplate = function (title) { - var div = document.createElement('div'); - var data = {}; - data.id = 'whiteboard'; - data.title = title; - data.name = 'whiteboard'; - var comp = Blaze.renderWithData(Template.whiteboard, data); // loading data is optional - Blaze.insert(comp, div); - return div; -}; - -describe('whiteboard template', function () { - beforeEach(function () { - emptyMeetingsCollection(); - emptyPresentationsCollection(); - emptySlidesCollection(); - emptyShapesCollection(); - }); - - it('should contain a pencil icon inside the title entry', function () { - var div = renderWhiteboardTemplate('Whiteboard: default.pdf'); - - expect($(div).find('.title').find('.glyphicon-pencil')[0]).toBeDefined(); - }); - - it('should contain the correct title', function () { - var div = renderWhiteboardTemplate('Whiteboard: default.pdf'); - - expect($(div).find('.title:eq(0)').html()).toContain('Whiteboard: default.pdf'); - }); - - // TODO: finish the following - it('should be rendered successfully', function () { - var meeting1 = { - meetingId: 'meeting001', - meetingName: 'first meeting', - }; - Meetings.insert(meeting1); - - var presentation1 = { - meetingId: 'meeting001', - presentation: { - id: 'presentation001', - name: 'default.pdf', - current: true, - }, - }; - Presentations.insert(presentation1); - - var slide1 = { - meetingId: 'meeting001', - presentationId: 'presentation001', - slide: { - id: 'slide001', - num: 1, - current: true, - width_ratio: 100.0, - height_ratio: 100.0, - x_offset: 0.0, - y_offset: 0.0, - png_uri: 'http://bigbluebutton.org/wp-content/uploads/2013/05/bbb-overview.png', - }, - }; - Slides.insert(slide1); - - var div = document.createElement('DIV'); - Blaze.render(Template.main, div); - - expect($(div).find('#whiteboard-navbar')[0]).toBeDefined(); - }); -}); diff --git a/bigbluebutton-html5/tests/jasmine/client/unit/globalsSpec.js b/bigbluebutton-html5/tests/jasmine/client/unit/globalsSpec.js deleted file mode 100755 index e83236e850576cb3ce7d129c6313f1fe00c43a00..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/tests/jasmine/client/unit/globalsSpec.js +++ /dev/null @@ -1,11 +0,0 @@ -describe('Global getters', function () { - it('should correctly return current config information required by the footer', function () { - var returnedInfo = getBuildInformation(); - expect(returnedInfo.copyrightYear).toEqual('2014'); - expect(returnedInfo.bbbServerVersion).toEqual('0.9.0'); - expect(returnedInfo.dateOfBuild).toEqual('Sept 25, 2014'); - expect(returnedInfo.link).toEqual( - "<a href='http://bigbluebutton.org/' target='_blank'>http://bigbluebutton.org</a>" - ); - }); -}); diff --git a/bigbluebutton-html5/tests/jasmine/server/unit/CollectionMethodsSpec.js b/bigbluebutton-html5/tests/jasmine/server/unit/CollectionMethodsSpec.js deleted file mode 100755 index 1ca49dee84cb2a14f68d4c5d179636948fb2691b..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/tests/jasmine/server/unit/CollectionMethodsSpec.js +++ /dev/null @@ -1,746 +0,0 @@ -describe('Collections', function () { - beforeEach(function () { - MeteorStubs.install(); - }); - - afterEach(function () { - MeteorStubs.uninstall(); - }); - - //---------------------------------------------------------------------- - // publish.coffee - //---------------------------------------------------------------------- - - it('should all be correctly handled by remove() after calling clearCollections()', function () { - spyOn(Users, 'remove'); - spyOn(Chat, 'remove'); - spyOn(Meetings, 'remove'); - spyOn(Shapes, 'remove'); - spyOn(Slides, 'remove'); - spyOn(Presentations, 'remove'); - - clearUsersCollection(); - clearChatCollection(); - clearMeetingsCollection(); - clearShapesCollection(); - clearSlidesCollection(); - clearPresentationsCollection(); - - expect(Users.remove).toHaveBeenCalled(); - expect(Chat.remove).toHaveBeenCalled(); - expect(Meetings.remove).toHaveBeenCalled(); - expect(Shapes.remove).toHaveBeenCalled(); - expect(Slides.remove).toHaveBeenCalled(); - expect(Presentations.remove).toHaveBeenCalled(); - }); - - //---------------------------------------------------------------------- - // chat.coffee - //---------------------------------------------------------------------- - - it('should be handled correctly by insert() on calling addChatToCollection()' + - ' in case of private chat', function () { - spyOn(Users, 'findOne').and.callFake(function (doc) { - if (doc.userId == 'user001') return { userId: 'user001' }; - else if (doc.userId == 'user002') return { userUd: 'user002' }; - }); - - spyOn(Chat, 'insert'); - - addChatToCollection('meeting001', { - from_time: '123', - from_userid: 'user001', - to_userid: 'user002', - chat_type: 'PRIVATE_CHAT', - message: 'Hello!', - to_username: 'Anton', - from_tz_offset: '240', - from_color: '0x000000', - from_username: 'Maxim', - from_lang: 'en', - }); - - expect(Chat.insert).toHaveBeenCalledWith({ - meetingId: 'meeting001', - message: { - chat_type: 'PRIVATE_CHAT', - message: 'Hello!', - to_username: 'Anton', - from_tz_offset: '240', - from_color: '0x000000', - to_userid: 'user002',//not "dbid002" - from_userid: 'user001',//not "dbid001" - from_time: '123', - from_username: 'Maxim', - from_lang: 'en', - }, - }); - }); - - it('should be handled correctly by insert() on calling ' + - 'addChatToCollection() in case of public chat', function () { - spyOn(Users, 'findOne').and.callFake(function (doc) { - if (doc.userId == 'user001') return { _id: 'dbid001' }; - else if (doc.userId == 'user002') return { _id: 'dbid002' }; - }); - - spyOn(Chat, 'insert'); - - addChatToCollection('meeting001', { - from_time: '123', - from_userid: 'user001', - to_userid: 'public_chat_userid', - chat_type: 'PUBLIC_CHAT', - message: 'Hello!', - to_username: 'public_chat_username', - from_tz_offset: '240', - from_color: '0x000000', - from_username: 'Maxim', - from_lang: 'en', - }); - - expect(Chat.insert).toHaveBeenCalledWith({ - meetingId: 'meeting001', - message: { - chat_type: 'PUBLIC_CHAT', - message: 'Hello!', - to_username: 'public_chat_username', - from_tz_offset: '240', - from_color: '0x000000', - to_userid: 'public_chat_userid', - from_userid: 'user001', - from_time: '123', - from_username: 'Maxim', - from_lang: 'en', - }, - }); - }); - - //---------------------------------------------------------------------- - // meetings.coffee - //---------------------------------------------------------------------- - - it( - 'should not be updated on calling addMeetingToCollection() if ' + - 'the meeting is already in the collection', function () { - spyOn(Meetings, 'findOne').and.callFake(function (doc) { - if (doc.meetingId == 'meeting001') return { meetingId: 'meeting001' }; - else return undefined; - }); - - spyOn(Meetings, 'insert'); - - addMeetingToCollection('meeting001', 'Demo Meeting', false, '12345', '0'); - - expect(Meetings.insert).not.toHaveBeenCalled(); - }); - - it( - 'should be handled correctly by insert() on calling addMeetingToCollection() ' + - 'with a brand new meeting', function () { - spyOn(Meetings, 'findOne').and.returnValue(undefined);//collection is empty - spyOn(Meetings, 'insert'); - - addMeetingToCollection('meeting001', 'Demo Meeting', false, '12345', '0'); - - expect(Meetings.insert).toHaveBeenCalledWith({ - meetingId: 'meeting001', - meetingName: 'Demo Meeting', - intendedForRecording: false, - currentlyBeingRecorded: false,//default value - voiceConf: '12345', - duration: '0', - }); - }); - - it( - 'should not be touched on calling removeMeetingFromCollection() ' + - 'if there is no wanted meeting in the collection', function () { - spyOn(Meetings, 'findOne').and.returnValue(undefined);//collection is empty - spyOn(Meetings, 'remove'); - - removeMeetingFromCollection('meeting001'); - - expect(Meetings.remove).not.toHaveBeenCalled(); - }); - - //TODO: emulate a find() call - /*it("should be correctly updated after the removeMeetingFromCollection() call", function () { - spyOn(Meetings, "findOne").and.callFake(function(doc) { - if(doc.meetingId == "meeting001") return { _id: "id001", meetingId: "meeting001" }; - else return undefined; - }); - - spyOn(Meetings, "remove"); - - removeMeetingFromCollection("meeting001"); - - expect(Meetings.remove).toHaveBeenCalled(); - });*/ - - //---------------------------------------------------------------------- - // shapes.coffee - //---------------------------------------------------------------------- - - // addShapeToCollection() - it( - 'should be handled correctly by insert() on calling addShapeToCollection() ' + - 'with a text', function () { - spyOn(Shapes, 'find').and.returnValue({ - count: function () { - return 1; - }, - }); - spyOn(Shapes, 'insert'); - - addShapeToCollection('meeting001', 'whiteboard001', { - shape_type: 'text', - status: 'textPublished', - shape: { - type: 'text', - textBoxHeight: 24.5, - backgroundColor: 16777215, - fontColor: 0, - status: 'textPublished', - dataPoints: '36.5,55.0', - x: 36.5, - textBoxWidth: 36.0, - whiteboardId: 'whiteboard001', - fontSize: 18, - id: 'shape001', - y: 55.0, - calcedFontSize: 3.6, - text: 'Hello World!', - background: true, - }, - }); - - expect(Shapes.insert).toHaveBeenCalledWith({ - meetingId: 'meeting001', - whiteboardId: 'whiteboard001', - shape: { - type: 'text', - textBoxHeight: 24.5, - backgroundColor: 16777215, - fontColor: 0, - status: 'textPublished', - dataPoints: '36.5,55.0', - x: 36.5, - textBoxWidth: 36.0, - whiteboardId: 'whiteboard001', - fontSize: 18, - id: 'shape001', - y: 55.0, - calcedFontSize: 3.6, - text: 'Hello World!', - background: true, - }, - }); - }); - - it( - 'should be handled correctly by insert() on calling addShapeToCollection() with a ' + - 'finished standard shape', function () { - spyOn(Shapes, 'find').and.returnValue({ - count: function () { - return 1; - }, - }); - spyOn(Shapes, 'insert'); - - addShapeToCollection('meeting001', 'whiteboard001', { - wb_id: 'whiteboard001', - shape_type: 'rectangle', - status: 'DRAW_END', - id: 'shape001', - shape: { - type: 'rectangle', - status: 'DRAW_END', - points: [60.0, 17.0, 73.0, 57.5], - whiteboardId: 'whiteboard001', - id: 'shape001', - square: false, - transparency: false, - thickness: 10, - color: 0, - }, - }); - - expect(Shapes.insert).toHaveBeenCalledWith({ - meetingId: 'meeting001', - whiteboardId: 'whiteboard001', - shape: { - wb_id: 'whiteboard001', - shape_type: 'rectangle', - status: 'DRAW_END', - id: 'shape001', - shape: { - type: 'rectangle', - status: 'DRAW_END', - points: [60.0, 17.0, 73.0, 57.5], - whiteboardId: 'whiteboard001', - id: 'shape001', - square: false, - transparency: false, - thickness: 10, - color: 0, - }, - }, - }); - }); - - it( - 'should be handled correctly by insert() on calling addShapeToCollection() ' + - 'with a pencil being used', function () { - spyOn(Shapes, 'find').and.returnValue({ - count: function () { - return 1; - }, - }); - spyOn(Shapes, 'insert'); - - addShapeToCollection('meeting001', 'whiteboard001', { - wb_id: 'whiteboard001', - shape_type: 'pencil', - status: 'DRAW_START', - id: 'shape001', - shape: { - type: 'pencil', - status: 'DRAW_START', - points: [35.8, 63.6, 36.1, 63.4, 36.2, 63.2], - whiteboardId: 'whiteboard001', - id: 'shape001', - square: undefined, - transparency: false, - thickness: 10, - color: 0, - }, - }); - - expect(Shapes.insert).toHaveBeenCalledWith({ - meetingId: 'meeting001', - whiteboardId: 'whiteboard001', - shape: { - wb_id: 'whiteboard001', - shape_type: 'pencil', - status: 'DRAW_START', - id: 'shape001', - shape: { - type: 'pencil', - status: 'DRAW_START', - points: [35.8, 63.6, 36.1, 63.4, 36.2, 63.2], - whiteboardId: 'whiteboard001', - id: 'shape001', - square: undefined, - transparency: false, - thickness: 10, - color: 0, - }, - }, - }); - }); - - // removeAllShapesFromSlide() - it( - 'should not be touched on calling removeAllShapesFromSlide() ' + - 'with undefined meetingId', function () { - spyOn(Shapes, 'remove'); - removeAllShapesFromSlide(undefined, 'whiteboard001'); - expect(Shapes.remove).not.toHaveBeenCalled(); - }); - - it( - 'should not be touched on calling removeAllShapesFromSlide() ' + - 'with undefined whiteboardId', function () { - spyOn(Shapes, 'remove'); - removeAllShapesFromSlide('meeting001', undefined); - expect(Shapes.remove).not.toHaveBeenCalled(); - }); - - it( - 'should not be touched on calling removeAllShapesFromSlide() ' + - 'if there is no shapes on the whiteboard', function () { - spyOn(Shapes, 'find').and.returnValue(undefined); - spyOn(Shapes, 'remove'); - removeAllShapesFromSlide('meeting001', 'whiteboard001'); - expect(Shapes.remove).not.toHaveBeenCalled(); - }); - - it( - 'should be cleared on calling removeAllShapesFromSlide() ' + - 'if there are shapes on the whiteboard', function () { - spyOn(Shapes, 'find').and.callFake(function (doc) { - if (doc.meetingId === 'meeting001' && doc.whiteboardId === 'whiteboard001') - return { - fetch: function () { - return [{ shape: { id: 'shape001' } }]; - }, - }; - else return undefined; - }); - - spyOn(Shapes, 'findOne').and.callFake(function (doc) { - if ( - doc.meetingId === 'meeting001' && - doc.whiteboardId === 'whiteboard001' && - doc['shape.id'] === 'shape001' - ) - return { - _id: 'doc001', - }; - else return undefined; - }); - - spyOn(Shapes, 'remove'); - removeAllShapesFromSlide('meeting001', 'whiteboard001'); - expect(Shapes.remove).toHaveBeenCalledWith('doc001'); - }); - - // removeShapeFromSlide() - it( - 'should not be touched on calling removeShapeFromSlide() ' + - 'with undefined meetingId', function () { - spyOn(Shapes, 'find').and.callFake(function (doc) { - if (doc.meetingId === undefined && doc.whiteboardId === 'whiteboard001') - return { - count: function () { - return 0; - }, - }; - else return undefined; - }); - - spyOn(Shapes, 'findOne').and.callFake(function (doc) { - if ( - doc.meetingId === undefined && - doc.whiteboardId === 'whiteboard001' && - doc['shape.id'] === 'shape001' - ) - return { - _id: 'doc001', - }; - else return undefined; - }); - - spyOn(Shapes, 'remove'); - - removeShapeFromSlide(undefined, 'whiteboard001', 'shape001'); - - expect(Shapes.remove).not.toHaveBeenCalled(); - }); - - it( - 'should not be touched on calling removeShapeFromSlide() ' + - 'with undefined whiteboardId', function () { - spyOn(Shapes, 'find').and.callFake(function (doc) { - if (doc.meetingId === 'meeting001' && doc.whiteboardId === undefined) - return { - count: function () { - return 0; - }, - }; - else return undefined; - }); - - spyOn(Shapes, 'findOne').and.callFake(function (doc) { - if ( - doc.meetingId === 'meeting001' && - doc.whiteboardId === undefined && - doc['shape.id'] === 'shape001' - ) - return { - _id: 'doc001', - }; - else return undefined; - }); - - spyOn(Shapes, 'remove'); - - removeShapeFromSlide('meeting001', undefined, 'shape001'); - - expect(Shapes.remove).not.toHaveBeenCalled(); - }); - - it( - 'should not be touched on calling removeShapeFromSlide() ' + - 'with undefined shapeId', function () { - spyOn(Shapes, 'find').and.callFake(function (doc) { - if (doc.meetingId === 'meeting001' && doc.whiteboardId === 'whiteboard001') - return { - count: function () { - return 0; - }, - }; - else return undefined; - }); - - spyOn(Shapes, 'findOne').and.callFake(function (doc) { - if ( - doc.meetingId === 'meeting001' && - doc.whiteboardId === 'whiteboard001' && - doc['shape.id'] === undefined - ) - return { - _id: 'doc001', - }; - else return undefined; - }); - - spyOn(Shapes, 'remove'); - - removeShapeFromSlide('meeting001', 'whiteboard001', undefined); - - expect(Shapes.remove).not.toHaveBeenCalled(); - }); - - it( - 'should not be touched on calling removeShapeFromSlide() ' + - 'if there is no wanted shape on the whiteboard', function () { - spyOn(Shapes, 'find').and.callFake(function (doc) { - if (doc.meetingId === 'meeting001' && doc.whiteboardId === 'whiteboard001') - return { - count: function () { - return 0; - }, - }; - else return undefined; - }); - - spyOn(Shapes, 'findOne').and.callFake(function (doc) { - if ( - doc.meetingId === 'meeting001' && - doc.whiteboardId === 'whiteboard001' && - doc['shape.id'] === 'shape001' - ) - return undefined; - else return { - _id: 'doc001', - }; - }); - - spyOn(Shapes, 'remove'); - - removeShapeFromSlide('meeting001', 'whiteboard001', undefined); - - expect(Shapes.remove).not.toHaveBeenCalled(); - }); - - it( - 'should be updated correctly on calling removeShapeFromSlide() ' + - 'with an existing shape', function () { - spyOn(Shapes, 'find').and.callFake(function (doc) { - if (doc.meetingId === 'meeting001' && doc.whiteboardId === 'whiteboard001') - return { - count: function () { - return 0; - }, - }; - else return undefined; - }); - - spyOn(Shapes, 'findOne').and.callFake(function (doc) { - if ( - doc.meetingId === 'meeting001' && - doc.whiteboardId === 'whiteboard001' && - doc['shape.id'] === 'shape001' - ) - return { - _id: 'doc001', - }; - else return undefined; - }); - - spyOn(Shapes, 'remove'); - removeShapeFromSlide('meeting001', 'whiteboard001', 'shape001'); - expect(Shapes.remove).toHaveBeenCalledWith('doc001'); - }); - - //---------------------------------------------------------------------- - // presentation.coffee - //---------------------------------------------------------------------- - - it( - 'should be handled correctly by insert() ' + - 'on calling addPresentationToCollection()', function () { - spyOn(Presentations, 'findOne').and.returnValue(undefined); - - spyOn(Presentations, 'insert'); - - addPresentationToCollection('meeting001', { - id: 'presentation001', - name: 'Presentation 001', - current: true, - }); - - expect(Presentations.insert).toHaveBeenCalledWith({ - meetingId: 'meeting001', - presentation: { - id: 'presentation001', - name: 'Presentation 001', - current: true, - }, - pointer: { - x: 0.0, - y: 0.0, - }, - }); - }); - - it( - 'should be handled correctly on calling addPresentationToCollection() ' + - 'when presentation is already in the collection', function () { - spyOn(Presentations, 'findOne').and.returnValue({ _id: 'dbid001' }); - - spyOn(Presentations, 'insert'); - - addPresentationToCollection('meeting001', { - id: 'presentation001', - name: 'Presentation 001', - current: true, - }); - - expect(Presentations.insert).not.toHaveBeenCalledWith({ - meetingId: 'meeting001', - presentation: { - id: 'presentation001', - name: 'Presentation 001', - current: true, - }, - pointer: { - x: 0.0, - y: 0.0, - }, - }); - }); - - it( - 'should be handled correctly by remove() ' + - 'on calling removePresentationFromCollection', function () { - spyOn(Presentations, 'findOne').and.returnValue({ _id: 'dbid001' }); - spyOn(Presentations, 'remove'); - - removePresentationFromCollection('meeting0001', 'presentation001'); - - expect(Presentations.remove).toHaveBeenCalled(); - }); - - it( - 'should be handled correctly by remove() ' + - 'on calling removePresentationFromCollection', function () { - spyOn(Presentations, 'findOne').and.returnValue(undefined); - spyOn(Presentations, 'remove'); - - removePresentationFromCollection('meeting0001', 'presentation001'); - - expect(Presentations.remove).not.toHaveBeenCalled(); - }); - - //---------------------------------------------------------------------- - // slides.coffee - //---------------------------------------------------------------------- - - // removeSlideFromCollection() - it( - 'should not be touched on calling removeSlideFromCollection() ' + - 'with undefined meetingId', function () { - spyOn(Slides, 'remove'); - removeSlideFromCollection(undefined, 'presentation001/2'); - expect(Slides.remove).not.toHaveBeenCalled(); - }); - - it( - 'should not be touched on calling removeSlideFromCollection() ' + - 'with undefined slideId', function () { - spyOn(Slides, 'remove'); - removeSlideFromCollection('meeting001', undefined); - expect(Slides.remove).not.toHaveBeenCalled(); - }); - - it( - 'should not be touched on calling removeSlideFromCollection() ' + - 'with a slide that does not exist', function () { - spyOn(Slides, 'findOne').and.callFake(function (doc) { - if (doc.meetingId === 'meeting001' && doc['slide.id'] === 'slide001') - return undefined; - else return { meetingId: 'meeting001' }; - }); - - spyOn(Slides, 'remove'); - removeSlideFromCollection('meeting001', 'slide001'); - expect(Slides.remove).not.toHaveBeenCalled(); - }); - - it( - 'should be handled correctly by remove() on calling removeSlideFromCollection() ' + - 'with an existing slide', function () { - spyOn(Slides, 'findOne').and.callFake(function (doc) { - if (doc.meetingId === 'meeting001' && doc['slide.id'] === 'slide001') - return { _id: 'doc001' }; - else return undefined; - }); - - spyOn(Slides, 'remove'); - removeSlideFromCollection('meeting001', 'slide001'); - expect(Slides.remove).toHaveBeenCalledWith('doc001'); - }); - - // addSlideToCollection() - it( - 'should not be touched on calling addSlideToCollection() ' + - 'if the slide is already in the collection', function () { - spyOn(Slides, 'findOne').and.callFake(function (doc) { - if (doc.meetingId === 'meeting001' && doc['slide.id'] === 'presentation001/2') - return { _id: 'doc001' }; - else return undefined; - }); - - spyOn(Slides, 'insert'); - addSlideToCollection('meeting001', 'presentation001', { - id: 'presentation001/2', - }); - expect(Slides.insert).not.toHaveBeenCalled(); - }); - - it( - 'should be handled correctly by insert() on calling addSlideToCollection() ' + - 'with a brand new slide', function () { - spyOn(Slides, 'findOne').and.callFake(function (doc) { - if (doc.meetingId === 'meeting001' && doc['slide.id'] === 'presentation001/2') - return undefined; - else return { _id: 'doc001' }; - }); - - spyOn(Slides, 'insert'); - addSlideToCollection('meeting001', 'presentation001', { - height_ratio: 100, - y_offset: 0, - num: 2, - x_offset: 0, - current: true, - png_uri: 'http://localhost/bigbluebutton/presentation/presentation001/png/2', - txt_uri: 'http://localhost/bigbluebutton/presentation/presentation001/textfiles/slide-2.txt', - id: 'presentation001/2', - width_ratio: 100, - swf_uri: 'http://localhost/bigbluebutton/presentation/presentation001/slide/2', - thumb_uri: 'http://localhost/bigbluebutton/presentation/presentation001/thumbnail/1', - }); - expect(Slides.insert).toHaveBeenCalledWith({ - meetingId: 'meeting001', - presentationId: 'presentation001', - slide: { - height_ratio: 100, - y_offset: 0, - num: 2, - x_offset: 0, - current: true, - png_uri: 'http://localhost/bigbluebutton/presentation/presentation001/png/2', - txt_uri: 'http://localhost/bigbluebutton/presentation/presentation001/textfiles/' + - 'slide-2.txt', - id: 'presentation001/2', - width_ratio: 100, - swf_uri: 'http://localhost/bigbluebutton/presentation/presentation001/slide/2', - thumb_uri: 'http://localhost/bigbluebutton/presentation/presentation001/thumbnail/1', - }, - }); - }); -}); diff --git a/bigbluebutton-html5/tests/jasmine/server/unit/config-stubs.js b/bigbluebutton-html5/tests/jasmine/server/unit/config-stubs.js deleted file mode 100644 index 83ddbb1184c4b9884825639c21d23840fda37f80..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/tests/jasmine/server/unit/config-stubs.js +++ /dev/null @@ -1,12 +0,0 @@ -/* - Stub the logger -*/ - -Logger = {}; -Logger.prototype = { - constructor: Logger, -}; -Logger.info = function () {}; - -//Meteor.log = Logger; //TODO this should import logger - diff --git a/bigbluebutton-html5/tests/nightwatch/chatting.js b/bigbluebutton-html5/tests/nightwatch/chatting.js deleted file mode 100755 index 09b9b14919aedf0f00320009d3ee62f77ffaaa58..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/tests/nightwatch/chatting.js +++ /dev/null @@ -1,71 +0,0 @@ -module.exports = { - 'Welcome message title in the public chat of Demo Meeting is correct': function (browser) { - browser - .url('http://192.168.244.140:4000') - .waitForElementVisible('body', 1000) - .assert.visible('input[ng-model=username]') - .setValue('input[ng-model=username]', ['Maxim', browser.Keys.ENTER]) - .waitForElementVisible('#chatbody .chat li:last-of-type', 10000) - .verify.containsText('#chatbody .chat li:last-of-type div', 'Welcome to Demo Meeting') - .deleteCookies() - .closeWindow() - .end(); - }, - - 'Public chat`s welcome message title in the non-default meeting is correct': function (browser) { - browser - .url('http://192.168.244.140:4000') - .waitForElementVisible('body', 1000) - .assert.visible('input[ng-model=username]') - .setValue('input[ng-model=username]', 'Maxim') - .assert.visible('input[ng-model=meetingName]') - .setValue('input[ng-model=meetingName]', ['Meeting1', browser.Keys.ENTER]) - .waitForElementVisible('#chatbody .chat li:last-of-type', 10000) - .verify.containsText('#chatbody .chat li:last-of-type div', 'Welcome to Meeting1') - .deleteCookies() - .closeWindow() - .end(); - }, - - 'Sending a message in a public chat using Enter': function (browser) { - browser - .url('http://192.168.244.140:4000') - .waitForElementVisible('body', 1000) - .assert.visible('input[ng-model=username]') - .setValue('input[ng-model=username]', ['Maxim', browser.Keys.ENTER]) - .waitForElementVisible('#newMessageInput', 10000) - .setValue( - '#newMessageInput', - ['this message is to be sent via Enter key', browser.Keys.ENTER] - ) - .pause(500) - .verify.containsText( - '#chatbody .chat li:last-of-type div', - 'this message is to be sent via Enter key' - ) - .verify.containsText('#chatbody .chat li:nth-last-of-type(2) div', 'Welcome to Demo Meeting') - .deleteCookies() - .closeWindow() - .end(); - }, - - 'Sending a message in a public chat using Send button': function (browser) { - browser - .url('http://192.168.244.140:4000') - .waitForElementVisible('body', 1000) - .assert.visible('input[ng-model=username]') - .setValue('input[ng-model=username]', ['Maxim', browser.Keys.ENTER]) - .waitForElementVisible('#newMessageInput', 10000) - .setValue('#newMessageInput', 'this message is to be sent via Send button') - .click('#sendMessageButton') - .pause(500) - .verify.containsText( - '#chatbody .chat li:last-of-type div', - 'this message is to be sent via Send button' - ) - .verify.containsText('#chatbody .chat li:nth-last-of-type(2) div', 'Welcome to Demo Meeting') - .deleteCookies() - .closeWindow() - .end(); - }, -}; diff --git a/bigbluebutton-html5/tests/nightwatch/loggingInOut.js b/bigbluebutton-html5/tests/nightwatch/loggingInOut.js deleted file mode 100755 index caa6592bf5e06a5fbb96cd89a82ce21ab99150ea..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/tests/nightwatch/loggingInOut.js +++ /dev/null @@ -1,60 +0,0 @@ -module.exports = { - 'Logging into Demo Meeting using Enter key': function (browser) { - browser - .url('http://192.168.244.140:4000') - .waitForElementVisible('body', 1000) - .assert.visible('input[ng-model=username]') - .setValue('input[ng-model=username]', ['Maxim', browser.Keys.ENTER]) - .waitForElementVisible('body #main', 10000) - .verify.urlEquals('http://192.168.244.140:3000/') - .waitForElementVisible('.navbarTitle span', 1000) - .verify.containsText('.navbarTitle span', 'Demo Meeting') - .deleteCookies() - .closeWindow() - .end(); - }, - - 'Logging into Demo Meeting using Send button': function (browser) { - browser - .url('http://192.168.244.140:4000') - .waitForElementVisible('body', 1000) - .assert.visible('input[ng-model=username]') - .setValue('input[ng-model=username]', 'Maxim') - .click('input.success') - .waitForElementVisible('body #main', 10000) - .verify.urlEquals('http://192.168.244.140:3000/') - .waitForElementVisible('.navbarTitle span', 1000) - .verify.containsText('.navbarTitle span', 'Demo Meeting') - .deleteCookies() - .closeWindow() - .end(); - }, - - 'Logging into a meeting with non-default name': function (browser) { - browser - .url('http://192.168.244.140:4000') - .waitForElementVisible('body', 1000) - .assert.visible('input[ng-model=username]') - .setValue('input[ng-model=username]', 'Maxim') - .assert.visible('input[ng-model=meetingName]') - .setValue('input[ng-model=meetingName]', ['Meeting1', browser.Keys.ENTER]) - .waitForElementVisible('.navbarTitle span', 10000) - .verify.containsText('.navbarTitle span', 'Meeting1') - .deleteCookies() - .closeWindow() - .end(); - }, - - 'Loading the presentation': function (browser) { - browser - .url('http://192.168.244.140:4000') - .waitForElementVisible('body', 1000) - .assert.visible('input[ng-model=username]') - .setValue('input[ng-model=username]', ['Maxim', browser.Keys.ENTER]) - .waitForElementVisible('#whiteboard-paper', 10000) - .waitForElementVisible('#whiteboard-paper > #svggroup', 30000) - .deleteCookies() - .closeWindow() - .end(); - }, -}; diff --git a/bigbluebutton-html5/tests/nightwatch/scaling.js b/bigbluebutton-html5/tests/nightwatch/scaling.js deleted file mode 100755 index f828ab147526437f8606ca98cc193643687472b4..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/tests/nightwatch/scaling.js +++ /dev/null @@ -1,69 +0,0 @@ -module.exports = { - 'Checking navbar`s height while scaling if there is a long meeting name ': function (browser) { - var longMeetingName = new Array(101).join('x'); // 100-element array of 'x' - browser - .url('http://192.168.244.140:4000') - .resizeWindow(1920, 1080) - .waitForElementVisible('body', 1000) - .assert.visible('input[ng-model=username]') - .setValue('input[ng-model=username]', 'Maxim') - .assert.visible('input[ng-model=meetingName]') - .setValue('input[ng-model=meetingName]', [longMeetingName, browser.Keys.ENTER]) - .waitForElementVisible('#navbar', 10000) - .getElementSize('#navbar', function (result1) { - _this = this; - for (var w = 1900; w >= 100; w -= 100) { - _this = _this - .resizeWindow(w, 1080) - .getElementSize('#navbar', function (result2) { - this.verify.equal(result2.value.height, result1.value.height); - }); - } - - for (var w = 100; w <= 1900; w += 100) { - _this = _this - .resizeWindow(w, 1080) - .getElementSize('#navbar', function (result2) { - this.verify.equal(result2.value.height, result1.value.height); - }); - } - }) - .deleteCookies() - .closeWindow() - .end(); - }, - - 'Checking the margin between the navbar and the top while scaling horizont': function (browser) { - var longMeetingName = new Array(101).join('x'); // 100-element array of 'x' - browser - .url('http://192.168.244.140:4000') - .resizeWindow(1920, 1080) - .waitForElementVisible('body', 1000) - .assert.visible('input[ng-model=username]') - .setValue('input[ng-model=username]', 'Maxim') - .assert.visible('input[ng-model=meetingName]') - .setValue('input[ng-model=meetingName]', [longMeetingName, browser.Keys.ENTER]) - .waitForElementVisible('#navbar', 10000) - .getLocation('#whiteboard-navbar', function (result1) { - _this = this; - for (var w = 1000; w >= 100; w -= 100) { - _this = _this - .resizeWindow(w, 1080) - .getLocation('#whiteboard-navbar', function (result2) { - this.verify.equal(result2.value.y, result1.value.y); - }); - } - - for (var w = 100; w <= 100; w += 100) { - _this = _this - .resizeWindow(w, 1080) - .getLocation('#whiteboard-navbar', function (result2) { - this.verify.equal(result2.value.y, result1.value.y); - }); - } - }) - .deleteCookies() - .closeWindow() - .end(); - }, -}; diff --git a/bigbluebutton-html5/tests/webdriverio/INSTALL.md b/bigbluebutton-html5/tests/webdriverio/INSTALL.md new file mode 100644 index 0000000000000000000000000000000000000000..7ecd165f45c3086e9422f31994f4bc431e0775be --- /dev/null +++ b/bigbluebutton-html5/tests/webdriverio/INSTALL.md @@ -0,0 +1,91 @@ +# Acceptance Testing in HTML Client. Getting Started + +The test suite for HTML5 client is currently under active development. The following instructions will help you install all the necessary tools and libraries to run the exiting specs and start writing your own tests. + +## Run Selenium Server + +Assuming that you have the BigBlueButton repository in `/home/firstuser/dev`, navigate to the directory containing acceptance tests: +```sh +$ cd /home/firstuser/dev/bigbluebutton/bigbluebutton-html5/tests/webdriverio +``` + +Now, you should navigate to the `tools` directory inside `webdriverio`. This folder will store all the Selenium- and browser-related third-party files that you need to download. + +Download Selenium jar file: +```sh +$ curl -O http://selenium-release.storage.googleapis.com/3.4/selenium-server-standalone-3.4.0.jar +``` + +and browser-specific WebDriver server. + +Firefox WebDriver (GeckoDriver): +```sh +$ curl -L https://github.com/mozilla/geckodriver/releases/download/v0.16.1/geckodriver-v0.16.1-linux64.tar.gz | tar xz +``` + +Chrome WebDriver (ChromeDriver): +```sh +$ wget https://chromedriver.storage.googleapis.com/2.29/chromedriver_linux64.zip +$ unzip chromedriver_linux64.zip +``` + +Along with the WebDriver, you need to install the browser itself. + +How to install Chrome: +```sh +$ wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - +$ sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' +$ sudo apt-get update +$ sudo apt-get install google-chrome-stable +``` + +How to install Firefox: +```sh +$ wget sourceforge.net/projects/ubuntuzilla/files/mozilla/apt/pool/main/f/firefox-mozilla-build/firefox-mozilla-build_53.0.3-0ubuntu1_amd64.deb +$ sudo dpkg -i firefox-mozilla-build_53.0.3-0ubuntu1_amd64.deb +``` + +In order to run headless browser, we will use Xvfb display server: +```sh +$ sudo apt-get install xvfb +``` + +At this point, you can run the Selenium server (replace `./geckodriver` with `./chromedriver` if you use Chrome): +```sh +$ xvfb-run java -jar selenium-server-standalone-3.4.0.jar +``` + +If you get an error `Xvfb failed to start`, run it with an `-a` option (Xvfb will use another display if the current one is already in use): +```sh +$ xvfb-run -a java -jar selenium-server-standalone-3.4.0.jar +``` + +Congratulations! You have Selenium server up and running. It is ready to handle your test cases. Now, keep the `xvfb-run` process running and continue in a new terminal session. + +## Run the test specs + +We use WebdriverIO interface to write the acceptance test cases. In order to execute the existing tests, you need to use `wdio` test runner. By default, it will look into any `*.spec.js` file inside the `/home/firstuser/dev/bigbluebutton/bigbluebutton-html5/tests/webdriverio/specs` directory. You can change the location of the test specs by modifying the `wdio` config file: `wdio.conf.js` (inside the `webdriverio` directory). + +Before proceeding any further, make sure HTML5 client is up and running. +Node.js installation is also required: + +```sh +$ sudo apt-get install nodejs-legacy +``` + +You can run all of the existing test specs with a single npm command: + +```sh +$ cd /home/firstuser/dev/bigbluebutton/bigbluebutton-html5 +$ npm run test +``` + +### Test suites + +To make it easier to run a single specific set of tests, we group the specs into test suits. All the suits are defined in `wdio.conf.js`. + +To run a single test suite, you need to pass its name to the npm script: +```sh +$ npm run test -- --suite login +``` + diff --git a/bigbluebutton-html5/tests/webdriverio/pageobjects/landing.page.js b/bigbluebutton-html5/tests/webdriverio/pageobjects/landing.page.js new file mode 100644 index 0000000000000000000000000000000000000000..d93adeddadff045c273985c49b8da20d913a631b --- /dev/null +++ b/bigbluebutton-html5/tests/webdriverio/pageobjects/landing.page.js @@ -0,0 +1,49 @@ +'use strict'; + +let Page = require('./page'); +let pageObject = new Page(); + +class LandingPage extends Page { + open() { + super.open('demo/demoHTML5.jsp'); + } + + get title() { + return 'Join Meeting via HTML5 Client'; + } + + get url() { + return 'http://localhost:8080/demo/demoHTML5.jsp'; + } + + get username() { + return $('input[name=username]'); + } + + get joinButton() { + return $('input[type=submit]'); + } + + joinWithButtonClick() { + this.joinButton.click(); + } + + joinWithEnterKey() { + pageObject.pressEnter(); + } + + get loadedHomePage() { + return $('#app'); + } +} + +// To use in the future tests that will require login +browser.addCommand('loginToClient', function (page) { + page.open(); + page.username.waitForExist(); + page.username.setValue('Maxim'); + page.joinWithButtonClick(); +}); + +module.exports = new LandingPage(); + diff --git a/bigbluebutton-html5/tests/webdriverio/pageobjects/page.js b/bigbluebutton-html5/tests/webdriverio/pageobjects/page.js new file mode 100644 index 0000000000000000000000000000000000000000..5bd871a89d49236687e663fc479a5f7a3374a8e7 --- /dev/null +++ b/bigbluebutton-html5/tests/webdriverio/pageobjects/page.js @@ -0,0 +1,18 @@ +'use strict'; + +class Page { + open(path) { + browser.url(path); + } + + pressEnter() { + browser.keys('Enter'); + } + + isFirefox() { + return browser.desiredCapabilities.browserName == 'firefox'; + } +} + +module.exports = Page; + diff --git a/bigbluebutton-html5/tests/webdriverio/specs/login.spec.js b/bigbluebutton-html5/tests/webdriverio/specs/login.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..8680daeb450a86f3b537394239312ffc22c1e629 --- /dev/null +++ b/bigbluebutton-html5/tests/webdriverio/specs/login.spec.js @@ -0,0 +1,57 @@ +'use strict'; + +let LandingPage = require('../pageobjects/landing.page'); +let chai = require('chai'); + +describe('Landing page', function () { + it('should have correct title', function () { + LandingPage.open(); + chai.expect(browser.getTitle()).to.equal(LandingPage.title); + }); + + it('should allow user to login if the username is specified and the Join button is clicked', + function () { + LandingPage.open(); + LandingPage.username.waitForExist(); + LandingPage.username.setValue('Maxim'); + LandingPage.joinWithButtonClick(); + LandingPage.loadedHomePage.waitForExist(5000); + }); + + it('should not allow user to login if the username is not specified (login using a button)', + function () { + LandingPage.open(); + + // we intentionally don't enter username here + + LandingPage.joinWithButtonClick(); + + browser.pause(5000); // amount of time we usually wait for the home page to appear + + // verify that we are still on the landing page + chai.expect(browser.getUrl()).to.equal(LandingPage.url); + }); + + if (!LandingPage.isFirefox()) { + it('should allow user to login if the username is specified and then Enter key is pressed', + function () { + LandingPage.open(); + LandingPage.username.waitForExist(); + LandingPage.username.setValue('Maxim'); + LandingPage.joinWithEnterKey(); + LandingPage.loadedHomePage.waitForExist(5000); + }); + + it('should not allow user to login if the username is not specified (login using Enter key)', + function () { + LandingPage.open(); + + // we intentionally don't enter username here + + LandingPage.joinWithEnterKey(); + browser.pause(5000); // amount of time we usually wait for the gome page to appear + chai.expect(browser.getUrl()).to.equal(LandingPage.url); + }); + } +}); + diff --git a/bigbluebutton-html5/tests/webdriverio/tools/.gitkeep b/bigbluebutton-html5/tests/webdriverio/tools/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bigbluebutton-html5/tests/webdriverio/wdio.conf.js b/bigbluebutton-html5/tests/webdriverio/wdio.conf.js new file mode 100644 index 0000000000000000000000000000000000000000..bd5d50e992b2640f294e92ad23bcccc4ec1a1325 --- /dev/null +++ b/bigbluebutton-html5/tests/webdriverio/wdio.conf.js @@ -0,0 +1,23 @@ +exports.config = { + specs: ['tests/webdriverio/specs/**/*.spec.js'], + capabilities: [ + { + browserName: 'chrome', + }, + ], + baseUrl: 'http://localhost:8080', + framework: 'jasmine', + reporters: ['spec', 'junit'], + reporterOptions: { + junit: { + outputDir: './tests/webdriverio/reports', + }, + }, + screenshotPath: 'screenshots', + suites: { + login: [ + 'tests/webdriverio/specs/login.spec.js', + ], + }, +}; +