diff --git a/client/coral-admin/src/AppRouter.js b/client/coral-admin/src/AppRouter.js index 99eea97ae..5827f0a21 100644 --- a/client/coral-admin/src/AppRouter.js +++ b/client/coral-admin/src/AppRouter.js @@ -1,6 +1,6 @@ import React from 'react'; -import {Router, Route, IndexRedirect, browserHistory, Redirect} from 'react-router'; -import {useBasename} from 'history'; +import {Router, Route, IndexRedirect, Redirect} from 'react-router'; +import {history} from 'coral-framework/helpers/router'; import Configure from 'routes/Configure'; import Dashboard from 'routes/Dashboard'; @@ -57,8 +57,6 @@ const routes = ( ); -const AppRouter = () => browserHistory)({ - basename: '/talk/' -})} routes={routes}/>; +const AppRouter = () => ; export default AppRouter; diff --git a/client/coral-embed-stream/src/AppRouter.js b/client/coral-embed-stream/src/AppRouter.js index 6ee63caab..c2e7b2c5d 100644 --- a/client/coral-embed-stream/src/AppRouter.js +++ b/client/coral-embed-stream/src/AppRouter.js @@ -1,5 +1,6 @@ import React from 'react'; -import {Router, Route, browserHistory} from 'react-router'; +import {Router, Route} from 'react-router'; +import {history} from 'coral-framework/helpers/router'; import Embed from './containers/Embed'; import {LoginContainer} from 'coral-sign-in/containers/LoginContainer'; @@ -11,6 +12,6 @@ const routes = ( ); -const AppRouter = () => ; +const AppRouter = () => ; export default AppRouter; diff --git a/client/coral-embed-stream/src/components/Embed.js b/client/coral-embed-stream/src/components/Embed.js index a069984dc..f918b7a16 100644 --- a/client/coral-embed-stream/src/components/Embed.js +++ b/client/coral-embed-stream/src/components/Embed.js @@ -36,7 +36,7 @@ export default class Embed extends React.Component {
{ init(JSON.parse(config)); }); + + pym.onMessage('login', (token) => { + if (token) { + store.dispatch(handleAuthToken(token)); + } + store.dispatch(checkLogin()); + }); + + pym.onMessage('logout', () => { + store.dispatch(logout()); + }); } else { init(); } diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css index 055107b33..802cd2e5b 100644 --- a/client/coral-embed-stream/style/default.css +++ b/client/coral-embed-stream/style/default.css @@ -257,6 +257,8 @@ body { margin: 0px 5px; padding: 5px 5px; border-radius: 2px; + font-size: 12px; + font-weight: bold; } /* Comment Action Styles */ diff --git a/client/coral-embed/src/index.js b/client/coral-embed/src/index.js index fda97c4b3..64c274660 100644 --- a/client/coral-embed/src/index.js +++ b/client/coral-embed/src/index.js @@ -5,8 +5,6 @@ import {buildUrl} from 'coral-framework/utils'; import queryString from 'query-string'; import EventEmitter from 'eventemitter2'; -const eventEmitter = new EventEmitter({wildcard: true}); - // TODO: Styles should live in a separate file const snackbarStyles = { position: 'fixed', @@ -50,7 +48,7 @@ function buildStreamIframeUrl(talkBaseUrl, query) { // Set up postMessage listeners/handlers on the pymParent // e.g. to resize the iframe, and navigate the host page -function configurePymParent(pymParent, opts) { +function configurePymParent(pymParent, eventEmitter, opts) { let notificationOffset = 200; let cachedHeight; const snackbar = document.createElement('div'); @@ -203,6 +201,23 @@ function configurePymParent(pymParent, opts) { * @param {String} [opts.asset_url] - Asset URL * @param {String} [opts.asset_id] - Asset ID * @param {String} [opts.auth_token] - (optional) A jwt representing the session + * @return {Object} + * + * Example: + * ``` + * const embed = Talk.render(document.getElementById('talkStreamEmbed'), opts); + * + * // trigger a login with optional token. + * embed.login(token); + * + * // trigger a logout. + * embed.logout(); + * + * // listen to events (in this case all events). + * embed.on('**', function(value) { + * console.log(this.event, value); + * }); + * ``` */ Talk.render = function(el, opts) { if (!el) { @@ -256,14 +271,31 @@ Talk.render = function(el, opts) { } } + const pymParent = new pym.Parent(el.id, buildStreamIframeUrl(opts.talk, query), { + title: opts.title, + id: `${el.id}_iframe`, + name: `${el.id}_iframe` + }); + + const eventEmitter = new EventEmitter({wildcard: true}); + configurePymParent( - new pym.Parent(el.id, buildStreamIframeUrl(opts.talk, query), { - title: opts.title, - id: `${el.id}_iframe`, - name: `${el.id}_iframe` - }), + pymParent, + eventEmitter, opts ); + + return { + on(eventName, callback) { + eventEmitter.on(eventName, callback); + }, + login(token) { + pymParent.sendMessage('login', token); + }, + logout() { + pymParent.sendMessage('logout'); + } + }; }; export default Coral; diff --git a/client/coral-framework/actions/auth.js b/client/coral-framework/actions/auth.js index d3c29dc3c..f4cf5217e 100644 --- a/client/coral-framework/actions/auth.js +++ b/client/coral-framework/actions/auth.js @@ -276,9 +276,7 @@ export const fetchForgotPassword = (email) => (dispatch, getState) => { export const logout = () => (dispatch) => { return coralApi('/auth', {method: 'DELETE'}).then(() => { - if (!bowser.safari && !bowser.ios) { - Storage.removeItem('token'); - } + Storage.removeItem('token'); // Reset the websocket. resetWebsocket(); @@ -306,9 +304,7 @@ export const checkLogin = () => (dispatch) => { coralApi('/auth') .then((result) => { if (!result.user) { - if (!bowser.safari && !bowser.ios) { - Storage.removeItem('token'); - } + Storage.removeItem('token'); throw new Error('Not logged in'); } @@ -325,6 +321,11 @@ export const checkLogin = () => (dispatch) => { }) .catch((error) => { console.error(error); + if (error.status && error.status === 401) { + + // Unauthorized. + Storage.removeItem('token'); + } const errorMessage = error.translation_key ? t(`error.${error.translation_key}`) : error.toString(); dispatch(checkLoginFailure(errorMessage)); }); diff --git a/client/coral-framework/helpers/request.js b/client/coral-framework/helpers/request.js index 782aa83f6..ffddc9c5e 100644 --- a/client/coral-framework/helpers/request.js +++ b/client/coral-framework/helpers/request.js @@ -67,6 +67,7 @@ const handleResp = (res) => { } error.message = message; + error.status = res.status; throw error; }); } else if (res.status === 204) { diff --git a/client/coral-framework/helpers/router.js b/client/coral-framework/helpers/router.js new file mode 100644 index 000000000..e6277e9d8 --- /dev/null +++ b/client/coral-framework/helpers/router.js @@ -0,0 +1,7 @@ +import {useBasename} from 'history'; +import {browserHistory} from 'react-router'; +import {BASE_PATH} from 'coral-framework/constants/url'; + +export const history = useBasename(() => browserHistory)({ + basename: BASE_PATH +}); diff --git a/client/talk-plugin-flags/components/FlagButton.js b/client/talk-plugin-flags/components/FlagButton.js index 6b7e3cc56..85ceed0ea 100644 --- a/client/talk-plugin-flags/components/FlagButton.js +++ b/client/talk-plugin-flags/components/FlagButton.js @@ -91,7 +91,7 @@ export default class FlagButton extends Component { reason: null, message }; - if (reason === 'I don\'t agree with this comment') { + if (reason === 'COMMENT_NOAGREE') { postDontAgree(action) .then(({data}) => { if (itemType === 'COMMENTS') { diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index b5637517d..000000000 --- a/docs/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Coral Talk Documentation - -To preview the documentation, run: - -```bash -docker run --rm --volume=$PWD:/srv/jekyll -p 127.0.0.1:4000:4000 -it jekyll/jekyll:pages jekyll serve -``` - -From the `docs` directory. Then visit: [http://127.0.0.1:4000/talk/](http://127.0.0.1:4000/talk/). \ No newline at end of file diff --git a/docs/_data/navigation.yml b/docs/_data/navigation.yml index 68b4d9803..0a9577e2b 100755 --- a/docs/_data/navigation.yml +++ b/docs/_data/navigation.yml @@ -34,6 +34,8 @@ docs: url: /docs/running/configuration/ - title: "Secrets" url: /docs/running/secrets/ + - title: "Plugins" + url: /docs/running/plugins/ - title: "Database Migrations" url: /docs/running/migrations/ - title: "Architecture" diff --git a/docs/_docs/00-01-faq.md b/docs/_docs/00-01-faq.md index c923aa65a..cdaf5dbf3 100644 --- a/docs/_docs/00-01-faq.md +++ b/docs/_docs/00-01-faq.md @@ -58,10 +58,10 @@ Fork the Talk repo, clone it locally (no need to go through the install from sou ``` cd docs -docker build --no-cache -t mydocs . -docker run -v "$PWD:/src" -p 4000:4000 mydocs serve -H 0.0.0.0 +docker run --rm --volume=$PWD:/srv/jekyll -p 127.0.0.1:4000:4000 -it jekyll/jekyll:pages jekyll serve ``` -You can edit the files in docs with any editor and view the live updates in a browser by hitting `http://localhost:4000`. +You can edit the files in docs with any editor and view the live updates in a browser by hitting From the docs directory. +Then visit: [http://127.0.0.1:4000/talk/](http://127.0.0.1:4000/talk/). Once you've made the changes, file a PR back to the `coralproject/talk` repo. diff --git a/docs/_docs/01-01-install.md b/docs/_docs/01-01-install.md index 1ba511522..055217797 100644 --- a/docs/_docs/01-01-install.md +++ b/docs/_docs/01-01-install.md @@ -18,4 +18,4 @@ While Talk can be installed in many ways, we support two install paths: * [Install via Docker](docker) (deployment) If you have success installing Talk in another way, please consider -[contributing to this documentation](faq#how-do-i-contribute-to-these-docs)! +[contributing to this documentation]({{ "/docs/faq/" | absolute_url }}#how-do-i-contribute-to-these-docs)! diff --git a/docs/_docs/02-01-configuration.md b/docs/_docs/02-01-configuration.md index cb9a51d23..ab644e5e3 100644 --- a/docs/_docs/02-01-configuration.md +++ b/docs/_docs/02-01-configuration.md @@ -59,6 +59,10 @@ These are only used during the webpack build. send keep alive messages through the websocket to keep the socket alive. (Default `30s`) - `TALK_INSTALL_LOCK` (_optional for dynamic setup_) - When `TRUE`, disables the dynamic setup endpoint. (Default `FALSE`) +### Word Filter + +- `TALK_DISABLE_AUTOFLAG_SUSPECT_WORDS` (_optional_) When `TRUE`, disables flagging of comments that match the suspect word filter. (Default `FALSE`) + ### JWT The following are configuration shared with every type of secret used. @@ -125,6 +129,4 @@ The default could be read as: ### Plugins -- `TALK_PLUGINS_JSON` (_optional_) - used to specify the plugin config via the - environment. -- `TALK_DISABLE_AUTOFLAG_SUSPECT_WORDS` (_optional_) When `TRUE`, disables flagging of comments that match the suspect word filter. (Default `FALSE`) \ No newline at end of file +Plugins configuration can be found on the [Plugins]({{ "/docs/running/plugins/" | absolute_url }}) page. \ No newline at end of file diff --git a/docs/_docs/02-03-plugins.md b/docs/_docs/02-03-plugins.md new file mode 100644 index 000000000..e17f53f9e --- /dev/null +++ b/docs/_docs/02-03-plugins.md @@ -0,0 +1,25 @@ +--- +title: Plugins +permalink: /docs/running/plugins/ +--- + +Configuration for the available plugins are stored in a JSON encoded string. The format +of this document are available with the [Plugins Overview]({{ "/docs/plugins/" | absolute_url }}). + +You can override the plugin config by specifying the content in the `TALK_PLUGIN_JSON` +environment variable. + +## Bundled Plugin Configuration +{:.no_toc} + +Some of the core plugins that are bundled with Talk require specific configuration to be +available. + +{% include toc %} + +### Facebook Authentication + +- `TALK_FACEBOOK_APP_ID` (*required*) - the Facebook app id for your Facebook +Login enabled app. +- `TALK_FACEBOOK_APP_SECRET` (*required*) - the Facebook app secret for your +Facebook Login enabled app. \ No newline at end of file diff --git a/docs/_docs/02-03-migrations.md b/docs/_docs/02-04-migrations.md similarity index 100% rename from docs/_docs/02-03-migrations.md rename to docs/_docs/02-04-migrations.md diff --git a/docs/_docs/04-01-plugins.md b/docs/_docs/04-01-plugins.md index bfe2c4407..8b9b1c99a 100644 --- a/docs/_docs/04-01-plugins.md +++ b/docs/_docs/04-01-plugins.md @@ -5,7 +5,7 @@ permalink: /docs/plugins/ ## Recipes -Recipes are plugin templates provided by the Coral Core team. Developers can use these recipes to build their own plugins. You can find all the Talk recipes here: https://github.com/coralproject/talk-recipes/ +Recipes are plugin templates provided by the Coral Core team. Developers can use these recipes to build their own plugins. You can find all the Talk recipes here: [https://github.com/coralproject/talk-recipes/](https://github.com/coralproject/talk-recipes/). ## Plugin Registration diff --git a/plugins/talk-plugin-facebook-auth/README.md b/plugins/talk-plugin-facebook-auth/README.md deleted file mode 100644 index 6faceed09..000000000 --- a/plugins/talk-plugin-facebook-auth/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# talk-plugin-facebook-auth - -This plugin provides facebook authentication support for Talk. - -## Configuration - -This plugin looks for the following configuration from the environment: - -- `TALK_FACEBOOK_APP_ID` (*required*) - the Facebook app id for your Facebook -Login enabled app. -- `TALK_FACEBOOK_APP_SECRET` (*required*) - the Facebook app secret for your -Facebook Login enabled app. - -### License - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - - See the License for the specific language governing permissions and limitations under the License. diff --git a/plugins/talk-plugin-featured-comments/client/containers/Tab.js b/plugins/talk-plugin-featured-comments/client/containers/Tab.js index f28a63566..fee7f5da6 100644 --- a/plugins/talk-plugin-featured-comments/client/containers/Tab.js +++ b/plugins/talk-plugin-featured-comments/client/containers/Tab.js @@ -17,7 +17,7 @@ const enhance = compose( withFragments({ asset: gql` fragment TalkFeaturedComments_Tab_asset on Asset { - featuredCommentsCount: totalCommentCount(tags: ["FEATURED"], excludeIgnored: $excludeIgnored) + featuredCommentsCount: totalCommentCount(tags: ["FEATURED"], excludeIgnored: $excludeIgnored) @skip(if: $hasComment) }`, }), excludeIf((props) => props.asset.featuredCommentsCount === 0), diff --git a/plugins/talk-plugin-featured-comments/client/containers/TabPane.js b/plugins/talk-plugin-featured-comments/client/containers/TabPane.js index 3a082e732..2195b0107 100644 --- a/plugins/talk-plugin-featured-comments/client/containers/TabPane.js +++ b/plugins/talk-plugin-featured-comments/client/containers/TabPane.js @@ -79,7 +79,7 @@ const enhance = compose( asset: gql` fragment TalkFeaturedComments_TabPane_asset on Asset { id - featuredComments: comments(tags: ["FEATURED"], excludeIgnored: $excludeIgnored, deep: true) { + featuredComments: comments(tags: ["FEATURED"], excludeIgnored: $excludeIgnored, deep: true) @skip(if: $hasComment) { nodes { ...${getDefinitionName(Comment.fragments.comment)} } diff --git a/views/article.ejs b/views/article.ejs index a98aa81c3..098a95524 100644 --- a/views/article.ejs +++ b/views/article.ejs @@ -26,7 +26,7 @@

Admin - All Assets