created chatlog component

This commit is contained in:
dank074 2021-10-15 21:34:36 -05:00
parent 37f0497e71
commit 2d2604cdc9
10 changed files with 164 additions and 113 deletions

View File

@ -2,5 +2,6 @@
width: 200px; width: 200px;
} }
@import './views/chatlog/ModToolsChatlogView'; @import './views/room-chatlog/ModToolsChatlogView';
@import './views/room/ModToolsRoomView'; @import './views/room/ModToolsRoomView';
@import './views/chatlog/ChatlogView';

View File

@ -9,6 +9,7 @@ import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../
import { ModToolsContextProvider } from './context/ModToolsContext'; import { ModToolsContextProvider } from './context/ModToolsContext';
import { ModToolsViewProps } from './ModToolsView.types'; import { ModToolsViewProps } from './ModToolsView.types';
import { initialModTools, ModToolsActions, ModToolsReducer } from './reducers/ModToolsReducer'; import { initialModTools, ModToolsActions, ModToolsReducer } from './reducers/ModToolsReducer';
import { ModToolsChatlogView } from './views/room-chatlog/ModToolsChatlogView';
import { ModToolsRoomView } from './views/room/ModToolsRoomView'; import { ModToolsRoomView } from './views/room/ModToolsRoomView';
import { ModToolsTicketsView } from './views/tickets/ModToolsTicketsView'; import { ModToolsTicketsView } from './views/tickets/ModToolsTicketsView';
import { ModToolsUserView } from './views/user/ModToolsUserView'; import { ModToolsUserView } from './views/user/ModToolsUserView';
@ -22,6 +23,7 @@ export const ModToolsView: FC<ModToolsViewProps> = props =>
const [ isRoomVisible, setIsRoomVisible ] = useState(false); const [ isRoomVisible, setIsRoomVisible ] = useState(false);
const [ isUserVisible, setIsUserVisible ] = useState(false); const [ isUserVisible, setIsUserVisible ] = useState(false);
const [ isTicketsVisible, setIsTicketsVisible ] = useState(false); const [ isTicketsVisible, setIsTicketsVisible ] = useState(false);
const [ isChatlogVisible, setChatlogVisible ] = useState(false);
const onModToolsEvent = useCallback((event: ModToolsEvent) => const onModToolsEvent = useCallback((event: ModToolsEvent) =>
{ {
@ -166,7 +168,7 @@ export const ModToolsView: FC<ModToolsViewProps> = props =>
<NitroCardHeaderView headerText={ 'Mod Tools' } onCloseClick={ event => setIsVisible(false) } /> <NitroCardHeaderView headerText={ 'Mod Tools' } onCloseClick={ event => setIsVisible(false) } />
<NitroCardContentView className="text-black"> <NitroCardContentView className="text-black">
<button className="btn btn-primary btn-sm w-100 mb-2" onClick={ () => handleClick('toggle_room') } disabled={ !currentRoomId }><i className="fas fa-home"></i> Room Tool</button> <button className="btn btn-primary btn-sm w-100 mb-2" onClick={ () => handleClick('toggle_room') } disabled={ !currentRoomId }><i className="fas fa-home"></i> Room Tool</button>
<button className="btn btn-primary btn-sm w-100 mb-2" onClick={ () => {} } disabled={ !currentRoomId }><i className="fas fa-comments"></i> Chatlog Tool</button> <button className="btn btn-primary btn-sm w-100 mb-2" onClick={ () => setChatlogVisible(value => !value) } disabled={ !currentRoomId }><i className="fas fa-comments"></i> Chatlog Tool</button>
<button className="btn btn-primary btn-sm w-100 mb-2" onClick={ () => setIsUserVisible(value => !value) } disabled={ !selectedUser }><i className="fas fa-user"></i> User: { selectedUser ? selectedUser.name : '' }</button> <button className="btn btn-primary btn-sm w-100 mb-2" onClick={ () => setIsUserVisible(value => !value) } disabled={ !selectedUser }><i className="fas fa-user"></i> User: { selectedUser ? selectedUser.name : '' }</button>
<button className="btn btn-primary btn-sm w-100" onClick={ () => setIsTicketsVisible(value => !value) }><i className="fas fa-exclamation-circle"></i> Report Tool</button> <button className="btn btn-primary btn-sm w-100" onClick={ () => setIsTicketsVisible(value => !value) }><i className="fas fa-exclamation-circle"></i> Report Tool</button>
</NitroCardContentView> </NitroCardContentView>
@ -174,10 +176,12 @@ export const ModToolsView: FC<ModToolsViewProps> = props =>
{ openRooms && openRooms.map(roomId => { openRooms && openRooms.map(roomId =>
{ {
return <ModToolsRoomView key={ roomId } roomId={ roomId } onCloseClick={ () => handleClick('close_room', roomId.toString()) } />; return <ModToolsRoomView key={ roomId } roomId={ roomId } onCloseClick={ () => handleClick('close_room', roomId.toString()) } />;
}) } })
}
{ isUserVisible && <ModToolsUserView /> } { isUserVisible && <ModToolsUserView /> }
{ isTicketsVisible && <ModToolsTicketsView onCloseClick={ () => setIsTicketsVisible(false) } /> } { isTicketsVisible && <ModToolsTicketsView onCloseClick={ () => setIsTicketsVisible(false) } /> }
{ isChatlogVisible && <ModToolsChatlogView roomId={currentRoomId} onCloseClick={ () => setChatlogVisible(false) }/>}
</ModToolsContextProvider> </ModToolsContextProvider>
); );
} }

