mirror of
https://github.com/wassname/talk.git
synced 2026-09-13 13:10:43 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22516457ef | ||
|
|
533d7633e1 | ||
|
|
e8fb234838 | ||
|
|
9b8ab6de5f | ||
|
|
a88644d98e | ||
|
|
745fb4056c | ||
|
|
a582773e1d | ||
|
|
6057edcb07 | ||
|
|
852466e9a1 | ||
|
|
f53db233ce | ||
|
|
31cf9a4f7d | ||
|
|
81338d1386 | ||
|
|
84bbc3d0c3 | ||
|
|
d26e331a4f | ||
|
|
e3e2e0f52e | ||
|
|
0dc3e8968a | ||
|
|
f900050ef4 | ||
|
|
0f456330c5 | ||
|
|
9d050e8b51 | ||
|
|
7581f0201d | ||
|
|
86b2ec1e56 | ||
|
|
fd1ee39db4 | ||
|
|
8c6f12c24d | ||
|
|
11a4a5ebe3 | ||
|
|
f3ecbf5dc6 | ||
|
|
116d3c0c81 | ||
|
|
3358cef433 | ||
|
|
ec93789cff | ||
|
|
f60fac651b | ||
|
|
514a549a77 | ||
|
|
88f6cad840 | ||
|
|
7615dc2aaf | ||
|
|
51bfde8cf8 | ||
|
|
5ebc39a2e1 | ||
|
|
d5020efa70 | ||
|
|
a396efef0d | ||
|
|
9618e5dab1 | ||
|
|
54296fa484 | ||
|
|
c109188efe | ||
|
|
08ead49629 | ||
|
|
bc27d7fbec | ||
|
|
4ee8cf7c96 | ||
|
|
0e15bc46d2 | ||
|
|
9bc41ad020 | ||
|
|
f1cdcb149b | ||
|
|
bf89fc2b3e | ||
|
|
7c2e56b751 | ||
|
|
4542dbdb43 | ||
|
|
787f1c68e7 | ||
|
|
09cf8c5490 | ||
|
|
ddedf4dc7e | ||
|
|
ca811a3496 | ||
|
|
10719bd874 | ||
|
|
bb23c80004 | ||
|
|
2491445579 | ||
|
|
3642c642d6 | ||
|
|
fce7b08ca0 | ||
|
|
aa9dcb4e04 | ||
|
|
9e9c016f4b | ||
|
|
40b247350b | ||
|
|
2945184b07 | ||
|
|
a55472e086 | ||
|
|
033433549a | ||
|
|
2ef07429c2 | ||
|
|
b83d737530 | ||
|
|
18346d1683 | ||
|
|
ce4a3408fc | ||
|
|
2dbba52fbd | ||
|
|
59b8dfccda | ||
|
|
3394628f27 | ||
|
|
8ee74b7d24 | ||
|
|
f85af8e88f | ||
|
|
9d6592feef | ||
|
|
53c87118db | ||
|
|
bdc9c5f05c | ||
|
|
e334c3266a | ||
|
|
a31ee3bc96 | ||
|
|
a7eb757be7 | ||
|
|
4038fcbcd6 | ||
|
|
5714f441bb | ||
|
|
ac96e5e312 |
@@ -9,7 +9,7 @@ job_defaults: &job_defaults
|
||||
working_directory: ~/coralproject/talk
|
||||
resource_class: large
|
||||
docker:
|
||||
- image: circleci/node:10
|
||||
- image: circleci/node:12
|
||||
environment:
|
||||
<<: *job_environment
|
||||
|
||||
|
||||
@@ -102,6 +102,8 @@ let typescriptTypeCheckingOverrides = {
|
||||
},
|
||||
},
|
||||
}],
|
||||
// 28.11.19: (cvle) Disabled because behavior of regexp.exec seems different than str.match?
|
||||
"@typescript-eslint/prefer-regexp-exec": "off",
|
||||
"@typescript-eslint/require-await": "off",
|
||||
"@typescript-eslint/no-misused-promises": "off",
|
||||
"@typescript-eslint/unbound-method": "off", // 10.10.19: (cvle) seems to give false positive.
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
about: Create a bug report to help us improve Coral
|
||||
labels: "bug"
|
||||
---
|
||||
|
||||
<!--
|
||||
Please provide as much detail as possible, including a screenshot or copy-paste of any related error messages, logs, or other output that might be related. Places to look for information include your browser console, server console, and network logs. The more information you can give the better.
|
||||
Please note that but submitting a bug report, you agree to our Code of Conduct: http://code-of-conduct.voxmedia.com/
|
||||
|
||||
When submitting a bug report, provide as much detail as possible, including a screenshot or copy-paste of any related error messages, logs, or other output that might be related. Places to look for information include your browser console, server console, and network logs. The more information you can give the better.
|
||||
|
||||
Please help us by doing the following steps before logging an issue:
|
||||
* Search: https://github.com/coralproject/talk/search
|
||||
* Read the docs: https://docs.coralproject.net
|
||||
* Search for other similar issues: https://github.com/coralproject/talk/search
|
||||
* Read our docs: https://docs.coralproject.net
|
||||
|
||||
Please fill in the *entire* template below.
|
||||
-->
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
about: Suggest a feature idea for Coral
|
||||
labels: "feature idea"
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
Please note that but submitting a feature request, you agree to our Code of Conduct: http://code-of-conduct.voxmedia.com/
|
||||
|
||||
Please help us by doing the following steps before logging an issue:
|
||||
* Search: https://github.com/coralproject/talk/search
|
||||
* Search to see if there are similar requests and ideas that are already logged: https://github.com/coralproject/talk/search
|
||||
|
||||
-->
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<!--
|
||||
Thank you for submitting a pull request!
|
||||
Thank you for submitting a pull request! Please note that by contributing to Coral, you agree to our Code of Conduct: http://code-of-conduct.voxmedia.com/
|
||||
|
||||
Please verify that:
|
||||
* [ ] Code is up-to-date with the base branch
|
||||
Before submitting your PR, please verify that:
|
||||
* [ ] Your code is up-to-date with the base branch
|
||||
* [ ] You've successfully run `npm run test` locally
|
||||
|
||||
Refer to CONTRIBUTING.MD for more details.
|
||||
https://github.com/coralproject/talk/blob/master/CONTRIBUTING.md
|
||||
-->
|
||||
|
||||
## What does this PR do?
|
||||
|
||||
## How do I test this PR?
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"projects": {
|
||||
"tenant": {
|
||||
"schemaPath": "src/core/server/graph/tenant/schema/schema.graphql"
|
||||
"schemaPath": "src/core/server/graph/schema/schema.graphql"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+4
@@ -54,4 +54,8 @@
|
||||
"d\\.ts$",
|
||||
"__generated__"
|
||||
],
|
||||
"debug.node.autoAttach": "on",
|
||||
"search.exclude": {
|
||||
"package-lock.json": true
|
||||
},
|
||||
}
|
||||
|
||||
@@ -64,3 +64,8 @@ where the string is used.
|
||||
|
||||
Once a language has enough coverage, it should be added to
|
||||
`src/core/common/helpers/i18n/locales.ts`.
|
||||
|
||||
The [Perspective API](https://github.com/conversationai/perspectiveapi/blob/master/2-api/methods.md#analyzecomment-request)
|
||||
also supports comments in specific languages. When the language is supported in
|
||||
Coral and supported by the Perspective API, the language should be added to the
|
||||
language map in `src/core/server/services/comments/pipeline/phases/toxic.ts`.
|
||||
|
||||
+3
-8
@@ -1,4 +1,4 @@
|
||||
FROM node:10-alpine
|
||||
FROM node:12-alpine
|
||||
|
||||
# Install build dependancies.
|
||||
RUN apk --no-cache add git python
|
||||
@@ -7,9 +7,6 @@ RUN apk --no-cache add git python
|
||||
RUN mkdir -p /usr/src/app
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Setup the environment for production.
|
||||
ENV NODE_ENV production
|
||||
|
||||
# Bundle application source.
|
||||
COPY . /usr/src/app
|
||||
|
||||
@@ -19,15 +16,13 @@ RUN mkdir -p dist/core/common/__generated__ && \
|
||||
echo "{\"revision\": \"${REVISION_HASH}\"}" > dist/core/common/__generated__/revision.json
|
||||
|
||||
# Install build static assets and clear caches.
|
||||
RUN NODE_ENV=development npm install && \
|
||||
npm run generate && \
|
||||
RUN npm ci && \
|
||||
npm run build && \
|
||||
npm prune --production
|
||||
|
||||
# Setup the environment
|
||||
ENV PATH /usr/src/app/bin:$PATH
|
||||
ENV NODE_ENV production
|
||||
ENV PORT 5000
|
||||
EXPOSE 5000
|
||||
ENV NODE_ENV production
|
||||
|
||||
CMD ["npm", "run", "start"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Coral 
|
||||
# Coral 
|
||||
|
||||
Online comments are broken. Our open-source commenting platform, Coral, rethinks
|
||||
how moderation, comment display, and conversation function, creating the
|
||||
|
||||
@@ -6,6 +6,7 @@ module.exports = {
|
||||
roots: ["<rootDir>/src"],
|
||||
collectCoverageFrom: ["**/*.{js,jsx,mjs,ts,tsx}"],
|
||||
coveragePathIgnorePatterns: ["/node_modules/"],
|
||||
setupFilesAfterEnv: ["<rootDir>/src/core/server/test/setupTestFramework.ts"],
|
||||
testMatch: ["**/*.spec.{js,jsx,mjs,ts,tsx}"],
|
||||
testPathIgnorePatterns: ["/node_modules/", "/client/"],
|
||||
testEnvironment: "node",
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
// Apply all the configuration provided in the .env file.
|
||||
require("dotenv").config();
|
||||
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
|
||||
const extensions = [".ts", ".tsx", ".js"];
|
||||
// TODO: There is some weird issue with including paths.ts here
|
||||
const postCSSConfigPath = "./src/core/build/postcss.config";
|
||||
const isProduction = process.NODE_ENV === "production";
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
|
||||
const styleLoader = {
|
||||
@@ -18,7 +16,7 @@ const styleLoader = {
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
module.exports = {
|
||||
title: "Coral 5.0",
|
||||
source: "./src",
|
||||
typescript: true,
|
||||
@@ -60,7 +58,7 @@ export default {
|
||||
"@babel/typescript",
|
||||
[
|
||||
"@babel/env",
|
||||
{ targets: { node: "10.0.0" }, modules: "commonjs" },
|
||||
{ targets: { node: "12.0.0" }, modules: "commonjs" },
|
||||
],
|
||||
],
|
||||
// This is a feature of `babel-loader` for webpack (not Babel itself).
|
||||
|
||||
@@ -0,0 +1,586 @@
|
||||
## Viewer Events
|
||||
_Viewer Events_ are emitted when the viewer performs certain actions.
|
||||
They can be subscribed to using the `events` parameter in
|
||||
`Coral.createStreamEmbed`.
|
||||
```html
|
||||
<script>
|
||||
const CoralStreamEmbed = Coral.createStreamEmbed({
|
||||
events: function(events) {
|
||||
events.onAny(function(eventName, data) {
|
||||
console.log(eventName, data);
|
||||
});
|
||||
},
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
Example events:
|
||||
- `setMainTab {tab: "PROFILE"}`
|
||||
- `showFeaturedCommentTooltip`
|
||||
- `viewConversation {from: "FEATURED_COMMENTS", commentID: "c45fb5f5-03f9-49a3-a755-488c698ca0df"}`
|
||||
|
||||
### Viewer Network Events
|
||||
|
||||
_Viewer Network Events_ are events that involves a network request and thus can succeed or fail. Succeeding events will have a `.success` appended to the event name while failing events have an `.error` appended to the event name.
|
||||
|
||||
Moreover _Viewer Network Events_ contains the `rtt` field which indicates the time it needed from initiating the request until the _UI_ has been updated with the response data.
|
||||
|
||||
Example events:
|
||||
```
|
||||
createComment.success
|
||||
{
|
||||
body: "Hello world!",
|
||||
storyID: "238b95ec-2b80-43f4-ab68-a6ea1f4e2584",
|
||||
rtt: 307,
|
||||
success: {
|
||||
id: "6fecfb11-4d0f-4edc-89b7-878a9928addd"
|
||||
status: "APPROVED"`
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
createComment.error
|
||||
{
|
||||
body: "Hi!",
|
||||
storyID: "238b95ec-2b80-43f4-ab68-a6ea1f4e2584",
|
||||
rtt: 229,
|
||||
error: {
|
||||
code: "COMMENT_BODY_TOO_SHORT"
|
||||
message: "Comment body must have at least 10 characters."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Event List
|
||||
<!-- START docs:events -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN npm run docs:events -->
|
||||
### Index
|
||||
- <a href="#approveComment">approveComment</a>
|
||||
- <a href="#banUser">banUser</a>
|
||||
- <a href="#cancelAccountDeletion">cancelAccountDeletion</a>
|
||||
- <a href="#changeEmail">changeEmail</a>
|
||||
- <a href="#changePassword">changePassword</a>
|
||||
- <a href="#changeUsername">changeUsername</a>
|
||||
- <a href="#closeStory">closeStory</a>
|
||||
- <a href="#copyPermalink">copyPermalink</a>
|
||||
- <a href="#createComment">createComment</a>
|
||||
- <a href="#createCommentFocus">createCommentFocus</a>
|
||||
- <a href="#createCommentReaction">createCommentReaction</a>
|
||||
- <a href="#createCommentReply">createCommentReply</a>
|
||||
- <a href="#editComment">editComment</a>
|
||||
- <a href="#featureComment">featureComment</a>
|
||||
- <a href="#gotoModeration">gotoModeration</a>
|
||||
- <a href="#ignoreUser">ignoreUser</a>
|
||||
- <a href="#loadMoreAllComments">loadMoreAllComments</a>
|
||||
- <a href="#loadMoreFeaturedComments">loadMoreFeaturedComments</a>
|
||||
- <a href="#loadMoreHistoryComments">loadMoreHistoryComments</a>
|
||||
- <a href="#loginPrompt">loginPrompt</a>
|
||||
- <a href="#openSortMenu">openSortMenu</a>
|
||||
- <a href="#openStory">openStory</a>
|
||||
- <a href="#rejectComment">rejectComment</a>
|
||||
- <a href="#removeCommentReaction">removeCommentReaction</a>
|
||||
- <a href="#removeUserIgnore">removeUserIgnore</a>
|
||||
- <a href="#replyCommentFocus">replyCommentFocus</a>
|
||||
- <a href="#reportComment">reportComment</a>
|
||||
- <a href="#requestAccountDeletion">requestAccountDeletion</a>
|
||||
- <a href="#requestDownloadCommentHistory">requestDownloadCommentHistory</a>
|
||||
- <a href="#resendEmailVerification">resendEmailVerification</a>
|
||||
- <a href="#setCommentsOrderBy">setCommentsOrderBy</a>
|
||||
- <a href="#setCommentsTab">setCommentsTab</a>
|
||||
- <a href="#setMainTab">setMainTab</a>
|
||||
- <a href="#setProfileTab">setProfileTab</a>
|
||||
- <a href="#showAbsoluteTimestamp">showAbsoluteTimestamp</a>
|
||||
- <a href="#showAllReplies">showAllReplies</a>
|
||||
- <a href="#showAuthPopup">showAuthPopup</a>
|
||||
- <a href="#showEditEmailDialog">showEditEmailDialog</a>
|
||||
- <a href="#showEditForm">showEditForm</a>
|
||||
- <a href="#showEditPasswordDialog">showEditPasswordDialog</a>
|
||||
- <a href="#showEditUsernameDialog">showEditUsernameDialog</a>
|
||||
- <a href="#showFeaturedCommentTooltip">showFeaturedCommentTooltip</a>
|
||||
- <a href="#showIgnoreUserdDialog">showIgnoreUserdDialog</a>
|
||||
- <a href="#showModerationPopover">showModerationPopover</a>
|
||||
- <a href="#showMoreOfConversation">showMoreOfConversation</a>
|
||||
- <a href="#showMoreReplies">showMoreReplies</a>
|
||||
- <a href="#showReplyForm">showReplyForm</a>
|
||||
- <a href="#showReportPopover">showReportPopover</a>
|
||||
- <a href="#showSharePopover">showSharePopover</a>
|
||||
- <a href="#showUserPopover">showUserPopover</a>
|
||||
- <a href="#signOut">signOut</a>
|
||||
- <a href="#unfeatureComment">unfeatureComment</a>
|
||||
- <a href="#updateNotificationSettings">updateNotificationSettings</a>
|
||||
- <a href="#updateStorySettings">updateStorySettings</a>
|
||||
- <a href="#viewConversation">viewConversation</a>
|
||||
- <a href="#viewFullDiscussion">viewFullDiscussion</a>
|
||||
- <a href="#viewNewComments">viewNewComments</a>
|
||||
|
||||
### Events
|
||||
- <a id="approveComment">**approveComment.success**, **approveComment.error**</a>: This event is emitted when the viewer approves a comment.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="banUser">**banUser.success**, **banUser.error**</a>: This event is emitted when the viewer bans a user.
|
||||
```ts
|
||||
{
|
||||
userID: string;
|
||||
commentID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="cancelAccountDeletion">**cancelAccountDeletion.success**, **cancelAccountDeletion.error**</a>: This event is emitted when the viewer cancels the account deletion.
|
||||
```ts
|
||||
{
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="changeEmail">**changeEmail.success**, **changeEmail.error**</a>: This event is emitted when the viewer changes its email.
|
||||
```ts
|
||||
{
|
||||
oldEmail: string;
|
||||
newEmail: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="changePassword">**changePassword.success**, **changePassword.error**</a>: This event is emitted when the viewer changes its password.
|
||||
```ts
|
||||
{
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="changeUsername">**changeUsername.success**, **changeUsername.error**</a>: This event is emitted when the viewer changes its username.
|
||||
```ts
|
||||
{
|
||||
oldUsername: string;
|
||||
newUsername: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="closeStory">**closeStory.success**, **closeStory.error**</a>: This event is emitted when the viewer closes the story.
|
||||
```ts
|
||||
{
|
||||
storyID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="copyPermalink">**copyPermalink**</a>: This event is emitted when the viewer copies the permalink with the button.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
}
|
||||
```
|
||||
- <a id="createComment">**createComment.success**, **createComment.error**</a>: This event is emitted when a top level comment is created.
|
||||
```ts
|
||||
{
|
||||
storyID: string;
|
||||
body: string;
|
||||
success: {
|
||||
id: string;
|
||||
status: COMMENT_STATUS;
|
||||
};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="createCommentFocus">**createCommentFocus**</a>: This event is emitted when the viewer focus on the RTE to create a comment.
|
||||
- <a id="createCommentReaction">**createCommentReaction.success**, **createCommentReaction.error**</a>: This event is emitted when the viewer reacts to a comment.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="createCommentReply">**createCommentReply.success**, **createCommentReply.error**</a>: This event is emitted when a comment reply is created.
|
||||
```ts
|
||||
{
|
||||
body: string;
|
||||
parentID: string;
|
||||
success: {
|
||||
id: string;
|
||||
status: COMMENT_STATUS;
|
||||
};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="editComment">**editComment.success**, **editComment.error**</a>: This event is emitted when the viewer edits a comment.
|
||||
```ts
|
||||
{
|
||||
body: string;
|
||||
commentID: string;
|
||||
success: {
|
||||
status: COMMENT_STATUS;
|
||||
};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="featureComment">**featureComment.success**, **featureComment.error**</a>: This event is emitted when the viewer features a comment.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="gotoModeration">**gotoModeration**</a>: This event is emitted when the viewer goes to moderation.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
}
|
||||
```
|
||||
- <a id="ignoreUser">**ignoreUser.success**, **ignoreUser.error**</a>: This event is emitted when the viewer ignores a user.
|
||||
```ts
|
||||
{
|
||||
userID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="loadMoreAllComments">**loadMoreAllComments.success**, **loadMoreAllComments.error**</a>: This event is emitted when the viewer loads more top level comments into the comment stream.
|
||||
```ts
|
||||
{
|
||||
storyID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="loadMoreFeaturedComments">**loadMoreFeaturedComments.success**, **loadMoreFeaturedComments.error**</a>: This event is emitted when the viewer loads more featured comments.
|
||||
```ts
|
||||
{
|
||||
storyID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="loadMoreHistoryComments">**loadMoreHistoryComments.success**, **loadMoreHistoryComments.error**</a>: This event is emitted when the viewer loads more top level comments into the history comment stream.
|
||||
```ts
|
||||
{
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="loginPrompt">**loginPrompt**</a>: This event is emitted when the viewer does an action that will prompt a login dialog.
|
||||
- <a id="openSortMenu">**openSortMenu**</a>: This event is emitted when the viewer clicks on the sort menu.
|
||||
- <a id="openStory">**openStory.success**, **openStory.error**</a>: This event is emitted when the viewer opens the story.
|
||||
```ts
|
||||
{
|
||||
storyID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="rejectComment">**rejectComment.success**, **rejectComment.error**</a>: This event is emitted when the viewer rejects a comment.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="removeCommentReaction">**removeCommentReaction.success**, **removeCommentReaction.error**</a>: This event is emitted when the viewer removes its reaction from a comment.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="removeUserIgnore">**removeUserIgnore.success**, **removeUserIgnore.error**</a>: This event is emitted when the viewer remove a user from its ignored users list.
|
||||
```ts
|
||||
{
|
||||
userID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="replyCommentFocus">**replyCommentFocus**</a>: This event is emitted when the viewer focus on the RTE to reply to a comment.
|
||||
- <a id="reportComment">**reportComment.success**, **reportComment.error**</a>: This event is emitted when the viewer reports a comment.
|
||||
```ts
|
||||
{
|
||||
reason: string;
|
||||
commentID: string;
|
||||
additionalDetails?: string | undefined;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="requestAccountDeletion">**requestAccountDeletion.success**, **requestAccountDeletion.error**</a>: This event is emitted when the viewer requests to delete its account.
|
||||
```ts
|
||||
{
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="requestDownloadCommentHistory">**requestDownloadCommentHistory.success**, **requestDownloadCommentHistory.error**</a>: This event is emitted when the viewer requests to download its comment history.
|
||||
```ts
|
||||
{
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="resendEmailVerification">**resendEmailVerification.success**, **resendEmailVerification.error**</a>: This event is emitted when the viewer request another email verification email.
|
||||
```ts
|
||||
{
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="setCommentsOrderBy">**setCommentsOrderBy**</a>: This event is emitted when the viewer changes the sort order of the comments.
|
||||
```ts
|
||||
{
|
||||
orderBy: string;
|
||||
}
|
||||
```
|
||||
- <a id="setCommentsTab">**setCommentsTab**</a>: This event is emitted when the viewer changes the tab of the comments tab bar.
|
||||
```ts
|
||||
{
|
||||
tab: string;
|
||||
}
|
||||
```
|
||||
- <a id="setMainTab">**setMainTab**</a>: This event is emitted when the viewer changes the tab of the main tab bar.
|
||||
```ts
|
||||
{
|
||||
tab: string;
|
||||
}
|
||||
```
|
||||
- <a id="setProfileTab">**setProfileTab**</a>: This event is emitted when the viewer changes the tab of the profile tab bar.
|
||||
```ts
|
||||
{
|
||||
tab: string;
|
||||
}
|
||||
```
|
||||
- <a id="showAbsoluteTimestamp">**showAbsoluteTimestamp**</a>: This event is emitted when the viewer clicks on the relative timestamp to show the absolute time.
|
||||
- <a id="showAllReplies">**showAllReplies.success**, **showAllReplies.error**</a>: This event is emitted when the viewer reveals all replies of a comment.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="showAuthPopup">**showAuthPopup**</a>: This event is emitted when the viewer requests the auth popup.
|
||||
```ts
|
||||
{
|
||||
view: string;
|
||||
}
|
||||
```
|
||||
- <a id="showEditEmailDialog">**showEditEmailDialog**</a>: This event is emitted when the viewer opens the edit email dialog.
|
||||
- <a id="showEditForm">**showEditForm**</a>: This event is emitted when the viewer opens the edit form.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
}
|
||||
```
|
||||
- <a id="showEditPasswordDialog">**showEditPasswordDialog**</a>: This event is emitted when the viewer opens the edit password dialog.
|
||||
- <a id="showEditUsernameDialog">**showEditUsernameDialog**</a>: This event is emitted when the viewer opens the edit username dialog.
|
||||
- <a id="showFeaturedCommentTooltip">**showFeaturedCommentTooltip**</a>: This event is emitted when the viewer clicks to show the featured comment tooltip.
|
||||
- <a id="showIgnoreUserdDialog">**showIgnoreUserdDialog**</a>: This event is emitted when the viewer opens the ignore user dialog.
|
||||
- <a id="showModerationPopover">**showModerationPopover**</a>: This event is emitted when the viewer opens the moderation popover.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
}
|
||||
```
|
||||
- <a id="showMoreOfConversation">**showMoreOfConversation.success**, **showMoreOfConversation.error**</a>: This event is emitted when the viewer reveals more of the parent conversation thread.
|
||||
```ts
|
||||
{
|
||||
commentID: string | null;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="showMoreReplies">**showMoreReplies**</a>: This event is emitted when the viewer reveals new live replies.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
count: number;
|
||||
}
|
||||
```
|
||||
- <a id="showReplyForm">**showReplyForm**</a>: This event is emitted when the viewer opens the reply form.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
}
|
||||
```
|
||||
- <a id="showReportPopover">**showReportPopover**</a>: This event is emitted when the viewer opens the report popover.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
}
|
||||
```
|
||||
- <a id="showSharePopover">**showSharePopover**</a>: This event is emitted when the viewer opens the share popover.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
}
|
||||
```
|
||||
- <a id="showUserPopover">**showUserPopover**</a>: This event is emitted when the viewer clicks on a username which shows the user popover.
|
||||
```ts
|
||||
{
|
||||
userID: string;
|
||||
}
|
||||
```
|
||||
- <a id="signOut">**signOut.success**, **signOut.error**</a>: This event is emitted when the viewer signs out.
|
||||
```ts
|
||||
{
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="unfeatureComment">**unfeatureComment.success**, **unfeatureComment.error**</a>: This event is emitted when the viewer unfeatures a comment.
|
||||
```ts
|
||||
{
|
||||
commentID: string;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="updateNotificationSettings">**updateNotificationSettings.success**, **updateNotificationSettings.error**</a>: This event is emitted when the viewer updates its notification settings.
|
||||
```ts
|
||||
{
|
||||
onReply?: boolean | null | undefined;
|
||||
onFeatured?: boolean | null | undefined;
|
||||
onStaffReplies?: boolean | null | undefined;
|
||||
onModeration?: boolean | null | undefined;
|
||||
digestFrequency?: "NONE" | "DAILY" | "HOURLY" | null | undefined;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="updateStorySettings">**updateStorySettings.success**, **updateStorySettings.error**</a>: This event is emitted when the viewer updates the story settings.
|
||||
```ts
|
||||
{
|
||||
storyID: string;
|
||||
live?: {
|
||||
enabled?: boolean | null | undefined;
|
||||
} | null | undefined;
|
||||
moderation?: "POST" | "PRE" | null | undefined;
|
||||
premodLinksEnable?: boolean | null | undefined;
|
||||
messageBox?: {
|
||||
enabled?: boolean | null | undefined;
|
||||
icon?: string | null | undefined;
|
||||
content?: string | null | undefined;
|
||||
} | null | undefined;
|
||||
success: {};
|
||||
error: {
|
||||
message: string;
|
||||
code?: string | undefined;
|
||||
};
|
||||
}
|
||||
```
|
||||
- <a id="viewConversation">**viewConversation**</a>: This event is emitted when the viewer changes to the single conversation view.
|
||||
```ts
|
||||
{
|
||||
from: "FEATURED_COMMENTS" | "COMMENT_STREAM" | "COMMENT_HISTORY";
|
||||
commentID: string;
|
||||
}
|
||||
```
|
||||
- <a id="viewFullDiscussion">**viewFullDiscussion**</a>: This event is emitted when the viewer exits the single conversation.
|
||||
```ts
|
||||
{
|
||||
commentID: string | null;
|
||||
}
|
||||
```
|
||||
- <a id="viewNewComments">**viewNewComments**</a>: This event is emitted when the viewer reveals new live comments.
|
||||
```ts
|
||||
{
|
||||
storyID: string;
|
||||
count: number;
|
||||
}
|
||||
```
|
||||
<!-- END docs:events -->
|
||||
Generated
+1218
-348
File diff suppressed because it is too large
Load Diff
+51
-30
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@coralproject/talk",
|
||||
"version": "5.2.0",
|
||||
"version": "5.4.0",
|
||||
"author": "The Coral Project",
|
||||
"homepage": "https://coralproject.net/",
|
||||
"sideEffects": [
|
||||
@@ -11,8 +11,8 @@
|
||||
"url": "git://github.com/coralproject/talk.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0",
|
||||
"npm": ">=6.9.0"
|
||||
"node": "^12",
|
||||
"npm": "^6"
|
||||
},
|
||||
"bugs": "https://github.com/coralproject/talk/issues",
|
||||
"contributors": [
|
||||
@@ -26,6 +26,7 @@
|
||||
"build:server": "gulp server",
|
||||
"migration:create": "ts-node --transpile-only ./scripts/migration/create.ts",
|
||||
"doctoc": "doctoc --title='## Table of Contents' --github README.md",
|
||||
"docs:events": "ts-node ./scripts/generateEventDocs.ts ./src/core/client/stream/events.ts ./events.md",
|
||||
"generate": "npm-run-all generate:css-types generate:schema generate:relay",
|
||||
"generate-persist": "npm-run-all generate:css-types generate:schema generate:relay-persist",
|
||||
"generate:css-types": "tcm src/core/client/",
|
||||
@@ -45,9 +46,9 @@
|
||||
"lint:server": "eslint 'src/**/*.{js,ts,tsx}' --ignore-pattern 'src/core/client/**'",
|
||||
"lint:client": "eslint 'src/core/client/**/*.{js,ts,tsx}'",
|
||||
"lint:scripts": "eslint 'scripts/**/*.{js,ts,tsx}'",
|
||||
"lint:graphql": "graphql-schema-linter src/core/server/graph/tenant/schema/schema.graphql",
|
||||
"lint:graphql": "graphql-schema-linter src/core/server/graph/schema/schema.graphql",
|
||||
"lint-fix": "npm run lint:server -- --fix && npm run lint:client -- --fix && npm run lint:scripts -- --fix",
|
||||
"test": "node scripts/test.js --env=jsdom",
|
||||
"test": "node --trace-warnings scripts/test.js --env=jsdom",
|
||||
"tscheck": "npm-run-all --parallel tscheck:*",
|
||||
"tscheck:server": "tsc --project ./src/tsconfig.json --noEmit",
|
||||
"tscheck:client": "tsc --project ./src/core/client/tsconfig.json --noEmit",
|
||||
@@ -57,6 +58,10 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@coralproject/bunyan-prettystream": "^0.1.4",
|
||||
"@fluent/bundle": "^0.14.0",
|
||||
"@fluent/dom": "^0.6.0",
|
||||
"@metascraper/helpers": "^5.7.21",
|
||||
"abort-controller": "^3.0.0",
|
||||
"akismet-api": "^4.2.0",
|
||||
"apollo-server-express": "^2.8.1",
|
||||
"archiver": "^3.0.3",
|
||||
@@ -74,58 +79,58 @@
|
||||
"cron": "^1.7.1",
|
||||
"csv-stringify": "^5.3.0",
|
||||
"dataloader": "^1.4.0",
|
||||
"dompurify": "^1.0.8",
|
||||
"dompurify": "^2.0.7",
|
||||
"dotenv": "^6.0.0",
|
||||
"dotenv-expand": "^4.2.0",
|
||||
"env-rewrite": "^1.0.2",
|
||||
"express": "^4.16.3",
|
||||
"express-enforces-ssl": "^1.1.0",
|
||||
"express-static-gzip": "^0.3.2",
|
||||
"fluent": "^0.10.0",
|
||||
"fluent-dom": "^0.4.1",
|
||||
"fs-extra": "^6.0.1",
|
||||
"graphql": "^0.13.2",
|
||||
"graphql-config": "^2.0.1",
|
||||
"graphql-extensions": "^0.2.1",
|
||||
"graphql-fields": "^1.1.0",
|
||||
"graphql-import": "^0.7.1",
|
||||
"graphql-playground-html": "^1.6.0",
|
||||
"graphql-redis-subscriptions": "^2.1.0",
|
||||
"graphql-subscriptions": "^1.1.0",
|
||||
"graphql-tools": "^3.0.5",
|
||||
"helmet": "^3.21.2",
|
||||
"html-minifier": "^3.5.21",
|
||||
"html-to-text": "^4.0.0",
|
||||
"ioredis": "^4.9.0",
|
||||
"joi": "^13.4.0",
|
||||
"jsdom": "^15.0.0",
|
||||
"jsonwebtoken": "^8.3.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"juice": "^5.2.0",
|
||||
"jwks-rsa": "^1.3.0",
|
||||
"jwks-rsa": "^1.6.0",
|
||||
"keymaster": "^1.6.2",
|
||||
"linkifyjs": "^2.1.8",
|
||||
"lodash": "^4.17.15",
|
||||
"lru-cache": "^5.1.1",
|
||||
"luxon": "^1.12.0",
|
||||
"metascraper-author": "^3.11.8",
|
||||
"metascraper-date": "^3.11.4",
|
||||
"metascraper-description": "^3.11.8",
|
||||
"metascraper-image": "^3.11.8",
|
||||
"metascraper-title": "^3.11.8",
|
||||
"metascraper-author": "^5.8.0",
|
||||
"metascraper-description": "^5.8.0",
|
||||
"metascraper-image": "^5.8.0",
|
||||
"metascraper-title": "^5.8.0",
|
||||
"mongodb": "^3.2.7",
|
||||
"mongodb-core": "^3.2.7",
|
||||
"ms": "^2.1.1",
|
||||
"node-fetch": "^2.2.0",
|
||||
"node-fetch": "^2.6.0",
|
||||
"nodemailer": "^4.6.7",
|
||||
"nunjucks": "^3.1.3",
|
||||
"on-finished": "^2.3.0",
|
||||
"passport": "^0.4.0",
|
||||
"passport-facebook": "^2.1.1",
|
||||
"passport-google-oauth2": "^0.1.6",
|
||||
"passport": "^0.4.1",
|
||||
"passport-facebook": "^3.0.0",
|
||||
"passport-google-oauth2": "^0.2.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"passport-oauth2": "^1.4.0",
|
||||
"passport-strategy": "^1.0.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"permit": "^0.2.4",
|
||||
"prom-client": "^11.3.0",
|
||||
"proxy-agent": "^3.1.0",
|
||||
"proxy-agent": "^3.1.1",
|
||||
"querystringify": "^2.1.0",
|
||||
"react-helmet": "^5.2.1",
|
||||
"source-map-support": "^0.5.12",
|
||||
@@ -146,7 +151,8 @@
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/preset-typescript": "^7.3.3",
|
||||
"@coralproject/npm-run-all": "^4.1.5",
|
||||
"@coralproject/rte": "^0.10.15",
|
||||
"@coralproject/rte": "^0.11.0",
|
||||
"@fluent/react": "^0.10.0",
|
||||
"@intervolga/optimize-cssnano-plugin": "^1.0.6",
|
||||
"@types/agent-base": "^4.2.0",
|
||||
"@types/archiver": "^3.0.0",
|
||||
@@ -167,22 +173,26 @@
|
||||
"@types/cors": "^2.8.4",
|
||||
"@types/cron": "^1.7.1",
|
||||
"@types/cross-spawn": "^6.0.0",
|
||||
"@types/dompurify": "0.0.33",
|
||||
"@types/dotenv": "^4.0.3",
|
||||
"@types/enzyme": "^3.1.15",
|
||||
"@types/enzyme-adapter-react-16": "^1.0.3",
|
||||
"@types/eventemitter2": "^4.1.0",
|
||||
"@types/express": "^4.16.0",
|
||||
"@types/express-enforces-ssl": "^1.1.1",
|
||||
"@types/flat": "0.0.28",
|
||||
"@types/fs-extra": "^5.0.4",
|
||||
"@types/graphql": "^0.13.3",
|
||||
"@types/helmet": "0.0.45",
|
||||
"@types/html-minifier": "^3.5.2",
|
||||
"@types/html-to-text": "^1.4.31",
|
||||
"@types/html-webpack-plugin": "^3.2.0",
|
||||
"@types/ioredis": "^4.0.10",
|
||||
"@types/jest": "^24.0.13",
|
||||
"@types/jest": "^24.0.23",
|
||||
"@types/jest-axe": "^3.2.1",
|
||||
"@types/joi": "^13.0.8",
|
||||
"@types/jsdom": "^12.2.3",
|
||||
"@types/jsonwebtoken": "^7.2.7",
|
||||
"@types/jsonwebtoken": "^8.3.5",
|
||||
"@types/linkifyjs": "^2.1.1",
|
||||
"@types/lodash": "^4.14.118",
|
||||
"@types/lru-cache": "^5.1.0",
|
||||
@@ -192,19 +202,21 @@
|
||||
"@types/mongodb": "^3.1.22",
|
||||
"@types/ms": "^0.7.30",
|
||||
"@types/node": "^10.5.2",
|
||||
"@types/node-fetch": "^2.3.3",
|
||||
"@types/node-fetch": "^2.5.3",
|
||||
"@types/nodemailer": "^4.6.2",
|
||||
"@types/nunjucks": "^3.1.1",
|
||||
"@types/object-diff": "0.0.0",
|
||||
"@types/on-finished": "^2.3.1",
|
||||
"@types/passport": "^0.4.6",
|
||||
"@types/passport": "^1.0.2",
|
||||
"@types/passport-facebook": "^2.1.8",
|
||||
"@types/passport-local": "^1.0.33",
|
||||
"@types/passport-oauth2": "^1.4.5",
|
||||
"@types/passport-strategy": "^0.2.33",
|
||||
"@types/permit": "^0.2.1",
|
||||
"@types/prettier": "^1.19.0",
|
||||
"@types/prop-types": "^15.5.8",
|
||||
"@types/react": "^16.8.15",
|
||||
"@types/react-axe": "^3.1.0",
|
||||
"@types/react-copy-to-clipboard": "^4.2.6",
|
||||
"@types/react-dom": "^16.8.4",
|
||||
"@types/react-helmet": "^5.0.10",
|
||||
@@ -219,6 +231,7 @@
|
||||
"@types/simplemde": "^1.11.7",
|
||||
"@types/sinon": "^7.0.11",
|
||||
"@types/source-map-support": "^0.5.0",
|
||||
"@types/stack-trace": "0.0.29",
|
||||
"@types/stack-utils": "^1.0.1",
|
||||
"@types/throng": "^4.0.2",
|
||||
"@types/uuid": "^3.4.4",
|
||||
@@ -271,11 +284,10 @@
|
||||
"eslint-plugin-react": "^7.15.1",
|
||||
"eventemitter2": "^5.0.1",
|
||||
"farce": "^0.2.6",
|
||||
"final-form": "4.11.0",
|
||||
"final-form": "4.18.6",
|
||||
"final-form-arrays": "1.1.2",
|
||||
"flat": "^4.1.0",
|
||||
"fluent-intl-polyfill": "^0.1.0",
|
||||
"fluent-langneg": "^0.1.1",
|
||||
"fluent-react": "^0.8.4",
|
||||
"fork-ts-checker-webpack-plugin": "^1.5.0",
|
||||
"found": "^0.4.0-alpha.17",
|
||||
"found-relay": "^0.4.0-alpha.8",
|
||||
@@ -290,6 +302,7 @@
|
||||
"husky": "^2.2.0",
|
||||
"intersection-observer": "^0.6.0",
|
||||
"jest": "^24.8.0",
|
||||
"jest-axe": "^3.2.0",
|
||||
"jest-junit": "^6.4.0",
|
||||
"jest-localstorage-mock": "^2.4.0",
|
||||
"jest-mock-console": "^1.0.0",
|
||||
@@ -317,11 +330,13 @@
|
||||
"pym.js": "^1.3.2",
|
||||
"raw-loader": "^0.5.1",
|
||||
"react": "^16.9.0-alpha.0",
|
||||
"react-axe": "^3.3.0",
|
||||
"react-copy-to-clipboard": "^5.0.1",
|
||||
"react-dev-utils": "^9.0.0",
|
||||
"react-dom": "^16.9.0-alpha.0",
|
||||
"react-error-overlay": "^5.1.6",
|
||||
"react-final-form": "4.0.2",
|
||||
"react-final-form": "6.3.0",
|
||||
"react-final-form-arrays": "3.1.0",
|
||||
"react-popper": "^1.3.2",
|
||||
"react-relay": "^4.0.0",
|
||||
"react-relay-network-modern": "^4.0.4",
|
||||
@@ -342,6 +357,7 @@
|
||||
"simulant": "^0.2.2",
|
||||
"sinon": "^7.3.2",
|
||||
"sockjs-client": "^1.3.0",
|
||||
"stack-trace": "0.0.10",
|
||||
"strip-ansi": "^5.2.0",
|
||||
"style-loader": "^0.23.1",
|
||||
"subscriptions-transport-ws": "^0.9.16",
|
||||
@@ -357,6 +373,8 @@
|
||||
"tslint": "^5.20.0",
|
||||
"typed-css-modules": "^0.4.2",
|
||||
"typeface-manuale": "^0.0.71",
|
||||
"typeface-nunito": "0.0.72",
|
||||
"typeface-open-sans": "0.0.75",
|
||||
"typeface-source-sans-pro": "^0.0.54",
|
||||
"typescript": "3.3.4000",
|
||||
"typescript-snapshots-plugin": "^1.6.0",
|
||||
@@ -377,8 +395,11 @@
|
||||
"*.{j,t}s{,x}": [
|
||||
"eslint"
|
||||
],
|
||||
"src/core/server/graph/tenant/schema/schema.graphql": [
|
||||
"src/core/server/graph/schema/schema.graphql": [
|
||||
"graphql-schema-linter"
|
||||
],
|
||||
"{src/core/client/stream/events.ts,scripts/generateEventDocs.ts,events.md}": [
|
||||
"npm run docs:events -- --verify"
|
||||
]
|
||||
},
|
||||
"bundlesize": [
|
||||
|
||||
@@ -74,7 +74,7 @@ if (persist) {
|
||||
if (fs.existsSync(persist)) {
|
||||
// Create the new filename.
|
||||
const name = path.basename(program.src);
|
||||
const generated = "./src/core/server/graph/common/persisted/__generated__";
|
||||
const generated = "./src/core/server/graph/persisted/__generated__";
|
||||
|
||||
// Create the generated directory if it doesn't exist.
|
||||
fs.ensureDirSync(generated);
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
/* eslint-disable no-bitwise */
|
||||
|
||||
import { codeBlock, stripIndent } from "common-tags";
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import ts from "typescript";
|
||||
|
||||
interface DocEntry {
|
||||
name: string;
|
||||
docs?: string;
|
||||
type: "ViewerNetworkEvent" | "ViewerEvent";
|
||||
text?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* We use this regexp to find a previous block that we
|
||||
* are going to update in the readme file.
|
||||
*/
|
||||
const BLOCK_REGEXP = /<!-- START docs:events -->(.|\n)*<!-- END docs:events -->/gm;
|
||||
|
||||
/** Build flags that affects AST generation */
|
||||
const buildFlags =
|
||||
// Do not truncate output.
|
||||
ts.NodeBuilderFlags.NoTruncation |
|
||||
// Use multiline object literals format.
|
||||
ts.NodeBuilderFlags.MultilineObjectLiterals;
|
||||
|
||||
/** Generate documentation for all classes in a set of .ts files */
|
||||
function gatherEntries(
|
||||
fileNames: string[],
|
||||
options: ts.CompilerOptions
|
||||
): DocEntry[] {
|
||||
// Build a program using the set of root file names in fileNames
|
||||
const program = ts.createProgram(fileNames, options);
|
||||
|
||||
const printer = ts.createPrinter({
|
||||
noEmitHelpers: true,
|
||||
omitTrailingSemicolon: true,
|
||||
removeComments: false,
|
||||
});
|
||||
|
||||
// Get the checker, we will use it to find more about classes
|
||||
const checker = program.getTypeChecker();
|
||||
|
||||
const data: DocEntry[] = [];
|
||||
|
||||
/** Hold a pointer to the sourcefile we are currently processing. */
|
||||
let currentSourceFile: ts.SourceFile;
|
||||
|
||||
// Visit every sourceFile in the program
|
||||
for (const sourceFile of program.getSourceFiles()) {
|
||||
if (!sourceFile.isDeclarationFile) {
|
||||
currentSourceFile = sourceFile;
|
||||
// Walk the tree to search for classes
|
||||
ts.forEachChild(sourceFile, visit);
|
||||
}
|
||||
}
|
||||
|
||||
const sorted = data.sort((a, b) => {
|
||||
if (a.name > b.name) {
|
||||
return 1;
|
||||
}
|
||||
if (b.name > a.name) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
return sorted;
|
||||
|
||||
/** visit nodes finding exported events */
|
||||
function visit(node: ts.Node) {
|
||||
// Only consider exported nodes
|
||||
if (!isNodeExported(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ts.isVariableStatement(node)) {
|
||||
if (
|
||||
!node.getFullText().includes("createViewerNetworkEvent") &&
|
||||
!node.getFullText().includes("createViewerEvent")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const firstChild = node.declarationList.declarations[0];
|
||||
if (ts.isVariableDeclaration(firstChild)) {
|
||||
const symbol = checker.getSymbolAtLocation(firstChild.name);
|
||||
if (symbol) {
|
||||
serializeEventSymbol(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function serializeEventSymbol(symbol: ts.Symbol) {
|
||||
const type = checker.getTypeOfSymbolAtLocation(
|
||||
symbol,
|
||||
symbol.valueDeclaration
|
||||
);
|
||||
const typeNode = checker.typeToTypeNode(type, undefined, buildFlags)!;
|
||||
const typeName = symbol.getName();
|
||||
const entry: DocEntry = {
|
||||
name: typeName,
|
||||
docs: ts.displayPartsToString(symbol.getDocumentationComment(checker)),
|
||||
type: type.getSymbol()!.getName() as DocEntry["type"],
|
||||
};
|
||||
typeNode.forEachChild(ch => {
|
||||
if (ts.isTypeLiteralNode(ch)) {
|
||||
const text = printer.printNode(
|
||||
ts.EmitHint.Unspecified,
|
||||
ch,
|
||||
currentSourceFile
|
||||
);
|
||||
if (text !== "{}") {
|
||||
entry.text = text;
|
||||
}
|
||||
/*
|
||||
Go through each parameter.
|
||||
ch.members.forEach(m => {
|
||||
if (ts.isPropertySignature(m)) {
|
||||
if (ts.isIdentifier(m.name)) {
|
||||
data.parameters[m.name.text] = printer.printNode(
|
||||
ts.EmitHint.Unspecified,
|
||||
m.type!,
|
||||
currentSourceFile
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
});
|
||||
data.push(entry);
|
||||
}
|
||||
|
||||
/** True if this is visible outside this file, false otherwise */
|
||||
function isNodeExported(node: ts.Node): boolean {
|
||||
return (
|
||||
// eslint-disable-next-line no-bitwise, @typescript-eslint/no-unnecessary-type-assertion
|
||||
(ts.getCombinedModifierFlags(node as ts.Declaration) &
|
||||
ts.ModifierFlags.Export) !==
|
||||
0 ||
|
||||
(!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function prefixLines(text: string, prefix: string) {
|
||||
return text.split("\n").join(`\n${prefix}`);
|
||||
}
|
||||
|
||||
function getEventName(typeName: string) {
|
||||
return (
|
||||
typeName[0].toLocaleLowerCase() +
|
||||
typeName.slice(1, typeName.length - "Event".length)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes "%future added value" from text. This is a placeholder type
|
||||
* added by Relay to help with future proofness.
|
||||
*/
|
||||
function removeFutureAddedValue(text: string) {
|
||||
return text
|
||||
.replace(': "%future added value" | ', ": ")
|
||||
.replace(' | "%future added value"', "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Append or update previous documention in markdownFile.
|
||||
*
|
||||
* @param markdownFile The markdown file we want to inject the docs too.
|
||||
* @param entries data as returned by gatherEntries.
|
||||
*/
|
||||
function emitDocs(markdownFile: string, entries: DocEntry[], verify = false) {
|
||||
const previousContent = fs.existsSync(markdownFile)
|
||||
? fs.readFileSync(markdownFile).toString()
|
||||
: "";
|
||||
const summary = stripIndent`
|
||||
- ${entries
|
||||
.map(
|
||||
e => `<a href="#${getEventName(e.name)}">${getEventName(e.name)}</a>`
|
||||
)
|
||||
.join("\n - ")}
|
||||
`;
|
||||
const list = entries
|
||||
.map(
|
||||
e =>
|
||||
codeBlock`
|
||||
- ${
|
||||
e.type === "ViewerEvent"
|
||||
? `<a id="${getEventName(e.name)}">**${getEventName(e.name)}**</a>`
|
||||
: `<a id="${getEventName(e.name)}">**${getEventName(
|
||||
e.name
|
||||
)}.success**, **${getEventName(e.name)}.error**</a>`
|
||||
}: ${e.docs ? e.docs.replace("\n", " ") : ""}
|
||||
${
|
||||
e.text
|
||||
? codeBlock`
|
||||
\`\`\`ts
|
||||
${removeFutureAddedValue(e.text)}
|
||||
\`\`\`
|
||||
`
|
||||
: ""
|
||||
}
|
||||
`
|
||||
)
|
||||
.join("\n");
|
||||
|
||||
const output = stripIndent`
|
||||
<!-- START docs:events -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN npm run docs:events -->
|
||||
### Index
|
||||
${prefixLines(summary, " ")}
|
||||
|
||||
### Events
|
||||
${prefixLines(list, " ")}
|
||||
<!-- END docs:events -->
|
||||
`;
|
||||
|
||||
let newContent;
|
||||
// Find previous block.
|
||||
if (BLOCK_REGEXP.test(previousContent)) {
|
||||
newContent = previousContent.replace(BLOCK_REGEXP, output);
|
||||
} else {
|
||||
newContent = previousContent + "\n" + output;
|
||||
}
|
||||
if (previousContent === newContent) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`${markdownFile} is up to date`);
|
||||
return;
|
||||
}
|
||||
if (verify) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(
|
||||
`${markdownFile} is outdated, please run \`npm run docs:events\``
|
||||
);
|
||||
process.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
fs.writeFileSync(markdownFile, newContent);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Successfully injected documentation into ${markdownFile}`);
|
||||
}
|
||||
|
||||
function main() {
|
||||
if (process.argv.length < 4) {
|
||||
throw new Error("Must provide path to events and a markdown file.");
|
||||
}
|
||||
|
||||
const eventFile = process.argv[2];
|
||||
const markdownFile = process.argv[3];
|
||||
|
||||
// Find tsconfig file.
|
||||
const configFile = ts.findConfigFile(eventFile, fs.existsSync);
|
||||
if (!configFile) {
|
||||
throw new Error("tsconfig file not found");
|
||||
}
|
||||
const configText = fs.readFileSync(configFile).toString();
|
||||
const result = ts.parseConfigFileTextToJson(configFile, configText);
|
||||
if (result.error) {
|
||||
throw result.error;
|
||||
}
|
||||
|
||||
// Parse the JSON raw data into actual consumable compiler options.
|
||||
const config = ts.parseJsonConfigFileContent(
|
||||
result.config,
|
||||
ts.sys,
|
||||
path.dirname(configFile)
|
||||
);
|
||||
|
||||
const entries = gatherEntries([eventFile], config.options);
|
||||
emitDocs(markdownFile, entries, process.argv[4] === "--verify");
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -12,12 +12,12 @@ async function main() {
|
||||
name: "tenant",
|
||||
fileName: path.join(
|
||||
__dirname,
|
||||
"../src/core/server/graph/tenant/schema/__generated__/types.ts"
|
||||
"../src/core/server/graph/schema/__generated__/types.ts"
|
||||
),
|
||||
config: {
|
||||
contextType: "TenantContext",
|
||||
contextType: "GraphContext",
|
||||
importStatements: [
|
||||
'import TenantContext from "coral-server/graph/tenant/context";',
|
||||
'import GraphContext from "coral-server/graph/context";',
|
||||
'import { Cursor } from "coral-server/models/helpers";',
|
||||
],
|
||||
customScalarType: { Cursor: "Cursor", Time: "Date" },
|
||||
|
||||
@@ -23,9 +23,10 @@ export default class ChokidarWatcher implements Watcher {
|
||||
let firstError: Error | null = null;
|
||||
|
||||
// If this is set, a pending promise is waiting for the next result.
|
||||
let pending:
|
||||
| ({ resolve: (result: string) => void; reject: (error: Error) => void })
|
||||
| null = null;
|
||||
let pending: {
|
||||
resolve: (result: string) => void;
|
||||
reject: (error: Error) => void;
|
||||
} | null = null;
|
||||
|
||||
// Only start client if we have something to watch.
|
||||
if (paths.length) {
|
||||
|
||||
@@ -48,7 +48,7 @@ export default class SaneWatcher implements Watcher {
|
||||
const queue: string[] = [];
|
||||
|
||||
// If this is set, a pending promise is waiting for the next result.
|
||||
let pending: ({ resolve: (result: string) => void }) | null = null;
|
||||
let pending: { resolve: (result: string) => void } | null = null;
|
||||
|
||||
// Only start client if we have something to watch.
|
||||
if (paths.length) {
|
||||
|
||||
@@ -392,7 +392,7 @@ export default function createWebpackConfig(
|
||||
"@babel/typescript",
|
||||
[
|
||||
"@babel/env",
|
||||
{ targets: { node: "10.0.0" }, modules: "commonjs" },
|
||||
{ targets: { node: "12.0.0" }, modules: "commonjs" },
|
||||
],
|
||||
],
|
||||
// This is a feature of `babel-loader` for webpack (not Babel itself).
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<title>Coral - Account</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
import potentiallyInjectAxe from "coral-framework/helpers/potentiallyInjectAxe";
|
||||
import { createManaged } from "coral-framework/lib/bootstrap";
|
||||
|
||||
import App from "./App";
|
||||
@@ -11,6 +12,8 @@ import localesData from "./locales";
|
||||
import "coral-ui/theme/variables.css";
|
||||
|
||||
async function main() {
|
||||
// Potentially inject react-axe for runtime a11y checks.
|
||||
await potentiallyInjectAxe();
|
||||
const ManagedCoralContextProvider = await createManaged({
|
||||
initLocalState,
|
||||
localesData,
|
||||
|
||||
@@ -3,8 +3,10 @@ import React, { FunctionComponent } from "react";
|
||||
import { HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
const NotFound: FunctionComponent = () => (
|
||||
<HorizontalGutter>
|
||||
<Typography variant="heading3">Not Found</Typography>
|
||||
<HorizontalGutter container="main">
|
||||
<Typography variant="heading3" container="h1">
|
||||
Not Found
|
||||
</Typography>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import cn from "classnames";
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Flex, HorizontalGutter, Icon, Typography } from "coral-ui/components";
|
||||
@@ -10,7 +10,7 @@ const DownloadDescription: FunctionComponent = () => {
|
||||
return (
|
||||
<HorizontalGutter size="double">
|
||||
<Localized id="download-landingPage-title">
|
||||
<div className={styles.title}>Download Your Comment History</div>
|
||||
<h1 className={styles.title}>Download Your Comment History</h1>
|
||||
</Localized>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.section}>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent, useCallback, useState } from "react";
|
||||
|
||||
import { Button, HorizontalGutter } from "coral-ui/components";
|
||||
@@ -11,8 +11,9 @@ interface Props {
|
||||
|
||||
const DownloadForm: FunctionComponent<Props> = ({ token }) => {
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
const onClick = useCallback(() => {
|
||||
const onSubmit = useCallback(() => {
|
||||
setSubmitted(true);
|
||||
return true;
|
||||
}, [setSubmitted]);
|
||||
|
||||
return (
|
||||
@@ -21,15 +22,15 @@ const DownloadForm: FunctionComponent<Props> = ({ token }) => {
|
||||
className={styles.form}
|
||||
method="post"
|
||||
action="/api/account/download"
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<input name="token" type="hidden" value={token} />
|
||||
<Localized id="download-landingPage-downloadComments ">
|
||||
<Localized id="download-landingPage-downloadComments">
|
||||
<Button
|
||||
type="submit"
|
||||
variant="filled"
|
||||
color="primary"
|
||||
disabled={submitted}
|
||||
onClick={onClick}
|
||||
className={styles.downloadButton}
|
||||
>
|
||||
Download My Comment History
|
||||
|
||||
@@ -32,35 +32,35 @@ const DownloadRoute: FunctionComponent<Props> = ({ token }) => {
|
||||
|
||||
if (state === "UNCHECKED") {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<HorizontalGutter size="double">
|
||||
<Loading />
|
||||
</HorizontalGutter>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
if (state !== "VALID" || error) {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<HorizontalGutter size="double">
|
||||
<DownloadDescription />
|
||||
<Sorry />
|
||||
</HorizontalGutter>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<DownloadDescription />
|
||||
<DownloadForm token={token!} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { CallOut, Flex, Icon } from "coral-ui/components";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import { FORM_ERROR } from "final-form";
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { useCallback } from "react";
|
||||
import { Form } from "react-final-form";
|
||||
|
||||
|
||||
@@ -35,36 +35,36 @@ const ConfirmRoute: React.FunctionComponent<Props> = ({ token }) => {
|
||||
|
||||
if (state === "UNCHECKED") {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<Loading />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
if (state !== "VALID" || error) {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<Sorry reason={error} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
return !finished ? (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<ConfirmForm token={token!} onSuccess={onSuccess} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
) : (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<Success />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React from "react";
|
||||
|
||||
import { CallOut, HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React from "react";
|
||||
|
||||
import { HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React from "react";
|
||||
|
||||
import { CallOut, HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React from "react";
|
||||
|
||||
import { HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import { FORM_ERROR } from "final-form";
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { useCallback } from "react";
|
||||
import { Form } from "react-final-form";
|
||||
|
||||
|
||||
@@ -35,36 +35,36 @@ const UnsubscribeRoute: React.FunctionComponent<Props> = ({ token }) => {
|
||||
|
||||
if (state === "UNCHECKED") {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<Loading />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
if (state !== "VALID" || error) {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<Sorry reason={error} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
return !finished ? (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<UnsubscribeForm token={token!} onSuccess={onSuccess} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
) : (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<Success />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import { FORM_ERROR } from "final-form";
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { useCallback } from "react";
|
||||
import { Field, Form } from "react-final-form";
|
||||
|
||||
|
||||
@@ -35,36 +35,36 @@ const ResetRoute: React.FunctionComponent<Props> = ({ token }) => {
|
||||
|
||||
if (state === "UNCHECKED") {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<Loading />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
if (state !== "VALID" || error) {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<Sorry reason={error} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
return !finished ? (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<ResetPasswordForm token={token!} onSuccess={onSuccess} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
) : (
|
||||
<div className={styles.container}>
|
||||
<main className={styles.container}>
|
||||
<div className={styles.root}>
|
||||
<Success />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React from "react";
|
||||
|
||||
import { CallOut, HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React from "react";
|
||||
|
||||
import { HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
@@ -10,7 +10,7 @@ exports[`renders form 1`] = `
|
||||
<div
|
||||
className="MainLayout-centered"
|
||||
>
|
||||
<div
|
||||
<main
|
||||
className="ConfirmRoute-container"
|
||||
>
|
||||
<div
|
||||
@@ -58,7 +58,7 @@ exports[`renders form 1`] = `
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -73,7 +73,7 @@ exports[`renders missing confirm token 1`] = `
|
||||
<div
|
||||
className="MainLayout-centered"
|
||||
>
|
||||
<div
|
||||
<main
|
||||
className="ConfirmRoute-container"
|
||||
>
|
||||
<div
|
||||
@@ -100,7 +100,7 @@ exports[`renders missing confirm token 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -10,7 +10,7 @@ exports[`renders form 1`] = `
|
||||
<div
|
||||
className="MainLayout-centered"
|
||||
>
|
||||
<div
|
||||
<main
|
||||
className="ResetRoute-container"
|
||||
>
|
||||
<div
|
||||
@@ -115,7 +115,7 @@ Make sure it is unique and be sure to keep it secure.
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -130,7 +130,7 @@ exports[`renders missing reset token 1`] = `
|
||||
<div
|
||||
className="MainLayout-centered"
|
||||
>
|
||||
<div
|
||||
<main
|
||||
className="ResetRoute-container"
|
||||
>
|
||||
<div
|
||||
@@ -157,7 +157,7 @@ exports[`renders missing reset token 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -10,7 +10,7 @@ exports[`renders form 1`] = `
|
||||
<div
|
||||
className="MainLayout-centered"
|
||||
>
|
||||
<div
|
||||
<main
|
||||
className="UnsubscribeRoute-container"
|
||||
>
|
||||
<div
|
||||
@@ -48,7 +48,7 @@ exports[`renders form 1`] = `
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -63,7 +63,7 @@ exports[`renders missing confirm token 1`] = `
|
||||
<div
|
||||
className="MainLayout-centered"
|
||||
>
|
||||
<div
|
||||
<main
|
||||
className="UnsubscribeRoute-container"
|
||||
>
|
||||
<div
|
||||
@@ -90,7 +90,7 @@ exports[`renders missing confirm token 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -31,7 +31,9 @@ it("renders missing confirm token", async () => {
|
||||
replaceHistoryLocation("http://localhost/account/email/confirm");
|
||||
const { root } = await createTestRenderer();
|
||||
await waitForElement(() => within(root).getByTestID("invalid-link"));
|
||||
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("renders form", async () => {
|
||||
@@ -57,6 +59,7 @@ it("renders form", async () => {
|
||||
);
|
||||
});
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
restMock.verify();
|
||||
});
|
||||
|
||||
@@ -98,6 +101,7 @@ it("renders error from server", async () => {
|
||||
);
|
||||
});
|
||||
restMock.verify();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ it("renders missing reset token", async () => {
|
||||
const { root } = await createTestRenderer();
|
||||
await waitForElement(() => within(root).getByTestID("invalid-link"));
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("renders form", async () => {
|
||||
@@ -57,6 +58,7 @@ it("renders form", async () => {
|
||||
);
|
||||
});
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
restMock.verify();
|
||||
});
|
||||
|
||||
@@ -98,6 +100,7 @@ it("renders error from server", async () => {
|
||||
);
|
||||
});
|
||||
restMock.verify();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ it("renders missing confirm token", async () => {
|
||||
const { root } = await createTestRenderer();
|
||||
await waitForElement(() => within(root).getByTestID("invalid-link"));
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("renders form", async () => {
|
||||
@@ -53,6 +54,7 @@ it("renders form", async () => {
|
||||
await waitForElement(() => within(root).getByTestID("unsubscribe-form"));
|
||||
});
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
restMock.verify();
|
||||
});
|
||||
|
||||
@@ -93,6 +95,7 @@ it("renders error from server", async () => {
|
||||
);
|
||||
});
|
||||
restMock.verify();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Typography } from "coral-ui/components";
|
||||
|
||||
import ApprovedIcon from "./ApprovedIcon";
|
||||
import DecisionItem from "./DecisionItem";
|
||||
import DotDivider from "./DotDivider";
|
||||
@@ -10,6 +8,7 @@ import Footer from "./Footer";
|
||||
import GoToCommentLink from "./GoToCommentLink";
|
||||
import Info from "./Info";
|
||||
import Timestamp from "./Timestamp";
|
||||
import Username from "./Username";
|
||||
|
||||
interface Props {
|
||||
href: string;
|
||||
@@ -18,10 +17,6 @@ interface Props {
|
||||
onGotoComment?: React.EventHandler<React.MouseEvent>;
|
||||
}
|
||||
|
||||
const Username: FunctionComponent<{ username: string }> = ({ username }) => (
|
||||
<strong>{username}</strong>
|
||||
);
|
||||
|
||||
const ApprovedComment: FunctionComponent<Props> = props => (
|
||||
<DecisionItem icon={<ApprovedIcon />}>
|
||||
<Localized
|
||||
@@ -31,9 +26,7 @@ const ApprovedComment: FunctionComponent<Props> = props => (
|
||||
<Info>{"Approved comment by <Username></Username>"}</Info>
|
||||
</Localized>
|
||||
<Footer>
|
||||
<Typography variant="timestamp">
|
||||
<Timestamp>{props.date}</Timestamp>
|
||||
</Typography>
|
||||
<Timestamp>{props.date}</Timestamp>
|
||||
<DotDivider />
|
||||
<GoToCommentLink href={props.href} onClick={props.onGotoComment} />
|
||||
</Footer>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
.root {
|
||||
color: var(--palette-success-main);
|
||||
color: var(--v2-palette-success-main);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Icon } from "coral-ui/components";
|
||||
import { Icon } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./ApprovedIcon.css";
|
||||
|
||||
const ApprovedIcon: FunctionComponent = () => (
|
||||
<Icon className={styles.root}>check</Icon>
|
||||
<Icon size="md" className={styles.root}>
|
||||
check_circled
|
||||
</Icon>
|
||||
);
|
||||
|
||||
export default ApprovedIcon;
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
}
|
||||
|
||||
.historyIcon {
|
||||
color: var(--palette-text-secondary);
|
||||
margin-right: calc(1.5 * var(--mini-unit));
|
||||
color: var(--v2-palette-text-secondary);
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { BaseButton, ClickOutside, Icon, Popover } from "coral-ui/components";
|
||||
import {
|
||||
BaseButton,
|
||||
ClickOutside,
|
||||
Icon,
|
||||
Popover,
|
||||
} from "coral-ui/components/v2";
|
||||
|
||||
import DecisionHistoryQuery from "./DecisionHistoryQuery";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Delay, Flex, Spinner } from "coral-ui/components";
|
||||
import { Delay, Flex, Spinner } from "coral-ui/components/v2";
|
||||
|
||||
import Main from "./Main";
|
||||
import Title from "./Title";
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
.root {
|
||||
padding: calc(0.5 * var(--mini-unit)) calc(0.5 * var(--mini-unit))
|
||||
calc(0.5 * var(--mini-unit)) 0;
|
||||
padding: var(--v2-spacing-2) var(--v2-spacing-1);
|
||||
}
|
||||
|
||||
.leftCol {
|
||||
@@ -8,6 +7,6 @@
|
||||
justify-content: center;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: calc(3 * var(--mini-unit));
|
||||
padding-top: 3px;
|
||||
margin-right: var(--v2-spacing-2);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Flex } from "coral-ui/components";
|
||||
import { Flex } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./DecisionItem.css";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
list-style-type: none;
|
||||
|
||||
& > * {
|
||||
border-bottom: 1px solid var(--palette-divider);
|
||||
border-bottom: 1px solid var(--v2-palette-decision-history-border);
|
||||
}
|
||||
& > *:last-child {
|
||||
border-bottom: 0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.root {
|
||||
height: 100%;
|
||||
font-size: calc(12rem / var(--rem-base));
|
||||
line-height: calc(12em / 12);
|
||||
color: var(--palette-divider);
|
||||
padding: 0 calc(0.5 * var(--mini-unit));
|
||||
font-size: var(--v2-font-size-1);
|
||||
line-height: var(--v2-line-height-reset);
|
||||
color: var(--v2-palette-timestamp);
|
||||
padding: 0 var(--v2-spacing-1);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
.root {
|
||||
padding: calc(1.5 * var(--mini-unit)) calc(2 * var(--mini-unit));
|
||||
}
|
||||
|
||||
.text {
|
||||
font-family: var(--v2-font-family-primary);
|
||||
font-weight: var(--v2-font-weight-primary-regular);
|
||||
font-size: var(--v2-font-size-2);
|
||||
line-height: var(--v2-line-height-body-short);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Flex, Typography } from "coral-ui/components";
|
||||
import { Flex } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./Empty.css";
|
||||
|
||||
const Empty: FunctionComponent<{}> = () => (
|
||||
<Flex justifyContent="center" alignItems="center" className={styles.root}>
|
||||
<Localized id="decisionHistory-youWillSeeAList">
|
||||
<Typography>
|
||||
<div className={styles.text}>
|
||||
You will see a list of your post moderation actions here.
|
||||
</Typography>
|
||||
</div>
|
||||
</Localized>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
.root {
|
||||
margin-top: var(--v2-spacing-1);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Flex } from "coral-ui/components";
|
||||
import { Flex } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./Footer.css";
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
.root {
|
||||
font-size: calc(12rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-regular);
|
||||
font-family: var(--font-family-sans-serif);
|
||||
line-height: calc(14em / 12);
|
||||
letter-spacing: calc(0.2em / 12);
|
||||
color: var(--palette-primary-main);
|
||||
text-decoration: none;
|
||||
line-height: var(--v2-line-height-reset);
|
||||
font-weight: var(--v2-font-weight-primary-bold);
|
||||
font-family: var(--v2-font-family-primary);
|
||||
font-size: var(--v2-font-size-1);
|
||||
color: var(--v2-palette-link-text);
|
||||
font-style: var(--v2-font-style-underline);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import { Link } from "found";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Icon, TextLink } from "coral-ui/components";
|
||||
import { Icon, TextLink } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./GoToCommentLink.css";
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
.root {
|
||||
font-size: calc(14rem / var(--rem-base));
|
||||
line-height: calc(16em / 12);
|
||||
/*
|
||||
Fallback begin
|
||||
|
||||
@@ -10,4 +8,9 @@
|
||||
word-break: break-all;
|
||||
/* Fallback end */
|
||||
word-break: break-word;
|
||||
color: var(--v2-palette-text-primary);
|
||||
font-weight: var(--v2-font-weight-primary-semi-bold);
|
||||
font-family: var(--v2-font-family-primary);
|
||||
line-height: var(--v2-line-height-body-short);
|
||||
font-size: var(--v2-font-size-2);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Typography } from "coral-ui/components";
|
||||
|
||||
import styles from "./Info.css";
|
||||
|
||||
interface Props {
|
||||
@@ -9,7 +7,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const Info: FunctionComponent<Props> = props => (
|
||||
<Typography className={styles.root}>{props.children}</Typography>
|
||||
<span className={styles.root}>{props.children}</span>
|
||||
);
|
||||
|
||||
export default Info;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Typography } from "coral-ui/components";
|
||||
|
||||
import DecisionItem from "./DecisionItem";
|
||||
import DotDivider from "./DotDivider";
|
||||
import Footer from "./Footer";
|
||||
@@ -10,6 +8,7 @@ import GoToCommentLink from "./GoToCommentLink";
|
||||
import Info from "./Info";
|
||||
import RejectedIcon from "./RejectedIcon";
|
||||
import Timestamp from "./Timestamp";
|
||||
import Username from "./Username";
|
||||
|
||||
interface Props {
|
||||
href: string;
|
||||
@@ -18,10 +17,6 @@ interface Props {
|
||||
onGotoComment?: React.EventHandler<React.MouseEvent>;
|
||||
}
|
||||
|
||||
const Username: FunctionComponent<{ username: string }> = ({ username }) => (
|
||||
<strong>{username}</strong>
|
||||
);
|
||||
|
||||
const RejectedComment: FunctionComponent<Props> = props => (
|
||||
<DecisionItem icon={<RejectedIcon />}>
|
||||
<Localized
|
||||
@@ -31,9 +26,7 @@ const RejectedComment: FunctionComponent<Props> = props => (
|
||||
<Info>{"Rejected comment by <Username></Username>"}</Info>
|
||||
</Localized>
|
||||
<Footer>
|
||||
<Typography variant="timestamp">
|
||||
<Timestamp>{props.date}</Timestamp>
|
||||
</Typography>
|
||||
<Timestamp>{props.date}</Timestamp>
|
||||
<DotDivider />
|
||||
<GoToCommentLink href={props.href} onClick={props.onGotoComment} />
|
||||
</Footer>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
.root {
|
||||
color: var(--palette-error-main);
|
||||
color: var(--v2-palette-error-main);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Icon } from "coral-ui/components";
|
||||
import { Icon } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./RejectedIcon.css";
|
||||
|
||||
const RejectedIcon: FunctionComponent = () => (
|
||||
<Icon className={styles.root}>cancel</Icon>
|
||||
<Icon size="md" className={styles.root}>
|
||||
cancel
|
||||
</Icon>
|
||||
);
|
||||
|
||||
export default RejectedIcon;
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
.root {
|
||||
font-size: var(--v2-font-size-2);
|
||||
font-weight: var(--v2-font-weight-primary-bold);
|
||||
font-family: var(--v2-font-family-primary);
|
||||
line-height: var(--v2-line-height-reset);
|
||||
text-transform: uppercase;
|
||||
font-size: calc(12rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-family: var(--font-family-sans-serif);
|
||||
line-height: calc(2 * var(--mini-unit));
|
||||
letter-spacing: calc(0.2em / 12);
|
||||
color: var(--palette-grey-main);
|
||||
color: var(--v2-palette-link-text);
|
||||
width: 100%;
|
||||
border-top: 1px solid var(--palette-divider);
|
||||
border-top: 1px solid var(--v2-palette-decision-history-border);
|
||||
text-align: center;
|
||||
padding-top: var(--v2-spacing-1);
|
||||
padding-bottom: var(--v2-spacing-1);
|
||||
|
||||
&:disabled {
|
||||
color: var(--palette-grey-lighter);
|
||||
color: var(--v2-palette-grey-lighter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { BaseButton } from "coral-ui/components";
|
||||
import { BaseButton } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./ShowMoreButton.css";
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
.root {
|
||||
color: var(--palette-text-secondary);
|
||||
font-family: var(--font-family-sans-serif);
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-size: calc(12rem / var(--rem-base));
|
||||
line-height: calc(14em / 12);
|
||||
letter-spacing: 0;
|
||||
color: var(--v2-palette-timestamp);
|
||||
font-family: var(--v2-font-family-primary);
|
||||
font-weight: var(--v2-font-weight-primary-bold);
|
||||
font-size: var(--v2-font-size-1);
|
||||
line-height: var(--v2-line-height-reset);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { RelativeTime } from "coral-ui/components";
|
||||
import { Timestamp } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./Timestamp.css";
|
||||
|
||||
@@ -9,7 +9,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const DecisionHistory: FunctionComponent<Props> = props => (
|
||||
<RelativeTime className={styles.root} date={props.children} />
|
||||
<Timestamp className={styles.root}>{props.children}</Timestamp>
|
||||
);
|
||||
|
||||
export default DecisionHistory;
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
.root {
|
||||
padding: 0 calc(0.5 * var(--mini-unit));
|
||||
background-color: #f2f2f2;
|
||||
color: var(--palette-text-primary);
|
||||
border-bottom: 1px solid var(--palette-grey-lighter);
|
||||
background: var(--v2-palette-decision-history-title-background);
|
||||
padding: var(--v2-spacing-1);
|
||||
color: var(--v2-palette-text-primary);
|
||||
border-bottom: 1px solid var(--v2-palette-decision-history-border);
|
||||
font-size: var(--v2-font-size-icon-medium);
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: var(--v2-spacing-2);
|
||||
}
|
||||
|
||||
.text {
|
||||
text-transform: uppercase;
|
||||
font-size: calc(12rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-family: var(--font-family-sans-serif);
|
||||
line-height: calc(12em / 12);
|
||||
letter-spacing: calc(0.2em / 12);
|
||||
color: var(--palette-text-primary);
|
||||
font-weight: var(--v2-font-weight-primary-bold);
|
||||
color: var(--v2-palette-text-primary);
|
||||
font-size: var(--v2-font-size-2);
|
||||
line-height: 1;
|
||||
font-family: var(--v2-font-family-primary);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { Flex, Icon, Typography } from "coral-ui/components";
|
||||
import { Flex, Icon } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./Title.css";
|
||||
|
||||
const Title: FunctionComponent = () => (
|
||||
<Flex className={styles.root} alignItems="center">
|
||||
<Icon>history</Icon>{" "}
|
||||
<Icon className={styles.icon} size="md">
|
||||
history
|
||||
</Icon>
|
||||
<Localized id="decisionHistory-yourDecisionHistory">
|
||||
<Typography container="span" className={styles.text}>
|
||||
Your Decision History
|
||||
</Typography>
|
||||
<span className={styles.text}>Your Decision History</span>
|
||||
</Localized>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
.root {
|
||||
color: var(--v2-palette-username-emphasis);
|
||||
font-weight: var(--v2-font-weight-secondary-bold);
|
||||
font-family: var(--v2-font-family-secondary);
|
||||
line-height: var(--v2-line-height-body-short);
|
||||
font-size: var(--v2-font-size-3);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import styles from "./Username.css";
|
||||
|
||||
interface Props {
|
||||
username: string;
|
||||
}
|
||||
|
||||
const Username: FunctionComponent<Props> = ({ username }) => (
|
||||
<strong className={styles.root}>{username}</strong>
|
||||
);
|
||||
|
||||
export default Username;
|
||||
+3
-7
@@ -17,13 +17,9 @@ exports[`renders correctly 1`] = `
|
||||
</Info>
|
||||
</Localized>
|
||||
<Footer>
|
||||
<ForwardRef(forwardRef)
|
||||
variant="timestamp"
|
||||
>
|
||||
<DecisionHistory>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</DecisionHistory>
|
||||
</ForwardRef(forwardRef)>
|
||||
<DecisionHistory>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</DecisionHistory>
|
||||
<Footer />
|
||||
<GoToCommentLink
|
||||
href="#"
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
exports[`renders correctly 1`] = `
|
||||
<ForwardRef(forwardRef)
|
||||
className="ApprovedIcon-root"
|
||||
size="md"
|
||||
>
|
||||
check
|
||||
check_circled
|
||||
</ForwardRef(forwardRef)>
|
||||
`;
|
||||
|
||||
@@ -9,9 +9,11 @@ exports[`renders correctly 1`] = `
|
||||
<Localized
|
||||
id="decisionHistory-youWillSeeAList"
|
||||
>
|
||||
<ForwardRef(forwardRef)>
|
||||
<div
|
||||
className="Empty-text"
|
||||
>
|
||||
You will see a list of your post moderation actions here.
|
||||
</ForwardRef(forwardRef)>
|
||||
</div>
|
||||
</Localized>
|
||||
</ForwardRef(forwardRef)>
|
||||
`;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<ForwardRef(forwardRef)
|
||||
<span
|
||||
className="Info-root"
|
||||
>
|
||||
children
|
||||
</ForwardRef(forwardRef)>
|
||||
</span>
|
||||
`;
|
||||
|
||||
+3
-7
@@ -17,13 +17,9 @@ exports[`renders correctly 1`] = `
|
||||
</Info>
|
||||
</Localized>
|
||||
<Footer>
|
||||
<ForwardRef(forwardRef)
|
||||
variant="timestamp"
|
||||
>
|
||||
<DecisionHistory>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</DecisionHistory>
|
||||
</ForwardRef(forwardRef)>
|
||||
<DecisionHistory>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</DecisionHistory>
|
||||
<Footer />
|
||||
<GoToCommentLink
|
||||
href="#"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
exports[`renders correctly 1`] = `
|
||||
<ForwardRef(forwardRef)
|
||||
className="RejectedIcon-root"
|
||||
size="md"
|
||||
>
|
||||
cancel
|
||||
</ForwardRef(forwardRef)>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<ForwardRef(forwardRef)
|
||||
<Timestamp
|
||||
className="Timestamp-root"
|
||||
date="2018-07-06T18:24:00.000Z"
|
||||
/>
|
||||
toggleAbsolute={true}
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</Timestamp>
|
||||
`;
|
||||
|
||||
@@ -5,19 +5,20 @@ exports[`renders correctly 1`] = `
|
||||
alignItems="center"
|
||||
className="Title-root"
|
||||
>
|
||||
<ForwardRef(forwardRef)>
|
||||
<ForwardRef(forwardRef)
|
||||
className="Title-icon"
|
||||
size="md"
|
||||
>
|
||||
history
|
||||
</ForwardRef(forwardRef)>
|
||||
|
||||
<Localized
|
||||
id="decisionHistory-yourDecisionHistory"
|
||||
>
|
||||
<ForwardRef(forwardRef)
|
||||
<span
|
||||
className="Title-text"
|
||||
container="span"
|
||||
>
|
||||
Your Decision History
|
||||
</ForwardRef(forwardRef)>
|
||||
</span>
|
||||
</Localized>
|
||||
</ForwardRef(forwardRef)>
|
||||
`;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { FunctionComponent } from "react";
|
||||
|
||||
import { PropTypesOf } from "coral-framework/types";
|
||||
import { LogoHorizontal } from "coral-ui/components";
|
||||
import { AppBar, Begin, Divider, End } from "coral-ui/components/AppBar";
|
||||
import { AppBar, Begin, Divider, End } from "coral-ui/components/v2/AppBar";
|
||||
|
||||
import { DecisionHistoryButton } from "./DecisionHistory";
|
||||
import NavigationContainer from "./Navigation";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { AppBarNavigation } from "coral-ui/components";
|
||||
import { AppBarNavigation } from "coral-ui/components/v2";
|
||||
|
||||
import NavigationLink from "./NavigationLink";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Link, LocationDescriptor } from "found";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { AppBarNavigationItem } from "coral-ui/components";
|
||||
import { AppBarNavigationItem } from "coral-ui/components/v2";
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
.button {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
margin-left: 5px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: var(--v2-palette-user-menu-button);
|
||||
}
|
||||
|
||||
.buttonText {
|
||||
font-size: calc(18rem / var(--rem-base));
|
||||
letter-spacing: calc(-0.2em / 18);
|
||||
font-family: var(--v2-font-family-secondary);
|
||||
color: var(--v2-palette-user-menu-button);
|
||||
font-size: var(--v2-font-size-4);
|
||||
margin-left: 2px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import {
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
DropdownButton,
|
||||
DropdownDivider,
|
||||
Popover,
|
||||
} from "coral-ui/components";
|
||||
} from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./UserMenu.css";
|
||||
|
||||
@@ -60,13 +60,15 @@ const UserMenu: FunctionComponent<Props> = props => (
|
||||
className={styles.button}
|
||||
onClick={toggleVisibility}
|
||||
ref={ref}
|
||||
variant="regular"
|
||||
size="small"
|
||||
variant="text"
|
||||
uppercase={false}
|
||||
>
|
||||
<ButtonIcon size="lg">account_circle</ButtonIcon>
|
||||
<ButtonIcon className={styles.icon} size="lg">
|
||||
account_circle
|
||||
</ButtonIcon>
|
||||
<span className={styles.buttonText}>{props.username}</span>
|
||||
{
|
||||
<ButtonIcon size="lg">
|
||||
<ButtonIcon className={styles.icon} size="lg">
|
||||
{visible ? "arrow_drop_up" : "arrow_drop_down"}
|
||||
</ButtonIcon>
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
import { withInView } from "coral-framework/lib/intersection";
|
||||
import { BaseButton, Spinner } from "coral-ui/components";
|
||||
import { BaseButton, Spinner } from "coral-ui/components/v2";
|
||||
|
||||
interface Props {
|
||||
inView: boolean | undefined;
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
.root {
|
||||
border: 1px solid var(--palette-success-main);
|
||||
border: 1px solid var(--v2-palette-button-outline-approve);
|
||||
box-sizing: border-box;
|
||||
border-radius: var(--round-corners);
|
||||
border-radius: var(--v2-round-corners);
|
||||
width: 65px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--palette-success-main);
|
||||
color: var(--v2-palette-button-outline-approve);
|
||||
&:not(:disabled):active {
|
||||
background-color: var(--palette-success-main);
|
||||
color: var(--palette-common-white);
|
||||
background-color: var(--v2-palette-button-outline-approve);
|
||||
color: var(--v2-colors-pure-white);
|
||||
}
|
||||
}
|
||||
|
||||
.invert {
|
||||
background-color: var(--palette-success-main);
|
||||
color: var(--palette-common-white);
|
||||
background-color: var(--v2-palette-button-outline-approve);
|
||||
color: var(--v2-colors-pure-white);
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-weight: var(--font-weight-bold);
|
||||
font-weight: var(--v2-font-weight-primary-semi-bold);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import cn from "classnames";
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { PropTypesOf } from "coral-framework/types";
|
||||
import { BaseButton, Icon } from "coral-ui/components";
|
||||
import { BaseButton, Icon } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./ApproveButton.css";
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { graphql } from "react-relay";
|
||||
import { Environment } from "relay-runtime";
|
||||
|
||||
import { BanCommentUserMutation as MutationTypes } from "coral-admin/__generated__/BanCommentUserMutation.graphql";
|
||||
import {
|
||||
commitMutationPromiseNormalized,
|
||||
createMutation,
|
||||
MutationInput,
|
||||
} from "coral-framework/lib/relay";
|
||||
|
||||
import { BanCommentUserMutation as MutationTypes } from "coral-admin/__generated__/BanCommentUserMutation.graphql";
|
||||
|
||||
const clientMutationId = 0;
|
||||
|
||||
const BanCommentUserMutation = createMutation(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { CommentAuthorContainer_comment as CommentData } from "coral-admin/__generated__/CommentAuthorContainer_comment.graphql";
|
||||
import { graphql, withFragmentContainer } from "coral-framework/lib/relay";
|
||||
import { Tag } from "coral-ui/components";
|
||||
import { Tag } from "coral-ui/components/v2";
|
||||
|
||||
import { CommentAuthorContainer_comment as CommentData } from "coral-admin/__generated__/CommentAuthorContainer_comment.graphql";
|
||||
|
||||
import styles from "./CommentAuthorContainer.css";
|
||||
|
||||
@@ -17,11 +18,11 @@ const CommentAuthorContainer: FunctionComponent<Props> = ({ comment }) => {
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Localized id="commentAuthor-status-banned">
|
||||
<div className={styles.authorStatus}>
|
||||
<div className={styles.authorStatus}>
|
||||
<Localized id="commentAuthor-status-banned">
|
||||
<Tag color="error">BANNED</Tag>
|
||||
</div>
|
||||
</Localized>
|
||||
</Localized>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,13 +1,52 @@
|
||||
$comment-content: var(--v2-colors-mono-900);
|
||||
$comment-blockquote-bg: var(--v2-colors-grey-100);
|
||||
$comment-highlight-bg: var(--v2-colors-yellow-500);
|
||||
$comment-link: var(--v2-palette-primary-main);
|
||||
$comment-link-active: var(--v2-palette-primary-darkest);
|
||||
|
||||
.root {
|
||||
composes: root from "coral-stream/shared/htmlContent.css";
|
||||
composes: bodyCommentV2 from "coral-ui/shared/typography.css";
|
||||
font-family: var(--v2-font-family-primary);
|
||||
font-size: var(--v2-font-size-3);
|
||||
line-height: var(--v2-line-height-body-comment);
|
||||
color: $comment-content;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
& * bold,
|
||||
& * strong {
|
||||
font-weight: var(--v2-font-weight-primary-bold);
|
||||
}
|
||||
& * italic,
|
||||
& * em {
|
||||
font-style: italic;
|
||||
}
|
||||
blockquote {
|
||||
background-color: $comment-blockquote-bg;
|
||||
padding: var(--mini-unit);
|
||||
margin: calc(2 * var(--mini-unit)) 0 calc(2 * var(--mini-unit))
|
||||
var(--mini-unit);
|
||||
border-radius: var(--round-corners);
|
||||
&::after {
|
||||
content: none;
|
||||
}
|
||||
&::before {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
mark {
|
||||
background-color: var(--palette-highlight);
|
||||
background-color: $comment-highlight-bg;
|
||||
padding: 0 2px;
|
||||
a {
|
||||
color: $comment-link;
|
||||
}
|
||||
}
|
||||
a {
|
||||
color: var(--palette-primary-dark);
|
||||
background-color: var(--palette-highlight);
|
||||
color: $comment-link;
|
||||
background-color: $comment-highlight-bg;
|
||||
padding: 0 2px;
|
||||
&:hover {
|
||||
color: $comment-link-active;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { memoize } from "lodash";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { createPurify } from "coral-common/utils/purify";
|
||||
import { Typography } from "coral-ui/components";
|
||||
|
||||
import styles from "./CommentContent.css";
|
||||
|
||||
@@ -131,10 +130,9 @@ const CommentContent: FunctionComponent<Props> = ({
|
||||
|
||||
// Finally we render the content of the Shadow DOM Tree
|
||||
return (
|
||||
<Typography
|
||||
<div
|
||||
className={cn(className, styles.root)}
|
||||
dangerouslySetInnerHTML={{ __html: node.innerHTML }}
|
||||
container="div"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { graphql, withFragmentContainer } from "coral-framework/lib/relay";
|
||||
import { HorizontalGutter, Timestamp } from "coral-ui/components";
|
||||
import { HorizontalGutter, Timestamp } from "coral-ui/components/v2";
|
||||
|
||||
import { CommentRevisionContainer_comment as CommentData } from "coral-admin/__generated__/CommentRevisionContainer_comment.graphql";
|
||||
import { CommentRevisionContainer_settings as SettingsData } from "coral-admin/__generated__/CommentRevisionContainer_settings.graphql";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
right: 0px;
|
||||
top: 2px;
|
||||
|
||||
border: 1px solid var(--palette-grey-lighter);
|
||||
border: 1px solid var(--v2-palette-grey-main);
|
||||
box-sizing: border-box;
|
||||
border-radius: var(--round-corners);
|
||||
padding: 2px var(--spacing-2) 2px var(--spacing-2);
|
||||
@@ -11,22 +11,21 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
font-size: calc(14rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-regular);
|
||||
font-family: var(--font-family-sans-serif);
|
||||
color: var(--v2-palette-grey-main);
|
||||
font-size: var(--v2-font-size-2);
|
||||
font-weight: var(--v2-font-weight-primary-regular);
|
||||
font-family: var(--v2-font-family-primary);
|
||||
line-height: 1.2;
|
||||
letter-spacing: calc(0.2em / 14);
|
||||
color: var(--palette-grey-lighter);
|
||||
|
||||
|
||||
&:active {
|
||||
background-color: var(--palette-primary-lightest);
|
||||
border-color: var(--palette-primary-main);
|
||||
color: var(--palette-primary-main);
|
||||
background-color: var(--v2-palette-primary-lightest);
|
||||
border-color: var(--v2-palette-primary-main);
|
||||
color: var(--v2-palette-primary-main);
|
||||
}
|
||||
}
|
||||
|
||||
.invert {
|
||||
background-color: var(--palette-primary-main);
|
||||
border-color: var(--palette-primary-main);
|
||||
color: var(--palette-text-light) ;
|
||||
}
|
||||
background-color: var(--v2-palette-primary-main);
|
||||
border-color: var(--v2-palette-primary-main);
|
||||
color: var(--v2-palette-text-light);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Localized } from "@fluent/react/compat";
|
||||
import cn from "classnames";
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { PropTypesOf } from "coral-framework/types";
|
||||
import { BaseButton } from "coral-ui/components";
|
||||
import { BaseButton } from "coral-ui/components/v2";
|
||||
|
||||
import styles from "./FeatureButton.css";
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
.category {
|
||||
color: var(--palette-error-darkest);
|
||||
font-size: var(--v2-font-size-4);
|
||||
font-weight: var(--v2-font-weight-primary-regular);
|
||||
font-family: var(--v2-font-family-primary);
|
||||
line-height: var(--v2-line-height-body-short);
|
||||
color: var(--v2-palette-accordion-label);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user