Merge branch 'slots-debug' of github.com:coralproject/talk into slots-debug

* 'slots-debug' of github.com:coralproject/talk: (78 commits)
  added translations
  lint
  improved db query support, added tests
  added .vscode to gitignore
  Disallow logout from unauthenticated requests
  parse env json the same as the rest, with hjson
  Slack plugin fix
  disabled firefox local integration tests :(
  re-enabled headless support
  added logs to artifacts
  disable headless tests, run with full browsers
  applied fix to allow local run with firefox
  store test results as artifacts every time
  replaced circleci image with ours temp
  Update Comment.js
  Update UserDetailComment.js
  Update Comment.js
  Update UserDetailComment.js
  Remove curly quote
  Update sidebar
  ...
This commit is contained in:
okbel
2018-03-14 23:22:24 -03:00
227 changed files with 5039 additions and 1337 deletions
+34 -26
View File
@@ -16,7 +16,9 @@ integration_job: &integration_job
environment:
<<: *integration_environment
docker:
- image: circleci/node:8-browsers
# TODO: replace with node:8-browsers when build issues are resolved.
# - image: circleci/node:8-browsers
- image: coralproject/ci
- image: circleci/mongo:3
- image: circleci/redis:4-alpine
steps:
@@ -32,10 +34,14 @@ integration_job: &integration_job
- store_test_results:
when: always
path: /tmp/circleci-test-results
- store_artifacts:
when: always
path: /tmp/circleci-test-results
version: 2
jobs:
# npm_dependencies will install the dependencies used by all other steps.
# npm_dependencies will install the dependencies used by all other steps.
npm_dependencies:
<<: *job_defaults
steps:
@@ -56,7 +62,7 @@ jobs:
- persist_to_workspace:
root: .
paths: node_modules
# lint will perform file linting.
lint:
<<: *job_defaults
@@ -67,7 +73,7 @@ jobs:
- run:
name: Perform linting
command: yarn lint
# build_assets will build the static assets.
build_assets:
<<: *job_defaults
@@ -90,7 +96,7 @@ jobs:
- persist_to_workspace:
root: .
paths: dist
# test_unit will run the unit tests.
test_unit:
<<: *job_defaults
@@ -102,7 +108,7 @@ jobs:
- checkout
- attach_workspace:
at: ~/coralproject/talk
- run:
- run:
name: Setup the test results directory
command: mkdir -p /tmp/circleci-test-results
- run:
@@ -120,7 +126,7 @@ jobs:
- store_test_results:
when: always
path: /tmp/circleci-test-results
# test_integration_chrome_local will run the integration tests locally with
# chrome headless.
test_integration_chrome_local:
@@ -128,7 +134,7 @@ jobs:
environment:
<<: *integration_environment
E2E_BROWSERS: chrome
# test_integration_firefox_local will run the integration tests locally with
# firefox headless.
test_integration_firefox_local:
@@ -145,7 +151,7 @@ jobs:
<<: *integration_environment
BROWSERSTACK: true
E2E_BROWSERS: chrome
# test_integration_firefox will run the integration tests with firefox in
# browserstack.
test_integration_firefox:
@@ -154,7 +160,7 @@ jobs:
<<: *integration_environment
BROWSERSTACK: true
E2E_BROWSERS: firefox
# test_integration_edge will run the integration tests with edge in
# browserstack.
test_integration_edge:
@@ -163,7 +169,7 @@ jobs:
<<: *integration_environment
BROWSERSTACK: true
E2E_BROWSERS: edge
# test_integration_ie will run the integration tests with ie in
# browserstack.
test_integration_ie:
@@ -174,7 +180,7 @@ jobs:
E2E_BROWSERS: ie
# TODO: remove when more reliable
E2E_MAX_RETRIES: 1
# test_integration_safari will run the integration tests with safari in
# browserstack.
test_integration_safari:
@@ -185,7 +191,7 @@ jobs:
E2E_BROWSERS: safari
# TODO: remove when more reliable
E2E_MAX_RETRIES: 1
# deploy will deploy the application as a docker image.
deploy:
<<: *job_defaults
@@ -236,13 +242,14 @@ workflows:
requires:
- npm_dependencies
- test_integration_chrome_local:
<<: *filter_develop
requires:
- build_assets
- test_integration_firefox_local:
<<: *filter_develop
requires:
- build_assets
# TODO: uncomment when more reliable
# - test_integration_firefox_local:
# <<: *filter_develop
# requires:
# - build_assets
deploy-tagged:
jobs:
- npm_dependencies:
@@ -271,14 +278,15 @@ workflows:
<<: *filter_deploy
requires:
- build_assets
- test_integration_ie:
<<: *filter_deploy
requires:
- build_assets
- test_integration_safari:
<<: *filter_deploy
requires:
- build_assets
# TODO: uncomment when more reliable
# - test_integration_ie:
# <<: *filter_deploy
# requires:
# - build_assets
# - test_integration_safari:
# <<: *filter_deploy
# requires:
# - build_assets
- deploy:
<<: *filter_deploy
requires:
@@ -289,4 +297,4 @@ workflows:
- test_integration_edge
# TODO: uncomment when more reliable
# - test_integration_ie
# - test_integration_safari
# - test_integration_safari
+1 -1
View File
@@ -23,7 +23,7 @@ if [[ "$BROWSERSTACK" == "true" && -n "$BROWSERSTACK_KEY" ]]; then
echo Testing on browserstack
node scripts/e2e.js --reports-folder "$REPORTS_FOLDER" --retries "$E2E_MAX_RETRIES" --timeout "$E2E_WAIT_FOR_TIMEOUT" --browsers "$E2E_BROWSERS" --browserstack
else
# When browserstack is not available test locally using chrome headless.
# When browserstack is not available test locally.
echo Testing locally
node scripts/e2e.js --reports-folder "$REPORTS_FOLDER" --retries "$E2E_MAX_RETRIES" --timeout "$E2E_WAIT_FOR_TIMEOUT" --browsers "$E2E_BROWSERS" --headless
fi
+1 -2
View File
@@ -1,6 +1,5 @@
**/*.html
dist
docs
node_modules
public
**/*.min.js
+2 -1
View File
@@ -14,6 +14,7 @@ client/coral-framework/graphql/introspection.json
*.swp
*.DS_STORE
.prettierrc.json
.vscode
coverage/
test/e2e/reports/
@@ -22,8 +23,8 @@ test/e2e/selenium-debug.log
browserstack.err
plugins.json
plugins/*
plugins/*
!plugins/talk-plugin-akismet
!plugins/talk-plugin-auth
!plugins/talk-plugin-author-menu
+3 -3
View File
@@ -54,12 +54,12 @@ We are looking for _documentarians_ to:
* take the lead in making sections, or the over all structure better.
Our documentation is stored in markdown files in the [docs](docs) directory. We
use Jekyll to provide our docs. To preview:
use [Hexo](https://hexo.io/) to provide our docs. To preview:
```shell
cd docs
bundle install
bundle exec jekyll serve
yarn
yarn start
```
Then visit http://127.0.0.1:4000/talk/.
+2 -2
View File
@@ -12,11 +12,11 @@ You're just one click away from trying Talk - all you need is a Heroku account a
## Technical Documentation
From getting up and running, to advanced configuration, to how to scale Talk, our [Talk Technical Docs](https://coralproject.github.io/talk/) have everything you need to know.
From getting up and running, to advanced configuration, to how to scale Talk, our [Talk Technical Docs](https://docs.coralproject.net/talk/) have everything you need to know.
## Product Guide
Learn more about Talk, including a deep dive into features for commenters and moderators, and FAQs in our [Talk Product Guide](https://coralproject.github.io/talk/how-talk-works).
Learn more about Talk, including a deep dive into features for commenters and moderators, and FAQs in our [Talk Product Guide](https:/docs.coralproject.net/talk/how-talk-works).
## Relevant Links
+7 -1
View File
@@ -10,6 +10,12 @@ const serve = require('../serve');
program
.option('-j, --jobs', 'enable job processing on this thread')
.option(
'--disabled-jobs <jobs>',
'disable jobs specified if the -j option is passed, specified as a comma separated list',
val => val.split(','),
[]
)
.option(
'-w, --websockets',
'enable the websocket (subscriptions) handler on this thread'
@@ -17,7 +23,7 @@ program
.parse(process.argv);
// Start serving.
serve({ jobs: program.jobs, websockets: program.websockets }).catch(err => {
serve(program).catch(err => {
console.error(err);
util.shutdown(1);
});
+49
View File
@@ -312,10 +312,59 @@ async function verifyUserEmail(userID, email) {
}
}
/**
* createUser will prompt the user for the user information when creating a
* local user.
*/
async function createUser() {
try {
const answers = await inquirer.prompt([
{
name: 'email',
message: 'Email',
},
{
name: 'username',
message: 'Username',
},
{
name: 'password',
message: 'Password',
type: 'password',
},
{
name: 'role',
message: 'Role',
type: 'list',
choices: USER_ROLES,
},
]);
const { email, username, password, role } = answers;
// Create the user.
const user = await UsersService.createLocalUser(email, password, username);
// Set the role.
await UsersService.setRole(user.id, role);
console.log(`Created User[${user.id}]`);
util.shutdown(0);
} catch (err) {
console.error(err);
util.shutdown(1);
}
}
//==============================================================================
// Setting up the program command line arguments.
//==============================================================================
program
.command('create')
.description('creates a local user')
.action(createUser);
program
.command('delete <userID>')
.description('delete a user')
@@ -12,7 +12,7 @@ class MyPluginComponent extends React.Component {
<small>
To read more about plugins check{' '}
<a href="https://coralproject.github.io/talk/plugins-client.html">
<a href="https://docs.coralproject.net/talk/plugins-client">
our docs and guides!
</a>
</small>
+1 -1
View File
@@ -13,7 +13,7 @@
};
```
To read more info on how to build client plugins. Please, go to: https://coralproject.github.io/talk/plugins-client.html
To read more info on how to build client plugins. Please, go to: https://docs.coralproject.net/talk/plugins-client
*/
import MyPluginComponent from './components/MyPluginComponent';
+5 -8
View File
@@ -2,6 +2,7 @@
require('../services/env');
const debug = require('debug')('talk:util');
const { uniq } = require('lodash');
const util = (module.exports = {});
@@ -23,11 +24,7 @@ util.shutdown = (defaultCode = 0, signal = null) => {
debug(`${util.toshutdown.length} jobs now being called`);
Promise.all(
util.toshutdown
.map(func => (func ? func(signal) : null))
.filter(func => func)
)
Promise.all(util.toshutdown.map(func => (func ? func(signal) : null)))
.then(() => {
debug('Shutdown complete, now exiting');
process.exit(defaultCode);
@@ -49,14 +46,14 @@ util.onshutdown = jobs => {
debug(`${jobs.length} jobs registered to be called during shutdown`);
// Add the new jobs to shutdown to the object reference.
util.toshutdown = util.toshutdown.concat(jobs);
util.toshutdown = uniq(util.toshutdown.concat(jobs));
};
// Attach to the SIGTERM + SIGINT handles to ensure a clean shutdown in the
// event that we have an external event. SIGUSR2 is called when the app is asked
// to be 'killed', same procedure here.
process.on('SIGTERM', () => util.shutdown(0, 'SIGTERM'));
process.on('SIGINT', () => util.shutdown(0, 'SIGINT'));
process.once('SIGTERM', () => util.shutdown(0, 'SIGTERM'));
process.once('SIGINT', () => util.shutdown(0, 'SIGINT'));
process.once('SIGUSR2', () => util.shutdown(0, 'SIGUSR2'));
// Makes the script crash on unhandled rejections instead of silently
@@ -76,7 +76,8 @@ class UserDetailComment extends React.Component {
</div>
</div>
<div className={styles.story}>
Story: {comment.asset.title}
{t('common.story')}:{' '}
{comment.asset.title ? comment.asset.title : comment.asset.url}
{
<Link to={`/admin/moderate/${comment.asset.id}`}>
{t('modqueue.moderate')}
@@ -109,6 +110,7 @@ class UserDetailComment extends React.Component {
<div className={styles.sideActions}>
<IfHasLink text={comment.body}>
<span className={styles.hasLinks}>
{/* TODO: translate string */}
<Icon name="error_outline" /> Contains Link
</span>
</IfHasLink>
@@ -122,7 +122,8 @@ class Comment extends React.Component {
</div>
<div className={styles.moderateArticle}>
Story: {comment.asset.title}
{t('common.story')}:{' '}
{comment.asset.title ? comment.asset.title : comment.asset.url}
{!currentAsset && (
<Link to={`/admin/moderate/${comment.asset.id}`}>
{t('modqueue.moderate')}
@@ -156,6 +157,7 @@ class Comment extends React.Component {
<div className={styles.sideActions}>
<IfHasLink text={comment.body}>
<span className={styles.hasLinks}>
{/* TODO: translate string */}
<Icon name="error_outline" /> Contains Link
</span>
</IfHasLink>
+5
View File
@@ -4,6 +4,7 @@ import get from 'lodash/get';
import merge from 'lodash/merge';
import moment from 'moment';
import 'moment/locale/ar';
import 'moment/locale/da';
import 'moment/locale/de';
import 'moment/locale/es';
@@ -12,6 +13,7 @@ import 'moment/locale/pt-br';
import { createStorage } from 'coral-framework/services/storage';
import arTA from 'timeago.js/locales/ar';
import daTA from 'timeago.js/locales/da';
import deTA from 'timeago.js/locales/de';
import esTA from 'timeago.js/locales/es';
@@ -21,6 +23,7 @@ import zh_CNTA from 'timeago.js/locales/zh_CN';
import zh_TWTA from 'timeago.js/locales/zh_TW';
import nl from 'timeago.js/locales/nl';
import ar from '../../../locales/ar.yml';
import en from '../../../locales/en.yml';
import da from '../../../locales/da.yml';
import de from '../../../locales/de.yml';
@@ -33,6 +36,7 @@ import nl_NL from '../../../locales/nl_NL.yml';
const defaultLanguage = process.env.TALK_DEFAULT_LANG;
const translations = {
...ar,
...en,
...da,
...de,
@@ -88,6 +92,7 @@ export function setupTranslations() {
lang = defaultLanguage;
}
ta.register('ar', arTA);
ta.register('es', esTA);
ta.register('da', daTA);
ta.register('de', deTA);
+5 -3
View File
@@ -1,3 +1,5 @@
_site
.sass-cache
.jekyll-metadata
public/*
!public/_redirects
.deploy*/
db.json
*.log
-24
View File
@@ -1,24 +0,0 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "3.5.2"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-seo-tag", "~> 2.1"
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
-55
View File
@@ -1,55 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
colorator (1.1.0)
ffi (1.9.18)
forwardable-extended (2.6.0)
jekyll (3.5.2)
addressable (~> 2.4)
colorator (~> 1.0)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 1.1)
kramdown (~> 1.3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (~> 1.7)
safe_yaml (~> 1.0)
jekyll-sass-converter (1.5.0)
sass (~> 3.4)
jekyll-seo-tag (2.3.0)
jekyll (~> 3.3)
jekyll-watch (1.5.0)
listen (~> 3.0, < 3.1)
kramdown (1.15.0)
liquid (4.0.0)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
mercenary (0.3.6)
pathutil (0.14.0)
forwardable-extended (~> 2.6)
public_suffix (3.0.0)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rouge (1.11.1)
safe_yaml (1.0.4)
sass (3.5.1)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
PLATFORMS
ruby
DEPENDENCIES
jekyll (= 3.5.2)
jekyll-seo-tag (~> 2.1)
tzinfo-data
BUNDLED WITH
1.15.4
+162 -59
View File
@@ -1,69 +1,172 @@
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
# Hexo Configuration
## Docs: https://hexo.io/docs/configuration.html
## Source: https://github.com/hexojs/hexo/
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
# Site
title: Talk Documentation
description: > # this means to ignore newlines until "baseurl:"
subtitle:
description: >
Documentation and guides for Talk from The Coral Project.
baseurl: "/talk" # the subpath of your site, e.g. /blog
url: "https://coralproject.github.io" # the base hostname & protocol for your site, e.g. http://example.com
google_analytics: UA-73335347-5
versions:
node: 8+
yarn: 1.3.2+
mongodb: 3.2+
redis: 3.2.5+
docker: 17.06.2+
docker_compose: 1.14.0+
author:
language: en
timezone:
# Build settings
markdown: kramdown
kramdown:
syntax_highlighter_opts:
disable : true
# URL
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
url: https://docs.coralproject.net/talk/
root: /talk/
permalink: :permalink/
permalink_defaults:
plugins:
- jekyll-seo-tag
# Directory
source_dir: source
public_dir: public/talk
tag_dir: tags
archive_dir: archives
category_dir: categories
code_dir: downloads/code
i18n_dir: :lang
skip_render:
# Exclude from processing.
# The following items will not be processed, by default. Create a custom list
# to override the default setting.
# exclude:
# - Gemfile
# - Gemfile.lock
# - node_modules
# - vendor/bundle/
# - vendor/cache/
# - vendor/gems/
# - vendor/ruby/
# Writing
new_post_name: :title.md # File name of new posts
default_layout: doc
titlecase: false # Transform title into titlecase
external_link: true # Open external links in new tab
filename_case: 0
render_drafts: false
post_asset_folder: false
relative_link: false
future: true
highlight:
enable: false
# Home page setting
# path: Root path for your blogs index page. (default = '')
# per_page: Posts displayed per page. (0 = disable pagination)
# order_by: Posts order. (Order by date descending by default)
index_generator:
path: ''
# Sass/SCSS
sass:
sass_dir: _sass
style: compressed # http://sass-lang.com/documentation/file.SASS_REFERENCE.html#output_style
# Category & Tag
default_category: uncategorized
category_map:
tag_map:
# Collections
collections:
docs:
output: true
permalink: /:path/
# Date / Time format
## Hexo uses Moment.js to parse and display date
## You can customize the date format as defined in
## http://momentjs.com/docs/#/displaying/format/
date_format: YYYY-MM-DD
time_format: HH:mm:ss
# Defaults
defaults:
# _docs
- scope:
path: ""
type: docs
values:
layout: doc
# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: coral
# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type:
sidebar:
top:
- title: GitHub
url: https://github.com/coralproject/
- title: Docker
url: https://hub.docker.com/r/coralproject/
- title: Roadmap
url: https://www.pivotaltracker.com/n/projects/1863625
side:
- title: Installation
children:
- title: Talk Quickstart
url: /
- title: Installation from Docker
url: /installation-from-docker/
- title: Installation from Source
url: /installation-from-source/
- title: Planning your Talk Architecture
url: /planning-architecture/
- title: Configuration
children:
- title: Required Configuration
url: /configuration/
- title: Advanced Configuration
url: /advanced-configuration/
- title: Integrating
children:
- title: Authentication
url: /integrating/authentication/
- title: Configuring the Comment Stream
url: /integrating/configuring-comment-stream/
- title: Configuring the Admin
url: /integrating/configuring-admin/
- title: Notifications
url: /integrating/notifications/
- title: Event Tracking and Metrics
url: /integrating/event-tracking-metrics/
- title: Styling and CSS
url: /integrating/styling-css/
- title: Translations and i18n
url: /integrating/translations-i18n/
- title: Product Guide
children:
- title: How Talk Works
url: /how-talk-works/
- title: Commenter Features
url: /commenter-features/
- title: Moderator Features
url: /moderator-features/
- title: Trust
url: /trust/
- title: Toxic Comments
url: /toxic-comments/
- title: Configuring Talk
url: /configuring-talk/
- title: Plugins
children:
- title: Plugins Overview
url: /plugins/
- title: Plugin Directory
url: /plugins-directory/
- title: Plugin Recipes
url: /plugin-recipes/
- title: Tutorials
children:
- title: Creating a Basic Plugin
url: /building-basic-plugin/
- title: Customizing Plugins with Coral UI
url: /customizing-plugins-coral-ui/
- title: API
children:
- title: Server Plugins
url: /reference/server/
- title: GraphQL
url: /reference/graphql/
- title: Migrating
children:
- title: Migrating to v4.0.0
url: /migration/4/
- title: Migrating to v4.1.0
url: /migration/4.1/
- title: Contact
url: /contact/
marked:
gfm: true
pedantic: false
sanitize: false
tables: true
breaks: false
smartLists: true
smartypants: true
modifyAnchors: ''
autolink: true
node_sass:
outputStyle: compressed
precision: 5
sourceComments: false
-13
View File
@@ -1,13 +0,0 @@
items:
- title: GitHub release
img: https://img.shields.io/github/release/coralproject/talk.svg
link: https://github.com/coralproject/talk/releases
- title: ImageLayers Size
img: https://img.shields.io/imagelayers/image-size/coralproject/talk/latest.svg
link: https://hub.docker.com/r/coralproject/talk/
- title: Docker Pulls
img: https://img.shields.io/docker/pulls/coralproject/talk.svg
link: https://hub.docker.com/r/coralproject/talk/
- title: CircleCI
img: https://img.shields.io/circleci/project/github/coralproject/talk.svg
link: https://circleci.com/gh/coralproject/talk
-49
View File
@@ -1,49 +0,0 @@
items:
- title: Installation
children:
- title: Talk Quickstart
url: /
- title: Installation from Docker
url: /installation-from-docker/
- title: Installation from Source
url: /installation-from-source/
- title: Configuration
children:
- title: Required Configuration
url: /configuration/
- title: Advanced Configuration
url: /advanced-configuration/
- title: Product Guide
children:
- title: How Talk Works
url: /how-talk-works/
- title: Commenter Features
url: /commenter-features/
- title: Moderator Features
url: /moderator-features/
- title: Trust
url: /trust/
- title: Toxic Comments
url: /toxic-comments/
- title: Configuring Talk
url: /configuring-talk/
- title: Plugins
children:
- title: Plugins Overview
url: /plugins/
- title: Default Plugins
url: /default-plugins/
- title: Additional Plugins
url: /additional-plugins/
- title: Plugin Recipes
url: /plugin-recipes/
- title: FAQ
children:
- title: FAQ
url: /faq/
- title: Migrating
children:
- title: Migrating to v4.0.0
url: /migration/4/
- title: Migrating to v4.1.0
url: /migration/4.1/
-150
View File
@@ -1,150 +0,0 @@
---
title: Default Plugins
permalink: /default-plugins/
class: configuration
---
The default Talk plugins can be found in the `plugins.default.json` file
[here](https://github.com/coralproject/talk/blob/master/plugins.default.json).
Talk ships out of the box with these plugins enabled:
{% include toc.html %}
We ship [Additional Plugins]({{ "/additional-plugins/" | relative_url }}) with
Talk that are not enabled by default. You can enable these or disable these
default plugins by consulting the [Plugins Overview]({{ "/plugins/" | relative_url }})
page.
## talk-plugin-auth
Source: [plugins/talk-plugin-auth](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-auth){:target="_blank"}
Enables generic registration via an email address, a username, a password, and a
password confirmation. To sync Talk auth with your own auth systems, you can use
this plugin as a template.
## talk-plugin-facebook-auth
Source: [plugins/talk-plugin-auth](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-auth){:target="_blank"}
Requires: [talk-plugin-facebook-auth](#talk-plugin-facebook-auth){:.param}
Enables sign-in via Facebook via the server side passport middleware.
Configuration:
- [TALK_FACEBOOK_APP_ID]({{ "/configuration/#talk_facebook_app_id" | relative_url }}){:.param} (**required**) - See the existing documentation for the [TALK_FACEBOOK_APP_ID]({{ "/configuration/#talk_facebook_app_id" | relative_url }}){:.param}.
- [TALK_FACEBOOK_APP_SECRET]({{ "/configuration/#talk_facebook_app_secret" | relative_url }}){:.param} (**required**) - See the existing documentation for the [TALK_FACEBOOK_APP_SECRET]({{ "/configuration/#talk_facebook_app_secret" | relative_url }}){:.param}.
## talk-plugin-featured-comments
Source: [plugins/talk-plugin-featured-comments](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-featured-comments){:target="_blank"}
Enables the ability for Moderators to feature and un-feature comments via the
Stream and the Admin. Featured comments show in a first-place tab on the Stream
if there are any featured comments on that story.
## talk-plugin-respect
Source: [plugins/talk-plugin-respect](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-respect){:target="_blank"}
Enables a `respect` reaction button. Why a "respect" button, you ask?
[Read more here](https://mediaengagement.org/research/engagement-buttons/).
## talk-plugin-comment-content
Source: [plugins/talk-plugin-comment-content](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-comment-content){:target="_blank"}
Pluginizes the text of a comment to support custom treatment of this text. This
plugin currently parses the given text to see if it contains a link, and makes
them clickable.
## talk-plugin-ignore-user
Source: [plugins/talk-plugin-ignore-user](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-ignore-user){:target="_blank"}
Enables ability for users to ignore (or "mute") other users. If a user is
ignored, you will not see any of their comments. You can un-ignore a user via
the My Profile tab.
## talk-plugin-permalink
Source: [plugins/talk-plugin-permalink](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-permalink){:target="_blank"}
Enables a `Link` button that will provide a permalink to the comment that can be
shared with others.
## talk-plugin-viewing-options
Source: [plugins/talk-plugin-viewing-options](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-viewing-options){:target="_blank"}
Pluginizes the sorting/viewing options for a comment stream.
## talk-plugin-sort-newest
Source: [plugins/talk-plugin-sort-newest](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-sort-newest){:target="_blank"}
Requires: [talk-plugin-viewing-options](#talk-plugin-viewing-options){:.param}
Provides a sort for the newest comments first. This isn't necessarily required
as the default sort without options/plugins is newest first.
## talk-plugin-sort-oldest
Source: [plugins/talk-plugin-sort-oldest](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-sort-oldest){:target="_blank"}
Requires: [talk-plugin-viewing-options](#talk-plugin-viewing-options){:.param}
Provides a sort for the newest comments first.
## talk-plugin-sort-most-respected
Source: [plugins/talk-plugin-sort-most-respected](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-sort-most-respected){:target="_blank"}
Requires: [talk-plugin-viewing-options](#talk-plugin-viewing-options){:.param}, [talk-plugin-respect](#talk-plugin-respect){:.param}
Provides a sort for the comments with the most `respect` reactions first.
## talk-plugin-sort-most-replied
Source: [plugins/talk-plugin-sort-most-replied](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-sort-most-replied){:target="_blank"}
Requires: [talk-plugin-viewing-options](#talk-plugin-viewing-options){:.param}
Provides a sort for the comments with the most replies first.
## talk-plugin-offtopic
Source: [plugins/talk-plugin-offtopic](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-offtopic){:target="_blank"}
Allows the comment authors to tag their comment as `Off-Topic` which will add a
visible badge on the frontend to other users that their comment is off-topic.
## talk-plugin-author-menu
Source: [plugins/talk-plugin-author-menu](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-author-menu){:target="_blank"}
Pluginizes the author's name on hover.
## talk-plugin-member-since
Source: [plugins/talk-plugin-member-since](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-member-since){:target="_blank"}
Requires: [talk-plugin-author-menu](#talk-plugin-author-menu){:.param}
Displays the date that the user was created as a `Member Since ${created_at}`.
## talk-plugin-moderation-actions
Source: [plugins/talk-plugin-moderation-actions](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-moderation-actions){:target="_blank"}
Enables in-stream moderation so that Moderators can reject, approve comments,
as well as ban users, directly from the comment stream. When [talk-plugin-featured-comments](#talk-plugin-featured-comments){:.param} is enabled
## talk-plugin-flag-details
Source: [plugins/talk-plugin-flag-details](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-flag-details){:target="_blank"}
Pluginizes the Flag Details area of comments in the Moderation Queues to display
data. Some basic details are already included on flags by default.
-171
View File
@@ -1,171 +0,0 @@
---
title: Additional Plugins
permalink: /additional-plugins/
class: configuration
---
Talk ships with several plugins that aren't enabled by default:
{% include toc.html %}
These plugins can be enabled by consulting the
[Plugins Overview]({{ "/plugins/" | relative_url }}) page.
## talk-plugin-like
Source: [plugins/talk-plugin-like](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-like){:target="_blank"}
Enables a `like` reaction button.
## talk-plugin-sort-most-liked
Source: [plugins/talk-plugin-sort-most-liked](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-sort-most-liked){:target="_blank"}
Requires: [talk-plugin-viewing-options]({{ "/default-plugins/#talk-plugin-viewing-options" | relative_url }}){:.param}, [talk-plugin-like](#talk-plugin-like){:.param}
Provides a sort for the comments with the most `like` reactions first.
## talk-plugin-love
Source: [plugins/talk-plugin-love](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-love){:target="_blank"}
Enables a `love` reaction button.
## talk-plugin-sort-most-loved
Source: [plugins/talk-plugin-sort-most-loved](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-sort-most-loved){:target="_blank"}
Requires: [talk-plugin-viewing-options]({{ "/default-plugins/#talk-plugin-viewing-options" | relative_url }}){:.param}, [talk-plugin-love](#talk-plugin-love){:.param}
Provides a sort for the comments with the most `love` reactions first.
## talk-plugin-remember-sort
Source: [plugins/talk-plugin-remember-sort](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-remember-sort){:target="_blank"}
Requires: [talk-plugin-viewing-options]({{ "/default-plugins/#talk-plugin-viewing-options" | relative_url }}){:.param}
Enables saving a users last sort selection as they browse other articles.
## talk-plugin-deep-reply-count
Source: [plugins/talk-plugin-deep-reply-count](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-deep-reply-count){:target="_blank"}
Enables counting of comments to include replies via a new graph edge. Not
recommended for large installations as it will unreasonably reduce the query
efficiency to compute this number.
## talk-plugin-slack-notifications
Source: [plugins/talk-plugin-slack-notifications](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-slack-notifications){:target="_blank"}
Enables all new comments that are written to be posted to a Slack channel as
well. Configure an
[Incoming Webhook](https://api.slack.com/incoming-webhooks){:target="_blank"}
app and provide that url in the form of the `SLACK_WEBHOOK_URL`
detailed below.
*Warning: On high volume sites, this means every single comment will flow into
Slack, if this isn't what you want, be sure to use the provided plugin as a
recipe to further customize the behavior*.
Configuration:
- `SLACK_WEBHOOK_URL` (**required**) - The webhook url that will be
used to post new comments to.
## talk-plugin-toxic-comments
Source: [plugins/talk-plugin-toxic-comments](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-toxic-comments){:target="_blank"}
Using the [Perspective API](http://perspectiveapi.com/){:target="_blank"}, this
plugin will warn users and reject comments that exceed the predefined toxicity
threshold. For more information on what Toxic Comments are, check out the
[Toxic Comments]({{ "/toxic-comments/" | relative_url }}) documentation.
Configuration:
- `TALK_PERSPECTIVE_API_KEY` (**required**) - The API Key for Perspective. You
can register and get your own key at [http://perspectiveapi.com/](http://perspectiveapi.com/){:target="_blank"}.
- `TALK_TOXICITY_THRESHOLD` - If the comments toxicity exceeds this threshold,
the comment will be rejected. (Default `0.8`)
- `TALK_PERSPECTIVE_API_ENDPOINT` - API Endpoint for hitting the
perspective API. (Default `https://commentanalyzer.googleapis.com/v1alpha1`)
- `TALK_PERSPECTIVE_TIMEOUT` - The timeout for sending a comment to
be processed before it will skip the toxicity analysis, parsed by
[ms](https://www.npmjs.com/package/ms){:target="_blank"}. (Default `300ms`)
- `TALK_PERSPECTIVE_DO_NOT_STORE` - Whether the API is permitted to store comment and context from this request. Stored comments will be used for future research and community model building purposes to improve the API over time. (Default `true`) [Perspective API - Analize Comment Request](https://github.com/conversationai/perspectiveapi/blob/master/api_reference.md#analyzecomment-request){:target="_blank"}
## talk-plugin-subscriber
Source: [plugins/talk-plugin-subscriber](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-subscriber){:target="_blank"}
Enables a `Subscriber` badge to be added to comments where the author has the
`SUBSCRIBER` tag. This must match with a custom auth integration that adds the
tag to the users that are subscribed to the service.
## talk-plugin-akismet
Source: [plugins/talk-plugin-akismet](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-akismet){:target="_blank"}
Enables spam detection from [Akismet](https://akismet.com/). Comments will be passed to the Akismet API for spam detection. If a comment
is determined to be spam, it will prompt the user, indicating that the comment might be considered spam. If the user continues after this
point with the still spam-like comment, the comment will be reported as containing spam, and sent for moderator approval.
**Note: [Akismet](https://akismet.com/) is a premium service, charges may apply.**
Configuration:
- `TALK_AKISMET_API_KEY` (**required**) - The Akismet API key located on your account page.
- `TALK_AKISMET_SITE` (**required**) - The URL where you are embedding the comment stream on to provide context to Akismet. If you're hosting talk on https://talk.mynews.org/, and your news site is https://mynews.org/, then you should set this parameter to `https://mynews.org/`
## talk-plugin-notifications
Source: [plugins/talk-plugin-notifications](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-notifications){:target="_blank"}
Enables the Notification system for sending out enabled email notifications to
users when they interact with Talk. By itself, this plugin will not send
anything. You need to enable one of the `talk-plugin-notifications-category-*` plugins.
**Note that all `talk-plugin-notifications-*` plugins must be registered
*before* this plugin in order to work. For example:**
```js
{
"server": [
// ...
"talk-plugin-notifications-category-reply",
"talk-plugin-notifications",
// ...
]
}
```
{:.no-copy}
Configuration:
- `DISABLE_REQUIRE_EMAIL_VERIFICATIONS` - When `TRUE`, it will disable the verification email check before sending notifications for those emails. **Note that organizations implementing a custom authentication system _must_ disable this feature, as they don't use our integrated auth**. (Default `FALSE`).
### talk-plugin-notifications-category-reply
{:.param}
Source: [plugins/talk-plugin-notifications-category-reply](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-notifications-category-reply){:target="_blank"}
Replies made to each user will trigger an email to be sent with the notification
details if enabled.
### talk-plugin-notifications-category-featured
{:.param}
Source: [plugins/talk-plugin-notifications-category-featured](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-notifications-category-featured){:target="_blank"}
When a comment is featured (via the `talk-plugin-featured-comments` plugin), the
user will receive a notification email.
### talk-plugin-notifications-category-staff
{:.param}
Source: [plugins/talk-plugin-notifications-category-staff](https://github.com/coralproject/talk/tree/master/plugins/talk-plugin-notifications-category-staff){:target="_blank"}
Replies made to each user by a staff member will trigger an email to be sent
with the notification details if enabled.
-3
View File
@@ -1,3 +0,0 @@
{% for item in site.data.badges.items %}<a class="plain-link" target="_blank" title="{{ item.title }}" href="{{ item.link }}">
<img src="{{ item.img }}" alt="{{ item.title }}"/>
</a>{% endfor %}
-13
View File
@@ -1,13 +0,0 @@
In order for the demo to work, you must add
`{{ site.url | remove: "http://" | remove: "https://" | remove: "/" }}` to your
permitted domains list. You can do this by visiting
[http://127.0.0.1:3000/admin/configure](http://127.0.0.1:3000/admin/configure){:target="_blank"}
now and selecting *Tech Settings* from the sidebar.
Once you have added the domain of these docs, you can click the button below.
<div class="demo">
<button id="talk-demo-embed-button" type="button" class="btn btn-block btn-coral">Start Demo</button>
<div class="alert" role="alert"></div>
<div class="mount"></div>
</div>
-37
View File
@@ -1,37 +0,0 @@
# For details on the syntax of docker-compose.yml files, check out:
# https://docs.docker.com/compose/compose-file/compose-file-v2/
version: '2'
services:
talk:
image: coralproject/talk:latest
restart: always
ports:
- "3000:3000"
depends_on:
- mongo
- redis
environment:
- NODE_ENV=development # remove this line in production
- TALK_MONGO_URL=mongodb://mongo/talk
- TALK_REDIS_URL=redis://redis
- TALK_ROOT_URL=http://127.0.0.1:3000
- TALK_PORT=3000
- TALK_JWT_SECRET=password
- TALK_FACEBOOK_APP_ID=12345
- TALK_FACEBOOK_APP_SECRET=123abc
mongo:
image: mongo:latest
restart: always
volumes:
- mongo:/data/db
redis:
image: redis:latest
restart: always
volumes:
- redis:/data
volumes:
mongo:
external: false
redis:
external: false
-12
View File
@@ -1,12 +0,0 @@
<header class="header">
<form class="search d-flex align-items-center">
<input type="search" class="form-control" id="search-input" placeholder="Search documentation..." aria-label="Search for..." autocomplete="off">
<nav class="header__nav">
<a target="_blank" alt="Coral Project Github" href="https://github.com/coralproject/">Github</a>
<a target="_blank" alt="Coral Project Docker Hub" href="https://hub.docker.com/r/coralproject/">Docker</a>
<a target="_blank" alt="Coral Project Roadmap" href="https://www.pivotaltracker.com/n/projects/1863625">Roadmap</a>
<a target="_blank" alt="Coral Project Google Group" href="https://groups.google.com/forum/#!forum/coral-talk-users">Google Group</a>
<a href="#" alt="Toggle Sidebar" id="sidebar-toggle">{% include images/hamburger.svg %}</a>
</nav>
</form>
</header>
-5
View File
@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" class="hamburger" viewBox="0 0 32 32">
<rect x="0" y="3" width="32" height="5" rx="3" ry="3"/>
<rect x="0" y="14" width="32" height="5" rx="3" ry="3"/>
<rect x="0" y="25" width="32" height="5" rx="3" ry="3"/>
</svg>

Before

Width:  |  Height:  |  Size: 326 B

-30
View File
@@ -1,30 +0,0 @@
<aside class="sidebar">
<a class="brand" href="{{ "/" | relative_url }}">
<h2>
{% include images/logo.svg %}
<span>Talk</span>
</h2>
</a>
<ul class="sidebar__list">
{% for item in site.data.nav.items %}
<li class="sidebar__section{% for item in item.children %}{% if page.url == item.url %} active toggled{% endif %}{% endfor %}">
<a href="#" class="sidebar__header">{{ item.title }}</a>
<ul class="sidebar__links">
{% for item in item.children %}
<li class="{% if page.url == item.url %}active{% endif %}">
<a href="{% if page.url != item.url %}{{ item.url | relative_url }}{% else %}#{% endif %}">{{ item.title }}</a>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
<div class="notice">
<p>Don't see what you're looking for? We're upgrading the docs, check out our <a href="https://github.com/coralproject/talk/tree/ef49d9a3d2acc4d2fc03b00e0c872dfbc57f005a/docs/_docs" target="_blank" class="coral-link-invert">old docs</a>.</p>
<p><a href="https://coralproject.net/" class="coral-link-invert" target="_blank">The Coral Project</a> from Mozilla</p>
<a href="https://www.mozilla.org/" target="_blank" title="Mozilla"><figure class="mozilla" alt="Mozilla">{% include images/moz-logo-bw-rgb.svg %}</figure></a>
</div>
</aside>
<div class="sidebar__backdrop"></div>
-28
View File
@@ -1,28 +0,0 @@
<!DOCTYPE html>
<html lang="{{ page.lang | default: site.lang | default: "en" }}">
{% include head.html %}
<body>
<div>
<div>
{% include sidebar.html %}
<main class="content" role="main">
{% include header.html %}
{{ content }}
</main>
{% include footer.html %}
</div>
</div>
</body>
</html>
-11
View File
@@ -1,11 +0,0 @@
---
layout: default
---
<article{% if page.class %} class="{{ page.class }}"{% endif %}>
<a class="btn btn-sm btn-light float-right suggest-edits plain-link" href="https://github.com/coralproject/talk/edit/master/docs/{{ page.path }}" title="Suggest edits to this page">Suggest Edits</a>
<h1>{{ page.title }}</h1>
<hr/>
{{ content }}
</article>
-5
View File
@@ -1,5 +0,0 @@
---
# Only the main Sass file needs front matter (the dashes are enough)
---
@import "talk";
-143
View File
@@ -1,143 +0,0 @@
$(document).ready(function() {
// Setup the highlighting.
hljs.initHighlighting();
// Setup code copying.
$("pre:not(.no-copy)").each(function() {
var button = $("<button type=\"button\" class=\"copy-to-clipboard\" aria-hidden=\"true\">Copy</button>");
$(this).prepend(button);
});
// Setup the clipboard links.
var clipboard = new Clipboard(".copy-to-clipboard",{
text: function(t) {
return t.nextElementSibling.innerText
}
});
clipboard.on("success", function(target) {
target.clearSelection(),
target.trigger.textContent = "Copied to clipboard",
setTimeout(function() {
target.trigger.textContent = "Copy"
}, 2e3)
});
// Setup the menu controls.
$("a.sidebar__header").on("click", function(e) {
e.preventDefault();
$(".sidebar__section.toggled").removeClass("toggled");
$(this).parents(".sidebar__section").addClass("toggled");
});
$("#sidebar-toggle, .sidebar__backdrop").on("click", function(e) {
e.preventDefault();
$("body, .sidebar").toggleClass("sidebar--toggled");
});
// Setup header controls for the search bar.
$("#search-input").on("focus", function() {
$(".header").addClass("header--toggled");
});
$("#search-input").on("blur", function() {
$(".header").removeClass("header--toggled");
});
// Setup the search control.
docsearch({
apiKey: '259b9f08146e7407341fa04498544ad6',
indexName: 'coralproject',
inputSelector: '#search-input',
debug: false
});
if ($(".demo").length > 0) {
var embedScriptLoaded = false;
function loadEmbedScript(callback) {
if (!embedScriptLoaded) {
$.getScript({
url: "http://127.0.0.1:3000/embed.js",
dataType: "script",
})
.done(function() {
embedScriptLoaded = true;
callback();
})
.fail(function(err) {
callback(err);
});
}
return null;
}
var embed = null;
function loadEmbed() {
if (embedScriptLoaded && embed === null) {
// Unhide the mount.
$(".demo .mount").show();
var el = $(".demo .mount")[0];
embed = Coral.Talk.render(el, {talk: 'http://127.0.0.1:3000/'});
$(".demo .alert")
.show()
.html("Demo is running below from your local Talk installation running at <a href=\"http://127.0.0.1:3000/\" target=\"_blank\">http://127.0.0.1:3000/</a>. Go ahead and comment!")
.removeClass("alert-warning alert-info")
.addClass("alert-success");
$(".demo button")
.off("click")
.on("click", removeEmbed)
.text("Stop Demo");
}
}
function removeEmbed() {
if (embed !== null) {
embed.remove();
embed = null;
$(".demo .mount").hide();
$(".demo .alert").hide();
$(".demo button")
.off("click")
.text("Start Demo")
.on("click", loadEmbed);
}
}
function demoCycle(firstRun) {
loadEmbedScript(function(err) {
if (err) {
if (firstRun !== true) {
$(".demo .alert")
.show()
.html("Can't load your embed.js script from your local Talk installation running at <a href=\"http://127.0.0.1:3000/\" target=\"_blank\">http://127.0.0.1:3000/</a>, ensure the server is running and try again.")
.addClass("alert-warning");
}
return;
}
if (firstRun === true) {
$(".demo .alert")
.show()
.html("We've loaded your embed.js from your local Talk installation running at <a href=\"http://127.0.0.1:3000/\" target=\"_blank\">http://127.0.0.1:3000/</a>, click Start Demo to embed Talk on the page from your local instance.")
.removeClass("alert-warning")
.addClass("alert-info");
$(".demo button")
.off("click")
.text("Start Demo")
.on("click", loadEmbed);
} else {
$(".demo button").off("click");
loadEmbed();
}
});
}
// // Run the cycle now.
// demoCycle(true);
// Initially bind the loadEmbedScript handler. We'll replace this with the
// loadEmbed handler when the script is loaded.
$(".demo button").on("click", demoCycle);
}
});
+27
View File
@@ -0,0 +1,27 @@
{
"name": "hexo-site",
"version": "0.0.0",
"private": true,
"hexo": {
"version": "3.6.0"
},
"scripts": {
"start": "hexo serve",
"build": "hexo generate",
"develop-theme": "nodemon -x 'rm db.json; hexo serve' -w assets/ -w code/ -w source/ -w themes/ -w scripts/"
},
"dependencies": {
"cheerio": "^1.0.0-rc.2",
"common-tags": "^1.7.2",
"graphql-docs": "^0.2.0",
"hexo": "^3.6.0",
"hexo-generator-index": "^0.2.0",
"hexo-renderer-marked": "^0.3.0",
"hexo-renderer-sass": "^0.3.2",
"hexo-server": "^0.3.1",
"lunr": "^2.1.6"
},
"devDependencies": {
"nodemon": "^1.14.12"
}
}
+1
View File
@@ -0,0 +1 @@
/ /talk/
@@ -3,37 +3,35 @@ title: Talk Quickstart
permalink: /
---
{% include badges.html %}
Online comments are broken. Our open-source Talk tool rethinks how moderation,
comment display, and conversation function, creating the opportunity for safer,
smarter discussions around your work. Read more about our product features and
goals [here](https://coralproject.net/products/talk.html){:target="_blank"}. The
goals [here](https://coralproject.net/products/talk.html). The
documentation available here is pertaining to the technical details for
installing, configuring, and deploying Talk.
Talk is a [Node](https://nodejs.org/){:target="_blank"} application with
Talk is a [Node](https://nodejs.org/) application with
dependencies managed by
[Yarn](https://yarnpkg.com/en/docs/install){:target="_blank"} that connects to
[MongoDB](https://docs.mongodb.com/manual/installation/){:target="_blank"} and
[Redis](https://redis.io/topics/quickstart){:target="_blank"} databases in order
[Yarn](https://yarnpkg.com/en/docs/install) that connects to
[MongoDB](https://docs.mongodb.com/manual/installation/) and
[Redis](https://redis.io/topics/quickstart) databases in order
to persist data. The following versions are supported:
- Node {{ site.versions.node }}
- Yarn {{ site.versions.yarn }}
- MongoDB {{ site.versions.mongodb }}
- Redis {{ site.versions.redis }}
- Node 8+
- Yarn 1.3.2+
- MongoDB 3.2+
- Redis 3.2.5+
An optional dependency for Talk is
[Docker](https://www.docker.com/community-edition#/download){:target="_blank"}.
[Docker](https://www.docker.com/community-edition#/download).
It is used during [development](#development) to set up the database and can be
used to [install via Docker](#installation-from-docker). We have tested Talk
and this documentation with versions {{ site.versions.docker }}.
and this documentation with versions 17.06.2+.
Another optional dependency for Talk is
[Docker Compose](https://docs.docker.com/compose/install/){:target="_blank"}. It
[Docker Compose](https://docs.docker.com/compose/install/). It
can be used to setup your environment easily for testing. We have tested Talk
and this documentation with versions {{ site.versions.docker_compose }}.
and this documentation with versions 1.14.0+.
## Installation
@@ -44,12 +42,46 @@ provided docker image. The following is a `docker-compose.yml` file that can
be used to setup Talk:
```yml
{% include files/docker-compose.yml %}
# For details on the syntax of docker-compose.yml files, check out:
# https://docs.docker.com/compose/compose-file/compose-file-v2/
version: '2'
services:
talk:
image: coralproject/talk:latest
restart: always
ports:
- "3000:3000"
depends_on:
- mongo
- redis
environment:
- NODE_ENV=development # remove this line in production
- TALK_MONGO_URL=mongodb://mongo/talk
- TALK_REDIS_URL=redis://redis
- TALK_ROOT_URL=http://127.0.0.1:3000
- TALK_PORT=3000
- TALK_JWT_SECRET=password
mongo:
image: mongo:latest
restart: always
volumes:
- mongo:/data/db
redis:
image: redis:latest
restart: always
volumes:
- redis:/data
volumes:
mongo:
external: false
redis:
external: false
```
This is the bare minimum needed to run the demo, for more configuration
variables, check out the [Configuration]({{ "/configuration/" | relative_url }}) section.
{: .code-aside}
variables, check out the [Configuration](./configuration/) section.
And you can then start it with:
@@ -71,7 +103,7 @@ Creating redis_1 ... done
Creating talk_1 ...
Creating talk_1 ... done
```
{: .no-copy }
And when you run `docker-compose ps`, you should see something like:
@@ -82,7 +114,7 @@ mongo_1 docker-entrypoint.sh mongod Up 27017/tcp
redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
talk_1 yarn start Up 0.0.0.0:3000->3000/tcp
```
{: .no-copy }
Continue onto the [Running](#running) section for details on how to complete the
installation and get started using Talk.
@@ -107,8 +139,8 @@ yarn
yarn build
```
You can either setup the required databases by visiting the docs for [MongoDB](https://docs.mongodb.com/manual/installation/){:target="_blank"} and
[Redis](https://redis.io/topics/quickstart){:target="_blank"}, or using the following commands which will leverage Docker:
You can either setup the required databases by visiting the docs for [MongoDB](https://docs.mongodb.com/manual/installation/) and
[Redis](https://redis.io/topics/quickstart), or using the following commands which will leverage Docker:
```bash
docker run -p 127.0.0.1:6379:6379 -d redis
@@ -118,7 +150,7 @@ docker run -p 127.0.0.1:27017:27017 -d mongo
Didn't work? Sometimes you may already have a container running on these ports,
run `docker ps` to see what other containers you have running and running
`docker stop <id>` on those containers to stop them.
{: .code-aside}
_This documentation assumes that you will be running MongoDB on
`127.0.0.1:27017` and Redis on `127.0.0.1:6379`. The above Docker commands bind
@@ -140,9 +172,9 @@ TALK_FACEBOOK_APP_SECRET=A-Facebook-App-Secret
```
This is only the bare minimum needed to run the demo, for more configuration
variables, check out the [Configuration]({{ "/configuration/" | relative_url }}) section. Facebook login above
variables, check out the [Configuration](./configuration/) section. Facebook login above
will definitely not work unless you change those values as well.
{: .code-aside}
You can now start the application by running:
@@ -156,17 +188,17 @@ installation and get started using Talk.
## Running
You can now navigate to
[http://127.0.0.1:3000/admin/install](http://127.0.0.1:3000/admin/install){:target="_blank"}
[http://127.0.0.1:3000/admin/install](http://127.0.0.1:3000/admin/install)
and go through the admin installation. There you will be prompted to create your
first admin account, and specify the domain whitelist for domains that are
allowed to have the comment box on.
_During development, ensure you whitelist 127.0.0.1:3000 otherwise the
[http://127.0.0.1:3000/](http://127.0.0.1:3000/){:target="_blank"} page will not
[http://127.0.0.1:3000/](http://127.0.0.1:3000/) page will not
load._
Once you've completed the installation, you can visit
[http://127.0.0.1:3000/](http://127.0.0.1:3000/){:target="_blank"} where you can
[http://127.0.0.1:3000/](http://127.0.0.1:3000/) where you can
view our development area where we test out features in Talk where you can write
comments and see them in the admin interface where you can do moderation and
reconfigure the user experience.
@@ -178,7 +210,19 @@ Talk. To demonstrate what your own self-hosted copy of Talk can do, below
you'll find a demo that can be used to test the copy that is running now on your
machine.
{% include demo.html %}
In order for the demo to work, you must add
`https://docs.coralproject.net/` to your
permitted domains list. You can do this by visiting
[http://127.0.0.1:3000/admin/configure](http://127.0.0.1:3000/admin/configure)
now and selecting *Tech Settings* from the sidebar.
Once you have added the domain of these docs, you can click the button below.
<div class="demo">
<button id="talk-demo-embed-button" type="button" class="btn btn-block btn-coral">Start Demo</button>
<div class="alert" role="alert"></div>
<div class="mount"></div>
</div>
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
@@ -3,15 +3,13 @@ title: Installation from Docker
permalink: /installation-from-docker/
---
{% include badges.html %}
[Docker](https://www.docker.com/community-edition#/download){:target="_blank"} {{ site.versions.docker }} and
[Docker Compose](https://docs.docker.com/compose/install/){:target="_blank"} {{ site.versions.docker_compose }} are required
[Docker](https://www.docker.com/community-edition#/download) 17.06.2+ and
[Docker Compose](https://docs.docker.com/compose/install/) 1.14.0+ are required
to perform installation via Docker. This is the recommended way to deploy the
application when used in production.
Available as [coralproject/talk](https://hub.docker.com/r/coralproject/talk/){:target="_blank"} on
Docker Hub. [(latest/Dockerfile)](https://github.com/coralproject/talk/blob/master/Dockerfile){:target="_blank"}
Available as [coralproject/talk](https://hub.docker.com/r/coralproject/talk/) on
Docker Hub. [(latest/Dockerfile)](https://github.com/coralproject/talk/blob/master/Dockerfile)
Images are tagged using the following notation:
@@ -27,7 +25,7 @@ Images are tagged using the following notation:
extending Talk or are sure of a specific version you want to freeze.
We provide tags with `*-onbuild`
[(onbuild/Dockerfile)](https://github.com/coralproject/talk/blob/master/Dockerfile.onbuild){:target="_blank"}
[(onbuild/Dockerfile)](https://github.com/coralproject/talk/blob/master/Dockerfile.onbuild)
that can be used for easy plugin integration and acts as a customization
endpoint. To use this image tag, refer to the
[onbuild](#onbuild) section.
@@ -39,12 +37,46 @@ provided docker image. The following is a `docker-compose.yml` file that can
be used to setup Talk:
```yml
{% include files/docker-compose.yml %}
# For details on the syntax of docker-compose.yml files, check out:
# https://docs.docker.com/compose/compose-file/compose-file-v2/
version: '2'
services:
talk:
image: coralproject/talk:latest
restart: always
ports:
- "3000:3000"
depends_on:
- mongo
- redis
environment:
- NODE_ENV=development # remove this line in production
- TALK_MONGO_URL=mongodb://mongo/talk
- TALK_REDIS_URL=redis://redis
- TALK_ROOT_URL=http://127.0.0.1:3000
- TALK_PORT=3000
- TALK_JWT_SECRET=password
mongo:
image: mongo:latest
restart: always
volumes:
- mongo:/data/db
redis:
image: redis:latest
restart: always
volumes:
- redis:/data
volumes:
mongo:
external: false
redis:
external: false
```
This is the bare minimum needed to start Talk, for more configuration
variables, check out the [Configuration]({{ "/configuration/" | relative_url }}) section.
{: .code-aside}
variables, check out the [Configuration](./configuration/) section.
And you can then start it with:
@@ -66,7 +98,7 @@ Creating redis_1 ... done
Creating talk_1 ...
Creating talk_1 ... done
```
{: .no-copy }
And when you run `docker-compose ps`, you should see something like:
@@ -77,9 +109,9 @@ mongo_1 docker-entrypoint.sh mongod Up 27017/tcp
redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
talk_1 yarn start Up 0.0.0.0:3000->3000/tcp
```
{: .no-copy }
At this stage, you should refer to the [configuration]({{ "/configuration/" | relative_url }}) for
At this stage, you should refer to the [configuration](./configuration/) for
configuration variables that are specific to your installation.
## Onbuild
@@ -99,9 +131,9 @@ docker build -t my-awesome-talk-image --build-arg TALK_DEFAULT_LANG=es .
```
Don't forget to replace `my-awesome-talk-image` with your own image name, and
specify your build variables with the `--build-arg`. Refer to [Dockerfile.onbuild](https://github.com/coralproject/talk/blob/master/Dockerfile.onbuild){:target="_blank"} for the
specify your build variables with the `--build-arg`. Refer to [Dockerfile.onbuild](https://github.com/coralproject/talk/blob/master/Dockerfile.onbuild) for the
available build variables.
{: .code-aside}
This accomplishes a lot:
@@ -110,8 +142,8 @@ This accomplishes a lot:
2. Installs any new dependencies that were required by any new plugins.
3. Builds the new static bundles so that they are ready to serve when the image
is running.
4. Specifies a build time variable [TALK_DEFAULT_LANG]({{ "/advanced-configuration/#talk_default_lang" | relative_url }}){:.param}. Refer
to [Dockerfile.onbuild](https://github.com/coralproject/talk/blob/master/Dockerfile.onbuild){:target="_blank"} for the
4. Specifies a build time variable [TALK_DEFAULT_LANG](./advanced-configuration/#talk_default_lang). Refer
to [Dockerfile.onbuild](https://github.com/coralproject/talk/blob/master/Dockerfile.onbuild) for the
available build variables.
This means that you can create a repository for your organization that simply
@@ -3,15 +3,12 @@ title: Installation from Source
permalink: /installation-from-source/
---
{% include badges.html %}
To install Talk from Source, ensure that you have Node version
{{ site.versions.node }}. Installing via source is the recommended method when
developing as it give you the best tooling. We release versions using semantic
versioning, and do so to our
[Github Releases](https://github.com/coralproject/talk/releases){:target="_blank"}
page. There you can download archives of older versions or the latest release.
The examples following will download the latest code on our master branch.
To install Talk from Source, ensure that you have Node version 8+.
Installing via source is the recommended method when developing as it give you
the best tooling. We release versions using semantic versioning, and do so to
our [GitHub Releases](https://github.com/coralproject/talk/releases) page.
There you can download archives of older versions or the latest release. The
examples following will download the latest code on our master branch.
## Installing
@@ -32,8 +29,8 @@ yarn
yarn build
```
You can either setup the required databases by visiting the docs for [MongoDB](https://docs.mongodb.com/manual/installation/){:target="_blank"} and
[Redis](https://redis.io/topics/quickstart){:target="_blank"}, or using the following commands which will leverage Docker:
You can either setup the required databases by visiting the docs for [MongoDB](https://docs.mongodb.com/manual/installation/) and
[Redis](https://redis.io/topics/quickstart), or using the following commands which will leverage Docker:
```bash
docker run -p 127.0.0.1:6379:6379 -d redis
@@ -43,7 +40,7 @@ docker run -p 127.0.0.1:27017:27017 -d mongo
Didn't work? Sometimes you may already have a container running on these ports,
run `docker ps` to see what other containers you have running and running
`docker stop <id>` on those containers to stop them.
{: .code-aside}
_This documentation assumes that you will be running MongoDB on
`127.0.0.1:27017` and Redis on `127.0.0.1:6379`. The above Docker commands bind
@@ -65,10 +62,10 @@ TALK_FACEBOOK_APP_SECRET=A-Facebook-App-Secret
```
This is the bare minimum needed to start Talk, for more configuration
variables, check out the [Configuration]({{ "/configuration/" | relative_url }})
variables, check out the [Configuration](./configuration/)
section. Facebook login above will definitely not work unless you change those
values as well.
{: .code-aside}
You can now start the application by running:
@@ -76,5 +73,5 @@ You can now start the application by running:
yarn watch:server
```
At this stage, you should refer to the [configuration]({{ "/configuration/" | relative_url }}) for
configuration variables that are specific to your installation.
At this stage, you should refer to the [configuration](./configuration/) for
configuration variables that are specific to your installation.
@@ -0,0 +1,21 @@
---
title: Planning your Talk Architecture
permalink: /planning-architecture/
---
Talk is architected to be able to run on as little as 500MB of RAM. To do this however you will need to use the pre-compiled Docker container, as compiling the code and dependencies will cause a memory spike.
For the average small blog or newsroom, these are our recommended machines:
- **Digital Ocean**: ~$5/month for their 1GB droplet
- **Google Cloud**: ~$14/month for a g1 small
- **AWS**: ~$16/month for a t2small
From there, youre free to separate app servers and DB servers, and scale up as much as you need.
One larger newsrooms setup, as an example of Talk performing at scale, is:
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
@@ -2,22 +2,21 @@
title: Required Configuration
permalink: /configuration/
class: configuration
toc: true
---
Talk requires configuration in order to customize the installation. The default
behavior is to load it's configuration from the environment, following the
[12 Factor App Manifesto](https://12factor.net/){:target="_blank"}.
[12 Factor App Manifesto](https://12factor.net/).
In development, you can specify configuration in a file named `.env` and it will
be loaded into the environment when you run `yarn watch:server`.
The following variables do not have defaults, and are **required** to start your
instance of Talk:
{% include toc.html %}
The above variables do not have defaults, and are **required** to start your
instance of Talk.
If you've already configured your application with the required configuration,
you can further customize it's behavior by applying
[Advanced Configuration]({{ "/advanced-configuration/" | relative_url }}).
[Advanced Configuration](./advanced-configuration/).
## TALK_MONGO_URL
@@ -28,7 +27,7 @@ form of:
TALK_MONGO_URL=mongodb://<DATABASE USER>:<DATABASE PASSWORD>@<DATABASE HOST>:<DATABASE PORT>/<DATABASE NAME>
```
Refer to [connection string uri format](https://docs.mongodb.com/manual/reference/connection-string/){:target="_blank"}
Refer to [connection string uri format](https://docs.mongodb.com/manual/reference/connection-string/)
for the detailed url scheme of the MongoDB url.
## TALK_REDIS_URL
@@ -47,7 +46,7 @@ where I want to use database #2, I could set the `TALK_REDIS_URL` to:
TALK_REDIS_URL=redis://127.0.0.1:6379/2
```
Refer to [uri scheme](http://www.iana.org/assignments/uri-schemes/prov/redis){:target="_blank"}
Refer to [uri scheme](http://www.iana.org/assignments/uri-schemes/prov/redis)
for the detailed url scheme of the Redis url.
## TALK_ROOT_URL
@@ -59,8 +58,8 @@ TALK_ROOT_URL=<SCHEME>://<HOST>:<PORT?>/<PATHNAME>
```
For example, if we installed our application onto the `talk.coralproject.net`
domain, where we used a proxy like [Caddy](https://caddyserver.com){:target="_blank"}
or [Nginx](https://nginx.org){:target="_blank"} to perform SSL termination, then
domain, where we used a proxy like [Caddy](https://caddyserver.com)
or [Nginx](https://nginx.org) to perform SSL termination, then
`TALK_ROOT_URL` would be:
```plain
@@ -79,8 +78,7 @@ An example for `TALK_JWT_SECRET` could be:
```plain
TALK_JWT_SECRET=jX9y8G2ApcVLwyL{$6s3
```
{: .no-copy}
Be default, we sign our tokens with HMAC using a SHA-256 hash algorithm. If you
want to change the signing algorithm, or use multiple signing/verifying keys,
refer to our [Advanced Configuration]({{ "/advanced-configuration/" | relative_url }}) documentation.
refer to our [Advanced Configuration](./advanced-configuration/) documentation.
@@ -2,32 +2,31 @@
title: Advanced Configuration
permalink: /advanced-configuration/
class: configuration
toc: true
---
Talk requires configuration in order to customize the installation. The default
behavior is to load its configuration from the environment, following the
[12 Factor App Manifesto](https://12factor.net/){:target="_blank"}.
[12 Factor App Manifesto](https://12factor.net/).
In development, you can specify configuration in a file named `.env` and it will
be loaded into the environment when you run `yarn watch:server`.
The following variables have defaults, and are _optional_ to start your
instance of Talk:
{% include toc.html %}
The variables above have defaults, and are _optional_ to start your
instance of Talk.
If this is your first time configuring Talk, ensure you've also added the
[Required Configuration]({{ "/configuration/" | relative_url }}) as well,
[Required Configuration](./configuration) as well,
otherwise the application will fail to start.
## TALK_CACHE_EXPIRY_COMMENT_COUNT
Configure the duration for which comment counts are cached for, parsed by
[ms](https://www.npmjs.com/package/ms){:target="_blank"}. (Default `1hr`)
[ms](https://www.npmjs.com/package/ms). (Default `1hr`)
## TALK_DEFAULT_LANG
This is a **Build Variable** and must be consumed during build. If using the
[Docker-onbuild]({{ "/installation-from-docker/#onbuild" | relative_url }})
[Docker-onbuild](./installation-from-docker/#onbuild)
image you can specify it with `--build-arg TALK_DEFAULT_LANG=en`.
Specify the default translation language. (Default `en`)
@@ -35,7 +34,7 @@ Specify the default translation language. (Default `en`)
## TALK_DEFAULT_STREAM_TAB
This is a **Build Variable** and must be consumed during build. If using the
[Docker-onbuild]({{ "/installation-from-docker/#onbuild" | relative_url }})
[Docker-onbuild](./installation-from-docker/#onbuild)
image you can specify it with `--build-arg TALK_DEFAULT_STREAM_TAB=all`.
Specify the default stream tab in the admin. (Default `all`)
@@ -47,71 +46,27 @@ When `TRUE`, disables flagging of comments that match the suspect word filter. (
## TALK_DISABLE_EMBED_POLYFILL
When set to `TRUE`, the build process will not include the
[babel-polyfill](https://babeljs.io/docs/usage/polyfill/){:target="_blank"}
[babel-polyfill](https://babeljs.io/docs/usage/polyfill/)
in the embed.js target that is loaded on the page that loads the embed. (Default
`FALSE`)
## TALK_DISABLE_STATIC_SERVER
When `TRUE`, it will not mount the static asset serving routes on the router.
This is used primarily in conjunction with [TALK_STATIC_URI](#talk_static_uri){: .param}
This is used primarily in conjunction with [TALK_STATIC_URI](#talk_static_uri)
when the static assets are being hosted on an external domain. (Default `FALSE`)
## TALK_FACEBOOK_APP_ID
The Facebook App ID for your Facebook Login enabled app. You can learn more
about getting a Facebook App ID at the
[Facebook Developers Portal](https://developers.facebook.com){:target="_blank"}
or by visiting the
[Creating an App ID](https://developers.facebook.com/docs/apps/register){:target="_blank"}
guide. This is only required while the `talk-plugin-facebook-auth` plugin is
enabled.
## TALK_FACEBOOK_APP_SECRET
The Facebook App Secret for your Facebook Login enabled app. You can learn more
about getting a Facebook App Secret at the
[Facebook Developers Portal](https://developers.facebook.com){:target="_blank"}
or by visiting the
[Creating an App ID](https://developers.facebook.com/docs/apps/register){:target="_blank"}
guide. This is only required while the `talk-plugin-facebook-auth` plugin is
enabled.
## TALK_GOOGLE_CLIENT_ID
The Google OAuth2 client ID for your Google login web app. You can learn more
about getting a Google Client ID at the
[Google API Console](https://console.developers.google.com/apis/){:target="_blank"}.
You will need to enable the Google+ API in the dashboard and create credentials
for a new OAuth client ID web application. The authorized JavaScript origin
should be set to the Talk domain, and the authorized redirect URI should be set
to http://<example.com>/api/v1/auth/google/callback. This is only required while
the `talk-plugin-google-auth` plugin is enabled.
## TALK_GOOGLE_CLIENT_SECRET
The Google OAuth2 client ID for your Google login web app. You can learn more
about getting a Google Client ID at the
[Google API Console](https://console.developers.google.com/apis/){:target="_blank"}.
You will need to enable the Google+ API in the dashboard and create credentials
for a new OAuth client ID web application. The authorized JavaScript origin
should be set to the Talk domain, and the authorized redirect URI should be set
to http://<example.com>/api/v1/auth/google/callback. This is only required while
the `talk-plugin-google-auth` plugin is enabled.
## TALK_HELMET_CONFIGURATION
A JSON string representing the configuration passed to the
[helmet](https://github.com/helmetjs/helmet){:target="_blank"} middleware. It
can be used to disable features like [HSTS](https://helmetjs.github.io/docs/hsts/){:target="_blank"}
[helmet](https://github.com/helmetjs/helmet) middleware. It
can be used to disable features like [HSTS](https://helmetjs.github.io/docs/hsts/)
and others by simply providing the configuration as detailed on the
[helmet docs](https://helmetjs.github.io/docs/){:target="_blank"}. (Default `{}`)
[helmet docs](https://helmetjs.github.io/docs/). (Default `{}`)
For sites that do not have SSL enabled on all their pages across their domain,
it is critical that you specify the following to disable the
[HSTS](https://helmetjs.github.io/docs/hsts/){:target="_blank"} headers from
[HSTS](https://helmetjs.github.io/docs/hsts/) headers from
being sent:
```plain
@@ -130,11 +85,10 @@ set to `TRUE` after you've deployed Talk. (Default `FALSE`)
The algorithm used to sign/verify JWTs used for session management. Read up
about alternative algorithms on the
[jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken#algorithms-supported){:target="_blank"}
[jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken#algorithms-supported)
package. (Default `HS256`)
### Shared Secret
{:.no_toc}
You would use a shared secret when you have no need to share the tokens with
other applications in your organization.
@@ -152,10 +106,8 @@ These must be provided in the form:
"secret": "<my secret key>"
}
```
{: .no-copy}
### Asymmetric Secret
{:.no_toc}
You would use a asymmetric secret when you want to share the token in your
organization, and would like to pass an existing auth token to Talk in order to
@@ -178,7 +130,6 @@ These must be provided in the form:
"private": "<the PEM encoded private key>"
}
```
{: .no-copy}
Note that when using the asymmetric keys as discussed above, the certificates
must have their newlines replaced with `\\n`, this is to ensure that the
@@ -186,19 +137,19 @@ newlines are preserved after JSON decoding. Not doing so will result in parsing
errors.
To assist with this process, we have developed a tool that can generate new
certificates that match our required format: [coralcert](https://github.com/coralproject/coralcert){:target="_blank"}.
This tool can generate RSA and ECDSA certificates, check it's [README](https://github.com/coralproject/coralcert){:target="_blank"}
certificates that match our required format: [coralcert](https://github.com/coralproject/coralcert).
This tool can generate RSA and ECDSA certificates, check it's [README](https://github.com/coralproject/coralcert)
for more details.
## TALK_JWT_AUDIENCE
The audience [aud](https://tools.ietf.org/html/rfc7519#section-4.1.3){:target="_blank"}
The audience [aud](https://tools.ietf.org/html/rfc7519#section-4.1.3)
claim for login JWT tokens. (Default `talk`)
## TALK_JWT_CLEAR_COOKIE_LOGOUT
When `FALSE`, Talk will not clear the cookie with name
[TALK_JWT_SIGNING_COOKIE_NAME](#talk_jwt_signing_cookie_name){: .param} when logging out
[TALK_JWT_SIGNING_COOKIE_NAME](#talk_jwt_signing_cookie_name) when logging out
but will still blacklist the token. (Default `TRUE`)
## TALK_JWT_COOKIE_NAME
@@ -209,8 +160,8 @@ user. (Default `authorization`)
## TALK_JWT_COOKIE_NAMES
The different cookie names to check for a JWT token in, separated by a `,`. By
default, we always use the value of [TALK_JWT_COOKIE_NAME](#talk_jwt_cookie_name){: .param}
and [TALK_JWT_SIGNING_COOKIE_NAME](#talk_jwt_signing_cookie_name){: .param} for this
default, we always use the value of [TALK_JWT_COOKIE_NAME](#talk_jwt_cookie_name)
and [TALK_JWT_SIGNING_COOKIE_NAME](#talk_jwt_signing_cookie_name) for this
value. Any additional cookie names specified here will be appended to the list
of cookie names to inspect.
@@ -231,30 +182,30 @@ Would mean we would check the following cookies (in order) for a valid token:
## TALK_JWT_DISABLE_AUDIENCE
When `TRUE`, Talk will not verify or sign JWTs with an audience
[aud](https://tools.ietf.org/html/rfc7519#section-4.1.3){:target="_blank"}
claim, even if [TALK_JWT_AUDIENCE](#talk_jwt_audience){: .param} is set. (Default `FALSE`)
[aud](https://tools.ietf.org/html/rfc7519#section-4.1.3)
claim, even if [TALK_JWT_AUDIENCE](#talk_jwt_audience) is set. (Default `FALSE`)
## TALK_JWT_DISABLE_ISSUER
When `TRUE`, Talk will not verify or sign JWTs with an issuer
[iss](https://tools.ietf.org/html/rfc7519#section-4.1.1){:target="_blank"}
claim, even if [TALK_JWT_ISSUER](#talk_jwt_issuer){: .param} is set. (Default `FALSE`)
[iss](https://tools.ietf.org/html/rfc7519#section-4.1.1)
claim, even if [TALK_JWT_ISSUER](#talk_jwt_issuer) is set. (Default `FALSE`)
## TALK_JWT_EXPIRY
The expiry duration [exp](https://tools.ietf.org/html/rfc7519#section-4.1.4){:target="_blank"}
The expiry duration [exp](https://tools.ietf.org/html/rfc7519#section-4.1.4)
for the tokens issued for logged in sessions, parsed by
[ms](https://www.npmjs.com/package/ms){:target="_blank"}. (Default `1 day`)
[ms](https://www.npmjs.com/package/ms). (Default `1 day`)
If the user logs out, then an entry is created in the token blacklist of it's
[jti](https://tools.ietf.org/html/rfc7519#section-4.1.7){:target="_blank"} for
[jti](https://tools.ietf.org/html/rfc7519#section-4.1.7) for
set to be automatically removed at it's expiry time. It is important for this
reason to create reasonable expiry lengths as to minimize the storage overhead.
## TALK_JWT_ISSUER
The issuer [iss](https://tools.ietf.org/html/rfc7519#section-4.1.1){:target="_blank"}
claim for login JWT tokens. (Defaults to value of [TALK_ROOT_URL]({{ "/configuration/#talk_root_url" | relative_url }}){: .param})
The issuer [iss](https://tools.ietf.org/html/rfc7519#section-4.1.1)
claim for login JWT tokens. (Defaults to value of [TALK_ROOT_URL](./configuration/#talk_root_url))
## TALK_JWT_SECRET
@@ -265,7 +216,6 @@ An example for `TALK_JWT_SECRET` could be:
```plain
TALK_JWT_SECRET=jX9y8G2ApcVLwyL{$6s3
```
{: .no-copy}
You can also express this secret in the JSON syntax:
@@ -273,50 +223,48 @@ You can also express this secret in the JSON syntax:
TALK_JWT_SECRET={"secret": "jX9y8G2ApcVLwyL{$6s3"}
```
Refer to the documentation for [TALK_JWT_ALG](#talk_jwt_alg){: .param} for other signing
Refer to the documentation for [TALK_JWT_ALG](#talk_jwt_alg) for other signing
methods and other forms of the `TALK_JWT_SECRET`. If you are interested in using
multiple keys, then refer to [TALK_JWT_SECRETS](#talk_jwt_secrets){: .param}.
multiple keys, then refer to [TALK_JWT_SECRETS](#talk_jwt_secrets).
## TALK_JWT_SECRETS
Used when specifying multiple secrets used for key rotations. This is a JSON
encoded array, where each element matches the JWT Secret pattern. When this is
used, you do not need to specify a [TALK_JWT_SECRET](#talk_jwt_secret){: .param} as this
used, you do not need to specify a [TALK_JWT_SECRET](#talk_jwt_secret) as this
will take precedence. **The first secret in `TALK_JWT_SECRETS` will be used for
signing, and must contain a private key if used with an asymmetric algorithm.**
All secrets should specify a `kid` field which uniquely identifies a given key
and will sign all tokens with that `kid` for later identification.
When the value of [TALK_JWT_ALG](#talk_jwt_alg){: .param} is a `HS*` value, then the value
When the value of [TALK_JWT_ALG](#talk_jwt_alg) is a `HS*` value, then the value
of the `TALK_JWT_SECRETS` should take the form:
```plain
TALK_JWT_SECRETS=[{"kid": "1", "secret": "my-super-secret"}, {"kid": "2", "secret": "my-other-super-secret"}]
```
{: .no-copy}
Note that the secret is stored in a JSON object, keyed by `secret`. This is only
needed when specifying in the multiple secrets for `TALK_JWT_SECRETS`, but may
be used to specify the single [TALK_JWT_SECRET](#talk_jwt_secret){: .param}.
{: .code-aside}
be used to specify the single [TALK_JWT_SECRET](#talk_jwt_secret).
When the value of [TALK_JWT_ALG](#talk_jwt_alg){: .param} is **not** a `HS*` value, then
When the value of [TALK_JWT_ALG](#talk_jwt_alg) is **not** a `HS*` value, then
the value of the `TALK_JWT_SECRETS` should take the form:
```plain
TALK_JWT_SECRETS=[{"kid": "1", "private": "<my private key>", "public": "<my public key>"}, ...]
```
{: .no-copy}
Refer to the documentation on the [TALK_JWT_ALG](#talk_jwt_alg){: .param} for more
Refer to the documentation on the [TALK_JWT_ALG](#talk_jwt_alg) for more
information on what to store in these parameters.
{: .code-aside}
## TALK_JWT_SIGNING_COOKIE_NAME
The default cookie name that is use to set a cookie containing a JWT that was
issued by Talk. (Defaults to value of [TALK_JWT_COOKIE_NAME](#talk_jwt_cookie_name){: .param})
issued by Talk. (Defaults to value of [TALK_JWT_COOKIE_NAME](#talk_jwt_cookie_name))
## TALK_JWT_USER_ID_CLAIM
@@ -343,15 +291,15 @@ TALK_JWT_USER_ID_CLAIM=user.id
The keepalive timeout that should be used to send keep alive messages through
the websocket to keep the socket alive, parsed by
[ms](https://www.npmjs.com/package/ms){:target="_blank"}. (Default `30s`)
[ms](https://www.npmjs.com/package/ms). (Default `30s`)
## TALK_RECAPTCHA_PUBLIC
Setting a reCAPTCHA Public and Secret key will enable and require reCAPTCHA upon multiple failed login attempts.
Client secret used for enabling reCAPTCHA powered logins. If
[TALK_RECAPTCHA_SECRET](#talk_recaptcha_secret){: .param} and
[TALK_RECAPTCHA_PUBLIC](#talk_recaptcha_public){: .param} are not provided it will instead
[TALK_RECAPTCHA_SECRET](#talk_recaptcha_secret) and
[TALK_RECAPTCHA_PUBLIC](#talk_recaptcha_public) are not provided it will instead
default to providing only a time based lockout. Refer to
[reCAPTCHA](https://www.google.com/recaptcha/intro/index.html) for information
on getting an account setup.
@@ -359,8 +307,8 @@ on getting an account setup.
## TALK_RECAPTCHA_SECRET
Server secret used for enabling reCAPTCHA powered logins. If
[TALK_RECAPTCHA_SECRET](#talk_recaptcha_secret){: .param} and
[TALK_RECAPTCHA_PUBLIC](#talk_recaptcha_public){: .param} are not provided it will instead
[TALK_RECAPTCHA_SECRET](#talk_recaptcha_secret) and
[TALK_RECAPTCHA_PUBLIC](#talk_recaptcha_public) are not provided it will instead
default to providing only a time based lockout. Refer to
[reCAPTCHA](https://www.google.com/recaptcha/intro/index.html) for information
on getting an account setup.
@@ -370,14 +318,14 @@ on getting an account setup.
Configuration overrides for the redis client configuration in a JSON encoded
string. Configuration is overridden as the second parameter to the redis client
constructor, and is merged with default configuration. Refer to the
[ioredis](https://github.com/luin/ioredis){:target="_blank"} docs on the
[ioredis](https://github.com/luin/ioredis) docs on the
available options. (Default `{}`)
## TALK_REDIS_CLUSTER_CONFIGURATION
The JSON encoded form of the cluster nodes. Only required when
[TALK_REDIS_CLUSTER_MODE](#talk_redis_cluster_mode){: .param} is `CLUSTER`. See
[https://github.com/luin/ioredis#cluster](https://github.com/luin/ioredis#cluster){:target="_blank"}
[TALK_REDIS_CLUSTER_MODE](#talk_redis_cluster_mode) is `CLUSTER`. See
[https://github.com/luin/ioredis#cluster](https://github.com/luin/ioredis#cluster)
for configuration details. (Default `[]`)
## TALK_REDIS_CLUSTER_MODE
@@ -389,17 +337,17 @@ The cluster mode of the redis client. Can be either `NONE` or `CLUSTER`.
The time factor that will be multiplied against the current attempt count
between attempts to connect to redis, parsed by
[ms](https://www.npmjs.com/package/ms){:target="_blank"}. (Default `500 ms`)
[ms](https://www.npmjs.com/package/ms). (Default `500 ms`)
## TALK_REDIS_RECONNECTION_BACKOFF_MINIMUM_TIME
The minimum time used to delay before attempting to reconnect to redis, parsed
by [ms](https://www.npmjs.com/package/ms){:target="_blank"}. (Default `1 sec`)
by [ms](https://www.npmjs.com/package/ms). (Default `1 sec`)
## TALK_ROOT_URL_MOUNT_PATH
When set to `TRUE`, the routes will be mounted onto the `<PATHNAME>` component
of the [TALK_ROOT_URL]({{ "/configuration/#talk_root_url" | relative_url }}){: .param}.
of the [TALK_ROOT_URL](./configuration/#talk_root_url).
You would use this when your upstream proxy cannot strip the prefix from the
url. (Default `FALSE`)
@@ -447,12 +395,12 @@ Used to set the uri where the static assets should be served from. This is used
when you want to upload the static assets through your build process to a
service like Google Cloud Storage or Amazon S3 and you would then specify the
CDN/Storage url. (Defaults to value of
[TALK_ROOT_URL]({{ "/configuration/#talk_root_url" | relative_url }}){: .param})
[TALK_ROOT_URL](./configuration/#talk_root_url))
## TALK_THREADING_LEVEL
This is a **Build Variable** and must be consumed during build. If using the
[Docker-onbuild]({{ "/installation-from-docker/#onbuild" | relative_url }})
[Docker-onbuild](./installation-from-docker/#onbuild)
image you can specify it with `--build-arg TALK_THREADING_LEVEL=3`.
Specify the maximum depth of the comment thread. (Default `3`)
@@ -466,13 +414,13 @@ Used to override the location to connect to the websocket endpoint to
potentially another host. This should be used when you need to route websocket
requests out of your CDN in order to serve traffic more efficiently.
If the value of [TALK_ROOT_URL]({{ "/configuration/#talk_root_url" | relative_url }}){: .param}
If the value of [TALK_ROOT_URL](./configuration/#talk_root_url)
is a https url, then this defaults to `wss://${location.host}${MOUNT_PATH}api/v1/live`.
Otherwise, it defaults to `ws://${location.host}${MOUNT_PATH}api/v1/live`.
Where `MOUNT_PATH` is either `/` if [TALK_ROOT_URL_MOUNT_PATH](#talk_root_url_mount_path){: .param}
Where `MOUNT_PATH` is either `/` if [TALK_ROOT_URL_MOUNT_PATH](#talk_root_url_mount_path)
is `FALSE`, or the path component of
[TALK_ROOT_URL]({{ "/configuration/#talk_root_url" | relative_url }}){: .param} if it's `TRUE`.
[TALK_ROOT_URL](./configuration/#talk_root_url) if it's `TRUE`.
**Warning: if used without managing the auth state manually, auth
cannot be persisted due to browser restrictions.**
@@ -523,13 +471,13 @@ or set to `FALSE`.
## TALK_SETTINGS_CACHE_TIME
The duration of time that the settings object will be kept in the Redis cache,
parsed by [ms](https://www.npmjs.com/package/ms){:target="_blank"}. (Default
parsed by [ms](https://www.npmjs.com/package/ms). (Default
`1hr`)
## APOLLO_ENGINE_KEY
Used to set the key for use with
[Apollo Engine](https://www.apollographql.com/engine/){:target="_blank"} for
[Apollo Engine](https://www.apollographql.com/engine/) for
tracing of GraphQL requests.
**Note: Apollo Engine is a premium service, charges may apply.**
@@ -20,7 +20,7 @@ Talk Core is the core application of Talk - this contains all of the standard
commenting features that are necessary for a comment section, and ones that we
believe are important to be universal. If you would like to contribute to Talk,
be sure to check out our
[Contributor's Guide](https://github.com/coralproject/talk/blob/master/CONTRIBUTING.md){:target="_blank"}.
[Contributor's Guide](https://github.com/coralproject/talk/blob/master/CONTRIBUTING.md).
## Plugins
@@ -28,13 +28,13 @@ Plugins are additional functionality which are optional to use with Talk. You
can turn these on or off, depending on your specific needs. Plugins are either
part of our core plugins, which ship with Talk, or they are developed by 3rd
parties and either used privately and internally, or are open sourced for use
across the greater community. You can explore the plugins we offer by visiting our [Default Plugins]({{ "/default-plugins/" | relative_url}})
and [Additional Plugins]({{ "/additional-plugins/" | relative_url }}) pages.
across the greater community. You can explore the plugins we offer by visiting our [Default Plugins](./default-plugins/)
and [Additional Plugins](./additional-plugins/) pages.
## Recipes
Recipes are plugin templates that are created by the Talk team and 3rd party
developers, in order to help contributors and newsrooms build plugins easily.
You can explore the recipes we offer by visiting our [Plugin Recipes]({{ "/plugin-recipes/" | relative_url}})
You can explore the recipes we offer by visiting our [Plugin Recipes](./plugin-recipes/)
page.
@@ -11,7 +11,7 @@ There are 2 ways that newsrooms can support signup/login functionality with Talk
* 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){:target="_blank"})
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
@@ -31,7 +31,7 @@ https://<your asset url>?commentId=<the comment id>
Talk supports by default 3 levels of threading, meaning each top-level comment
has a depth of 3 replies; replies beyond that are not nested below the 3rd
level. You can adjust this using the
[TALK_THREADING_LEVEL]({{ "/advanced-configuration/#talk_threading_level" | relative_url }}){:.param}
[TALK_THREADING_LEVEL](./advanced-configuration/#talk_threading_level)
configuration variable. We dont recommend deep threading because it can cause
issues with styling, especially on mobile.
@@ -73,7 +73,7 @@ useful tool to ensure commenters are concise with their comments.
Talk comes with a `respect` button out of the box. Why a “respect” button, you
ask?
[Read more here](https://mediaengagement.org/research/engagement-buttons/){:target="_blank"}.
[Read more here](https://mediaengagement.org/research/engagement-buttons/).
We also have 2 more plugins, `like` and `love`, that you can turn on and
experiment with on your own Talk install.
@@ -162,7 +162,7 @@ Staff role.
The Featured comment badge shows when a comment has been featured.
Another optional badge is the Subscriber badge (which is available as a
[Recipe]({{ "/plugin-recipes/#recipe-subscriber" | relative_url}}).
[Recipe](./plugin-recipes/#recipe-subscriber).
Badges are another easy part of Talk to customize by creating a new `tag`, then
setting some rules for when it should show, and how the badge should be styled.
@@ -56,8 +56,8 @@ history.
**Toxic**
The Toxic badge signifies comments that are above the set Toxicity Probability
Threshold. Note you must have [talk-plugin-toxic-comments]({{ "/additional-plugins/#talk-plugin-toxic-comments" | relative_url }}){:.param} enabled.
[Read more about Toxic Comments here]({{ "/toxic-comments/" | relative_url}}).
Threshold. Note you must have [talk-plugin-toxic-comments](./additional-plugins/#talk-plugin-toxic-comments) enabled.
[Read more about Toxic Comments here](./toxic-comments/).
**Suspect**
@@ -122,7 +122,7 @@ automatically.
**Reports**
This shows if a commenter is a reliable flagger, an unreliable flagger, or a
neutral flagger. [Read more about reliable and unreliable flaggers here]({{"/trust/#reliable-and-unreliable-flaggers" | relative_url }}).
neutral flagger. [Read more about reliable and unreliable flaggers here](./trust/#reliable-and-unreliable-flaggers).
**Moderating from this View**
@@ -173,7 +173,7 @@ manage your team members roles (Admins, Moderators, Staff), as well as search
for commenters and take action on them (e.g. Ban/Un-ban, Suspend, etc.). ###
Configure
See [Configuring Talk]({{ "/configuring-talk/" | relative_url }}).
See [Configuring Talk](./configuring-talk/).
## Moderating via the Comment Stream
@@ -28,7 +28,7 @@ Here are the default thresholds:
+3 and higher: Reliable
```
You can configure your own Trust thresholds by using [TRUST_THRESHOLD]({{"/advanced-configuration/#trust_thresholds" | relative_url }}{:.param}) in your
You can configure your own Trust thresholds by using [TRUST_THRESHOLD](./advanced-configuration/#trust_thresholds) in your
configuration.
@@ -19,13 +19,13 @@ Talk (0.8 or 80% is the default), which works like this:
queues
Read more about Corals take on toxicity
[on our blog](https://blog.coralproject.net/toxic-avenging/){:target="_blank"}.
[on our blog](https://blog.coralproject.net/toxic-avenging/).
## What is the Perspective API?
The likely toxicity of a comment is evaluated using scores generated from
[Perspective API](http://perspectiveapi.com/){:target="_blank"}. This is part of
the [Conversation AI](https://conversationai.github.io/){:target="_blank"}
[Perspective API](http://perspectiveapi.com/). This is part of
the [Conversation AI](https://conversationai.github.io/)
research effort run by Jigsaw (a section of Google that works on global problems
around speech and access to information).
@@ -50,7 +50,7 @@ trying to improve a broken part of the internet.
## How do I add the Toxic Comments plugin?
To enable this behavior, visit the
[talk-plugin-toxic-comments]({{ "/additional-plugins/#talk-plugin-toxic-comments" | relative_url }})
[talk-plugin-toxic-comments](./additional-plugins/#talk-plugin-toxic-comments)
plugin documentation.
@@ -19,7 +19,7 @@ Allows toggling of pre-moderating comments that have links.
### Ask Readers a Question & Question Icons
Admins can choose to Ask Readers a Question in order to help guide the
discussion. [Read more about why this is important on our blog](https://blog.coralproject.net/the-empty-box/){:target="_blank"}.
discussion. [Read more about why this is important on our blog](https://blog.coralproject.net/the-empty-box/).
There are a selection of icons to display different messaging other than a
question on a particular stream, like an announcement, or general information
@@ -45,7 +45,7 @@ A maximum comment length across the site.
#### Comment Stream Description
Description text that will appear above every comment stream site-wide. We
recommend linking to your Code of Conduct or Community Guidelines. [Read tips on how to write a Code of Conduct here](https://guides.coralproject.net/create-a-code-of-conduct/){:target="_blank"}.
recommend linking to your Code of Conduct or Community Guidelines. [Read tips on how to write a Code of Conduct here](https://guides.coralproject.net/create-a-code-of-conduct/).
#### Closed Stream Message
@@ -2,6 +2,7 @@
title: Plugin Recipes
permalink: /plugin-recipes/
class: configuration
toc: true
---
Plugin Recipes are plugin templates used to help bootstrap the development of a
@@ -14,11 +15,9 @@ needs.
The following are the available recipes for use:
{% include toc.html %}
## recipe-avatar
Source: [talk-recipes/tree/master/plugins/avatar](https://github.com/coralproject/talk-recipes/tree/master/plugins/avatar){:target="_blank"}
Source: [talk-recipes/tree/master/plugins/avatar](https://github.com/coralproject/talk-recipes/tree/master/plugins/avatar)
Provides support for avatars hosted via third party, extends the User Model and
provides UI on the client-side too.
@@ -26,7 +25,7 @@ provides UI on the client-side too.
## recipe-translations
Source: [talk-recipes/tree/master/plugins/translations](https://github.com/coralproject/talk-recipes/tree/master/plugins/translations){:target="_blank"}
Source: [talk-recipes/tree/master/plugins/translations](https://github.com/coralproject/talk-recipes/tree/master/plugins/translations)
Provides an example for overriding application text through the translation
system.
@@ -34,7 +33,7 @@ system.
## recipe-subscriber
Source: [talk-recipes/tree/master/plugins/subscriber](https://github.com/coralproject/talk-recipes/tree/master/plugins/subscriber){:target="_blank"}
Source: [talk-recipes/tree/master/plugins/subscriber](https://github.com/coralproject/talk-recipes/tree/master/plugins/subscriber)
Provides an example for adding `SUBSCRIBER` badges for users with the
`SUBSCRIBER` tag added to their user model through a direct server plugin with
@@ -43,7 +42,7 @@ the auth system.
## recipe-author-name
Source: [talk-recipes/tree/master/plugins/author-name](https://github.com/coralproject/talk-recipes/tree/master/plugins/author-name){:target="_blank"}
Source: [talk-recipes/tree/master/plugins/author-name](https://github.com/coralproject/talk-recipes/tree/master/plugins/author-name)
Enables the ability to hover over a commenters name and add plugin
functionality there. The Member Since plugin that is provided in this recipe is
+256
View File
@@ -0,0 +1,256 @@
---
title: Creating a Basic Pride Reaction Plugin
permalink: /building-basic-plugin/
---
In this tutorial, we will build a basic reaction plugin.
## What is a plugin?
Talk has two parts - the first is core. Our core code includes all commenting and moderation features that are necessary for a comment section, and ones that we believe are important to be universal. This code can be found in our [Talk repo](https://github.com/coralproject/talk).
The other part is plugins. Plugins are additional functionality which are optional to use with Talk. You can turn these on or off, depending on your specific needs. Plugins are either part of our core plugins, which ship with Talk, or they are developed by 3rd parties and either used privately and internally, or are open sourced for use across the greater community.
## Reactions
Talk exposes a friendly API to create new reactions. To explore the capabilities of Talk we are going to create a new reaction together step-by-step.
In Talk, there are currently three ways commenters can react to comments: Like, Love, and Respect. These reactions are separated into plugins so that you can customize which reactions you want to use by toggling them on or off - or by adding your own custom reactions, which is what we are going to do today.
We can create a new plugin from scratch or we can use the Talk CLI to generate a plugin template for us to use. CLI stands for Command Line Interface, meaning can access utilities via the command line that make it easy to interact and integrate with Talk.
Please note this tutorial assumes you have already [installed and configured Talk locally](/talk/).
## Creating a new plugin using the Talk CLI
* Open your terminal
* Go to the Talk folder
* Enter `./bin/cli-plugins` in the command line
![Using the Plugin CLI](/talk/images/pride_reaction_tutorial_1.png)
You will see 3 options: `create`, `list` and `reconcile`
* `create`: This is what we use to create new plugins. It will display a wizard and ask us a couple of questions in order to understand how we want to build our plugin.
* `list`: Shows a list of all plugins.
* `reconcile`: Reconciles local plugins and downloads their external dependencies.
In order to create our new plugin, enter this: `./bin/cli-plugins create`.
The CLI will now ask us 4 questions:
![Generating our Plugin](/talk/images/pride_reaction_tutorial_2.png)
#### Explaining the questions of the cli-plugins create
1. This is where you will submit the name of your plugin; our usual naming convention is `talk-plugin-`, so we will enter `talk-plugin-pride` for ours.
2. *Does this plugin extend the capabilities of the server?* If your plugin needs to extend the schema of the database, or interact with route or services you will say `yes`. In this case, we will need to store the user's comment reaction, so we will say `yes`
3. *Does this plugin extend the capabilities of the client?* If your plugin adds visual content to Talk, you will say `yes`. In this case we need to add a button with which the users can react to the comments, so we will again put `yes`.
4. *Should we add it to plugins.json?* Choosing yes will activate our plugin instantly. Select `yes` in this case.
So now a plugin has been created inside our local `/plugins` folder. We can see our plugin here now, listed as `talk-plugin-pride`.
## The structure of our plugin
This is the structure of our plugin. Let's see what each piece does.
![The Structure of a Plugin](/talk/images/pride_reaction_tutorial_3.png)
* `index.js`
The index file contains everything we export to the server. In this case, we see only one thing: `module.exports = {}`. This means we are currently not exporting anything to the server - but we will do this later.
* `/client`
The `client` folder contains all the necessary files to extend the client.
* `index.js`
In this file we will describe how we are going to extend our client. It is generally useful to indicate where the plugin will be embedded. In our case we want to put it in each comment. Later we will see how to do this. It also serves to add functionality such as how to use `reducers` and `translations`.
* `.eslintrc.json`
These are the ESLint rules. By default they are the ones that Talk uses.
* `translations.yml`
This file is not mandatory but we can use it to add translations of the copy that is shown to users.
* `/components`
These are the components. By default we will find the generated file `MyPluginComponent.js` and its CSS styles in `ModulesMyPluginComponent.css`
Now let's run our Talk instance. We can see the plugin was generated and we can see it in our embed:
![Viewing our Plugin](/talk/images/pride_reaction_tutorial_4.png)
It is important to note that Talk does not dictate the architecture of the plugins. But for reasons of performance and consistency it is important that we follow certain basic guidelines.
To create components you must be familiar with React. If you're not, I recommend the official guides, especially [Components and Props - React](https://reactjs.org/docs/components-and-props.html).
It's important to note that the files that were generated by default with the plugin creator can be deleted or reused. Whatever your preference!
Now that we know what all of our plugin files do, let's create our plugin :sunglasses:
## Building our plugin
The first thing we should think about is what our plugin consists of and what experience we want to offer. We know that we want there to be a button, that it can be clicked, and that it creates a reaction in the comment. So let's build it.
Since our button is a component let's create a new file inside that folder. Let's call this `PrideButton.js`.
The minimum expression of our button looks like this:
```js
import React from 'react';
class PrideButton extends React.Component {
render() {
return <button>Pride!</button>;
}
}
export default PrideButton;
```
Alright, we have our button. So now we want to tell it where to show - in this case, we want it under every comment. To do this we are going to make use of **slots**. Slots are small places inside Talk where we can place plugins. We already have a slot in Talk where we can place reactions. This slot is called `commentReactions`.
To add it there, we will go to `client/index.js` and add the following lines:
```
import PrideButton from './components/PrideButton';
export default {
slots: {
commentReactions: [PrideButton],
},
};
```
You will notice that we deleted the slot object `MyPluginComponent`. This is because we don't want to show the little example code that the CLI generated for us. We can also delete any files we won't us, or we can just leave them but not export them; if they're not exported, they won't be added to the Talk `bundle.js`.
Now, if we go to Talk we will see that our `PrideButton` is now there on each comment - now it's time to tell the button what to do.
![Our Newly Created Pride Button](/talk/images/pride_reaction_tutorial_5.png)
## Adding functionality with the Talk API
Talk exposes a series of tools that plugins can use. In this case we can use `withReaction`. `withReaction` is a HOC (High Order Component) that adds functionality to our components.
We will use it like so:
```js
import React from 'react';
import { withReaction } from 'plugin-api/beta/client/hocs';
class PrideButton extends React.Component {
render() {
return <button>Pride!</button>;
}
}
export default withReaction('pride')(PrideButton);
```
The first parameter we passed to `withReactions` is the name of the reaction. In our case, we will use 'pride'. We must be consistent with this since this will impact storing our data later.
In our next step, let's make clicking our button either generate a reaction or remove the reaction, in case they have already acted on the comment with the same reaction.
```js
import React from 'react';
import { withReaction } from 'plugin-api/beta/client/hocs';
class PrideButton extends React.Component {
handleClick = () => {
const { postReaction, deleteReaction, alreadyReacted } = this.props;
if (alreadyReacted) {
deleteReaction();
} else {
postReaction();
}
};
render() {
return <button onClick={this.handleClick}>Pride!</button>;
}
}
export default withReaction('pride')(PrideButton);
```
`withReactions` makes the component receive `postReaction`, `deleteReaction` and `alreadyReacted`:
* `postReaction`: Posts the reaction to the served <Function>
* `deleteReaction`: Removes the reaction <Function>
* `alreadyReacted`: Lets us know if a user has already reaction to the comment
* `count`: Tells us the number of times that users have reacted to the comment
Now, our frontend functionality is complete, but for all this to work, we still need to add something else to our `index.js` in our main plugin folder. This time we want to extend the server.
```js
const { getReactionConfig } = require('../../plugin-api/beta/server');
module.exports = getReactionConfig('pride');
```
`getReactionConfig` adds the necessary functionality on the server side.
Now our plugin works! People can react to comments with pride!
We don't want to stop quite yet though - let's improve how our button looks visually - and also we aren't checking if a user has already reacted to the comment or not. Let's change that.
### Adding CSS
We are going to create a `PrideButton.css` inside of the folder components. Let's make our button noticable and bright:
```css
.reacted {
background: red;
}
.button {
background: wheat
}
```
And we will add the the use case if someone has already reacted:
```js
import React from 'react';
import styles from './PrideButton.css';
import { withReaction } from 'plugin-api/beta/client/hocs';
class PrideButton extends React.Component {
handleClick = () => {
const { postReaction, deleteReaction, alreadyReacted } = this.props;
if (alreadyReacted) {
deleteReaction();
} else {
postReaction();
}
};
render() {
const { alreadyReacted, count } = this.props;
return (
<button
className={alreadyReacted ? styles.reacted : styles.button}
onClick={this.handleClick}
>
Orgullo!
{count > 0 && count}
</button>
);
}
}
export default withReaction('pride')(PrideButton);
````
And that's it! You've created your first reaction button! :rainbow:
If you would like to continue to the next part of our Plugin Tutorial, see Part 2 in the sidebar.
@@ -0,0 +1,337 @@
---
title: Customizing Plugins with Coral UI
permalink: /customizing-plugins-coral-ui/
---
This is Part 2 of our Plugin Tutorial and assumes you've already completed [Building a Basic Plugin](/building-basic-plugin.md).
Note: We will be using Sketch in this tutorial to generate our SVG code. You can download Sketch here: https://www.sketchapp.com/.
## Coral UI
Within Talk, we have a set of tools we can leverage for our user interface, or UI. We simply call these tools Coral UI.
Within Coral UI, we have icons, buttons, alerts and other components. You can see all the elements available to use within `client/coral-ui`.
To get started using Coral UI, we're going to import it into our component.
```js
import { Icon, Button } from 'plugin-api/beta/client/components/ui';
const myButton = () =>
<Button>
<Icon name="favorite" />
Favorito
</Button>
```
The Coral UI Icon component uses icons from Material Design. You can see the entire list of icons and their respective names at [Material icons - Material Design](https://material.io/icons/).
## Using SVGs
For the Pride Plugin icon, none of the Material icons really seemed to fit so we decided to be a little creative and make our own from scratch.
To do this, we needed to create two states:
- The inactive icon (before someone has clicked/reacted)
- The active icon (after someone has clicked/reacted)
To add a little additional creativity here, we thought that the inactive icon could be grayscale and the active one could be in full color. And a rainbow would be a great idea!
![Mockups for our Pride icon](/talk/images/pride_reaction_tutorial_6.png)
## Export / Copy SVG code
[Sketch](https://www.sketchapp.com/) gives us a way to export the SVG code:
* Right click on the SVG
* Click "Copy SVG code" or "Copy SVG code"
![Exporting SVG Code from Sketch](/talk/images/pride_reaction_tutorial_7.png)
We can export it as a file or copy the inline code to our component. We personally prefer to have the inline code to have more control over the classes and the customization. In this case, we can pass different color palettes, `grayscale` and the other colors `colored`.
Then we can create `RainBowIcon.js` and write the following code:
```js
import React from 'react';
import PropTypes from 'prop-types';
// Las paletas de colores que vamos a utilizar
const colorPalette = {
grayscale: ['#C6C6C6', '#C6C6C6', '#7E7E7E', '#7C7C7C', '#7C7C7C', '#9F9F9F'],
colored: ['#F5C15F', '#EB7835', '#EB5242', '#CB4AB0', '#49B1DE', '#61C482'],
};
const RainbowIcon = ({ paletteType = 'colored', palette = [] }) => {
return (
<svg
width="19px"
height="9px"
viewBox="0 0 19 9"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
<g transform="translate(-492.000000, -630.000000)">
<g transform="translate(492.000000, 630.000000)">
<path
d="M9.5,0 C4.24785714,0 0,4.02428571 0,9 L2.71428571,9 C2.71428571,5.45142857 5.75428571,2.57142857 9.5,2.57142857 C13.2457143,2.57142857 16.2857143,5.45142857 16.2857143,9 L19,9 C19,4.02428571 14.7521429,0 9.5,0 Z"
fill={palette[0] || colorPalette[paletteType][0]}
/>
<path
d="M9.5,1 C4.80071429,1 1,4.57714286 1,9 L3.42857143,9 C3.42857143,5.84571429 6.14857143,3.28571429 9.5,3.28571429 C12.8514286,3.28571429 15.5714286,5.84571429 15.5714286,9 L18,9 C18,4.57714286 14.1992857,1 9.5,1 Z"
fill={palette[1] || colorPalette[paletteType][1]}
/>
<path
d="M9.5,2 C5.35357143,2 2,5.13 2,9 L4.14285714,9 C4.14285714,6.24 6.54285714,4 9.5,4 C12.4571429,4 14.8571429,6.24 14.8571429,9 L17,9 C17,5.13 13.6464286,2 9.5,2 Z"
fill={palette[2] || colorPalette[paletteType][2]}
/>
<path
d="M9.5,3 C5.90642857,3 3,5.68285714 3,9 L4.85714286,9 C4.85714286,6.63428571 6.93714286,4.71428571 9.5,4.71428571 C12.0628571,4.71428571 14.1428571,6.63428571 14.1428571,9 L16,9 C16,5.68285714 13.0935714,3 9.5,3 Z"
fill={palette[3] || colorPalette[paletteType][3]}
/>
<path
d="M9.5,4 C6.45928571,4 4,6.23571429 4,9 L5.57142857,9 C5.57142857,7.02857143 7.33142857,5.42857143 9.5,5.42857143 C11.6685714,5.42857143 13.4285714,7.02857143 13.4285714,9 L15,9 C15,6.23571429 12.5407143,4 9.5,4 Z"
fill={palette[4] || colorPalette[paletteType][4]}
/>
<path
d="M9.5,5 C7.01214286,5 5,6.78857143 5,9 L6.28571429,9 C6.28571429,7.42285714 7.72571429,6.14285714 9.5,6.14285714 C11.2742857,6.14285714 12.7142857,7.42285714 12.7142857,9 L14,9 C14,6.78857143 11.9878571,5 9.5,5 Z"
fill={palette[5] || colorPalette[paletteType][5]}
/>
</g>
</g>
</g>
</svg>
);
};
// This is important to do so we pass the correct properties to the component
RainbowIcon.propTypes = {
paletteType: PropTypes.oneOf(['colored', 'grayscale']),
palette: PropTypes.array,
};
export default RainbowIcon;
````
Most of the component is code generated by Sketch, except for the properties that we can control control with the palettes. The color of the rainbow lines will be given based on the order of the colors of the palette.
We have two props for our component: `paletteType` and `palette`:
`paletteType`: since we we have two palettes we've created, we can pass these directly as `colored` and `greyscale`
`palette`: if we want to pass an array of colors we can do it using this property
Ready! So now we have our icon. Now let's modify the our button `PrideButton.js` to use our new icon.
```js
import React from 'react';
import cn from 'classnames';
import styles from './PrideButton.css';
import { withReaction } from 'plugin-api/beta/client/hocs';
import RainbowIcon from './RainbowIcon';
class PrideButton extends React.Component {
handleClick = () => {
const { postReaction, deleteReaction, alreadyReacted } = this.props;
if (alreadyReacted) {
deleteReaction();
} else {
postReaction();
}
};
render() {
const { alreadyReacted } = this.props;
return (
<div className={cn(styles.container, 'talk-plugin-pride-container')}>
<a
className={cn(styles.button, 'talk-plugin-pride-button')}
onClick={this.handleClick}
>
{alreadyReacted ? (
<RainbowIcon />
) : (
<RainbowIcon paletteType="grayscale" />
)}
</a>
</div>
);
}
}
export default withReaction('pride')(PrideButton);
```
We will use the property `alreadyReacted` to change the icon and render one in grayscale (using the property `grayscale`).
There are many pros and cons of using inline SVGs that are outside the scope of this tutorial. If you'd like to learn more, you can read [5 Gotchas You're Gonna Face Getting Inline SVG Into Production](https://css-tricks.com/gotchas-on-getting-svg-into-production/) and its follow-up post [Part 2 Gotchas](https://css-tricks.com/gotchas-getting-inline-svg-production-part-ii/).
You can view the source code up to this point here: [talk-plugin-pride @ ae5c1a5](https://github.com/coralproject/talk-plugin-pride/commit/ae5c1a5e26390b9374c87ce5530d60c10b5c325e).
To keep performance top of mine, and given that this portion of SVG code can not be cached, we will create separate SVG files for the two icon states.
We will create the folder `assets` and place our two files inside it: `ColoredRainbowIcon.svg` and `GrayscaleRainbowIcon.svg`. We can export them both with Sketch or simply copy the SVG code into each file.
## Using an SVG in our components
We are going to import our SVG icons just as we did with our components, the only difference is the `.svg` at the end.
```js
import ColoredRainbowIcon from '../assets/ColoredRainbowIcon.svg';
import GrayscaleRainbowIcon from '../assets/GrayscaleRainbowIcon.svg';
```
Since Webpack will give us the new url of the resource, we can us it like this:
```js
<img
src={ColoredRainbowIcon}
className={cn(styles.icon, `${plugin}-icon`)}
/>
```
## Using media queries
Now of course we will need to support several devices and browsers, so we'll need to make sure our plugin responds correctly. For this we can use media queries.
In this case, we want to make sure that on mobile devices that are less than 425px, the reaction label is not shown.
```
@media (max-width: 425px) {
.label {
display: none;
}
}
```
If you look at our PostCSS configuration, you will notice that we use PreCSS. PreCSS allows us to optionally use a syntax that is similar to Sass and allows us to make use of variables:
```css
@custom-media --viewport-medium (width <= 50rem);
@custom-selector :--heading h1, h2, h3, h4, h5, h6;
:root {
--fontSize: 1rem;
--mainColor: #12345678;
}
@media (--viewport-medium) {
body {
color: var(--mainColor);
font-family: system-ui;
font-size: var(--fontSize);
line-height: calc(var(--fontSize) * 1.5);
overflow-wrap: break-word;
padding-inline: calc((var(--fontSize) / 2) + 1px);
}
}
```
To learn more about PreCSS: https://github.com/jonathantneal/precss
## Adding animations
To make the user experience even more fun, we wanted the user to see a small animation when they click on our Pride Button:
```css
.reacted {
animation: rainbow 1s 1;
}
@keyframes rainbow{
20%{color: #EB5242;}
40%{color: #F5C15F;}
60%{color: #61C482;}
80%{color: #49B1DE;}
100%{color: #EB7835;}
}
```
Now lets add this styling through our `classnames` library:
```js
<button
className={cn(
styles.button,
{[styles.reacted]: alreadyReacted}
)}
onClick={this.handleClick}
>
```
Perfect! Now every time a user clicks our reaction, the style is activated, and the animation is triggered.
This is what our completed Reaction now looks like:
```js
import React from 'react';
import cn from 'classnames';
import styles from './PrideButton.css';
import { withReaction } from 'plugin-api/beta/client/hocs';
import ColoredRainbowIcon from '../assets/ColoredRainbowIcon.svg';
import GrayscaleRainbowIcon from '../assets/GrayscaleRainbowIcon.svg';
const plugin = 'talk-plugin-pride';
class PrideButton extends React.Component {
handleClick = () => {
const { postReaction, deleteReaction, alreadyReacted, user } = this.props;
// If the current user does not exist, trigger sign in dialog.
if (!user) {
showSignInDialog();
return;
}
if (alreadyReacted) {
deleteReaction();
} else {
postReaction();
}
};
render() {
const { count, alreadyReacted } = this.props;
return (
<div className={cn(styles.container, `${plugin}-container`)}>
<button
className={cn(
styles.button,
{
[`${styles.reacted} talk-plugin-pride-reacted`]: alreadyReacted,
},
`${plugin}-button`
)}
onClick={this.handleClick}
>
<span className={cn(`${plugin}-label`, styles.label)}>Pride</span>
{alreadyReacted ? (
<img
src={ColoredRainbowIcon}
className={cn(styles.icon, `${plugin}-icon`)}
/>
) : (
<img
src={GrayscaleRainbowIcon}
className={cn(styles.icon, `${plugin}-icon`)}
/>
)}
<span className={cn(`${plugin}-count`)}>{count > 0 && count}</span>
</button>
</div>
);
}
}
export default withReaction('pride')(PrideButton);
```
To view the completed source code, look here: https://github.com/coralproject/talk-plugin-pride
@@ -19,7 +19,7 @@ process:
```
This will prompt you to perform a database backup before starting the migration
process. Data loss is entirely possible otherwise.
{: .code-aside}
### Docker Compose
@@ -31,5 +31,5 @@ docker-compose run --rm talk cli migration run
```
This will prompt you to perform a database backup before starting the migration
process. Data loss is entirely possible otherwise.
{: .code-aside}
@@ -33,7 +33,7 @@ Running the following will start the migration process:
```
This will prompt you to perform a database backup before starting the migration
process. Data loss is entirely possible otherwise.
{: .code-aside}
The migration itself may take some time to complete, as we're reformatting
documents rather than performing a nice table alter. If the process crashes
+1 -5
View File
@@ -1,7 +1,3 @@
---
layout: doc
---
<style type="text/css" media="screen">
.container {
margin: 10px auto;
@@ -19,4 +15,4 @@ layout: doc
<p><strong>Page not found :(</strong></p>
<p>The requested page could not be found. Try searching above for your page.</p>
</div>
</div>
+142
View File
@@ -0,0 +1,142 @@
- name: talk-plugin-akismet
description: Enables auto-moderation from Akismet.
tags:
- moderation
- name: talk-plugin-auth
description: Enables internal authentication from Coral.
tags:
- default
- auth
- name: talk-plugin-author-menu
description: Enables the comment author name plugin area.
tags:
- default
- name: talk-plugin-comment-content
description: Linkifies comment content that contains links.
tags:
- default
- name: talk-plugin-deep-reply-count
description: Enables deep reply count graph edge including all decendant replies.
- name: talk-plugin-facebook-auth
description: Enables a Facebook login strategy so users can login with their Facebook account.
tags:
- auth
- name: talk-plugin-featured-comments
description: Allows comments to be featured for other users.
tags:
- default
- name: talk-plugin-flag-details
description: Show flag details in the admin panel.
tags:
- default
- name: talk-plugin-google-auth
description: Enables a Google login strategy so users can login with their Google account.
tags:
- auth
- name: talk-plugin-ignore-user
description: Allows other users to ignore one another to hide their comments from view.
tags:
- default
- name: talk-plugin-like
description: Allows the like reaction for comments
tags:
- reaction
- name: talk-plugin-love
description: Allows the love reaction for comments
tags:
- reaction
- name: talk-plugin-member-since
description: Shows the users created at time as their member since date.
tags:
- default
- name: talk-plugin-moderation-actions
description: Allows moderators to take actions on comments from the comment stream.
tags:
- default
- name: talk-plugin-notifications
description: The base notification plugin which enables notifications to be sent.
tags:
- notifications
- name: talk-plugin-notifications-category-featured
description: Enables the on-featured notification.
tags:
- notifications
- name: talk-plugin-notifications-category-reply
description: Enables the on-reply notification.
tags:
- notifications
- name: talk-plugin-notifications-category-staff
description: Enables the on-staff-reply notification.
tags:
- notifications
- name: talk-plugin-notifications-digest-daily
description: Enables daily digesting of comment notifications as an option.
tags:
- notifications
- name: talk-plugin-notifications-digest-hourly
description: Enables hourly digesting of comment notifications as an option.
tags:
- notifications
- name: talk-plugin-offtopic
description: Allows users to mark a comment as off-topic when they create it.
tags:
- default
- name: talk-plugin-permalink
description: Shows a Link button on comments for direct-linking to a comment.
tags:
- default
- name: talk-plugin-remember-sort
description: Remembers the sort selection made by a user.
- name: talk-plugin-respect
description: Enables the respect reaction for comments.
tags:
- default
- reaction
- name: talk-plugin-rich-text
description: Enables rich text plugins that save data as HTML.
- name: talk-plugin-rich-text-pell
description: Enables the pell rich text editor.
- name: talk-plugin-slack-notifications
description: Sends all comments as notifications to a slack channel
- name: talk-plugin-sort-most-liked
description: Enables sorting by most liked.
tags:
- reaction
- sorting
- name: talk-plugin-sort-most-loved
description: Enables sorting by most loved.
tags:
- reaction
- sorting
- name: talk-plugin-sort-most-replied
description: Enables sorting by most replied.
tags:
- default
- sorting
- name: talk-plugin-sort-most-respected
description: Enables sorting by most respected.
tags:
- default
- reaction
- sorting
- name: talk-plugin-sort-newest
description: Enables sorting by newest.
tags:
- default
- sorting
- name: talk-plugin-sort-oldest
description: Enables sorting by oldest.
tags:
- default
- sorting
- name: talk-plugin-subscriber
description: Shows a subscriber tag on users that have the tag in the database.
- name: talk-plugin-toxic-comments
description: Enables auto-moderation from Google's Perspective API.
tags:
- moderation
- name: talk-plugin-viewing-options
description: Enables the dropdown used to display sorting options on the embed stream.
tags:
- default
- sorting
+17
View File
@@ -0,0 +1,17 @@
---
title: Contact
permalink: /contact/
---
## How can I get help integrating Talk into my newsroom?
We're here to help with newsrooms of all sizes. Email our Integration Engineer
([jeff@mozillafoundation.org](mailto:jeff@mozillafoundation.org)) to set up a meeting.
## How do I request a feature or submit a bug?
The best way is to [submit a GitHub issue](https://github.com/coralproject/talk/issues). Make sure you give plenty of details, our Core Team can usually respond within a few hours on weekdays.
## 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, or get in touch directly with Jeff via jeff@mozillafoundation.org.
Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

+86
View File
@@ -0,0 +1,86 @@
---
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
methods of doing so:
1. Passport Middleware
2. Custom Token Integration
Both methods work, but there are product decisions that will affect the overall
choice.
## Passport Middleware
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.
## Custom Token Integration
You can integrate Talk with any authentication service to enable single sign-on
for users. The steps to do that are:
1. Create a service that generates [JWT tokens](https://jwt.io).
2. Push the token into the embed.
3. Implement the `tokenUserNotFound` hook to process the token.
### Create JWT Token
You should create an external service that is responsible for generating a JWT
for use with Talk. The token can be generated as easy as checking out the
following node app: https://github.com/coralproject/talk-token-example
Using that demo application, you'll see how you can:
1. Create a node application that can issue JWT's that are compatible with Talk.
2. Provide a validation endpoint that can be used by Talk to validate the token
and get the user via the `tokenUserNotFound` hook.
### Push token into embed
We're assuming that your CMS is capable of authenticating a user account, or
at least having the user's details available to send off to the token creation
service we created/used in the previous step.
Using the token that was created for the user, you simply have to ammend the template where Talk is rendering to read as the following:
```js
Coral.Talk.render(document.getElementById('coralStreamEmbed'), {
// ...
auth_token: '<your generated JWT token issued for this user>',
});
```
Which will pass down the token to Talk and will fire the next steps
`tokenUserNotFound` hook to complete the auth flow.
### Implement `tokenUserNotFound`
This is the only piece of code you'll have to write that lives inside Talk.
The role of this code is to live as a plugin and provide Talk with a way of
taking the token that you gave it, and turning into a user.
Using the example application we were working with in the JWT issuing step
above, we'll need to ensure that the configuration is consistent in-between both
Talk and the JWT issuer. Namely, the following environment variables from our
example issuer and Talk must match:
| Talk | Token Issuer Example |
|------|----------------------|
|`JWT_ISSUER`|`JWT_ISSUER`|
|`JWT_AUDIENCE`|`JWT_AUDIENCE`|
|`JWT_AUDIENCE`|`JWT_AUDIENCE`|
|`SECRET`|`JWT_SECRET`*|
\* Note that secrets is a pretty complex topic, refer to the
[TALK-JWT-SECRET](/talk/advanced-configuration/#TALK-JWT-SECRET) configuration
reference, the basic takeaway is that the secret used to sign the tokens issued
by the issuer must be able to be verified by Talk.
For an example of implementing the plugin, refer to [`tokenUserNotFound`](/talk/reference/server/#tokenUserNotFound)
reference.
@@ -0,0 +1,52 @@
---
title: Configuring the Talk Admin
permalink: /integrating/configuring-admin/
---
Using plugins and configuration variables, you can modify the way the Admin looks and how moderation works.
### Creating a Custom Moderation Queue
Talk can support custom pluggable mod queues, meaning you can write a plugin that has some logic and determines which comments should appear there. This works by adding a field modQueues` in the `index.js` of your client side plugin, like so:
```
modQueues: {
newQueueKey: {
// name
name: 'My Queue Name',
// material design icon
icon: 'star',
// Filter by tags
tags: ['MY_TAG'],
// Filter by statuses
statuses: ['NONE', 'PREMOD', 'ACCEPTED', 'REJECTED'],
// Filter by comment containing action_type
action_type: 'FLAG',
},
},
```
So if we wanted to make a Featured queue, we could do this like so:
```
modQueues: {
featured: {
tags: ['FEATURED'],
icon: 'star',
name: 'Featured',
},
},
```
For more information, see here: https://github.com/coralproject/talk/pull/849
### Flag Details
To show more detailed information about reporting/flags, you can enable `talk-plugin-flag-details`.
@@ -0,0 +1,89 @@
---
title: Configuring the Talk Comment Stream
permalink: /integrating/configuring-comment-stream/
---
Using plugins and configuration variables, you can modify the way the Talk comment stream behaves. Here are some common configuration options:
### Rich Text Editor
To enable our default rich text editor plugin, you'll need to:
1. Enable `talk-plugin-rich-text` as a server-side plugin
2. Enable `talk-plugin-rich-text-pell` as a client-side plugin
3. If you have `talk-plugin-comment-content` enabled, you will need to disable this (this supports hyperlinks in the comment body)
Out of the box, our Talk Editor supports Bold, Italic, and Blockquote.
If you want to support another editor, you can create a plugin and replace the client-side one with the editor of your choice.
For more information on our implementation, see https://github.com/coralproject/talk/pull/1391
For more information on Pell, check out https://jaredreich.com/pell
### Sorting/Filtering the Stream
To enable sorting and filtering plugins, you will first need to enable the viewing options plugin:
`talk-plugin-viewing-options`
Then you can enable these sorting options:
`talk-plugin-sort-most-replied`
`talk-plugin-sort-most-respected`
`talk-plugin-sort-newest`
`talk-plugin-sort-oldest`
And/or this filtering option:
`talk-plugin-offtopic`
### Comment Timestamp Display
You can customize the way timestamps display to commenters on both the comment stream and their My Profile tab. The default display is via relative timestamps, e.g. "2 minutes ago", "20 days ago", "3 months ago".
Customizing this will require creating a plugin that leverages the two plugin slots `commentTimestamp` and `historyCommentTimestamp` to replace this with a custom component.
For more information, please see https://github.com/coralproject/talk/pull/979.
### Comment Author Menu
The comment author menu can house plugins related to the comment author. We have recipes for showing the commenter's "member since" date, and to show a subscriber badge. These will require some integration on your side to connect them to the data source that houses this information.
`talk-plugin-member-since`
`talk-plugin-subscriber`
To get started, check out our Talk Recipes: https://github.com/coralproject/talk-recipes
### Ignoring Users
To enable the ignore user functionality, you will need to enable a few things.
First, you'll enable `talk-plugin-author-menu`, as this houses the Ignore button.
And then we will enable the Ignore User plugin: `talk-plugin-ignore-user`.
And finally, we will need to enable Profile Settings; this is the tab on My Profile > Settings where commenters can manage their Ignored Users list.
`talk-plugin-profile-settings`
### Featured Comments
To enable the featuring of comments, you'll need to activate `talk-plugin-featured-comments`. If you would like the Featured Comments tab to be the default tab you land on for the stream, you will need to set the default tab ENV variable:
`TALK_DEFAULT_STREAM_TAB=talk-plugin-featured-comments`
### Reactions
Talk supports a myriad of commenter reactions, such as:
`talk-plugin-like`
`talk-plugin-love`
`talk-plugin-respect`
If you want to build your own reaction plugin, check out our Plugins docs and tutorials.
@@ -0,0 +1,33 @@
---
title: Tracking Talk Events and Metrics
permalink: /integrating/event-tracking-metrics/
---
Talk supports event emitting via Redux, Apollo and GraphQL. This means that common actions taken within Talk, such as successfully posting a comment, posting a reaction, or changing a setting, are automatically emitted from Talk. To send these events to your analytics tool of choice, however, will require some integration on your part.
First, we want to uncomment the tracking code in `article.ejs` (https://github.com/coralproject/talk/blob/93bda87ad061a2dc5eb8dc5b65a579a20efb76f7/views/article.ejs#L34). This will enable events to be sent via the Talk embed that is on your article pages. This will start a stream of events to the browser console, so that you can see which events are available.
```
events: function(events) {
events.onAny(function(eventName, data) {
// logs all available events.
console.log(eventName, data);
});
},
```
Now, we want to add our code that sends the events to our analytics system. In this case, we're sending the `PostComment.success` event. The particular way you send this will depend on what tool you're using. Refer to your tool's API and docs to determine this.
```
events: function(events) {
events.onAny(function(eventName, data) {
console.log(eventName, data);
if (eventName === 'mutation.PostComment.success') {
my_event_tracker.send('postComment', data);
}
});
},
```
You can continue this process for any specific events you'd like to track. You can also remove the `console.log` to stop events being emitted to the browser and instead only send the events to your analytics tool.
PR for Reference: https://github.com/coralproject/talk/pull/785
+73
View File
@@ -0,0 +1,73 @@
---
title: Notifications
permalink: /integrating/notifications/
---
Talk currently supports 3 types of email notifications.
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.
### Configuring SMTP
You must setup SMTP to use notifications. The following ENV variables must be set:
```
TALK_SMTP_FROM_ADDRESS=email@email.com
TALK_SMTP_USERNAME=username
TALK_SMTP_PASSWORD=password
TALK_SMTP_HOST=smtp.domain.net
TALK_SMTP_PORT=2525
```
### Enabling 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.
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.
See https://github.com/coralproject/talk/blob/8b669a31c551a042f0f079d8cfc16825673eb8f0/plugins/talk-plugin-notifications-reply/index.js for an example.
### Commenter Notification Settings
Note that notifications REQUIRE the `talk-plugin-profile-settings` plugin; this is where on My Profile commenters will enable and manage their notification settings.
### Notification Categories
Talk currently supports the following Notifications options out of the box:
`talk-plugin-notifications-category-reply`
`talk-plugin-notifications-category-staff-reply`
`talk-plugin-notifications-category-featured`
### Notification Digests
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
### Connect API
This exposes the `graph/connectors.js` via the `connect` hook.
```
module.exports = {
connect(connectors) {
// use `connectors`, contents of https://github.com/coralproject/talk/blob/b758dc91cb1f1969ecd895b6059306b318995b33/graph/connectors.js#L104
}
}
```
See https://github.com/coralproject/talk/blob/90290cfa2de88e62f687e1ed0235ba6dfe4cde26/plugins/talk-plugin-notifications/server/connect.js for an example.
### 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###
+10
View File
@@ -0,0 +1,10 @@
---
title: Styling Talk with CSS
permalink: /integrating/styling-css/
---
You can add your own stylesheet in Admin > Configure > Tech Settings.
If you would like to change the styling of any elements in Talk, we provide global classnames with the prefix `talk-`. The easiest way to find the classname for the element you're looking for is to use the web inspector, and then update your stylesheet accordingly.
Plugins also have their own stylesheets located in the client directory.
@@ -0,0 +1,28 @@
---
title: Translations and i18n
permalink: /integrating/translations-i18n/
---
Were so proud to have received submissions from a lot of 3rd party contributors translating Talk into their own languages.
### Languages
You can see what languages Talk currently supports here: https://github.com/coralproject/talk/tree/master/locales
You can set the default language Talk uses by setting `TALK_DEFAULT_LANG` in your ENV.
### Changing the Language
To change Talk's language, to see what translations are missing, or to troubleshoot translations, you can update the language in the local storage of your browser, by typing this into your browser console:
`localStorage.setItem('locale', 'fr')`
That would set the language to French.
### Contributing a Translation
To add a new Talk translation, simply translate the `en.yml` file (https://github.com/coralproject/talk/blob/master/locales/en.yml) into a new yml file with the language code of your choice. You can find supported language codes here: http://www.localeplanet.com/icu/iso639.html
If you are a developer contributing a new language, you'll need to add the required i18n support in the i18n files (or you can leave that to us if you like). If you're a non-developer, you can submit the translation via GitHub if you feel comfortable doing that, or feel free to email it to us via our Support: support@coralproject.net
If you want to suggest a new language or put a placeholder for a translation youre working on, feel free to create a GitHub issue: https://github.com/coralproject/talk/issues/new
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-akismet/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-auth/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-author-menu/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-comment-content/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-deep-reply-count/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-facebook-auth/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-featured-comments/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-flag-details/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-google-auth/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-ignore-user/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-like/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-love/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-member-since/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-moderation-actions/README.md
@@ -0,0 +1 @@
../../../plugins/talk-plugin-notifications-category-featured/README.md
@@ -0,0 +1 @@
../../../plugins/talk-plugin-notifications-category-reply/README.md
@@ -0,0 +1 @@
../../../plugins/talk-plugin-notifications-category-staff/README.md
@@ -0,0 +1 @@
../../../plugins/talk-plugin-notifications-digest-daily/README.md
@@ -0,0 +1 @@
../../../plugins/talk-plugin-notifications-digest-hourly/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-notifications/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-offtopic/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-permalink/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-remember-sort/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-respect/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-rich-text-pell/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-rich-text/README.md
@@ -0,0 +1 @@
../../../plugins/talk-plugin-slack-notifications/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-sort-most-liked/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-sort-most-loved/README.md
+1
View File
@@ -0,0 +1 @@
../../../plugins/talk-plugin-sort-most-replied/README.md
@@ -0,0 +1 @@
../../../plugins/talk-plugin-sort-most-respected/README.md

Some files were not shown because too many files have changed in this diff Show More