import ChatbotToggle from '@patternfly/chatbot/dist/dynamic/ChatbotToggle';
import Chatbot from '@patternfly/chatbot/dist/dynamic/Chatbot';
import ChatbotContent from '@patternfly/chatbot/dist/dynamic/ChatbotContent';
import ChatbotWelcomePrompt from '@patternfly/chatbot/dist/dynamic/ChatbotWelcomePrompt';
import ChatbotFooter, { ChatbotFootnote } from '@patternfly/chatbot/dist/dynamic/ChatbotFooter';
import MessageBar from '@patternfly/chatbot/dist/dynamic/MessageBar';
import MessageBox from '@patternfly/chatbot/dist/dynamic/MessageBox';
import Message, { MessageProps } from '@patternfly/chatbot/dist/dynamic/Message';
import FileDropZone from '@patternfly/chatbot/dist/dynamic/FileDropZone';
import SourceDetailsMenuItem from '@patternfly/chatbot/dist/dynamic/SourceDetailsMenuItem';
import ChatbotAlert from '@patternfly/chatbot/dist/dynamic/ChatbotAlert';
import { Divider, DropdownGroup, DropdownItem, DropdownList, DropEvent } from '@patternfly/react-core';
import FileDetailsLabel from '@patternfly/chatbot/dist/dynamic/FileDetailsLabel';
import { BellIcon, CalendarAltIcon, ClipboardIcon, CodeIcon, UploadIcon } from '@patternfly/react-icons';
import { useDropzone } from 'react-dropzone';
import userAvatar from '../Messages/user_avatar.svg';
import patternflyAvatar from '../Messages/patternfly_avatar.jpg';
import '@patternfly/react-core/dist/styles/base.css';
import '@patternfly/chatbot/dist/css/main.css';
import { cloneElement, FunctionComponent, isValidElement, ReactNode, useState, Children } from 'react';
const initialMenuItems = [
}
name="auth-operator"
type="Pod"
/>
,
}>
Alerts
}>
Events
}>
Logs
}>
YAML - Status
}>
YAML - All contents
];
const messages: MessageProps[] = [
{
role: 'user',
content: 'Hello, can you give me an example of what you can do?',
name: 'User',
avatar: userAvatar,
avatarProps: { isBordered: true }
},
{
role: 'bot',
content: 'I sure can!',
name: 'Bot',
avatar: patternflyAvatar
}
];
export const AttachmentMenuDemo: FunctionComponent = () => {
const [chatbotVisible, setChatbotVisible] = useState(true);
const [file, setFile] = useState();
const [isLoadingFile, setIsLoadingFile] = useState(false);
const [userFacingMenuItems, setUserFacingMenuItems] = useState([]);
const [error, setError] = useState();
const [showAlert, setShowAlert] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const { open, getInputProps } = useDropzone({
onDropAccepted: (files: File[]) => {
setIsLoadingFile(true);
setIsOpen(false);
// any custom validation you may want
if (files.length > 1) {
setShowAlert(true);
setFile(undefined);
setError('Uploaded more than one file.');
return;
}
// this is 25MB in bytes; size is in bytes
if (files[0].size > 25000000) {
setShowAlert(true);
setFile(undefined);
setError('File is larger than 25MB.');
return;
}
setFile(files[0]);
setShowAlert(false);
setError(undefined);
// this is just for demo purposes, to make the loading state really obvious
setTimeout(() => {
setIsLoadingFile(false);
}, 1000);
}
});
const handleSend = (message) => alert(message);
// Attachments
// --------------------------------------------------------------------------
const handleFileDrop = (event: DropEvent, data: File[]) => {
setIsOpen(false);
setFile(data[0]);
setIsLoadingFile(true);
setTimeout(() => {
setIsLoadingFile(false);
}, 1000);
};
const onClose = () => {
setFile(undefined);
};
// Attachmenu menu
// --------------------------------------------------------------------------
const uploadMenuItems = [
,
{
open();
setIsOpen(!isOpen);
}}
key="upload"
value="upload"
id="upload"
icon={}
>
Upload from computer
];
const onToggleClick = () => {
setUserFacingMenuItems(initialMenuItems.concat(uploadMenuItems));
};
const findMatchingElements = (elements: ReactNode[], targetValue: string) => {
let matchingElements = [] as ReactNode[];
elements.forEach((element) => {
if (isValidElement(element)) {
// Check if the element's value matches the targetValue
if (element.props.value && element.props.value.toLowerCase().includes(targetValue.toLowerCase())) {
matchingElements.push(cloneElement(element, { key: element.props.value }));
}
// Recursively check the element's children
const children = Children.toArray(element.props.children);
matchingElements = matchingElements.concat(findMatchingElements(children, targetValue));
}
});
return matchingElements;
};
const onTextChange = (textValue: string) => {
if (textValue === '') {
setUserFacingMenuItems(initialMenuItems.concat(uploadMenuItems));
return;
}
const newMenuItems = findMatchingElements(initialMenuItems, textValue);
// this is necessary because the React nodes we find traversing the recursive search
// aren't correctly wrapped in a DropdownList. This leads to problems with the
// auth-operator item where it winds up floating in a bad place in the DOM and never
// gets removed
setUserFacingMenuItems(
<>
{newMenuItems.length === 0 ? (
No results found
) : (
newMenuItems.map((item) => item)
)}
{uploadMenuItems.map((item) => item)}
>
);
};
// Main return statement
// --------------------------------------------------------------------------
return (
<>
{/* this is required for react-dropzone to work in Safari and Firefox */}
setChatbotVisible(!chatbotVisible)}
/>
<>
{showAlert && (
{
setShowAlert(false);
setError(undefined);
}}
title="File upload failed"
>
{error}
)}
{messages.map((message) => (
))}
{file && (
)}
{
// eslint-disable-next-line no-console
console.log('selected', value);
},
attachMenuInputPlaceholder: 'Search cluster resources...',
onAttachMenuInputChange: onTextChange,
onAttachMenuToggleClick: onToggleClick
}}
/>
>
>
);
};