Skip to content

Commit

Permalink
Merge pull request #4509 from coralproject/develop
Browse files Browse the repository at this point in the history
[8.7.2] Release develop into main
  • Loading branch information
kabeaty authored Jan 30, 2024
2 parents 48e89dd + aa6cebe commit ef750fe
Show file tree
Hide file tree
Showing 56 changed files with 1,441 additions and 89 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2020 Vox Media, Inc
Copyright 2024 Vox Media, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
4 changes: 2 additions & 2 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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.1",
"version": "8.7.2",
"author": "The Coral Project",
"homepage": "https://coralproject.net/",
"sideEffects": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import ModMessageAction, { ModMessageActionProps } from "./ModMessageAction";
import PremodAction, { PremodActionProps } from "./PremodAction";
import SiteBanAction from "./SiteBanAction";
import SuspensionAction, { SuspensionActionProps } from "./SuspensionAction";
import UserDeletionAction, {
UserDeletionActionProps,
} from "./UserDeletionAction";
import UsernameChangeAction, {
UsernameChangeActionProps,
} from "./UsernameChangeAction";
Expand All @@ -18,14 +21,16 @@ export interface HistoryActionProps {
| "site-ban"
| "premod"
| "warning"
| "modMessage";
| "modMessage"
| "deletion";
action:
| UsernameChangeActionProps
| SuspensionActionProps
| BanActionProps
| PremodActionProps
| WarningActionProps
| ModMessageActionProps;
| ModMessageActionProps
| UserDeletionActionProps;
}

