Skip to content

Commit

Permalink
Merge pull request #19412 from Expensify/dangrous-flagcommentpane
Browse files Browse the repository at this point in the history
  • Loading branch information
youssef-lr authored May 31, 2023
2 parents 8e6c3e2 + 83929ca commit 36fe848
Show file tree
Hide file tree
Showing 20 changed files with 414 additions and 16 deletions.
7 changes: 7 additions & 0 deletions assets/images/flag.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions assets/images/flag_level_01.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions assets/images/flag_level_02.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions assets/images/flag_level_03.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -2438,6 +2438,10 @@ const CONST = {
MODERATOR_DECISION_HIDDEN: 'hidden',
FLAG_SEVERITY_SPAM: 'spam',
FLAG_SEVERITY_INCONSIDERATE: 'inconsiderate',
FLAG_SEVERITY_INTIMIDATION: 'intimidation',
FLAG_SEVERITY_BULLYING: 'bullying',
FLAG_SEVERITY_HARASSMENT: 'harassment',
FLAG_SEVERITY_ASSAULT: 'assault',
},
};

Expand Down
2 changes: 2 additions & 0 deletions src/ROUTES.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ export default {
NEW_TASK_DETAILS: `${NEW_TASK}/details`,
NEW_TASK_TITLE: `${NEW_TASK}/title`,
NEW_TASK_DESCRIPTION: `${NEW_TASK}/description`,
FLAG_COMMENT: `flag/:reportID/:reportActionID`,
getFlagCommentRoute: (reportID, reportActionID) => `flag/${reportID}/${reportActionID}`,
SEARCH: 'search',
SET_PASSWORD_WITH_VALIDATE_CODE: 'setpassword/:accountID/:validateCode',
DETAILS: 'details',
Expand Down
8 changes: 8 additions & 0 deletions src/components/Icon/Expensicons.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ import ExpensifyWordmark from '../../../assets/images/expensify-wordmark.svg';
import Expand from '../../../assets/images/expand.svg';
import Eye from '../../../assets/images/eye.svg';
import EyeDisabled from '../../../assets/images/eye-disabled.svg';
import Flag from '../../../assets/images/flag.svg';
import FlagLevelOne from '../../../assets/images/flag_level_01.svg';
import FlagLevelTwo from '../../../assets/images/flag_level_02.svg';
import FlagLevelThree from '../../../assets/images/flag_level_03.svg';
import Gallery from '../../../assets/images/gallery.svg';
import Gear from '../../../assets/images/gear.svg';
import Globe from '../../../assets/images/globe.svg';
Expand Down Expand Up @@ -162,6 +166,10 @@ export {
EyeDisabled,
FallbackAvatar,
FallbackWorkspaceAvatar,
Flag,
FlagLevelOne,
FlagLevelTwo,
FlagLevelThree,
Gallery,
Gear,
Globe,
Expand Down
21 changes: 21 additions & 0 deletions src/components/MenuItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import PressableWithSecondaryInteraction from './PressableWithSecondaryInteracti
import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions';
import * as DeviceCapabilities from '../libs/DeviceCapabilities';
import ControlSelection from '../libs/ControlSelection';
import variables from '../styles/variables';

const propTypes = {
...menuItemPropTypes,
Expand Down Expand Up @@ -62,6 +63,9 @@ const defaultProps = {
shouldStackHorizontally: false,
avatarSize: undefined,
shouldBlockSelection: false,
hoverAndPressStyle: [],
furtherDetails: '',
furtherDetailsIcon: undefined,
};

const MenuItem = (props) => {
Expand Down Expand Up @@ -112,6 +116,7 @@ const MenuItem = (props) => {
props.style,
!props.interactive && styles.cursorDefault,
StyleUtils.getButtonBackgroundColorStyle(getButtonState(props.focused || hovered, pressed, props.success, props.disabled, props.interactive), true),
(hovered || pressed) && props.hoverAndPressStyle,
...(_.isArray(props.wrapperStyle) ? props.wrapperStyle : [props.wrapperStyle]),
]}
disabled={props.disabled}
Expand Down Expand Up @@ -187,6 +192,22 @@ const MenuItem = (props) => {
{props.description}
</Text>
)}
{Boolean(props.furtherDetails) && (
<View style={[styles.flexRow, styles.mt2, styles.alignItemsCenter]}>
<Icon
src={props.furtherDetailsIcon}
height={variables.iconSizeNormal}
width={variables.iconSizeNormal}
inline
/>
<Text
style={[styles.furtherDetailsText, styles.ph2, styles.pt1]}
numberOfLines={2}
>
{props.furtherDetails}
</Text>
</View>
)}
</View>
</View>
<View style={[styles.flexRow, styles.menuItemTextContainer, styles.pointerEventsNone]}>
Expand Down
9 changes: 9 additions & 0 deletions src/components/menuItemPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ const propTypes = {

/** The ref to the menu item */
forwardedRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),

/** Any adjustments to style when menu item is hovered or pressed */
hoverAndPressStyle: PropTypes.arrayOf(PropTypes.object),

/** Text to display under the main item */
furtherDetails: PropTypes.string,

/** An icon to display under the main item */
furtherDetailsIcon: PropTypes.oneOfType([PropTypes.elementType, PropTypes.string]),
};

export default propTypes;
18 changes: 18 additions & 0 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ export default {
deleteConfirmation: ({action}) => `Are you sure you want to delete this ${ReportActionsUtils.isMoneyRequestAction(action) ? 'request' : 'comment'}?`,
onlyVisible: 'Only visible to',
replyInThread: 'Reply in thread',
flagAsOffensive: 'Flag as offensive',
},
emojiReactions: {
addReactionTooltip: 'Add reaction',
Expand Down Expand Up @@ -1406,8 +1407,25 @@ export default {
copied: 'Copied!',
},
moderation: {
flagDescription: 'All flagged messages will be sent to a moderator for review.',
chooseAReason: 'Choose a reason for flagging below:',
spam: 'Spam',
spamDescription: 'Unsolicited off-topic promotion',
inconsiderate: 'Inconsiderate',
inconsiderateDescription: 'Insulting or disrespectful phrasing, with questionable intentions',
intimidation: 'Intimidation',
intimidationDescription: 'Aggressively pursuing an agenda over valid objections',
bullying: 'Bullying',
bullyingDescription: 'Targeting an individual to obtain obedience',
harassment: 'Harassment',
harassmentDescription: 'Racist, misogynistic, or other broadly discriminatory behavior',
assault: 'Assault',
assaultDescription: 'Specifically targeted emotional attack with the intention of harm',
flaggedContent: 'This message has been flagged as violating our community rules and the content has been hidden.',
hideMessage: 'Hide message',
revealMessage: 'Reveal message',
levelOneResult: 'Sends anonymous warning and message is reported for review.',
levelTwoResult: 'Message hidden from channel, plus anonymous warning and message is reported for review.',
levelThreeResult: 'Message removed from channel plus anonymous warning and message is reported for review.',
},
};
18 changes: 18 additions & 0 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ export default {
deleteConfirmation: ({action}) => `¿Estás seguro de que quieres eliminar este ${ReportActionsUtils.isMoneyRequestAction(action) ? 'pedido' : 'comentario'}`,
onlyVisible: 'Visible sólo para',
replyInThread: 'Responder en el hilo',
flagAsOffensive: 'Marcar como ofensivo',
},
emojiReactions: {
addReactionTooltip: 'Añadir una reacción',
Expand Down Expand Up @@ -1872,8 +1873,25 @@ export default {
copied: '¡Copiado!',
},
moderation: {
flagDescription: 'Todos los mensajes marcados se enviarán a un moderador para su revisión.',
chooseAReason: 'Elige abajo un motivo para reportarlo:',
spam: 'Spam',
spamDescription: 'Promoción fuera de tema no solicitada',
inconsiderate: 'Desconsiderado',
inconsiderateDescription: 'Frase insultante o irrespetuosa, con intenciones cuestionables',
intimidation: 'Intimidación',
intimidationDescription: 'Persigue agresivamente una agenda sobre objeciones válidas',
bullying: 'Bullying',
bullyingDescription: 'Apunta a un individuo para obtener obediencia',
harassment: 'Acoso',
harassmentDescription: 'Comportamiento racista, misógino u otro comportamiento discriminatorio',
assault: 'Agresion',
assaultDescription: 'Ataque emocional específicamente dirigido con la intención de hacer daño',
flaggedContent: 'Este mensaje ha sido marcado por violar las reglas de nuestra comunidad y el contenido se ha ocultado.',
hideMessage: 'Ocultar mensaje',
revealMessage: 'Revelar mensaje',
levelOneResult: 'Envia una advertencia anónima y el mensaje es reportado para revisión.',
levelTwoResult: 'Mensaje ocultado del canal, más advertencia anónima y mensaje reportado para revisión.',
levelThreeResult: 'Mensaje eliminado del canal, más advertencia anónima y mensaje reportado para revisión.',
},
};
6 changes: 6 additions & 0 deletions src/libs/Navigation/AppNavigator/AuthScreens.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,12 @@ class AuthScreens extends React.Component {
component={ModalStackNavigators.YearPickerStackNavigator}
listeners={modalScreenListeners}
/>
<RootStack.Screen
name="Flag_Comment"
options={modalScreenOptions}
component={ModalStackNavigators.FlagCommentStackNavigator}
listeners={modalScreenListeners}
/>
<RootStack.Screen
name={SCREENS.NOT_FOUND}
options={{headerShown: false}}
Expand Down
11 changes: 11 additions & 0 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.js
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,16 @@ const YearPickerStackNavigator = createModalStackNavigator([
},
]);

const FlagCommentStackNavigator = createModalStackNavigator([
{
getComponent: () => {
const FlagCommentPage = require('../../../pages/FlagCommentPage').default;
return FlagCommentPage;
},
name: 'FlagComment_Root',
},
]);

export {
IOUBillStackNavigator,
IOURequestModalStackNavigator,
Expand All @@ -723,4 +733,5 @@ export {
ReimbursementAccountModalStackNavigator,
WalletStatementStackNavigator,
YearPickerStackNavigator,
FlagCommentStackNavigator,
};
5 changes: 5 additions & 0 deletions src/libs/Navigation/linkingConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,11 @@ export default {
YearPicker_Root: ROUTES.SELECT_YEAR,
},
},
Flag_Comment: {
screens: {
FlagComment_Root: ROUTES.FLAG_COMMENT,
},
},
[SCREENS.NOT_FOUND]: '*',
},
},
Expand Down
33 changes: 33 additions & 0 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,24 @@ function canEditReportAction(reportAction) {
);
}

