From f09550a4acd075411392dd0cdc321f23862aee06 Mon Sep 17 00:00:00 2001 From: Belen Curcio Date: Mon, 10 Jul 2017 16:56:46 -0300 Subject: [PATCH] Avatar plugin support extending fragments --- .eslintignore | 1 + .gitignore | 1 + .../src/containers/Comment.js | 3 +- plugin-api/beta/client/hocs/index.js | 1 + plugins/talk-plugin-avatar/client/.babelrc | 14 ++++ .../talk-plugin-avatar/client/.eslintrc.json | 23 ++++++ .../client/assets/avatar-placeholder.png | Bin 0 -> 8811 bytes .../client/components/UserAvatar.js | 8 ++ .../client/components/styles.css | 4 + .../client/containers/UserAvatar.js | 12 +++ plugins/talk-plugin-avatar/client/index.js | 7 ++ plugins/talk-plugin-avatar/index.js | 75 ++++++++++++++++++ plugins/talk-plugin-avatar/package.json | 11 +++ 13 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 plugins/talk-plugin-avatar/client/.babelrc create mode 100644 plugins/talk-plugin-avatar/client/.eslintrc.json create mode 100644 plugins/talk-plugin-avatar/client/assets/avatar-placeholder.png create mode 100644 plugins/talk-plugin-avatar/client/components/UserAvatar.js create mode 100644 plugins/talk-plugin-avatar/client/components/styles.css create mode 100644 plugins/talk-plugin-avatar/client/containers/UserAvatar.js create mode 100644 plugins/talk-plugin-avatar/client/index.js create mode 100644 plugins/talk-plugin-avatar/index.js create mode 100644 plugins/talk-plugin-avatar/package.json diff --git a/.eslintignore b/.eslintignore index 3a259c106..9ed3e5361 100644 --- a/.eslintignore +++ b/.eslintignore @@ -13,4 +13,5 @@ plugins/* !plugins/coral-plugin-viewing-options !plugins/coral-plugin-comment-content !plugins/talk-plugin-permalink +!plugins/talk-plugin-avatar node_modules diff --git a/.gitignore b/.gitignore index 0be1266c6..e94a01a6c 100644 --- a/.gitignore +++ b/.gitignore @@ -26,5 +26,6 @@ plugins/* !plugins/coral-plugin-viewing-options !plugins/coral-plugin-comment-content !plugins/talk-plugin-permalink +!plugins/talk-plugin-avatar **/node_modules/* diff --git a/client/coral-embed-stream/src/containers/Comment.js b/client/coral-embed-stream/src/containers/Comment.js index 040d1a83e..1ffac82cf 100644 --- a/client/coral-embed-stream/src/containers/Comment.js +++ b/client/coral-embed-stream/src/containers/Comment.js @@ -10,7 +10,8 @@ const pluginFragments = getSlotsFragments([ 'commentInfoBar', 'commentActions', 'commentContent', - 'commentReactions' + 'commentReactions', + 'commentAvatar' ]); export default withFragments({ diff --git a/plugin-api/beta/client/hocs/index.js b/plugin-api/beta/client/hocs/index.js index 7be682670..7f3476cfd 100644 --- a/plugin-api/beta/client/hocs/index.js +++ b/plugin-api/beta/client/hocs/index.js @@ -1 +1,2 @@ export {default as withReaction} from './withReaction'; +export {default as withFragments} from 'coral-framework/hocs/withFragments'; diff --git a/plugins/talk-plugin-avatar/client/.babelrc b/plugins/talk-plugin-avatar/client/.babelrc new file mode 100644 index 000000000..60be246eb --- /dev/null +++ b/plugins/talk-plugin-avatar/client/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + "es2015" + ], + "plugins": [ + "add-module-exports", + "transform-class-properties", + "transform-decorators-legacy", + "transform-object-assign", + "transform-object-rest-spread", + "transform-async-to-generator", + "transform-react-jsx" + ] +} \ No newline at end of file diff --git a/plugins/talk-plugin-avatar/client/.eslintrc.json b/plugins/talk-plugin-avatar/client/.eslintrc.json new file mode 100644 index 000000000..9fe56bd14 --- /dev/null +++ b/plugins/talk-plugin-avatar/client/.eslintrc.json @@ -0,0 +1,23 @@ +{ + "env": { + "browser": true, + "es6": true, + "mocha": true + }, + "parserOptions": { + "sourceType": "module", + "ecmaFeatures": { + "experimentalObjectRestSpread": true, + "jsx": true + } + }, + "parser": "babel-eslint", + "plugins": [ + "react" + ], + "rules": { + "react/jsx-uses-react": "error", + "react/jsx-uses-vars": "error", + "no-console": ["warn", { "allow": ["warn", "error"] }] + } +} diff --git a/plugins/talk-plugin-avatar/client/assets/avatar-placeholder.png b/plugins/talk-plugin-avatar/client/assets/avatar-placeholder.png new file mode 100644 index 0000000000000000000000000000000000000000..2e828f0fb9c775fd824f571f78ee59e3f2f73ace GIT binary patch literal 8811 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 PKSg=4vUIhiaq#~E;=)iN literal 0 HcmV?d00001 diff --git a/plugins/talk-plugin-avatar/client/components/UserAvatar.js b/plugins/talk-plugin-avatar/client/components/UserAvatar.js new file mode 100644 index 000000000..ae1ab30f9 --- /dev/null +++ b/plugins/talk-plugin-avatar/client/components/UserAvatar.js @@ -0,0 +1,8 @@ +import React from 'react'; +import styles from './styles.css'; +import avatarPlaceholder from '../assets/avatar-placeholder.png'; + +const UserAvatar = ({comment: {user}}) => + + +export default UserAvatar; diff --git a/plugins/talk-plugin-avatar/client/components/styles.css b/plugins/talk-plugin-avatar/client/components/styles.css new file mode 100644 index 000000000..fc6111845 --- /dev/null +++ b/plugins/talk-plugin-avatar/client/components/styles.css @@ -0,0 +1,4 @@ +.avatarPlaceholder { + height: 50px; + width: 50px; +} \ No newline at end of file diff --git a/plugins/talk-plugin-avatar/client/containers/UserAvatar.js b/plugins/talk-plugin-avatar/client/containers/UserAvatar.js new file mode 100644 index 000000000..76b558e05 --- /dev/null +++ b/plugins/talk-plugin-avatar/client/containers/UserAvatar.js @@ -0,0 +1,12 @@ +import {gql} from 'react-apollo'; +import {withFragments} from 'plugin-api/beta/client/hocs'; +import UserAvatar from '../components/UserAvatar'; + +export default withFragments({ + comment: gql` + fragment UserAvatar_comment on Comment { + user { + avatar + } + }` +})(UserAvatar); diff --git a/plugins/talk-plugin-avatar/client/index.js b/plugins/talk-plugin-avatar/client/index.js new file mode 100644 index 000000000..922e464b8 --- /dev/null +++ b/plugins/talk-plugin-avatar/client/index.js @@ -0,0 +1,7 @@ +import UserAvatar from './components/UserAvatar'; + +export default { + slots: { + commentAvatar: [UserAvatar] + } +} \ No newline at end of file diff --git a/plugins/talk-plugin-avatar/index.js b/plugins/talk-plugin-avatar/index.js new file mode 100644 index 000000000..b91a58835 --- /dev/null +++ b/plugins/talk-plugin-avatar/index.js @@ -0,0 +1,75 @@ +// We need the UserModel because we need to update the user. +const UserModel = require('models/user'); + +// Get some middleware to use with the webhook. +const auth = require('middleware/authentication'); +const authz = require('middleware/authorization'); + +// Load some config from the environment. This could be changed to a settings +// option later if you want to go that route. +const DEFAULT_AVATAR = process.env.DEFAULT_AVATAR; + +module.exports = { + + // The new type definitions provides the new "avatar" field needed to inject + // into the User type. + typeDefs: ` + type User { + avatar: String + } + `, + + // The User resolver will return the avatar from the embedded user metadata. + resolvers: { + User: { + avatar(user) { + if (user && user.metadata && user.metadata.avatar) { + return user.metadata.avatar; + } + + return DEFAULT_AVATAR; + } + } + }, + + // The custom router routes that we add here will allow an external system to + // update the avatar when it changes on the remote system. Note that we do + // use the auth/authz middleware, checking for the ADMIN role. This can be + // used in conjunction with a personal access token generated from an ADMIN. + router(router) { + router.post('/webhooks/user_update', auth, authz.needed('ADMIN'), async (req, res, next) => { + + // We expect that the payload for the new avatar is in the following form: + // + // { + // "id": "123123-123123-12312313", + // "avatar": "https://great-cdn.cloudfront.net/best-photo.jpg" + // ... + // } + + + // Extract the data from the payload. + let { + id, + avatar + } = req.body; + + try { + + // Update the user model. + await UserModel.update({id}, { + $set: { + 'metadata.avatar': avatar + } + }); + + } catch (e) { + return next(e); + } + + // Respond with a `202 Accepted` to indicate that we were able to process + // the update. + res.status(202).end() + }); + } +}; \ No newline at end of file diff --git a/plugins/talk-plugin-avatar/package.json b/plugins/talk-plugin-avatar/package.json new file mode 100644 index 000000000..c652a86d0 --- /dev/null +++ b/plugins/talk-plugin-avatar/package.json @@ -0,0 +1,11 @@ +{ + "name": "talk-plugin-avatar", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Belen Curcio ", + "license": "ISC" +}