|
| 1 | +import { FunctionComponent, useState } from 'react'; |
| 2 | +import { ChatbotDisplayMode } from '@patternfly/chatbot/dist/dynamic/Chatbot'; |
| 3 | +import ChatbotConversationHistoryNav, { |
| 4 | + Conversation |
| 5 | +} from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav'; |
| 6 | +import { |
| 7 | + Button, |
| 8 | + Checkbox, |
| 9 | + MenuToggle, |
| 10 | + MenuToggleElement, |
| 11 | + Select, |
| 12 | + SelectList, |
| 13 | + SelectOption, |
| 14 | + Tooltip |
| 15 | +} from '@patternfly/react-core'; |
| 16 | +import { FilterIcon, SortAmountDownIcon } from '@patternfly/react-icons'; |
| 17 | + |
| 18 | +const initialConversations: { [key: string]: Conversation[] } = { |
| 19 | + Today: [{ id: '1', text: 'Red Hat products and services' }], |
| 20 | + 'This month': [ |
| 21 | + { |
| 22 | + id: '2', |
| 23 | + text: 'Enterprise Linux installation and setup' |
| 24 | + }, |
| 25 | + { id: '3', text: 'Troubleshoot system crash' } |
| 26 | + ], |
| 27 | + March: [ |
| 28 | + { id: '4', text: 'Ansible security and updates' }, |
| 29 | + { id: '5', text: 'Red Hat certification' }, |
| 30 | + { id: '6', text: 'Lightspeed user documentation' } |
| 31 | + ], |
| 32 | + February: [ |
| 33 | + { id: '7', text: 'Crashing pod assistance' }, |
| 34 | + { id: '8', text: 'OpenShift AI pipelines' }, |
| 35 | + { id: '9', text: 'Updating subscription plan' }, |
| 36 | + { id: '10', text: 'Red Hat licensing options' } |
| 37 | + ], |
| 38 | + January: [ |
| 39 | + { id: '11', text: 'RHEL system performance' }, |
| 40 | + { id: '12', text: 'Manage user accounts' } |
| 41 | + ] |
| 42 | +}; |
| 43 | + |
| 44 | +export const ChatbotHeaderTitleDemo: FunctionComponent = () => { |
| 45 | + const [isDrawerOpen, setIsDrawerOpen] = useState(true); |
| 46 | + const [hasDrawerHeadDivider, setHasDrawerHeadDivider] = useState(false); |
| 47 | + const [showSearchActionStart, setShowSearchActionStart] = useState(false); |
| 48 | + const [showSearchActionEnd, setShowSearchActionEnd] = useState(false); |
| 49 | + const [isLoading, setIsLoading] = useState(false); |
| 50 | + const [isSortSelectOpen, setIsSortSelectOpen] = useState(false); |
| 51 | + const [selectedSort, setSelectedSort] = useState<string>('newest'); |
| 52 | + const [conversations, setConversations] = useState<Conversation[] | { [key: string]: Conversation[] }>( |
| 53 | + initialConversations |
| 54 | + ); |
| 55 | + const displayMode = ChatbotDisplayMode.embedded; |
| 56 | + |
| 57 | + const sortLabels: { [key: string]: string } = { |
| 58 | + newest: 'Date (newest first)', |
| 59 | + oldest: 'Date (oldest first)', |
| 60 | + 'alphabetical-asc': 'Name (A-Z)', |
| 61 | + 'alphabetical-desc': 'Name (Z-A)' |
| 62 | + }; |
| 63 | + |
| 64 | + const onSortSelect = ( |
| 65 | + _event: React.MouseEvent<Element, MouseEvent> | undefined, |
| 66 | + value: string | number | undefined |
| 67 | + ) => { |
| 68 | + setSelectedSort(value as string); |
| 69 | + setIsSortSelectOpen(false); |
| 70 | + }; |
| 71 | + |
| 72 | + const findMatchingItems = (targetValue: string) => { |
| 73 | + const filteredConversations = Object.entries(initialConversations).reduce((acc, [key, items]) => { |
| 74 | + const filteredItems = items.filter((item) => item.text.toLowerCase().includes(targetValue.toLowerCase())); |
| 75 | + if (filteredItems.length > 0) { |
| 76 | + acc[key] = filteredItems; |
| 77 | + } |
| 78 | + return acc; |
| 79 | + }, {}); |
| 80 | + |
| 81 | + return filteredConversations; |
| 82 | + }; |
| 83 | + |
| 84 | + return ( |
| 85 | + <> |
| 86 | + <Checkbox |
| 87 | + label="Display drawer" |
| 88 | + isChecked={isDrawerOpen} |
| 89 | + onChange={() => setIsDrawerOpen(!isDrawerOpen)} |
| 90 | + id="search-actions-drawer-visible" |
| 91 | + name="drawer-visible" |
| 92 | + /> |
| 93 | + <Checkbox |
| 94 | + label="Show drawer head divider" |
| 95 | + isChecked={hasDrawerHeadDivider} |
| 96 | + onChange={() => setHasDrawerHeadDivider(!hasDrawerHeadDivider)} |
| 97 | + id="search-actions-drawer-head-divider" |
| 98 | + name="drawer-head-divider" |
| 99 | + /> |
| 100 | + <Checkbox |
| 101 | + label="Show search action start" |
| 102 | + isChecked={showSearchActionStart} |
| 103 | + onChange={() => setShowSearchActionStart(!showSearchActionStart)} |
| 104 | + id="search-actions-show-search-action-start" |
| 105 | + name="show-search-action-start" |
| 106 | + /> |
| 107 | + <Checkbox |
| 108 | + label="Show search action end" |
| 109 | + isChecked={showSearchActionEnd} |
| 110 | + onChange={() => setShowSearchActionEnd(!showSearchActionEnd)} |
| 111 | + id="search-actions-show-search-action-end" |
| 112 | + name="show-search-action-end" |
| 113 | + /> |
| 114 | + <Checkbox |
| 115 | + label="Show loading state" |
| 116 | + isChecked={isLoading} |
| 117 | + onChange={() => setIsLoading(!isLoading)} |
| 118 | + id="search-actions-drawer-is-loading" |
| 119 | + name="drawer-is-loading" |
| 120 | + /> |
| 121 | + <ChatbotConversationHistoryNav |
| 122 | + displayMode={displayMode} |
| 123 | + onDrawerToggle={() => setIsDrawerOpen(!isDrawerOpen)} |
| 124 | + isDrawerOpen={isDrawerOpen} |
| 125 | + setIsDrawerOpen={setIsDrawerOpen} |
| 126 | + // eslint-disable-next-line no-console |
| 127 | + onSelectActiveItem={(e, selectedItem) => console.log(`Selected history item with id ${selectedItem}`)} |
| 128 | + conversations={conversations} |
| 129 | + onNewChat={() => { |
| 130 | + setIsDrawerOpen(!isDrawerOpen); |
| 131 | + }} |
| 132 | + handleTextInputChange={(value: string) => { |
| 133 | + if (value === '') { |
| 134 | + setConversations(initialConversations); |
| 135 | + } else { |
| 136 | + const newConversations: { [key: string]: Conversation[] } = findMatchingItems(value); |
| 137 | + setConversations(newConversations); |
| 138 | + } |
| 139 | + }} |
| 140 | + drawerContent={<div>Drawer content</div>} |
| 141 | + hasDrawerHeadDivider={hasDrawerHeadDivider} |
| 142 | + isLoading={isLoading} |
| 143 | + searchActionStart={ |
| 144 | + showSearchActionStart ? ( |
| 145 | + <Tooltip content="Filter options" aria="none" aria-live="off"> |
| 146 | + <Button |
| 147 | + variant="control" |
| 148 | + aria-label="Filter options" |
| 149 | + // eslint-disable-next-line no-console |
| 150 | + onClick={() => console.log('Filter button clicked')} |
| 151 | + icon={<FilterIcon />} |
| 152 | + /> |
| 153 | + </Tooltip> |
| 154 | + ) : undefined |
| 155 | + } |
| 156 | + searchActionEnd={ |
| 157 | + showSearchActionEnd ? ( |
| 158 | + <Select |
| 159 | + id="sort-select" |
| 160 | + isOpen={isSortSelectOpen} |
| 161 | + selected={selectedSort} |
| 162 | + onSelect={onSortSelect} |
| 163 | + shouldFocusToggleOnSelect |
| 164 | + onOpenChange={(isOpen) => setIsSortSelectOpen(isOpen)} |
| 165 | + toggle={(toggleRef: React.Ref<MenuToggleElement>) => ( |
| 166 | + <Tooltip aria="none" aria-live="off" content={`Sort - ${sortLabels[selectedSort]}`}> |
| 167 | + <MenuToggle |
| 168 | + ref={toggleRef} |
| 169 | + onClick={() => setIsSortSelectOpen(!isSortSelectOpen)} |
| 170 | + isExpanded={isSortSelectOpen} |
| 171 | + variant="plain" |
| 172 | + aria-label={`${sortLabels[selectedSort]}, Sort conversations`} |
| 173 | + icon={ |
| 174 | + <SortAmountDownIcon |
| 175 | + style={{ |
| 176 | + transform: |
| 177 | + selectedSort === 'oldest' || selectedSort === 'alphabetical-asc' ? 'scaleY(-1)' : 'none' |
| 178 | + }} |
| 179 | + /> |
| 180 | + } |
| 181 | + /> |
| 182 | + </Tooltip> |
| 183 | + )} |
| 184 | + > |
| 185 | + <SelectList> |
| 186 | + {Object.keys(sortLabels).map((currentLabel) => ( |
| 187 | + <SelectOption key={currentLabel} value={currentLabel}> |
| 188 | + {sortLabels[currentLabel]} |
| 189 | + </SelectOption> |
| 190 | + ))} |
| 191 | + </SelectList> |
| 192 | + </Select> |
| 193 | + ) : undefined |
| 194 | + } |
| 195 | + /> |
| 196 | + </> |
| 197 | + ); |
| 198 | +}; |
0 commit comments