mirror of
https://github.com/wassname/talk.git
synced 2026-08-20 12:50:41 +08:00
[CORL-404] Recent Comment History (#2354)
* feat: initial support for auto pre-moderation * chore: refactor collection access * fix: linting * fix: rebasing issue * fix: exported helpers * feat: added extensions, lintd * fix: rebase fix * feat: renamed automaticPreModeration to recentCommentHistory * feat: initial implementation of admin config * feat: support recent history markers * feat: rename visible to published * feat: reworked history drawer * chore: extracted tooltip * feat: implemented user drawer * fix: fixed translation key * fix: resolved issue with NaN
This commit is contained in:
@@ -2,7 +2,13 @@ import { Localized } from "fluent-react/compat";
|
||||
import React, { ChangeEvent, Component } from "react";
|
||||
|
||||
import { UNIT } from "coral-framework/lib/i18n";
|
||||
import { Flex, Option, SelectField, TextField } from "coral-ui/components";
|
||||
import {
|
||||
Flex,
|
||||
Option,
|
||||
SelectField,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "coral-ui/components";
|
||||
|
||||
import styles from "./DurationField.css";
|
||||
|
||||
@@ -12,58 +18,12 @@ import styles from "./DurationField.css";
|
||||
*/
|
||||
export const DURATION_UNIT = UNIT;
|
||||
|
||||
type UnitElementCallback = (
|
||||
currentValue: UNIT,
|
||||
unitValue: string
|
||||
) => React.ReactElement<any>;
|
||||
|
||||
// This is used to render the Option elements to inlcude in the select field.
|
||||
const unitElementMap: Record<UNIT, UnitElementCallback> = {
|
||||
[UNIT.SECONDS]: (currentValue, unitValue) => (
|
||||
<Localized
|
||||
id="framework-durationField-seconds"
|
||||
$value={currentValue}
|
||||
key={unitValue}
|
||||
>
|
||||
<Option value={unitValue}>Seconds</Option>
|
||||
</Localized>
|
||||
),
|
||||
[UNIT.MINUTES]: (currentValue, unitValue) => (
|
||||
<Localized
|
||||
id="framework-durationField-minutes"
|
||||
$value={currentValue}
|
||||
key={unitValue}
|
||||
>
|
||||
<Option value={unitValue}>Minutes</Option>
|
||||
</Localized>
|
||||
),
|
||||
[UNIT.HOURS]: (currentValue, unitValue) => (
|
||||
<Localized
|
||||
id="framework-durationField-hours"
|
||||
$value={currentValue}
|
||||
key={unitValue}
|
||||
>
|
||||
<Option value={unitValue}>Hours</Option>
|
||||
</Localized>
|
||||
),
|
||||
[UNIT.DAYS]: (currentValue, unitValue) => (
|
||||
<Localized
|
||||
id="framework-durationField-days"
|
||||
$value={currentValue}
|
||||
key={unitValue}
|
||||
>
|
||||
<Option value={unitValue}>Days</Option>
|
||||
</Localized>
|
||||
),
|
||||
[UNIT.WEEKS]: (currentValue, unitValue) => (
|
||||
<Localized
|
||||
id="framework-durationField-weeks"
|
||||
$value={currentValue}
|
||||
key={unitValue}
|
||||
>
|
||||
<Option value={unitValue}>Weeks</Option>
|
||||
</Localized>
|
||||
),
|
||||
const DURATION_UNIT_MAP = {
|
||||
[DURATION_UNIT.SECONDS]: "second",
|
||||
[DURATION_UNIT.MINUTES]: "minute",
|
||||
[DURATION_UNIT.HOURS]: "hour",
|
||||
[DURATION_UNIT.DAYS]: "day",
|
||||
[DURATION_UNIT.WEEKS]: "week",
|
||||
};
|
||||
|
||||
interface Props {
|
||||
@@ -86,7 +46,7 @@ interface State {
|
||||
* Element callbacks to generate the rendered
|
||||
* Option element for the select field
|
||||
*/
|
||||
elementCallbacks: ReadonlyArray<UnitElementCallback>;
|
||||
elementCallbacks: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +77,7 @@ function valueToState(value: string, units: ReadonlyArray<UNIT>, unit?: UNIT) {
|
||||
unit,
|
||||
value,
|
||||
units,
|
||||
elementCallbacks: units.map(k => unitElementMap[k]),
|
||||
elementCallbacks: units.map(k => DURATION_UNIT_MAP[k]),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -177,6 +137,25 @@ class DurationField extends Component<Props, State> {
|
||||
|
||||
public render() {
|
||||
const { disabled, name } = this.props;
|
||||
|
||||
if (!this.state.elementCallbacks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let adornment: React.ReactNode = null;
|
||||
if (this.state.elementCallbacks.length === 1) {
|
||||
const unit = this.state.elementCallbacks[0];
|
||||
adornment = (
|
||||
<Localized
|
||||
id="framework-durationField-unit"
|
||||
$unit={unit}
|
||||
$value={parseInt(this.state.value, 10)}
|
||||
>
|
||||
<Typography variant="bodyCopy">{unit}</Typography>
|
||||
</Localized>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex itemGutter>
|
||||
<TextField
|
||||
@@ -189,23 +168,36 @@ class DurationField extends Component<Props, State> {
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck={false}
|
||||
adornment={adornment}
|
||||
textAlignCenter
|
||||
aria-label="value"
|
||||
/>
|
||||
<SelectField
|
||||
name={`${name}-unit`}
|
||||
onChange={this.handleUnitChange}
|
||||
disabled={disabled}
|
||||
aria-label="unit"
|
||||
classes={{
|
||||
select: styles.unit,
|
||||
}}
|
||||
value={(this.state.unit || this.state.units[0]).toString()}
|
||||
>
|
||||
{this.state.elementCallbacks!.map((cb, i) =>
|
||||
cb(parseInt(this.state.value, 10), this.state.units[i].toString())
|
||||
)}
|
||||
</SelectField>
|
||||
{!adornment && (
|
||||
<SelectField
|
||||
name={`${name}-unit`}
|
||||
onChange={this.handleUnitChange}
|
||||
disabled={disabled}
|
||||
aria-label="unit"
|
||||
classes={{
|
||||
select: styles.unit,
|
||||
}}
|
||||
value={(this.state.unit || this.state.units[0]).toString()}
|
||||
>
|
||||
{this.state.elementCallbacks.map((unit, i) => {
|
||||
const value = this.state.units[i];
|
||||
return (
|
||||
<Localized
|
||||
id="framework-durationField-unit"
|
||||
$unit={unit}
|
||||
$value={parseInt(this.state.value, 10)}
|
||||
key={i}
|
||||
>
|
||||
<Option value={value.toString()}>{unit}</Option>
|
||||
</Localized>
|
||||
);
|
||||
})}
|
||||
</SelectField>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ exports[`accepts invalid input 1`] = `
|
||||
itemGutter={true}
|
||||
>
|
||||
<withPropsOnChange(TextField)
|
||||
adornment={null}
|
||||
aria-label="value"
|
||||
autoCapitalize="off"
|
||||
autoComplete="off"
|
||||
@@ -30,33 +31,36 @@ exports[`accepts invalid input 1`] = `
|
||||
value="1"
|
||||
>
|
||||
<Localized
|
||||
$unit="second"
|
||||
$value={NaN}
|
||||
id="framework-durationField-seconds"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="1"
|
||||
>
|
||||
Seconds
|
||||
second
|
||||
</Option>
|
||||
</Localized>
|
||||
<Localized
|
||||
$unit="minute"
|
||||
$value={NaN}
|
||||
id="framework-durationField-minutes"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="60"
|
||||
>
|
||||
Minutes
|
||||
minute
|
||||
</Option>
|
||||
</Localized>
|
||||
<Localized
|
||||
$unit="hour"
|
||||
$value={NaN}
|
||||
id="framework-durationField-hours"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="3600"
|
||||
>
|
||||
Hours
|
||||
hour
|
||||
</Option>
|
||||
</Localized>
|
||||
</withPropsOnChange(WithKeyboardFocus)>
|
||||
@@ -68,6 +72,7 @@ exports[`renders correctly with default units 1`] = `
|
||||
itemGutter={true}
|
||||
>
|
||||
<withPropsOnChange(TextField)
|
||||
adornment={null}
|
||||
aria-label="value"
|
||||
autoCapitalize="off"
|
||||
autoComplete="off"
|
||||
@@ -93,33 +98,36 @@ exports[`renders correctly with default units 1`] = `
|
||||
value="3600"
|
||||
>
|
||||
<Localized
|
||||
$unit="hour"
|
||||
$value={NaN}
|
||||
id="framework-durationField-hours"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="3600"
|
||||
>
|
||||
Hours
|
||||
hour
|
||||
</Option>
|
||||
</Localized>
|
||||
<Localized
|
||||
$unit="day"
|
||||
$value={NaN}
|
||||
id="framework-durationField-days"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="86400"
|
||||
>
|
||||
Days
|
||||
day
|
||||
</Option>
|
||||
</Localized>
|
||||
<Localized
|
||||
$unit="week"
|
||||
$value={NaN}
|
||||
id="framework-durationField-weeks"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="604800"
|
||||
>
|
||||
Weeks
|
||||
week
|
||||
</Option>
|
||||
</Localized>
|
||||
</withPropsOnChange(WithKeyboardFocus)>
|
||||
@@ -131,6 +139,7 @@ exports[`renders correctly with specified units 1`] = `
|
||||
itemGutter={true}
|
||||
>
|
||||
<withPropsOnChange(TextField)
|
||||
adornment={null}
|
||||
aria-label="value"
|
||||
autoCapitalize="off"
|
||||
autoComplete="off"
|
||||
@@ -156,23 +165,25 @@ exports[`renders correctly with specified units 1`] = `
|
||||
value="1"
|
||||
>
|
||||
<Localized
|
||||
$unit="second"
|
||||
$value={NaN}
|
||||
id="framework-durationField-seconds"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="1"
|
||||
>
|
||||
Seconds
|
||||
second
|
||||
</Option>
|
||||
</Localized>
|
||||
<Localized
|
||||
$unit="hour"
|
||||
$value={NaN}
|
||||
id="framework-durationField-hours"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="3600"
|
||||
>
|
||||
Hours
|
||||
hour
|
||||
</Option>
|
||||
</Localized>
|
||||
</withPropsOnChange(WithKeyboardFocus)>
|
||||
@@ -184,6 +195,7 @@ exports[`use best matching unit 1`] = `
|
||||
itemGutter={true}
|
||||
>
|
||||
<withPropsOnChange(TextField)
|
||||
adornment={null}
|
||||
aria-label="value"
|
||||
autoCapitalize="off"
|
||||
autoComplete="off"
|
||||
@@ -209,33 +221,36 @@ exports[`use best matching unit 1`] = `
|
||||
value="3600"
|
||||
>
|
||||
<Localized
|
||||
$unit="second"
|
||||
$value={1}
|
||||
id="framework-durationField-seconds"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="1"
|
||||
>
|
||||
Seconds
|
||||
second
|
||||
</Option>
|
||||
</Localized>
|
||||
<Localized
|
||||
$unit="minute"
|
||||
$value={1}
|
||||
id="framework-durationField-minutes"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="60"
|
||||
>
|
||||
Minutes
|
||||
minute
|
||||
</Option>
|
||||
</Localized>
|
||||
<Localized
|
||||
$unit="hour"
|
||||
$value={1}
|
||||
id="framework-durationField-hours"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="3600"
|
||||
>
|
||||
Hours
|
||||
hour
|
||||
</Option>
|
||||
</Localized>
|
||||
</withPropsOnChange(WithKeyboardFocus)>
|
||||
@@ -247,6 +262,7 @@ exports[`use initial unit if 0 1`] = `
|
||||
itemGutter={true}
|
||||
>
|
||||
<withPropsOnChange(TextField)
|
||||
adornment={null}
|
||||
aria-label="value"
|
||||
autoCapitalize="off"
|
||||
autoComplete="off"
|
||||
@@ -272,33 +288,36 @@ exports[`use initial unit if 0 1`] = `
|
||||
value="1"
|
||||
>
|
||||
<Localized
|
||||
$unit="second"
|
||||
$value={0}
|
||||
id="framework-durationField-seconds"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="1"
|
||||
>
|
||||
Seconds
|
||||
second
|
||||
</Option>
|
||||
</Localized>
|
||||
<Localized
|
||||
$unit="minute"
|
||||
$value={0}
|
||||
id="framework-durationField-minutes"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="60"
|
||||
>
|
||||
Minutes
|
||||
minute
|
||||
</Option>
|
||||
</Localized>
|
||||
<Localized
|
||||
$unit="hour"
|
||||
$value={0}
|
||||
id="framework-durationField-hours"
|
||||
id="framework-durationField-unit"
|
||||
>
|
||||
<Option
|
||||
value="3600"
|
||||
>
|
||||
Hours
|
||||
hour
|
||||
</Option>
|
||||
</Localized>
|
||||
</withPropsOnChange(WithKeyboardFocus)>
|
||||
|
||||
Reference in New Issue
Block a user