F: Prepare frontend for Synthesis execution
Some checks are pending
Backend CI / build (3.12) (push) Waiting to run
Frontend CI / build (22.x) (push) Waiting to run

This commit is contained in:
Ivan 2024-07-29 23:15:03 +03:00
parent 617d8daeb2
commit 282925c9a3
10 changed files with 116 additions and 30 deletions

View File

@ -1,5 +1,4 @@
''' Serializers for persistent data manipulation. '''
import re
from typing import cast
from django.db.models import F

View File

@ -73,3 +73,10 @@ export function postExecuteOperation(oss: string, request: FrontExchange<ITarget
request: request
});
}
export function postExecuteAll(oss: string, request: FrontExchange<IPositionsData, IOperationSchemaData>) {
AxiosPost({
endpoint: `/api/oss/${oss}/execute-all`,
request: request
});
}

View File

@ -108,7 +108,7 @@ export { LuNetwork as IconGenerateStructure } from 'react-icons/lu';
export { LuBookCopy as IconInlineSynthesis } from 'react-icons/lu';
export { LuWand2 as IconGenerateNames } from 'react-icons/lu';
export { GrConnect as IconConnect } from 'react-icons/gr';
export { BsPlay as IconExecute } from 'react-icons/bs';
export { BiPlayCircle as IconExecute } from 'react-icons/bi';
// ======== Graph UI =======
export { BiCollapse as IconGraphCollapse } from 'react-icons/bi';

View File

