[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:
Nick Funk
2019-09-06 12:29:27 -06:00
committed by GitHub
parent d2af78d3d7
commit aa8e1e2d7a
71 changed files with 3861 additions and 3575 deletions
@@ -52,7 +52,7 @@ Make sure it is unique and be sure to keep it secure.
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -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)>
@@ -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 sites 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 sites 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>
);
};
@@ -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"
@@ -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>
);
@@ -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
storys 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
storys 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>
);
@@ -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}
@@ -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>
);
};
@@ -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>
);
};
@@ -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 commenters 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 users 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 users 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>
);
};
@@ -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 {}}
@@ -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>
);
@@ -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>
);
@@ -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>
);
@@ -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>
);
@@ -24,7 +24,7 @@ we require users to create a password.
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -151,7 +151,7 @@ we require users to create a password.
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -241,7 +241,7 @@ we require users to create a password.
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -353,7 +353,7 @@ GraphQL request (4:3)
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -438,7 +438,7 @@ we require users to create a password.
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -23,7 +23,7 @@ exports[`checks for invalid username 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -127,7 +127,7 @@ exports[`renders createUsername view 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -194,7 +194,7 @@ exports[`shows error when submitting empty form 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -283,7 +283,7 @@ GraphQL request (4:3)
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -345,7 +345,7 @@ exports[`successfully sets username 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -122,21 +122,24 @@ exports[`renders configure advanced 1`] = `
className="Box-root HorizontalGutter-root HorizontalGutter-oneAndAHalf"
>
<legend
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
className="Box-root Typography-root Typography-heading3 Typography-colorTextPrimary Header-root"
>
Embed Code
Embed code
</legend>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
<div
className="Box-root HorizontalGutter-root SectionContent-sectionContent HorizontalGutter-double"
>
Copy and paste the code below into your CMS to embed Coral comment streams in
<p
className="Box-root Typography-root Typography-bodyShort Typography-colorTextPrimary"
>
Copy and paste the code below into your CMS to embed Coral comment streams in
each of your sites stories.
</p>
<textarea
className="EmbedCode-textArea"
readOnly={true}
rows={22}
value="<div id=\\"coral_thread\\"></div>
</p>
<textarea
className="EmbedCode-textArea"
readOnly={true}
rows={22}
value="<div id=\\"coral_thread\\"></div>
<script type=\\"text/javascript\\">
(function() {
var d = document, s = d.createElement('script');
@@ -158,26 +161,27 @@ each of your sites stories.
(d.head || d.body).appendChild(s);
})();
</script>"
/>
<div
className="Box-root HorizontalGutter-root EmbedCode-copyArea HorizontalGutter-full"
>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
data-color="primary"
data-variant="filled"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
/>
<div
className="Box-root HorizontalGutter-root EmbedCode-copyArea HorizontalGutter-full"
>
<span>
Copy
</span>
</button>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
data-color="primary"
data-variant="filled"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Copy
</span>
</button>
</div>
</div>
</fieldset>
<div
@@ -187,35 +191,39 @@ each of your sites stories.
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<label
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
className="Box-root Typography-root Typography-heading3 Typography-colorTextPrimary Header-root"
htmlFor="configure-advanced-customCSSURL"
>
Custom CSS
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
>
URL of a CSS stylesheet that will override default Embed Stream styles. Can be internal or external.
</p>
<div
className="TextField-root TextField-fullWidth"
className="Box-root HorizontalGutter-root SectionContent-sectionContent HorizontalGutter-double"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="TextField-input TextField-colorRegular"
disabled={false}
id="configure-advanced-customCSSURL"
name="customCSSURL"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder=""
spellCheck={false}
type="text"
value=""
/>
<p
className="Box-root Typography-root Typography-bodyShort Typography-colorTextPrimary"
>
URL of a CSS stylesheet that will override default Embed Stream styles. Can be internal or external.
</p>
<div
className="TextField-root TextField-fullWidth"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="TextField-input TextField-colorRegular"
disabled={false}
id="configure-advanced-customCSSURL"
name="customCSSURL"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder=""
spellCheck={false}
type="text"
value=""
/>
</div>
</div>
</div>
</div>
@@ -226,64 +234,68 @@ each of your sites stories.
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<label
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
className="Box-root Typography-root Typography-heading3 Typography-colorTextPrimary Header-root"
htmlFor="configure-advanced-liveUpdates"
>
Comment Stream Live Updates
Comment stream live updates
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
<div
className="Box-root HorizontalGutter-root SectionContent-sectionContent HorizontalGutter-double"
>
When enabled, there will be real-time loading and updating of comments as new comments and replies are published
</p>
<div>
<div
className="Box-root Flex-root RadioButton-root Flex-flex Flex-alignCenter"
<p
className="Box-root Typography-root Typography-bodyShort Typography-colorTextPrimary"
>
<input
checked={true}
className="RadioButton-input"
disabled={false}
id="live.enabled-true"
name="live.enabled"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="radio"
value={true}
/>
<label
className="RadioButton-label"
htmlFor="live.enabled-true"
When enabled, there will be real-time loading and updating of comments as new comments and replies are published
</p>
<div>
<div
className="Box-root Flex-root RadioButton-root Flex-flex Flex-alignCenter"
>
<span>
On
</span>
</label>
</div>
<div
className="Box-root Flex-root RadioButton-root Flex-flex Flex-alignCenter"
>
<input
checked={false}
className="RadioButton-input"
disabled={false}
id="live.enabled-false"
name="live.enabled"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="radio"
value={false}
/>
<label
className="RadioButton-label"
htmlFor="live.enabled-false"
<input
checked={true}
className="RadioButton-input"
disabled={false}
id="live.enabled-true"
name="live.enabled"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="radio"
value={true}
/>
<label
className="RadioButton-label"
htmlFor="live.enabled-true"
>
<span>
On
</span>
</label>
</div>
<div
className="Box-root Flex-root RadioButton-root Flex-flex Flex-alignCenter"
>
<span>
Off
</span>
</label>
<input
checked={false}
className="RadioButton-input"
disabled={false}
id="live.enabled-false"
name="live.enabled"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="radio"
value={false}
/>
<label
className="RadioButton-label"
htmlFor="live.enabled-false"
>
<span>
Off
</span>
</label>
</div>
</div>
</div>
</div>
@@ -295,37 +307,41 @@ each of your sites stories.
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<label
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
className="Box-root Typography-root Typography-heading3 Typography-colorTextPrimary Header-root"
htmlFor="configure-advanced-allowedDomains"
>
Permitted Domains
Permitted domains
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
<div
className="Box-root HorizontalGutter-root SectionContent-sectionContent HorizontalGutter-double"
>
Domains where your Coral instance is allowed to be embedded
<p
className="Box-root Typography-root Typography-bodyShort Typography-colorTextPrimary"
>
Domains where your Coral instance is allowed to be embedded
including the scheme (ex. http://localhost:3000, https://staging.domain.com,
https://domain.com).
</p>
<div
className="TextField-root TextField-fullWidth"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="TextField-input TextField-colorRegular"
disabled={false}
id="configure-advanced-allowedDomains"
name="allowedDomains"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder=""
spellCheck={false}
type="text"
value="http://localhost:8080"
/>
</p>
<div
className="TextField-root TextField-fullWidth"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="TextField-input TextField-colorRegular"
disabled={false}
id="configure-advanced-allowedDomains"
name="allowedDomains"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder=""
spellCheck={false}
type="text"
value="http://localhost:8080"
/>
</div>
</div>
</div>
</div>
@@ -336,7 +352,7 @@ https://domain.com).
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<h1
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
className="Box-root Typography-root Typography-heading3 Typography-colorTextPrimary Header-root"
>
Story creation
</h1>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -125,35 +125,39 @@ exports[`renders configure organization 1`] = `
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<label
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
className="Box-root Typography-root Typography-heading3 Typography-colorTextPrimary Header-root"
htmlFor="configure-organization-organization.name"
>
Organization Name
Organization name
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
>
Your organization name will appear on emails sent by Coral to your community and organization members.
</p>
<div
className="TextField-root TextField-fullWidth"
className="Box-root HorizontalGutter-root SectionContent-sectionContent HorizontalGutter-double"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="TextField-input TextField-colorRegular"
disabled={false}
id="configure-organization-organization.name"
name="organization.name"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder=""
spellCheck={false}
type="text"
value="Coral"
/>
<p
className="Box-root Typography-root Typography-bodyShort Typography-colorTextPrimary"
>
Your organization name will appear on emails sent by Coral to your community and organization members.
</p>
<div
className="TextField-root TextField-fullWidth"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="TextField-input TextField-colorRegular"
disabled={false}
id="configure-organization-organization.name"
name="organization.name"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder=""
spellCheck={false}
type="text"
value="Coral"
/>
</div>
</div>
</div>
</div>
@@ -164,38 +168,42 @@ exports[`renders configure organization 1`] = `
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<label
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
className="Box-root Typography-root Typography-heading3 Typography-colorTextPrimary Header-root"
htmlFor="configure-organization-organization.contactEmail"
>
Organization Email
Organization email
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
<div
className="Box-root HorizontalGutter-root SectionContent-sectionContent HorizontalGutter-double"
>
This email address will be used as in emails and across
<p
className="Box-root Typography-root Typography-bodyShort Typography-colorTextPrimary"
>
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.
</p>
<div
className="TextField-root TextField-fullWidth"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="TextField-input TextField-colorRegular"
disabled={false}
id="configure-organization-organization.contactEmail"
name="organization.contactEmail"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder=""
spellCheck={false}
type="text"
value="coral@test.com"
/>
</p>
<div
className="TextField-root TextField-fullWidth"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="TextField-input TextField-colorRegular"
disabled={false}
id="configure-organization-organization.contactEmail"
name="organization.contactEmail"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder=""
spellCheck={false}
type="text"
value="coral@test.com"
/>
</div>
</div>
</div>
</div>
@@ -206,35 +214,39 @@ status of their accounts or moderation questions.
className="Box-root HorizontalGutter-root HorizontalGutter-full"
>
<label
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
className="Box-root Typography-root Typography-heading3 Typography-colorTextPrimary Header-root"
htmlFor="configure-organization-organization.url"
>
Organization URL
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
>
Your organization url will appear on emails sent by Coral to your community and organization members.
</p>
<div
className="TextField-root TextField-fullWidth"
className="Box-root HorizontalGutter-root SectionContent-sectionContent HorizontalGutter-double"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="TextField-input TextField-colorRegular"
disabled={false}
id="configure-organization-organization.url"
name="organization.url"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder=""
spellCheck={false}
type="text"
value="https://test.com/"
/>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
>
Your organization url will appear on emails sent by Coral to your community and organization members.
</p>
<div
className="TextField-root TextField-fullWidth"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="TextField-input TextField-colorRegular"
disabled={false}
id="configure-organization-organization.url"
name="organization.url"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder=""
spellCheck={false}
type="text"
value="https://test.com/"
/>
</div>
</div>
</div>
</div>
@@ -122,58 +122,62 @@ exports[`renders configure wordList 1`] = `
className="Box-root HorizontalGutter-root HorizontalGutter-oneAndAHalf"
>
<h1
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
className="Box-root Typography-root Typography-heading3 Typography-colorTextPrimary Header-root"
>
Banned Words and Phrases
Banned words and phrases
</h1>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
>
Comments containing a word or phrase in the banned words list are
<strong>
automatically rejected and are not published
</strong>
.
</p>
<div
className="Box-root HorizontalGutter-root FormField-root HorizontalGutter-half"
className="Box-root HorizontalGutter-root SectionContent-sectionContent HorizontalGutter-double"
>
<label
className="Box-root Typography-root Typography-inputLabel Typography-colorTextPrimary InputLabel-root"
htmlFor="configure-wordlist-banned"
>
Banned Word List
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-bodyShort Typography-colorTextPrimary"
>
Separate banned words or phrases with a new line. Attempting to copy
and paste a comma separated list?
<a
className="ExternalLink-root"
href="#"
rel="noopener noreferrer"
target="_blank"
>
Learn how to convert your list
to a new line separated list.
</a>
Comments containing a word or phrase in the banned words list are
<strong>
automatically rejected and are not published
</strong>
.
</p>
<div>
<textarea
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="BannedWordListConfig-textArea WordListTextArea-textArea"
disabled={false}
id="configure-wordlist-banned"
name="wordList.banned"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
spellCheck={false}
value="fuck"
/>
<div
className="Box-root HorizontalGutter-root FormField-root HorizontalGutter-half"
>
<label
className="Box-root Typography-root Typography-inputLabel Typography-colorTextPrimary InputLabel-root"
htmlFor="configure-wordlist-banned"
>
Banned word list
</label>
<p
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Separate banned words or phrases with a new line. Attempting to copy
and paste a comma separated list?
<a
className="ExternalLink-root"
href="#"
rel="noopener noreferrer"
target="_blank"
>
Learn how to convert your list
to a new line separated list.
</a>
</p>
<div>
<textarea
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="BannedWordListConfig-textArea WordListTextArea-textArea"
disabled={false}
id="configure-wordlist-banned"
name="wordList.banned"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
spellCheck={false}
value="fuck"
/>
</div>
</div>
</div>
</div>
@@ -181,60 +185,64 @@ to a new line separated list.
className="Box-root HorizontalGutter-root HorizontalGutter-oneAndAHalf"
>
<h1
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
className="Box-root Typography-root Typography-heading3 Typography-colorTextPrimary Header-root"
>
Suspect Words and Phrases
Suspect words and phrases
</h1>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
>
Comments containing a word or phrase in the Suspect Words List
are
<strong>
placed into the Reported Queue for moderator review and are
published (if comments are not pre-moderated).
</strong>
</p>
<div
className="Box-root HorizontalGutter-root FormField-root HorizontalGutter-half"
className="Box-root HorizontalGutter-root SectionContent-sectionContent HorizontalGutter-double"
>
<label
className="Box-root Typography-root Typography-inputLabel Typography-colorTextPrimary InputLabel-root"
htmlFor="configure-wordlist-suspect"
>
Suspect Word List
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-bodyShort Typography-colorTextPrimary"
>
Separate suspect words or phrases with a new line. Attempting to copy
and paste a comma separated list?
<a
className="ExternalLink-root"
href="#"
rel="noopener noreferrer"
target="_blank"
>
Learn how to convert your list
to a new line separated list.
</a>
Comments containing a word or phrase in the Suspect Words List
are
<strong>
placed into the Reported Queue for moderator review and are
published (if comments are not pre-moderated).
</strong>
</p>
<div>
<textarea
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="SuspectWordListConfig-textArea WordListTextArea-textArea"
disabled={false}
id="configure-wordlist-suspect"
name="wordList.suspect"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
spellCheck={false}
value="idiot
<div
className="Box-root HorizontalGutter-root FormField-root HorizontalGutter-half"
>
<label
className="Box-root Typography-root Typography-inputLabel Typography-colorTextPrimary InputLabel-root"
htmlFor="configure-wordlist-suspect"
>
Suspect word list
</label>
<p
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Separate suspect words or phrases with a new line. Attempting to copy
and paste a comma separated list?
<a
className="ExternalLink-root"
href="#"
rel="noopener noreferrer"
target="_blank"
>
Learn how to convert your list
to a new line separated list.
</a>
</p>
<div>
<textarea
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="SuspectWordListConfig-textArea WordListTextArea-textArea"
disabled={false}
id="configure-wordlist-suspect"
name="wordList.suspect"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
spellCheck={false}
value="idiot
stupid"
/>
/>
</div>
</div>
</div>
</div>
@@ -187,7 +187,7 @@ it("change permitted domains to be empty", async () => {
});
const permittedDomainsField = within(advancedContainer).getByLabelText(
"Permitted Domains"
"Permitted domains"
);
// Let's change the permitted domains.
@@ -234,7 +234,7 @@ it("change permitted domains to include more domains", async () => {
});
const permittedDomainsField = within(advancedContainer).getByLabelText(
"Permitted Domains"
"Permitted domains"
);
// Let's change the permitted domains.
@@ -130,7 +130,7 @@ it("change site wide commenting", async () => {
});
const sitewideCommentingContainer = within(generalContainer).getAllByText(
"Sitewide Commenting",
"Sitewide commenting",
{ selector: "fieldset" }
)[0];
@@ -138,7 +138,7 @@ it("change site wide commenting", async () => {
"Off - Comment streams closed for new comments"
);
const contentField = within(sitewideCommentingContainer).getByLabelText(
"Sitewide Closed Comments Message"
"Sitewide closed comments message"
);
// Let's enable it.
@@ -191,13 +191,13 @@ it("change community guidlines", async () => {
});
const guidelinesContainer = within(generalContainer).getAllByText(
"Community Guidelines Summary",
"Community guidelines summary",
{ selector: "fieldset" }
)[0];
const onField = within(guidelinesContainer).getByLabelText("On");
const contentField = within(guidelinesContainer).getByLabelText(
"Community Guidelines Summary"
"Community guidelines summary"
);
// Let's enable it.
@@ -244,7 +244,7 @@ it("change closed stream message", async () => {
} = await createTestRenderer({ resolvers });
const contentField = within(generalContainer).getByLabelText(
"Closed Stream Message"
"Closed comment stream message"
);
// Let's change the content.
@@ -284,7 +284,7 @@ it("change comment editing time", async () => {
} = await createTestRenderer({ resolvers });
const durationFieldset = within(generalContainer).getByText(
"Comment Edit Timeframe",
"Comment edit timeframe",
{ selector: "fieldset" }
);
const valueField = within(durationFieldset).getByLabelText("value");
@@ -353,15 +353,15 @@ it("change comment length limitations", async () => {
});
const commentLengthContainer = within(generalContainer).getByText(
"Comment Length",
"Comment length",
{ selector: "fieldset" }
);
const onField = within(commentLengthContainer).getByLabelText("On");
const minField = within(commentLengthContainer).getByLabelText(
"Minimum Comment Length"
"Minimum comment length"
);
const maxField = within(commentLengthContainer).getByLabelText(
"Maximum Comment Length"
"Maximum comment length"
);
// Let's turn on and set some invalid values.
@@ -439,12 +439,12 @@ it("change closing comment streams", async () => {
} = await createTestRenderer({ resolvers });
const closingCommentStreamsContainer = within(generalContainer).getByText(
"Closing Comment Streams",
"Closing comment streams",
{ selector: "fieldset" }
);
const onField = within(closingCommentStreamsContainer).getByLabelText("On");
const durationFieldset = within(closingCommentStreamsContainer).getByText(
"Close Comments After",
"Close comments after",
{ selector: "fieldset" }
);
const valueField = within(durationFieldset).getByLabelText("value");
@@ -503,7 +503,7 @@ it("handle server error", async () => {
});
const contentField = within(generalContainer).getByLabelText(
"Closed Stream Message"
"Closed comment stream message"
);
// Let's change the content.
@@ -177,13 +177,12 @@ it("change akismet settings", async () => {
saveChangesButton,
} = await createTestRenderer({ resolvers });
const akismetContainer = within(moderationContainer).getByText(
"Akismet Spam Detection Filter",
{ selector: "fieldset" }
const akismetContainer = within(moderationContainer).getByTestID(
"akismet-config"
);
const onField = within(akismetContainer).getByLabelText("On");
const keyField = within(akismetContainer).getByLabelText("API Key");
const keyField = within(akismetContainer).getByLabelText("API key");
const siteField = within(akismetContainer).getByLabelText("Site URL");
// Let's turn it on.
@@ -260,19 +259,18 @@ it("change perspective settings", async () => {
saveChangesButton,
} = await createTestRenderer({ resolvers });
const perspectiveContainer = within(moderationContainer).getByText(
"Perspective Toxic Comment Filter",
{ selector: "fieldset" }
const perspectiveContainer = within(moderationContainer).getByTestID(
"perspective-container"
);
const onField = within(perspectiveContainer).getByLabelText("On");
const allowField = within(perspectiveContainer).getByLabelText("Allow");
const keyField = within(perspectiveContainer).getByLabelText("API Key");
const keyField = within(perspectiveContainer).getByLabelText("API key");
const thresholdField = within(perspectiveContainer).getByLabelText(
"Toxicity Threshold"
"Toxicity threshold"
);
const endpointField = within(perspectiveContainer).getByLabelText(
"Custom Endpoint"
"Custom endpoint"
);
// Let's turn it on.
@@ -80,7 +80,7 @@ it("change organization name", async () => {
} = await createTestRenderer({ resolvers });
const organizationNameField = within(organizationContainer).getByLabelText(
"Organization Name"
"Organization name"
);
// Let's change some organization name.
@@ -140,7 +140,7 @@ it("change organization contact email", async () => {
} = await createTestRenderer({ resolvers });
const organizationEmailField = within(organizationContainer).getByLabelText(
"Organization Email"
"Organization email"
);
// Let's change some organization name.
@@ -83,10 +83,10 @@ it("change banned and suspect words", async () => {
});
const bannedField = within(wordListContainer).getByLabelText(
"Banned Word List"
"Banned word list"
);
const suspectField = within(wordListContainer).getByLabelText(
"Suspect Word List"
"Suspect word list"
);
// Let's change the wordlist contents.
@@ -119,7 +119,7 @@ exports[`renders form 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.”
</p>
@@ -150,7 +150,7 @@ exports[`renders form 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -24,7 +24,7 @@ we require users to create a password.
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -142,7 +142,7 @@ we require users to create a password.
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -231,7 +231,7 @@ we require users to create a password.
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -343,7 +343,7 @@ GraphQL request (4:3)
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -428,7 +428,7 @@ we require users to create a password.
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -23,7 +23,7 @@ exports[`checks for invalid username 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -118,7 +118,7 @@ exports[`renders createUsername view 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -184,7 +184,7 @@ exports[`shows error when submitting empty form 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -273,7 +273,7 @@ GraphQL request (4:3)
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -335,7 +335,7 @@ exports[`successfully sets username 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -64,7 +64,7 @@ exports[`accepts correct password 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -108,7 +108,7 @@ exports[`accepts correct password 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -233,7 +233,7 @@ exports[`accepts valid email 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -277,7 +277,7 @@ exports[`accepts valid email 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -428,7 +428,7 @@ exports[`accepts valid username 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -459,7 +459,7 @@ exports[`accepts valid username 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -597,7 +597,7 @@ exports[`auth configuration renders all auth enabled 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -628,7 +628,7 @@ exports[`auth configuration renders all auth enabled 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -923,7 +923,7 @@ exports[`checks for invalid characters in username 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -967,7 +967,7 @@ exports[`checks for invalid characters in username 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -1118,7 +1118,7 @@ exports[`checks for invalid email 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -1162,7 +1162,7 @@ exports[`checks for invalid email 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -1313,7 +1313,7 @@ exports[`checks for too long username 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -1357,7 +1357,7 @@ exports[`checks for too long username 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -1508,7 +1508,7 @@ exports[`checks for too short password 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -1552,7 +1552,7 @@ exports[`checks for too short password 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -1703,7 +1703,7 @@ exports[`checks for too short username 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -1747,7 +1747,7 @@ exports[`checks for too short username 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -1926,7 +1926,7 @@ exports[`renders sign up form 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -1957,7 +1957,7 @@ exports[`renders sign up form 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -2098,7 +2098,7 @@ exports[`shows error when submitting empty form 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -2142,7 +2142,7 @@ exports[`shows error when submitting empty form 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -2287,7 +2287,7 @@ exports[`shows server error 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -2318,7 +2318,7 @@ exports[`shows server error 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -2443,7 +2443,7 @@ exports[`submits form successfully 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
You may use “_” and “.” Spaces not permitted.
</p>
@@ -2474,7 +2474,7 @@ exports[`submits form successfully 1`] = `
Password
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -18,7 +18,7 @@ exports[`works with multiple form components 1`] = `
Username
</label>
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
An identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -13,7 +13,7 @@ const InputDescription: FunctionComponent<InputDescriptionProps> = props => {
const { className, children, ...rest } = props;
return (
<Typography
variant="detail"
variant="fieldDescription"
color="textSecondary"
className={className}
{...rest}
@@ -2,7 +2,7 @@
exports[`renders correctly 1`] = `
<p
className="Box-root Typography-root Typography-detail Typography-colorTextSecondary"
className="Box-root Typography-root Typography-fieldDescription Typography-colorTextSecondary"
>
Form Components should go here
</p>
@@ -1,3 +1,4 @@
.root {
display: block;
padding-bottom: var(--spacing-1)
}
@@ -52,6 +52,14 @@
font-weight: var(--font-weight-medium);
}
.bodyShort {
composes: bodyShort from "coral-ui/shared/typography.css";
}
.fieldDescription {
composes: fieldDescription from "coral-ui/shared/typography.css";
}
.button {
composes: button from "coral-ui/shared/typography.css";
}
@@ -24,6 +24,8 @@ type Variant =
| "header5"
| "bodyCopy"
| "bodyCopyBold"
| "bodyShort"
| "fieldDescription"
| "inputLabel"
| "detail"
| "timestamp";
@@ -165,6 +167,8 @@ Typography.defaultProps = {
header5: "h1",
bodyCopy: "p",
bodyCopyBold: "p",
bodyShort: "p",
fieldDescription: "p",
timestamp: "span",
inputLabel: "label",
detail: "p",
+8
View File
@@ -143,6 +143,14 @@
@mixin bodyCopy;
}
.bodyShort {
@mixin bodyShort;
}
.fieldDescription {
@mixin fieldDescription;
}
.button {
color: var(--palette-text-secondary);
font-family: var(--font-family-sans-serif);
+16
View File
@@ -7,6 +7,22 @@
color: var(--palette-text-primary);
}
@define-mixin bodyShort {
font-size: var(--font-size-rem-4);
font-weight: var(--font-weight-regular);
font-family: var(--font-family-sans-serif);
line-height: var(--line-height-body-short);
color: var(--palette-text-primary);
}
@define-mixin fieldDescription {
font-size: var(--font-size-rem-3);
font-weight: var(--font-weight-regular);
font-family: var(--font-family-sans-serif);
line-height: var(--line-height-body-short);
color: var(--palette-grey-dark);
}
@define-mixin heading1 {
font-size: calc(24rem / var(--rem-base));
font-weight: var(--font-weight-medium);
+11
View File
@@ -100,6 +100,16 @@ const variables = {
6: "24px",
7: "28px",
8: "32px",
rem: {
1: "0.75rem",
2: "0.875rem",
3: "1rem",
4: "1.125rem",
5: "1.25rem",
6: "1.5rem",
7: "1.75rem",
8: "2rem",
},
},
fontWeight: {
sans: {
@@ -117,6 +127,7 @@ const variables = {
1: "1.1em",
2: "1.2em",
3: "1.45em",
bodyShort: 1.142,
},
/* Breakpoints */
breakpoints: {
-1
View File
@@ -174,7 +174,6 @@ configure-email-smtpPasswordLabel = Adgangskode
### Authentication
configure-auth-authIntegrations = Autentificeringsintegrationer
configure-auth-clientID = Klient-id
configure-auth-clientSecret = Klienthemmelighed
configure-auth-configBoxEnabled = Aktiveret
+47 -48
View File
@@ -85,47 +85,49 @@ configure-permissionField-allow = Allow
configure-permissionField-dontAllow = Don't allow
### General
configure-general-guidelines-title = Community Guidelines Summary
configure-general-guidelines-title = Community guidelines summary
configure-general-guidelines-explanation =
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 <externalLink>here</externalLink>.
configure-general-guidelines-showCommunityGuidelines = Show Community Guidelines Summary
configure-general-guidelines-showCommunityGuidelines = Show community guidelines summary
#### Locale
configure-general-locale-language = Language
configure-general-locale-chooseLanguage = Choose the language for your Coral community.
#### Sitewide Commenting
configure-general-sitewideCommenting-title = Sitewide Commenting
configure-general-sitewideCommenting-title = Sitewide commenting
configure-general-sitewideCommenting-explanation =
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.
configure-general-sitewideCommenting-enableNewCommentsSitewide =
Enable New Comments Sitewide
Enable new comments sitewide
configure-general-sitewideCommenting-onCommentStreamsOpened =
On - Comment streams opened for new comments
configure-general-sitewideCommenting-offCommentStreamsClosed =
Off - Comment streams closed for new comments
configure-general-sitewideCommenting-message = Sitewide Closed Comments Message
configure-general-sitewideCommenting-message = Sitewide closed comments message
configure-general-sitewideCommenting-messageExplanation =
Write a message that will be displayed when comment streams are closed sitewide
#### Closing Comment Streams
configure-general-closingCommentStreams-title = Closing Comment Streams
configure-general-closingCommentStreams-title = Closing comment streams
configure-general-closingCommentStreams-explanation = Set comment streams to close after a defined period of time after a storys publication
configure-general-closingCommentStreams-closeCommentsAutomatically = Close Comments Automatically
configure-general-closingCommentStreams-closeCommentsAfter = Close Comments After
configure-general-closingCommentStreams-closeCommentsAutomatically = Close comments automatically
configure-general-closingCommentStreams-closeCommentsAfter = Close comments after
#### Comment Length
configure-general-commentLength-title = Comment Length
configure-general-commentLength-maxCommentLength = Maximum Comment Length
configure-general-commentLength-setLimit = Set a limit on the length of comments sitewide
configure-general-commentLength-limitCommentLength = Limit Comment Length
configure-general-commentLength-minCommentLength = Minimum Comment Length
configure-general-commentLength-title = Comment length
configure-general-commentLength-maxCommentLength = Maximum comment length
configure-general-commentLength-setLimit =
Set minimum and maximum comment length requirements.
Blank spaces at the beginning and the end of a comment will be trimmed.
configure-general-commentLength-limitCommentLength = Limit comment length
configure-general-commentLength-minCommentLength = Minimum comment length
configure-general-commentLength-characters = Characters
configure-general-commentLength-textField =
.placeholder = No limit
@@ -133,23 +135,23 @@ configure-general-commentLength-validateLongerThanMin =
Please enter a number longer than the minimum length
#### Comment Editing
configure-general-commentEditing-title = Comment Editing
configure-general-commentEditing-title = Comment editing
configure-general-commentEditing-explanation =
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.
configure-general-commentEditing-commentEditTimeFrame = Comment Edit Timeframe
configure-general-commentEditing-commentEditTimeFrame = Comment edit timeframe
configure-general-commentEditing-seconds = Seconds
#### Closed Stream Message
configure-general-closedStreamMessage-title = Closed Stream Message
configure-general-closedStreamMessage-title = Closed comment stream message
configure-general-closedStreamMessage-explanation = Write a message to appear after a story is closed for commenting.
### Organization
configure-organization-name = Organization Name
configure-organization-name = Organization name
configure-organization-nameExplanation =
Your organization name will appear on emails sent by { -product-name } to your community and organization members.
configure-organization-email = Organization Email
configure-organization-email = Organization email
configure-organization-emailExplanation =
This email address will be used as in emails and across
the platform for community members to get in touch with
@@ -174,16 +176,15 @@ configure-email-smtpHostDescription = (ex. smtp.sendgrid.com)
configure-email-smtpPortLabel = SMTP port
configure-email-smtpPortDescription = (ex. 25)
configure-email-smtpTLSLabel = TLS
configure-email-smtpAuthenticationLabel = SMTP Authentication
configure-email-smtpAuthenticationLabel = SMTP authentication
configure-email-smtpCredentialsHeader = Email credentials
configure-email-smtpUsernameLabel = Username
configure-email-smtpPasswordLabel = Password
### Authentication
configure-auth-authIntegrations = Authentication Integrations
configure-auth-clientID = Client ID
configure-auth-clientSecret = Client Secret
configure-auth-clientSecret = Client secret
configure-auth-configBoxEnabled = Enabled
configure-auth-targetFilterCoralAdmin = { -product-name } Admin
configure-auth-targetFilterCommentStream = Comment Stream
@@ -223,12 +224,12 @@ configure-auth-sso-regenerateWarning =
Regenerating a key will invalidate any existing user sessions,
and all signed-in users will be signed out.
configure-auth-local-loginWith = Login with Email Authentication
configure-auth-local-useLoginOn = Use Email Authentication login on
configure-auth-local-loginWith = Login with email authentication
configure-auth-local-useLoginOn = Use email authentication login on
configure-auth-oidc-loginWith = Login with OpenID Connect
configure-auth-oidc-toLearnMore = To learn more: <Link></Link>
configure-auth-oidc-providerName = Provider Name
configure-auth-oidc-providerName = Provider name
configure-auth-oidc-providerNameDescription =
The provider of the OpenID Connect integration. This will be used when the name of the provider
needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
@@ -245,12 +246,11 @@ configure-auth-oidc-useLoginOn = Use OpenID Connect login on
### Recent Comment History
configure-moderation-recentCommentHistory-title = Recent comment history
configure-moderation-recentCommentHistory-timeFrame = Recent comment history timeframe
configure-moderation-recentCommentHistory-title = Recent history
configure-moderation-recentCommentHistory-timeFrame = Recent comment history time period
configure-moderation-recentCommentHistory-timeFrame-description =
Time period over which a commenter's rejection rate is calcualted
and submitted comments are counted.
configure-moderation-recentCommentHistory-enabled = Recent comment history filter
The period of time over which a users rejection rate is calculated.
configure-moderation-recentCommentHistory-enabled = Recent history filter
configure-moderation-recentCommentHistory-enabled-description =
Prevents repeat offenders from publishing comments without approval.
After a commenter's rejection rate rises above the defined threshold
@@ -259,9 +259,8 @@ configure-moderation-recentCommentHistory-enabled-description =
falls below the threshold.
configure-moderation-recentCommentHistory-triggerRejectionRate = Rejection rate threshold
configure-moderation-recentCommentHistory-triggerRejectionRate-description =
Calculated by the number of rejected comments divided by the sum of
a commenters rejected and published comments, over the recent
comment history timeframe (does not include comments pending for
A users rejected comments divided by their published comments, over
the time period set below (does not include comments pending for
toxicity, spam or pre-moderation.)
#### Pre-Moderation
@@ -274,9 +273,9 @@ configure-moderation-preModeration-moderation =
configure-moderation-preModeration-premodLinksEnable =
Pre-moderate comments containing links sitewide
configure-moderation-apiKey = API Key
configure-moderation-apiKey = API key
configure-moderation-akismet-title = Akismet Spam Detection Filter
configure-moderation-akismet-title = Spam detection filter
configure-moderation-akismet-explanation =
Submitted comments are passed to the Akismet API for spam detection.
If a comment is determined to be spam, it will prompt the user,
@@ -287,7 +286,7 @@ configure-moderation-akismet-explanation =
the comment will be published.
#### Akismet
configure-moderation-akismet-filter = Spam Detection Filter
configure-moderation-akismet-filter = Spam detection filter
configure-moderation-akismet-accountNote =
Note: You must add your active domain(s)
in your Akismet account: <externalLink>https://akismet.com/account/</externalLink>
@@ -295,24 +294,24 @@ configure-moderation-akismet-siteURL = Site URL
#### Perspective
configure-moderation-perspective-title = Perspective Toxic Comment Filter
configure-moderation-perspective-title = Toxic comment filter
configure-moderation-perspective-explanation =
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 <strong>will not be published</strong> and are placed in
the <strong>Pending Queue for review by a moderator</strong>. If approved by a moderator, the comment will be published.
configure-moderation-perspective-filter = Toxic Comment Filter
configure-moderation-perspective-toxicityThreshold = Toxicity Threshold
configure-moderation-perspective-filter = Toxic comment filter
configure-moderation-perspective-toxicityThreshold = Toxicity threshold
configure-moderation-perspective-toxicityThresholdDescription =
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 }.
configure-moderation-perspective-toxicityModel = Toxicity Model
configure-moderation-perspective-toxicityModel = Toxicity model
configure-moderation-perspective-toxicityModelDescription =
Choose your Perspective Model. The default is { $default }. You can find out more about model choices <externalLink>here</externalLink>.
configure-moderation-perspective-allowStoreCommentData = Allow Google to Store Comment Data
configure-moderation-perspective-allowStoreCommentData = Allow Google to store comment data
configure-moderation-perspective-allowStoreCommentDataDescription =
Stored comments will be used for future research and community model building purposes to
improve the API over time.
configure-moderation-perspective-customEndpoint = Custom Endpoint
configure-moderation-perspective-customEndpoint = Custom endpoint
configure-moderation-perspective-defaultEndpoint =
By default the endpoint is set to { $default }. You may override this here.
configure-moderation-perspective-accountNote =
@@ -320,22 +319,22 @@ configure-moderation-perspective-accountNote =
<externalLink>https://github.com/conversationai/perspectiveapi/blob/master/quickstart.md</externalLink>
#### Banned Words Configuration
configure-wordList-banned-bannedWordsAndPhrases = Banned Words and Phrases
configure-wordList-banned-bannedWordsAndPhrases = Banned words and phrases
configure-wordList-banned-explanation =
Comments containing a word or phrase in the banned words list are <strong>automatically rejected and are not published</strong>.
configure-wordList-banned-wordList = Banned Word List
configure-wordList-banned-wordList = Banned word list
configure-wordList-banned-wordListDetail =
Separate banned words or phrases with a new line. Attempting to copy
and paste a comma separated list? <externalLink>Learn how to convert your list
to a new line separated list.</externalLink>
#### Suspect Words Configuration
configure-wordList-suspect-bannedWordsAndPhrases = Suspect Words and Phrases
configure-wordList-suspect-bannedWordsAndPhrases = Suspect words and phrases
configure-wordList-suspect-explanation =
Comments containing a word or phrase in the Suspect Words List
are <strong>placed into the Reported Queue for moderator review and are
published (if comments are not pre-moderated).</strong>
configure-wordList-suspect-wordList = Suspect Word List
configure-wordList-suspect-wordList = Suspect word list
configure-wordList-suspect-wordListDetail =
Separate suspect words or phrases with a new line. Attempting to copy
and paste a comma separated list? <externalLink>Learn how to convert your list
@@ -346,17 +345,17 @@ configure-advanced-customCSS = Custom CSS
configure-advanced-customCSS-explanation =
URL of a CSS stylesheet that will override default Embed Stream styles. Can be internal or external.
configure-advanced-permittedDomains = Permitted Domains
configure-advanced-permittedDomains = Permitted domains
configure-advanced-permittedDomains-description =
Domains where your { -product-name } instance is allowed to be embedded
including the scheme (ex. http://localhost:3000, https://staging.domain.com,
https://domain.com).
configure-advanced-liveUpdates = Comment Stream Live Updates
configure-advanced-liveUpdates = Comment stream live updates
configure-advanced-liveUpdates-explanation =
When enabled, there will be real-time loading and updating of comments as new comments and replies are published
configure-advanced-embedCode-title = Embed Code
configure-advanced-embedCode-title = Embed code
configure-advanced-embedCode-explanation =
Copy and paste the code below into your CMS to embed Coral comment streams in
each of your sites stories.
-1
View File
@@ -154,7 +154,6 @@ configure-organization-emailExplanation =
### Authentication
configure-auth-authIntegrations = Integrações de Autenticação
configure-auth-clientID = Client ID
configure-auth-clientSecret = Client Secret
configure-auth-configBoxEnabled = Habilitado