feat: added drag and drop sorting for topics list
This commit is contained in:
parent
cf3ba3c440
commit
c9b57536c4
@ -8,6 +8,7 @@ import {
|
||||
updateAssistants as _updateAssistants,
|
||||
updateDefaultAssistant as _updateDefaultAssistant,
|
||||
updateTopic as _updateTopic,
|
||||
updateTopics as _updateTopics,
|
||||
addAssistant,
|
||||
removeAssistant,
|
||||
updateAssistant
|
||||
@ -46,6 +47,7 @@ export function useAssistant(id: string) {
|
||||
addTopic: (topic: Topic) => dispatch(_addTopic({ assistantId: assistant.id, topic })),
|
||||
removeTopic: (topic: Topic) => dispatch(_removeTopic({ assistantId: assistant.id, topic })),
|
||||
updateTopic: (topic: Topic) => dispatch(_updateTopic({ assistantId: assistant.id, topic })),
|
||||
updateTopics: (topics: Topic[]) => dispatch(_updateTopics({ assistantId: assistant.id, topics })),
|
||||
removeAllTopics: () => dispatch(_removeAllTopics({ assistantId: assistant.id })),
|
||||
setModel: (model: Model) => dispatch(_setModel({ assistantId: assistant.id, model }))
|
||||
}
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
import { Assistant } from '@renderer/types'
|
||||
import { find } from 'lodash'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
export function useActiveTopic(assistant: Assistant) {
|
||||
const [activeTopic, setActiveTopic] = useState(assistant?.topics[0])
|
||||
|
||||
useEffect(() => {
|
||||
assistant?.topics && setActiveTopic(assistant?.topics[0])
|
||||
}, [assistant])
|
||||
// activeTopic not in assistant.topics
|
||||
if (!find(assistant.topics, { id: activeTopic?.id })) {
|
||||
setActiveTopic(assistant.topics[0])
|
||||
}
|
||||
}, [activeTopic?.id, assistant])
|
||||
|
||||
return { activeTopic, setActiveTopic }
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import AssistantSettingPopup from '@renderer/components/Popups/AssistantSettingP
|
||||
import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { getDefaultTopic } from '@renderer/services/assistant'
|
||||
import { Assistant } from '@renderer/types'
|
||||
import { uuid } from '@renderer/utils'
|
||||
import { droppableReorder, uuid } from '@renderer/utils'
|
||||
import { Dropdown, MenuProps } from 'antd'
|
||||
import { last } from 'lodash'
|
||||
import { FC, useRef } from 'react'
|
||||
@ -16,13 +16,6 @@ interface Props {
|
||||
onCreateAssistant: () => void
|
||||
}
|
||||
|
||||
const reorder = (list: Assistant[], startIndex: number, endIndex: number, len = 1) => {
|
||||
const result = Array.from(list)
|
||||
const removed = result.splice(startIndex, len)
|
||||
result.splice(endIndex, 0, ...removed)
|
||||
return result
|
||||
}
|
||||
|
||||
const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAssistant }) => {
|
||||
const { assistants, removeAssistant, updateAssistant, addAssistant, updateAssistants } = useAssistants()
|
||||
const targetAssistant = useRef<Assistant | null>(null)
|
||||
@ -73,7 +66,7 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
|
||||
if (result.destination) {
|
||||
const sourceIndex = result.source.index
|
||||
const destIndex = result.destination.index
|
||||
const reorderAssistants = reorder(assistants, sourceIndex, destIndex)
|
||||
const reorderAssistants = droppableReorder<Assistant>(assistants, sourceIndex, destIndex)
|
||||
updateAssistants(reorderAssistants)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@ import { FC, useRef } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { DeleteOutlined, EditOutlined, SignatureOutlined } from '@ant-design/icons'
|
||||
import LocalStorage from '@renderer/services/storage'
|
||||
import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd'
|
||||
import { droppableReorder } from '@renderer/utils'
|
||||
|
||||
interface Props {
|
||||
assistant: Assistant
|
||||
@ -17,7 +19,7 @@ interface Props {
|
||||
|
||||
const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
|
||||
const { showRightSidebar } = useShowRightSidebar()
|
||||
const { removeTopic, updateTopic, removeAllTopics } = useAssistant(assistant.id)
|
||||
const { removeTopic, updateTopic, removeAllTopics, updateTopics } = useAssistant(assistant.id)
|
||||
const currentTopic = useRef<Topic | null>(null)
|
||||
|
||||
const topicMenuItems: MenuProps['items'] = [
|
||||
@ -70,6 +72,14 @@ const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
|
||||
})
|
||||
}
|
||||
|
||||
const onDragEnd = (result: DropResult) => {
|
||||
if (result.destination) {
|
||||
const sourceIndex = result.source.index
|
||||
const destIndex = result.destination.index
|
||||
updateTopics(droppableReorder(assistant.topics, sourceIndex, destIndex))
|
||||
}
|
||||
}
|
||||
|
||||
if (!showRightSidebar) {
|
||||
return null
|
||||
}
|
||||
@ -92,17 +102,33 @@ const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
|
||||
</DeleteButton>
|
||||
</Popconfirm>
|
||||
</TopicTitle>
|
||||
{assistant.topics.map((topic) => (
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<Droppable droppableId="droppable">
|
||||
{(provided) => (
|
||||
<div {...provided.droppableProps} ref={provided.innerRef}>
|
||||
{assistant.topics.map((topic, index) => (
|
||||
<Draggable key={`draggable_${topic.id}_${index}`} draggableId={topic.id} index={index}>
|
||||
{(provided) => (
|
||||
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
||||
<Dropdown
|
||||
menu={{ items: topicMenuItems }}
|
||||
trigger={['contextMenu']}
|
||||
key={topic.id}
|
||||
onOpenChange={(open) => open && (currentTopic.current = topic)}>
|
||||
<TopicListItem className={topic.id === activeTopic?.id ? 'active' : ''} onClick={() => setActiveTopic(topic)}>
|
||||
<TopicListItem
|
||||
className={topic.id === activeTopic?.id ? 'active' : ''}
|
||||
onClick={() => setActiveTopic(topic)}>
|
||||
{topic.name}
|
||||
</TopicListItem>
|
||||
</Dropdown>
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
@ -65,6 +65,16 @@ const assistantsSlice = createSlice({
|
||||
: assistant
|
||||
)
|
||||
},
|
||||
updateTopics: (state, action: PayloadAction<{ assistantId: string; topics: Topic[] }>) => {
|
||||
state.assistants = state.assistants.map((assistant) =>
|
||||
assistant.id === action.payload.assistantId
|
||||
? {
|
||||
...assistant,
|
||||
topics: action.payload.topics
|
||||
}
|
||||
: assistant
|
||||
)
|
||||
},
|
||||
removeAllTopics: (state, action: PayloadAction<{ assistantId: string }>) => {
|
||||
state.assistants = state.assistants.map((assistant) => {
|
||||
if (assistant.id === action.payload.assistantId) {
|
||||
@ -99,6 +109,7 @@ export const {
|
||||
addTopic,
|
||||
removeTopic,
|
||||
updateTopic,
|
||||
updateTopics,
|
||||
removeAllTopics,
|
||||
setModel
|
||||
} = assistantsSlice.actions
|
||||
|
||||
@ -81,3 +81,10 @@ export const getDefaultGroupName = (id: string) => {
|
||||
|
||||
return id.toUpperCase()
|
||||
}
|
||||
|
||||
export function droppableReorder<T>(list: T[], startIndex: number, endIndex: number, len = 1) {
|
||||
const result = Array.from(list)
|
||||
const removed = result.splice(startIndex, len)
|
||||
result.splice(endIndex, 0, ...removed)
|
||||
return result
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user