diff --git a/bin/cli-plugins b/bin/cli-plugins
index b1dee381b..942036d29 100755
--- a/bin/cli-plugins
+++ b/bin/cli-plugins
@@ -8,13 +8,14 @@
// https://yarnpkg.com/
const program = require('./commander');
+const inquirer = require('inquirer');
// Make things colorful!
require('colors');
const emoji = require('node-emoji');
const dir = process.cwd();
-const fs = require('fs');
+const fs = require('fs-extra');
const path = require('path');
const spawn = require('cross-spawn');
const semver = require('semver');
@@ -272,10 +273,128 @@ async function reconcilePluginDeps({skipLocal, skipRemote, dryRun, upgradeRemote
console.log(`✨ Done in ${totalTime}s.`);
}
+async function createSeedPlugin() {
+ const pluginsDir = path.join(__dirname, 'plugins');
+
+ function pluginNameExists(pluginName) {
+ const pluginNames = fs.readdirSync(pluginsDir);
+ return !!pluginNames
+ .filter((pn) => pn === pluginName).length;
+ }
+
+ let answers = await inquirer.prompt([
+ {
+ type: 'input',
+ name: 'pluginName',
+ message: 'Plugin Name:',
+ validate: (input) => {
+
+ if (pluginNameExists(input)) {
+ return 'Please, choose another name. That name already exists';
+ }
+
+ if (input && input.length > 0) {
+ return true;
+ }
+
+ return 'Plugin Name is required.';
+ }
+ },
+ {
+ type: 'confirm',
+ name: 'server',
+ message: 'Is this plugin extending the server capabilities?'
+ },
+ {
+ type: 'confirm',
+ name: 'client',
+ message: 'Is this plugin extending the client capabilities?'
+ },
+ {
+ type: 'confirm',
+ name: 'addPluginsJson',
+ message: 'Should we add it to the plugins.json?'
+ }
+ ]);
+
+ //==============================================================================
+ // Creating plugin seed
+ //==============================================================================
+
+ const seedPlugin = path.join(__dirname, 'bin/templates/plugin');
+ const newPluginPath = path.join(pluginsDir, answers.pluginName);
+
+ if (fs.existsSync(seedPlugin)) {
+
+ if (answers.server && answers.client) {
+
+ // This is a server-side and client-side plugin!, let's copy the template
+ fs.copySync(seedPlugin, newPluginPath);
+ } else {
+
+ fs.copySync(seedPlugin, newPluginPath, {filter: (p) => {
+
+ // Allowing plugin folder and files with no subfolders
+ const rootRx = /plugin$|plugin\/[^/]*(\.).{2,3}/igm;
+ if (rootRx.test(p) && (fs.lstatSync(p).isDirectory() || fs.lstatSync(p).isFile())) {
+ return true;
+ }
+
+ // If it's a client-side plugin, copying client folder
+ if (answers.client) {
+ return /client/.test(p);
+ }
+
+ // If it's a server-side plugin, copying server folder
+ if (answers.server) {
+ return /server/.test(p);
+ }
+
+ }});
+ }
+
+ // Let's add this to the plugins.json
+ if (answers.addPluginsJson) {
+ const pluginsJson = path.join(dir, 'plugins.json');
+
+ fs.readJson(pluginsJson)
+ .then((j) => {
+
+ // This is a client-side plugin, let's push this.
+ if (answers.client) {
+ j.client.push(answers.pluginName);
+
+ const output = JSON.stringify(j, null, 2);
+ fs.writeFileSync(pluginsJson, output);
+ }
+
+ // This is a server-side plugin, let's push this.
+ if (answers.server) {
+ j.server.push(answers.pluginName);
+
+ const output = JSON.stringify(j, null, 2);
+ fs.writeFileSync(pluginsJson, output);
+ }
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ console.log(`✨ Yay! Plugin created! Find your plugin: ${answers.pluginName} in the ./plugins folder`);
+ }
+
+}
+
//==============================================================================
// Setting up the program command line arguments.
//==============================================================================
+program
+ .command('create')
+ .description('creates a seed plugin')
+ .action(createSeedPlugin);
+
program
.command('list')
.description('')
diff --git a/bin/templates/plugin/client/.babelrc b/bin/templates/plugin/client/.babelrc
new file mode 100644
index 000000000..60be246eb
--- /dev/null
+++ b/bin/templates/plugin/client/.babelrc
@@ -0,0 +1,14 @@
+{
+ "presets": [
+ "es2015"
+ ],
+ "plugins": [
+ "add-module-exports",
+ "transform-class-properties",
+ "transform-decorators-legacy",
+ "transform-object-assign",
+ "transform-object-rest-spread",
+ "transform-async-to-generator",
+ "transform-react-jsx"
+ ]
+}
\ No newline at end of file
diff --git a/bin/templates/plugin/client/.eslintrc.json b/bin/templates/plugin/client/.eslintrc.json
new file mode 100644
index 000000000..9fe56bd14
--- /dev/null
+++ b/bin/templates/plugin/client/.eslintrc.json
@@ -0,0 +1,23 @@
+{
+ "env": {
+ "browser": true,
+ "es6": true,
+ "mocha": true
+ },
+ "parserOptions": {
+ "sourceType": "module",
+ "ecmaFeatures": {
+ "experimentalObjectRestSpread": true,
+ "jsx": true
+ }
+ },
+ "parser": "babel-eslint",
+ "plugins": [
+ "react"
+ ],
+ "rules": {
+ "react/jsx-uses-react": "error",
+ "react/jsx-uses-vars": "error",
+ "no-console": ["warn", { "allow": ["warn", "error"] }]
+ }
+}
diff --git a/bin/templates/plugin/client/components/MyPluginComponent.css b/bin/templates/plugin/client/components/MyPluginComponent.css
new file mode 100644
index 000000000..187e68750
--- /dev/null
+++ b/bin/templates/plugin/client/components/MyPluginComponent.css
@@ -0,0 +1,27 @@
+.myPluginContainer {
+ padding: 10px;
+ background: #f0f0f0;
+ border: 1px solid #d6d6d6;
+ margin: 10px 0;
+ text-align: center;
+ border-radius: 3px;
+}
+
+.logo {
+ position: block;
+ animation: spin 2s infinite ease;
+ animation-delay: 1s;
+}
+
+@keyframes spin {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+.description {
+ color: #444444;
+}
diff --git a/bin/templates/plugin/client/components/MyPluginComponent.js b/bin/templates/plugin/client/components/MyPluginComponent.js
new file mode 100644
index 000000000..89e274e1a
--- /dev/null
+++ b/bin/templates/plugin/client/components/MyPluginComponent.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import {CoralLogo} from 'plugin-api/beta/client/components/ui';
+import styles from './MyPluginComponent.css';
+
+class MyPluginComponent extends React.Component {
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default MyPluginComponent;
diff --git a/bin/templates/plugin/client/index.js b/bin/templates/plugin/client/index.js
new file mode 100644
index 000000000..acd0910be
--- /dev/null
+++ b/bin/templates/plugin/client/index.js
@@ -0,0 +1,26 @@
+
+/**
+ This is a client index example file and it could look like this:
+
+ ```
+ import LoveButton from './components/LoveButton';
+
+ export default {
+ slots: {
+ commentReactions: [LoveButton]
+ },
+ reducer,
+ translations
+ };
+ ```
+
+ To read more info on how to build client plugins. Please, go to: https://coralproject.github.io/talk/plugins-client.html
+ */
+
+import MyPluginComponent from './components/MyPluginComponent';
+
+export default {
+ slots: {
+ stream: [MyPluginComponent]
+ }
+};
diff --git a/bin/templates/plugin/client/translations.yml b/bin/templates/plugin/client/translations.yml
new file mode 100644
index 000000000..d8407b801
--- /dev/null
+++ b/bin/templates/plugin/client/translations.yml
@@ -0,0 +1,15 @@
+#
+# This file is for translations and they should look like this:
+#
+#
+# ```
+# en:
+# coral-plugin-respect:
+# respect: Respect
+# respected: Respected
+# es:
+# coral-plugin-respect:
+# respect: Respetar
+# respected: Respetado
+# ```
+#
diff --git a/bin/templates/plugin/index.js b/bin/templates/plugin/index.js
new file mode 100644
index 000000000..f053ebf79
--- /dev/null
+++ b/bin/templates/plugin/index.js
@@ -0,0 +1 @@
+module.exports = {};
diff --git a/client/coral-embed-stream/src/components/Embed.js b/client/coral-embed-stream/src/components/Embed.js
index 57632d199..fee6fe025 100644
--- a/client/coral-embed-stream/src/components/Embed.js
+++ b/client/coral-embed-stream/src/components/Embed.js
@@ -8,6 +8,7 @@ import {TabBar, Tab, TabContent, TabPane} from 'coral-ui';
import ProfileContainer from 'coral-settings/containers/ProfileContainer';
import ConfigureStreamContainer
from 'coral-configure/containers/ConfigureStreamContainer';
+import cn from 'classnames';
export default class Embed extends React.Component {
changeTab = (tab) => {
@@ -25,47 +26,46 @@ export default class Embed extends React.Component {
};
render() {
- const {activeTab} = this.props;
+ const {activeTab, commentId} = this.props;
const {user} = this.props.auth;
+ const hasHighlightedComment = !!commentId;
return (
-
-
-
-
- {t('embed_comments_tab')}
+
+
+
+ {t('embed_comments_tab')}
+
+
+ {t('framework.my_profile')}
+
+ {can(user, 'UPDATE_CONFIG') &&
+
+ {t('framework.configure_stream')}
-
- {t('framework.my_profile')}
-
- {can(user, 'UPDATE_CONFIG') &&
-
- {t('framework.configure_stream')}
-
- }
-
-
+ }
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/client/coral-embed-stream/src/components/Stream.js b/client/coral-embed-stream/src/components/Stream.js
index 67e22ab6a..4107c8497 100644
--- a/client/coral-embed-stream/src/components/Stream.js
+++ b/client/coral-embed-stream/src/components/Stream.js
@@ -109,7 +109,7 @@ class Stream extends React.Component {
{comment &&
diff --git a/plugins/coral-plugin-love/client/styles.css b/plugins/coral-plugin-love/client/styles.css
index 316104e95..d7753a0e9 100644
--- a/plugins/coral-plugin-love/client/styles.css
+++ b/plugins/coral-plugin-love/client/styles.css
@@ -27,3 +27,9 @@
.icon {
padding: 0 2px;
}
+
+@media (max-width: 425px) {
+ .label {
+ display: none;
+ }
+}
diff --git a/plugins/coral-plugin-respect/client/RespectButton.js b/plugins/coral-plugin-respect/client/RespectButton.js
index 9bc556b67..878525051 100644
--- a/plugins/coral-plugin-respect/client/RespectButton.js
+++ b/plugins/coral-plugin-respect/client/RespectButton.js
@@ -45,11 +45,11 @@ class RespectButton extends React.Component {
className={cn(styles.button, {[styles.respected]: alreadyReacted}, `${plugin}-button`)}
onClick={this.handleClick}
>
-
+
{t(alreadyReacted ? 'coral-plugin-respect.respected' : 'coral-plugin-respect.respect')}
- {count > 0 && count}
+ {count > 0 && count}
);
diff --git a/plugins/coral-plugin-respect/client/styles.css b/plugins/coral-plugin-respect/client/styles.css
index e984dc3af..3ab0fbd29 100644
--- a/plugins/coral-plugin-respect/client/styles.css
+++ b/plugins/coral-plugin-respect/client/styles.css
@@ -28,3 +28,9 @@
.icon {
padding: 0 2px;
}
+
+@media (max-width: 425px) {
+ .label {
+ display: none;
+ }
+}
diff --git a/views/embed/stream.ejs b/views/embed/stream.ejs
index 03897d85f..99ca2072a 100644
--- a/views/embed/stream.ejs
+++ b/views/embed/stream.ejs
@@ -15,7 +15,7 @@
-
+