@ -223,6 +223,7 @@ function PickSubstitutions({
<div className='flex flex-col gap-[0.125rem] border-x border-t clr-input'>
<SelectOperation
noBorder
placeholder='Выберите аргумент'
items={operations.filter(item => item.id !== rightArgument?.id)}
value={leftArgument}
onSelectValue={setLeftArgument}
@ -275,6 +276,7 @@ function PickSubstitutions({
<div className='flex flex-col gap-[0.125rem] border-x border-t clr-input'>
<SelectOperation
noBorder
placeholder='Выберите аргумент'
items={operations.filter(item => item.id !== leftArgument?.id)}
value={rightArgument}
onSelectValue={setRightArgument}

View File

@ -19,6 +19,7 @@ import {
patchUpdateOperation,
patchUpdatePositions,
postCreateOperation,
postExecuteAll,
postExecuteOperation
} from '@/backend/oss';
import { type ErrorData } from '@/components/info/InfoError';
@ -68,6 +69,7 @@ interface IOssContext {
setInput: (data: IOperationSetInputData, callback?: () => void) => void;
updateOperation: (data: IOperationUpdateData, callback?: () => void) => void;
executeOperation: (data: ITargetOperation, callback?: () => void) => void;
executeAll: (data: IPositionsData, callback?: () => void) => void;
}
const OssContext = createContext<IOssContext | null>(null);
@ -411,6 +413,28 @@ export const OssState = ({ itemID, children }: OssStateProps) => {
[itemID, schema, library]
);
const executeAll = useCallback(
(data: IPositionsData, callback?: () => void) => {
if (!schema) {
return;
}
setProcessingError(undefined);
postExecuteAll(itemID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
library.setGlobalOSS(newData);
library.reloadItems(() => {
if (callback) callback();
});
}
});
},
[itemID, schema, library]
);
return (
<OssContext.Provider
value={{
@ -437,7 +461,8 @@ export const OssState = ({ itemID, children }: OssStateProps) => {
createInput,
setInput,
updateOperation,
executeOperation
executeOperation,
executeAll
}}
>
{children}

View File

@ -24,7 +24,7 @@ interface NodeContextMenuProps extends ContextMenuData {
onCreateInput: (target: OperationID) => void;
onEditSchema: (target: OperationID) => void;
onEditOperation: (target: OperationID) => void;
onRunOperation: (target: OperationID) => void;
onExecuteOperation: (target: OperationID) => void;
}
function NodeContextMenu({
@ -36,7 +36,7 @@ function NodeContextMenu({
onCreateInput,
onEditSchema,
onEditOperation,
onRunOperation
onExecuteOperation
}: NodeContextMenuProps) {
const controller = useOssEdit();
const [isOpen, setIsOpen] = useState(false);
@ -97,7 +97,7 @@ function NodeContextMenu({
const handleRunSynthesis = () => {
handleHide();
onRunOperation(operation.id);
onExecuteOperation(operation.id);
};
return (

View File

@ -162,13 +162,21 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
[controller, getPositions]
);
const handleRunOperation = useCallback(
const handleExecuteOperation = useCallback(
(target: OperationID) => {
controller.runOperation(target, getPositions());
controller.executeOperation(target, getPositions());
},
[controller, getPositions]
);
const handleExecuteSelected = useCallback(() => {
if (controller.selected.length === 1) {
handleExecuteOperation(controller.selected[0]);
} else {
controller.executeAll(getPositions());
}
}, [controller, handleExecuteOperation, getPositions]);
const handleFitView = useCallback(() => {
flow.fitView({ duration: PARAMETER.zoomDuration });
}, [flow]);
@ -285,8 +293,8 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
onNodesChange={handleNodesChange}
onEdgesChange={onEdgesChange}
onNodeClick={handleNodeClick}
fitView
proOptions={{ hideAttribution: true }}
fitView
nodeTypes={OssNodeTypes}
maxZoom={2}
minZoom={0.75}
@ -299,7 +307,17 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
{showGrid ? <Background gap={10} /> : null}
</ReactFlow>
),
[nodes, edges, handleNodesChange, handleContextMenu, handleClickCanvas, onEdgesChange, OssNodeTypes, showGrid]
[
nodes,
edges,
handleNodesChange,
handleContextMenu,
handleClickCanvas,
onEdgesChange,
handleNodeClick,
OssNodeTypes,
showGrid
]
);
return (
@ -313,6 +331,8 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
onFitView={handleFitView}
onCreate={handleCreateOperation}
onDelete={handleDeleteSelected}
onEdit={() => handleEditOperation(controller.selected[0])}
onExecute={handleExecuteSelected}
onResetPositions={handleResetPositions}
onSavePositions={handleSavePositions}
onSaveImage={handleSaveImage}
@ -328,7 +348,7 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
onCreateInput={handleCreateInput}
onEditSchema={handleEditSchema}
onEditOperation={handleEditOperation}
onRunOperation={handleRunOperation}
onExecuteOperation={handleExecuteOperation}
{...menuProps}
/>
) : null}

View File

@ -4,6 +4,8 @@ import {
IconAnimation,
IconAnimationOff,
IconDestroy,
IconEdit2,
IconExecute,
IconFitImage,
IconGrid,
IconImage,
@ -28,6 +30,8 @@ interface ToolbarOssGraphProps {
edgeStraight: boolean;
onCreate: () => void;
onDelete: () => void;
onEdit: () => void;
onExecute: () => void;
onFitView: () => void;
onSaveImage: () => void;
onSavePositions: () => void;
@ -44,6 +48,8 @@ function ToolbarOssGraph({
edgeStraight,
onCreate,
onDelete,
onEdit,
onExecute,
onFitView,
onSaveImage,
onSavePositions,
@ -57,6 +63,12 @@ function ToolbarOssGraph({
return (
<div className='flex flex-col items-center'>
<div className='cc-icons'>
<MiniButton
title='Сбросить изменения'
icon={<IconReset size='1.25rem' className='icon-primary' />}
disabled={!isModified}
onClick={onResetPositions}
/>
<MiniButton
icon={<IconFitImage size='1.25rem' className='icon-primary' />}
title='Сбросить вид'
@ -116,19 +128,30 @@ function ToolbarOssGraph({
onClick={onSavePositions}
/>
<MiniButton
title='Сбросить изменения'
icon={<IconReset size='1.25rem' className='icon-primary' />}
disabled={!isModified}
onClick={onResetPositions}
/>
<MiniButton
title='Новая операция'
title={prepareTooltip('Новая операция', 'Ctrl + Q')}
icon={<IconNewItem size='1.25rem' className='icon-green' />}
disabled={controller.isProcessing}
onClick={onCreate}
/>
<MiniButton
title='Удалить выбранную'
title='Выполнить выбранную / все операции'
icon={
<IconExecute
size='1.25rem'
className={controller.selected.length === 1 ? 'icon-primary' : 'icon-green'}
/>
}
disabled={controller.isProcessing}
onClick={onExecute}
/>
<MiniButton
titleHtml={prepareTooltip('Редактировать выбранную', 'Ctrl + клик')}
icon={<IconEdit2 size='1.25rem' className='icon-primary' />}
disabled={controller.selected.length !== 1 || controller.isProcessing}
onClick={onEdit}
/>
<MiniButton
titleHtml={prepareTooltip('Удалить выбранную', 'Delete')}
icon={<IconDestroy size='1.25rem' className='icon-red' />}
disabled={controller.selected.length !== 1 || controller.isProcessing}
onClick={onDelete}
@ -138,5 +161,5 @@ function ToolbarOssGraph({
</div>
);
}
//IconExecute
export default ToolbarOssGraph;

View File

@ -56,7 +56,8 @@ export interface IOssEditContext {
createInput: (target: OperationID, positions: IOperationPosition[]) => void;
promptEditInput: (target: OperationID, positions: IOperationPosition[]) => void;
promptEditOperation: (target: OperationID, positions: IOperationPosition[]) => void;
runOperation: (target: OperationID, positions: IOperationPosition[]) => void;
executeOperation: (target: OperationID, positions: IOperationPosition[]) => void;
executeAll: (positions: IOperationPosition[]) => void;
}
const OssEditContext = createContext<IOssEditContext | null>(null);
@ -279,15 +280,21 @@ export const OssEditState = ({ selected, setSelected, children }: OssEditStatePr
[model, targetOperationID, positions]
);
const runOperation = useCallback(
const executeOperation = useCallback(
(target: OperationID, positions: IOperationPosition[]) => {
model.executeOperation(
{
const data = {
target: target,
positions: positions
};
model.executeOperation(data, () => toast.success(information.operationExecuted));
},
() => toast.success(information.changesSaved)
[model]
);
const executeAll = useCallback(
(positions: IOperationPosition[]) => {
const data = { positions: positions };
model.executeAll(data, () => toast.success(information.allOperationExecuted));
},
[model]
);
@ -320,7 +327,8 @@ export const OssEditState = ({ selected, setSelected, children }: OssEditStatePr
createInput,
promptEditInput,
promptEditOperation,
runOperation
executeOperation,
executeAll
}}
>
{model.schema ? (

View File

@ -940,6 +940,8 @@ export const information = {
versionDestroyed: 'Версия удалена',
itemDestroyed: 'Схема удалена',
operationDestroyed: 'Операция удалена',
operationExecuted: 'Операция выполнена',
allOperationExecuted: 'Все операции выполнены',
constituentsDestroyed: (aliases: string) => `Конституенты удалены: ${aliases}`
};