From cce464b82ac9cae6fe207534075191c929c59a2a Mon Sep 17 00:00:00 2001 From: immber Date: Wed, 28 Nov 2018 13:56:31 -0800 Subject: [PATCH 01/38] merging in typo fixes from docs (rtd) branch --- docs/.gitignore | 3 ++- docs/source/01-01-talk-quickstart.md | 2 ++ docs/source/integrating/asset-management.md | 11 ++++++----- scripts/generateIntrospectionResult.js | 12 +++++++++--- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/docs/.gitignore b/docs/.gitignore index be0603043..6c8794979 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -3,4 +3,5 @@ public/* .deploy*/ db.json *.log -source/_data/introspection.json \ No newline at end of file +source/_data/introspection.json +rtd/build/* \ No newline at end of file diff --git a/docs/source/01-01-talk-quickstart.md b/docs/source/01-01-talk-quickstart.md index 8478ed0f2..e85e09e1e 100644 --- a/docs/source/01-01-talk-quickstart.md +++ b/docs/source/01-01-talk-quickstart.md @@ -187,8 +187,10 @@ and walk through the initial setup steps. * First, enter your **Organization Name** and **Organization Contact Email**. This will appear in emails when inviting new team members. * Next, create your Admin user. You can specify an **Email Address**, **Username**, and **Password** + * Finally, enter your list of **Permitted Domains**, read [here](/talk/configuring-talk/#permitted-domains) about whitelisting domains + _During development, ensure you whitelist 127.0.0.1:3000 otherwise the [http://127.0.0.1:3000/](http://127.0.0.1:3000/) page will not load._ diff --git a/docs/source/integrating/asset-management.md b/docs/source/integrating/asset-management.md index 52bb11b69..4a1de24ea 100644 --- a/docs/source/integrating/asset-management.md +++ b/docs/source/integrating/asset-management.md @@ -18,11 +18,12 @@ By default, Talk will use "Lazy Asset Creation" to dynamically generate Assets in Talk in order to make it easier for lighter installations. In order to have more strict control over this flow, we will create a plugin that will: -1. Disable "Lazy Asset Creation" by [Overriding a Resolver](#overriding-a-resolver). -2. Create Assets from our CMS by [Creating a New Asset Route](#creating-a-new-asset-route). -3. Facilitate updates from our CMS to keep Talk in sync by [Creating an Asset Update Route](#creating-an-asset-update-route). -We will then modify our embed so that we can [Target the Asset](#target-the-asset). +1. Disable "Lazy Asset Creation" by [Overriding a Resolver](#Overriding%20a%20Resolver). +2. Create Assets from our CMS by [Creating a New Asset Route](#Creating%20a%20New%20Asset%20Route). +3. Facilitate updates from our CMS to keep Talk in sync by [Creating an Asset Update Route](#Creating%20an%20Asset%20Update%20Route). + +We will then modify our embed so that we can [Target the Asset](#Target%20the%20Asset). But first we should grab our basic plugin structure: @@ -248,7 +249,7 @@ module.exports = router => { }; ``` -As you can see from the previous step of [Creating a New Asset Route](#creating-a-New-Asset-Route) +As you can see from the previous step of [Creating a New Asset Route](#Creating%20a%20New%20Asset%20Route) , we have added the new `PUT` route to the router. This is a simple addition that allows your CMS to call into Talk when the asset has updated it's title, it's url (or really anything in the [AssetSchema](https://github.com/coralproject/talk/blob/master/models/asset.js)) to keep the Talk Admin and links up to date. diff --git a/scripts/generateIntrospectionResult.js b/scripts/generateIntrospectionResult.js index 6f289e8e8..b4e788fc1 100755 --- a/scripts/generateIntrospectionResult.js +++ b/scripts/generateIntrospectionResult.js @@ -112,10 +112,14 @@ const generateIntrospectionResult = async (resultLocation, options = {}) => { return; } - const { data } = await graphql(schema, getIntrospectionQuery(options)); + const result = await graphql(schema, getIntrospectionQuery(options)); // Serialize the introspection result as JSON. - const introspectionResult = JSON.stringify(data, null, 2); + const introspectionResult = JSON.stringify( + options.raw ? result : result.data, + null, + 2 + ); // Write the introspection result to the filesystem. fs.writeFileSync(resultLocation, introspectionResult, 'utf8'); @@ -145,7 +149,9 @@ Promise.all([ generateIntrospectionResult(graphIntrospectionFilename, { descriptions: false, }), - generateIntrospectionResult(docsIntrospectionFilename), + generateIntrospectionResult(docsIntrospectionFilename, { + raw: true, + }), ]).catch(err => { console.error(err); process.exit(1); From 5ae293af89c8e2697c00bf27997dc4b8b743a757 Mon Sep 17 00:00:00 2001 From: immber Date: Wed, 28 Nov 2018 13:58:56 -0800 Subject: [PATCH 02/38] revert generateIntrospectionResult.json --- scripts/generateIntrospectionResult.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/scripts/generateIntrospectionResult.js b/scripts/generateIntrospectionResult.js index b4e788fc1..6f289e8e8 100755 --- a/scripts/generateIntrospectionResult.js +++ b/scripts/generateIntrospectionResult.js @@ -112,14 +112,10 @@ const generateIntrospectionResult = async (resultLocation, options = {}) => { return; } - const result = await graphql(schema, getIntrospectionQuery(options)); + const { data } = await graphql(schema, getIntrospectionQuery(options)); // Serialize the introspection result as JSON. - const introspectionResult = JSON.stringify( - options.raw ? result : result.data, - null, - 2 - ); + const introspectionResult = JSON.stringify(data, null, 2); // Write the introspection result to the filesystem. fs.writeFileSync(resultLocation, introspectionResult, 'utf8'); @@ -149,9 +145,7 @@ Promise.all([ generateIntrospectionResult(graphIntrospectionFilename, { descriptions: false, }), - generateIntrospectionResult(docsIntrospectionFilename, { - raw: true, - }), + generateIntrospectionResult(docsIntrospectionFilename), ]).catch(err => { console.error(err); process.exit(1); From bac0ee9c3b2ff9418dfa9197cfbc5c21288119a2 Mon Sep 17 00:00:00 2001 From: immber Date: Wed, 28 Nov 2018 14:00:07 -0800 Subject: [PATCH 03/38] revert git ignore --- docs/.gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/.gitignore b/docs/.gitignore index 6c8794979..be0603043 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -3,5 +3,4 @@ public/* .deploy*/ db.json *.log -source/_data/introspection.json -rtd/build/* \ No newline at end of file +source/_data/introspection.json \ No newline at end of file From e9cec73966253658a3f8cc1ba23227839147b5ad Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 30 Nov 2018 14:44:35 -0800 Subject: [PATCH 04/38] added asset mgmt to prelaunch checklist --- docs/source/01-05-pre-launch-checklist.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/01-05-pre-launch-checklist.md b/docs/source/01-05-pre-launch-checklist.md index d30419e01..23e7d48a6 100644 --- a/docs/source/01-05-pre-launch-checklist.md +++ b/docs/source/01-05-pre-launch-checklist.md @@ -28,6 +28,8 @@ permalink: /pre-launch-checklist/ - [ ] Do you want to provide single sign-on (SSO) by integrating with an external auth system? - See [Authenticating with Talk](/talk/integrating/authentication/) +- [ ] Do you want to integrate Talk with your CMS to automate embedding Talk Comment Stream into your site? + - See [Asset Management](/talk/integrating/asset-management/) - [ ] Do you want to use Social sign-on? - Facebook From 4659392ad383b9533c957d6f1840a164cbefb915 Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 30 Nov 2018 15:10:00 -0800 Subject: [PATCH 05/38] updated cusotm plugin docker onbuild instructions --- docs/source/plugins/overview.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/source/plugins/overview.md b/docs/source/plugins/overview.md index 2e8a9c2a5..1f734edeb 100644 --- a/docs/source/plugins/overview.md +++ b/docs/source/plugins/overview.md @@ -105,6 +105,8 @@ Then the application can be started as is. ### Docker +To deploy customized plugins to a production instance of Talk, we recommend using the Docker onbuild strategy outlined below. + If you deploy using Docker, you can extend from the `*-onbuild` image, an example `Dockerfile` for your project could be: @@ -112,14 +114,22 @@ example `Dockerfile` for your project could be: FROM coralproject/talk:4.5-onbuild ``` -Where the directory for your instance would contain a `plugins.json` file -describing the plugin requirements and a `plugins` directory containing any +Establish a private repository for your instance that includes the following: + +* a `plugins.json` file +listing the plugin requirements +* a `plugins` directory containing any other local plugins that should be included. +* a Dockerfile as outlined above + +Git submodules can also be used to point to plugin directories that might be outside your primary repository. Onbuild triggers will execute when the image is building with your custom configuration and will ensure that the image is ready to use by building all assets inside the image as well. +Once built, you can deploy the docker image to your architecture by tagging the image and including it in your docker-compose.yml. + For more information on the onbuild image, refer to the [Installation from Docker](/talk/installation-from-docker/) documentation. From 76c959f790cb332357d0f8b215a0cf86a7746c94 Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 30 Nov 2018 17:11:42 -0800 Subject: [PATCH 06/38] add google to auth options --- docs/source/integrating/authentication.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/source/integrating/authentication.md b/docs/source/integrating/authentication.md index 77315a9d8..1e5567289 100644 --- a/docs/source/integrating/authentication.md +++ b/docs/source/integrating/authentication.md @@ -3,8 +3,10 @@ title: Authenticating with Talk permalink: /integrating/authentication/ --- -You can integrate Talk with any external authentication service that will enable -seamless single sign-on for users within your organization. There are a few +Out of the box Talk supports account registration with username and password, as well as features like forgot password. + +You can also integrate Talk with any external authentication service that will enable +seamless single sign-on (SSO) for users within your organization. There are a few methods of doing so: 1. Passport Middleware @@ -17,8 +19,12 @@ choice. You would choose the **Passport Middleware** route when you are OK using an auth that is triggered from inside Talk that is not connected to an external auth -state (you don't use the auth anywhere else now). A great example of this is our -[talk-plugin-facebook-auth](/talk/plugin/talk-plugin-facebook-auth/) plugin. +state (you don't use the auth anywhere else now). + +Plugins are available for the follwing 3rd party authentication providers: + +* [Facebook](/talk/plugin/talk-plugin-facebook-auth/) +* [Google](/talk/plugin/talk-plugin-google-auth/) ## Custom Token Integration From 847ded5bb47cb9d18d7d52a0628dec19b5a1cc0b Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 30 Nov 2018 17:19:27 -0800 Subject: [PATCH 07/38] add google to auth options --- docs/source/03-02-product-guide-commenter-features.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/source/03-02-product-guide-commenter-features.md b/docs/source/03-02-product-guide-commenter-features.md index 3d60eeda9..c89e018e7 100644 --- a/docs/source/03-02-product-guide-commenter-features.md +++ b/docs/source/03-02-product-guide-commenter-features.md @@ -5,13 +5,15 @@ permalink: /commenter-features/ ## Signing up for Talk -There are 2 ways that newsrooms can support signup/login functionality with Talk: +There are 3 ways that newsrooms can support signup/login functionality with Talk: * Use Talk’s auth plugin out of the box (supports account registration with username and password, as well as features like forgot password) +* Use 3rd party authentication provider such as FaceBook or Google. We provide plugins that support logging in with either [Facebook](/talk/plugin/talk-plugin-facebook-auth/) +or [Google](/talk/plugin/talk-plugin-google-auth/). (Note: you must provide your own Facebook App ID and Secret, which you can read more about here: [https://developers.facebook.com](https://developers.facebook.com)) + * Create their own auth plugin to integrate with your own auth systems -We also provide a Facebook auth plugin that supports logging in with Facebook (you must provide your own Facebook App ID and Secret, which you can read more about here: [https://developers.facebook.com](https://developers.facebook.com)) ## Comments and Replies From 92681f52aa5943086886efc04ec10887c2497ab3 Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 30 Nov 2018 17:39:02 -0800 Subject: [PATCH 08/38] added yarn watch to from source --- docs/source/01-03-installation-from-source.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/01-03-installation-from-source.md b/docs/source/01-03-installation-from-source.md index 9f4b96d93..978ffedd0 100644 --- a/docs/source/01-03-installation-from-source.md +++ b/docs/source/01-03-installation-from-source.md @@ -70,5 +70,7 @@ You can now start the application by running: yarn watch:server ``` +If you are developing a custom plugin you can use `yarn watch:client` or `yarn watch` to run both client and server. + At this stage, you should refer to the [configuration](/talk/configuration/) for configuration variables that are specific to your installation. From 3668a2cffaabfd6390db321181f8c931da884004 Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 30 Nov 2018 17:56:20 -0800 Subject: [PATCH 09/38] added dev links to quickstart --- docs/source/01-01-talk-quickstart.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/source/01-01-talk-quickstart.md b/docs/source/01-01-talk-quickstart.md index e85e09e1e..c17170335 100644 --- a/docs/source/01-01-talk-quickstart.md +++ b/docs/source/01-01-talk-quickstart.md @@ -222,6 +222,17 @@ Once you have added the domain of these docs, you can click the button below.
+### Developer Endpoints + +With your local instance of Talk running in development mode (env variable `NODE_ENV=development`) you should now also be able to access the following developer routes: + +[http://127.0.0.1:3000/dev](http://127.0.0.1:3000/dev]) provides a sample comment stream + +[http://127.0.0.1:3000/dev/assets](http://127.0.0.1:3000/dev/assets]) provides a list of all stories in Talk and can generate new sample assets + +###Conclusion At this point you've successfully installed, configured, and ran your very own instance of Talk! Continue through this documentation on this site to learn more on how to configure, develop with, and contribute to Talk! + + From cfae6b53744766f7d63855ae7e11e5974a672ed2 Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 30 Nov 2018 18:04:20 -0800 Subject: [PATCH 10/38] typo on following --- docs/source/integrating/authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/integrating/authentication.md b/docs/source/integrating/authentication.md index 1e5567289..f834f3e53 100644 --- a/docs/source/integrating/authentication.md +++ b/docs/source/integrating/authentication.md @@ -21,7 +21,7 @@ You would choose the **Passport Middleware** route when you are OK using an auth that is triggered from inside Talk that is not connected to an external auth state (you don't use the auth anywhere else now). -Plugins are available for the follwing 3rd party authentication providers: +Plugins are available for the following 3rd party authentication providers: * [Facebook](/talk/plugin/talk-plugin-facebook-auth/) * [Google](/talk/plugin/talk-plugin-google-auth/) From 2fac30416352c84f273895e89a12214ed8ef1cd0 Mon Sep 17 00:00:00 2001 From: immber Date: Mon, 3 Dec 2018 09:33:03 -0800 Subject: [PATCH 11/38] fixed typos --- docs/source/01-01-talk-quickstart.md | 6 +++--- docs/source/01-05-pre-launch-checklist.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/01-01-talk-quickstart.md b/docs/source/01-01-talk-quickstart.md index c17170335..6c5ecb5d1 100644 --- a/docs/source/01-01-talk-quickstart.md +++ b/docs/source/01-01-talk-quickstart.md @@ -226,11 +226,11 @@ Once you have added the domain of these docs, you can click the button below. With your local instance of Talk running in development mode (env variable `NODE_ENV=development`) you should now also be able to access the following developer routes: -[http://127.0.0.1:3000/dev](http://127.0.0.1:3000/dev]) provides a sample comment stream +* [http://127.0.0.1:3000/dev](http://127.0.0.1:3000/dev]) provides a sample comment stream -[http://127.0.0.1:3000/dev/assets](http://127.0.0.1:3000/dev/assets]) provides a list of all stories in Talk and can generate new sample assets +* [http://127.0.0.1:3000/dev/assets](http://127.0.0.1:3000/dev/assets]) provides a list of all stories in Talk and can generate new sample assets -###Conclusion +### Conclusion At this point you've successfully installed, configured, and ran your very own instance of Talk! Continue through this documentation on this site to learn more on how to configure, develop with, and contribute to Talk! diff --git a/docs/source/01-05-pre-launch-checklist.md b/docs/source/01-05-pre-launch-checklist.md index 23e7d48a6..854ead062 100644 --- a/docs/source/01-05-pre-launch-checklist.md +++ b/docs/source/01-05-pre-launch-checklist.md @@ -23,7 +23,7 @@ permalink: /pre-launch-checklist/ - [ ] Do you need to migrate comments from a legacy system? We currently support Disqus, Livefyre, and Civil Comments. - Use the [Talk Import](https://github.com/coralproject/talk-importer) framework - + - [ ] Do you want to provide single sign-on (SSO) by integrating with an external auth system? - See [Authenticating with Talk](/talk/integrating/authentication/) From 99777d6b495cc7eb030a0ee92544300ed2692866 Mon Sep 17 00:00:00 2001 From: immber Date: Mon, 3 Dec 2018 11:07:40 -0800 Subject: [PATCH 12/38] fixing links --- docs/source/integrating/asset-management.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/integrating/asset-management.md b/docs/source/integrating/asset-management.md index 4a1de24ea..190b67c63 100644 --- a/docs/source/integrating/asset-management.md +++ b/docs/source/integrating/asset-management.md @@ -19,11 +19,11 @@ in Talk in order to make it easier for lighter installations. In order to have more strict control over this flow, we will create a plugin that will: -1. Disable "Lazy Asset Creation" by [Overriding a Resolver](#Overriding%20a%20Resolver). -2. Create Assets from our CMS by [Creating a New Asset Route](#Creating%20a%20New%20Asset%20Route). -3. Facilitate updates from our CMS to keep Talk in sync by [Creating an Asset Update Route](#Creating%20an%20Asset%20Update%20Route). +1. Disable "Lazy Asset Creation" by [Overriding a Resolver](#overriding-a-resolver). +2. Create Assets from our CMS by [Creating a New Asset Route](#creating-a-new-asset-route). +3. Facilitate updates from our CMS to keep Talk in sync by [Creating an Asset Update Route](#creating-an-asset-update-route). -We will then modify our embed so that we can [Target the Asset](#Target%20the%20Asset). +We will then modify our embed so that we can [Target the Asset](#target-the-asset). But first we should grab our basic plugin structure: From cd9cb56844a54835ac22747c3d197d8d30d222e3 Mon Sep 17 00:00:00 2001 From: immber Date: Wed, 12 Dec 2018 12:44:19 -0800 Subject: [PATCH 13/38] added lazy render and updated lazy load --- docs/source/integrating/asset-management.md | 75 ++++++++++++++++++--- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/docs/source/integrating/asset-management.md b/docs/source/integrating/asset-management.md index 190b67c63..c70fda5cc 100644 --- a/docs/source/integrating/asset-management.md +++ b/docs/source/integrating/asset-management.md @@ -3,21 +3,75 @@ title: Asset Management permalink: /integrating/asset-management/ --- +## Embedding Comments on Your Site +Talk provides an embed script that you can drop into your site where you want a comments section to appear. By default that script dynamically generate Assets +in Talk in order to make it easier for lighter installations. + +You can find the embed script inside talk under `Configure > Tech Settings > Embed Script`. It should look something like this, but with your domain in place of ``: +``` +
+ +``` + +## Triggering the Comments Section (client side, i.e. Your site) + +When the embed script is triggered on your page load several things are initiated inside Talk, including fetching all comments for the specified article, establishing websocket connections for this user, and checking user’s session for SSO/authentication. + +Instead of greedily triggering the embed to render on _EVERY PAGE LOAD_, we highly recommend implementing a _“lazy”_ rendering strategy to only render the comments section if a user wants to interact with it. This will greatly improve your initial page load performance, and will be critical to managing server resources if you’re running Talk on a heavy-traffic production site. + +We recommend using one of these _“lazy”_ loading strategies: + +#### Scroll to Comments Section +Wait for user to scroll to the comment section before triggering the embed to render. + +You can pass lazy: true to the render options, like so: +``` +Coral.Talk.render(document.getElementById('container'), { + talk: 'https://my-talk-installation.com', + lazy: true, +}); +``` + +Or you can enable lazy rendering by default on all assets using ENV variable `TALK_DEFAULT_LAZY_RENDER=TRUE` + +#### Show Comments Button + You can hide the comments section until a user clicks button, then trigger the embed to render + +This example uses jQuery to render the embed on the button's click event +``` + + +
+ +
+ + +``` + +## Creating Assets in Talk (server side, i.e. What you need to send to Talk) One of the most frequent questions that we get asked by organizations trying to integrate Talk is: _How do we hook our CMS up to Talk so that articles are in sync?_ -This guide is designed to explain the steps to take your base installation of -Talk and configure it to allow only assets pushed into it from your CMS, and -keep your URL/title in sync. We won't cover here how to install the plugin, as -it is covered in our [Plugins Overview](/talk/plugins/). +### “Lazy Asset Creation” +Talk’s provided embed script by default dynamically generates Assets in Talk based on each unique url that triggers it. The url must reference an existing Permitted Domain. If your articles/stories always have unique urls, then you will not need to modify the default behavior. -## Why do we need to create a plugin? - -By default, Talk will use "Lazy Asset Creation" to dynamically generate Assets -in Talk in order to make it easier for lighter installations. In order to have -more strict control over this flow, we will create a plugin that will: +## Customizing the Integration with a Plugin +In order to have more strict control over the asset creation flow to allow only assets pushed into it from your CMS, and keep your URL/title in sync we will create a plugin. +We will create a plugin that will: 1. Disable "Lazy Asset Creation" by [Overriding a Resolver](#overriding-a-resolver). 2. Create Assets from our CMS by [Creating a New Asset Route](#creating-a-new-asset-route). @@ -25,6 +79,9 @@ more strict control over this flow, we will create a plugin that will: We will then modify our embed so that we can [Target the Asset](#target-the-asset). + +This guide is designed to explain the steps to take your base installation of Talk and configure it. We won't cover here how to install the plugin, as it is covered in our [Plugins Overview](/talk/plugins/). + But first we should grab our basic plugin structure: ```sh From 78ba82cc05eb44444f5f9432171e687ccf16b1ea Mon Sep 17 00:00:00 2001 From: Christian Ruttorf Date: Thu, 13 Dec 2018 17:42:50 +0100 Subject: [PATCH 14/38] add localization for QuestionBoxBuilder title, add PropTypes for QuestionBoxBuilder --- .../tabs/configure/components/QuestionBoxBuilder.js | 12 +++++++++++- .../src/tabs/configure/components/Settings.js | 1 + locales/de.yml | 1 + locales/en.yml | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/client/coral-embed-stream/src/tabs/configure/components/QuestionBoxBuilder.js b/client/coral-embed-stream/src/tabs/configure/components/QuestionBoxBuilder.js index 64593fc43..67fae6e3d 100644 --- a/client/coral-embed-stream/src/tabs/configure/components/QuestionBoxBuilder.js +++ b/client/coral-embed-stream/src/tabs/configure/components/QuestionBoxBuilder.js @@ -1,6 +1,7 @@ import React from 'react'; import QuestionBox from '../../../components/QuestionBox'; import DefaultQuestionBoxIcon from '../../../components/DefaultQuestionBoxIcon'; +import PropTypes from 'prop-types'; import cn from 'classnames'; import styles from './QuestionBoxBuilder.css'; import { Icon } from 'coral-ui'; @@ -12,6 +13,7 @@ const icons = [{ default: DefaultIcon }, 'forum', 'build', 'format_quote']; class QuestionBoxBuilder extends React.Component { render() { const { + title, questionBoxIcon, questionBoxContent, onContentChange, @@ -20,7 +22,7 @@ class QuestionBoxBuilder extends React.Component { return (
-

Include an Icon

+

{title}

    {icons.map(item => { @@ -53,4 +55,12 @@ class QuestionBoxBuilder extends React.Component { } } +QuestionBoxBuilder.propTypes = { + title: PropTypes.string, + questionBoxIcon: PropTypes.string, + questionBoxContent: PropTypes.string, + onContentChange: PropTypes.func, + onIconChange: PropTypes.func, +}; + export default QuestionBoxBuilder; diff --git a/client/coral-embed-stream/src/tabs/configure/components/Settings.js b/client/coral-embed-stream/src/tabs/configure/components/Settings.js index 2b1e49c84..32f04be68 100644 --- a/client/coral-embed-stream/src/tabs/configure/components/Settings.js +++ b/client/coral-embed-stream/src/tabs/configure/components/Settings.js @@ -69,6 +69,7 @@ class Settings extends React.Component { {questionBoxEnable && (
    Date: Thu, 13 Dec 2018 12:51:50 -0800 Subject: [PATCH 15/38] added version note --- docs/source/integrating/asset-management.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/integrating/asset-management.md b/docs/source/integrating/asset-management.md index c70fda5cc..cae92340f 100644 --- a/docs/source/integrating/asset-management.md +++ b/docs/source/integrating/asset-management.md @@ -37,6 +37,7 @@ Coral.Talk.render(document.getElementById('container'), { ``` Or you can enable lazy rendering by default on all assets using ENV variable `TALK_DEFAULT_LAZY_RENDER=TRUE` +_*Note: This feature requires Talk version 4.6.8 or greater_ #### Show Comments Button You can hide the comments section until a user clicks button, then trigger the embed to render From 374951bd33861f33d6aff01f85a35fde528b6d74 Mon Sep 17 00:00:00 2001 From: immber Date: Thu, 13 Dec 2018 13:04:01 -0800 Subject: [PATCH 16/38] renamed asset management to cms-integration --- docs/_config.yml | 4 ++-- docs/source/01-05-pre-launch-checklist.md | 2 +- .../integrating/{asset-management.md => cms-integration.md} | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) rename docs/source/integrating/{asset-management.md => cms-integration.md} (99%) diff --git a/docs/_config.yml b/docs/_config.yml index 57fe6d666..d9de09850 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -104,8 +104,8 @@ sidebar: children: - title: Authentication url: /integrating/authentication/ - - title: Asset Management - url: /integrating/asset-management/ + - title: CMS Integration + url: /integrating/cms-integration/ - title: Asset Scraping url: /integrating/asset-scraping/ - title: Configuring the Comment Stream diff --git a/docs/source/01-05-pre-launch-checklist.md b/docs/source/01-05-pre-launch-checklist.md index 854ead062..01e42b9bd 100644 --- a/docs/source/01-05-pre-launch-checklist.md +++ b/docs/source/01-05-pre-launch-checklist.md @@ -29,7 +29,7 @@ permalink: /pre-launch-checklist/ - See [Authenticating with Talk](/talk/integrating/authentication/) - [ ] Do you want to integrate Talk with your CMS to automate embedding Talk Comment Stream into your site? - - See [Asset Management](/talk/integrating/asset-management/) + - See [CMS Integration](/talk/integrating/cms-integration/) - [ ] Do you want to use Social sign-on? - Facebook diff --git a/docs/source/integrating/asset-management.md b/docs/source/integrating/cms-integration.md similarity index 99% rename from docs/source/integrating/asset-management.md rename to docs/source/integrating/cms-integration.md index cae92340f..f832d15ae 100644 --- a/docs/source/integrating/asset-management.md +++ b/docs/source/integrating/cms-integration.md @@ -1,6 +1,6 @@ --- -title: Asset Management -permalink: /integrating/asset-management/ +title: CMS Integration +permalink: /integrating/cms-integration/ --- ## Embedding Comments on Your Site @@ -37,6 +37,7 @@ Coral.Talk.render(document.getElementById('container'), { ``` Or you can enable lazy rendering by default on all assets using ENV variable `TALK_DEFAULT_LAZY_RENDER=TRUE` + _*Note: This feature requires Talk version 4.6.8 or greater_ #### Show Comments Button From 7eed540671eb52a19f75f31bd8e3a321616c56b8 Mon Sep 17 00:00:00 2001 From: immber Date: Thu, 13 Dec 2018 13:10:14 -0800 Subject: [PATCH 17/38] added link to asset scraping --- docs/source/integrating/cms-integration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/integrating/cms-integration.md b/docs/source/integrating/cms-integration.md index f832d15ae..521ab5cf8 100644 --- a/docs/source/integrating/cms-integration.md +++ b/docs/source/integrating/cms-integration.md @@ -70,6 +70,8 @@ sync?_ ### “Lazy Asset Creation” Talk’s provided embed script by default dynamically generates Assets in Talk based on each unique url that triggers it. The url must reference an existing Permitted Domain. If your articles/stories always have unique urls, then you will not need to modify the default behavior. +Assets created in this way will then be scraped to load metadata, see [Asset Scraping](/talk/integrating/asset-scraping/) + ## Customizing the Integration with a Plugin In order to have more strict control over the asset creation flow to allow only assets pushed into it from your CMS, and keep your URL/title in sync we will create a plugin. From 95435f079385475d66a94e83546b8433155410f7 Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 14 Dec 2018 09:05:52 -0800 Subject: [PATCH 18/38] Docs update (#2120) * merging in typo fixes from docs (rtd) branch * revert generateIntrospectionResult.json * revert git ignore * added asset mgmt to prelaunch checklist * updated cusotm plugin docker onbuild instructions * add google to auth options * add google to auth options * added yarn watch to from source * added dev links to quickstart * typo on following * fixed typos * fixing links * added lazy render and updated lazy load * added version note * renamed asset management to cms-integration * added link to asset scraping --- docs/_config.yml | 4 +- docs/source/01-05-pre-launch-checklist.md | 2 +- ...asset-management.md => cms-integration.md} | 81 ++++++++++++++++--- 3 files changed, 74 insertions(+), 13 deletions(-) rename docs/source/integrating/{asset-management.md => cms-integration.md} (75%) diff --git a/docs/_config.yml b/docs/_config.yml index 57fe6d666..d9de09850 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -104,8 +104,8 @@ sidebar: children: - title: Authentication url: /integrating/authentication/ - - title: Asset Management - url: /integrating/asset-management/ + - title: CMS Integration + url: /integrating/cms-integration/ - title: Asset Scraping url: /integrating/asset-scraping/ - title: Configuring the Comment Stream diff --git a/docs/source/01-05-pre-launch-checklist.md b/docs/source/01-05-pre-launch-checklist.md index 854ead062..01e42b9bd 100644 --- a/docs/source/01-05-pre-launch-checklist.md +++ b/docs/source/01-05-pre-launch-checklist.md @@ -29,7 +29,7 @@ permalink: /pre-launch-checklist/ - See [Authenticating with Talk](/talk/integrating/authentication/) - [ ] Do you want to integrate Talk with your CMS to automate embedding Talk Comment Stream into your site? - - See [Asset Management](/talk/integrating/asset-management/) + - See [CMS Integration](/talk/integrating/cms-integration/) - [ ] Do you want to use Social sign-on? - Facebook diff --git a/docs/source/integrating/asset-management.md b/docs/source/integrating/cms-integration.md similarity index 75% rename from docs/source/integrating/asset-management.md rename to docs/source/integrating/cms-integration.md index 190b67c63..521ab5cf8 100644 --- a/docs/source/integrating/asset-management.md +++ b/docs/source/integrating/cms-integration.md @@ -1,23 +1,81 @@ --- -title: Asset Management -permalink: /integrating/asset-management/ +title: CMS Integration +permalink: /integrating/cms-integration/ --- +## Embedding Comments on Your Site +Talk provides an embed script that you can drop into your site where you want a comments section to appear. By default that script dynamically generate Assets +in Talk in order to make it easier for lighter installations. + +You can find the embed script inside talk under `Configure > Tech Settings > Embed Script`. It should look something like this, but with your domain in place of ``: +``` +
    + +``` + +## Triggering the Comments Section (client side, i.e. Your site) + +When the embed script is triggered on your page load several things are initiated inside Talk, including fetching all comments for the specified article, establishing websocket connections for this user, and checking user’s session for SSO/authentication. + +Instead of greedily triggering the embed to render on _EVERY PAGE LOAD_, we highly recommend implementing a _“lazy”_ rendering strategy to only render the comments section if a user wants to interact with it. This will greatly improve your initial page load performance, and will be critical to managing server resources if you’re running Talk on a heavy-traffic production site. + +We recommend using one of these _“lazy”_ loading strategies: + +#### Scroll to Comments Section +Wait for user to scroll to the comment section before triggering the embed to render. + +You can pass lazy: true to the render options, like so: +``` +Coral.Talk.render(document.getElementById('container'), { + talk: 'https://my-talk-installation.com', + lazy: true, +}); +``` + +Or you can enable lazy rendering by default on all assets using ENV variable `TALK_DEFAULT_LAZY_RENDER=TRUE` + +_*Note: This feature requires Talk version 4.6.8 or greater_ + +#### Show Comments Button + You can hide the comments section until a user clicks button, then trigger the embed to render + +This example uses jQuery to render the embed on the button's click event +``` + + +
    + +
    + + +``` + +## Creating Assets in Talk (server side, i.e. What you need to send to Talk) One of the most frequent questions that we get asked by organizations trying to integrate Talk is: _How do we hook our CMS up to Talk so that articles are in sync?_ -This guide is designed to explain the steps to take your base installation of -Talk and configure it to allow only assets pushed into it from your CMS, and -keep your URL/title in sync. We won't cover here how to install the plugin, as -it is covered in our [Plugins Overview](/talk/plugins/). +### “Lazy Asset Creation” +Talk’s provided embed script by default dynamically generates Assets in Talk based on each unique url that triggers it. The url must reference an existing Permitted Domain. If your articles/stories always have unique urls, then you will not need to modify the default behavior. -## Why do we need to create a plugin? +Assets created in this way will then be scraped to load metadata, see [Asset Scraping](/talk/integrating/asset-scraping/) -By default, Talk will use "Lazy Asset Creation" to dynamically generate Assets -in Talk in order to make it easier for lighter installations. In order to have -more strict control over this flow, we will create a plugin that will: +## Customizing the Integration with a Plugin +In order to have more strict control over the asset creation flow to allow only assets pushed into it from your CMS, and keep your URL/title in sync we will create a plugin. +We will create a plugin that will: 1. Disable "Lazy Asset Creation" by [Overriding a Resolver](#overriding-a-resolver). 2. Create Assets from our CMS by [Creating a New Asset Route](#creating-a-new-asset-route). @@ -25,6 +83,9 @@ more strict control over this flow, we will create a plugin that will: We will then modify our embed so that we can [Target the Asset](#target-the-asset). + +This guide is designed to explain the steps to take your base installation of Talk and configure it. We won't cover here how to install the plugin, as it is covered in our [Plugins Overview](/talk/plugins/). + But first we should grab our basic plugin structure: ```sh From 08146fd9795d0072f8195f1dfce6718f5421f32b Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 14 Dec 2018 12:04:28 -0800 Subject: [PATCH 19/38] added redirect --- docs/public/_redirects | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/public/_redirects b/docs/public/_redirects index 617eb6adc..5bb190a8b 100644 --- a/docs/public/_redirects +++ b/docs/public/_redirects @@ -1,3 +1,4 @@ / /talk/ /talk/reference/server/ /talk/api/server/ -/talk/reference/graphql/ /talk/api/graphql/ \ No newline at end of file +/talk/reference/graphql/ /talk/api/graphql/ +/talk/integrating/asset-management/ /talk/integrating/cms-integration \ No newline at end of file From c8fc419ceca31ab8027c2729ebf6c54e6ac065bb Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 14 Dec 2018 20:46:57 +0000 Subject: [PATCH 20/38] Update _redirects --- docs/public/_redirects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/public/_redirects b/docs/public/_redirects index 5bb190a8b..df70683ab 100644 --- a/docs/public/_redirects +++ b/docs/public/_redirects @@ -1,4 +1,4 @@ / /talk/ /talk/reference/server/ /talk/api/server/ /talk/reference/graphql/ /talk/api/graphql/ -/talk/integrating/asset-management/ /talk/integrating/cms-integration \ No newline at end of file +/talk/integrating/asset-management/ /talk/integrating/cms-integration/ From d6515e23f806ff09c8891f31fd84c5a47be2027f Mon Sep 17 00:00:00 2001 From: Christian Ruttorf Date: Sun, 16 Dec 2018 08:48:21 +0100 Subject: [PATCH 21/38] fix ui/css bug in moderation/comment component caused by long words/links --- client/coral-admin/src/routes/Moderation/components/Comment.css | 1 + 1 file changed, 1 insertion(+) diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.css b/client/coral-admin/src/routes/Moderation/components/Comment.css index 282a83f3e..fc2236167 100644 --- a/client/coral-admin/src/routes/Moderation/components/Comment.css +++ b/client/coral-admin/src/routes/Moderation/components/Comment.css @@ -62,6 +62,7 @@ font-weight: 300; margin-bottom: 8px; overflow-wrap: break-word; + word-break:break-word; } .body { From 08f579225b13e4d0c41367ca262ff097d416a76a Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Mon, 17 Dec 2018 16:34:43 +0000 Subject: [PATCH 22/38] Bump version 4.6.11 (#2130) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b1f4b5a56..584afc428 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "talk", - "version": "4.6.10", + "version": "4.6.11", "description": "A better commenting experience from Mozilla, The New York Times, and the Washington Post. https://coralproject.net", "main": "app.js", "private": true, From ec816636e6addc04a34b4bf52978090dcfc17a35 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 19 Dec 2018 12:40:08 -0700 Subject: [PATCH 23/38] feat: added concurrency features --- bin/cli-serve | 22 +++++++++++++++++----- config.js | 3 +++ package.json | 1 + services/kue.js | 4 ++-- yarn.lock | 7 +++++++ 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/bin/cli-serve b/bin/cli-serve index d40edc9e4..0a63aa6cf 100755 --- a/bin/cli-serve +++ b/bin/cli-serve @@ -1,8 +1,10 @@ #!/usr/bin/env node +const throng = require('throng'); +const { CONCURRENCY } = require('../config'); +const { logger } = require('../services/logging'); const util = require('./util'); const program = require('commander'); -const serve = require('../serve'); //============================================================================== // Setting up the program command line arguments. @@ -22,8 +24,18 @@ program ) .parse(process.argv); -// Start serving. -serve(program).catch(err => { - console.error(err); - util.shutdown(1); +throng({ + workers: CONCURRENCY, + start: i => { + logger.info({ workerID: i }, 'started worker'); + + // Load in the serve. + const serve = require('../serve'); + + // Start serving. + serve(program).catch(err => { + console.error(err); + util.shutdown(1); + }); + }, }); diff --git a/config.js b/config.js index 007aafb46..d01ad8817 100644 --- a/config.js +++ b/config.js @@ -217,6 +217,9 @@ const CONFIG = { // messages through the websocket to keep the socket alive. KEEP_ALIVE: process.env.TALK_KEEP_ALIVE || '30s', + // CONCURRENCY is the number of workers that will serve traffic. + CONCURRENCY: parseInt(process.env.TALK_CONCURRENCY || '1'), + //------------------------------------------------------------------------------ // Cache configuration //------------------------------------------------------------------------------ diff --git a/package.json b/package.json index 584afc428..75dcaf268 100644 --- a/package.json +++ b/package.json @@ -205,6 +205,7 @@ "style-loader": "^0.16.0", "subscriptions-transport-ws": "^0.7.2", "supports-color": "^4", + "throng": "^4.0.0", "timeago.js": "^2.0.3", "timekeeper": "^1.0.0", "tlds": "^1.196.0", diff --git a/services/kue.js b/services/kue.js index 380f6a8c5..9db766d0e 100644 --- a/services/kue.js +++ b/services/kue.js @@ -91,12 +91,12 @@ class Task { static shutdown() { debug('Shutting down the Queue'); - return new Promise((resolve, reject) => { + return new Promise(resolve => { // Shutdown and give the queue 5 seconds to shutdown before we start // killing jobs. getQueue().shutdown(5000, err => { if (err) { - return reject(err); + return resolve(); } debug('Queue shut down.'); diff --git a/yarn.lock b/yarn.lock index 8d904c9f7..e5f1afb14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12823,6 +12823,13 @@ throat@^4.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= +throng@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/throng/-/throng-4.0.0.tgz#983c6ba1993b58eae859998aa687ffe88df84c17" + integrity sha1-mDxroZk7WOroWZmKpof/6I34TBc= + dependencies: + lodash.defaults "^4.0.1" + through2@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" From 9f7d4858710c5f7b1c8ab131ebf97e9c6014052c Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 19 Dec 2018 20:39:25 +0000 Subject: [PATCH 24/38] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 75dcaf268..fce56b057 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "talk", - "version": "4.6.11", + "version": "4.7.0", "description": "A better commenting experience from Mozilla, The New York Times, and the Washington Post. https://coralproject.net", "main": "app.js", "private": true, From 2c3589cdaca77f2b91463b2b52972ea4f8cb4fbb Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 4 Jan 2019 16:49:16 -0800 Subject: [PATCH 25/38] added cert to auth section --- docs/source/integrating/authentication.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/integrating/authentication.md b/docs/source/integrating/authentication.md index f834f3e53..981ceb156 100644 --- a/docs/source/integrating/authentication.md +++ b/docs/source/integrating/authentication.md @@ -61,6 +61,9 @@ The generated JWT must contain the following claims: - [`iss`](https://tools.ietf.org/html/rfc7519#section-4.1.1): the issuer for the token must match the value of `TALK_JWT_ISSUER` - [`aud`](https://tools.ietf.org/html/rfc7519#section-4.1.3): the audience for the token must match the value of `TALK_JWT_AUDIENCE` +### Generate a key to sign the JWT +Optionally you can use https://github.com/coralproject/coralcert to generate a key with which to sign the JWTs and specify the secret as an environment variable. + ### Push token into embed We're assuming that your CMS is capable of authenticating a user account, or From 886222260db0347dd22e4020b64a9458927cef6d Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 4 Jan 2019 16:55:56 -0800 Subject: [PATCH 26/38] fb requires ssl --- plugins/talk-plugin-facebook-auth/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/talk-plugin-facebook-auth/README.md b/plugins/talk-plugin-facebook-auth/README.md index 08780adda..839265b04 100644 --- a/plugins/talk-plugin-facebook-auth/README.md +++ b/plugins/talk-plugin-facebook-auth/README.md @@ -29,6 +29,8 @@ Configuration: guide. This is only required while the `talk-plugin-facebook-auth` plugin is enabled. +_NOTE: FabceBook auth requires your site to use `https` (SSL) not `http`. If your site is not `https` you can not use this plugin!_ + ## GDPR Compliance In order to facilitate compliance with the From 8f633fbe780e6c563c21f9dc8e3a824b38fafdc0 Mon Sep 17 00:00:00 2001 From: immber Date: Fri, 4 Jan 2019 17:20:49 -0800 Subject: [PATCH 27/38] added comment count to checklist --- docs/source/01-05-pre-launch-checklist.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/source/01-05-pre-launch-checklist.md b/docs/source/01-05-pre-launch-checklist.md index 01e42b9bd..f07953eb6 100644 --- a/docs/source/01-05-pre-launch-checklist.md +++ b/docs/source/01-05-pre-launch-checklist.md @@ -58,9 +58,10 @@ permalink: /pre-launch-checklist/ - Install [talk-plugin-rich-text](/talk/plugin/talk-plugin-rich-text) -- [ ] Do you want to display comment counts? - - Use the GraphQL [CommentCountQuery](https://docs.coralproject.net/talk/api/graphql/#CommentCountQuery) - - Install [talk-plugin-deep-reply-count](/talk/plugin/talk-plugin-deep-reply-count) if necessary. +- [ ] Do you want to display comment counts on your embed stream or on a homepage with dozens of articles? + - Install [talk-plugin-comment-count](https://github.com/coralproject/talk-plugin-comment-count) for summary counts on multiple articles + - Install [talk-plugin-deep-reply-count](/talk/plugin/talk-plugin-deep-reply-count) to add counts to the embed stream + - Or use the GraphQL [CommentCountQuery](https://docs.coralproject.net/talk/api/graphql/#CommentCountQuery) - [ ] Do you want to translate Talk to a different language? From ba31dbbdf917950fb0f909e81d3237252a85af3d Mon Sep 17 00:00:00 2001 From: immber Date: Tue, 8 Jan 2019 09:53:46 -0800 Subject: [PATCH 28/38] added logout wait time --- docs/source/07-02-troubleshooting-tips.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/07-02-troubleshooting-tips.md b/docs/source/07-02-troubleshooting-tips.md index 6d7304a83..0b4a7a682 100644 --- a/docs/source/07-02-troubleshooting-tips.md +++ b/docs/source/07-02-troubleshooting-tips.md @@ -38,3 +38,6 @@ If you're using `talk-plugin-auth`: * See if you can isolate if it's a particular group of users that are experiencing this issue, e.g. mods, admins, subscribers? Confirm they have the appropriate permissions to comment. * Note if this is a new issue that happened after an upgrade - did you read the [migration docs](/talk/migration/3/) and the [release notes](https://github.com/coralproject/talk/releases)? This might help you resolve the issue. * If you're still experiencing issues, log a [support ticket](mailto:support@coralproject.net) so we can help diagnose the issue + +If a user has been locked out due to too many failed login attempts: +* How long does the user have to wait before they will be allowed to login? 10 mins \ No newline at end of file From db5bf9a676e0f7240b47db8e79fa6eaadf50ae20 Mon Sep 17 00:00:00 2001 From: immber Date: Tue, 8 Jan 2019 10:04:39 -0800 Subject: [PATCH 29/38] added twitter faq --- docs/source/integrating/authentication.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/integrating/authentication.md b/docs/source/integrating/authentication.md index 981ceb156..05f88449e 100644 --- a/docs/source/integrating/authentication.md +++ b/docs/source/integrating/authentication.md @@ -26,6 +26,9 @@ Plugins are available for the following 3rd party authentication providers: * [Facebook](/talk/plugin/talk-plugin-facebook-auth/) * [Google](/talk/plugin/talk-plugin-google-auth/) +_FAQ: Can I create a Twitter auth plugin?_ +This is currently not possible because Talk uses passport.js which does not support Twitter's oAuth2 requirements. + ## Custom Token Integration You can integrate Talk with any authentication service to enable single sign-on From 83819df922f4fb6690a39d778cdf1002e2a2ae96 Mon Sep 17 00:00:00 2001 From: immber Date: Tue, 8 Jan 2019 13:27:08 -0800 Subject: [PATCH 30/38] added talk-plugin-comment-count to plugins directory --- docs/source/_data/plugins.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/source/_data/plugins.yml b/docs/source/_data/plugins.yml index 0e09de210..3c08715fe 100644 --- a/docs/source/_data/plugins.yml +++ b/docs/source/_data/plugins.yml @@ -146,3 +146,8 @@ tags: - default - sorting +- name: talk-plugin-comment-count + description: This plugin enables adding comment counts to Talk’s embed or in other locations on your site. + link: https://github.com/coralproject/talk-plugin-comment-count + tags: + - counts From c98d227411b16c14767d9530176538e14b6c14c9 Mon Sep 17 00:00:00 2001 From: immber Date: Tue, 8 Jan 2019 15:12:44 -0800 Subject: [PATCH 31/38] updated notifications page --- docs/source/integrating/notifications.md | 86 ++++++++++++++++++------ 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/docs/source/integrating/notifications.md b/docs/source/integrating/notifications.md index a5f625083..7ee9d0834 100644 --- a/docs/source/integrating/notifications.md +++ b/docs/source/integrating/notifications.md @@ -3,22 +3,13 @@ title: Notifications permalink: /integrating/notifications/ --- -Talk currently supports 3 types of email notifications. +There are several plugins included with Talk that once enabled will control how and when Talk sends emails to users based on user activity. Only basic user profile notifications are enabled by default. - -1. When someone replies to my comment -2. When a staff member replies to my comment -3. When my comment gets featured - -Talk support 3 options for notification frequency: immediately, hourly or daily. Commenters can also opt-out of email notifications. Notifications are set to OFF by default. - -Commenters cannot enable notifications until they have verified their email. - -Note: Notifications are not currently supported for users that sign-up via Facebook or Google auth, or don't have an email attached to their account for any other reason. +_NOTE: Notifications are only supported for users that have an email address in Talk! If you are using authenticate via Facebook, Google, or SSO and you want to persist the user’s email, you will also need to enable `talk-plugin-local-auth` ([See Authentication](/talk/integrating/authentication/))_ ### Configuring SMTP -You must setup SMTP to use notifications. The following ENV variables must be set: +You must setup SMTP to send email notifications. The following ENV variables must be set: ``` TALK_SMTP_FROM_ADDRESS=email@email.com @@ -28,28 +19,72 @@ TALK_SMTP_HOST=smtp.domain.net TALK_SMTP_PORT=2525 ``` -### Enabling Notifications +See our documentation on [setting env variables](/talk/advanced-configuration/#talk-smtp-from-address) for reference. -Enabling the `talk-plugin-notifications` creates a NotificationManager that creates and manages events send from the event emitter that is linked to the Graph API PubSub system. +When running Talk in production we recommend using a 3rd party mail service provider like SendGrid or MailGun. -Adding the `talk-plugin-notifications` plugin will also enable the `notifications` plugin hook. Any plugin that registers before the `talk-plugin-notifications` plugin will get picked up by. +If you are having difficulty with your SMTP settings you can add `DEBUG=talk:jobs:mailer` to your .env to see additional logs from the mailer service. -See https://github.com/coralproject/talk/blob/8b669a31c551a042f0f079d8cfc16825673eb8f0/plugins/talk-plugin-notifications-reply/index.js for an example. +All notifications require SMTP settings to be correctly configured first, then enable the corresponding plugin, and configure any settings in the Talk Admin. If SMTP is not enabled, it will log to the server console that some variables were not provided. -### Notification Categories +### Notification Types & Plugins -Talk currently supports the following Notifications options out of the box: +In addition to the core notifications included with Talk, some plugins add features that are supported by and will add additional types of email notifications. Commenters can opt-out of most email notifications, and comment activity notifications are set to OFF by default. Commenters cannot enable notifications until they have verified their email. -`talk-plugin-notifications-category-reply` -`talk-plugin-notifications-category-staff-reply` -`talk-plugin-notifications-category-featured` +You can see a list of all the plugins related to notifications by visiting: +https://docs.coralproject.net/talk/plugins-directory/?q=notifications + +#### Type: User Profile Notifications (Included by Talk core) + +* When user registers, sends email confirmation and verification +* When user requests password reset +* When user changes username, sends confirmation +* When a user is banned or suspended + +#### Type: GDPR Notifications (optional) +`talk-plugin-profile-data:` +* When my comment history is ready for download (only one link can be generated every 7 days, and the link is valid for 24 hours) + +`talk-plugin-local-auth:` +* When user changes their email address +* When a user adds a new email address + +#### Type: Comment Activity Notifications (optional) +Talk support 3 options for notification frequency for this type of notification: +* immediately +* hourly +* daily + +`talk-plugin-notifications:` +* Enables notifications configuration (required for all comment activity notifications below) + +`talk-plugin-notifications-category-reply:` +* When someone replies to my comment + +`talk-plugin-notifications-category-staff-reply:` +* When a staff member replies to my comment + +`talk-plugin-notifications-category-featured:` +* When my comment gets featured ### Notification Digests +Notification digests are enabled by enabling the corresponding plugin, otherwise comment activity notifications are sent immediately. +* `talk-plugin-notifications-digest-daily` +* `talk-plugin-notifications-digest-hourly` + Talk supports hourly and daily digests out the box, if you would like to create your own, refer to the below: https://github.com/coralproject/talk/blob/9cc9969320dca47bb0f8f81e8d944ae4d19e548b/plugins/talk-plugin-notifications/server/connect.js#L69-L102 + +### Customizing Notifications + +Enabling the `talk-plugin-notifications` creates a NotificationManager that creates and manages events send from the event emitter that is linked to the Graph API PubSub system. This allows the instance that received the mutation to also fire off a notification job that can be handled. It also enabels the `notifications` plugin hook. Any plugin that registers after the `talk-plugin-notifications` can export the notifications plugin to reference it. + +See https://github.com/coralproject/talk/blob/8b669a31c551a042f0f079d8cfc16825673eb8f0/plugins/talk-plugin-notifications-reply/index.js for an example. + + ### Connect API This exposes the `graph/connectors.js` via the `connect` hook. @@ -67,3 +102,12 @@ See https://github.com/coralproject/talk/blob/90290cfa2de88e62f687e1ed0235ba6dfe ### Email Templates Email templates are text based and support translations. If you would like to create a new email template, you can register it via the Connect API, see https://github.com/coralproject/talk/blob/8b669a31c551a042f0f079d8cfc16825673eb8f0/plugins/talk-plugin-notifications/server/connect.js#L12-L28### + +Any email template registered with the same name as another template will replace the existing template for that type of email. _NOTE: that also means that the template data sent to each email template will __not__ change, so bear that in mind when designing templates that you may not have rich access to data._ + +An example of this is with the `talk-plugin-notifications-category-featured` plugin: + +Notification translation is located: https://github.com/coralproject/talk/blob/dd0601a80132d2849c53ef7eaf12ff382f3920b9/plugins/talk-plugin-notifications-category-featured/translations.yml#L13 + +Where the template content is provided: https://github.com/coralproject/talk/blob/dd0601a80132d2849c53ef7eaf12ff382f3920b9/plugins/talk-plugin-notifications-category-featured/index.js#L79 + From b0b5807c8b98637cdf277ffa21deec4af930dda8 Mon Sep 17 00:00:00 2001 From: immber Date: Tue, 8 Jan 2019 16:39:06 -0800 Subject: [PATCH 32/38] added scaling talk --- docs/source/01-04-planning-architecture.md | 35 +++++++++++++++++++++ docs/source/images/ServerArch.png | Bin 0 -> 27124 bytes 2 files changed, 35 insertions(+) create mode 100644 docs/source/images/ServerArch.png diff --git a/docs/source/01-04-planning-architecture.md b/docs/source/01-04-planning-architecture.md index d11ca4ac2..de1cfe803 100644 --- a/docs/source/01-04-planning-architecture.md +++ b/docs/source/01-04-planning-architecture.md @@ -19,3 +19,38 @@ Application servers: c4.xlarge (16 VM nginx + Talk VM machine pairs) Mongo nodes: 3x c3.medium (large db cluster, 1 master, 2 read replicas) If you need help with Talk performance or want custom scaling help or recommendations, let us know by logging a ticket and one of our engineers will get in touch with you: https://support.coralproject.net + +## How to Scale Talk Components +### Scaling the Talk Application + +In addition to scaling by adding additional app servers, Talk as a server component can flex to various roles. Depending on the desired configuration the roles can be split up to ensure high availability, and best matching to underlying host resources. + +There are three components to the Talk application that can be served independently or in combination on a single thread: API Server, WebSockets, and Jobs + +![ServerArchitectureDiagram](/talk/images/ServerArch.png) + +In the diagram we see the difference between a Typical configuration (which just adds additional Talk application instances) vs the Split configuration where different Talk components could be spread across different machine resources to optimize infrastructure utilization. +See [Serving the Application](/talk/configuration-cli-tools/#serving-the-application) + +### Scaling Redis + +Redis serves as a general cache and pub/sub broker. We treat all the data stored in Redis as ephemeral, so using as a cache serves us well for Talk to synchronize expensive query caches. It also serves as our pub/sub broker for use with live updates as propagated through the GraphQL subscription system. For this reason it is not recommended to implement multiple instances of Redis. + +### Scaling MongoDB + +MongoDB is treated as our general store for persisted data. Talk supports the most common strategies for scaling MongoDB instances including replicas and/or sharding. Depending on your specific data use cases, refer to MongoDBs documentation for more information about scaling https://www.mongodb.com/mongodb-scale. + +### Load Balancer +While this subject lives outside the Talk ecosystem, it is critical for application delivery. For websockets to work correctly, a load balancer must be selected that can support long lived connections that are required for websockets to work. + +## Running Talk in Production + +When you are ready to launch your production instance of Talk update your NODE_ENV environment variable from `development` to `production` mode. + +Then launch talk with `yarn start` or with the command `NODE_ENV=production ./bin/cli-serve -j -w` + + + + + + diff --git a/docs/source/images/ServerArch.png b/docs/source/images/ServerArch.png new file mode 100644 index 0000000000000000000000000000000000000000..aed5ffccaba6082506f1ba65ff68ff075485d0b0 GIT binary patch literal 27124 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 literal 0 HcmV?d00001 From 83379b58a7102abd7815707ba492160342ef488b Mon Sep 17 00:00:00 2001 From: immber Date: Tue, 8 Jan 2019 16:46:49 -0800 Subject: [PATCH 33/38] em that can not be opted out of --- docs/source/integrating/notifications.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/integrating/notifications.md b/docs/source/integrating/notifications.md index 7ee9d0834..04fe8f59f 100644 --- a/docs/source/integrating/notifications.md +++ b/docs/source/integrating/notifications.md @@ -41,6 +41,8 @@ https://docs.coralproject.net/talk/plugins-directory/?q=notifications * When user changes username, sends confirmation * When a user is banned or suspended +_NOTE: Users can not opt-out of User Profile Notifications_ + #### Type: GDPR Notifications (optional) `talk-plugin-profile-data:` * When my comment history is ready for download (only one link can be generated every 7 days, and the link is valid for 24 hours) From 8f54c1d3c3c043b9b8732dc2647e7d6a4126ffd5 Mon Sep 17 00:00:00 2001 From: immber Date: Wed, 9 Jan 2019 12:38:33 -0800 Subject: [PATCH 34/38] fixed md typo --- docs/source/plugins/overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/plugins/overview.md b/docs/source/plugins/overview.md index 1f734edeb..b4e1f41d5 100644 --- a/docs/source/plugins/overview.md +++ b/docs/source/plugins/overview.md @@ -67,9 +67,9 @@ External plugins can be resolved by running: This achieves two things: 1. It will traverse into local plugin folders and install their dependencies. - _Note that if the plugin is already installed and available in the + __Note that if the plugin is already installed and available in the node_modules folder, it will not be fetched again unless there is a version - mismatch._ This will result in the project `package.json` and `yarn.lock` + mismatch.__ This will result in the project `package.json` and `yarn.lock` files to be modified, this is normal as this ensures that repeated deployments (with the same config) will have the same config, these changes should not be committed to source control. From 76ef0f7d521069aa3b5deab55229a06ce51cd5cd Mon Sep 17 00:00:00 2001 From: immber Date: Thu, 10 Jan 2019 10:55:20 -0800 Subject: [PATCH 35/38] pulled community link from readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index dd04b096f..72207c1f3 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,6 @@ The current recommended release version is v4.5.0. ^4.5 (and all future even-num - [Talk Product Roadmap](https://www.pivotaltracker.com/n/projects/1863625) - [Our Blog](https://blog.coralproject.net/) -- [Community Forums](https://community.coralproject.net/) - [Community Guides for Journalism](https://guides.coralproject.net/) - [More About Us](https://coralproject.net/) From f69a9c826d1a1bf04441e6f881b226a34e3fce84 Mon Sep 17 00:00:00 2001 From: immber Date: Thu, 10 Jan 2019 17:04:22 -0800 Subject: [PATCH 36/38] removed link to community from faq --- docs/source/07-01-faq.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/source/07-01-faq.md b/docs/source/07-01-faq.md index 8f34adbf1..f3bf92396 100644 --- a/docs/source/07-01-faq.md +++ b/docs/source/07-01-faq.md @@ -11,8 +11,6 @@ To log a bug or request a feature, submit a Support ticket ([support@coralprojec You can also request help on Github by [submitting an issue](https://github.com/coralproject/talk/issues). This also increases your chances of having someone from the community respond to help. -And you can also search our [Coral Community](https://community.coralproject.net) to see if your issue has been solved, or to get tips from the community. - ## How can our dev team contribute to Talk? We are lucky to work with newsroom dev teams and individual contributors who span the world, and come from newsrooms of all sizes. You can read our [Contribution Guide](https://github.com/coralproject/talk/blob/master/CONTRIBUTING.md) to get started, but feel free to reach out to us via Github too. From acc83e27ce907f15596535f788d2feacdfd4af22 Mon Sep 17 00:00:00 2001 From: immber Date: Mon, 14 Jan 2019 10:37:36 -0800 Subject: [PATCH 37/38] added TALK_CONCURRENCY to adv config --- docs/source/01-04-planning-architecture.md | 2 ++ docs/source/02-02-advanced-configuration.md | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/docs/source/01-04-planning-architecture.md b/docs/source/01-04-planning-architecture.md index de1cfe803..602222b8f 100644 --- a/docs/source/01-04-planning-architecture.md +++ b/docs/source/01-04-planning-architecture.md @@ -49,6 +49,8 @@ When you are ready to launch your production instance of Talk update your NODE_E Then launch talk with `yarn start` or with the command `NODE_ENV=production ./bin/cli-serve -j -w` +By default Talk will run on a single thread, but you can also run multiple Talk threads on a single application instance by setting the environment variable `TALK_CONCURRENCY`. [See Advanced Configuration](/talk/advanced-configuration/#talk-concurrency) + diff --git a/docs/source/02-02-advanced-configuration.md b/docs/source/02-02-advanced-configuration.md index 49769be0b..1d12d2b47 100644 --- a/docs/source/02-02-advanced-configuration.md +++ b/docs/source/02-02-advanced-configuration.md @@ -23,6 +23,10 @@ otherwise the application will fail to start. Configure the duration for which comment counts are cached for, parsed by [ms](https://www.npmjs.com/package/ms). (Default `1hr`) +## TALK_CONCURRENCY + +This environment variable allows multiple worker processes to be spawned to handle traffic. Defaults to 1 if not set. + ## TALK_DEFAULT_LANG This is a **Build Variable** and must be consumed during build. If using the From df5e863cc4eca6ceab10e6578cde9feb291cda03 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Mon, 14 Jan 2019 13:45:28 -0800 Subject: [PATCH 38/38] updated default phrasing to be consistent Co-Authored-By: immber --- docs/source/02-02-advanced-configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/02-02-advanced-configuration.md b/docs/source/02-02-advanced-configuration.md index 1d12d2b47..1a60ac98b 100644 --- a/docs/source/02-02-advanced-configuration.md +++ b/docs/source/02-02-advanced-configuration.md @@ -25,7 +25,7 @@ Configure the duration for which comment counts are cached for, parsed by ## TALK_CONCURRENCY -This environment variable allows multiple worker processes to be spawned to handle traffic. Defaults to 1 if not set. +This environment variable allows multiple worker processes to be spawned to handle traffic. (Default `1`) ## TALK_DEFAULT_LANG