make toggle a separate component so we can display an outcome icon beside it
This commit is contained in:
@@ -1,34 +1,18 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Table, Typography, Tooltip, Switch } from "antd";
|
import { Table, Typography, Tooltip, Switch, Button, Result } from "antd";
|
||||||
|
import { RowSelectionType } from "antd/es/table/interface";
|
||||||
import { ColumnsType } from 'antd/es/table';
|
import { ColumnsType } from 'antd/es/table';
|
||||||
import format from 'date-fns/format'
|
import format from 'date-fns/format'
|
||||||
|
|
||||||
import {
|
import ToggleSwitch from './components/toggle';
|
||||||
CHAT_HISTORY,
|
|
||||||
UPDATE_CHAT_MESSGAE_VIZ,
|
import { CHAT_HISTORY, fetchData } from "../utils/apis";
|
||||||
fetchData,
|
import { MessageType } from '../types/chat';
|
||||||
} from "../utils/apis";
|
|
||||||
|
|
||||||
const { Title } = Typography;
|
const { Title } = Typography;
|
||||||
|
|
||||||
interface Message {
|
function createUserNameFilters(messages: MessageType[]) {
|
||||||
key: string;
|
|
||||||
author: string;
|
|
||||||
body: string;
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
timestamp: string;
|
|
||||||
type: string;
|
|
||||||
visible: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MessageToggleProps {
|
|
||||||
isVisible: boolean;
|
|
||||||
message: Message;
|
|
||||||
setMessage: (message: Message) => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
function createUserNameFilters(messages: Message[]) {
|
|
||||||
const filtered = messages.reduce((acc, curItem) => {
|
const filtered = messages.reduce((acc, curItem) => {
|
||||||
const curAuthor = curItem.author;
|
const curAuthor = curItem.author;
|
||||||
if (!acc.some(item => item.text === curAuthor)) {
|
if (!acc.some(item => item.text === curAuthor)) {
|
||||||
@@ -52,38 +36,9 @@ function createUserNameFilters(messages: Message[]) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function MessageToggle({ isVisible, message, setMessage }: MessageToggleProps) {
|
|
||||||
const { id: messageId } = message;
|
|
||||||
|
|
||||||
const updateChatMessage = async () => {
|
|
||||||
const result = await fetchData(UPDATE_CHAT_MESSGAE_VIZ, {
|
|
||||||
auth: true,
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
visible: !isVisible,
|
|
||||||
id: messageId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.success && result.message === "changed") {
|
|
||||||
setMessage({
|
|
||||||
...message,
|
|
||||||
visible: !isVisible,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Switch
|
|
||||||
size="small"
|
|
||||||
onChange={updateChatMessage}
|
|
||||||
defaultChecked={isVisible}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Chat() {
|
export default function Chat() {
|
||||||
const [messages, setMessages] = useState([]);
|
const [messages, setMessages] = useState([]);
|
||||||
|
const [selectedRowKeys, setSelectedRows] = useState([]);
|
||||||
|
|
||||||
const getInfo = async () => {
|
const getInfo = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -96,6 +51,7 @@ export default function Chat() {
|
|||||||
|
|
||||||
const updateMessage = message => {
|
const updateMessage = message => {
|
||||||
const messageIndex = messages.findIndex(m => m.id === message.id);
|
const messageIndex = messages.findIndex(m => m.id === message.id);
|
||||||
|
console.log("====update?", message, messages[messageIndex])
|
||||||
messages.splice(messageIndex, 1, message)
|
messages.splice(messageIndex, 1, message)
|
||||||
setMessages([...messages]);
|
setMessages([...messages]);
|
||||||
};
|
};
|
||||||
@@ -105,17 +61,16 @@ export default function Chat() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const nameFilters = createUserNameFilters(messages);
|
const nameFilters = createUserNameFilters(messages);
|
||||||
const rowSelection = {
|
|
||||||
onChange: (selectedRowKeys, selectedRows) => {
|
const rowSelection: RowSelectionType = {
|
||||||
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
|
selectedRowKeys,
|
||||||
|
onChange: selectedKeys => {
|
||||||
|
setSelectedRows(selectedKeys);
|
||||||
},
|
},
|
||||||
getCheckboxProps: record => ({
|
|
||||||
disabled: record.name === 'Disabled User', // Column configuration not to be checked
|
|
||||||
name: record.name,
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const chatColumns: ColumnsType<Message> = [
|
|
||||||
|
const chatColumns: ColumnsType<MessageType> = [
|
||||||
{
|
{
|
||||||
title: 'Time',
|
title: 'Time',
|
||||||
dataIndex: 'timestamp',
|
dataIndex: 'timestamp',
|
||||||
@@ -160,7 +115,7 @@ export default function Chat() {
|
|||||||
filters: [{ text: 'visible', value: true }, { text: 'hidden', value: false }],
|
filters: [{ text: 'visible', value: true }, { text: 'hidden', value: false }],
|
||||||
onFilter: (value, record) => record.visible === value,
|
onFilter: (value, record) => record.visible === value,
|
||||||
render: (visible, record) => (
|
render: (visible, record) => (
|
||||||
<MessageToggle
|
<ToggleSwitch
|
||||||
isVisible={visible}
|
isVisible={visible}
|
||||||
message={record}
|
message={record}
|
||||||
setMessage={updateMessage}
|
setMessage={updateMessage}
|
||||||
@@ -174,6 +129,16 @@ export default function Chat() {
|
|||||||
return (
|
return (
|
||||||
<div className="chat-messages">
|
<div className="chat-messages">
|
||||||
<Title level={2}>Chat Messages</Title>
|
<Title level={2}>Chat Messages</Title>
|
||||||
|
<p>click things and stuff</p>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
// onClick={}
|
||||||
|
disabled={!selectedRowKeys.length}
|
||||||
|
loading={false}
|
||||||
|
>
|
||||||
|
Bulk toggle
|
||||||
|
</Button>
|
||||||
|
<Switch />
|
||||||
<Table
|
<Table
|
||||||
size="small"
|
size="small"
|
||||||
className="messages-table"
|
className="messages-table"
|
||||||
@@ -183,12 +148,7 @@ export default function Chat() {
|
|||||||
dataSource={messages}
|
dataSource={messages}
|
||||||
columns={chatColumns}
|
columns={chatColumns}
|
||||||
rowKey={(row) => row.id}
|
rowKey={(row) => row.id}
|
||||||
|
rowSelection={rowSelection}
|
||||||
rowSelection={{
|
|
||||||
type: "checkbox",
|
|
||||||
...rowSelection,
|
|
||||||
}}
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
|
|||||||
75
web/pages/components/toggle.tsx
Normal file
75
web/pages/components/toggle.tsx
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Wrapper for AntDesign Switch that makes an api call, then displays a confirmation icon upon
|
||||||
|
// TODO: make it more generic, maybe. This one is currently just for message visiblity updates.
|
||||||
|
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { Switch } from "antd";
|
||||||
|
import { CheckCircleFilled, ExclamationCircleFilled } from "@ant-design/icons";
|
||||||
|
import { fetchData, UPDATE_CHAT_MESSGAE_VIZ } from "../../utils/apis";
|
||||||
|
import { MessageType } from '../../types/chat';
|
||||||
|
|
||||||
|
interface MessageToggleProps {
|
||||||
|
isVisible: boolean;
|
||||||
|
message: MessageType;
|
||||||
|
setMessage: (message: MessageType) => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const OUTCOME_TIMEOUT = 3000;
|
||||||
|
|
||||||
|
export default function ToggleSwitch({ isVisible, message, setMessage }: MessageToggleProps) {
|
||||||
|
let outcomeTimeout = null;
|
||||||
|
const [outcome, setOutcome] = useState(0);
|
||||||
|
|
||||||
|
const { id: messageId } = message;
|
||||||
|
|
||||||
|
const resetOutcome = () => {
|
||||||
|
outcomeTimeout = setTimeout(() => { setOutcome(0)}, OUTCOME_TIMEOUT);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
clearTimeout(outcomeTimeout);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const updateChatMessage = async () => {
|
||||||
|
clearTimeout(outcomeTimeout);
|
||||||
|
setOutcome(0);
|
||||||
|
const result = await fetchData(UPDATE_CHAT_MESSGAE_VIZ, {
|
||||||
|
auth: true,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
visible: !isVisible,
|
||||||
|
id: messageId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.success && result.message === "changed") {
|
||||||
|
setMessage({ ...message, visible: !isVisible });
|
||||||
|
setOutcome(1);
|
||||||
|
} else {
|
||||||
|
setMessage({ ...message, visible: isVisible });
|
||||||
|
setOutcome(-1);
|
||||||
|
}
|
||||||
|
resetOutcome();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let outcomeIcon = <CheckCircleFilled style={{ color: 'transparent' }} />;
|
||||||
|
if (outcome) {
|
||||||
|
outcomeIcon = outcome > 0 ?
|
||||||
|
<CheckCircleFilled style={{ color: 'var(--ant-success)' }} /> :
|
||||||
|
<ExclamationCircleFilled style={{ color: 'var(--ant-warning)' }} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="toggle-switch">
|
||||||
|
<span className="outcome-icon">{outcomeIcon}</span>
|
||||||
|
<Switch
|
||||||
|
size="small"
|
||||||
|
onChange={updateChatMessage}
|
||||||
|
checked={isVisible}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -17,4 +17,16 @@
|
|||||||
}
|
}
|
||||||
.ant-table-filter-dropdown {
|
.ant-table-filter-dropdown {
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-switch {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.outcome-icon {
|
||||||
|
margin-right: .5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,4 +3,10 @@
|
|||||||
--owncast-purple-highlight: #ccd;
|
--owncast-purple-highlight: #ccd;
|
||||||
|
|
||||||
--online-color: #73dd3f;
|
--online-color: #73dd3f;
|
||||||
|
|
||||||
|
|
||||||
|
--ant-error: #ff4d4f;
|
||||||
|
--ant-success: #52c41a;
|
||||||
|
--ant-warning: #faad14;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,4 +41,4 @@ pre {
|
|||||||
background-color: rgb(44, 44, 44);
|
background-color: rgb(44, 44, 44);
|
||||||
color:lightgrey;
|
color:lightgrey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
web/types/chat.ts
Normal file
10
web/types/chat.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export interface MessageType {
|
||||||
|
author: string;
|
||||||
|
body: string;
|
||||||
|
id: string;
|
||||||
|
key: string;
|
||||||
|
name: string;
|
||||||
|
timestamp: string;
|
||||||
|
type: string;
|
||||||
|
visible: boolean;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user