mirror of
https://github.com/wassname/talk.git
synced 2026-09-13 13:10:43 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b97a8fca2 | ||
|
|
6bff2de371 | ||
|
|
05283b08f7 | ||
|
|
838687a3ae | ||
|
|
7b0213299a | ||
|
|
f4dbc7a24d | ||
|
|
161e8b4117 | ||
|
|
6f3535984c | ||
|
|
e3557c1f7a | ||
|
|
692b6af09d | ||
|
|
25932e10d6 | ||
|
|
ec13a001a2 | ||
|
|
702a616e6c | ||
|
|
a3dd208fbd | ||
|
|
55c3406990 | ||
|
|
197fbc33e0 | ||
|
|
008a4fd7d5 | ||
|
|
8c5665095f | ||
|
|
647b2ea0c8 | ||
|
|
e61f88b98d | ||
|
|
b024421bbb | ||
|
|
ce95467145 | ||
|
|
1564b380b1 | ||
|
|
593b8959c5 | ||
|
|
3fda3b4b7c | ||
|
|
7e680038d6 | ||
|
|
71b8bb5d60 | ||
|
|
cfbafdeb5c | ||
|
|
c19d4a433a | ||
|
|
13cc80bd35 | ||
|
|
1eea2daeae | ||
|
|
5b29e7d351 | ||
|
|
3af39d99e4 | ||
|
|
1abf988366 | ||
|
|
205f943ab5 | ||
|
|
879683da4f | ||
|
|
974e884432 | ||
|
|
846319f1a9 | ||
|
|
e5237ae805 | ||
|
|
b9d88251e6 | ||
|
|
0d720626d4 | ||
|
|
50b2c6aa88 | ||
|
|
382019d907 | ||
|
|
97103739c2 | ||
|
|
9cf13691ad | ||
|
|
e6107173fb | ||
|
|
1d9ec7a779 | ||
|
|
0c345fe913 | ||
|
|
b6f06f1e89 | ||
|
|
aea3a7449e | ||
|
|
4db73ae73a | ||
|
|
2af7acd3db | ||
|
|
da9847b88f | ||
|
|
5b9f9f1b0d | ||
|
|
5427f295f6 | ||
|
|
620273769f | ||
|
|
dff3d79569 | ||
|
|
0904453e41 | ||
|
|
90eafb557c | ||
|
|
bcb294c625 | ||
|
|
b070a7cc52 | ||
|
|
e48d89a607 | ||
|
|
cb57e5c1e1 | ||
|
|
bf363621d3 |
@@ -1,4 +1,4 @@
|
||||
# Talk · [](https://circleci.com/gh/coralproject/talk) · [](https://nodesecurity.io/orgs/coralproject/projects/7bd7d26c-47ed-4a5f-8c4a-b919bf1c2946) · [](CONTRIBUTING.md#pull-requests)
|
||||
# Talk · [](https://circleci.com/gh/coralproject/talk) · [](CONTRIBUTING.md#pull-requests)
|
||||
|
||||
Online comments are broken. Our open-source commenting platform, Talk, rethinks how moderation, comment display, and conversation function, creating the opportunity for safer, smarter discussions around your work. [Read more about Talk here](https://coralproject.net/talk).
|
||||
|
||||
@@ -14,7 +14,7 @@ Learn more about Talk, including a deep dive into features for commenters and mo
|
||||
|
||||
## 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/).
|
||||
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://coralproject.net/blog/youve-installed-talk-now-what/).
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import queryString from 'query-string';
|
||||
import queryString from 'querystringify';
|
||||
|
||||
import {
|
||||
FETCH_USERS_REQUEST,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import queryString from 'query-string';
|
||||
import queryString from 'querystringify';
|
||||
|
||||
import {
|
||||
FETCH_ASSETS_REQUEST,
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import React from 'react';
|
||||
import styles from './Forbidden.css';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
const Forbidden = () => (
|
||||
<div className={styles.container}>
|
||||
<p className={styles.copy}>
|
||||
This page is for team use only. Please contact an administrator if you
|
||||
want to join this team.
|
||||
</p>
|
||||
<p className={styles.copy}>{t('error.PAGE_NOT_AVAILABLE_ROLE')}</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class ForgotPassword extends React.Component {
|
||||
href="#"
|
||||
onClick={this.handleSignInLink}
|
||||
>
|
||||
Sign in
|
||||
{t('login.sign_in')}
|
||||
</a>
|
||||
<Success />
|
||||
</div>
|
||||
@@ -48,7 +48,7 @@ class ForgotPassword extends React.Component {
|
||||
onChange={this.handleEmailChange}
|
||||
/>
|
||||
<Button type="submit" cStyle="black" full>
|
||||
{t('login.reset_password')}
|
||||
{t('login.reset_password_send_button')}
|
||||
</Button>
|
||||
<p className={styles.cta}>
|
||||
{t('login.go_back')}{' '}
|
||||
|
||||
@@ -14,7 +14,9 @@ import ApproveButton from './ApproveButton';
|
||||
import RejectButton from 'coral-admin/src/components/RejectButton';
|
||||
import CommentDeletedTombstone from './CommentDeletedTombstone';
|
||||
|
||||
import t, { timeago } from 'coral-framework/services/i18n';
|
||||
import { buildCommentURL } from 'coral-framework/utils/url';
|
||||
import TimeAgo from 'coral-framework/components/TimeAgo';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
class UserDetailComment extends React.Component {
|
||||
approve = () =>
|
||||
@@ -73,9 +75,7 @@ class UserDetailComment extends React.Component {
|
||||
checked={selected}
|
||||
onChange={e => toggleSelect(e.target.value, e.target.checked)}
|
||||
/>
|
||||
<span className={styles.created}>
|
||||
{timeago(comment.created_at)}
|
||||
</span>
|
||||
<TimeAgo className={styles.created} datetime={comment.created_at} />
|
||||
{comment.editing && comment.editing.edited ? (
|
||||
<span>
|
||||
<span className={styles.editedMarker}>
|
||||
@@ -112,7 +112,7 @@ class UserDetailComment extends React.Component {
|
||||
/>
|
||||
<a
|
||||
className={styles.external}
|
||||
href={`${comment.asset.url}?commentId=${comment.id}`}
|
||||
href={buildCommentURL(comment.asset.url, comment.id)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
|
||||
@@ -176,7 +176,7 @@ class People extends React.Component {
|
||||
})
|
||||
}
|
||||
>
|
||||
Suspend User
|
||||
{t('modqueue.suspend')}
|
||||
</ActionsMenuItem>
|
||||
)}
|
||||
|
||||
@@ -195,7 +195,7 @@ class People extends React.Component {
|
||||
})
|
||||
}
|
||||
>
|
||||
Ban User
|
||||
{t('modqueue.ban_user_actions')}
|
||||
</ActionsMenuItem>
|
||||
)}
|
||||
</ActionsMenu>
|
||||
|
||||
@@ -53,7 +53,7 @@ class EmbedLink extends Component {
|
||||
{t('embedlink.copy')}
|
||||
</Button>
|
||||
<div className={styles.copiedText}>
|
||||
{this.state.copied && 'Copied!'}
|
||||
{this.state.copied && t('embedlink.copied')}
|
||||
</div>
|
||||
</div>
|
||||
</ConfigureCard>
|
||||
|
||||
@@ -10,7 +10,9 @@ const Wordlist = ({ suspectWords, bannedWords, onChangeWordlist }) => (
|
||||
<p>{t('configure.banned_word_text')}</p>
|
||||
<TagsInput
|
||||
value={bannedWords}
|
||||
inputProps={{ placeholder: 'word or phrase' }}
|
||||
inputProps={{
|
||||
placeholder: t('configure.suspect_or_forbidden_words_placeholder'),
|
||||
}}
|
||||
onChange={tags => onChangeWordlist('banned', tags)}
|
||||
/>
|
||||
</ConfigureCard>
|
||||
@@ -18,7 +20,9 @@ const Wordlist = ({ suspectWords, bannedWords, onChangeWordlist }) => (
|
||||
<p>{t('configure.suspect_word_text')}</p>
|
||||
<TagsInput
|
||||
value={suspectWords}
|
||||
inputProps={{ placeholder: 'word or phrase' }}
|
||||
inputProps={{
|
||||
placeholder: t('configure.suspect_or_forbidden_words_placeholder'),
|
||||
}}
|
||||
onChange={tags => onChangeWordlist('suspect', tags)}
|
||||
/>
|
||||
</ConfigureCard>
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
line-height: 1.5;
|
||||
font-weight: 300;
|
||||
margin-bottom: 8px;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.body {
|
||||
@@ -188,4 +189,4 @@
|
||||
|
||||
.commentContentFooter {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@ import cn from 'classnames';
|
||||
import ApproveButton from 'coral-admin/src/components/ApproveButton';
|
||||
import RejectButton from 'coral-admin/src/components/RejectButton';
|
||||
import CommentDeletedTombstone from '../../../components/CommentDeletedTombstone';
|
||||
import TimeAgo from 'coral-framework/components/TimeAgo';
|
||||
|
||||
import t, { timeago } from 'coral-framework/services/i18n';
|
||||
import { buildCommentURL } from 'coral-framework/utils/url';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
class Comment extends React.Component {
|
||||
ref = null;
|
||||
@@ -126,9 +128,10 @@ class Comment extends React.Component {
|
||||
{comment.user.username}
|
||||
</span>
|
||||
|
||||
<span className={styles.created}>
|
||||
{timeago(comment.created_at)}
|
||||
</span>
|
||||
<TimeAgo
|
||||
className={styles.created}
|
||||
datetime={comment.created_at}
|
||||
/>
|
||||
{comment.editing && comment.editing.edited ? (
|
||||
<span>
|
||||
<span className={styles.editedMarker}>
|
||||
@@ -168,7 +171,7 @@ class Comment extends React.Component {
|
||||
<div className={styles.commentContentFooter}>
|
||||
<a
|
||||
className={styles.external}
|
||||
href={`${comment.asset.url}?commentId=${comment.id}`}
|
||||
href={buildCommentURL(comment.asset.url, comment.id)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styles from './Story.css';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
const formatDate = date => {
|
||||
const d = new Date(date);
|
||||
@@ -14,7 +15,9 @@ const Story = ({ author, title, createdAt, open, id, goToStory }) => {
|
||||
<div className={styles.meta}>
|
||||
<span className={styles.author}>By {author}</span>
|
||||
<span className={styles.createdAt}>{formatDate(createdAt)}</span>
|
||||
<span className={styles.status}>{open ? 'Open' : 'Closed'}</span>
|
||||
<span className={styles.status}>
|
||||
{open ? t('streams.open') : t('streams.closed')}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { createPostMessage } from 'coral-framework/services/postMessage';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const staticConfig = getStaticConfiguration();
|
||||
const { STATIC_ORIGIN: origin } = staticConfig;
|
||||
const { BASE_ORIGIN: origin } = staticConfig;
|
||||
const postMessage = createPostMessage(origin);
|
||||
|
||||
// Get the auth element and parse it as JSON by decoding it.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as actions from '../constants/stream';
|
||||
import { buildUrl } from 'coral-framework/utils/url';
|
||||
import queryString from 'query-string';
|
||||
import queryString from 'querystringify';
|
||||
|
||||
export const setActiveReplyBox = id => ({
|
||||
type: actions.SET_ACTIVE_REPLY_BOX,
|
||||
@@ -14,12 +14,13 @@ export const setSort = ({ sortOrder, sortBy }) => ({
|
||||
});
|
||||
|
||||
export const viewAllComments = () => (dispatch, _, { pym }) => {
|
||||
const search = queryString.stringify({
|
||||
...queryString.parse(location.search),
|
||||
comment_id: undefined,
|
||||
});
|
||||
const query = queryString.parse(location.search);
|
||||
|
||||
// remove the comment_id url param
|
||||
delete query.comment_id;
|
||||
|
||||
const search = queryString.stringify(query);
|
||||
|
||||
const url = buildUrl({ ...location, search });
|
||||
|
||||
try {
|
||||
|
||||
@@ -9,6 +9,7 @@ import cn from 'classnames';
|
||||
import { getTotalReactionsCount } from 'coral-framework/utils';
|
||||
|
||||
import t from 'coral-framework/services/i18n';
|
||||
import { buildCommentURL } from 'coral-framework/utils/url';
|
||||
|
||||
class Comment extends React.Component {
|
||||
render() {
|
||||
@@ -79,9 +80,10 @@ class Comment extends React.Component {
|
||||
<li>
|
||||
<a
|
||||
className={styles.viewLink}
|
||||
href={`${this.props.comment.asset.url}?commentId=${
|
||||
href={buildCommentURL(
|
||||
this.props.comment.asset.url,
|
||||
this.props.comment.id
|
||||
}`}
|
||||
)}
|
||||
target="_parent"
|
||||
>
|
||||
<Icon name="open_in_new" className={styles.iconView} />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import queryString from 'query-string';
|
||||
import queryString from 'querystringify';
|
||||
import pym from 'pym.js';
|
||||
import EventEmitter from 'eventemitter2';
|
||||
import { buildUrl } from 'coral-framework/utils/url';
|
||||
@@ -94,12 +94,13 @@ export default class Stream {
|
||||
|
||||
// Remove the permalink comment id from the hash.
|
||||
this.pym.onMessage('coral-view-all-comments', () => {
|
||||
const search = queryString.stringify({
|
||||
...queryString.parse(location.search),
|
||||
commentId: undefined,
|
||||
});
|
||||
const query = queryString.parse(location.search);
|
||||
|
||||
// Remove the commentId url param.
|
||||
delete query.commentId;
|
||||
|
||||
const search = queryString.stringify(query);
|
||||
|
||||
const url = buildUrl({ ...location, search });
|
||||
|
||||
// Change the url.
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { timeago } from 'coral-framework/services/i18n';
|
||||
import cn from 'classnames';
|
||||
import styles from './CommentTimestamp.css';
|
||||
import TimeAgo from 'coral-framework/components/TimeAgo';
|
||||
|
||||
const CommentTimestamp = ({ className, created_at }) => (
|
||||
<div className={cn(className, styles.timestamp, 'talk-comment-timestamp')}>
|
||||
{timeago(created_at)}
|
||||
</div>
|
||||
<TimeAgo
|
||||
className={cn(className, styles.timestamp, 'talk-comment-timestamp')}
|
||||
datetime={created_at}
|
||||
/>
|
||||
);
|
||||
|
||||
CommentTimestamp.propTypes = {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.timeago {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { timeago } from 'coral-framework/services/i18n';
|
||||
import cn from 'classnames';
|
||||
import styles from './TimeAgo.css';
|
||||
|
||||
class TimeAgo extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { timeago: true };
|
||||
}
|
||||
toggleDate = () => this.setState({ timeago: !this.state.timeago });
|
||||
render() {
|
||||
var displayTime = this.state.timeago
|
||||
? timeago(this.props.datetime)
|
||||
: new Date(this.props.datetime).toLocaleString();
|
||||
|
||||
var titleDate = !this.state.timeago
|
||||
? timeago(this.props.datetime)
|
||||
: new Date(this.props.datetime).toLocaleString();
|
||||
return (
|
||||
<span
|
||||
onClick={this.toggleDate}
|
||||
className={cn(
|
||||
this.props.className,
|
||||
styles.timeago,
|
||||
'talk-comment-timeago'
|
||||
)}
|
||||
title={titleDate}
|
||||
>
|
||||
{displayTime}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TimeAgo.propTypes = {
|
||||
datetime: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
export default TimeAgo;
|
||||
@@ -1,7 +1,7 @@
|
||||
import url from 'url';
|
||||
import parse from 'url-parse';
|
||||
|
||||
const base = document.querySelector('base');
|
||||
const baseUrl = (base && url.parse(base.href)) || {};
|
||||
const baseUrl = (base && parse(base.href)) || {};
|
||||
|
||||
export const BASE_URL = base.href;
|
||||
export const BASE_PATH = baseUrl.pathname;
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ export async function createContext({
|
||||
});
|
||||
|
||||
const staticConfig = getStaticConfiguration();
|
||||
let { LIVE_URI: liveUri, STATIC_ORIGIN: origin } = staticConfig;
|
||||
let { LIVE_URI: liveUri, BASE_ORIGIN: origin } = staticConfig;
|
||||
if (liveUri == null) {
|
||||
// The protocol must match the origin protocol, secure/insecure.
|
||||
const protocol = location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
|
||||
@@ -75,10 +75,15 @@ let TIMEAGO_INSTANCE;
|
||||
// detectLanguage will try to get the locale from storage if available,
|
||||
// otherwise will try to get it from the navigator, otherwise, it will fallback
|
||||
// to the default language.
|
||||
const detectLanguage = () =>
|
||||
first(
|
||||
const detectLanguage = () => {
|
||||
var browserLanguages = navigator.languages;
|
||||
//IE11 and MS-EDGE do not provide navigator.languages
|
||||
if (!browserLanguages) {
|
||||
browserLanguages = [navigator.language];
|
||||
}
|
||||
return first(
|
||||
negotiateLanguages(
|
||||
navigator.languages,
|
||||
browserLanguages,
|
||||
whitelistedLanguages || supportedLocales,
|
||||
{
|
||||
defaultLocale,
|
||||
@@ -86,6 +91,7 @@ const detectLanguage = () =>
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export function setupTranslations() {
|
||||
// locale
|
||||
@@ -100,10 +106,10 @@ export function setupTranslations() {
|
||||
ta.register('da', daTA);
|
||||
ta.register('de', deTA);
|
||||
ta.register('fr', frTA);
|
||||
ta.register('nl-NL', nlTA);
|
||||
ta.register('pt-BR', pt_BRTA);
|
||||
ta.register('zh-CN', zh_CNTA);
|
||||
ta.register('zh-TW', zh_TWTA);
|
||||
ta.register('nl_NL', nlTA);
|
||||
ta.register('pt_BR', pt_BRTA);
|
||||
ta.register('zh_CN', zh_CNTA);
|
||||
ta.register('zh_TW', zh_TWTA);
|
||||
TIMEAGO_INSTANCE = ta();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { capitalize } from 'coral-framework/helpers/strings';
|
||||
import assignWith from 'lodash/assignWith';
|
||||
import mapValues from 'lodash/mapValues';
|
||||
export * from 'coral-framework/helpers/strings';
|
||||
export * from './url';
|
||||
|
||||
export const getTotalActionCount = (type, comment) => {
|
||||
return comment.action_summaries
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import parse from 'url-parse';
|
||||
|
||||
export function buildUrl(
|
||||
{ protocol, hostname, port, pathname, search, hash } = window.location
|
||||
) {
|
||||
@@ -10,3 +12,10 @@ export function buildUrl(
|
||||
port ? `:${port}` : ''
|
||||
}${pathname}${search}${hash}`;
|
||||
}
|
||||
|
||||
export function buildCommentURL(assetURL, commentID) {
|
||||
const u = parse(assetURL, true);
|
||||
u.query.commentId = commentID;
|
||||
u.set('query', u.query);
|
||||
return u.href;
|
||||
}
|
||||
|
||||
@@ -22,13 +22,10 @@ to persist data. The following versions are supported:
|
||||
- MongoDB 3.2+
|
||||
- Redis 3.2.5+
|
||||
|
||||
An optional dependency for Talk is
|
||||
[Docker](https://www.docker.com/community-edition#/download).
|
||||
It is used during development to set up the database and can be
|
||||
used to [install via Docker](#installation-from-docker). We have tested Talk
|
||||
and this documentation with versions 17.06.2+.
|
||||
You can run Talk (and its dependencies) locally or from [Docker](https://www.docker.com/community-edition#/download) containers. Docker is used in the local example below for the database and cache, however it is possible to run Talk without Docker by configuring your own MongoDB and Redis instances. We have tested Talk
|
||||
and this documentation with Docker versions 17.06.2+.
|
||||
|
||||
Another optional dependency for Talk is
|
||||
An optional dependency for Talk is
|
||||
[Docker Compose](https://docs.docker.com/compose/install/). It
|
||||
can be used to setup your environment easily for testing. We have tested Talk
|
||||
and this documentation with versions 1.14.0+.
|
||||
@@ -38,8 +35,9 @@ and this documentation with versions 1.14.0+.
|
||||
### Installation from Docker
|
||||
|
||||
To use Talk without major customization you can run the application using our
|
||||
provided docker image. The following is a `docker-compose.yml` file that can
|
||||
be used to setup Talk:
|
||||
provided docker image.
|
||||
|
||||
Start by making a new directory and create a file called `docker-compose.yml` and copy the following:
|
||||
|
||||
```yml
|
||||
# For details on the syntax of docker-compose.yml files, check out:
|
||||
@@ -79,7 +77,7 @@ volumes:
|
||||
external: false
|
||||
```
|
||||
|
||||
This is the bare minimum needed to run the demo, for more configuration
|
||||
The environment variables listed above are the bare minimum needed to run the demo, for more configuration
|
||||
variables, check out the [Configuration](/talk/configuration/) section.
|
||||
|
||||
|
||||
@@ -104,8 +102,7 @@ Creating talk_1 ...
|
||||
Creating talk_1 ... done
|
||||
```
|
||||
|
||||
|
||||
And when you run `docker-compose ps`, you should see something like:
|
||||
Once everything has completed, run `docker-compose ps`, and you should see something like:
|
||||
|
||||
```
|
||||
Name Command State Ports
|
||||
@@ -116,8 +113,8 @@ talk_1 yarn start Up 0.0.0.0:3000->3000/tcp
|
||||
```
|
||||
|
||||
|
||||
Continue onto the [Running](#running) section for details on how to complete the
|
||||
installation and get started using Talk.
|
||||
You now have a Talk instance up and running! Continue on to the [Setup](#setup) section for details on how to complete the
|
||||
initial setup and get started using Talk.
|
||||
|
||||
### Installation from Source
|
||||
|
||||
@@ -178,32 +175,35 @@ You can now start the application by running:
|
||||
yarn watch:server
|
||||
```
|
||||
|
||||
Continue onto the [Running](#running) section for details on how to complete the
|
||||
Continue onto the [Setup](#setup) section for details on how to complete the
|
||||
installation and get started using Talk.
|
||||
|
||||
## Running
|
||||
## Setup
|
||||
### Create Admin Account
|
||||
|
||||
You can now navigate to
|
||||
With Talk running, you can now navigate to
|
||||
[http://127.0.0.1:3000/admin/install](http://127.0.0.1:3000/admin/install)
|
||||
and go through the admin installation. There you will be prompted to create your
|
||||
first admin account, and specify the domain whitelist for domains that are
|
||||
allowed to have the comment box on.
|
||||
and walk through the initial setup steps.
|
||||
|
||||
* First, enter your **Organization Name** and **Organization Contact Email**. This will appear in emails when inviting new team members.
|
||||
* Next, create your Admin user. You can specify an **Email Address**, **Username**, and **Password**
|
||||
* Finally, enter your list of **Permitted Domains**, read [here](/talk/configuring-talk/#permitted-domains) about whitelisting domains
|
||||
|
||||
_During development, ensure you whitelist 127.0.0.1:3000 otherwise the
|
||||
[http://127.0.0.1:3000/](http://127.0.0.1:3000/) page will not
|
||||
load._
|
||||
|
||||
Once you've completed the installation, you can visit
|
||||
[http://127.0.0.1:3000/](http://127.0.0.1:3000/) where you can
|
||||
view our development area where we test out features in Talk where you can write
|
||||
comments and see them in the admin interface where you can do moderation and
|
||||
reconfigure the user experience.
|
||||
Once the setup wizard has been completed you can log into Talk ([http://127.0.0.1:3000/](http://127.0.0.1:3000/)) using the email address and password for the Admin user account that you just created.
|
||||
|
||||
## Demo
|
||||
From here you can test out features in Talk, see comments in the admin interface where you can do moderation, and configure the user experience.
|
||||
In the next step you'll create some user comments to moderate.
|
||||
|
||||
|
||||
### Demo Embedded Comments
|
||||
|
||||
If you've followed the documentation above, you'll now have a running copy of
|
||||
Talk. To demonstrate what your own self-hosted copy of Talk can do, below
|
||||
you'll find a demo that can be used to test the copy that is running now on your
|
||||
Talk. To demonstrate what your own self-hosted copy of Talk can do, we created the demo below
|
||||
that can be used to test the copy that is running now on your
|
||||
machine.
|
||||
|
||||
In order for the demo to work, you must add
|
||||
|
||||
@@ -144,9 +144,9 @@ Some queries you may notice seem to return `null` or an error of
|
||||
route that requires authorization. You can perform authorization a few ways in
|
||||
Talk:
|
||||
|
||||
1. As a [Bearer Token](#Bearer-Token)
|
||||
2. As a [Query Parameter](#Query-Parameter)
|
||||
3. As a [Cookie](#Cookie)
|
||||
1. As a [Bearer Token](#bearer-token)
|
||||
2. As a [Query Parameter](#query-parameter)
|
||||
3. As a [Cookie](#cookie)
|
||||
|
||||
Essentially, you need to get access to a JWT token that you can use to authorize
|
||||
your requests. Generating one is simple, you can use the CLI tools in Talk to do
|
||||
|
||||
@@ -18,11 +18,11 @@ By default, Talk will use "Lazy Asset Creation" to dynamically generate Assets
|
||||
in Talk in order to make it easier for lighter installations. In order to have
|
||||
more strict control over this flow, we will create a plugin that will:
|
||||
|
||||
1. Disable "Lazy Asset Creation" by [Overriding a Resolver](#Overriding-a-Resolver).
|
||||
2. Create Assets from our CMS by [Creating a New Asset Route](#Creating-a-New-Asset-Route).
|
||||
3. Facilitate updates from our CMS to keep Talk in sync by [Creating an Asset Update Route](#Creating-an-Asset-Update-Route).
|
||||
1. Disable "Lazy Asset Creation" by [Overriding a Resolver](#overriding-a-resolver).
|
||||
2. Create Assets from our CMS by [Creating a New Asset Route](#creating-a-new-asset-route).
|
||||
3. Facilitate updates from our CMS to keep Talk in sync by [Creating an Asset Update Route](#creating-an-asset-update-route).
|
||||
|
||||
We will then modify our embed so that we can [Target the Asset](#Target-the-Asset).
|
||||
We will then modify our embed so that we can [Target the Asset](#target-the-asset).
|
||||
|
||||
But first we should grab our basic plugin structure:
|
||||
|
||||
@@ -248,7 +248,7 @@ module.exports = router => {
|
||||
};
|
||||
```
|
||||
|
||||
As you can see from the previous step of [Creating a New Asset Route](#Creating-a-New-Asset-Route)
|
||||
As you can see from the previous step of [Creating a New Asset Route](#creating-a-New-Asset-Route)
|
||||
, we have added the new `PUT` route to the router. This is a simple addition
|
||||
that allows your CMS to call into Talk when the asset has updated it's title,
|
||||
it's url (or really anything in the [AssetSchema](https://github.com/coralproject/talk/blob/master/models/asset.js)) to keep the Talk Admin and links up to date.
|
||||
|
||||
@@ -231,6 +231,15 @@ class ErrContainsProfanity extends TalkError {
|
||||
}
|
||||
}
|
||||
|
||||
class ErrHTTPNotFound extends TalkError {
|
||||
constructor() {
|
||||
super('http not found', {
|
||||
translation_key: 'NOT_FOUND',
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class ErrNotFound extends TalkError {
|
||||
constructor() {
|
||||
super('not found', {
|
||||
@@ -432,4 +441,5 @@ module.exports = {
|
||||
ErrSpecialChars,
|
||||
ErrUsernameTaken,
|
||||
ExtendableError,
|
||||
ErrHTTPNotFound,
|
||||
};
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
const { SubscriptionManager } = require('graphql-subscriptions');
|
||||
const { SubscriptionServer } = require('subscriptions-transport-ws');
|
||||
const debug = require('debug')('talk:graph:subscriptions');
|
||||
const DataLoader = require('dataloader');
|
||||
|
||||
const { getPubsub } = require('./pubsub');
|
||||
const schema = require('../schema');
|
||||
const Context = require('../context');
|
||||
const plugins = require('../../services/plugins');
|
||||
const User = require('../../models/user');
|
||||
const { singleJoinBy } = require('../loaders/util');
|
||||
|
||||
const { deserializeUser } = require('../../services/subscriptions');
|
||||
const setupFunctions = require('./setupFunctions');
|
||||
@@ -59,31 +62,103 @@ const onConnect = async (connectionParams, connection) => {
|
||||
}`;
|
||||
}
|
||||
|
||||
try {
|
||||
// Pull the user off of the upgrade request.
|
||||
const hydratedRequest = await deserializeUser(connection.upgradeReq);
|
||||
|
||||
// Update the connections upgrade request, as we'll use that to verify that
|
||||
// the user is allowed each operation.
|
||||
connection.upgradeReq = hydratedRequest;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
// Call all the hooks.
|
||||
await Promise.all(
|
||||
hooks.onConnect.map(hook => hook(connectionParams, connection))
|
||||
);
|
||||
};
|
||||
|
||||
const onOperation = (parsedMessage, baseParams, connection) => {
|
||||
// Cache the upgrade request.
|
||||
let upgradeReq = connection.upgradeReq;
|
||||
/**
|
||||
* batchedUserRefresher will get users based on ID for websocket user refresh
|
||||
* operations to reduce load related to user refreshing.
|
||||
*/
|
||||
const batchedUserRefresher = new DataLoader(
|
||||
userIDs => {
|
||||
debug(`OPERATION: refreshing ${userIDs.length} users.`);
|
||||
return User.find({ id: { $in: userIDs } }).then(
|
||||
singleJoinBy(userIDs, 'id')
|
||||
);
|
||||
},
|
||||
{
|
||||
// Disable the cache, as this dataloader is long lived, and the point of
|
||||
// using this dataloader is to batch refetch operations rather than caching
|
||||
// then as we normally would.
|
||||
cache: false,
|
||||
}
|
||||
);
|
||||
|
||||
// Attach the context per request.
|
||||
baseParams.context = async () => {
|
||||
let req;
|
||||
const contextGenerator = req => {
|
||||
// Pull the user(?) off the request.
|
||||
const { user, jwt } = req;
|
||||
|
||||
try {
|
||||
req = await deserializeUser(upgradeReq);
|
||||
debug(`user ${req.user ? 'was' : 'was not'} on websocket request`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (!user || !jwt) {
|
||||
// There is no valid user on the request, let it continue as is then.
|
||||
return async () => new Context(req);
|
||||
}
|
||||
|
||||
return new Context({});
|
||||
// Provide a flag that can be used to short circuit invalid requests.
|
||||
let expiredLogin = false;
|
||||
|
||||
async function refreshUser() {
|
||||
// Check to see if this request has been short circuited.
|
||||
if (expiredLogin) {
|
||||
// It has, let's exit here.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Validate that the JWT for this user has not expired.
|
||||
const { exp = false } = jwt;
|
||||
if (exp && exp < Date.now() / 1000) {
|
||||
// Mark that this token has expired, don't bother performing this syscall
|
||||
// again to check the time.
|
||||
expiredLogin = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Let's refresh the user from the database, as they may have changed.
|
||||
const refreshedUser = await batchedUserRefresher.load(user.id);
|
||||
if (!refreshedUser) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return refreshedUser;
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the context builder function that'll use the passed context to
|
||||
// generate future contexts.
|
||||
return async () => {
|
||||
// Refresh the user (potentially null).
|
||||
const refreshedUser = await refreshUser();
|
||||
|
||||
// Attach the refreshedUser to the request.
|
||||
req.user = refreshedUser;
|
||||
|
||||
// Return the new context.
|
||||
return new Context(req);
|
||||
};
|
||||
};
|
||||
|
||||
const onOperation = async (parsedMessage, baseParams, connection) => {
|
||||
// Pull the upgrade request off of the connection.
|
||||
const upgradeReq = connection.upgradeReq;
|
||||
|
||||
// Attach the context handler to the request.
|
||||
baseParams.context = contextGenerator(upgradeReq);
|
||||
|
||||
return baseParams;
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@ const fetch = require('node-fetch');
|
||||
const { merge } = require('lodash');
|
||||
const { version } = require('../../package.json');
|
||||
const { SCRAPER_HEADERS, SCRAPER_PROXY_URL } = require('../../config');
|
||||
const HttpsProxyAgent = require('https-proxy-agent');
|
||||
const ProxyAgent = require('proxy-agent');
|
||||
|
||||
// Load the scraper with the rules.
|
||||
const metascraper = require('metascraper').load([
|
||||
@@ -37,7 +37,7 @@ const headers = merge(
|
||||
);
|
||||
|
||||
// Add proxy configuration if exists.
|
||||
const agent = SCRAPER_PROXY_URL ? new HttpsProxyAgent(SCRAPER_PROXY_URL) : null;
|
||||
const agent = SCRAPER_PROXY_URL ? new ProxyAgent(SCRAPER_PROXY_URL) : null;
|
||||
|
||||
/**
|
||||
* Scrapes the given asset for metadata.
|
||||
|
||||
@@ -48,6 +48,8 @@ de:
|
||||
comment_post_notif_premod: 'Vielen Dank für Ihren Kommentar. Unsere Moderatoren werden ihn in Kürze bearbeiten.'
|
||||
comment_singular: Kommentar
|
||||
common:
|
||||
copied: 'Kopiert'
|
||||
notsupported: 'Nicht unterstützt'
|
||||
copy: Kopieren
|
||||
error: 'Ein Problem ist aufgetreten.'
|
||||
reaction: 'Reaktion'
|
||||
@@ -216,6 +218,7 @@ de:
|
||||
embed_comments_tab: Kommentare
|
||||
embedlink:
|
||||
copy: 'In die Zwischenablage kopieren'
|
||||
copied: 'Kopiert'
|
||||
error:
|
||||
ALREADY_EXISTS: 'Ressource existiert bereits'
|
||||
CANNOT_IGNORE_STAFF: 'Mitarbeiter können nicht ignoriert werden.'
|
||||
|
||||
@@ -49,6 +49,8 @@ en:
|
||||
comment_singular: Comment
|
||||
common:
|
||||
copy: Copy
|
||||
copied: 'Copied'
|
||||
notsupported: 'Not supported'
|
||||
error: 'An error has occurred.'
|
||||
reaction: reaction
|
||||
reactions: reactions
|
||||
@@ -144,6 +146,7 @@ en:
|
||||
organization_info_copy_2: 'We recommend creating a generic email account (eg. community@yournewsroom.com) for this purpose. This means it can remain consistent over time, and doesn''t expose a name that users could target if their account were blocked.'
|
||||
organization_information: 'Organization Information'
|
||||
organization_name: 'Organization Name'
|
||||
suspect_or_forbidden_words_placeholder: 'Word or phrase'
|
||||
product_guide_link: 'Product Guide'
|
||||
report_bug_or_feedback: 'Report a bug or give feedback'
|
||||
require_email_verification: 'Require Email Verification'
|
||||
@@ -219,6 +222,7 @@ en:
|
||||
embed_comments_tab: Comments
|
||||
embedlink:
|
||||
copy: 'Copy to Clipboard'
|
||||
copied: 'Copied'
|
||||
error:
|
||||
ALREADY_EXISTS: 'Resource already exists'
|
||||
AUTHENTICATION: 'An error occurred trying to authenticate your account.'
|
||||
@@ -249,6 +253,7 @@ en:
|
||||
organization_contact_email: 'Organization email is not valid.'
|
||||
organization_name: 'Organization name must only contain letters or numbers.'
|
||||
password: 'Password must be at least 8 characters'
|
||||
PAGE_NOT_AVAILABLE_ROLE: 'This page is for team use only. Please contact an administrator if you want to join this team.'
|
||||
PASSWORD_INCORRECT: 'Your current password was entered incorrectly'
|
||||
PASSWORD_LENGTH: 'Password is too short'
|
||||
PASSWORD_REQUIRED: 'Must input a password'
|
||||
@@ -359,6 +364,7 @@ en:
|
||||
sign_in_button: 'Sign Inx'
|
||||
sign_in_message: 'Sign in to interact with your community.'
|
||||
password: Password
|
||||
reset_password_send_button: 'Retrieve Password'
|
||||
request_passowrd: 'Request a new one.'
|
||||
team_sign_in: 'Team sign in'
|
||||
marketing: 'This looks like an ad/marketing'
|
||||
@@ -372,6 +378,7 @@ en:
|
||||
approve: Approve
|
||||
approved: Approved
|
||||
ban_user: Ban
|
||||
ban_user_actions: 'Ban User'
|
||||
billion: B
|
||||
close: Close
|
||||
empty_queue: 'No more comments to moderate! You''re all caught up. Go have some ☕️'
|
||||
@@ -406,6 +413,7 @@ en:
|
||||
show_shortcuts: 'Show Shortcuts'
|
||||
singleview: 'Zen mode'
|
||||
sort: Sort
|
||||
suspend: 'Suspend User'
|
||||
system_withheld: 'System Withheld'
|
||||
thismenu: 'Open this menu'
|
||||
thousand: k
|
||||
|
||||
+16
-2
@@ -139,6 +139,8 @@ es:
|
||||
organization_info_copy_2: 'Recomendamos crear un email genérico (ej: community@yournewsroom.com) for this purpose. Esto significa que puede permanecer consistente con el tiempo y no expone un nombre que los usuarios puedan atacar si su cuenta fue bloqueada.'
|
||||
organization_information: 'Información de la Organización'
|
||||
organization_name: 'Nombre de la Organización'
|
||||
product_guide_link: 'Guía de Talk'
|
||||
report_bug_or_feedback: 'Registrar un error de Talk'
|
||||
require_email_verification: 'Necesita confirmación su correo'
|
||||
require_email_verification_text: 'Nuevos usuarios deben confirmar sus correos antes de comentar'
|
||||
save: Guardar
|
||||
@@ -157,6 +159,7 @@ es:
|
||||
suspect_word_title: 'Lista de palabras sospechosas'
|
||||
tech_settings: 'Configuración Técnica'
|
||||
title: 'Configurar los comentarios'
|
||||
view_last_version: 'Ver la versión de Talk'
|
||||
weeks: Semanas
|
||||
wordlist: 'Palabras Suspendidas'
|
||||
confirm_email:
|
||||
@@ -280,7 +283,7 @@ es:
|
||||
comment_is_ignored: 'Este comentario está escondido porque has ignorado al usuario.'
|
||||
comment_is_rejected: 'Has rechazado este comentario.'
|
||||
comments: comentarios
|
||||
configure_stream: 'Configurar Hilo de Comentarios'
|
||||
configure_stream: 'Configurar'
|
||||
content_not_available: 'Este contenido no se encuentra disponible'
|
||||
edit_name:
|
||||
button: Enviar
|
||||
@@ -324,6 +327,17 @@ es:
|
||||
submit: 'Terminar la Instalación'
|
||||
title: 'Dominios permitidos'
|
||||
like: 'Me gusta'
|
||||
login:
|
||||
email_address: 'Dirección de correo'
|
||||
forgot_password: '¿Olvidaste tu contraseña?'
|
||||
go_back: 'Regresar'
|
||||
sign_in: 'Entrar'
|
||||
sign_in_button: 'Entrar'
|
||||
sign_in_message: 'Regístrese para interactuar con su comunidad.'
|
||||
password: Contraseña
|
||||
reset_password_send_button: 'Recuperar Contraseña'
|
||||
request_password: 'Solicita uno nuevo.'
|
||||
team_sign_in: 'Entrada del equipo'
|
||||
loading_results: 'Cargando Resultados'
|
||||
marketing: 'Esto parece una propaganda'
|
||||
moderate_this_stream: 'Moderar este hilo de comentarios'
|
||||
@@ -421,7 +435,7 @@ es:
|
||||
step_2_header: 'Ayúdanos a comprender'
|
||||
step_3_header: 'Gracias por tu participación'
|
||||
stream:
|
||||
all_comments: 'Todos los comentarios'
|
||||
all_comments: 'Todos'
|
||||
comment_not_found: 'Este comentario ha sido eliminado o no existe.'
|
||||
no_comments: 'Todavía no hay comentarios. ¿Por qué no escribes uno?'
|
||||
no_comments_and_closed: 'No hubo comentarios en este artículo.'
|
||||
|
||||
+75
-7
@@ -38,6 +38,9 @@ pt_BR:
|
||||
name: Nome
|
||||
post: Enviar
|
||||
reply: Responder
|
||||
comment_history_blank:
|
||||
info: 'Uma história de seus comentários irá aparecer aqui'
|
||||
title: 'Você não escreveu nenhum comentário'
|
||||
comment_offensive: 'Este comentário é ofensivo'
|
||||
comment_plural: Comentários
|
||||
comment_post_banned_word: 'Seu comentário não foi publicado porque contém conteúdo inadequado.'
|
||||
@@ -83,6 +86,7 @@ pt_BR:
|
||||
username_and_email: 'Nome de usuário e email'
|
||||
yes_ban_user: 'Sim, banir este usuário'
|
||||
configure:
|
||||
access_message: 'Você deve ser um administrador para acessar as configurações. Por favor procure o administrador mais próximo e solicite acesso.’'
|
||||
apply: Aplicar
|
||||
banned_word_text: 'Os comentários que contenham essas palavras ou frases (não sensíveis a maiúsculas e minúsculas) serão automaticamente removidos da lista de comentários. Digite uma palavra e pressione Enter ou Tab para adicionar ou cole uma lista separada por vírgulas.'
|
||||
banned_words_title: 'Lista de palavras proibidas'
|
||||
@@ -140,11 +144,19 @@ pt_BR:
|
||||
organization_info_copy_2: 'Recomendamos a criação de uma conta de e-mail genérica (por exemplo, comunidade@suaredacao.com) para essa finalidade. Isso significa que ele pode permanecer consistente ao longo do tempo e não expor um nome que os usuários pudessem segmentar se a conta fosse bloqueada.'
|
||||
organization_information: 'Informações da Organização'
|
||||
organization_name: 'Nome da Organização'
|
||||
suspect_or_forbidden_words_placeholder: 'Palavra ou frase'
|
||||
product_guide_link: 'Guia do Produto'
|
||||
report_bug_or_feedback: 'Relatar bug ou dar um feedback'
|
||||
require_email_verification: 'Requerer verificação de email'
|
||||
require_email_verification: 'Solicitar verificação de email'
|
||||
require_email_verification_text: 'Novos usuários devem verificar seu e-mail antes de comentar'
|
||||
save: Salvar
|
||||
save_changes: 'Salvar alterações'
|
||||
save_changes_dialog:
|
||||
cancel: Cancelar
|
||||
copy: 'Você fez uma ou mais alterações sem salvar. Gostaria de salvar ou descartar suas alterações?'
|
||||
discard: Discartar
|
||||
save_settings: 'Configurações salvas'
|
||||
unsaved_changes: 'Alterações não salvas'
|
||||
shortcuts: Atalhos
|
||||
sign_out: Sair
|
||||
stories: Histórias
|
||||
@@ -159,6 +171,7 @@ pt_BR:
|
||||
confirm_email:
|
||||
click_to_confirm: 'Clique abaixo para confirmar seu endereço de email'
|
||||
confirm: Confirmar
|
||||
email_confirmation: 'Confirmação de E-mail'
|
||||
continue: Continuar
|
||||
createdisplay:
|
||||
check_the_form: 'Formulário inválido. Verifique as entradas do formulário.'
|
||||
@@ -194,45 +207,60 @@ pt_BR:
|
||||
if_you_did_not: 'Se você não solicitou isso, você pode ignorar este e-mail.'
|
||||
subject: 'Confirmação de e-mail'
|
||||
to_confirm: 'Para confirmar a conta, visite este link: '
|
||||
password_change:
|
||||
body: "A sua senha foi alterada.\n\nSe você não solicitou essa alteracão, por favor nos contate em {0}"
|
||||
subject: '{0} password change'
|
||||
password_reset:
|
||||
if_you_did: 'Se você solicitou isso, '
|
||||
please_click: 'clique aqui para redefinir sua senha.'
|
||||
subject: 'Alteracao de Senha'
|
||||
we_received_a_request: 'Recebemos um pedido para redefinir sua senha. Se você não solicitou esta alteração, pode ignorar este e-mail.'
|
||||
suspended:
|
||||
subject: 'Sua conta foi suspensa'
|
||||
embed_comments_tab: Comentários
|
||||
embedlink:
|
||||
copy: 'Copiar para área de transferência'
|
||||
copy: 'Copiar conteúdo'
|
||||
copied: 'Copiado'
|
||||
error:
|
||||
ALREADY_EXISTS: 'O recurso já existe'
|
||||
AUTHENTICATION: ‘Ocorreu um erro durante a autenticação da sua conta’
|
||||
CANNOT_IGNORE_STAFF: 'Não é possível ignorar membros Staff.'
|
||||
COMMENT_PARENT_NOT_VISIBLE: 'O comentário que você está respondendo foi removido ou não existe.'
|
||||
COMMENT_TOO_SHORT: 'Seu comentário precisar ter mais de um caracter. Revise seu comentário e envie novamente'
|
||||
COMMENTING_CLOSED: 'Os comentários já estão fechados.'
|
||||
COMMENTING_DISABLED: 'Commenting is currently disabled on this site'
|
||||
confirm_password: 'Suas senhas não coincidem. Por favor, tente novamente.'
|
||||
DELETION_NOT_SCHEDULED: 'Deletion was not scheduled'
|
||||
EDIT_USERNAME_NOT_AUTHORIZED: 'Você não tem permissão para revisar seu nome de usuário.'
|
||||
EDIT_WINDOW_ENDED: 'Você não pode mais editar esse comentário. O tempo expirou.'
|
||||
email: 'Não é um e-mail válido'
|
||||
EMAIL_ALREADY_VERIFIED: 'Endereço de e-mail já verificado '
|
||||
EMAIL_IN_USE: 'Endereço de e-mail já está em uso.'
|
||||
email_not_verified: 'O endereço de e-mail {0} não é verificado.'
|
||||
EMAIL_NOT_VERIFIED: 'E-mail não verificado'
|
||||
email_password: 'Combinação de e-mail e/ou senha incorreta.'
|
||||
EMAIL_REQUIRED: 'É necessário o endereço de e-mail.'
|
||||
EMAIL_VERIFICATION_TOKEN_INVALID: 'O token de verificação do email é inválido.'
|
||||
INCORRECT_PASSWORD: 'Incorrect Password'
|
||||
INVALID_ASSET_URL: 'O URL do recurso é inválido'
|
||||
LOGIN_MAXIMUM_EXCEEDED: 'Você fez muitas tentativas de senha mal sucedidas. Espere alguns instantes.'
|
||||
network_error: 'Falha ao conectar-se ao servidor. Verifique a sua conexão com a internet e tente novamente.'
|
||||
NO_SPECIAL_CHARACTERS: 'Nomes de usuários podem conter números de letras e _ somente'
|
||||
NOT_AUTHORIZED: 'Você não está autorizado a executar esta ação.'
|
||||
NOT_FOUND: 'Recurso não encontrado'
|
||||
organization_contact_email: 'O Email da organização não é válido.'
|
||||
organization_name: 'O nome da organização só deve conter letras ou números.'
|
||||
password: 'A senha deve conter pelo menos 8 caracteres'
|
||||
PAGE_NOT_AVAILABLE_ROLE: 'Essa página só pode ser acessada para uso do time. Por favor entre em contato com um administrador caso queira fazer parte desse time.'
|
||||
PASSWORD_INCORRECT: 'A senha inserida está incorreta'
|
||||
PASSWORD_LENGTH: 'A senha é muito curta'
|
||||
PASSWORD_REQUIRED: 'Você deve inserir uma senha.'
|
||||
PASSWORD_RESET_TOKEN_INVALID: 'Seu link de redefinição de senha é inválido.'
|
||||
PROFANITY_ERROR: 'Os nomes de usuários não devem conter palavrões. Entre em contato com o administrador se você acredita que isso seja incorreto.'
|
||||
RATE_LIMIT_EXCEEDED: 'Tentativas excedidas'
|
||||
required_field: 'Esse campo é obrigatório'
|
||||
SAME_USERNAME_PROVIDED: 'Você deve enviar um nome de usuário diferente.'
|
||||
temporarily_suspended: 'Sua conta está suspensa. Ela será reativada {0}. Por favor entre em contato caso tenha dúvidas.'
|
||||
unexpected: 'Ocorreu um erro inesperado. Desculpa!'
|
||||
username: 'Nomes de usuários podem conter números de letras e _ somente'
|
||||
USERNAME_IN_USE: 'Nome de usuário já em uso'
|
||||
@@ -246,6 +274,7 @@ pt_BR:
|
||||
changed_name:
|
||||
msg: 'Sua alteração de nome de usuário está sendo analisada por nossa equipe de moderação.'
|
||||
comment: comentário
|
||||
comment_is_deleted: 'This commenter has deleted their account.'
|
||||
comment_is_hidden: 'Este comentário não está disponível.'
|
||||
comment_is_ignored: 'Este comentário está oculto porque você ignorou esse usuário.'
|
||||
comment_is_rejected: 'Você rejeitou este comentário.'
|
||||
@@ -303,6 +332,7 @@ pt_BR:
|
||||
sign_in_button: 'Entrar'
|
||||
sign_in_message: 'Entre para interagir com a comunidade.'
|
||||
password: Senha
|
||||
reset_password_send_button: 'Recuperar Senha'
|
||||
request_passowrd: 'Recupere-a clicando aqui.'
|
||||
team_sign_in: 'Team sign in'
|
||||
marketing: 'Isso parece um anúncio/marketing'
|
||||
@@ -316,6 +346,7 @@ pt_BR:
|
||||
approve: Aprovar
|
||||
approved: Aprovado
|
||||
ban_user: Banir
|
||||
ban_user_actions: 'Banir Usuário'
|
||||
billion: B
|
||||
close: Fechar
|
||||
empty_queue: 'Não há mais comentários para moderar! Aproveite para relaxar e esticar as pernas'
|
||||
@@ -336,6 +367,7 @@ pt_BR:
|
||||
notify_edited: '{0} editou o comentário "{1}"'
|
||||
notify_flagged: '{0} marcou o comentário "{1}"'
|
||||
notify_rejected: '{0} rejeitou o comentário "{1}"'
|
||||
notify_reset: '{0} resetar status do comentário "{1}"'
|
||||
oldest_first: 'Mais velhos primeiro'
|
||||
premod: pré-moderação
|
||||
prev_comment: 'Vá para o comentário anterior'
|
||||
@@ -349,6 +381,8 @@ pt_BR:
|
||||
show_shortcuts: 'Ver atalhos'
|
||||
singleview: 'Modo zen'
|
||||
sort: Ordenar
|
||||
suspend: 'Suspender Usuário'
|
||||
system_withheld: 'Sistema de Rejeição'
|
||||
thismenu: 'Abra este menu'
|
||||
thousand: k
|
||||
toggle_search: 'Abrir busca'
|
||||
@@ -362,7 +396,9 @@ pt_BR:
|
||||
other: Outro
|
||||
password_reset:
|
||||
change_password: 'Alterar senha'
|
||||
change_password_help: 'Please enter a new password to use to login. Make it secure!'
|
||||
confirm_new_password: 'Confirmar nova senha'
|
||||
mail_sent: 'Se você tem uma conta registrada, um link para alterar sua senha foi enviado para o e-mail informado'
|
||||
new_password: 'Nova senha'
|
||||
new_password_help: 'A senha deve ter mais de 8 caracteres'
|
||||
set_new_password: 'Alterar sua senha'
|
||||
@@ -383,6 +419,13 @@ pt_BR:
|
||||
username: 'nome de usuário'
|
||||
write_message: 'Escreve uma mensagem'
|
||||
yes_suspend: 'Sim suspender'
|
||||
reject_username_dialog:
|
||||
cancel: Cancel
|
||||
description: 'Nos ajude a entender'
|
||||
message: 'Motivo para reportar (Opcional)'
|
||||
reason: Motivo
|
||||
reject_username: 'Rejeitar nome de Usuário'
|
||||
title: 'Rejeitar nome de Usuário'
|
||||
reply: Responder
|
||||
report: Denunciar
|
||||
report_notif: 'Obrigado por denunciar este comentário. Nossa equipe de moderação foi notificada e irá revisá-la em breve.'
|
||||
@@ -398,7 +441,7 @@ pt_BR:
|
||||
user_no_comment: 'Você nunca deixou um comentário. Participe da conversa!'
|
||||
step_1_header: 'Relatar um problema'
|
||||
step_2_header: 'Ajude-nos a entender'
|
||||
step_3_header: 'Obrigdo por sua contribuição'
|
||||
step_3_header: 'Obrigado por sua contribuição'
|
||||
stream:
|
||||
all_comments: 'Todos os comentários'
|
||||
comment_not_found: 'Este comentário foi removido ou não existe.'
|
||||
@@ -406,16 +449,16 @@ pt_BR:
|
||||
no_comments_and_closed: 'Não houve comentários sobre este artigo.'
|
||||
temporarily_suspended: 'De acordo com as diretrizes da comunidade de {0}, sua conta foi temporariamente suspensa. Por favor, volte para a conversa {1}.'
|
||||
streams:
|
||||
all: Todos
|
||||
all: Todas
|
||||
article: História
|
||||
closed: Fechado
|
||||
closed: Fechada
|
||||
empty_result: 'Nenhum resultado encontrado para esta pesquisa. Que tal refazer a pesquisa com termos diferentes?'
|
||||
filter_streams: 'Filtra as listas'
|
||||
most_recent_stories: 'Matérias mais recentes'
|
||||
newest: 'O mais novo'
|
||||
no_results: 'No results'
|
||||
no_results: 'Nenhum resultado'
|
||||
oldest: 'O mais velho'
|
||||
open: Aberto
|
||||
open: Aberta
|
||||
pubdate: 'Data de publicação'
|
||||
search: Pesquisar
|
||||
search_results: 'Pesquisar Resultados'
|
||||
@@ -442,11 +485,36 @@ pt_BR:
|
||||
bio_flags: 'Marcadas para este perfil'
|
||||
user_bio: 'Perfil do usuário'
|
||||
username_flags: 'Marcadas para este usuário'
|
||||
user_detail:
|
||||
all: Todo
|
||||
ban: 'Banir usuário'
|
||||
banned: Banido
|
||||
email: Email
|
||||
id: ID
|
||||
karma: Karma
|
||||
karma_docs_link: 'https://docs.coralproject.net/talk/trust/#user-karma-score'
|
||||
learn_more: 'Saiba Mais'
|
||||
member_since: 'Membro desde'
|
||||
reject_rate: 'Taxa de rejeição'
|
||||
reject_username: 'Rejeitar Usuário'
|
||||
rejected: Rejeitado
|
||||
remove_ban: 'Remover Bloqueio'
|
||||
remove_suspension: 'Remover Suspensão'
|
||||
suspend: 'Suspender Ususário'
|
||||
suspended: Suspenso
|
||||
total_comments: 'Total de comentários'
|
||||
unreliable: Não confiável
|
||||
user_history: 'Histórico do usuário'
|
||||
user_karma_score: 'Nota Usuário do Karma'
|
||||
username: Usuário
|
||||
username_needs_approval: 'Usuário precisa de aprovação'
|
||||
username_rejected: 'Usuário rejeitado'
|
||||
user_impersonating: 'Este usuário está representando'
|
||||
user_no_comment: 'Você nunca deixou um comentário. Participe da conversa!'
|
||||
username_offensive: 'Esse nome de usuário é ofensivo'
|
||||
validators:
|
||||
confirm_password: 'Suas senhas não coincidem. Por favor, tente novamente.'
|
||||
required: 'Esse campo é obrigatório'
|
||||
verify_email: 'Não é um e-mail válido'
|
||||
verify_organization_name: 'O nome da organização só deve conter letras ou números.'
|
||||
verify_password: 'A senha deve conter pelo menos 8 caracteres'
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const { logger } = require('../services/logging');
|
||||
const { ErrHTTPNotFound } = require('../errors');
|
||||
const now = require('performance-now');
|
||||
|
||||
const log = (req, res, next) => {
|
||||
@@ -33,7 +34,12 @@ const log = (req, res, next) => {
|
||||
};
|
||||
|
||||
const error = (err, req, res, next) => {
|
||||
logger.error({ err }, 'http error');
|
||||
// Don't log out an error for ErrHTTPNotFound as this is already
|
||||
// logged with the included request logger.
|
||||
if (!(err instanceof ErrHTTPNotFound)) {
|
||||
logger.error({ err }, 'http error');
|
||||
}
|
||||
|
||||
next(err);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ const { merge } = require('lodash');
|
||||
|
||||
const {
|
||||
BASE_URL,
|
||||
BASE_ORIGIN,
|
||||
BASE_PATH,
|
||||
MOUNT_PATH,
|
||||
STATIC_URL,
|
||||
@@ -29,6 +30,7 @@ const TALK_CLIENT_ENV = Object.keys(process.env)
|
||||
LIVE_URI: WEBSOCKET_LIVE_URI,
|
||||
STATIC_URL,
|
||||
STATIC_ORIGIN,
|
||||
BASE_ORIGIN,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
+6
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "talk",
|
||||
"version": "4.6.1",
|
||||
"version": "4.6.4",
|
||||
"description": "A better commenting experience from Mozilla, The New York Times, and the Washington Post. https://coralproject.net",
|
||||
"main": "app.js",
|
||||
"private": true,
|
||||
@@ -14,7 +14,7 @@
|
||||
"start": "NODE_ENV=production ./bin/cli-serve -j -w",
|
||||
"prebuild": "npm-run-all clean generate-introspection",
|
||||
"build": "NODE_ENV=production parallel-webpack --bail",
|
||||
"lint:yaml": "yamllint locales/*.yml",
|
||||
"lint:yaml": "yamllint locales/*.y{a,}ml plugins/**/*.y{a,}ml",
|
||||
"lint:js": "eslint bin/cli* .",
|
||||
"lint": "npm-run-all lint:*",
|
||||
"plugins:reconcile": "./bin/cli plugins reconcile",
|
||||
@@ -126,7 +126,6 @@
|
||||
"history": "^3.0.0",
|
||||
"hjson": "^3.1.1",
|
||||
"hjson-loader": "^1.0.0",
|
||||
"https-proxy-agent": "^2.2.0",
|
||||
"immutability-helper": "^2.2.0",
|
||||
"imports-loader": "^0.7.1",
|
||||
"inquirer": "^3.2.2",
|
||||
@@ -171,8 +170,9 @@
|
||||
"postcss-smart-import": "^0.5.1",
|
||||
"precss": "1.4.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"proxy-agent": "^3.0.1",
|
||||
"pym.js": "^1.3.2",
|
||||
"query-string": "^5.0.0",
|
||||
"querystringify": "^2.0.0",
|
||||
"react": "^15.4.2",
|
||||
"react-apollo": "^1.4.12",
|
||||
"react-broadcast": "^0.6.2",
|
||||
@@ -201,7 +201,7 @@
|
||||
"smoothscroll-polyfill": "^0.3.5",
|
||||
"snake-case": "2.1.0",
|
||||
"style-loader": "^0.16.0",
|
||||
"subscriptions-transport-ws": "^0.7.2",
|
||||
"subscriptions-transport-ws": "^0.8.3",
|
||||
"supports-color": "^4",
|
||||
"timeago.js": "^2.0.3",
|
||||
"timekeeper": "^1.0.0",
|
||||
@@ -209,6 +209,7 @@
|
||||
"uglifyjs-webpack-plugin": "^1.1.6",
|
||||
"url-join": "^2.0.2",
|
||||
"url-loader": "^0.6.0",
|
||||
"url-parse": "^1.4.3",
|
||||
"url-search-params": "^0.9.0",
|
||||
"uuid": "^3.1.0",
|
||||
"webpack": "^3.10.0",
|
||||
|
||||
@@ -10,4 +10,5 @@ export {
|
||||
getShallowChanges,
|
||||
createDefaultResponseFragments,
|
||||
handlePopupAuth,
|
||||
buildCommentURL,
|
||||
} from 'coral-framework/utils';
|
||||
|
||||
@@ -343,48 +343,48 @@ nl_NL:
|
||||
pt_BR:
|
||||
talk-plugin-auth:
|
||||
login:
|
||||
email_verify_cta: "Please verify your email address."
|
||||
request_new_verify_email: "Request another email"
|
||||
verify_email: "Thank you for creating an account! We sent an email to the address you provided to verify your account."
|
||||
verify_email2: "You must verify your account before engaging with the community."
|
||||
not_you: "Not you?"
|
||||
logged_in_as: "Signed in as"
|
||||
facebook_sign_in: "Sign in with Facebook"
|
||||
facebook_sign_up: "Sign up with Facebook"
|
||||
logout: "Sign out"
|
||||
sign_in: "Sign in"
|
||||
sign_in_to_join: "Sign in to join the conversation"
|
||||
or: "Or"
|
||||
email: "Email Address"
|
||||
password: "Password"
|
||||
forgot_your_pass: "Forgot your password?"
|
||||
need_an_account: "Need an account?"
|
||||
register: "Register"
|
||||
sign_up: "Sign Up"
|
||||
confirm_password: "Confirm Password"
|
||||
username: "Username"
|
||||
already_have_an_account: "Already have an account?"
|
||||
recover_password: "Recover password"
|
||||
email_in_use: "Email address already in use"
|
||||
email_or_username_in_use: "Email address or Username already in use"
|
||||
required_field: "This field is required"
|
||||
passwords_dont_match: "Passwords don't match."
|
||||
special_characters: "Usernames can contain letters, numbers and _ only"
|
||||
sign_in_to_comment: "Sign in to comment"
|
||||
check_the_form: "Invalid Form. Please, check the fields"
|
||||
already_have_an_account: "Já possui uma conta?"
|
||||
check_the_form: "Formulário inválido. Por favor confira os campos"
|
||||
confirm_password: "Confirmar senha"
|
||||
email: "Endereço de email"
|
||||
email_in_use: "Endereço de email já está em uso"
|
||||
email_or_username_in_use: "Endereço de email ou nome de usuário já em uso"
|
||||
email_verify_cta: "Por favor verifique seu endereço de email."
|
||||
facebook_sign_in: "Entrar com o Facebook"
|
||||
facebook_sign_up: "Cadastrar com o Facebook"
|
||||
forgot_your_pass: "Esqueceu sua senha?"
|
||||
request_new_verify_email: "Solicite outro email"
|
||||
verify_email: "Obrigado por criar uma conta! Enviamos um email para o endereço de email informado para verificar sua conta."
|
||||
verify_email2: "Você deve verificar sua conta antes de participar da comunidade."
|
||||
logged_in_as: "Logado como"
|
||||
logout: "Sair"
|
||||
need_an_account: "Precisa de uma conta?"
|
||||
not_you: "Não é você?"
|
||||
or: "Ou"
|
||||
password: "Senha"
|
||||
passwords_dont_match: "As senhas não conferem."
|
||||
recover_password: "Recuperar senha"
|
||||
register: "Registrar"
|
||||
required_field: "Esse campo é obrigatório"
|
||||
sign_in: "Entrar"
|
||||
sign_in_to_comment: "Entre para comentar"
|
||||
sign_in_to_join: "Entre para participar da conversa"
|
||||
sign_up: "Inscreva-se"
|
||||
special_characters: "Nome de usuário contem somente letras, números and _"
|
||||
username: "Nome de usuário"
|
||||
set_username_dialog:
|
||||
check_the_form: "Invalid Form. Please check the fields"
|
||||
continue: "Continue with the same Facebook username"
|
||||
error_create: "Error when changing username"
|
||||
fake_comment_body: "This is an example comment. Readers can share their thoughts and opinions with newsrooms in the comments section."
|
||||
fake_comment_date: "1 minute ago"
|
||||
if_you_dont_change_your_name: "If you don't change your username at this step your Facebook display name will appear alongside of all your comments."
|
||||
required_field: "Required field"
|
||||
save: Save
|
||||
special_characters: "Usernames can contain letters numbers and _ only"
|
||||
username: Username
|
||||
write_your_username: "Edit your username"
|
||||
your_username: "Your username appears on every comment you post."
|
||||
check_the_form: "Formulário inválido. Por favor confira os campos"
|
||||
continue: "Continue com o mesmo nome de usuário do Facebook"
|
||||
error_create: "Erro ao trocar o nome de usuário"
|
||||
fake_comment_body: "Esse é um comentário de exemplo. Leitores podem compartilhar pensamentos e opiniões na seção de comentários."
|
||||
fake_comment_date: "1 minuto atrás"
|
||||
if_you_dont_change_your_name: "Se você não mudar seu nome de usuário neste ponto do processo, o nome que está no seu Facebook irá aparecer junto de todos os seus comentários"
|
||||
required_field: "Campo obrigatório"
|
||||
save: Salvar
|
||||
special_characters: "Nome de usuários podem conter somente letras números e _"
|
||||
username: Nome de usuário
|
||||
write_your_username: "Edite seu nome de usuário"
|
||||
your_username: "Seu nome de usuário aparece em cada comentário feito."
|
||||
zh_CN:
|
||||
talk-plugin-auth:
|
||||
login:
|
||||
|
||||
@@ -5,7 +5,13 @@ import { t } from 'plugin-api/beta/client/services';
|
||||
import { Icon } from 'plugin-api/beta/client/components/ui';
|
||||
|
||||
export default ({ className = '' }) => (
|
||||
<div className={cn(styles.tooltip, className)}>
|
||||
<div
|
||||
className={cn(
|
||||
styles.tooltip,
|
||||
className,
|
||||
'talk-plugin-featured-comments-tooltip'
|
||||
)}
|
||||
>
|
||||
<Icon name="info_outline" className={styles.icon} />
|
||||
<h3 className={styles.headline}>
|
||||
{t('talk-plugin-featured-comments.featured_comments')}:
|
||||
|
||||
@@ -62,7 +62,7 @@ es:
|
||||
talk-plugin-featured-comments:
|
||||
un_feature: Desmarcar
|
||||
feature: Remarcar
|
||||
featured: Remarcado
|
||||
featured: Remarcados
|
||||
featured_comments: Comentarios Remarcados
|
||||
go_to_conversation: Ir al comentario
|
||||
tooltip_description: Comentarios seleccionados por nuestro equipo que valen la pena ser leidos
|
||||
@@ -102,19 +102,19 @@ nl_NL:
|
||||
yes_feature_comment: Ja, reactie uitlichten.
|
||||
pt_BR:
|
||||
talk-plugin-featured-comments:
|
||||
un_feature: Un-Feature
|
||||
feature: Feature
|
||||
featured: Featured
|
||||
featured_comments: Featured Comments
|
||||
go_to_conversation: Go to conversation
|
||||
tooltip_description: Comments selected by our team as worth reading
|
||||
notify_self_featured: 'The comment from {0} is now featured and approved'
|
||||
notify_featured: '{0} featured and approved comment "{1}"'
|
||||
notify_unfeatured: '{0} unfeatured comment "{1}"'
|
||||
feature_comment: Feature comment?
|
||||
are_you_sure: Are you sure you would like to feature this comment?
|
||||
cancel: Cancel
|
||||
yes_feature_comment: Yes, feature comment
|
||||
un_feature: Desfazer
|
||||
feature: Destacar
|
||||
featured: Destacado
|
||||
featured_comments: Comentários destacados
|
||||
go_to_conversation: Ir para conversa
|
||||
tooltip_description: Vale a pena ler os comentários selecionados pelo nosso time
|
||||
notify_self_featured: 'O comentário do {0} está em destaque e aprovado'
|
||||
notify_featured: '{0} destacou e aprovou o comentário "{1}"'
|
||||
notify_unfeatured: '{0} Desmarcar comentário "{1}"'
|
||||
feature_comment: Destacar comentário?
|
||||
are_you_sure: Você tem certeza que deseja destacar esse comentário?
|
||||
cancel: Cancelar
|
||||
yes_feature_comment: Sim, destacar comentário
|
||||
zh_CN:
|
||||
talk-plugin-featured-comments:
|
||||
un_feature: "取消精选"
|
||||
|
||||
@@ -8,17 +8,17 @@ en:
|
||||
sign_up: "Sign up with Google"
|
||||
es:
|
||||
talk-plugin-google-auth:
|
||||
google_sign_in: "Entrar con Google"
|
||||
google_sign_up: "Registrarse con Google"
|
||||
sign_in: "Entrar con Google"
|
||||
sign_up: "Registrarse con Google"
|
||||
fr:
|
||||
talk-plugin-google-auth:
|
||||
google_sign_in: "Connectez-vous avec Google"
|
||||
google_sign_up: "Inscrivez-vous avec Google"
|
||||
sign_in: "Connectez-vous avec Google"
|
||||
sign_up: "Inscrivez-vous avec Google"
|
||||
zh_CN:
|
||||
talk-plugin-google-auth:
|
||||
google_sign_in: "使用 Google 帐号"
|
||||
google_sign_up: "使用 Google 帐号"
|
||||
sign_in: "使用 Google 帐号"
|
||||
sign_up: "使用 Google 帐号"
|
||||
zh_TW:
|
||||
talk-plugin-google-auth:
|
||||
google_sign_in: "使用 Google 帳號"
|
||||
google_sign_up: "使用 Google 帳號"
|
||||
sign_in: "使用 Google 帳號"
|
||||
sign_up: "使用 Google 帳號"
|
||||
|
||||
@@ -52,16 +52,17 @@ de:
|
||||
es:
|
||||
talk-plugin-ignore-user:
|
||||
section_title: "Usuarios ignorados"
|
||||
section_info: Because you ignored the following commenters, their comments are hidden.
|
||||
blank_info: Actualmente no ignoras a ningún usuario
|
||||
section_info: Debido a que ignoró a los siguientes comentaristas, sus comentarios están ocultos.
|
||||
stop_ignoring: "No ignorar más"
|
||||
ignore_user: Ignore User
|
||||
cancel: Cancel
|
||||
ignore_user: Ignorar usuario
|
||||
cancel: Cancelar
|
||||
confirmation: |
|
||||
When you ignore a user, all comments they wrote on the site will be hidden from you. You can
|
||||
undo this later from My Profile.
|
||||
Cuando ignora a un usuario, todos los comentarios que escribió en el sitio estarán ocultos.
|
||||
Puede deshacer esto más tarde desde Mi Perfil.
|
||||
notify_success: |
|
||||
You are now ignoring {0}. You can undo this action from My Profile.
|
||||
confirmation_title: Ignore {0}?
|
||||
Ahora estás ignorando a {0}. Puede deshacer esta acción desde Mi Perfil.
|
||||
confirmation_title: Ignorar a {0}?
|
||||
fr:
|
||||
talk-plugin-ignore-user:
|
||||
section_title: "Utilisateurs ignorés"
|
||||
@@ -90,17 +91,18 @@ nl_NL:
|
||||
confirmation_title: Negeer {0}?
|
||||
pt_BR:
|
||||
talk-plugin-ignore-user:
|
||||
blank_info: Atualmente você não está ignorando nenhum usuário
|
||||
section_title: "Usuários ignorados"
|
||||
section_info: "Porque você ignorou os seguintes comentadores, seus comentários estão ocultos."
|
||||
stop_ignoring: "Pare de ignorar"
|
||||
ignore_user: Ignore User
|
||||
cancel: Cancel
|
||||
confirmation: |
|
||||
When you ignore a user, all comments they wrote on the site will be hidden from you. You can
|
||||
undo this later from My Profile.
|
||||
stop_ignoring: "Parar de ignorar"
|
||||
ignore_user: Ignorar usuário
|
||||
cancel: Cancelar
|
||||
confirmation:
|
||||
Quando você ignora um usuário, todos os comentários que ele ele(a) escreveu não serão exibidos para você. Você pode
|
||||
desfazer isso depois no Meu Perfil
|
||||
notify_success: |
|
||||
You are now ignoring {0}. You can undo this action from My Profile.
|
||||
confirmation_title: Ignore {0}?
|
||||
Agora você está ignorando {0}. Você pode desfazer essa ação em Meu Perfil.
|
||||
confirmation_title: Ignorar {0}?
|
||||
zh_CN:
|
||||
talk-plugin-ignore-user:
|
||||
section_title: "被忽略用户"
|
||||
|
||||
@@ -150,6 +150,82 @@ en:
|
||||
description_2: "You can change your account settings by visiting"
|
||||
path: "My Profile > Settings"
|
||||
alert: "Email Added!"
|
||||
pt_BR:
|
||||
email:
|
||||
email_change_original:
|
||||
subject: Mudança de email
|
||||
body: Seu endereço de email foi alterado de {0} para {1}. Se você não solicitou essa alteração, por favor contate {2}.
|
||||
error:
|
||||
NO_LOCAL_PROFILE: Nenhum email existente está vinculado a essa conta.
|
||||
LOCAL_PROFILE: Já existe um endereço de email associado a essa conta.
|
||||
INCORRECT_PASSWORD: A senha informada está incorreta.
|
||||
talk-plugin-local-auth:
|
||||
change_password:
|
||||
change_password: "Mudar senha"
|
||||
passwords_dont_match: "Senhas não conferem"
|
||||
required_field: "Esse campo é obrigatório"
|
||||
forgot_password: "Esqueceu sua senha?"
|
||||
old_password: "Senha antiga"
|
||||
new_password: "Nova senha"
|
||||
confirm_new_password: "Confirme a nova senha"
|
||||
save: "Salvar"
|
||||
cancel: "Cancelar"
|
||||
edit: "Editar"
|
||||
changed_password_msg: "Senha alterada - Sua senha foi alterada com sucesso"
|
||||
forgot_password_sent: "Esqueceu a senha - Nós enviamos um email para recuperação da senha"
|
||||
change_username:
|
||||
change_username_note: "Nomes de usuários só podem ser alterados uma vez a cada 14 dias"
|
||||
is_not_eligible: "Seu nome de usuário não pode ser alterado."
|
||||
save: "Salvar"
|
||||
edit_profile: "Editar perfil"
|
||||
cancel: "Cancelar"
|
||||
confirm_username_change: "Confirmar alteração do nome de usuário"
|
||||
description: "Você está tentando alterar seu nome de usuário. Seu novo nome de usuário irá aparecer em todos os comentários antigos e novos."
|
||||
old_username: "Nome de usuário antigo"
|
||||
new_username: "Nome de usuário novo"
|
||||
re_enter: "Repita o novo usuário"
|
||||
bottom_note: "Atenção: Não será possível alterar seu nome de usuário por 14 dias"
|
||||
confirm_changes: "Confirmar mudanças"
|
||||
username_does_not_match: "Nome de usuário não confere"
|
||||
cant_be_equal: "Seu novo {0} deve ser diferente do atual"
|
||||
changed_username_success_msg: "Nome de usuário alterado - Nome de usuário alterado com sucesso. Não será possível alterar por 14 dias."
|
||||
change_username_attempt: "Usuário não pode ser alterado. Nome de usuário só pode ser alterado a cada 14 dias."
|
||||
change_email:
|
||||
confirm_email_change: "Confirmar alteração de email"
|
||||
description: "Você está tentando alterar seu endereço de email. Seu novo email será usado para entrar na plataforma e receber avisos da sua conta."
|
||||
old_email: "Endereço de email antigo"
|
||||
new_email: "Endereço de email novo"
|
||||
enter_password: "Digite a senha"
|
||||
incorrect_password: "Senha incorreta"
|
||||
confirm_change: "Confirmar alteração"
|
||||
cancel: "Cancelar"
|
||||
change_email_msg: "Endereço de email alterado. este endereço de email será usado para entrar e receber notificações de email."
|
||||
add_email:
|
||||
add_email_address: "Adicionar endereço de email"
|
||||
enter_email_address: "Entre com o endereço de email:"
|
||||
invalid_email_address: "Email inválido"
|
||||
confirm_email_address: "Confirmar endereço de email:"
|
||||
email_does_not_match: "Endereço de email não confere"
|
||||
insert_password: "Insira a senha:"
|
||||
confirm_password: "Confirmar senha:"
|
||||
required_field: "Esse campo é obrigatório"
|
||||
done: "Feito"
|
||||
content:
|
||||
title: "Adicione um endereço de email"
|
||||
description: "Para a sua segurança, exigimos que os usuários adicionem um endereço de email para suas contas. Seu email será usado para:"
|
||||
item_1: "Receba avisos de alterações na sua conta(endereço de email, usuário, senha, etc.)"
|
||||
item_2: "Permitir que você baixe seus comentários."
|
||||
item_3: "Envie notificações de comentários que você escolheu receber."
|
||||
verify:
|
||||
title: "Verifique seu endereço de email"
|
||||
description: "Enviamos um email para {0} para verificar sua conta. Ele pode ser usado para confirmar alterações na conta e notificações."
|
||||
added:
|
||||
title: "Endereço de email adicionado"
|
||||
description: "Seu endereço de email foi adicionado na sua conta."
|
||||
subtitle: "Precisa alterar seu endereço de email?"
|
||||
description_2: "Você pode alterar as configurações da sua conta em"
|
||||
path: "Meu Perfil > Configurações"
|
||||
alert: "Email adicionado!"
|
||||
de:
|
||||
email:
|
||||
email_change_original:
|
||||
@@ -227,6 +303,14 @@ de:
|
||||
alert: "E-Mail-Adresse hinzugefügt!"
|
||||
es:
|
||||
talk-plugin-local-auth:
|
||||
email:
|
||||
email_change_original:
|
||||
subject: Cambio de correo electrónico
|
||||
body: Su dirección de correo electrónico ha cambiado de {0} a {1}. Si no solicitó este cambio, póngase en contacto con {2}.
|
||||
error:
|
||||
NO_LOCAL_PROFILE: No hay una dirección de correo electrónico asociada a esta cuenta.
|
||||
LOCAL_PROFILE: Una dirección de correo electrónico ya está asociada a esta cuenta.
|
||||
INCORRECT_PASSWORD: La contraseña dada fue incorrecta.
|
||||
change_password:
|
||||
change_password: "Cambiar Contraseña"
|
||||
passwords_dont_match: "Las contraseñas no coinciden"
|
||||
@@ -252,3 +336,38 @@ es:
|
||||
username_does_not_match: "El usuario no coincide"
|
||||
changed_username_success_msg: "Usuario Actualizado - Tu usuario ha sido exitosamente actualizado. No podrás cambiar el usuario por 14 días."
|
||||
change_username_attempt: "El usuario no puede ser actualizado. Los usuarios pueden ser cambiados cada 14 días."
|
||||
change_email:
|
||||
confirm_email_change: "Confirmar cambio de dirección de correo electrónico"
|
||||
description: "Está intentando cambiar su dirección de correo electrónico. Su nueva dirección de correo electrónico se usará para iniciar sesión y recibir notificaciones de la cuenta."
|
||||
new_email: "Nueva dirección de correo electrónico"
|
||||
enter_password: "Introducir la contraseña"
|
||||
incorrect_password: "Contraseña incorrecta"
|
||||
confirm_change: "Confirmar cambio"
|
||||
cancel: "Cancelar"
|
||||
change_email_msg: "Dirección de correo electrónico modificada. Esta dirección de correo electrónico ahora se utilizará para iniciar sesión y notificaciones por correo electrónico."
|
||||
add_email:
|
||||
add_email_address: "Agregar dirección de correo electrónico"
|
||||
enter_email_address: "Introducir la dirección de correo electrónico:"
|
||||
invalid_email_address: "Dirección de correo electrónico no válida"
|
||||
confirm_email_address: "Confirmar el correo:"
|
||||
email_does_not_match: "La dirección de Email no coincide"
|
||||
insert_password: "Insertar contraseña:"
|
||||
confirm_password: "Confirmar contraseña:"
|
||||
required_field: "Este campo es requerido"
|
||||
done: "Hecho"
|
||||
content:
|
||||
title: "Agregar una dirección de correo electrónico"
|
||||
description: "Para su seguridad adicional, solicitamos a los usuarios que agreguen una dirección de correo electrónico a sus cuentas. Su dirección de correo electrónico se usará para:"
|
||||
item_1: "Recibe actualizaciones sobre cualquier cambio en tu cuenta (dirección de correo electrónico, nombre de usuario, contraseña, etc.)"
|
||||
item_2: "Permitir que descargues tus comentarios."
|
||||
item_3: "Envía notificaciones de comentarios que hayas elegido recibir."
|
||||
verify:
|
||||
title: "Verificar su dirección de correo electrónico"
|
||||
description: "Hemos enviado un correo electrónico a {0} para verificar su cuenta. Debe verificar su dirección de correo electrónico para que se pueda usar para notificaciones y notificaciones de cambio de cuenta."
|
||||
added:
|
||||
title: "Dirección de correo electrónico agregada"
|
||||
description: "Su dirección de correo electrónico ha sido agregada a su cuenta."
|
||||
subtitle: "¿Necesita cambiar su dirección de correo electrónico?"
|
||||
description_2: "Puedes cambiar la configuración de tu cuenta visitando"
|
||||
path: "Mi perfil > Configuración"
|
||||
alert: "¡Correo electrónico agregado!"
|
||||
|
||||
@@ -21,7 +21,7 @@ nl_NL:
|
||||
member_since: "Gebruiker sinds"
|
||||
pt_BR:
|
||||
talk-plugin-member-since:
|
||||
member_since: "Member Since"
|
||||
member_since: "Membro desde"
|
||||
zh_CN:
|
||||
talk-plugin-member-since:
|
||||
member_since: "成员加入日期"
|
||||
|
||||
@@ -84,16 +84,16 @@ nl_NL:
|
||||
ban_user_dialog_headline: "Gebruiker verbannen?"
|
||||
pt_BR:
|
||||
talk-plugin-moderation-actions:
|
||||
reject_comment: "Reject"
|
||||
approve_comment: "Approve"
|
||||
approved_comment: "Approved"
|
||||
moderation_actions: "Moderation Actions"
|
||||
ban_user: "Ban User"
|
||||
ban_user_dialog_sub: "Are you sure you would like to ban this user?"
|
||||
ban_user_dialog_copy: "Note: Banning this user will also place this comment in the Rejected queue."
|
||||
ban_user_dialog_cancel: "Cancel"
|
||||
ban_user_dialog_yes: "Yes. Ban user"
|
||||
ban_user_dialog_headline: "Ban User?"
|
||||
reject_comment: "Rejeitar"
|
||||
approve_comment: "Aprovar"
|
||||
approved_comment: "Aprovado"
|
||||
moderation_actions: "Ações"
|
||||
ban_user: "Banir Usuário"
|
||||
ban_user_dialog_sub: "Tem certeza que deseja banir esse usuário?"
|
||||
ban_user_dialog_copy: "Nota: Banindo esse usuário também irá colocar esse comentário na fila de Rejeitado."
|
||||
ban_user_dialog_cancel: "Cancelar"
|
||||
ban_user_dialog_yes: "Sim. Banir usuário"
|
||||
ban_user_dialog_headline: "Banir usuário?"
|
||||
zh_CN:
|
||||
talk-plugin-moderation-actions:
|
||||
reject_comment: "拒绝"
|
||||
|
||||
@@ -4,6 +4,9 @@ ar:
|
||||
en:
|
||||
talk-plugin-notifications-category-featured:
|
||||
toggle_description: My comment is featured
|
||||
es:
|
||||
talk-plugin-notifications-category-featured:
|
||||
toggle_description: Mi comentario esta presentado
|
||||
de:
|
||||
talk-plugin-notifications-category-featured:
|
||||
toggle_description: Mein Kommentar wird empfohlen
|
||||
|
||||
@@ -11,6 +11,12 @@ en:
|
||||
featured:
|
||||
subject: "One of your comments was featured on {0}"
|
||||
body: "{0}\nA member of our team has selected this comment to be featured for other readers: {1}"
|
||||
es:
|
||||
talk-plugin-notifications:
|
||||
categories:
|
||||
featured:
|
||||
subject: "Uno de tus comentarios apareció en {0}"
|
||||
body: "{0}\nUn miembro de nuestro equipo ha seleccionado este comentario para ser presentado por otros lectores: {1}"
|
||||
de:
|
||||
talk-plugin-notifications:
|
||||
categories:
|
||||
|
||||
@@ -4,6 +4,9 @@ ar:
|
||||
en:
|
||||
talk-plugin-notifications-category-reply:
|
||||
toggle_description: My comment receives a reply
|
||||
es:
|
||||
talk-plugin-notifications-category-reply:
|
||||
toggle_description: Mi comentario recibe una respuesta
|
||||
de:
|
||||
talk-plugin-notifications-category-reply:
|
||||
toggle_description: Jemand antwortet auf meinen Kommentar
|
||||
|
||||
@@ -11,6 +11,12 @@ en:
|
||||
reply:
|
||||
subject: "Someone has replied to your comment on {0}"
|
||||
body: "{0}\n{1} replied to your comment: {2}"
|
||||
es:
|
||||
talk-plugin-notifications:
|
||||
categories:
|
||||
reply:
|
||||
subject: "Alguien ha respondido a tu comentario en {0}"
|
||||
body: "{0}\n{1} respondió a tu comentario: {2}"
|
||||
de:
|
||||
talk-plugin-notifications:
|
||||
categories:
|
||||
|
||||
@@ -4,6 +4,9 @@ ar:
|
||||
en:
|
||||
talk-plugin-notifications-category-staff:
|
||||
toggle_description: A staff member replies to my comment
|
||||
es:
|
||||
talk-plugin-notifications-category-staff:
|
||||
toggle_description: Un miembro del personal responde a mi comentario
|
||||
de:
|
||||
talk-plugin-notifications-category-staff:
|
||||
toggle_description: Ein Redaktionsmitglied antwortet auf meinen Kommentar
|
||||
|
||||
@@ -11,6 +11,12 @@ en:
|
||||
staff:
|
||||
subject: "Someone at {0} has replied to your comment"
|
||||
body: "{0}\n{1} works for {2} and has replied to your comment: {3}"
|
||||
es:
|
||||
talk-plugin-notifications:
|
||||
categories:
|
||||
staff:
|
||||
subject: "Alguien en {0} ha respondido a tu comentario"
|
||||
body: "{0}\n{1} trabaja para {2} y ha respondido a tu comentario: {3}"
|
||||
de:
|
||||
talk-plugin-notifications:
|
||||
categories:
|
||||
|
||||
@@ -6,6 +6,10 @@ en:
|
||||
talk-plugin-notifications:
|
||||
digest_enum:
|
||||
DAILY: In a daily digest
|
||||
es:
|
||||
talk-plugin-notifications:
|
||||
digest_enum:
|
||||
DAILY: En un resumen diario
|
||||
de:
|
||||
talk-plugin-notifications:
|
||||
digest_enum:
|
||||
|
||||
@@ -6,6 +6,10 @@ en:
|
||||
talk-plugin-notifications:
|
||||
digest_enum:
|
||||
HOURLY: In an hourly digest
|
||||
es:
|
||||
talk-plugin-notifications:
|
||||
digest_enum:
|
||||
HOURLY: En un resumen por hora
|
||||
de:
|
||||
talk-plugin-notifications:
|
||||
digest_enum:
|
||||
|
||||
@@ -34,6 +34,24 @@ en:
|
||||
digest_option: Send notifications
|
||||
digest_enum:
|
||||
NONE: Immediately
|
||||
es:
|
||||
talk-plugin-notifications:
|
||||
settings_title: Notificaciones
|
||||
settings_subtitle: Reciba notificaciones cuando
|
||||
turn_off_all: No quiero recibir notificaciones
|
||||
banner_info:
|
||||
title: Se requiere verificación de correo electrónico
|
||||
text: Para recibir notificaciones por correo electrónico, debe tener una dirección de correo electrónico verificada.
|
||||
verify_now: Verifica tu correo electrónico ahora.
|
||||
banner_success:
|
||||
title: Verificación del correo electrónico enviada
|
||||
text: Se envió un correo electrónico a {0} que contiene un enlace de verificación.
|
||||
banner_error:
|
||||
title: Error
|
||||
text: Ha habido un error al enviar su correo electrónico de verificación. Por favor, inténtelo de nuevo más tarde.
|
||||
digest_option: Enviar notificaciones
|
||||
digest_enum:
|
||||
NONE: Inmediatamente
|
||||
de:
|
||||
talk-plugin-notifications:
|
||||
settings_title: Benachrichtigungen
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import cn from 'classnames';
|
||||
import styles from './styles.css';
|
||||
import { t } from 'plugin-api/beta/client/services';
|
||||
import { buildCommentURL } from 'plugin-api/beta/client/utils';
|
||||
import { ClickOutside } from 'plugin-api/beta/client/components';
|
||||
import { Icon, Button } from 'plugin-api/beta/client/components/ui';
|
||||
|
||||
@@ -90,7 +91,7 @@ export default class PermalinkButton extends React.Component {
|
||||
className={cn(styles.input, `${name}-copy-field`)}
|
||||
type="text"
|
||||
ref={input => (this.permalinkInput = input)}
|
||||
defaultValue={`${asset.url}?commentId=${comment.id}`}
|
||||
defaultValue={buildCommentURL(asset.url, comment.id)}
|
||||
readOnly
|
||||
/>
|
||||
|
||||
@@ -105,9 +106,9 @@ export default class PermalinkButton extends React.Component {
|
||||
},
|
||||
])}
|
||||
>
|
||||
{!copyFailure && !copySuccessful && 'Copy'}
|
||||
{copySuccessful && 'Copied'}
|
||||
{copyFailure && 'Not supported'}
|
||||
{!copyFailure && !copySuccessful && t('common.copy')}
|
||||
{copySuccessful && t('common.copied')}
|
||||
{copyFailure && t('common.notsupported')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -100,6 +100,57 @@ en:
|
||||
subtitle: "Are you sure you want to delete your account?"
|
||||
description: "To confirm you would like to delete your account please type in the following phrase into the text box below:"
|
||||
type_to_confirm: "Type phrase below to confirm"
|
||||
es:
|
||||
download_request:
|
||||
section_title: "Descargar el historial de mis comentarios"
|
||||
you_will_get_a_copy: "Recibirás un correo electrónico con un enlace para descargar tu historial de comentarios. Puedes hacer"
|
||||
download_rate: "una solicitud de descarga cada {0} días"
|
||||
most_recent_request: "Tu solicitud más reciente"
|
||||
request: "Solicitar historial de comentarios"
|
||||
rate_limit: "Puedes enviar otra solicitud de historial de comentarios en {0}"
|
||||
hours: "{0} horas"
|
||||
days: "{0} dias"
|
||||
hour: "{0} hora"
|
||||
day: "{0} día"
|
||||
download_preparing: "Preparando para la descarga de la cuenta - Revises tu correo electrónico en breve para obtener un enlace de descarga"
|
||||
delete_request:
|
||||
account_deletion_cancelled: 'Solicitud de eliminación de cuenta cancelada - Tu solicitud para eliminar tu cuenta ha sido cancelada.'
|
||||
account_deletion_requested: 'Eliminación de cuenta solicitada'
|
||||
received_on: "Se recibió una solicitud para eliminar tu cuenta en "
|
||||
cancel_request_description: "Si deseas reactivar tu cuenta, puedes cancelar tu solicitud para eliminar tu cuenta a continuación"
|
||||
before: "antes"
|
||||
cancel_account_deletion_request: "Cancelar solicitud de eliminación de cuenta"
|
||||
delete_my_account: "Borrar mi cuenta"
|
||||
delete_my_account_description: "Al eliminar tu cuenta, se borrará definitivamente tu perfil y se eliminarán todos tus comentarios de este sitio."
|
||||
already_submitted_request_description: "Ya ha enviado una solicitud para eliminar tu cuenta. Tu cuenta será eliminada después de {0}. Puedes cancelar la solicitud hasta ese momento."
|
||||
your_request_submitted_description: "Tu solicitud ha sido enviada y la confirmación ha sido enviada a la dirección de correo electrónico asociada con tu cuenta."
|
||||
your_account_deletion_scheduled: "Tu cuenta está programada para ser eliminada después de:"
|
||||
changed_your_mind: "¿Has cambiado de opinión?"
|
||||
simply_go_to: "Simplemente acceda a su cuenta nuevamente antes de esta hora y haga clic en"
|
||||
tell_us_why: "Dinos por qué"
|
||||
feedback_copy: "Nos gustaría saber por qué eligió eliminar tu cuenta. Envíenos tus comentarios sobre nuestro sistema de comentarios por correo electrónico"
|
||||
done: "Hecho"
|
||||
cancel: "Cancelar"
|
||||
proceed: "Proceder"
|
||||
input_is_not_correct: "La entrada no es correcta"
|
||||
step_0:
|
||||
you_are_attempting: "Estás intentando eliminar tu cuenta. Esto significa:"
|
||||
item_1: "Todos tus comentarios son eliminados de este sitio"
|
||||
item_2: "Todos tus comentarios son eliminados de nuestra base de datos"
|
||||
item_3: "Tu nombre de usuario y dirección de correo electrónico se eliminan de nuestro sistema"
|
||||
step_1:
|
||||
subtitle: "¿Cuándo se eliminará mi cuenta?"
|
||||
description: "Tu cuenta se eliminará {0} horas después de que se hayas enviado su solicitud."
|
||||
subtitle_2: "¿Todavía puedo escribir comentarios hasta que mi cuenta se elimine?"
|
||||
description_2: "Sí, todavía puedes comentar, responder y reaccionar a los comentarios hasta que expire {0} horas."
|
||||
step_2:
|
||||
description: "Antes de que se elimine tu cuenta, te recomendamos que descargues su historial de comentarios para tus registros. Después de que se elimine su cuenta, no podrás solicitar su historial de comentarios."
|
||||
to_download: "Para descargar tu historial de comentarios, ve a:"
|
||||
path: "Mi perfil > Descargar historial de mis comentarios"
|
||||
step_3:
|
||||
subtitle: "¿Seguro que quieres eliminar tu cuenta?"
|
||||
description: "Para confirmar que deseas eliminar tu cuenta, escriba la siguiente frase en el cuadro de texto a continuación:"
|
||||
type_to_confirm: "Escriba la frase a continuación para confirmar"
|
||||
de:
|
||||
download_request:
|
||||
section_title: "Mein Kommentar-Archiv herunterladen"
|
||||
@@ -151,3 +202,54 @@ de:
|
||||
subtitle: "Sind Sie sicher, dass Sie Ihr Benutzerkonto löschen möchten?"
|
||||
description: "Um zu bestätigen, dass Sie Ihr Konto löschen möchten, geben Sie bitte folgende Zeichen in das Textfeld ein:"
|
||||
type_to_confirm: "Zur Bestätigung Zeichenfolge eingeben"
|
||||
pt_BR:
|
||||
download_request:
|
||||
section_title: "Baixar meu histórico de comentários"
|
||||
you_will_get_a_copy: "Você receberá um email com um link para baixar seu histórico de comentários. Você pode fazer"
|
||||
download_rate: "uma requisição de Download a cada {0} dias"
|
||||
most_recent_request: "Suas solicitações mais recentes"
|
||||
request: "Solicitar histórico de comentários"
|
||||
rate_limit: "Você pode solicitar outro histórico de comentários em {0}"
|
||||
hours: "{0} horas"
|
||||
days: "{0} dias"
|
||||
hour: "{0} hora"
|
||||
day: "{0} dia"
|
||||
download_preparing: "Preparando Download - Cheque seu email para acessar um link de download"
|
||||
delete_request:
|
||||
account_deletion_cancelled: 'Solicitação de exclusão de conta cancelada - Sua solicitação de exclusão cancelada.'
|
||||
account_deletion_requested: 'Exclusão de conta solicitada'
|
||||
received_on: "Uma solicitação para deletar sua conta foi recebida "
|
||||
cancel_request_description: "Se você deseja reativar sua conta, você pode cancelar a solicitação de exclusão abaixo"
|
||||
before: "antes"
|
||||
cancel_account_deletion_request: "Cancelar requisiçao de exclusão da conta"
|
||||
delete_my_account: "Deletar minha conta"
|
||||
delete_my_account_description: "Deletando sua conta seu perfil será excluído permanentemente e todos os seus comentários serão removidos desse site."
|
||||
already_submitted_request_description: "Você já enviou uma solicitação de exclusão da conta. Sua conta será deletada depois de {0}. Você pode cancelar até a data informada"
|
||||
your_request_submitted_description: "Sua solicitação foi enviada e uma confirmação foi enviada para o endereço de email associado a sua conta."
|
||||
your_account_deletion_scheduled: "Sua conta está programada para ser deletada depois de:"
|
||||
changed_your_mind: "Mudou de ideia?"
|
||||
simply_go_to: "Simplesmente volte para sua conta novamente e clique"
|
||||
tell_us_why: "Nos diga porque"
|
||||
feedback_copy: "Gostariámos de saber porque você deseja excluir sua conta. Nos envie um feedback através do nosso sistema de comentário"
|
||||
done: "Feito"
|
||||
cancel: "Cancelar"
|
||||
proceed: "Proceder"
|
||||
input_is_not_correct: "A entrada está incorreta"
|
||||
step_0:
|
||||
you_are_attempting: "Você está tentando deletar sua conta. Isso significa:"
|
||||
item_1: "Todos os seus comentários estão removidos desse site"
|
||||
item_2: "Todos os seus comentários estão removidos dos nossos bancos de dado"
|
||||
item_3: "Seu usuário e endereço de email estão removidos do nosso sistema"
|
||||
step_1:
|
||||
subtitle: "Quando minha conta será deletada?"
|
||||
description: "Sua conta será deletada {0} horas depois que sua solicitação for enviada."
|
||||
subtitle_2: "Ainda posso comentar antes da minha conta ser deletada?"
|
||||
description_2: "Sim, você ainda pode comentar, responder, e reagir aos comentários até as {0} horas expirarem."
|
||||
step_2:
|
||||
description: "Antes da sua conta ser deletada, nós recomendamos você a baixar seu histórico de comentários. Depois que sua conta for deletada, não será possível solicitar seu histórico de comentários."
|
||||
to_download: "Para baixar seu histórico de comentários, vá em:"
|
||||
path: "Meu Perfil > Baixar meu histórico de comentários"
|
||||
step_3:
|
||||
subtitle: "Você tem certeza que deseja deletar sua conta?"
|
||||
description: "Para confirmar que você deseja deletar sua conta por favor digite a frase a seguir na caixa de texto abaixo:"
|
||||
type_to_confirm: "Digite a frase abaixo para confirmar"
|
||||
|
||||
@@ -73,6 +73,43 @@ en:
|
||||
body: "You have cancelled your account deletion request for {0}. Your account is now reactivated."
|
||||
error:
|
||||
DOWNLOAD_TOKEN_INVALID: "Your download link is not valid."
|
||||
es:
|
||||
download_landing:
|
||||
download_your_account: "Descargue su historial de comentarios"
|
||||
download_details: "Su historial de comentarios se descargará en un archivo .zip. Después de descomprimir el historial de comentarios, tendrá un archivo de valores separados por comas (o .csv) que podrá importar fácilmente en su aplicación de hoja de cálculo favorita."
|
||||
all_information_included: "Para cada uno de sus comentarios se incluye la siguiente información:"
|
||||
information_included:
|
||||
date: "Cuando escribiste el comentario"
|
||||
url: "La URL del enlace permanente para el comentario"
|
||||
body: "El texto de comentario"
|
||||
asset_url: "La URL del artículo o historia donde aparece el comentario"
|
||||
confirm: "Descargar el historial de mis comentarios"
|
||||
email:
|
||||
download:
|
||||
subject: "Sus comentarios están listos para su descarga desde {0}"
|
||||
download_link_ready: "Haga clic aquí para descargar sus comentarios de {0} a partir de {1}:"
|
||||
download_archive: "Descargar archivo"
|
||||
delete:
|
||||
subject: "Su cuenta para {0} está programada para ser eliminada"
|
||||
body: |
|
||||
Se recibió una solicitud para eliminar su cuenta. Su cuenta está programada para ser eliminada {1}.
|
||||
|
||||
Después de ese momento, todos sus comentarios serán eliminados del sitio, todos sus comentarios serán eliminados de nuestra base de datos y su nombre de usuario y dirección de correo electrónico serán eliminados de nuestro sistema.
|
||||
|
||||
Si cambia de opinión, puede iniciar sesión en su cuenta y cancelar la solicitud antes de la hora programada para la eliminación de su cuenta.
|
||||
deleted:
|
||||
subject: "Su cuenta para {0} ha sido eliminada"
|
||||
body: |
|
||||
Su cuenta de comentarista para {0} ahora se borró. ¡Sentimos verte partir!
|
||||
|
||||
Si desea volver a unirse a la discusión en el futuro, puede registrarse para obtener una nueva cuenta.
|
||||
|
||||
Si desea darnos su opinión sobre por qué se fue y qué podemos hacer para mejorar la experiencia de comentarios, envíenos un correo electrónico a {1}.
|
||||
cancelDelete:
|
||||
subject: "La solicitud de eliminación de su cuenta para {0} ha sido cancelada"
|
||||
body: "Ha cancelado la solicitud de eliminación de cuenta para {0}. Su cuenta ahora está reactivada."
|
||||
error:
|
||||
DOWNLOAD_TOKEN_INVALID: "Su enlace de descarga no es válido."
|
||||
de:
|
||||
download_landing:
|
||||
download_your_account: "Mein Kommentar-Archiv herunterladen"
|
||||
|
||||
@@ -28,8 +28,8 @@ nl_NL:
|
||||
respected: Gerespecteerd
|
||||
pt_BR:
|
||||
talk-plugin-respect:
|
||||
respect: Respect
|
||||
respected: Respected
|
||||
respect: Respeitar
|
||||
respected: Respeitado
|
||||
zh_CN:
|
||||
talk-plugin-respect:
|
||||
respect: "赞"
|
||||
|
||||
@@ -21,7 +21,7 @@ nl_NL:
|
||||
label: Meest beantwoord eerst
|
||||
pt_BR:
|
||||
talk-plugin-sort-most-replied:
|
||||
label: Most replied first
|
||||
label: Mais respondidos primeiro
|
||||
zh_CN:
|
||||
talk-plugin-sort-most-replied:
|
||||
label: "最多回复在前"
|
||||
|
||||
@@ -21,7 +21,7 @@ nl_NL:
|
||||
label: Meest gerespecteerd eerst
|
||||
pt_BR:
|
||||
talk-plugin-sort-most-respected:
|
||||
label: Most respected first
|
||||
label: Mais respeitados primeiro
|
||||
zh_CN:
|
||||
talk-plugin-sort-most-respected:
|
||||
label: "最多被赞在前"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
en:
|
||||
talk-plugin-sort-most-upvoted:
|
||||
label: Most upvoted first
|
||||
de:
|
||||
talk-plugin-sort-most-upvoted:
|
||||
label: Am besten bewertet
|
||||
es:
|
||||
talk-plugin-sort-oldest:
|
||||
label: Más votadas primero
|
||||
|
||||
@@ -21,7 +21,7 @@ nl_NL:
|
||||
label: Nieuwste eerst
|
||||
pt_BR:
|
||||
talk-plugin-sort-newest:
|
||||
label: Newest first
|
||||
label: Mais novos primeiro
|
||||
zh_CN:
|
||||
talk-plugin-sort-newest:
|
||||
label: "最新发表在前"
|
||||
|
||||
@@ -21,7 +21,7 @@ nl_NL:
|
||||
label: Oudste eerst
|
||||
pt_BR:
|
||||
talk-plugin-sort-oldest:
|
||||
label: Oldest first
|
||||
label: Mais antigos primeiro
|
||||
zh_CN:
|
||||
talk-plugin-sort-oldest:
|
||||
label: "最早发表在前"
|
||||
|
||||
@@ -71,17 +71,17 @@ de:
|
||||
es:
|
||||
error:
|
||||
COMMENT_IS_TOXIC: |
|
||||
Are you sure? The language in this comment might violate our community guidelines.
|
||||
You can edit the comment or submit it for moderator review.
|
||||
¿Estás seguro? El lenguaje en este comentario puede violar nuestras pautas de la comunidad.
|
||||
Puede editar el comentario o enviarlo para la revisión del moderador.
|
||||
talk-plugin-toxic-comments:
|
||||
unlikely: "Unlikely"
|
||||
highly_likely: "Highly Likely"
|
||||
possibly: "Possibly"
|
||||
likely: "Likely"
|
||||
toxic_comment: "Toxic Comment"
|
||||
unlikely: "Improbable"
|
||||
highly_likely: "Altamente Improbable"
|
||||
possibly: "Posiblemente"
|
||||
likely: "Probable"
|
||||
toxic_comment: "Comentario Tóxico"
|
||||
still_toxic: |
|
||||
This edited comment might still violate our community guidelines.
|
||||
Our moderation team will review your comment shortly.
|
||||
Este comentario editado aún puede infringir las pautas de nuestra comunidad.
|
||||
Nuestro equipo de moderación revisará tu comentario en breve.
|
||||
flags:
|
||||
reasons:
|
||||
comment:
|
||||
|
||||
@@ -20,7 +20,7 @@ de:
|
||||
filter: Filtern
|
||||
es:
|
||||
talk-plugin-viewing-options:
|
||||
viewing_options: "Opciones de visualización"
|
||||
viewing_options: "Opciones"
|
||||
sort: Ordenado por
|
||||
filter: Filtrado por
|
||||
fr:
|
||||
@@ -35,7 +35,7 @@ nl_NL:
|
||||
filter: Filtering
|
||||
pt_BR:
|
||||
talk-plugin-viewing-options:
|
||||
viewing_options: "Viewing Options"
|
||||
viewing_options: "Ver opções"
|
||||
sort: Sorting
|
||||
filter: Filtering
|
||||
zh_CN:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const authorization = require('../../../middleware/authorization');
|
||||
const errors = require('../../../errors');
|
||||
const { ErrHTTPNotFound } = require('../../../errors');
|
||||
const AssetsService = require('../../../services/assets');
|
||||
const AssetModel = require('../../../models/asset');
|
||||
|
||||
@@ -90,7 +90,7 @@ router.get(
|
||||
// Send back the asset.
|
||||
let asset = await AssetsService.findById(req.params.asset_id);
|
||||
if (!asset) {
|
||||
return next(errors.ErrNotFound);
|
||||
return next(new ErrHTTPNotFound());
|
||||
}
|
||||
|
||||
return res.json(asset);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const casual = require('casual');
|
||||
const { ErrNotFound } = require('../../errors');
|
||||
const { ErrHTTPNotFound } = require('../../errors');
|
||||
const Asset = require('../../models/asset');
|
||||
|
||||
router.get('/id/:asset_id', async (req, res, next) => {
|
||||
try {
|
||||
const asset = await Asset.findOne({ id: req.params.asset_id });
|
||||
if (asset === null) {
|
||||
throw new ErrNotFound();
|
||||
throw new ErrHTTPNotFound();
|
||||
}
|
||||
|
||||
res.render('dev/article.njk', {
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ const SetupService = require('../services/setup');
|
||||
const authentication = require('../middleware/authentication');
|
||||
const logging = require('../middleware/logging');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const { TalkError, ErrNotFound } = require('../errors');
|
||||
const { TalkError, ErrHTTPNotFound } = require('../errors');
|
||||
const express = require('express');
|
||||
const i18n = require('../middleware/i18n');
|
||||
const path = require('path');
|
||||
@@ -146,7 +146,7 @@ router.use(require('./plugins'));
|
||||
|
||||
// Catch 404 and forward to error handler.
|
||||
router.use((req, res, next) => {
|
||||
next(new ErrNotFound());
|
||||
next(new ErrHTTPNotFound());
|
||||
});
|
||||
|
||||
// Add logging for errors.
|
||||
|
||||
+11
-1
@@ -19,6 +19,7 @@ const ms = require('ms');
|
||||
const _ = require('lodash');
|
||||
const { attachStaticLocals } = require('../middleware/staticTemplate');
|
||||
const { encodeJSONForHTML } = require('./response');
|
||||
const { STATIC_URL, BASE_URL } = require('../url');
|
||||
|
||||
// Create a redis client to use for authentication.
|
||||
const { createClientFactory } = require('./redis');
|
||||
@@ -97,6 +98,15 @@ const HandleGenerateCredentials = (req, res, next) => (err, user) => {
|
||||
res.json({ user, token });
|
||||
};
|
||||
|
||||
/**
|
||||
* authPopupCallbackCSP is the header sent via Content-Security-Policy when
|
||||
* a social callback request is being made.
|
||||
*/
|
||||
const authPopupCallbackCSP = (() =>
|
||||
STATIC_URL && BASE_URL !== STATIC_URL
|
||||
? `default-src 'self' ${STATIC_URL.replace(/\/$/, '')};`
|
||||
: "default-src 'self';")();
|
||||
|
||||
/**
|
||||
* Returns the response to the login attempt via a popup callback with some JS.
|
||||
*/
|
||||
@@ -106,7 +116,7 @@ const HandleAuthPopupCallback = (req, res, next) => (err, user) => {
|
||||
res.header('Pragma', 'no-cache');
|
||||
|
||||
// Ensure the only scripts that can run here are those on the Talk domain.
|
||||
res.header('Content-Security-Policy', "default-src 'self';");
|
||||
res.header('Content-Security-Policy', authPopupCallbackCSP);
|
||||
|
||||
// Attach static locals to the response locals object.
|
||||
attachStaticLocals(res.locals);
|
||||
|
||||
+10
-3
@@ -5,7 +5,6 @@ const Assets = require('./assets');
|
||||
const Settings = require('./settings');
|
||||
const { ADD_COMMENT_TAG } = require('../perms/constants');
|
||||
const { ErrNotAuthorized } = require('../errors');
|
||||
const { get, has } = require('lodash');
|
||||
|
||||
const updateModel = async (item_type, query, update) => {
|
||||
// Get the model to update with.
|
||||
@@ -60,8 +59,16 @@ class TagsService {
|
||||
asset = await Assets.findById(id);
|
||||
}
|
||||
|
||||
if (asset && has(asset, 'settings.tags')) {
|
||||
return get(asset, 'settings.tags');
|
||||
// Lodash has issues with determining property existence when the object
|
||||
// is a Mongoose model, this is likely related to how Mongoose proxies the
|
||||
// object, but this concrete check works.
|
||||
if (
|
||||
asset &&
|
||||
asset.settings &&
|
||||
asset.settings.tags &&
|
||||
Array.isArray(asset.settings.tags)
|
||||
) {
|
||||
return asset.settings.tags;
|
||||
}
|
||||
|
||||
// Extract the tags from the settings object.
|
||||
|
||||
+12
-2
@@ -68,6 +68,8 @@ async function upsertUser(
|
||||
},
|
||||
});
|
||||
if (user) {
|
||||
user.wasUpserted = false;
|
||||
user.$ignore('wasUpserted');
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -98,8 +100,16 @@ async function upsertUser(
|
||||
// Save the user in the database.
|
||||
await user.save();
|
||||
|
||||
// Emit that the user was created.
|
||||
ctx.pubsub.publish('userCreated', user);
|
||||
if (ctx) {
|
||||
// Emit that the user was created if the context is set.
|
||||
ctx.pubsub.publish('userCreated', user);
|
||||
}
|
||||
|
||||
// Indicate that the user was upserted.
|
||||
user.wasUpserted = true;
|
||||
user.$ignore('wasUpserted');
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
// Users is the interface for the application to interact with the
|
||||
|
||||
@@ -2,6 +2,7 @@ const TagsService = require('../../../services/tags');
|
||||
const UsersService = require('../../../services/users');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
const CommentModel = require('../../../models/comment');
|
||||
const AssetModel = require('../../../models/asset');
|
||||
const Context = require('../../../graph/context');
|
||||
|
||||
const chai = require('chai');
|
||||
@@ -18,6 +19,24 @@ describe('services.TagsService', () => {
|
||||
'1Coral!!',
|
||||
'Stampi'
|
||||
);
|
||||
// We don't care about the asset value, just that it exists.
|
||||
await AssetModel.create({
|
||||
id: '123',
|
||||
settings: {
|
||||
tags: [
|
||||
{
|
||||
name: 'TEST',
|
||||
permissions: {
|
||||
public: true,
|
||||
self: true,
|
||||
roles: [],
|
||||
},
|
||||
models: ['COMMENTS'],
|
||||
created_at: new Date(),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
comment = await CommentModel.create({
|
||||
id: '1',
|
||||
body: 'comment 10',
|
||||
@@ -28,6 +47,18 @@ describe('services.TagsService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getAll', () => {
|
||||
it('retrieves tags from the asset', async () => {
|
||||
const tags = await TagsService.getAll({
|
||||
item_type: 'COMMENTS',
|
||||
asset_id: comment.asset_id,
|
||||
});
|
||||
|
||||
expect(tags.length).to.equal(1);
|
||||
expect(tags[0].name).to.equal('TEST');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#add', () => {
|
||||
it('adds a tag', async () => {
|
||||
const id = comment.id;
|
||||
|
||||
@@ -363,6 +363,58 @@ describe('services.UsersService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#upsertExternalUser', () => {
|
||||
it('should return a user when the desired user is found', async () => {
|
||||
const ctx = Context.forSystem();
|
||||
let user = await UsersService.upsertExternalUser(
|
||||
ctx,
|
||||
'an-id',
|
||||
'a-provider',
|
||||
'a-display-name'
|
||||
);
|
||||
|
||||
expect(user).to.be.defined;
|
||||
expect(user.wasUpserted).to.be.true;
|
||||
|
||||
user = await UsersService.upsertExternalUser(
|
||||
ctx,
|
||||
'an-id',
|
||||
'a-provider',
|
||||
'a-display-name'
|
||||
);
|
||||
|
||||
expect(user).to.be.defined;
|
||||
expect(user.wasUpserted).to.be.false;
|
||||
});
|
||||
|
||||
it('should return a user when the desired user is not found', async () => {
|
||||
const ctx = Context.forSystem();
|
||||
let user = await UsersService.upsertExternalUser(
|
||||
ctx,
|
||||
'an-id',
|
||||
'a-provider',
|
||||
'a-display-name'
|
||||
);
|
||||
|
||||
expect(user).to.be.defined;
|
||||
expect(user.wasUpserted).to.be.true;
|
||||
expect(user).to.have.property('metadata');
|
||||
expect(user.metadata).to.have.property('displayName', 'a-display-name');
|
||||
});
|
||||
|
||||
it('should work if the context passed is null', async () => {
|
||||
let user = await UsersService.upsertExternalUser(
|
||||
null,
|
||||
'an-id',
|
||||
'a-provider',
|
||||
'a-display-name'
|
||||
);
|
||||
|
||||
expect(user).to.be.defined;
|
||||
expect(user.wasUpserted).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isValidUsername', () => {
|
||||
it('should not allow non-alphanumeric characters in usernames', () => {
|
||||
return UsersService.isValidUsername('hi🖕')
|
||||
|
||||
@@ -11,6 +11,8 @@ const BASE_URL = trailingSlash(ROOT_URL);
|
||||
// The BASE_PATH is simply the path component of the BASE_URL.
|
||||
const BASE_PATH = new URL(BASE_URL).pathname;
|
||||
|
||||
const BASE_ORIGIN = new URL(BASE_URL).origin;
|
||||
|
||||
// The MOUNT_PATH is derived from the BASE_PATH, if it is provided and enabled.
|
||||
// This will mount all the application routes onto it.
|
||||
const MOUNT_PATH = ROOT_URL_MOUNT_PATH ? BASE_PATH : '/';
|
||||
@@ -22,6 +24,7 @@ const STATIC_ORIGIN = new URL(STATIC_URI).origin;
|
||||
|
||||
module.exports = {
|
||||
BASE_URL,
|
||||
BASE_ORIGIN,
|
||||
BASE_PATH,
|
||||
MOUNT_PATH,
|
||||
STATIC_URL,
|
||||
|
||||
@@ -185,14 +185,8 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.4.tgz#cdeb6bcbef9b6c584374b81aa7f48ecf3da404fa"
|
||||
|
||||
"@types/node@*":
|
||||
version "10.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.3.1.tgz#51092fbacaed768a122a293814474fbf6e5e8b6d"
|
||||
|
||||
"@types/ws@^3.0.0":
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-3.2.1.tgz#b0c1579e58e686f83ce0a97bb9463d29705827fb"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
version "10.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.4.tgz#0f4cb2dc7c1de6096055357f70179043c33e9897"
|
||||
|
||||
JSONStream@^1.0.7:
|
||||
version "1.3.3"
|
||||
@@ -267,6 +261,12 @@ agent-base@2:
|
||||
extend "~3.0.0"
|
||||
semver "~5.0.1"
|
||||
|
||||
agent-base@4, agent-base@^4.2.0, agent-base@~4.2.0:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
|
||||
dependencies:
|
||||
es6-promisify "^5.0.0"
|
||||
|
||||
agent-base@^4.1.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce"
|
||||
@@ -2959,7 +2959,7 @@ defined@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
|
||||
|
||||
degenerator@~1.0.2:
|
||||
degenerator@^1.0.4, degenerator@~1.0.2:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-1.0.4.tgz#fcf490a37ece266464d9cc431ab98c5819ced095"
|
||||
dependencies:
|
||||
@@ -4290,7 +4290,7 @@ get-stream@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
||||
|
||||
get-uri@2:
|
||||
get-uri@2, get-uri@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-2.0.2.tgz#5c795e71326f6ca1286f2fc82575cd2bab2af578"
|
||||
dependencies:
|
||||
@@ -4542,7 +4542,7 @@ graphql-redis-subscriptions@1.3.0:
|
||||
optionalDependencies:
|
||||
ioredis "^3.1.2"
|
||||
|
||||
graphql-subscriptions@^0.4.2, graphql-subscriptions@^0.4.3:
|
||||
graphql-subscriptions@^0.4.2, graphql-subscriptions@^0.4.3, graphql-subscriptions@^0.4.4:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-0.4.4.tgz#39cff32d08dd3c990113864bab77154403727e9b"
|
||||
dependencies:
|
||||
@@ -4998,6 +4998,13 @@ http-proxy-agent@1:
|
||||
debug "2"
|
||||
extend "3"
|
||||
|
||||
http-proxy-agent@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
|
||||
dependencies:
|
||||
agent-base "4"
|
||||
debug "3.1.0"
|
||||
|
||||
http-signature@~1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
|
||||
@@ -5037,7 +5044,7 @@ https-proxy-agent@1:
|
||||
debug "2"
|
||||
extend "3"
|
||||
|
||||
https-proxy-agent@^2.2.0, https-proxy-agent@^2.2.1:
|
||||
https-proxy-agent@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0"
|
||||
dependencies:
|
||||
@@ -6943,7 +6950,7 @@ lru-cache@^2.5.0:
|
||||
version "2.7.3"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
|
||||
|
||||
lru-cache@^4.0.1, lru-cache@^4.1.1:
|
||||
lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
|
||||
dependencies:
|
||||
@@ -7568,7 +7575,7 @@ neo-async@^2.5.0:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.1.tgz#acb909e327b1e87ec9ef15f41b8a269512ad41ee"
|
||||
|
||||
netmask@~1.0.4:
|
||||
netmask@^1.0.6, netmask@~1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35"
|
||||
|
||||
@@ -8210,6 +8217,29 @@ pac-proxy-agent@1:
|
||||
raw-body "2"
|
||||
socks-proxy-agent "2"
|
||||
|
||||
pac-proxy-agent@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz#90d9f6730ab0f4d2607dcdcd4d3d641aa26c3896"
|
||||
dependencies:
|
||||
agent-base "^4.2.0"
|
||||
debug "^3.1.0"
|
||||
get-uri "^2.0.0"
|
||||
http-proxy-agent "^2.1.0"
|
||||
https-proxy-agent "^2.2.1"
|
||||
pac-resolver "^3.0.0"
|
||||
raw-body "^2.2.0"
|
||||
socks-proxy-agent "^3.0.0"
|
||||
|
||||
pac-resolver@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-3.0.0.tgz#6aea30787db0a891704deb7800a722a7615a6f26"
|
||||
dependencies:
|
||||
co "^4.6.0"
|
||||
degenerator "^1.0.4"
|
||||
ip "^1.1.5"
|
||||
netmask "^1.0.6"
|
||||
thunkify "^2.1.2"
|
||||
|
||||
pac-resolver@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-2.0.0.tgz#99b88d2f193fbdeefc1c9a529c1f3260ab5277cd"
|
||||
@@ -9083,6 +9113,23 @@ proxy-agent@2.0.0:
|
||||
pac-proxy-agent "1"
|
||||
socks-proxy-agent "2"
|
||||
|
||||
proxy-agent@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-3.0.1.tgz#4fb7b61b1476d0fe8e3a3384d90e2460bbded3f9"
|
||||
dependencies:
|
||||
agent-base "^4.2.0"
|
||||
debug "^3.1.0"
|
||||
http-proxy-agent "^2.1.0"
|
||||
https-proxy-agent "^2.2.1"
|
||||
lru-cache "^4.1.2"
|
||||
pac-proxy-agent "^2.0.1"
|
||||
proxy-from-env "^1.0.0"
|
||||
socks-proxy-agent "^4.0.1"
|
||||
|
||||
proxy-from-env@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee"
|
||||
|
||||
prr@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
||||
@@ -9275,14 +9322,6 @@ query-string@^4.1.0, query-string@^4.2.2:
|
||||
object-assign "^4.1.0"
|
||||
strict-uri-encode "^1.0.0"
|
||||
|
||||
query-string@^5.0.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb"
|
||||
dependencies:
|
||||
decode-uri-component "^0.2.0"
|
||||
object-assign "^4.1.0"
|
||||
strict-uri-encode "^1.0.0"
|
||||
|
||||
querystring-es3@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
|
||||
@@ -9291,6 +9330,10 @@ querystring@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
||||
|
||||
querystringify@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.0.0.tgz#fa3ed6e68eb15159457c89b37bc6472833195755"
|
||||
|
||||
raf@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575"
|
||||
@@ -9337,7 +9380,7 @@ range-parser@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
|
||||
|
||||
raw-body@2, raw-body@2.3.3:
|
||||
raw-body@2, raw-body@2.3.3, raw-body@^2.2.0:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3"
|
||||
dependencies:
|
||||
@@ -9922,6 +9965,10 @@ require_optional@^1.0.1:
|
||||
resolve-from "^2.0.0"
|
||||
semver "^5.1.0"
|
||||
|
||||
requires-port@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||
|
||||
resolve-cwd@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
|
||||
@@ -10420,6 +10467,10 @@ smart-buffer@^1.0.13, smart-buffer@^1.0.4:
|
||||
version "1.1.15"
|
||||
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16"
|
||||
|
||||
smart-buffer@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3"
|
||||
|
||||
smartquotes@~2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/smartquotes/-/smartquotes-2.3.1.tgz#01ebb595d6c7a9e24d90e8cb95c17d0e1af49407"
|
||||
@@ -10482,6 +10533,20 @@ socks-proxy-agent@2:
|
||||
extend "3"
|
||||
socks "~1.1.5"
|
||||
|
||||
socks-proxy-agent@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz#2eae7cf8e2a82d34565761539a7f9718c5617659"
|
||||
dependencies:
|
||||
agent-base "^4.1.0"
|
||||
socks "^1.1.10"
|
||||
|
||||
socks-proxy-agent@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz#5936bf8b707a993079c6f37db2091821bffa6473"
|
||||
dependencies:
|
||||
agent-base "~4.2.0"
|
||||
socks "~2.2.0"
|
||||
|
||||
socks@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.9.tgz#628d7e4d04912435445ac0b6e459376cb3e6d691"
|
||||
@@ -10489,13 +10554,20 @@ socks@1.1.9:
|
||||
ip "^1.1.2"
|
||||
smart-buffer "^1.0.4"
|
||||
|
||||
socks@~1.1.5:
|
||||
socks@^1.1.10, socks@~1.1.5:
|
||||
version "1.1.10"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.10.tgz#5b8b7fc7c8f341c53ed056e929b7bf4de8ba7b5a"
|
||||
dependencies:
|
||||
ip "^1.1.4"
|
||||
smart-buffer "^1.0.13"
|
||||
|
||||
socks@~2.2.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.1.tgz#68ad678b3642fbc5d99c64c165bc561eab0215f9"
|
||||
dependencies:
|
||||
ip "^1.1.5"
|
||||
smart-buffer "^4.0.1"
|
||||
|
||||
sort-keys@^1.0.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
|
||||
@@ -10828,19 +10900,19 @@ stylus@0.54.5, stylus@~0.54.5:
|
||||
sax "0.5.x"
|
||||
source-map "0.1.x"
|
||||
|
||||
subscriptions-transport-ws@^0.7.2:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.7.3.tgz#15858f03e013e1fc28f8c2d631014ec1548d38f0"
|
||||
subscriptions-transport-ws@^0.8.3:
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.8.3.tgz#d4b22db7f5951bd30e7c6f4dc4774d34ed9f1751"
|
||||
dependencies:
|
||||
"@types/ws" "^3.0.0"
|
||||
backo2 "^1.0.2"
|
||||
eventemitter3 "^2.0.3"
|
||||
graphql-subscriptions "^0.4.3"
|
||||
graphql-tag "^2.0.0"
|
||||
graphql-subscriptions "^0.4.4"
|
||||
graphql-tag "^2.4.2"
|
||||
iterall "^1.1.1"
|
||||
lodash.assign "^4.2.0"
|
||||
lodash.isobject "^3.0.2"
|
||||
lodash.isstring "^4.0.1"
|
||||
symbol-observable "^1.0.4"
|
||||
ws "^3.0.0"
|
||||
|
||||
sugarss@^0.2.0:
|
||||
@@ -11053,7 +11125,7 @@ through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
|
||||
thunkify@~2.1.1:
|
||||
thunkify@^2.1.2, thunkify@~2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/thunkify/-/thunkify-2.1.2.tgz#faa0e9d230c51acc95ca13a361ac05ca7e04553d"
|
||||
|
||||
@@ -11487,6 +11559,13 @@ url-parse-lax@^1.0.0:
|
||||
dependencies:
|
||||
prepend-http "^1.0.1"
|
||||
|
||||
url-parse@^1.4.3:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.3.tgz#bfaee455c889023219d757e045fa6a684ec36c15"
|
||||
dependencies:
|
||||
querystringify "^2.0.0"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
url-regex@~4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/url-regex/-/url-regex-4.1.1.tgz#a5617b22e15e26dac57ce74c3f52088bcdfec995"
|
||||
|
||||
Reference in New Issue
Block a user