mirror of
https://github.com/wassname/talk.git
synced 2026-08-11 11:27:10 +08:00
[CORL-645] Resolve mismanaged branch merging (#2746)
* Create preliminary schema for setting Slack channels CORL-645 * Implement preliminary slack notification using tenant slack channels CORL-645 * Very preliminarily get data loading with FieldArray's for slack channels CORL-645 * Update settings input on schema to allow saving Slack settings to tenant CORL-645 * Filter off UNMODERATED queue events from slack channels We don't send these to slack through our filters, we only care about pending, reported, and featured CORL-645 * Include a moderation link in comments pushed to Slack CORL-645 * Hook up proper callback functions for adding/removing slack channels CORL-645 * Add missing translation for Slack navigation item CORL-645 * Update snapshots for preliminary Slack configuration changes CORL-645 * Add some FormField wrappers around slack config elements Makes the UI appear a little nicer CORL-645 * Set up slack config to only provide one slack channel We need to do this until we can get ArrayField's working in final-form. CORL-645 * Disable the other trigger checkboxes when "All Comments" is checked CORL-645 * Clean up the formatting of Slack messages CORL-645 * Add error handling around sending comments to Slack CORL-645 * Add links to external Slack setup documentation CORL-645 * Replace form state with wrapped field element CORL-645 * Clean up fetch request sending Slack notifications CORL-645 * Prefer global string replacement over RegEx CORL-645 * Use URL class to construct comment URL's CORL-645 * Require slack configuration in schema CORL-645 * Initialize Slack in fixtures Also fix up a flaky test that wasn't waiting on form submission and on-change events. CORL-645 * Preliminarily fix up styles to match other config pages CORL-645 * Create placeholder add/remove buttons * Convert SlackConfigContainer to FunctionalComponent CORL-645 * Add name field to slack channels CORL-645 * Disable inner fields on Slack channel when not enabled CORL-645 * Improve the delete channel button CORL-645 * Use pureMerge to extract slack channel settings CORL-645 * Do a bit of cleanup on the add channel button CORL-645 * Update the styling of the Slack config - Use sub header for channel headings - Update add channel button text - Move the remove channel button down - Other minor spacing tweaks CORL-645
This commit is contained in:
Generated
+1
-1
@@ -24980,7 +24980,7 @@
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
|
||||
"resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz",
|
||||
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
|
||||
"dev": true
|
||||
}
|
||||
|
||||
@@ -1,28 +1,41 @@
|
||||
.header {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.description {
|
||||
padding-bottom: var(--spacing-1);
|
||||
padding-bottom: var(--v2-spacing-1);
|
||||
}
|
||||
|
||||
.channelName {
|
||||
margin-right: var(--spacing-2);
|
||||
.enabledCheckbox {
|
||||
margin-right: var(--v2-spacing-1);
|
||||
}
|
||||
|
||||
.trigger {
|
||||
padding-left: var(--spacing-1);
|
||||
padding-left: var(--v2-spacing-1);
|
||||
padding-bottom: var(--v2-spacing-2);
|
||||
}
|
||||
|
||||
.button {
|
||||
padding-top: var(--v2-spacing-1);
|
||||
padding-bottom: var(--v2-spacing-1);
|
||||
}
|
||||
|
||||
.removeButton {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
|
||||
margin-bottom: 2px;
|
||||
|
||||
float: right;
|
||||
margin-bottom: var(--v2-spacing-1);
|
||||
}
|
||||
|
||||
.buttonIcon {
|
||||
padding-right: var(--spacing-1);
|
||||
padding-right: var(--v2-spacing-1);
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: var(--v2-spacing-3) var(--v2-spacing-2) 0 var(--v2-spacing-2);
|
||||
}
|
||||
|
||||
.textField {
|
||||
padding-bottom: var(--v2-spacing-4);
|
||||
}
|
||||
|
||||
.notificationsLabel {
|
||||
padding-bottom: var(--v2-spacing-1);
|
||||
}
|
||||
|
||||
.notificationToggles {
|
||||
padding-bottom: var(--v2-spacing-3);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
import cn from "classnames";
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { FunctionComponent, useCallback } from "react";
|
||||
import { Field } from "react-final-form";
|
||||
|
||||
import { parseBool } from "coral-framework/lib/form";
|
||||
import { ExternalLink } from "coral-framework/lib/i18n/components";
|
||||
import { InputDescription, InputLabel } from "coral-ui/components";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ButtonIcon,
|
||||
CheckBox,
|
||||
Flex,
|
||||
FormField,
|
||||
FormFieldDescription,
|
||||
Label,
|
||||
TextField,
|
||||
} from "coral-ui/components/v2";
|
||||
|
||||
import Header from "../../Header";
|
||||
import ConfigBoxWithToggleField from "../Auth/ConfigBoxWithToggleField";
|
||||
import Subheader from "../../Subheader";
|
||||
|
||||
import styles from "./SlackChannel.css";
|
||||
|
||||
@@ -37,193 +38,221 @@ const SlackChannel: FunctionComponent<Props> = ({
|
||||
}, [index, onRemoveClicked]);
|
||||
|
||||
return (
|
||||
<ConfigBoxWithToggleField
|
||||
title={
|
||||
<Flex
|
||||
className={styles.header}
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
>
|
||||
<div>
|
||||
<Field name={`${channel}.name`}>
|
||||
{({ input }) => (
|
||||
<Header className={styles.channelName}>{input.value}</Header>
|
||||
)}
|
||||
</Field>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
size="small"
|
||||
variant="filled"
|
||||
color="alert"
|
||||
onClick={onRemove}
|
||||
className={styles.removeButton}
|
||||
>
|
||||
<ButtonIcon size="md" className={styles.buttonIcon}>
|
||||
delete_forever
|
||||
</ButtonIcon>
|
||||
<Localized id="configure-slack-channel-remove">Remove</Localized>
|
||||
</Button>
|
||||
</div>
|
||||
</Flex>
|
||||
}
|
||||
name={`${channel}.enabled`}
|
||||
disabled={disabled}
|
||||
>
|
||||
{(disabledInside: boolean) => (
|
||||
<>
|
||||
<FormField>
|
||||
<Field name={`${channel}.name`}>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Localized id="configure-slack-channel-name-label">
|
||||
<InputLabel container="legend">Name</InputLabel>
|
||||
<>
|
||||
<Field name={`${channel}.name`}>
|
||||
{({ input }) => (
|
||||
<Subheader>
|
||||
<Flex justifyContent="space-between">
|
||||
<div>
|
||||
{input.value ? (
|
||||
input.value
|
||||
) : (
|
||||
<Localized id="configure-slack-channel-defaultName">
|
||||
New channel
|
||||
</Localized>
|
||||
<Localized id="configure-slack-channel-name-description">
|
||||
<InputDescription className={styles.description}>
|
||||
This is only for your information, to easily identify each
|
||||
Slack connection. Slack does not tell us the name of the
|
||||
channel/s you're connecting to Coral.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<TextField
|
||||
id={`configure-slack-channel-name-${input.name}`}
|
||||
disabled={disabled || disabledInside}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Field name={`${channel}.hookURL`}>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<Localized id="configure-slack-channel-hookURL-label">
|
||||
<InputLabel container="legend">Webhook URL</InputLabel>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-slack-channel-hookURL-description"
|
||||
externalLink={
|
||||
<ExternalLink href="https://docs.coralproject.net/coral/v5/integrating/slack/#i-need-to-find-the-webhook-url-again-where-is-it" />
|
||||
}
|
||||
>
|
||||
<InputDescription className={styles.description}>
|
||||
Slack provides a channel-specific URL to activate webhook
|
||||
connections. To find the URL for one of your Slack
|
||||
channels, follow the instructions here.
|
||||
</InputDescription>
|
||||
</Localized>
|
||||
<TextField
|
||||
id={`configure-slack-channel-hookURL-${input.name}`}
|
||||
disabled={disabled || disabledInside}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
{...input}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Localized id="configure-slack-channel-triggers-label">
|
||||
<InputLabel container="legend">
|
||||
Receive notifications in this Slack channel for
|
||||
</InputLabel>
|
||||
</Localized>
|
||||
<Field
|
||||
name={`${channel}.triggers.allComments`}
|
||||
subscription={{ value: true }}
|
||||
>
|
||||
{({ input: { value } }) => (
|
||||
<>
|
||||
<Field
|
||||
name={`${channel}.triggers.allComments`}
|
||||
type="checkbox"
|
||||
parse={parseBool}
|
||||
>
|
||||
{({ input }) => (
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Field
|
||||
name={`${channel}.enabled`}
|
||||
type="checkbox"
|
||||
parse={parseBool}
|
||||
>
|
||||
{({ input: enabledInput }) => (
|
||||
<Localized id="configure-auth-configBoxEnabled">
|
||||
<CheckBox
|
||||
id={`configure-slack-channel-triggers-allComments-${input.name}`}
|
||||
disabled={disabled || disabledInside}
|
||||
className={styles.trigger}
|
||||
{...input}
|
||||
id={`${channel}.enabled`}
|
||||
disabled={disabled}
|
||||
className={styles.enabledCheckbox}
|
||||
{...enabledInput}
|
||||
>
|
||||
<Localized id="configure-slack-channel-triggers-allComments">
|
||||
All Comments
|
||||
</Localized>
|
||||
Enabled
|
||||
</CheckBox>
|
||||
)}
|
||||
</Field>
|
||||
<Field
|
||||
name={`${channel}.triggers.reportedComments`}
|
||||
type="checkbox"
|
||||
parse={parseBool}
|
||||
>
|
||||
{({ input }) => (
|
||||
<CheckBox
|
||||
id={`configure-slack-channel-triggers-reportedComments-${input.name}`}
|
||||
disabled={disabled || value || disabledInside}
|
||||
className={styles.trigger}
|
||||
{...input}
|
||||
>
|
||||
<Localized id="configure-slack-channel-triggers-reportedComments">
|
||||
Reported Comments
|
||||
</Localized>
|
||||
</CheckBox>
|
||||
)}
|
||||
</Field>
|
||||
<Field
|
||||
name={`${channel}.triggers.pendingComments`}
|
||||
type="checkbox"
|
||||
parse={parseBool}
|
||||
>
|
||||
{({ input }) => (
|
||||
<CheckBox
|
||||
id={`configure-slack-channel-triggers-pendingComments-${input.name}`}
|
||||
disabled={disabled || value || disabledInside}
|
||||
className={styles.trigger}
|
||||
{...input}
|
||||
>
|
||||
<Localized id="configure-slack-channel-triggers-pendingComments">
|
||||
Pending Comments
|
||||
</Localized>
|
||||
</CheckBox>
|
||||
)}
|
||||
</Field>
|
||||
<Field
|
||||
name={`${channel}.triggers.featuredComments`}
|
||||
type="checkbox"
|
||||
parse={parseBool}
|
||||
>
|
||||
{({ input }) => (
|
||||
<CheckBox
|
||||
id={`configure-slack-channel-triggers-featuredComments-${input.name}`}
|
||||
disabled={disabled || value || disabledInside}
|
||||
className={styles.trigger}
|
||||
{...input}
|
||||
>
|
||||
<Localized id="configure-slack-channel-triggers-featuredComments">
|
||||
Featured Comments
|
||||
</Localized>
|
||||
</CheckBox>
|
||||
)}
|
||||
</Field>
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
</>
|
||||
)}
|
||||
</ConfigBoxWithToggleField>
|
||||
</Localized>
|
||||
)}
|
||||
</Field>
|
||||
</div>
|
||||
</Flex>
|
||||
</Subheader>
|
||||
)}
|
||||
</Field>
|
||||
<Field name={`${channel}.enabled`} subscription={{ value: true }}>
|
||||
{({ input: { value: channelEnabled } }) => (
|
||||
<Box className={styles.content}>
|
||||
<FormField>
|
||||
<Field name={`${channel}.name`}>
|
||||
{({ input }) => (
|
||||
<>
|
||||
<Localized id="configure-slack-channel-name-label">
|
||||
<Label>Name</Label>
|
||||
</Localized>
|
||||
<Localized id="configure-slack-channel-name-description">
|
||||
<FormFieldDescription className={styles.description}>
|
||||
This is only for your information, to easily identify
|
||||
each Slack connection. Slack does not tell us the name
|
||||
of the channel/s you're connecting to Coral.
|
||||
</FormFieldDescription>
|
||||
</Localized>
|
||||
<TextField
|
||||
id={`configure-slack-channel-name-${input.name}`}
|
||||
disabled={disabled || !channelEnabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
className={styles.textField}
|
||||
{...input}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<Field name={`${channel}.hookURL`}>
|
||||
{({ input }) => (
|
||||
<>
|
||||
<Localized id="configure-slack-channel-hookURL-label">
|
||||
<Label>Webhook URL</Label>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-slack-channel-hookURL-description"
|
||||
externalLink={
|
||||
<ExternalLink href="https://docs.coralproject.net/coral/v5/integrating/slack/#i-need-to-find-the-webhook-url-again-where-is-it" />
|
||||
}
|
||||
>
|
||||
<FormFieldDescription className={styles.description}>
|
||||
Slack provides a channel-specific URL to activate
|
||||
webhook connections. To find the URL for one of your
|
||||
Slack channels, follow the instructions here.
|
||||
</FormFieldDescription>
|
||||
</Localized>
|
||||
<TextField
|
||||
id={`configure-slack-channel-hookURL-${input.name}`}
|
||||
disabled={disabled || !channelEnabled}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
fullWidth
|
||||
className={styles.textField}
|
||||
{...input}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<FormField>
|
||||
<div className={styles.notificationsLabel}>
|
||||
<Localized id="configure-slack-channel-triggers-label">
|
||||
<Label>Receive notifications in this Slack channel for</Label>
|
||||
</Localized>
|
||||
</div>
|
||||
<Field
|
||||
name={`${channel}.triggers.allComments`}
|
||||
subscription={{ value: true }}
|
||||
>
|
||||
{({ input: { value: allCommentsValue } }) => (
|
||||
<div className={styles.notificationToggles}>
|
||||
<Field
|
||||
name={`${channel}.triggers.allComments`}
|
||||
type="checkbox"
|
||||
parse={parseBool}
|
||||
>
|
||||
{({ input }) => (
|
||||
<CheckBox
|
||||
id={`configure-slack-channel-triggers-allComments-${input.name}`}
|
||||
disabled={disabled || !channelEnabled}
|
||||
className={styles.trigger}
|
||||
{...input}
|
||||
>
|
||||
<Localized id="configure-slack-channel-triggers-allComments">
|
||||
All Comments
|
||||
</Localized>
|
||||
</CheckBox>
|
||||
)}
|
||||
</Field>
|
||||
<Field
|
||||
name={`${channel}.triggers.reportedComments`}
|
||||
type="checkbox"
|
||||
parse={parseBool}
|
||||
>
|
||||
{({ input }) => (
|
||||
<CheckBox
|
||||
id={`configure-slack-channel-triggers-reportedComments-${input.name}`}
|
||||
disabled={
|
||||
disabled || allCommentsValue || !channelEnabled
|
||||
}
|
||||
className={styles.trigger}
|
||||
{...input}
|
||||
>
|
||||
<Localized id="configure-slack-channel-triggers-reportedComments">
|
||||
Reported Comments
|
||||
</Localized>
|
||||
</CheckBox>
|
||||
)}
|
||||
</Field>
|
||||
<Field
|
||||
name={`${channel}.triggers.pendingComments`}
|
||||
type="checkbox"
|
||||
parse={parseBool}
|
||||
>
|
||||
{({ input }) => (
|
||||
<CheckBox
|
||||
id={`configure-slack-channel-triggers-pendingComments-${input.name}`}
|
||||
disabled={
|
||||
disabled || allCommentsValue || !channelEnabled
|
||||
}
|
||||
className={styles.trigger}
|
||||
{...input}
|
||||
>
|
||||
<Localized id="configure-slack-channel-triggers-pendingComments">
|
||||
Pending Comments
|
||||
</Localized>
|
||||
</CheckBox>
|
||||
)}
|
||||
</Field>
|
||||
<Field
|
||||
name={`${channel}.triggers.featuredComments`}
|
||||
type="checkbox"
|
||||
parse={parseBool}
|
||||
>
|
||||
{({ input }) => (
|
||||
<CheckBox
|
||||
id={`configure-slack-channel-triggers-featuredComments-${input.name}`}
|
||||
disabled={
|
||||
disabled || allCommentsValue || !channelEnabled
|
||||
}
|
||||
className={styles.trigger}
|
||||
{...input}
|
||||
>
|
||||
<Localized id="configure-slack-channel-triggers-featuredComments">
|
||||
Featured Comments
|
||||
</Localized>
|
||||
</CheckBox>
|
||||
)}
|
||||
</Field>
|
||||
</div>
|
||||
)}
|
||||
</Field>
|
||||
</FormField>
|
||||
<div>
|
||||
<Button
|
||||
size="medium"
|
||||
variant="filled"
|
||||
color="alert"
|
||||
onClick={onRemove}
|
||||
className={cn(styles.removeButton, styles.button)}
|
||||
>
|
||||
<Localized id="configure-slack-channel-remove">
|
||||
Remove
|
||||
</Localized>
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
)}
|
||||
</Field>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
.icon {
|
||||
padding-right: var(--spacing-2);
|
||||
}
|
||||
|
||||
.button {
|
||||
padding-top: var(--v2-spacing-1);
|
||||
padding-bottom: var(--v2-spacing-1);
|
||||
}
|
||||
|
||||
@@ -112,13 +112,13 @@ const SlackConfigContainer: FunctionComponent<Props> = ({ form, settings }) => {
|
||||
<Button
|
||||
size="medium"
|
||||
variant="filled"
|
||||
color="emphasis"
|
||||
onClick={onAddChannel}
|
||||
className={styles.button}
|
||||
>
|
||||
<ButtonIcon size="md" className={styles.icon}>
|
||||
add
|
||||
</ButtonIcon>
|
||||
<Localized id="configure-slack-addChannel">Add</Localized>
|
||||
<Localized id="configure-slack-addChannel">Add Channel</Localized>
|
||||
</Button>
|
||||
<FieldArray name="slack.channels">
|
||||
{({ fields }) =>
|
||||
|
||||
@@ -388,10 +388,11 @@ configure-slack-description =
|
||||
Automatically send comments from Coral moderation queues to Slack
|
||||
channels. You will need Slack admin access to set this up. For
|
||||
steps on how to create a Slack App see our <externalLink>documentation</externalLink>.
|
||||
configure-slack-addChannel = Add
|
||||
configure-slack-addChannel = Add Channel
|
||||
|
||||
configure-slack-channel-defaultName = New channel
|
||||
configure-slack-channel-enabled = Enabled
|
||||
configure-slack-channel-remove = Remove
|
||||
configure-slack-channel-remove = Remove Channel
|
||||
configure-slack-channel-name-label = Name
|
||||
configure-slack-channel-name-description =
|
||||
This is only for your information, to easily identify
|
||||
|
||||
Reference in New Issue
Block a user