mirror of
https://github.com/wassname/talk.git
synced 2026-06-30 20:55:06 +08:00
merge
This commit is contained in:
@@ -6,6 +6,7 @@ dist/coral-admin/bundle.js
|
||||
tests/e2e/reports
|
||||
.DS_Store
|
||||
*.iml
|
||||
*.swp
|
||||
dump.rdb
|
||||
.env
|
||||
gaba.cfg
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
@@ -0,0 +1 @@
|
||||
<mxfile userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36" version="6.0.1.8" editor="www.draw.io" type="device"><diagram name="Page-1">7Vpbc6M2FP41nrYP6wFksP1oO0k7nd1O2nTa7qMMCtZGICpE4vTXVwIJkCVnnQbbWU/z4MDRBen7zk0HRmCVbX9ksNh8ogkio8BLtiNwNQqC6dwTv1Lw3AjCYNoIUoaTRuR3gjv8D1JCNS6tcIJKoyOnlHBcmMKY5jmKuSGDjNEns9s9JeZTC5giS3AXQ2JL/8QJ3zTSWeh18p8QTjf6yb6nWtYwfkgZrXL1vFEA7uu/pjmDei7Vv9zAhD71ROB6BFaMUt5cZdsVIhJaDVsz7mZPa7tuhnJ+yIBJ1Ix4hKRCesn1wvizBkOMELiLm6VYbSGFMaGVmGD5tMEc3RUwlsInoQlCtuEZEXe+uFRTI8bRdu/6/HbXQpkQzRBnz6KLGhBpjdCK1Nw9daQEGvpNn5C56giVIqTtzB0Y4kLh4cYGOKBIhJqoW8r4hqY0h+S6ky5r7pGcwTPBQFvM/5LicajuPuuWXCys1yRvP6sJSg4ZX0iNrmGHZYljLb7BpJ08T+xOQtjr8gVx/qwsDVacClG3g4+UFqpfyRl9QCtKKKv3DLz6r23R9tARbLEpIKMVixVmCkWx4hSpXoHSOgnni1rAEIEcP5pW+RZOw/kxOPV7jHrjaWiQalA6Bt8IqTvU/BeWQ+9EpEb+8UkNTFLHfmTyGrbtt4hhsQXEviETHoDtJpKcgO3AiliLohCCO8REqBkFERErWib4UVym8vL7X0R6MgpWcp/bgqGyHH8pf9AdxeN6fS1FOijEOdCyot7eEAemZojzdZbRC3L+xBXkZt7b0Zx8Pf4fH4I2fVIQABcEMxcEkwEgiCbHdx8vhYTatVyil/AnjtB/Ii/huxTbcg2LJMP5SObIN+JXHmOYWAbN9zkHewLpet6JI/F1dqwdSTCzrShwWFE0hBGF5zWi6cUaUXhGIwotI1pRBmWX62yNkvIdaDmYOWLFsbTcn9vJRyWeGni3jD5i4T7OAUmkE2Bt+L59TPY9YEMCBoCkXW4HySeIiUrIsNj1OQAJDECmDhVxlQ2GwCME53WEl+oHdc3gLCfMwC6T/UzXwta9XyskJI5Dx0OF3tcxY7aTYx/qN6cDGAVwBBKCxWa+kxjeib1biIhtcRMEU8dymkvLuRe6uiOCBKe51GkxvzyFLyVIOIZkoRoynCS12blQ34Pra4qWhxxnpg6kgyGQjo7hfuyi5WW4mDe4DjX0lmIxY0t9sHOYB7ucNi5Njepoff1EjR+0Jqr1o93PYSWAo5TPTJVpg5Sjzn056mRGLDC3I1ZzLD1BxJrYdZz/X14ci9TwRKQC+/hxw2jtNq7zRJ5CSJXivHTlIwzBWHS8YSiptoemJfqFXxOLE1qt6xbf0BV/TyQd9k3g7rkvmJzw3DeZWsCrYpFQNFU+imAmd52vy8JdK1rRLKtyzJ/39f1qtekTzGHa1bgPJK/KyCKWC+0yoY9wjcgtLXFd7AJXa8o5zUQHIhuW7UvsniWp19h2NsXpDtntO21pd4V+GyKVA+epEg+gEMAMkD6w9QEcSx1mdjrbI9eiDWXrujLwrmkbnhLgOHcfixKdYvco+Q0l2C7HaHgTyGEp4N13Dhj4O4adigSIbGjmcxsa3x8AG/2sgXMBqyRxifE+1J8fnaH8GjpKazRP6dV+p3FqrTYNPnAWHl3v7QZR68CCx3C+PXyivyv5RdVSFhU+qPrAQvQg6J53rbuR975JrexpZMOHslZPOYs/Kbb2LLpS/jskD+LfgsWSj5hXjfgKw5TBrBcUmseZS3ghJTjz9v4QLWNfUkiKDXzlNi6p1mNmIbZbb2VvrDTL3L39LrA55nffXoLrfwE=</diagram></mxfile>
|
||||
@@ -60,23 +60,43 @@ class CommentStream extends Component {
|
||||
componentDidMount () {
|
||||
// Set up messaging between embedded Iframe an parent component
|
||||
this.pym = new Pym.Child({polling: 100});
|
||||
const path = /https?\:\/\/([^?#]+)/.exec(this.pym.parentUrl);
|
||||
this.props.getStream(window.location);
|
||||
|
||||
const path = this.pym.parentUrl.split('#')[0];
|
||||
|
||||
this.props.getStream(path || window.location);
|
||||
this.path = path;
|
||||
|
||||
this.pym.sendMessage('childReady');
|
||||
|
||||
this.pym.onMessage('DOMContentLoaded', hash => {
|
||||
const commentId = hash.replace('#', 'c_');
|
||||
let count = 0;
|
||||
const interval = setInterval(() => {
|
||||
if (document.getElementById(commentId)) {
|
||||
window.clearInterval(interval);
|
||||
this.pym.scrollParentToChildEl(commentId);
|
||||
}
|
||||
|
||||
if (++count > 100) { // ~10 seconds
|
||||
// give up waiting for the comments to load.
|
||||
// it would be weird for the page to jump after that long.
|
||||
window.clearInterval(interval);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
render () {
|
||||
const rootItemId = this.props.items.assets && Object.keys(this.props.items.assets)[0];
|
||||
const rootItem = this.props.items.assets && this.props.items.assets[rootItemId];
|
||||
const {actions, users, comments} = this.props.items;
|
||||
const {loggedIn, user, showSignInDialog} = this.props.auth;
|
||||
const {loggedIn, user, showSignInDialog, signInOffset} = this.props.auth;
|
||||
const {status} = this.props.config;
|
||||
const {activeTab} = this.state;
|
||||
|
||||
return <div className={showSignInDialog ? 'expandForSignin' : ''}>
|
||||
const expandForLogin = showSignInDialog ? {
|
||||
minHeight: document.body.scrollHeight + 150
|
||||
} : {};
|
||||
return <div style={expandForLogin}>
|
||||
{
|
||||
rootItem
|
||||
? <div className="commentStream">
|
||||
@@ -85,7 +105,7 @@ class CommentStream extends Component {
|
||||
<Tab>Settings</Tab>
|
||||
<Tab>Configure Stream</Tab>
|
||||
</TabBar>
|
||||
{loggedIn && <UserBox user={user} logout={this.props.logout} />}
|
||||
{loggedIn && <UserBox user={user} logout={this.props.logout} />}
|
||||
{/* Add to the restricted param a boolean if the user is suspended*/}
|
||||
<RestrictedContent restricted={false} restrictedComp={<SuspendedAccount />}>
|
||||
<TabContent show={activeTab === 0}>
|
||||
@@ -109,7 +129,7 @@ class CommentStream extends Component {
|
||||
</div>
|
||||
: <p>Comments are closed for this thread.</p>
|
||||
}
|
||||
{!loggedIn && <SignInContainer />}
|
||||
{!loggedIn && <SignInContainer offset={signInOffset} />}
|
||||
{
|
||||
rootItem.comments && rootItem.comments.map((commentId) => {
|
||||
const comment = comments[commentId];
|
||||
@@ -267,7 +287,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
getStream: (rootId) => dispatch(getStream(rootId)),
|
||||
addNotification: (type, text) => dispatch(addNotification(type, text)),
|
||||
clearNotification: () => dispatch(clearNotification()),
|
||||
showSignInDialog: () => dispatch(showSignInDialog()),
|
||||
showSignInDialog: (offset) => dispatch(showSignInDialog(offset)),
|
||||
postAction: (item, action, user, itemType) => dispatch(postAction(item, action, user, itemType)),
|
||||
deleteAction: (item, action, user, itemType) => dispatch(deleteAction(item, action, user, itemType)),
|
||||
appendItemArray: (item, property, value, addToFront, itemType) => dispatch(appendItemArray(item, property, value, addToFront, itemType)),
|
||||
|
||||
@@ -8,7 +8,7 @@ body {
|
||||
}
|
||||
|
||||
.expandForSignin {
|
||||
min-height: 550px;
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
button {
|
||||
@@ -113,7 +113,6 @@ hr {
|
||||
|
||||
/* Comment styles */
|
||||
.comment {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import coralApi, {base} from '../helpers/response';
|
||||
import {addItem} from './items';
|
||||
|
||||
// Dialog Actions
|
||||
export const showSignInDialog = () => ({type: actions.SHOW_SIGNIN_DIALOG});
|
||||
export const showSignInDialog = (offset = 0) => ({type: actions.SHOW_SIGNIN_DIALOG, offset});
|
||||
export const hideSignInDialog = () => ({type: actions.HIDE_SIGNIN_DIALOG});
|
||||
|
||||
export const changeView = view => dispatch =>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import timeago from 'timeago.js';
|
||||
import esTA from '../../../../node_modules/timeago.js/locales/es';
|
||||
import has from 'lodash/has';
|
||||
import get from 'lodash/get';
|
||||
|
||||
/**
|
||||
* Default locales, this should be overriden by config file
|
||||
@@ -46,21 +48,18 @@ class i18n {
|
||||
* it takes a string with the translation key and returns
|
||||
* the translation value or the key itself if not found
|
||||
* it works with nested translations (my.page.title)
|
||||
*
|
||||
* any extra parameters are optional and replace a variable marked by {0}, {1}, etc in the translation.
|
||||
*/
|
||||
|
||||
this.t = (key) => {
|
||||
const arr = key.split('.');
|
||||
let translation = this.translations;
|
||||
try {
|
||||
for (let i = 0; i < arr.length; i++) {translation = translation[arr[i]];}
|
||||
} catch (error) {
|
||||
console.warn(`${key} language key not set`);
|
||||
return key;
|
||||
}
|
||||
|
||||
const val = String(translation);
|
||||
if (val) {
|
||||
return val;
|
||||
this.t = (key, ...replacements) => {
|
||||
if (has(this.translations, key)) {
|
||||
let translation = get(this.translations, key);
|
||||
// replace any {n} with the arguments passed to this method
|
||||
replacements.forEach((str, i) => {
|
||||
translation = translation.replace(new RegExp(`\\{${i}\\}`, 'g'), str);
|
||||
});
|
||||
return translation;
|
||||
} else {
|
||||
console.warn(`${key} language key not set`);
|
||||
return key;
|
||||
|
||||
@@ -22,7 +22,8 @@ export default function auth (state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case actions.SHOW_SIGNIN_DIALOG :
|
||||
return state
|
||||
.set('showSignInDialog', true);
|
||||
.set('showSignInDialog', true)
|
||||
.set('signInOffset', action.offset);
|
||||
case actions.HIDE_SIGNIN_DIALOG :
|
||||
return state.merge(Map({
|
||||
isLoading: false,
|
||||
|
||||
@@ -8,7 +8,8 @@ const FlagButton = ({flag, id, postAction, deleteAction, addItem, showSignInDial
|
||||
const flagged = flag && flag.current_user;
|
||||
const onFlagClick = () => {
|
||||
if (!currentUser) {
|
||||
showSignInDialog();
|
||||
const offset = document.getElementById(`c_${id}`).getBoundingClientRect().top - 75;
|
||||
showSignInDialog(offset);
|
||||
return;
|
||||
}
|
||||
if (!flagged) {
|
||||
|
||||
@@ -8,7 +8,8 @@ const LikeButton = ({like, id, postAction, deleteAction, addItem, showSignInDial
|
||||
const liked = like && like.current_user;
|
||||
const onLikeClick = () => {
|
||||
if (!currentUser) {
|
||||
showSignInDialog();
|
||||
const offset = document.getElementById(`c_${id}`).getBoundingClientRect().top - 75;
|
||||
showSignInDialog(offset);
|
||||
return;
|
||||
}
|
||||
if (!liked) {
|
||||
|
||||
@@ -6,8 +6,14 @@ import SignInContent from './SignInContent';
|
||||
import SingUpContent from './SignUpContent';
|
||||
import ForgotContent from './ForgotContent';
|
||||
|
||||
const SignDialog = ({open, view, handleClose, ...props}) => (
|
||||
<Dialog className={styles.dialog} open={open}>
|
||||
const SignDialog = ({open, view, handleClose, offset, ...props}) => (
|
||||
<Dialog
|
||||
className={styles.dialog}
|
||||
open={open}
|
||||
style={{
|
||||
position: 'relative',
|
||||
top: offset !== 0 && offset
|
||||
}}>
|
||||
<span className={styles.close} onClick={handleClose}>×</span>
|
||||
{view === 'SIGNIN' && <SignInContent {...props} />}
|
||||
{view === 'SIGNUP' && <SingUpContent {...props} />}
|
||||
|
||||
@@ -129,7 +129,7 @@ class SignInContainer extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {auth, showSignInDialog, noButton} = this.props;
|
||||
const {auth, showSignInDialog, noButton, offset} = this.props;
|
||||
return (
|
||||
<div>
|
||||
{!noButton && <Button id='coralSignInButton' onClick={showSignInDialog} full>
|
||||
@@ -138,6 +138,7 @@ class SignInContainer extends Component {
|
||||
<SignDialog
|
||||
open={auth.showSignInDialog}
|
||||
view={auth.view}
|
||||
offset={offset}
|
||||
{...this}
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
|
||||
+29
-3
@@ -1,10 +1,36 @@
|
||||
const nodemailer = require('nodemailer');
|
||||
|
||||
if (!process.env.TALK_SMTP_CONNECTION_URL) {
|
||||
console.error('TALK_SMTP_CONNECTION_URL should be defined if you would like to send password reset emails from Talk');
|
||||
const smtpRequiredProps = [
|
||||
'TALK_SMTP_USERNAME',
|
||||
'TALK_SMTP_PASSWORD',
|
||||
'TALK_SMTP_PROVIDER'
|
||||
];
|
||||
|
||||
smtpRequiredProps.forEach(prop => {
|
||||
if (!process.env[prop]) {
|
||||
console.error(`process.env.${prop} should be defined if you would like to send password reset emails from Talk`);
|
||||
}
|
||||
});
|
||||
|
||||
const options = {
|
||||
// list of providers here:
|
||||
// https://github.com/nodemailer/nodemailer-wellknown#supported-services
|
||||
service: process.env.TALK_SMTP_PROVIDER,
|
||||
auth: {
|
||||
user: process.env.TALK_SMTP_USERNAME,
|
||||
pass: process.env.TALK_SMTP_PASSWORD
|
||||
}
|
||||
};
|
||||
|
||||
if (process.env.TALK_SMTP_PORT) {
|
||||
options.port = process.env.TALK_SMTP_PORT;
|
||||
}
|
||||
|
||||
const defaultTransporter = nodemailer.createTransport(process.env.TALK_SMTP_CONNECTION_URL);
|
||||
if (process.env.TALK_SMTP_HOST) {
|
||||
options.host = process.env.TALK_SMTP_HOST;
|
||||
}
|
||||
|
||||
const defaultTransporter = nodemailer.createTransport(options);
|
||||
|
||||
const mailer = {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user