View File

@ -0,0 +1,28 @@
.chatlog-messages {
color: $black;
$username-col-width: 100px;
.username-label {
width: $username-col-width;
}
.chatlog {
min-height: 200px;
min-width: 400px;
.chatlog-container {
color: $black;
div.chatlog-entry {
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
.username {
color: #1E7295;
text-decoration: underline;
width: $username-col-width;
}
}
}
}
}

View File

@ -0,0 +1,57 @@
import { UserProfileComposer } from '@nitrots/nitro-renderer';
import { FC } from 'react';
import { AutoSizer, CellMeasurerCache, List, ListRowProps, ListRowRenderer } from 'react-virtualized';
import { SendMessageHook } from '../../../../hooks';
import { ChatlogViewProps } from './ChatlogView.types';
export const ChatlogView: FC<ChatlogViewProps> = props =>
{
const { record = null } = props;
const cache = new CellMeasurerCache({
defaultHeight: 20,
fixedWidth: true
});
const rowRenderer: ListRowRenderer = (props: ListRowProps) =>
{
const item = record.chatlog[props.index];
return (
<div key={props.key} style={props.style} className="row chatlog-entry justify-content-start">
<div className="col-md-auto text-center">{item.timestamp}</div>
<div className="col-sm-2 justify-content-start username"><span className="fw-bold cursor-pointer" onClick={() => SendMessageHook(new UserProfileComposer(item.userId))}>{item.userName}</span></div>
<div className="col-lg-auto justify-content-start">{item.message}</div>
</div>
);
}
return (
<>
{record && <div className="chatlog-messages w-100 h-100 overflow-hidden">
<div className="row align-items-start w-100">
<div className="col-md-auto text-center">Time</div>
<div className="col-sm-2 username-label">User</div>
<div className="col-lg-auto">Message</div>
</div>
<div className="row w-100 h-100 chatlog">
<AutoSizer defaultWidth={400} defaultHeight={200}>
{({ height, width }) =>
{
return (
<List
width={width}
height={height}
rowCount={record.chatlog.length}
rowHeight={20}
className={'chatlog-container'}
rowRenderer={rowRenderer} />
)
}
}
</AutoSizer>
</div>
</div>}
</>
);
}

View File

@ -0,0 +1,6 @@
import { ChatRecordData } from '@nitrots/nitro-renderer';
export interface ChatlogViewProps
{
record: ChatRecordData;
}

View File

@ -1,26 +0,0 @@
.nitro-mod-tools-chatlog {
width: 480px;
.chatlog-messages {
height: 300px;
max-height: 300px;
.table {
color: $black;
> :not(caption) > * > * {
box-shadow: none;
border-bottom: 1px solid rgba(0, 0, 0, .2);
}
&.table-striped > tbody > tr:nth-of-type(odd) {
color: $black;
background: rgba(0, 0, 0, .05);
}
td {
padding: 0px 5px;
}
}
}
}

View File

