mirror of
https://github.com/wassname/talk.git
synced 2026-08-10 12:41:02 +08:00
[CORL-560] Update Admin > Config area to match new designs (#2514)
* Add solid background to Moderate > Config area headers CORL-560 * Update Config > General section text and font weight CORL-560 * Update ordering of Config > Moderation page items CORL-560 * Update text and font weights in Configure > Moderation page CORL-560 * Update text and font weight on Configure > Organization page CORL-560 * Update text and font weight on Configure > Banned and Suspect Words page CORL-560 * Update text and font weight on Configure > Authentication page CORL-560 * Update text and font weights on Configure > Email page CORL-560 * Update text and font weights on Configure > Advanced page CORL-560 * Repair tests around the styling changes made to the moderation config area CORL-560 * Fix capitalization on the Config > General page CORL-560 * Make email checkbox light themed so its text shows up on new headers CORL-560 * Update Header width to account for padding Prevents it from sticking out over the edge of the page layout CORL-560 * Align "Sort by" text to the drop down in Admin > Config > General > Reactions CORL-560 * Update Admin > Config > General snapshot to adjust for vertical aligned text Vertical flex aligned the "Sort by" text to a combo box in a previous changed CORL-560 * Rename "Perspective Toxic Comment Filter" header to "Toxic Comment Filter" CORL-560 * Use overlay scrolling if available to prevent scroll bar width popping CORL-560 * Remove overflow-y: overlay CORL-560 * Rename Akismet Spam Detection to Spam Detection CORL-560 * Make all non-complex text fields full width in Admin > Config CORL-560 * Remove Authentication Integrations header Area underneath was empty CORL-560 * Re-arrange SSO Key Field layout CORL-560 * Create new typography types for bodyShort and fieldDescription CORL-560 * Update Admin > Config to use bodyShort, fieldDescription typography CORL-560 * Add a slight padding on InputLabel CORL-560 * Add padding on either side of Admin > Config section content CORL-560
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
.root {
|
||||
padding-bottom: calc(0.5 * var(--mini-unit));
|
||||
border-bottom: 1px solid var(--palette-text-primary);
|
||||
border-style: none;
|
||||
border-radius: 1px;
|
||||
background: var(--palette-text-primary);
|
||||
color: var(--palette-text-light);
|
||||
padding: var(--spacing-2);
|
||||
margin-bottom: calc(1.5 * var(--mini-unit));
|
||||
display: block;
|
||||
width: 100%;
|
||||
width: calc(100% - 2 * var(--spacing-2));
|
||||
font-family: var(--font-family-sans-serif);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ type Props = PropTypesOf<typeof Typography>;
|
||||
|
||||
const Header: FunctionComponent<Props> = ({ children, className, ...rest }) => (
|
||||
<Typography
|
||||
variant="heading1"
|
||||
variant="heading3"
|
||||
className={cn(className, styles.root)}
|
||||
{...rest}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.sectionContent {
|
||||
padding-left: var(--spacing-2);
|
||||
padding-right: var(--spacing-2);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { HorizontalGutter } from "coral-ui/components";
|
||||
|
||||
import styles from "./SectionContent.css";
|
||||
|
||||
interface Props {
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const SectionContent: FunctionComponent<Props> = ({ children }) => {
|
||||
return (
|
||||
<HorizontalGutter size="double" className={styles.sectionContent}>
|
||||
{children}
|
||||
</HorizontalGutter>
|
||||
);
|
||||
};
|
||||
|
||||
export default SectionContent;
|
||||
@@ -3,7 +3,7 @@
|
||||
exports[`renders correctly 1`] = `
|
||||
<ForwardRef(forwardRef)
|
||||
className="Header-root"
|
||||
variant="heading1"
|
||||
variant="heading3"
|
||||
>
|
||||
child
|
||||
</ForwardRef(forwardRef)>
|
||||
|
||||
+14
-11
@@ -5,6 +5,7 @@ import { FormField, HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import OnOffField from "../../OnOffField";
|
||||
import SectionContent from "../../SectionContent";
|
||||
|
||||
interface Props {
|
||||
disabled: boolean;
|
||||
@@ -15,19 +16,21 @@ const CommentStreamLiveUpdates: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<HorizontalGutter size="full">
|
||||
<Localized id="configure-advanced-liveUpdates">
|
||||
<Header container={<label htmlFor="configure-advanced-liveUpdates" />}>
|
||||
Comment Stream Live Updates
|
||||
Comment stream live updates
|
||||
</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-advanced-liveUpdates-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
When enabled, there will be real-time loading and updating of comments
|
||||
as new comments and replies are published
|
||||
</Typography>
|
||||
</Localized>
|
||||
<OnOffField name="live.enabled" disabled={disabled} />
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-advanced-liveUpdates-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="bodyShort">
|
||||
When enabled, there will be real-time loading and updating of
|
||||
comments as new comments and replies are published
|
||||
</Typography>
|
||||
</Localized>
|
||||
<OnOffField name="live.enabled" disabled={disabled} />
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
</FormField>
|
||||
);
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
|
||||
interface Props {
|
||||
disabled: boolean;
|
||||
@@ -28,32 +29,38 @@ const CustomCSSConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
Custom CSS
|
||||
</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-advanced-customCSS-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
URL of a CSS stylesheet that will override default Embed Stream
|
||||
styles. Can be internal or external.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field name="customCSSURL" parse={parseEmptyAsNull} format={formatEmpty}>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id={`configure-advanced-${input.name}`}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-advanced-customCSS-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="bodyShort">
|
||||
URL of a CSS stylesheet that will override default Embed Stream
|
||||
styles. Can be internal or external.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field
|
||||
name="customCSSURL"
|
||||
parse={parseEmptyAsNull}
|
||||
format={formatEmpty}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id={`configure-advanced-${input.name}`}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
</FormField>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { GetMessage, withGetMessage } from "coral-framework/lib/i18n";
|
||||
import { HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
|
||||
import styles from "./EmbedCode.css";
|
||||
|
||||
@@ -78,23 +79,25 @@ const EmbedCode: FunctionComponent<Props> = ({ staticURI, getMessage }) => {
|
||||
return (
|
||||
<HorizontalGutter size="oneAndAHalf" container="fieldset">
|
||||
<Localized id="configure-advanced-embedCode-title">
|
||||
<Header container="legend">Embed Code</Header>
|
||||
<Header container="legend">Embed code</Header>
|
||||
</Localized>
|
||||
<Localized id="configure-advanced-embedCode-explanation">
|
||||
<Typography variant="detail">
|
||||
Copy and paste the code below into your CMS to embed Coral comment
|
||||
streams in each of your site’s stories.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<textarea
|
||||
rows={embed.rows}
|
||||
className={styles.textArea}
|
||||
readOnly
|
||||
value={embed.text}
|
||||
/>
|
||||
<HorizontalGutter className={styles.copyArea}>
|
||||
<CopyButton size="regular" text={embed.text} />
|
||||
</HorizontalGutter>
|
||||
<SectionContent>
|
||||
<Localized id="configure-advanced-embedCode-explanation">
|
||||
<Typography variant="bodyShort">
|
||||
Copy and paste the code below into your CMS to embed Coral comment
|
||||
streams in each of your site’s stories.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<textarea
|
||||
rows={embed.rows}
|
||||
className={styles.textArea}
|
||||
readOnly
|
||||
value={embed.text}
|
||||
/>
|
||||
<HorizontalGutter className={styles.copyArea}>
|
||||
<CopyButton size="regular" text={embed.text} />
|
||||
</HorizontalGutter>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
};
|
||||
|
||||
+38
-35
@@ -17,6 +17,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
|
||||
interface Props {
|
||||
disabled: boolean;
|
||||
@@ -29,43 +30,45 @@ const PermittedDomainsConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<Header
|
||||
container={<label htmlFor="configure-advanced-allowedDomains" />}
|
||||
>
|
||||
Permitted Domains
|
||||
Permitted domains
|
||||
</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-advanced-permittedDomains-description"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
The domains you would like to permit for Coral, e.g. your local,
|
||||
staging and production environments including the scheme (ex.
|
||||
http://localhost:3000, https://staging.domain.com,
|
||||
https://domain.com).
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field
|
||||
name="allowedDomains"
|
||||
parse={parseStringList}
|
||||
format={formatStringList}
|
||||
validate={validateStrictURLList}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id={`configure-advanced-${input.name}`}
|
||||
disabled={disabled}
|
||||
color={colorFromMeta(meta)}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
{...input}
|
||||
fullWidth
|
||||
/>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-advanced-permittedDomains-description"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="bodyShort">
|
||||
The domains you would like to permit for Coral, e.g. your local,
|
||||
staging and production environments including the scheme (ex.
|
||||
http://localhost:3000, https://staging.domain.com,
|
||||
https://domain.com).
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field
|
||||
name="allowedDomains"
|
||||
parse={parseStringList}
|
||||
format={formatStringList}
|
||||
validate={validateStrictURLList}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id={`configure-advanced-${input.name}`}
|
||||
disabled={disabled}
|
||||
color={colorFromMeta(meta)}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
{...input}
|
||||
fullWidth
|
||||
/>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
</FormField>
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import OnOffField from "../../OnOffField";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
|
||||
import styles from "./AccountFeaturesConfig.css";
|
||||
|
||||
@@ -25,114 +26,118 @@ const AccountFeaturesConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<Localized id="configure-account-features-title">
|
||||
<Header container="legend">Commenter account mangement features</Header>
|
||||
</Localized>
|
||||
<Localized id="configure-account-features-explanation">
|
||||
<Typography variant="bodyCopy">
|
||||
You can enable and disable certain features for your commenters to use
|
||||
within their Profile. These features also assist towards GDPR
|
||||
compliance.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<HorizontalGutter container={<FieldSet />}>
|
||||
<Localized id="configure-account-features-allow">
|
||||
<Typography variant="heading4">Allow users to:</Typography>
|
||||
<SectionContent>
|
||||
<Localized id="configure-account-features-explanation">
|
||||
<Typography variant="bodyShort">
|
||||
You can enable and disable certain features for your commenters to
|
||||
use within their Profile. These features also assist towards GDPR
|
||||
compliance.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<FormField container="fieldset">
|
||||
<Flex justifyContent="space-between">
|
||||
<HorizontalGutter size="half">
|
||||
<Localized id="configure-account-features-change-usernames">
|
||||
<InputLabel container="legend">
|
||||
Change their usernames
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-account-features-change-usernames-details">
|
||||
<Typography>
|
||||
Usernames can be changed once every 14 days.
|
||||
</Typography>
|
||||
</Localized>
|
||||
</HorizontalGutter>
|
||||
<OnOffField
|
||||
name="accountFeatures.changeUsername"
|
||||
disabled={disabled || false}
|
||||
className={styles.radioButtons}
|
||||
onLabel={
|
||||
<Localized id="configure-account-features-yes">
|
||||
<span>Yes</span>
|
||||
<HorizontalGutter container={<FieldSet />}>
|
||||
<Localized id="configure-account-features-allow">
|
||||
<Typography variant="heading4">Allow users to:</Typography>
|
||||
</Localized>
|
||||
<FormField container="fieldset">
|
||||
<Flex justifyContent="space-between">
|
||||
<HorizontalGutter size="half">
|
||||
<Localized id="configure-account-features-change-usernames">
|
||||
<InputLabel container="legend">
|
||||
Change their usernames
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
}
|
||||
offLabel={
|
||||
<Localized id="configure-account-features-no">
|
||||
<span>No</span>
|
||||
<Localized id="configure-account-features-change-usernames-details">
|
||||
<Typography>
|
||||
Usernames can be changed once every 14 days.
|
||||
</Typography>
|
||||
</Localized>
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</FormField>
|
||||
</HorizontalGutter>
|
||||
<HorizontalGutter size="double">
|
||||
<FormField container="fieldset">
|
||||
<Flex justifyContent="space-between">
|
||||
<HorizontalGutter size="half">
|
||||
<Localized id="configure-account-features-download-comments">
|
||||
<InputLabel container="legend">
|
||||
Download their comments
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-account-features-download-comments-details">
|
||||
<Typography>
|
||||
Commenters can download a csv of their comment history.
|
||||
</Typography>
|
||||
</Localized>
|
||||
</HorizontalGutter>
|
||||
<OnOffField
|
||||
name="accountFeatures.downloadComments"
|
||||
disabled={disabled || false}
|
||||
className={styles.radioButtons}
|
||||
onLabel={
|
||||
<Localized id="configure-account-features-yes">
|
||||
<span>Yes</span>
|
||||
</HorizontalGutter>
|
||||
<OnOffField
|
||||
name="accountFeatures.changeUsername"
|
||||
disabled={disabled || false}
|
||||
className={styles.radioButtons}
|
||||
onLabel={
|
||||
<Localized id="configure-account-features-yes">
|
||||
<span>Yes</span>
|
||||
</Localized>
|
||||
}
|
||||
offLabel={
|
||||
<Localized id="configure-account-features-no">
|
||||
<span>No</span>
|
||||
</Localized>
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</FormField>
|
||||
</HorizontalGutter>
|
||||
<HorizontalGutter size="double">
|
||||
<FormField container="fieldset">
|
||||
<Flex justifyContent="space-between">
|
||||
<HorizontalGutter size="half">
|
||||
<Localized id="configure-account-features-download-comments">
|
||||
<InputLabel container="legend">
|
||||
Download their comments
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
}
|
||||
offLabel={
|
||||
<Localized id="configure-account-features-no">
|
||||
<span>No</span>
|
||||
<Localized id="configure-account-features-download-comments-details">
|
||||
<Typography>
|
||||
Commenters can download a csv of their comment history.
|
||||
</Typography>
|
||||
</Localized>
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</FormField>
|
||||
</HorizontalGutter>
|
||||
<HorizontalGutter size="double">
|
||||
<FormField container="fieldset">
|
||||
<Flex justifyContent="space-between">
|
||||
<HorizontalGutter size="half">
|
||||
<Localized id="configure-account-features-delete-account">
|
||||
<InputLabel container="legend">Delete their account</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-account-features-delete-account-details">
|
||||
<Typography>
|
||||
Removes all of their comment data, username, and email address
|
||||
from the site and the database.
|
||||
</Typography>
|
||||
</Localized>
|
||||
</HorizontalGutter>
|
||||
<OnOffField
|
||||
name="accountFeatures.deleteAccount"
|
||||
disabled={disabled || false}
|
||||
className={styles.radioButtons}
|
||||
onLabel={
|
||||
<Localized id="configure-account-features-yes">
|
||||
<span>Yes</span>
|
||||
</HorizontalGutter>
|
||||
<OnOffField
|
||||
name="accountFeatures.downloadComments"
|
||||
disabled={disabled || false}
|
||||
className={styles.radioButtons}
|
||||
onLabel={
|
||||
<Localized id="configure-account-features-yes">
|
||||
<span>Yes</span>
|
||||
</Localized>
|
||||
}
|
||||
offLabel={
|
||||
<Localized id="configure-account-features-no">
|
||||
<span>No</span>
|
||||
</Localized>
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</FormField>
|
||||
</HorizontalGutter>
|
||||
<HorizontalGutter size="double">
|
||||
<FormField container="fieldset">
|
||||
<Flex justifyContent="space-between">
|
||||
<HorizontalGutter size="half">
|
||||
<Localized id="configure-account-features-delete-account">
|
||||
<InputLabel container="legend">
|
||||
Delete their account
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
}
|
||||
offLabel={
|
||||
<Localized id="configure-account-features-no">
|
||||
<span>No</span>
|
||||
<Localized id="configure-account-features-delete-account-fieldDescriptions">
|
||||
<Typography>
|
||||
Removes all of their comment data, username, and email
|
||||
address from the site and the database.
|
||||
</Typography>
|
||||
</Localized>
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</FormField>
|
||||
</HorizontalGutter>
|
||||
</HorizontalGutter>
|
||||
<OnOffField
|
||||
name="accountFeatures.deleteAccount"
|
||||
disabled={disabled || false}
|
||||
className={styles.radioButtons}
|
||||
onLabel={
|
||||
<Localized id="configure-account-features-yes">
|
||||
<span>Yes</span>
|
||||
</Localized>
|
||||
}
|
||||
offLabel={
|
||||
<Localized id="configure-account-features-no">
|
||||
<span>No</span>
|
||||
</Localized>
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</FormField>
|
||||
</HorizontalGutter>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { PropTypesOf } from "coral-framework/types";
|
||||
import { HorizontalGutter } from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import { OnInitValuesFct } from "./AuthConfigContainer";
|
||||
import FacebookConfigContainer from "./FacebookConfigContainer";
|
||||
import GoogleConfigContainer from "./GoogleConfigContainer";
|
||||
@@ -32,9 +30,6 @@ const AuthIntegrationsConfig: FunctionComponent<Props> = ({
|
||||
onInitValues,
|
||||
}) => (
|
||||
<HorizontalGutter size="double">
|
||||
<Localized id="configure-auth-authIntegrations">
|
||||
<Header>Auth Integrations</Header>
|
||||
</Localized>
|
||||
<LocalAuthConfigContainer
|
||||
disabled={disabled}
|
||||
auth={auth}
|
||||
|
||||
@@ -35,6 +35,7 @@ const ClientSecretField: FunctionComponent<Props> = ({
|
||||
color={colorFromMeta(meta)}
|
||||
{...input}
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
|
||||
@@ -20,7 +20,7 @@ const ClientSecretField: FunctionComponent<Props> = ({
|
||||
}) => (
|
||||
<FormField>
|
||||
<Localized id="configure-auth-clientSecret">
|
||||
<InputLabel>Client Secret</InputLabel>
|
||||
<InputLabel>Client secret</InputLabel>
|
||||
</Localized>
|
||||
<Field
|
||||
name={name}
|
||||
@@ -35,6 +35,7 @@ const ClientSecretField: FunctionComponent<Props> = ({
|
||||
// TODO: (wyattjoh) figure out how to add translations to these props
|
||||
hidePasswordTitle="Show Client Secret"
|
||||
showPasswordTitle="Hide Client Secret"
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
|
||||
@@ -15,7 +15,7 @@ const LocalAuthConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<ConfigBoxWithToggleField
|
||||
title={
|
||||
<Localized id="configure-auth-local-loginWith">
|
||||
<span>Login with LocalAuth</span>
|
||||
<span>Login with email authentication</span>
|
||||
</Localized>
|
||||
}
|
||||
name="auth.integrations.local.enabled"
|
||||
@@ -26,7 +26,7 @@ const LocalAuthConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<TargetFilterField
|
||||
label={
|
||||
<Localized id="configure-auth-local-useLoginOn">
|
||||
<span>Use LocalAuth login on</span>
|
||||
<span>Use email authentication login on</span>
|
||||
</Localized>
|
||||
}
|
||||
name="auth.integrations.local.targetFilter"
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
Flex,
|
||||
FormField,
|
||||
HorizontalGutter,
|
||||
InputDescription,
|
||||
InputLabel,
|
||||
TextField,
|
||||
TextLink,
|
||||
@@ -26,7 +27,6 @@ import { FormProps } from "./AuthConfigContainer";
|
||||
import ClientIDField from "./ClientIDField";
|
||||
import ClientSecretField from "./ClientSecretField";
|
||||
import ConfigBoxWithToggleField from "./ConfigBoxWithToggleField";
|
||||
import ConfigDescription from "./ConfigDescription";
|
||||
import RedirectField from "./RedirectField";
|
||||
import RegistrationField from "./RegistrationField";
|
||||
import TargetFilterField from "./TargetFilterField";
|
||||
@@ -74,14 +74,14 @@ const OIDCConfig: FunctionComponent<Props> = ({
|
||||
<HorizontalRule />
|
||||
<FormField>
|
||||
<Localized id="configure-auth-oidc-providerName">
|
||||
<InputLabel>Provider Name</InputLabel>
|
||||
<InputLabel>Provider name</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-auth-oidc-providerNameDescription">
|
||||
<ConfigDescription>
|
||||
<InputDescription>
|
||||
The provider of the OIDC integration. This will be used when the
|
||||
name of the provider needs to be displayed, e.g. “Log in with
|
||||
{" <Facebook>"}”
|
||||
</ConfigDescription>
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field
|
||||
name={`auth.integrations.oidc.name`}
|
||||
@@ -97,6 +97,7 @@ const OIDCConfig: FunctionComponent<Props> = ({
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
color={colorFromMeta(meta)}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
@@ -119,11 +120,11 @@ const OIDCConfig: FunctionComponent<Props> = ({
|
||||
<InputLabel>Issuer</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-auth-oidc-issuerDescription">
|
||||
<ConfigDescription>
|
||||
<InputDescription>
|
||||
After entering your Issuer information, click the Discover
|
||||
button to have Coral complete the remaining fields. You may also
|
||||
enter the information manually
|
||||
</ConfigDescription>
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field
|
||||
name={`auth.integrations.oidc.issuer`}
|
||||
@@ -140,6 +141,7 @@ const OIDCConfig: FunctionComponent<Props> = ({
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
color={colorFromMeta(meta)}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<Button
|
||||
@@ -176,6 +178,7 @@ const OIDCConfig: FunctionComponent<Props> = ({
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
color={colorFromMeta(meta)}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
@@ -201,6 +204,7 @@ const OIDCConfig: FunctionComponent<Props> = ({
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
color={colorFromMeta(meta)}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
@@ -226,6 +230,7 @@ const OIDCConfig: FunctionComponent<Props> = ({
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
color={colorFromMeta(meta)}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
|
||||
@@ -16,7 +16,7 @@ const RedirectField: FunctionComponent<Props> = ({ url, description }) => (
|
||||
</Localized>
|
||||
{description}
|
||||
<Flex direction="row" itemGutter="half" alignItems="center">
|
||||
<TextField name="redirectURI" value={url} readOnly />
|
||||
<TextField name="redirectURI" value={url} fullWidth readOnly />
|
||||
<CopyButton text={url} />
|
||||
</Flex>
|
||||
</FormField>
|
||||
|
||||
@@ -2,9 +2,12 @@ import { Localized } from "fluent-react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { Field } from "react-final-form";
|
||||
|
||||
import { CheckBox, FormField, InputLabel } from "coral-ui/components";
|
||||
|
||||
import ConfigDescription from "./ConfigDescription";
|
||||
import {
|
||||
CheckBox,
|
||||
FormField,
|
||||
InputDescription,
|
||||
InputLabel,
|
||||
} from "coral-ui/components";
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
@@ -17,9 +20,9 @@ const RegistrationField: FunctionComponent<Props> = ({ name, disabled }) => (
|
||||
<InputLabel>Registration</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-auth-registrationDescription">
|
||||
<ConfigDescription>
|
||||
<InputDescription>
|
||||
Allow users to create a new account with this provider.
|
||||
</ConfigDescription>
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<FormField>
|
||||
<Field name={name} type="checkbox">
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
.root {
|
||||
padding-bottom: var(--spacing-4);
|
||||
}
|
||||
|
||||
.keyGenerated {
|
||||
composes: button from "coral-ui/shared/typography.css";
|
||||
color: var(--palette-text-secondary);
|
||||
width: calc(29 * var(--mini-unit));
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -9,8 +12,18 @@
|
||||
color: var(--palette-text-secondary);
|
||||
flex-shrink: 0;
|
||||
padding-top: 3px;
|
||||
padding-right: var(--spacing-1);
|
||||
}
|
||||
|
||||
.warn {
|
||||
color: var(--palette-text-secondary);
|
||||
}
|
||||
|
||||
.warningSection {
|
||||
padding-top: var(--spacing-1);
|
||||
padding-bottom: var(--spacing-1);
|
||||
}
|
||||
|
||||
.regenerateButton {
|
||||
float: right;
|
||||
}
|
||||
|
||||
@@ -26,46 +26,49 @@ const SSOKeyField: FunctionComponent<Props> = ({
|
||||
disabled,
|
||||
onRegenerate,
|
||||
}) => (
|
||||
<FormField data-testid="configure-auth-sso-key">
|
||||
<FormField className={styles.root} data-testid="configure-auth-sso-key">
|
||||
<Localized id="configure-auth-sso-key">
|
||||
<InputLabel>Key</InputLabel>
|
||||
</Localized>
|
||||
<Flex direction="row" itemGutter="half" alignItems="center">
|
||||
<PasswordField
|
||||
name="key"
|
||||
value={generatedKey}
|
||||
readOnly
|
||||
// TODO: (wyattjoh) figure out how to add translations to these props
|
||||
hidePasswordTitle="Show SSO Key"
|
||||
showPasswordTitle="Hide SSO Key"
|
||||
/>
|
||||
<Localized id="configure-auth-sso-regenerate">
|
||||
<Button
|
||||
id="configure-auth-sso-regenerate"
|
||||
variant="filled"
|
||||
color="primary"
|
||||
size="small"
|
||||
disabled={disabled}
|
||||
onClick={onRegenerate}
|
||||
>
|
||||
Regenerate
|
||||
</Button>
|
||||
</Localized>
|
||||
</Flex>
|
||||
<Flex direction="row" itemGutter="half">
|
||||
<Localized id="configure-auth-sso-regenerateAt" $date={keyGeneratedAt}>
|
||||
<Typography className={styles.keyGenerated}>
|
||||
KEY GENERATED AT: {keyGeneratedAt}
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Icon className={styles.warnIcon}>warning</Icon>
|
||||
<Localized id="configure-auth-sso-regenerateWarning">
|
||||
<Typography className={styles.warn} variant="bodyCopy">
|
||||
Regenerating a key will invalidate any existing user sessions, and all
|
||||
signed-in users will be signed out
|
||||
</Typography>
|
||||
</Localized>
|
||||
</Flex>
|
||||
<PasswordField
|
||||
name="key"
|
||||
value={generatedKey}
|
||||
readOnly
|
||||
// TODO: (wyattjoh) figure out how to add translations to these props
|
||||
hidePasswordTitle="Show SSO Key"
|
||||
showPasswordTitle="Hide SSO Key"
|
||||
fullWidth
|
||||
/>
|
||||
<Localized id="configure-auth-sso-regenerateAt" $date={keyGeneratedAt}>
|
||||
<Typography className={styles.keyGenerated}>
|
||||
KEY GENERATED AT: {keyGeneratedAt}
|
||||
</Typography>
|
||||
</Localized>
|
||||
<div className={styles.warningSection}>
|
||||
<Flex direction="row" itemGutter="half">
|
||||
<Icon className={styles.warnIcon}>warning</Icon>
|
||||
<Localized id="configure-auth-sso-regenerateWarning">
|
||||
<Typography className={styles.warn} variant="bodyShort">
|
||||
Regenerating a key will invalidate any existing user sessions, and
|
||||
all signed-in users will be signed out
|
||||
</Typography>
|
||||
</Localized>
|
||||
</Flex>
|
||||
</div>
|
||||
|
||||
<Localized id="configure-auth-sso-regenerate">
|
||||
<Button
|
||||
id="configure-auth-sso-regenerate"
|
||||
variant="filled"
|
||||
color="primary"
|
||||
size="small"
|
||||
disabled={disabled}
|
||||
onClick={onRegenerate}
|
||||
className={styles.regenerateButton}
|
||||
>
|
||||
Regenerate
|
||||
</Button>
|
||||
</Localized>
|
||||
</FormField>
|
||||
);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import FromContainer from "./FromContainer";
|
||||
import SMTPContainer from "./SMTPContainer";
|
||||
|
||||
@@ -92,7 +93,12 @@ class EmailConfigContainer extends React.Component<Props> {
|
||||
<div>
|
||||
<FormField>
|
||||
<Localized id="configure-email-configBoxEnabled">
|
||||
<CheckBox id={input.name} {...input} disabled={submitting}>
|
||||
<CheckBox
|
||||
id={input.name}
|
||||
{...input}
|
||||
light
|
||||
disabled={submitting}
|
||||
>
|
||||
Enabled
|
||||
</CheckBox>
|
||||
</Localized>
|
||||
@@ -103,7 +109,7 @@ class EmailConfigContainer extends React.Component<Props> {
|
||||
</Field>
|
||||
<Field name="email.enabled" subscription={{ value: true }}>
|
||||
{({ input: { value } }) => (
|
||||
<>
|
||||
<SectionContent>
|
||||
<FromContainer
|
||||
email={email}
|
||||
disabled={submitting || !value}
|
||||
@@ -114,7 +120,7 @@ class EmailConfigContainer extends React.Component<Props> {
|
||||
disabled={submitting || !value}
|
||||
onInitValues={this.handleOnInitValues}
|
||||
/>
|
||||
</>
|
||||
</SectionContent>
|
||||
)}
|
||||
</Field>
|
||||
</HorizontalGutter>
|
||||
|
||||
@@ -97,7 +97,7 @@ const SMTP: FunctionComponent<Props> = ({ disabled }) => (
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Localized id="configure-email-smtpAuthenticationLabel">
|
||||
<InputLabel>SMTP Authentication</InputLabel>
|
||||
<InputLabel>SMTP authentication</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField
|
||||
name="email.smtp.authentication"
|
||||
|
||||
+26
-22
@@ -6,6 +6,7 @@ import { MarkdownEditor } from "coral-framework/components/loadables";
|
||||
import { HorizontalGutter, Spinner, Typography } from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
interface Props {
|
||||
@@ -20,30 +21,33 @@ const ClosedStreamMessageConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<label htmlFor="configure-general-closedStreamMessage-content" />
|
||||
}
|
||||
>
|
||||
Closed Stream Message
|
||||
Closed comment stream message
|
||||
</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-general-closedStreamMessage-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Write a message to appear after a story is closed for commenting.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field name="closeCommenting.message">
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<MarkdownEditor
|
||||
id="configure-general-closedStreamMessage-content"
|
||||
{...input}
|
||||
/>
|
||||
</Suspense>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-general-closedStreamMessage-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="bodyShort">
|
||||
Write a message to appear after a story is closed for commenting.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field name="closeCommenting.message">
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<MarkdownEditor
|
||||
id="configure-general-closedStreamMessage-content"
|
||||
{...input}
|
||||
/>
|
||||
</Suspense>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
+48
-43
@@ -18,6 +18,7 @@ import {
|
||||
|
||||
import Header from "../../Header";
|
||||
import OnOffField from "../../OnOffField";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
interface Props {
|
||||
@@ -29,51 +30,55 @@ const ClosingCommentStreamsConfig: FunctionComponent<Props> = ({
|
||||
}) => (
|
||||
<HorizontalGutter size="oneAndAHalf" container={<FieldSet />}>
|
||||
<Localized id="configure-general-closingCommentStreams-title">
|
||||
<Header container="legend">Closing Comment Streams</Header>
|
||||
<Header container="legend">Closing comment streams</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-general-closingCommentStreams-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Set comment streams to close after a defined period of time after a
|
||||
story’s publication
|
||||
</Typography>
|
||||
</Localized>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-general-closingCommentStreams-closeCommentsAutomatically">
|
||||
<InputLabel container="legend">Close Comments Automatically</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField name="closeCommenting.auto" disabled={disabled} />
|
||||
</FormField>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-general-closingCommentStreams-closeCommentsAfter">
|
||||
<InputLabel container="legend">Close Comments After</InputLabel>
|
||||
</Localized>
|
||||
|
||||
<Field
|
||||
name="closeCommenting.timeout"
|
||||
validate={composeValidators(
|
||||
required,
|
||||
validateWholeNumberGreaterThan(0)
|
||||
)}
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-general-closingCommentStreams-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<DurationField
|
||||
units={[
|
||||
DURATION_UNIT.HOURS,
|
||||
DURATION_UNIT.DAYS,
|
||||
DURATION_UNIT.WEEKS,
|
||||
]}
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<Typography variant="bodyShort">
|
||||
Set comment streams to close after a defined period of time after a
|
||||
story’s publication
|
||||
</Typography>
|
||||
</Localized>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-general-closingCommentStreams-closeCommentsAutomatically">
|
||||
<InputLabel container="legend">
|
||||
Close comments automatically
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField name="closeCommenting.auto" disabled={disabled} />
|
||||
</FormField>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-general-closingCommentStreams-closeCommentsAfter">
|
||||
<InputLabel container="legend">Close comments after</InputLabel>
|
||||
</Localized>
|
||||
|
||||
<Field
|
||||
name="closeCommenting.timeout"
|
||||
validate={composeValidators(
|
||||
required,
|
||||
validateWholeNumberGreaterThan(0)
|
||||
)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<DurationField
|
||||
units={[
|
||||
DURATION_UNIT.HOURS,
|
||||
DURATION_UNIT.DAYS,
|
||||
DURATION_UNIT.WEEKS,
|
||||
]}
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
interface Props {
|
||||
@@ -26,46 +27,48 @@ interface Props {
|
||||
const CommentEditingConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<HorizontalGutter size="oneAndAHalf">
|
||||
<Localized id="configure-general-commentEditing-title">
|
||||
<Header>Comment Editing</Header>
|
||||
<Header>Comment editing</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-general-commentEditing-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Set a limit on how long commenters have to edit their comments sitewide.
|
||||
Edited comments are marked as (Edited) on the comment stream and the
|
||||
moderation panel.
|
||||
</Typography>
|
||||
</Localized>
|
||||
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-general-commentEditing-commentEditTimeFrame">
|
||||
<InputLabel container="legend">Comment Edit Timeframe</InputLabel>
|
||||
</Localized>
|
||||
<Field
|
||||
name="editCommentWindowLength"
|
||||
validate={composeValidators(
|
||||
required,
|
||||
validateWholeNumberGreaterThanOrEqual(0)
|
||||
)}
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-general-commentEditing-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<DurationField
|
||||
units={[
|
||||
DURATION_UNIT.SECONDS,
|
||||
DURATION_UNIT.MINUTES,
|
||||
DURATION_UNIT.HOURS,
|
||||
]}
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<Typography variant="bodyShort">
|
||||
Set a limit on how long commenters have to edit their comments
|
||||
sitewide. Edited comments are marked as (Edited) on the comment stream
|
||||
and the moderation panel.
|
||||
</Typography>
|
||||
</Localized>
|
||||
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-general-commentEditing-commentEditTimeFrame">
|
||||
<InputLabel container="legend">Comment edit timeframe</InputLabel>
|
||||
</Localized>
|
||||
<Field
|
||||
name="editCommentWindowLength"
|
||||
validate={composeValidators(
|
||||
required,
|
||||
validateWholeNumberGreaterThanOrEqual(0)
|
||||
)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<DurationField
|
||||
units={[
|
||||
DURATION_UNIT.SECONDS,
|
||||
DURATION_UNIT.MINUTES,
|
||||
DURATION_UNIT.HOURS,
|
||||
]}
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@ import Header from "../../Header";
|
||||
import OnOffField from "../../OnOffField";
|
||||
|
||||
import { formatEmpty, parseEmptyAsNull } from "coral-framework/lib/form";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
import styles from "./CommentLengthConfig.css";
|
||||
|
||||
const validateMaxLongerThanMin = createValidator(
|
||||
@@ -41,113 +43,116 @@ interface Props {
|
||||
const CommentLengthConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<HorizontalGutter size="oneAndAHalf" container={<FieldSet />}>
|
||||
<Localized id="configure-general-commentLength-title">
|
||||
<Header container="legend">Comment Length</Header>
|
||||
<Header container="legend">Comment length</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-general-commentLength-setLimit"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Set a limit on the length of comments sitewide
|
||||
</Typography>
|
||||
</Localized>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-general-commentLength-limitCommentLength">
|
||||
<InputLabel>Limit Comment Length</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField name="charCount.enabled" disabled={disabled} />
|
||||
</FormField>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-general-commentLength-minCommentLength">
|
||||
<InputLabel htmlFor="configure-general-commentLength-min">
|
||||
Minimum Comment Length
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Field
|
||||
name="charCount.min"
|
||||
validate={validateWholeNumberGreaterThan(0)}
|
||||
parse={parseEmptyAsNull}
|
||||
format={formatEmpty}
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-general-commentLength-setLimit"
|
||||
strong={<strong />}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Localized
|
||||
id="configure-general-commentLength-textField"
|
||||
attrs={{ placeholder: true }}
|
||||
>
|
||||
<TextField
|
||||
id="configure-general-commentLength-min"
|
||||
classes={{
|
||||
input: styles.commentLengthTextInput,
|
||||
}}
|
||||
{...input}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
adornment={
|
||||
<Localized id="configure-general-commentLength-characters">
|
||||
<Typography variant="bodyCopy">Characters</Typography>
|
||||
</Localized>
|
||||
}
|
||||
placeholder={"No limit"}
|
||||
textAlignCenter
|
||||
/>
|
||||
</Localized>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Localized id="configure-general-commentLength-maxCommentLength">
|
||||
<InputLabel htmlFor="configure-general-commentLength-max">
|
||||
Maximum Comment Length
|
||||
</InputLabel>
|
||||
<Typography variant="bodyShort">
|
||||
Set minimum and maximum comment length requirements. Blank spaces at
|
||||
the beginning and the end of a comment will be trimmed.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field
|
||||
name="charCount.max"
|
||||
validate={composeValidators(
|
||||
validateWholeNumberGreaterThan(0),
|
||||
validateMaxLongerThanMin
|
||||
)}
|
||||
parse={parseEmptyAsNull}
|
||||
format={formatEmpty}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Localized
|
||||
id="configure-general-commentLength-textField"
|
||||
attrs={{ placeholder: true }}
|
||||
>
|
||||
<TextField
|
||||
id="configure-general-commentLength-max"
|
||||
classes={{
|
||||
input: styles.commentLengthTextInput,
|
||||
}}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
adornment={
|
||||
<Localized id="configure-general-commentLength-characters">
|
||||
<Typography variant="bodyCopy">Characters</Typography>
|
||||
</Localized>
|
||||
}
|
||||
placeholder={"No limit"}
|
||||
textAlignCenter
|
||||
{...input}
|
||||
/>
|
||||
</Localized>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-general-commentLength-limitCommentLength">
|
||||
<InputLabel>Limit comment length</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField name="charCount.enabled" disabled={disabled} />
|
||||
</FormField>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-general-commentLength-minCommentLength">
|
||||
<InputLabel htmlFor="configure-general-commentLength-min">
|
||||
Minimum comment length
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Field
|
||||
name="charCount.min"
|
||||
validate={validateWholeNumberGreaterThan(0)}
|
||||
parse={parseEmptyAsNull}
|
||||
format={formatEmpty}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Localized
|
||||
id="configure-general-commentLength-textField"
|
||||
attrs={{ placeholder: true }}
|
||||
>
|
||||
<TextField
|
||||
id="configure-general-commentLength-min"
|
||||
classes={{
|
||||
input: styles.commentLengthTextInput,
|
||||
}}
|
||||
{...input}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
adornment={
|
||||
<Localized id="configure-general-commentLength-characters">
|
||||
<Typography variant="bodyCopy">Characters</Typography>
|
||||
</Localized>
|
||||
}
|
||||
placeholder={"No limit"}
|
||||
textAlignCenter
|
||||
/>
|
||||
</Localized>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Localized id="configure-general-commentLength-maxCommentLength">
|
||||
<InputLabel htmlFor="configure-general-commentLength-max">
|
||||
Maximum comment length
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Field
|
||||
name="charCount.max"
|
||||
validate={composeValidators(
|
||||
validateWholeNumberGreaterThan(0),
|
||||
validateMaxLongerThanMin
|
||||
)}
|
||||
parse={parseEmptyAsNull}
|
||||
format={formatEmpty}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Localized
|
||||
id="configure-general-commentLength-textField"
|
||||
attrs={{ placeholder: true }}
|
||||
>
|
||||
<TextField
|
||||
id="configure-general-commentLength-max"
|
||||
classes={{
|
||||
input: styles.commentLengthTextInput,
|
||||
}}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
adornment={
|
||||
<Localized id="configure-general-commentLength-characters">
|
||||
<Typography variant="bodyCopy">Characters</Typography>
|
||||
</Localized>
|
||||
}
|
||||
placeholder={"No limit"}
|
||||
textAlignCenter
|
||||
{...input}
|
||||
/>
|
||||
</Localized>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
@@ -8,13 +8,14 @@ import {
|
||||
FieldSet,
|
||||
FormField,
|
||||
HorizontalGutter,
|
||||
InputDescription,
|
||||
InputLabel,
|
||||
Spinner,
|
||||
Typography,
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import OnOffField from "../../OnOffField";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
interface Props {
|
||||
@@ -24,51 +25,52 @@ interface Props {
|
||||
const GuidelinesConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<HorizontalGutter size="oneAndAHalf" container={<FieldSet />}>
|
||||
<Localized id="configure-general-guidelines-title">
|
||||
<Header container="legend">Community Guidelines Summary</Header>
|
||||
<Header container="legend">Community guidelines summary</Header>
|
||||
</Localized>
|
||||
<SectionContent>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-general-guidelines-showCommunityGuidelines">
|
||||
<InputLabel container="legend">
|
||||
Show community guidelines summary
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField name="communityGuidelines.enabled" disabled={disabled} />
|
||||
</FormField>
|
||||
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-general-guidelines-showCommunityGuidelines">
|
||||
<InputLabel container="legend">
|
||||
Show Community Guidelines Summary
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField name="communityGuidelines.enabled" disabled={disabled} />
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Localized id="configure-general-guidelines-title">
|
||||
<InputLabel htmlFor="configure-general-guidelines-content">
|
||||
Community guidelines summary
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-general-guidelines-explanation"
|
||||
strong={<strong />}
|
||||
externalLink={<ExternalLink href="#" />}
|
||||
>
|
||||
<InputDescription>
|
||||
Write a summary of your community guidelines that will appear at the
|
||||
top of each comment stream sitewide. Your summary can be formatted
|
||||
using Markdown Syntax. More information on how to use Markdown can
|
||||
be found here.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
</FormField>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-general-guidelines-title">
|
||||
<InputLabel htmlFor="configure-general-guidelines-content">
|
||||
Community Guidelines Summary
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-general-guidelines-explanation"
|
||||
strong={<strong />}
|
||||
externalLink={<ExternalLink href="#" />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Write a summary of your community guidelines that will appear at the
|
||||
top of each comment stream sitewide. Your summary can be formatted
|
||||
using Markdown Syntax. More information on how to use Markdown can be
|
||||
found here.
|
||||
</Typography>
|
||||
</Localized>
|
||||
</FormField>
|
||||
|
||||
<Field name="communityGuidelines.content">
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<MarkdownEditor
|
||||
id="configure-general-guidelines-content"
|
||||
{...input}
|
||||
/>
|
||||
</Suspense>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<Field name="communityGuidelines.content">
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<MarkdownEditor
|
||||
id="configure-general-guidelines-content"
|
||||
{...input}
|
||||
/>
|
||||
</Suspense>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import { required } from "coral-framework/lib/validation";
|
||||
import { FormField, HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
interface Props {
|
||||
@@ -28,26 +29,28 @@ const LocaleConfigContainer: React.FunctionComponent<Props> = props => {
|
||||
Language
|
||||
</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-general-locale-chooseLanguage"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Choose the language for your Coral community.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field name="locale" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<LocaleField
|
||||
id={`configure-locale-${input.name}`}
|
||||
disabled={props.disabled}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-general-locale-chooseLanguage"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Choose the language for your Coral community.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field name="locale" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<LocaleField
|
||||
id={`configure-locale-${input.name}`}
|
||||
disabled={props.disabled}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
</FormField>
|
||||
);
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
import styles from "./ReactionConfig.css";
|
||||
@@ -32,136 +33,141 @@ const ReactionsConfig: FunctionComponent<Props> = ({ disabled, settings }) => (
|
||||
<Localized id="configure-general-reactions-title">
|
||||
<Header container="legend">Reactions</Header>
|
||||
</Localized>
|
||||
<Localized id="configure-general-reactions-explanation" strong={<strong />}>
|
||||
<Typography variant="detail">
|
||||
Allow your community to engage with one another and express themselves
|
||||
with one-click reactions. By default, Coral allows commenters to
|
||||
"Respect" each other's comments, but you may customize reaction text
|
||||
based on the needs of your community.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<HorizontalGutter size="double">
|
||||
<FormField>
|
||||
<Field name="reaction.label" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<Flex itemGutter="double">
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-label">
|
||||
<InputLabel>Reaction label</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-general-reactions-input">
|
||||
<TextField
|
||||
className={styles.textInput}
|
||||
id={input.name}
|
||||
type="text"
|
||||
fullWidth
|
||||
placeholder="E.g. Respect"
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
</Localized>
|
||||
<ValidationMessage fullWidth meta={meta} />
|
||||
</HorizontalGutter>
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-preview">
|
||||
<Typography variant="heading3">Preview</Typography>
|
||||
</Localized>
|
||||
<ReactionButton
|
||||
readOnly
|
||||
className={styles.reactionButton}
|
||||
reacted={false}
|
||||
label={input.value}
|
||||
labelActive={settings.reaction.labelActive}
|
||||
icon={settings.reaction.icon}
|
||||
iconActive={settings.reaction.iconActive}
|
||||
totalReactions={0}
|
||||
onClick={() => null}
|
||||
/>
|
||||
</HorizontalGutter>
|
||||
</Flex>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Field name="reaction.labelActive" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<Flex itemGutter="double">
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-active-label">
|
||||
<InputLabel>Active reaction label</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-general-reactions-active-input">
|
||||
<TextField
|
||||
className={styles.textInput}
|
||||
id={input.name}
|
||||
type="text"
|
||||
placeholder="E.g. Respected"
|
||||
fullWidth
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
</Localized>
|
||||
<ValidationMessage fullWidth meta={meta} />
|
||||
</HorizontalGutter>
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-preview">
|
||||
<Typography variant="heading3">Preview</Typography>
|
||||
</Localized>
|
||||
<ReactionButton
|
||||
className={styles.reactionButton}
|
||||
readOnly
|
||||
reacted
|
||||
label={settings.reaction.label}
|
||||
labelActive={input.value}
|
||||
icon={settings.reaction.icon}
|
||||
iconActive={settings.reaction.iconActive}
|
||||
totalReactions={0}
|
||||
onClick={() => null}
|
||||
/>
|
||||
</HorizontalGutter>
|
||||
</Flex>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Field name="reaction.sortLabel" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<Flex itemGutter="double">
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-sort-label">
|
||||
<InputLabel>Sort label</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-general-reactions-sort-input">
|
||||
<TextField
|
||||
id={input.name}
|
||||
className={styles.textInput}
|
||||
type="text"
|
||||
placeholder="E.g. Most respected"
|
||||
fullWidth
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
</Localized>
|
||||
<ValidationMessage fullWidth meta={meta} />
|
||||
</HorizontalGutter>
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-preview">
|
||||
<Typography variant="heading3">Preview</Typography>
|
||||
</Localized>
|
||||
<Flex justifyContent="center" itemGutter>
|
||||
<Localized id="configure-general-reaction-sortMenu-sortBy">
|
||||
<Typography variant="bodyCopyBold">Sort By</Typography>
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-general-reactions-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="bodyShort">
|
||||
Allow your community to engage with one another and express themselves
|
||||
with one-click reactions. By default, Coral allows commenters to
|
||||
"Respect" each other's comments, but you may customize reaction text
|
||||
based on the needs of your community.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<HorizontalGutter size="double">
|
||||
<FormField>
|
||||
<Field name="reaction.label" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<Flex itemGutter="double">
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-label">
|
||||
<InputLabel>Reaction label</InputLabel>
|
||||
</Localized>
|
||||
<SelectField>
|
||||
<Option value={input.value}>{input.value}</Option>{" "}
|
||||
</SelectField>
|
||||
</Flex>
|
||||
</HorizontalGutter>
|
||||
</Flex>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
</HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-input">
|
||||
<TextField
|
||||
className={styles.textInput}
|
||||
id={input.name}
|
||||
type="text"
|
||||
fullWidth
|
||||
placeholder="E.g. Respect"
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
</Localized>
|
||||
<ValidationMessage fullWidth meta={meta} />
|
||||
</HorizontalGutter>
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-preview">
|
||||
<Typography variant="heading3">Preview</Typography>
|
||||
</Localized>
|
||||
<ReactionButton
|
||||
readOnly
|
||||
className={styles.reactionButton}
|
||||
reacted={false}
|
||||
label={input.value}
|
||||
labelActive={settings.reaction.labelActive}
|
||||
icon={settings.reaction.icon}
|
||||
iconActive={settings.reaction.iconActive}
|
||||
totalReactions={0}
|
||||
onClick={() => null}
|
||||
/>
|
||||
</HorizontalGutter>
|
||||
</Flex>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Field name="reaction.labelActive" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<Flex itemGutter="double">
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-active-label">
|
||||
<InputLabel>Active reaction label</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-general-reactions-active-input">
|
||||
<TextField
|
||||
className={styles.textInput}
|
||||
id={input.name}
|
||||
type="text"
|
||||
placeholder="E.g. Respected"
|
||||
fullWidth
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
</Localized>
|
||||
<ValidationMessage fullWidth meta={meta} />
|
||||
</HorizontalGutter>
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-preview">
|
||||
<Typography variant="heading3">Preview</Typography>
|
||||
</Localized>
|
||||
<ReactionButton
|
||||
className={styles.reactionButton}
|
||||
readOnly
|
||||
reacted
|
||||
label={settings.reaction.label}
|
||||
labelActive={input.value}
|
||||
icon={settings.reaction.icon}
|
||||
iconActive={settings.reaction.iconActive}
|
||||
totalReactions={0}
|
||||
onClick={() => null}
|
||||
/>
|
||||
</HorizontalGutter>
|
||||
</Flex>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Field name="reaction.sortLabel" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<Flex itemGutter="double">
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-sort-label">
|
||||
<InputLabel>Sort label</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-general-reactions-sort-input">
|
||||
<TextField
|
||||
id={input.name}
|
||||
className={styles.textInput}
|
||||
type="text"
|
||||
placeholder="E.g. Most respected"
|
||||
fullWidth
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
</Localized>
|
||||
<ValidationMessage fullWidth meta={meta} />
|
||||
</HorizontalGutter>
|
||||
<HorizontalGutter>
|
||||
<Localized id="configure-general-reactions-preview">
|
||||
<Typography variant="heading3">Preview</Typography>
|
||||
</Localized>
|
||||
<Flex justifyContent="center" alignItems="center" itemGutter>
|
||||
<Localized id="configure-general-reaction-sortMenu-sortBy">
|
||||
<Typography variant="bodyCopyBold">Sort By</Typography>
|
||||
</Localized>
|
||||
<SelectField>
|
||||
<Option value={input.value}>{input.value}</Option>{" "}
|
||||
</SelectField>
|
||||
</Flex>
|
||||
</HorizontalGutter>
|
||||
</Flex>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
</HorizontalGutter>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
+60
-55
@@ -14,6 +14,7 @@ import {
|
||||
|
||||
import Header from "../../Header";
|
||||
import OnOffField from "../../OnOffField";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
interface Props {
|
||||
@@ -23,65 +24,69 @@ interface Props {
|
||||
const SitewideCommentingConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<HorizontalGutter size="oneAndAHalf" container="fieldset">
|
||||
<Localized id="configure-general-sitewideCommenting-title">
|
||||
<Header container="legend">Sitewide Commenting</Header>
|
||||
<Header container="legend">Sitewide commenting</Header>
|
||||
</Localized>
|
||||
<Localized id="configure-general-sitewideCommenting-explanation">
|
||||
<Typography variant="detail">
|
||||
Open or close comment streams for new comments sitewide. When new
|
||||
comments are turned off sitewide, new comments cannot be submitted, but
|
||||
existing comments can continue to receive “Respect” reactions, be
|
||||
reported, and be shared.
|
||||
</Typography>
|
||||
</Localized>
|
||||
|
||||
<FormField container="fieldset">
|
||||
<Localized id="configure-general-sitewideCommenting-enableNewCommentsSitewide">
|
||||
<InputLabel container="legend">Enable New Comments Sitewide</InputLabel>
|
||||
<SectionContent>
|
||||
<Localized id="configure-general-sitewideCommenting-explanation">
|
||||
<Typography variant="bodyShort">
|
||||
Open or close comment streams for new comments sitewide. When new
|
||||
comments are turned off sitewide, new comments cannot be submitted,
|
||||
but existing comments can continue to receive “Respect” reactions, be
|
||||
reported, and be shared.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<OnOffField
|
||||
name="disableCommenting.enabled"
|
||||
disabled={disabled}
|
||||
invert
|
||||
onLabel={
|
||||
<Localized id="configure-general-sitewideCommenting-onCommentStreamsOpened">
|
||||
<span>On - Comment streams opened for new comments</span>
|
||||
</Localized>
|
||||
}
|
||||
offLabel={
|
||||
<Localized id="configure-general-sitewideCommenting-offCommentStreamsClosed">
|
||||
<span>Off - Comment streams closed for new comments</span>
|
||||
</Localized>
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-general-sitewideCommenting-message">
|
||||
<InputLabel htmlFor="configure-general-sitewideCommenting-message">
|
||||
Sitewide Closed Comments Message
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-general-sitewideCommenting-messageExplanation">
|
||||
<InputDescription>
|
||||
Write a message that will be displayed when comment streams are closed
|
||||
sitewide
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
</FormField>
|
||||
<FormField container="fieldset">
|
||||
<Localized id="configure-general-sitewideCommenting-enableNewCommentsSitewide">
|
||||
<InputLabel container="legend">
|
||||
Enable new comments sitewide
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField
|
||||
name="disableCommenting.enabled"
|
||||
disabled={disabled}
|
||||
invert
|
||||
onLabel={
|
||||
<Localized id="configure-general-sitewideCommenting-onCommentStreamsOpened">
|
||||
<span>On - Comment streams opened for new comments</span>
|
||||
</Localized>
|
||||
}
|
||||
offLabel={
|
||||
<Localized id="configure-general-sitewideCommenting-offCommentStreamsClosed">
|
||||
<span>Off - Comment streams closed for new comments</span>
|
||||
</Localized>
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<Field name="disableCommenting.message">
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<MarkdownEditor
|
||||
id="configure-general-sitewideCommenting-message"
|
||||
{...input}
|
||||
/>
|
||||
</Suspense>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<FormField>
|
||||
<Localized id="configure-general-sitewideCommenting-message">
|
||||
<InputLabel htmlFor="configure-general-sitewideCommenting-message">
|
||||
Sitewide closed comments message
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-general-sitewideCommenting-messageExplanation">
|
||||
<InputDescription>
|
||||
Write a message that will be displayed when comment streams are
|
||||
closed sitewide
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
</FormField>
|
||||
|
||||
<Field name="disableCommenting.message">
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<MarkdownEditor
|
||||
id="configure-general-sitewideCommenting-message"
|
||||
{...input}
|
||||
/>
|
||||
</Suspense>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ const APIKeyField: FunctionComponent<Props> = ({
|
||||
<>
|
||||
<Localized id="configure-moderation-apiKey">
|
||||
<InputLabel htmlFor={`configure-moderation-${input.name}`}>
|
||||
API Key
|
||||
API key
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<PasswordField
|
||||
@@ -36,6 +36,7 @@ const APIKeyField: FunctionComponent<Props> = ({
|
||||
hidePasswordTitle="Show API Key"
|
||||
showPasswordTitle="Hide API Key"
|
||||
color={colorFromMeta(meta)}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
import ConfigurationSubHeader from "../../ConfigurationSubHeader";
|
||||
import Header from "../../Header";
|
||||
import OnOffField from "../../OnOffField";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
import APIKeyField from "./APIKeyField";
|
||||
|
||||
@@ -33,76 +34,83 @@ const isEnabled: Condition = (value, values) =>
|
||||
|
||||
const AkismetConfig: FunctionComponent<Props> = ({ disabled }) => {
|
||||
return (
|
||||
<HorizontalGutter size="oneAndAHalf" container={<FieldSet />}>
|
||||
<HorizontalGutter
|
||||
size="oneAndAHalf"
|
||||
container={<FieldSet />}
|
||||
data-testid="akismet-config"
|
||||
>
|
||||
<Localized id="configure-moderation-akismet-title">
|
||||
<Header container="legend">Akismet Spam Detection Filter</Header>
|
||||
<Header container="legend">Spam detection filter</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-moderation-akismet-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Submitted comments are passed to the Akismet API for spam detection.
|
||||
If a comment is determined to be spam, it will prompt the user,
|
||||
indicating that the comment might be considered spam. If the user
|
||||
continues after this point with the still spam-like comment, the
|
||||
comment will be marked as containing spam, will not be published and
|
||||
are placed in the Pending Queue for review by a moderator. If approved
|
||||
by a moderator, the comment will be published.
|
||||
</Typography>
|
||||
</Localized>
|
||||
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-akismet-filter">
|
||||
<InputLabel container="legend">Spam Detection Filter</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField name="integrations.akismet.enabled" disabled={disabled} />
|
||||
</FormField>
|
||||
<div>
|
||||
<ConfigurationSubHeader />
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-moderation-akismet-accountNote"
|
||||
externalLink={<ExternalLink />}
|
||||
id="configure-moderation-akismet-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Note: You must add your active domain(s) in your Akismet account:
|
||||
https://akismet.com/account/
|
||||
<Typography variant="bodyShort">
|
||||
Submitted comments are passed to the Akismet API for spam detection.
|
||||
If a comment is determined to be spam, it will prompt the user,
|
||||
indicating that the comment might be considered spam. If the user
|
||||
continues after this point with the still spam-like comment, the
|
||||
comment will be marked as containing spam, will not be published and
|
||||
are placed in the Pending Queue for review by a moderator. If
|
||||
approved by a moderator, the comment will be published.
|
||||
</Typography>
|
||||
</Localized>
|
||||
</div>
|
||||
<APIKeyField
|
||||
name="integrations.akismet.key"
|
||||
disabled={disabled}
|
||||
validate={validateWhen(isEnabled, required)}
|
||||
/>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-moderation-akismet-siteURL">
|
||||
<InputLabel htmlFor="configure-moderation-akismet-site">
|
||||
Site URL
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Field
|
||||
name="integrations.akismet.site"
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-akismet-filter">
|
||||
<InputLabel container="legend">Spam detection filter</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField name="integrations.akismet.enabled" disabled={disabled} />
|
||||
</FormField>
|
||||
<div>
|
||||
<ConfigurationSubHeader />
|
||||
<Localized
|
||||
id="configure-moderation-akismet-accountNote"
|
||||
externalLink={<ExternalLink />}
|
||||
>
|
||||
<Typography variant="fieldDescription">
|
||||
Note: You must add your active domain(s) in your Akismet account:
|
||||
https://akismet.com/account/
|
||||
</Typography>
|
||||
</Localized>
|
||||
</div>
|
||||
<APIKeyField
|
||||
name="integrations.akismet.key"
|
||||
disabled={disabled}
|
||||
validate={validateWhen(isEnabled, required)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id="configure-moderation-akismet-site"
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
color={colorFromMeta(meta)}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
/>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-moderation-akismet-siteURL">
|
||||
<InputLabel htmlFor="configure-moderation-akismet-site">
|
||||
Site URL
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Field
|
||||
name="integrations.akismet.site"
|
||||
validate={validateWhen(isEnabled, required)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id="configure-moderation-akismet-site"
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
color={colorFromMeta(meta)}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -23,12 +23,12 @@ const ModerationConfig: FunctionComponent<Props> = ({
|
||||
onInitValues,
|
||||
}) => (
|
||||
<HorizontalGutter size="double" data-testid="configure-moderationContainer">
|
||||
<RecentCommentHistoryConfigContainer
|
||||
<PreModerationConfigContainer
|
||||
disabled={disabled}
|
||||
settings={settings}
|
||||
onInitValues={onInitValues}
|
||||
/>
|
||||
<PreModerationConfigContainer
|
||||
<RecentCommentHistoryConfigContainer
|
||||
disabled={disabled}
|
||||
settings={settings}
|
||||
onInitValues={onInitValues}
|
||||
|
||||
+189
-177
@@ -30,6 +30,7 @@ import ConfigurationSubHeader from "../../ConfigurationSubHeader";
|
||||
import Header from "../../Header";
|
||||
import OnOffField from "../../OnOffField";
|
||||
import PermissionField from "../../PermissionField";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
import APIKeyField from "./APIKeyField";
|
||||
|
||||
@@ -44,190 +45,201 @@ const isEnabled: Condition = (value, values) =>
|
||||
|
||||
const PerspectiveConfig: FunctionComponent<Props> = ({ disabled }) => {
|
||||
return (
|
||||
<HorizontalGutter size="oneAndAHalf" container={<FieldSet />}>
|
||||
<HorizontalGutter
|
||||
size="oneAndAHalf"
|
||||
container={<FieldSet />}
|
||||
data-testid="perspective-container"
|
||||
>
|
||||
<Localized id="configure-moderation-perspective-title">
|
||||
<Header container="legend">Perspective Toxic Comment Filter</Header>
|
||||
<Header container="legend">Toxic comment filter</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-moderation-perspective-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Using the Perspective API, the Toxic Comment filter warns users when
|
||||
comments exceed the predefined toxicity threshold. Comments with a
|
||||
toxicity score above the threshold will not be published and are
|
||||
placed in the Pending Queue for review by a moderator. If approved by
|
||||
a moderator, the comment will be published.
|
||||
</Typography>
|
||||
</Localized>
|
||||
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-perspective-filter">
|
||||
<InputLabel container="legend">Toxic Comment Filter</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField
|
||||
name="integrations.perspective.enabled"
|
||||
disabled={disabled}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-moderation-perspective-toxicityThreshold">
|
||||
<InputLabel htmlFor="configure-moderation-perspective-threshold">
|
||||
Toxicity Threshold
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-moderation-perspective-toxicityThresholdDescription"
|
||||
$default={TOXICITY_THRESHOLD_DEFAULT + "%"}
|
||||
id="configure-moderation-perspective-explanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<InputDescription>
|
||||
This value can be set a percentage between 0 and 100. This number
|
||||
represents the likelihood that a comment is toxic, according to
|
||||
Perspective API. By default the threshold is set to $default.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field
|
||||
name="integrations.perspective.threshold"
|
||||
parse={parsePercentage}
|
||||
format={formatPercentage}
|
||||
validate={validatePercentage(0, 1)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id="configure-moderation-perspective-threshold"
|
||||
classes={{
|
||||
input: styles.thresholdTextField,
|
||||
}}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
adornment={<Typography variant="bodyCopy">%</Typography>}
|
||||
placeholder={TOXICITY_THRESHOLD_DEFAULT.toString()}
|
||||
textAlignCenter
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-moderation-perspective-toxicityModel">
|
||||
<InputLabel htmlFor="configure-moderation-perspective-model">
|
||||
Toxicity Model
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-moderation-perspective-toxicityModelDescription"
|
||||
externalLink={
|
||||
<ExternalLink
|
||||
href={
|
||||
"https://github.com/conversationai/perspectiveapi/blob/master/api_reference.md#models"
|
||||
}
|
||||
/>
|
||||
}
|
||||
$default={TOXICITY_MODEL_DEFAULT}
|
||||
>
|
||||
<InputDescription>
|
||||
Choose your Perspective Model. The default is $default. You can find
|
||||
out more about model choices here.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field name="integrations.perspective.model">
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id="configure-moderation-perspective-model"
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
placeholder={TOXICITY_MODEL_DEFAULT}
|
||||
spellCheck={false}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-perspective-allowStoreCommentData">
|
||||
<InputLabel container="legend">
|
||||
Allow Google to Store Comment Data
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-moderation-perspective-allowStoreCommentDataDescription">
|
||||
<InputDescription>
|
||||
Stored comments will be used for future research and community model
|
||||
building purposes to improve the API over time.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<div>
|
||||
<PermissionField
|
||||
name="integrations.perspective.doNotStore"
|
||||
disabled={disabled}
|
||||
invert
|
||||
/>
|
||||
</div>
|
||||
</FormField>
|
||||
<div>
|
||||
<ConfigurationSubHeader />
|
||||
<Localized
|
||||
id="configure-moderation-perspective-accountNote"
|
||||
externalLink={<ExternalLink />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
For additional information on how to set up the Perspective Toxic
|
||||
Comment Filter please visit:
|
||||
https://github.com/conversationai/perspectiveapi/blob/master/quickstart.md
|
||||
<Typography variant="bodyShort">
|
||||
Using the Perspective API, the Toxic Comment filter warns users when
|
||||
comments exceed the predefined toxicity threshold. Comments with a
|
||||
toxicity score above the threshold will not be published and are
|
||||
placed in the Pending Queue for review by a moderator. If approved
|
||||
by a moderator, the comment will be published.
|
||||
</Typography>
|
||||
</Localized>
|
||||
</div>
|
||||
<APIKeyField
|
||||
name="integrations.perspective.key"
|
||||
disabled={disabled}
|
||||
validate={validateWhen(isEnabled, required)}
|
||||
/>
|
||||
<FormField>
|
||||
<Localized id="configure-moderation-perspective-customEndpoint">
|
||||
<InputLabel htmlFor="configure-moderation-perspective-customEndpoint">
|
||||
Custom Endpoint
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-moderation-perspective-defaultEndpoint"
|
||||
$default={TOXICITY_ENDPOINT_DEFAULT}
|
||||
>
|
||||
<InputDescription>
|
||||
By default the endpoint is set to $default. You may override this
|
||||
here
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field name="integrations.perspective.endpoint" validate={validateURL}>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id="configure-moderation-perspective-customEndpoint"
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
placeholder={TOXICITY_ENDPOINT_DEFAULT}
|
||||
spellCheck={false}
|
||||
{...input}
|
||||
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-perspective-filter">
|
||||
<InputLabel container="legend">Toxic comment filter</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField
|
||||
name="integrations.perspective.enabled"
|
||||
disabled={disabled}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-moderation-perspective-toxicityThreshold">
|
||||
<InputLabel htmlFor="configure-moderation-perspective-threshold">
|
||||
Toxicity threshold
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-moderation-perspective-toxicityThresholdDescription"
|
||||
$default={TOXICITY_THRESHOLD_DEFAULT + "%"}
|
||||
>
|
||||
<InputDescription>
|
||||
This value can be set a percentage between 0 and 100. This number
|
||||
represents the likelihood that a comment is toxic, according to
|
||||
Perspective API. By default the threshold is set to $default.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field
|
||||
name="integrations.perspective.threshold"
|
||||
parse={parsePercentage}
|
||||
format={formatPercentage}
|
||||
validate={validatePercentage(0, 1)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id="configure-moderation-perspective-threshold"
|
||||
classes={{
|
||||
input: styles.thresholdTextField,
|
||||
}}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
adornment={<Typography variant="bodyShort">%</Typography>}
|
||||
placeholder={TOXICITY_THRESHOLD_DEFAULT.toString()}
|
||||
textAlignCenter
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-moderation-perspective-toxicityModel">
|
||||
<InputLabel htmlFor="configure-moderation-perspective-model">
|
||||
Toxicity model
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-moderation-perspective-toxicityModelDescription"
|
||||
externalLink={
|
||||
<ExternalLink
|
||||
href={
|
||||
"https://github.com/conversationai/perspectiveapi/blob/master/api_reference.md#models"
|
||||
}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
}
|
||||
$default={TOXICITY_MODEL_DEFAULT}
|
||||
>
|
||||
<InputDescription>
|
||||
Choose your Perspective Model. The default is $default. You can
|
||||
find out more about model choices here.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field name="integrations.perspective.model">
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id="configure-moderation-perspective-model"
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
placeholder={TOXICITY_MODEL_DEFAULT}
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-perspective-allowStoreCommentData">
|
||||
<InputLabel container="legend">
|
||||
Allow Google to store comment data
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-moderation-perspective-allowStoreCommentDataDescription">
|
||||
<InputDescription>
|
||||
Stored comments will be used for future research and community
|
||||
model building purposes to improve the API over time.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<div>
|
||||
<PermissionField
|
||||
name="integrations.perspective.doNotStore"
|
||||
disabled={disabled}
|
||||
invert
|
||||
/>
|
||||
</div>
|
||||
</FormField>
|
||||
<div>
|
||||
<ConfigurationSubHeader />
|
||||
<Localized
|
||||
id="configure-moderation-perspective-accountNote"
|
||||
externalLink={<ExternalLink />}
|
||||
>
|
||||
<Typography variant="fieldDescription">
|
||||
For additional information on how to set up the Perspective Toxic
|
||||
Comment Filter please visit:
|
||||
https://github.com/conversationai/perspectiveapi/blob/master/quickstart.md
|
||||
</Typography>
|
||||
</Localized>
|
||||
</div>
|
||||
<APIKeyField
|
||||
name="integrations.perspective.key"
|
||||
disabled={disabled}
|
||||
validate={validateWhen(isEnabled, required)}
|
||||
/>
|
||||
<FormField>
|
||||
<Localized id="configure-moderation-perspective-customEndpoint">
|
||||
<InputLabel htmlFor="configure-moderation-perspective-customEndpoint">
|
||||
Custom endpoint
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-moderation-perspective-defaultEndpoint"
|
||||
$default={TOXICITY_ENDPOINT_DEFAULT}
|
||||
>
|
||||
<InputDescription>
|
||||
By default the endpoint is set to $default. You may override this
|
||||
here
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field
|
||||
name="integrations.perspective.endpoint"
|
||||
validate={validateURL}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id="configure-moderation-perspective-customEndpoint"
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
placeholder={TOXICITY_ENDPOINT_DEFAULT}
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
};
|
||||
|
||||
+29
-26
@@ -12,6 +12,7 @@ import {
|
||||
|
||||
import Header from "../../Header";
|
||||
import OnOffField from "../../OnOffField";
|
||||
import SectionContent from "../../SectionContent";
|
||||
|
||||
interface Props {
|
||||
disabled: boolean;
|
||||
@@ -31,33 +32,35 @@ const PreModerationConfig: FunctionComponent<Props> = ({ disabled }) => {
|
||||
<Localized id="configure-moderation-preModeration-title">
|
||||
<Header container="legend">Pre-moderation</Header>
|
||||
</Localized>
|
||||
<Localized id="configure-moderation-preModeration-explanation">
|
||||
<Typography variant="detail">
|
||||
When pre-moderation is turned on, comments will not be published
|
||||
unless approved by a moderator.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-preModeration-moderation">
|
||||
<InputLabel container="legend">
|
||||
Pre-moderate all comments sitewide
|
||||
</InputLabel>
|
||||
<SectionContent>
|
||||
<Localized id="configure-moderation-preModeration-explanation">
|
||||
<Typography variant="bodyShort">
|
||||
When pre-moderation is turned on, comments will not be published
|
||||
unless approved by a moderator.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<OnOffField
|
||||
name="moderation"
|
||||
disabled={disabled}
|
||||
parse={parse}
|
||||
format={format}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-preModeration-premodLinksEnable">
|
||||
<InputLabel container="legend">
|
||||
Pre-moderate comments containing links sitewide
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField name="premodLinksEnable" disabled={disabled} />
|
||||
</FormField>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-preModeration-moderation">
|
||||
<InputLabel container="legend">
|
||||
Pre-moderate all comments sitewide
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField
|
||||
name="moderation"
|
||||
disabled={disabled}
|
||||
parse={parse}
|
||||
format={format}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-preModeration-premodLinksEnable">
|
||||
<InputLabel container="legend">
|
||||
Pre-moderate comments containing links sitewide
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<OnOffField name="premodLinksEnable" disabled={disabled} />
|
||||
</FormField>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
};
|
||||
|
||||
+91
-90
@@ -26,6 +26,7 @@ import {
|
||||
|
||||
import Header from "../../Header";
|
||||
import OnOffField from "../../OnOffField";
|
||||
import SectionContent from "../../SectionContent";
|
||||
|
||||
import styles from "./RecentCommentHistoryConfig.css";
|
||||
|
||||
@@ -37,97 +38,97 @@ const RecentCommentHistoryConfig: FunctionComponent<Props> = ({ disabled }) => {
|
||||
return (
|
||||
<HorizontalGutter size="oneAndAHalf" container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-recentCommentHistory-title">
|
||||
<Header container="legend">Recent comment history</Header>
|
||||
<Header container="legend">Recent history</Header>
|
||||
</Localized>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-recentCommentHistory-timeFrame">
|
||||
<InputLabel container="legend">
|
||||
Recent comment history timeframe
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-moderation-recentCommentHistory-timeFrame-description">
|
||||
<InputDescription>
|
||||
Time period over which a commenter's rejection rate is calcualted
|
||||
and submitted comments are counted.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field
|
||||
name="recentCommentHistory.timeFrame"
|
||||
validate={composeValidators(
|
||||
required,
|
||||
validateWholeNumberGreaterThan(0)
|
||||
)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<DurationField
|
||||
units={[DURATION_UNIT.DAYS]}
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-recentCommentHistory-enabled">
|
||||
<InputLabel container="legend">
|
||||
Recent comment history filter
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-moderation-recentCommentHistory-enabled-description"
|
||||
strong={<strong />}
|
||||
>
|
||||
<InputDescription>
|
||||
Prevents repeat offenders from publishing comments without approval.
|
||||
After a commenter's rejection rate rises above the defined threshold
|
||||
below, their next submitted comments are{" "}
|
||||
<strong>sent to Pending for moderator approval.</strong> The filter
|
||||
is removed when their rejection rate falls below the threshold.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<OnOffField name="recentCommentHistory.enabled" disabled={disabled} />
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Localized id="configure-moderation-recentCommentHistory-triggerRejectionRate">
|
||||
<InputLabel>Rejection rate threshold</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-moderation-recentCommentHistory-triggerRejectionRate-description">
|
||||
<InputDescription>
|
||||
Calculated by the number of rejected comments divided by the sum of
|
||||
a commenter’s rejected and published comments, over the recent
|
||||
comment history timeframe (does not include comments pending for
|
||||
toxicity, spam or pre-moderation.)
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field
|
||||
name="recentCommentHistory.triggerRejectionRate"
|
||||
parse={parsePercentage}
|
||||
format={formatPercentage}
|
||||
validate={validatePercentage(0, 1)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
classes={{
|
||||
input: styles.thresholdTextField,
|
||||
}}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
adornment={<Typography variant="bodyCopy">%</Typography>}
|
||||
textAlignCenter
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<SectionContent>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-recentCommentHistory-timeFrame">
|
||||
<InputLabel container="legend">
|
||||
Recent comment history time period
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-moderation-recentCommentHistory-timeFrame-description">
|
||||
<InputDescription>
|
||||
The period of time over which a user’s rejection rate is
|
||||
calculated.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field
|
||||
name="recentCommentHistory.timeFrame"
|
||||
validate={composeValidators(
|
||||
required,
|
||||
validateWholeNumberGreaterThan(0)
|
||||
)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<DurationField
|
||||
units={[DURATION_UNIT.DAYS]}
|
||||
disabled={disabled}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField container={<FieldSet />}>
|
||||
<Localized id="configure-moderation-recentCommentHistory-enabled">
|
||||
<InputLabel container="legend">Recent history filter</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-moderation-recentCommentHistory-enabled-description"
|
||||
strong={<strong />}
|
||||
>
|
||||
<InputDescription>
|
||||
Prevents repeat offenders from publishing comments without
|
||||
approval. After a commenter's rejection rate rises above the
|
||||
defined threshold below, their next submitted comments are{" "}
|
||||
<strong>sent to Pending for moderator approval.</strong> The
|
||||
filter is removed when their rejection rate falls below the
|
||||
threshold.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<OnOffField name="recentCommentHistory.enabled" disabled={disabled} />
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Localized id="configure-moderation-recentCommentHistory-triggerRejectionRate">
|
||||
<InputLabel>Rejection rate threshold</InputLabel>
|
||||
</Localized>
|
||||
<Localized id="configure-moderation-recentCommentHistory-triggerRejectionRate-description">
|
||||
<InputDescription>
|
||||
A user’s rejected comments divided by their published comments,
|
||||
over the time period set below (does not include comments pending
|
||||
for toxicity, spam or pre-moderation.)
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<Field
|
||||
name="recentCommentHistory.triggerRejectionRate"
|
||||
parse={parsePercentage}
|
||||
format={formatPercentage}
|
||||
validate={validatePercentage(0, 1)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
classes={{
|
||||
input: styles.thresholdTextField,
|
||||
}}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
adornment={<Typography variant="bodyShort">%</Typography>}
|
||||
textAlignCenter
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
};
|
||||
|
||||
+2
-2
@@ -5,12 +5,12 @@ exports[`renders correctly 1`] = `
|
||||
data-testid="configure-moderationContainer"
|
||||
size="double"
|
||||
>
|
||||
<Relay(RecentCommentHistoryConfigContainer)
|
||||
<Relay(PreModerationConfigContainer)
|
||||
disabled={false}
|
||||
onInitValues={[Function]}
|
||||
settings={Object {}}
|
||||
/>
|
||||
<Relay(PreModerationConfigContainer)
|
||||
<Relay(RecentCommentHistoryConfigContainer)
|
||||
disabled={false}
|
||||
onInitValues={[Function]}
|
||||
settings={Object {}}
|
||||
|
||||
+35
-27
@@ -15,6 +15,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
interface Props {
|
||||
@@ -30,35 +31,42 @@ const OrganizationNameConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<label htmlFor="configure-organization-organization.contactEmail" />
|
||||
}
|
||||
>
|
||||
Organization Email
|
||||
Organization email
|
||||
</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-organization-emailExplanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">This Email will be used</Typography>
|
||||
</Localized>
|
||||
<Field
|
||||
name="organization.contactEmail"
|
||||
validate={composeValidators(required, validateEmail)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id={`configure-organization-${input.name}`}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage fullWidth meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-organization-emailExplanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="bodyShort">
|
||||
This email address will be used as in emails and across the platform
|
||||
for community members to get in touch with the organization should
|
||||
they have any questions about the status of their accounts or
|
||||
moderation questions.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field
|
||||
name="organization.contactEmail"
|
||||
validate={composeValidators(required, validateEmail)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id={`configure-organization-${input.name}`}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage fullWidth meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
</FormField>
|
||||
);
|
||||
|
||||
+30
-27
@@ -11,6 +11,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
interface Props {
|
||||
@@ -26,35 +27,37 @@ const OrganizationNameConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<label htmlFor="configure-organization-organization.name" />
|
||||
}
|
||||
>
|
||||
Organization Name
|
||||
Organization name
|
||||
</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-organization-nameExplanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Your organization name will appear on emails sent by Coral to your
|
||||
community and organization members
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field name="organization.name" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id={`configure-organization-${input.name}`}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-organization-nameExplanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="bodyShort">
|
||||
Your organization name will appear on emails sent by Coral to your
|
||||
community and organization members
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field name="organization.name" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id={`configure-organization-${input.name}`}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
</FormField>
|
||||
);
|
||||
|
||||
+29
-23
@@ -15,6 +15,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
interface Props {
|
||||
@@ -33,29 +34,34 @@ const OrganizationURLConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
Organization URL
|
||||
</Header>
|
||||
</Localized>
|
||||
<Localized id="configure-organization-urlExplanation" strong={<strong />}>
|
||||
<Typography variant="detail">This URL will be used</Typography>
|
||||
</Localized>
|
||||
<Field
|
||||
name="organization.url"
|
||||
validate={composeValidators(required, validateURL)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id={`configure-organization-${input.name}`}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage fullWidth meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-organization-urlExplanation"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">This URL will be used</Typography>
|
||||
</Localized>
|
||||
<Field
|
||||
name="organization.url"
|
||||
validate={composeValidators(required, validateURL)}
|
||||
>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<TextField
|
||||
id={`configure-organization-${input.name}`}
|
||||
disabled={disabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage fullWidth meta={meta} />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
</FormField>
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import WordListTextArea from "./WordListTextArea";
|
||||
|
||||
import styles from "./BannedWordListConfig.css";
|
||||
@@ -22,41 +23,43 @@ interface Props {
|
||||
const BannedWordListConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<HorizontalGutter size="oneAndAHalf">
|
||||
<Localized id="configure-wordList-banned-bannedWordsAndPhrases">
|
||||
<Header>Banned Words and Phrases</Header>
|
||||
</Localized>
|
||||
<Localized id="configure-wordList-banned-explanation" strong={<strong />}>
|
||||
<Typography variant="detail">
|
||||
Comments containing a word or phrase in the banned words list are
|
||||
automatically rejected and are not published.
|
||||
</Typography>
|
||||
<Header>Banned words and phrases</Header>
|
||||
</Localized>
|
||||
<SectionContent>
|
||||
<Localized id="configure-wordList-banned-explanation" strong={<strong />}>
|
||||
<Typography variant="bodyShort">
|
||||
Comments containing a word or phrase in the banned words list are
|
||||
automatically rejected and are not published.
|
||||
</Typography>
|
||||
</Localized>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-wordList-banned-wordList">
|
||||
<InputLabel htmlFor="configure-wordlist-banned">
|
||||
Banned Word List
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-wordList-banned-wordListDetail"
|
||||
strong={<strong />}
|
||||
externalLink={<ExternalLink href="#" />}
|
||||
>
|
||||
<InputDescription>
|
||||
Separate banned words or phrases with a new line. Attempting to copy
|
||||
and paste a comma separated list? Learn how to convert your list to a
|
||||
new line separated list.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<div>
|
||||
<WordListTextArea
|
||||
id="configure-wordlist-banned"
|
||||
name={"wordList.banned"}
|
||||
disabled={disabled}
|
||||
className={styles.textArea}
|
||||
/>
|
||||
</div>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Localized id="configure-wordList-banned-wordList">
|
||||
<InputLabel htmlFor="configure-wordlist-banned">
|
||||
Banned word list
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-wordList-banned-wordListDetail"
|
||||
strong={<strong />}
|
||||
externalLink={<ExternalLink href="#" />}
|
||||
>
|
||||
<InputDescription>
|
||||
Separate banned words or phrases with a new line. Attempting to copy
|
||||
and paste a comma separated list? Learn how to convert your list to
|
||||
a new line separated list.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<div>
|
||||
<WordListTextArea
|
||||
id="configure-wordlist-banned"
|
||||
name={"wordList.banned"}
|
||||
disabled={disabled}
|
||||
className={styles.textArea}
|
||||
/>
|
||||
</div>
|
||||
</FormField>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
+37
-31
@@ -11,6 +11,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import SectionContent from "../../SectionContent";
|
||||
import WordListTextArea from "./WordListTextArea";
|
||||
|
||||
import styles from "./SuspectWordListConfig.css";
|
||||
@@ -22,42 +23,47 @@ interface Props {
|
||||
const SuspectWordListConfig: FunctionComponent<Props> = ({ disabled }) => (
|
||||
<HorizontalGutter size="oneAndAHalf">
|
||||
<Localized id="configure-wordList-suspect-bannedWordsAndPhrases">
|
||||
<Header>Suspect Words and Phrases</Header>
|
||||
<Header>Suspect words and phrases</Header>
|
||||
</Localized>
|
||||
<Localized id="configure-wordList-suspect-explanation" strong={<strong />}>
|
||||
<Typography variant="detail">
|
||||
Comments containing a word or phrase in the Suspect Words List are
|
||||
placed into the Reported Queue for moderator review and are published
|
||||
(if comments are not pre-moderated).
|
||||
</Typography>
|
||||
</Localized>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-wordList-suspect-wordList">
|
||||
<InputLabel htmlFor="configure-wordlist-suspect">
|
||||
Suspect Word List
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<SectionContent>
|
||||
<Localized
|
||||
id="configure-wordList-suspect-wordListDetail"
|
||||
id="configure-wordList-suspect-explanation"
|
||||
strong={<strong />}
|
||||
externalLink={<ExternalLink href="#" />}
|
||||
>
|
||||
<InputDescription>
|
||||
Separate suspect words or phrases with a new line. Attempting to copy
|
||||
and paste a comma separated list? Learn how to convert your list to a
|
||||
new line separated list.
|
||||
</InputDescription>
|
||||
<Typography variant="bodyShort">
|
||||
Comments containing a word or phrase in the Suspect Words List are
|
||||
placed into the Reported Queue for moderator review and are published
|
||||
(if comments are not pre-moderated).
|
||||
</Typography>
|
||||
</Localized>
|
||||
<div>
|
||||
<WordListTextArea
|
||||
id="configure-wordlist-suspect"
|
||||
name={"wordList.suspect"}
|
||||
disabled={disabled}
|
||||
className={styles.textArea}
|
||||
/>
|
||||
</div>
|
||||
</FormField>
|
||||
|
||||
<FormField>
|
||||
<Localized id="configure-wordList-suspect-wordList">
|
||||
<InputLabel htmlFor="configure-wordlist-suspect">
|
||||
Suspect word list
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-wordList-suspect-wordListDetail"
|
||||
strong={<strong />}
|
||||
externalLink={<ExternalLink href="#" />}
|
||||
>
|
||||
<InputDescription>
|
||||
Separate suspect words or phrases with a new line. Attempting to
|
||||
copy and paste a comma separated list? Learn how to convert your
|
||||
list to a new line separated list.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<div>
|
||||
<WordListTextArea
|
||||
id="configure-wordlist-suspect"
|
||||
name={"wordList.suspect"}
|
||||
disabled={disabled}
|
||||
className={styles.textArea}
|
||||
/>
|
||||
</div>
|
||||
</FormField>
|
||||
</SectionContent>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user