Allow unauthenticated users to flag user reviews (#12589)
This commit is contained in:
Родитель
2087d4c3bc
Коммит
5f24adcbb3
|
@ -14,11 +14,14 @@ import type { ElementEvent, HTMLElementEventHandler } from 'amo/types/dom';
|
|||
import type { ErrorHandlerType } from 'amo/types/errorHandler';
|
||||
import type { DispatchFunc } from 'amo/types/redux';
|
||||
|
||||
import './styles.scss';
|
||||
|
||||
type Props = {|
|
||||
buttonText: string,
|
||||
reason: FlagReviewReasonType,
|
||||
review: UserReviewType,
|
||||
wasFlaggedText: string,
|
||||
disabled?: boolean,
|
||||
|};
|
||||
|
||||
type PropsFromState = {|
|
||||
|
@ -47,7 +50,8 @@ export class FlagReviewBase extends React.Component<InternalProps> {
|
|||
};
|
||||
|
||||
renderControls(): React.Node {
|
||||
const { errorHandler, flagState, buttonText, wasFlaggedText } = this.props;
|
||||
const { disabled, errorHandler, flagState, buttonText, wasFlaggedText } =
|
||||
this.props;
|
||||
|
||||
if (flagState) {
|
||||
if (flagState.inProgress && !errorHandler.hasError()) {
|
||||
|
@ -63,6 +67,7 @@ export class FlagReviewBase extends React.Component<InternalProps> {
|
|||
className="FlagReview-button"
|
||||
onClick={this.onClick}
|
||||
type="button"
|
||||
disabled={!!disabled}
|
||||
>
|
||||
{buttonText}
|
||||
</button>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
@import '~amo/css/styles';
|
||||
|
||||
.FlagReview-button[disabled] {
|
||||
@include disabled;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
color: initial !important;
|
||||
}
|
||||
}
|
|
@ -65,8 +65,16 @@ export class FlagReviewMenuBase extends React.Component<InternalProps> {
|
|||
'A user cannot flag their own review.',
|
||||
);
|
||||
|
||||
const enableFeatureFeedbackFormLinks = config.get(
|
||||
'enableFeatureFeedbackFormLinks',
|
||||
);
|
||||
|
||||
const disableItemsForUnauthenticatedUsers = enableFeatureFeedbackFormLinks
|
||||
? !siteUser
|
||||
: false;
|
||||
|
||||
let items;
|
||||
if (!siteUser) {
|
||||
if (!enableFeatureFeedbackFormLinks && !siteUser) {
|
||||
items = [
|
||||
<ListItem key="login-required">
|
||||
<AuthenticateButton
|
||||
|
@ -87,13 +95,14 @@ export class FlagReviewMenuBase extends React.Component<InternalProps> {
|
|||
review={review}
|
||||
buttonText={i18n.gettext('This is spam')}
|
||||
wasFlaggedText={i18n.gettext('Flagged as spam')}
|
||||
disabled={disableItemsForUnauthenticatedUsers}
|
||||
/>
|
||||
</ListItem>,
|
||||
<ListItem
|
||||
className="FlagReviewMenu-flag-language-item"
|
||||
key="flag-language"
|
||||
>
|
||||
{config.get('enableFeatureFeedbackFormLinks') ? (
|
||||
{enableFeatureFeedbackFormLinks ? (
|
||||
<Link to={`/feedback/review/${review.id}/`}>
|
||||
{i18n.gettext('This contains inappropriate language')}
|
||||
</Link>
|
||||
|
@ -124,6 +133,7 @@ export class FlagReviewMenuBase extends React.Component<InternalProps> {
|
|||
wasFlaggedText={i18n.gettext(
|
||||
'Flagged as a bug report or support request',
|
||||
)}
|
||||
disabled={disableItemsForUnauthenticatedUsers}
|
||||
/>
|
||||
</ListItem>
|
||||
),
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
a,
|
||||
a:link,
|
||||
button {
|
||||
&:not(.Button) {
|
||||
&:not(.Button):not([disabled]) {
|
||||
@include font-medium;
|
||||
|
||||
cursor: pointer;
|
||||
|
|
|
@ -1485,6 +1485,11 @@ describe(__filename, () => {
|
|||
|
||||
await openFlagMenu();
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: 'This is spam',
|
||||
}),
|
||||
).not.toBeDisabled();
|
||||
expect(
|
||||
// It would have to be a 'button' if `enableFeatureFeedbackFormLinks`
|
||||
// was set to `false`.
|
||||
|
@ -1492,6 +1497,11 @@ describe(__filename, () => {
|
|||
name: 'This contains inappropriate language',
|
||||
}),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: 'This is a bug report or support request',
|
||||
}),
|
||||
).not.toBeDisabled();
|
||||
});
|
||||
|
||||
it('can be configured with an openerClass', () => {
|
||||
|
@ -1525,6 +1535,60 @@ describe(__filename, () => {
|
|||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('when enableFeatureFeedbackFormLinks is enabled', () => {
|
||||
beforeEach(() => {
|
||||
const fakeConfig = getMockConfig({
|
||||
enableFeatureFeedbackFormLinks: true,
|
||||
});
|
||||
config.get.mockImplementation((key) => {
|
||||
return fakeConfig[key];
|
||||
});
|
||||
});
|
||||
|
||||
it('shows the menu for signed-out users', async () => {
|
||||
render({ review: _setReview() });
|
||||
|
||||
await openFlagMenu();
|
||||
|
||||
expect(
|
||||
screen.queryByRole('link', { name: 'Log in to flag this review' }),
|
||||
).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: 'This is spam',
|
||||
}),
|
||||
).toBeDisabled();
|
||||
expect(
|
||||
screen.getByRole('link', {
|
||||
name: 'This contains inappropriate language',
|
||||
}),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: 'This is a bug report or support request',
|
||||
}),
|
||||
).toBeDisabled();
|
||||
});
|
||||
|
||||
it('shows the menu for signed-in users', async () => {
|
||||
dispatchSignInActionsWithStore({ store, userId: 999 });
|
||||
render({ review: _setReview() });
|
||||
|
||||
await openFlagMenu();
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: 'This is spam',
|
||||
}),
|
||||
).not.toBeDisabled();
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: 'This is a bug report or support request',
|
||||
}),
|
||||
).not.toBeDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
it('prompts you to flag a developer response after login', async () => {
|
||||
renderNestedReply();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче