diff --git a/api/mutations/thread/publishThread.js b/api/mutations/thread/publishThread.js index 42c5156a69..e505995edc 100644 --- a/api/mutations/thread/publishThread.js +++ b/api/mutations/thread/publishThread.js @@ -19,7 +19,6 @@ import { _adminProcessToxicThreadQueue, _adminProcessUserSpammingThreadsQueue, } from 'shared/bull/queues'; -import getSpectrumScore from 'athena/queues/moderationEvents/spectrum'; import getPerspectiveScore from 'athena/queues/moderationEvents/perspective'; import { events } from 'shared/analytics'; import { trackQueue } from 'shared/bull/queues'; @@ -275,27 +274,23 @@ export default requireAuth( const title = thread.content.title; const text = `${title} ${body}`; - const scores = await Promise.all([ - getSpectrumScore(text, dbThread.id, dbThread.creatorId).catch(err => 0), - getPerspectiveScore(text).catch(err => 0), - ]).catch(err => + const scores = await getPerspectiveScore(text).catch(err => console.error( 'Error getting thread moderation scores from providers', err.message ) ); - const spectrumScore = scores && scores[0]; const perspectiveScore = scores && scores[1]; // if neither models returned results - if (!spectrumScore && !perspectiveScore) { + if (!perspectiveScore) { debug('Toxicity checks from providers say not toxic'); return false; } // if both services agree that the thread is >= 98% toxic - if ((spectrumScore + perspectiveScore) / 2 >= 0.9) { + if (perspectiveScore >= 0.9) { debug('Thread is toxic according to both providers'); return true; } diff --git a/api/mutations/user/editUser.js b/api/mutations/user/editUser.js index b7b1a9db92..f4aecaa748 100644 --- a/api/mutations/user/editUser.js +++ b/api/mutations/user/editUser.js @@ -55,7 +55,7 @@ export default requireAuth( const pendingEmail = input.email; // if user is changing their email, make sure it's not taken by someone else - if (pendingEmail !== currentUser.email) { + if (pendingEmail !== currentUser.email || !currentUser.email) { if (!isEmail(input.email)) { return new UserError('Please enter a valid email address.'); } diff --git a/api/package.json b/api/package.json index 52f9a52af2..641ebda609 100644 --- a/api/package.json +++ b/api/package.json @@ -16,7 +16,7 @@ "babel-plugin-transform-flow-strip-types": "^6.22.0", "babel-plugin-transform-object-rest-spread": "^6.23.0", "babel-preset-env": "^1.7.0", - "backpack-core": "^0.8.2", + "backpack-core": "^0.8.3", "body-parser": "^1.18.3", "bull": "3.3.10", "casual": "^1.5.12", @@ -116,7 +116,7 @@ "sanitize-filename": "^1.6.1", "serialize-javascript": "^1.5.0", "session-rethinkdb": "^2.0.0", - "slate": "^0.44.6", + "slate": "^0.44.7", "slate-markdown": "0.1.0", "slugg": "^1.1.0", "string-replace-to-array": "^1.0.3", diff --git a/api/queries/user/email.js b/api/queries/user/email.js index 32a68a73fe..1a0ff99bf5 100644 --- a/api/queries/user/email.js +++ b/api/queries/user/email.js @@ -3,8 +3,13 @@ import type { GraphQLContext } from '../../'; import type { DBUser } from 'shared/types'; import { isAdmin } from '../../utils/permissions'; -export default ({ id, email }: DBUser, _: any, { user }: GraphQLContext) => { +export default async ( + { id }: DBUser, + _: any, + { user, loaders }: GraphQLContext +) => { // Only admins and the user themselves can view the email if (!user || (id !== user.id && !isAdmin(user.id))) return null; + const { email } = await loaders.user.load(id); return email; }; diff --git a/api/yarn.lock b/api/yarn.lock index b4e40ca5c0..86c9e08d06 100644 --- a/api/yarn.lock +++ b/api/yarn.lock @@ -2270,10 +2270,10 @@ backo2@^1.0.2: resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= -backpack-core@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/backpack-core/-/backpack-core-0.8.2.tgz#d8ef661ecbee43a87bce1888603a54eee8490873" - integrity sha512-EKAiTtL0Ij97bQc+rvzAmSr9moYlbiZD1OBjujCIg/Hr1nasXtViJrw1EedOUjXNFudIa0acfnCAXde/8FcNKQ== +backpack-core@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/backpack-core/-/backpack-core-0.8.3.tgz#7c92458d29c77987fcb278ee83b23b55624ec2af" + integrity sha512-d94a47CT1+/Ozb9L7wICoenQF4tyaSOxqPrKxFmk33TW67oKHrA6Ye/1ZJjBUVYwjfNCae6iO2xqyrjRzzQAcA== dependencies: "@babel/core" "^7.1.2" babel-loader "^8.0.2" @@ -2281,7 +2281,7 @@ backpack-core@^0.8.2: cross-spawn "^5.0.1" friendly-errors-webpack-plugin "^1.7.0" json-loader "^0.5.7" - nodemon "^1.11.0" + nodemon "^1.18.7" ramda "^0.23.0" source-map-support "^0.4.15" webpack "^4.23.1" @@ -3685,11 +3685,6 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= -duplexer@^0.1.1, duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - duplexify@^3.4.2, duplexify@^3.6.0: version "3.6.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.1.tgz#b1a7a29c4abfd639585efaecce80d666b1e34125" @@ -3919,20 +3914,6 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= -event-stream@~3.3.0: - version "3.3.6" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.6.tgz#cac1230890e07e73ec9cacd038f60a5b66173eef" - integrity sha512-dGXNg4F/FgVzlApjzItL+7naHutA3fDqbV/zAZqDDlXTjiMnQmZKu+prImWKszeBM5UQeGvAl3u1wBiKeDh61g== - dependencies: - duplexer "^0.1.1" - flatmap-stream "^0.1.0" - from "^0.1.7" - map-stream "0.0.7" - pause-stream "^0.0.11" - split "^1.0.1" - stream-combiner "^0.2.2" - through "^2.3.8" - eventemitter3@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" @@ -4265,11 +4246,6 @@ find-with-regex@^1.0.2, find-with-regex@^1.1.3: resolved "https://registry.yarnpkg.com/find-with-regex/-/find-with-regex-1.1.3.tgz#d6c6f2debee898d36b6a77e05709b13dd5dc8a26" integrity sha512-zkEVQ1H3PIQL/19ADKt1lCQU4QGM3OneiderUcFgn5EgTm/TnoUh7HxPAwP8w/vXxWSLC6KtpbDQpypJ5+majw== -flatmap-stream@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/flatmap-stream/-/flatmap-stream-0.1.2.tgz#b1da359a93f24f6d96e46f948552d997e3c2863d" - integrity sha512-ucyr6WkLXjyMuHPtOUq4l+nSAxgWi7v4QO508eQ9resnGj+lSup26oIsUI5aH8k4Qfpjsxa8dDf9UCKkS2KHzQ== - flexbuffer@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/flexbuffer/-/flexbuffer-0.0.6.tgz#039fdf23f8823e440c38f3277e6fef1174215b30" @@ -4381,11 +4357,6 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -from@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= - fs-extra@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" @@ -6429,11 +6400,6 @@ map-obj@^1.0.0, map-obj@^1.0.1: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= -map-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" - integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg= - map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -6867,16 +6833,16 @@ node-releases@^1.0.1: dependencies: semver "^5.3.0" -nodemon@^1.11.0: - version "1.18.6" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.6.tgz#89b1136634d6c0afc7de24cc932a760e999e2c76" - integrity sha512-4pHQNYEZun+IkIC2jCaXEhkZnfA7rQe73i8RkdRyDJls/K+WxR7IpI5uNUsAvQ0zWvYcCDNGD+XVtw2ZG86/uQ== +nodemon@^1.18.7: + version "1.18.7" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.7.tgz#716b66bf3e89ac4fcfb38a9e61887a03fc82efbb" + integrity sha512-xuC1V0F5EcEyKQ1VhHYD13owznQbUw29JKvZ8bVH7TmuvVNHvvbp9pLgE4PjTMRJVe0pJ8fGRvwR2nMiosIsPQ== dependencies: chokidar "^2.0.4" debug "^3.1.0" ignore-by-default "^1.0.1" minimatch "^3.0.4" - pstree.remy "^1.1.0" + pstree.remy "^1.1.2" semver "^5.5.0" supports-color "^5.2.0" touch "^3.1.0" @@ -7365,13 +7331,6 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" -pause-stream@^0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= - dependencies: - through "~2.3" - pause@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" @@ -7572,13 +7531,6 @@ prr@~1.0.1: resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= -ps-tree@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014" - integrity sha1-tCGyQUDWID8e08dplrRCewjowBQ= - dependencies: - event-stream "~3.3.0" - pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -7589,12 +7541,10 @@ psl@^1.1.24: resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ== -pstree.remy@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.0.tgz#f2af27265bd3e5b32bbfcc10e80bac55ba78688b" - integrity sha512-q5I5vLRMVtdWa8n/3UEzZX7Lfghzrg9eG2IKk2ENLSofKRCXVqMvMUHxCKgXNaqH/8ebhBxrqftHWnyTFweJ5Q== - dependencies: - ps-tree "^1.1.0" +pstree.remy@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.2.tgz#4448bbeb4b2af1fed242afc8dc7416a6f504951a" + integrity sha512-vL6NLxNHzkNTjGJUpMm5PLC+94/0tTlC1vkP9bdU0pOHih+EujMjgMTwfZopZvHWRFbqJ5Y73OMoau50PewDDA== public-encrypt@^4.0.0: version "4.0.3" @@ -8580,10 +8530,10 @@ slate-markdown@0.1.0: react "^0.14.0 || ^15.0.0" styled-components "^2.0.0" -slate@^0.44.6: - version "0.44.6" - resolved "https://registry.yarnpkg.com/slate/-/slate-0.44.6.tgz#47ab3127641bc1faa3e5a5b01bfab8861843c82e" - integrity sha512-Q5DASlX7tUXrAaQFb5AliZjAeuXkI1oVq3HM8A/mb4qClwpSpuKq/uOcA3855bFzAOXSjUM/kESK3M3oiIHnNA== +slate@^0.44.7: + version "0.44.7" + resolved "https://registry.yarnpkg.com/slate/-/slate-0.44.7.tgz#3cf8a3f2bd78c03e02a6cf8bb726ae9f43582e13" + integrity sha512-h2aW2r20qtn4oUk8rh7qbW3NluLMlsDCctFNwWdrDmGnwTfszfVApcapnOFmv+qmKnZsPZLqidl3mHnXVL/lcQ== dependencies: debug "^3.1.0" direction "^0.1.5" @@ -8728,13 +8678,6 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" -split@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== - dependencies: - through "2" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -8803,14 +8746,6 @@ stream-browserify@^2.0.1: inherits "~2.0.1" readable-stream "^2.0.2" -stream-combiner@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858" - integrity sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg= - dependencies: - duplexer "~0.1.1" - through "~2.3.4" - stream-each@^1.1.0: version "1.2.3" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" @@ -9130,7 +9065,7 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through@2, through@^2.3.8, through@~2.3, through@~2.3.4: +through@^2.3.8, through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= diff --git a/athena/queues/moderationEvents/message.js b/athena/queues/moderationEvents/message.js index a091c91e79..6713ad308e 100644 --- a/athena/queues/moderationEvents/message.js +++ b/athena/queues/moderationEvents/message.js @@ -5,7 +5,6 @@ import { getThreadById } from '../../models/thread'; import { getCommunityById } from '../../models/community'; import { getChannelById } from '../../models/channel'; import { toState, toPlainText } from 'shared/draft-utils'; -import getSpectrumScore from './spectrum'; import getPerspectiveScore from './perspective'; import { _adminSendToxicContentEmailQueue } from 'shared/bull/queues'; import type { Job, AdminToxicMessageJobData } from 'shared/bull/types'; @@ -21,11 +20,8 @@ export default async (job: Job) => { ? toPlainText(toState(JSON.parse(message.content.body))) : message.content.body; - const scores = await Promise.all([ - getSpectrumScore(text, message.id, message.senderId), - getPerspectiveScore(text), - ]).catch(err => - console.error('Error getting message moderation scores from providers', { + const perspectiveScore = await getPerspectiveScore(text).catch(err => + console.error('Error getting message moderation score from providers', { error: err.message, data: { text, @@ -34,11 +30,7 @@ export default async (job: Job) => { }) ); - const spectrumScore = scores && scores[0]; - const perspectiveScore = scores && scores[1]; - - // if neither models returned results - if (!spectrumScore && !perspectiveScore) return; + if (!perspectiveScore) return; const [user, thread] = await Promise.all([ getUserById(message.senderId), @@ -58,7 +50,6 @@ export default async (job: Job) => { community, channel, toxicityConfidence: { - spectrumScore, perspectiveScore, }, }); diff --git a/athena/queues/moderationEvents/perspective.js b/athena/queues/moderationEvents/perspective.js index a4a41a5b43..ed59299092 100644 --- a/athena/queues/moderationEvents/perspective.js +++ b/athena/queues/moderationEvents/perspective.js @@ -29,7 +29,7 @@ export default async (text: string) => { }); // if something failed? - if (!request || !request.data) return; + if (!request || !request.data) return null; // get the scores from the request const { attributeScores } = request.data; diff --git a/athena/queues/moderationEvents/spectrum.js b/athena/queues/moderationEvents/spectrum.js deleted file mode 100644 index 13613b4471..0000000000 --- a/athena/queues/moderationEvents/spectrum.js +++ /dev/null @@ -1,42 +0,0 @@ -// @flow -const debug = require('debug')('athena:queue:moderation-events:spectrum'); -require('now-env'); -import axios from 'axios'; -const SPECTRUM_MODERATION_API_KEY = process.env.SPECTRUM_MODERATION_API_KEY; - -if (!SPECTRUM_MODERATION_API_KEY) { - debug('No API key for Spectrum provided, not sending moderation events.'); -} - -export default async (text: string, contextId: string, userId: string) => { - if (!SPECTRUM_MODERATION_API_KEY) return; - const request = await axios({ - method: 'post', - url: 'https://api.prod.getspectrum.io/api/v1/classification', - headers: { - Authorization: `Apikey ${SPECTRUM_MODERATION_API_KEY}`, - 'Content-Type': 'application/json', - }, - data: { - jsonrpc: '2.0', - method: 'classifyText', - params: { - text: text, - meta: { - authorId: userId, - }, - }, - id: contextId, - }, - }); - - const { data } = request; - - if (!data || !data.result) return; - - const { toxicityConfidence } = data.result; - - if (toxicityConfidence > 0.9) return toxicityConfidence; - - return null; -}; diff --git a/athena/queues/moderationEvents/thread.js b/athena/queues/moderationEvents/thread.js index 938cce46d0..7815637fc2 100644 --- a/athena/queues/moderationEvents/thread.js +++ b/athena/queues/moderationEvents/thread.js @@ -4,7 +4,6 @@ import { getUserById } from 'shared/db/queries/user'; import { getCommunityById } from '../../models/community'; import { getChannelById } from '../../models/channel'; import { toState, toPlainText } from 'shared/draft-utils'; -import getSpectrumScore from './spectrum'; import getPerspectiveScore from './perspective'; import { _adminSendToxicContentEmailQueue } from 'shared/bull/queues'; import type { Job, AdminToxicThreadJobData } from 'shared/bull/types'; @@ -26,10 +25,7 @@ export default async (job: Job) => { const title = thread.content.title; const text = `${title} ${body}`; - const scores = await Promise.all([ - getSpectrumScore(text, thread.id, thread.creatorId), - getPerspectiveScore(text), - ]).catch(err => + const perspectiveScore = await getPerspectiveScore(text).catch(err => console.error('Error getting thread moderation scores from providers', { error: err.message, data: { @@ -39,11 +35,8 @@ export default async (job: Job) => { }) ); - const spectrumScore = scores && scores[0]; - const perspectiveScore = scores && scores[1]; - // if neither models returned results - if (!spectrumScore && !perspectiveScore) return; + if (!perspectiveScore) return; const [user, community, channel] = await Promise.all([ getUserById(thread.creatorId), @@ -59,7 +52,6 @@ export default async (job: Job) => { community, channel, toxicityConfidence: { - spectrumScore, perspectiveScore, }, }); diff --git a/cypress/integration/channel/settings/members_spec.js b/cypress/integration/channel/settings/members_spec.js new file mode 100644 index 0000000000..c52ddfdab6 --- /dev/null +++ b/cypress/integration/channel/settings/members_spec.js @@ -0,0 +1,48 @@ +import data from '../../../../shared/testing/data'; + +const channel = data.channels[0]; +const community = data.communities.find( + community => community.id === channel.communityId +); + +const { userId: ownerInChannelId } = data.usersChannels.find( + ({ channelId, isOwner }) => channelId === channel.id && isOwner +); + +const membersChannels = data.usersChannels.filter( + uc => uc.channelId === channel.id +); +const members = membersChannels + .filter(mc => mc.isMember) + .map(mc => data.users.find(user => mc.userId === user.id)); +const member = members[0]; + +describe('sending a message to channel member', () => { + beforeEach(() => { + cy.auth(ownerInChannelId).then(() => + cy.visit(`/${community.slug}/${channel.slug}/settings`) + ); + }); + + it('should render all members', () => { + cy.get('[data-cy="channel-overview"]').should('be.visible'); + + members.map(member => { + cy.contains(member.name) + .scrollIntoView() + .should('be.visible'); + }); + }); + + it('should init a new dm', () => { + cy.get('[data-cy="channel-overview"]').should('be.visible'); + + cy.get('[data-cy="message-user-button"]') + .first() + .click(); + + cy.url().should('include', '/messages/new'); + + cy.get('[data-cy="selected-user-pill"]').should('be.visible'); + }); +}); diff --git a/cypress/integration/channel/view/members_spec.js b/cypress/integration/channel/view/members_spec.js index 741a8c2ab5..5052261bb0 100644 --- a/cypress/integration/channel/view/members_spec.js +++ b/cypress/integration/channel/view/members_spec.js @@ -6,6 +6,7 @@ const community = data.communities.find( const usersChannels = data.usersChannels .filter(({ channelId, isMember }) => channelId === channel.id && isMember) .map(o => o.userId); + const members = data.users.filter(user => usersChannels.indexOf(user.id) >= 0); describe('renders members list on channel view', () => { @@ -14,12 +15,14 @@ describe('renders members list on channel view', () => { }); it('should render members component', () => { - cy.get('[data-cy="channel-members-list"]').should('be.visible'); + cy.get('[data-cy="channel-members-list"]') + .scrollIntoView() + .should('be.visible'); members.map(member => { - cy - .get('[data-cy="channel-view"]') + cy.get('[data-cy="channel-view"]') .contains(`${member.name}`) + .scrollIntoView() .should('be.visible'); }); }); diff --git a/cypress/integration/thread_spec.js b/cypress/integration/thread_spec.js index 4063fa500f..9f007493bb 100644 --- a/cypress/integration/thread_spec.js +++ b/cypress/integration/thread_spec.js @@ -387,7 +387,7 @@ describe('edit message signed out', () => { }); }); -describe('edit message signed in', () => { +describe.only('edit message signed in', () => { beforeEach(() => { cy.auth(moderator.userId).then(() => cy.visit(`/thread/${thread.id}`)); }); @@ -397,9 +397,10 @@ describe('edit message signed in', () => { cy.get('[data-cy="edit-message"]').should($p => { expect($p).to.have.length(2); }); - cy.contains('The next one is an emoji-only one :scream:').should( - 'be.visible' - ); + cy.contains('The next one is an emoji-only one :scream:') + .scrollIntoView() + .should('be.visible'); + cy.get('[data-cy="edit-message"]') .last() .click({ force: true }); @@ -407,14 +408,19 @@ describe('edit message signed in', () => { cy.get('[data-cy="edit-message-input"]') .scrollIntoView() .should('be.visible'); + cy.get('[data-cy="edit-message-cancel"]') .scrollIntoView() .should('be.visible'); - cy.get('[data-cy="edit-message-save"]').should('be.visible'); + + cy.get('[data-cy="edit-message-save"]') + .scrollIntoView() + .should('be.visible'); cy.get('[data-cy="edit-message-cancel"]').click(); cy.get('[data-cy="edit-message-input"]').should('not.be.visible'); + cy.get('[data-cy="edit-message-cancel"]').should('not.be.visible'); cy.get('[data-cy="edit-message-save"]').should('not.be.visible'); @@ -428,10 +434,11 @@ describe('edit message signed in', () => { cy.get('[data-cy="edit-message-save"]').click(); cy.get('[data-cy="edit-message-input"]').should('not.be.visible'); + cy.get('[data-cy="edited-message-indicator"]').should('be.visible'); - cy.contains('The next one is an emoji-only one :scream: with edits').should( - 'be.visible' - ); + cy.contains('The next one is an emoji-only one :scream: with edits') + .scrollIntoView() + .should('be.visible'); }); }); diff --git a/email-templates/adminToxicContent.html b/email-templates/adminToxicContent.html index 76aa140d88..115323f1f4 100644 --- a/email-templates/adminToxicContent.html +++ b/email-templates/adminToxicContent.html @@ -31,10 +31,6 @@

Info:

    - {{#data.toxicityConfidence.spectrumPercent}} -
  • Spectrum: {{.}}% confident
  • - {{/data.toxicityConfidence.spectrumPercent}} - {{#data.toxicityConfidence.perspectivePercent}}
  • Perspective: {{.}}% confident
  • {{/data.toxicityConfidence.perspectivePercent}} diff --git a/flow-typed/npm/electron-is-dev_vx.x.x.js b/flow-typed/npm/electron-is-dev_vx.x.x.js new file mode 100644 index 0000000000..f5228c6e82 --- /dev/null +++ b/flow-typed/npm/electron-is-dev_vx.x.x.js @@ -0,0 +1,33 @@ +// flow-typed signature: 56cb87472f7011e6a22325af9a351724 +// flow-typed version: <>/electron-is-dev_v1.0.1/flow_v0.66.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'electron-is-dev' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'electron-is-dev' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ + + +// Filename aliases +declare module 'electron-is-dev/index' { + declare module.exports: $Exports<'electron-is-dev'>; +} +declare module 'electron-is-dev/index.js' { + declare module.exports: $Exports<'electron-is-dev'>; +} diff --git a/flow-typed/npm/electron-updater_vx.x.x.js b/flow-typed/npm/electron-updater_vx.x.x.js new file mode 100644 index 0000000000..d84baf6c66 --- /dev/null +++ b/flow-typed/npm/electron-updater_vx.x.x.js @@ -0,0 +1,186 @@ +// flow-typed signature: be94c12fa70b80b91f6bef7efa92a8fe +// flow-typed version: <>/electron-updater_v4.0.5/flow_v0.66.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'electron-updater' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'electron-updater' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'electron-updater/out/AppAdapter' { + declare module.exports: any; +} + +declare module 'electron-updater/out/AppImageUpdater' { + declare module.exports: any; +} + +declare module 'electron-updater/out/AppUpdater' { + declare module.exports: any; +} + +declare module 'electron-updater/out/BaseUpdater' { + declare module.exports: any; +} + +declare module 'electron-updater/out/differentialDownloader/DataSplitter' { + declare module.exports: any; +} + +declare module 'electron-updater/out/differentialDownloader/DifferentialDownloader' { + declare module.exports: any; +} + +declare module 'electron-updater/out/differentialDownloader/downloadPlanBuilder' { + declare module.exports: any; +} + +declare module 'electron-updater/out/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader' { + declare module.exports: any; +} + +declare module 'electron-updater/out/differentialDownloader/GenericDifferentialDownloader' { + declare module.exports: any; +} + +declare module 'electron-updater/out/differentialDownloader/multipleRangeDownloader' { + declare module.exports: any; +} + +declare module 'electron-updater/out/DownloadedUpdateHelper' { + declare module.exports: any; +} + +declare module 'electron-updater/out/ElectronAppAdapter' { + declare module.exports: any; +} + +declare module 'electron-updater/out/electronHttpExecutor' { + declare module.exports: any; +} + +declare module 'electron-updater/out/MacUpdater' { + declare module.exports: any; +} + +declare module 'electron-updater/out/main' { + declare module.exports: any; +} + +declare module 'electron-updater/out/NsisUpdater' { + declare module.exports: any; +} + +declare module 'electron-updater/out/providerFactory' { + declare module.exports: any; +} + +declare module 'electron-updater/out/providers/BintrayProvider' { + declare module.exports: any; +} + +declare module 'electron-updater/out/providers/GenericProvider' { + declare module.exports: any; +} + +declare module 'electron-updater/out/providers/GitHubProvider' { + declare module.exports: any; +} + +declare module 'electron-updater/out/providers/PrivateGitHubProvider' { + declare module.exports: any; +} + +declare module 'electron-updater/out/providers/Provider' { + declare module.exports: any; +} + +declare module 'electron-updater/out/windowsExecutableCodeSignatureVerifier' { + declare module.exports: any; +} + +// Filename aliases +declare module 'electron-updater/out/AppAdapter.js' { + declare module.exports: $Exports<'electron-updater/out/AppAdapter'>; +} +declare module 'electron-updater/out/AppImageUpdater.js' { + declare module.exports: $Exports<'electron-updater/out/AppImageUpdater'>; +} +declare module 'electron-updater/out/AppUpdater.js' { + declare module.exports: $Exports<'electron-updater/out/AppUpdater'>; +} +declare module 'electron-updater/out/BaseUpdater.js' { + declare module.exports: $Exports<'electron-updater/out/BaseUpdater'>; +} +declare module 'electron-updater/out/differentialDownloader/DataSplitter.js' { + declare module.exports: $Exports<'electron-updater/out/differentialDownloader/DataSplitter'>; +} +declare module 'electron-updater/out/differentialDownloader/DifferentialDownloader.js' { + declare module.exports: $Exports<'electron-updater/out/differentialDownloader/DifferentialDownloader'>; +} +declare module 'electron-updater/out/differentialDownloader/downloadPlanBuilder.js' { + declare module.exports: $Exports<'electron-updater/out/differentialDownloader/downloadPlanBuilder'>; +} +declare module 'electron-updater/out/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.js' { + declare module.exports: $Exports<'electron-updater/out/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader'>; +} +declare module 'electron-updater/out/differentialDownloader/GenericDifferentialDownloader.js' { + declare module.exports: $Exports<'electron-updater/out/differentialDownloader/GenericDifferentialDownloader'>; +} +declare module 'electron-updater/out/differentialDownloader/multipleRangeDownloader.js' { + declare module.exports: $Exports<'electron-updater/out/differentialDownloader/multipleRangeDownloader'>; +} +declare module 'electron-updater/out/DownloadedUpdateHelper.js' { + declare module.exports: $Exports<'electron-updater/out/DownloadedUpdateHelper'>; +} +declare module 'electron-updater/out/ElectronAppAdapter.js' { + declare module.exports: $Exports<'electron-updater/out/ElectronAppAdapter'>; +} +declare module 'electron-updater/out/electronHttpExecutor.js' { + declare module.exports: $Exports<'electron-updater/out/electronHttpExecutor'>; +} +declare module 'electron-updater/out/MacUpdater.js' { + declare module.exports: $Exports<'electron-updater/out/MacUpdater'>; +} +declare module 'electron-updater/out/main.js' { + declare module.exports: $Exports<'electron-updater/out/main'>; +} +declare module 'electron-updater/out/NsisUpdater.js' { + declare module.exports: $Exports<'electron-updater/out/NsisUpdater'>; +} +declare module 'electron-updater/out/providerFactory.js' { + declare module.exports: $Exports<'electron-updater/out/providerFactory'>; +} +declare module 'electron-updater/out/providers/BintrayProvider.js' { + declare module.exports: $Exports<'electron-updater/out/providers/BintrayProvider'>; +} +declare module 'electron-updater/out/providers/GenericProvider.js' { + declare module.exports: $Exports<'electron-updater/out/providers/GenericProvider'>; +} +declare module 'electron-updater/out/providers/GitHubProvider.js' { + declare module.exports: $Exports<'electron-updater/out/providers/GitHubProvider'>; +} +declare module 'electron-updater/out/providers/PrivateGitHubProvider.js' { + declare module.exports: $Exports<'electron-updater/out/providers/PrivateGitHubProvider'>; +} +declare module 'electron-updater/out/providers/Provider.js' { + declare module.exports: $Exports<'electron-updater/out/providers/Provider'>; +} +declare module 'electron-updater/out/windowsExecutableCodeSignatureVerifier.js' { + declare module.exports: $Exports<'electron-updater/out/windowsExecutableCodeSignatureVerifier'>; +} diff --git a/flow-typed/npm/electron_vx.x.x.js b/flow-typed/npm/electron_vx.x.x.js new file mode 100644 index 0000000000..84da4b2d0d --- /dev/null +++ b/flow-typed/npm/electron_vx.x.x.js @@ -0,0 +1,45 @@ +// flow-typed signature: 8dd143dc1ccb8d078e45dd9625583512 +// flow-typed version: <>/electron_v3.0.10/flow_v0.66.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'electron' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'electron' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'electron/cli' { + declare module.exports: any; +} + +declare module 'electron/install' { + declare module.exports: any; +} + +// Filename aliases +declare module 'electron/cli.js' { + declare module.exports: $Exports<'electron/cli'>; +} +declare module 'electron/index' { + declare module.exports: $Exports<'electron'>; +} +declare module 'electron/index.js' { + declare module.exports: $Exports<'electron'>; +} +declare module 'electron/install.js' { + declare module.exports: $Exports<'electron/install'>; +} diff --git a/hermes/queues/send-admin-toxic-content-email.js b/hermes/queues/send-admin-toxic-content-email.js index 3b088c7091..a0a3a2f66e 100644 --- a/hermes/queues/send-admin-toxic-content-email.js +++ b/hermes/queues/send-admin-toxic-content-email.js @@ -17,22 +17,14 @@ export default job => { thread, community, channel, - toxicityConfidence: { spectrumScore, perspectiveScore }, + toxicityConfidence: { perspectiveScore }, } = job.data; const toPercent = (num: number) => Math.round(num * 100); - const spectrumPercent = spectrumScore ? toPercent(spectrumScore) : null; - const perspectivePercent = perspectiveScore - ? toPercent(perspectiveScore) - : null; - let avgPercent; - if (spectrumPercent && perspectivePercent) { - avgPercent = (spectrumPercent + perspectivePercent) / 2; - } else { - avgPercent = spectrumPercent || perspectivePercent || 0; - } - const subject = `Toxic alert (${avgPercent.toString()}%): ${text}`; + const perspectivePercent = perspectiveScore.toPercent(perspectiveScore); + + const subject = `Toxic alert (${perspectivePercent.toString()}%): ${text}`; try { return sendEmail({ @@ -50,7 +42,6 @@ export default job => { community, channel, toxicityConfidence: { - spectrumPercent, perspectivePercent, }, }, diff --git a/hyperion/index.js b/hyperion/index.js index 3efaacef6c..fca4d8c7f5 100644 --- a/hyperion/index.js +++ b/hyperion/index.js @@ -147,13 +147,10 @@ app.use( return; } - if (path.indexOf('.html') === -1) { + if (path.endsWith('.js')) { // Cache static files in now CDN for seven days // (the filename changes if the file content changes, so we can cache these forever) - res.setHeader( - 'Cache-Control', - `max-age=${ONE_HOUR}, s-maxage=${ONE_HOUR}` - ); + res.setHeader('Cache-Control', `s-maxage=${ONE_HOUR}`); } }, }) @@ -162,11 +159,8 @@ app.get('/static/js/:name', (req: express$Request, res, next) => { if (!req.params.name) return next(); const existingFile = jsFiles.find(file => file.startsWith(req.params.name)); if (existingFile) { - if (existingFile.indexOf('.html') === -1) { - res.setHeader( - 'Cache-Control', - `max-age=${ONE_HOUR}, s-maxage=${ONE_HOUR}` - ); + if (existingFile.endsWith('.js')) { + res.setHeader('Cache-Control', `s-maxage=${ONE_HOUR}`); } return res.sendFile( path.resolve(__dirname, '..', 'build', 'static', 'js', req.params.name) diff --git a/hyperion/renderer/index.js b/hyperion/renderer/index.js index f4a66e77f1..f3ac64d1e8 100644 --- a/hyperion/renderer/index.js +++ b/hyperion/renderer/index.js @@ -132,7 +132,7 @@ const renderer = (req: express$Request, res: express$Response) => { if (!req.user) { res.setHeader( 'Cache-Control', - `max-age=${FIVE_MINUTES}, s-maxage=${ONE_HOUR}, stale-while-revalidate=${FIVE_MINUTES}, must-revalidate` + `s-maxage=${ONE_HOUR}, stale-while-revalidate=${FIVE_MINUTES}, must-revalidate` ); } else { res.setHeader('Cache-Control', 's-maxage=0'); @@ -182,7 +182,7 @@ const renderer = (req: express$Request, res: express$Response) => { : 'Only output in production.'; res.status(500); res.send( - `Oops, something went wrong. Please try again! (Error ID: ${sentryId})` + `Spectrum Chat Error
    😢

    Oops, something went wrong. Sorry!

    Please refresh or go home.

    ` ); }); }; diff --git a/now.json b/now.json index a9da14b8d3..017bf7860f 100644 --- a/now.json +++ b/now.json @@ -46,7 +46,7 @@ "API_TOKEN_SECRET": "@api-token-secret", "SENTRY_DSN_CLIENT": "@sentry-dsn-client", "SENTRY_DSN_SERVER": "@sentry-dsn-server", - "SPECTRUM_MODERATION_API_KEY": "@spectrum-moderation-api-key", + "AMPLITUDE_API_KEY": "@amplitude-api-key", "AMPLITUDE_API_KEY_DEVELOPMENT": "@amplitude-api-key-development", "ENCRYPTION_KEY": "@encryption-key", diff --git a/package.json b/package.json index 905454fb31..1c8a772f5d 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "cors": "^2.8.3", "cryptr": "^3.0.0", "css.escape": "^1.5.1", - "cypress": "^3.1.2", + "cypress": "^3.1.3", "dataloader": "^1.3.0", "debounce": "^1.2.0", "debug": "^4.1.0", diff --git a/shared/db/db.js b/shared/db/db.js index 1090e8646d..93b3923eee 100644 --- a/shared/db/db.js +++ b/shared/db/db.js @@ -7,7 +7,10 @@ const IS_PROD = !process.env.FORCE_DEV && process.env.NODE_ENV === 'production'; const DEFAULT_CONFIG = { // Connect to the test database when, well, testing db: !process.env.TEST_DB ? 'spectrum' : 'testing', - max: 20, // Maximum number of connections, default is 1000 + max: + process.env.SENTRY_NAME === 'api' || process.env.SENTRY_NAME === 'hyperion' + ? 60 + : 1, // Maximum number of connections, default is 1000 buffer: 1, // Minimum number of connections open at any given moment, default is 50 timeoutGb: 60 * 1000, // How long should an unused connection stick around, default is an hour, this is a minute }; diff --git a/shared/middlewares/toobusy.js b/shared/middlewares/toobusy.js index 04122b9a46..8424d786c0 100644 --- a/shared/middlewares/toobusy.js +++ b/shared/middlewares/toobusy.js @@ -8,13 +8,14 @@ export default ( res: express$Response | http$ServerResponse, next: express$NextFunction | (() => void) ) => { - // Don't send 503s in testing, that's dumb, just wait it out - if (process.env.NODE_ENV !== 'testing' && !process.env.TEST_DB && toobusy()) { - res.statusCode = 503; - res.end( - 'It looks like Spectrum is very busy right now, please try again in a minute.' - ); - } else { - next(); - } + next(); + // // Don't send 503s in testing, that's dumb, just wait it out + // if (process.env.NODE_ENV !== 'testing' && !process.env.TEST_DB && toobusy()) { + // res.statusCode = 503; + // res.end( + // 'It looks like Spectrum is very busy right now, please try again in a minute.' + // ); + // } else { + // next(); + // } }; diff --git a/src/components/icons/index.js b/src/components/icons/index.js index 7832f48a24..52bbe52bb2 100644 --- a/src/components/icons/index.js +++ b/src/components/icons/index.js @@ -835,6 +835,23 @@ export const Glyph = ({ glyph }: GlyphProps) => { /> ); + case 'announcement': + return ( + + + + + + + ); } }; diff --git a/src/components/profile/community.js b/src/components/profile/community.js index 470a49a997..1a4aa50001 100644 --- a/src/components/profile/community.js +++ b/src/components/profile/community.js @@ -187,7 +187,7 @@ class CommunityWithData extends React.Component { - {community.metaData.onlineMembers} online + {community.metaData.onlineMembers.toLocaleString()} online )} diff --git a/src/routes.js b/src/routes.js index 065b74ac27..11c14f8d4e 100644 --- a/src/routes.js +++ b/src/routes.js @@ -24,6 +24,7 @@ import PrivateCommunityJoin from 'src/views/privateCommunityJoin'; import ThreadSlider from 'src/views/threadSlider'; import Navbar from 'src/views/navbar'; import Status from 'src/views/status'; +import AnnouncementBanner from 'src/views/announcementBanner'; import Login from 'src/views/login'; import DirectMessages from 'src/views/directMessages'; import { FullscreenThreadView } from 'src/views/thread'; @@ -178,6 +179,7 @@ class Routes extends React.Component { */} {() => null} + diff --git a/src/views/announcementBanner/index.js b/src/views/announcementBanner/index.js new file mode 100644 index 0000000000..c36b97e148 --- /dev/null +++ b/src/views/announcementBanner/index.js @@ -0,0 +1,48 @@ +// @flow +import * as React from 'react'; +import Icon from 'src/components/icons'; +import { Bar, Content, Dismiss, Bold } from './style'; +import { getItemFromStorage, storeItem } from 'src/helpers/localStorage'; + +const lsKey = 'hasDismissedAnnouncementBanner'; + +type State = { + visible: boolean, +}; + +class Banner extends React.Component<{}, State> { + state = { visible: false }; + + componentDidMount() { + const hidden = getItemFromStorage(lsKey); + if (!hidden) this.setState({ visible: true }); + } + + dismiss = () => { + storeItem(lsKey, true); + return this.setState({ visible: false }); + }; + + render() { + const { visible } = this.state; + if (!visible) return null; + return ( + + + +

    + Spectrum is now part of GitHub! + Read the announcement... +

    +
    + × +
    + ); + } +} + +export default Banner; diff --git a/src/views/announcementBanner/style.js b/src/views/announcementBanner/style.js new file mode 100644 index 0000000000..05c5104828 --- /dev/null +++ b/src/views/announcementBanner/style.js @@ -0,0 +1,56 @@ +// @flow +import styled from 'styled-components'; +import theme from 'shared/theme'; +import Link from 'src/components/link'; + +export const Bar = styled.div` + display: flex; + background: ${theme.brand.wash}; + align-items: center; + border-bottom: 1px solid ${theme.brand.border}; + color: ${theme.brand.default}; + font-size: 14px; + font-weight: 400; + padding: 0 8px 0 0; + justify-content: center; + flex: 0 0 48px; + max-height: 48px; +`; + +export const Content = styled(Link)` + display: flex; + justify-content: center; + align-items: center; + line-height: 1.2; + padding: 12px 0; + flex: 1 0 auto; + + @media (max-width: 768px) { + justify-content: flex-start; + padding-left: 12px; + flex: 1 1 auto; + + .icon { + margin-right: 8px; + } + } +`; + +export const Bold = styled.span` + margin: 0 4px 0 8px; + font-weight: 500; + + @media (max-width: 768px) { + margin-left: 0; + } +`; + +export const Dismiss = styled.div` + display: flex; + align-items: center; + justify-content: center; + font-size: 18px; + padding-bottom: 4px; + padding: 0 12px 4px 12px; + cursor: pointer; +`; diff --git a/src/views/channel/index.js b/src/views/channel/index.js index 3ac22d5210..c157fd87d5 100644 --- a/src/views/channel/index.js +++ b/src/views/channel/index.js @@ -422,7 +422,7 @@ class ChannelView extends React.Component { - {channel.metaData.onlineMembers} online + {channel.metaData.onlineMembers.toLocaleString()} online )} diff --git a/src/views/channelSettings/components/channelMembers.js b/src/views/channelSettings/components/channelMembers.js index 57edc420d2..b220215208 100644 --- a/src/views/channelSettings/components/channelMembers.js +++ b/src/views/channelSettings/components/channelMembers.js @@ -74,7 +74,7 @@ class ChannelMembers extends Component { > {currentUser && user.id !== currentUser.id && ( - + initMessage(user)} diff --git a/src/views/channelSettings/components/overview.js b/src/views/channelSettings/components/overview.js index 26e8cda8a2..dd772b49bf 100644 --- a/src/views/channelSettings/components/overview.js +++ b/src/views/channelSettings/components/overview.js @@ -83,7 +83,13 @@ class Overview extends React.Component { )} - {!channel.isPrivate && } + {!channel.isPrivate && ( + + )} diff --git a/src/views/community/components/memberGrid.js b/src/views/community/components/memberGrid.js index 0a10934ef9..2e3c0ff0d4 100644 --- a/src/views/community/components/memberGrid.js +++ b/src/views/community/components/memberGrid.js @@ -110,7 +110,7 @@ class CommunityMemberGrid extends React.Component { > {currentUser && user.id !== currentUser.id && ( - + this.initMessage(user)} diff --git a/src/views/directMessages/containers/newThread.js b/src/views/directMessages/containers/newThread.js index c69d7a989d..dee17f6a7d 100644 --- a/src/views/directMessages/containers/newThread.js +++ b/src/views/directMessages/containers/newThread.js @@ -733,6 +733,7 @@ class NewThread extends React.Component { selected={focusedSelectedUser === user.id} onClick={() => this.setFocusedSelectedUser(user.id)} key={user.id} + data-cy="selected-user-pill" > {user.name} diff --git a/src/views/userSettings/components/editForm.js b/src/views/userSettings/components/editForm.js index 5c7c531fc3..f5a40f2d8a 100644 --- a/src/views/userSettings/components/editForm.js +++ b/src/views/userSettings/components/editForm.js @@ -10,7 +10,6 @@ import Icon from 'src/components/icons'; import { SERVER_URL, CLIENT_URL } from 'src/api/constants'; import GithubProfile from 'src/components/githubProfile'; import { GithubSigninButton } from 'src/components/loginButtonSet/github'; -import { withCurrentUser } from 'src/components/withCurrentUser'; import { Input, TextArea, @@ -62,7 +61,6 @@ type State = { }; type Props = { - currentUser: Object, dispatch: Dispatch, client: Object, editUser: Function, @@ -293,9 +291,9 @@ class UserWithData extends React.Component { }; handleUsernameValidation = ({ error, username }) => { - const { currentUser } = this.props; + const { user } = this.props; // we want to reset error if was typed same username which was set before - const usernameError = currentUser.username === username ? '' : error; + const usernameError = user.username === username ? '' : error; this.setState({ usernameError, username, @@ -307,7 +305,7 @@ class UserWithData extends React.Component { }; render() { - const { currentUser } = this.props; + const { user } = this.props; const { name, username, @@ -416,7 +414,7 @@ class UserWithData extends React.Component { {emailError && {emailError}} { if (!profile) { return ( @@ -475,7 +473,6 @@ const UserSettings = compose( editUserMutation, withRouter, withApollo, - withCurrentUser, connect() )(UserWithData); export default UserSettings; diff --git a/src/views/userSettings/index.js b/src/views/userSettings/index.js index 84699a25bb..85d0487df8 100644 --- a/src/views/userSettings/index.js +++ b/src/views/userSettings/index.js @@ -77,29 +77,6 @@ class UserSettings extends React.Component { ); } - // if the user isn't logged in, or for some reason the user settings that were returned don't match the user id in the store, we show a warning error state - if (!currentUser || (user && user.id !== currentUser.id)) { - return ( - - > - - - - - - ); - } - // user is viewing their own settings, validated on the server if (user && user.id && currentUser.id === user.id) { const subnavItems = [ diff --git a/yarn.lock b/yarn.lock index cd2315c43b..64b57f5de0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3642,11 +3642,6 @@ commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" -compare-versions@3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26" - integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg== - component-cookie@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/component-cookie/-/component-cookie-1.1.4.tgz#1b88b3dda4953d890163dd52fa53df374247cf8d" @@ -4131,10 +4126,10 @@ cycle@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" -cypress@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.1.2.tgz#d1adbb48afecad54a84adf25f30536b400aa0f18" - integrity sha512-anII950IRqmpQcxlo9te3vTcrl4keuGJaWlBQ5hbAb77D2YrcDv7Iux1FvX1vy/ZzzTdMaiiOts5sa8h63iP0g== +cypress@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.1.3.tgz#f6253e2428c9f76e0541440b959b6282d1757467" + integrity sha512-ZusTQffKBVrLDvcxEinymTH0iCUL7hM1m6q9X+557wDtpd6S4et330QQE1IW10Pnyp+vYIHpkWxDm43B9G14nA== dependencies: "@cypress/listr-verbose-renderer" "0.4.1" "@cypress/xvfb" "1.2.3" @@ -4154,7 +4149,6 @@ cypress@^3.1.2: check-more-types "2.24.0" commander "2.11.0" common-tags "1.4.0" - compare-versions "3.4.0" debug "3.1.0" execa "0.10.0" executable "4.1.1"