const AccountHistoryAction: FunctionComponent<HistoryActionProps> = ({
Expand All @@ -49,6 +54,8 @@ const AccountHistoryAction: FunctionComponent<HistoryActionProps> = ({
return <WarningAction {...(action as WarningActionProps)} />;
case "modMessage":
return <ModMessageAction {...(action as ModMessageActionProps)} />;
case "deletion":
return <UserDeletionAction {...(action as UserDeletionActionProps)} />;
default:
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { graphql } from "react-relay";
import { Environment } from "relay-runtime";

import {
commitMutationPromiseNormalized,
createMutation,
MutationInput,
} from "coral-framework/lib/relay";

import { CancelScheduledAccountDeletionMutation as MutationTypes } from "coral-admin/__generated__/CancelScheduledAccountDeletionMutation.graphql";

let clientMutationId = 0;

const CancelScheduledAccountDeletionMutation = createMutation(
"cancelScheduleAccountDeletion",
async (environment: Environment, input: MutationInput<MutationTypes>) => {
const result = await commitMutationPromiseNormalized<MutationTypes>(
environment,
{
mutation: graphql`
mutation CancelScheduledAccountDeletionMutation(
$input: CancelScheduledAccountDeletionInput!
) {
cancelScheduledAccountDeletion(input: $input) {
user {
scheduledDeletionDate
status {
deletion {
history {
updateType
createdBy {
username
}
createdAt
}
}
}
}
clientMutationId
}
}
`,
variables: {
input: {
userID: input.userID,
clientMutationId: (clientMutationId++).toString(),
},
},
}
);
return result;
}
);

export default CancelScheduledAccountDeletionMutation;
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
.root {
width: 280px;
font-family: var(--font-family-primary);
max-width: 80vw;
text-align: left;
}

.title {
font-family: var(--font-family-primary);
font-weight: var(--font-weight-primary-semi-bold);
font-size: var(--font-size-3);
line-height: 1;

color: var(--palette-text-500);
}

.header {
font-family: var(--font-family-primary);
font-weight: var(--font-weight-primary-bold);
font-size: var(--font-size-2);
color: var(--palette-text-500);
margin-bottom: var(--spacing-1);
margin-top: var(--spacing-3);
}

.username {
font-size: var(--font-size-2);
}

.orderedList {
margin: 0;
padding-left: var(--spacing-4);

li {
font-family: var(--font-family-primary);
font-size: var(--font-size-2);
}
}

.callOut {
padding: var(--spacing-1);
font-weight: var(--font-weight-primary-semi-bold);
margin-top: var(--spacing-3);
font-size: var(--font-size-1);
}

.moreInfo {
font-size: var(--font-size-2);
margin-top: var(--spacing-2);
}

.icon {
display: inline-block;
margin-right: var(--spacing-1);
position: relative;
top: 2px;
}

.confirmationInput {
box-sizing: border-box;
font-family: var(--font-family-primary);
font-size: var(--font-size-2);
line-height: 2.25;
padding-left: var(--spacing-2);
width: 100%;
}

.description {
font-family: var(--font-family-primary);
font-weight: var(--font-weight-primary-regular);
font-size: var(--font-size-3);
line-height: 1;

color: var(--palette-text-500);
}

.actions {
padding-top: var(--spacing-3);
}

.link {
display: inline;
vertical-align: baseline;
white-space: break-spaces;
}

.container {
margin-top: var(--spacing-2);
}

.error {
color: var(--palette-error-500);
margin-top: var(--spacing-2);
font-weight: var(--font-weight-primary-semi-bold);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { Localized } from "@fluent/react/compat";
import React, {
FunctionComponent,
useCallback,
useMemo,
useState,
} from "react";

import { useMutation } from "coral-framework/lib/relay";
import {
AlertCircleIcon,
AlertTriangleIcon,
SvgIcon,
} from "coral-ui/components/icons";
import { Box, Button, CallOut, Flex } from "coral-ui/components/v2";

import ScheduleAccountDeletionMutation from "./ScheduleAccountDeletionMutation";

import styles from "./DeleteAccountPopover.css";

interface Props {
onDismiss: () => void;
userID: string;
username: string | null;
}

const DeleteAccountPopover: FunctionComponent<Props> = ({
onDismiss,
userID,
username,
}) => {
const scheduleAccountDeletion = useMutation(ScheduleAccountDeletionMutation);
const [requestDeletionError, setRequestDeletionError] = useState<
string | null
>(null);

const onRequestDeletion = useCallback(async () => {
try {
await scheduleAccountDeletion({ userID });
} catch (e) {
if (e.message) {
setRequestDeletionError(e.message as string);
}
}
}, [userID, scheduleAccountDeletion, setRequestDeletionError]);

const deleteAccountConfirmationText = "delete";
const [
deleteAccountConfirmationTextInput,
setDeleteAccountConfirmationTextInput,
] = useState("");

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

const deleteAccountButtonDisabled = useMemo(() => {
return !(
deleteAccountConfirmationTextInput.toLowerCase() ===
deleteAccountConfirmationText
);
}, [deleteAccountConfirmationText, deleteAccountConfirmationTextInput]);

return (
<Box className={styles.root} p={3}>
<>
<Localized id="moderate-user-drawer-deleteAccount-popover-title">
<div className={styles.title}>Delete account</div>
</Localized>
<Localized id="moderate-user-drawer-deleteAccount-popover-username">
<div className={styles.header}>Username</div>
</Localized>
<div className={styles.username}>{username ?? ""}</div>
<Localized id="moderate-user-drawer-deleteAccount-popover-header-description">
<div className={styles.header}>Delete account will</div>
</Localized>
<div>
<ol className={styles.orderedList}>
<Localized id="moderate-user-drawer-deleteAccount-popover-description-list-removeComments">
<li>
Remove all comments written by this user from the database.
</li>
</Localized>
<Localized id="moderate-user-drawer-deleteAccount-popover-description-list-deleteAll">
<li>
Delete all record of this account. The user could then create a
new account using the same email address. If you want to Ban
this user instead and retain their history, press "CANCEL" and
use the Status dropdown below the username.
</li>
</Localized>
</ol>
</div>
<CallOut className={styles.callOut} color="error" fullWidth borderless>
<SvgIcon size="xs" className={styles.icon} Icon={AlertTriangleIcon} />
<Localized id="moderate-user-drawer-deleteAccount-popover-callout">
<span>This removes all records of this user</span>
</Localized>
</CallOut>
<Localized id="moderate-user-drawer-deleteAccount-popover-timeframe">
<div className={styles.moreInfo}>
This will go into effect in 24 hours.
</div>
</Localized>
<Localized
id="moderate-user-drawer-deleteAccount-popover-confirm"
vars={{ text: deleteAccountConfirmationText }}
>
<div className={styles.header}>
Type in "{deleteAccountConfirmationText}" to confirm
</div>
</Localized>
<input
className={styles.confirmationInput}
type="text"
placeholder=""
onChange={onDeleteAccountConfirmationTextInputChange}
/>
{requestDeletionError && (
<div className={styles.error}>
<SvgIcon Icon={AlertCircleIcon} className={styles.icon} />
{requestDeletionError}
</div>
)}
<Flex
justifyContent="flex-end"
itemGutter="half"
className={styles.actions}
>
<Localized id="moderate-user-drawer-deleteAccount-popover-cancelButton">
<Button
variant="outlined"
size="regular"
color="mono"
onClick={onDismiss}
>
Cancel
</Button>
</Localized>
<Localized id="moderate-user-drawer-deleteAccount-popover-deleteButton">
<Button
disabled={deleteAccountButtonDisabled}
variant="regular"
size="regular"
color="alert"
onClick={onRequestDeletion}
>
Delete
</Button>
</Localized>
</Flex>
</>
</Box>
);
};

export default DeleteAccountPopover;
Loading

0 comments on commit ef750fe

Please sign in to comment.