mirror of
https://github.com/wassname/talk.git
synced 2026-09-13 13:10:43 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1575b15e36 | ||
|
|
7da9126a76 | ||
|
|
9453d207f5 | ||
|
|
869c760a8b | ||
|
|
b283595c97 | ||
|
|
d672af63f9 | ||
|
|
b4ad78fd65 | ||
|
|
713de46c2a | ||
|
|
fc1e51ed62 | ||
|
|
4eef6f4218 | ||
|
|
c8cfd7c0f8 | ||
|
|
0e4cbf5f44 | ||
|
|
448b988281 | ||
|
|
7a688495f2 | ||
|
|
b9cf7084eb | ||
|
|
b99161f0cb | ||
|
|
6faa4862de | ||
|
|
eff3f1dfd8 | ||
|
|
73aa77d7da | ||
|
|
5580ab385f | ||
|
|
40eb0e97ec | ||
|
|
b7e1ce0205 | ||
|
|
bfde9bf8c7 | ||
|
|
54f9b28086 | ||
|
|
03a5eb7f9b | ||
|
|
43e60e6544 | ||
|
|
ebd16666e6 | ||
|
|
f2129082a9 | ||
|
|
74226aa6fc | ||
|
|
b6ed5b792b | ||
|
|
39e45c30ba | ||
|
|
ed734ebb08 |
@@ -34,7 +34,7 @@
|
||||
color: #063b9a;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
letter-spacing: .5px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-left: 10px;
|
||||
font-size: 13px;
|
||||
margin-left: 5px;
|
||||
@@ -109,7 +109,7 @@
|
||||
}
|
||||
|
||||
.external {
|
||||
font-size: .7em;
|
||||
font-size: 0.7em;
|
||||
text-decoration: none;
|
||||
color: #063b9a;
|
||||
cursor: pointer;
|
||||
@@ -119,7 +119,7 @@
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
opacity: .9;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
> i {
|
||||
@@ -139,3 +139,25 @@
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.bodyHistoryToggle {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
line-height: 1px;
|
||||
font-weight: 300;
|
||||
text-decoration: underline;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.editedCommentBody {
|
||||
padding: 0 5px 5px 5px;
|
||||
}
|
||||
|
||||
.editedComment {
|
||||
margin-top: 6px;
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ import TimeAgo from 'coral-framework/components/TimeAgo';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
class UserDetailComment extends React.Component {
|
||||
state = { showingEditHistory: false };
|
||||
|
||||
approve = () =>
|
||||
this.props.comment.status === 'ACCEPTED'
|
||||
? null
|
||||
@@ -29,6 +31,29 @@ class UserDetailComment extends React.Component {
|
||||
? null
|
||||
: this.props.rejectComment({ commentId: this.props.comment.id });
|
||||
|
||||
getBodyHistory = () => {
|
||||
const bodyHistory = [];
|
||||
const comment = this.props.comment;
|
||||
for (let i = 0; i < comment.body_history.length - 1; i++) {
|
||||
bodyHistory.push(
|
||||
<div key={i} className={styles.editedComment}>
|
||||
<div>
|
||||
<TimeAgo className={styles.created} datetime={comment.created_at} />
|
||||
</div>
|
||||
<div className={styles.editedCommentBody}>
|
||||
{comment.body_history[i].body}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return bodyHistory;
|
||||
};
|
||||
|
||||
toggleEditHistory = () => {
|
||||
this.setState({ showingEditHistory: !this.state.showingEditHistory });
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
comment,
|
||||
@@ -81,6 +106,14 @@ class UserDetailComment extends React.Component {
|
||||
<span className={styles.editedMarker}>
|
||||
({t('comment.edited')})
|
||||
</span>
|
||||
<span
|
||||
className={styles.bodyHistoryToggle}
|
||||
onClick={this.toggleEditHistory}
|
||||
>
|
||||
{this.state.showingEditHistory
|
||||
? t('comment.hide_edit_history')
|
||||
: t('comment.show_edit_history')}
|
||||
</span>
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
@@ -142,6 +175,14 @@ class UserDetailComment extends React.Component {
|
||||
</div>
|
||||
</CommentAnimatedEdit>
|
||||
</div>
|
||||
|
||||
{this.state.showingEditHistory ? (
|
||||
<div className={styles.container}>
|
||||
{t('comment.edit_history')}
|
||||
{this.getBodyHistory()}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<CommentDetails root={root} comment={comment} />
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -42,6 +42,10 @@ export default withFragments({
|
||||
status_history {
|
||||
type
|
||||
}
|
||||
body_history {
|
||||
body
|
||||
created_at
|
||||
}
|
||||
${getSlotFragmentSpreads(slots, 'comment')}
|
||||
...${getDefinitionName(CommentLabels.fragments.comment)}
|
||||
...${getDefinitionName(CommentDetails.fragments.comment)}
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
font-weight: 300;
|
||||
margin-bottom: 8px;
|
||||
overflow-wrap: break-word;
|
||||
word-break:break-word;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.body {
|
||||
@@ -103,7 +103,7 @@
|
||||
color: #063b9a;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
letter-spacing: .5px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-left: 10px;
|
||||
font-size: 13px;
|
||||
margin-left: 5px;
|
||||
@@ -111,14 +111,14 @@
|
||||
border-bottom: solid 1px;
|
||||
line-height: 16px;
|
||||
&:hover {
|
||||
opacity: .9;
|
||||
opacity: 0.9;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.username {
|
||||
color: #393B44;
|
||||
color: #393b44;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
@@ -127,12 +127,12 @@
|
||||
margin-left: -5px;
|
||||
transition: background-color 200ms ease;
|
||||
&:hover {
|
||||
background-color: #E0E0E0;
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
}
|
||||
|
||||
.external {
|
||||
font-size: .7em;
|
||||
font-size: 0.7em;
|
||||
text-decoration: none;
|
||||
color: #063b9a;
|
||||
cursor: pointer;
|
||||
@@ -140,7 +140,7 @@
|
||||
white-space: nowrap;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
opacity: .9;
|
||||
opacity: 0.9;
|
||||
}
|
||||
i {
|
||||
font-size: 12px;
|
||||
@@ -196,3 +196,25 @@
|
||||
.commentContentFooter {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.bodyHistoryToggle {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
line-height: 1px;
|
||||
font-weight: 300;
|
||||
text-decoration: underline;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.editedCommentBody {
|
||||
padding: 0 5px 5px 5px;
|
||||
}
|
||||
|
||||
.editedComment {
|
||||
margin-top: 6px;
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import t from 'coral-framework/services/i18n';
|
||||
class Comment extends React.Component {
|
||||
ref = null;
|
||||
|
||||
state = { showingEditHistory: false };
|
||||
|
||||
handleRef = ref => (this.ref = ref);
|
||||
|
||||
handleFocusOrClick = () => {
|
||||
@@ -45,6 +47,30 @@ class Comment extends React.Component {
|
||||
? null
|
||||
: this.props.rejectComment({ commentId: this.props.comment.id });
|
||||
|
||||
getBodyHistory = () => {
|
||||
const bodyHistory = [];
|
||||
const comment = this.props.comment;
|
||||
for (let i = 0; i < comment.body_history.length - 1; i++) {
|
||||
bodyHistory.push(
|
||||
<div key={i} className={styles.editedComment}>
|
||||
<div>
|
||||
<TimeAgo className={styles.created} datetime={comment.created_at} />
|
||||
</div>
|
||||
<div className={styles.editedCommentBody}>
|
||||
{comment.body_history[i].body}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return bodyHistory;
|
||||
};
|
||||
|
||||
toggleEditHistory = () => {
|
||||
this.setState({ showingEditHistory: !this.state.showingEditHistory });
|
||||
this.props.clearHeightCache && this.props.clearHeightCache();
|
||||
};
|
||||
|
||||
componentDidUpdate(prev) {
|
||||
if (!prev.selected && this.props.selected) {
|
||||
this.ref.focus();
|
||||
@@ -137,6 +163,14 @@ class Comment extends React.Component {
|
||||
<span className={styles.editedMarker}>
|
||||
({t('comment.edited')})
|
||||
</span>
|
||||
<span
|
||||
className={styles.bodyHistoryToggle}
|
||||
onClick={this.toggleEditHistory}
|
||||
>
|
||||
{this.state.showingEditHistory
|
||||
? t('comment.hide_edit_history')
|
||||
: t('comment.show_edit_history')}
|
||||
</span>
|
||||
</span>
|
||||
) : null}
|
||||
<div className={styles.adminCommentInfoBar}>
|
||||
@@ -201,6 +235,14 @@ class Comment extends React.Component {
|
||||
</div>
|
||||
</CommentAnimatedEdit>
|
||||
</div>
|
||||
|
||||
{this.state.showingEditHistory ? (
|
||||
<div className={styles.container}>
|
||||
{t('comment.edit_history')}
|
||||
{this.getBodyHistory()}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<CommentDetails
|
||||
root={root}
|
||||
comment={comment}
|
||||
|
||||
@@ -52,6 +52,10 @@ export default withFragments({
|
||||
status_history {
|
||||
type
|
||||
}
|
||||
body_history {
|
||||
body
|
||||
created_at
|
||||
}
|
||||
hasParent
|
||||
${getSlotFragmentSpreads(slots, 'comment')}
|
||||
...${getDefinitionName(CommentLabels.fragments.comment)}
|
||||
|
||||
@@ -3,6 +3,7 @@ import URLSearchParams from '@ungap/url-search-params';
|
||||
import pym from 'pym.js';
|
||||
import EventEmitter from 'eventemitter2';
|
||||
import { buildUrl } from 'coral-framework/utils/url';
|
||||
|
||||
import SnackBar from './SnackBar';
|
||||
import onIntersect from './onIntersect';
|
||||
import {
|
||||
@@ -92,6 +93,21 @@ function viewportDimensions() {
|
||||
};
|
||||
}
|
||||
|
||||
function parseAMPHash(opts) {
|
||||
const result = { ...opts };
|
||||
const query = window.location.hash.length && window.location.hash.substr(1);
|
||||
if (query) {
|
||||
const parsed = queryString.parse(query);
|
||||
if (parsed.asset_url && !result.asset_url) {
|
||||
result.asset_url = parsed.asset_url;
|
||||
}
|
||||
if (parsed.asset_id && !result.asset_id) {
|
||||
result.asset_id = parsed.asset_id;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export default class Bridge {
|
||||
constructor(
|
||||
element,
|
||||
@@ -110,19 +126,23 @@ export default class Bridge {
|
||||
lazy = process.env.TALK_DEFAULT_LAZY_RENDER === 'TRUE',
|
||||
// Any additional options are extracted to be sent to the embed via the
|
||||
// pym bridge.
|
||||
amp,
|
||||
...opts
|
||||
}
|
||||
) {
|
||||
this.pym = null;
|
||||
this.element = element;
|
||||
this.opts = opts;
|
||||
this.amp = amp;
|
||||
this.lazy = !amp && lazy;
|
||||
|
||||
// Parse amp hash.
|
||||
this.opts = amp ? parseAMPHash(opts) : opts;
|
||||
this.query = buildQuery(this.opts);
|
||||
this.emitter = new EventEmitter({ wildcard: true });
|
||||
this.snackBar = new SnackBar(snackBarStyles || {});
|
||||
this.snackBar = amp ? null : new SnackBar(snackBarStyles || {});
|
||||
this.onAuthChanged = onAuthChanged;
|
||||
this.talkBaseUrl = ensureEndSlash(talkBaseUrl);
|
||||
this.talkStaticUrl = ensureEndSlash(talkStaticUrl);
|
||||
this.lazy = lazy;
|
||||
|
||||
// Store queued operations in a queue that can be processed once the stream
|
||||
// is rendered.
|
||||
@@ -179,6 +199,16 @@ export default class Bridge {
|
||||
if (height !== cachedHeight) {
|
||||
this.pym.el.firstChild.style.height = `${height}px`;
|
||||
cachedHeight = height;
|
||||
if (this.amp) {
|
||||
window.parent.postMessage(
|
||||
{
|
||||
sentinel: 'amp',
|
||||
type: 'embed-size',
|
||||
height,
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -267,8 +297,10 @@ export default class Bridge {
|
||||
// Setup Pym.
|
||||
this.setupPym();
|
||||
|
||||
// Attach the snackBar to the pym parent and to the body of the page.
|
||||
this.snackBar.attach(window.document.body, this.pym);
|
||||
if (this.snackBar) {
|
||||
// Attach the snackBar to the pym parent and to the body of the page.
|
||||
this.snackBar.attach(window.document.body, this.pym);
|
||||
}
|
||||
|
||||
// If the user clicks outside the embed, then tell the embed.
|
||||
document.addEventListener('click', this.handleClick.bind(this), true);
|
||||
@@ -315,7 +347,10 @@ export default class Bridge {
|
||||
this.emitter.removeAllListeners();
|
||||
|
||||
// Remove the snackbar.
|
||||
this.snackBar.remove();
|
||||
if (this.snackBar) {
|
||||
this.snackBar.remove();
|
||||
this.snackBar = null;
|
||||
}
|
||||
|
||||
// Remove the pym parent.
|
||||
this.pym.remove();
|
||||
|
||||
@@ -56,6 +56,7 @@ export const Talk = {
|
||||
* @param {String} [config.auth_token] - (optional) A jwt representing the session
|
||||
* @param {String} [config.lazy] - (optional) If set the stream will only render lazily
|
||||
* @param {String} [config.talkStaticUrl] - (optional) Static URL used to serve Talk
|
||||
* @param {Boolean} [config.amp] - (optional) Run Talk in AMP mode
|
||||
* @return {Object}
|
||||
*/
|
||||
render: (element, config) => {
|
||||
|
||||
@@ -120,6 +120,8 @@ sidebar:
|
||||
url: /integrating/translations-i18n/
|
||||
- title: GDPR Compliance
|
||||
url: /integrating/gdpr/
|
||||
- title: Accelerated Mobile Page
|
||||
url: /integrating/amp/
|
||||
- title: Product Guide
|
||||
children:
|
||||
- title: How Talk Works
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"hexo": {
|
||||
"version": "3.7.1"
|
||||
"version": "3.8.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "hexo serve",
|
||||
|
||||
@@ -77,7 +77,8 @@ permalink: /pre-launch-checklist/
|
||||
- See [our blog for more information](https://coralproject.net/blog/slacking-on/)
|
||||
|
||||
|
||||
- [ ] Has your community team configured Talk to match your community strategy?
|
||||
- [ ] Have you configured Talk’s admin settings and determined your community strategy?
|
||||
- See [our tutorial for more information](https://docs.coralproject.net/talk/when-youve-installed-talk/)
|
||||
- See [Configuring Talk](/talk/configuring-talk/)
|
||||
|
||||
|
||||
|
||||
@@ -81,12 +81,17 @@ Usage: cli-assets [options] [command]
|
||||
Commands:
|
||||
|
||||
list [options] list all the assets in the database
|
||||
debug <url> prints the scraped metadata from that URL
|
||||
refresh [age] queues the assets that exceed the age requested
|
||||
update-url <assetID> <url> update the URL of an asset
|
||||
merge <srcID> <dstID> merges two assets together by moving comments from src to dst and deleting the src asset
|
||||
rewrite [options] <search> <replace> rewrites asset url's using the provided regex replacement pattern
|
||||
```
|
||||
|
||||
When using the `refresh` command, the `age` value specifies how far back in time to re-scrape assets; i.e. to re-scrape everything that was scraped in the last week use `1w` or `7d`. Supports ms (milliseconds), s (seconds), m (minutes), h (hours), d (days) and w (weeks). Assets that have not been scraped will also be queued for scraping.
|
||||
|
||||
See also, [Asset Scraping](/talk/integrating/asset-scraping/) for more details about asset scraping.
|
||||
|
||||
## Setting up the application
|
||||
You can also run a setup wizard to setup the wizard using `./bin/cli setup`. Below is a list of additional options available for this command:
|
||||
```
|
||||
|
||||
@@ -57,7 +57,7 @@ The timeframe in seconds in which commenters have to edit their comment.
|
||||
|
||||
#### Close Comments After
|
||||
|
||||
Default time after which all comment streams will close.
|
||||
Default time after which all comment streams will close. Applies to assets created in Talk after this configuration is saved, and does not update existing assets.
|
||||
|
||||
### Moderation Settings
|
||||
|
||||
|
||||
@@ -87,6 +87,8 @@ The most important predictors of the success of an online community are:
|
||||
|
||||
#### Effectively
|
||||
|
||||
* Keep conversations fresh and reduce moderation overhead by configuring Talk to automatically close commenting after a specified time window. Should comments be open for a day, a week, or a month? Set a manageable window and automatically close stories for commenting after that time period.
|
||||
|
||||
* If you're using the Toxic Comments plugin, make sure that its threshold is set at the level that catches most comments with fewest false positives (default is 80%). You can see the Likely to be Toxic level of every comment by clicking "More Details" on the comment card in the moderation view.
|
||||
|
||||
* Publicly discourage behavior in the comments that doesn't cross the line but suggests that the tone or focus could shift quickly in a direction you don't want. Point to relevant sections of your community guidelines. [Read more about defining and discouraging this kind of behavior here.](https://guides.coralproject.net/manage-a-successful-community/)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: Accelerated Mobile Page
|
||||
permalink: /integrating/amp/
|
||||
---
|
||||
|
||||
[AMP](https://amp.dev/) is a light-weight, stripped down HTML page that aims to improve reader experience. _Talk v4.9.0+_ comes with [AMP](https://amp.dev/) support. The current caveat however is that _toast notifications_ are not being rendered when viewing inside AMP.
|
||||
|
||||
# How to integrate
|
||||
Put the following code into your _AMP_ page and replace `$TALK_URL` and `$ASSET_URL` with the
|
||||
corresponding values. You can also pass `asset_id` instead of `asset_url`.
|
||||
|
||||
```html
|
||||
<amp-iframe
|
||||
width=600 height=140
|
||||
layout="responsive"
|
||||
sandbox="allow-scripts allow-same-origin allow-modals allow-popups allow-forms"
|
||||
resizable
|
||||
src="https://$TALK_URL/embed/amp#asset_url=$ASSET_URL">
|
||||
<div placeholder></div>
|
||||
<div overflow tabindex=0 role=button aria-label="Read more">Read more</div>
|
||||
</amp-iframe>
|
||||
```
|
||||
|
||||
## Single Sign-On
|
||||
For SSO integration you need to create a page with the following output and replace `$TALK_URL` and `$AUTH_TOKEN` with the appropriate values. Inject your SSO auth scripts to get the `$AUTH_TOKEN` for the current user. Integrating with [amp-access](https://amp.dev/documentation/components/amp-access) is recommended which opens a 1st-party popup to not have browsers block your cookies. This page is then used in `src` of `<amp-iframe>` above. It must be accessed over `https` and live in a different domain than the `amp` page.
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<title>Coral Talk Amp Embed</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id='coralStreamEmbed'></div>
|
||||
<script src="https://$TALK_URL/static/embed.js"></script>
|
||||
<script>
|
||||
window.TalkEmbed = Coral.Talk.render(document.getElementById('coralStreamEmbed'), {
|
||||
talk: '$TALK_URL',
|
||||
auth_token: '$AUTH_TOKEN',
|
||||
amp: true,
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -9,6 +9,9 @@ in a simple way. We use the following
|
||||
[meta tags](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta) on
|
||||
the target pages that allow us to extract some properties.
|
||||
|
||||
Asset scraping is performed by the `scraper` job which is enabled by default when you launch Talk. If your production site is behind a paywall or otherwise prevents scraping, you might need to confiugre a [TALK_SCRAPER_PROXY_URL](/talk/advanced-configuration/#talk-scraper-proxy-url) or custom [TALK_SCRAPER_HEADERS](/talk/advanced-configuration/#talk-scraper-headers).
|
||||
|
||||
|
||||
| Asset Property | Selector |
|
||||
|--------------------|----------|
|
||||
| `title` | See [`metascraper-title`](https://github.com/microlinkhq/metascraper/blob/dc664c37ea1b238b1e3e9d5342edfacc9027892c/packages/metascraper-title/index.js) |
|
||||
@@ -19,7 +22,7 @@ the target pages that allow us to extract some properties.
|
||||
| `modified_date` | `meta[property="article:modified"]` |
|
||||
| `section` | `meta[property="article:section"]` |
|
||||
|
||||
You can use the `./bin/cli assets debug <url>` to print the scraped metadata
|
||||
You can use the `./bin/cli assets debug <url>` command to print the scraped metadata
|
||||
from that URL. For example:
|
||||
|
||||
```bash
|
||||
@@ -41,4 +44,8 @@ from that URL. For example:
|
||||
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ section │ │
|
||||
└──────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
|
||||
You can use the `./bin/cli assets refresh [age]` to trigger scraping or rescrape assets where the scraper job was unsuccessful.
|
||||
+6
-1
@@ -111,7 +111,12 @@ const processJob = transport => async ({ id, data }, done) => {
|
||||
const { message } = data;
|
||||
|
||||
// Get the email address from the job data.
|
||||
message.to = await getEmailAddress(data);
|
||||
try {
|
||||
message.to = await getEmailAddress(data);
|
||||
} catch (err) {
|
||||
logger.error({ err }, 'Failed to get user email address to send mail');
|
||||
return done(err);
|
||||
}
|
||||
|
||||
const log = logger.child({ jobID: id });
|
||||
log.info('Starting to send mail');
|
||||
|
||||
+77
-2
@@ -3,6 +3,13 @@ de:
|
||||
sort_comments: 'Kommentare sortieren'
|
||||
view_options: Ansichtsoptionen
|
||||
already_flagged_username: 'Sie haben diesen Nutzernamen schon markiert.'
|
||||
alwayspremoddialog:
|
||||
are_you_sure: 'Sind sie sicher, dass sie immer vormoderieren wollen für {0}?'
|
||||
always_premod_user: 'Nutzer immer vormoderieren?'
|
||||
cancel: Abbrechen
|
||||
note: 'Hinweis: {0}'
|
||||
note_always_premod_user: 'Kommentare dieses Nutzers werden niemals automatisch freigegeben sondern erscheinen immer in der Liste für Vormoderation.'
|
||||
yes_always_premod_user: 'Nutzer vormoderieren'
|
||||
bandialog:
|
||||
are_you_sure: 'Sind Sie sich sicher, dass Sie {0} sperren möchten?'
|
||||
ban_user: 'Nutzer sperren?'
|
||||
@@ -28,6 +35,9 @@ de:
|
||||
flagged: markiert
|
||||
undo_reject: 'Rückgängig machen'
|
||||
view_context: 'Kontext ansehen'
|
||||
edit_history: 'Verlauf anpassen'
|
||||
show_edit_history: 'Zeige Verlaufshistorie'
|
||||
hide_edit_history: 'Verstecke Verlaufshistorie'
|
||||
comment_box:
|
||||
cancel: Abbrechen
|
||||
characters_remaining: 'verbleibende Zeichen'
|
||||
@@ -48,9 +58,10 @@ 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'
|
||||
contains_link: 'Enthält einen Link'
|
||||
copy: Kopieren
|
||||
copied: 'Kopiert'
|
||||
notsupported: 'Nicht unterstützt'
|
||||
error: 'Ein Problem ist aufgetreten.'
|
||||
reaction: 'Reaktion'
|
||||
reactions: 'Reaktionen'
|
||||
@@ -62,6 +73,8 @@ de:
|
||||
active: Aktiv
|
||||
admin: Administrator
|
||||
ads_marketing: 'Dies scheint Werbung zu sein'
|
||||
all: 'Alle'
|
||||
always_premod: 'Vormoderiert'
|
||||
are_you_sure: 'Sind Sie sich sicher, dass Sie {0} sperren möchten?'
|
||||
ban_user: 'Nutzer sperren?'
|
||||
banned: Gesperrt
|
||||
@@ -69,6 +82,8 @@ de:
|
||||
cancel: Abbrechen
|
||||
commenter: Kommentator
|
||||
dont_like_username: 'Unsympathischer Nutzername'
|
||||
filter_users: 'Nutzer filtern'
|
||||
filter_role: Rolle
|
||||
flaggedaccounts: 'Gemeldete Nutzernamen'
|
||||
flags: Markierungen
|
||||
impersonating: 'Identität unklar'
|
||||
@@ -85,6 +100,7 @@ de:
|
||||
spam_ads: Spam/Werbung
|
||||
staff: Mitarbeiter
|
||||
status: Status
|
||||
suspended: 'Vorübergehend gesperrt'
|
||||
username_and_email: 'Nutzername und E-Mail'
|
||||
yes_ban_user: 'Ja, Nutzer sperren'
|
||||
configure:
|
||||
@@ -111,6 +127,8 @@ de:
|
||||
copy_and_paste: 'Kopieren Sie diesen Code in Ihr CMS, um die Kommentarfunktion an entsprechender Stelle anzuzeigen.'
|
||||
custom_css_url: 'Benutzerdefinierte CSS-URL'
|
||||
custom_css_url_desc: 'URL eines CSS-Stylesheets zum Überschreiben des Standard-Designs'
|
||||
custom_admin_css_url: 'Benutzerdefinierte CSS URL für Admin Panel'
|
||||
custom_admin_css_url_desc: 'URL eines CSS-Stylesheets zum Überschreiben des Standart-Designs für das Admin Panel.'
|
||||
days: Tage
|
||||
description: 'Ändern Sie die Einstellungen für den Kommentarbereich dieses Artikels.'
|
||||
disable_commenting_desc: 'Verfassen Sie eine Nachricht, die angezeigt wird, solange das Kommentieren deaktiviert ist.'
|
||||
@@ -147,6 +165,9 @@ de:
|
||||
organization_info_copy_2: 'Wir empfehlen, einee generische E-Mail-Adresse (z.B. community@yournewsroom.com) für diesen Zweck einzurichten. Die kann über die Zeit gleich bleiben, und gibt nach außen keine Namen preis, die von Nutzern im Fall von Konflikten für persönliche Angriffe missbraucht werden könnten.'
|
||||
organization_information: 'Über die Organisation'
|
||||
organization_name: 'Name der Organisation'
|
||||
suspect_or_forbidden_words_placeholder: 'Wort oder Phrase'
|
||||
product_guide_link: 'Produkt Guide'
|
||||
report_bug_or_feedback: 'Feedback'
|
||||
require_email_verification: 'E-Mail-Bestätigung erforderlich'
|
||||
require_email_verification_text: 'Neue Nutzer müssen ihre E-Mail-Adresse bestätigen.'
|
||||
save: Speichern
|
||||
@@ -165,6 +186,7 @@ de:
|
||||
suspect_word_title: 'Liste verdächtiger Wörter'
|
||||
tech_settings: 'Technische Einstellungen'
|
||||
title: 'Kommentarbereich konfigurieren'
|
||||
view_last_version: 'Letzte Version'
|
||||
weeks: Wochen
|
||||
wordlist: 'Gesperrte Wörter'
|
||||
confirm_email:
|
||||
@@ -222,6 +244,7 @@ de:
|
||||
copied: 'Kopiert'
|
||||
error:
|
||||
ALREADY_EXISTS: 'Ressource existiert bereits'
|
||||
AUTHENTICATION: 'Bei der Anmeldung ist ein Fehler aufgetreten.'
|
||||
CANNOT_IGNORE_STAFF: 'Mitarbeiter können nicht ignoriert werden.'
|
||||
COMMENT_PARENT_NOT_VISIBLE: 'Der Kommentar, auf den Sie antworten möchten, wurde entfernt oder existiert nicht.'
|
||||
COMMENT_TOO_SHORT: 'Kommentare sollten mehr als ein Zeichen enthalten, bitte überprüfen Sie Ihren Kommentar und probieren Sie es erneut.'
|
||||
@@ -250,6 +273,7 @@ de:
|
||||
organization_contact_email: 'E-Mail-Adresse der Organisation ist ungültig.'
|
||||
organization_name: 'Namen von Organisationen dürfen nur Buchstaben und Zahlen enthalten.'
|
||||
password: 'Passwort muss mindestens 8 Zeichen enthalten'
|
||||
PAGE_NOT_AVAILABLE_ROLE: 'Der Zugriff auf diese Seite ist eingeschränkt. Bitte wenden Sie sich an den Administrator.'
|
||||
PASSWORD_INCORRECT: 'Ihr bestehendes Passwort wurde falsch eingegeben'
|
||||
PASSWORD_LENGTH: 'Passwort ist zu kurz'
|
||||
PASSWORD_REQUIRED: 'Passwort ist erforderlich'
|
||||
@@ -265,6 +289,13 @@ de:
|
||||
USERNAME_REQUIRED: 'Nutzername muss angegeben werden'
|
||||
flag_comment: 'Kommentar melden'
|
||||
flag_reason: 'Grund der Meldung (optional)'
|
||||
flag_reasons:
|
||||
username:
|
||||
impersonating: 'Gibt sich für jemand anderen aus'
|
||||
nolike: 'Ich mag diesen Nutzernamen nicht'
|
||||
offensive: 'Dieser Nutzername ist unangemessen'
|
||||
other: Sonstiges
|
||||
spam: 'Dies scheint Werbung zu sein'
|
||||
flag_username: 'Nutzername melden'
|
||||
flagged_usernames:
|
||||
notify_approved: '{0} hat Nutzername {1} freigegeben'
|
||||
@@ -281,6 +312,7 @@ de:
|
||||
comment_spam: Spam
|
||||
links: Link
|
||||
suspect_word: 'Verdächtiges Wort'
|
||||
trust: Karma
|
||||
user:
|
||||
username_impersonating: 'Identität unklar'
|
||||
username_nolike: Unerwünscht
|
||||
@@ -300,6 +332,7 @@ de:
|
||||
comments: Kommentare
|
||||
configure_stream: Konfigurieren
|
||||
content_not_available: 'Dieser Inhalt ist nicht verfügbar'
|
||||
edit: Ändern
|
||||
edit_name:
|
||||
button: Senden
|
||||
error: 'Nutzernamen dürfen nur Buchstaben, Zahlen und _ enthalten'
|
||||
@@ -343,16 +376,30 @@ de:
|
||||
title: 'Zugelassene Domains'
|
||||
like: 'Gefällt mir'
|
||||
loading_results: 'Lädt Ergebnisse'
|
||||
login:
|
||||
email_address: 'E-Mail-Adresse'
|
||||
forgot_password: 'Passwort vergessen?'
|
||||
go_back: 'Zurück'
|
||||
sign_in: 'Anmelden'
|
||||
sign_in_button: 'Anmelden'
|
||||
sign_in_message: 'Anmelden um mit der Community zu interagieren.'
|
||||
password: Passwort
|
||||
reset_password_send_button: 'Passwort erhalten'
|
||||
request_passowrd: 'Neues anfordern.'
|
||||
team_sign_in: 'Team Anmeldung'
|
||||
marketing: 'Dies scheint Werbung zu sein'
|
||||
moderate_all_streams: 'Moderate comments on All Stories'
|
||||
moderate_this_stream: 'Diesen Kommentarbereich moderieren'
|
||||
modqueue:
|
||||
account: Konto-Markierungen
|
||||
actions: Aktionen
|
||||
all: Alle
|
||||
all_streams: 'Alle Kommentarbereiche'
|
||||
always_premod_user_actions: 'Nutzer immer vormoderieren'
|
||||
approve: Freigeben
|
||||
approved: Freigegeben
|
||||
ban_user: Sperren
|
||||
ban_user_actions: 'Nutzer sperren'
|
||||
billion: Mrd
|
||||
close: Schließen
|
||||
empty_queue: 'Keine weiteren Kommentare zu moderieren! Arbeite nicht zu viel, gönn’ dir eine Pause!'
|
||||
@@ -387,6 +434,7 @@ de:
|
||||
show_shortcuts: 'Tastaturkürzel anzeigen'
|
||||
singleview: Zen-Modus
|
||||
sort: Sortieren
|
||||
suspend: 'Nutzer vorübergehend sperren'
|
||||
system_withheld: 'System Withheld'
|
||||
thismenu: 'Dieses Menü öffnen'
|
||||
thousand: T
|
||||
@@ -424,6 +472,13 @@ de:
|
||||
username: Nutzername
|
||||
write_message: 'Nachricht schreiben'
|
||||
yes_suspend: 'Ja, vorübergehend sperren'
|
||||
reject_username_dialog:
|
||||
cancel: Abbrechen
|
||||
description: 'Sagen Sie uns warun der Name nicht Ok ist?'
|
||||
message: 'Grund für die Meldung (optional)'
|
||||
reason: Begründung
|
||||
reject_username: 'Nutzernamen ablehnen'
|
||||
title: 'Nutzernamen ablehnen'
|
||||
reply: Antworten
|
||||
report: Melden
|
||||
report_notif: 'Vielen Dank für Ihre Meldung. Unsere Moderatoren wurden informiert und werden sich in Kürze darum kümmern.'
|
||||
@@ -452,11 +507,14 @@ de:
|
||||
closed: Geschlossen
|
||||
empty_result: 'Ihre Suche war ohne Ergebnisse. Versuchen Sie, Ihre Anfrage weiter zu fassen.'
|
||||
filter_streams: 'Kommentarbereiche filtern'
|
||||
most_recent_stories: 'Neueste Artikel'
|
||||
newest: Neueste
|
||||
no_results: 'Keine Ergebnisse'
|
||||
oldest: Älteste
|
||||
open: Offen
|
||||
pubdate: Veröffentlichungsdatum
|
||||
search: Suchen
|
||||
search_results: Suchergebnisse
|
||||
sort_by: 'Sortieren nach'
|
||||
status: Status
|
||||
stream_status: Status
|
||||
@@ -484,24 +542,41 @@ de:
|
||||
username_flags: 'Markierungen für diesen Nutzernamen'
|
||||
user_detail:
|
||||
all: Alle
|
||||
always_premod: 'Nutzer immer vormoderieren'
|
||||
always_premoded: 'Vormoderiert'
|
||||
ban: 'Nutzer sperren'
|
||||
banned: Gesperrt
|
||||
email: E-Mail
|
||||
id: ID
|
||||
karma: Karma
|
||||
karma_docs_link: 'https://docs.coralproject.net/talk/trust/#user-karma-score'
|
||||
learn_more: 'Mehr erfahren'
|
||||
member_since: 'Mitglied seit'
|
||||
reject_rate: Ablehn-Rate
|
||||
reject_username: 'Nutzernamen ablehnen'
|
||||
rejected: Abgelehnte
|
||||
remove_always_premod: 'Vormoderation entfernen'
|
||||
remove_ban: 'Sperre aufheben'
|
||||
remove_suspension: 'Vorübergehende Sperrung aufheben'
|
||||
suspend: 'Nutzer vorübergehend sperren'
|
||||
suspended: 'Vorübergehend gesperrt'
|
||||
total_comments: 'Anzahl Kommentare'
|
||||
unreliable: Unzuverlässig
|
||||
user_history: Konto-Verlauf
|
||||
user_karma_score: 'Nutzer Karma Wert'
|
||||
username: Username
|
||||
username_needs_approval: 'Nutzername muss akzetiert werden'
|
||||
username_rejected: 'Nutzername abgelehnt'
|
||||
user_history:
|
||||
action: Aktion
|
||||
always_premod_removed: 'Vormoderation entfernen'
|
||||
ban_removed: 'Sperrung aufgehoben'
|
||||
date: Datum
|
||||
suspended: 'Vorübergehend gesperrt, {0}'
|
||||
suspension_removed: 'Vorübergehende Sperrung aufgehoben'
|
||||
system: System
|
||||
taken_by: Durch
|
||||
user_always_premoded: 'Nutzer vormoderiert'
|
||||
user_banned: 'Nutzer gesperrt'
|
||||
username_status: 'Nutzername {0}'
|
||||
user_impersonating: 'Gibt sich für jemand anderen aus'
|
||||
|
||||
@@ -35,6 +35,9 @@ en:
|
||||
flagged: flagged
|
||||
undo_reject: Undo
|
||||
view_context: 'View context'
|
||||
edit_history: 'Edit history'
|
||||
show_edit_history: 'Show edit history'
|
||||
hide_edit_history: 'Hide edit history'
|
||||
comment_box:
|
||||
cancel: Cancel
|
||||
characters_remaining: 'characters remaining'
|
||||
|
||||
@@ -35,6 +35,9 @@ es:
|
||||
flagged: Reportado
|
||||
undo_reject: Deshacer
|
||||
view_context: 'Ver contexto'
|
||||
edit_history: 'Historial de ediciones'
|
||||
show_edit_history: 'Mostrar historial de ediciones'
|
||||
hide_edit_history: 'Ocultar historial de ediciones'
|
||||
comment_box:
|
||||
cancel: Cancelar
|
||||
characters_remaining: 'caracteres restantes'
|
||||
|
||||
@@ -12,6 +12,8 @@ const {
|
||||
STATIC_ORIGIN,
|
||||
} = require('../url');
|
||||
|
||||
const { PORT } = require('../config');
|
||||
|
||||
const { RECAPTCHA_PUBLIC, WEBSOCKET_LIVE_URI } = require('../config');
|
||||
|
||||
// Grab TALK_CLIENT_* environment variables.
|
||||
@@ -42,6 +44,7 @@ const TEMPLATE_LOCALS = {
|
||||
MOUNT_PATH,
|
||||
STATIC_URL,
|
||||
TALK_CLIENT_ENV,
|
||||
PORT,
|
||||
data: TALK_CLIENT_ENV,
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "talk",
|
||||
"version": "4.8.7",
|
||||
"version": "4.9.1",
|
||||
"description": "A better commenting experience from Mozilla, The New York Times, and the Washington Post. https://coralproject.net",
|
||||
"main": "app.js",
|
||||
"private": true,
|
||||
|
||||
@@ -11,23 +11,42 @@ plugin:
|
||||
- Client
|
||||
---
|
||||
|
||||
Enables sign-in via Facebook via the server side passport middleware.
|
||||
Enables sign-in via Facebook via the server side passport middleware. Requires creating and registering a login app with Facebook.
|
||||
|
||||
Configuration:
|
||||
**Configuration:**
|
||||
|
||||
- `TALK_FACEBOOK_APP_ID` (**required**) - The Facebook App ID for your Facebook
|
||||
Login enabled app. You can learn more about getting a Facebook App ID at the
|
||||
[Facebook Developers Portal](https://developers.facebook.com) or by visiting
|
||||
the [Creating an App ID](https://developers.facebook.com/docs/apps/register)
|
||||
guide. This is only required while the `talk-plugin-facebook-auth` plugin is
|
||||
Login enabled app. This is only required while the `talk-plugin-facebook-auth` plugin is
|
||||
enabled.
|
||||
- `TALK_FACEBOOK_APP_SECRET` (**required**) - The Facebook App Secret for your
|
||||
Facebook Login enabled app. You can learn more about getting a Facebook App
|
||||
Secret at the [Facebook Developers Portal](https://developers.facebook.com)
|
||||
or by visiting the
|
||||
[Creating an App ID](https://developers.facebook.com/docs/apps/register)
|
||||
guide. This is only required while the `talk-plugin-facebook-auth` plugin is
|
||||
Facebook Login enabled app. This is only required while the `talk-plugin-facebook-auth` plugin is
|
||||
enabled.
|
||||
|
||||
You can learn more about getting a Facebook App ID at the
|
||||
[Facebook Developers Portal](https://developers.facebook.com) or by visiting
|
||||
their [Creating an App ID](https://developers.facebook.com/docs/apps/register)
|
||||
guide.
|
||||
|
||||
**Setting up your Facebook app:**
|
||||
* Go to [Facebook Developers Portal](https://developers.facebook.com) and click on Getting Started or My Apps
|
||||
* Create a new app > set the App Name and Email to create an app id
|
||||
* Confirm that you are not a robot, then configure the app as follows:
|
||||
* In Settings > Basic:
|
||||
* add app domains (your Talk domain)
|
||||
* add a link to your privacy policy
|
||||
* add a link to your terms of service
|
||||
* In Settings > Advanced:
|
||||
* turn on "Require App Secret"
|
||||
* Add a "Product" (Under "Products" click + to add a Product):
|
||||
* Setup "Facebook Login"
|
||||
* choose `www`
|
||||
* enter your Talk domain url
|
||||
* click _Next_ several times to get through the add code steps (You do not need to modify any code, the plugin takes care of this part for you.)
|
||||
* Under Product Settings:
|
||||
* set Valid OAuth Redirect URIs to your callback url (Use your Talk domain with this endpoint: `/api/v1/auth/facebook/callback`)
|
||||
* Locate your App Id and App Secret, set these as config vars on your instance of Talk
|
||||
* Toggle the "Live" button on the top bar to make app live
|
||||
|
||||
|
||||
_NOTE: Facebook auth requires your site to use `https` (SSL) not `http`. If your site is not `https` you can not use this plugin!_
|
||||
|
||||
|
||||
@@ -38,13 +38,15 @@
|
||||
color: #484747;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding: 0 16px 0 0;
|
||||
font-size: 1.02em;
|
||||
margin-left: 6px;
|
||||
letter-spacing: 0.2px;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 2px;
|
||||
line-height: 22px;
|
||||
box-sizing: border-box;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.icon {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
.dialog {
|
||||
border: none;
|
||||
box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14), 0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2);
|
||||
width: 400px;
|
||||
top: 10px;
|
||||
}
|
||||
@@ -17,6 +17,8 @@ import {
|
||||
EmailAddressAdded,
|
||||
} from '../components/AddEmailAddress';
|
||||
|
||||
import styles from './AddEmailAddressDialog.css';
|
||||
|
||||
class AddEmailAddressDialog extends React.Component {
|
||||
state = {
|
||||
step: 0,
|
||||
@@ -72,7 +74,11 @@ class AddEmailAddressDialog extends React.Component {
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Dialog open={true} id="talk-plugin-local-auth-email-dialog">
|
||||
<Dialog
|
||||
open={true}
|
||||
id="talk-plugin-local-auth-email-dialog"
|
||||
className={styles.dialog}
|
||||
>
|
||||
{step === 0 && <AddEmailForm onSubmit={this.handleSubmit} />}
|
||||
{step === 1 &&
|
||||
!requireEmailConfirmation && (
|
||||
|
||||
@@ -344,7 +344,7 @@ de:
|
||||
change_username_attempt: "Der Nutzername kann zur Zeit nicht aktualisiert werden. Änderungen sind nur nach jeweils 14 Tagen möglich."
|
||||
change_email:
|
||||
confirm_email_change: "Änderung der E-Mail-Adresse bestätigen"
|
||||
description: "Sie versuchen, Ihre E-Mail-Adresse ändern: die neue E-Mail-Adresse wird zum Login sowie für Benachrichtigungen bzgl. Ihres Benutzerkontos verwendet."
|
||||
description: "Sie versuchen Ihre E-Mail-Adresse zu ändern: die neue E-Mail-Adresse wird zum Login sowie für Benachrichtigungen bzgl. Ihres Benutzerkontos verwendet."
|
||||
old_email: "Alte E-Mail-Adresse"
|
||||
new_email: "Neue E-Mail-Adresse"
|
||||
enter_password: "Passwort"
|
||||
|
||||
@@ -41,7 +41,7 @@ type CancelAccountDeletionResponse implements Response {
|
||||
errors: [UserError!]
|
||||
}
|
||||
|
||||
# DownloadUserResponse contaisn the account download archiveURL that can be used
|
||||
# DownloadUserResponse contains the account download archiveURL that can be used
|
||||
# to directly download a zip file containing the user data.
|
||||
type DownloadUserResponse implements Response {
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ ar:
|
||||
label: الأكثر ردودً أولاً
|
||||
da:
|
||||
talk-plugin-sort-most-replied:
|
||||
label: Most replied first
|
||||
label: Most replied first
|
||||
de:
|
||||
talk-plugin-sort-most-replied:
|
||||
label: Häufigste Antworten zuerst
|
||||
@@ -15,7 +15,7 @@ es:
|
||||
label: Más respondidas primero
|
||||
fr:
|
||||
talk-plugin-sort-most-replied:
|
||||
label: Most replied first
|
||||
label: Les plus répondus en premier
|
||||
he:
|
||||
talk-plugin-sort-most-replied:
|
||||
label: הכי השיב קודם
|
||||
@@ -30,7 +30,7 @@ pt_BR:
|
||||
label: Mais respondidos primeiro
|
||||
sr:
|
||||
talk-plugin-sort-most-replied:
|
||||
label: Prvo sa najviše odgovora
|
||||
label: Prvo sa najviše odgovora
|
||||
zh_CN:
|
||||
talk-plugin-sort-most-replied:
|
||||
label: "最多回复在前"
|
||||
|
||||
@@ -15,7 +15,7 @@ es:
|
||||
label: Más respetadas primero
|
||||
fr:
|
||||
talk-plugin-sort-most-respected:
|
||||
label: Most respected first
|
||||
label: Les plus respectés en premier
|
||||
he:
|
||||
talk-plugin-sort-most-respected:
|
||||
label: הכי מכובד קודם
|
||||
|
||||
@@ -3,7 +3,7 @@ ar:
|
||||
label: الأحدث أولاً
|
||||
da:
|
||||
talk-plugin-sort-newest:
|
||||
label: Newest first
|
||||
label: Newest first
|
||||
de:
|
||||
talk-plugin-sort-newest:
|
||||
label: Neueste zuerst
|
||||
@@ -15,7 +15,7 @@ es:
|
||||
label: Más nuevas primero
|
||||
fr:
|
||||
talk-plugin-sort-newest:
|
||||
label: Newest first
|
||||
label: Les plus récents en premier
|
||||
he:
|
||||
talk-plugin-sort-newest:
|
||||
label: מהראשונה לאחרונה
|
||||
|
||||
@@ -3,7 +3,7 @@ ar:
|
||||
label: الأقدم أولاً
|
||||
da:
|
||||
talk-plugin-sort-oldest:
|
||||
label: Oldest first
|
||||
label: Oldest first
|
||||
de:
|
||||
talk-plugin-sort-oldest:
|
||||
label: Älteste zuerst
|
||||
@@ -15,7 +15,7 @@ es:
|
||||
label: Más viejas primero
|
||||
fr:
|
||||
talk-plugin-sort-oldest:
|
||||
label: Oldest first
|
||||
label: Les plus anciens en premier
|
||||
he:
|
||||
talk-plugin-sort-oldest:
|
||||
label: מהאחרונה לראשונה
|
||||
|
||||
@@ -7,7 +7,7 @@ da:
|
||||
talk-plugin-viewing-options:
|
||||
viewing_options: "Viewing Options"
|
||||
sort: Sorting
|
||||
filter: Filtering
|
||||
filter: Filtering
|
||||
de:
|
||||
talk-plugin-viewing-options:
|
||||
viewing_options: "Ansichtsoptionen"
|
||||
@@ -25,9 +25,9 @@ es:
|
||||
filter: Filtrado por
|
||||
fr:
|
||||
talk-plugin-viewing-options:
|
||||
viewing_options: "Viewing Options"
|
||||
sort: Sorting
|
||||
filter: Filtering
|
||||
viewing_options: "Options d'affichage"
|
||||
sort: Trier par
|
||||
filter: Filtrer par
|
||||
he:
|
||||
talk-plugin-viewing-options:
|
||||
viewing_options: "אפשרויות צפייה"
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
return res.render('dev/amp.njk', {
|
||||
title: 'Coral Talk AMP',
|
||||
asset_url: '',
|
||||
asset_id: '',
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/button', (req, res) => {
|
||||
return res.render('dev/amp-button.njk', {
|
||||
title: 'Coral Talk AMP',
|
||||
asset_url: '',
|
||||
asset_id: '',
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
@@ -19,5 +19,6 @@ router.get('/', staticTemplate, async (req, res) => {
|
||||
});
|
||||
}
|
||||
});
|
||||
router.use('/amp', staticTemplate, require('./amp'));
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -5,4 +5,8 @@ router.use('/stream', (req, res) => {
|
||||
res.render('embed/stream.njk');
|
||||
});
|
||||
|
||||
router.use('/amp', (req, res) => {
|
||||
res.render('embed/amp.njk');
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<!-- ## Introduction -->
|
||||
<!--
|
||||
This is a sample showing how to use Talk with AMP. You need to access
|
||||
this using an URL other than localhost. You can use ngrok to achieve that.
|
||||
-->
|
||||
<!-- -->
|
||||
<!doctype html>
|
||||
<html ⚡>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script async src="https://cdn.ampproject.org/v0.js"></script>
|
||||
<link rel="canonical" href="/dev">
|
||||
|
||||
<!-- ## Setup -->
|
||||
<script async custom-element="amp-iframe" src="https://cdn.ampproject.org/v0/amp-iframe-0.1.js"></script>
|
||||
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
|
||||
|
||||
<title>Coral Talk AMP</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
|
||||
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
|
||||
|
||||
<style amp-custom>
|
||||
.container {
|
||||
width: auto;
|
||||
max-width: 680px;
|
||||
padding: 0 15px;
|
||||
margin: auto;
|
||||
}
|
||||
.title {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: .5rem;
|
||||
font-size: 2.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
|
||||
}
|
||||
.hide{
|
||||
display:none
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 class="title">Coral Talk AMP</h1>
|
||||
<p>
|
||||
Ask to go outside and ask to come inside and ask to go outside and ask to
|
||||
come inside the dog smells bad. Lick butt and make a weird face. Toilet
|
||||
paper attack claws fluff everywhere meow miao french ciao litterbox. Shake
|
||||
treat bag immediately regret falling into bathtub or white cat sleeps on a
|
||||
black shirt so what a cat-ass-trophy! eat owner's food spit up on light
|
||||
gray carpet instead of adjacent linoleum. Warm up laptop with butt lick
|
||||
butt fart rainbows until owner yells pee in litter box hiss at cats
|
||||
scratch the box so loved it, hated it, loved it, hated it but need to
|
||||
check on human, have not seen in an hour might be dead oh look, human is
|
||||
alive, hiss at human, feed me.
|
||||
</p>
|
||||
<button id=menu on="tap:AMP.setState({visible: !visible})">Show Comments</button>
|
||||
<div [class]=visible?"show":"hide" class="hide">
|
||||
<amp-iframe
|
||||
width=600 height=140
|
||||
layout="responsive"
|
||||
sandbox="allow-scripts allow-same-origin allow-modals allow-popups allow-forms"
|
||||
resizable
|
||||
src="http://localhost:3000/embed/amp">
|
||||
<div placeholder></div>
|
||||
<div overflow tabindex=0 role=button aria-label="Read more">Read more</div>
|
||||
</amp-iframe>
|
||||
</div<
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
<!-- ## Introduction -->
|
||||
<!--
|
||||
This is a sample showing how to use Talk with AMP. You need to access
|
||||
this using an URL other than localhost. You can use ngrok to achieve that.
|
||||
-->
|
||||
<!-- -->
|
||||
<!doctype html>
|
||||
<html ⚡>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script async src="https://cdn.ampproject.org/v0.js"></script>
|
||||
<link rel="canonical" href="/dev">
|
||||
|
||||
<!-- ## Setup -->
|
||||
<script async custom-element="amp-iframe" src="https://cdn.ampproject.org/v0/amp-iframe-0.1.js"></script>
|
||||
|
||||
<title>Coral Talk AMP</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
|
||||
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
|
||||
|
||||
<style amp-custom>
|
||||
.container {
|
||||
width: auto;
|
||||
max-width: 680px;
|
||||
padding: 0 15px;
|
||||
margin: auto;
|
||||
}
|
||||
.title {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: .5rem;
|
||||
font-size: 2.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 class="title">Coral Talk AMP</h1>
|
||||
<p>
|
||||
Dismember a mouse and then regurgitate parts of it on the family room
|
||||
floor. Dont wait for the storm to pass, dance in the rain stand in front
|
||||
of the computer screen, so stares at human while pushing stuff off a table
|
||||
chew the plant meow hiss at vacuum cleaner. Terrorize the
|
||||
hundred-and-twenty-pound rottweiler and steal his bed, not sorry chew the
|
||||
plant. Litter kitter kitty litty little kitten big roar roar feed me rub
|
||||
whiskers on bare skin act innocent sleep on keyboard, so give me attention
|
||||
or face the wrath of my claws for demand to be let outside at once, and
|
||||
expect owner to wait for me as i think about it spread kitty litter all
|
||||
over house so nya nya nyan. Catty ipsum massacre a bird in the living room
|
||||
and then look like the cutest and most innocent animal on the planet you
|
||||
have cat to be kitten me right meow. Hiss and stare at nothing then run
|
||||
suddenly away refuse to come home when humans are going to bed; stay out
|
||||
all night then yowl like i am dying at 4am and lick plastic bags. Chase
|
||||
dog then run away purrr purr littel cat, little cat purr purr and step on
|
||||
your keyboard while you're gaming and then turn in a circle . Twitch tail
|
||||
in permanent irritation put butt in owner's face and the dog smells bad
|
||||
yet attempt to leap between furniture but woefully miscalibrate and
|
||||
bellyflop onto the floor; what's your problem? i meant to do that now i
|
||||
shall wash myself intently. Sniff all the things groom forever, stretch
|
||||
tongue and leave it slightly out, blep, but bring your owner a dead bird
|
||||
decide to want nothing to do with my owner today for lay on arms while
|
||||
you're using the keyboard meow meow, i tell my human or scratch. Sleep on
|
||||
my human's head then cats take over the world bleghbleghvomit my furball
|
||||
really tie the room together sleep more napping, more napping all the
|
||||
napping is exhausting. When in doubt, wash drink water out of the faucet,
|
||||
cats are fats i like to pets them they like to meow back and cat dog hate
|
||||
mouse eat string barf pillow no baths hate everything yet swat at dog
|
||||
kitty kitty but you call this cat food. Cough furball into food bowl then
|
||||
scratch owner for a new one flex claws on the human's belly and purr like
|
||||
a lawnmower for has closed eyes but still sees you groom yourself 4 hours
|
||||
- checked, have your beauty sleep 18 hours - checked, be fabulous for the
|
||||
rest of the day - checked. Freak human out make funny noise mow mow mow
|
||||
mow mow mow success now attack human flex claws on the human's belly and
|
||||
purr like a lawnmower or meowwww. Terrorize the hundred-and-twenty-pound
|
||||
rottweiler and steal his bed, not sorry paw at your fat belly so yowling
|
||||
nonstop the whole night small kitty warm kitty little balls of fur or eat
|
||||
owner's food reward the chosen human with a slow blink. Gate keepers of
|
||||
hell plan steps for world domination for more napping, more napping all
|
||||
the napping is exhausting give me some of your food give me some of your
|
||||
food give me some of your food meh, i don't want it so flop over. Make
|
||||
meme, make cute face ears back wide eyed so sit and stare. Dead stare with
|
||||
ears cocked furrier and even more furrier hairball. Stand in front of the
|
||||
computer screen demand to have some of whatever the human is cooking, then
|
||||
sniff the offering and walk away for catasstrophe, kitty scratches couch
|
||||
bad kitty. Wack the mini furry mouse intrigued by the shower, and pooping
|
||||
rainbow while flying in a toasted bread costume in space. Mesmerizing
|
||||
birds love me! shake treat bag, yet lies down where is my slave? I'm
|
||||
getting hungry so lick face hiss at owner, pee a lot, and meow repeatedly
|
||||
scratch at fence purrrrrr eat muffins and poutine until owner comes back.
|
||||
You have cat to be kitten me right meow sniff other cat's butt and hang
|
||||
jaw half open thereafter but run outside as soon as door open so munch on
|
||||
tasty moths or munch on tasty moths, for paw at beetle and eat it before
|
||||
it gets away. Sit on human. Gnaw the corn cob massacre a bird in the
|
||||
living room and then look like the cutest and most innocent animal on the
|
||||
planet for sit on the laptop. Meow scratch leg; meow for can opener to
|
||||
feed me cat fur is the new black but hide when guests come over, and Gate
|
||||
keepers of hell. Refuse to come home when humans are going to bed; stay
|
||||
out all night then yowl like i am dying at 4am cat slap dog in face or eat
|
||||
a rug and furry furry hairs everywhere oh no human coming lie on counter
|
||||
don't get off counter for i like fish sit on human they not getting up
|
||||
ever but meow meow but cuddle no cuddle cuddle love scratch scratch.
|
||||
</p>
|
||||
<p>
|
||||
I show my fluffy belly but it's a trap! if you pet it i will tear up your
|
||||
hand refuse to drink water except out of someone's glass mice, so cough
|
||||
hairball, eat toilet paper or curl into a furry donut lick sellotape but
|
||||
wack the mini furry mouse. When owners are asleep, cry for no apparent
|
||||
reason. Chase imaginary bugs. Stinky cat reward the chosen human with a
|
||||
slow blink, or chase dog then run away. Chew on cable scratch the
|
||||
furniture for you are a captive audience while sitting on the toilet, pet
|
||||
me for i like cats because they are fat and fluffy and spend all night
|
||||
ensuring people don't sleep sleep all day. Scoot butt on the rug need to
|
||||
check on human, have not seen in an hour might be dead oh look, human is
|
||||
alive, hiss at human, feed me, leave fur on owners clothes, so instantly
|
||||
break out into full speed gallop across the house for no reason play
|
||||
riveting piece on synthesizer keyboard and scoot butt on the rug yet meow
|
||||
meow. Attack dog, run away and pretend to be victim annoy the old grumpy
|
||||
cat, start a fight and then retreat to wash when i lose or meow go back to
|
||||
sleep owner brings food and water tries to pet on head, so scratch get
|
||||
sprayed by water because bad cat. Meowwww pelt around the house and up and
|
||||
down stairs chasing phantoms drink water out of the faucet meow meow, i
|
||||
tell my human. Destroy couch.
|
||||
</p>
|
||||
<p>
|
||||
Ask to go outside and ask to come inside and ask to go outside and ask to
|
||||
come inside the dog smells bad. Lick butt and make a weird face. Toilet
|
||||
paper attack claws fluff everywhere meow miao french ciao litterbox. Shake
|
||||
treat bag immediately regret falling into bathtub or white cat sleeps on a
|
||||
black shirt so what a cat-ass-trophy! eat owner's food spit up on light
|
||||
gray carpet instead of adjacent linoleum. Warm up laptop with butt lick
|
||||
butt fart rainbows until owner yells pee in litter box hiss at cats
|
||||
scratch the box so loved it, hated it, loved it, hated it but need to
|
||||
check on human, have not seen in an hour might be dead oh look, human is
|
||||
alive, hiss at human, feed me.
|
||||
</p>
|
||||
<amp-iframe
|
||||
width=600 height=140
|
||||
layout="responsive"
|
||||
sandbox="allow-scripts allow-same-origin allow-modals allow-popups allow-forms"
|
||||
resizable
|
||||
src="http://localhost:{{ PORT }}/embed/amp">
|
||||
<div placeholder></div>
|
||||
<div overflow tabindex=0 role=button aria-label="Read more">Read more</div>
|
||||
</amp-iframe>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<title>Coral Talk Amp Embed</title>
|
||||
<style>body { margin: 0; }</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='coralStreamEmbed'></div>
|
||||
<script src="{{ resolve('embed.js') }}"></script>
|
||||
<script>
|
||||
window.TalkEmbed = Coral.Talk.render(document.getElementById('coralStreamEmbed'), {
|
||||
talk: '{{ BASE_URL }}',
|
||||
auth_token: '',
|
||||
amp: true,
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user