From d497ad33694633d40e4768fd1dbbdfa04bdafe6e Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 11 May 2017 17:27:02 -0600 Subject: [PATCH 01/16] initial pagination rewrite, cleanups to comment edit --- client/coral-framework/translations.json | 2 +- errors.js | 13 +- graph/loaders/assets.js | 31 +- graph/loaders/comments.js | 34 +- graph/mutators/action.js | 20 +- graph/mutators/comment.js | 233 +++--- graph/mutators/user.js | 16 +- graph/resolvers/asset.js | 2 +- graph/typeDefs.graphql | 43 +- package.json | 6 +- services/comments.js | 149 ++-- test/server/graph/mutations/editComment.js | 11 +- test/server/graph/queries/asset.js | 113 +-- yarn.lock | 791 +++++++++++---------- 14 files changed, 721 insertions(+), 743 deletions(-) diff --git a/client/coral-framework/translations.json b/client/coral-framework/translations.json index 40860fc3a..f2b0ad1cc 100644 --- a/client/coral-framework/translations.json +++ b/client/coral-framework/translations.json @@ -33,7 +33,7 @@ "unexpectedError": "Unexpected error while saving changes. Sorry!" }, "error": { - "editWindowExpired": "You can no longer edit this comment. The time window to do so has expired.", + "EDIT_WINDOW_ENDED": "You can no longer edit this comment. The time window to do so has expired.", "emailNotVerified": "Email address {0} not verified.", "email": "Not a valid E-Mail", "networkError": "Failed to connect to server. Check your internet connection and try again.", diff --git a/errors.js b/errors.js index 19b0ec90c..94bed0d12 100644 --- a/errors.js +++ b/errors.js @@ -112,10 +112,12 @@ const ErrContainsProfanity = new APIError('This username contains elements which }); const ErrNotFound = new APIError('not found', { + translation_key: 'NOT_FOUND', status: 404 }); const ErrInvalidAssetURL = new APIError('asset_url is invalid', { + translation_key: 'INVALID_ASSET_URL', status: 400 }); @@ -148,16 +150,17 @@ const ErrPermissionUpdateUsername = new APIError('You do not have permission to status: 500 }); +// ErrLoginAttemptMaximumExceeded is returned when the login maximum is exceeded. const ErrLoginAttemptMaximumExceeded = new APIError('You have made too many incorrect password attempts.', { translation_key: 'LOGIN_MAXIMUM_EXCEEDED', status: 429 }); -class ErrEditWindowHasEnded extends APIError { - constructor(message) { - super(message || 'Edit window is over.', {status: 403, translation_key: 'error.editWindowExpired'}); - } -} +// ErrEditWindowHasEnded is returned when the edit window has expired. +const ErrEditWindowHasEnded = new APIError('Edit window is over', { + translation_key: 'EDIT_WINDOW_ENDED', + status: 403 +}); module.exports = { ExtendableError, diff --git a/graph/loaders/assets.js b/graph/loaders/assets.js index ba8fb3751..d74199279 100644 --- a/graph/loaders/assets.js +++ b/graph/loaders/assets.js @@ -25,34 +25,31 @@ const genAssetsByID = (context, ids) => AssetModel.find({ * @param {String} asset_url the url passed in from the query * @returns {Promise} resolves to the asset */ -const findOrCreateAssetByURL = (context, asset_url) => { +const findOrCreateAssetByURL = async (context, asset_url) => { // Verify that the asset_url is parsable. let parsed_asset_url = url.parse(asset_url); if (!parsed_asset_url.protocol) { - return Promise.reject(errors.ErrInvalidAssetURL); + throw errors.ErrInvalidAssetURL; } - return AssetsService.findOrCreateByUrl(asset_url) - .then((asset) => { + let asset = await AssetsService.findOrCreateByUrl(asset_url); - // If the asset wasn't scraped before, scrape it! Otherwise just return - // the asset. - if (!asset.scraped) { - return scraper.create(asset).then(() => asset); - } + // If the asset wasn't scraped before, scrape it! Otherwise just return + // the asset. + if (!asset.scraped) { + await scraper.create(asset); + } - return asset; - }); + return asset; }; -const getAssetsForMetrics = ({loaders: {Actions, Comments}}) => { - return Actions.getByTypes({action_type: 'FLAG', item_type: 'COMMENT'}) - .then((actions) => { // ALL ACTIONS :O - const ids = actions.map(({item_id}) => item_id); +const getAssetsForMetrics = async ({loaders: {Actions, Comments}}) => { + let actions = await Actions.getByTypes({action_type: 'FLAG', item_type: 'COMMENT'}); - return Comments.getByQuery({ids}); - }); + const ids = actions.map(({item_id}) => item_id); + + return Comments.getByQuery({ids}); }; /** diff --git a/graph/loaders/comments.js b/graph/loaders/comments.js index 0faa124da..cc2a5dd09 100644 --- a/graph/loaders/comments.js +++ b/graph/loaders/comments.js @@ -120,8 +120,8 @@ const getParentCountByAssetIDPersonalized = async (context, {assetId, excludeIgn const ignoredUsers = freshUser.ignoresUsers; query.author_id = {$nin: ignoredUsers}; } - const count = await CommentModel.where(query).count(); - return count; + + return CommentModel.where(query).count(); }; /** @@ -263,13 +263,9 @@ const getCommentsByQuery = async ({user}, {ids, statuses, asset_id, parent_id, a comments = comments.where({parent_id}); } - if (excludeIgnored && user) { - - // load afresh, as `user` may be from cache and not have recent ignores - const freshUser = await UsersService.findById(user.id); - const ignoredUsers = freshUser.ignoresUsers; + if (excludeIgnored && user && user.ignoresUsers) { comments = comments.where({ - author_id: {$nin: ignoredUsers} + author_id: {$nin: user.ignoresUsers} }); } @@ -294,6 +290,27 @@ const getCommentsByQuery = async ({user}, {ids, statuses, asset_id, parent_id, a .limit(limit); }; +const getCommentsConnection = async ({user}, query) => { + let {limit} = query; + + // Increate the limit by one. + query.limit++; + + let comments = await getCommentsByQuery({user}, query); + + if (!comments) { + comments = []; + } + + return { + edges: comments.slice(0, limit), + pageInfo: { + hasNextPage: Boolean(comments.length > limit), + cursor: comments.length > 0 ? comments[comments.length - 1].created_at : null + } + }; +}; + /** * Gets the recent replies. * @param {Object} context graph context @@ -431,6 +448,7 @@ module.exports = (context) => ({ Comments: { get: new DataLoader((ids) => genComments(context, ids)), getByQuery: (query) => getCommentsByQuery(context, query), + getConnection: (query) => getCommentsConnection(context, query), getCountByQuery: (query) => getCommentCountByQuery(context, query), countByAssetID: new SharedCounterDataLoader('Comments.totalCommentCount', 3600, (ids) => getCountsByAssetID(context, ids)), countByAssetIDPersonalized: (query) => getCountsByAssetIDPersonalized(context, query), diff --git a/graph/mutators/action.js b/graph/mutators/action.js index a572a641c..c5f225e33 100644 --- a/graph/mutators/action.js +++ b/graph/mutators/action.js @@ -12,23 +12,23 @@ const errors = require('../../errors'); * @param {String} action_type type of the action * @return {Promise} resolves to the action created */ -const createAction = ({user = {}}, {item_id, item_type, action_type, group_id, metadata = {}}) => { - return ActionsService.insertUserAction({ +const createAction = async ({user = {}}, {item_id, item_type, action_type, group_id, metadata = {}}) => { + let action = await ActionsService.insertUserAction({ item_id, item_type, user_id: user.id, group_id, action_type, metadata - }).then((action) => { - if (item_type === 'USERS' && action_type === 'FLAG') { - return UsersService - .setStatus(item_id, 'PENDING') - .then(() => action); - } - - return action; }); + + if (item_type === 'USERS' && action_type === 'FLAG') { + + // Set the user as pending if it was a user flag. + await UsersService.setStatus(item_id, 'PENDING'); + } + + return action; }; /** diff --git a/graph/mutators/comment.js b/graph/mutators/comment.js index 7e5bc3a1b..ddbcf9c5d 100644 --- a/graph/mutators/comment.js +++ b/graph/mutators/comment.js @@ -16,7 +16,7 @@ const Wordlist = require('../../services/wordlist'); * @param {String} [status='NONE'] the status of the new comment * @return {Promise} resolves to the created comment */ -const createComment = ({user, loaders: {Comments}, pubsub}, {body, asset_id, parent_id = null, tags = []}, status = 'NONE') => { +const createComment = async ({user, loaders: {Comments}, pubsub}, {body, asset_id, parent_id = null, tags = []}, status = 'NONE') => { // Building array of tags tags = tags.map(tag => ({name: tag})); @@ -26,37 +26,35 @@ const createComment = ({user, loaders: {Comments}, pubsub}, {body, asset_id, par tags.push({name: 'STAFF'}); } - return CommentsService.publicCreate({ + let comment = await CommentsService.publicCreate({ body, asset_id, parent_id, status, tags, author_id: user.id - }) - .then((comment) => { - - // If the loaders are present, clear the caches for these values because we - // just added a new comment, hence the counts should be updated. We should - // perform these increments in the event that we do have a new comment that - // is approved or without a comment. - if (status === 'NONE' || status === 'APPROVED') { - if (parent_id != null) { - Comments.countByParentID.incr(parent_id); - } else { - Comments.parentCountByAssetID.incr(asset_id); - } - Comments.countByAssetID.incr(asset_id); - - if (pubsub) { - - // Publish the newly added comment via the subscription. - pubsub.publish('commentAdded', comment); - } - } - - return comment; }); + + // If the loaders are present, clear the caches for these values because we + // just added a new comment, hence the counts should be updated. We should + // perform these increments in the event that we do have a new comment that + // is approved or without a comment. + if (status === 'NONE' || status === 'APPROVED') { + if (parent_id != null) { + Comments.countByParentID.incr(parent_id); + } else { + Comments.parentCountByAssetID.incr(asset_id); + } + Comments.countByAssetID.incr(asset_id); + + if (pubsub) { + + // Publish the newly added comment via the subscription. + pubsub.publish('commentAdded', comment); + } + } + + return comment; }; /** @@ -65,7 +63,7 @@ const createComment = ({user, loaders: {Comments}, pubsub}, {body, asset_id, par * @param {String} [asset_id] id of asset comment is posted on * @return {Object} resolves to the wordlist results */ -const filterNewComment = ({body, asset_id}) => { +const filterNewComment = (context, {body, asset_id}) => { // Create a new instance of the Wordlist. const wl = new Wordlist(); @@ -85,50 +83,40 @@ const filterNewComment = ({body, asset_id}) => { * @param {Object} [wordlist={}] the results of the wordlist scan * @return {Promise} resolves to the comment's status */ -const resolveNewCommentStatus = ({asset_id, body}, wordlist = {}, settings = {}) => { +const resolveNewCommentStatus = async (context, {asset_id, body}, wordlist = {}, settings = {}) => { // Decide the status based on whether or not the current asset/settings // has pre-mod enabled or not. If the comment was rejected based on the // wordlist, then reject it, otherwise if the moderation setting is // premod, set it to `premod`. - let status; - if (wordlist.banned) { - status = Promise.resolve('REJECTED'); - } else if (settings.premodLinksEnable && linkify.test(body)) { - status = Promise.resolve('PREMOD'); - } else if (asset_id) { - status = AssetsService - .rectifySettings(AssetsService.findById(asset_id).then((asset) => { - if (!asset) { - return Promise.reject(errors.ErrNotFound); - } - - // Check to see if the asset has closed commenting... - if (asset.isClosed) { - - // They have, ensure that we send back an error. - return Promise.reject(new errors.ErrAssetCommentingClosed(asset.closedMessage)); - } - - return asset; - })) - - // Return `premod` if pre-moderation is enabled and an empty "new" status - // in the event that it is not in pre-moderation mode. - .then(({moderation, charCountEnable, charCount}) => { - - // Reject if the comment is too long - if (charCountEnable && body.length > charCount) { - return 'REJECTED'; - } - return moderation === 'PRE' ? 'PREMOD' : 'NONE'; - }); - } else { - status = 'NONE'; + return 'REJECTED'; + } + + if (settings.premodLinksEnable && linkify.test(body)) { + return 'PREMOD'; } - return status; + let asset = await AssetsService.findById(asset_id); + if (!asset) { + throw errors.ErrNotFound; + } + + // Check to see if the asset has closed commenting... + if (asset.isClosed) { + throw new errors.ErrAssetCommentingClosed(asset.closedMessage); + } + + // Return `premod` if pre-moderation is enabled and an empty "new" status + // in the event that it is not in pre-moderation mode. + let {moderation, charCountEnable, charCount} = await AssetsService.rectifySettings(asset); + + // Reject if the comment is too long + if (charCountEnable && body.length > charCount) { + return 'REJECTED'; + } + + return moderation === 'PRE' ? 'PREMOD' : 'NONE'; }; /** @@ -139,45 +127,42 @@ const resolveNewCommentStatus = ({asset_id, body}, wordlist = {}, settings = {}) * @param {Object} commentInput the new comment to be created * @return {Promise} resolves to a new comment */ -const createPublicComment = (context, commentInput) => { +const createPublicComment = async (context, commentInput) => { // First we filter the comment contents to ensure that we note any validation // issues. - return filterNewComment(commentInput) + let [wordlist, settings] = await filterNewComment(context, commentInput); - // We then take the wordlist and the comment into consideration when - // considering what status to assign the new comment, and resolve the new - // status to set the comment to. - .then(([wordlist, settings]) => resolveNewCommentStatus(commentInput, wordlist, settings) + // We then take the wordlist and the comment into consideration when + // considering what status to assign the new comment, and resolve the new + // status to set the comment to. + let status = await resolveNewCommentStatus(context, commentInput, wordlist, settings); - // Then we actually create the comment with the new status. - .then((status) => createComment(context, commentInput, status)) - .then((comment) => { + // Then we actually create the comment with the new status. + let comment = await createComment(context, commentInput, status); - // If the comment has a suspect word or a link, we need to add a - // flag to it to indicate that it needs to be looked at. - // Otherwise just return the new comment. + // If the comment has a suspect word or a link, we need to add a + // flag to it to indicate that it needs to be looked at. + // Otherwise just return the new comment. - // TODO: Check why the wordlist is undefined - if (wordlist != null && wordlist.suspect != null) { + // TODO: Check why the wordlist is undefined + if (wordlist != null && wordlist.suspect != null) { - // TODO: this is kind of fragile, we should refactor this to resolve - // all these const's that we're using like 'COMMENTS', 'FLAG' to be - // defined in a checkable schema. - return ActionsService.insertUserAction({ - item_id: comment.id, - item_type: 'COMMENTS', - action_type: 'FLAG', - user_id: null, - group_id: 'Matched suspect word filter', - metadata: {} - }) - .then(() => comment); - } + // TODO: this is kind of fragile, we should refactor this to resolve + // all these const's that we're using like 'COMMENTS', 'FLAG' to be + // defined in a checkable schema. + await ActionsService.insertUserAction({ + item_id: comment.id, + item_type: 'COMMENTS', + action_type: 'FLAG', + user_id: null, + group_id: 'Matched suspect word filter', + metadata: {} + }); + } - // Finally, we return the comment. - return comment; - })); + // Finally, we return the comment. + return comment; }; /** @@ -187,26 +172,23 @@ const createPublicComment = (context, commentInput) => { * @param {String} status the new status of the comment */ -const setCommentStatus = ({user, loaders: {Comments}}, {id, status}) => { - return CommentsService - .pushStatus(id, status, user ? user.id : null) - .then((comment) => { +const setCommentStatus = async ({user, loaders: {Comments}}, {id, status}) => { + let comment = await CommentsService.pushStatus(id, status, user ? user.id : null); - // If the loaders are present, clear the caches for these values because we - // just added a new comment, hence the counts should be updated. It would - // be nice if we could decrement the counters here, but that would result - // in us having to know the initial state of the comment, which would - // require another database query. - if (comment.parent_id != null) { - Comments.countByParentID.clear(comment.parent_id); - } else { - Comments.parentCountByAssetID.clear(comment.asset_id); - } + // If the loaders are present, clear the caches for these values because we + // just added a new comment, hence the counts should be updated. It would + // be nice if we could decrement the counters here, but that would result + // in us having to know the initial state of the comment, which would + // require another database query. + if (comment.parent_id != null) { + Comments.countByParentID.clear(comment.parent_id); + } else { + Comments.parentCountByAssetID.clear(comment.asset_id); + } - Comments.countByAssetID.clear(comment.asset_id); + Comments.countByAssetID.clear(comment.asset_id); - return comment; - }); + return comment; }; /** @@ -233,29 +215,16 @@ const removeCommentTag = ({user, loaders: {Comments}}, {id, tag}) => { * @param {Object} edit describes how to edit the comment * @param {String} edit.body the new Comment body */ -const editComment = async ({user, loaders: {Comments}}, {id, asset_id, edit}) => { - const {body} = edit; - const determineStatusForComment = async ({body, asset_id}) => { - const [wordlist, settings] = await filterNewComment({asset_id, body}); - const status = await resolveNewCommentStatus({asset_id, body}, wordlist, settings); - return status; - }; - const status = await determineStatusForComment({body, asset_id}); - try { - await CommentsService.edit(id, asset_id, user.id, Object.assign({status}, edit)); - } catch (error) { - switch (error.name) { - case 'CommentNotFound': - throw new errors.APIError('Comment not found', { - status: 404, - translation_key: 'NOT_FOUND', - }); - case 'NotAuthorizedToEdit': - throw errors.ErrNotAuthorized; - default: - throw error; - } - } +const editComment = async (context, {id, asset_id, edit: {body}}) => { + + // Get the wordlist and the settings object. + const [wordlist, settings] = await filterNewComment(context, {asset_id, body}); + + // Determine the new status of the comment. + const status = await resolveNewCommentStatus(context, {asset_id, body}, wordlist, settings); + + await CommentsService.edit(id, context.user.id, {body, status}); + return {status}; }; diff --git a/graph/mutators/user.js b/graph/mutators/user.js index d68351701..2cc1962be 100644 --- a/graph/mutators/user.js +++ b/graph/mutators/user.js @@ -2,23 +2,19 @@ const errors = require('../../errors'); const UsersService = require('../../services/users'); const setUserStatus = ({user}, {id, status}) => { - return UsersService.setStatus(id, status) - .then(res => res); + return UsersService.setStatus(id, status); }; const suspendUser = ({user}, {id, message}) => { - return UsersService.suspendUser(id, message) - .then(res => { - return res; - }); + return UsersService.suspendUser(id, message); }; -const ignoreUser = async ({user}, userToIgnore) => { - return await UsersService.ignoreUsers(user.id, [userToIgnore.id]); +const ignoreUser = ({user}, userToIgnore) => { + return UsersService.ignoreUsers(user.id, [userToIgnore.id]); }; -const stopIgnoringUser = async ({user}, userToStopIgnoring) => { - return await UsersService.stopIgnoringUsers(user.id, [userToStopIgnoring.id]); +const stopIgnoringUser = ({user}, userToStopIgnoring) => { + return UsersService.stopIgnoringUsers(user.id, [userToStopIgnoring.id]); }; module.exports = (context) => { diff --git a/graph/resolvers/asset.js b/graph/resolvers/asset.js index c260d0070..7d356aac9 100644 --- a/graph/resolvers/asset.js +++ b/graph/resolvers/asset.js @@ -10,7 +10,7 @@ const Asset = { return Comments.genRecentComments.load(id); }, comments({id}, {sort, limit, excludeIgnored}, {loaders: {Comments}}) { - return Comments.getByQuery({ + return Comments.getConnection({ asset_id: id, sort, limit, diff --git a/graph/typeDefs.graphql b/graph/typeDefs.graphql index 26e7349ec..4a6224ee9 100644 --- a/graph/typeDefs.graphql +++ b/graph/typeDefs.graphql @@ -1,3 +1,12 @@ +################################################################################ +## Pagination +################################################################################ + +type PageInfo { + hasNextPage: Boolean! + cursor: String +} + ################################################################################ ## Custom Scalar Types ################################################################################ @@ -37,16 +46,13 @@ type User { actions: [Action] # the current roles of the user. - roles: [USER_ROLES] + roles: [USER_ROLES!] # determines whether the user can edit their username canEditName: Boolean # returns all comments based on a query. - comments(query: CommentsQuery): [Comment] - - # returns all users based on a query. - users(query: UsersQuery): [User] + comments(query: CommentsQuery): [Comment!] # returns user status status: USER_STATUS @@ -81,6 +87,12 @@ input UsersQuery { ## Comments ################################################################################ +# CommentConnection provides Comments with PageInfo. +type CommentConnection { + edges: [Comment!] + pageInfo: PageInfo! +} + # The statuses that a comment may have. enum COMMENT_STATUS { @@ -190,7 +202,7 @@ type Comment { recentReplies: [Comment] # the replies that were made to the comment. - replies(sort: SORT_ORDER = CHRONOLOGICAL, limit: Int = 3, excludeIgnored: Boolean): [Comment] + replies(sort: SORT_ORDER = CHRONOLOGICAL, limit: Int = 3, excludeIgnored: Boolean): CommentConnection # The count of replies on a comment. replyCount(excludeIgnored: Boolean): Int @@ -429,7 +441,7 @@ type Asset { recentComments: [Comment] # The top level comments that are attached to the asset. - comments(sort: SORT_ORDER = REVERSE_CHRONOLOGICAL, limit: Int = 10, excludeIgnored: Boolean): [Comment] + comments(sort: SORT_ORDER = REVERSE_CHRONOLOGICAL, limit: Int = 10, excludeIgnored: Boolean): CommentConnection # The count of top level comments on the asset. commentCount(excludeIgnored: Boolean): Int @@ -536,7 +548,7 @@ type RootQuery { asset(id: ID, url: String): Asset # Comments returned based on a query. - comments(query: CommentsQuery!): [Comment] + comments(query: CommentsQuery!): CommentConnection! # Return the count of comments satisfied by the query. Note that this edge is # expensive as it is not batched. Requires the `ADMIN` role. @@ -600,6 +612,7 @@ enum TAG_TYPE { STAFF } +# CreateCommentInput is the input content used to create a new comment. input CreateCommentInput { # The asset id @@ -729,19 +742,19 @@ type StopIgnoringUserResponse implements Response { errors: [UserError] } -# Input to editComment mutation +# Input to editComment mutation. input EditCommentInput { + # Update body of the comment body: String! } -type CommentInfoAfterEdit { - # New status of the edited comment - status: COMMENT_STATUS! -} - +# EditCommentResponse contains the updated comment and any errors that occured. type EditCommentResponse implements Response { - comment: CommentInfoAfterEdit! + + # The edited comment. + comment: Comment + # An array of errors relating to the mutation that occured. errors: [UserError] } diff --git a/package.json b/package.json index 6476223b3..1af9203e7 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "marked": "^0.3.6", "metascraper": "^1.0.6", "minimist": "^1.2.0", - "mongoose": "^4.9.1", + "mongoose": "^4.9.8", "morgan": "^1.8.1", "natural": "^0.5.0", "node-emoji": "^1.5.1", @@ -99,12 +99,10 @@ "react-recaptcha": "^2.2.6", "recompose": "^0.23.1", "redis": "^2.7.1", - "uuid": "^3.0.1", - "simplemde": "^1.11.2", - "subscriptions-transport-ws": "^0.5.5-alpha.0", "resolve": "^1.3.2", "semver": "^5.3.0", "simplemde": "^1.11.2", + "subscriptions-transport-ws": "^0.5.5-alpha.0", "timekeeper": "^1.0.0", "uuid": "^3.0.1" }, diff --git a/services/comments.js b/services/comments.js index 9325cdb8b..f46e318d7 100644 --- a/services/comments.js +++ b/services/comments.js @@ -3,19 +3,7 @@ const CommentModel = require('../models/comment'); const ActionModel = require('../models/action'); const ActionsService = require('./actions'); -const {ErrEditWindowHasEnded} = require('../errors'); - -// const ALLOWED_TAGS = [ -// {name: 'STAFF'}, -// {name: 'BEST'}, -// ]; - -const STATUSES = [ - 'ACCEPTED', - 'REJECTED', - 'PREMOD', - 'NONE', -]; +const errors = require('../errors'); const EDIT_WINDOW_MS = 30 * 1000; // 30 seconds @@ -54,84 +42,69 @@ module.exports = class CommentsService { /** * Edit a Comment * @param {String} id comment.id you want to edit (or its ID) - * @param {String} asset_id asset_id of the comment - * @param {String} editor user.id of the user trying to edit the comment (will err if not comment author) + * @param {String} author_id user.id of the user trying to edit the comment (will err if not comment author) * @param {String} body the new Comment body * @param {String} status the new Comment status */ - static async edit(id, asset_id, editor, {body, status, ignoreEditWindow}) { - if (status && ! STATUSES.includes(status)) { - throw new Error(`status ${status} is not supported`); - } + static async edit(id, author_id, {body, status, ignoreEditWindow = false}) { + const query = { + id, + author_id + }; + + // Establish the edit window (if it exists) and add the condition to the + // original query. const lastEditableCommentCreatedAt = new Date((new Date()).getTime() - EDIT_WINDOW_MS); - const filter = Object.assign( - { - id, - asset_id, - author_id: editor, - }, - ignoreEditWindow ? {} : { - created_at: { - $gt: lastEditableCommentCreatedAt, - }, - } - ); - const {nModified} = await CommentModel.update( - filter, - { - $set: { - body, - status, - }, - $push: { - body_history: { - body, - created_at: new Date(), - }, - status_history: { - type: status, - created_at: new Date(), - } - }, - } - ); - switch (nModified) { - case 0: { - - // disambiguate possible error cases - const comment = await this.findById(id); - - // return whether the comment should no longer be editable - // because its edit window expired - const editWindowExpired = (comment) => { - const now = new Date; - const editableUntil = this.getEditableUntilDate(comment); - return now > editableUntil; + if (!ignoreEditWindow) { + query.created_at = { + $gt: lastEditableCommentCreatedAt, }; - if ( ! comment || (comment.asset_id !== asset_id)) { - throw Object.assign(new Error('Comment not found'), { - name: 'CommentNotFound' - }); - } else if (comment.author_id !== editor) { - throw Object.assign(new Error('You aren\'t allowed to edit that comment'), { - name: 'NotAuthorizedToEdit' - }); - } else if (( ! ignoreEditWindow) && editWindowExpired(comment)) { - throw new ErrEditWindowHasEnded(); - } - throw new Error('Failed to edit comment. This could be because it can\'t be found, the edit window expired, or because you\'re not allowed to edit it.'); } - } - } - /** - * Until when can the provided comment be edited? - * @param {Comment} comment - comment to check last edit date of - * @returns {Date} last date at which comment can be edited - */ - static getEditableUntilDate(comment) { - const {created_at} = comment; - return new Date(Number(created_at) + EDIT_WINDOW_MS); + const { + value: comment + } = await CommentModel.findOneAndUpdate(query, { + $set: { + body, + status, + }, + $push: { + body_history: { + body, + created_at: new Date(), + }, + status_history: { + type: status, + created_at: new Date(), + } + }, + }, { + new: true, + rawResult: true + }); + + if (comment === null) { + + // Try to get the comment. + const comment = await CommentsService.findById(id); + if (comment === null) { + throw errors.ErrNotFound; + } + + // Check to see if the user was't allowed to edit it. + if (comment.author_id !== author_id) { + throw errors.ErrNotAuthorized; + } + + // Check to see if the edit window expired. + if (!ignoreEditWindow && comment.created_at <= lastEditableCommentCreatedAt) { + throw errors.ErrEditWindowHasEnded; + } + + throw new Error('comment edit failed for an unexpected reason'); + } + + return comment; } /** @@ -304,14 +277,6 @@ module.exports = class CommentsService { * @return {Promise} */ static pushStatus(id, status, assigned_by = null) { - - // Check to see if the comment status is in the allowable set of statuses. - if (STATUSES.indexOf(status) === -1) { - - // Comment status is not supported! Error out here. - return Promise.reject(new Error(`status ${status} is not supported`)); - } - return CommentModel.findOneAndUpdate({id}, { $push: { status_history: { diff --git a/test/server/graph/mutations/editComment.js b/test/server/graph/mutations/editComment.js index f449e37a8..5e64ac5d5 100644 --- a/test/server/graph/mutations/editComment.js +++ b/test/server/graph/mutations/editComment.js @@ -64,6 +64,9 @@ describe('graph.mutations.editComment', () => { console.error(response.errors); } expect(response.errors).to.be.empty; + if (response.data.editComment.errors && response.data.editComment.errors.length > 0) { + console.error(response.data.editComment.errors); + } expect(response.data.editComment.errors).to.be.null; // assert body has changed @@ -97,9 +100,12 @@ describe('graph.mutations.editComment', () => { body: newBody } }); + if (response.errors && response.errors.length > 0) { + console.error(response.errors); + } expect(response.errors).to.be.empty; expect(response.data.editComment.errors).to.not.be.empty; - expect(response.data.editComment.errors[0].translation_key).to.equal('error.editWindowExpired'); + expect(response.data.editComment.errors[0].translation_key).to.equal('EDIT_WINDOW_ENDED'); const commentAfterEdit = await CommentsService.findById(comment.id); // it *hasn't* changed from the original @@ -144,6 +150,9 @@ describe('graph.mutations.editComment', () => { body: newBody } }); + if (response.errors && response.errors.length > 0) { + console.error(response.errors); + } expect(response.errors).to.be.empty; expect(response.data.editComment.errors[0].translation_key).to.equal('NOT_FOUND'); }); diff --git a/test/server/graph/queries/asset.js b/test/server/graph/queries/asset.js index 79abeda0e..f25711809 100644 --- a/test/server/graph/queries/asset.js +++ b/test/server/graph/queries/asset.js @@ -9,85 +9,94 @@ const Asset = require('../../../../models/asset'); const CommentsService = require('../../../../services/comments'); describe('graph.queries.asset', () => { + let asset, users; beforeEach(async () => { await SettingsService.init(); + asset = await Asset.create({id: '1', url: 'https://example.com'}); + users = await UsersService.createLocalUsers([ + { + email: 'usernameA@example.com', + password: 'password', + username: 'usernameA' + }, + { + email: 'usernameB@example.com', + password: 'password', + username: 'usernameB' + }, + { + email: 'usernameC@example.com', + password: 'password', + username: 'usernameC' + } + ]); }); it('can get comments edge', async () => { - const assetId = 'fakeAssetId'; - const assetUrl = 'https://bengo.is'; - await Asset.create({id: assetId, url: assetUrl}); - - const user = await UsersService.createLocalUser('usernameA@example.com', 'password', 'usernameA'); - const context = new Context({user}); + const context = new Context({user: users[0]}); await CommentsService.publicCreate([1, 2].map(() => ({ - author_id: user.id, - asset_id: assetId, - body: `hello there! ${ String(Math.random()).slice(2)}`, + author_id: users[0].id, + asset_id: asset.id, + body: `hello there! ${String(Math.random()).slice(2)}`, }))); const assetCommentsQuery = ` - query assetCommentsQuery($assetId: ID!, $assetUrl: String!) { - asset(id: $assetId, url: $assetUrl) { + query assetCommentsQuery($id: ID!) { + asset(id: $id) { comments(limit: 10) { - id, - body, + edges { + id + body + } } } } `; - const assetCommentsResponse = await graphql(schema, assetCommentsQuery, {}, context, {assetId, assetUrl}); - const comments = assetCommentsResponse.data.asset.comments; + const res = await graphql(schema, assetCommentsQuery, {}, context, {id: asset.id}); + expect(res.erros).is.empty; + const comments = res.data.asset.comments.edges; expect(comments.length).to.equal(2); }); it('can query comments edge to exclude comments ignored by user', async () => { - const assetId = 'fakeAssetId1'; - const assetUrl = 'https://bengo.is/1'; - await Asset.create({id: assetId, url: assetUrl}); + const context = new Context({user: users[0]}); - const userA = await UsersService.createLocalUser('usernameA@example.com', 'password', 'usernameA'); - const userB = await UsersService.createLocalUser('usernameB@example.com', 'password', 'usernameB'); - const userC = await UsersService.createLocalUser('usernameC@example.com', 'password', 'usernameC'); - const context = new Context({user: userA}); - - // create 2 comments each for userB, userC - await Promise.all([userB, userC].map(user => CommentsService.publicCreate([1, 2].map(() => ({ + await Promise.all(users.slice(1, 3).map((user) => CommentsService.publicCreate({ author_id: user.id, - asset_id: assetId, - body: `hello there! ${ String(Math.random()).slice(2)}`, - }))))); + asset_id: asset.id, + body: `hello there! ${String(Math.random()).slice(2)}`, + }))); + + // Add the second user to the list of ignored users. + context.user.ignoresUsers.push(users[1].id); - // ignore userB - const ignoreUserMutation = ` - mutation ignoreUser ($id: ID!) { - ignoreUser(id:$id) { - errors { - translation_key - } - } - } - `; - const ignoreUserResponse = await graphql(schema, ignoreUserMutation, {}, context, {id: userB.id}); - if (ignoreUserResponse.errors && ignoreUserResponse.errors.length) { - console.error(ignoreUserResponse.errors); - } - expect(ignoreUserResponse.errors).to.be.empty; - - const assetCommentsWithoutIgnoredQuery = ` - query assetCommentsQuery($assetId: ID!, $assetUrl: String!, $excludeIgnored: Boolean!) { - asset(id: $assetId, url: $assetUrl) { + const query = ` + query assetCommentsQuery($id: ID!, $url: String!, $excludeIgnored: Boolean!) { + asset(id: $id, url: $url) { comments(limit: 10, excludeIgnored: $excludeIgnored) { - id, - body, + edges { + id + body + } } } } `; - const assetCommentsResponse = await graphql(schema, assetCommentsWithoutIgnoredQuery, {}, context, {assetId, assetUrl, excludeIgnored: true}); - const comments = assetCommentsResponse.data.asset.comments; - expect(comments.length).to.equal(2); + + { + const res = await graphql(schema, query, {}, context, { + id: asset.id, + url: asset.url, + excludeIgnored: true + }); + if (res.errors && res.errors.length) { + console.error(res.errors); + } + expect(res.errors).is.empty; + const comments = res.data.asset.comments.edges; + expect(comments.length).to.equal(1); + } }); }); diff --git a/yarn.lock b/yarn.lock index 7a1930df8..a87eed6ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,5 +1,7 @@ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 + + "@kadira/storybook-deployer@^1.1.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@kadira/storybook-deployer/-/storybook-deployer-1.2.0.tgz#1708f5cb37fa08ab4173b1bd99df6f4717dfae12" @@ -294,28 +296,28 @@ asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" -assert-plus@^1.0.0, assert-plus@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - assert@^1.1.1: version "1.4.1" resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" dependencies: util "0.10.3" -assertion-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" - assertion-error@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.0.tgz#c7f85438fdd466bc7ca16ab90c81513797a5d23b" +assertion-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" + ast-traverse@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ast-traverse/-/ast-traverse-0.1.1.tgz#69cf2b8386f19dcda1bb1e05d68fe359d8897de6" @@ -332,10 +334,20 @@ async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" -async@^1.4.0, async@^1.5.2, async@1.x: +async@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/async/-/async-1.2.1.tgz#a4816a17cd5ff516dfa2c7698a453369b9790de0" + +async@1.x, async@^1.4.0, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" +async@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" + dependencies: + lodash "^4.14.0" + async@^2.0.1, async@^2.1.2, async@^2.1.4: version "2.3.0" resolved "https://registry.yarnpkg.com/async/-/async-2.3.0.tgz#1013d1051047dd320fe24e494d5c66ecaf6147d9" @@ -346,16 +358,6 @@ async@~0.9.0: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" -async@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/async/-/async-1.2.1.tgz#a4816a17cd5ff516dfa2c7698a453369b9790de0" - -async@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" - dependencies: - lodash "^4.14.0" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1145,6 +1147,10 @@ backo2@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" +balanced-match@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.1.0.tgz#b504bd05869b39259dd0c5efc35d843176dccc4a" + balanced-match@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.2.1.tgz#7bc658b4bed61eee424ad74f75f5c3e2c4df3cc7" @@ -1153,15 +1159,11 @@ balanced-match@^0.4.1, balanced-match@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" -balanced-match@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.1.0.tgz#b504bd05869b39259dd0c5efc35d843176dccc4a" - base64-js@^1.0.2: version "1.2.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.0.tgz#a39992d723584811982be5e290bb6a53d86700f1" -base64url@^2.0.0, base64url@2.0.0: +base64url@2.0.0, base64url@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/base64url/-/base64url-2.0.0.tgz#eac16e03ea1438eff9423d69baa36262ed1f70bb" @@ -1191,7 +1193,7 @@ binary-extensions@^1.0.0: version "1.8.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774" -bindings@^1.2.1, bindings@1.2.1: +bindings@1.2.1, bindings@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" @@ -1207,14 +1209,6 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird@^2.10.2: - version "2.11.0" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" - -bluebird@^3.4.6, bluebird@3.4.7: - version "3.4.7" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" - bluebird@2.10.2: version "2.10.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.10.2.tgz#024a5517295308857f14f91f1106fc3b555f446b" @@ -1227,6 +1221,14 @@ bluebird@3.4.6: version "3.4.6" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.6.tgz#01da8d821d87813d158967e743d5fe6c62cf8c0f" +bluebird@3.4.7, bluebird@^3.4.6: + version "3.4.7" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" + +bluebird@^2.10.2: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" @@ -1474,7 +1476,7 @@ chai@^3.5.0: deep-eql "^0.1.3" type-detect "^1.0.0" -chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3, chalk@1.1.3: +chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -1639,7 +1641,7 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" -cli-table@^0.3.1, cli-table@0.3.1: +cli-table@0.3.1, cli-table@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" dependencies: @@ -1733,7 +1735,11 @@ colormin@^1.0.5: css-color-names "0.0.4" has "^1.0.1" -colors@^1.1.2, colors@~1.1.2, colors@1.1.2: +colors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + +colors@1.1.2, colors@^1.1.2, colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" @@ -1741,10 +1747,6 @@ colors@~0.6.0-1: version "0.6.2" resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc" -colors@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -1757,16 +1759,6 @@ combined-stream@~0.0.4: dependencies: delayed-stream "0.0.5" -commander@^2.5.0, commander@^2.8.1, commander@^2.9.0, commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - dependencies: - graceful-readlink ">= 1.0.0" - -commander@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" - commander@2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d" @@ -1777,6 +1769,16 @@ commander@2.8.x: dependencies: graceful-readlink ">= 1.0.0" +commander@2.9.0, commander@^2.5.0, commander@^2.8.1, commander@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +commander@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" + common-tags@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.4.0.tgz#1187be4f3d4cf0c0427d43f74eef1f73501614c0" @@ -1914,7 +1916,7 @@ cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" -cookiejar@^2.0.6, cookiejar@2.0.x: +cookiejar@2.0.x, cookiejar@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.0.6.tgz#0abf356ad00d1c5a219d88d44518046dd026acfe" @@ -1939,7 +1941,7 @@ core-js@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" -core-util-is@~1.0.0, core-util-is@1.0.2: +core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2152,7 +2154,7 @@ csso@~2.3.1: clap "^1.0.9" source-map "^0.5.3" -"cssom@>= 0.3.0 < 0.4.0", "cssom@>= 0.3.2 < 0.4.0", cssom@0.3.x: +cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0", "cssom@>= 0.3.2 < 0.4.0": version "0.3.2" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" @@ -2188,16 +2190,16 @@ cz-conventional-changelog@1.2.0: right-pad "^1.0.1" word-wrap "^1.0.3" +d3-helpers@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/d3-helpers/-/d3-helpers-0.3.0.tgz#4b31dce4a2121a77336384574d893fbed5fb293d" + d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" dependencies: es5-ext "^0.10.9" -d3-helpers@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/d3-helpers/-/d3-helpers-0.3.0.tgz#4b31dce4a2121a77336384574d893fbed5fb293d" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -2224,17 +2226,13 @@ date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" -debug@*, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.3, debug@2, debug@2.6.4: +debug@*, debug@2, debug@2.6.4, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.3: version "2.6.4" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.4.tgz#7586a9b3c39741c0282ae33445c4e8ac74734fe0" dependencies: ms "0.7.3" -debug@~0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" - -debug@~2.2.0, debug@2.2.0: +debug@2.2.0, debug@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" dependencies: @@ -2264,11 +2262,15 @@ debug@2.6.3: dependencies: ms "0.7.2" +debug@~0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" + decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" -deep-eql@^0.1.3, deep-eql@0.1.3: +deep-eql@0.1.3, deep-eql@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" dependencies: @@ -2334,19 +2336,19 @@ del@^2.0.2: pinkie-promise "^2.0.0" rimraf "^2.2.8" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - delayed-stream@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-0.0.5.tgz#d4b1f43a93e8296dfe02694f4680bc37a313c73f" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" -depd@~1.1.0, depd@1.1.0: +depd@1.1.0, depd@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" @@ -2402,7 +2404,7 @@ dns-prefetch-control@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz#60ddb457774e178f1f9415f0cabb0e85b0b300b2" -doctrine@^1.2.2, doctrine@1.5.0: +doctrine@1.5.0, doctrine@^1.2.2: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" dependencies: @@ -2420,7 +2422,7 @@ doctypes@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" -dom-serializer@~0.1.0, dom-serializer@0: +dom-serializer@0, dom-serializer@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" dependencies: @@ -2431,21 +2433,21 @@ domain-browser@^1.1.1: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" +domelementtype@1, domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + domelementtype@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" -domelementtype@~1.1.1, domelementtype@1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - -domhandler@^2.3.0, domhandler@2.3: +domhandler@2.3, domhandler@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" dependencies: domelementtype "1" -domutils@^1.5.1, domutils@1.5, domutils@1.5.1: +domutils@1.5, domutils@1.5.1, domutils@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" dependencies: @@ -2494,14 +2496,14 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" -ejs@^2.5.6: - version "2.5.6" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.6.tgz#479636bfa3fe3b1debd52087f0acb204b4f19c88" - ejs@0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/ejs/-/ejs-0.8.3.tgz#db8aac47ff80a7df82b4c82c126fe8970870626f" +ejs@^2.5.6: + version "2.5.6" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.6.tgz#479636bfa3fe3b1debd52087f0acb204b4f19c88" + electron-to-chromium@^1.2.7: version "1.3.8" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.8.tgz#b2c8a2c79bb89fbbfd3724d9555e15095b5f5fb6" @@ -2532,18 +2534,18 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" -end-of-stream@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" - dependencies: - once "^1.4.0" - end-of-stream@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e" dependencies: once "~1.3.0" +end-of-stream@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" + dependencies: + once "^1.4.0" + enhanced-resolve@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.1.0.tgz#9f4b626f577245edcf4b2ad83d86e17f4f421dec" @@ -2553,14 +2555,14 @@ enhanced-resolve@^3.0.0: object-assign "^4.0.1" tapable "^0.2.5" -entities@^1.1.1, entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - entities@1.0: version "1.0.0" resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" +entities@^1.1.1, entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + env-rewrite@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/env-rewrite/-/env-rewrite-1.0.2.tgz#3e344a95af1bdaab34a559479b8be3abd0804183" @@ -2616,7 +2618,7 @@ es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: es6-iterator "2" es6-symbol "~3.1" -es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@2: +es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" dependencies: @@ -2635,14 +2637,14 @@ es6-map@^0.1.3: es6-symbol "~3.1.1" event-emitter "~0.3.5" -es6-promise@^3.0.2, es6-promise@^3.2.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" - es6-promise@3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4" +es6-promise@^3.0.2, es6-promise@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" + es6-set@~0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" @@ -2653,7 +2655,7 @@ es6-set@~0.1.5: es6-symbol "3.1.1" event-emitter "~0.3.5" -es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1, es6-symbol@3.1.1: +es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" dependencies: @@ -2677,11 +2679,11 @@ escape-regexp-component@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/escape-regexp-component/-/escape-regexp-component-1.0.2.tgz#9c63b6d0b25ff2a88c3adbd18c5b61acc3b9faa2" -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5, escape-string-regexp@1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" -escodegen@^1.6.1, escodegen@1.x.x: +escodegen@1.x.x, escodegen@^1.6.1: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" dependencies: @@ -2820,14 +2822,14 @@ esprima-fb@~15001.1001.0-dev-harmony-fb: version "15001.1001.0-dev-harmony-fb" resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz#43beb57ec26e8cf237d3dd8b33e42533577f2659" +esprima@3.x.x, esprima@^3.1.1, esprima@~3.1.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + esprima@^2.6.0, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" -esprima@^3.1.1, esprima@~3.1.0, esprima@3.x.x: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - esquery@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" @@ -2964,14 +2966,14 @@ express@^4.12.2, express@^4.15.2: utils-merge "1.0.0" vary "~1.1.0" +extend@3, extend@^3.0.0, extend@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" + extend@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/extend/-/extend-1.3.0.tgz#d1516fb0ff5624d2ebf9123ea1dac5a1994004f8" -extend@^3.0.0, extend@~3.0.0, extend@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" - external-editor@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.1.tgz#4c597c6c88fa6410e41dbbaa7b1be2336aa31095" @@ -3067,11 +3069,11 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" -finalhandler@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.2.tgz#d0e36f9dbc557f2de14423df6261889e9d60c93a" +finalhandler@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.0.tgz#b5691c2c0912092f18ac23e9416bde5cd7dc6755" dependencies: - debug "2.6.4" + debug "2.6.1" encodeurl "~1.0.1" escape-html "~1.0.3" on-finished "~2.3.0" @@ -3079,11 +3081,11 @@ finalhandler@~1.0.0: statuses "~1.3.1" unpipe "~1.0.0" -finalhandler@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.0.tgz#b5691c2c0912092f18ac23e9416bde5cd7dc6755" +finalhandler@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.2.tgz#d0e36f9dbc557f2de14423df6261889e9d60c93a" dependencies: - debug "2.6.1" + debug "2.6.4" encodeurl "~1.0.1" escape-html "~1.0.3" on-finished "~2.3.0" @@ -3150,6 +3152,14 @@ forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" +form-data@1.0.0-rc4: + version "1.0.0-rc4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.0-rc4.tgz#05ac6bc22227b43e4461f488161554699d4f8b5e" + dependencies: + async "^1.5.2" + combined-stream "^1.0.5" + mime-types "^2.1.10" + form-data@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-0.2.0.tgz#26f8bc26da6440e299cbdcfb69035c4f77a6e466" @@ -3166,14 +3176,6 @@ form-data@^2.1.2, form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" -form-data@1.0.0-rc4: - version "1.0.0-rc4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.0-rc4.tgz#05ac6bc22227b43e4461f488161554699d4f8b5e" - dependencies: - async "^1.5.2" - combined-stream "^1.0.5" - mime-types "^2.1.10" - formidable@^1.0.17: version "1.1.1" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.1.1.tgz#96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9" @@ -3392,37 +3394,6 @@ glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" -glob@^5.0.15, glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@7.0.5: version "7.0.5" resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" @@ -3445,6 +3416,37 @@ glob@7.0.x: once "^1.3.0" path-is-absolute "^1.0.0" +glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^5.0.15, glob@^5.0.3: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^9.0.0, globals@^9.14.0: version "9.17.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" @@ -3861,15 +3863,15 @@ https-proxy-agent@1: debug "2" extend "3" -iconv-lite@^0.4.5, iconv-lite@~0.4.13, iconv-lite@0.4.15: - version "0.4.15" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" - iconv-lite@0.4.13: version "0.4.13" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" -icss-replace-symbols@^1.0.2, icss-replace-symbols@1.0.2: +iconv-lite@0.4.15, iconv-lite@^0.4.5, iconv-lite@~0.4.13: + version "0.4.15" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" + +icss-replace-symbols@1.0.2, icss-replace-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.0.2.tgz#cb0b6054eb3af6edc9ab1d62d01933e2d4c8bfa5" @@ -3933,7 +3935,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@2, inherits@2.0.3: +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -3952,7 +3954,24 @@ inquirer-confirm@0.2.2: bluebird "2.9.24" inquirer "0.8.2" -inquirer@^0.12.0, inquirer@0.12.0: +inquirer@0.11.1: + version "0.11.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.11.1.tgz#623b6e0c101d2fe9e8e8ed902e651e0519d143e5" + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^1.0.1" + figures "^1.3.5" + lodash "^3.3.1" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + strip-ansi "^3.0.0" + through "^2.3.6" + +inquirer@0.12.0, inquirer@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" dependencies: @@ -3970,6 +3989,19 @@ inquirer@^0.12.0, inquirer@0.12.0: strip-ansi "^3.0.0" through "^2.3.6" +inquirer@0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.8.2.tgz#41586548e1c5d9b3f81df7325034baacab6f58ab" + dependencies: + ansi-regex "^1.1.1" + chalk "^1.0.0" + cli-width "^1.0.1" + figures "^1.3.5" + lodash "^3.3.1" + readline2 "^0.1.1" + rx "^2.4.3" + through "^2.3.6" + inquirer@^3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" @@ -3988,36 +4020,6 @@ inquirer@^3.0.6: strip-ansi "^3.0.0" through "^2.3.6" -inquirer@0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.11.1.tgz#623b6e0c101d2fe9e8e8ed902e651e0519d143e5" - dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" - cli-width "^1.0.1" - figures "^1.3.5" - lodash "^3.3.1" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - strip-ansi "^3.0.0" - through "^2.3.6" - -inquirer@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.8.2.tgz#41586548e1c5d9b3f81df7325034baacab6f58ab" - dependencies: - ansi-regex "^1.1.1" - chalk "^1.0.0" - cli-width "^1.0.1" - figures "^1.3.5" - lodash "^3.3.1" - readline2 "^0.1.1" - rx "^2.4.3" - through "^2.3.6" - interpret@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90" @@ -4271,14 +4273,14 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -isarray@^1.0.0, isarray@~1.0.0, isarray@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + isemail@1.x.x: version "1.2.0" resolved "https://registry.yarnpkg.com/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a" @@ -4435,7 +4437,7 @@ js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" -js-yaml@^3.4.3, js-yaml@^3.5.1, js-yaml@^3.7.0, js-yaml@3.x: +js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.5.1, js-yaml@^3.7.0: version "3.8.3" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.3.tgz#33a05ec481c850c8875929166fe1beb61c728766" dependencies: @@ -4598,9 +4600,9 @@ jws@^3.1.4: jwa "^1.1.4" safe-buffer "^5.0.1" -kareem@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/kareem/-/kareem-1.4.0.tgz#640285bc0174f10d4bf2127bb30e861bc0372c1c" +kareem@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/kareem/-/kareem-1.4.1.tgz#ed76200044fa041ef32b4da8261e2553f1173531" keymaster@^1.6.2: version "1.6.2" @@ -4949,7 +4951,7 @@ lodash.pick@^4.2.1, lodash.pick@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" -lodash.reduce@^4.4.0, lodash.reduce@4.6.0: +lodash.reduce@4.6.0, lodash.reduce@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" @@ -4973,18 +4975,18 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@^3.3.1, lodash@3.10.1: +lodash@3.10.1, lodash@^3.3.1: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.6, lodash@^4.17.2, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - lodash@3.9.3: version "3.9.3" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.9.3.tgz#0159e86832feffc6d61d852b12a953b99496bd32" +lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.6, lodash@^4.17.2, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" @@ -5081,7 +5083,7 @@ metascraper@^1.0.6: popsicle "^6.2.0" to-title-case "^1.0.0" -methods@^1.1.1, methods@^1.1.2, methods@~1.1.2, methods@1.x: +methods@1.x, methods@^1.1.1, methods@^1.1.2, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -5130,7 +5132,7 @@ mime-types@~2.0.3: dependencies: mime-db "~1.12.0" -mime@^1.3.4, mime@1.3.4: +mime@1.3.4, mime@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" @@ -5146,17 +5148,13 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, "minimatch@2 || 3", minimatch@3.0.3: +"minimatch@2 || 3", minimatch@3.0.3, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" dependencies: brace-expansion "^1.0.0" -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -minimist@~0.0.1, minimist@0.0.8: +minimist@0.0.8, minimist@~0.0.1: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -5164,11 +5162,9 @@ minimist@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.0.tgz#cdf225e8898f840a258ded44fc91776770afdc93" -mkdirp@^0.5.0, mkdirp@^0.5.1, "mkdirp@>=0.5 0", mkdirp@~0.5.0, mkdirp@~0.5.1, mkdirp@0.5.1, mkdirp@0.5.x: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" mkdirp@0.5.0: version "0.5.0" @@ -5176,6 +5172,12 @@ mkdirp@0.5.0: dependencies: minimist "0.0.8" +mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + mkpath@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mkpath/-/mkpath-1.0.0.tgz#ebb3a977e7af1c683ae6fda12b545a6ba6c5853d" @@ -5221,14 +5223,14 @@ mocha@^3.1.2: mkdirp "0.5.1" supports-color "3.1.2" -moment@^2.10.3, moment@2.x.x: - version "2.18.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" - moment@2.17.0: version "2.17.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.17.0.tgz#a4c292e02aac5ddefb29a6eed24f51938dd3b74f" +moment@2.x.x, moment@^2.10.3: + version "2.18.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" + mongodb-core@2.1.10: version "2.1.10" resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.10.tgz#eb290681d196d3346a492161aa2ea0905e63151b" @@ -5244,14 +5246,14 @@ mongodb@2.2.26: mongodb-core "2.1.10" readable-stream "2.2.7" -mongoose@^4.9.1: - version "4.9.6" - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.9.6.tgz#8485879893a33fe4b8c8b596950cfa9a8d597ec1" +mongoose@^4.9.8: + version "4.9.8" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.9.8.tgz#ef64304231dc2455ab15a0c0cb6c149ce8c787bb" dependencies: async "2.1.4" bson "~1.0.4" hooks-fixed "2.0.0" - kareem "1.4.0" + kareem "1.4.1" mongodb "2.2.26" mpath "0.2.1" mpromise "0.5.5" @@ -5288,10 +5290,6 @@ mquery@2.3.0: regexp-clone "0.0.1" sliced "0.0.5" -ms@^0.7.1, ms@0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" - ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" @@ -5300,6 +5298,10 @@ ms@0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" +ms@0.7.3, ms@^0.7.1: + version "0.7.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" + muri@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/muri/-/muri-1.2.1.tgz#ec7ea5ce6ca6a523eb1ab35bacda5fa816c9aa3c" @@ -5316,7 +5318,7 @@ mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -nan@^2.3.0, nan@^2.4.0, nan@2.5.0: +nan@2.5.0, nan@^2.3.0, nan@^2.4.0: version "2.5.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.0.tgz#aa8f1e34531d807e9e27755b234b4a6ec0c152a8" @@ -5427,7 +5429,7 @@ node-libs-browser@^2.0.0: util "^0.10.3" vm-browserify "0.0.4" -node-pre-gyp@^0.6.29, node-pre-gyp@0.6.32: +node-pre-gyp@0.6.32, node-pre-gyp@^0.6.29: version "0.6.32" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.32.tgz#fc452b376e7319b3d255f5f34853ef6fd8fe1fd5" dependencies: @@ -5519,15 +5521,15 @@ nodemon@^1.11.0: undefsafe "0.0.3" update-notifier "0.5.0" -nopt@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" +nopt@3.x, nopt@~3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" dependencies: abbrev "1" -nopt@~3.0.6, nopt@3.x: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" dependencies: abbrev "1" @@ -5671,7 +5673,7 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -optimist@^0.6.1, optimist@0.6.1: +optimist@0.6.1, optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" dependencies: @@ -5864,16 +5866,16 @@ path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + path-to-regexp@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" dependencies: isarray "0.0.1" -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -6183,33 +6185,33 @@ postcss-mixins@^2.1.0: postcss "^5.0.10" postcss-simple-vars "^1.0.1" -postcss-modules-extract-imports@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.0.1.tgz#8fb3fef9a6dd0420d3f6d4353cf1ff73f2b2a341" - dependencies: - postcss "^5.0.4" - postcss-modules-extract-imports@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.0.0.tgz#5b07f368e350cda6fd5c8844b79123a7bd3e37be" dependencies: postcss "^5.0.4" -postcss-modules-local-by-default@^1.0.1, postcss-modules-local-by-default@1.1.1: +postcss-modules-extract-imports@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.0.1.tgz#8fb3fef9a6dd0420d3f6d4353cf1ff73f2b2a341" + dependencies: + postcss "^5.0.4" + +postcss-modules-local-by-default@1.1.1, postcss-modules-local-by-default@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.1.1.tgz#29a10673fa37d19251265ca2ba3150d9040eb4ce" dependencies: css-selector-tokenizer "^0.6.0" postcss "^5.0.4" -postcss-modules-scope@^1.0.0, postcss-modules-scope@1.0.2: +postcss-modules-scope@1.0.2, postcss-modules-scope@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.0.2.tgz#ff977395e5e06202d7362290b88b1e8cd049de29" dependencies: css-selector-tokenizer "^0.6.0" postcss "^5.0.4" -postcss-modules-values@^1.1.0, postcss-modules-values@1.2.2: +postcss-modules-values@1.2.2, postcss-modules-values@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.2.2.tgz#f0e7d476fe1ed88c5e4c7f97533a3e772ad94ca1" dependencies: @@ -6375,6 +6377,14 @@ postcss-zindex@^2.0.1: postcss "^5.0.4" uniqs "^2.0.0" +postcss@5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.1.2.tgz#bd84886a66bcad489afaf7c673eed5ef639551e2" + dependencies: + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.1.2" + postcss@^5.0.0, postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.19, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.1.2, postcss@^5.2.13, postcss@^5.2.15, postcss@^5.2.16, postcss@^5.2.17, postcss@^5.2.4, postcss@^5.2.5: version "5.2.17" resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.17.tgz#cf4f597b864d65c8a492b2eabe9d706c879c388b" @@ -6384,14 +6394,6 @@ postcss@^5.0.0, postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0. source-map "^0.5.6" supports-color "^3.2.3" -postcss@5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.1.2.tgz#bd84886a66bcad489afaf7c673eed5ef639551e2" - dependencies: - js-base64 "^2.1.9" - source-map "^0.5.6" - supports-color "^3.1.2" - pre-git@^3.10.0: version "3.14.0" resolved "https://registry.yarnpkg.com/pre-git/-/pre-git-3.14.0.tgz#abe7d6411febe8c908a6a89a94f9ae02a63aa81f" @@ -6456,7 +6458,7 @@ process@^0.11.0: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" -progress@^1.1.8, progress@1.1.8: +progress@1.1.8, progress@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" @@ -6619,26 +6621,26 @@ pug@^2.0.0-beta3: pug-runtime "^2.0.3" pug-strip-comments "^1.0.2" -punycode@^1.2.4, punycode@^1.4.1, punycode@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" +punycode@1.4.1, punycode@^1.2.4, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + pym.js@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/pym.js/-/pym.js-1.2.0.tgz#feb1e2c9b396613e5172192b0cdd75408f9c8322" -q@^1.1.2, q@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" - q@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/q/-/q-1.1.2.tgz#6357e291206701d99f197ab84e57e8ad196f2a89" +q@1.4.1, q@^1.1.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" + q@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/q/-/q-2.0.3.tgz#75b8db0255a1a5af82f58c3f3aaa1efec7d0d134" @@ -6647,7 +6649,7 @@ q@2.0.3: pop-iterate "^1.0.1" weak-map "^1.0.5" -qs@^6.1.0, qs@^6.2.0, qs@~6.4.0, qs@6.4.0: +qs@6.4.0, qs@^6.1.0, qs@^6.2.0, qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" @@ -6674,14 +6676,14 @@ quote@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/quote/-/quote-0.4.0.tgz#10839217f6c1362b89194044d29b233fd7f32f01" -ramda@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.23.0.tgz#ccd13fff73497a93974e3e86327bfd87bd6e8e2b" - ramda@0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.9.1.tgz#cc914dc3a82c608d003090203787c3f6826c1d87" +ramda@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.23.0.tgz#ccd13fff73497a93974e3e86327bfd87bd6e8e2b" + random-bytes@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" @@ -6743,7 +6745,7 @@ react-apollo@^1.1.0: optionalDependencies: react-dom "0.14.x || 15.* || ^15.0.0" -react-dom@^15.3.1, react-dom@^15.4.2, "react-dom@0.14.x || 15.* || ^15.0.0": +"react-dom@0.14.x || 15.* || ^15.0.0", react-dom@^15.3.1, react-dom@^15.4.2: version "15.5.4" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.5.4.tgz#ba0c28786fd52ed7e4f2135fe0288d462aef93da" dependencies: @@ -6858,7 +6860,16 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@2, readable-stream@2.2.7: +readable-stream@1.1, readable-stream@1.1.x: + version "1.1.13" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@2, readable-stream@2.2.7, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.6: version "2.2.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1" dependencies: @@ -6882,15 +6893,6 @@ readable-stream@~2.1.4: string_decoder "~0.10.x" util-deprecate "~1.0.1" -readable-stream@1.1, readable-stream@1.1.x: - version "1.1.13" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readdirp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" @@ -6915,15 +6917,6 @@ readline2@^1.0.1: is-fullwidth-code-point "^1.0.0" mute-stream "0.0.5" -recast@^0.11.17: - version "0.11.23" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3" - dependencies: - ast-types "0.9.6" - esprima "~3.1.0" - private "~0.1.5" - source-map "~0.5.0" - recast@0.10.33: version "0.10.33" resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.33.tgz#942808f7aa016f1fa7142c461d7e5704aaa8d697" @@ -6933,6 +6926,15 @@ recast@0.10.33: private "~0.1.5" source-map "~0.5.0" +recast@^0.11.17: + version "0.11.23" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3" + dependencies: + ast-types "0.9.6" + esprima "~3.1.0" + private "~0.1.5" + source-map "~0.5.0" + rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" @@ -7117,6 +7119,31 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" +request@2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + request@^2.55.0, request@^2.74.0, request@^2.79.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -7144,38 +7171,6 @@ request@^2.55.0, request@^2.74.0, request@^2.79.0: tunnel-agent "^0.6.0" uuid "^3.0.0" -request@2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - -require_optional@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.0.tgz#52a86137a849728eb60a55533617f8f914f59abf" - dependencies: - resolve-from "^2.0.0" - semver "^5.1.0" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -7199,6 +7194,13 @@ require-uncached@^1.0.2: caller-path "^0.1.0" resolve-from "^1.0.0" +require_optional@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.0.tgz#52a86137a849728eb60a55533617f8f914f59abf" + dependencies: + resolve-from "^2.0.0" + semver "^5.1.0" + resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" @@ -7241,7 +7243,7 @@ right-pad@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/right-pad/-/right-pad-1.0.1.tgz#8ca08c2cbb5b55e74dafa96bf7fd1a27d568c8d0" -rimraf@^2.2.8, rimraf@^2.4.4, rimraf@~2.5.1, rimraf@~2.5.4, rimraf@2: +rimraf@2, rimraf@^2.2.8, rimraf@^2.4.4, rimraf@~2.5.1, rimraf@~2.5.4: version "2.5.4" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04" dependencies: @@ -7283,14 +7285,14 @@ safe-buffer@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" -sax@^1.1.4, sax@^1.2.1, sax@~1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828" - sax@0.5.x: version "0.5.8" resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1" +sax@^1.1.4, sax@^1.2.1, sax@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828" + selenium-standalone@^5.11.2: version "5.11.2" resolved "https://registry.yarnpkg.com/selenium-standalone/-/selenium-standalone-5.11.2.tgz#724ccaa72fb26f3711e0e20989e478c4133df844" @@ -7317,18 +7319,18 @@ semver-regex@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9" -semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@~5.3.0, "semver@2 || 3 || 4 || 5": +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" -semver@~5.0.1: - version "5.0.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" - semver@5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.1.0.tgz#85f2cf8550465c4df000cf7d86f6b054106ab9e5" +semver@~5.0.1: + version "5.0.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" + send@0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/send/-/send-0.15.1.tgz#8a02354c26e6f5cca700065f5f0cdeba90ec7b5f" @@ -7392,6 +7394,10 @@ shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" +shelljs@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.0.tgz#ce1ed837b4b0e55b5ec3dab84251ab9dbdc0c7ec" + shelljs@^0.7.0, shelljs@^0.7.5: version "0.7.7" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1" @@ -7400,10 +7406,6 @@ shelljs@^0.7.0, shelljs@^0.7.5: interpret "^1.0.0" rechoir "^0.6.2" -shelljs@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.0.tgz#ce1ed837b4b0e55b5ec3dab84251ab9dbdc0c7ec" - signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -7482,7 +7484,7 @@ socks-proxy-agent@2: extend "3" socks "~1.1.5" -socks@~1.1.5, socks@1.1.9: +socks@1.1.9, socks@~1.1.5: version "1.1.9" resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.9.tgz#628d7e4d04912435445ac0b6e459376cb3e6d691" dependencies: @@ -7509,13 +7511,19 @@ source-map-support@^0.4.2: dependencies: source-map "^0.5.6" -source-map@^0.4.4, source-map@0.4.x: +source-map@0.1.x: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + dependencies: + amdefine ">=0.0.4" + +source-map@0.4.x, source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3, source-map@0.5.x: +source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" @@ -7525,12 +7533,6 @@ source-map@~0.2.0: dependencies: amdefine ">=0.0.4" -source-map@0.1.x: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - dependencies: - amdefine ">=0.0.4" - spdx-correct@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" @@ -7627,16 +7629,6 @@ strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" -string_decoder@^0.10.25, string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -string_decoder@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667" - dependencies: - buffer-shims "~1.0.0" - string-hash@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" @@ -7666,6 +7658,16 @@ string.prototype.codepointat@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/string.prototype.codepointat/-/string.prototype.codepointat-0.2.0.tgz#6b26e9bd3afcaa7be3b4269b526de1b82000ac78" +string_decoder@^0.10.25, string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667" + dependencies: + buffer-shims "~1.0.0" + stringmap@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/stringmap/-/stringmap-0.2.2.tgz#556c137b258f942b8776f5b2ef582aa069d7d1b1" @@ -7710,7 +7712,7 @@ style-loader@^0.16.0: dependencies: loader-utils "^1.0.2" -stylus@~0.54.5, stylus@0.54.5: +stylus@0.54.5, stylus@~0.54.5: version "0.54.5" resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.5.tgz#42b9560931ca7090ce8515a798ba9e6aa3d6dc79" dependencies: @@ -7763,16 +7765,16 @@ supertest@^2.0.1: methods "1.x" superagent "^2.0.0" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -supports-color@^3.1.0, supports-color@3.1.2: +supports-color@3.1.2, supports-color@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" dependencies: has-flag "^1.0.0" +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + supports-color@^3.1.2, supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" @@ -7799,7 +7801,7 @@ symbol-observable@^1.0.2, symbol-observable@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" -symbol-tree@^3.2.1, "symbol-tree@>= 3.1.0 < 4.0.0": +"symbol-tree@>= 3.1.0 < 4.0.0", symbol-tree@^3.2.1: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -7866,7 +7868,7 @@ text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" -through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.8, through@2: +through@2, through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -8023,14 +8025,14 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" - type-detect@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" +type-detect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" + type-is@~1.6.14: version "1.6.15" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" @@ -8071,7 +8073,7 @@ uid-number@~0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" -uid-safe@~2.1.4, uid-safe@2.1.4: +uid-safe@2.1.4, uid-safe@~2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.4.tgz#3ad6f38368c6d4c8c75ec17623fb79aa1d071d81" dependencies: @@ -8107,7 +8109,7 @@ uniqs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" -unpipe@~1.0.0, unpipe@1.0.0: +unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -8148,7 +8150,7 @@ util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -util@^0.10.3, util@0.10.3: +util@0.10.3, util@^0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" dependencies: @@ -8287,7 +8289,7 @@ whatwg-encoding@^1.0.1: dependencies: iconv-lite "0.4.13" -whatwg-fetch@^2.0.0, whatwg-fetch@>=0.10.0: +whatwg-fetch@>=0.10.0, whatwg-fetch@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" @@ -8312,24 +8314,28 @@ which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" -which@^1.1.1, which@^1.2.9: - version "1.2.14" - resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" - dependencies: - isexe "^2.0.0" - which@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/which/-/which-1.1.1.tgz#9ce512459946166e12c083f08ec073380fc8cbbb" dependencies: is-absolute "^0.1.7" +which@^1.1.1, which@^1.2.9: + version "1.2.14" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" + dependencies: + isexe "^2.0.0" + wide-align@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad" dependencies: string-width "^1.0.1" +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + window-size@^0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" @@ -8338,10 +8344,6 @@ window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - with@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/with/-/with-5.1.1.tgz#fa4daa92daf32c4ea94ed453c81f04686b575dfe" @@ -8349,22 +8351,22 @@ with@^5.0.0: acorn "^3.1.0" acorn-globals "^3.0.0" -word-wrap@^1.0.3, word-wrap@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.1.tgz#248f459b465d179a17bc407c854d3151d07e45d8" - word-wrap@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.1.0.tgz#356153d61d10610d600785c5d701288e0ae764a6" +word-wrap@1.2.1, word-wrap@^1.0.3: + version "1.2.1" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.1.tgz#248f459b465d179a17bc407c854d3151d07e45d8" + +wordwrap@0.0.2, wordwrap@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + wordwrap@^1.0.0, wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" -wordwrap@~0.0.2, wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -8407,7 +8409,7 @@ xdg-basedir@^2.0.0: dependencies: os-homedir "^1.0.0" -xml-name-validator@^2.0.1, "xml-name-validator@>= 2.0.1 < 3.0.0": +"xml-name-validator@>= 2.0.1 < 3.0.0", xml-name-validator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" @@ -8533,4 +8535,3 @@ yauzl@^2.5.0: dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.0.1" - From 547ba126bef5cde43c500f7dd72d9a36a4e7b4ad Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 11 May 2017 17:31:22 -0600 Subject: [PATCH 02/16] cleanup to mutators --- graph/mutators/comment.js | 14 +++++++------- graph/resolvers/root_mutation.js | 4 ++-- models/user.js | 3 ++- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/graph/mutators/comment.js b/graph/mutators/comment.js index ddbcf9c5d..048e24fac 100644 --- a/graph/mutators/comment.js +++ b/graph/mutators/comment.js @@ -172,7 +172,7 @@ const createPublicComment = async (context, commentInput) => { * @param {String} status the new status of the comment */ -const setCommentStatus = async ({user, loaders: {Comments}}, {id, status}) => { +const setStatus = async ({user, loaders: {Comments}}, {id, status}) => { let comment = await CommentsService.pushStatus(id, status, user ? user.id : null); // If the loaders are present, clear the caches for these values because we @@ -215,7 +215,7 @@ const removeCommentTag = ({user, loaders: {Comments}}, {id, tag}) => { * @param {Object} edit describes how to edit the comment * @param {String} edit.body the new Comment body */ -const editComment = async (context, {id, asset_id, edit: {body}}) => { +const edit = async (context, {id, asset_id, edit: {body}}) => { // Get the wordlist and the settings object. const [wordlist, settings] = await filterNewComment(context, {asset_id, body}); @@ -232,10 +232,10 @@ module.exports = (context) => { let mutators = { Comment: { create: () => Promise.reject(errors.ErrNotAuthorized), - setCommentStatus: () => Promise.reject(errors.ErrNotAuthorized), + setStatus: () => Promise.reject(errors.ErrNotAuthorized), addCommentTag: () => Promise.reject(errors.ErrNotAuthorized), removeCommentTag: () => Promise.reject(errors.ErrNotAuthorized), - editComment: () => Promise.reject(errors.ErrNotAuthorized), + edit: () => Promise.reject(errors.ErrNotAuthorized), } }; @@ -244,7 +244,7 @@ module.exports = (context) => { } if (context.user && context.user.can('mutation:setCommentStatus')) { - mutators.Comment.setCommentStatus = (action) => setCommentStatus(context, action); + mutators.Comment.setStatus = (action) => setStatus(context, action); } if (context.user && context.user.can('mutation:addCommentTag')) { @@ -255,8 +255,8 @@ module.exports = (context) => { mutators.Comment.removeCommentTag = (action) => removeCommentTag(context, action); } - if (context.user) { - mutators.Comment.editComment = (action) => editComment(context, action); + if (context.user && context.user.can('mutation:editComment')) { + mutators.Comment.edit = (action) => edit(context, action); } return mutators; diff --git a/graph/resolvers/root_mutation.js b/graph/resolvers/root_mutation.js index d3cee718c..3ad6fbfd8 100644 --- a/graph/resolvers/root_mutation.js +++ b/graph/resolvers/root_mutation.js @@ -6,7 +6,7 @@ const RootMutation = { return wrapResponse('comment')(Comment.create(comment)); }, editComment(_, args, {mutators: {Comment}}) { - return wrapResponse('comment')(Comment.editComment(args)); + return wrapResponse('comment')(Comment.edit(args)); }, createFlag(_, {flag: {item_id, item_type, reason, message}}, {mutators: {Action}}) { return wrapResponse('flag')(Action.create({item_id, item_type, action_type: 'FLAG', group_id: reason, metadata: {message}})); @@ -30,7 +30,7 @@ const RootMutation = { return wrapResponse(null)(User.stopIgnoringUser({id})); }, setCommentStatus(_, {id, status}, {mutators: {Comment}}) { - return wrapResponse(null)(Comment.setCommentStatus({id, status})); + return wrapResponse(null)(Comment.setStatus({id, status})); }, addCommentTag(_, {id, tag}, {mutators: {Comment}}) { return wrapResponse('comment')(Comment.addCommentTag({id, tag}).then(() => CommentsService.findById(id))); diff --git a/models/user.js b/models/user.js index 458ac68f0..3544dd309 100644 --- a/models/user.js +++ b/models/user.js @@ -199,7 +199,8 @@ const USER_GRAPH_OPERATIONS = [ 'mutation:suspendUser', 'mutation:setCommentStatus', 'mutation:addCommentTag', - 'mutation:removeCommentTag' + 'mutation:removeCommentTag', + 'mutation:editComment' ]; /** From 08e7a90d6926c6d772f697e37b16c6ceb49a11ad Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 11 May 2017 17:34:47 -0600 Subject: [PATCH 03/16] lint fixes --- .eslintrc.json | 1 + .../coral-admin/src/containers/Community/components/User.js | 4 ++-- client/coral-embed-stream/src/components/Comment.js | 4 ++-- client/coral-embed-stream/src/containers/Embed.js | 2 +- client/coral-plugin-best/BestButton.js | 6 +++--- client/coral-plugin-infobox/Markdown.js | 2 +- graph/resolvers/root_query.js | 2 +- 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 293657679..65be1bab6 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -36,6 +36,7 @@ "no-unneeded-ternary": [1], "object-curly-spacing": [1], "space-infix-ops": ["error"], + "space-in-parens": ["error", "never"], "no-const-assign": [2], "no-duplicate-imports": [2], "prefer-template": [1], diff --git a/client/coral-admin/src/containers/Community/components/User.js b/client/coral-admin/src/containers/Community/components/User.js index 20b599a7a..b6e4a0cc6 100644 --- a/client/coral-admin/src/containers/Community/components/User.js +++ b/client/coral-admin/src/containers/Community/components/User.js @@ -37,7 +37,7 @@ const User = props => {
flag{lang.t('community.flags')}({ user.actions.length }): { user.action_summaries.map( - (action, i ) => { + (action, i) => { return {lang.t(`community.${action.reason}`)} ({action.count}) ; @@ -46,7 +46,7 @@ const User = props => {
{ user.action_summaries.map( - (action_sum, i ) => { + (action_sum, i) => { return
{lang.t(`community.${action_sum.reason}`)} ({action_sum.count}) diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index 13d286296..a7f7b760a 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -427,7 +427,7 @@ export default Comment; // return whether the comment is editable function commentIsStillEditable (comment) { const editing = comment && comment.editing; - if ( ! editing) {return false;} + if (! editing) {return false;} const editableUntil = getEditableUntilDate(comment); const editWindowExpired = (editableUntil - new Date) < 0; return ! editWindowExpired; @@ -436,7 +436,7 @@ function commentIsStillEditable (comment) { // return number of milliseconds before edit window expires function editWindowRemainingMs (comment) { const editableUntil = getEditableUntilDate(comment); - if ( ! editableUntil) {return;} + if (! editableUntil) {return;} const now = new Date(); const editWindowRemainingMs = (editableUntil - now); return editWindowRemainingMs; diff --git a/client/coral-embed-stream/src/containers/Embed.js b/client/coral-embed-stream/src/containers/Embed.js index 0d21aac0a..3cc84a097 100644 --- a/client/coral-embed-stream/src/containers/Embed.js +++ b/client/coral-embed-stream/src/containers/Embed.js @@ -124,7 +124,7 @@ export default compose( * producing a new queryStream result where asset.comments reflects the edit */ function reduceEditCommentActionsToUpdateStreamQuery(previousResult, action) { - if ( ! (action.type === 'APOLLO_MUTATION_RESULT' && action.operationName === 'editComment')) { + if (! (action.type === 'APOLLO_MUTATION_RESULT' && action.operationName === 'editComment')) { return previousResult; } const resultHasErrors = (result) => { diff --git a/client/coral-plugin-best/BestButton.js b/client/coral-plugin-best/BestButton.js index 96ef45f86..df20bf53d 100644 --- a/client/coral-plugin-best/BestButton.js +++ b/client/coral-plugin-best/BestButton.js @@ -29,7 +29,7 @@ export const BestIndicator = ({children = }) => ( * Component that only renders children if the provided user prop can modify best tags */ export const IfUserCanModifyBest = ({user, children}) => { - if ( ! ( user && canModifyBestTag(user))) {return null;} + if (! (user && canModifyBestTag(user))) {return null;} return children; }; @@ -63,7 +63,7 @@ export class BestButton extends Component { async onClickAddBest(e) { e.preventDefault(); const {addBest} = this.props; - if ( ! addBest) { + if (! addBest) { console.warn('BestButton#onClickAddBest called even though there is no addBest prop. doing nothing'); return; } @@ -78,7 +78,7 @@ export class BestButton extends Component { async onClickRemoveBest(e) { e.preventDefault(); const {removeBest} = this.props; - if ( ! removeBest) { + if (! removeBest) { console.warn('BestButton#onClickAddBest called even though there is no removeBest prop. doing nothing'); return; } diff --git a/client/coral-plugin-infobox/Markdown.js b/client/coral-plugin-infobox/Markdown.js index 59b63bcb0..b5cf88d22 100644 --- a/client/coral-plugin-infobox/Markdown.js +++ b/client/coral-plugin-infobox/Markdown.js @@ -4,7 +4,7 @@ import marked from 'marked'; const renderer = new marked.Renderer(); // Set link target to `_parent` to work properly in an embed. -renderer.link = ( href, title, text ) => +renderer.link = (href, title, text) => `${text}`; marked.setOptions({renderer}); diff --git a/graph/resolvers/root_query.js b/graph/resolvers/root_query.js index 4dcb7ea11..749660acb 100644 --- a/graph/resolvers/root_query.js +++ b/graph/resolvers/root_query.js @@ -90,7 +90,7 @@ const RootQuery = { // get currentUser again since context.user was out of date when running test/graph/mutations/ignoreUser const currentUser = (await Users.getByQuery({ids: [user.id], limit: 1}))[0]; - if ( ! (currentUser && Array.isArray(currentUser.ignoresUsers) && currentUser.ignoresUsers.length)) { + if (! (currentUser && Array.isArray(currentUser.ignoresUsers) && currentUser.ignoresUsers.length)) { return []; } return await Users.getByQuery({ids: currentUser.ignoresUsers}); From a65d045c6583e1ddd0c5d93ebda258cb1e4ac6d0 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 11 May 2017 17:38:49 -0600 Subject: [PATCH 04/16] lint fixes --- .eslintrc.json | 4 ++++ client/coral-embed-stream/src/components/Comment.js | 6 +++--- .../src/components/EditableCommentContent.js | 2 +- client/coral-embed-stream/src/components/TopRightMenu.js | 2 +- client/coral-embed-stream/src/containers/Embed.js | 4 ++-- client/coral-plugin-best/BestButton.js | 8 ++++---- client/coral-plugin-commentbox/CommentForm.js | 2 +- graph/resolvers/root_query.js | 2 +- models/user.js | 2 +- 9 files changed, 18 insertions(+), 14 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 65be1bab6..f27e2a1bc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -37,6 +37,10 @@ "object-curly-spacing": [1], "space-infix-ops": ["error"], "space-in-parens": ["error", "never"], + "space-unary-ops": ["error", { + "words": true, + "nonwords": false + }], "no-const-assign": [2], "no-duplicate-imports": [2], "prefer-template": [1], diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index a7f7b760a..715d5b954 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -427,16 +427,16 @@ export default Comment; // return whether the comment is editable function commentIsStillEditable (comment) { const editing = comment && comment.editing; - if (! editing) {return false;} + if (!editing) {return false;} const editableUntil = getEditableUntilDate(comment); const editWindowExpired = (editableUntil - new Date) < 0; - return ! editWindowExpired; + return !editWindowExpired; } // return number of milliseconds before edit window expires function editWindowRemainingMs (comment) { const editableUntil = getEditableUntilDate(comment); - if (! editableUntil) {return;} + if (!editableUntil) {return;} const now = new Date(); const editWindowRemainingMs = (editableUntil - now); return editWindowRemainingMs; diff --git a/client/coral-embed-stream/src/components/EditableCommentContent.js b/client/coral-embed-stream/src/components/EditableCommentContent.js index 03b61edce..052da8e48 100644 --- a/client/coral-embed-stream/src/components/EditableCommentContent.js +++ b/client/coral-embed-stream/src/components/EditableCommentContent.js @@ -113,7 +113,7 @@ export class EditableCommentContent extends React.Component { // should be disabled if user hasn't actually changed their // original comment - return (comment.body !== originalBody) && ! editWindowExpired; + return (comment.body !== originalBody) && !editWindowExpired; }} saveComment={this.editComment} bodyLabel={lang.t('editComment.bodyInputLabel')} diff --git a/client/coral-embed-stream/src/components/TopRightMenu.js b/client/coral-embed-stream/src/components/TopRightMenu.js index e6b264c27..84d64f061 100644 --- a/client/coral-embed-stream/src/components/TopRightMenu.js +++ b/client/coral-embed-stream/src/components/TopRightMenu.js @@ -72,7 +72,7 @@ class Toggleable extends React.Component { }; } toggle() { - this.setState({isOpen: ! this.state.isOpen}); + this.setState({isOpen: !this.state.isOpen}); } close() { this.setState({isOpen: false}); diff --git a/client/coral-embed-stream/src/containers/Embed.js b/client/coral-embed-stream/src/containers/Embed.js index 3cc84a097..dcf531fa7 100644 --- a/client/coral-embed-stream/src/containers/Embed.js +++ b/client/coral-embed-stream/src/containers/Embed.js @@ -124,7 +124,7 @@ export default compose( * producing a new queryStream result where asset.comments reflects the edit */ function reduceEditCommentActionsToUpdateStreamQuery(previousResult, action) { - if (! (action.type === 'APOLLO_MUTATION_RESULT' && action.operationName === 'editComment')) { + if (!(action.type === 'APOLLO_MUTATION_RESULT' && action.operationName === 'editComment')) { return previousResult; } const resultHasErrors = (result) => { @@ -151,7 +151,7 @@ function reduceEditCommentActionsToUpdateStreamQuery(previousResult, action) { return editedComment; }; const commentIsStillVisible = (comment) => { - return ! ((id === comment.id) && (['PREMOD', 'REJECTED'].includes(status))); + return !((id === comment.id) && (['PREMOD', 'REJECTED'].includes(status))); }; const resultReflectingEdit = update(previousResult, { asset: { diff --git a/client/coral-plugin-best/BestButton.js b/client/coral-plugin-best/BestButton.js index df20bf53d..43bea7624 100644 --- a/client/coral-plugin-best/BestButton.js +++ b/client/coral-plugin-best/BestButton.js @@ -29,7 +29,7 @@ export const BestIndicator = ({children = }) => ( * Component that only renders children if the provided user prop can modify best tags */ export const IfUserCanModifyBest = ({user, children}) => { - if (! (user && canModifyBestTag(user))) {return null;} + if (!(user && canModifyBestTag(user))) {return null;} return children; }; @@ -63,7 +63,7 @@ export class BestButton extends Component { async onClickAddBest(e) { e.preventDefault(); const {addBest} = this.props; - if (! addBest) { + if (!addBest) { console.warn('BestButton#onClickAddBest called even though there is no addBest prop. doing nothing'); return; } @@ -78,7 +78,7 @@ export class BestButton extends Component { async onClickRemoveBest(e) { e.preventDefault(); const {removeBest} = this.props; - if (! removeBest) { + if (!removeBest) { console.warn('BestButton#onClickAddBest called even though there is no removeBest prop. doing nothing'); return; } @@ -93,7 +93,7 @@ export class BestButton extends Component { render() { const {isBest, addBest, removeBest} = this.props; const {isSaving} = this.state; - const disabled = isSaving || ! (isBest ? removeBest : addBest); + const disabled = isSaving || !(isBest ? removeBest : addBest); return (

- Forgot your password? { + Forgot your password? { e.preventDefault(); this.setState({requestPassword: true}); }}>Request a new one. @@ -82,7 +82,7 @@ class AdminLogin extends React.Component { this.setState({email: e.target.value})} /> + onChange={(e) => this.setState({email: e.target.value})} />

diff --git a/client/coral-admin/src/containers/Configure/EmbedLink.js b/client/coral-admin/src/containers/Configure/EmbedLink.js index 86ab8b1f8..d61c64c11 100644 --- a/client/coral-admin/src/containers/Configure/EmbedLink.js +++ b/client/coral-admin/src/containers/Configure/EmbedLink.js @@ -30,7 +30,7 @@ class EmbedLink extends Component { location.protocol, '//', location.hostname, - location.port ? (`:${ window.location.port}`) : '' + location.port ? (`:${window.location.port}`) : '' ].join(''); const coralJsUrl = [talkBaseUrl, '/embed.js'].join(''); const nonce = String(Math.random()).slice(2); diff --git a/client/coral-admin/src/containers/Configure/StreamSettings.js b/client/coral-admin/src/containers/Configure/StreamSettings.js index 08ec062c8..646eb9d9e 100644 --- a/client/coral-admin/src/containers/Configure/StreamSettings.js +++ b/client/coral-admin/src/containers/Configure/StreamSettings.js @@ -170,7 +170,7 @@ export default StreamSettings; // To see if we are talking about weeks, days or hours // We talk the remainder of the division and see if it's 0 -const getTimeoutMeasure = ts => { +const getTimeoutMeasure = (ts) => { if (ts % TIMESTAMPS['weeks'] === 0) { return 'weeks'; } else if (ts % TIMESTAMPS['days'] === 0) { @@ -182,6 +182,6 @@ const getTimeoutMeasure = ts => { // Dividing the amount by it's measure (hours, days, weeks) we // obtain the amount of time -const getTimeoutAmount = ts => ts / TIMESTAMPS[getTimeoutMeasure(ts)]; +const getTimeoutAmount = (ts) => ts / TIMESTAMPS[getTimeoutMeasure(ts)]; const lang = new I18n(translations); diff --git a/client/coral-admin/src/containers/Configure/Wordlist.js b/client/coral-admin/src/containers/Configure/Wordlist.js index 8eb010b79..983047acf 100644 --- a/client/coral-admin/src/containers/Configure/Wordlist.js +++ b/client/coral-admin/src/containers/Configure/Wordlist.js @@ -15,8 +15,8 @@ const Wordlist = ({suspectWords, bannedWords, onChangeWordlist}) => ( value={bannedWords} inputProps={{placeholder: 'word or phrase'}} addOnPaste={true} - pasteSplit={data => data.split(',').map(d => d.trim())} - onChange={tags => onChangeWordlist('banned', tags)} + pasteSplit={(data) => data.split(',').map((d) => d.trim())} + onChange={(tags) => onChangeWordlist('banned', tags)} /> @@ -28,8 +28,8 @@ const Wordlist = ({suspectWords, bannedWords, onChangeWordlist}) => ( value={suspectWords} inputProps={{placeholder: 'word or phrase'}} addOnPaste={true} - pasteSplit={data => data.split(',').map(d => d.trim())} - onChange={tags => onChangeWordlist('suspect', tags)} /> + pasteSplit={(data) => data.split(',').map((d) => d.trim())} + onChange={(tags) => onChangeWordlist('suspect', tags)} /> diff --git a/client/coral-admin/src/containers/Dashboard/ActivityWidget.js b/client/coral-admin/src/containers/Dashboard/ActivityWidget.js index a6e293b82..d6cbb8edd 100644 --- a/client/coral-admin/src/containers/Dashboard/ActivityWidget.js +++ b/client/coral-admin/src/containers/Dashboard/ActivityWidget.js @@ -17,7 +17,7 @@ const ActivityWidget = ({assets}) => {
{ assets.length - ? assets.map(asset => { + ? assets.map((asset) => { return (
Moderate diff --git a/client/coral-admin/src/containers/Dashboard/Dashboard.js b/client/coral-admin/src/containers/Dashboard/Dashboard.js index e6cfa27cd..e764bf596 100644 --- a/client/coral-admin/src/containers/Dashboard/Dashboard.js +++ b/client/coral-admin/src/containers/Dashboard/Dashboard.js @@ -35,7 +35,7 @@ class Dashboard extends React.Component { } } -const mapStateToProps = state => { +const mapStateToProps = (state) => { return { settings: state.settings.toJS(), moderation: state.moderation.toJS() diff --git a/client/coral-admin/src/containers/Dashboard/FlagWidget.js b/client/coral-admin/src/containers/Dashboard/FlagWidget.js index ea72cddc6..6a50223bc 100644 --- a/client/coral-admin/src/containers/Dashboard/FlagWidget.js +++ b/client/coral-admin/src/containers/Dashboard/FlagWidget.js @@ -18,10 +18,10 @@ const FlagWidget = ({assets}) => {
{ assets.length - ? assets.map(asset => { + ? assets.map((asset) => { let flagSummary = null; if (asset.action_summaries) { - flagSummary = asset.action_summaries.find(s => s.__typename === 'FlagAssetActionSummary'); + flagSummary = asset.action_summaries.find((s) => s.__typename === 'FlagAssetActionSummary'); } return ( diff --git a/client/coral-admin/src/containers/Dashboard/LikeWidget.js b/client/coral-admin/src/containers/Dashboard/LikeWidget.js index b878c281b..4d7483667 100644 --- a/client/coral-admin/src/containers/Dashboard/LikeWidget.js +++ b/client/coral-admin/src/containers/Dashboard/LikeWidget.js @@ -18,8 +18,8 @@ const LikeWidget = ({assets}) => {
{ assets.length - ? assets.map(asset => { - const likeSummary = asset.action_summaries.find(s => s.type === 'LikeAssetActionSummary'); + ? assets.map((asset) => { + const likeSummary = asset.action_summaries.find((s) => s.type === 'LikeAssetActionSummary'); return (
Moderate diff --git a/client/coral-admin/src/containers/Dashboard/MostLikedCommentsWidget.js b/client/coral-admin/src/containers/Dashboard/MostLikedCommentsWidget.js index 0c41ac7c6..c29c9ad43 100644 --- a/client/coral-admin/src/containers/Dashboard/MostLikedCommentsWidget.js +++ b/client/coral-admin/src/containers/Dashboard/MostLikedCommentsWidget.js @@ -7,7 +7,7 @@ import BanUserDialog from 'coral-admin/src/components/BanUserDialog'; const lang = new I18n(translations); -const MostLikedCommentsWidget = props => { +const MostLikedCommentsWidget = (props) => { const { comments, moderation, diff --git a/client/coral-admin/src/containers/Install/InstallContainer.js b/client/coral-admin/src/containers/Install/InstallContainer.js index 75c41387a..67f266123 100644 --- a/client/coral-admin/src/containers/Install/InstallContainer.js +++ b/client/coral-admin/src/containers/Install/InstallContainer.js @@ -64,32 +64,32 @@ InstallContainer.contextTypes = { router: React.PropTypes.object }; -const mapStateToProps = state => ({ +const mapStateToProps = (state) => ({ install: state.install.toJS() }); -const mapDispatchToProps = dispatch => ({ +const mapDispatchToProps = (dispatch) => ({ nextStep: () => dispatch(nextStep()), - goToStep: step => dispatch(goToStep(step)), + goToStep: (step) => dispatch(goToStep(step)), previousStep: () => dispatch(previousStep()), finishInstall: () => dispatch(finishInstall()), - checkInstall: next => dispatch(checkInstall(next)), - handleDomainsChange: value => { + checkInstall: (next) => dispatch(checkInstall(next)), + handleDomainsChange: (value) => { dispatch(updatePermittedDomains(value)); }, - handleSettingsChange: e => { + handleSettingsChange: (e) => { const {name, value} = e.currentTarget; dispatch(updateSettingsFormData(name, value)); }, - handleUserChange: e => { + handleUserChange: (e) => { const {name, value} = e.currentTarget; dispatch(updateUserFormData(name, value)); }, - handleSettingsSubmit: e => { + handleSettingsSubmit: (e) => { e.preventDefault(); dispatch(submitSettings()); }, - handleUserSubmit: e => { + handleUserSubmit: (e) => { e.preventDefault(); dispatch(submitUser()); } diff --git a/client/coral-admin/src/containers/Install/components/Steps/AddOrganizationName.js b/client/coral-admin/src/containers/Install/components/Steps/AddOrganizationName.js index bcac6ef29..b25ddf143 100644 --- a/client/coral-admin/src/containers/Install/components/Steps/AddOrganizationName.js +++ b/client/coral-admin/src/containers/Install/components/Steps/AddOrganizationName.js @@ -6,7 +6,7 @@ const lang = new I18n(translations); import translations from '../../translations.json'; import I18n from 'coral-framework/modules/i18n/i18n'; -const AddOrganizationName = props => { +const AddOrganizationName = (props) => { const {handleSettingsChange, handleSettingsSubmit, install} = props; return (
diff --git a/client/coral-admin/src/containers/Install/components/Steps/CreateYourAccount.js b/client/coral-admin/src/containers/Install/components/Steps/CreateYourAccount.js index 416fac195..e46f013a8 100644 --- a/client/coral-admin/src/containers/Install/components/Steps/CreateYourAccount.js +++ b/client/coral-admin/src/containers/Install/components/Steps/CreateYourAccount.js @@ -6,7 +6,7 @@ const lang = new I18n(translations); import translations from '../../translations.json'; import I18n from 'coral-framework/modules/i18n/i18n'; -const InitialStep = props => { +const InitialStep = (props) => { const {handleUserChange, handleUserSubmit, install} = props; return (
diff --git a/client/coral-admin/src/containers/Install/components/Steps/InitialStep.js b/client/coral-admin/src/containers/Install/components/Steps/InitialStep.js index 1838e3178..18b49ce64 100644 --- a/client/coral-admin/src/containers/Install/components/Steps/InitialStep.js +++ b/client/coral-admin/src/containers/Install/components/Steps/InitialStep.js @@ -6,7 +6,7 @@ const lang = new I18n(translations); import translations from '../../translations.json'; import I18n from 'coral-framework/modules/i18n/i18n'; -const InitialStep = props => { +const InitialStep = (props) => { const {nextStep} = props; return (
diff --git a/client/coral-admin/src/containers/Install/components/Steps/InviteTeamMembers.js b/client/coral-admin/src/containers/Install/components/Steps/InviteTeamMembers.js index 35a4a41de..880aa69a4 100644 --- a/client/coral-admin/src/containers/Install/components/Steps/InviteTeamMembers.js +++ b/client/coral-admin/src/containers/Install/components/Steps/InviteTeamMembers.js @@ -2,7 +2,7 @@ import React from 'react'; import styles from './style.css'; import {Button, Select, Option, TextField} from 'coral-ui'; -const InviteTeamMembers = props => { +const InviteTeamMembers = (props) => { const {nextStep} = props; return (
diff --git a/client/coral-admin/src/containers/Install/components/Steps/PermittedDomainsStep.js b/client/coral-admin/src/containers/Install/components/Steps/PermittedDomainsStep.js index f2c1546f6..9058db4c2 100644 --- a/client/coral-admin/src/containers/Install/components/Steps/PermittedDomainsStep.js +++ b/client/coral-admin/src/containers/Install/components/Steps/PermittedDomainsStep.js @@ -7,7 +7,7 @@ const lang = new I18n(translations); import translations from '../../translations.json'; import I18n from 'coral-framework/modules/i18n/i18n'; -const PermittedDomainsStep = props => { +const PermittedDomainsStep = (props) => { const {finishInstall, install, handleDomainsChange} = props; const domains = install.data.settings.domains.whitelist; return ( @@ -19,8 +19,8 @@ const PermittedDomainsStep = props => { value={domains} inputProps={{placeholder: 'URL'}} addOnPaste={true} - pasteSplit={data => data.split(',').map(d => d.trim())} - onChange={tags => handleDomainsChange(tags)} + pasteSplit={(data) => data.split(',').map((d) => d.trim())} + onChange={(tags) => handleDomainsChange(tags)} /> diff --git a/client/coral-admin/src/containers/LayoutContainer.js b/client/coral-admin/src/containers/LayoutContainer.js index 42e2baade..5515cdda4 100644 --- a/client/coral-admin/src/containers/LayoutContainer.js +++ b/client/coral-admin/src/containers/LayoutContainer.js @@ -42,17 +42,17 @@ class LayoutContainer extends Component { } } -const mapStateToProps = state => ({ +const mapStateToProps = (state) => ({ auth: state.auth.toJS(), TALK_RECAPTCHA_PUBLIC: state.config.get('data').get('TALK_RECAPTCHA_PUBLIC', null) }); -const mapDispatchToProps = dispatch => ({ +const mapDispatchToProps = (dispatch) => ({ checkLogin: () => dispatch(checkLogin()), fetchConfig: () => dispatch(fetchConfig()), handleLogin: (username, password, recaptchaResponse) => dispatch(handleLogin(username, password, recaptchaResponse)), - requestPasswordReset: email => dispatch(requestPasswordReset(email)), - toggleShortcutModal: toggle => dispatch(toggleShortcutModal(toggle)), + requestPasswordReset: (email) => dispatch(requestPasswordReset(email)), + toggleShortcutModal: (toggle) => dispatch(toggleShortcutModal(toggle)), handleLogout: () => dispatch(logout()) }); diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js index 9606be543..3d1c1dd7a 100644 --- a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js +++ b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js @@ -61,14 +61,14 @@ class ModerationContainer extends Component { select = (next) => () => { if (next) { - this.setState(prevState => + this.setState((prevState) => ({ ...prevState, selectedIndex: prevState.selectedIndex < this.getComments().length - 1 ? prevState.selectedIndex + 1 : prevState.selectedIndex })); } else { - this.setState(prevState => + this.setState((prevState) => ({ ...prevState, selectedIndex: prevState.selectedIndex > 0 ? @@ -126,7 +126,7 @@ class ModerationContainer extends Component { } if (providedAssetId) { - asset = assets.find(asset => asset.id === this.props.params.id); + asset = assets.find((asset) => asset.id === this.props.params.id); if (!asset) { return ; @@ -202,17 +202,17 @@ class ModerationContainer extends Component { } } -const mapStateToProps = state => ({ +const mapStateToProps = (state) => ({ moderation: state.moderation.toJS(), settings: state.settings.toJS(), assets: state.assets.get('assets') }); -const mapDispatchToProps = dispatch => ({ - toggleModal: toggle => dispatch(toggleModal(toggle)), +const mapDispatchToProps = (dispatch) => ({ + toggleModal: (toggle) => dispatch(toggleModal(toggle)), onClose: () => dispatch(toggleModal(false)), singleView: () => dispatch(singleView()), - updateAssets: assets => dispatch(updateAssets(assets)), + updateAssets: (assets) => dispatch(updateAssets(assets)), fetchSettings: () => dispatch(fetchSettings()), showBanUserDialog: (user, commentId, commentStatus, showRejectedNote) => dispatch(showBanUserDialog(user, commentId, commentStatus, showRejectedNote)), hideBanUserDialog: () => dispatch(hideBanUserDialog(false)), diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationLayout.js b/client/coral-admin/src/containers/ModerationQueue/ModerationLayout.js index 0db97cda0..02a798900 100644 --- a/client/coral-admin/src/containers/ModerationQueue/ModerationLayout.js +++ b/client/coral-admin/src/containers/ModerationQueue/ModerationLayout.js @@ -1,6 +1,6 @@ import React from 'react'; -const ModerationLayout = props => ( +const ModerationLayout = (props) => (
{props.children}
diff --git a/client/coral-admin/src/containers/ModerationQueue/components/Comment.js b/client/coral-admin/src/containers/ModerationQueue/components/Comment.js index 55a00096d..0f31210c0 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/Comment.js +++ b/client/coral-admin/src/containers/ModerationQueue/components/Comment.js @@ -27,11 +27,11 @@ const Comment = ({ ...props }) => { const links = linkify.getMatches(comment.body); - const linkText = links ? links.map(link => link.raw) : []; + const linkText = links ? links.map((link) => link.raw) : []; const flagActionSummaries = getActionSummary('FlagActionSummary', comment); const flagActions = comment.actions && - comment.actions.filter(a => a.__typename === 'FlagAction'); + comment.actions.filter((a) => a.__typename === 'FlagAction'); let commentType = ''; if (comment.status === 'PREMOD') { commentType = 'premod'; @@ -43,7 +43,7 @@ const Comment = ({ // this should be the behavior on the front end as well. // currently the highlighter plugin does not support this out of the box. const searchWords = [...suspectWords, ...bannedWords] - .filter(w => { + .filter((w) => { return new RegExp(`(^|\\s)${w}(\\s|$)`).test(comment.body); }) .concat(linkText); diff --git a/client/coral-admin/src/containers/ModerationQueue/components/CommentType.js b/client/coral-admin/src/containers/ModerationQueue/components/CommentType.js index 5ad4138ca..346b5f1e6 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/CommentType.js +++ b/client/coral-admin/src/containers/ModerationQueue/components/CommentType.js @@ -2,7 +2,7 @@ import React, {PropTypes} from 'react'; import styles from './CommentType.css'; import {Icon} from 'coral-ui'; -const CommentType = props => { +const CommentType = (props) => { const typeData = getTypeData(props.type); return ( @@ -12,7 +12,7 @@ const CommentType = props => { ); }; -const getTypeData = type => { +const getTypeData = (type) => { switch (type) { case 'premod': return {icon: 'query_builder', text: 'Pre-Mod', className: 'premod'}; diff --git a/client/coral-admin/src/containers/ModerationQueue/components/FlagBox.js b/client/coral-admin/src/containers/ModerationQueue/components/FlagBox.js index 62b4e554d..f2f52e75e 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/FlagBox.js +++ b/client/coral-admin/src/containers/ModerationQueue/components/FlagBox.js @@ -55,7 +55,7 @@ class FlagBox extends Component {