diff --git a/src/views/mod-tools/ModToolsMessageHandler.tsx b/src/views/mod-tools/ModToolsMessageHandler.tsx index 1c5713d1..0ffe0d0f 100644 --- a/src/views/mod-tools/ModToolsMessageHandler.tsx +++ b/src/views/mod-tools/ModToolsMessageHandler.tsx @@ -1,11 +1,12 @@ import { CfhSanctionMessageEvent, CfhTopicsInitEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ModeratorActionResultMessageEvent, ModeratorInitMessageEvent, ModeratorToolPreferencesEvent, RoomEngineEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; +import { NotificationAlertEvent } from '../../events'; import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent'; import { ModToolsOpenRoomChatlogEvent } from '../../events/mod-tools/ModToolsOpenRoomChatlogEvent'; import { ModToolsOpenRoomInfoEvent } from '../../events/mod-tools/ModToolsOpenRoomInfoEvent'; import { ModToolsOpenUserChatlogEvent } from '../../events/mod-tools/ModToolsOpenUserChatlogEvent'; import { ModToolsOpenUserInfoEvent } from '../../events/mod-tools/ModToolsOpenUserInfoEvent'; -import { CreateMessageHook, useRoomEngineEvent, useUiEvent } from '../../hooks'; +import { CreateMessageHook, dispatchUiEvent, useRoomEngineEvent, useUiEvent } from '../../hooks'; import { useModToolsContext } from './context/ModToolsContext'; import { ModToolsActions } from './reducers/ModToolsReducer'; @@ -84,6 +85,7 @@ export const ModToolsMessageHandler: FC<{}> = props => if(!parser) return; // todo: let user know it failed + dispatchUiEvent(new NotificationAlertEvent(['Failed to pick issue'], null, null, null, 'Error', null)); }, []); const onIssueDeletedMessageEvent = useCallback((event: IssueDeletedMessageEvent) => @@ -115,11 +117,11 @@ export const ModToolsMessageHandler: FC<{}> = props => if(parser.success) { - // do something + dispatchUiEvent(new NotificationAlertEvent(['Moderation action was successfull'], null, null, null, 'Success', null)); } else { - // let user know it was a failure + dispatchUiEvent(new NotificationAlertEvent(['There was a problem applying that moderation action'], null, null, null, 'Error', null)); } }, []); @@ -128,9 +130,18 @@ export const ModToolsMessageHandler: FC<{}> = props => const parser = event.getParser(); if(!parser) return; + + const categories = parser.callForHelpCategories; + + dispatchModToolsState({ + type: ModToolsActions.SET_CFH_CATEGORIES, + payload: { + cfhCategories: categories + } + }); console.log(parser); - }, []); + }, [dispatchModToolsState]); const onCfhSanctionMessageEvent = useCallback((event: CfhSanctionMessageEvent) => { diff --git a/src/views/mod-tools/reducers/ModToolsReducer.tsx b/src/views/mod-tools/reducers/ModToolsReducer.tsx index ee94db45..b6fcf343 100644 --- a/src/views/mod-tools/reducers/ModToolsReducer.tsx +++ b/src/views/mod-tools/reducers/ModToolsReducer.tsx @@ -1,4 +1,4 @@ -import { IssueMessageData, ModeratorInitData } from '@nitrots/nitro-renderer'; +import { CallForHelpCategoryData, IssueMessageData, ModeratorInitData } from '@nitrots/nitro-renderer'; import { Reducer } from 'react'; export interface IModToolsState @@ -10,6 +10,7 @@ export interface IModToolsState openUserInfo: number[]; openUserChatlogs: number[]; tickets: IssueMessageData[] + cfhCategories: CallForHelpCategoryData[]; } export interface IModToolsAction @@ -23,6 +24,7 @@ export interface IModToolsAction openUserInfo?: number[]; openUserChatlogs?: number[]; tickets?: IssueMessageData[]; + cfhCategories?: CallForHelpCategoryData[]; } } @@ -35,6 +37,7 @@ export class ModToolsActions public static SET_OPEN_ROOM_CHATLOGS: string = 'MTA_SET_OPEN_CHATLOGS'; public static SET_OPEN_USER_CHATLOGS: string = 'MTA_SET_OPEN_USER_CHATLOGS'; public static SET_TICKETS: string = 'MTA_SET_TICKETS'; + public static SET_CFH_CATEGORIES: string = 'MTA_SET_CFH_CATEGORIES'; public static RESET_STATE: string = 'MTA_RESET_STATE'; } @@ -45,7 +48,8 @@ export const initialModTools: IModToolsState = { openRoomChatlogs: null, openUserChatlogs: null, openUserInfo: null, - tickets: null + tickets: null, + cfhCategories: null }; export const ModToolsReducer: Reducer = (state, action) => @@ -87,6 +91,11 @@ export const ModToolsReducer: Reducer = (state, return { ...state, tickets }; } + case ModToolsActions.SET_CFH_CATEGORIES: { + const cfhCategories = (action.payload.cfhCategories || state.cfhCategories || null); + + return { ...state, cfhCategories }; + } case ModToolsActions.RESET_STATE: { return { ...initialModTools }; } diff --git a/src/views/mod-tools/utils/ModActionDefinition.ts b/src/views/mod-tools/utils/ModActionDefinition.ts new file mode 100644 index 00000000..b8318afa --- /dev/null +++ b/src/views/mod-tools/utils/ModActionDefinition.ts @@ -0,0 +1,49 @@ +export class ModActionDefinition +{ + public static ALERT:number = 1; + public static MUTE:number = 2; + public static BAN:number = 3; + public static KICK:number = 4; + public static TRADE_LOCK:number = 5; + public static MESSAGE:number = 6; + + private readonly _actionId:number; + private readonly _name:string; + private readonly _actionType:number; + private readonly _sanctionTypeId:number; + private readonly _actionLengthHours:number; + + constructor(actionId:number, actionName:string, actionType:number, sanctionTypeId:number, actionLengthHours:number) + { + this._actionId = actionId; + this._name = actionName; + this._actionType = actionType; + this._sanctionTypeId = sanctionTypeId; + this._actionLengthHours = actionLengthHours; + } + + public get actionId():number + { + return this._actionId; + } + + public get name():string + { + return this._name; + } + + public get actionType():number + { + return this._actionType; + } + + public get sanctionTypeId():number + { + return this._sanctionTypeId; + } + + public get actionLengthHours():number + { + return this._actionLengthHours; + } +} diff --git a/src/views/mod-tools/views/user/user-mod-action/ModToolsUserModActionView.tsx b/src/views/mod-tools/views/user/user-mod-action/ModToolsUserModActionView.tsx index 2a8495a2..59e244f8 100644 --- a/src/views/mod-tools/views/user/user-mod-action/ModToolsUserModActionView.tsx +++ b/src/views/mod-tools/views/user/user-mod-action/ModToolsUserModActionView.tsx @@ -1,16 +1,191 @@ -import { FC } from 'react'; +import { CallForHelpTopicData, DefaultSanctionMessageComposer, ModAlertMessageComposer, ModBanMessageComposer, ModKickMessageComposer, ModMessageMessageComposer, ModMuteMessageComposer, ModTradingLockMessageComposer } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useMemo, useState } from 'react'; +import { LocalizeText } from '../../../../../api'; +import { NotificationAlertEvent } from '../../../../../events'; +import { dispatchUiEvent, SendMessageHook } from '../../../../../hooks'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../../layout'; +import { useModToolsContext } from '../../../context/ModToolsContext'; +import { ModActionDefinition } from '../../../utils/ModActionDefinition'; import { ModToolsUserModActionViewProps } from './ModToolsUserModActionView.types'; +const actions = [ + new ModActionDefinition(1, 'Alert', ModActionDefinition.ALERT, 1, 0), + new ModActionDefinition(2, 'Mute 1h', ModActionDefinition.MUTE, 2, 0), + new ModActionDefinition(4, 'Ban 7 days', ModActionDefinition.BAN, 4, 0), + new ModActionDefinition(3, 'Ban 18h', ModActionDefinition.BAN, 3, 0), + new ModActionDefinition(5, 'Ban 30 days (step 1)', ModActionDefinition.BAN, 5, 0), + new ModActionDefinition(7, 'Ban 30 days (step 2)', ModActionDefinition.BAN, 7, 0), + new ModActionDefinition(6, 'Ban 100 years', ModActionDefinition.BAN, 6, 0), + new ModActionDefinition(106, 'Ban avatar-only 100 years', ModActionDefinition.BAN, 6, 0), + new ModActionDefinition(101, 'Kick', ModActionDefinition.KICK, 0, 0), + new ModActionDefinition(102, 'Lock trade 1 week', ModActionDefinition.TRADE_LOCK, 0, 168), + new ModActionDefinition(104, 'Lock trade permanent', ModActionDefinition.TRADE_LOCK, 0, 876000), + new ModActionDefinition(105, 'Message', ModActionDefinition.MESSAGE, 0, 0), +]; + export const ModToolsUserModActionView: FC = props => { const { user = null, onCloseClick = null } = props; + const { modToolsState = null, dispatchModToolsState = null } = useModToolsContext(); + const { cfhCategories = null, settings = null } = modToolsState; + const [ selectedTopic, setSelectedTopic ] = useState(-1); + const [ selectedAction, setSelectedAction ] = useState(-1); + const [ message, setMessage ] = useState(''); + + const topics = useMemo(() => + { + const values: CallForHelpTopicData[] = []; + + if(!cfhCategories) return values; + + for(let category of cfhCategories) + { + for(let topic of category._Str_14841) + { + values.push(topic) + } + } + + return values; + }, [cfhCategories]); + + const sendSanction = useCallback(() => + { + if(selectedTopic === -1) + { + dispatchUiEvent(new NotificationAlertEvent(['You must select a CFH topic'], null, null, null, 'Error', null)); + return; + } + if(!settings || !settings.cfhPermission) + { + dispatchUiEvent(new NotificationAlertEvent(['You do not have permission to do this'], null, null, null, 'Error', null)); + return; + } + + const category = topics[selectedTopic]; + const sanction = actions[selectedAction]; + + if(!category) + { + dispatchUiEvent(new NotificationAlertEvent(['You must select a CFH topic'], null, null, null, 'Error', null)); + return; + } + + const messageOrDefault = message.trim().length === 0 ? LocalizeText('help.cfh.topic.' + category.id) : message; + + if(!sanction) // send default sanction + { + SendMessageHook(new DefaultSanctionMessageComposer(user.userId, category.id, messageOrDefault)); + onCloseClick(null); + return; + } + + switch(sanction.actionType) + { + case ModActionDefinition.ALERT: + + if(!settings.alertPermission) + { + dispatchUiEvent(new NotificationAlertEvent(['You have insufficient permissions.'], null, null, null, 'Error', null)); + return; + } + + if(message.trim().length === 0) + { + dispatchUiEvent(new NotificationAlertEvent(['Please write a message to user.'], null, null, null, 'Error', null)); + return; + } + + SendMessageHook(new ModAlertMessageComposer(user.userId, message, category.id)); + + break; + case ModActionDefinition.MUTE: + SendMessageHook(new ModMuteMessageComposer(user.userId, messageOrDefault, category.id)); + + break; + case ModActionDefinition.BAN: + + if(!settings.banPermission) + { + dispatchUiEvent(new NotificationAlertEvent(['You have insufficient permissions.'], null, null, null, 'Error', null)); + return; + } + + SendMessageHook(new ModBanMessageComposer(user.userId, messageOrDefault, category.id, selectedAction, (sanction.actionId === 106))); + + break; + + case ModActionDefinition.KICK: + + if(!settings.kickPermission) + { + dispatchUiEvent(new NotificationAlertEvent(['You have insufficient permissions.'], null, null, null, 'Error', null)); + return; + } + + SendMessageHook(new ModKickMessageComposer(user.userId, messageOrDefault, category.id)); + + break; + + case ModActionDefinition.TRADE_LOCK: + { + const numSeconds = sanction.actionLengthHours * 60; + SendMessageHook(new ModTradingLockMessageComposer(user.userId, messageOrDefault, numSeconds, category.id)); + } + break; + + case ModActionDefinition.MESSAGE: + + if(message.trim().length === 0) + { + dispatchUiEvent(new NotificationAlertEvent(['Please write a message to user.'], null, null, null, 'Error', null)); + return; + } + + SendMessageHook(new ModMessageMessageComposer(user.userId, message, category.id)); + + break; + } + + onCloseClick(null); + }, [message, onCloseClick, selectedAction, selectedTopic, settings, topics, user.userId]); return ( - + - {user &&
} + { user && + <> +
+ +
+ +
+ +
+ +
+ +