Merge pull request #17 from simoleo89/mod-tools-i18n

Localize all mod tools hardcoded texts
This commit is contained in:
DuckieTM
2026-03-19 09:48:54 +01:00
committed by GitHub
16 changed files with 222 additions and 124 deletions
+96
View File
@@ -0,0 +1,96 @@
{
"moderation.modtools.title": "Mod Tools",
"moderation.modtools.roomtool": "Room Tool",
"moderation.modtools.roomchatlogs": "Chatlog Tool",
"moderation.modtools.userinfo": "User Info",
"moderation.modtools.tickets": "Tickets",
"moderation.roomtool.info.title": "Room Info",
"moderation.roomtool.roomowner.title": "Owner:",
"moderation.roomtool.usersinroom.title": "Users in room:",
"moderation.roomtool.ownerinroom.title": "Owner here:",
"moderation.roomtool.true.title": "Yes",
"moderation.roomtool.false.title": "No",
"moderation.roomtool.button.visit.title": "Visit Room",
"moderation.roomtool.kickall.title": "Kick everyone out",
"moderation.roomtool.closeroom.title": "Enable the doorbell",
"moderation.roomtool.inappropiatename.title": "Change room name",
"moderation.roomtool.presets.title": "Type a mandatory message...",
"moderation.roomtool.button.caution.title": "Send Caution",
"moderation.roomtool.button.message.title": "Send Alert",
"moderation.tickets.title": "Tickets",
"moderation.tickets.open": "Open Issues",
"moderation.tickets.my": "My Issues",
"moderation.tickets.picked": "Picked Issues",
"moderation.tickets.col.type": "Type",
"moderation.tickets.col.roomPlayer": "Room/Player",
"moderation.tickets.col.opened": "Opened",
"moderation.tickets.col.picker": "Picker",
"moderation.tickets.pick": "Pick Issue",
"moderation.tickets.handle": "Handle",
"moderation.tickets.release": "Release",
"moderation.issue.resolving": "Resolving issue %id%",
"moderation.issue.info": "Issue Information",
"moderation.issue.source": "Source",
"moderation.issue.category": "Category",
"moderation.issue.description": "Description",
"moderation.issue.caller": "Caller",
"moderation.issue.reported": "Reported User",
"moderation.issue.chatlog": "Chatlog",
"moderation.issue.close.useless": "Close as useless",
"moderation.issue.close.abusive": "Close as abusive",
"moderation.issue.close.resolved": "Close as resolved",
"moderation.issue.release": "Release",
"moderation.chatlog.issue": "Issue Chatlog",
"moderation.chatlog.room": "Room Chatlog",
"moderation.chatlog.col.time": "Time",
"moderation.chatlog.col.user": "User",
"moderation.chatlog.col.message": "Message",
"moderation.chatlog.visit": "Visit",
"moderation.chatlog.roomtools": "Room Tools",
"moderation.chatlog.user": "User Chatlog: %username%",
"moderation.userinfo.roomchat": "Room Chat",
"moderation.userinfo.sendmessage": "Send Message",
"moderation.userinfo.roomvisits": "Room Visits",
"moderation.userinfo.modaction": "Mod Action",
"moderation.sendmessage.title": "Send Message",
"moderation.sendmessage.to": "Message To: %username%",
"moderation.sendmessage.send": "Send message",
"moderation.sendmessage.error.empty": "Please write a message to user.",
"moderation.error": "Error",
"moderation.roomvisits.title": "User Visits",
"moderation.roomvisits.col.time": "Time",
"moderation.roomvisits.col.roomname": "Room name",
"moderation.roomvisits.col.visit": "Visit",
"moderation.roomvisits.visitroom": "Visit Room",
"moderation.modaction.title": "Mod Action: %username%",
"moderation.modaction.cfhtopic": "CFH Topic",
"moderation.modaction.sanctiontype": "Sanction Type",
"moderation.modaction.message.hint": "Optional message type, overrides default",
"moderation.modaction.defaultsanction": "Default Sanction",
"moderation.modaction.sanction": "Sanction",
"moderation.modaction.alert": "Alert",
"moderation.modaction.mute1h": "Mute 1h",
"moderation.modaction.ban18h": "Ban 18h",
"moderation.modaction.ban7days": "Ban 7 days",
"moderation.modaction.ban30days.step1": "Ban 30 days (step 1)",
"moderation.modaction.ban30days.step2": "Ban 30 days (step 2)",
"moderation.modaction.ban100years": "Ban 100 years",
"moderation.modaction.banavataronly100years": "Ban avatar-only 100 years",
"moderation.modaction.kick": "Kick",
"moderation.modaction.locktrade1week": "Lock trade 1 week",
"moderation.modaction.locktradepermanent": "Lock trade permanent",
"moderation.modaction.message": "Message",
"moderation.modaction.error.notopic": "You must select a CFH topic",
"moderation.modaction.error.notopicorsanction": "You must select a CFH topic and Sanction",
"moderation.modaction.error.nopermission": "You do not have permission to do this",
"moderation.modaction.error.nosanction": "You must select a sanction",
"moderation.modaction.error.emptymessage": "Please write a message to user"
}
+6 -6
View File
@@ -1,6 +1,6 @@
import { AddLinkEventTracker, CreateLinkEvent, ILinkEventTracker, RemoveLinkEventTracker, RoomEngineEvent, RoomId, RoomObjectCategory, RoomObjectType } from '@nitrots/nitro-renderer';
import { FC, useEffect, useRef, useState } from 'react';
import { GetRoomSession, ISelectedUser } from '../../api';
import { GetRoomSession, ISelectedUser, LocalizeText } from '../../api';
import { Button, DraggableWindowPosition, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common';
import { useModTools, useNitroEvent, useObjectSelectedEvent } from '../../hooks';
import { ModToolsChatlogView } from './views/room/ModToolsChatlogView';
@@ -125,23 +125,23 @@ export const ModToolsView: FC<{}> = props =>
<>
{ isVisible &&
<NitroCardView className="nitro-mod-tools min-w-[200px]" theme="primary-slim" uniqueKey="mod-tools" windowPosition={ DraggableWindowPosition.TOP_LEFT } >
<NitroCardHeaderView headerText={ 'Mod Tools' } onCloseClick={ event => setIsVisible(false) } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.modtools.title') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardContentView className="text-black" gap={ 2 }>
<Button active={ isRoomInfoOpen } disabled={ (currentRoomId <= 0) } gap={ 2 } justifyContent="start" onClick={ event => CreateLinkEvent(`mod-tools/toggle-room-info/${ currentRoomId }`) }>
<div className="nitro-icon icon-small-room shrink-0" /> Room Tool
<div className="nitro-icon icon-small-room shrink-0" /> { LocalizeText('moderation.modtools.roomtool') }
</Button>
<Button active={ isRoomChatlogOpen } disabled={ (currentRoomId <= 0) } gap={ 2 } innerRef={ elementRef } justifyContent="start" onClick={ event => CreateLinkEvent(`mod-tools/toggle-room-chatlog/${ currentRoomId }`) }>
<div className="nitro-icon icon-chat-history shrink-0" /> Chatlog Tool
<div className="nitro-icon icon-chat-history shrink-0" /> { LocalizeText('moderation.modtools.roomchatlogs') }
</Button>
<Button active={ !!isUserInfoOpen } disabled={ !selectedUser } gap={ 2 } justifyContent="start" onClick={ () => CreateLinkEvent(`mod-tools/toggle-user-info/${ selectedUser.userId }`) }>
<div className="nitro-icon icon-user shrink-0" />
{ selectedUser
? <span className="truncate">{ selectedUser.username }</span>
: <span className="opacity-50 italic">Select a user</span>
: <span className="opacity-50 italic">{ LocalizeText('moderation.modtools.userinfo') }</span>
}
</Button>
<Button active={ isTicketsVisible } gap={ 2 } justifyContent="start" onClick={ () => setIsTicketsVisible(prevValue => !prevValue) }>
<div className="nitro-icon icon-tickets shrink-0" /> Report Tool
<div className="nitro-icon icon-tickets shrink-0" /> { LocalizeText('moderation.modtools.tickets') }
</Button>
</NitroCardContentView>
</NitroCardView> }
@@ -1,6 +1,6 @@
import { ChatRecordData, CreateLinkEvent } from '@nitrots/nitro-renderer';
import { FC, useMemo } from 'react';
import { TryVisitRoom } from '../../../../api';
import { LocalizeText, TryVisitRoom } from '../../../../api';
import { Button, Column, Flex, Grid, InfiniteScroll, Text } from '../../../../common';
import { useModTools } from '../../../../hooks';
import { ChatlogRecord } from './ChatlogRecord';
@@ -49,8 +49,8 @@ export const ChatlogView: FC<ChatlogViewProps> = props =>
<Flex alignItems="center" className="bg-muted rounded p-2" gap={ 2 } justifyContent="between">
<Text bold truncate>{ props.roomName }</Text>
<div className="flex gap-1 shrink-0">
<Button size="sm" onClick={ event => TryVisitRoom(props.roomId) }>Visit</Button>
<Button size="sm" onClick={ event => openRoomInfo(props.roomId) }>Room Tools</Button>
<Button size="sm" onClick={ event => TryVisitRoom(props.roomId) }>{ LocalizeText('moderation.chatlog.visit') }</Button>
<Button size="sm" onClick={ event => openRoomInfo(props.roomId) }>{ LocalizeText('moderation.chatlog.roomtools') }</Button>
</div>
</Flex>
);
@@ -61,9 +61,9 @@ export const ChatlogView: FC<ChatlogViewProps> = props =>
<Column fit gap={ 0 } overflow="hidden">
<Column gap={ 2 }>
<Grid className="text-black font-bold border-bottom pb-1 text-[11px] uppercase opacity-60 tracking-wider" gap={ 1 }>
<div className="col-span-2">Time</div>
<div className="col-span-3">User</div>
<div className="col-span-7">Message</div>
<div className="col-span-2">{ LocalizeText('moderation.chatlog.col.time') }</div>
<div className="col-span-3">{ LocalizeText('moderation.chatlog.col.user') }</div>
<div className="col-span-7">{ LocalizeText('moderation.chatlog.col.message') }</div>
</Grid>
</Column>
{ (records && (records.length > 0)) &&
@@ -1,6 +1,6 @@
import { ChatRecordData, GetRoomChatlogMessageComposer, RoomChatlogEvent } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { SendMessageComposer } from '../../../../api';
import { LocalizeText, SendMessageComposer } from '../../../../api';
import { DraggableWindowPosition, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common';
import { useMessageEvent } from '../../../../hooks';
import { ChatlogView } from '../chatlog/ChatlogView';
@@ -34,7 +34,7 @@ export const ModToolsChatlogView: FC<ModToolsChatlogViewProps> = props =>
return (
<NitroCardView className="nitro-mod-tools-chatlog min-w-[400px] max-h-[500px]" theme="primary-slim" windowPosition={ DraggableWindowPosition.TOP_LEFT }>
<NitroCardHeaderView headerText={ `Room Chatlog` } onCloseClick={ onCloseClick } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.chatlog.room') } onCloseClick={ onCloseClick } />
<NitroCardContentView className="text-black" overflow="auto">
{ roomChatlog &&
<ChatlogView records={ [ roomChatlog ] } /> }
@@ -1,6 +1,6 @@
import { CreateLinkEvent, GetModeratorRoomInfoMessageComposer, ModerateRoomMessageComposer, ModeratorActionMessageComposer, ModeratorRoomInfoEvent } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { SendMessageComposer, TryVisitRoom } from '../../../../api';
import { LocalizeText, SendMessageComposer, TryVisitRoom } from '../../../../api';
import { Button, Column, DraggableWindowPosition, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
import { useMessageEvent } from '../../../../hooks';
@@ -70,7 +70,7 @@ export const ModToolsRoomView: FC<ModToolsRoomViewProps> = props =>
return (
<NitroCardView className="nitro-mod-tools-room min-w-[280px]" theme="primary-slim" windowPosition={ DraggableWindowPosition.TOP_LEFT }>
<NitroCardHeaderView headerText={ 'Room Info' } onCloseClick={ event => onCloseClick() } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.roomtool.info.title') } onCloseClick={ event => onCloseClick() } />
<NitroCardContentView className="text-black" gap={ 2 }>
{ name &&
<div className="bg-muted rounded px-2 py-1.5 text-center">
@@ -80,41 +80,41 @@ export const ModToolsRoomView: FC<ModToolsRoomViewProps> = props =>
<div className="flex gap-2">
<Column grow gap={ 1 }>
<div className="flex items-center gap-1">
<Text bold className="opacity-60 shrink-0">Owner:</Text>
<Text bold className="opacity-60 shrink-0">{ LocalizeText('moderation.roomtool.roomowner.title') }</Text>
<Text bold pointer truncate underline onClick={ () => CreateLinkEvent(`mod-tools/open-user-info/${ ownerId }`) }>{ ownerName }</Text>
</div>
<div className="flex items-center gap-1">
<Text bold className="opacity-60 shrink-0">Users in room:</Text>
<Text bold className="opacity-60 shrink-0">{ LocalizeText('moderation.roomtool.usersinroom.title') }</Text>
<Text>{ usersInRoom }</Text>
</div>
<div className="flex items-center gap-1">
<Text bold className="opacity-60 shrink-0">Owner here:</Text>
<Text className={ ownerInRoom ? 'text-green-700' : 'text-red-700' }>{ ownerInRoom ? 'Yes' : 'No' }</Text>
<Text bold className="opacity-60 shrink-0">{ LocalizeText('moderation.roomtool.ownerinroom.title') }</Text>
<Text className={ ownerInRoom ? 'text-green-700' : 'text-red-700' }>{ ownerInRoom ? LocalizeText('moderation.roomtool.true.title') : LocalizeText('moderation.roomtool.false.title') }</Text>
</div>
</Column>
<div className="flex flex-col gap-1 shrink-0">
<Button onClick={ event => TryVisitRoom(roomId) }>Visit Room</Button>
<Button onClick={ event => CreateLinkEvent(`mod-tools/open-room-chatlog/${ roomId }`) }>Chatlog</Button>
<Button onClick={ event => TryVisitRoom(roomId) }>{ LocalizeText('moderation.roomtool.button.visit.title') }</Button>
<Button onClick={ event => CreateLinkEvent(`mod-tools/open-room-chatlog/${ roomId }`) }>{ LocalizeText('moderation.modtools.roomchatlogs') }</Button>
</div>
</div>
<Column className="bg-muted rounded p-2" gap={ 1 }>
<div className="flex items-center gap-2">
<input checked={ kickUsers } className="form-check-input" type="checkbox" onChange={ event => setKickUsers(event.target.checked) } />
<Text small>Kick everyone out</Text>
<Text small>{ LocalizeText('moderation.roomtool.kickall.title') }</Text>
</div>
<div className="flex items-center gap-2">
<input checked={ lockRoom } className="form-check-input" type="checkbox" onChange={ event => setLockRoom(event.target.checked) } />
<Text small>Enable the doorbell</Text>
<Text small>{ LocalizeText('moderation.roomtool.closeroom.title') }</Text>
</div>
<div className="flex items-center gap-2">
<input checked={ changeRoomName } className="form-check-input" type="checkbox" onChange={ event => setChangeRoomName(event.target.checked) } />
<Text small>Change room name</Text>
<Text small>{ LocalizeText('moderation.roomtool.inappropiatename.title') }</Text>
</div>
</Column>
<textarea className="min-h-[60px] px-2 py-1.5 rounded text-sm border border-black/10" placeholder="Type a mandatory message..." value={ message } onChange={ event => setMessage(event.target.value) }></textarea>
<textarea className="min-h-[60px] px-2 py-1.5 rounded text-sm border border-black/10" placeholder={ LocalizeText('moderation.roomtool.presets.title') } value={ message } onChange={ event => setMessage(event.target.value) }></textarea>
<div className="flex gap-2">
<Button className="grow" variant="danger" onClick={ event => handleClick('send_message') }>Send Caution</Button>
<Button className="grow" onClick={ event => handleClick('alert_only') }>Send Alert</Button>
<Button className="grow" variant="danger" onClick={ event => handleClick('send_message') }>{ LocalizeText('moderation.roomtool.button.caution.title') }</Button>
<Button className="grow" onClick={ event => handleClick('alert_only') }>{ LocalizeText('moderation.roomtool.button.message.title') }</Button>
</div>
</NitroCardContentView>
</NitroCardView>
@@ -1,6 +1,6 @@
import { CfhChatlogData, CfhChatlogEvent, GetCfhChatlogMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { SendMessageComposer } from '../../../../api';
import { LocalizeText, SendMessageComposer } from '../../../../api';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common';
import { useMessageEvent } from '../../../../hooks';
import { ChatlogView } from '../chatlog/ChatlogView';
@@ -32,7 +32,7 @@ export const CfhChatlogView: FC<CfhChatlogViewProps> = props =>
return (
<NitroCardView className="nitro-mod-tools-chatlog" theme="primary-slim">
<NitroCardHeaderView headerText={ 'Issue Chatlog' } onCloseClick={ onCloseClick } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.chatlog.issue') } onCloseClick={ onCloseClick } />
<NitroCardContentView className="text-black">
{ chatlogData && <ChatlogView records={ [ chatlogData.chatRecord ] } /> }
</NitroCardContentView>
@@ -35,33 +35,33 @@ export const ModToolsIssueInfoView: FC<IssueInfoViewProps> = props =>
return (
<>
<NitroCardView className="nitro-mod-tools-handle-issue" theme="primary-slim">
<NitroCardHeaderView headerText={ 'Resolving issue ' + issueId } onCloseClick={ () => onIssueInfoClosed(issueId) } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.issue.resolving', [ 'id' ], [ String(issueId) ]) } onCloseClick={ () => onIssueInfoClosed(issueId) } />
<NitroCardContentView className="text-black">
<Text fontSize={ 4 }>Issue Information</Text>
<Text fontSize={ 4 }>{ LocalizeText('moderation.issue.info') }</Text>
<Grid overflow="auto">
<Column size={ 8 }>
<table className="table table-striped table-sm table-text-small text-black m-0">
<tbody>
<tr>
<th>Source</th>
<th>{ LocalizeText('moderation.issue.source') }</th>
<td>{ GetIssueCategoryName(ticket.categoryId) }</td>
</tr>
<tr>
<th>Category</th>
<th>{ LocalizeText('moderation.issue.category') }</th>
<td className="text-break">{ LocalizeText('help.cfh.topic.' + ticket.reportedCategoryId) }</td>
</tr>
<tr>
<th>Description</th>
<th>{ LocalizeText('moderation.issue.description') }</th>
<td className="text-break">{ ticket.message }</td>
</tr>
<tr>
<th>Caller</th>
<th>{ LocalizeText('moderation.issue.caller') }</th>
<td>
<Text bold pointer underline onClick={ event => openUserInfo(ticket.reporterUserId) }>{ ticket.reporterUserName }</Text>
</td>
</tr>
<tr>
<th>Reported User</th>
<th>{ LocalizeText('moderation.issue.reported') }</th>
<td>
<Text bold pointer underline onClick={ event => openUserInfo(ticket.reportedUserId) }>{ ticket.reportedUserName }</Text>
</td>
@@ -70,11 +70,11 @@ export const ModToolsIssueInfoView: FC<IssueInfoViewProps> = props =>
</table>
</Column>
<Column gap={ 1 } size={ 4 }>
<Button variant="secondary" onClick={ () => setcfhChatlogOpen(!cfhChatlogOpen) }>Chatlog</Button>
<Button onClick={ event => closeIssue(CloseIssuesMessageComposer.RESOLUTION_USELESS) }>Close as useless</Button>
<Button variant="danger" onClick={ event => closeIssue(CloseIssuesMessageComposer.RESOLUTION_ABUSIVE) }>Close as abusive</Button>
<Button variant="success" onClick={ event => closeIssue(CloseIssuesMessageComposer.RESOLUTION_RESOLVED) }>Close as resolved</Button>
<Button variant="secondary" onClick={ event => releaseIssue(issueId) } >Release</Button>
<Button variant="secondary" onClick={ () => setcfhChatlogOpen(!cfhChatlogOpen) }>{ LocalizeText('moderation.issue.chatlog') }</Button>
<Button onClick={ event => closeIssue(CloseIssuesMessageComposer.RESOLUTION_USELESS) }>{ LocalizeText('moderation.issue.close.useless') }</Button>
<Button variant="danger" onClick={ event => closeIssue(CloseIssuesMessageComposer.RESOLUTION_ABUSIVE) }>{ LocalizeText('moderation.issue.close.abusive') }</Button>
<Button variant="success" onClick={ event => closeIssue(CloseIssuesMessageComposer.RESOLUTION_RESOLVED) }>{ LocalizeText('moderation.issue.close.resolved') }</Button>
<Button variant="secondary" onClick={ event => releaseIssue(issueId) } >{ LocalizeText('moderation.issue.release') }</Button>
</Column>
</Grid>
</NitroCardContentView>
@@ -1,6 +1,6 @@
import { IssueMessageData, ReleaseIssuesMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useRef } from 'react';
import { SendMessageComposer } from '../../../../api';
import { LocalizeText, SendMessageComposer } from '../../../../api';
import { Button, Column, Grid } from '../../../../common';
interface ModToolsMyIssuesTabViewProps
@@ -28,9 +28,9 @@ export const ModToolsMyIssuesTabView: FC<ModToolsMyIssuesTabViewProps> = props =
<Column gap={ 0 } overflow="hidden">
<Column gap={ 2 }>
<Grid className="text-black font-bold border-bottom pb-1" gap={ 1 }>
<div className="col-span-2">Type</div>
<div className="col-span-3">Room/Player</div>
<div className="col-span-3">Opened</div>
<div className="col-span-2">{ LocalizeText('moderation.tickets.col.type') }</div>
<div className="col-span-3">{ LocalizeText('moderation.tickets.col.roomPlayer') }</div>
<div className="col-span-3">{ LocalizeText('moderation.tickets.col.opened') }</div>
<div className="col-span-2"></div>
<div className="col-span-2"></div>
</Grid>
@@ -44,10 +44,10 @@ export const ModToolsMyIssuesTabView: FC<ModToolsMyIssuesTabViewProps> = props =
<div className="col-span-3">{ issue.reportedUserName }</div>
<div className="col-span-3">{ new Date(Date.now() - issue.issueAgeInMilliseconds).toLocaleTimeString() }</div>
<div className="col-span-2">
<Button variant="primary" onClick={ event => handleIssue(issue.issueId) }>Handle</Button>
<Button variant="primary" onClick={ event => handleIssue(issue.issueId) }>{ LocalizeText('moderation.tickets.handle') }</Button>
</div>
<div className="col-span-2">
<Button variant="danger" onClick={ () => releaseIssue(issue.issueId) }>Release</Button>
<Button variant="danger" onClick={ () => releaseIssue(issue.issueId) }>{ LocalizeText('moderation.tickets.release') }</Button>
</div>
</Grid>
);
@@ -1,6 +1,6 @@
import { IssueMessageData, PickIssuesMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useRef } from 'react';
import { SendMessageComposer } from '../../../../api';
import { LocalizeText, SendMessageComposer } from '../../../../api';
import { Button, Column, Grid } from '../../../../common';
interface ModToolsOpenIssuesTabViewProps
@@ -27,9 +27,9 @@ export const ModToolsOpenIssuesTabView: FC<ModToolsOpenIssuesTabViewProps> = pro
<Column gap={ 0 } overflow="hidden">
<Column gap={ 2 }>
<Grid className="text-black font-bold border-bottom pb-1" gap={ 1 }>
<div className="col-span-2">Type</div>
<div className="col-span-3">Room/Player</div>
<div className="col-span-4">Opened</div>
<div className="col-span-2">{ LocalizeText('moderation.tickets.col.type') }</div>
<div className="col-span-3">{ LocalizeText('moderation.tickets.col.roomPlayer') }</div>
<div className="col-span-4">{ LocalizeText('moderation.tickets.col.opened') }</div>
<div className="col-span-3"></div>
</Grid>
</Column>
@@ -42,7 +42,7 @@ export const ModToolsOpenIssuesTabView: FC<ModToolsOpenIssuesTabViewProps> = pro
<div className="col-span-3">{ issue.reportedUserName }</div>
<div className="col-span-4">{ new Date(Date.now() - issue.issueAgeInMilliseconds).toLocaleTimeString() }</div>
<div className="col-span-3">
<Button variant="success" onClick={ () => pickIssue(issue.issueId) }>Pick Issue</Button>
<Button variant="success" onClick={ () => pickIssue(issue.issueId) }>{ LocalizeText('moderation.tickets.pick') }</Button>
</div>
</Grid>
);
@@ -1,5 +1,6 @@
import { IssueMessageData } from '@nitrots/nitro-renderer';
import { FC } from 'react';
import { LocalizeText } from '../../../../api';
import { Column, Grid } from '../../../../common';
interface ModToolsPickedIssuesTabViewProps
@@ -15,10 +16,10 @@ export const ModToolsPickedIssuesTabView: FC<ModToolsPickedIssuesTabViewProps> =
<Column gap={ 0 } overflow="hidden">
<Column gap={ 2 }>
<Grid className="text-black font-bold border-bottom pb-1" gap={ 1 }>
<div className="col-span-2">Type</div>
<div className="col-span-3">Room/Player</div>
<div className="col-span-4">Opened</div>
<div className="col-span-3">Picker</div>
<div className="col-span-2">{ LocalizeText('moderation.tickets.col.type') }</div>
<div className="col-span-3">{ LocalizeText('moderation.tickets.col.roomPlayer') }</div>
<div className="col-span-4">{ LocalizeText('moderation.tickets.col.opened') }</div>
<div className="col-span-3">{ LocalizeText('moderation.tickets.col.picker') }</div>
</Grid>
</Column>
<Column className="striped-children" gap={ 0 } overflow="auto">
@@ -1,5 +1,6 @@
import { GetSessionDataManager, IssueMessageData } from '@nitrots/nitro-renderer';
import { FC, useState } from 'react';
import { LocalizeText } from '../../../../api';
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../common';
import { useModTools } from '../../../../hooks';
import { ModToolsIssueInfoView } from './ModToolsIssueInfoView';
@@ -12,10 +13,10 @@ interface ModToolsTicketsViewProps
onCloseClick: () => void;
}
const TABS: string[] = [
'Open Issues',
'My Issues',
'Picked Issues'
const TAB_KEYS: string[] = [
'moderation.tickets.open',
'moderation.tickets.my',
'moderation.tickets.picked'
];
export const ModToolsTicketsView: FC<ModToolsTicketsViewProps> = props =>
@@ -71,12 +72,12 @@ export const ModToolsTicketsView: FC<ModToolsTicketsViewProps> = props =>
return (
<>
<NitroCardView className="nitro-mod-tools-tickets">
<NitroCardHeaderView headerText={ 'Tickets' } onCloseClick={ onCloseClick } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.tickets.title') } onCloseClick={ onCloseClick } />
<NitroCardTabsView>
{ TABS.map((tab, index) =>
{ TAB_KEYS.map((tabKey, index) =>
{
return (<NitroCardTabsItemView key={ index } isActive={ (currentTab === index) } onClick={ event => setCurrentTab(index) }>
{ tab }
{ LocalizeText(tabKey) }
</NitroCardTabsItemView>);
}) }
</NitroCardTabsView>
@@ -1,6 +1,6 @@
import { ChatRecordData, GetUserChatlogMessageComposer, UserChatlogEvent } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { SendMessageComposer } from '../../../../api';
import { LocalizeText, SendMessageComposer } from '../../../../api';
import { DraggableWindowPosition, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common';
import { useMessageEvent } from '../../../../hooks';
import { ChatlogView } from '../chatlog/ChatlogView';
@@ -34,7 +34,7 @@ export const ModToolsUserChatlogView: FC<ModToolsUserChatlogViewProps> = props =
return (
<NitroCardView className="nitro-mod-tools-chatlog" theme="primary-slim" windowPosition={ DraggableWindowPosition.TOP_LEFT }>
<NitroCardHeaderView headerText={ `User Chatlog: ${ username || '' }` } onCloseClick={ onCloseClick } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.chatlog.user', [ 'username' ], [ username || '' ]) } onCloseClick={ onCloseClick } />
<NitroCardContentView className="text-black h-full">
{ userChatlog &&
<ChatlogView records={ userChatlog } /> }
@@ -11,18 +11,18 @@ interface ModToolsUserModActionViewProps
}
const MOD_ACTION_DEFINITIONS = [
new ModActionDefinition(1, 'Alert', ModActionDefinition.ALERT, 1, 0),
new ModActionDefinition(2, 'Mute 1h', ModActionDefinition.MUTE, 2, 0),
new ModActionDefinition(3, 'Ban 18h', ModActionDefinition.BAN, 3, 0),
new ModActionDefinition(4, 'Ban 7 days', ModActionDefinition.BAN, 4, 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),
new ModActionDefinition(1, 'moderation.modaction.alert', ModActionDefinition.ALERT, 1, 0),
new ModActionDefinition(2, 'moderation.modaction.mute1h', ModActionDefinition.MUTE, 2, 0),
new ModActionDefinition(3, 'moderation.modaction.ban18h', ModActionDefinition.BAN, 3, 0),
new ModActionDefinition(4, 'moderation.modaction.ban7days', ModActionDefinition.BAN, 4, 0),
new ModActionDefinition(5, 'moderation.modaction.ban30days.step1', ModActionDefinition.BAN, 5, 0),
new ModActionDefinition(7, 'moderation.modaction.ban30days.step2', ModActionDefinition.BAN, 7, 0),
new ModActionDefinition(6, 'moderation.modaction.ban100years', ModActionDefinition.BAN, 6, 0),
new ModActionDefinition(106, 'moderation.modaction.banavataronly100years', ModActionDefinition.BAN, 6, 0),
new ModActionDefinition(101, 'moderation.modaction.kick', ModActionDefinition.KICK, 0, 0),
new ModActionDefinition(102, 'moderation.modaction.locktrade1week', ModActionDefinition.TRADE_LOCK, 0, 168),
new ModActionDefinition(104, 'moderation.modaction.locktradepermanent', ModActionDefinition.TRADE_LOCK, 0, 876000),
new ModActionDefinition(105, 'moderation.modaction.message', ModActionDefinition.MESSAGE, 0, 0),
];
export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = props =>
@@ -60,7 +60,7 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
const category = topics[selectedTopic];
if(selectedTopic === -1) errorMessage = 'You must select a CFH topic';
if(selectedTopic === -1) errorMessage = LocalizeText('moderation.modaction.error.notopic');
if(errorMessage) return sendAlert(errorMessage);
@@ -82,10 +82,10 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
const category = topics[selectedTopic];
const sanction = MOD_ACTION_DEFINITIONS[selectedAction];
if((selectedTopic === -1) || (selectedAction === -1)) errorMessage = 'You must select a CFH topic and Sanction';
else if(!settings || !settings.cfhPermission) errorMessage = 'You do not have permission to do this';
else if(!category) errorMessage = 'You must select a CFH topic';
else if(!sanction) errorMessage = 'You must select a sanction';
if((selectedTopic === -1) || (selectedAction === -1)) errorMessage = LocalizeText('moderation.modaction.error.notopicorsanction');
else if(!settings || !settings.cfhPermission) errorMessage = LocalizeText('moderation.modaction.error.nopermission');
else if(!category) errorMessage = LocalizeText('moderation.modaction.error.notopic');
else if(!sanction) errorMessage = LocalizeText('moderation.modaction.error.nosanction');
if(errorMessage)
{
@@ -101,7 +101,7 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
case ModActionDefinition.ALERT: {
if(!settings.alertPermission)
{
sendAlert('You have insufficient permissions');
sendAlert(LocalizeText('moderation.modaction.error.nopermission'));
return;
}
@@ -115,7 +115,7 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
case ModActionDefinition.BAN: {
if(!settings.banPermission)
{
sendAlert('You have insufficient permissions');
sendAlert(LocalizeText('moderation.modaction.error.nopermission'));
return;
}
@@ -126,7 +126,7 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
case ModActionDefinition.KICK: {
if(!settings.kickPermission)
{
sendAlert('You have insufficient permissions');
sendAlert(LocalizeText('moderation.modaction.error.nopermission'));
return;
}
@@ -142,7 +142,7 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
case ModActionDefinition.MESSAGE: {
if(message.trim().length === 0)
{
sendAlert('Please write a message to user');
sendAlert(LocalizeText('moderation.modaction.error.emptymessage'));
return;
}
@@ -161,23 +161,23 @@ export const ModToolsUserModActionView: FC<ModToolsUserModActionViewProps> = pro
return (
<NitroCardView className="nitro-mod-tools-user-action" theme="primary-slim" windowPosition={ DraggableWindowPosition.TOP_LEFT }>
<NitroCardHeaderView headerText={ 'Mod Action: ' + (user ? user.username : '') } onCloseClick={ () => onCloseClick() } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.modaction.title', [ 'username' ], [ user ? user.username : '' ]) } onCloseClick={ () => onCloseClick() } />
<NitroCardContentView className="text-black">
<select className="form-select form-select-sm" value={ selectedTopic } onChange={ event => setSelectedTopic(parseInt(event.target.value)) }>
<option disabled value={ -1 }>CFH Topic</option>
<option disabled value={ -1 }>{ LocalizeText('moderation.modaction.cfhtopic') }</option>
{ topics.map((topic, index) => <option key={ index } value={ index }>{ LocalizeText('help.cfh.topic.' + topic.id) }</option>) }
</select>
<select className="form-select form-select-sm" value={ selectedAction } onChange={ event => setSelectedAction(parseInt(event.target.value)) }>
<option disabled value={ -1 }>Sanction Type</option>
{ MOD_ACTION_DEFINITIONS.map((action, index) => <option key={ index } value={ index }>{ action.name }</option>) }
<option disabled value={ -1 }>{ LocalizeText('moderation.modaction.sanctiontype') }</option>
{ MOD_ACTION_DEFINITIONS.map((action, index) => <option key={ index } value={ index }>{ LocalizeText(action.name) }</option>) }
</select>
<div className="flex flex-col gap-1">
<Text small>Optional message type, overrides default</Text>
<Text small>{ LocalizeText('moderation.modaction.message.hint') }</Text>
<textarea className="min-h-[calc(1.5em+ .5rem+2px)] px-[.5rem] py-[.25rem] rounded-[.2rem]" value={ message } onChange={ event => setMessage(event.target.value) } />
</div>
<Flex gap={ 1 } justifyContent="between">
<Button variant="primary" onClick={ sendDefaultSanction }>Default Sanction</Button>
<Button variant="success" onClick={ sendSanction }>Sanction</Button>
<Button variant="primary" onClick={ sendDefaultSanction }>{ LocalizeText('moderation.modaction.defaultsanction') }</Button>
<Button variant="success" onClick={ sendSanction }>{ LocalizeText('moderation.modaction.sanction') }</Button>
</Flex>
</NitroCardContentView>
</NitroCardView>
@@ -1,6 +1,6 @@
import { GetRoomVisitsMessageComposer, RoomVisitsData, RoomVisitsEvent } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react';
import { SendMessageComposer, TryVisitRoom } from '../../../../api';
import { LocalizeText, SendMessageComposer, TryVisitRoom } from '../../../../api';
import { Column, DraggableWindowPosition, Grid, InfiniteScroll, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
import { useMessageEvent } from '../../../../hooks';
@@ -33,14 +33,14 @@ export const ModToolsUserRoomVisitsView: FC<ModToolsUserRoomVisitsViewProps> = p
return (
<NitroCardView className="nitro-mod-tools-user-visits" theme="primary-slim" windowPosition={ DraggableWindowPosition.TOP_LEFT }>
<NitroCardHeaderView headerText={ 'User Visits' } onCloseClick={ onCloseClick } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.roomvisits.title') } onCloseClick={ onCloseClick } />
<NitroCardContentView className="text-black" gap={ 1 }>
<Column fullHeight gap={ 0 } overflow="hidden">
<Column gap={ 2 }>
<Grid className="text-black font-bold border-bottom pb-1" gap={ 1 }>
<div className="col-span-2">Time</div>
<div className="col-span-7">Room name</div>
<div className="col-span-3">Visit</div>
<div className="col-span-2">{ LocalizeText('moderation.roomvisits.col.time') }</div>
<div className="col-span-7">{ LocalizeText('moderation.roomvisits.col.roomname') }</div>
<div className="col-span-3">{ LocalizeText('moderation.roomvisits.col.visit') }</div>
</Grid>
</Column>
<InfiniteScroll rowRender={ row =>
@@ -49,7 +49,7 @@ export const ModToolsUserRoomVisitsView: FC<ModToolsUserRoomVisitsViewProps> = p
<Grid alignItems="center" className="text-black py-1 border-bottom" fullHeight={ false } gap={ 1 }>
<Text className="col-span-2">{ row.enterHour.toString().padStart(2, '0') }: { row.enterMinute.toString().padStart(2, '0') }</Text>
<Text className="col-span-7">{ row.roomName }</Text>
<Text bold pointer underline className="col-span-3" variant="primary" onClick={ event => TryVisitRoom(row.roomId) }>Visit Room</Text>
<Text bold pointer underline className="col-span-3" variant="primary" onClick={ event => TryVisitRoom(row.roomId) }>{ LocalizeText('moderation.roomvisits.visitroom') }</Text>
</Grid>
);
} } rows={ roomVisitData?.rooms ?? [] } />
@@ -1,6 +1,6 @@
import { ModMessageMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useState } from 'react';
import { ISelectedUser, SendMessageComposer } from '../../../../api';
import { ISelectedUser, LocalizeText, SendMessageComposer } from '../../../../api';
import { Button, DraggableWindowPosition, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
import { useNotification } from '../../../../hooks';
@@ -22,7 +22,7 @@ export const ModToolsUserSendMessageView: FC<ModToolsUserSendMessageViewProps> =
{
if(message.trim().length === 0)
{
simpleAlert('Please write a message to user.', null, null, null, 'Error', null);
simpleAlert(LocalizeText('moderation.sendmessage.error.empty'), null, null, null, LocalizeText('moderation.error'), null);
return;
}
@@ -34,11 +34,11 @@ export const ModToolsUserSendMessageView: FC<ModToolsUserSendMessageViewProps> =
return (
<NitroCardView className="nitro-mod-tools-user-message" theme="primary-slim" windowPosition={ DraggableWindowPosition.TOP_LEFT }>
<NitroCardHeaderView headerText={ 'Send Message' } onCloseClick={ () => onCloseClick() } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.sendmessage.title') } onCloseClick={ () => onCloseClick() } />
<NitroCardContentView className="text-black">
<Text>Message To: { user.username }</Text>
<Text>{ LocalizeText('moderation.sendmessage.to', [ 'username' ], [ user.username ]) }</Text>
<textarea className="min-h-[calc(1.5em+ .5rem+2px)] px-[.5rem] py-[.25rem] rounded-[.2rem]" value={ message } onChange={ event => setMessage(event.target.value) }></textarea>
<Button fullWidth onClick={ sendMessage }>Send message</Button>
<Button fullWidth onClick={ sendMessage }>{ LocalizeText('moderation.sendmessage.send') }</Button>
</NitroCardContentView>
</NitroCardView>
);
@@ -27,60 +27,60 @@ export const ModToolsUserView: FC<ModToolsUserViewProps> = props =>
return [
{
localeKey: 'modtools.userinfo.userName',
localeKey: 'moderation.userinfo.userName',
value: userInfo.userName,
showOnline: true
},
{
localeKey: 'modtools.userinfo.cfhCount',
localeKey: 'moderation.userinfo.cfhCount',
value: userInfo.cfhCount.toString()
},
{
localeKey: 'modtools.userinfo.abusiveCfhCount',
localeKey: 'moderation.userinfo.abusiveCfhCount',
value: userInfo.abusiveCfhCount.toString()
},
{
localeKey: 'modtools.userinfo.cautionCount',
localeKey: 'moderation.userinfo.cautionCount',
value: userInfo.cautionCount.toString()
},
{
localeKey: 'modtools.userinfo.banCount',
localeKey: 'moderation.userinfo.banCount',
value: userInfo.banCount.toString()
},
{
localeKey: 'modtools.userinfo.lastSanctionTime',
localeKey: 'moderation.userinfo.lastSanctionTime',
value: userInfo.lastSanctionTime
},
{
localeKey: 'modtools.userinfo.tradingLockCount',
localeKey: 'moderation.userinfo.tradingLockCount',
value: userInfo.tradingLockCount.toString()
},
{
localeKey: 'modtools.userinfo.tradingExpiryDate',
localeKey: 'moderation.userinfo.tradingExpiryDate',
value: userInfo.tradingExpiryDate
},
{
localeKey: 'modtools.userinfo.minutesSinceLastLogin',
localeKey: 'moderation.userinfo.minutesSinceLastLogin',
value: FriendlyTime.format(userInfo.minutesSinceLastLogin * 60, '.ago', 2)
},
{
localeKey: 'modtools.userinfo.lastPurchaseDate',
localeKey: 'moderation.userinfo.lastPurchaseDate',
value: userInfo.lastPurchaseDate
},
{
localeKey: 'modtools.userinfo.primaryEmailAddress',
localeKey: 'moderation.userinfo.primaryEmailAddress',
value: userInfo.primaryEmailAddress
},
{
localeKey: 'modtools.userinfo.identityRelatedBanCount',
localeKey: 'moderation.userinfo.identityRelatedBanCount',
value: userInfo.identityRelatedBanCount.toString()
},
{
localeKey: 'modtools.userinfo.registrationAgeInMinutes',
localeKey: 'moderation.userinfo.registrationAgeInMinutes',
value: FriendlyTime.format(userInfo.registrationAgeInMinutes * 60, '.ago', 2)
},
{
localeKey: 'modtools.userinfo.userClassification',
localeKey: 'moderation.userinfo.userClassification',
value: userInfo.userClassification
}
];
@@ -105,7 +105,7 @@ export const ModToolsUserView: FC<ModToolsUserViewProps> = props =>
return (
<>
<NitroCardView className="nitro-mod-tools-user" theme="primary-slim" windowPosition={ DraggableWindowPosition.TOP_LEFT }>
<NitroCardHeaderView headerText={ LocalizeText('modtools.userinfo.title', [ 'username' ], [ userInfo.userName ]) } onCloseClick={ () => onCloseClick() } />
<NitroCardHeaderView headerText={ LocalizeText('moderation.userinfo.title', [ 'username' ], [ userInfo.userName ]) } onCloseClick={ () => onCloseClick() } />
<NitroCardContentView className="text-black">
<Grid overflow="hidden">
<Column overflow="auto" size={ 8 }>
@@ -130,16 +130,16 @@ export const ModToolsUserView: FC<ModToolsUserViewProps> = props =>
</Column>
<Column gap={ 1 } size={ 4 }>
<Button onClick={ event => CreateLinkEvent(`mod-tools/open-user-chatlog/${ userId }`) }>
Room Chat
{ LocalizeText('moderation.userinfo.roomchat') }
</Button>
<Button onClick={ event => setSendMessageVisible(!sendMessageVisible) }>
Send Message
{ LocalizeText('moderation.userinfo.sendmessage') }
</Button>
<Button onClick={ event => setRoomVisitsVisible(!roomVisitsVisible) }>
Room Visits
{ LocalizeText('moderation.userinfo.roomvisits') }
</Button>
<Button onClick={ event => setModActionVisible(!modActionVisible) }>
Mod Action
{ LocalizeText('moderation.userinfo.modaction') }
</Button>
</Column>
</Grid>