Skip to content

Commit

Permalink
Merge branch 'develop' into chore/CORL-3020-pnpm
Browse files Browse the repository at this point in the history
  • Loading branch information
kabeaty committed Mar 15, 2024
2 parents c5bcfc5 + ec20339 commit 94e259e
Show file tree
Hide file tree
Showing 137 changed files with 4,364 additions and 694 deletions.
18 changes: 18 additions & 0 deletions INDEXES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ The goal of this document is to date-mark the indexes you add to support the cha

If you are releasing, you can use this readme to check all the indexes prior to the release you are deploying and have a good idea of what indexes you might need to deploy to Mongo along with your release of a new Coral Docker image to kubernetes.

## 2024-03-07

```
db.notifications.createIndex({ tenantID: 1, replyID: 1 });
```

- This index speeds up the retrieval of notifications by replyID, which is used to determine whether to decrement/increment notification counts if a comment is rejected/approved in moderation.

## 2024-02-02

```
db.notifications.createIndex({ createdAt: 1 }, { partialFilterExpression: { isDSA: { $eq: null } }, expireAfterSeconds: 30 * 24 * 60 * 60 });
```

- This creates a TTL on non-DSA marked notifications that will delete them after 30 days
- The `partialFilterExpression` finds any notifications that aren't marked as `isDSA` so we don't delete important DSA notifications
- You can modify the expiry time by changing `expireAfterSeconds`

## 2023-11-24

```
Expand Down
27 changes: 25 additions & 2 deletions client/CLIENT_EVENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,16 @@ createComment.error
- <a href="#signedIn">signedIn</a>
- <a href="#unfeatureComment">unfeatureComment</a>
- <a href="#unmarkAll">unmarkAll</a>
- <a href="#updateNotificationSettings">updateNotificationSettings</a>
- <a href="#updateEmailNotificationSettings">updateEmailNotificationSettings</a>
- <a href="#updateInPageNotificationSettings">updateInPageNotificationSettings</a>
- <a href="#updateStorySettings">updateStorySettings</a>
- <a href="#updateUserMediaSettings">updateUserMediaSettings</a>
- <a href="#viewConversation">viewConversation</a>
- <a href="#viewFullDiscussion">viewFullDiscussion</a>
- <a href="#viewNewComments">viewNewComments</a>
- <a href="#viewNewCommentsNetwork">viewNewCommentsNetwork</a>
- <a href="#viewNewRepliesNetwork">viewNewRepliesNetwork</a>
- <a href="#viewNotificationsFeed">viewNotificationsFeed</a>

### Events
- <a id="addACommentButton">**addACommentButton**</a>: This event is emitted when the viewer clicks the add a comment button in alternate oldest view.
Expand Down Expand Up @@ -614,7 +616,7 @@ createComment.error
source: "keyboard" | "mobileToolbar";
}
```
- <a id="updateNotificationSettings">**updateNotificationSettings.success**, **updateNotificationSettings.error**</a>: This event is emitted when the viewer updates its notification settings.
- <a id="updateEmailNotificationSettings">**updateEmailNotificationSettings.success**, **updateEmailNotificationSettings.error**</a>: This event is emitted when the viewer updates their email notification settings.
```ts
{
onReply?: boolean | null | undefined;
Expand All @@ -629,6 +631,21 @@ createComment.error
};
}
```
- <a id="updateInPageNotificationSettings">**updateInPageNotificationSettings.success**, **updateInPageNotificationSettings.error**</a>: This event is emitted when the viewer updates their in-page notification settings.
```ts
{
onReply?: boolean | null | undefined;
onFeatured?: boolean | null | undefined;
onStaffReplies?: boolean | null | undefined;
onModeration?: boolean | null | undefined;
enabled?: boolean | null | undefined;
success: {};
error: {
message: string;
code?: string | undefined;
};
}
```
- <a id="updateStorySettings">**updateStorySettings.success**, **updateStorySettings.error**</a>: This event is emitted when the viewer updates the story settings.
```ts
{
Expand Down Expand Up @@ -713,4 +730,10 @@ createComment.error
};
}
```
- <a id="viewNotificationsFeed">**viewNotificationsFeed**</a>: This event is emitted when the viewer clicks to view their notifications feed.
```ts
{
userID?: string | undefined;
}
```
<!-- END docs:events -->
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@coralproject/talk",
"version": "8.7.3",
"version": "8.8.0",
"author": "The Coral Project",
"homepage": "https://coralproject.net/",
"sideEffects": [
Expand Down
19 changes: 19 additions & 0 deletions client/src/core/client/admin/components/BanModal.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,22 @@ $ban-modal-text: var(--palette-text-500);
.rejectExistingReason {
background-color: var(--palette-grey-100);
}

.domainBanCallOut {
padding: var(--spacing-1);
margin-bottom: var(--spacing-2);
}

.alertIcon {
margin-right: var(--spacing-1);
}

.domainBanConfirmationInput {
font-family: var(--font-family-primary);
line-height: 2.25;
padding-left: var(--spacing-2);
}

.domainBanConfirmationLabel {
margin-bottom: var(--spacing-1);
}
27 changes: 18 additions & 9 deletions client/src/core/client/admin/components/BanModal.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
replaceHistoryLocation,
} from "coral-framework/testHelpers";

