mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2025-12-06 02:30:47 -08:00
feat: create new chat in the store and wiki
This commit is contained in:
parent
45d12ce1a0
commit
083eda4e6d
9 changed files with 277 additions and 52 deletions
|
|
@ -488,7 +488,9 @@
|
||||||
"InPort": "In Ports",
|
"InPort": "In Ports",
|
||||||
"StopWorkflow": "Stop Workflow",
|
"StopWorkflow": "Stop Workflow",
|
||||||
"ToggleDebugPanel": "Toggle Debug Panel",
|
"ToggleDebugPanel": "Toggle Debug Panel",
|
||||||
"ClearDebugPanel": "Clear Debug Panel"
|
"ClearDebugPanel": "Clear Debug Panel",
|
||||||
|
"NewChat": "New Chat",
|
||||||
|
"DeleteChat": "Delete Chat"
|
||||||
},
|
},
|
||||||
"Description": "Description",
|
"Description": "Description",
|
||||||
"Tags": "Tags",
|
"Tags": "Tags",
|
||||||
|
|
|
||||||
|
|
@ -493,6 +493,8 @@
|
||||||
"InPort": "入口",
|
"InPort": "入口",
|
||||||
"StopWorkflow": "停止工作流",
|
"StopWorkflow": "停止工作流",
|
||||||
"ToggleDebugPanel": "切换开关调试面板",
|
"ToggleDebugPanel": "切换开关调试面板",
|
||||||
"ClearDebugPanel": "清空调试面板"
|
"ClearDebugPanel": "清空调试面板",
|
||||||
|
"NewChat": "新对话",
|
||||||
|
"DeleteChat": "删除对话"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
85
src/pages/Workflow/RunWorkflow/ChatArea.tsx
Normal file
85
src/pages/Workflow/RunWorkflow/ChatArea.tsx
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
import ChatBubbleOutline from '@mui/icons-material/ChatBubbleOutline';
|
||||||
|
import { Box, IconButton, Typography } from '@mui/material';
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { styled } from 'styled-components';
|
||||||
|
import { plugins } from '../DebugPanel/plugins';
|
||||||
|
import { useChatsStore } from './useChatsStore';
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
padding: 0 1em;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
chatID: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChatArea: React.FC<Props> = ({ chatID }) => {
|
||||||
|
/**
|
||||||
|
* Use the chatsStore to get the relevant chat elements.
|
||||||
|
*/
|
||||||
|
const elements = useChatsStore((state) => state.chats[chatID]?.chatJSON?.elements ?? {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ref to the Container element for scrolling
|
||||||
|
*/
|
||||||
|
const containerReference = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
|
const onSubmit = useChatsStore((state) => (id: string, content: unknown) => {
|
||||||
|
state.submitElementInChat(chatID, id, content);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container ref={containerReference}>
|
||||||
|
{Object.values(elements).map(element => {
|
||||||
|
// eslint-disable-next-line unicorn/no-null, @typescript-eslint/strict-boolean-expressions
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
const { type, id, props = {}, isSubmitted, timestamp } = element;
|
||||||
|
const plugin = plugins.find(p => p.type === type);
|
||||||
|
if (plugin === undefined) {
|
||||||
|
// TODO: return a placeholder element instead
|
||||||
|
// eslint-disable-next-line unicorn/no-null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const { Component } = plugin;
|
||||||
|
return (
|
||||||
|
<div key={id}>
|
||||||
|
<Typography color='textSecondary'>
|
||||||
|
{new Date(timestamp).toLocaleTimeString()}
|
||||||
|
</Typography>
|
||||||
|
<Component {...props} onSubmit={onSubmit} id={id} isSubmitted={isSubmitted} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const EmptyContainer = styled(Box)`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 0.7;
|
||||||
|
`;
|
||||||
|
export const EmptyChatArea: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<EmptyContainer>
|
||||||
|
<IconButton color='primary' size='large'>
|
||||||
|
<ChatBubbleOutline fontSize='inherit' />
|
||||||
|
</IconButton>
|
||||||
|
<Typography variant='h6' gutterBottom>
|
||||||
|
No Chat Selected
|
||||||
|
</Typography>
|
||||||
|
<Typography color='textSecondary'>
|
||||||
|
Start a chat by sending a message.
|
||||||
|
</Typography>
|
||||||
|
</EmptyContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
56
src/pages/Workflow/RunWorkflow/ChatsList.tsx
Normal file
56
src/pages/Workflow/RunWorkflow/ChatsList.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* eslint-disable @typescript-eslint/promise-function-async */
|
||||||
|
import { Button, List, ListItem } from '@mui/material';
|
||||||
|
import { IWorkspaceWithMetadata } from '@services/workspaces/interface';
|
||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { styled } from 'styled-components';
|
||||||
|
import { useChatDataSource } from './useChatDataSource';
|
||||||
|
|
||||||
|
// Styled Components
|
||||||
|
const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const AddChatButton = styled(Button)`
|
||||||
|
margin: 10px 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledListItem = styled(ListItem)`
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
interface IChatsListProps {
|
||||||
|
workflowID: string | undefined;
|
||||||
|
workspacesList: IWorkspaceWithMetadata[] | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChatsList: React.FC<IChatsListProps> = ({ workflowID, workspacesList }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [chatList, onAddChat, onDeleteChat] = useChatDataSource(workspacesList, workflowID);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<AddChatButton variant='contained' color='primary' onClick={() => onAddChat()}>
|
||||||
|
{t('Workflow.NewChat')}
|
||||||
|
</AddChatButton>
|
||||||
|
<List>
|
||||||
|
{chatList.map((chat) => (
|
||||||
|
<StyledListItem key={chat.id}>
|
||||||
|
{chat.title}
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
onDeleteChat(chat.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('Workflow.DeleteChat')}
|
||||||
|
</Button>
|
||||||
|
</StyledListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
33
src/pages/Workflow/RunWorkflow/index.tsx
Normal file
33
src/pages/Workflow/RunWorkflow/index.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { PageType } from '@services/pages/interface';
|
||||||
|
import { WindowNames } from '@services/windows/WindowProperties';
|
||||||
|
import { useWorkspacesListObservable } from '@services/workspaces/hooks';
|
||||||
|
import React from 'react';
|
||||||
|
import { styled } from 'styled-components';
|
||||||
|
import { useRoute } from 'wouter';
|
||||||
|
import { ChatArea, EmptyChatArea } from './ChatArea';
|
||||||
|
import { ChatsList } from './ChatsList';
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const RunWorkflow: React.FC = () => {
|
||||||
|
const [, parameters] = useRoute(`/${WindowNames.main}/${PageType.workflow}/run/:workflowID/:runID/`);
|
||||||
|
/**
|
||||||
|
* This will be the active chat ID if the URL matches, otherwise it'll be undefined.
|
||||||
|
*/
|
||||||
|
const activeRunID = parameters?.runID;
|
||||||
|
const workflowID = parameters?.workflowID;
|
||||||
|
const workspacesList = useWorkspacesListObservable();
|
||||||
|
// DEBUG: console workflowID
|
||||||
|
console.log(`workflowID`, workflowID, parameters);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<ChatsList workflowID={workflowID} workspacesList={workspacesList} />
|
||||||
|
{activeRunID === undefined ? <EmptyChatArea /> : <ChatArea chatID={activeRunID} />}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -8,9 +8,10 @@ export interface ChatsStoreState {
|
||||||
chats: Record<string, IChatListItem | undefined>;
|
chats: Record<string, IChatListItem | undefined>;
|
||||||
}
|
}
|
||||||
export interface ChatsStoreActions {
|
export interface ChatsStoreActions {
|
||||||
addChat: (fields: { title?: string; workflowID: string; workspaceID: string }) => string;
|
addChat: (fields: { title?: string; workflowID: string; workspaceID: string }) => IChatListItem;
|
||||||
addElementToChat: (chatID: string, element: Pick<UIElementState, 'type' | 'props' | 'author'>) => string;
|
addElementToChat: (chatID: string, element: Pick<UIElementState, 'type' | 'props' | 'author'>) => string;
|
||||||
clearElementsInChat: (chatID: string) => void;
|
clearElementsInChat: (chatID: string) => void;
|
||||||
|
getChat: (chatID: string) => IChatListItem | undefined;
|
||||||
removeChat: (chatID: string) => void;
|
removeChat: (chatID: string) => void;
|
||||||
removeElementFromChat: (chatID: string, id: string) => void;
|
removeElementFromChat: (chatID: string, id: string) => void;
|
||||||
submitElementInChat: (chatID: string, id: string, content: unknown) => void;
|
submitElementInChat: (chatID: string, id: string, content: unknown) => void;
|
||||||
|
|
@ -28,12 +29,21 @@ export const chatsStore = createStore(
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getChat: (chatID) => {
|
||||||
|
let result;
|
||||||
|
set((state) => {
|
||||||
|
result = state.chats[chatID];
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
addChat: (fields) => {
|
addChat: (fields) => {
|
||||||
const id = String(Math.random());
|
const id = String(Math.random());
|
||||||
|
const newChatItem = { chatJSON: { elements: {} }, id, tags: [], title: 'New Chat', ...fields };
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.chats[id] = { chatJSON: { elements: {} }, id, tags: [], title: 'New Chat', ...fields };
|
state.chats[id] = newChatItem;
|
||||||
});
|
});
|
||||||
return id;
|
return newChatItem;
|
||||||
},
|
},
|
||||||
|
|
||||||
addElementToChat: (chatID, { type, props, author }) => {
|
addElementToChat: (chatID, { type, props, author }) => {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ export interface IChatListItem {
|
||||||
*/
|
*/
|
||||||
chatJSONString?: string;
|
chatJSONString?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
|
/**
|
||||||
|
* Random generated ID
|
||||||
|
*/
|
||||||
id: string;
|
id: string;
|
||||||
image?: string;
|
image?: string;
|
||||||
metadata?: {
|
metadata?: {
|
||||||
|
|
@ -35,6 +38,9 @@ export interface IChatListItem {
|
||||||
workspace: IWorkspaceWithMetadata;
|
workspace: IWorkspaceWithMetadata;
|
||||||
};
|
};
|
||||||
tags: string[];
|
tags: string[];
|
||||||
|
/**
|
||||||
|
* From caption field, or use ID
|
||||||
|
*/
|
||||||
title: string;
|
title: string;
|
||||||
workflowID: string;
|
workflowID: string;
|
||||||
workspaceID: string;
|
workspaceID: string;
|
||||||
|
|
@ -67,7 +73,7 @@ export function useChatsFromWiki(workspacesList: IWorkspaceWithMetadata[] | unde
|
||||||
const chatTiddlersInWorkspace = chatsByWorkspace[workspaceIndex];
|
const chatTiddlersInWorkspace = chatsByWorkspace[workspaceIndex];
|
||||||
return chatTiddlersInWorkspace.map((tiddler) => {
|
return chatTiddlersInWorkspace.map((tiddler) => {
|
||||||
const chatItem: IChatListItem = {
|
const chatItem: IChatListItem = {
|
||||||
id: `${workspace.id}:${tiddler.title}`,
|
id: tiddler.title,
|
||||||
title: (tiddler.caption as string | undefined) ?? tiddler.title,
|
title: (tiddler.caption as string | undefined) ?? tiddler.title,
|
||||||
chatJSONString: tiddler.text,
|
chatJSONString: tiddler.text,
|
||||||
chatJSON: JSON.parse(tiddler.text) as SingleChatState,
|
chatJSON: JSON.parse(tiddler.text) as SingleChatState,
|
||||||
|
|
@ -91,14 +97,15 @@ export function useChatsFromWiki(workspacesList: IWorkspaceWithMetadata[] | unde
|
||||||
return chatItems;
|
return chatItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addChatToWiki(newItem: IChatListItem, oldItem?: IChatListItem) {
|
export async function addChatToWiki(newItem: IChatListItem) {
|
||||||
await window.service.wiki.wikiOperation(
|
await window.service.wiki.wikiOperation(
|
||||||
WikiChannel.addTiddler,
|
WikiChannel.addTiddler,
|
||||||
newItem.workspaceID,
|
newItem.workspaceID,
|
||||||
newItem.title,
|
newItem.id,
|
||||||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/prefer-nullish-coalescing
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/prefer-nullish-coalescing
|
||||||
newItem.chatJSONString || '[]',
|
newItem.chatJSONString || '[]',
|
||||||
{
|
{
|
||||||
|
caption: newItem.title,
|
||||||
type: 'application/json',
|
type: 'application/json',
|
||||||
tags: [...newItem.tags, chatTiddlerTagName],
|
tags: [...newItem.tags, chatTiddlerTagName],
|
||||||
description: newItem.description ?? '',
|
description: newItem.description ?? '',
|
||||||
|
|
@ -107,13 +114,6 @@ export async function addChatToWiki(newItem: IChatListItem, oldItem?: IChatListI
|
||||||
},
|
},
|
||||||
{ withDate: true },
|
{ withDate: true },
|
||||||
);
|
);
|
||||||
if (oldItem !== undefined) {
|
|
||||||
window.service.wiki.wikiOperation(
|
|
||||||
WikiChannel.deleteTiddler,
|
|
||||||
oldItem.workspaceID,
|
|
||||||
oldItem.title,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sortChat(a: IChatListItem, b: IChatListItem) {
|
export function sortChat(a: IChatListItem, b: IChatListItem) {
|
||||||
|
|
@ -127,33 +127,20 @@ export function sortChat(a: IChatListItem, b: IChatListItem) {
|
||||||
* @param workflowID The workflow ID that these chats were generated with.
|
* @param workflowID The workflow ID that these chats were generated with.
|
||||||
*/
|
*/
|
||||||
export function useChatDataSource(workspacesList: IWorkspaceWithMetadata[] | undefined, workflowID: string | undefined) {
|
export function useChatDataSource(workspacesList: IWorkspaceWithMetadata[] | undefined, workflowID: string | undefined) {
|
||||||
const [chats, setChats] = useState<IChatListItem[]>([]);
|
|
||||||
const initialChats = useChatsFromWiki(workspacesList, workflowID);
|
const initialChats = useChatsFromWiki(workspacesList, workflowID);
|
||||||
|
const workspaceID = useWorkspaceIDToStoreNewChats(workspacesList);
|
||||||
|
const {
|
||||||
|
updateChats,
|
||||||
|
addChat,
|
||||||
|
removeChat,
|
||||||
|
chatList,
|
||||||
|
} = useChatsStore((state) => ({
|
||||||
|
updateChats: state.updateChats,
|
||||||
|
addChat: state.addChat,
|
||||||
|
removeChat: state.removeChat,
|
||||||
|
chatList: Object.values(state.chats).filter((item): item is IChatListItem => item !== undefined).sort((a, b) => sortChat(a, b)),
|
||||||
|
}));
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setChats(initialChats.sort(sortChat));
|
|
||||||
}, [initialChats]);
|
|
||||||
|
|
||||||
const onAddChat = useCallback(async (newItem: IChatListItem, oldItem?: IChatListItem) => {
|
|
||||||
await addChatToWiki(newItem, oldItem);
|
|
||||||
setChats((chats) => [...chats.filter(item => item.title !== newItem.title), newItem].sort(sortChat));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onDeleteChat = useCallback((item: IChatListItem) => {
|
|
||||||
window.service.wiki.wikiOperation(
|
|
||||||
WikiChannel.deleteTiddler,
|
|
||||||
item.workspaceID,
|
|
||||||
item.title,
|
|
||||||
);
|
|
||||||
setChats((chats) => chats.filter(chat => chat.id !== item.id).sort(sortChat));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return [chats, onAddChat, onDeleteChat] as const;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useLoadInitialChatDataToStore(workspacesList: IWorkspaceWithMetadata[] | undefined, workflowID: string | undefined) {
|
|
||||||
const updateChats = useChatsStore((state) => state.updateChats);
|
|
||||||
const [initialChats] = useChatDataSource(workspacesList, workflowID);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const chatsDict = initialChats.reduce<Record<string, IChatListItem>>((accumulator, chat) => {
|
const chatsDict = initialChats.reduce<Record<string, IChatListItem>>((accumulator, chat) => {
|
||||||
accumulator[chat.id] = chat;
|
accumulator[chat.id] = chat;
|
||||||
|
|
@ -161,4 +148,42 @@ export function useLoadInitialChatDataToStore(workspacesList: IWorkspaceWithMeta
|
||||||
}, {});
|
}, {});
|
||||||
updateChats(chatsDict);
|
updateChats(chatsDict);
|
||||||
}, [initialChats, updateChats]);
|
}, [initialChats, updateChats]);
|
||||||
}
|
|
||||||
|
const onAddChat = useCallback(async (newItemFields?: {
|
||||||
|
title?: string | undefined;
|
||||||
|
}) => {
|
||||||
|
if (workspaceID === undefined || workflowID === undefined) return;
|
||||||
|
const newItem = addChat({
|
||||||
|
workflowID,
|
||||||
|
workspaceID,
|
||||||
|
...newItemFields,
|
||||||
|
});
|
||||||
|
await addChatToWiki(newItem);
|
||||||
|
}, [addChat, workflowID, workspaceID]);
|
||||||
|
|
||||||
|
const onDeleteChat = useCallback((chatID: string) => {
|
||||||
|
if (workspaceID === undefined) return;
|
||||||
|
window.service.wiki.wikiOperation(
|
||||||
|
WikiChannel.deleteTiddler,
|
||||||
|
workspaceID,
|
||||||
|
chatID,
|
||||||
|
);
|
||||||
|
removeChat(chatID);
|
||||||
|
}, [removeChat, workspaceID]);
|
||||||
|
|
||||||
|
return [chatList, onAddChat, onDeleteChat] as const;
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect store and dataSource
|
||||||
|
|
||||||
|
export function useWorkspaceIDToStoreNewChats(workspacesList: IWorkspaceWithMetadata[] | undefined) {
|
||||||
|
const [workspaceIDToStoreNewChats, setWorkspaceIDToStoreNewChats] = useState<string | undefined>();
|
||||||
|
// set workspaceIDToStoreNewChats on initial load && workspacesList has value, make it default to save to first workspace.
|
||||||
|
useEffect(() => {
|
||||||
|
if (workspaceIDToStoreNewChats === undefined && workspacesList?.[0] !== undefined) {
|
||||||
|
const workspaceID = workspacesList[0].id;
|
||||||
|
setWorkspaceIDToStoreNewChats(workspaceID);
|
||||||
|
}
|
||||||
|
}, [workspaceIDToStoreNewChats, workspacesList]);
|
||||||
|
return workspaceIDToStoreNewChats;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import styled from 'styled-components';
|
||||||
import { useLocation } from 'wouter';
|
import { useLocation } from 'wouter';
|
||||||
|
|
||||||
import { DeleteConfirmationDialog } from './DeleteConfirmationDialog';
|
import { DeleteConfirmationDialog } from './DeleteConfirmationDialog';
|
||||||
import { useHandleOpenInTheGraphEditor } from './useClickHandler';
|
import { useHandleOpenInTheGraphEditor, useHandleOpenInTheRunWorkflow } from './useClickHandler';
|
||||||
import type { IWorkflowTiddler } from './useWorkflowDataSource';
|
import type { IWorkflowTiddler } from './useWorkflowDataSource';
|
||||||
|
|
||||||
const WorkflowListContainer = styled(Box)`
|
const WorkflowListContainer = styled(Box)`
|
||||||
|
|
@ -81,10 +81,9 @@ export function WorkflowListItem(props: IWorkflowListItemProps) {
|
||||||
window.service.wiki.wikiOperation(WikiChannel.openTiddler, item.workspaceID, item.title);
|
window.service.wiki.wikiOperation(WikiChannel.openTiddler, item.workspaceID, item.title);
|
||||||
}, [item, setLocation]);
|
}, [item, setLocation]);
|
||||||
|
|
||||||
const handleOpenInTheGraphEditorRaw = useHandleOpenInTheGraphEditor();
|
const handleOpenInTheGraphEditor = useHandleOpenInTheGraphEditor(item);
|
||||||
const handleOpenInTheGraphEditor = useCallback(() => {
|
const handleOpenInTheRunWorkflow = useHandleOpenInTheRunWorkflow(item);
|
||||||
handleOpenInTheGraphEditorRaw(item);
|
|
||||||
}, [handleOpenInTheGraphEditorRaw, item]);
|
|
||||||
const menuID = `workflow-list-item-menu-${item.id}`;
|
const menuID = `workflow-list-item-menu-${item.id}`;
|
||||||
return (
|
return (
|
||||||
<WorkflowCard>
|
<WorkflowCard>
|
||||||
|
|
@ -108,7 +107,7 @@ export function WorkflowListItem(props: IWorkflowListItemProps) {
|
||||||
</CardActionArea>
|
</CardActionArea>
|
||||||
<ItemMenuCardActions>
|
<ItemMenuCardActions>
|
||||||
<Button onClick={handleOpenInTheGraphEditor}>{t('Open')}</Button>
|
<Button onClick={handleOpenInTheGraphEditor}>{t('Open')}</Button>
|
||||||
<Button onClick={handleOpenInTheGraphEditor}>{t('Open')}</Button>
|
<Button onClick={handleOpenInTheRunWorkflow}>{t('Workflow.Use')}</Button>
|
||||||
<Button aria-controls={menuID} aria-haspopup='true' onClick={handleOpenItemMenu}>
|
<Button aria-controls={menuID} aria-haspopup='true' onClick={handleOpenItemMenu}>
|
||||||
{anchorElement === null ? <MenuIcon /> : <MenuOpenIcon />}
|
{anchorElement === null ? <MenuIcon /> : <MenuOpenIcon />}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,29 @@
|
||||||
|
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
||||||
import { PageType } from '@services/pages/interface';
|
import { PageType } from '@services/pages/interface';
|
||||||
import { WindowNames } from '@services/windows/WindowProperties';
|
import { WindowNames } from '@services/windows/WindowProperties';
|
||||||
import { useCallback, useContext } from 'react';
|
import { MouseEvent, useCallback, useContext } from 'react';
|
||||||
import { useLocation } from 'wouter';
|
import { useLocation } from 'wouter';
|
||||||
import { WorkflowContext } from '../GraphEditor/hooks/useContext';
|
import { WorkflowContext } from '../GraphEditor/hooks/useContext';
|
||||||
import type { IWorkflowListItem } from './WorkflowList';
|
import type { IWorkflowListItem } from './WorkflowList';
|
||||||
|
|
||||||
export function useHandleOpenInTheGraphEditor() {
|
export function useHandleOpenInTheGraphEditor(item?: IWorkflowListItem) {
|
||||||
const [, setLocation] = useLocation();
|
const [, setLocation] = useLocation();
|
||||||
const workflowContext = useContext(WorkflowContext);
|
const workflowContext = useContext(WorkflowContext);
|
||||||
const handleOpenInTheGraphEditor = useCallback((item: IWorkflowListItem) => {
|
const handleOpenInTheGraphEditor = useCallback((item1?: IWorkflowListItem | MouseEvent<HTMLButtonElement>) => {
|
||||||
setLocation(`/${WindowNames.main}/${PageType.workflow}/${item.id}/`);
|
const workflowID = item?.id ?? (item1 as IWorkflowListItem)?.id;
|
||||||
|
if (!workflowID) return;
|
||||||
|
setLocation(`/${WindowNames.main}/${PageType.workflow}/workflow/${workflowID}/`);
|
||||||
workflowContext.setOpenedWorkflowItem(item);
|
workflowContext.setOpenedWorkflowItem(item);
|
||||||
}, [setLocation, workflowContext]);
|
}, [setLocation, workflowContext, item]);
|
||||||
|
return handleOpenInTheGraphEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useHandleOpenInTheRunWorkflow(item: IWorkflowListItem) {
|
||||||
|
const [, setLocation] = useLocation();
|
||||||
|
const workflowContext = useContext(WorkflowContext);
|
||||||
|
const handleOpenInTheGraphEditor = useCallback(() => {
|
||||||
|
setLocation(`/${WindowNames.main}/${PageType.workflow}/run/${item.id}/`);
|
||||||
|
workflowContext.setOpenedWorkflowItem(item);
|
||||||
|
}, [setLocation, workflowContext, item]);
|
||||||
return handleOpenInTheGraphEditor;
|
return handleOpenInTheGraphEditor;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue