From e713b39846d6cb73c97acb89e090bc5982c5324f Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 12 Mar 2018 09:17:30 -0300 Subject: [PATCH 01/37] clearer api - wip debug tools --- .../coral-embed-stream/src/tabs/stream/containers/Stream.js | 2 +- client/coral-framework/services/plugins.js | 6 ++++-- views/article.ejs | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js index 191490914..0f516f935 100644 --- a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js @@ -465,7 +465,7 @@ const mapStateToProps = state => ({ activeStreamTab: state.stream.activeTab, previousStreamTab: state.stream.previousTab, commentClassNames: state.stream.commentClassNames, - pluginConfig: state.config.plugin_config, + pluginConfig: state.config.plugins_config, sortOrder: state.stream.sortOrder, sortBy: state.stream.sortBy, }); diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index 222cc1b42..5afcd3f78 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -84,7 +84,8 @@ class PluginsService { * query datas are only passed to the component if it is defined in `component.fragments`. */ getSlotComponentProps(component, reduxState, props, queryData) { - const pluginConfig = get(reduxState, 'config.plugin_config') || emptyConfig; + const pluginConfig = + get(reduxState, 'config.plugins_config') || emptyConfig; return { ...props, config: pluginConfig, @@ -98,7 +99,8 @@ class PluginsService { * Returns React Elements for given slot. */ getSlotElements(slot, reduxState, props = {}, queryData = {}, options = {}) { - const pluginConfig = get(reduxState, 'config.plugin_config') || emptyConfig; + const pluginConfig = + get(reduxState, 'config.plugins_config') || emptyConfig; const { slotSize = 0 } = options; const isDisabled = component => { diff --git a/views/article.ejs b/views/article.ejs index 48d361d38..9bffc6451 100644 --- a/views/article.ejs +++ b/views/article.ejs @@ -42,7 +42,7 @@ * }); * }, */ - plugin_config: { + plugins_config: { /** * You can disable rendering slot components of a plugin by doing: * @@ -51,7 +51,7 @@ * }, */ test: 'data', - debug: false + debug: true } }) "> From 6200ba39c2985c1ae3f02a94376c54b3bfaa2270 Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 12 Mar 2018 10:21:42 -0300 Subject: [PATCH 02/37] Adding debug tools --- .../src/tabs/stream/containers/Stream.js | 2 +- client/coral-framework/components/Slot.css | 28 ++++++++++++++++++- client/coral-framework/components/Slot.js | 15 ++++++++-- client/coral-framework/services/plugins.js | 14 +++++----- plugin-api/beta/client/selectors/index.js | 2 +- 5 files changed, 49 insertions(+), 12 deletions(-) diff --git a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js index 0f516f935..8515a2db4 100644 --- a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js @@ -465,7 +465,7 @@ const mapStateToProps = state => ({ activeStreamTab: state.stream.activeTab, previousStreamTab: state.stream.previousTab, commentClassNames: state.stream.commentClassNames, - pluginConfig: state.config.plugins_config, + pluginsConfig: state.config.plugins_config, sortOrder: state.stream.sortOrder, sortBy: state.stream.sortBy, }); diff --git a/client/coral-framework/components/Slot.css b/client/coral-framework/components/Slot.css index 6a95d79ad..ea3a88fea 100644 --- a/client/coral-framework/components/Slot.css +++ b/client/coral-framework/components/Slot.css @@ -3,5 +3,31 @@ } .debug { - background-color: coral; + background-color: #e2e2e2; + border-style: dotted solid; + border-width: 2px; + border: dotted 2px coral; + padding: 2px; + margin: 1px; + position: relative; +} + +.debug::before { + content: "•slot: " attr(data-slot-name) "\A" "•classname: " attr(data-slot-classname); + display: inline-block; + position: absolute; + bottom: 50%; + background: #000; + color: #FFF; + padding: 5px; + border-radius: 5px; + opacity:0; transition:0.3s; overflow:hidden; + pointer-events: none; + z-index: 999!important; + white-space: pre-wrap; +} + +.debug:hover::before { + opacity:1; + bottom: 100%; } \ No newline at end of file diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index 952844ed0..ca10d99c0 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -72,7 +72,7 @@ class Slot extends React.Component { } = this.props; const { plugins } = this.context; let children = this.getChildren(); - const pluginConfig = + const pluginsConfig = get(reduxState, 'config.plugins_config') || emptyConfig; if (children.length === 0 && DefaultComponent) { const props = plugins.getSlotComponentProps( @@ -88,13 +88,24 @@ class Slot extends React.Component { children = children.map(childFactory); } + const debugProps = pluginsConfig.debug + ? { + 'data-slot-name': fill, + 'data-slot-classname': `talk-slot-${kebabCase(fill)}`, + } + : {}; + return ( {children} diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index 5afcd3f78..f0e6ff304 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -10,7 +10,7 @@ import get from 'lodash/get'; import { getDisplayName } from 'coral-framework/helpers/hoc'; import camelize from '../helpers/camelize'; -// This is returned for pluginConfig when it is empty. +// This is returned for pluginsConfig when it is empty. const emptyConfig = {}; // Memoize the warnings so we only show them once. @@ -84,11 +84,11 @@ class PluginsService { * query datas are only passed to the component if it is defined in `component.fragments`. */ getSlotComponentProps(component, reduxState, props, queryData) { - const pluginConfig = + const pluginsConfig = get(reduxState, 'config.plugins_config') || emptyConfig; return { ...props, - config: pluginConfig, + config: pluginsConfig, ...(component.fragments ? pick(queryData, Object.keys(component.fragments)) : withWarnings(component, queryData)), @@ -99,15 +99,15 @@ class PluginsService { * Returns React Elements for given slot. */ getSlotElements(slot, reduxState, props = {}, queryData = {}, options = {}) { - const pluginConfig = + const pluginsConfig = get(reduxState, 'config.plugins_config') || emptyConfig; const { slotSize = 0 } = options; const isDisabled = component => { if ( - pluginConfig && - pluginConfig[component.talkPluginName] && - pluginConfig[component.talkPluginName].disable_components + pluginsConfig && + pluginsConfig[component.talkPluginName] && + pluginsConfig[component.talkPluginName].disable_components ) { return true; } diff --git a/plugin-api/beta/client/selectors/index.js b/plugin-api/beta/client/selectors/index.js index 97e4623e4..c7951ca56 100644 --- a/plugin-api/beta/client/selectors/index.js +++ b/plugin-api/beta/client/selectors/index.js @@ -1 +1 @@ -export const pluginConfigSelector = state => state.config.pluginConfig; +export const pluginsConfigSelector = state => state.config.pluginsConfig; From 68fb51122350ec88fc312d66a38373449373997b Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 12 Mar 2018 13:41:00 -0300 Subject: [PATCH 03/37] desc styling --- client/coral-framework/components/Slot.css | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/client/coral-framework/components/Slot.css b/client/coral-framework/components/Slot.css index ea3a88fea..69bfe937e 100644 --- a/client/coral-framework/components/Slot.css +++ b/client/coral-framework/components/Slot.css @@ -13,21 +13,26 @@ } .debug::before { - content: "•slot: " attr(data-slot-name) "\A" "•classname: " attr(data-slot-classname); + content: attr(data-slot-name); display: inline-block; position: absolute; - bottom: 50%; + background: #000; color: #FFF; padding: 5px; border-radius: 5px; - opacity:0; transition:0.3s; overflow:hidden; + opacity: 0; + transition: 0.3s; + overflow: hidden; pointer-events: none; z-index: 999!important; white-space: pre-wrap; + min-height: 16px; + top: 50%; + left: 0; } .debug:hover::before { - opacity:1; - bottom: 100%; + opacity: 1; + top: 100%; } \ No newline at end of file From 77be539710ebc71b60ee2dabd255f314eb9a4f20 Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 12 Mar 2018 13:49:35 -0300 Subject: [PATCH 04/37] Adding it to the docs, not sure if it should live there. --- client/coral-framework/components/Slot.js | 1 - docs/_docs/04-05-talk-slots-and-plugins-ES.md | 0 2 files changed, 1 deletion(-) create mode 100644 docs/_docs/04-05-talk-slots-and-plugins-ES.md diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index ca10d99c0..18d3163e0 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -91,7 +91,6 @@ class Slot extends React.Component { const debugProps = pluginsConfig.debug ? { 'data-slot-name': fill, - 'data-slot-classname': `talk-slot-${kebabCase(fill)}`, } : {}; diff --git a/docs/_docs/04-05-talk-slots-and-plugins-ES.md b/docs/_docs/04-05-talk-slots-and-plugins-ES.md new file mode 100644 index 000000000..e69de29bb From 5dbbf80068a6d9da3a60222c1b03f822beb3f601 Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 12 Mar 2018 14:27:41 -0300 Subject: [PATCH 05/37] Adding it to the docs, not sure if it should live there. --- docs/_docs/04-05-talk-slots-and-plugins-ES.md | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/docs/_docs/04-05-talk-slots-and-plugins-ES.md b/docs/_docs/04-05-talk-slots-and-plugins-ES.md index e69de29bb..846ccd033 100644 --- a/docs/_docs/04-05-talk-slots-and-plugins-ES.md +++ b/docs/_docs/04-05-talk-slots-and-plugins-ES.md @@ -0,0 +1,157 @@ +# Plugins y Slots +Los *Slots* son una parte muy importante para crear plugins. Estos nos permiten inyectar nuestros plugins en la interfaz visual de Talk. + +Talk por defecto muestra varios plugins - Observemos el archivo `plugins.default.json` : + +```json +{ + "server": [ + "talk-plugin-auth", + "talk-plugin-featured-comments", + "talk-plugin-offtopic", + "talk-plugin-respect" + ], + "client": [ + "talk-plugin-auth", + "talk-plugin-author-menu", + "talk-plugin-comment-content", + "talk-plugin-featured-comments", + "talk-plugin-flag-details", + "talk-plugin-ignore-user", + "talk-plugin-member-since", + "talk-plugin-moderation-actions", + "talk-plugin-offtopic", + "talk-plugin-permalink", + "talk-plugin-respect", + "talk-plugin-sort-most-replied", + "talk-plugin-sort-most-respected", + "talk-plugin-sort-newest", + "talk-plugin-sort-oldest", + "talk-plugin-viewing-options", + "talk-plugin-profile-settings" + ] +} +``` + +La parte que nos interesa es `client`, ya que estos son los plugins que van a utilizar los *slots* para meterse en distintas partes de Talk. + +Por ejemplo: Si observamos el plugin `talk-plugin-respect`, que está dentro de la carpeta `plugins` vamos a notar que el `client/index.js` luce asi: + +```js +import RespectButton from './RespectButton'; +import translations from './translations.yml'; + +export default { + translations, + slots: { + commentReactions: [RespectButton], + }, +}; + +``` + +Dentro de la propiedad `slots` especificamos qué *slots* utilizará el plugin. Ahí estamos diciendo que el componente `RespectButton` se incrustará en el slot `commentReactions`. + +Los slots reciben un /Array/ de componentes. Es decir, puede ser uno o varios. + +### Anatomía del component Slot +En el core de Talk tenemos 32 slots declarados. El componente Slot tiene una propiedad `fill` donde establecemos el nombre del slot. Una declaración de un `` luce así: + +```js + +``` + +Esto probablemente no lo utilices para desarrollar plugins, pero sí para buscar donde se va a embeber tu plugin. + +### Lista de Slots + +* `adminCommentDetailArea` +* `adminCommentMoreDetails` +* `adminCommentLabels` +* `adminModerationSettings` +* `adminStreamSettings` +* `adminTechSettings` +* `adminCommentInfoBar` +* `adminCommentContent` +* `adminSideActions` +* `adminModeration` +* `adminModerationIndicator` + +* `commentInputDetailArea` +* `commentAvatar` +* `commentAuthorName` +* `commentAuthorTags` +* `commentTimestamp` +* `commentInfoBar` +* `commentContent` +* `commentReactions` +* `commentActions` +* `commentInputArea` + +* `draftArea` +* `streamSettings` +* `historyCommentTimestamp` +* `profileSections` +* `embed` +* `stream` +* `streamFilter` +* `streamQuestionArea` +* `login` +* `userProfile` +* `userDetailCommentContent` + +### Cómo sé donde colocar mi plugin? + +Lo primero que debemos pensar es a qué componente afectará la funcionalidad del plugin. Por ejemplo, si queremos agregar funcionalidad a todos los comentarios que se renderizan en la lista total de comentarios, esto tendrá que ver con el componente `Comment`. + +Los slots habilitados para agregar funcionalidad a los comentarios tienen un prefix `comment` como el `commentContent` o el `commentReactions`, que vimos previamente. + +### Deshabilitando plugins por configuración + +Los plugins se eliminan borrando su entrada en el `plugins.json`. Pero si por alguna razón necesitamos hacerlo por configuración, podemos hacerlo. + +Dentro de `views/article.ejs` embebemos Talk y notarás que podemos envialarle un objeto de configuración. Para deshabilitar visualmente a los plugins podemos utilizar la propiedad `disable_components` en `true`. y se utiliza de la siguiente forma: + +```js +plugins_config: { + 'talk-plugin-love': { + disable_components: true, + }, +} +``` + +### Enviando información a los slots / plugins + +Dentro de `plugins_config` podemos pasar todas las propiedades que queramos y los plugins las recibirán. + +Por ejemplo: Si enviamos esto +```js +plugins_config: { + test: 'data' +} +``` + +El plugin recibirá por props un objeto config con las propiedades que le pasamos. Haciendo un console.log de `this.props` verás: + +```js +config: {test: 'data'} +``` + +### Debug Slots + +Podés debuggear Slots / Plugins sólo con pasar la propiedad `debug` con valor `true`. + +```js +plugins_config: { + debug: true +} +``` + +Esto mostrará todos los slots disponibles en la UI y su nombre si pasas el mouse sobre ellos. + +### Slot ClassNames +Los slots autogeneran sus clases con el prefijo `talk-slot-` seguido del nombre del slot en kebab case. +Por ejemplo, la clase autogenerada del slot `commentContent` es `talk-slot-comment-content`. \ No newline at end of file From b80184d9ee05aa7ffa0f684f312c3f02b145cfb7 Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 12 Mar 2018 14:29:18 -0300 Subject: [PATCH 06/37] set debug to false --- views/article.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/article.ejs b/views/article.ejs index 9bffc6451..896be9730 100644 --- a/views/article.ejs +++ b/views/article.ejs @@ -51,7 +51,7 @@ * }, */ test: 'data', - debug: true + debug: false } }) "> From 4f844dfd58510abe7604360bcda8c5b9dba1f88c Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 14 Mar 2018 22:38:27 -0300 Subject: [PATCH 07/37] Adding deprecation notice --- .../src/tabs/stream/containers/Stream.js | 2 +- client/coral-framework/components/Slot.js | 12 +++++++++++- client/coral-framework/services/plugins.js | 10 +++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js index 8515a2db4..9b12349c5 100644 --- a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js @@ -465,7 +465,7 @@ const mapStateToProps = state => ({ activeStreamTab: state.stream.activeTab, previousStreamTab: state.stream.previousTab, commentClassNames: state.stream.commentClassNames, - pluginsConfig: state.config.plugins_config, + pluginsConfig: state.config.plugins_config || state.config.plugin_config, sortOrder: state.stream.sortOrder, sortBy: state.stream.sortBy, }); diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index 18d3163e0..25e6521eb 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -72,8 +72,18 @@ class Slot extends React.Component { } = this.props; const { plugins } = this.context; let children = this.getChildren(); + + if (!!get(reduxState, 'config.plugin_config')) { + console.warn( + `deprecation warning: config.plugin_config will be phased out soon, please replace calls from config.plugin_config to config.plugins_config` + ); + } + const pluginsConfig = - get(reduxState, 'config.plugins_config') || emptyConfig; + get(reduxState, 'config.plugins_config') || + get(reduxState, 'config.plugin_config') || + emptyConfig; + if (children.length === 0 && DefaultComponent) { const props = plugins.getSlotComponentProps( DefaultComponent, diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index f0e6ff304..5d2c88e55 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -84,8 +84,16 @@ class PluginsService { * query datas are only passed to the component if it is defined in `component.fragments`. */ getSlotComponentProps(component, reduxState, props, queryData) { + if (!!get(reduxState, 'config.plugin_config')) { + console.warn( + `deprecation warning: config.plugin_config will be phased out soon, please replace calls from config.plugin_config to config.plugins_config` + ); + } + const pluginsConfig = - get(reduxState, 'config.plugins_config') || emptyConfig; + get(reduxState, 'config.plugins_config') || + get(reduxState, 'config.plugin_config') || + emptyConfig; return { ...props, config: pluginsConfig, From 7d7e3f60d383ff27df4a878fd5b548c942c86ec7 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 14 Mar 2018 23:33:06 -0300 Subject: [PATCH 08/37] show dep message only once --- client/coral-framework/components/Slot.js | 6 ------ client/coral-framework/services/plugins.js | 8 +++++++- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index 25e6521eb..a2def60fa 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -73,12 +73,6 @@ class Slot extends React.Component { const { plugins } = this.context; let children = this.getChildren(); - if (!!get(reduxState, 'config.plugin_config')) { - console.warn( - `deprecation warning: config.plugin_config will be phased out soon, please replace calls from config.plugin_config to config.plugins_config` - ); - } - const pluginsConfig = get(reduxState, 'config.plugins_config') || get(reduxState, 'config.plugin_config') || diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index 5d2c88e55..fb8ae045d 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -83,11 +83,17 @@ class PluginsService { * getSlotComponentProps calculate the props we would pass to the slot component. * query datas are only passed to the component if it is defined in `component.fragments`. */ + showPluginsConfigWarning = true; + getSlotComponentProps(component, reduxState, props, queryData) { - if (!!get(reduxState, 'config.plugin_config')) { + if ( + !!get(reduxState, 'config.plugin_config') && + this.showPluginsConfigWarning + ) { console.warn( `deprecation warning: config.plugin_config will be phased out soon, please replace calls from config.plugin_config to config.plugins_config` ); + this.showPluginsConfigWarning = false; } const pluginsConfig = From 3b2a9e5c7501ea575c6f0b3c73b7f6fdd728c6aa Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 15 Mar 2018 15:03:01 -0600 Subject: [PATCH 09/37] improved context perf --- graph/context.js | 36 ++++++++++++++++++++++++++++++++---- services/logging.js | 20 ++++++++++---------- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/graph/context.js b/graph/context.js index 52bb7fdfc..dcbbc5f6b 100644 --- a/graph/context.js +++ b/graph/context.js @@ -42,6 +42,32 @@ const decorateContextPlugins = (context, contextPlugins) => { ); }; +/** + * Some pieces of the Context are quite complex to setup, using multiple merges + * and other lodash functions. This proxies that access such that it is only + * loaded if it is used. Helpful for a query that only uses a loader, and not a + * mutator. + * + * @param {Object} ctx the graph proxy + * @param {Function} loader the loadable component that should be proxied + */ +const proxyContextLoader = (ctx, loader) => + new Proxy( + { loaded: false, data: null }, + { + get: (obj, prop) => { + if (obj.loaded) { + return obj.data[prop]; + } + + obj.data = loader(ctx); + obj.loaded = true; + + return obj.data[prop]; + }, + } + ); + /** * Stores the request context. */ @@ -61,16 +87,18 @@ class Context { this.connectors = connectors; // Create the loaders. - this.loaders = loaders(this); + this.loaders = proxyContextLoader(this, loaders); // Create the mutators. - this.mutators = mutators(this); + this.mutators = proxyContextLoader(this, mutators); // Decorate the plugin context. - this.plugins = decorateContextPlugins(this, contextPlugins); + this.plugins = proxyContextLoader(this, () => + decorateContextPlugins(this, contextPlugins) + ); // Bind the publish/subscribe to the context. - this.pubsub = getBroker(); + this.pubsub = proxyContextLoader(this, () => getBroker()); // Bind the parent context. this.parent = ctx; diff --git a/services/logging.js b/services/logging.js index 00e9c523b..47ef93af8 100644 --- a/services/logging.js +++ b/services/logging.js @@ -1,18 +1,18 @@ const { version } = require('../package.json'); const Logger = require('bunyan'); const { LOGGING_LEVEL, REVISION_HASH } = require('../config'); +const logger = new Logger({ + src: true, + name: 'talk', + version, + revision: REVISION_HASH, + level: LOGGING_LEVEL, + serializers: Logger.stdSerializers, +}); // Create the logging instance that all logger's are branched from. function createLogger(name, traceID) { - return new Logger({ - src: true, - name, - traceID, - version, - revision: REVISION_HASH, - level: LOGGING_LEVEL, - serializers: Logger.stdSerializers, - }); + return logger.child({ origin: name, traceID }); } -module.exports = { createLogger }; +module.exports = { logger, createLogger }; From 96dff8ed25c0ab7efe66c0c619c0041e83fbbcdf Mon Sep 17 00:00:00 2001 From: okbel Date: Fri, 16 Mar 2018 20:16:28 -0300 Subject: [PATCH 10/37] wip :0 --- .../coral-embed-stream/src/constants/debug.js | 2 ++ .../coral-embed-stream/src/reducers/debug.js | 20 +++++++++++++++++++ .../coral-embed-stream/src/reducers/index.js | 2 ++ client/coral-embed/src/Stream.js | 4 ++++ client/coral-embed/src/StreamInterface.js | 4 ++++ client/coral-framework/components/Slot.js | 4 +++- client/coral-framework/services/bootstrap.js | 6 ++++++ 7 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 client/coral-embed-stream/src/constants/debug.js create mode 100644 client/coral-embed-stream/src/reducers/debug.js diff --git a/client/coral-embed-stream/src/constants/debug.js b/client/coral-embed-stream/src/constants/debug.js new file mode 100644 index 000000000..d31784af9 --- /dev/null +++ b/client/coral-embed-stream/src/constants/debug.js @@ -0,0 +1,2 @@ +export const ENABLE_PLUGINS_DEBUG = 'ENABLE_PLUGINS_DEBUG'; +export const DISABLE_PLUGINS_DEBUG = 'DISABLE_PLUGINS_DEBUG'; diff --git a/client/coral-embed-stream/src/reducers/debug.js b/client/coral-embed-stream/src/reducers/debug.js new file mode 100644 index 000000000..bcd919ebf --- /dev/null +++ b/client/coral-embed-stream/src/reducers/debug.js @@ -0,0 +1,20 @@ +import * as actions from '../constants/debug'; + +const initialState = { + plugins: false, +}; + +export default function DEBUG(state = initialState, action) { + switch (action.type) { + case actions.ENABLE_PLUGINS_DEBUG: + return { + plugins: true, + }; + case actions.DISABLE_PLUGINS_DEBUG: + return { + plugins: false, + }; + default: + return state; + } +} diff --git a/client/coral-embed-stream/src/reducers/index.js b/client/coral-embed-stream/src/reducers/index.js index 15056d414..a896e64c0 100644 --- a/client/coral-embed-stream/src/reducers/index.js +++ b/client/coral-embed-stream/src/reducers/index.js @@ -3,6 +3,7 @@ import embed from './embed'; import configure from './configure'; import stream from './stream'; import profile from './profile'; +import debug from './debug'; export default { login, @@ -10,4 +11,5 @@ export default { configure, stream, profile, + debug, }; diff --git a/client/coral-embed/src/Stream.js b/client/coral-embed/src/Stream.js index fc8c0d5e7..fffa26aba 100644 --- a/client/coral-embed/src/Stream.js +++ b/client/coral-embed/src/Stream.js @@ -161,6 +161,10 @@ export default class Stream { ); } + dispatch(action) { + this.pym.sendMessage('dispatch', action); + } + login(token) { this.pym.sendMessage('login', token); } diff --git a/client/coral-embed/src/StreamInterface.js b/client/coral-embed/src/StreamInterface.js index 4c6e29970..67e2fff1b 100644 --- a/client/coral-embed/src/StreamInterface.js +++ b/client/coral-embed/src/StreamInterface.js @@ -3,6 +3,10 @@ export default class StreamInterface { this._stream = stream; } + dispatch(action) { + return this._stream.dispatch(action); + } + on(eventName, callback) { return this._stream.emitter.on(eventName, callback); } diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index a2def60fa..4f56f7994 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -69,6 +69,7 @@ class Slot extends React.Component { defaultComponent: DefaultComponent, queryData, fill, + debugPlugins, } = this.props; const { plugins } = this.context; let children = this.getChildren(); @@ -103,7 +104,7 @@ class Slot extends React.Component { className={cn( { [styles.inline]: inline, - [styles.debug]: pluginsConfig.debug, + [styles.debug]: debugPlugins || pluginsConfig.debug, }, className, `talk-slot-${kebabCase(fill)}` @@ -156,6 +157,7 @@ Slot.propTypes = { const mapStateToProps = state => ({ reduxState: state, + debugPlugins: state.debug.plugins, }); export default connect(mapStateToProps, null)(Slot); diff --git a/client/coral-framework/services/bootstrap.js b/client/coral-framework/services/bootstrap.js index 691404369..fc06ea441 100644 --- a/client/coral-framework/services/bootstrap.js +++ b/client/coral-framework/services/bootstrap.js @@ -215,6 +215,12 @@ export async function createContext({ pym.onMessage('logout', () => { store.dispatch(logout()); }); + + pym.onMessage('dispatch', action => { + store.dispatch({ + type: action, + }); + }); } const preInitList = []; From a700e91911517debb15f5bcbccd4e89fb4f73e27 Mon Sep 17 00:00:00 2001 From: okbel Date: Sat, 17 Mar 2018 16:26:46 -0300 Subject: [PATCH 11/37] adding debugPlugins --- client/coral-framework/components/Slot.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index 4f56f7994..c69b10cf1 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -93,11 +93,12 @@ class Slot extends React.Component { children = children.map(childFactory); } - const debugProps = pluginsConfig.debug - ? { - 'data-slot-name': fill, - } - : {}; + const debugProps = + debugPlugins || pluginsConfig.debug + ? { + 'data-slot-name': fill, + } + : {}; return ( Date: Sat, 17 Mar 2018 16:44:01 -0300 Subject: [PATCH 12/37] refactor due to auth probs --- client/coral-framework/components/Slot.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index c69b10cf1..3719db8c2 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -69,7 +69,7 @@ class Slot extends React.Component { defaultComponent: DefaultComponent, queryData, fill, - debugPlugins, + debug = {}, } = this.props; const { plugins } = this.context; let children = this.getChildren(); @@ -94,7 +94,7 @@ class Slot extends React.Component { } const debugProps = - debugPlugins || pluginsConfig.debug + debug.plugins || pluginsConfig.debug ? { 'data-slot-name': fill, } @@ -105,7 +105,7 @@ class Slot extends React.Component { className={cn( { [styles.inline]: inline, - [styles.debug]: debugPlugins || pluginsConfig.debug, + [styles.debug]: debug.plugins || pluginsConfig.debug, }, className, `talk-slot-${kebabCase(fill)}` @@ -123,7 +123,7 @@ Slot.defaultProps = { }; Slot.propTypes = { - debugPlugins: PropTypes.bool, + debug: PropTypes.object, fill: PropTypes.string.isRequired, inline: PropTypes.bool, className: PropTypes.string, @@ -159,7 +159,7 @@ Slot.propTypes = { const mapStateToProps = state => ({ reduxState: state, - debugPlugins: state.debug.plugins, + debug: state.debug, }); export default connect(mapStateToProps, null)(Slot); From 40782a5d0b6aff92d29e7884ae0b6e08df9f47d2 Mon Sep 17 00:00:00 2001 From: okbel Date: Sat, 17 Mar 2018 18:55:39 -0300 Subject: [PATCH 13/37] Adding off method to the Stream Interface --- client/coral-embed/src/StreamInterface.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/coral-embed/src/StreamInterface.js b/client/coral-embed/src/StreamInterface.js index 67e2fff1b..57339cf90 100644 --- a/client/coral-embed/src/StreamInterface.js +++ b/client/coral-embed/src/StreamInterface.js @@ -11,6 +11,10 @@ export default class StreamInterface { return this._stream.emitter.on(eventName, callback); } + off(eventName, callback) { + return this._stream.emitter.off(eventName, callback); + } + login(token) { return this._stream.login(token); } From 346a099c1b9d05d2ecedaf6162977ed82617d225 Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 19 Mar 2018 15:10:14 -0300 Subject: [PATCH 14/37] changes - ready to be tested --- client/coral-embed-stream/src/tabs/stream/containers/Stream.js | 2 ++ client/coral-framework/components/Slot.js | 2 ++ client/coral-framework/services/plugins.js | 1 + 3 files changed, 5 insertions(+) diff --git a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js index 9b12349c5..1eae7d816 100644 --- a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js @@ -465,6 +465,8 @@ const mapStateToProps = state => ({ activeStreamTab: state.stream.activeTab, previousStreamTab: state.stream.previousTab, commentClassNames: state.stream.commentClassNames, + + // @Deprecated plugin_config pluginsConfig: state.config.plugins_config || state.config.plugin_config, sortOrder: state.stream.sortOrder, sortBy: state.stream.sortBy, diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index 3719db8c2..b4b0a725a 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -74,6 +74,8 @@ class Slot extends React.Component { const { plugins } = this.context; let children = this.getChildren(); + // @Deprecated plugin_config + const pluginsConfig = get(reduxState, 'config.plugins_config') || get(reduxState, 'config.plugin_config') || diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index fb8ae045d..7f1323587 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -87,6 +87,7 @@ class PluginsService { getSlotComponentProps(component, reduxState, props, queryData) { if ( + process.env.NODE_ENV !== 'production' && !!get(reduxState, 'config.plugin_config') && this.showPluginsConfigWarning ) { From eb331551c5675968c90e56702c7fb70b470008b7 Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 19 Mar 2018 15:14:48 -0300 Subject: [PATCH 15/37] support for both --- plugin-api/beta/client/selectors/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugin-api/beta/client/selectors/index.js b/plugin-api/beta/client/selectors/index.js index c7951ca56..5ae41f6e0 100644 --- a/plugin-api/beta/client/selectors/index.js +++ b/plugin-api/beta/client/selectors/index.js @@ -1 +1,3 @@ -export const pluginsConfigSelector = state => state.config.pluginsConfig; +// @Deprecated plugin_config +export const pluginsConfigSelector = state => + state.config.plugins_config || state.config.plugin_config; From 8a2fa2432f611abed0a0ec0282094544d2d65326 Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 19 Mar 2018 15:26:18 -0300 Subject: [PATCH 16/37] @Deprecated plugin_config --- client/coral-framework/services/plugins.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index 7f1323587..fbd2ae21f 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -97,6 +97,7 @@ class PluginsService { this.showPluginsConfigWarning = false; } + // @Deprecated plugin_config const pluginsConfig = get(reduxState, 'config.plugins_config') || get(reduxState, 'config.plugin_config') || From d6fba2d515c1a82a7d7cd4b2caff5040c09d632d Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 20 Mar 2018 11:52:44 -0300 Subject: [PATCH 17/37] refactor into using config reducer --- .../coral-embed-stream/src/constants/debug.js | 2 -- .../src/reducers/configure.js | 2 +- .../coral-embed-stream/src/reducers/debug.js | 20 ------------------- client/coral-framework/components/Slot.js | 16 ++++++--------- client/coral-framework/constants/config.js | 2 ++ client/coral-framework/reducers/config.js | 14 ++++++++++++- 6 files changed, 22 insertions(+), 34 deletions(-) delete mode 100644 client/coral-embed-stream/src/constants/debug.js delete mode 100644 client/coral-embed-stream/src/reducers/debug.js diff --git a/client/coral-embed-stream/src/constants/debug.js b/client/coral-embed-stream/src/constants/debug.js deleted file mode 100644 index d31784af9..000000000 --- a/client/coral-embed-stream/src/constants/debug.js +++ /dev/null @@ -1,2 +0,0 @@ -export const ENABLE_PLUGINS_DEBUG = 'ENABLE_PLUGINS_DEBUG'; -export const DISABLE_PLUGINS_DEBUG = 'DISABLE_PLUGINS_DEBUG'; diff --git a/client/coral-embed-stream/src/reducers/configure.js b/client/coral-embed-stream/src/reducers/configure.js index 41d87f8d8..48b28ec72 100644 --- a/client/coral-embed-stream/src/reducers/configure.js +++ b/client/coral-embed-stream/src/reducers/configure.js @@ -8,7 +8,7 @@ const initialState = { errors: {}, }; -export default function config(state = initialState, action) { +export default function configure(state = initialState, action) { switch (action.type) { case actions.UPDATE_PENDING: { let next = state; diff --git a/client/coral-embed-stream/src/reducers/debug.js b/client/coral-embed-stream/src/reducers/debug.js deleted file mode 100644 index bcd919ebf..000000000 --- a/client/coral-embed-stream/src/reducers/debug.js +++ /dev/null @@ -1,20 +0,0 @@ -import * as actions from '../constants/debug'; - -const initialState = { - plugins: false, -}; - -export default function DEBUG(state = initialState, action) { - switch (action.type) { - case actions.ENABLE_PLUGINS_DEBUG: - return { - plugins: true, - }; - case actions.DISABLE_PLUGINS_DEBUG: - return { - plugins: false, - }; - default: - return state; - } -} diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index b4b0a725a..d60d69185 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -69,7 +69,6 @@ class Slot extends React.Component { defaultComponent: DefaultComponent, queryData, fill, - debug = {}, } = this.props; const { plugins } = this.context; let children = this.getChildren(); @@ -95,19 +94,18 @@ class Slot extends React.Component { children = children.map(childFactory); } - const debugProps = - debug.plugins || pluginsConfig.debug - ? { - 'data-slot-name': fill, - } - : {}; + const debugProps = pluginsConfig.debug + ? { + 'data-slot-name': fill, + } + : {}; return ( ({ reduxState: state, - debug: state.debug, }); export default connect(mapStateToProps, null)(Slot); diff --git a/client/coral-framework/constants/config.js b/client/coral-framework/constants/config.js index bf846af1d..b18b67387 100644 --- a/client/coral-framework/constants/config.js +++ b/client/coral-framework/constants/config.js @@ -1,3 +1,5 @@ const prefix = `TALK_FRAMEWORK`; export const MERGE_CONFIG = `${prefix}_MERGE_CONFIG`; +export const ENABLE_PLUGINS_DEBUG = `${prefix}_ENABLE_PLUGINS_DEBUG`; +export const DISABLE_PLUGINS_DEBUG = `${prefix}_DISABLE_PLUGINS_DEBUG`; diff --git a/client/coral-framework/reducers/config.js b/client/coral-framework/reducers/config.js index f7aebd9e2..eccc0d4bf 100644 --- a/client/coral-framework/reducers/config.js +++ b/client/coral-framework/reducers/config.js @@ -1,10 +1,22 @@ -import { MERGE_CONFIG } from '../constants/config'; +import { + MERGE_CONFIG, + ENABLE_PLUGINS_DEBUG, + DISABLE_PLUGINS_DEBUG, +} from '../constants/config'; import { LOGOUT } from '../constants/auth'; const initialState = {}; export default function config(state = initialState, action) { switch (action.type) { + case ENABLE_PLUGINS_DEBUG: + return { + plugins: true, + }; + case DISABLE_PLUGINS_DEBUG: + return { + plugins: false, + }; case LOGOUT: return { ...state, From aa40e7033b628d7fc333a32cf5e01c05880a0532 Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Tue, 20 Mar 2018 11:04:58 -0400 Subject: [PATCH 18/37] Update README --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 31e285607..b7818dd0a 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,17 @@ From getting up and running, to advanced configuration, to how to scale Talk, ou 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 +## Pre-Launch Guide +You’ve installed Talk on your server, and you’re preparing to launch it on your site. The real community work starts now, before you go live. You have a unique opportunity pre-launch to set your community up for success. Read our [Talk Community Guide](https://blog.coralproject.net/youve-installed-talk-now-what/). + +## More Resources + +- [Talk Product Roadmap](https://www.pivotaltracker.com/n/projects/1863625) - [Our Blog](https://blog.coralproject.net/) - [Community Forums](https://community.coralproject.net/) - [Community Guides for Journalism](https://guides.coralproject.net/) - [More About Us](https://coralproject.net/) -- [Talk Roadmap](https://www.pivotaltracker.com/n/projects/1863625) ## End-to-End Testing From 40ec1a42dcd7ff6051a7e0618a1612723020945e Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Tue, 20 Mar 2018 11:06:18 -0400 Subject: [PATCH 19/37] Fix link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b7818dd0a..6bdb7fda0 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ From getting up and running, to advanced configuration, to how to scale Talk, ou ## Product Guide -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). +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). ## Pre-Launch Guide From 030deb1b81e8a191a5850e514235e34722aeebd9 Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 20 Mar 2018 12:09:32 -0300 Subject: [PATCH 20/37] refactor into using config reducer --- client/coral-embed-stream/src/reducers/index.js | 2 -- client/coral-embed/src/Stream.js | 8 ++++++-- client/coral-embed/src/StreamInterface.js | 12 ++++++++---- client/coral-framework/actions/config.js | 14 +++++++++++++- client/coral-framework/components/Slot.js | 1 - client/coral-framework/reducers/config.js | 12 ++++++++++-- client/coral-framework/services/bootstrap.js | 12 +++++++----- 7 files changed, 44 insertions(+), 17 deletions(-) diff --git a/client/coral-embed-stream/src/reducers/index.js b/client/coral-embed-stream/src/reducers/index.js index a896e64c0..15056d414 100644 --- a/client/coral-embed-stream/src/reducers/index.js +++ b/client/coral-embed-stream/src/reducers/index.js @@ -3,7 +3,6 @@ import embed from './embed'; import configure from './configure'; import stream from './stream'; import profile from './profile'; -import debug from './debug'; export default { login, @@ -11,5 +10,4 @@ export default { configure, stream, profile, - debug, }; diff --git a/client/coral-embed/src/Stream.js b/client/coral-embed/src/Stream.js index fffa26aba..600e19741 100644 --- a/client/coral-embed/src/Stream.js +++ b/client/coral-embed/src/Stream.js @@ -161,8 +161,12 @@ export default class Stream { ); } - dispatch(action) { - this.pym.sendMessage('dispatch', action); + enableDebug() { + this.pym.sendMessage('enableDebug'); + } + + disableDebug() { + this.pym.sendMessage('disableDebug'); } login(token) { diff --git a/client/coral-embed/src/StreamInterface.js b/client/coral-embed/src/StreamInterface.js index 57339cf90..50bce0800 100644 --- a/client/coral-embed/src/StreamInterface.js +++ b/client/coral-embed/src/StreamInterface.js @@ -3,10 +3,6 @@ export default class StreamInterface { this._stream = stream; } - dispatch(action) { - return this._stream.dispatch(action); - } - on(eventName, callback) { return this._stream.emitter.on(eventName, callback); } @@ -26,4 +22,12 @@ export default class StreamInterface { remove() { return this._stream.remove(); } + + enableDebug() { + return this._stream.enableDebug(); + } + + disableDebug() { + return this._stream.disableDebug(); + } } diff --git a/client/coral-framework/actions/config.js b/client/coral-framework/actions/config.js index dd1522333..3a04d3fa4 100644 --- a/client/coral-framework/actions/config.js +++ b/client/coral-framework/actions/config.js @@ -1,6 +1,18 @@ -import { MERGE_CONFIG } from '../constants/config'; +import { + MERGE_CONFIG, + ENABLE_PLUGINS_DEBUG, + DISABLE_PLUGINS_DEBUG, +} from '../constants/config'; export const mergeConfig = config => ({ type: MERGE_CONFIG, config, }); + +export const enablePlugins = () => ({ + type: ENABLE_PLUGINS_DEBUG, +}); + +export const disablePlugins = () => ({ + type: DISABLE_PLUGINS_DEBUG, +}); diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index d60d69185..0dea70e57 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -74,7 +74,6 @@ class Slot extends React.Component { let children = this.getChildren(); // @Deprecated plugin_config - const pluginsConfig = get(reduxState, 'config.plugins_config') || get(reduxState, 'config.plugin_config') || diff --git a/client/coral-framework/reducers/config.js b/client/coral-framework/reducers/config.js index eccc0d4bf..b063f9b97 100644 --- a/client/coral-framework/reducers/config.js +++ b/client/coral-framework/reducers/config.js @@ -11,11 +11,19 @@ export default function config(state = initialState, action) { switch (action.type) { case ENABLE_PLUGINS_DEBUG: return { - plugins: true, + ...state, + plugins_config: { + ...state.plugins_config, + debug: true, + }, }; case DISABLE_PLUGINS_DEBUG: return { - plugins: false, + ...state, + plugins_config: { + ...state.plugins_config, + debug: false, + }, }; case LOGOUT: return { diff --git a/client/coral-framework/services/bootstrap.js b/client/coral-framework/services/bootstrap.js index fc06ea441..f2263ecac 100644 --- a/client/coral-framework/services/bootstrap.js +++ b/client/coral-framework/services/bootstrap.js @@ -25,7 +25,7 @@ import { createIntrospection } from 'coral-framework/services/introspection'; import introspectionData from 'coral-framework/graphql/introspection.json'; import coreReducers from '../reducers'; import { checkLogin as checkLoginAction } from '../actions/auth'; -import { mergeConfig } from '../actions/config'; +import { mergeConfig, enableDebug, disableDebug } from '../actions/config'; import { setAuthToken, logout } from '../actions/auth'; /** @@ -216,10 +216,12 @@ export async function createContext({ store.dispatch(logout()); }); - pym.onMessage('dispatch', action => { - store.dispatch({ - type: action, - }); + pym.onMessage('enableDebug', () => { + store.dispatch(enableDebug()); + }); + + pym.onMessage('disableDebug', () => { + store.dispatch(disableDebug()); }); } From cd9c26099531d120ed06bd3839eb5711b550ed60 Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 20 Mar 2018 13:10:42 -0300 Subject: [PATCH 21/37] refactor into using config reducer --- client/coral-embed/src/Stream.js | 8 ++++---- client/coral-embed/src/StreamInterface.js | 8 ++++---- client/coral-framework/actions/config.js | 4 ++-- client/coral-framework/services/bootstrap.js | 14 +++++++++----- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/client/coral-embed/src/Stream.js b/client/coral-embed/src/Stream.js index 600e19741..d0ada6080 100644 --- a/client/coral-embed/src/Stream.js +++ b/client/coral-embed/src/Stream.js @@ -161,12 +161,12 @@ export default class Stream { ); } - enableDebug() { - this.pym.sendMessage('enableDebug'); + enablePluginsDebug() { + this.pym.sendMessage('enablePluginsDebug'); } - disableDebug() { - this.pym.sendMessage('disableDebug'); + disablePluginsDebug() { + this.pym.sendMessage('disablePluginsDebug'); } login(token) { diff --git a/client/coral-embed/src/StreamInterface.js b/client/coral-embed/src/StreamInterface.js index 50bce0800..1e54dd155 100644 --- a/client/coral-embed/src/StreamInterface.js +++ b/client/coral-embed/src/StreamInterface.js @@ -23,11 +23,11 @@ export default class StreamInterface { return this._stream.remove(); } - enableDebug() { - return this._stream.enableDebug(); + enablePluginsDebug() { + return this._stream.enablePluginsDebug(); } - disableDebug() { - return this._stream.disableDebug(); + disablePluginsDebug() { + return this._stream.disablePluginsDebug(); } } diff --git a/client/coral-framework/actions/config.js b/client/coral-framework/actions/config.js index 3a04d3fa4..859fac4d5 100644 --- a/client/coral-framework/actions/config.js +++ b/client/coral-framework/actions/config.js @@ -9,10 +9,10 @@ export const mergeConfig = config => ({ config, }); -export const enablePlugins = () => ({ +export const enablePluginsDebug = () => ({ type: ENABLE_PLUGINS_DEBUG, }); -export const disablePlugins = () => ({ +export const disablePluginsDebug = () => ({ type: DISABLE_PLUGINS_DEBUG, }); diff --git a/client/coral-framework/services/bootstrap.js b/client/coral-framework/services/bootstrap.js index f2263ecac..878c2e303 100644 --- a/client/coral-framework/services/bootstrap.js +++ b/client/coral-framework/services/bootstrap.js @@ -25,7 +25,11 @@ import { createIntrospection } from 'coral-framework/services/introspection'; import introspectionData from 'coral-framework/graphql/introspection.json'; import coreReducers from '../reducers'; import { checkLogin as checkLoginAction } from '../actions/auth'; -import { mergeConfig, enableDebug, disableDebug } from '../actions/config'; +import { + mergeConfig, + enablePluginsDebug, + disablePluginsDebug, +} from '../actions/config'; import { setAuthToken, logout } from '../actions/auth'; /** @@ -216,12 +220,12 @@ export async function createContext({ store.dispatch(logout()); }); - pym.onMessage('enableDebug', () => { - store.dispatch(enableDebug()); + pym.onMessage('enablePluginsDebug', () => { + store.dispatch(enablePluginsDebug()); }); - pym.onMessage('disableDebug', () => { - store.dispatch(disableDebug()); + pym.onMessage('disablePluginsDebug', () => { + store.dispatch(disablePluginsDebug()); }); } From b6ba59ac513351b96470c1b023e7ee5deb53bb59 Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 20 Mar 2018 13:19:20 -0300 Subject: [PATCH 22/37] using the plugins service --- .../src/tabs/stream/containers/Stream.js | 3 --- client/coral-framework/components/Slot.js | 7 ------- client/coral-framework/services/plugins.js | 8 ++++++++ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js index 1eae7d816..9687a9370 100644 --- a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js @@ -465,9 +465,6 @@ const mapStateToProps = state => ({ activeStreamTab: state.stream.activeTab, previousStreamTab: state.stream.previousTab, commentClassNames: state.stream.commentClassNames, - - // @Deprecated plugin_config - pluginsConfig: state.config.plugins_config || state.config.plugin_config, sortOrder: state.stream.sortOrder, sortBy: state.stream.sortBy, }); diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index 0dea70e57..049d075ab 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -93,12 +93,6 @@ class Slot extends React.Component { children = children.map(childFactory); } - const debugProps = pluginsConfig.debug - ? { - 'data-slot-name': fill, - } - : {}; - return ( {children} diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index fbd2ae21f..8f9ad5b41 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -102,8 +102,16 @@ class PluginsService { get(reduxState, 'config.plugins_config') || get(reduxState, 'config.plugin_config') || emptyConfig; + + const debugProps = pluginsConfig.debug + ? { + 'data-slot-name': props.fill, + } + : {}; + return { ...props, + ...debugProps, config: pluginsConfig, ...(component.fragments ? pick(queryData, Object.keys(component.fragments)) From 6c35f02e6b722506fc89c902119d63a543977f15 Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 20 Mar 2018 13:50:28 -0300 Subject: [PATCH 23/37] changes --- client/coral-framework/components/Slot.js | 10 +++++++--- client/coral-framework/services/plugins.js | 12 +++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index 049d075ab..e6a3eda2d 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -8,6 +8,7 @@ import isEqual from 'lodash/isEqual'; import get from 'lodash/get'; import { getShallowChanges } from 'coral-framework/utils'; import omit from 'lodash/omit'; +import merge from 'lodash/merge'; const emptyConfig = {}; @@ -75,9 +76,10 @@ class Slot extends React.Component { // @Deprecated plugin_config const pluginsConfig = - get(reduxState, 'config.plugins_config') || - get(reduxState, 'config.plugin_config') || - emptyConfig; + merge( + get(reduxState, 'config.plugins_config'), + get(reduxState, 'config.plugin_config') + ) || emptyConfig; if (children.length === 0 && DefaultComponent) { const props = plugins.getSlotComponentProps( @@ -93,6 +95,8 @@ class Slot extends React.Component { children = children.map(childFactory); } + // console.log('pluginsConfig', pluginsConfig); + return ( Date: Tue, 20 Mar 2018 13:04:13 -0400 Subject: [PATCH 24/37] English version of docs --- docs/source/04-06-slots-and-plugins.md | 169 +++++++++++++++++++ docs/source/plugins/slots-and-plugins-ES.md | 157 ++++++++++++++++++ docs/source/plugins/slots-and-plugins.md | 170 ++++++++++++++++++++ 3 files changed, 496 insertions(+) create mode 100644 docs/source/04-06-slots-and-plugins.md create mode 100644 docs/source/plugins/slots-and-plugins-ES.md create mode 100644 docs/source/plugins/slots-and-plugins.md diff --git a/docs/source/04-06-slots-and-plugins.md b/docs/source/04-06-slots-and-plugins.md new file mode 100644 index 000000000..86e3addeb --- /dev/null +++ b/docs/source/04-06-slots-and-plugins.md @@ -0,0 +1,169 @@ +--- +title: Slots and Plugins +permalink: /slots-and-plugins/ +--- + +Plugins make use of **"slots"** in order to change Talk's interface. + +By default, Talk has various plugins provided by default. We can see this in `plugins.default.json`: + +```json +{ + "server": [ + "talk-plugin-auth", + "talk-plugin-featured-comments", + "talk-plugin-offtopic", + "talk-plugin-respect" + ], + "client": [ + "talk-plugin-auth", + "talk-plugin-author-menu", + "talk-plugin-comment-content", + "talk-plugin-featured-comments", + "talk-plugin-flag-details", + "talk-plugin-ignore-user", + "talk-plugin-member-since", + "talk-plugin-moderation-actions", + "talk-plugin-offtopic", + "talk-plugin-permalink", + "talk-plugin-respect", + "talk-plugin-sort-most-replied", + "talk-plugin-sort-most-respected", + "talk-plugin-sort-newest", + "talk-plugin-sort-oldest", + "talk-plugin-viewing-options", + "talk-plugin-profile-settings" + ] +} +``` + +Let's only focus on the plugins which are listed under `client` - these are the plugins that use *slots* to inject certain functionality into the Talk UI. + +For example, if we look at the Respect plugin (`talk-plugin-respect`), we can see its `client/index.js` looks like this: + + +```js +import RespectButton from './RespectButton'; +import translations from './translations.yml'; + +export default { + translations, + slots: { + commentReactions: [RespectButton], + }, +}; + +``` + +Inside the `slots` property, we specify which **slots** the plugin will use. Above we are saying that the `RespectButton` component is being injected into the slot `commentReactions`. + +Slots can receive an Array of components, so we can use one plugin or many for one slot. + +### Anatomy of the Slot Component + +In Talk core, we have 32 slots available for us to use. The component `Slot` has a `fill` property where we establish the name of the slot. It looks like this: + + +```js + +``` + +You won't have to use this to build plugins, but it's helpful to find where to embed your plugin. + +### Slot List + +* `adminCommentDetailArea` +* `adminCommentMoreDetails` +* `adminCommentLabels` +* `adminModerationSettings` +* `adminStreamSettings` +* `adminTechSettings` +* `adminCommentInfoBar` +* `adminCommentContent` +* `adminSideActions` +* `adminModeration` +* `adminModerationIndicator` + +* `commentInputDetailArea` +* `commentAvatar` +* `commentAuthorName` +* `commentAuthorTags` +* `commentTimestamp` +* `commentInfoBar` +* `commentContent` +* `commentReactions` +* `commentActions` +* `commentInputArea` + +* `draftArea` +* `streamSettings` +* `historyCommentTimestamp` +* `profileSections` +* `embed` +* `stream` +* `streamFilter` +* `streamQuestionArea` +* `login` +* `userProfile` +* `userDetailCommentContent` + +### Where should I insert my plugin? + +The first thing we should consider is what components will be affected by our plugin's functionality. For example, if we want to add functionality to all the comments that are rendered in a total list of comments, we would use the component `Comment`. + +The slots that are able to add functionality to comments start with `comment`, like `commentContent`, or `commentReactions`, as you can see above. + +### Disabling plugins via `plugins_config` + +Typically, you will manage plugins via your `plugins.json` file. If you want to remove a plugin, you would simply delete it there. However, we can also do this directly with the `plugins_config`. + +Let's look at our example article, `views/article.ejs`. Here we see can we have the Talk embed, and within the embed, we can also send a configuration object. To disable a plugin visually, we can pass `true` to the property `disable_components`. Like so: + + +```js +plugins_config: { + 'talk-plugin-love': { + disable_components: true, + }, +} +``` + +### Sending information to slots and plugins + + +Inside our `plugins_config`, we can also send properities and our plugins will receive them. For example, if we send this: + +```js +plugins_config: { + test: 'data' +} +``` + +The plugin will receive a config object with the properties we've passed. If we do a `console.log` with `this.props`, we would see: + +```js +config: {test: 'data'} +``` + +### Debugging slots and plugins + + +You can debug slots and plugins simply by passing the `debug` property with value `true`: + + +```js +plugins_config: { + debug: true +} +``` + +This will turn on a visual aid to show you all of Talk's available slots and their names. Just move your mouse around! + +### Slot ClassNames + +Slots autogenerate their classes with the prefix `talk-slot`, followed by the name of the slot in kebab case. + +For example, the class autogenerated for the slot `commentContent` is `talk-slot-comment-content`. diff --git a/docs/source/plugins/slots-and-plugins-ES.md b/docs/source/plugins/slots-and-plugins-ES.md new file mode 100644 index 000000000..846ccd033 --- /dev/null +++ b/docs/source/plugins/slots-and-plugins-ES.md @@ -0,0 +1,157 @@ +# Plugins y Slots +Los *Slots* son una parte muy importante para crear plugins. Estos nos permiten inyectar nuestros plugins en la interfaz visual de Talk. + +Talk por defecto muestra varios plugins - Observemos el archivo `plugins.default.json` : + +```json +{ + "server": [ + "talk-plugin-auth", + "talk-plugin-featured-comments", + "talk-plugin-offtopic", + "talk-plugin-respect" + ], + "client": [ + "talk-plugin-auth", + "talk-plugin-author-menu", + "talk-plugin-comment-content", + "talk-plugin-featured-comments", + "talk-plugin-flag-details", + "talk-plugin-ignore-user", + "talk-plugin-member-since", + "talk-plugin-moderation-actions", + "talk-plugin-offtopic", + "talk-plugin-permalink", + "talk-plugin-respect", + "talk-plugin-sort-most-replied", + "talk-plugin-sort-most-respected", + "talk-plugin-sort-newest", + "talk-plugin-sort-oldest", + "talk-plugin-viewing-options", + "talk-plugin-profile-settings" + ] +} +``` + +La parte que nos interesa es `client`, ya que estos son los plugins que van a utilizar los *slots* para meterse en distintas partes de Talk. + +Por ejemplo: Si observamos el plugin `talk-plugin-respect`, que está dentro de la carpeta `plugins` vamos a notar que el `client/index.js` luce asi: + +```js +import RespectButton from './RespectButton'; +import translations from './translations.yml'; + +export default { + translations, + slots: { + commentReactions: [RespectButton], + }, +}; + +``` + +Dentro de la propiedad `slots` especificamos qué *slots* utilizará el plugin. Ahí estamos diciendo que el componente `RespectButton` se incrustará en el slot `commentReactions`. + +Los slots reciben un /Array/ de componentes. Es decir, puede ser uno o varios. + +### Anatomía del component Slot +En el core de Talk tenemos 32 slots declarados. El componente Slot tiene una propiedad `fill` donde establecemos el nombre del slot. Una declaración de un `` luce así: + +```js + +``` + +Esto probablemente no lo utilices para desarrollar plugins, pero sí para buscar donde se va a embeber tu plugin. + +### Lista de Slots + +* `adminCommentDetailArea` +* `adminCommentMoreDetails` +* `adminCommentLabels` +* `adminModerationSettings` +* `adminStreamSettings` +* `adminTechSettings` +* `adminCommentInfoBar` +* `adminCommentContent` +* `adminSideActions` +* `adminModeration` +* `adminModerationIndicator` + +* `commentInputDetailArea` +* `commentAvatar` +* `commentAuthorName` +* `commentAuthorTags` +* `commentTimestamp` +* `commentInfoBar` +* `commentContent` +* `commentReactions` +* `commentActions` +* `commentInputArea` + +* `draftArea` +* `streamSettings` +* `historyCommentTimestamp` +* `profileSections` +* `embed` +* `stream` +* `streamFilter` +* `streamQuestionArea` +* `login` +* `userProfile` +* `userDetailCommentContent` + +### Cómo sé donde colocar mi plugin? + +Lo primero que debemos pensar es a qué componente afectará la funcionalidad del plugin. Por ejemplo, si queremos agregar funcionalidad a todos los comentarios que se renderizan en la lista total de comentarios, esto tendrá que ver con el componente `Comment`. + +Los slots habilitados para agregar funcionalidad a los comentarios tienen un prefix `comment` como el `commentContent` o el `commentReactions`, que vimos previamente. + +### Deshabilitando plugins por configuración + +Los plugins se eliminan borrando su entrada en el `plugins.json`. Pero si por alguna razón necesitamos hacerlo por configuración, podemos hacerlo. + +Dentro de `views/article.ejs` embebemos Talk y notarás que podemos envialarle un objeto de configuración. Para deshabilitar visualmente a los plugins podemos utilizar la propiedad `disable_components` en `true`. y se utiliza de la siguiente forma: + +```js +plugins_config: { + 'talk-plugin-love': { + disable_components: true, + }, +} +``` + +### Enviando información a los slots / plugins + +Dentro de `plugins_config` podemos pasar todas las propiedades que queramos y los plugins las recibirán. + +Por ejemplo: Si enviamos esto +```js +plugins_config: { + test: 'data' +} +``` + +El plugin recibirá por props un objeto config con las propiedades que le pasamos. Haciendo un console.log de `this.props` verás: + +```js +config: {test: 'data'} +``` + +### Debug Slots + +Podés debuggear Slots / Plugins sólo con pasar la propiedad `debug` con valor `true`. + +```js +plugins_config: { + debug: true +} +``` + +Esto mostrará todos los slots disponibles en la UI y su nombre si pasas el mouse sobre ellos. + +### Slot ClassNames +Los slots autogeneran sus clases con el prefijo `talk-slot-` seguido del nombre del slot en kebab case. +Por ejemplo, la clase autogenerada del slot `commentContent` es `talk-slot-comment-content`. \ No newline at end of file diff --git a/docs/source/plugins/slots-and-plugins.md b/docs/source/plugins/slots-and-plugins.md new file mode 100644 index 000000000..d230ac0ba --- /dev/null +++ b/docs/source/plugins/slots-and-plugins.md @@ -0,0 +1,170 @@ +--- +title: Plugins Overview +permalink: /plugin-slots/ +toc: true +--- + +Plugins make use of "slots" in order to change Talk's interface. + +By default, Talk has various plugins provided by default. We can see this in `plugins.default.json`: + +```json +{ + "server": [ + "talk-plugin-auth", + "talk-plugin-featured-comments", + "talk-plugin-offtopic", + "talk-plugin-respect" + ], + "client": [ + "talk-plugin-auth", + "talk-plugin-author-menu", + "talk-plugin-comment-content", + "talk-plugin-featured-comments", + "talk-plugin-flag-details", + "talk-plugin-ignore-user", + "talk-plugin-member-since", + "talk-plugin-moderation-actions", + "talk-plugin-offtopic", + "talk-plugin-permalink", + "talk-plugin-respect", + "talk-plugin-sort-most-replied", + "talk-plugin-sort-most-respected", + "talk-plugin-sort-newest", + "talk-plugin-sort-oldest", + "talk-plugin-viewing-options", + "talk-plugin-profile-settings" + ] +} +``` + +Let's only focus on the plugins which are listed under `client` - these are the plugins that use *slots* to inject certain functionality into the Talk UI. + +For example, if we look at the Respect plugin (`talk-plugin-respect`), we can see its `client/index.js` looks like this: + + +```js +import RespectButton from './RespectButton'; +import translations from './translations.yml'; + +export default { + translations, + slots: { + commentReactions: [RespectButton], + }, +}; + +``` + +Inside the `slots` property, we specify what *slots* the plugin will use. Above we are saying that the `RespectButton` component is being injected into the slot `commentReactions`. + +Slots can receive an Array of components, so we can use one plugin or many for one slot. + +### Anatomy of the Slot Component + +In Talk core, we have 32 slots available for us to use. The component `Slot` has a `fill` property where we establish the name of the slot. It looks like this: + + +```js + +``` + +You won't have to use this to build plugins, but it's helpful to find where to embed your plugin. + +### Slot List + +* `adminCommentDetailArea` +* `adminCommentMoreDetails` +* `adminCommentLabels` +* `adminModerationSettings` +* `adminStreamSettings` +* `adminTechSettings` +* `adminCommentInfoBar` +* `adminCommentContent` +* `adminSideActions` +* `adminModeration` +* `adminModerationIndicator` + +* `commentInputDetailArea` +* `commentAvatar` +* `commentAuthorName` +* `commentAuthorTags` +* `commentTimestamp` +* `commentInfoBar` +* `commentContent` +* `commentReactions` +* `commentActions` +* `commentInputArea` + +* `draftArea` +* `streamSettings` +* `historyCommentTimestamp` +* `profileSections` +* `embed` +* `stream` +* `streamFilter` +* `streamQuestionArea` +* `login` +* `userProfile` +* `userDetailCommentContent` + +### Where should I insert my plugin? + +The first thing we should consider is what components will be affected by our plugin's functionality. For example, if we want to add functionality to all the comments that are rendered in a total list of comments, we would use the component `Comment`. + +The slots that are able to add functionality to comments start with `comment`, like `commentContent`, or `commentReactions`, as you can see above. + +### Disabling plugins via `plugins_config` + +Typically, you will manage plugins via your `plugins.json` file. If you want to remove a plugin, you would simply delete it there. However, we can also do this directly with the `plugins_config`. + +Let's look at our example article, `views/article.ejs`. Here we see can we have the Talk embed, and within the embed, we can also send a configuration object. To disable a plugin visually, we can pass `true` to the property `disable_components`. Like so: + + +```js +plugins_config: { + 'talk-plugin-love': { + disable_components: true, + }, +} +``` + +### Sending information to slots and plugins + + +Inside our `plugins_config`, we can also send properities and our plugins will receive them. For example, if we send this: + +```js +plugins_config: { + test: 'data' +} +``` + +The plugin will receive a config object with the properties we've passed. If we do a `console.log` with `this.props`, we would see: + +```js +config: {test: 'data'} +``` + +### Debugging slots and plugins + + +You can debug slots and plugins simply by passing the `debug` property with value `true`: + + +```js +plugins_config: { + debug: true +} +``` + +This will turn on a visual aid to show you all of Talk's available slots and their names. Just move your mouse around! + +### Slot ClassNames + +Slots autogenerate their classes with the prefix `talk-slot`, followed by the name of the slot in kebab case. + +For example, the class autogenerated for the slot `commentContent` is `talk-slot-comment-content`. From 8fc69b05516884877f043a62b2d403a22c164f5f Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Tue, 20 Mar 2018 13:06:37 -0400 Subject: [PATCH 25/37] Translate Slot docs into English --- docs/_config.yml | 2 + docs/_docs/04-05-talk-slots-and-plugins-ES.md | 157 ------------------ 2 files changed, 2 insertions(+), 157 deletions(-) delete mode 100644 docs/_docs/04-05-talk-slots-and-plugins-ES.md diff --git a/docs/_config.yml b/docs/_config.yml index 2a6fa2725..f524fed0a 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -136,6 +136,8 @@ sidebar: url: /plugins-directory/ - title: Plugin Recipes url: /plugin-recipes/ + - title: Slots and Plugins + url: /slots-and-plugins/ - title: Tutorials children: - title: Creating a Basic Plugin diff --git a/docs/_docs/04-05-talk-slots-and-plugins-ES.md b/docs/_docs/04-05-talk-slots-and-plugins-ES.md deleted file mode 100644 index 846ccd033..000000000 --- a/docs/_docs/04-05-talk-slots-and-plugins-ES.md +++ /dev/null @@ -1,157 +0,0 @@ -# Plugins y Slots -Los *Slots* son una parte muy importante para crear plugins. Estos nos permiten inyectar nuestros plugins en la interfaz visual de Talk. - -Talk por defecto muestra varios plugins - Observemos el archivo `plugins.default.json` : - -```json -{ - "server": [ - "talk-plugin-auth", - "talk-plugin-featured-comments", - "talk-plugin-offtopic", - "talk-plugin-respect" - ], - "client": [ - "talk-plugin-auth", - "talk-plugin-author-menu", - "talk-plugin-comment-content", - "talk-plugin-featured-comments", - "talk-plugin-flag-details", - "talk-plugin-ignore-user", - "talk-plugin-member-since", - "talk-plugin-moderation-actions", - "talk-plugin-offtopic", - "talk-plugin-permalink", - "talk-plugin-respect", - "talk-plugin-sort-most-replied", - "talk-plugin-sort-most-respected", - "talk-plugin-sort-newest", - "talk-plugin-sort-oldest", - "talk-plugin-viewing-options", - "talk-plugin-profile-settings" - ] -} -``` - -La parte que nos interesa es `client`, ya que estos son los plugins que van a utilizar los *slots* para meterse en distintas partes de Talk. - -Por ejemplo: Si observamos el plugin `talk-plugin-respect`, que está dentro de la carpeta `plugins` vamos a notar que el `client/index.js` luce asi: - -```js -import RespectButton from './RespectButton'; -import translations from './translations.yml'; - -export default { - translations, - slots: { - commentReactions: [RespectButton], - }, -}; - -``` - -Dentro de la propiedad `slots` especificamos qué *slots* utilizará el plugin. Ahí estamos diciendo que el componente `RespectButton` se incrustará en el slot `commentReactions`. - -Los slots reciben un /Array/ de componentes. Es decir, puede ser uno o varios. - -### Anatomía del component Slot -En el core de Talk tenemos 32 slots declarados. El componente Slot tiene una propiedad `fill` donde establecemos el nombre del slot. Una declaración de un `` luce así: - -```js - -``` - -Esto probablemente no lo utilices para desarrollar plugins, pero sí para buscar donde se va a embeber tu plugin. - -### Lista de Slots - -* `adminCommentDetailArea` -* `adminCommentMoreDetails` -* `adminCommentLabels` -* `adminModerationSettings` -* `adminStreamSettings` -* `adminTechSettings` -* `adminCommentInfoBar` -* `adminCommentContent` -* `adminSideActions` -* `adminModeration` -* `adminModerationIndicator` - -* `commentInputDetailArea` -* `commentAvatar` -* `commentAuthorName` -* `commentAuthorTags` -* `commentTimestamp` -* `commentInfoBar` -* `commentContent` -* `commentReactions` -* `commentActions` -* `commentInputArea` - -* `draftArea` -* `streamSettings` -* `historyCommentTimestamp` -* `profileSections` -* `embed` -* `stream` -* `streamFilter` -* `streamQuestionArea` -* `login` -* `userProfile` -* `userDetailCommentContent` - -### Cómo sé donde colocar mi plugin? - -Lo primero que debemos pensar es a qué componente afectará la funcionalidad del plugin. Por ejemplo, si queremos agregar funcionalidad a todos los comentarios que se renderizan en la lista total de comentarios, esto tendrá que ver con el componente `Comment`. - -Los slots habilitados para agregar funcionalidad a los comentarios tienen un prefix `comment` como el `commentContent` o el `commentReactions`, que vimos previamente. - -### Deshabilitando plugins por configuración - -Los plugins se eliminan borrando su entrada en el `plugins.json`. Pero si por alguna razón necesitamos hacerlo por configuración, podemos hacerlo. - -Dentro de `views/article.ejs` embebemos Talk y notarás que podemos envialarle un objeto de configuración. Para deshabilitar visualmente a los plugins podemos utilizar la propiedad `disable_components` en `true`. y se utiliza de la siguiente forma: - -```js -plugins_config: { - 'talk-plugin-love': { - disable_components: true, - }, -} -``` - -### Enviando información a los slots / plugins - -Dentro de `plugins_config` podemos pasar todas las propiedades que queramos y los plugins las recibirán. - -Por ejemplo: Si enviamos esto -```js -plugins_config: { - test: 'data' -} -``` - -El plugin recibirá por props un objeto config con las propiedades que le pasamos. Haciendo un console.log de `this.props` verás: - -```js -config: {test: 'data'} -``` - -### Debug Slots - -Podés debuggear Slots / Plugins sólo con pasar la propiedad `debug` con valor `true`. - -```js -plugins_config: { - debug: true -} -``` - -Esto mostrará todos los slots disponibles en la UI y su nombre si pasas el mouse sobre ellos. - -### Slot ClassNames -Los slots autogeneran sus clases con el prefijo `talk-slot-` seguido del nombre del slot en kebab case. -Por ejemplo, la clase autogenerada del slot `commentContent` es `talk-slot-comment-content`. \ No newline at end of file From dbe80c40d7a370d257289983bec54968645a71d6 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 20 Mar 2018 18:25:04 +0100 Subject: [PATCH 26/37] Render when pluginsConfig changes --- client/coral-framework/hocs/withSlotElements.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/coral-framework/hocs/withSlotElements.js b/client/coral-framework/hocs/withSlotElements.js index a4b39c907..dc44f97db 100644 --- a/client/coral-framework/hocs/withSlotElements.js +++ b/client/coral-framework/hocs/withSlotElements.js @@ -83,6 +83,11 @@ const createHOC = ({ } if (changes.length === 1 && changes[0] === 'reduxState') { + // If pluginsConfig changed, we'll have to rerender everything. + if (this.props.reduxState.pluginsConfig !== next.reduxState.pluginsConfig) { + return true; + } + const prevChildrenKeys = this.getSlotElements(this.props).map( child => child.key ); From 84a79be9c1ed4edbb8413ce6dcff6765e8fcdcee Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 20 Mar 2018 18:31:09 +0100 Subject: [PATCH 27/37] Only use plugins_config in redux --- client/coral-framework/components/Slot.js | 1 + client/coral-framework/services/bootstrap.js | 12 +++++- client/coral-framework/services/plugins.js | 39 +------------------- 3 files changed, 13 insertions(+), 39 deletions(-) diff --git a/client/coral-framework/components/Slot.js b/client/coral-framework/components/Slot.js index a2f90161f..048c4da80 100644 --- a/client/coral-framework/components/Slot.js +++ b/client/coral-framework/components/Slot.js @@ -30,6 +30,7 @@ class Slot extends React.Component { className, `talk-slot-${kebabCase(fill)}` )} + data-slot-name={fill} > {children} diff --git a/client/coral-framework/services/bootstrap.js b/client/coral-framework/services/bootstrap.js index 878c2e303..82a55cdec 100644 --- a/client/coral-framework/services/bootstrap.js +++ b/client/coral-framework/services/bootstrap.js @@ -66,8 +66,16 @@ function initExternalConfig({ store, pym, inIframe }) { } return new Promise(resolve => { pym.sendMessage('getConfig'); - pym.onMessage('config', config => { - store.dispatch(mergeConfig(JSON.parse(config))); + pym.onMessage('config', rawConfig => { + const config = JSON.parse(rawConfig); + if (config.plugin_config) { + console.warn( + 'Deprecation Warning: `config.plugin_config` will be phased out soon, please replace `config.plugin_config with `config.plugins_config`' + ); + config.plugins_config = config.plugin_config; + delete config.plugin_config; + } + store.dispatch(mergeConfig(config)); resolve(); }); }); diff --git a/client/coral-framework/services/plugins.js b/client/coral-framework/services/plugins.js index 3bc9bc5bc..bb16fc5e7 100644 --- a/client/coral-framework/services/plugins.js +++ b/client/coral-framework/services/plugins.js @@ -68,47 +68,14 @@ function addMetaDataToSlotComponents(plugins) { }); } -// @Deprecated -const showPluginConfigDeprecationWarningOnce = (() => { - let shown = false; - return () => { - if (!shown) { - shown = true; - console.warn( - `deprecation warning: config.plugin_config will be phased out soon, please replace calls from config.plugin_config to config.plugins_config` - ); - } - }; -})(); - /** * getSlotComponentProps calculate the props we would pass to the slot component. * query datas are only passed to the component if it is defined in `component.fragments`. */ function getSlotComponentProps(component, reduxState, props, queryData) { - // @Deprecated - const pluginsConfig = - get(reduxState, 'config.plugins_config') || - get(reduxState, 'config.plugin_config') || - emptyConfig; - - if ( - process.env.NODE_ENV !== 'production' && - !!get(reduxState, 'config.plugin_config') - ) { - showPluginConfigDeprecationWarningOnce(); - } - - console.log('slot plugins_config', get(reduxState, 'config.plugins_config')); - - const debugProps = pluginsConfig.debug - ? { - 'data-slot-name': props.fill, - } - : {}; + const pluginsConfig = get(reduxState, 'config.plugins_config') || emptyConfig; return { ...props, - ...debugProps, config: pluginsConfig, ...(component.fragments ? pick(queryData, Object.keys(component.fragments)) @@ -159,9 +126,7 @@ class PluginsService { */ getSlotElements(slot, reduxState, props = {}, options = {}) { const pluginsConfig = - get(reduxState, 'config.plugins_config') || - get(reduxState, 'config.plugin_config') || - emptyConfig; + get(reduxState, 'config.plugins_config') || emptyConfig; const { size = 0 } = options; const { queryData, rest } = splitProps(props); From d98e64d6d7e15702a0c5073caf39a33e39361761 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 20 Mar 2018 18:45:56 +0100 Subject: [PATCH 28/37] Deprecation stuff --- client/coral-framework/services/bootstrap.js | 9 ++++++--- plugin-api/beta/client/selectors/index.js | 4 +--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/client/coral-framework/services/bootstrap.js b/client/coral-framework/services/bootstrap.js index 82a55cdec..e0bfbb950 100644 --- a/client/coral-framework/services/bootstrap.js +++ b/client/coral-framework/services/bootstrap.js @@ -69,9 +69,12 @@ function initExternalConfig({ store, pym, inIframe }) { pym.onMessage('config', rawConfig => { const config = JSON.parse(rawConfig); if (config.plugin_config) { - console.warn( - 'Deprecation Warning: `config.plugin_config` will be phased out soon, please replace `config.plugin_config with `config.plugins_config`' - ); + // @Deprecated + if (process.env.NODE_ENV !== 'production') { + console.warn( + 'Deprecation Warning: `config.plugin_config` will be phased out soon, please replace `config.plugin_config with `config.plugins_config`' + ); + } config.plugins_config = config.plugin_config; delete config.plugin_config; } diff --git a/plugin-api/beta/client/selectors/index.js b/plugin-api/beta/client/selectors/index.js index 5ae41f6e0..c3a0b6821 100644 --- a/plugin-api/beta/client/selectors/index.js +++ b/plugin-api/beta/client/selectors/index.js @@ -1,3 +1 @@ -// @Deprecated plugin_config -export const pluginsConfigSelector = state => - state.config.plugins_config || state.config.plugin_config; +export const pluginsConfigSelector = state => state.config.plugins_config; From d08aaecd127ed790890970d107661e1421b6e7b0 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 20 Mar 2018 19:00:19 +0100 Subject: [PATCH 29/37] Rerender all Slot Components when config changes --- client/coral-framework/hocs/withSlotElements.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/coral-framework/hocs/withSlotElements.js b/client/coral-framework/hocs/withSlotElements.js index dc44f97db..9b432ade8 100644 --- a/client/coral-framework/hocs/withSlotElements.js +++ b/client/coral-framework/hocs/withSlotElements.js @@ -83,8 +83,10 @@ const createHOC = ({ } if (changes.length === 1 && changes[0] === 'reduxState') { - // If pluginsConfig changed, we'll have to rerender everything. - if (this.props.reduxState.pluginsConfig !== next.reduxState.pluginsConfig) { + // If config changed, we'll have to rerender everything. + // Should only happen during development as this is + // usually static. + if (this.props.reduxState.config !== next.reduxState.config) { return true; } From cd2426511c0c0c05b58ca4fe81a2bb64e84777b0 Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Tue, 20 Mar 2018 14:08:23 -0400 Subject: [PATCH 30/37] Remove dupe files --- docs/source/plugins/slots-and-plugins-ES.md | 157 ------------------ docs/source/plugins/slots-and-plugins.md | 170 -------------------- 2 files changed, 327 deletions(-) delete mode 100644 docs/source/plugins/slots-and-plugins-ES.md delete mode 100644 docs/source/plugins/slots-and-plugins.md diff --git a/docs/source/plugins/slots-and-plugins-ES.md b/docs/source/plugins/slots-and-plugins-ES.md deleted file mode 100644 index 846ccd033..000000000 --- a/docs/source/plugins/slots-and-plugins-ES.md +++ /dev/null @@ -1,157 +0,0 @@ -# Plugins y Slots -Los *Slots* son una parte muy importante para crear plugins. Estos nos permiten inyectar nuestros plugins en la interfaz visual de Talk. - -Talk por defecto muestra varios plugins - Observemos el archivo `plugins.default.json` : - -```json -{ - "server": [ - "talk-plugin-auth", - "talk-plugin-featured-comments", - "talk-plugin-offtopic", - "talk-plugin-respect" - ], - "client": [ - "talk-plugin-auth", - "talk-plugin-author-menu", - "talk-plugin-comment-content", - "talk-plugin-featured-comments", - "talk-plugin-flag-details", - "talk-plugin-ignore-user", - "talk-plugin-member-since", - "talk-plugin-moderation-actions", - "talk-plugin-offtopic", - "talk-plugin-permalink", - "talk-plugin-respect", - "talk-plugin-sort-most-replied", - "talk-plugin-sort-most-respected", - "talk-plugin-sort-newest", - "talk-plugin-sort-oldest", - "talk-plugin-viewing-options", - "talk-plugin-profile-settings" - ] -} -``` - -La parte que nos interesa es `client`, ya que estos son los plugins que van a utilizar los *slots* para meterse en distintas partes de Talk. - -Por ejemplo: Si observamos el plugin `talk-plugin-respect`, que está dentro de la carpeta `plugins` vamos a notar que el `client/index.js` luce asi: - -```js -import RespectButton from './RespectButton'; -import translations from './translations.yml'; - -export default { - translations, - slots: { - commentReactions: [RespectButton], - }, -}; - -``` - -Dentro de la propiedad `slots` especificamos qué *slots* utilizará el plugin. Ahí estamos diciendo que el componente `RespectButton` se incrustará en el slot `commentReactions`. - -Los slots reciben un /Array/ de componentes. Es decir, puede ser uno o varios. - -### Anatomía del component Slot -En el core de Talk tenemos 32 slots declarados. El componente Slot tiene una propiedad `fill` donde establecemos el nombre del slot. Una declaración de un `` luce así: - -```js - -``` - -Esto probablemente no lo utilices para desarrollar plugins, pero sí para buscar donde se va a embeber tu plugin. - -### Lista de Slots - -* `adminCommentDetailArea` -* `adminCommentMoreDetails` -* `adminCommentLabels` -* `adminModerationSettings` -* `adminStreamSettings` -* `adminTechSettings` -* `adminCommentInfoBar` -* `adminCommentContent` -* `adminSideActions` -* `adminModeration` -* `adminModerationIndicator` - -* `commentInputDetailArea` -* `commentAvatar` -* `commentAuthorName` -* `commentAuthorTags` -* `commentTimestamp` -* `commentInfoBar` -* `commentContent` -* `commentReactions` -* `commentActions` -* `commentInputArea` - -* `draftArea` -* `streamSettings` -* `historyCommentTimestamp` -* `profileSections` -* `embed` -* `stream` -* `streamFilter` -* `streamQuestionArea` -* `login` -* `userProfile` -* `userDetailCommentContent` - -### Cómo sé donde colocar mi plugin? - -Lo primero que debemos pensar es a qué componente afectará la funcionalidad del plugin. Por ejemplo, si queremos agregar funcionalidad a todos los comentarios que se renderizan en la lista total de comentarios, esto tendrá que ver con el componente `Comment`. - -Los slots habilitados para agregar funcionalidad a los comentarios tienen un prefix `comment` como el `commentContent` o el `commentReactions`, que vimos previamente. - -### Deshabilitando plugins por configuración - -Los plugins se eliminan borrando su entrada en el `plugins.json`. Pero si por alguna razón necesitamos hacerlo por configuración, podemos hacerlo. - -Dentro de `views/article.ejs` embebemos Talk y notarás que podemos envialarle un objeto de configuración. Para deshabilitar visualmente a los plugins podemos utilizar la propiedad `disable_components` en `true`. y se utiliza de la siguiente forma: - -```js -plugins_config: { - 'talk-plugin-love': { - disable_components: true, - }, -} -``` - -### Enviando información a los slots / plugins - -Dentro de `plugins_config` podemos pasar todas las propiedades que queramos y los plugins las recibirán. - -Por ejemplo: Si enviamos esto -```js -plugins_config: { - test: 'data' -} -``` - -El plugin recibirá por props un objeto config con las propiedades que le pasamos. Haciendo un console.log de `this.props` verás: - -```js -config: {test: 'data'} -``` - -### Debug Slots - -Podés debuggear Slots / Plugins sólo con pasar la propiedad `debug` con valor `true`. - -```js -plugins_config: { - debug: true -} -``` - -Esto mostrará todos los slots disponibles en la UI y su nombre si pasas el mouse sobre ellos. - -### Slot ClassNames -Los slots autogeneran sus clases con el prefijo `talk-slot-` seguido del nombre del slot en kebab case. -Por ejemplo, la clase autogenerada del slot `commentContent` es `talk-slot-comment-content`. \ No newline at end of file diff --git a/docs/source/plugins/slots-and-plugins.md b/docs/source/plugins/slots-and-plugins.md deleted file mode 100644 index d230ac0ba..000000000 --- a/docs/source/plugins/slots-and-plugins.md +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: Plugins Overview -permalink: /plugin-slots/ -toc: true ---- - -Plugins make use of "slots" in order to change Talk's interface. - -By default, Talk has various plugins provided by default. We can see this in `plugins.default.json`: - -```json -{ - "server": [ - "talk-plugin-auth", - "talk-plugin-featured-comments", - "talk-plugin-offtopic", - "talk-plugin-respect" - ], - "client": [ - "talk-plugin-auth", - "talk-plugin-author-menu", - "talk-plugin-comment-content", - "talk-plugin-featured-comments", - "talk-plugin-flag-details", - "talk-plugin-ignore-user", - "talk-plugin-member-since", - "talk-plugin-moderation-actions", - "talk-plugin-offtopic", - "talk-plugin-permalink", - "talk-plugin-respect", - "talk-plugin-sort-most-replied", - "talk-plugin-sort-most-respected", - "talk-plugin-sort-newest", - "talk-plugin-sort-oldest", - "talk-plugin-viewing-options", - "talk-plugin-profile-settings" - ] -} -``` - -Let's only focus on the plugins which are listed under `client` - these are the plugins that use *slots* to inject certain functionality into the Talk UI. - -For example, if we look at the Respect plugin (`talk-plugin-respect`), we can see its `client/index.js` looks like this: - - -```js -import RespectButton from './RespectButton'; -import translations from './translations.yml'; - -export default { - translations, - slots: { - commentReactions: [RespectButton], - }, -}; - -``` - -Inside the `slots` property, we specify what *slots* the plugin will use. Above we are saying that the `RespectButton` component is being injected into the slot `commentReactions`. - -Slots can receive an Array of components, so we can use one plugin or many for one slot. - -### Anatomy of the Slot Component - -In Talk core, we have 32 slots available for us to use. The component `Slot` has a `fill` property where we establish the name of the slot. It looks like this: - - -```js - -``` - -You won't have to use this to build plugins, but it's helpful to find where to embed your plugin. - -### Slot List - -* `adminCommentDetailArea` -* `adminCommentMoreDetails` -* `adminCommentLabels` -* `adminModerationSettings` -* `adminStreamSettings` -* `adminTechSettings` -* `adminCommentInfoBar` -* `adminCommentContent` -* `adminSideActions` -* `adminModeration` -* `adminModerationIndicator` - -* `commentInputDetailArea` -* `commentAvatar` -* `commentAuthorName` -* `commentAuthorTags` -* `commentTimestamp` -* `commentInfoBar` -* `commentContent` -* `commentReactions` -* `commentActions` -* `commentInputArea` - -* `draftArea` -* `streamSettings` -* `historyCommentTimestamp` -* `profileSections` -* `embed` -* `stream` -* `streamFilter` -* `streamQuestionArea` -* `login` -* `userProfile` -* `userDetailCommentContent` - -### Where should I insert my plugin? - -The first thing we should consider is what components will be affected by our plugin's functionality. For example, if we want to add functionality to all the comments that are rendered in a total list of comments, we would use the component `Comment`. - -The slots that are able to add functionality to comments start with `comment`, like `commentContent`, or `commentReactions`, as you can see above. - -### Disabling plugins via `plugins_config` - -Typically, you will manage plugins via your `plugins.json` file. If you want to remove a plugin, you would simply delete it there. However, we can also do this directly with the `plugins_config`. - -Let's look at our example article, `views/article.ejs`. Here we see can we have the Talk embed, and within the embed, we can also send a configuration object. To disable a plugin visually, we can pass `true` to the property `disable_components`. Like so: - - -```js -plugins_config: { - 'talk-plugin-love': { - disable_components: true, - }, -} -``` - -### Sending information to slots and plugins - - -Inside our `plugins_config`, we can also send properities and our plugins will receive them. For example, if we send this: - -```js -plugins_config: { - test: 'data' -} -``` - -The plugin will receive a config object with the properties we've passed. If we do a `console.log` with `this.props`, we would see: - -```js -config: {test: 'data'} -``` - -### Debugging slots and plugins - - -You can debug slots and plugins simply by passing the `debug` property with value `true`: - - -```js -plugins_config: { - debug: true -} -``` - -This will turn on a visual aid to show you all of Talk's available slots and their names. Just move your mouse around! - -### Slot ClassNames - -Slots autogenerate their classes with the prefix `talk-slot`, followed by the name of the slot in kebab case. - -For example, the class autogenerated for the slot `commentContent` is `talk-slot-comment-content`. From 5cd2cce7d84a3c04b9002842ad77c772385c217e Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 20 Mar 2018 15:59:48 -0300 Subject: [PATCH 31/37] removing pell --- .gitignore | 1 - plugins/talk-plugin-rich-text-pell/README.md | 49 -------- .../client/.eslintrc.json | 3 - .../client/components/CommentContent.js | 23 ---- .../client/components/Editor.css | 41 ------- .../client/components/Editor.js | 108 ------------------ .../client/containers/CommentContent.js | 12 -- .../client/containers/Editor.js | 12 -- .../client/index.js | 70 ------------ .../client/utils.js | 20 ---- plugins/talk-plugin-rich-text-pell/index.js | 1 - .../talk-plugin-rich-text-pell/package.json | 12 -- 12 files changed, 352 deletions(-) delete mode 100644 plugins/talk-plugin-rich-text-pell/README.md delete mode 100644 plugins/talk-plugin-rich-text-pell/client/.eslintrc.json delete mode 100644 plugins/talk-plugin-rich-text-pell/client/components/CommentContent.js delete mode 100644 plugins/talk-plugin-rich-text-pell/client/components/Editor.css delete mode 100644 plugins/talk-plugin-rich-text-pell/client/components/Editor.js delete mode 100644 plugins/talk-plugin-rich-text-pell/client/containers/CommentContent.js delete mode 100644 plugins/talk-plugin-rich-text-pell/client/containers/Editor.js delete mode 100644 plugins/talk-plugin-rich-text-pell/client/index.js delete mode 100644 plugins/talk-plugin-rich-text-pell/client/utils.js delete mode 100644 plugins/talk-plugin-rich-text-pell/index.js delete mode 100644 plugins/talk-plugin-rich-text-pell/package.json diff --git a/.gitignore b/.gitignore index 7c0007dc9..6f3ac70b8 100644 --- a/.gitignore +++ b/.gitignore @@ -62,7 +62,6 @@ plugins/* !plugins/talk-plugin-toxic-comments !plugins/talk-plugin-viewing-options !plugins/talk-plugin-rich-text -!plugins/talk-plugin-rich-text-pell **/node_modules/* yarn-error.log diff --git a/plugins/talk-plugin-rich-text-pell/README.md b/plugins/talk-plugin-rich-text-pell/README.md deleted file mode 100644 index da70d48d0..000000000 --- a/plugins/talk-plugin-rich-text-pell/README.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: talk-plugin-rich-text-pell -permalink: /plugin/talk-plugin-rich-text-pell/ -layout: plugin -plugin: - name: talk-plugin-rich-text-pell - depends: - - name: talk-plugin-rich-text - provides: - - Client ---- - -Enables rich text support client-side by using [Pell](https://github.com/jaredreich/pell). - -## Installation - -Add `"talk-plugin-rich-text-pell"` to the `plugins.json` in your Talk -installation. Remember to add this in the `client` property since this plugin -only covers the client side. To add server support, please use -[talk-plugin-rich-text](/talk/plugin/talk-plugin-rich-text). - -_Note: Ensure that you don't have any other plugins utilizing the -`commentContent` slot, as it would result in duplicate comments._ - -## How does this work? - -This plugin contains 2 important components: - -- The Editor (`./components/Editor.js`) -- The Comment Content Renderer (`./components/CommentContent.js`) - -The editor component contains the rich text editor. For this particular plugin -we chose [Pell](https://github.com/jaredreich/pell). Pell is the simplest and -smallest WYSIWYG text editor with no dependencies that we could find. - -If you check our `index.js` you will notice that we inject this editor in the -`commentBox` slot. We do this to replace the core comment box with this one. - -Now, in order to render the new styled comments we need a comment renderer. For -this task we will have to replace our core comment renderer by using the -`commentContent` slot. - -If you are not familiar with GraphQL `client/index.js` will look complicated, -but fear not! With those functions we specify what to expect from the server -schema, how to perform optimistic updates and how keep the client store updated -with the latest changes. - -We encourage you to see the files and check how easy is to build plugins! If you -have any feedback, please let us know. diff --git a/plugins/talk-plugin-rich-text-pell/client/.eslintrc.json b/plugins/talk-plugin-rich-text-pell/client/.eslintrc.json deleted file mode 100644 index c8a6db18a..000000000 --- a/plugins/talk-plugin-rich-text-pell/client/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "@coralproject/eslint-config-talk/client" -} diff --git a/plugins/talk-plugin-rich-text-pell/client/components/CommentContent.js b/plugins/talk-plugin-rich-text-pell/client/components/CommentContent.js deleted file mode 100644 index 7e4a202bc..000000000 --- a/plugins/talk-plugin-rich-text-pell/client/components/CommentContent.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { pluginName } from '../../package.json'; - -class CommentContent extends React.Component { - render() { - const { comment } = this.props; - return comment.richTextBody ? ( -
- ) : ( -
{comment.body}
- ); - } -} - -CommentContent.propTypes = { - comment: PropTypes.object.isRequired, -}; - -export default CommentContent; diff --git a/plugins/talk-plugin-rich-text-pell/client/components/Editor.css b/plugins/talk-plugin-rich-text-pell/client/components/Editor.css deleted file mode 100644 index 4561e7c6b..000000000 --- a/plugins/talk-plugin-rich-text-pell/client/components/Editor.css +++ /dev/null @@ -1,41 +0,0 @@ -.content { - background: #fff; - border: solid 1px #bbb; - min-height: 120px; - box-sizing: border-box; - outline: 0; - overflow-y: auto; - width: 100%; - padding: 10px; - font-style: unset; -} - -.button > i { - vertical-align: middle; -} - -.button { - background-color: transparent; - padding: 3px; - border: none; - color: #4e4e4e; - margin-right: 3px; -} - -.button:hover{ - cursor: pointer; - border-radius: 3px; - background-color: #eae8e8; -} - -.actionBar { - user-select: none; - padding: 5px 10px; - border-top: 1px solid #bbb; - border-left: 1px solid #bbb; - border-right: 1px solid #bbb; -} - -.container { - box-sizing: border-box; -} \ No newline at end of file diff --git a/plugins/talk-plugin-rich-text-pell/client/components/Editor.js b/plugins/talk-plugin-rich-text-pell/client/components/Editor.js deleted file mode 100644 index c129e146d..000000000 --- a/plugins/talk-plugin-rich-text-pell/client/components/Editor.js +++ /dev/null @@ -1,108 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { init } from 'pell'; -import styles from './Editor.css'; -import cn from 'classnames'; -import { pluginName } from '../../package.json'; -import { htmlNormalizer } from '../utils'; - -class Editor extends React.Component { - ref = null; - - handleRef = ref => (this.ref = ref); - - componentDidMount() { - const { onChange, actions, classNames, isReply } = this.props; - - init({ - element: this.ref, - onChange: richTextBody => { - // We want to save the original comment body - const originalBody = this.ref.childNodes[1].innerText; - onChange(originalBody, { richTextBody: htmlNormalizer(richTextBody) }); - }, - actions, - classes: { - actionbar: cn( - styles.actionBar, - classNames.actionbar, - `${pluginName}-action-bar` - ), - content: cn( - styles.content, - classNames.content, - `${pluginName}-content` - ), - button: cn(styles.button, classNames.button, `${pluginName}-button`), - }, - }); - - // To edit comments and have the previous html comment - if (this.props.comment && this.props.comment.richTextBody && !isReply) { - this.ref.content.innerHTML = this.props.comment.richTextBody; - } - - if (this.props.registerHook) { - this.clearInputHook = this.props.registerHook( - 'postSubmit', - (res, handleBodyChange) => { - this.ref.content.innerHTML = ''; - handleBodyChange('', { richTextBody: '' }); - } - ); - } - } - - componentWillUnmount() { - this.props.unregisterHook(this.clearInputHook); - } - - render() { - const { id, classNames } = this.props; - - return ( -
- ); - } -} - -Editor.defaultProps = { - defaultContent: '', - styleWithCSS: false, - actions: [ - { name: 'bold', icon: 'format_bold' }, - { name: 'italic', icon: 'format_italic' }, - { name: 'quote', icon: 'format_quote' }, - ], - classNames: { - button: '', - content: '', - actionbar: '', - container: '', - }, -}; - -Editor.propTypes = { - id: PropTypes.string, - value: PropTypes.string, - placeholder: PropTypes.string, - onChange: PropTypes.func, - disabled: PropTypes.bool, - rows: PropTypes.number, - comment: PropTypes.object, - classNames: PropTypes.object, - actions: PropTypes.array, - registerHook: PropTypes.func, - unregisterHook: PropTypes.func, - isReply: PropTypes.bool, -}; - -export default Editor; diff --git a/plugins/talk-plugin-rich-text-pell/client/containers/CommentContent.js b/plugins/talk-plugin-rich-text-pell/client/containers/CommentContent.js deleted file mode 100644 index 8bd36da23..000000000 --- a/plugins/talk-plugin-rich-text-pell/client/containers/CommentContent.js +++ /dev/null @@ -1,12 +0,0 @@ -import { gql } from 'react-apollo'; -import { withFragments } from 'plugin-api/beta/client/hocs'; -import CommentContent from '../components/CommentContent'; - -export default withFragments({ - comment: gql` - fragment TalkPluginRTE_CommentContent_comment on Comment { - body - richTextBody - } - `, -})(CommentContent); diff --git a/plugins/talk-plugin-rich-text-pell/client/containers/Editor.js b/plugins/talk-plugin-rich-text-pell/client/containers/Editor.js deleted file mode 100644 index 2bdc3490f..000000000 --- a/plugins/talk-plugin-rich-text-pell/client/containers/Editor.js +++ /dev/null @@ -1,12 +0,0 @@ -import { gql } from 'react-apollo'; -import { withFragments } from 'plugin-api/beta/client/hocs'; -import Editor from '../components/Editor'; - -export default withFragments({ - comment: gql` - fragment TalkPluginRTE_Editor_comment on Comment { - body - richTextBody - } - `, -})(Editor); diff --git a/plugins/talk-plugin-rich-text-pell/client/index.js b/plugins/talk-plugin-rich-text-pell/client/index.js deleted file mode 100644 index cf9eb11cd..000000000 --- a/plugins/talk-plugin-rich-text-pell/client/index.js +++ /dev/null @@ -1,70 +0,0 @@ -import Editor from './containers/Editor'; -import CommentContent from './containers/CommentContent'; -import { gql } from 'react-apollo'; - -export default { - slots: { - draftArea: [Editor], - commentContent: [CommentContent], - adminCommentContent: [CommentContent], - userDetailCommentContent: [CommentContent], - }, - fragments: { - CreateCommentResponse: gql` - fragment TalkRTE_CreateCommentResponse on CreateCommentResponse { - comment { - richTextBody - } - } - `, - EditCommentResponse: gql` - fragment TalkRTE_EditCommentResponse on EditCommentResponse { - comment { - richTextBody - } - } - `, - }, - mutations: { - PostComment: ({ variables: { input } }) => { - return { - optimisticResponse: { - createComment: { - comment: { - richTextBody: input.richTextBody, - }, - }, - }, - }; - }, - EditComment: ({ variables: { id, edit } }) => { - return { - optimisticResponse: { - editComment: { - comment: { - richTextBody: edit.richTextBody, - }, - }, - }, - update: proxy => { - const editCommentFragment = gql` - fragment Talk_EditComment on Comment { - richTextBody - } - `; - - const fragmentId = `Comment_${id}`; - - proxy.writeFragment({ - fragment: editCommentFragment, - id: fragmentId, - data: { - __typename: 'Comment', - richTextBody: edit.richTextBody, - }, - }); - }, - }; - }, - }, -}; diff --git a/plugins/talk-plugin-rich-text-pell/client/utils.js b/plugins/talk-plugin-rich-text-pell/client/utils.js deleted file mode 100644 index 6155fbfb2..000000000 --- a/plugins/talk-plugin-rich-text-pell/client/utils.js +++ /dev/null @@ -1,20 +0,0 @@ -export function htmlNormalizer(htmlInput) { - let str = htmlInput; - // We are normalizing the input from contenteditable of each browser, also removing unnecesary html tags - // https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content#Differences_in_markup_generation - - // Old browsers uses `p` normalize to `div` instead. - str = str - .replace(/

/g, '

') // IE and old browsers outputs

instead of

s - .replace(/<\/p>/g, '
'); // IE and old browsers outputs

instead of

s - - // Remove first opening tag, otherwise - // with the following transformation below - // we might add an unintended first empty line. - if (str.startsWith('
')) { - str = str.replace('
', ''); - } - - // Normalize
s to
. - return str.replace(/
/g, '
').replace(/<\/div>/g, ''); -} diff --git a/plugins/talk-plugin-rich-text-pell/index.js b/plugins/talk-plugin-rich-text-pell/index.js deleted file mode 100644 index f053ebf79..000000000 --- a/plugins/talk-plugin-rich-text-pell/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = {}; diff --git a/plugins/talk-plugin-rich-text-pell/package.json b/plugins/talk-plugin-rich-text-pell/package.json deleted file mode 100644 index 65543a89a..000000000 --- a/plugins/talk-plugin-rich-text-pell/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "@coralproject/talk-plugin-rich-text-pell", - "pluginName": "talk-plugin-rich-text-pell", - "version": "0.0.1", - "description": "Pell's Rich Text Editor for Talk", - "main": "index.js", - "author": "The Coral Project Team ", - "license": "Apache-2.0", - "dependencies": { - "pell": "^1.0.1" - } -} From db64f21beb7489f2e21b3a32c4f83eb2529c234b Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Tue, 20 Mar 2018 16:09:33 -0400 Subject: [PATCH 32/37] Typo --- docs/source/04-06-slots-and-plugins.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/04-06-slots-and-plugins.md b/docs/source/04-06-slots-and-plugins.md index 86e3addeb..907c85862 100644 --- a/docs/source/04-06-slots-and-plugins.md +++ b/docs/source/04-06-slots-and-plugins.md @@ -120,7 +120,7 @@ The slots that are able to add functionality to comments start with `comment`, l Typically, you will manage plugins via your `plugins.json` file. If you want to remove a plugin, you would simply delete it there. However, we can also do this directly with the `plugins_config`. -Let's look at our example article, `views/article.ejs`. Here we see can we have the Talk embed, and within the embed, we can also send a configuration object. To disable a plugin visually, we can pass `true` to the property `disable_components`. Like so: +Let's look at our example article, `views/article.ejs`. Here we see we have the Talk embed, and within the embed, we can also send a configuration object. To disable a plugin visually, we can pass `true` to the property `disable_components`. Like so: ```js From db1934e897c417825ffbcf171e60c0e1f8071b8b Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Tue, 20 Mar 2018 16:04:41 -0600 Subject: [PATCH 33/37] fixed password reset email form --- routes/api/v1/account.js | 2 +- yarn.lock | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/routes/api/v1/account.js b/routes/api/v1/account.js index e1395323d..f7d8ea126 100644 --- a/routes/api/v1/account.js +++ b/routes/api/v1/account.js @@ -80,7 +80,7 @@ router.post('/password/reset', async (req, res, next) => { token, }, subject: 'Password Reset', - to: email, + email, }); } diff --git a/yarn.lock b/yarn.lock index 3556a26ba..786086d39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8239,10 +8239,6 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -pell@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pell/-/pell-1.0.1.tgz#8f1e97165001024e5f371e0ce0b329457c847b5d" - pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" From 3415163cfb1cea003b419fe9c19ea3f76c9fd4b4 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Tue, 20 Mar 2018 16:07:42 -0600 Subject: [PATCH 34/37] changed name based on review --- graph/context.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/graph/context.js b/graph/context.js index dcbbc5f6b..e9ac7ea61 100644 --- a/graph/context.js +++ b/graph/context.js @@ -51,7 +51,7 @@ const decorateContextPlugins = (context, contextPlugins) => { * @param {Object} ctx the graph proxy * @param {Function} loader the loadable component that should be proxied */ -const proxyContextLoader = (ctx, loader) => +const createLazyContextLoader = (ctx, loader) => new Proxy( { loaded: false, data: null }, { @@ -87,18 +87,18 @@ class Context { this.connectors = connectors; // Create the loaders. - this.loaders = proxyContextLoader(this, loaders); + this.loaders = createLazyContextLoader(this, loaders); // Create the mutators. - this.mutators = proxyContextLoader(this, mutators); + this.mutators = createLazyContextLoader(this, mutators); // Decorate the plugin context. - this.plugins = proxyContextLoader(this, () => + this.plugins = createLazyContextLoader(this, () => decorateContextPlugins(this, contextPlugins) ); // Bind the publish/subscribe to the context. - this.pubsub = proxyContextLoader(this, () => getBroker()); + this.pubsub = createLazyContextLoader(this, () => getBroker()); // Bind the parent context. this.parent = ctx; From b43b67e8fa2b828e333a13799aeebf0dd56e830e Mon Sep 17 00:00:00 2001 From: Juan Pablo Kutianski Date: Tue, 20 Mar 2018 23:10:30 -0300 Subject: [PATCH 35/37] change Facebook to Google+ --- plugins/talk-plugin-google-auth/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/talk-plugin-google-auth/README.md b/plugins/talk-plugin-google-auth/README.md index edf0b9488..f68b56c32 100644 --- a/plugins/talk-plugin-google-auth/README.md +++ b/plugins/talk-plugin-google-auth/README.md @@ -11,7 +11,7 @@ plugin: - Client --- -Enables sign-in via Facebook via the server side passport middleware. +Enables sign-in via Google+ via the server side passport middleware. 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 @@ -26,4 +26,4 @@ Configuration: the [Google API Console](https://console.developers.google.com/apis/). - `TALK_GOOGLE_CLIENT_SECRET` (**required**) - 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/). \ No newline at end of file + ID at the [Google API Console](https://console.developers.google.com/apis/). From a43c173a125423557f93ee51a1891b7ea4d7700a Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 21 Mar 2018 11:04:41 -0600 Subject: [PATCH 36/37] Added support for forcing the notification settings pane --- middleware/staticTemplate.js | 27 ++++++++++++++----- plugin-api/beta/client/selectors/index.js | 1 + .../client/containers/Settings.js | 20 ++++++++++++-- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/middleware/staticTemplate.js b/middleware/staticTemplate.js index b7d01feb4..01503cca0 100644 --- a/middleware/staticTemplate.js +++ b/middleware/staticTemplate.js @@ -13,6 +13,25 @@ const { const { RECAPTCHA_PUBLIC, WEBSOCKET_LIVE_URI } = require('../config'); +// Grab TALK_CLIENT_* environment variables. +const TALK_CLIENT = /^TALK_CLIENT_/i; + +// TALK_CLIENT_ENV is all the environment keys that are loaded at runtime. +const TALK_CLIENT_ENV = Object.keys(process.env) + .filter(key => TALK_CLIENT.test(key)) + .reduce( + (env, key) => { + env[key] = process.env[key]; + return env; + }, + { + TALK_RECAPTCHA_PUBLIC: RECAPTCHA_PUBLIC, + LIVE_URI: WEBSOCKET_LIVE_URI, + STATIC_URL, + STATIC_ORIGIN, + } + ); + // TEMPLATE_LOCALS stores the static data that is provided as a `text/json` on // to the client from the template. const TEMPLATE_LOCALS = { @@ -20,12 +39,8 @@ const TEMPLATE_LOCALS = { BASE_PATH, MOUNT_PATH, STATIC_URL, - data: { - TALK_RECAPTCHA_PUBLIC: RECAPTCHA_PUBLIC, - LIVE_URI: WEBSOCKET_LIVE_URI, - STATIC_URL, - STATIC_ORIGIN, - }, + TALK_CLIENT_ENV, + data: TALK_CLIENT_ENV, }; // attachStaticLocals will attach the locals to the response only. diff --git a/plugin-api/beta/client/selectors/index.js b/plugin-api/beta/client/selectors/index.js index c3a0b6821..605711dbc 100644 --- a/plugin-api/beta/client/selectors/index.js +++ b/plugin-api/beta/client/selectors/index.js @@ -1 +1,2 @@ export const pluginsConfigSelector = state => state.config.plugins_config; +export const staticConfigSelector = state => state.config.static; diff --git a/plugins/talk-plugin-notifications/client/containers/Settings.js b/plugins/talk-plugin-notifications/client/containers/Settings.js index 27af031e8..5862650ec 100644 --- a/plugins/talk-plugin-notifications/client/containers/Settings.js +++ b/plugins/talk-plugin-notifications/client/containers/Settings.js @@ -9,6 +9,8 @@ import { } from 'plugin-api/beta/client/hocs'; import { getSlotFragmentSpreads } from 'plugin-api/beta/client/utils'; import { withUpdateNotificationSettings } from '../mutations'; +import { connect } from 'plugin-api/beta/client/hocs'; +import { staticConfigSelector } from 'plugin-api/beta/client/selectors'; const slots = ['notificationSettings']; @@ -42,8 +44,11 @@ class SettingsContainer extends React.Component { }; getNeedEmailVerification() { - return !this.props.root.me.profiles.some( - profile => profile.provider === 'local' && profile.confirmedAt + return ( + this.props.root.settings.notificationsRequireConfirmation && + !this.props.root.me.profiles.some( + profile => profile.provider === 'local' && profile.confirmedAt + ) ); } @@ -94,11 +99,22 @@ const enhance = compose( } } } + settings { + notificationsRequireConfirmation + } } `, }), + // Grab the static configuration from the redux store. + connect(state => ({ + static: staticConfigSelector(state), + })), excludeIf( props => + // If the environment variable for TALK_CLIENT_FORCE_NOTIFICATION_SETTINGS + // is `TRUE`, then always show it. + props.static.TALK_CLIENT_FORCE_NOTIFICATION_SETTINGS !== 'TRUE' && + // Only show the settings pane if we have a local profile otherwise. !props.root.me.profiles.some(profile => profile.provider === 'local') ), withUpdateNotificationSettings, From 0b017002358097fbce19f92b9e747d9a399500e4 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 21 Mar 2018 11:12:04 -0600 Subject: [PATCH 37/37] updated docs --- plugins/talk-plugin-notifications/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/talk-plugin-notifications/README.md b/plugins/talk-plugin-notifications/README.md index 0ce1b61a8..9e8318a0f 100644 --- a/plugins/talk-plugin-notifications/README.md +++ b/plugins/talk-plugin-notifications/README.md @@ -16,6 +16,7 @@ anything. You need to enable one of the `talk-plugin-notifications-category-*` p 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_CLIENT_FORCE_NOTIFICATION_SETTINGS` - When `TRUE`, the settings pane for notifications will show always, even if the user does not have a `local` profile. (Default `FALSE`). You can enable other notification options by adding more `talk-plugin-notification-*` plugins! \ No newline at end of file