import { PROTECTED_EMAIL_DOMAINS } from "coral-common/common/lib/constants";
import { pureMerge } from "coral-common/common/lib/utils";
import {
GQLNEW_USER_MODERATION,
Expand Down Expand Up @@ -136,11 +135,21 @@ it("creates domain ban for unmoderated domain while updating user ban status", a
const modal = getBanModal(container, user);

const banDomainButton = within(modal).getByLabelText(
`Ban all new commenter accounts from test.com`
`Ban all commenter accounts from test.com`
);
userEvent.click(banDomainButton);
screen.debug(banDomainButton);
userEvent.click(within(modal).getByRole("button", { name: "Ban" }));

const banSaveButton = within(modal).getByRole("button", { name: "Ban" });

expect(banSaveButton).toBeDisabled();

const domainBanConfirmation = within(modal).getByTestId(
"domainBanConfirmation"
);
userEvent.type(domainBanConfirmation, "ban");

expect(banSaveButton).toBeEnabled();
userEvent.click(banSaveButton);

await waitFor(() =>
expect(resolvers.Mutation!.createEmailDomain!.called).toBeTruthy()
Expand Down Expand Up @@ -172,7 +181,7 @@ test.each(gteOrgMods)(
const modal = getBanModal(container, commenterUser);

const banDomainButton = within(modal).getByLabelText(
`Ban all new commenter accounts from test.com`
`Ban all commenter accounts from test.com`
);

expect(banDomainButton).toBeInTheDocument();
Expand All @@ -198,7 +207,7 @@ test.each(siteMods)(
const modal = getBanModal(container, commenterUser);

const banDomainButton = within(modal).queryByText(
`Ban all new commenter accounts from test.com`
`Ban all commenter accounts from test.com`
);

expect(banDomainButton).toBeNull();
Expand Down Expand Up @@ -233,14 +242,14 @@ it("does not display ban domain option for moderated domain", async () => {
const modal = getBanModal(container, user);

const banDomainButton = within(modal).queryByText(
`Ban all new commenter accounts from test.com`
`Ban all commenter accounts from test.com`
);

expect(banDomainButton).not.toBeInTheDocument();
});

it("does not display ban domain option for protected domain", async () => {
const protectedDomain = PROTECTED_EMAIL_DOMAINS.values().next().value;
const protectedDomain = "gmail.com";
const protectedEmailResolver = createResolversStub<GQLResolver>({
Query: {
users: () => ({
Expand Down Expand Up @@ -279,7 +288,7 @@ it("does not display ban domain option for protected domain", async () => {
const modal = getBanModal(container, user);

const banDomainButton = within(modal).queryByText(
`Ban all new commenter accounts from test.com`
`Ban all commenter accounts from test.com`
);

expect(banDomainButton).not.toBeInTheDocument();
Expand Down
64 changes: 60 additions & 4 deletions client/src/core/client/admin/components/BanModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { Form } from "react-final-form";
import { graphql } from "react-relay";

import NotAvailable from "coral-admin/components/NotAvailable";
import { PROTECTED_EMAIL_DOMAINS } from "coral-common/common/lib/constants";
import { extractDomain } from "coral-common/common/lib/email";
import {
isOrgModerator,
Expand All @@ -21,9 +20,11 @@ import { useGetMessage } from "coral-framework/lib/i18n";
import { useLocal, useMutation } from "coral-framework/lib/relay";
import { GQLREJECTION_REASON_CODE, GQLUSER_ROLE } from "coral-framework/schema";
import {
AlertTriangleIcon,
ArrowsDownIcon,
ArrowsUpIcon,
ButtonSvgIcon,
SvgIcon,
} from "coral-ui/components/icons";
import {
Button,
Expand Down Expand Up @@ -75,6 +76,7 @@ interface Props {
emailDomainModeration: UserStatusChangeContainer_settings["emailDomainModeration"];
userRole: string;
isMultisite: boolean;
protectedEmailDomains: ReadonlyArray<string>;
}

interface BanButtonProps {
Expand Down Expand Up @@ -139,6 +141,7 @@ const BanModal: FunctionComponent<Props> = ({
userBanStatus,
userRole,
isMultisite,
protectedEmailDomains,
}) => {
const createDomainBan = useMutation(BanDomainMutation);
const banUser = useMutation(BanUserMutation);
Expand Down Expand Up @@ -231,7 +234,7 @@ const BanModal: FunctionComponent<Props> = ({
updateType !== UpdateType.NO_SITES &&
emailDomain &&
!domainIsConfigured &&
!PROTECTED_EMAIL_DOMAINS.has(emailDomain);
!protectedEmailDomains.includes(emailDomain);

useEffect(() => {
if (viewerIsSingleSiteMod) {
Expand Down Expand Up @@ -328,6 +331,17 @@ const BanModal: FunctionComponent<Props> = ({
rejectExistingCommentsMessage,
} = getTextForUpdateType(updateType);

const domainBanConfirmationText = "ban";
const [domainBanConfirmationTextInput, setDomainBanConfirmationTextInput] =
useState("");

const onDomainBanConfirmationTextInputChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
setDomainBanConfirmationTextInput(e.target.value);
},
[setDomainBanConfirmationTextInput]
);

const pendingSiteBanUpdates = banSiteIDs.length + unbanSiteIDs.length > 0;
const requiresSiteBanUpdates =
updateType === UpdateType.SPECIFIC_SITES ||
Expand All @@ -340,7 +354,13 @@ const BanModal: FunctionComponent<Props> = ({

const disableForm =
(requiresSiteBanUpdates && !pendingSiteBanUpdates) ||
requiresRejectionReasonForDSA;
requiresRejectionReasonForDSA ||
(!!canBanDomain &&
banDomain &&
!(
domainBanConfirmationTextInput.toLowerCase() ===
domainBanConfirmationText
));

return (
<ChangeStatusModal
Expand Down Expand Up @@ -519,13 +539,49 @@ const BanModal: FunctionComponent<Props> = ({
setBanDomain(target.checked);
}}
>
Ban all new commenter accounts from{" "}
Ban all commenter accounts from{" "}
<strong>{emailDomain}</strong>
</CheckBox>
</Localized>
</HorizontalGutter>
</Flex>
)}
{canBanDomain && banDomain && (
<Flex direction="column">
<CallOut
className={styles.domainBanCallOut}
color="warning"
>
<SvgIcon
size="xs"
className={styles.alertIcon}
Icon={AlertTriangleIcon}
/>
<Localized id="community-banModal-banEmailDomain-callOut">
<span>
This will prevent any commenter from using this
email domain.
</span>
</Localized>
</CallOut>

<Localized
id="community-banModal-banEmailDomain-confirmationText"
vars={{ text: domainBanConfirmationText }}
>
<div className={styles.domainBanConfirmationLabel}>
Type in "{domainBanConfirmationText}" to confirm
</div>
</Localized>
<input
data-testid="domainBanConfirmation"
className={styles.domainBanConfirmationInput}
type="text"
placeholder=""
onChange={onDomainBanConfirmationTextInputChange}
/>
</Flex>
)}
{/* customize message button*/}
{updateType !== UpdateType.NO_SITES && (
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ const ModerateCardContainer: FunctionComponent<Props> = ({
userEmail={comment.author.email}
userRole={comment.author.role}
isMultisite={settings.multisite}
protectedEmailDomains={settings.protectedEmailDomains}
/>
)}
</>
Expand Down Expand Up @@ -530,6 +531,7 @@ const enhanced = withFragmentContainer<Props>({
`,
settings: graphql`
fragment ModerateCardContainer_settings on Settings {
protectedEmailDomains
locale
wordList {
banned
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ const UserStatusChangeContainer: FunctionComponent<Props> = ({
emailDomainModeration={settings.emailDomainModeration}
userBanStatus={user.status.ban}
userRole={user.role}
protectedEmailDomains={settings.protectedEmailDomains}
/>
)}
</>
Expand Down Expand Up @@ -286,6 +287,7 @@ const enhanced = withFragmentContainer<Props>({
newUserModeration
}
multisite
protectedEmailDomains
}
`,
viewer: graphql`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import FeaturedByConfig from "./FeaturedByConfig";
import FlairBadgeConfigContainer from "./FlairBadgeConfigContainer";
import FlattenRepliesConfig from "./FlattenRepliesConfig";
import GuidelinesConfig from "./GuidelinesConfig";
import InPageNotificationsConfig from "./InPageNotificationsConfig";
import LocaleConfig from "./LocaleConfig";
import MediaLinksConfig from "./MediaLinksConfig";
import MemberBioConfig from "./MemberBioConfig";
Expand Down Expand Up @@ -50,6 +51,7 @@ const GeneralConfigContainer: React.FunctionComponent<Props> = ({
>
<LocaleConfig disabled={submitting} />
<DSAConfigContainer disabled={submitting} settings={settings} />
<InPageNotificationsConfig disabled={submitting} />
<FlattenRepliesConfig disabled={submitting} />
<SitewideCommentingConfig disabled={submitting} />
<AnnouncementConfigContainer disabled={submitting} settings={settings} />
Expand All @@ -75,6 +77,7 @@ const enhanced = withFragmentContainer<Props>({
fragment GeneralConfigContainer_settings on Settings {
...AnnouncementConfigContainer_settings
...FlattenRepliesConfig_formValues @relay(mask: false)
...InPageNotificationsConfig_formValues @relay(mask: false)
...LocaleConfig_formValues @relay(mask: false)
...DSAConfigContainer_formValues @relay(mask: false)
...DSAConfigContainer_settings
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.disabledLabel {
color: var(--palette-grey-400);
}
Loading

0 comments on commit 94e259e

Please sign in to comment.