make toggle a separate component so we can display an outcome icon beside it

This commit is contained in:
gingervitis 2020-12-25 20:29:15 -08:00
parent 6cb8cee8b7
commit 310c6573d3
6 changed files with 133 additions and 70 deletions

View file

@ -1,34 +1,18 @@
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 format from 'date-fns/format'
import {
CHAT_HISTORY,
UPDATE_CHAT_MESSGAE_VIZ,
fetchData,
} from "../utils/apis";
import ToggleSwitch from './components/toggle';
import { CHAT_HISTORY, fetchData } from "../utils/apis";
import { MessageType } from '../types/chat';
const { Title } = Typography;
interface Message {
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[]) {
function createUserNameFilters(messages: MessageType[]) {
const filtered = messages.reduce((acc, curItem) => {
const curAuthor = curItem.author;
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() {
const [messages, setMessages] = useState([]);
const [selectedRowKeys, setSelectedRows] = useState([]);
const getInfo = async () => {
try {
@ -96,6 +51,7 @@ export default function Chat() {
const updateMessage = message => {
const messageIndex = messages.findIndex(m => m.id === message.id);
console.log("====update?", message, messages[messageIndex])
messages.splice(messageIndex, 1, message)
setMessages([...messages]);
};
@ -105,17 +61,16 @@ export default function Chat() {
}, []);
const nameFilters = createUserNameFilters(messages);
const rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
const rowSelection: RowSelectionType = {
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',
dataIndex: 'timestamp',
@ -160,7 +115,7 @@ export default function Chat() {
filters: [{ text: 'visible', value: true }, { text: 'hidden', value: false }],
onFilter: (value, record) => record.visible === value,
render: (visible, record) => (
<MessageToggle
<ToggleSwitch
isVisible={visible}
message={record}
setMessage={updateMessage}
@ -174,6 +129,16 @@ export default function Chat() {
return (
<div className="chat-messages">
<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
size="small"
className="messages-table"
@ -183,12 +148,7 @@ export default function Chat() {
dataSource={messages}
columns={chatColumns}
rowKey={(row) => row.id}
rowSelection={{
type: "checkbox",
...rowSelection,
}}
rowSelection={rowSelection}
/>
</div>)
}

View 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>
);
}

View file

@ -17,4 +17,16 @@
}
.ant-table-filter-dropdown {
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;
}
}

View file

@ -3,4 +3,10 @@
--owncast-purple-highlight: #ccd;
--online-color: #73dd3f;
--ant-error: #ff4d4f;
--ant-success: #52c41a;
--ant-warning: #faad14;
}

View file

@ -41,4 +41,4 @@ pre {
background-color: rgb(44, 44, 44);
color:lightgrey;
}
}
}

10
web/types/chat.ts Normal file
View file

@ -0,0 +1,10 @@
export interface MessageType {
author: string;
body: string;
id: string;
key: string;
name: string;
timestamp: string;
type: string;
visible: boolean;
}