mirror of
https://github.com/wassname/talk.git
synced 2026-07-13 08:11:15 +08:00
[CORL-116] Configure sitewide commenting (#2193)
* feat: configure sitewide commenting * fix: repaired snapshots * fix: updated snapshots * test: update snapshots
This commit is contained in:
@@ -11,48 +11,56 @@ interface Props {
|
||||
name: string;
|
||||
disabled: boolean;
|
||||
invert?: boolean;
|
||||
onLabel?: React.ReactNode;
|
||||
offLabel?: React.ReactNode;
|
||||
}
|
||||
|
||||
const OnOffField: StatelessComponent<Props> = ({
|
||||
name,
|
||||
disabled,
|
||||
onLabel,
|
||||
offLabel,
|
||||
invert = false,
|
||||
}) => (
|
||||
<div>
|
||||
<Field name={name} type="radio" parse={parseStringBool} value={!invert}>
|
||||
{({ input }) => (
|
||||
<Localized id="configure-onOffField-on">
|
||||
<RadioButton
|
||||
id={`${input.name}-true`}
|
||||
name={input.name}
|
||||
onChange={input.onChange}
|
||||
onFocus={input.onFocus}
|
||||
onBlur={input.onBlur}
|
||||
checked={input.checked}
|
||||
disabled={disabled}
|
||||
value={input.value}
|
||||
>
|
||||
On
|
||||
</RadioButton>
|
||||
</Localized>
|
||||
<RadioButton
|
||||
id={`${input.name}-true`}
|
||||
name={input.name}
|
||||
onChange={input.onChange}
|
||||
onFocus={input.onFocus}
|
||||
onBlur={input.onBlur}
|
||||
checked={input.checked}
|
||||
disabled={disabled}
|
||||
value={input.value}
|
||||
>
|
||||
{onLabel || (
|
||||
<Localized id="configure-onOffField-on">
|
||||
<span>On</span>
|
||||
</Localized>
|
||||
)}
|
||||
</RadioButton>
|
||||
)}
|
||||
</Field>
|
||||
<Field name={name} type="radio" parse={parseStringBool} value={invert}>
|
||||
{({ input }) => (
|
||||
<Localized id="configure-onOffField-off">
|
||||
<RadioButton
|
||||
id={`${input.name}-fase`}
|
||||
name={input.name}
|
||||
onChange={input.onChange}
|
||||
onFocus={input.onFocus}
|
||||
onBlur={input.onBlur}
|
||||
checked={input.checked}
|
||||
disabled={disabled}
|
||||
value={input.value}
|
||||
>
|
||||
Off
|
||||
</RadioButton>
|
||||
</Localized>
|
||||
<RadioButton
|
||||
id={`${input.name}-false`}
|
||||
name={input.name}
|
||||
onChange={input.onChange}
|
||||
onFocus={input.onFocus}
|
||||
onBlur={input.onBlur}
|
||||
checked={input.checked}
|
||||
disabled={disabled}
|
||||
value={input.value}
|
||||
>
|
||||
{offLabel || (
|
||||
<Localized id="configure-onOffField-off">
|
||||
<span>Off</span>
|
||||
</Localized>
|
||||
)}
|
||||
</RadioButton>
|
||||
)}
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
+8
-1
@@ -8,6 +8,7 @@ import ClosingCommentStreamsConfigContainer from "../containers/ClosingCommentSt
|
||||
import CommentEditingConfigContainer from "../containers/CommentEditingConfigContainer";
|
||||
import CommentLengthConfigContainer from "../containers/CommentLengthConfigContainer";
|
||||
import GuidelinesConfigContainer from "../containers/GuidelinesConfigContainer";
|
||||
import SitewideCommentingConfigContainer from "../containers/SitewideCommentingConfigContainer";
|
||||
|
||||
interface Props {
|
||||
disabled: boolean;
|
||||
@@ -15,7 +16,8 @@ interface Props {
|
||||
PropTypesOf<typeof CommentLengthConfigContainer>["settings"] &
|
||||
PropTypesOf<typeof CommentEditingConfigContainer>["settings"] &
|
||||
PropTypesOf<typeof ClosedStreamMessageConfigContainer>["settings"] &
|
||||
PropTypesOf<typeof ClosingCommentStreamsConfigContainer>["settings"];
|
||||
PropTypesOf<typeof ClosingCommentStreamsConfigContainer>["settings"] &
|
||||
PropTypesOf<typeof SitewideCommentingConfigContainer>["settings"];
|
||||
onInitValues: (values: any) => void;
|
||||
}
|
||||
|
||||
@@ -25,6 +27,11 @@ const General: StatelessComponent<Props> = ({
|
||||
onInitValues,
|
||||
}) => (
|
||||
<HorizontalGutter size="double" data-testid="configure-generalContainer">
|
||||
<SitewideCommentingConfigContainer
|
||||
disabled={disabled}
|
||||
settings={settings}
|
||||
onInitValues={onInitValues}
|
||||
/>
|
||||
<GuidelinesConfigContainer
|
||||
disabled={disabled}
|
||||
settings={settings}
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { StatelessComponent, Suspense } from "react";
|
||||
import { Field } from "react-final-form";
|
||||
|
||||
import {
|
||||
FormField,
|
||||
HorizontalGutter,
|
||||
InputDescription,
|
||||
InputLabel,
|
||||
Spinner,
|
||||
Typography,
|
||||
ValidationMessage,
|
||||
} from "talk-ui/components";
|
||||
|
||||
import OnOffField from "talk-admin/routes/configure/components/OnOffField";
|
||||
import Header from "../../../components/Header";
|
||||
import LazyMarkdown from "./LazyMarkdown";
|
||||
|
||||
interface Props {
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
const SitewideCommentingConfig: StatelessComponent<Props> = ({ disabled }) => (
|
||||
<HorizontalGutter size="oneAndAHalf" container="fieldset">
|
||||
<Localized id="configure-general-sitewideCommenting-title">
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<Field name="disableCommenting.message">
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<LazyMarkdown
|
||||
id="configure-general-sitewideCommenting-message"
|
||||
name={input.name}
|
||||
onChange={input.onChange}
|
||||
value={input.value}
|
||||
/>
|
||||
</Suspense>
|
||||
{meta.touched &&
|
||||
(meta.error || meta.submitError) && (
|
||||
<ValidationMessage>
|
||||
{meta.error || meta.submitError}
|
||||
</ValidationMessage>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
export default SitewideCommentingConfig;
|
||||
+1
@@ -50,6 +50,7 @@ const enhanced = withFragmentContainer<Props>({
|
||||
...CommentEditingConfigContainer_settings
|
||||
...ClosedStreamMessageConfigContainer_settings
|
||||
...ClosingCommentStreamsConfigContainer_settings
|
||||
...SitewideCommentingConfigContainer_settings
|
||||
}
|
||||
`,
|
||||
})(GeneralConfigContainer);
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import React from "react";
|
||||
import { graphql } from "react-relay";
|
||||
|
||||
import { SitewideCommentingConfigContainer_settings as SettingsData } from "talk-admin/__generated__/SitewideCommentingConfigContainer_settings.graphql";
|
||||
import { withFragmentContainer } from "talk-framework/lib/relay";
|
||||
|
||||
import SitewideCommentingConfig from "../components/SitewideCommentingConfig";
|
||||
|
||||
interface Props {
|
||||
settings: SettingsData;
|
||||
onInitValues: (values: SettingsData) => void;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
class SitewideCommentingConfigContainer extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
props.onInitValues(props.settings);
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { disabled } = this.props;
|
||||
return <SitewideCommentingConfig disabled={disabled} />;
|
||||
}
|
||||
}
|
||||
|
||||
const enhanced = withFragmentContainer<Props>({
|
||||
settings: graphql`
|
||||
fragment SitewideCommentingConfigContainer_settings on Settings {
|
||||
disableCommenting {
|
||||
enabled
|
||||
message
|
||||
}
|
||||
}
|
||||
`,
|
||||
})(SitewideCommentingConfigContainer);
|
||||
|
||||
export default enhanced;
|
||||
@@ -107,6 +107,107 @@ exports[`renders configure general 1`] = `
|
||||
className="HorizontalGutter-root HorizontalGutter-double"
|
||||
data-testid="configure-generalContainer"
|
||||
>
|
||||
<fieldset
|
||||
className="HorizontalGutter-root HorizontalGutter-oneAndAHalf"
|
||||
>
|
||||
<legend
|
||||
className="Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
|
||||
>
|
||||
Sitewide Commenting
|
||||
</legend>
|
||||
<p
|
||||
className="Typography-root Typography-detail Typography-colorTextPrimary"
|
||||
>
|
||||
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.
|
||||
</p>
|
||||
<fieldset
|
||||
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
|
||||
>
|
||||
<legend
|
||||
className="Typography-root Typography-inputLabel Typography-colorTextPrimary InputLabel-root"
|
||||
>
|
||||
Enable New Comments Sitewide
|
||||
</legend>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root RadioButton-root Flex-flex Flex-alignCenter"
|
||||
>
|
||||
<input
|
||||
checked={true}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="disableCommenting.enabled-true"
|
||||
name="disableCommenting.enabled"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="disableCommenting.enabled-true"
|
||||
>
|
||||
<span>
|
||||
On - Comment streams opened for new comments
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root RadioButton-root Flex-flex Flex-alignCenter"
|
||||
>
|
||||
<input
|
||||
checked={false}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="disableCommenting.enabled-false"
|
||||
name="disableCommenting.enabled"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="disableCommenting.enabled-false"
|
||||
>
|
||||
<span>
|
||||
Off - Comment streams closed for new comments
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div
|
||||
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
|
||||
>
|
||||
<label
|
||||
className="Typography-root Typography-inputLabel Typography-colorTextPrimary InputLabel-root"
|
||||
htmlFor="configure-general-sitewideCommenting-message"
|
||||
>
|
||||
Sitewide Closed Comments Message
|
||||
</label>
|
||||
<p
|
||||
className="Typography-root Typography-detail Typography-colorTextSecondary"
|
||||
>
|
||||
Write a message that will be displayed when comment streams are closed sitewide
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className="MarkdownEditor-wrapper"
|
||||
>
|
||||
<textarea
|
||||
id="configure-general-sitewideCommenting-message"
|
||||
name="disableCommenting.message"
|
||||
onChange={[Function]}
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset
|
||||
className="FieldSet-root HorizontalGutter-root HorizontalGutter-oneAndAHalf"
|
||||
>
|
||||
@@ -143,7 +244,9 @@ exports[`renders configure general 1`] = `
|
||||
className="RadioButton-label"
|
||||
htmlFor="communityGuidelines.enabled-true"
|
||||
>
|
||||
On
|
||||
<span>
|
||||
On
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
@@ -153,7 +256,7 @@ exports[`renders configure general 1`] = `
|
||||
checked={true}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="communityGuidelines.enabled-fase"
|
||||
id="communityGuidelines.enabled-false"
|
||||
name="communityGuidelines.enabled"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
@@ -163,9 +266,11 @@ exports[`renders configure general 1`] = `
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="communityGuidelines.enabled-fase"
|
||||
htmlFor="communityGuidelines.enabled-false"
|
||||
>
|
||||
Off
|
||||
<span>
|
||||
Off
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -248,7 +353,9 @@ Markdown can be found
|
||||
className="RadioButton-label"
|
||||
htmlFor="charCount.enabled-true"
|
||||
>
|
||||
On
|
||||
<span>
|
||||
On
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
@@ -258,7 +365,7 @@ Markdown can be found
|
||||
checked={true}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="charCount.enabled-fase"
|
||||
id="charCount.enabled-false"
|
||||
name="charCount.enabled"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
@@ -268,9 +375,11 @@ Markdown can be found
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="charCount.enabled-fase"
|
||||
htmlFor="charCount.enabled-false"
|
||||
>
|
||||
Off
|
||||
<span>
|
||||
Off
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -471,7 +580,9 @@ moderation panel.
|
||||
className="RadioButton-label"
|
||||
htmlFor="autoCloseStream-true"
|
||||
>
|
||||
On
|
||||
<span>
|
||||
On
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
@@ -481,7 +592,7 @@ moderation panel.
|
||||
checked={true}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="autoCloseStream-fase"
|
||||
id="autoCloseStream-false"
|
||||
name="autoCloseStream"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
@@ -491,9 +602,11 @@ moderation panel.
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="autoCloseStream-fase"
|
||||
htmlFor="autoCloseStream-false"
|
||||
>
|
||||
Off
|
||||
<span>
|
||||
Off
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -158,7 +158,9 @@ the
|
||||
className="RadioButton-label"
|
||||
htmlFor="integrations.perspective.enabled-true"
|
||||
>
|
||||
On
|
||||
<span>
|
||||
On
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
@@ -168,7 +170,7 @@ the
|
||||
checked={true}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="integrations.perspective.enabled-fase"
|
||||
id="integrations.perspective.enabled-false"
|
||||
name="integrations.perspective.enabled"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
@@ -178,9 +180,11 @@ the
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="integrations.perspective.enabled-fase"
|
||||
htmlFor="integrations.perspective.enabled-false"
|
||||
>
|
||||
Off
|
||||
<span>
|
||||
Off
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -424,7 +428,9 @@ the comment will be published.
|
||||
className="RadioButton-label"
|
||||
htmlFor="integrations.akismet.enabled-true"
|
||||
>
|
||||
On
|
||||
<span>
|
||||
On
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
@@ -434,7 +440,7 @@ the comment will be published.
|
||||
checked={true}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="integrations.akismet.enabled-fase"
|
||||
id="integrations.akismet.enabled-false"
|
||||
name="integrations.akismet.enabled"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
@@ -444,9 +450,11 @@ the comment will be published.
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="integrations.akismet.enabled-fase"
|
||||
htmlFor="integrations.akismet.enabled-false"
|
||||
>
|
||||
Off
|
||||
<span>
|
||||
Off
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -68,6 +68,67 @@ it("renders configure general", async () => {
|
||||
expect(within(configureContainer).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("change site wide commenting", async () => {
|
||||
let settingsRecord = cloneDeep(settings);
|
||||
const updateSettingsStub = createSinonStub(s =>
|
||||
s.onFirstCall().callsFake((_: any, data: any) => {
|
||||
expect(data.input.settings.disableCommenting).toEqual({
|
||||
enabled: true,
|
||||
message: "Closing message",
|
||||
});
|
||||
settingsRecord = merge(settingsRecord, data.input.settings);
|
||||
return {
|
||||
settings: settingsRecord,
|
||||
clientMutationId: data.input.clientMutationId,
|
||||
};
|
||||
})
|
||||
);
|
||||
const {
|
||||
configureContainer,
|
||||
generalContainer,
|
||||
saveChangesButton,
|
||||
} = await createTestRenderer({
|
||||
Mutation: {
|
||||
updateSettings: updateSettingsStub,
|
||||
},
|
||||
});
|
||||
|
||||
const sitewideCommentingContainer = within(generalContainer).getAllByText(
|
||||
"Sitewide Commenting",
|
||||
{ selector: "fieldset" }
|
||||
)[0];
|
||||
|
||||
const offField = within(sitewideCommentingContainer).getByLabelText(
|
||||
"Off - Comment streams closed for new comments"
|
||||
);
|
||||
const contentField = within(sitewideCommentingContainer).getByLabelText(
|
||||
"Sitewide Closed Comments Message"
|
||||
);
|
||||
|
||||
// Let's enable it.
|
||||
offField.props.onChange(offField.props.value.toString());
|
||||
|
||||
// Let's change the content.
|
||||
contentField.props.onChange("Closing message");
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(offField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(offField.props.disabled).toBe(false);
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
expect(updateSettingsStub.called).toBe(true);
|
||||
});
|
||||
|
||||
it("change community guidlines", async () => {
|
||||
let settingsRecord = cloneDeep(settings);
|
||||
const updateSettingsStub = createSinonStub(s =>
|
||||
|
||||
@@ -11,6 +11,9 @@ export const settings = {
|
||||
max: 1000,
|
||||
min: 3,
|
||||
},
|
||||
disableCommenting: {
|
||||
enabled: false,
|
||||
},
|
||||
closedTimeout: 604800,
|
||||
autoCloseStream: false,
|
||||
closedMessage: null,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { uniq } from "lodash";
|
||||
import { ReactTestInstance } from "react-test-renderer";
|
||||
|
||||
import { queryAllByText } from "./byText";
|
||||
@@ -62,6 +63,7 @@ export function queryAllByLabelText(
|
||||
options?: TextMatchOptions
|
||||
) {
|
||||
const matches = container.findAll(ariaLabelMatcher(pattern, options));
|
||||
// Find matching aria-labelledby and id pairs.
|
||||
queryAllByText(container, pattern, options).forEach(i => {
|
||||
if (typeof i.type !== "string") {
|
||||
return;
|
||||
@@ -77,15 +79,20 @@ export function queryAllByLabelText(
|
||||
);
|
||||
} catch {} // tslint:disable-line:no-empty
|
||||
}
|
||||
if (i.type === "label" && i.props.htmlFor) {
|
||||
try {
|
||||
matches.push(
|
||||
container.find(
|
||||
x => typeof x.type === "string" && x.props.id === i.props.htmlFor
|
||||
)
|
||||
);
|
||||
} catch {} // tslint:disable-line:no-empty
|
||||
}
|
||||
});
|
||||
return matches;
|
||||
// Find matching labels.
|
||||
queryAllByText(container, pattern, { ...options, selector: "label" }).forEach(
|
||||
i => {
|
||||
if (i.props.htmlFor) {
|
||||
try {
|
||||
matches.push(
|
||||
container.find(
|
||||
x => typeof x.type === "string" && x.props.id === i.props.htmlFor
|
||||
)
|
||||
);
|
||||
} catch {} // tslint:disable-line:no-empty
|
||||
}
|
||||
}
|
||||
);
|
||||
return uniq(matches);
|
||||
}
|
||||
|
||||
@@ -764,6 +764,23 @@ type CharCount {
|
||||
max: Int
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## DisableCommenting
|
||||
################################################################################
|
||||
|
||||
type DisableCommenting {
|
||||
"""
|
||||
enabled when true will disable commenting site-wide.
|
||||
"""
|
||||
enabled: Boolean!
|
||||
|
||||
"""
|
||||
message will be shown above the comment stream while
|
||||
commenting is disabled site-wide.
|
||||
"""
|
||||
message: String
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## Email
|
||||
################################################################################
|
||||
@@ -937,13 +954,7 @@ type Settings {
|
||||
"""
|
||||
disableCommenting will disable commenting site-wide.
|
||||
"""
|
||||
disableCommenting: Boolean!
|
||||
|
||||
"""
|
||||
disableCommentingMessage will be shown above the comment stream while
|
||||
commenting is disabled site-wide.
|
||||
"""
|
||||
disableCommentingMessage: String
|
||||
disableCommenting: DisableCommenting!
|
||||
|
||||
"""
|
||||
editCommentWindowLength is the length of time (in seconds) after a comment is
|
||||
@@ -2125,6 +2136,19 @@ input SettingsCharCountInput {
|
||||
max: Int
|
||||
}
|
||||
|
||||
input SettingsDisableCommentingInput {
|
||||
"""
|
||||
enabled when true will disable commenting site-wide.
|
||||
"""
|
||||
enabled: Boolean
|
||||
|
||||
"""
|
||||
message will be shown above the comment stream while
|
||||
commenting is disabled site-wide.
|
||||
"""
|
||||
message: String
|
||||
}
|
||||
|
||||
"""
|
||||
SettingsInput is the partial type of the Settings type for performing mutations.
|
||||
"""
|
||||
@@ -2196,13 +2220,7 @@ input SettingsInput {
|
||||
"""
|
||||
disableCommenting will disable commenting site-wide.
|
||||
"""
|
||||
disableCommenting: Boolean
|
||||
|
||||
"""
|
||||
disableCommentingMessage will be shown above the comment stream while
|
||||
commenting is disabled site-wide.
|
||||
"""
|
||||
disableCommentingMessage: String
|
||||
disableCommenting: SettingsDisableCommentingInput
|
||||
|
||||
"""
|
||||
editCommentWindowLength is the length of time (in seconds) after a comment is
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Omit } from "talk-common/types";
|
||||
import {
|
||||
GQLAuthDisplayNameConfiguration,
|
||||
GQLCharCount,
|
||||
GQLDisableCommenting,
|
||||
GQLEmail,
|
||||
GQLExternalIntegrations,
|
||||
GQLFacebookAuthIntegration,
|
||||
@@ -34,8 +35,7 @@ export interface ModerationSettings {
|
||||
*/
|
||||
closedTimeout: number;
|
||||
closedMessage?: string;
|
||||
disableCommenting: boolean;
|
||||
disableCommentingMessage?: string;
|
||||
disableCommenting: GQLDisableCommenting;
|
||||
charCount: GQLCharCount;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,9 @@ export async function createTenant(mongo: Db, input: CreateTenantInput) {
|
||||
questionBoxEnable: false,
|
||||
premodLinksEnable: false,
|
||||
autoCloseStream: false,
|
||||
disableCommenting: false,
|
||||
disableCommenting: {
|
||||
enabled: false,
|
||||
},
|
||||
|
||||
// 2 weeks timeout.
|
||||
closedTimeout: 60 * 60 * 24 * 7 * 2,
|
||||
|
||||
@@ -68,6 +68,23 @@ configure-general-guidelines-explanation =
|
||||
Markdown can be found <externalLink>here</externalLink>.
|
||||
configure-general-guidelines-showCommunityGuidelines = Show Community Guidelines Summary
|
||||
|
||||
### 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
|
||||
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-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-explanation = Set comment streams to close after a defined period of time after a story’s publication
|
||||
|
||||
Reference in New Issue
Block a user