/**
* Can only flag if:
*
* - It was written by someone else
* - It's an ADDCOMMENT that is not an attachment
*
* @param {Object} reportAction
* @returns {Boolean}
*/
function canFlagReportAction(reportAction) {
return (
reportAction.actorEmail !== sessionEmail &&
reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT &&
!ReportActionsUtils.isDeletedAction(reportAction) &&
!ReportActionsUtils.isCreatedTaskReportAction(reportAction)
);
}

/**
* Whether the Money Request report is settled
*
Expand Down Expand Up @@ -2113,11 +2131,25 @@ function isReportDataReady() {
return !_.isEmpty(allReports) && _.some(_.keys(allReports), (key) => allReports[key].reportID);
}

/**
* Returns the parentReport if the given report is a thread.
*
* @param {Object} report
* @returns {Object}
*/
function getParentReport(report) {
if (!report || !report.parentReportID) {
return {};
}
return lodashGet(allReports, `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, {});
}

export {
getReportParticipantsTitle,
isReportMessageAttachment,
findLastAccessedReport,
canEditReportAction,
canFlagReportAction,
canDeleteReportAction,
canLeaveRoom,
sortReportsByLastRead,
Expand Down Expand Up @@ -2199,4 +2231,5 @@ export {
isAllowedToComment,
getMoneyRequestAction,
getBankAccountRoute,
getParentReport,
};
32 changes: 18 additions & 14 deletions src/libs/actions/Report.js
Original file line number Diff line number Diff line change
Expand Up @@ -1682,30 +1682,34 @@ function setLastOpenedPublicRoom(reportID) {
* @param {String} severity
*/
function flagComment(reportID, reportAction, severity) {
let newDecision;
const message = reportAction.message[0];
let updatedDecision;
if (severity === CONST.MODERATION.FLAG_SEVERITY_SPAM || severity === CONST.MODERATION.FLAG_SEVERITY_INCONSIDERATE) {
newDecision = {
decision: CONST.MODERATION.MODERATOR_DECISION_PENDING,
};
if (_.isEmpty(message.moderationDecisions) || message.moderationDecisions[message.moderationDecisions.length - 1].decision !== CONST.MODERATION.MODERATOR_DECISION_PENDING_HIDE) {
updatedDecision = [
{
decision: CONST.MODERATION.MODERATOR_DECISION_PENDING,
},
];
}
} else {
newDecision = {
decision: CONST.MODERATION.MODERATOR_DECISION_PENDING_HIDE,
};
updatedDecision = [
{
decision: CONST.MODERATION.MODERATOR_DECISION_PENDING_HIDE,
},
];
}

const message = reportAction.message[0];
const reportActionID = reportAction.reportActionID;

const updatedDecisions = [...(message.moderationDecisions || []), newDecision];

const updatedMessage = {
...message,
moderationDecisions: updatedDecisions,
moderationDecisions: updatedDecision,
};

const optimisticData = [
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
value: {
[reportActionID]: {
Expand All @@ -1718,7 +1722,7 @@ function flagComment(reportID, reportAction, severity) {

const failureData = [
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
value: {
[reportActionID]: {
Expand All @@ -1731,7 +1735,7 @@ function flagComment(reportID, reportAction, severity) {

const successData = [
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
value: {
[reportActionID]: {
Expand Down
Loading

0 comments on commit 36fe848

Please sign in to comment.