@ -1,84 +0,0 @@
import { ModtoolRequestRoomChatlogComposer, ModtoolRoomChatlogEvent, ModtoolRoomChatlogLine } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { TryVisitRoom } from '../../../../api';
import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
import { ModToolsChatlogViewProps } from './ModToolsChatlogView.types';
export const ModToolsChatlogView: FC<ModToolsChatlogViewProps> = props =>
{
const { roomId = null, onCloseClick = null } = props;
const [ roomName, setRoomName ] = useState(null);
const [ messages, setMessages ] = useState<ModtoolRoomChatlogLine[]>(null);
const [ loadedRoomId, setLoadedRoomId ] = useState(null);
const [ messagesRequested, setMessagesRequested ] = useState(false);
useEffect(() =>
{
if(messagesRequested) return;
SendMessageHook(new ModtoolRequestRoomChatlogComposer(roomId));
setMessagesRequested(true);
}, [ roomId, messagesRequested, setMessagesRequested ]);
const onModtoolRoomChatlogEvent = useCallback((event: ModtoolRoomChatlogEvent) =>
{
const parser = event.getParser();
setRoomName(parser.data.roomName);
setMessages(parser.data.chatlog);
setLoadedRoomId(parser.data.roomId);
}, [ setRoomName, setMessages ]);
CreateMessageHook(ModtoolRoomChatlogEvent, onModtoolRoomChatlogEvent);
const handleClick = useCallback((action: string, value?: string) =>
{
if(!action) return;
switch(action)
{
case 'close':
onCloseClick();
return;
case 'visit_room':
TryVisitRoom(loadedRoomId);
return;
}
}, [ onCloseClick, loadedRoomId ]);
return (
<NitroCardView className="nitro-mod-tools-chatlog" simple={ true }>
<NitroCardHeaderView headerText={ 'Room Chatlog' + (roomName ? ': ' + roomName : '') } onCloseClick={ event => handleClick('close') } />
<NitroCardContentView className="text-black h-100">
<div className="w-100 d-flex justify-content-end">
<button className="btn btn-sm btn-primary me-2" onClick={ event => handleClick('visit_room') }>Visit Room</button>
<button className="btn btn-sm btn-primary">Room Tools</button>
</div>
<div className="chatlog-messages overflow-auto">
{ messages && <table className="table table-striped">
<thead>
<tr>
<th className="text-center">Time</th>
<th className="text-center">User</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{ messages.map((message, index) =>
{
return <tr key={ index }>
<td className="text-center">{ message.timestamp }</td>
<td className="text-center"><a href="#" className="fw-bold">{ message.userName }</a></td>
<td className="word-break">{ message.message }</td>
</tr>;
}) }
</tbody>
</table> }
</div>
</NitroCardContentView>
</NitroCardView>
);
}

View File

@ -0,0 +1,3 @@
.nitro-mod-tools-room-chatlog {
}

View File

@ -0,0 +1,62 @@
import { ChatRecordData, ModtoolRequestRoomChatlogComposer, ModtoolRoomChatlogEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { TryVisitRoom } from '../../../../api';
import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
import { ChatlogView } from '../chatlog/ChatlogView';
import { ModToolsChatlogViewProps } from './ModToolsChatlogView.types';
export const ModToolsChatlogView: FC<ModToolsChatlogViewProps> = props =>
{
const { roomId = null, onCloseClick = null } = props;
const [roomChatlog, setRoomChatlog] = useState<ChatRecordData>(null);
useEffect(() =>
{
SendMessageHook(new ModtoolRequestRoomChatlogComposer(roomId));
}, [roomId]);
const onModtoolRoomChatlogEvent = useCallback((event: ModtoolRoomChatlogEvent) =>
{
const parser = event.getParser();
if(!parser) return;
setRoomChatlog(parser.data);
}, [setRoomChatlog]);
CreateMessageHook(ModtoolRoomChatlogEvent, onModtoolRoomChatlogEvent);
const handleClick = useCallback((action: string, value?: string) =>
{
if(!action) return;
switch(action)
{
case 'close':
onCloseClick();
return;
case 'visit_room':
TryVisitRoom(roomChatlog.roomId);
return;
}
}, [onCloseClick, roomChatlog]);
return (
<NitroCardView className="nitro-mod-tools-room-chatlog" simple={true}>
<NitroCardHeaderView headerText={'Room Chatlog' + (roomChatlog ? ': ' + roomChatlog.roomName : '')} onCloseClick={event => handleClick('close')} />
<NitroCardContentView className="text-black h-100">
{roomChatlog &&
<>
<div className="w-100 d-flex justify-content-start">
<button className="btn btn-sm btn-primary me-2" onClick={event => handleClick('visit_room')}>Visit Room</button>
<button className="btn btn-sm btn-primary">Room Tools</button>
</div>
<ChatlogView record={roomChatlog} />
</>
}
</NitroCardContentView>
</NitroCardView>
);
}