Compare commits

...
155 Commits
Author SHA1 Message Date
Nick FunkandWyatt Johnson d67c3d2907 Mark and allow word list timed out comments (#3097)
Will mark the comment's metdata as a word list
time out if it happens and also tag them with
suspect or banned word.

Then we show "possible suspect/banned word"
markers on the moderate card so moderators can
manually review them.

CORL-1264

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-08-11 22:05:50 +00:00
Wyatt Johnson 3398bd12c4 fix: export public flag, fix button (#3098) 2020-08-11 21:49:32 +00:00
Wyatt Johnsonandkodiakhq[bot] fc6de50dde fix: move deps (#3095)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-11 20:28:20 +00:00
Nick Funk 6c32316595 6.3.2 mobile and responsive UI fixes (#3096)
* Remove vertical padding and line height on badges

Allows them to align with the time and user name
text elements.

* Hide report button text on mobile screens

* Allow read more links to wrap text on mobile

* Wrap comment tags when on mobile screens

* Fix collapse alignment on mobile screens

* Update top bar responsive scaling

* Use MatchMedia inside ReportButton

* Fix justification on comment TopBarRight
2020-08-11 20:13:11 +00:00
bowser2010andkodiakhq[bot] 47abd030ef Adding new translation (#3093)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-10 21:13:22 +00:00
Nick Funkandkodiakhq[bot] 5ffb53d0eb Add media to comment data downloads (#3089)
This will update the admin and user CSV
downloads to include a "Media" column that
will specify the media type and the URL
for the media content.

CORL-1188

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-10 20:59:30 +00:00
Nick Funkandkodiakhq[bot] af842e98ee Move wordlist check after staff approval check (#3094)
This allows staff members to comment anything
they want, even if it's on the banned word list.

CORL-1255

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-10 20:42:47 +00:00
Kim Gardnerandkodiakhq[bot] 281f19d21c Bump version 6.3.2 (#3092)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-10 20:27:44 +00:00
Nick Funkandkodiakhq[bot] 45cd0e6628 [CORL-1248] Allow users to auto-show media in stream (#3086)
* Create preliminary media preferences

Allows user to select whether they want to
automatically show media or not.

CORL-1248

* Fix up the copy around media preferences

CORL-1248

* Rename EmbedPreferences to UserMediaSettings

CORL-1248

* Add error/validation messages to media prefs

CORL-1248

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-10 20:12:56 +00:00
Tessa Thornton adc508c7dc remove duplicate code and add comment to wrapper component (#3076)
* remove duplicate code and add comment to wrapper component:

* use react hooks recommended settings
2020-08-10 12:30:25 -04:00
Nick Funk 88a77f8712 Show media in the moderate view conversation modal (#3088) 2020-08-10 09:29:17 -06:00
Tessa Thornton 5d2ab3d061 adjust spacing on configure tab on mobile (#3087) 2020-08-07 12:02:46 -04:00
Tessa Thorntonandkodiakhq[bot] df6f666447 make spacing between discussions and headers explicit (#3084)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-06 19:20:57 +00:00
Vinhandkodiakhq[bot] e412b27c1e fix: auto focus on reply (#3083)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-06 19:03:04 +00:00
Vinhandkodiakhq[bot] 0fe0be832e fix: use same focus styling (#3078)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-06 18:48:08 +00:00
Tessa Thorntonandkodiakhq[bot] 288809ee14 add PERMIT argunment to auth directives that should be accessible to suspended or banned users (#3085)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-06 17:49:49 +00:00
Wyatt Johnsonandkodiakhq[bot] b97ec638b2 fix: ensure anonymousId or userId is added to the payload (#3075)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-06 16:35:02 +00:00
Wyatt JohnsonandVinh 2bbfbc7ddd [CORL-1242] Ensure SSO Access Tokens are not persisted (#3080)
* fix: ensure access tokens from sso are not persisted

* fix: increment storage key field to bust existing usage

Co-authored-by: Vinh <vinh@vinh.tech>
2020-08-06 15:20:46 +00:00
b029a01bd9 setTimeout Fixes (#3082)
* fix: fixed types and some unmanaged timeouts

* fix: refetch type

Co-authored-by: Chi Vinh Le <vinh@vinh.tech>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-06 14:56:57 +00:00
Wyatt Johnsonandkodiakhq[bot] 6fabeb2755 [CORL-1243] Subscription Errors (#3074)
* fix: fixed subscription event error

* fix: further subscription refinements

* fix: review fixes

* fix: exhastive deps

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-06 14:42:04 +00:00
Vinhandkodiakhq[bot] 459e11a5fa fix: correctly cleanup timeout (#3081)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-05 23:32:14 +00:00
Nick Funkandkodiakhq[bot] ce7d6969dd Add read more opens new tab feature flag (#3079)
If the feature flag READ_MORE_NEW_TAB is
set, then clicking on "Read more of this
conversation" will open a new tab.

CORL-1246

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-05 21:10:55 +00:00
Vinhandkodiakhq[bot] 6a8d6b07d6 [CORL-1240] Check existing data before handling subscriptions (#3077)
* fix: check existing data before handling subscriptions

* fix: typo

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-05 20:56:11 +00:00
Wyatt JohnsonandVinh 8ede245a8d feat: added data-coral-count to count elements (#3055)
Co-authored-by: Vinh <vinh@vinh.tech>
2020-08-05 19:10:13 +00:00
Nick Funkandkodiakhq[bot] 88eb9555c7 [CORL-1227] Fix scroll-able modal position popping (#3069)
* Disable scrolling on site moderators modal

The site moderator modal already has a scroll bar
inside it and its height is less than 480px. We
don't need a scrollbar on the modal background since
the modal window will always be fully visible on
even the smallest screens.

This eliminates the bug of the modal sliding away
when there are enough sites in the org to cause the
background scroll to be activated.

CORL-1227

* Stop checkboxes from shoving input element down

The checkbox input element that we style away
using ::before css was being shoved down the
dom non-relative to the checkbox root.

Now it's relative to the checkbox root and positioned
accordingly.

CORL-1227

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-05 15:49:33 +00:00
ce53134736 [CORL-794] Create a common date formatter (#3073)
* Create a common date formatter

Updates all uses of Intl.DateTimeFormat(...)
with re-usable date time formatter functions.

The formatter functions have default formatting
options, but these can be overridden.

CORL-794

* Include options in useMemo

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>

* Make date formatting accept single locale string

Makes formatDate and createDateFormatter accept
string | string[] | undefined for the locales
argument.

CORL-794

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-05 15:34:42 +00:00
0f1dd7d707 add react hooks eslint plugin (#3059)
* add eslint react hooks

* fix code breaking the rules-of-hooks eslint rule

* fix spinnerWhileRendering for tests

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-05 14:42:50 +00:00
Wyatt Johnsonandkodiakhq[bot] 9d02391062 [CORL-1239] Swap setTimeout for setLongTimeout (#3071)
* fix: ensure user editable time use setLongTimeout

* fix: fixed wrong type

* fix: fixed snapshots

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-04 18:24:31 +00:00
Wyatt Johnsonandkodiakhq[bot] 8aac2d33fc [CORL-1238] Duplicate User Race (#3068)
* fix: added a single retry to user create

* feat: added additional error context

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-04 18:09:55 +00:00
Tessa Thorntonandkodiakhq[bot] 3eddf5f155 [CORL-1233] Mobile display fixes (#3067)
* mobile display fixes

* show button full text at larger breakpoint

* update snaps

* hardcode in media query for reaction buttons

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-08-04 17:55:30 +00:00
Nick Funk 94ff8ff880 fix: replace outdated keys with signingSecrets (#3070)
Looks like this was missed during the migration
of `auth.integrations.sso.keys` renamed to
`auth.integrations.sso.signingSecrets`.

CORL-1159
2020-08-04 11:09:24 -06:00
Nick FunkandWyatt Johnson 7dfc064c9f Better use flex to align callout contents (#3060)
CORL-1201

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-08-03 17:25:47 -06:00
Wyatt Johnson d602cf873c fix: support mobile twitter links (#3066) 2020-08-03 16:51:15 +00:00
Wyatt Johnson 79627af8d6 fix: fixed incorrect connection access (#3064) 2020-08-03 15:21:09 +00:00
871d3f80c1 [CORL-1230] corrects logic for editing comments with media attachments (#3063)
* correctly attach media to edited comments

* ensure media can be removed in edits

* fix: updates to support repeat post

Co-authored-by: Kim Gardner <kgardnr@gmail.com>
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-07-31 18:03:54 +00:00
Wyatt Johnson f7d01174d7 fix: fixed overflow scrollbar appearing in dropdown (#3062) 2020-07-31 13:30:08 -04:00
Nick Funk 6966bb8d12 Replace positive/negative naming for success/error (#3058)
CORL-1200
2020-07-31 15:40:48 +00:00
Tessa Thornton 40ad2ed0cb remove hook causing crash from conversation modal replies (#3057) 2020-07-31 14:37:05 +00:00
802f656caa Stream UI bugfixes (#3041)
* fix: various ui fixes

* fix: tooltip button active color

* fix: teal color

* fix: RTE borders

* fix: snapshots

* fix: reduce padding of show more of this conversation button

* Fix font weight fallback values

* Replace RTE validation messages with v3 CallOuts

CORL-1213

* More styling classnames

* chore: remove not used style

* fix: reaction button primary color

* fix snapshots

* harmonize data-variant on buttons

* [CORL-1215] Install Style Tweaks (#3046)

* fix logic around repeat posts with or without media embeds: (#3042)

* fix: restore ReportCommentEvent (#3037)

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>

* fix: fixed issue with graphiql (#3043)

* README.md Update (#3045)

* chore: update README.md

* fix: removed README from doctoc

* fix: replaced emoji codes with emjoi

* fix: removed emoji's due to browser rendering issues

* fix: fixed bugs with install styles

Co-authored-by: Tessa Thornton <tessathornton@gmail.com>
Co-authored-by: Vinh <vinh@vinh.tech>

* fix: remove lineheight css variables and make them relative

* fix: adjust line-heights

* fix: update snapshots

* More css bindings for client styling

Set bindable class on community guidelines
Set bindable classname on "Comment on" label

* fix: more tweaks

* fix: snapshots

* fix: lint and tests

Co-authored-by: nick-funk <nick.funk@outlook.com>
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
Co-authored-by: Tessa Thornton <tessathornton@gmail.com>
2020-07-31 00:19:59 +02:00
dfdea2b9d2 [CORL-1150] Discussions Tab (#3050)
* feat: Added Site.topStories edge

* feat: Added User.ongoingDiscussions edge

* connect discussions tab to relay

* style discussions tab

* add message if no ongoing discussions

* style site name in story row

* fix: make line-heights relative

* add custom class hooks

* feat: condition display based on feature flag

* add target attribute to story links

* fix: expose some featureFlags

* fix: fixed sorting

* fix: copy fixes

Co-authored-by: tessalt <tessathornton@gmail.com>
Co-authored-by: Chi Vinh Le <vinh@vinh.tech>
2020-07-30 17:18:59 -04:00
Wyatt Johnson 9a9c92d360 Site Moderator Fixes (#3054)
* fix: disable banning for site moderators

* fix: fixed redirect issue for site moderators
2020-07-30 16:04:28 +00:00
ceadcc7ae1 fix warning about media key in tests (#3048)
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-07-29 23:29:51 +00:00
Kim GardnerandWyatt Johnson e0db803a21 Bump version 6.3.1 (#3053)
* Bump version 6.3.1

* chore: bump version in package-lock.json

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-07-29 19:12:05 -04:00
Tessa ThorntonandWyatt Johnson 7a099bbf05 don't save clientMutationId when creating announcement (#3049)
* don't save clientMutationId when creating announcement

* move mutationId filtering from resolver to mutation

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-07-29 21:38:12 +00:00
Wyatt Johnson 51112a11c0 [CORL-1219] Media Type Fixes (#3051)
* fix: better graphql types

* fix: fixed tests

* fix: fixed tests
2020-07-29 21:11:53 +00:00
Wyatt Johnson 6e50b28d8b [CORL-1149] Active Stories (#3040)
* fix: removed type assertions in place of stricter types

* fix: fixed bug with module ordering

* feat: support for story activity jsonp route
2020-07-28 16:34:05 +00:00
Tessa Thornton 1f72cdbfb3 ensure preloaded css is actually used (#3047) 2020-07-28 08:42:39 -04:00
Wyatt Johnson 87aba459d6 README.md Update (#3045)
* chore: update README.md

* fix: removed README from doctoc

* fix: replaced emoji codes with emjoi

* fix: removed emoji's due to browser rendering issues
2020-07-24 19:06:33 +00:00
Wyatt Johnson 9aa4591655 fix: fixed issue with graphiql (#3043) 2020-07-24 17:19:08 +00:00
VinhandWyatt Johnson 87d32680f0 fix: restore ReportCommentEvent (#3037)
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-07-24 16:48:02 +00:00
Tessa Thornton 25a1dcdf8d fix logic around repeat posts with or without media embeds: (#3042) 2020-07-23 15:36:08 -06:00
Tessa ThorntonandWyatt Johnson e90272aa58 remove debug style from comment stream (#3038)
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-07-22 23:32:27 +00:00
Tessa ThorntonandWyatt Johnson bbbff98270 pass custom stream css url through to html (#3039)
* pass custom stream css url through to html

* rename streamcssURL to customCSSURL

* only enable custom css query on stream route

* Update src/core/server/app/router/client.ts

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>

* simplify template for client html

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-07-22 18:57:47 +00:00
Nick Funkandkodiakhq[bot] fe19ffd7e1 Show nice error message on network time out (#3036)
Shows "Network error. Please refresh your page
and try again." when the retry middleware times
out from too many attempts on failed/timed out
requests.

CORL-1199

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-22 00:02:27 +00:00
Nick Funk 7f98f13990 Send staff comments to Slack with all comments enabled (#3035)
When we set up a Slack channel, you can select to have
"All comments" sent to the slack channel. If we do this
we want staff comments to come through as well.

This wasn't happening before because there is a `staffCreated`
flag instead of `created` when a staff member comments.

So we change the trigger return type to an array, and when
a staff comment appears, return `staffCreated` as well as
`created` so the all filter lets it through.

I also changed `getBlocks(...)` to `getContent(...)` as it
now returns a JSON object with both a `blocks` array and a
`text` string field. This fixes the problem where Slack would
notifications would say "this content cannot be displayed".
Now it will say the text provided.

CORL-1172
2020-07-21 18:01:38 +00:00
Nick Funk 1a9bd27236 Implement TODO for rejected message when replying (#3034)
Implements the proper callout for when a user
submits a comment with a banned word when replying
to another comment.

CORL-1191
2020-07-20 16:44:49 +00:00
dependabot[bot] 536e804d61 chore(deps): bump lodash from 4.17.15 to 4.17.19 (#3033)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-20 14:53:21 +00:00
Tessa Thorntonandkodiakhq[bot] 43d5d56c90 correct dashboard spacing (#3032)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-17 18:53:48 +00:00
Tessa Thorntonandkodiakhq[bot] cdcc991255 [CORL-1195] Fix bug with displaying site dashboards (#3031)
* fix bug where dashboard would not display data for sites beyond first page of results

* remove unused param

* remove unused file

* undo rename

* rename selectedSite to site

* check that sites.edges.length is greater than 0

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-17 17:25:19 +00:00
Tessa Thornton b221baff82 [CORL-1194] correct typo in config (#3030)
* correct typo in config

* update snap
2020-07-17 15:14:52 +00:00
Wyatt Johnsonandkodiakhq[bot] 5b589bfe2b [CORL-1180] Moderation + Editing Improvements (#3020)
* fix: handle moderating edited comments better

* fix: add back deleted audit trail entry

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-16 19:59:51 +00:00
Wyatt Johnsonandkodiakhq[bot] 4f5c0e285c [CORL-1192] Reduced Security Mode (#3027)
* feat: add support for disabling persisted query requirements

* fix: fixed type errors

* fix: rename flag

* fix: fixed logic around validation

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-16 19:34:16 +00:00
Tessa Thorntonandkodiakhq[bot] f26ab60398 [CORL-1185] translate error from iframe embeds (#3026)
* translate error from iframe embeds

* use transtlate function for iframe error message

* fix import order

* Fix typo in translation key

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-16 18:45:03 +00:00
Tessa Thorntonandkodiakhq[bot] e7f395190d [CORL-1183] Fix edit comment form (#3022)
* Fix edit comment form

* clean up editcomment stack for media attachments

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-16 18:29:05 +00:00
Tessa Thorntonandkodiakhq[bot] ace252eb72 continue polling for twitter iframe height longer (#3023)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-16 18:14:14 +00:00
Tessa Thorntonandkodiakhq[bot] 933d82e7c9 use padding-bottom trick to make giphy mp4s responsive (#3024)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-16 17:59:09 +00:00
Wyatt Johnsonandkodiakhq[bot] 6e64e6a01c fix: fixed bug with select dropdown (#3021)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-16 17:45:47 +00:00
Nick Funkandkodiakhq[bot] bb48e1fe33 Tweak up indent level padding/margins (#3025)
CORL-1186

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-16 17:31:55 +00:00
Nick Funkandkodiakhq[bot] 58a91c2e42 Replace Dashboard - staff comments icon (#3028)
The badge icon was removed from material fonts.
There are several icons in this category that are
in flux on material's site. Lets keep a close eye
on this as it could mean other icons stop working
in future as well.

CORL-1184

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-07-16 17:18:07 +00:00
Nick Funk 6a5a18e3a4 Enforce max width on mod card embeds (#3019)
Some gifs are too wide for the mod cards. Set
a max-width and force it on the media/iframe
so that it doesn't push out mod card controls.

CORL-1179
2020-07-16 16:18:02 +00:00
Wyatt Johnson d43fbe357a fix: add 'self' to the frame-ancestors directive (#3018) 2020-07-15 18:47:07 +00:00
Nick FunkandChi Vinh Le 5c863f1307 [CORL-1155] Fix theming for rebranded stream/admin (#3012)
* Repair theming and CSS variables for the rebrand

This separates the CSS variables into three sections
for admin, stream, as well as a shared set between
them.

This also adds injection of the raw colours from the
design team into post css variables.

Lastly, this re-maps the existing theme variables to
a new consolidated set with fallbacks for compatibility.

Since this is a singular commit from various WIP commits,
I am crediting @cvle as well as myself for this work.

Thank you all who helped make this rebrand with theming
possible!

CORL-1155

Co-authored-by: Chi Vinh Le <vinh@vinh.tech>

* Convert old css variables in CallOut

* Rename postive/negative => success/error

CORL-1155

* Change some CSS Variable names

* fix TextField/PasswordField colors

Co-authored-by: Chi Vinh Le <vinh@vinh.tech>
2020-07-15 18:20:25 +00:00
Tessa ThorntonandWyatt Johnson d4cb9cde9b [CORL-1174] Set height on iframe embeds in moderate cards (#3017)
* set height on iframe embeds in moderate cards

* fix: removed stripTags from server code

Co-authored-by: Wyatt Johnson <me@wyattjoh.ca>
2020-07-15 14:58:24 +00:00
c59c345756 [CORL-1108] Media Embeds (#3010)
* Create Twitter and YouTube embed components

Uses the `/api/oembed` endpoint to proxy the
oembed requests that the embed components drop
into an iframe.

CORL-1012

* Create preliminary embed link parsing/storage

CORL-1012

* Create preliminary embed section on comments

CORL-1012

* Preliminarily add admin embed config options

CORL-1012

* Show a "missing" message when embed is unavailable

CORL-1012

* Simplify naming of embeds in schema

embedLinks -> embed

CORL-1012

* Rename oEmbedHandler to oembedHandler

CORL-1012

* add backend services for giphy

* search gifs on frontend

* display selected gif

* show gif previews

* display giphy attribution and no results text

* save a gif to a comment

* use embeds feature for gif embeds

* clean up gif/video/tweet display

* style and configure post comment form

* preview and confirm twitter and youtube embeds

* moderate embeds on server

* update reply and edit forms

* update snaps

* fix some of the tests

* fix tests and types

* fix tests

* fix types

* show gifs in moderate cards

* correctly attach embeds to comments

* make gif rating configurable

* make gif rating configurable

* configure giphy api key

* refactor comment form

* only allow embeds if settings enabled

* scale youtube

* resize embeds if necessary

* make tweets and videos responsive

* set maxwidth on tweet embeds

* update copy for embed config

* force gif search results to fit container

* prevent double posting of gifs

* undo hiding html if empmty because now it doesn't contain random break tags

* use downsampled preview images

* update fixtures and snapshots

* remove unused css

* add i18n string

* remove console logs

* Fix styles on logged-out comment form

* click to pause gif in moderation

* style youtube and twitter embeds in mod stream"

* use mp4s for stream gifs

* use mp4 for moderation gifs

* clean up commentform

* fix dom tests

* update rte

* import oembed module with correct casing

* bump rte

* add correct return type for setInterval

* add migration for embeds config

* catch errors from gif search

* return early from iframe container size calculation if width and height are set

* remove unused classnames

* make giphy api key protected

* reorganize tenant embed settings schema

* update schema on backend to support single comment embed instead of array

* move findEmbedLinks to common

* wrap error

* return function for linkify instead of ternary

* remove unused url param

* clean up oembed service

* remove conditional in repeat post check

* use joi to validate giphy responses

* fix types for embeds

* fix optimistic responses

* move attachEmbeds function

* update snapshots

* fix: improved repeatPost checking

* force case change on oembed

* force rename file name

* feat: Rename Embed -> Media

* fix: cleanup of service functions

* fix: moved types

* fix: fixed logic bug

* fix: fixed translation

* show embeds on history comments

* fix: fixed iframe csp and query param bug

* correct validation for twitter oembed

* feat: save youtube still

* fix: typeerror

* fix: fixed errors related to final form

* fix: fixed issue with types

* fix: added docs to the schema

* fix: linting + tests

Co-authored-by: nick-funk <nick.funk@outlook.com>
Co-authored-by: Wyatt Johnson <me@wyattjoh.ca>
2020-07-15 02:16:06 +00:00
Wyatt Johnson f8234e53ed fix: added Other as flagging reason to ui (#3014) 2020-07-13 22:23:54 +00:00
Wyatt Johnson 7b2cdbad49 [CORL-1134] Site Moderators (#2995)
* feat: added server support for site moderators

* feat: added unscoped property to @auth directive

* feat: added frontend support for site moderator feature

* feat: added site moderator support to stream

* fix: linting

* fix: updated snapshots
2020-07-13 18:19:22 +00:00
Wyatt Johnson 00e074d49d fix: increased body size limit, added config option (#3011) 2020-07-09 22:02:01 +00:00
Natalie StroudandNatalie Stroud d848fc193e Fixed Spanish translation typo (#3008)
* Changed Envira to Enviar

* Changed Envira to Enviar

Co-authored-by: Natalie Stroud <stroudn1@nku.edu>
2020-06-30 01:48:24 +00:00
Vinhandkodiakhq[bot] 2acc761a5d [CORL-1074] Upgrade dependencies (#2999)
* chore: upgrade eslint, typescript

* chore: upgrade deps

* chore: revert upgrade ts-node-dev

* chore: revert unneeded comments

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-06-26 22:38:52 +00:00
Wyatt Johnsonandkodiakhq[bot] 0db5bc846d fix: use [contenthash] for more consistancy (#3002)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-06-26 22:09:23 +00:00
Wyatt Johnsonandkodiakhq[bot] e57940c418 fix: fixed usernames not displaying (#3005)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-06-26 21:51:13 +00:00
Wyatt Johnsonandkodiakhq[bot] ccb8f1defa fix: fixed anchor link for view conversation (#3006)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-06-26 21:36:10 +00:00
Wyatt Johnson 878c3bb3c0 fix: updated copy to reflect data (#3007) 2020-06-26 21:20:10 +00:00
Wyatt Johnson 86c81c7b9f feat: added kodiak config (#3003) 2020-06-26 19:47:25 +00:00
Wyatt Johnson 302613a185 Merge branch 'release/6.2' 2020-06-25 13:08:56 -06:00
Wyatt Johnson bf04b4c2a6 [CORL-1156] Q&A Feature Flag Fix (#3000)
* fix: fixed bug with feature flag handling

* chore: version bump
2020-06-25 18:59:03 +00:00
Wyatt Johnson f3ef9ef778 Replace nodemailer with emailjs (#2983)
* chore: replace nodemailer with emailjs

* fix: bumped version
2020-06-24 22:24:37 +00:00
Wyatt Johnson db8c9de0e7 Bump 6.3.0 (#2996)
* chore: bump version 6.3.0

* chore: upgrade mongodb
2020-06-23 17:05:00 +00:00
VinhandWyatt Johnson f2bf026740 [CORL-1129] Form initialization and reset bug (#2991)
* fix: form initialization and reset bug

* fix: test

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-06-22 23:39:07 +00:00
Wyatt Johnson 625c38a758 Merge branch 'release/6.2' 2020-06-22 10:35:23 -06:00
Wyatt Johnson 9022532525 [CORL-1148] Chrome Local Storage Issues (#2994)
* fix: moved storage access inside try/catch

* chore: version bump
2020-06-22 16:29:06 +00:00
Nick Funk caa4895b97 Clear session token on tenant install (#2990)
CORL-1122
2020-06-16 21:24:00 +00:00
dependabot[bot]andWyatt Johnson d1ee7d39f3 chore(deps): bump apollo-server-express from 2.11.0 to 2.14.2 (#2977)
* chore(deps): bump apollo-server-express from 2.11.0 to 2.14.2

Bumps [apollo-server-express](https://github.com/apollographql/apollo-server) from 2.11.0 to 2.14.2.
- [Release notes](https://github.com/apollographql/apollo-server/releases)
- [Changelog](https://github.com/apollographql/apollo-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/apollographql/apollo-server/compare/apollo-server-express@2.11.0...apollo-server-express@2.14.2)

Signed-off-by: dependabot[bot] <support@github.com>

* fix: adapted for module upgrade

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Wyatt Johnson <me@wyattjoh.ca>
2020-06-16 14:59:09 +00:00
feaf4858df [CORL-1126] Run regex in a sandbox so it can time out (#2988)
* Run regex in a sandbox so it can time out

If it times out, we flag it and system withhold
it for future analysis.

CORL-1126

* Pass regex and test string into wordList sandbox

Allows us to use the pre-cached regex instead of
regenerating it via an in-line script copy.

CORL-1126

* feat: improve script reuse

* fix: renamed some functions

* fix: improve script performance

* feat: added testString to log output if it times out

* fix: fixed issue with form alert not showing

* fix: use a timeout from config

Co-authored-by: Wyatt Johnson <me@wyattjoh.ca>
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-06-12 18:09:37 +00:00
ebe7731222 Stream Rebranding (#2926)
* [CORL-901] Rebrand comment actions and body (#2889)

* [ADR] Use Relay over Apollo (#2881)

* chore: ADR on Relay and Apollo

* chore: typo

* chore: add neg cons

* chore: add another pos

* chore: remove neg, because apollo needed an introspection query as a build step too..

* chore: fix number

* chore: deco

* chore: typo

* chore: clarification

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>

* chore: bump 6.0.0 (#2891)

* fix: added more checks to migration (#2894)

* Update stream username to new branding variables

CORL-901

* Update badges/tags to use new v2 controls

CORL-901

* Update timestamps to use new branding stream side

CORL-901

* Update stream edit action to new branding

CORL-901

* Update comment html body to new branding

CORL-901

* Update comment action buttons to new branding

CORL-901

* Update responsive styles for action buttons

CORL-901

* Set comment link colors to new branding blue

CORL-901

* Add children prop on ButtonsBar to align with tests

CORL-901

* Make Reported button text bolded and vivid red

CORL-901

* Make reaction buttons stream blue when reacted

CORL-901

* Make user badges bold text

CORL-901

* Set margins on comment action buttons

CORL-901

* Set aria-labels on reaction buttons

Ensures that we always have a usable aria
even when the reaction button is just an icon.

CORL-901

* Set aria-label's on Reply and Share button's

CORL-901

* Update tests to match stream branding changes

CORL-901

* Update color of "Read More of this conversation"

CORL-901

Co-authored-by: Vinh <vinh@vinh.tech>
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>

* [CORL-942] In-Stream Mod rebranding (#2902)

* [ADR] Use Relay over Apollo (#2881)

* chore: ADR on Relay and Apollo

* chore: typo

* chore: add neg cons

* chore: add another pos

* chore: remove neg, because apollo needed an introspection query as a build step too..

* chore: fix number

* chore: deco

* chore: typo

* chore: clarification

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>

* chore: bump 6.0.0 (#2891)

* fix: added more checks to migration (#2894)

* Update stream username to new branding variables

CORL-901

* Update badges/tags to use new v2 controls

CORL-901

* Update timestamps to use new branding stream side

CORL-901

* Update stream edit action to new branding

CORL-901

* Update comment html body to new branding

CORL-901

* Update comment action buttons to new branding

CORL-901

* Update responsive styles for action buttons

CORL-901

* Set comment link colors to new branding blue

CORL-901

* Add children prop on ButtonsBar to align with tests

CORL-901

* Make Reported button text bolded and vivid red

CORL-901

* Make reaction buttons stream blue when reacted

CORL-901

* Make user badges bold text

CORL-901

* Set margins on comment action buttons

CORL-901

* Set aria-labels on reaction buttons

Ensures that we always have a usable aria
even when the reaction button is just an icon.

CORL-901

* Set aria-label's on Reply and Share button's

CORL-901

* Update tests to match stream branding changes

CORL-901

* Update color of "Read More of this conversation"

CORL-901

* Update caret container to new branding

CORL-942

* Update moderation menu buttons to new branding

CORL-942

* Update in-stream ban popover to new branding

CORL-942

* Update reject tombstone to new branding

CORL-942

Co-authored-by: Vinh <vinh@vinh.tech>
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>

* [CORL-939] Rebrand RTE and reply (#2904)

* [ADR] Use Relay over Apollo (#2881)

* chore: ADR on Relay and Apollo

* chore: typo

* chore: add neg cons

* chore: add another pos

* chore: remove neg, because apollo needed an introspection query as a build step too..

* chore: fix number

* chore: deco

* chore: typo

* chore: clarification

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>

* chore: bump 6.0.0 (#2891)

* fix: added more checks to migration (#2894)

* Update stream username to new branding variables

CORL-901

* Update badges/tags to use new v2 controls

CORL-901

* Update timestamps to use new branding stream side

CORL-901

* Update stream edit action to new branding

CORL-901

* Update comment html body to new branding

CORL-901

* Update comment action buttons to new branding

CORL-901

* Update responsive styles for action buttons

CORL-901

* Set comment link colors to new branding blue

CORL-901

* Add children prop on ButtonsBar to align with tests

CORL-901

* Make Reported button text bolded and vivid red

CORL-901

* Make reaction buttons stream blue when reacted

CORL-901

* Make user badges bold text

CORL-901

* Set margins on comment action buttons

CORL-901

* Set aria-labels on reaction buttons

Ensures that we always have a usable aria
even when the reaction button is just an icon.

CORL-901

* Set aria-label's on Reply and Share button's

CORL-901

* Update tests to match stream branding changes

CORL-901

* Update color of "Read More of this conversation"

CORL-901

* Update caret container to new branding

CORL-942

* Update moderation menu buttons to new branding

CORL-942

* Update in-stream ban popover to new branding

CORL-942

* Update reject tombstone to new branding

CORL-942

* Update replyTo and rte to new branding

CORL-939

Co-authored-by: Vinh <vinh@vinh.tech>
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>

* Update message box to new branding

CORL-981

* Update user profile comment history to new branding

CORL-983

* Update stream tabs to new branding

CORL-982

* Update my profile tab bar to new branding

CORL-902

* Update download comments to new branding

CORL-902

* The Lord of the Buttons: Return of the Buttons

* Update the notification settings area to new branding

CORL-984

* Update the ignored users area to new branding

CORL-984

* Update change username to new branding

CORL-984

* Fixing snaps after rebase

* Use label instead of div for InputLabel's

Root element is now a label so that axe
will stop complaining that it can't find
the 'for' id on the label elements.

CORL-984

* More spacing tweaks for change username

CORL-903

* Update change email address to new branding

CORL-984

* Update change password to new branding

CORL-984

* Flesh out colour styles for v3 buttons

CORL-984

* Preliminarily update delete account to new branding

CORL-984

* Ensure client CSS style compatibility

CORL-984

* Update delete flow to new branding

CORL-984

* Add client classes to the delete account modal

CORL-984

* Further tweaks to the delete account modal

Modal callouts updated to new branding.
Deletion request callout updated to new
branding.
Fixing up tests that somehow were passing
before?
Fixing some margins and spacing around
deletion section.

* Move the account deletion callout to top

Puts it at the top of the my profile tab
so that it's clearly visible you are
deleting your account.

CORL-998

* Add first-class icon and title support to callouts

CORL-969

* Bold checkbox text when checked

CORL-984

* Finalize v3 buttons to match spec

This should be the last major change to
v3 buttons as the spec seems to have
solidified.

CORL-969

* Add in new stream red to colours

Use it for the negative v3 callouts

CORL-969

* Touch up some spacing on delete account

CORL-984

* Create tombstone component

Use it for ignored and deleted account
tombstones instead of the old callout.

CORL-969

* Use new tombstones in comment stream

CORL-969

* Update banned callout to new branding

CORL-969

* Set callout body text to regular font weight

CORL-969

* Update suspended callout to new branding

CORL-969

* Update closed stream callouts to new branding

CORL-969

* Update in-moderation callouts to new branding

CORL-969

* Update stream validation message to v3

CORL-969

* Improve ignored commenter management

Show "you are no longer ignoring" a
commenter when you choose to no longer
ignore them.

CORL-457

* Prettier cleanup after rebase off master

Somehow this was missed, probably needed to
kill and reload VSCode before I committed the
rebase.

* Switch previous callouts to use icon and title

CORL-969

* Update configure checkboxes to new branding

CORL-903

* Update Config > Q&A to new branding

CORL-903

* Update Config > Open/Close Stream to new branding

CORL-903

* Add validation message to config stream checkboxes

CORL-903

* Remove double list handling for Pref>Ignored

CORL-969

* Show experimental tag beside Q&A config

CORL-1051

* Move live update setting to its own section

CORL-903

* Remove moderation link from config area

CORL-903

* De-capitalize all the labels in configure

CORL-903

* Update message box config to new branding

Also moves it to new location in config.

CORL-903

* Re-brand the sign in/out field on the stream

CORL-1042

* Update tests for add message flow

CORl-903

* Rebrand Sign In/Up modals

CORL-999

* Re-brand SSO sign in/up modals

CORL-999

* Re-brand stream sorting controls

CORL-1043

* Create new stream focused colorFromMeta variant

* Rebrand go to moderation buttons

CORL-799

* Rebrand stream moderation drop-down

CORL-799

* Rebrand the report comment flow

Expands the report comment dialogs under
the comment instead of as a popover.
Also adds in the new branding styles.

CORL-941

* Rebrand the main stream tab bar

CORL-799

* Add new abusive reporting options

CORL-1009

* Rebrand featured comments

CORL-968

* Rebrand the community guidelines

CORL-1041

* Rebrand the share button

CORL-940

* Update style names on buttons

marginSize -> paddingSize
textSize -> fontSize

* Rebrand single conversation view

CORL-904

* Make indented comments grey coloured

CORL-904

* Make indented comment borders thinner

CORL-904

* Tweak colours/margins on single conversation view

CORL-904

* Add show comment on single conversation tombstones

CORL-412

* Rebrand single conversation view title

CORL-904

* Add clean target to package.json

Allows us to direct call gulp clean easily.

* Rebrand client side not found page

CORL-1025

* Rebrand password reset flow

CORL-1025

* Rebrand unsubscribe from notifications flow

CORL-1025

* Rebrand email confirmation flow

CORL-1025

* Rebrand download comments flow

CORL-1025

* Fix up account tests after rebrand

CORL-1025

* Add COMMENT_REPORTED_ABUSIVE to moderate card fragment

* Rebrand user ignore flow

Somehow this slipped through the cracks, fixed
it up now

* [CORL 1010] Collapse comment threads (#2976)

* toggle open and closed comment + replies

* show username and date for collapsed comment

* toggle comments and replies open and closed

* keep collapsed state of comments in reply list

* style collapsed comment toggle

* add css class overrides

* style answered comments when collapsed

* adjust spacing on collapse button:

* add hover styles

* add aria labels and update snapshots

* Fix tests and snaps after rebase

* Make main stream tabs visible on mobile (iPhone 5)

* Remove double horizontal rule under My Comments

Horizontal rule wasn't conditionally showing
when we toggled ability to let users download
comments on and off.

* Add aria labelling to main stream tabs

Can now pass in a localization id to assign
aria-label/title to the tab.

* Add localization to account not found

* Update snapshots

Co-authored-by: Vinh <vinh@vinh.tech>
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
Co-authored-by: Tessa Thornton <tessathornton@gmail.com>
2020-06-12 09:23:28 -06:00
Tessa ThorntonandWyatt Johnson 8966dad344 [CORL-1016] Admin Dashboard (#2942)
* count things in redis

* add rest routes for daily comment totals

* add route for new commenters

* retrieve hourly totals for new commenters and comments

* add rate limiting

* add routes and components for dashboard

* add top stories component

* add activity charts

* clean up rest responses

* style dashboard components

* make dashboard site-aware

* change new commenters to new signups

* generate new signups by day chart

* update status pie chart

* update status pie chart

* allow site selection in dashboard

* cache daily signups

* count user bans in redis

* clean up route and method names

* clean up comment statuses chart and change from pie to bar

* fix package lock

* make daily counts time zone aware

* count rejected comments

* clean up today counts

* count comments from site

* store hourly keys in utc

* show daily user signups

* move siteID from params to query params

* add average line for daily comments chart

* make average comments count hourly

* show percent values for rejected comments

* style dashboard

* simplify dashboard rest routes

* style today totals and top stories

* style signup and comment activity chart

* add site selector to nav

* feat: redis/mongo refactor

* fix: some small tweaks

- Added comments to magic numbers
- Added errors for missing input
- Consolidated promise resolutions

* Revert "add site selector to nav"

This reverts commit 1c2b1dee34fb2742b04932079fd45f7f3de98418.

* show first site dashboard by default

* style dashboard site switcher

* updte snapshot

* add dashboard 118n keys

* udpate comment activiyt chart with legend and tooltip

* implement refresh button and loading states

* change colours of charts for today

* adjust today values spacing

* remove unused package

* don't pass redis into oauth strat

* remove unused package

* Revert "remove unused package"

This reverts commit 5b7c83a072604810ce7097865655e9ef8114d9e0.

* fix merge conflicts

* Fix icons bug on smaller screens

* resolve merge conflict

Co-authored-by: Wyatt Johnson <me@wyattjoh.ca>
2020-06-12 10:39:28 -04:00
Wyatt Johnson 4179306cd0 fix: fixed naming of config (#2980) 2020-06-12 05:22:23 +00:00
dependabot[bot] 2c0153047e chore(deps): bump graphql-playground-html from 1.6.13 to 1.6.22 (#2984)
Bumps [graphql-playground-html](https://github.com/graphcool/graphql-playground) from 1.6.13 to 1.6.22.
- [Release notes](https://github.com/graphcool/graphql-playground/releases)
- [Commits](https://github.com/graphcool/graphql-playground/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-06-11 22:28:43 +00:00
Wyatt Johnson 21cd47f6ed [CORL-1077] Rudderstack Integration (#2987)
* feat: added rudderstack support with events

- Added events for
  - Comment Moderated
  - Comment Created
  - Story Created
  - Comment Reaction Created
  - User Flagged Comment

* fix: added logging to event tracking
2020-06-11 22:10:52 +00:00
Nick Funk 2f03b788a4 [CORL-1121] Remove username validation when updated by admin (#2986)
* Use SSO validation for updateUserUsername

CORL-1121

* Remove validation on admin-only user rename

We don't need to validate the user-name as
only admin's will be using this mutator. If
they're updating things incorrectly, that's
up to them to manage with this flow.

CORL-1121
2020-06-10 19:36:56 -04:00
Wyatt Johnson c19f4a35ca Merge branch 'release/6.2' 2020-06-08 17:31:32 -06:00
Wyatt Johnson 0fa27ae41b chore: bump version 2020-06-08 17:30:39 -06:00
Wyatt Johnson 0065875f12 fix: ensure access token is null not undefined (#2981) 2020-06-08 23:28:07 +00:00
dependabot[bot] b39af1f7e6 chore(deps): bump websocket-extensions from 0.1.3 to 0.1.4 (#2979)
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-06-08 14:42:47 -06:00
Tessa Thornton a949d7e881 [CORL 1031] Story actions (#2975)
* add story actions dropdown with rescrape button

* move open/close story mutation to story actions dropdown

* remove unused props

* fix tests
2020-06-08 14:14:22 -06:00
Wyatt Johnson eee909f05b feat: removed throng and cluster support (#2961) 2020-06-08 13:47:23 -06:00
Vinh 72e1b249b1 [CORL-1029] Better HTML Support (#2956)
* feat: Improve html handling, integrate new @coralproject/rte

* chore: refactor and add comments

* chore: remove obsolete line

* chore: rename `inputId` to `inputID`

* chore: upgrade @coralproject/rte

* fix: update snapshots

* chore: apply review suggestions

* fix: snapshot / tests

* fix: merge issues

* [CORL-1056] Configurable RTE (#2967)

* fix: merge issues

* feat: Configure RTE

* test: add tests

* chore: just a comment

* chore: remove unused translations
2020-06-08 13:24:38 -06:00
Wyatt Johnson ba08447d5e [CORL-1090] Sections Alpha (#2973)
* feat: added section filtering support

* fix: addressed issues around filtering sections

* fix: fixed issue with section filter
2020-06-04 13:32:04 +02:00
Wyatt JohnsonandKim Gardner 92c72f7041 fix: replace insert with push for slack channels (#2965)
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-06-01 21:23:15 +00:00
Wyatt JohnsonandKim Gardner 08a9788bcc fix: fixed error with method bindings on strategies (#2971)
- moved request bindings to after the cache handler

Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-06-01 17:10:42 -04:00
VinhandWyatt Johnson 3e0241b523 feat: add SignedOutEvent (#2968)
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-06-01 14:11:45 -04:00
Vinh fe8cb90a1c [CORL-1086] Support bodyClassName in embed (#2969)
* feat: support embed config `bodyClassName`

* chore: add comment
2020-05-21 22:27:27 +00:00
Wyatt Johnson 74366bec55 [CORL-1046] Slack Helper Text Fix (#2959)
* fix: moved helper text

* chore: version bump

* chore: update description to match github
2020-05-15 18:28:15 +00:00
Wyatt Johnson ed92f4916d [CORL-810] Custom Moderation Phases (#2901)
* feat: initial implementation

* feat: renamed fields from mutations

* fix: more renaming to streamline {Key,Secret}->SigningSecret

* feat: introduced WrappedInternalError

* feat: enhanced extern payload, more fetch options

- Added tenant.{id,domain} to extern payload
- Added site.id to the extern payload
- Added response size limit to fetch
- Added new SCRAPE_MAX_RESPONSE_SIZE env var for managing the size of
  responses for scraping

* fix: fixed bug with scrape invocation

* feat: added more queries + mutations

- Added Query.externalModerationPhase
- Added Mutation.createExternalModerationPhase
- Added Mutation.updateExternalModerationPhase
- Added Mutation.enableExternalModerationPhase
- Added Mutation.disableExternalModerationPhase
- Added Mutation.deleteExternalModerationPhase
- Added Mutation.rotateExternalModerationPhaseSigningSecret

* feat: added secret management

* fix: linting

* fix: merge conflict fix

* feat: added UI

* fix: linting

* fix: linting

* fix: updated snapshots

* fix: improved docs

* fix: improved docs

* fix: added locales

* review: improve naming

* review: some review changes

- Switched /moderation/phase to /moderation/phases
- Fixed scrolling
- Fixed redirection

* fix: added scroll timeout for webhooks
2020-05-14 19:20:35 +00:00
Wyatt Johnson ceb96dba75 [CORL-1048] Cookie Deprecation (#2944)
* feat: dropped cookie support due to ITP issues

* feat: added improved accessToken handling

* fix: linting

* fix: removed variadic part of JWT

* fix: bump long-settimeout version

* review: removed management classes

* fix: updated snaps

* review: renamed based on review

* review: removed guard clauses around errors surrounding auth
2020-05-13 22:39:22 +00:00
Wyatt JohnsonandVinh f73597d7d1 [CORL-1013] Count Reset (#2960)
* feat: added reset option for count.js

* fix: adjust reset beheviour

* fix: switched to bundlesize2

* fix: added flag to enable github checks

Co-authored-by: Vinh <vinh@vinh.tech>
2020-05-13 16:47:45 +00:00
Vinh 79e0da2c2f fix: bug when posting a comment without ever openened the AllCommentsTab first (#2963) 2020-05-13 17:31:15 +02:00
Wyatt Johnson 1f69bb2f14 [CORL-1075] Metrics Cleanup (#2955)
* feat: added support for metrics on another port

* fix: handle cluster better

* fix: linting
2020-05-11 21:01:53 +00:00
Wyatt JohnsonandVinh d0ab2ef8c5 feat: support auto-pause live updates (#2947)
Co-authored-by: Vinh <vinh@vinh.tech>
2020-05-07 16:21:37 +00:00
Wyatt Johnson 1624787004 i18n Validator (#2953)
* feat: added validate script and docs

* fix: added link
2020-05-07 16:07:07 +00:00
8ea88f9b96 Add flag deleted with value "true" to comments of deleted users (#2952)
* [Fix] Add deleted as true to comments of deleted users

* fix: revert deleted = true

Co-authored-by: hector.melo <hector.melo@corp.globo.com>
Co-authored-by: Wyatt Johnson <me@wyattjoh.ca>
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-05-07 15:46:04 +00:00
Cristian DeanandWyatt Johnson 45873398dd Update pt-BR translation (#2949)
Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-05-05 22:07:46 +00:00
Vinh 739d5b6611 fix: always show details on moderation card (#2946) 2020-05-04 11:53:37 -04:00
Kim GardnerandWyatt Johnson 192c3486af [CORL-1050] Add Perspective toxicity support for fr and pt (#2940)
* Add support for fr and pt

* fix: added some more docs

Co-authored-by: Wyatt Johnson <me@wyattjoh.ca>
2020-04-24 12:01:44 -06:00
Wyatt Johnson 0e9621c499 fix: Added linting rule to disable use of object prototypes (#2939) 2020-04-17 17:12:36 +00:00
Vinh 5b92f7e968 [CORL-1014] Style comments based on number of reactions (#2930)
* feat: add ability to style comments based on number of reactions

* feat: add coral-indent class

* fix: tests

* fix: snapshots
2020-04-15 18:28:07 +02:00
Vinh c9a0ab8848 [CORL-878] Upgrade dependencies (#2867)
* chore: upgrade fluent

* chore: upgrade metascraper

* chore: upgrade akismet-api

* chore: upgrade apollo-server-express

* chore: upgrade archiver

* chore: upgrade bull

* chore: upgrade express, cheerio, content-security-policy-builder

* chore: upgrade convict

* chore: upgrade cors, cron

* chore: upgrade csv-stringify

* chore: upgrade dompurify

* chore: upgrade dotenv

* chore: upgrade express-static-gzip

* chore: upgrade fs-extra

* chore: upgrade graphql-js

* chore: upgrade graphql packages

* chore: upgrade html-minifier

* chore: upgrade html-to-text

* chore: upgrade ioredis

* chore: upgrade joi

* chore: upgrade jsdom

* chore: upgrade jsonwebtoken

* chore: upgrade juice

* chore: upgrade jwks-rsa ad linkifyjs

* chore: upgrade lodash

* chore: upgrade luxon

* chore: upgrade metascraper

* chore: upgrade mongodb

* chore: upgrade ms

* chore: upgrade node and node-fetch types

* chore: upgrade nodemailer nunjucks and typescript-eslint

* chore: Upgrade passport

* upgrade: prom-client react-helmet source-map-support stack-utils

* chore: upgrade uuid

* chore: upgrade @babel packages

* chore: upgrade types

* chore: upgrade autoprefixer

* chore: upgrade jest

* chore: upgrade ts-jest

* chore: remove linkify.d.ts

* chore: upgrade bowser

* chore: case-sensitive-paths-webpack-plugin

* chore: upgrade classnames

* chore: upgrade commander

* chore: upgrade comment-json

* chore: upgrade cross-spawn compression-webpack-plugin del

* chore: upgrade build and watch related dependencies

* chore: upgrade css-vars-ponyfill

* chore: upgrade eslint and css-vars-ponyfill

* chore: upgrade enzyme and eventemitter2

* fix: form bug

* chore: upgrade farce

* chore: upgrade final form

* chore: upgrade react-popper

* chore: upgrade flat and fork-ts-checker-webpack-plugin

* chore: upgrade husky and gulp related, intersection observer

* chore: upgrade lint-staged

* chore: upgrade marked, loader-utils, mini-css-extract-plugin

* chore: upgrade postcss-nested, proxy-polyfill, pstree.remy

* chore: upgrade prettier

* chore: fix prettier changes, upgrade react

* chore: mute createFactory deprecated message

* chore: upgrade react-copy-to-clipbard, react-axe, react-dom, react-test-renderer, react-timeago

* chore: upgrade react-transistion-group, react-responsive

* chore: upgrade types

* chore: upgrade react-dev-utils, react-error-overlay regenerator-runtime

* chore: upgrade types, sinon, sockjs-client, strip-ansi

* chore: upgrade types, fonts

* chore: upgrade nunjucks, ts-node, typescript-snapshot-plugin, wait-for-expect

* chore: upgrade eslint packages

* chore: upgrade fluent, types

* chore: upgrade jsdom dep

* chore: upgrade mongo

* chore: upgrade deps

* chore: upgrade typescript, recompose

* chore: upgrade prettier

* chore: remove obsolete prettier config

* chore: upgrade jsdom types

* chore: upgrade typescript-eslint

* chore: upgrad deps

* chore: upgrade deps

* chore: upgrade relay related modules

* chore: upgrade docz WIP

* chore: upgrade docz

* chore: add guard

* chore: remove obsolete line

* chore: comment

* chore: refactors

* fix: hook count change error
2020-04-15 18:15:31 +02:00
Wyatt Johnson e180cf87d7 fix: added more details to slack config (#2937) 2020-04-14 22:28:14 +00:00
Kim Gardner de976a5397 Additional Dutch translations (#2936)
* Fix typo

* Add new NL translations
2020-04-14 22:18:34 +00:00
Wyatt Johnson 257830a6c5 [CORL-1035] Moderated By Bug (#2935)
* fix: improved moderated by component

* fix: uncommented line
2020-04-14 21:55:40 +00:00
Tessa Thornton 518056f382 [CORL-1033] don't show view conversation link if callback is not defined (#2934)
* don't show view conversation link if callback is not defined

* remove unnecessary callback
2020-04-13 17:39:17 +00:00
Tessa Thornton 84936ca35c fix error thrown attempting to remove announcements (#2933) 2020-04-13 16:09:33 +00:00
Wyatt Johnson 4194b08a12 [CORL-1002] Queue Improvements (#2931)
* fix: improved count handler for stories not found

* feat: removed performance-now

* feat: cleaned up processors, exposed counts

* feat: increased verb of schd jobs

* fix: removed dead code
2020-04-10 16:15:09 +00:00
Wyatt JohnsonandKim Gardner 98e6a3ccc7 chore: bump version 6.1.0 (#2932)
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-04-10 15:25:01 +00:00
Kim GardnerandGilles FRANCOIS 64f5171ff2 [CORL-1003] Add Markdown link to configure page & revert some French translations (#2928)
* french corrections

* Add translations

* Updated FR translations

* More FR fixes

Co-authored-by: Gilles FRANCOIS <gilles@sopress.net>
2020-04-10 10:37:11 -04:00
6711f09a79 [CORL-1001] Wordlist Fixes (#2920)
* fix: improve wordlist highlighting and perf

* fix: updated tests

* fix: implmeneted new regexp lib/patterns

* fix: improve comment body css

* fix: take into account the tree shaking is disabled

See: https://github.com/webpack/webpack/issues/7094

Co-authored-by: Chi Vinh Le <vinh@vinh.tech>
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-04-06 15:04:05 -04:00
Wyatt JohnsonandKim Gardner 8966a8201b fix: removed crossorigin attribute on custom css tags (#2919)
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-04-03 17:58:52 -04:00
Tessa ThorntonandKim Gardner 7fc0e2e489 [CORL-974] Add more classnames (#2913)
* wired css

* add more classnames to hook into

* update snaps

* update more snaps

Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-04-03 15:54:17 -04:00
Cristian DeanandWyatt Johnson 7c3c510bbc Add tenantDomain to StoryCreatedEventPayload (#2899)
* Add tenantID and siteID to StoryCreatedEventPayload

* fix: added tenantID to payload

* Remove tenantID from StoryCreatedCoralEvent

* Add tenantDomain to webhook schema

* fix: small comment fixes

Co-authored-by: Wyatt Johnson <me@wyattjoh.ca>
2020-04-02 21:39:58 +00:00
Wyatt Johnson 94ece10284 [CORL-996] Force SSL Configuration (#2917)
* fix: added new FORCE_SSL config, reverted production SSL handling

* fix: added another test to handle purify testing
2020-03-30 20:35:18 +00:00
ef01f427de Update PT-BR translations after release 6 (#2915)
Co-authored-by: hector.melo <hector.melo@corp.globo.com>
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-03-30 16:12:34 -04:00
Tessa ThorntonandKim Gardner 5db096942a remove 'mailto:' prefix from links (#2914)
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-03-27 14:09:42 -04:00
Tessa Thornton 4645ed4cd7 [CORL-943] Send test emails (#2882)
* add smtp test email

* disable button if email not enabled

* add error handling

* internationalize strings

* sort imports
2020-03-27 11:46:53 -04:00
7fd524cd6a [CORL-924/CORL-923] show all comments or staff comments in slack (#2872)
* add allcomments option to slack config

* create separate class for hadnling slack event publishing

* add strings

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-03-26 21:21:09 -04:00
Wyatt JohnsonandKim Gardner 3cb5d0ff9f [CORL-970] CircleCI Version Bump (#2893)
* feat: bump config version

* fix: removed old version tag

Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-03-26 21:04:44 -04:00
Tessa ThorntonandKim Gardner 44216221a4 show badges for suspended and premod users (#2895)
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-03-26 20:34:14 -04:00
Wyatt JohnsonandKim Gardner 0f9b2ba114 feat: added new DEFAULT_QA_STORY_MODE feature flag (#2905)
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-03-26 18:31:48 -04:00
Nick FunkandKim Gardner 071666e8b8 Add more punctuation types to word list rules (#2907)
CORL-957

Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-03-26 18:21:48 -04:00
Tessa ThorntonandKim Gardner 2a9a5099dc update click to copy link button styles (#2912)
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-03-26 17:50:02 -04:00
Wyatt JohnsonandKim Gardner d0f51d8815 fix: added more guard clauses around the endpoint (#2910)
Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-03-26 17:29:51 -04:00
Andrew LosowskyandKim Gardner b228725370 Updated text (#2911)
removed mention of Talk, Coral Project, and links to v4 userguides

Co-authored-by: Kim Gardner <kgardnr@gmail.com>
2020-03-26 14:46:19 -04:00
Tessa Thornton 58f2f71743 [CORL-916] conversation view (#2850)
* show comment counts for stories in story table

* remove debug code

* add modal to view comment

* load converasation view into modal

* style modal header

* style conversation view modal

* style conversation thread in conversation modal

* styles conversation view comments

* show replies to replies on click

* update snaps

* update snap

* pass settings prop through to comment content, set default replies to 5
2020-03-26 13:47:16 -04:00
Wyatt Johnson 8fd266deeb Merge branch 'master' into release/6 2020-03-23 12:20:18 -06:00
Nick FunkandWyatt Johnson 9a58673545 [CORL-929] SSO Key Rotation (Front-end) (#2877)
* feat: initial impl

* Create preliminary SSO rotation components

CORL-929

* Create rotateSSOKey mutation

CORL-929

* Fix sorting by date for SSO keys

CORL-929

* Show tool tips beside expiring/expired statuses

CORL-929

* Hook up Deactivate and Delete SSO key mutations

CORL-929

* Tweak expired tooltip on SSO keys

CORL-929

* Replace old SSO key config with key rotation

CORL-929

* Fix copy button for SSO key's secret

CORL-929

* Refactor SSOKeyCard func's into components

All the func's building the sub-components
were prime targets for component's with props.

CORL-929

* Update tests to match SSO Key rotation

CORL-929

* Fix typo in translation id

CORL-929

* Test key rotation

CORL-929

* Plumb disabled through SSO key rotation

CORL-929

* Remove duplicate input/payload pairs from schema

For some reason it perfectly duplicated the
input/payload pairs for SSO key rotation on
rebase.

CORL-929

* Remove debug logging

CORL-929

* Use switch instead of if's to compute SSO date field

CORL-929

* Use switch to compute SSO action button state

CORL-929

* Use switch to compute SSO StatusField state

CORL-929

* Remove 10 second key rotation option

CORL-929

* Use memo in sorting SSO keys

CORL-929

Co-authored-by: Wyatt Johnson <wyattjoh@gmail.com>
2020-03-20 20:59:59 +00:00
Wyatt Johnson 2dc63d3a27 [CORL-754] SSO Key Management (#2732)
* feat: initial impl

* feat: clean up redis when keys are deleted

* fix: remove test timeout value
2020-03-19 20:57:49 +00:00
2378 changed files with 97411 additions and 61043 deletions
+10 -9
View File
@@ -1,8 +1,8 @@
# job_environment will setup the environment for any job being executed.
job_environment: &job_environment
NODE_ENV: test
WEBPACK_MAX_CORES: 4
NODE_OPTIONS: --max-old-space-size=8192
NODE_ENV: "test"
WEBPACK_MAX_CORES: "4"
NODE_OPTIONS: "--max-old-space-size=8192"
# job_defaults applies all the defaults for each job.
job_defaults: &job_defaults
@@ -13,7 +13,7 @@ job_defaults: &job_defaults
environment:
<<: *job_environment
version: 2
version: 2.1
jobs:
# npm_dependencies will install the dependencies used by all other steps.
npm_dependencies:
@@ -49,7 +49,8 @@ jobs:
- ~/.npm
- persist_to_workspace:
root: .
paths: node_modules
paths:
- node_modules
# lint will perform file linting.
lint:
@@ -78,7 +79,7 @@ jobs:
<<: *job_defaults
environment:
<<: *job_environment
CI: true
CI: "true"
JEST_JUNIT_OUTPUT: "reports/junit/js-test-results.xml"
steps:
- checkout
@@ -115,14 +116,15 @@ jobs:
no_output_timeout: 30m
- run:
name: Verify Bundle Size
command: npx bundlesize
command: npx bundlesize2 --enable-github-checks
- save_cache:
key: v1-build-cache-{{ .Branch }}-{{ .Revision }}
paths:
- ./dist
- persist_to_workspace:
root: .
paths: dist
paths:
- dist
# docker_tests will test that the docker build process completes.
docker_tests:
@@ -173,7 +175,6 @@ filter_develop: &filter_develop
- next
workflows:
version: 2
build-test:
jobs:
- docker_tests:
-1
View File
@@ -27,4 +27,3 @@ yarn.lock
dist
*.css.d.ts
__generated__
README.md.orig
+85 -53
View File
@@ -1,10 +1,11 @@
const typescriptEslintRecommended = require('@typescript-eslint/eslint-plugin/dist/configs/eslint-recommended').default.overrides[0];
const typescriptRecommended = require('@typescript-eslint/eslint-plugin/dist/configs/recommended.json');
const typescriptRecommendedTypeChecking = require('@typescript-eslint/eslint-plugin/dist/configs/recommended-requiring-type-checking.json');
const typescriptEslintPrettier = require('eslint-config-prettier/@typescript-eslint');
const react = require('eslint-plugin-react').configs.recommended;
const jsxA11y = require('eslint-plugin-jsx-a11y').configs.recommended;
const reactPrettier = require('eslint-config-prettier/react');
const typescriptEslintRecommended = require("@typescript-eslint/eslint-plugin/dist/configs/eslint-recommended")
.overrides[0];
const typescriptRecommended = require("@typescript-eslint/eslint-plugin/dist/configs/recommended.js");
const typescriptRecommendedTypeChecking = require("@typescript-eslint/eslint-plugin/dist/configs/recommended-requiring-type-checking.js");
const typescriptEslintPrettier = require("eslint-config-prettier/@typescript-eslint");
const react = require("eslint-plugin-react").configs.recommended;
const jsxA11y = require("eslint-plugin-jsx-a11y").configs.recommended;
const reactPrettier = require("eslint-config-prettier/react");
const typescriptOverrides = {
files: ["*.ts", "*.tsx"],
@@ -20,11 +21,12 @@ const typescriptOverrides = {
"@typescript-eslint/tslint",
"react",
"jsx-a11y",
"react-hooks",
],
settings: {
react: {
version: "detect",
}
},
},
rules: Object.assign(
typescriptEslintRecommended.rules,
@@ -36,32 +38,45 @@ const typescriptOverrides = {
{
"@typescript-eslint/adjacent-overload-signatures": "error",
// TODO: (cvle) change `readonly` param to `array-simple` when upgraded typescript.
"@typescript-eslint/array-type": ["error", { "default": "array-simple", "readonly": "generic"}],
"@typescript-eslint/ban-types": "error",
"@typescript-eslint/array-type": [
"error",
{ default: "array-simple", readonly: "generic" },
],
"@typescript-eslint/ban-types": [
"error",
{
types: {
"{}": false,
object: false,
extendDefaults: true,
},
},
],
"@typescript-eslint/camelcase": "off",
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/explicit-member-accessibility": [
"error",
{
"overrides": {
"constructors": "off",
overrides: {
constructors: "off",
},
},
],
"@typescript-eslint/indent": "off",
"@typescript-eslint/interface-name-prefix": "error",
"@typescript-eslint/member-delimiter-style": "off",
"@typescript-eslint/no-empty-function": "error",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-parameter-properties": "off",
"@typescript-eslint/no-unused-vars": ["error", {"args": "none", "ignoreRestSiblings": true}],
"@typescript-eslint/no-unused-vars": [
"error",
{ args: "none", ignoreRestSiblings: true },
],
"@typescript-eslint/no-use-before-define": "off", // TODO: (cvle) Should be on?
"@typescript-eslint/no-use-before-declare": "off",
"@typescript-eslint/no-var-requires": "error",
@@ -77,38 +92,59 @@ const typescriptOverrides = {
"react/display-name": "error",
"react/prop-types": "off",
"react/no-unescaped-entities": "off",
"no-empty-function": "off",
// (tessalt) disabled because video elements are only used to display gifs, which have no audio
"jsx-a11y/media-has-caption": "off",
}
),
};
let typescriptTypeCheckingOverrides = {
const jestTypeCheckingOverrides = {
files: ["test/**/*.ts", "test/**/*.tsx"],
rules: {
"@typescript-eslint/no-floating-promises": "off",
},
};
const typescriptTypeCheckingOverrides = {
files: ["*.ts", "*.tsx"],
parserOptions: {
project: ["tsconfig.json", "./src/tsconfig.json", "./src/core/client/tsconfig.json"],
project: [
"./tsconfig.json",
"./src/tsconfig.json",
"./src/core/client/tsconfig.json",
],
// TODO: (cvle) this is a workaround, see: https://github.com/typescript-eslint/typescript-eslint/issues/1091.
createDefaultProgram: true,
},
rules: Object.assign(
typescriptRecommendedTypeChecking.rules,
{
"@typescript-eslint/tslint/config": ["error", {
"rules": {
rules: Object.assign(typescriptRecommendedTypeChecking.rules, {
"@typescript-eslint/tslint/config": [
"error",
{
rules: {
"ordered-imports": {
"options": {
"import-sources-order": "case-insensitive",
options: {
// Legacy sorting until this is fixed: https://github.com/SoominHan/import-sorter/issues/60
"import-sources-order": "case-insensitive-legacy",
"module-source-path": "full",
"named-imports-order": "case-insensitive",
"named-imports-order": "case-insensitive-legacy",
},
},
},
}],
// 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.
}
),
},
],
"@typescript-eslint/no-misused-promises": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-return": "off",
// 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/restrict-template-expressions": "off",
"@typescript-eslint/unbound-method": "off", // 10.10.19: (cvle) seems to give false positive.
}),
overrides: [jestTypeCheckingOverrides],
};
const jestOverrides = {
@@ -117,8 +153,8 @@ const jestOverrides = {
},
files: ["test/**/*.ts", "test/**/*.tsx"],
globals: {
"expectAndFail": "readonly",
"fail": "readonly",
expectAndFail: "readonly",
fail: "readonly",
},
};
@@ -140,35 +176,31 @@ module.exports = {
"eslint:recommended",
"plugin:jsdoc/recommended",
"plugin:prettier/recommended",
"plugin:react-hooks/recommended",
],
parserOptions: {
"ecmaVersion": 2018,
ecmaVersion: 2018,
},
rules: {
"arrow-body-style": "off",
"arrow-parens": [
"off",
"as-needed",
],
"camelcase": "off",
"complexity": "off",
"arrow-parens": ["off", "as-needed"],
camelcase: "off",
complexity: "off",
"constructor-super": "error",
"spaced-comment": ["error", "always"],
"curly": "error",
curly: "error",
"dot-notation": "error",
"eol-last": "off",
"eqeqeq": "error",
eqeqeq: "error",
"guard-for-in": "error",
"jsdoc/check-param-names": "off",
"jsdoc/require-jsdoc": "off",
"jsdoc/require-returns": "off",
"jsdoc/require-param": "off",
"jsdoc/require-param-type": "off",
"jsdoc/require-returns-type": "off",
"linebreak-style": "off",
"max-classes-per-file": [
"error",
1,
],
"max-classes-per-file": ["error", 1],
"member-ordering": "off",
"new-parens": "off",
"newline-per-chained-call": "off",
@@ -185,7 +217,7 @@ module.exports = {
"no-irregular-whitespace": "off",
"no-multiple-empty-lines": "off",
"no-new-wrappers": "error",
"no-prototype-builtins": "off",
"no-prototype-builtins": "error",
"no-shadow": "error",
"no-throw-literal": "error",
"no-undef": "off",
@@ -193,14 +225,14 @@ module.exports = {
"no-unsafe-finally": "error",
"no-unused-expressions": "error",
"no-unused-labels": "error",
"no-unused-vars": ["error", {"args": "none", "ignoreRestSiblings": true}],
"no-unused-vars": ["error", { args: "none", ignoreRestSiblings: true }],
"no-var": "error",
"object-shorthand": "error",
"one-var": "off",
"prefer-arrow-callback": "off",
"prefer-const": "error",
"quote-props": "off",
"radix": "error",
radix: "error",
"require-atomic-updates": "off",
"space-before-function-paren": "off",
"sort-imports": "off",
-1
View File
@@ -20,5 +20,4 @@ yarn.lock
dist
*.css.d.ts
__generated__
README.md.orig
persisted-queries.json
+44
View File
@@ -0,0 +1,44 @@
# .kodiak.toml
# Kodiak's configuration file should be placed at `.kodiak.toml` (repository
# root) or `.github/.kodiak.toml`.
# docs: https://kodiakhq.com/docs/config-reference
# version is the only required setting in a kodiak config.
# `1` is the only valid setting for this field.
version = 1
[merge]
# Label to enable Kodiak to merge a PR.
# By default, Kodiak will only act on PRs that have this label. You can disable
# this requirement via `merge.require_automerge_label`.
automerge_label = "🚀 merge it!" # default: "automerge"
# Kodiak will not merge a PR with any of these labels.
blocking_labels = ["don't merge"] # default: [], options: list of label names (e.g. ["wip"])
# Choose merge method for Kodiak to use.
#
# Kodiak will report a configuration error if the selected merge method is
# disabled for a repository.
#
# If you're using the "Require signed commits" GitHub Branch Protection setting
# to require commit signatures, _`"merge"` is the only compatible option_. Any
# other option will cause Kodiak to raise a configuration error.
method = "squash" # default: "merge", options: "merge", "squash", "rebase"
# Once a PR is merged, delete the branch. This option behaves like the GitHub
# repository setting "Automatically delete head branches", which automatically
# deletes head branches after pull requests are merged.
delete_branch_on_merge = true # default: false
# Don't wait for in-progress status checks on a PR to finish before updating the
# branch.
optimistic_updates = false # default: true
[merge.message]
# Strip HTML comments (`<!-- some HTML comment -->`) from merge commit body.
# This setting is useful for stripping HTML comments created by PR templates.
# This option only applies when `merge.message.body_type = "markdown"`.
strip_html_comments = true # default: false
-3
View File
@@ -1,3 +0,0 @@
{
"trailingComma": "es5"
}
+1 -1
View File
@@ -54,5 +54,5 @@
"search.exclude": {
"package-lock.json": true
},
"debug.node.autoAttach": "on"
"debug.node.autoAttach": "off"
}
+14
View File
@@ -129,9 +129,11 @@ createComment.error
- <a href="#showSharePopover">showSharePopover</a>
- <a href="#showUserPopover">showUserPopover</a>
- <a href="#signOut">signOut</a>
- <a href="#signedIn">signedIn</a>
- <a href="#unfeatureComment">unfeatureComment</a>
- <a href="#updateNotificationSettings">updateNotificationSettings</a>
- <a href="#updateStorySettings">updateStorySettings</a>
- <a href="#updateUserMediaSettings">updateUserMediaSettings</a>
- <a href="#viewConversation">viewConversation</a>
- <a href="#viewFullDiscussion">viewFullDiscussion</a>
- <a href="#viewNewComments">viewNewComments</a>
@@ -538,6 +540,7 @@ createComment.error
};
}
```
- <a id="signedIn">**signedIn**</a>: This event is emitted when the viewer signed in (not applicable for SSO).
- <a id="unfeatureComment">**unfeatureComment.success**, **unfeatureComment.error**</a>: This event is emitted when the viewer unfeatures a comment.
```ts
{
@@ -585,6 +588,17 @@ createComment.error
};
}
```
- <a id="updateUserMediaSettings">**updateUserMediaSettings.success**, **updateUserMediaSettings.error**</a>:
```ts
{
unfurlEmbeds?: boolean | 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
{
+10
View File
@@ -174,6 +174,16 @@ 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`.
To assist with the translation process, we have a script that is based on the
work by @cristiandean in https://github.com/coralproject/talk/pull/2949 that
will detect missing, new, or changed translation keys for the specified
language. You can use this with:
```sh
# usage: ./scripts/i18n/validate.ts <locale>
./scripts/i18n/validate.ts pt-BR
```
## Documentation
Documentation that is publicly shown on
+272
View File
@@ -0,0 +1,272 @@
# CSS Variables
Coral defines a set of CSS Variables that you can use to broadly customize the
look and feel of your comment stream. For example you can easily redefine the colors
or fonts that are being used.
To change the CSS Variables, use the following example in your custom CSS file:
```
:root {
--font-family-primary: 'Verdana';
--round-corners: 0px;
}
```
The following list contains the CSS Variables that can be customized.
**Info**: *Before 6.3.0 Coral uses a different set of CSS Variables. If you are still using
the old CSS Variables, please upgrade. Currently we have a compatibility layer to bridge the old CSS Variables to the new ones. This mechanism will be removed in the future.*
<!-- START docs:css-variables -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN npm run docs:css-variables -->
### Index
- <a href="#variables">Variables</a>
- <a href="#palette">palette</a>
- <a href="#palette-primary">palette-primary</a>
- <a href="#palette-background">palette-background</a>
- <a href="#palette-text">palette-text</a>
- <a href="#palette-grey">palette-grey</a>
- <a href="#palette-error">palette-error</a>
- <a href="#palette-success">palette-success</a>
- <a href="#palette-warning">palette-warning</a>
- <a href="#font-family">font-family</a>
- <a href="#font-weight">font-weight</a>
- <a href="#font-weight-primary">font-weight-primary</a>
- <a href="#font-weight-secondary">font-weight-secondary</a>
- <a href="#font-size">font-size</a>
- <a href="#shadow">shadow</a>
- <a href="#spacing">spacing</a>
- <a href="#mini-unit">mini-unit</a>
### Variables
Use this to remove round corners or make them more round.
`--round-corners: 3px;`
### palette
`--palette-divider: rgba(0, 0, 0, 0.12);`
#### palette-primary
Color palette that is used as the primary color.
`--palette-primary-100: #EBF6FF; /* Before 6.3.0: --palette-primary-lightest */`
`--palette-primary-200: #B7DCFF; /* Before 6.3.0: --palette-primary-lighter */`
`--palette-primary-300: #61B3FF; /* Before 6.3.0: --palette-primary-light */`
`--palette-primary-400: #2897FF; /* Before 6.3.0: --palette-primary-main */`
`--palette-primary-500: #0070D9; /* Before 6.3.0: --palette-primary-main */`
`--palette-primary-600: #0062BE; /* Before 6.3.0: --palette-primary-main */`
`--palette-primary-700: #005AAE; /* Before 6.3.0: --palette-primary-main */`
`--palette-primary-800: #004688; /* Before 6.3.0: --palette-primary-dark */`
`--palette-primary-900: #00386D; /* Before 6.3.0: --palette-primary-darkest */`
#### palette-background
Color palette that is used for background colors.
`--palette-background-body: #FFFFFF;`
`--palette-background-popover: #FFFFFF;`
`--palette-background-tooltip: #65696B;`
`--palette-background-input: #FFFFFF;`
`--palette-background-input-disabled: #EFEFEF;`
#### palette-text
Color palette that is used for text.
`--palette-text-000: #FFFFFF; /* Before 6.3.0: --palette-text-light */`
`--palette-text-100: #65696B; /* Before 6.3.0: --palette-text-secondary */`
`--palette-text-500: #353F44; /* Before 6.3.0: --palette-text-primary */`
`--palette-text-900: #14171A; /* Before 6.3.0: --palette-text-dark */`
`--palette-text-placeholder: #9FA4A6; /* Before 6.3.0: --palette-grey-lighter */`
`--palette-text-input-disabled: #9FA4A6; /* Before 6.3.0: --palette-grey-lighter */`
#### palette-grey
Color palette that is used for grey shades.
`--palette-grey-100: #F4F7F7; /* Before 6.3.0: --palette-grey-lightest */`
`--palette-grey-200: #EAEFF0; /* Before 6.3.0: --palette-grey-lightest */`
`--palette-grey-300: #CBD1D2; /* Before 6.3.0: --palette-grey-lighter */`
`--palette-grey-400: #9FA4A6; /* Before 6.3.0: --palette-grey-lighter */`
`--palette-grey-500: #65696B; /* Before 6.3.0: --palette-grey-main */`
`--palette-grey-600: #49545C; /* Before 6.3.0: --palette-grey-dark */`
`--palette-grey-700: #32404D; /* Before 6.3.0: --palette-grey-darkest */`
`--palette-grey-800: #202E3E; /* Before 6.3.0: --palette-grey-darkest */`
`--palette-grey-900: #132033; /* Before 6.3.0: --palette-grey-darkest */`
#### palette-error
Color palette that is used for indicating something is error red.
`--palette-error-100: #FCE5D9; /* Before 6.3.0: --palette-error-lightest */`
`--palette-error-200: #FAC6B4; /* Before 6.3.0: --palette-error-lighter */`
`--palette-error-300: #F29D8B; /* Before 6.3.0: --palette-error-lighter */`
`--palette-error-400: #E5766C; /* Before 6.3.0: --palette-error-light */`
`--palette-error-500: #D53F3F; /* Before 6.3.0: --palette-error-main */`
`--palette-error-600: #B72E39; /* Before 6.3.0: --palette-error-main */`
`--palette-error-700: #991F34; /* Before 6.3.0: --palette-error-dark */`
`--palette-error-800: #7B142E; /* Before 6.3.0: --palette-error-darkest */`
`--palette-error-900: #660C2B; /* Before 6.3.0: --palette-error-darkest */`
#### palette-success
Color palette that is used for indicating something is success green.
`--palette-success-100: #D8F9D5; /* Before 6.3.0: --palette-success-lightest */`
`--palette-success-200: #ADF3AD; /* Before 6.3.0: --palette-success-lighter */`
`--palette-success-300: #7CDB85; /* Before 6.3.0: --palette-success-lighter */`
`--palette-success-400: #54B767; /* Before 6.3.0: --palette-success-light */`
`--palette-success-500: #268742; /* Before 6.3.0: --palette-success-main */`
`--palette-success-600: #1B743D; /* Before 6.3.0: --palette-success-main */`
`--palette-success-700: #136138; /* Before 6.3.0: --palette-success-dark */`
`--palette-success-800: #0C4E32; /* Before 6.3.0: --palette-success-darkest */`
`--palette-success-900: #07402E; /* Before 6.3.0: --palette-success-darkest */`
#### palette-warning
Color palette that is used for indicating a warning and is usually yellow.
`--palette-warning-100: #FFFACC; /* Before 6.3.0: --palette-warning-main */`
`--palette-warning-500: #FFE91F; /* Before 6.3.0: --palette-warning-main */`
### font-family
Different font families currently in use.
`--font-family-primary: "Open Sans"; /* Before 6.3.0: --font-family-sans-serif */`
`--font-family-secondary: "Nunito"; /* Before 6.3.0: --font-family-serif */`
### font-weight
Different font weights with matching values for the fonts.
#### font-weight-primary
`--font-weight-primary-bold: 700; /* Before 6.3.0: --font-weight-bold */`
`--font-weight-primary-semi-bold: 600; /* Before 6.3.0: --font-weight-medium */`
`--font-weight-primary-regular: 300; /* Before 6.3.0: --font-weight-light */`
#### font-weight-secondary
`--font-weight-secondary-bold: 700; /* Before 6.3.0: --font-weight-bold */`
`--font-weight-secondary-regular: 300; /* Before 6.3.0: --font-weight-light */`
### font-size
`--font-size-1: 0.75rem;`
`--font-size-2: 0.875rem;`
`--font-size-3: 1rem;`
`--font-size-4: 1.125rem;`
`--font-size-5: 1.25rem;`
`--font-size-6: 1.5rem;`
`--font-size-7: 1.75rem;`
`--font-size-8: 2rem;`
`--font-size-9: 2.25rem;`
`--font-size-icon-xl: 2.25rem;`
`--font-size-icon-lg: 1.5rem;`
`--font-size-icon-md: 1.125rem;`
`--font-size-icon-sm: 0.875rem;`
`--font-size-icon-xs: 0.75rem;`
### shadow
Different shadows that are currently used in Coral.
`--shadow-popover: 1px 0px 4px rgba(0, 0, 0, 0.25); /* Before 6.3.0: --elevation-main */`
### spacing
Different spacing units currenty used in Coral.
`--spacing-1: 4px;`
`--spacing-2: 8px;`
`--spacing-3: 12px;`
`--spacing-4: 16px;`
`--spacing-5: 24px;`
`--spacing-6: 32px;`
`--spacing-7: 44px;`
`--spacing-8: 60px;`
`--spacing-9: 84px;`
### mini-unit
Grid units for smaller and larger screens.
`--mini-unit-small: 4;`
`--mini-unit-large: 8;`
<!-- END docs:css-variables -->
+240
View File
@@ -0,0 +1,240 @@
# External Moderation Phases Guide
This document is in reference to external moderation phases emitted by Coral.
You can configure external moderation phases on your installation of Coral by
visiting `/admin/configure/moderation/phases`.
Once you've configured a external moderation phase in Coral, you will start to
receive moderation requests in the form of a
[External Moderation Requests](#external-moderation-request) at the provided
callback URL. These will be in the form of `POST` requests with a `JSON`
payload.
When a comment is created or edited, it will be processed by moderation phases in
a predefined order. Any external moderation phase is run last, and only if all
other moderation phases before it do not return a status. The current set of
moderation phases is listed in order [here](https://github.com/coralproject/talk/blob/master/src/core/server/services/comments/pipeline/phases/index.ts).
Once you have received a moderation request, you must respond within the
provided timeout else the phase will be skipped and it will continue. It is
strongly recommended to [verify the request signature](#request-signing).
The external moderation phase must respond with one of the following:
1. Do not moderate the comment, and return a 204 without a body.
2. Perform a moderation action and return a 200 with a [External Moderation Response](#external-moderation-response)
as a `JSON` encoded body containing the operations you want to perform on the
comment.
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
## Table of Contents
- [Request Signing](#request-signing)
- [Schema](#schema)
- [External Moderation Request](#external-moderation-request)
- [External Moderation Response](#external-moderation-response)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Request Signing
Requests sent by Coral for external moderation phases use the same process as
those used by webhooks. Refer to the [webhooks documentation](WEBHOOKS.md#webhook-signing)
for instructions on how to verify signatures sent by Coral.
## Schema
### External Moderation Request
```ts
interface ExternalModerationRequest {
/**
* action refers to the specific operation being performed. If `NEW`, this
* is referring to a new comment being created. If `EDIT`, then this refers to
* an operation involving an edit operation on an existing Comment.
*/
action: "NEW" | "EDIT";
/**
* comment refers to the actual Comment data for the Comment being
* created/edited.
*/
comment: {
/**
* body refers to the actual body text of the Comment being created/edited.
*/
body: string;
/**
* parentID is the identifier for the parent comment (if this Comment is a
* reply, null otherwise).
*/
parentID: string | null;
};
/**
* author refers to the User that is creating/editing the Comment.
*/
author: {
/**
* id is the identifier for this User.
*/
id: string;
/**
* role refers to the role of this User.
*/
role: "COMMENTER" | "STAFF" | "MODERATOR" | "ADMIN";
};
/**
* story refers to the Story being commented on.
*/
story: {
/**
* id is the identifier for this Story.
*/
id: string;
/**
* url is the URL for this Story.
*/
url: string;
};
/**
* site refers to the Site that the story being commented on belongs to.
*/
site: {
/**
* id is the identifier for this Site.
*/
id: string;
};
/**
* tenantID is the identifer of the Tenant that this Comment is being
* created/edited on.
*/
tenantID: string;
/**
* tenantDomain is the domain that is associated with this Tenant that this
* Comment is being created/edited on.
*/
tenantDomain: string;
}
```
#### Example
New comment on a story:
```json
{
"action": "NEW",
"comment": {
"body": "Here's a comment!",
"parentID": null
},
"author": {
"id": "baf4e943-3594-4fcc-b2ba-3e8de7a76352",
"role": "COMMENTER"
},
"story": {
"id": "245b3856-b0a0-4d2f-a6bb-58c71f18d6a6",
"url": "http://localhost:1313/posts/a-story-url/"
},
"site": {
"id": "a4bede88-2d2c-4424-bc18-4322a9e285a6"
},
"tenantID": "19ba5794-7eeb-4d46-a81b-c00c61672501",
"tenantDomain": "localhost"
}
```
New reply on a comment on a story:
```json
{
"action": "NEW",
"comment": {
"body": "Here's a reply!",
"parentID": "d79b787f-f406-49a0-a179-72e3652e54be"
},
"author": {
"id": "baf4e943-3594-4fcc-b2ba-3e8de7a76352",
"role": "COMMENTER"
},
"story": {
"id": "245b3856-b0a0-4d2f-a6bb-58c71f18d6a6",
"url": "http://localhost:1313/posts/a-story-url/"
},
"site": {
"id": "a4bede88-2d2c-4424-bc18-4322a9e285a6"
},
"tenantID": "19ba5794-7eeb-4d46-a81b-c00c61672501",
"tenantDomain": "localhost"
}
```
### External Moderation Response
```ts
interface ExternalModerationResponse {
/**
* actions is an optional list of any flags to be added to this Comment.
*/
actions?: Array<{
actionType: "FLAG";
reason: "COMMENT_DETECTED_TOXIC" | "COMMENT_DETECTED_SPAM";
}>;
/**
* tags are any listed tags that should be added to the comment.
*/
tags?: Array<"FEATURED" | "STAFF">;
/**
* status when provided decides and terminates the moderation process by
* setting the status of the comment.
*/
status?: "NONE" | "APPROVED" | "REJECTED" | "PREMOD" | "SYSTEM_WITHHELD";
}
```
#### Examples
Add a flag to a comment and do not set a status:
```json
{
"actions": [{ "actionType": "FLAG", "reason": "COMMENT_DETECTED_TOXIC" }]
}
```
Reject a comment:
```json
{
"status": "REJECTED"
}
```
Feature a comment and do not set a status:
```json
{
"tags": ["FEATURED"]
}
```
Approve a comment and mark it as featured:
```json
{
"status": "APPROVED",
"tags": ["FEATURED"]
}
```
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright 2019 Vox Media, Inc
Copyright 2020 Vox Media, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+37 -26
View File
@@ -1,41 +1,52 @@
# Coral ![CircleCI](https://img.shields.io/circleci/project/github/coralproject/talk.svg)
<p align="center">
<a href="https://coralproject.net" target="_blank"><img width="250" src="https://docs.coralproject.net/coral/images/coralproject_by_voxmedia.svg" alt="Coral by Vox Media" /></a>
</p>
Online comments are broken. Our open-source commenting platform, Coral, rethinks
how moderation, comment display, and conversation function, creating the
opportunity for safer, smarter discussions around your work.
[Read more about Coral here](https://coralproject.net/talk).
<p align="center">
A better commenting experience from <a href="https://product.voxmedia.com/" target="_blank">Vox Media</a>.
</p>
Built with <3 by The Coral Project, a part of [Vox Media](https://product.voxmedia.com/).
<p align="center">
<a href="https://circleci.com/gh/coralproject/talk" target="_blank"><img src="https://img.shields.io/circleci/build/gh/coralproject/talk?style=flat-square" alt="CircleCI" /></a>
<a href="https://hub.docker.com/r/coralproject/talk" target="_blank"><img src="https://img.shields.io/docker/v/coralproject/talk?label=docker%20hub&sort=semver&style=flat-square" alt="Docker Image Version" /></a>
<a href="https://hub.docker.com/r/coralproject/talk" target="_blank"><img src="https://img.shields.io/docker/image-size/coralproject/talk?label=docker%20image%20size&sort=semver&style=flat-square" alt="Docker Image Size" /></a>
<a href="https://twitter.com/coralproject" target="_blank"><img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/coralproject?style=flat-square"></a>
</p>
Preview Coral easily by running Coral via a Heroku App:
## Description
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/coralproject/talk)
Online comments are broken. Our open-source commenting platform,
[Coral](https://coralproject.net), rethinks how moderation, comment display, and
conversation function, creating the opportunity for safer, smarter discussions
around your work.
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
## Table of Contents
- [Documentation](#documentation)
- [Pre-Launch Guide](#pre-launch-guide)
- [More Resources](#more-resources)
- [License](#license)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
We offer hosting and support packages for Coral, as well as exclusive,
customer-only features. [Contact us](https://coralproject.net/pricing/) for more
information or [sign up for a webinar](https://coralproject.net).
## Documentation
You can get started with Coral using our [Documentation](https://docs.coralproject.net/talk/).
If you're new to Coral, the [Coral documentation](https://docs.coralproject.net/)
is a great place to start running and developing with Coral.
## Pre-Launch Guide
Youve installed Coral, and youre preparing to launch it on your site. The real
community work starts now, before you go live. You have a unique opportunity
pre-launch to set your community up for success. Read our
[Community Guides](https://guides.coralproject.net/start-here/) to learn more.
Youve installed Talk on your server, and youre preparing to launch it on your site. The real community work starts now, before you go live. You have a unique opportunity pre-launch to set your community up for success. Read our [Talk Community Guide](https://coralproject.net/blog/youve-installed-talk-now-what/).
## Support
## More Resources
We can help you set up Coral, migrate your comments from another system,
integrate your registration platform, pair with your programmers, and help you
with bespoke installs. To learn more, [contact us](https://coralproject.net/pricing/).
- [Our Blog](https://coralproject.net/blog)
- [Community Guides for Journalism](https://guides.coralproject.net/)
- [More About Us](https://coralproject.net/)
## Contributing
Coral is a Apache-2.0 licensed open-source project built with <3 by the Coral
team, a part of [Vox Media](https://product.voxmedia.com/).
If you are interested in contributing to Coral, check out our [Contributor's Guide](CONTRIBUTING.md).
## License
Coral is released under the [Apache License, v2.0](/LICENSE).
Coral is [Apache-2.0 licensed](LICENSE).
+15
View File
@@ -174,6 +174,16 @@ function when comparing signatures.
* date when this event was created.
*/
createdAt: string;
/**
* tenantID is the ID of the Tenant that this event originated at.
*/
tenantID: string;
/**
* tenantDomain is the domain that is associated with this Tenant that this event originated at.
*/
tenantDomain: string;
}
```
@@ -199,6 +209,11 @@ function when comparing signatures.
* storyURL is the URL of the newly created Story.
*/
storyURL: string;
/**
* siteID is the Site that the newly created Story was created on.
*/
siteID: string;
}
createdAt: string;
}
-42
View File
@@ -1,42 +0,0 @@
{
"name": "Coral",
"description": "A better commenting experience from Vox Media.",
"env": {
"REWRITE_ENV": {
"description": "Used to rewrite the environment variables set by Heroku.",
"value": "REDIS_URI:REDIS_URL,MONGODB_URI:MONGO_URI"
},
"SIGNING_SECRET": {
"description": "The shared secret to use to sign JSON Web Tokens (JWT) with the selected signing algorithm.",
"generator": "secret"
},
"CONCURRENCY": {
"description": "The number of worker nodes to spawn to handle traffic.",
"value": "1"
},
"LOCALE": {
"description": "Specify the default locale to use for all requests without a locale specified",
"value": "en-US"
},
"ENABLE_GRAPHIQL": {
"description": "When true, this will enable the GraphiQL routes",
"value": "false"
},
"TRUST_PROXY": {
"description": "When set to 1, it instructs Coral to trust up to one proxy, this is needed for authentication support",
"value": "1"
}
},
"addons": [
{
"plan": "mongolab:sandbox",
"as": "MONGO"
},
{
"plan": "rediscloud:30",
"as": "REDIS"
}
],
"success_url": "/install",
"website": "https://github.com/coralproject/talk"
}
+1 -1
View File
@@ -10,7 +10,7 @@ const plugins =
const environment =
process.env.WEBPACK === "true"
? { targets: "IE 11", modules: false }
? { modules: false }
: { targets: { node: "current" }, modules: "commonjs" };
module.exports = {
+3 -5
View File
@@ -40,11 +40,9 @@ module.exports = {
snapshotSerializers: ["enzyme-to-json/serializer"],
globals: {
"ts-jest": {
useBabelrc: true,
tsConfigFile: path.resolve(
__dirname,
"../../src/core/client/tsconfig.json"
),
babelConfig: true,
tsConfig: path.resolve(__dirname, "../../src/core/client/tsconfig.json"),
},
},
preset: "ts-jest/presets/js-with-babel",
};
+3 -2
View File
@@ -21,8 +21,9 @@ module.exports = {
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
globals: {
"ts-jest": {
useBabelrc: true,
tsConfigFile: path.resolve(__dirname, "../../src/tsconfig.json"),
babelConfig: true,
tsConfig: path.resolve(__dirname, "../../src/tsconfig.json"),
},
},
preset: "ts-jest",
};
+3 -98
View File
@@ -1,105 +1,10 @@
// Apply all the configuration provided in the .env file.
require("dotenv").config();
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 appDirectory = fs.realpathSync(process.cwd());
const styleLoader = {
loader: require.resolve("style-loader"),
options: {
sourceMap: true,
hmr: true,
},
};
module.exports = {
title: "Coral 5.0",
source: "./src",
typescript: true,
title: "Coral 5",
src: "./src",
host: process.env.HOST || "0.0.0.0",
port: parseInt(process.env.DOCZ_PORT, 10) || 3030,
codeSandbox: false, // Too large to create code sandboxes..
modifyBundlerConfig: config => {
config.entry.app.push(
`${appDirectory}/src/core/client/ui/theme/variables.css.ts`
);
config.module.rules.push({
test: /\.css\.ts$/,
use: [
styleLoader,
{
loader: require.resolve("css-loader"),
options: {
modules: true,
importLoaders: 2,
localIdentName: "[name]-[local]-[hash:base64:5]",
sourceMap: true,
},
},
{
loader: require.resolve("postcss-loader"),
options: {
config: {
path: postCSSConfigPath,
},
parser: "postcss-js",
},
},
{
loader: require.resolve("babel-loader"),
options: {
configFile: false,
babelrc: false,
presets: [
"@babel/typescript",
[
"@babel/env",
{ targets: { node: "current" }, modules: "commonjs" },
],
],
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
},
},
],
});
config.module.rules.push({
test: /\.css$/,
use: [
styleLoader,
{
loader: require.resolve("css-loader"),
options: {
modules: true,
importLoaders: 1,
localIdentName: "[name]-[local]-[hash:base64:5]",
sourceMap: true,
},
},
{
loader: require.resolve("postcss-loader"),
options: {
config: {
path: postCSSConfigPath,
},
},
},
],
});
config.resolve.plugins = [
new TsconfigPathsPlugin({
extensions,
// TODO: There is some weird issue with including paths.ts here
configFile: "./src/core/client/tsconfig.json",
}),
];
// fs.writeFileSync(path.resolve(__dirname, "tmp"), stringify(config, null, 2));
return config;
},
files: "**/*.mdx",
};
+216
View File
@@ -0,0 +1,216 @@
const fs = require("fs");
const path = require("path");
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
/** Path to postCSSConfig */
const postCSSConfigPath = path.resolve(
__dirname,
"../src/core/build/postcss.config"
);
const rootDir = path.resolve(__dirname, "../");
const srcDir = path.resolve(rootDir, "./src");
const appTsconfig = path.resolve(rootDir, "./src/core/client/tsconfig.json");
const CSS_PATTERN = /\.css$/;
const MODULE_CSS_PATTERN = /\.module\.css$/;
// Define `RegExp.toJSON` so that we can stringify RegExp.
Object.defineProperty(RegExp.prototype, "toJSON", {
value: RegExp.prototype.toString,
});
const isCssRules = (rule) =>
rule.test &&
(rule.test.toString() === CSS_PATTERN.toString() ||
rule.test.toString() === MODULE_CSS_PATTERN.toString());
const findCssRules = (config) =>
config.module.rules.find(
(rule) => Array.isArray(rule.oneOf) && rule.oneOf.every(isCssRules)
);
exports.onCreateWebpackConfig = ({
stage,
rules,
loaders,
plugins,
actions,
getConfig,
}) => {
// Get webpack config.
const config = getConfig();
if (stage === "develop") {
config.entry.commons.push(
// Add our stream css variables file.
`${srcDir}/core/client/ui/theme/stream.css.ts`
);
}
/*
TODO: (cvle) couldn't get build to work...
if (stage === "build-javascript") {
config.entry.app = [
config.entry.app,
`${appDir}/core/client/ui/theme/stream.css.ts`,
];
}
*/
// Find the gatsby CSS rules.
const cssRules = findCssRules(config);
// Exclude them from our src dir because they are incomaptible with our
// CSS rules.
cssRules.exclude = srcDir;
// Add .tx .tsx to modules
config.resolve.extensions.push(".ts", ".tsx");
actions.replaceWebpackConfig(config);
// Write out webpack config to .docz folder.
fs.writeFileSync(
path.resolve(__dirname, "webpack-" + stage),
JSON.stringify(config, {}, 2)
);
// Turn on sourceMap during develop.
const sourceMap = stage.startsWith("develop");
// CSS loaders to prepend.
const prependCSSLoaders = [];
if (stage === "develop") {
prependCSSLoaders.push(loaders.style());
}
/*
TODO: (cvle) couldn't get build to work...
if (stage === "build-javascript") {
moreLoaders.push(loaders.style());
}
*/
actions.setWebpackConfig({
resolve: {
plugins: [
// Resolve our custom paths.
new TsconfigPathsPlugin({
extensions: [".ts", ".tsx", ".js"],
configFile: path.resolve(rootDir, "./src/core/client/tsconfig.json"),
}),
],
},
module: {
rules: [
{
include: srcDir,
oneOf: [
{
test: /\.css\.ts$/,
use: [
...prependCSSLoaders,
{
loader: require.resolve("css-loader"),
options: {
modules: {
localIdentName: "[name]-[local]-[hash:base64:5]",
},
importLoaders: 2,
sourceMap,
},
},
{
loader: require.resolve("postcss-loader"),
options: {
config: {
path: postCSSConfigPath,
},
parser: "postcss-js",
},
},
{
loader: require.resolve("babel-loader"),
options: {
configFile: false,
babelrc: false,
presets: [
"@babel/typescript",
[
"@babel/env",
{ targets: { node: "current" }, modules: "commonjs" },
],
],
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
},
},
],
},
{
test: /\.css$/,
use: [
...prependCSSLoaders,
{
loader: require.resolve("css-loader"),
options: {
modules: {
localIdentName: "[name]-[local]-[hash:base64:5]",
},
importLoaders: 1,
sourceMap,
},
},
{
loader: require.resolve("postcss-loader"),
options: {
config: {
path: postCSSConfigPath,
},
},
},
],
},
{
test: /\.tsx?$/,
use: [
{
loader: require.resolve("babel-loader"),
options: {
root: rootDir,
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
},
},
{
loader: require.resolve("ts-loader"),
options: {
configFile: appTsconfig,
compilerOptions: {
target: "es2015",
module: "esnext",
jsx: "preserve",
noEmit: false,
},
transpileOnly: true,
// Overwrites the behavior of `include` and `exclude` to only
// include files that are actually being imported and which
// are necessary to compile the bundle.
onlyCompileBundledFiles: true,
},
},
],
},
],
},
],
},
});
// Write out processed webpack config to .docz folder.
fs.writeFileSync(
path.resolve(__dirname, "webpack-" + stage + "-processed"),
JSON.stringify(getConfig(), {}, 2)
);
};
+33393 -16701
View File
File diff suppressed because it is too large Load Diff
+302 -261
View File
@@ -1,9 +1,10 @@
{
"name": "@coralproject/talk",
"version": "6.0.3",
"version": "6.3.2",
"author": "The Coral Project",
"homepage": "https://coralproject.net/",
"sideEffects": [
"*.css.ts",
"*.css"
],
"repository": {
@@ -18,15 +19,17 @@
"contributors": [
"https://github.com/coralproject/talk/graphs/contributors"
],
"description": "A better commenting experience from Mozilla, The Washington Post, and The New York Times.",
"description": "A better commenting experience from Vox Media.",
"scripts": {
"clean": "gulp clean",
"build": "NODE_ENV=production npm-run-all generate-persist --parallel build:client build:server",
"build:development": "NODE_ENV=development npm-run-all generate --parallel build:client build:server",
"build:client": "ts-node --transpile-only ./scripts/build.ts",
"build:server": "gulp server",
"migration:create": "ts-node --transpile-only ./scripts/migration/create.ts",
"docs:events": "ts-node ./scripts/generateEventDocs.ts ./src/core/client/stream/events.ts ./CLIENT_EVENTS.md",
"doctoc": "doctoc --maxlevel=3 --title '## Table of Contents' README.md CLIENT_EVENTS.md CONTRIBUTING.md WEBHOOKS.md",
"docs:css-variables": "ts-node ./scripts/generateCSSVariablesDocs.ts ./src/core/client/ui/theme/streamVariables.ts ./CSS_VARIABLES.md",
"doctoc": "doctoc --maxlevel=3 --title '## Table of Contents' CLIENT_EVENTS.md CONTRIBUTING.md WEBHOOKS.md EXTERNAL_MODERATION_PHASES.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/",
@@ -40,7 +43,7 @@
"generate:schema": "node ./scripts/generateSchemaTypes.js",
"docz": "docz",
"start": "NODE_ENV=production node dist/index.js",
"start:development": "NODE_ENV=development CONCURRENCY=${CONCURRENCY:-1} TS_NODE_PROJECT=./src/tsconfig.json ts-node-dev --inspect --transpile-only --no-notify -r tsconfig-paths/register ./src/index.ts",
"start:development": "NODE_ENV=development TS_NODE_PROJECT=./src/tsconfig.json ts-node-dev --inspect --transpile-only --no-notify -r tsconfig-paths/register ./src/index.ts",
"start:webpackDevServer": "ts-node --transpile-only ./scripts/start.ts",
"lint": "npm-run-all --parallel lint:* tscheck:*",
"lint:server": "eslint 'src/**/*.{js,ts,tsx}' --ignore-pattern 'src/core/client/**'",
@@ -58,336 +61,361 @@
"license": "Apache-2.0",
"dependencies": {
"@coralproject/bunyan-prettystream": "^0.1.4",
"@fluent/bundle": "^0.14.0",
"@emotion/core": "^10.0.28",
"@fluent/bundle": "^0.15.0",
"@fluent/dom": "^0.6.0",
"@metascraper/helpers": "^5.7.21",
"@hapi/joi": "^17.1.1",
"@metascraper/helpers": "^5.11.6",
"@rudderstack/rudder-sdk-node": "0.0.2",
"abort-controller": "^3.0.0",
"akismet-api": "^4.2.0",
"apollo-server-express": "^2.8.1",
"archiver": "^3.0.3",
"akismet-api": "^5.0.0",
"apollo-server-core": "^2.14.4",
"apollo-server-express": "^2.14.2",
"archiver": "^3.1.1",
"basic-auth": "^2.0.1",
"bcryptjs": "^2.4.3",
"bull": "^3.8.1",
"bull": "^3.13.0",
"bunyan": "^1.8.12",
"cheerio": "^1.0.0-rc.2",
"bytes": "^3.1.0",
"cheerio": "^1.0.0-rc.3",
"consolidate": "0.14.0",
"content-security-policy-builder": "^2.0.0",
"convict": "^4.3.1",
"content-security-policy-builder": "^2.1.0",
"convict": "^5.2.0",
"cookie": "^0.4.0",
"cookie-parser": "^1.4.4",
"cors": "^2.8.4",
"cron": "^1.7.1",
"csv-stringify": "^5.3.0",
"dataloader": "^1.4.0",
"dompurify": "^2.0.7",
"dotenv": "^6.0.0",
"dotenv-expand": "^4.2.0",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"cron": "^1.8.2",
"csv-stringify": "^5.3.6",
"dataloader": "1.4.0",
"dompurify": "^2.0.8",
"dotenv": "^8.2.0",
"emailjs": "^3.2.0",
"env-rewrite": "^1.0.2",
"express": "^4.17.1",
"express-enforces-ssl": "^1.1.0",
"express-static-gzip": "^0.3.2",
"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",
"express-static-gzip": "^2.0.6",
"fs-extra": "^8.1.0",
"graphql": "^14.6.0",
"graphql-config": "^2.2.2",
"graphql-extensions": "^0.11.0",
"graphql-fields": "2.0.3",
"graphql-playground-html": "1.6.13",
"graphql-redis-subscriptions": "^2.2.1",
"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",
"graphql-tools": "^4.0.7",
"helmet": "^3.22.0",
"html-minifier": "^4.0.0",
"html-to-text": "^5.1.1",
"ioredis": "^4.16.1",
"jsdom": "^16.2.2",
"jsonwebtoken": "^8.5.1",
"juice": "^5.2.0",
"jwks-rsa": "^1.6.0",
"keymaster": "^1.6.2",
"linkifyjs": "^2.1.8",
"lodash": "^4.17.15",
"juice": "^6.0.0",
"jwks-rsa": "^1.7.0",
"linkifyjs": "^2.1.9",
"lodash": "^4.17.19",
"long-settimeout": "^1.0.1",
"lru-cache": "^5.1.1",
"luxon": "^1.12.0",
"metascraper-author": "^5.8.0",
"metascraper-description": "^5.8.0",
"metascraper-image": "^5.8.0",
"metascraper-title": "^5.8.0",
"mongodb": "^3.2.7",
"luxon": "^1.22.2",
"metascraper-author": "^5.11.6",
"metascraper-description": "^5.11.6",
"metascraper-image": "^5.11.6",
"metascraper-title": "^5.11.6",
"mongodb": "^3.5.9",
"mongodb-core": "^3.2.7",
"ms": "^2.1.1",
"ms": "^2.1.2",
"node-fetch": "^2.6.0",
"nodemailer": "^4.6.7",
"nunjucks": "^3.1.3",
"nunjucks": "^3.2.1",
"on-finished": "^2.3.0",
"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-oauth2": "^1.5.0",
"passport-strategy": "^1.0.0",
"performance-now": "^2.1.0",
"permit": "^0.2.4",
"prom-client": "^11.3.0",
"prom-client": "^12.0.0",
"proxy-agent": "^3.1.1",
"querystringify": "^2.1.1",
"react-helmet": "^5.2.1",
"source-map-support": "^0.5.12",
"stack-utils": "^1.0.2",
"source-map-support": "^0.5.16",
"stack-utils": "^2.0.1",
"striptags": "^3.1.1",
"throng": "^4.0.0",
"tsscmp": "^1.0.6",
"url-regex": "^5.0.0",
"uuid": "^3.3.3",
"verror": "^1.10.0"
"uuid": "^7.0.3",
"verror": "^1.10.0",
"xregexp": "^4.3.0"
},
"devDependencies": {
"@babel/core": "^7.8.3",
"@babel/preset-env": "^7.8.3",
"@babel/preset-react": "^7.8.3",
"@babel/preset-typescript": "^7.8.3",
"@babel/runtime-corejs3": "^7.8.3",
"@babel/core": "^7.10.3",
"@babel/preset-env": "^7.10.3",
"@babel/preset-react": "^7.10.1",
"@babel/preset-typescript": "^7.10.1",
"@babel/runtime-corejs3": "^7.10.3",
"@coralproject/npm-run-all": "^4.1.5",
"@coralproject/rte": "^0.11.1",
"@fluent/react": "^0.10.0",
"@coralproject/rte": "^1.1.1",
"@fluent/react": "^0.11.1",
"@intervolga/optimize-cssnano-plugin": "^1.0.6",
"@types/agent-base": "^4.2.0",
"@types/archiver": "^3.0.0",
"@types/basic-auth": "^1.1.2",
"@types/bcryptjs": "^2.4.1",
"@types/bull": "^3.5.12",
"@types/bunyan": "^1.8.4",
"@types/case-sensitive-paths-webpack-plugin": "^2.1.2",
"@types/cheerio": "^0.22.8",
"@types/classnames": "^2.2.7",
"@types/commander": "^2.12.2",
"@types/archiver": "^3.1.0",
"@types/basic-auth": "^1.1.3",
"@types/bcryptjs": "^2.4.2",
"@types/bull": "^3.12.1",
"@types/bunyan": "^1.8.6",
"@types/bytes": "^3.1.0",
"@types/case-sensitive-paths-webpack-plugin": "^2.1.4",
"@types/cheerio": "^0.22.17",
"@types/classnames": "^2.2.10",
"@types/common-tags": "^1.8.0",
"@types/compression-webpack-plugin": "^2.0.0",
"@types/consolidate": "0.0.34",
"@types/convict": "^4.2.0",
"@types/compression-webpack-plugin": "^2.0.1",
"@types/consolidate": "0.14.0",
"@types/convict": "^5.2.1",
"@types/cookie": "^0.3.3",
"@types/cookie-parser": "^1.4.1",
"@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/cookie-parser": "^1.4.2",
"@types/cors": "^2.8.6",
"@types/cron": "^1.7.2",
"@types/cross-spawn": "^6.0.1",
"@types/dompurify": "^2.0.1",
"@types/enzyme": "^3.10.5",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/eventemitter2": "^4.1.0",
"@types/express": "^4.16.0",
"@types/express": "^4.17.4",
"@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/express-serve-static-core": "^4.17.3",
"@types/flat": "^5.0.0",
"@types/fs-extra": "^8.1.0",
"@types/hapi__joi": "^16.0.12",
"@types/helmet": "^0.0.45",
"@types/html-minifier": "^3.5.3",
"@types/html-minifier-terser": "^5.0.0",
"@types/html-to-text": "^1.4.31",
"@types/html-webpack-plugin": "^3.2.0",
"@types/ioredis": "^4.0.10",
"@types/jest": "^24.0.23",
"@types/jest-axe": "^3.2.1",
"@types/joi": "^13.0.8",
"@types/jsdom": "^12.2.3",
"@types/jsonwebtoken": "^8.3.5",
"@types/linkifyjs": "^2.1.1",
"@types/lodash": "^4.14.118",
"@types/html-webpack-plugin": "^3.2.3",
"@types/ioredis": "^4.14.9",
"@types/jest": "^26.0.3",
"@types/jest-axe": "^3.2.2",
"@types/jsdom": "^16.2.0",
"@types/jsonwebtoken": "^8.3.8",
"@types/linkifyjs": "^2.1.3",
"@types/lodash": "^4.14.149",
"@types/lru-cache": "^5.1.0",
"@types/luxon": "^1.12.0",
"@types/marked": "^0.6.0",
"@types/mini-css-extract-plugin": "^0.2.0",
"@types/mongodb": "^3.1.22",
"@types/ms": "^0.7.30",
"@types/node": "^10.5.2",
"@types/node-fetch": "^2.5.3",
"@types/nodemailer": "^4.6.2",
"@types/nunjucks": "^3.1.1",
"@types/object-diff": "0.0.0",
"@types/luxon": "^1.22.0",
"@types/marked": "^0.7.3",
"@types/mini-css-extract-plugin": "^0.9.1",
"@types/mongodb": "3.1.22",
"@types/ms": "^0.7.31",
"@types/node": "^12.12.34",
"@types/node-fetch": "^2.5.5",
"@types/nunjucks": "^3.1.3",
"@types/on-finished": "^2.3.1",
"@types/passport": "^1.0.2",
"@types/passport-facebook": "^2.1.8",
"@types/passport": "^1.0.3",
"@types/passport-facebook": "^2.1.9",
"@types/passport-local": "^1.0.33",
"@types/passport-oauth2": "^1.4.5",
"@types/passport-strategy": "^0.2.33",
"@types/passport-oauth2": "^1.4.8",
"@types/passport-strategy": "^0.2.35",
"@types/permit": "^0.2.1",
"@types/prettier": "^1.19.0",
"@types/prop-types": "^15.5.8",
"@types/react": "^16.8.15",
"@types/prettier": "^1.19.1",
"@types/react": "^16.9.31",
"@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",
"@types/react-relay": "^5.0.1",
"@types/react-responsive": "^3.0.1",
"@types/react-test-renderer": "^16.8.1",
"@types/react-transition-group": "^2.0.14",
"@types/recompose": "^0.26.5",
"@types/relay-runtime": "^5.0.5",
"@types/react-copy-to-clipboard": "^4.3.0",
"@types/react-dom": "^16.9.6",
"@types/react-helmet": "^5.0.15",
"@types/react-relay": "^7.0.3",
"@types/react-responsive": "^8.0.2",
"@types/react-test-renderer": "^16.9.2",
"@types/react-transition-group": "^4.2.4",
"@types/recharts": "^1.8.9",
"@types/recompose": "^0.30.7",
"@types/relay-runtime": "^8.0.7",
"@types/sane": "^2.0.0",
"@types/shallow-equals": "^1.0.0",
"@types/simplemde": "^1.11.7",
"@types/sinon": "^7.0.11",
"@types/source-map-support": "^0.5.0",
"@types/sinon": "^7.5.2",
"@types/source-map-support": "^0.5.1",
"@types/stack-trace": "0.0.29",
"@types/stack-utils": "^1.0.1",
"@types/throng": "^4.0.2",
"@types/uuid": "^3.4.4",
"@types/uuid": "^7.0.2",
"@types/verror": "^1.10.3",
"@types/vinyl": "^2.0.2",
"@types/webpack": "^4.4.31",
"@types/webpack-assets-manifest": "^3.0.0",
"@types/webpack-bundle-analyzer": "^2.13.1",
"@types/webpack-dev-server": "^3.1.5",
"@types/ws": "^5.1.2",
"@typescript-eslint/eslint-plugin": "2.3.3",
"@typescript-eslint/eslint-plugin-tslint": "2.3.3",
"@typescript-eslint/parser": "2.3.3",
"acorn": "^6.1.1",
"ansi-styles": "^3.2.0",
"autoprefixer": "^9.5.1",
"@types/vinyl": "^2.0.4",
"@types/webpack": "^4.41.17",
"@types/webpack-assets-manifest": "^3.0.1",
"@types/webpack-bundle-analyzer": "^3.8.0",
"@types/webpack-dev-server": "^3.11.0",
"@types/ws": "^7.2.3",
"@types/xregexp": "^4.3.0",
"@typescript-eslint/eslint-plugin": "^3.4.0",
"@typescript-eslint/eslint-plugin-tslint": "^3.4.0",
"@typescript-eslint/parser": "^3.4.0",
"autoprefixer": "^9.7.5",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^24.9.0",
"babel-loader": "^8.0.6",
"babel-jest": "^26.1.0",
"babel-loader": "^8.1.0",
"babel-plugin-lodash": "^3.3.4",
"babel-plugin-module-resolver": "^3.2.0",
"babel-plugin-relay": "^5.0.0",
"babel-plugin-module-resolver": "^4.0.0",
"babel-plugin-relay": "^9.1.0",
"babel-plugin-use-lodash-es": "^0.2.0",
"bowser": "^1.9.4",
"case-sensitive-paths-webpack-plugin": "^2.2.0",
"chalk": "^2.4.2",
"chokidar": "^3.0.0",
"bowser": "^2.9.0",
"case-sensitive-paths-webpack-plugin": "^2.3.0",
"chalk": "^3.0.0",
"chokidar": "^3.3.1",
"classnames": "^2.2.6",
"commander": "^2.20.0",
"comment-json": "^1.1.3",
"commander": "^5.0.0",
"comment-json": "^3.0.2",
"common-tags": "^1.8.0",
"compression-webpack-plugin": "^2.0.0",
"copy-webpack-plugin": "^5.0.3",
"compression-webpack-plugin": "^3.1.0",
"core-js": "^3.6.4",
"cross-spawn": "^6.0.5",
"css-loader": "^1.0.1",
"css-vars-ponyfill": "^2.1.2",
"del": "^4.1.1",
"cross-spawn": "^7.0.1",
"css-loader": "^3.4.2",
"css-vars-ponyfill": "^2.2.1",
"del": "^5.1.0",
"doctoc": "^1.4.0",
"docz": "^0.13.7",
"docz-theme-default": "^0.13.7",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1",
"enzyme-to-json": "^3.3.5",
"eslint": "^6.5.1",
"eslint-config-prettier": "^6.3.0",
"eslint-plugin-jsdoc": "^15.9.7",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-react": "^7.15.1",
"eventemitter2": "^5.0.1",
"farce": "^0.2.6",
"docz": "^v2.3.0-alpha.14",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"enzyme-to-json": "^3.5.0",
"eslint": "^7.3.1",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-jsdoc": "^28.5.1",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.20.0",
"eslint-plugin-react-hooks": "^4.0.8",
"eventemitter2": "^6.3.1",
"farce": "^0.2.8",
"final-form": "4.18.6",
"final-form-arrays": "1.1.2",
"flat": "^4.1.0",
"final-form-arrays": "^3.0.2",
"flat": "^5.0.0",
"fluent-intl-polyfill": "^0.1.0",
"fork-ts-checker-webpack-plugin": "^1.5.0",
"found": "^0.4.9",
"found-relay": "^0.4.3",
"graphql-schema-linter": "^0.2.0",
"graphql-schema-typescript": "^1.2.9",
"fork-ts-checker-webpack-plugin": "^4.1.2",
"found": "^0.4.10",
"found-relay": "^0.7.0",
"graphql-schema-linter": "^0.4.0",
"graphql-schema-typescript": "^1.3.2",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-cli": "^2.2.0",
"gulp-cli": "^2.3.0",
"gulp-sourcemaps": "^2.6.5",
"gulp-typescript": "^5.0.1",
"html-webpack-plugin": "^4.0.0-beta.11",
"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",
"lint-staged": "^8.1.6",
"loader-utils": "^1.2.3",
"lodash-es": "^4.17.14",
"marked": "^0.7.0",
"gulp-typescript": "^6.0.0-alpha.1",
"html-webpack-plugin": "^4.0.4",
"husky": "^4.2.3",
"intersection-observer": "^0.7.0",
"jest": "^26.1.0",
"jest-axe": "^3.4.0",
"jest-junit": "^11.0.1",
"jest-localstorage-mock": "^2.4.2",
"jest-mock-console": "^1.0.1",
"keymaster": "^1.6.2",
"lint-staged": "^10.2.11",
"loader-utils": "^2.0.0",
"lodash-es": "^4.17.15",
"marked": "^0.8.2",
"material-design-icons": "^3.0.1",
"mini-css-extract-plugin": "^0.6.0",
"object-diff": "0.0.4",
"postcss-advanced-variables": "^3.0.0",
"mini-css-extract-plugin": "^0.9.0",
"postcss-advanced-variables": "^3.0.1",
"postcss-calc-function": "^1.1.0",
"postcss-css-variables": "^0.11.0",
"postcss-flexbugs-fixes": "^4.1.0",
"postcss-font-magician": "^2.2.1",
"postcss-import": "^11.1.0",
"postcss-js": "^2.0.1",
"postcss-flexbugs-fixes": "^4.2.0",
"postcss-font-magician": "^2.3.1",
"postcss-import": "^12.0.1",
"postcss-js": "^2.0.3",
"postcss-loader": "^3.0.0",
"postcss-mixins": "^6.2.1",
"postcss-nested": "^4.1.1",
"postcss-mixins": "^6.2.3",
"postcss-nested": "^4.2.1",
"postcss-prepend-imports": "^1.0.1",
"postcss-preset-env": "^6.5.0",
"prettier": "^1.18.2",
"prop-types": "^15.6.2",
"proxy-polyfill": "^0.3.0",
"pstree.remy": "^1.1.6",
"postcss-preset-env": "^6.7.0",
"prettier": "^2.0.2",
"proxy-polyfill": "^0.3.1",
"pstree.remy": "^1.1.7",
"pym.js": "^1.3.2",
"raw-loader": "^0.5.1",
"react": "^16.9.0",
"react-axe": "^3.3.0",
"react-copy-to-clipboard": "^5.0.1",
"react-dev-utils": "^9.0.0",
"react-dom": "^16.9.0",
"react-error-overlay": "^5.1.6",
"raw-loader": "^4.0.0",
"react": "^16.13.1",
"react-axe": "^3.4.1",
"react-copy-to-clipboard": "^5.0.2",
"react-dev-utils": "^10.2.1",
"react-dom": "^16.13.1",
"react-error-overlay": "^6.0.7",
"react-final-form": "6.3.0",
"react-final-form-arrays": "3.1.0",
"react-popper": "^1.3.2",
"react-relay": "^5.0.0",
"react-relay-network-modern": "^4.0.4",
"react-responsive": "^7.0.0",
"react-test-renderer": "^16.9.0",
"react-timeago": "^4.1.9",
"react-transition-group": "^2.9.0",
"react-with-state-props": "^2.0.4",
"recompose": "0.27.1",
"regenerator-runtime": "^0.13.3",
"relay-compiler": "^5.0.0",
"relay-compiler-language-typescript": "^4.1.0",
"react-final-form-arrays": "^3.1.1",
"react-helmet": "^5.2.1",
"react-popper": "^1.3.7",
"react-relay": "^9.0.0",
"react-relay-network-modern": "^4.6.1",
"react-responsive": "^8.0.3",
"react-test-renderer": "^16.13.1",
"react-timeago": "^4.4.0",
"react-transition-group": "^4.3.0",
"recharts": "^1.8.5",
"recompose": "^0.30.0",
"regenerator-runtime": "^0.13.5",
"relay-compiler": "^9.0.0",
"relay-compiler-language-typescript": "^12.0.3",
"relay-local-schema": "^0.8.0",
"relay-runtime": "^5.0.0",
"relay-runtime": "^9.0.0",
"resize-observer-polyfill": "^1.5.1",
"sane": "^4.1.0",
"scheduler": "^0.15.0",
"shallow-equals": "^1.0.0",
"simplemde": "^1.11.2",
"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",
"sinon": "^9.0.1",
"sockjs-client": "^1.4.0",
"stack-trace": "^0.0.10",
"strip-ansi": "^6.0.0",
"style-loader": "^1.1.3",
"subscriptions-transport-ws": "^0.9.16",
"terser-webpack-plugin": "^1.2.3",
"thread-loader": "^2.1.2",
"terser-webpack-plugin": "^2.3.5",
"thread-loader": "^2.1.3",
"timekeeper": "^2.2.0",
"ts-jest": "<23.10.0",
"ts-loader": "^6.0.0",
"ts-node": "^8.1.0",
"ts-node-dev": "^1.0.0-pre.37",
"tsconfig-paths": "^3.8.0",
"ts-jest": "26.1.1",
"ts-loader": "^7.0.5",
"ts-node": "^8.10.2",
"ts-node-dev": "1.0.0-pre.44",
"tsconfig-paths": "^3.9.0",
"tsconfig-paths-webpack-plugin": "^3.2.0",
"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",
"wait-for-expect": "^1.1.1",
"webpack": "^4.41.5",
"tslint": "^6.1.2",
"typed-css-modules": "^0.6.4",
"typeface-manuale": "^1.1.4",
"typeface-nunito": "^1.1.3",
"typeface-open-sans": "^0.0.75",
"typeface-source-sans-pro": "^1.1.5",
"typescript": "^3.9.5",
"typescript-snapshots-plugin": "^1.7.0",
"wait-for-expect": "^1.3.0",
"webpack": "^4.43.0",
"webpack-assets-manifest": "^3.1.1",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-cli": "^3.3.2",
"webpack-dev-server": "3.2.1",
"webpack-bundle-analyzer": "^3.8.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0",
"whatwg-fetch": "^3.0.0"
},
"dependencies-pins-documentation": {
"ts-node-dev@1.0.0-pre.44": [
"Newer versions unbearibly slow"
],
"ts-jest@25.4.0": [
"Newer versions require every definition file to be included",
"in tsconfig.json in the `files` field. This is cumbersome and",
"here is a discussion of it: https://github.com/kulshekhar/ts-jest/issues/1604"
],
"wait-for-expect@1.x.x": [
"Newer versions breaks the use of jest fake timers"
],
"consolidate@14.0.0": [
"Newer versions has problems with using nunjucks.",
"Update when the following issue is resolved:",
"https://github.com/tj/consolidate.js/issues/244"
],
"final-form@4.18.6": [
"Newer versions has problems with resetting forms.",
"Update when the following issue is resolved:",
"https://github.com/final-form/final-form/issues/317"
],
"react-final-form@6.3.0": [
"Newer versions has problems with radio and checkbox fields.",
"Update when the following issue is resolved:",
"https://github.com/final-form/react-final-form/issues/683"
],
"graphql-playground-html@1.6.13": [
"A template was broken in a release.",
"Update when the following issue is resolved:",
"https://github.com/prisma-labs/graphql-playground/pull/1238"
]
},
"husky": {
"hooks": {
"pre-commit": "FAST_LINT=true lint-staged"
@@ -403,20 +431,33 @@
"{src/core/client/stream/events.ts,scripts/generateEventDocs.ts,CLIENT_EVENTS.md}": [
"npm run docs:events -- --verify"
],
"{README,CLIENT_EVENTS,CONTRIBUTING,WEBHOOKS}.md": [
"npm run doctoc",
"git add"
"{src/core/client/ui/theme/sharedVariables.ts,src/core/client/ui/theme/streamVariables.ts,scripts/generateCSSVariablesDocs.ts,CSS_VARIABLES.md}": [
"npm run docs:css-variables -- --verify"
],
"{CLIENT_EVENTS,CONTRIBUTING,WEBHOOKS,EXTERNAL_MODERATION_PHASES}.md": [
"npm run doctoc"
]
},
"bundlesize": [
{
"path": "./dist/static/assets/js/embed.js",
"maxSize": "15 kB"
},
{
"path": "./dist/static/assets/js/count.js",
"maxSize": "2 kB"
}
],
"graphql-schema-linter": {
"rules": [
"types-are-capitalized"
]
}
},
"browsers": [
">1%",
"last 4 versions",
"Firefox ESR",
"IE 11",
"not dead"
]
}
+13 -11
View File
@@ -27,14 +27,14 @@ const forkTsCheckerWebpackPlugin = require("react-dev-utils/ForkTsCheckerWebpack
const isInteractive = false;
function prepareUrls(protocol, host, port) {
const formatUrl = hostname =>
const formatUrl = (hostname) =>
url.format({
protocol,
hostname,
port,
pathname: "/",
});
const prettyPrintUrl = hostname =>
const prettyPrintUrl = (hostname) =>
url.format({
protocol,
hostname,
@@ -144,12 +144,12 @@ function createCompiler({
const tsMessagesPromises = [];
if (useTypeScript) {
compiler.compilers.forEach(singleCompiler => {
compiler.compilers.forEach((singleCompiler) => {
let tsMessagesPromise;
let tsMessagesResolver;
singleCompiler.hooks.beforeCompile.tap("beforeCompile", () => {
tsMessagesPromise = new Promise(resolve => {
tsMessagesResolver = msgs => resolve(msgs);
tsMessagesPromise = new Promise((resolve) => {
tsMessagesResolver = (msgs) => resolve(msgs);
});
tsMessagesPromises.push(tsMessagesPromise);
});
@@ -170,13 +170,15 @@ function createCompiler({
(diagnostics, lints) => {
console.log("RECEIVED");
const allMsgs = [...diagnostics, ...lints];
const format = message =>
const format = (message) =>
`${message.file}\n${typescriptFormatter(message, true)}`;
tsMessagesResolver({
errors: allMsgs.filter(msg => msg.severity === "error").map(format),
errors: allMsgs
.filter((msg) => msg.severity === "error")
.map(format),
warnings: allMsgs
.filter(msg => msg.severity === "warning")
.filter((msg) => msg.severity === "warning")
.map(format),
});
}
@@ -186,7 +188,7 @@ function createCompiler({
// "done" event fires when Webpack has finished recompiling the bundle.
// Whether or not you have warnings or errors, you will get this event.
compiler.hooks.done.tap("done", async stats => {
compiler.hooks.done.tap("done", async (stats) => {
if (isInteractive) {
clearConsole();
}
@@ -203,7 +205,7 @@ function createCompiler({
...config.stats,
};
if (Array.isArray(config)) {
statOptions.children = config.map(c => c.stats || {});
statOptions.children = config.map((c) => c.stats || {});
}
const statsData = stats.toJson(statOptions);
@@ -220,7 +222,7 @@ function createCompiler({
const results = await Promise.all(tsMessagesPromises);
clearTimeout(delayedMsg);
results.forEach(msgs => {
results.forEach((msgs) => {
statsData.errors.push(...msgs.errors);
statsData.warnings.push(...msgs.warnings);
+4 -2
View File
@@ -31,7 +31,7 @@ const isProduction = process.env.NODE_ENV === "production";
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on("unhandledRejection", err => {
process.on("unhandledRejection", (err) => {
throw err;
});
@@ -117,7 +117,9 @@ function build(previousFileSizes: any) {
return reject(err);
}
const messages = formatWebpackMessages(
stats.toJson({ children: webpackConfig.map(c => c.stats || {}) as any })
stats.toJson({
children: webpackConfig.map((c) => c.stats || {}) as any,
})
);
if (messages.errors.length) {
// Only keep the first error. Others are often indicative
+306
View File
@@ -0,0 +1,306 @@
import { stripIndent } from "common-tags";
import fs from "fs";
import { kebabCase, trim } from "lodash";
import path from "path";
import ts from "typescript";
import colors from "../src/core/client/ui/theme/colors";
/** We collect inforamtion from the AST and put it into DocEntry */
interface DocEntry {
/** Name of property */
key: string;
/** Documentation if available */
docs?: string;
/** Value if it is a leaf */
value?: string;
/** Children if it is a node */
children?: DocEntry[];
}
/**
* We use this regexp to find a previous block that we
* are going to update in the readme file.
*/
const BLOCK_REGEXP = /<!-- START docs:css-variables -->(.|\n)*<!-- END docs:css-variables -->/gm;
/** Sort doc entries will sort childrenless entries first */
function sortDocEntries(data: DocEntry[]) {
data.forEach((d) => {
if (d.children) {
d.children = sortDocEntries(d.children);
}
});
return data.sort((a, b) => {
if (a.children && !b.children) {
return 1;
}
if (b.children && !a.children) {
return -1;
}
return 0;
});
}
/** Generate documentation for all classes in a set of .ts files */
function gatherEntries(
fileName: string,
options: ts.CompilerOptions
): DocEntry[] {
// Build a program using the set of root file names in fileNames
const program = ts.createProgram([fileName], options);
// Get the checker, we will use it to find more about classes
const checker = program.getTypeChecker();
const data: DocEntry[] = [];
const currentSourceFile = program.getSourceFile(fileName)!;
ts.forEachChild(currentSourceFile, visit);
return sortDocEntries(data);
/** visit nodes finding css variables */
function visit(node: ts.Node) {
if (ts.isVariableStatement(node)) {
// TODO (cvle) - Currently the variable name is hardcoded. We might want to change that.
if (!node.getFullText().includes("streamVariables")) {
return;
}
const firstChild = node.declarationList.declarations[0];
if (ts.isVariableDeclaration(firstChild)) {
const symbol = checker.getSymbolAtLocation(firstChild.name);
if (symbol) {
const type = checker.getTypeOfSymbolAtLocation(
symbol,
symbol.valueDeclaration
);
type.getProperties().forEach((property) => {
serializePropertySymbol(property);
});
}
}
}
}
/** This will evaluate `symbol` and addthe doc entries */
function serializePropertySymbol(symbol: ts.Symbol, parent?: DocEntry) {
const entry: DocEntry = { key: symbol.name };
const pt = checker.getTypeOfSymbolAtLocation(
symbol,
symbol.valueDeclaration
);
if (pt.symbol?.name === "__object") {
pt.getProperties().forEach((p2) => {
serializePropertySymbol(p2, entry);
});
} else {
entry.value = symbol.valueDeclaration
// Last child contains value.
.getChildAt(symbol.valueDeclaration.getChildCount() - 1)!
.getFullText();
}
entry.docs = ts.displayPartsToString(
symbol.getDocumentationComment(checker)
);
if (parent) {
if (parent.children) {
parent.children.push(entry);
} else {
parent.children = [entry];
}
} else {
data.push(entry);
}
}
}
/**
* Finds any references to `object` by `variableName` and replaces the text
* with the actual value.
*
* E.g. `replaceObjectVariablesInText("colors.teal100", colors, "colors") === "#E2FAF7"`;
*/
function replaceObjectVariablesInText(
text: string,
object: any,
variableName: string
) {
let result = text;
Object.keys(object).forEach((c: string) => {
if (typeof object[c] === "object") {
result = replaceObjectVariablesInText(
result,
object[c],
`${variableName}.${c}`
);
} else {
result = result.replace(`${variableName}.${c}`, object[c]);
}
});
return result;
}
/**
* transforms value to be used in the documentation.
*/
function transformValue(value: string) {
let compat = "";
value = trim(value);
// Detect compat value.
if (value.startsWith("compat")) {
const result = /compat\((.*), *"(.*)"\)/.exec(value);
if (!result) {
throw new Error("Unrecognized compat format");
}
value = result[1];
compat = result[2];
}
// If it's a raw string, evaluate it to get rid of the initial quotes.
if (value[0] === '"' || value[0] === "'") {
// eslint-disable-next-line no-eval
value = eval(value);
}
// Replace all references to colors.
value = replaceObjectVariablesInText(value, colors, "colors");
if (compat) {
// add compat information.
return `${value}; /* Before 6.3.0: --${compat} */`;
}
return `${value};`;
}
function prefixLines(text: string, prefix: string) {
return text.split("\n").join(`\n${prefix}`);
}
function entries2Summary(
entries: DocEntry[],
keyprefix = "",
nestprefix = ""
): string {
let doc = "";
entries.forEach((entry) => {
if (!entry.children) {
return;
}
const header = kebabCase(keyprefix + entry.key);
doc += `${nestprefix}- <a href="#${header}">${header}</a>\n`;
if (entry.children) {
doc += entries2Summary(
entry.children,
keyprefix + entry.key + "-",
nestprefix + " "
);
}
});
return doc;
}
function entries2Doc(entries: DocEntry[], header = "###", prefix = ""): string {
let doc = "";
entries.forEach((entry) => {
if (entry.children) {
doc += `\n${header} ${kebabCase(prefix + entry.key)}\n`;
if (entry.docs) {
doc += `\n${entry.docs}\n`;
}
doc += entries2Doc(
entry.children,
header + "#",
`${prefix}${entry.key}-`
);
} else {
if (entry.docs) {
doc += `\n${entry.docs}\n`;
}
doc += `\n\`--${kebabCase(prefix + entry.key)}: ${transformValue(
entry.value!
)}\`\n`;
}
});
return doc;
}
/**
* 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 = entries2Summary(entries, "", " ");
const list = entries2Doc(entries);
const output = stripIndent`
<!-- START docs:css-variables -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN npm run docs:css-variables -->
### Index
- <a href="#variables">Variables</a>
${prefixLines(summary, " ")}
### Variables
${prefixLines(list, " ")}
<!-- END docs:css-variables -->
`;
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:css-variables\``
);
process.exit(1);
}
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 css variables and a markdown file.");
}
const variableFile = process.argv[2];
const markdownFile = process.argv[3];
// Find tsconfig file.
const configFile = ts.findConfigFile(variableFile, 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(variableFile, config.options);
emitDocs(markdownFile, entries, process.argv[4] === "--verify");
}
main();
+3 -3
View File
@@ -104,7 +104,7 @@ function gatherEntries(
docs: ts.displayPartsToString(symbol.getDocumentationComment(checker)),
type: type.getSymbol()!.getName() as DocEntry["type"],
};
typeNode.forEachChild(ch => {
typeNode.forEachChild((ch) => {
if (ts.isTypeLiteralNode(ch)) {
const text = printer.printNode(
ts.EmitHint.Unspecified,
@@ -179,13 +179,13 @@ function emitDocs(markdownFile: string, entries: DocEntry[], verify = false) {
const summary = stripIndent`
- ${entries
.map(
e => `<a href="#${getEventName(e.name)}">${getEventName(e.name)}</a>`
(e) => `<a href="#${getEventName(e.name)}">${getEventName(e.name)}</a>`
)
.join("\n - ")}
`;
const list = entries
.map(
e =>
(e) =>
codeBlock`
- ${
e.type === "ViewerEvent"
+3 -3
View File
@@ -47,7 +47,7 @@ async function main() {
}
// Create the types for this file.
const types = await generateTSTypesAsString(schema, {
const types = await generateTSTypesAsString(schema, file.fileName, {
tabSpaces: 2,
typePrefix: "GQL",
strictNulls: false,
@@ -66,13 +66,13 @@ if (require.main === module) {
// Only run the main module on file load if this is the main module (we're
// executing this file directly).
main()
.then(files => {
.then((files) => {
for (const { fileName } of files) {
// eslint-disable-next-line no-console
console.log(`Generated ${fileName}`);
}
})
.catch(err => {
.catch((err) => {
// eslint-disable-next-line no-console
console.error(err);
});
+153
View File
@@ -0,0 +1,153 @@
#!/usr/bin/env ./node_modules/.bin/tsnd
//
// Based on the script written by @cristiandean
//
// Source: https://gist.github.com/cristiandean/8196bc2b965f9acf9ad8f9e4530011c1
//
import { FluentResource } from "@fluent/bundle";
import fs from "fs";
import path from "path";
const PROJECT_ROOT = path.resolve(__dirname, "..", "..");
const LOCALE_DIRECTORIES = [
path.join(PROJECT_ROOT, "src/locales"),
path.join(PROJECT_ROOT, "src/core/server/locales"),
];
const wrap = (color: string) => (msg: string) => {
if (!msg) {
return;
}
// eslint-disable-next-line no-console
console.log(`${color}%s\x1b[0m`, msg);
};
const log = {
red: wrap("\x1b[31m"),
green: wrap("\x1b[32m"),
plain: wrap("\x1b[0m"),
};
interface LocaleFileListing {
locale: string;
files: LocaleFile[];
}
interface LocaleFile {
fileName: string;
directory: string;
filePath: string;
keys: Set<string>;
}
function loadLocale(locale: string) {
const listing: LocaleFileListing = { locale, files: [] };
for (const directory of LOCALE_DIRECTORIES) {
// Resolve the directory with the language code, this should be a folder
// containing language files for the specified context.
const localeDirectory = path.join(directory, locale);
if (!fs.existsSync(localeDirectory)) {
continue;
}
// The folder exists, list all files in this directory and begin loading
// them.
const localeFiles = fs.readdirSync(localeDirectory);
for (const fileName of localeFiles) {
const filePath = path.join(localeDirectory, fileName);
// Load the file.
const source = fs.readFileSync(filePath, "utf-8").toString();
// Create the resource based on the file.
const resource = new FluentResource(source);
// Iterate over the ids to create the set of ID's.
const keys = new Set<string>();
for (const entry of resource.body) {
if (entry.id.startsWith("-")) {
// Identifiers starting with a `-` define terms, these are not used
// for this as we're only comparing messages.
continue;
}
keys.add(entry.id);
}
// Add the new file.
listing.files.push({ fileName, directory, filePath, keys });
}
}
return listing;
}
function diffSet(a: Set<string>, b: Set<string>): Set<string> {
const n = new Set(a);
for (const e of b) {
n.delete(e);
}
return n;
}
function prefixDiffSet(prefix: string, a: Set<string>, b: Set<string>) {
return [...diffSet(a, b).values()]
.map((value) => `${prefix}${value}`)
.join("\n");
}
function diff(from: LocaleFileListing, to: LocaleFileListing) {
for (const f of from.files) {
// Log the header information for this file.
log.plain(`* From: ${f.filePath}`);
// Find the associated "to" file.
const t = to.files.find(
(file) => file.fileName === f.fileName && file.directory === f.directory
);
if (!t) {
log.red(
`* To: ${path.join(f.directory, to.locale, f.fileName)} (missing)`
);
log.plain("-".repeat(60));
continue;
}
log.plain(`* To: ${t.filePath}`);
log.green(prefixDiffSet(" + ", f.keys, t.keys));
log.red(prefixDiffSet(" - ", t.keys, f.keys));
log.plain("-".repeat(60));
}
}
function main() {
try {
if (process.argv.length < 3) {
throw new Error("usage: ./scripts/i18n/missingTranslations.ts <locale>");
}
// Load the target translation.
const to = loadLocale(process.argv[2]);
// Load the base language (US English).
const from = loadLocale("en-US");
// Report the difference in key existence.
diff(from, to);
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);
process.exit(1);
}
}
main();
+2 -1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env ts-node
import dotenv from "dotenv";
// Apply all the configuration provided in the .env file if it isn't already in
@@ -26,7 +27,7 @@ process.env.NODE_ENV = "development";
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on("unhandledRejection", err => {
process.on("unhandledRejection", (err) => {
throw err;
});
+1 -1
View File
@@ -17,7 +17,7 @@ process.env.NODE_ENV = "test";
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on("unhandledRejection", err => {
process.on("unhandledRejection", (err) => {
throw err;
});
+1
View File
@@ -1,5 +1,6 @@
import chokidar from "chokidar";
import path from "path";
import { Watcher, WatchOptions } from "./types";
function prependRootDir(
+1 -1
View File
@@ -76,7 +76,7 @@ export default class CommandExecutor implements Executor {
});
}
public execute(filePath: string) {
public execute(filePath: string): void {
this.spawnProcessPotentiallyDebounced();
}
}
+2 -2
View File
@@ -99,14 +99,14 @@ export default class LongRunningExecutor implements Executor {
}
// This is called before exiting.
public async onCleanup() {
public async onCleanup(): Promise<void> {
this.restartDebounced.cancel();
if (this.isRunning) {
await this.kill();
}
}
public execute(filePath: string) {
public execute(filePath: string): void {
if (this.isRunning) {
this.restartDebounced();
return;
+1 -1
View File
@@ -30,7 +30,7 @@ const cmd = program
.description("Run watchers defined in <configFile>")
.parse(process.argv);
run(cmd.args, cmd.opts()).catch(err => {
run(cmd.args, cmd.opts()).catch((err) => {
// eslint-disable-next-line no-console
console.error(err);
process.exit(1);
+4 -14
View File
@@ -1,4 +1,4 @@
import Joi from "joi";
import Joi from "@hapi/joi";
export interface WatchOptions {
ignore?: ReadonlyArray<string>;
@@ -44,23 +44,13 @@ export const configSchema = Joi.object({
watchers: Joi.object().pattern(
/.*/,
Joi.object({
paths: Joi.array()
.items(Joi.string())
.unique(),
ignore: Joi.array()
.items(Joi.string())
.unique()
.optional(),
paths: Joi.array().items(Joi.string()).unique(),
ignore: Joi.array().items(Joi.string()).unique().optional(),
executor: Joi.object(),
})
),
defaultSet: Joi.string().optional(),
sets: Joi.object()
.pattern(
/.*/,
Joi.array()
.items(Joi.string())
.unique()
)
.pattern(/.*/, Joi.array().items(Joi.string()).unique())
.optional(),
}).with("defaultSet", "sets");
+10 -7
View File
@@ -1,5 +1,5 @@
import Joi from "@hapi/joi";
import chalk from "chalk";
import Joi from "joi";
import { pickBy } from "lodash";
import SaneWatcher from "./SaneWatcher";
@@ -28,7 +28,7 @@ async function beginWatch(
}
function setupCleanup(watcher: Watcher, config: Config) {
["SIGINT", "SIGTERM"].forEach(signal =>
["SIGINT", "SIGTERM"].forEach((signal) =>
process.once(signal as any, async () => {
const cleanups = [];
if (watcher.onCleanup) {
@@ -50,7 +50,7 @@ function resolveSets(
value: ReadonlyArray<string>
) {
const resolved: string[] = [];
value.forEach(v => {
value.forEach((v) => {
if (v in sets) {
resolved.push(...sets[v]);
return;
@@ -66,12 +66,12 @@ function filterOnly(
sets?: Record<string, ReadonlyArray<string>>
): Config["watchers"] {
const resolved = sets ? resolveSets(sets, only) : only;
const unknown = resolved.filter(r => !(r in watchers));
const unknown = resolved.filter((r) => !(r in watchers));
if (unknown.length) {
throw new Error(`Watcher Configuration or Set for ${unknown} not found`);
}
return pickBy(watchers, (value, key) => {
if (resolved.indexOf(key) === -1) {
if (!resolved.includes(key)) {
// eslint-disable-next-line no-console
console.log(chalk.grey(`Disabled watcher "${key}"`));
return false;
@@ -80,7 +80,10 @@ function filterOnly(
}) as Config["watchers"];
}
export default async function watch(config: Config, options: Options = {}) {
export default async function watch(
config: Config,
options: Options = {}
): Promise<void> {
Joi.assert(config, configSchema);
const watcher: Watcher = config.backend || new SaneWatcher();
const rootDir = config.rootDir || process.cwd();
@@ -101,7 +104,7 @@ export default async function watch(config: Config, options: Options = {}) {
// eslint-disable-next-line no-console
console.log(chalk.cyanBright(`Start watcher "${key}"`));
const watcherConfig = watchersConfigs[key];
beginWatch(watcher, key, watcherConfig, rootDir).catch(err => {
beginWatch(watcher, key, watcherConfig, rootDir).catch((err) => {
// eslint-disable-next-line no-console
console.error(err);
process.exit(1);
+3 -1
View File
@@ -1,4 +1,5 @@
import convict from "convict";
import os from "os";
import { LOCALES } from "../common/helpers/i18n/locales";
@@ -67,7 +68,7 @@ const config = convict({
maxCores: {
doc: "Set maximum of available cores",
format: "nat",
default: require("os").cpus().length,
default: os.cpus().length,
env: "WEBPACK_MAX_CORES",
arg: "maxCores",
},
@@ -77,6 +78,7 @@ export type Config = typeof config;
export const createClientEnv = (c: Config) => ({
NODE_ENV: c.get("env"),
WEBPACK: "true",
});
// Setup the base configuration.
+12 -20
View File
@@ -7,7 +7,6 @@ import HtmlWebpackPlugin from "html-webpack-plugin";
import { identity } from "lodash";
import MiniCssExtractPlugin from "mini-css-extract-plugin";
import path from "path";
import typescriptFormatter from "react-dev-utils/typescriptFormatter";
import WatchMissingNodeModulesPlugin from "react-dev-utils/WatchMissingNodeModulesPlugin";
import TerserPlugin from "terser-webpack-plugin";
import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin";
@@ -82,10 +81,6 @@ export default function createWebpackConfig(
const styleLoader = {
loader: require.resolve("style-loader"),
options: {
sourceMap: !disableSourcemaps,
hmr: watch,
},
};
const localesOptions = {
@@ -114,10 +109,10 @@ export default function createWebpackConfig(
...ifBuild(
new MiniCssExtractPlugin({
filename: isProduction
? "assets/css/[name].[hash].css"
? "assets/css/[name].[contenthash].css"
: "assets/css/[name].css",
chunkFilename: isProduction
? "assets/css/[id].[hash].css"
? "assets/css/[id].[contenthash].css"
: "assets/css/[id].css",
}),
isProduction &&
@@ -222,10 +217,10 @@ export default function createWebpackConfig(
// Generated JS file names (with nested folders).
// There will be one main bundle, and one file per asynchronous chunk.
filename: isProduction
? "assets/js/[name].[chunkhash].js"
? "assets/js/[name].[contenthash].js"
: "assets/js/[name].js",
chunkFilename: isProduction
? "assets/js/[name].[chunkhash].chunk.js"
? "assets/js/[name].[contenthash].chunk.js"
: "assets/js/[name].chunk.js",
// We inferred the "public path" (such as / or /my-project) from homepage.
publicPath,
@@ -356,7 +351,7 @@ export default function createWebpackConfig(
options: {
limit: 10000,
name: isProduction
? "assets/media/[name].[hash].[ext]"
? "assets/media/[name].[contenthash].[ext]"
: "assets/media/[name].[ext]",
},
},
@@ -367,9 +362,10 @@ export default function createWebpackConfig(
{
loader: require.resolve("css-loader"),
options: {
modules: true,
modules: {
localIdentName: "[name]-[local]-[contenthash]",
},
importLoaders: 2,
localIdentName: "[name]-[local]-[contenthash]",
sourceMap: !disableSourcemaps,
},
},
@@ -471,9 +467,10 @@ export default function createWebpackConfig(
{
loader: require.resolve("css-loader"),
options: {
modules: true,
modules: {
localIdentName: "[name]-[local]-[contenthash]",
},
importLoaders: 1,
localIdentName: "[name]-[local]-[hash:base64:5]",
sourceMap: !disableSourcemaps,
},
},
@@ -502,7 +499,7 @@ export default function createWebpackConfig(
loader: require.resolve("file-loader"),
options: {
name: isProduction
? "assets/media/[name].[hash:8].[ext]"
? "assets/media/[name].[contenthash].[ext]"
: "assets/media/[name].[ext]",
},
},
@@ -525,11 +522,6 @@ export default function createWebpackConfig(
useTypescriptIncrementalApi: false,
checkSyntacticErrors: true,
tsconfig: paths.appTsconfig,
watch: paths.appSrc,
// TODO: (cvle) ForkTsCheckerWebpackPlugin are currently not working, so we resort to default reporting.
silent: false,
// The formatter is normally invoked directly in WebpackDevServerUtils during development
formatter: typescriptFormatter,
})
),
// Makes some environment variables available to the JS code, for example:
+12 -12
View File
@@ -40,7 +40,7 @@ function getFiles(target, pathToLocale, context) {
const files = fs.readdirSync(pathToLocale);
files.forEach(f => {
files.forEach((f) => {
if (commonFiles.includes(f)) {
common.push(f);
return;
@@ -62,12 +62,12 @@ function generateTarget(target, context) {
locales,
bundled,
} = context;
const getLocalePath = locale => path.join(pathToLocales, locale);
const getLocaleFiles = memoize(locale =>
const getLocalePath = (locale) => path.join(pathToLocales, locale);
const getLocaleFiles = memoize((locale) =>
getFiles(target, getLocalePath(locale), context)
);
const loadables = locales.filter(locale => !bundled.includes(locale));
const loadables = locales.filter((locale) => !bundled.includes(locale));
return `
var ret = {
@@ -81,22 +81,22 @@ function generateTarget(target, context) {
// Bundled locales are directly available in the main bundle.
${bundled
.map(
locale => `
(locale) => `
{
var suffixes = ${JSON.stringify(getLocaleFiles(locale).suffixes)};
var contents = [];
${getLocaleFiles(locale)
.common.map(
file => `
(file) => `
contents.push(require(${JSON.stringify(
path.join(getLocalePath(locale), file).replace(/\\/g, "/")
)}));
)}).default);
`
)
.join("\n")}
contents = contents.concat(suffixes.map(function(suffix) { return require("${path
.join(getLocalePath(locale), target)
.replace(/\\/g, "/")}" + suffix); }));
.replace(/\\/g, "/")}" + suffix).default; }));
ret.bundled[${JSON.stringify(locale)}] = contents.join("\\n");
}
`
@@ -106,13 +106,13 @@ function generateTarget(target, context) {
// Loadables are in a separate bundle, that can be easily loaded.
${loadables
.map(
locale => `
(locale) => `
ret.loadables[${JSON.stringify(locale)}] = function() {
var suffixes = ${JSON.stringify(getLocaleFiles(locale).suffixes)};
var promises = [];
${getLocaleFiles(locale)
.common.map(
file => `
(file) => `
promises.push(
import(
/* webpackChunkName: ${JSON.stringify(
@@ -147,7 +147,7 @@ function generateTarget(target, context) {
`;
}
module.exports = function(source) {
module.exports = function (source) {
const options = Object.assign(
{},
DEFAULT_QUERY_VALUES,
@@ -165,7 +165,7 @@ module.exports = function(source) {
let locales = fs.readdirSync(pathToLocales);
if (availableLocales) {
availableLocales.forEach(locale => {
availableLocales.forEach((locale) => {
if (!locales.includes(locale)) {
throw new Error(`locale ${fallbackLocale} not available`);
}
+3 -1
View File
@@ -20,7 +20,9 @@ export default {
appPublicPath: resolveSrc("core/build/publicPath.js"),
appLocales: resolveSrc("locales"),
appThemeVariables: resolveSrc("core/client/ui/theme/variables.ts"),
appThemeVariablesCSS: resolveSrc("core/client/ui/theme/variables.css"),
appSassLikeVariables: resolveSrc("core/client/ui/theme/sassLikeVariables.ts"),
appThemeStreamCSS: resolveSrc("core/client/ui/theme/stream.css"),
appThemeAdminCSS: resolveSrc("core/client/ui/theme/admin.css"),
appThemeMixinsCSS: resolveSrc("core/client/ui/theme/mixins.css"),
appStreamHTML: resolveSrc("core/client/stream/index.html"),
+15 -17
View File
@@ -3,7 +3,6 @@ require("ts-node/register");
const kebabCase = require("lodash/kebabCase");
const mapKeys = require("lodash/mapKeys");
const mapValues = require("lodash/mapValues");
const pickBy = require("lodash/pickBy");
const flat = require("flat");
const paths = require("./paths").default;
const autoprefixer = require("autoprefixer");
@@ -17,23 +16,28 @@ const postcssMixins = require("postcss-mixins");
const postcssPrependImports = require("postcss-prepend-imports");
const postcssAdvancedVariables = require("postcss-advanced-variables");
delete require.cache[paths.appThemeVariables];
const variables = require(paths.appThemeVariables).default;
const flatKebabVariables = mapKeys(
mapValues(flat(variables, { delimiter: "-" }), v => v.toString()),
delete require.cache[paths.appSassLikeVariables];
const sassLikeVariables = require(paths.appSassLikeVariables).default;
const kebabs = mapKeys(
mapValues(flat(sassLikeVariables, { delimiter: "-" }), (v) => v.toString()),
(_, k) => kebabCase(k)
);
// These are sass style variables used in media queries.
const mediaQueryVariables = mapValues(
pickBy(flatKebabVariables, (v, k) => k.startsWith("breakpoints-")),
// Generate sass-style variables to inject into css
const postCssVariables = mapValues(kebabs, (value, key) => {
// Add unit to breakpoints.
// Add 1 to support mobile first approach where we start
// with the smallest screen and gradually add styling for the
// next bigger screen. This is realized using `min-width` without
// ever using `max-width`.
v => `${Number.parseInt(v, 10) + 1}px`
);
if (key.toString().startsWith("breakpoints-")) {
return `${Number.parseInt(value, 10) + 1}px`;
}
// Default return the raw value
return value;
});
module.exports = {
// Necessary for external CSS imports to work
@@ -52,7 +56,7 @@ module.exports = {
// Support nesting.
postcssNested(),
// Sass style variables to be used in media queries.
postcssAdvancedVariables({ variables: mediaQueryVariables }),
postcssAdvancedVariables({ variables: postCssVariables }),
// Reduce some calc()
postcssCalcFunction(),
// Provides a modern CSS environment.
@@ -63,12 +67,6 @@ module.exports = {
postcssFlexbugsFixes,
// Vendor prefixing.
autoprefixer({
browsers: [
">1%",
"last 4 versions",
"Firefox ESR",
"not ie < 9", // React doesn't support IE8 anyway
],
flexbox: "no-2009",
}),
],
+2 -2
View File
@@ -1,10 +1,10 @@
.bar {
height: calc(6 * var(--mini-unit));
background-color: var(--palette-text-primary);
background-color: var(--palette-text-500);
}
.centered {
margin: 10% auto;
padding: 0 calc(0.5 * var(--mini-unit));
box-sizing: border-box;
}
}
@@ -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";
const Loading: FunctionComponent = () => (
<Flex justifyContent="center">
+2 -2
View File
@@ -10,7 +10,7 @@ import { initLocalState } from "./local";
import localesData from "./locales";
// Import css variables.
import "coral-ui/theme/variables.css";
import "coral-ui/theme/stream.css";
async function main() {
await injectConditionalPolyfills();
@@ -30,4 +30,4 @@ async function main() {
ReactDOM.render(<Index />, document.getElementById("app"));
}
main();
void main();
@@ -1,5 +1,6 @@
import { Environment } from "relay-runtime";
import { AuthState } from "coral-framework/lib/auth";
import { CoralContext } from "coral-framework/lib/bootstrap";
import { initLocalBaseState } from "coral-framework/lib/relay";
@@ -8,7 +9,8 @@ import { initLocalBaseState } from "coral-framework/lib/relay";
*/
export default async function initLocalState(
environment: Environment,
context: CoralContext
context: CoralContext,
auth?: AuthState
) {
await initLocalBaseState(environment, context);
initLocalBaseState(environment, context, auth);
}
@@ -0,0 +1,11 @@
.content {
font-family: var(--font-family-secondary);
font-style: normal;
font-weight: var(--font-weight-secondary-bold);
font-size: var(--font-size-6);
line-height: 1.17;
color: var(--palette-text-500);
text-align: center;
}
+7 -4
View File
@@ -1,12 +1,15 @@
import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react";
import { HorizontalGutter, Typography } from "coral-ui/components";
import { HorizontalGutter } from "coral-ui/components/v2";
import styles from "./NotFound.css";
const NotFound: FunctionComponent = () => (
<HorizontalGutter container="main">
<Typography variant="heading3" container="h1">
Not Found
</Typography>
<Localized id="notFound">
<div className={styles.content}>Not Found</div>
</Localized>
</HorizontalGutter>
);
@@ -1,12 +1,13 @@
.title {
font-family: var(--font-family-serif);
font-weight: 600;
font-family: var(--font-family-secondary);
font-style: normal;
font-size: calc(48rem / var(--rem-base));
line-height: calc(42em / 48);
text-align: center;
font-weight: var(--font-weight-secondary-bold);
font-size: var(--font-size-6);
line-height: 1.17;
color: var(--palette-common-black);
color: var(--palette-text-500);
padding-left: var(--spacing-2);
}
.content {
@@ -18,14 +19,15 @@
}
.sectionText {
font-family: var(--font-family-sans-serif);
font-weight: normal;
font-family: var(--font-family-primary);
font-style: normal;
font-size: calc(24rem / var(--rem-base));
line-height: calc(34em / 24);
letter-spacing: 0.3px;
font-weight: var(--font-weight-primary-regular);
font-size: var(--font-size-3);
line-height: 1.25;
color: var(--palette-text-primary);
color: var(--palette-text-500);
margin-bottom: var(--spacing-3);
}
.list {
@@ -34,7 +36,7 @@
}
.list li {
margin-bottom: calc(16em / 24);
margin-bottom: 0.75rem;
}
.listContent {
@@ -43,6 +45,6 @@
.bullet {
display: inline-block;
min-width: 24px;
min-width: 16px;
margin-right: var(--spacing-2);
}
}
@@ -2,7 +2,7 @@ import { Localized } from "@fluent/react/compat";
import cn from "classnames";
import React, { FunctionComponent } from "react";
import { Flex, HorizontalGutter, Icon, Typography } from "coral-ui/components";
import { Flex, HorizontalGutter, Icon } from "coral-ui/components/v2";
import styles from "./DownloadDescription.css";
@@ -10,84 +10,72 @@ const DownloadDescription: FunctionComponent = () => {
return (
<HorizontalGutter size="double">
<Localized id="download-landingPage-title">
<h1 className={styles.title}>Download Your Comment History</h1>
<h1 className={styles.title}>Download your comment history</h1>
</Localized>
<div className={styles.content}>
<div className={styles.section}>
<Localized id="download-landingPage-description">
<Typography variant="bodyCopy" className={styles.sectionText}>
<div className={styles.sectionText}>
Your comment history will be downloaded into a .zip file. After
your comment history is unzipped you will have a comma separated
value (or .csv) file that you can easily import into your favorite
spreadsheet application.
</Typography>
</div>
</Localized>
</div>
<div className={styles.section}>
<Localized id="download-landingPage-contentsDescription">
<Typography variant="bodyCopy" className={styles.sectionText}>
<div className={styles.sectionText}>
For each of your comments the following information is included:
</Typography>
</div>
</Localized>
<ul className={styles.list}>
<li>
<Flex alignItems="center">
<Icon size="lg" className={styles.bullet}>
<Flex alignItems="flex-start">
<Icon size="md" className={styles.bullet}>
check
</Icon>
<Localized id="download-landingPage-contentsDate">
<Typography
variant="bodyCopy"
className={cn(styles.sectionText, styles.listContent)}
>
<div className={cn(styles.sectionText, styles.listContent)}>
When you wrote the comment
</Typography>
</div>
</Localized>
</Flex>
</li>
<li>
<Flex alignItems="center">
<Icon size="lg" className={styles.bullet}>
<Flex alignItems="flex-start">
<Icon size="md" className={styles.bullet}>
check
</Icon>
<Localized id="download-landingPage-contentsUrl">
<Typography
variant="bodyCopy"
className={cn(styles.sectionText, styles.listContent)}
>
<div className={cn(styles.sectionText, styles.listContent)}>
The permalink URL for the comment
</Typography>
</div>
</Localized>
</Flex>
</li>
<li>
<Flex alignItems="center">
<Icon size="lg" className={styles.bullet}>
<Flex alignItems="flex-start">
<Icon size="md" className={styles.bullet}>
check
</Icon>
<Localized id="download-landingPage-contentsText">
<Typography
variant="bodyCopy"
className={cn(styles.sectionText, styles.listContent)}
>
<div className={cn(styles.sectionText, styles.listContent)}>
The comment text
</Typography>
</div>
</Localized>
</Flex>
</li>
<li>
<Flex alignItems="center">
<Icon size="lg" className={styles.bullet}>
<Flex alignItems="flex-start">
<Icon size="md" className={styles.bullet}>
check
</Icon>
<Localized id="download-landingPage-contentsStoryUrl">
<Typography
variant="bodyCopy"
className={cn(styles.sectionText, styles.listContent)}
>
<div className={cn(styles.sectionText, styles.listContent)}>
The URL on the article or story where the comment appears
</Typography>
</div>
</Localized>
</Flex>
</li>
@@ -1,8 +1,3 @@
.form {
text-align: center;
}
.downloadButton {
font-size: calc(18rem / var(--rem-base));
line-height: calc(23em / 18);
}
@@ -1,7 +1,8 @@
import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent, useCallback, useState } from "react";
import { Button, HorizontalGutter } from "coral-ui/components";
import { HorizontalGutter } from "coral-ui/components/v2";
import { Button } from "coral-ui/components/v3";
import styles from "./DownloadForm.css";
@@ -25,15 +26,16 @@ const DownloadForm: FunctionComponent<Props> = ({ token }) => {
onSubmit={onSubmit}
>
<input name="token" type="hidden" value={token} />
<Localized id="download-landingPage-downloadComments">
<Localized id="download-landingPage-download">
<Button
type="submit"
variant="filled"
color="primary"
paddingSize="medium"
disabled={submitted}
className={styles.downloadButton}
upperCase
>
Download My Comment History
Download
</Button>
</Localized>
</form>
@@ -6,11 +6,11 @@
.root {
display: inline-block;
max-width: calc(70 * var(--mini-unit));
max-width: calc(70 * var(--spacing-2));
@media (min-width: $breakpoints-xs) {
max-width: calc(90 * var(--mini-unit));
max-width: calc(60 * var(--spacing-2));
}
text-align: left;
}
}
@@ -6,7 +6,7 @@ import { useToken } from "coral-framework/hooks";
import { createFetch } from "coral-framework/lib/relay";
import { withRouteConfig } from "coral-framework/lib/router";
import { parseHashQuery } from "coral-framework/utils";
import { HorizontalGutter } from "coral-ui/components";
import { HorizontalGutter } from "coral-ui/components/v2";
import DownloadDescription from "./DownloadDescription";
import DownloadForm from "./DownloadForm";
@@ -1,7 +0,0 @@
.icon {
margin-right: var(--spacing-2);
}
.callout {
justify-content: left;
}
@@ -1,22 +1,21 @@
import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react";
import { CallOut, Flex, Icon } from "coral-ui/components";
import styles from "./Sorry.css";
import { Icon } from "coral-ui/components/v2";
import { CallOut } from "coral-ui/components/v3";
const Sorry: FunctionComponent = () => {
return (
<CallOut color="error" fullWidth className={styles.callout}>
<Flex>
<Icon size="md" className={styles.icon}>
error
</Icon>
<CallOut
color="error"
icon={<Icon>error</Icon>}
titleWeight="semiBold"
title={
<Localized id="download-landingPage-sorry">
Your download link is invalid.
</Localized>
</Flex>
</CallOut>
}
/>
);
};
@@ -0,0 +1,52 @@
.title {
font-family: var(--font-family-secondary);
font-style: normal;
font-weight: var(--font-weight-secondary-bold);
font-size: var(--font-size-6);
line-height: 1.17;
color: var(--palette-text-500);
margin-bottom: var(--spacing-2);
}
.description {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-regular);
font-size: var(--font-size-3);
line-height: 1.25;
color: var(--palette-text-500);
margin-bottom: var(--spacing-3);
}
.label {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-bold);
font-size: var(--font-size-2);
line-height: 1.14;
color: var(--palette-text-500);
margin-bottom: var(--spacing-1);
}
.labelDescription {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-regular);
font-size: var(--font-size-2);
line-height: 1.285;
color: var(--palette-text-100);
margin-bottom: var(--spacing-2);
}
.submit {
margin-top: var(--spacing-5);
margin-bottom: var(--spacing-1);
}
@@ -5,10 +5,12 @@ import { Form } from "react-final-form";
import { InvalidRequestError } from "coral-framework/lib/errors";
import { useMutation } from "coral-framework/lib/relay";
import { Button, HorizontalGutter, Typography } from "coral-ui/components";
import { Button } from "coral-ui/components/v3";
import ConfirmMutation from "./ConfirmMutation";
import styles from "./Confirm.css";
interface Props {
token: string;
disabled?: boolean;
@@ -33,18 +35,18 @@ const ConfirmForm: React.FunctionComponent<Props> = ({ onSuccess, token }) => {
<Form onSubmit={onSubmit}>
{({ handleSubmit, submitting }) => (
<form autoComplete="off" onSubmit={handleSubmit}>
<HorizontalGutter size="double">
<HorizontalGutter>
<Localized id="confirmEmail-emailConfirmation">
<Typography variant="heading1">Email Confirmation</Typography>
<div>
<div>
<Localized id="confirmEmail-confirmYourEmailAddress">
<div className={styles.title}>Confirm your email address</div>
</Localized>
<Localized id="confirmEmail-pleaseClickToConfirm">
<Typography variant="bodyCopy">
<div className={styles.description}>
Click below to confirm your email address.
</Typography>
</div>
</Localized>
</HorizontalGutter>
<HorizontalGutter>
</div>
<div>
<Localized id="confirmEmail-confirmEmail">
<Button
type="submit"
@@ -52,12 +54,14 @@ const ConfirmForm: React.FunctionComponent<Props> = ({ onSuccess, token }) => {
color="primary"
disabled={submitting}
fullWidth
upperCase
className={styles.submit}
>
Confirm email
</Button>
</Localized>
</HorizontalGutter>
</HorizontalGutter>
</div>
</div>
</form>
)}
</Form>
@@ -1,7 +1,9 @@
import { Localized } from "@fluent/react/compat";
import React from "react";
import { CallOut, HorizontalGutter, Typography } from "coral-ui/components";
import { CallOut } from "coral-ui/components/v3";
import styles from "./Confirm.css";
interface Props {
reason: React.ReactNode;
@@ -9,23 +11,27 @@ interface Props {
const Sorry: React.FunctionComponent<Props> = ({ reason }) => {
return (
<HorizontalGutter size="double">
<div>
<Localized id="confirmEmail-oopsSorry">
<Typography variant="heading1">Oops Sorry!</Typography>
<div className={styles.title}>Oops Sorry!</div>
</Localized>
<CallOut color="error" fullWidth>
{reason ? (
reason
) : (
<Localized id="account-tokenNotFound">
<span data-testid="invalid-link">
The specified link is invalid, check to see if it was copied
correctly.
</span>
</Localized>
)}
</CallOut>
</HorizontalGutter>
<CallOut
color="error"
titleWeight="semiBold"
title={
reason ? (
reason
) : (
<Localized id="account-tokenNotFound">
<span data-testid="invalid-link">
The specified link is invalid, check to see if it was copied
correctly.
</span>
</Localized>
)
}
/>
</div>
);
};
@@ -1,20 +1,18 @@
import { Localized } from "@fluent/react/compat";
import React from "react";
import { HorizontalGutter, Typography } from "coral-ui/components";
import styles from "./Confirm.css";
const Success: React.FunctionComponent = () => {
return (
<HorizontalGutter size="double">
<div>
<Localized id="confirmEmail-successfullyConfirmed">
<Typography variant="heading1">Email successfully confirmed</Typography>
<div className={styles.title}>Email successfully confirmed</div>
</Localized>
<Localized id="confirmEmail-youMayClose">
<Typography variant="bodyCopy">
You may now close this window.
</Typography>
<div className={styles.description}>You may now close this window.</div>
</Localized>
</HorizontalGutter>
</div>
);
};
@@ -1,7 +1,9 @@
import { Localized } from "@fluent/react/compat";
import React from "react";
import { CallOut, HorizontalGutter, Typography } from "coral-ui/components";
import { CallOut } from "coral-ui/components/v3";
import styles from "./Unsubscribe.css";
interface Props {
reason: React.ReactNode;
@@ -9,23 +11,27 @@ interface Props {
const Sorry: React.FunctionComponent<Props> = ({ reason }) => {
return (
<HorizontalGutter size="double">
<div>
<Localized id="unsubscribe-oopsSorry">
<Typography variant="heading1">Oops Sorry!</Typography>
<div className={styles.title}>Oops Sorry!</div>
</Localized>
<CallOut color="error" fullWidth>
{reason ? (
reason
) : (
<Localized id="account-tokenNotFound">
<span data-testid="invalid-link">
The specified link is invalid, check to see if it was copied
correctly.
</span>
</Localized>
)}
</CallOut>
</HorizontalGutter>
<CallOut
color="error"
titleWeight="semiBold"
title={
reason ? (
reason
) : (
<Localized id="account-tokenNotFound">
<span data-testid="invalid-link">
The specified link is invalid, check to see if it was copied
correctly.
</span>
</Localized>
)
}
/>
</div>
);
};
@@ -1,17 +1,20 @@
import { Localized } from "@fluent/react/compat";
import React from "react";
import { HorizontalGutter, Typography } from "coral-ui/components";
import styles from "./Unsubscribe.css";
const Success: React.FunctionComponent = () => {
return (
<HorizontalGutter data-testid="success" size="double">
<Localized id="unsubscribe-successfullyUnsubscribed">
<Typography variant="heading1">
You are now unsubscribed from all notifications
</Typography>
<div data-testid="success">
<Localized id="unsubscribe-unsubscribedSuccessfully">
<div className={styles.title}>
Unsubscribed successfully from email notifications
</div>
</Localized>
</HorizontalGutter>
<Localized id="unsubscribe-youMayNowClose">
<div className={styles.description}>You may now close this window</div>
</Localized>
</div>
);
};
@@ -0,0 +1,52 @@
.title {
font-family: var(--font-family-secondary);
font-style: normal;
font-weight: var(--font-weight-secondary-bold);
font-size: var(--font-size-6);
line-height: 1.17;
color: var(--palette-text-500);
margin-bottom: var(--spacing-2);
}
.description {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-regular);
font-size: var(--font-size-3);
line-height: 1.25;
color: var(--palette-text-500);
margin-bottom: var(--spacing-3);
}
.label {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-bold);
font-size: var(--font-size-2);
line-height: 1.14;
color: var(--palette-text-500);
margin-bottom: var(--spacing-1);
}
.labelDescription {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-regular);
font-size: var(--font-size-2);
line-height: 1.285;
color: var(--palette-text-100);
margin-bottom: var(--spacing-2);
}
.submit {
margin-top: var(--spacing-5);
margin-bottom: var(--spacing-1);
}
@@ -5,15 +5,12 @@ import { Form } from "react-final-form";
import { InvalidRequestError } from "coral-framework/lib/errors";
import { useMutation } from "coral-framework/lib/relay";
import {
Button,
CallOut,
HorizontalGutter,
Typography,
} from "coral-ui/components";
import { Button, CallOut } from "coral-ui/components/v3";
import UnsubscribeNotificationsMutation from "./UnsubscribeNotificationsMutation";
import styles from "./Unsubscribe.css";
interface Props {
token: string;
disabled?: boolean;
@@ -42,30 +39,34 @@ const UnsubscribeForm: React.FunctionComponent<Props> = ({
<Form onSubmit={onSubmit}>
{({ handleSubmit, submitting, submitError }) => (
<form onSubmit={handleSubmit}>
<HorizontalGutter>
<div>
<Localized id="unsubscribe-unsubscribeFromEmails">
<div className={styles.title}>
Unsubscribe from email notifications
</div>
</Localized>
<Localized id="unsubscribe-clickToConfirm">
<Typography variant="heading1">
<div className={styles.description}>
Click below to confirm that you want to unsubscribe from all
notifications.
</Typography>
</div>
</Localized>
{submitError && (
<CallOut color="error" fullWidth>
{submitError}
</CallOut>
)}
<Localized id="unsubscribe-confirm">
{submitError && <CallOut color="error" title={submitError} />}
<Localized id="unsubscribe-submit-unsubscribe">
<Button
type="submit"
variant="filled"
paddingSize="medium"
color="primary"
disabled={submitting}
upperCase
fullWidth
className={styles.submit}
>
Confirm
Unsubscribe
</Button>
</Localized>
</HorizontalGutter>
</div>
</form>
)}
</Form>
@@ -0,0 +1,52 @@
.title {
font-family: var(--font-family-secondary);
font-style: normal;
font-weight: var(--font-weight-secondary-bold);
font-size: var(--font-size-6);
line-height: 1.17;
color: var(--palette-text-500);
margin-bottom: var(--spacing-2);
}
.description {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-regular);
font-size: var(--font-size-3);
line-height: 1.25;
color: var(--palette-text-500);
margin-bottom: var(--spacing-3);
}
.label {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-bold);
font-size: var(--font-size-2);
line-height: 1.14;
color: var(--palette-text-500);
margin-bottom: var(--spacing-1);
}
.labelDescription {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-regular);
font-size: var(--font-size-2);
line-height: 1.285;
color: var(--palette-text-100);
margin-bottom: var(--spacing-2);
}
.submit {
margin-top: var(--spacing-5);
margin-bottom: var(--spacing-1);
}
@@ -4,26 +4,20 @@ import React, { useCallback } from "react";
import { Field, Form } from "react-final-form";
import { InvalidRequestError } from "coral-framework/lib/errors";
import { colorFromMeta, ValidationMessage } from "coral-framework/lib/form";
import { colorFromMeta } from "coral-framework/lib/form";
import { useMutation } from "coral-framework/lib/relay";
import {
composeValidators,
required,
validatePassword,
} from "coral-framework/lib/validation";
import {
Button,
CallOut,
FormField,
HorizontalGutter,
InputDescription,
InputLabel,
PasswordField,
Typography,
} from "coral-ui/components";
import { FormField, PasswordField } from "coral-ui/components/v2";
import { Button, CallOut, ValidationMessage } from "coral-ui/components/v3";
import ResetPasswordMutation from "./ResetPasswordMutation";
import styles from "./Reset.css";
interface Props {
token: string;
disabled?: boolean;
@@ -60,22 +54,20 @@ const ResetPasswordForm: React.FunctionComponent<Props> = ({
<Form onSubmit={onSubmit}>
{({ handleSubmit, submitting, submitError }) => (
<form autoComplete="off" onSubmit={handleSubmit}>
<HorizontalGutter size="double">
<HorizontalGutter>
<div>
<div>
<Localized id="resetPassword-resetYourPassword">
<Typography variant="heading1">
Reset your password
</Typography>
<div className={styles.title}>Reset your password</div>
</Localized>
<Localized id="resetPassword-pleaseEnterNewPassword">
<Typography variant="bodyCopy">
<div className={styles.description}>
Please enter a new password to use to sign in to your
account. Make sure it is unique and be sure to keep it
secure.
</Typography>
</div>
</Localized>
</HorizontalGutter>
<HorizontalGutter>
</div>
<div>
<Field
name="password"
validate={composeValidators(required, validatePassword)}
@@ -83,15 +75,17 @@ const ResetPasswordForm: React.FunctionComponent<Props> = ({
{({ input, meta }) => (
<FormField>
<Localized id="resetPassword-passwordLabel">
<InputLabel htmlFor={input.name}>Password</InputLabel>
<label className={styles.label} htmlFor={input.name}>
Password
</label>
</Localized>
<Localized
id="resetPassword-passwordDescription"
$minLength={8}
>
<InputDescription>
<div className={styles.labelDescription}>
{"Must be at least {$minLength} characters"}
</InputDescription>
</div>
</Localized>
<Localized
id="resetPassword-passwordTextField"
@@ -107,28 +101,27 @@ const ResetPasswordForm: React.FunctionComponent<Props> = ({
{...input}
/>
</Localized>
<ValidationMessage meta={meta} fullWidth />
<ValidationMessage meta={meta} />
</FormField>
)}
</Field>
{submitError && (
<CallOut color="error" fullWidth>
{submitError}
</CallOut>
)}
{submitError && <CallOut color="error" title={submitError} />}
<Localized id="resetPassword-resetPassword">
<Button
type="submit"
variant="filled"
color="primary"
paddingSize="medium"
disabled={submitting}
upperCase
fullWidth
className={styles.submit}
>
Reset Password
</Button>
</Localized>
</HorizontalGutter>
</HorizontalGutter>
</div>
</div>
</form>
)}
</Form>
@@ -1,7 +1,9 @@
import { Localized } from "@fluent/react/compat";
import React from "react";
import { CallOut, HorizontalGutter, Typography } from "coral-ui/components";
import { CallOut } from "coral-ui/components/v3";
import styles from "./Reset.css";
interface Props {
reason: React.ReactNode;
@@ -9,23 +11,27 @@ interface Props {
const Sorry: React.FunctionComponent<Props> = ({ reason }) => {
return (
<HorizontalGutter size="double">
<div>
<Localized id="resetPassword-oopsSorry">
<Typography variant="heading1">Oops Sorry!</Typography>
<div className={styles.title}>Oops Sorry!</div>
</Localized>
<CallOut color="error" fullWidth>
{reason ? (
reason
) : (
<Localized id="account-tokenNotFound">
<span data-testid="invalid-link">
The specified link is invalid, check to see if it was copied
correctly.
</span>
</Localized>
)}
</CallOut>
</HorizontalGutter>
<CallOut
color="error"
titleWeight="semiBold"
title={
reason ? (
reason
) : (
<Localized id="account-tokenNotFound">
<span data-testid="invalid-link">
The specified link is invalid, check to see if it was copied
correctly.
</span>
</Localized>
)
}
/>
</div>
);
};
@@ -1,21 +1,21 @@
import { Localized } from "@fluent/react/compat";
import React from "react";
import { HorizontalGutter, Typography } from "coral-ui/components";
import styles from "./Reset.css";
const Success: React.FunctionComponent = () => {
return (
<HorizontalGutter size="double">
<div>
<Localized id="resetPassword-successfullyReset">
<Typography variant="heading1">Password successfully reset</Typography>
<div className={styles.title}>Password successfully reset</div>
</Localized>
<Localized id="resetPassword-youMayClose">
<Typography variant="bodyCopy">
<div className={styles.description}>
You may now close this window and sign in to your account with your
new password.
</Typography>
</div>
</Localized>
</HorizontalGutter>
</div>
);
};
@@ -20,29 +20,22 @@ exports[`renders form 1`] = `
autoComplete="off"
onSubmit={[Function]}
>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<h1
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary"
<div>
<div>
<div
className="Confirm-title"
>
Email Confirmation
</h1>
<p
className="Box-root Typography-root Typography-bodyCopy Typography-colorTextPrimary"
Confirm your email address
</div>
<div
className="Confirm-description"
>
Click below to confirm your email address.
</p>
</div>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth"
data-color="primary"
className="BaseButton-root Button-base Button-filled Button-fontSizeSmall Button-textAlignCenter Button-fontFamilyPrimary Button-fontWeightPrimaryBold Button-paddingSizeSmall Button-colorPrimary Button-upperCase Button-fullWidth Confirm-submit"
data-variant="filled"
disabled={false}
onBlur={[Function]}
@@ -79,25 +72,34 @@ exports[`renders missing confirm token 1`] = `
<div
className="ConfirmRoute-root"
>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
>
<h1
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary"
<div>
<div
className="Confirm-title"
>
Oops Sorry!
</h1>
</div>
<div
className="CallOut-root CallOut-colorError CallOut-fullWidth"
className="CallOut-root CallOut-error CallOut-leftBorder"
>
<div
className="CallOut-inner"
className="CallOut-container"
>
<span
data-testid="invalid-link"
<div
className="CallOut-content"
>
The specified link is invalid, check to see if it was copied correctly.
</span>
<div
className="CallOut-title CallOut-titleSemiBold"
>
<span
data-testid="invalid-link"
>
The specified link is invalid, check to see if it was copied correctly.
</span>
</div>
<div
className="CallOut-body"
/>
</div>
</div>
</div>
</div>
@@ -21,41 +21,35 @@ exports[`renders form 1`] = `
autoComplete="off"
onSubmit={[Function]}
>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<h1
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary"
<div>
<div>
<div
className="Reset-title"
>
Reset your password
</h1>
<p
className="Box-root Typography-root Typography-bodyCopy Typography-colorTextPrimary"
</div>
<div
className="Reset-description"
>
Please enter a new password to use to sign in to your account.
Make sure it is unique and be sure to keep it secure.
</p>
</div>
</div>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<div>
<div
className="Box-root HorizontalGutter-root FormField-root HorizontalGutter-half"
className="Box-root HorizontalGutter-root FormField-root HorizontalGutter-spacing-2"
>
<label
className="Box-root Typography-root Typography-inputLabel Typography-colorTextPrimary InputLabel-root"
className="Reset-label"
htmlFor="password"
>
Password
</label>
<p
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
<div
className="Reset-labelDescription"
>
Must be at least 8 characters
</p>
</div>
<div
className="PasswordField-fullWidth PasswordField-root"
>
@@ -67,6 +61,7 @@ Make sure it is unique and be sure to keep it secure.
autoComplete="new-password"
autoCorrect="off"
className="PasswordField-colorRegular PasswordField-fullWidth PasswordField-input"
data-testid="password-field"
disabled={false}
id="password"
name="password"
@@ -97,8 +92,7 @@ Make sure it is unique and be sure to keep it secure.
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth"
data-color="primary"
className="BaseButton-root Button-base Button-filled Button-fontSizeSmall Button-textAlignCenter Button-fontFamilyPrimary Button-fontWeightPrimaryBold Button-paddingSizeMedium Button-colorPrimary Button-upperCase Button-fullWidth Reset-submit"
data-variant="filled"
disabled={false}
onBlur={[Function]}
@@ -136,25 +130,34 @@ exports[`renders missing reset token 1`] = `
<div
className="ResetRoute-root"
>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
>
<h1
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary"
<div>
<div
className="Reset-title"
>
Oops Sorry!
</h1>
</div>
<div
className="CallOut-root CallOut-colorError CallOut-fullWidth"
className="CallOut-root CallOut-error CallOut-leftBorder"
>
<div
className="CallOut-inner"
className="CallOut-container"
>
<span
data-testid="invalid-link"
<div
className="CallOut-content"
>
The specified link is invalid, check to see if it was copied correctly.
</span>
<div
className="CallOut-title CallOut-titleSemiBold"
>
<span
data-testid="invalid-link"
>
The specified link is invalid, check to see if it was copied correctly.
</span>
</div>
<div
className="CallOut-body"
/>
</div>
</div>
</div>
</div>
@@ -22,17 +22,19 @@ exports[`renders form 1`] = `
<form
onSubmit={[Function]}
>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<h1
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary"
<div>
<div
className="Unsubscribe-title"
>
Unsubscribe from email notifications
</div>
<div
className="Unsubscribe-description"
>
Click below to confirm that you want to unsubscribe from all notifications.
</h1>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth"
data-color="primary"
className="BaseButton-root Button-base Button-filled Button-fontSizeSmall Button-textAlignCenter Button-fontFamilyPrimary Button-fontWeightPrimaryBold Button-paddingSizeMedium Button-colorPrimary Button-upperCase Button-fullWidth Unsubscribe-submit"
data-variant="filled"
disabled={false}
onBlur={[Function]}
@@ -42,7 +44,7 @@ exports[`renders form 1`] = `
onTouchEnd={[Function]}
type="submit"
>
Confirm
Unsubscribe
</button>
</div>
</form>
@@ -69,25 +71,34 @@ exports[`renders missing confirm token 1`] = `
<div
className="UnsubscribeRoute-root"
>
<div
className="Box-root HorizontalGutter-root HorizontalGutter-double"
>
<h1
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary"
<div>
<div
className="Unsubscribe-title"
>
Oops Sorry!
</h1>
</div>
<div
className="CallOut-root CallOut-colorError CallOut-fullWidth"
className="CallOut-root CallOut-error CallOut-leftBorder"
>
<div
className="CallOut-inner"
className="CallOut-container"
>
<span
data-testid="invalid-link"
<div
className="CallOut-content"
>
The specified link is invalid, check to see if it was copied correctly.
</span>
<div
className="CallOut-title CallOut-titleSemiBold"
>
<span
data-testid="invalid-link"
>
The specified link is invalid, check to see if it was copied correctly.
</span>
</div>
<div
className="CallOut-body"
/>
</div>
</div>
</div>
</div>
@@ -53,9 +53,7 @@ it("renders form", async () => {
await act(async () => {
await waitForElement(() =>
within(root).getByText("Email Confirmation", {
exact: false,
})
within(root).getByText("Confirm your email address")
);
});
expect(within(root).toJSON()).toMatchSnapshot();
@@ -130,9 +128,7 @@ it("submits form", async () => {
await act(async () => {
await waitForElement(() =>
within(root).getByText("Email Confirmation", {
exact: false,
})
within(root).getByText("Confirm your email address")
);
});
const form = within(root).getByType("form");
@@ -17,7 +17,7 @@ interface Props {
onGotoComment?: React.EventHandler<React.MouseEvent>;
}
const ApprovedComment: FunctionComponent<Props> = props => (
const ApprovedComment: FunctionComponent<Props> = (props) => (
<DecisionItem icon={<ApprovedIcon />}>
<Localized
id="decisionHistory-approvedCommentBy"
@@ -1,3 +1,3 @@
.root {
color: var(--v2-palette-success-main);
color: var(--palette-success-500);
}
@@ -19,13 +19,13 @@ interface Props {
onClosePopover: () => void;
}
const DecisionHistory: FunctionComponent<Props> = props => (
const DecisionHistory: FunctionComponent<Props> = (props) => (
<div data-testid="decisionHistory-container">
<Title />
<Main>
<DecisionList>
{props.actions.length === 0 && <Empty />}
{props.actions.map(action => (
{props.actions.map((action) => (
<DecisionHistoryItemContainer
key={action.id}
action={action}
@@ -3,6 +3,6 @@
}
.historyIcon {
color: var(--v2-palette-text-secondary);
color: var(--palette-text-100);
margin-right: 10px;
}
@@ -23,7 +23,7 @@ export class DecisionHistoryContainer extends React.Component<
public render() {
const actions = this.props.viewer.commentModerationActionHistory.edges.map(
edge => edge.node
(edge) => edge.node
);
return (
<DecisionHistory
@@ -43,7 +43,7 @@ export class DecisionHistoryContainer extends React.Component<
this.setState({ disableLoadMore: true });
this.props.relay.loadMore(
10, // Fetch the next 10 feed items
error => {
(error) => {
this.setState({ disableLoadMore: false });
if (error) {
// eslint-disable-next-line no-console
@@ -1,6 +1,7 @@
import React, { Component } from "react";
import { graphql } from "react-relay";
import { graphql, QueryRenderer } from "coral-framework/lib/relay";
import { QueryRenderer } from "coral-framework/lib/relay";
import { DecisionHistoryQuery as QueryTypes } from "coral-admin/__generated__/DecisionHistoryQuery.graphql";
@@ -1,5 +1,5 @@
.root {
padding: var(--v2-spacing-2) var(--v2-spacing-1);
padding: var(--spacing-2) var(--spacing-1);
}
.leftCol {
@@ -8,5 +8,5 @@
flex-grow: 0;
flex-shrink: 0;
padding-top: 3px;
margin-right: var(--v2-spacing-2);
margin-right: var(--spacing-2);
}
@@ -9,7 +9,7 @@ interface Props {
children: React.ReactNode;
}
const DecisionItem: FunctionComponent<Props> = props => (
const DecisionItem: FunctionComponent<Props> = (props) => (
<li className={styles.root}>
<Flex>
<div className={styles.leftCol}>{props.icon}</div>
@@ -1,4 +1,4 @@
$decisionHistoryBorderColor: var(--v2-colors-grey-300);
$decisionHistoryBorderColor: var(--palette-grey-300);
.root {
margin: 0;
@@ -2,7 +2,7 @@ import React, { FunctionComponent } from "react";
import styles from "./DecisionList.css";
const DecisionList: FunctionComponent = props => (
const DecisionList: FunctionComponent = (props) => (
<ul className={styles.root}>{props.children}</ul>
);
@@ -1,7 +1,7 @@
.root {
height: 100%;
font-size: var(--v2-font-size-1);
line-height: var(--v2-line-height-reset);
color: var(--v2-colors-mono-100);
padding: 0 var(--v2-spacing-1);
font-size: var(--font-size-1);
line-height: 1.33;
color: var(--palette-text-100);
padding: 0 var(--spacing-1);
}
@@ -3,8 +3,8 @@
}
.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);
font-family: var(--font-family-primary);
font-weight: var(--font-weight-primary-regular);
font-size: var(--font-size-2);
line-height: 1.285;
}
@@ -1,3 +1,3 @@
.root {
margin-top: var(--v2-spacing-1);
margin-top: var(--spacing-1);
}
@@ -8,7 +8,7 @@ interface Props {
children: React.ReactNode;
}
const Footer: FunctionComponent<Props> = props => (
const Footer: FunctionComponent<Props> = (props) => (
<Flex className={styles.root} alignItems="baseline">
{props.children}
</Flex>
@@ -1,10 +1,10 @@
$moderateCardDecisionHistoryLinkTextColor: var(--v2-colors-teal-700);
$moderateCardDecisionHistoryLinkTextColor: $colors-teal-700;
.root {
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);
font-weight: var(--font-weight-primary-bold);
font-family: var(--font-family-primary);
font-size: var(--font-size-1);
line-height: 1.33;
color: $moderateCardDecisionHistoryLinkTextColor;
font-style: var(--v2-font-style-underline);
font-style: var(--font-style-underline);
}
@@ -11,7 +11,7 @@ interface Props {
onClick?: React.EventHandler<React.MouseEvent>;
}
const GoToCommentLink: FunctionComponent<Props> = props => {
const GoToCommentLink: FunctionComponent<Props> = (props) => {
return (
<Link
as={TextLink}
@@ -8,9 +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);
color: var(--palette-text-500);
font-weight: var(--font-weight-primary-semi-bold);
font-family: var(--font-family-primary);
font-size: var(--font-size-2);
line-height: 1.285;
}
@@ -6,7 +6,7 @@ interface Props {
children: React.ReactNode;
}
const Info: FunctionComponent<Props> = props => (
const Info: FunctionComponent<Props> = (props) => (
<span className={styles.root}>{props.children}</span>
);
@@ -2,7 +2,7 @@ import React, { FunctionComponent } from "react";
import styles from "./Main.css";
const Main: FunctionComponent = props => (
const Main: FunctionComponent = (props) => (
<div className={styles.root}>{props.children}</div>
);
@@ -17,7 +17,7 @@ interface Props {
onGotoComment?: React.EventHandler<React.MouseEvent>;
}
const RejectedComment: FunctionComponent<Props> = props => (
const RejectedComment: FunctionComponent<Props> = (props) => (
<DecisionItem icon={<RejectedIcon />}>
<Localized
id="decisionHistory-rejectedCommentBy"
@@ -1,3 +1,3 @@
.root {
color: var(--v2-palette-error-main);
color: var(--palette-error-500);
}
@@ -1,20 +1,20 @@
$moderateCardDecisionHistoryLinkTextColor: var(--v2-colors-teal-700);
$moderateCardDecisionHistoryBorderColor: var(--v2-colors-grey-300);
$moderateCardDecisionHistoryLinkTextColor: $colors-teal-700;
$moderateCardDecisionHistoryBorderColor: var(--palette-grey-300);
.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);
font-size: var(--font-size-2);
font-weight: var(--font-weight-primary-bold);
font-family: var(--font-family-primary);
line-height: 1.14;
text-transform: uppercase;
color: $moderateCardDecisionHistoryLinkTextColor;
width: 100%;
border-top: 1px solid $moderateCardDecisionHistoryBorderColor;
text-align: center;
padding-top: var(--v2-spacing-1);
padding-bottom: var(--v2-spacing-1);
padding-top: var(--spacing-1);
padding-bottom: var(--spacing-1);
&:disabled {
color: var(--v2-palette-grey-lighter);
color: var(--palette-grey-300);
}
}
@@ -10,7 +10,7 @@ interface Props {
onClick?: () => void;
}
const ShowMoreButton: FunctionComponent<Props> = props => (
const ShowMoreButton: FunctionComponent<Props> = (props) => (
<Localized id="decisionHistory-showMoreButton">
<BaseButton
className={styles.root}
@@ -1,9 +1,9 @@
$timestampColor: var(--v2-colors-mono-100);
$timestampColor: var(--palette-text-100);
.root {
color: $timestampColor;
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);
font-family: var(--font-family-primary);
font-weight: var(--font-weight-primary-bold);
font-size: var(--font-size-1);
line-height: 1.33;
}
@@ -8,7 +8,7 @@ interface Props {
children: string;
}
const DecisionHistory: FunctionComponent<Props> = props => (
const DecisionHistory: FunctionComponent<Props> = (props) => (
<Timestamp className={styles.root}>{props.children}</Timestamp>
);
@@ -1,23 +1,23 @@
$decisionHistoryBorderColor: var(--v2-colors-grey-300);
$decisionHistoryTitleBackgroundColor: var(--v2-colors-grey-200);
$decisionHistoryBorderColor: var(--palette-grey-300);
$decisionHistoryTitleBackgroundColor: var(--palette-grey-200);
.root {
background: $decisionHistoryTitleBackgroundColor;
padding: var(--v2-spacing-1);
color: var(--v2-palette-text-primary);
padding: var(--spacing-1);
color: var(--palette-text-500);
border-bottom: 1px solid $decisionHistoryBorderColor;
font-size: var(--v2-font-size-icon-medium);
}
.icon {
margin-right: var(--v2-spacing-2);
font-size: var(--font-size-icon-md);
margin-right: var(--spacing-2);
}
.text {
text-transform: uppercase;
font-weight: var(--v2-font-weight-primary-bold);
color: var(--v2-palette-text-primary);
font-size: var(--v2-font-size-2);
font-weight: var(--font-weight-primary-bold);
color: var(--palette-text-500);
font-size: var(--font-size-2);
line-height: 1;
font-family: var(--v2-font-family-primary);
font-family: var(--font-family-primary);
}
@@ -1,9 +1,9 @@
$moderateCardDecisionHistoryColor: var(--v2-colors-mono-900);
$moderateCardDecisionHistoryColor: var(--palette-text-900);
.root {
color: $moderateCardDecisionHistoryColor;
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);
font-weight: var(--font-weight-secondary-bold);
font-family: var(--font-family-secondary);
line-height: 1.3;
font-size: var(--font-size-3);
}
@@ -11,9 +11,7 @@ exports[`renders correctly 1`] = `
className="DecisionHistoryLoading-container"
justifyContent="center"
>
<Delay
ms={500}
>
<Delay>
<withPropsOnChange(Spinner)
size="sm"
/>
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<ForwardRef(render)
<Link
as={[Function]}
className="GoToCommentLink-root"
onClick={[Function]}
@@ -18,5 +18,5 @@ exports[`renders correctly 1`] = `
<ForwardRef(forwardRef)>
chevron_right
</ForwardRef(forwardRef)>
</ForwardRef(render)>
</Link>
`;

Some files were not shown because too many files have changed in this diff Show More