1
1
import { Localized } from "@fluent/react/compat" ;
2
- import React , { FunctionComponent , useState } from "react" ;
2
+ import React , { FunctionComponent , useCallback , useState } from "react" ;
3
3
import { Field } from "react-final-form" ;
4
4
import { graphql } from "relay-runtime" ;
5
5
6
+ import { DISPOSABLE_EMAIL_DOMAINS_LIST_URL } from "coral-common/common/lib/constants" ;
6
7
import { formatStringList , parseStringList } from "coral-framework/lib/form" ;
7
- import { withFragmentContainer } from "coral-framework/lib/relay" ;
8
+ import { useMutation , withFragmentContainer } from "coral-framework/lib/relay" ;
8
9
import { validateEmailDomainList } from "coral-framework/lib/validation" ;
9
10
import { AddIcon , ButtonSvgIcon } from "coral-ui/components/icons" ;
10
11
import {
11
12
Button ,
13
+ CallOut ,
14
+ FieldSet ,
12
15
Flex ,
13
16
FormField ,
14
17
FormFieldDescription ,
15
18
FormFieldHeader ,
16
19
HelperText ,
17
20
Label ,
18
21
Textarea ,
22
+ TextLink ,
19
23
} from "coral-ui/components/v2" ;
20
24
21
25
import { EmailDomainConfigContainer_settings } from "coral-admin/__generated__/EmailDomainConfigContainer_settings.graphql" ;
22
26
23
27
import ConfigBox from "../../ConfigBox" ;
24
28
import Header from "../../Header" ;
29
+ import OnOffField from "../../OnOffField" ;
25
30
import ValidationMessage from "../../ValidationMessage" ;
26
31
import EmailDomainTableContainer from "./EmailDomainTableContainer" ;
32
+ import RefreshDisposableEmailDomainsMutation from "./RefreshDisposableEmailDomainsMutation" ;
27
33
28
34
import styles from "./EmailDomainConfigContainer.css" ;
29
35
@@ -36,6 +42,9 @@ interface Props {
36
42
graphql `
37
43
fragment EmailDomainConfigContainer_formValues on Settings {
38
44
protectedEmailDomains
45
+ disposableEmailDomains {
46
+ enabled
47
+ }
39
48
}
40
49
` ;
41
50
@@ -45,6 +54,43 @@ const EmailDomainConfigContainer: FunctionComponent<Props> = ({
45
54
} ) => {
46
55
const { protectedEmailDomains } = settings ;
47
56
const [ showDomainList , setShowDomainList ] = useState ( false ) ;
57
+ const [
58
+ refreshDisposableEmailDomainsError ,
59
+ setRefreshDisposableEmailDomainsError ,
60
+ ] = useState < string | null > ( null ) ;
61
+ const [
62
+ refreshingDisposableEmailDomains ,
63
+ setRefreshingDisposableEmailDomains ,
64
+ ] = useState ( false ) ;
65
+
66
+ const refreshEmailDomains = useMutation (
67
+ RefreshDisposableEmailDomainsMutation
68
+ ) ;
69
+
70
+ const refreshDisposableEmailDomains = useCallback ( async ( ) => {
71
+ try {
72
+ setRefreshingDisposableEmailDomains ( true ) ;
73
+ await refreshEmailDomains ( ) ;
74
+ setTimeout ( ( ) => {
75
+ setRefreshingDisposableEmailDomains ( false ) ;
76
+ } , 1500 ) ;
77
+ } catch ( e ) {
78
+ setRefreshDisposableEmailDomainsError (
79
+ `Error refreshing disposable domains: ${ e } `
80
+ ) ;
81
+ setRefreshingDisposableEmailDomains ( false ) ;
82
+ }
83
+ } , [ refreshEmailDomains ] ) ;
84
+
85
+ const EmailDomainsListLink = ( ) => {
86
+ return (
87
+ < Localized id = "configure-moderation-emailDomains-disposableEmailDomains-list-linkText" >
88
+ < TextLink target = "_blank" href = { `${ DISPOSABLE_EMAIL_DOMAINS_LIST_URL } ` } >
89
+ { "disposable-email-domains" }
90
+ </ TextLink >
91
+ </ Localized >
92
+ ) ;
93
+ } ;
48
94
49
95
return (
50
96
< ConfigBox
@@ -92,11 +138,11 @@ const EmailDomainConfigContainer: FunctionComponent<Props> = ({
92
138
< Label component = "legend" > Exceptions</ Label >
93
139
</ Localized >
94
140
</ FormFieldHeader >
95
- < Localized id = "configure-moderation-emailDomains-exceptions-helperText" >
141
+ < Localized id = "configure-moderation-emailDomains-exceptions-ban-premod- helperText" >
96
142
< HelperText >
97
- These domains cannot be banned. Domains should be written without
98
- www, for example "gmail.com". Separate domains with a comma and a
99
- space.
143
+ These domains cannot be banned or pre-moderated . Domains should be
144
+ written without www, for example "gmail.com". Separate domains with
145
+ a comma and a space.
100
146
</ HelperText >
101
147
</ Localized >
102
148
< Field
@@ -124,6 +170,58 @@ const EmailDomainConfigContainer: FunctionComponent<Props> = ({
124
170
) }
125
171
</ Field >
126
172
</ FormField >
173
+ < FormField container = { < FieldSet /> } >
174
+ < FormFieldHeader >
175
+ < Localized id = "configure-moderation-emailDomains-disposableEmailDomains-enabled" >
176
+ < Label component = "legend" > Disposable email domains</ Label >
177
+ </ Localized >
178
+ < Localized id = "configure-moderation-emailDomains-disposableEmailDomains-helper-text" >
179
+ < HelperText >
180
+ If a new user registers using a disposable email address, set
181
+ their status to 'always pre-moderate comments.' Accounts with
182
+ disposable email addresses can have a high spam / troll
183
+ correlation.
184
+ </ HelperText >
185
+ </ Localized >
186
+ </ FormFieldHeader >
187
+ < OnOffField name = "disposableEmailDomains.enabled" disabled = { disabled } />
188
+ < Localized
189
+ id = "configure-moderation-emailDomains-disposableEmailDomains-update-button-helper-text"
190
+ elems = { {
191
+ link : < EmailDomainsListLink /> ,
192
+ } }
193
+ >
194
+ < HelperText >
195
+ The email domains come from the < EmailDomainsListLink /> list, which
196
+ is regularly updated. Use the button below to import their latest
197
+ list.
198
+ </ HelperText >
199
+ </ Localized >
200
+ < Localized
201
+ id = { `${
202
+ refreshingDisposableEmailDomains
203
+ ? "configure-moderation-emailDomains-disposableEmailDomains-updating"
204
+ : "configure-moderation-emailDomains-disposableEmailDomains-update-button"
205
+ } `}
206
+ >
207
+ < Button
208
+ onClick = { refreshDisposableEmailDomains }
209
+ disabled = {
210
+ ! settings . disposableEmailDomains ?. enabled ||
211
+ refreshingDisposableEmailDomains
212
+ }
213
+ >
214
+ { refreshingDisposableEmailDomains
215
+ ? "Updating"
216
+ : "Update disposable domains" }
217
+ </ Button >
218
+ </ Localized >
219
+ { refreshDisposableEmailDomainsError && (
220
+ < CallOut fullWidth color = "error" >
221
+ { refreshDisposableEmailDomainsError }
222
+ </ CallOut >
223
+ ) }
224
+ </ FormField >
127
225
</ ConfigBox >
128
226
) ;
129
227
} ;
@@ -132,6 +230,9 @@ const enhanced = withFragmentContainer<Props>({
132
230
settings : graphql `
133
231
fragment EmailDomainConfigContainer_settings on Settings {
134
232
protectedEmailDomains
233
+ disposableEmailDomains {
234
+ enabled
235
+ }
135
236
...EmailDomainTableContainer_settings
136
237
}
137
238
` ,
0 commit comments