F: Implementing backend for synthesis operation
This commit is contained in:
parent
6a21125e87
commit
2a30661355
|
@ -432,7 +432,8 @@ disable=too-many-public-methods,
|
|||
missing-function-docstring,
|
||||
attribute-defined-outside-init,
|
||||
ungrouped-imports,
|
||||
abstract-method
|
||||
abstract-method,
|
||||
fixme
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
|
|
|
@ -5,10 +5,12 @@ from django.core.exceptions import ValidationError
|
|||
from django.db import transaction
|
||||
from django.db.models import QuerySet
|
||||
|
||||
from apps.library.models import LibraryItem, LibraryItemType
|
||||
from apps.library.models import Editor, LibraryItem, LibraryItemType
|
||||
from apps.rsform.models import RSForm
|
||||
from shared import messages as msg
|
||||
|
||||
from .Argument import Argument
|
||||
from .Inheritance import Inheritance
|
||||
from .Operation import Operation
|
||||
from .Substitution import Substitution
|
||||
|
||||
|
@ -76,8 +78,8 @@ class OperationSchema:
|
|||
''' Delete operation. '''
|
||||
operation.delete()
|
||||
|
||||
# deal with attached schema
|
||||
# trigger on_change effects
|
||||
# TODO: deal with attached schema
|
||||
# TODO: trigger on_change effects
|
||||
|
||||
self.save()
|
||||
|
||||
|
@ -86,16 +88,15 @@ class OperationSchema:
|
|||
''' Set input schema for operation. '''
|
||||
if schema == target.result:
|
||||
return
|
||||
if schema:
|
||||
target.result = schema
|
||||
if schema is not None:
|
||||
target.result = schema
|
||||
target.alias = schema.alias
|
||||
target.title = schema.title
|
||||
target.comment = schema.comment
|
||||
else:
|
||||
target.result = None
|
||||
target.save()
|
||||
|
||||
# trigger on_change effects
|
||||
# TODO: trigger on_change effects
|
||||
|
||||
self.save()
|
||||
|
||||
|
@ -117,7 +118,7 @@ class OperationSchema:
|
|||
Argument.objects.create(operation=operation, argument=arg)
|
||||
if not changed:
|
||||
return
|
||||
# trigger on_change effects
|
||||
# TODO: trigger on_change effects
|
||||
self.save()
|
||||
|
||||
@transaction.atomic
|
||||
|
@ -148,6 +149,63 @@ class OperationSchema:
|
|||
|
||||
if not changed:
|
||||
return
|
||||
# trigger on_change effects
|
||||
# TODO: trigger on_change effects
|
||||
|
||||
self.save()
|
||||
|
||||
@transaction.atomic
|
||||
def create_input(self, operation: Operation) -> RSForm:
|
||||
''' Create input RSForm. '''
|
||||
schema = RSForm.create(
|
||||
owner=self.model.owner,
|
||||
alias=operation.alias,
|
||||
title=operation.title,
|
||||
comment=operation.comment,
|
||||
visible=False,
|
||||
access_policy=self.model.access_policy,
|
||||
location=self.model.location
|
||||
)
|
||||
Editor.set(schema.model, self.model.editors())
|
||||
operation.result = schema.model
|
||||
operation.save()
|
||||
self.save()
|
||||
return schema
|
||||
|
||||
@transaction.atomic
|
||||
def execute_operation(self, operation: Operation) -> bool:
|
||||
''' Execute target operation. '''
|
||||
schemas: list[LibraryItem] = [arg.argument.result for arg in operation.getArguments()]
|
||||
if None in schemas:
|
||||
return False
|
||||
substitutions = operation.getSubstitutions()
|
||||
receiver = self.create_input(operation)
|
||||
|
||||
parents: dict = {}
|
||||
children: dict = {}
|
||||
for operand in schemas:
|
||||
schema = RSForm(operand)
|
||||
items = list(schema.constituents())
|
||||
new_items = receiver.insert_copy(items)
|
||||
for (i, cst) in enumerate(new_items):
|
||||
parents[cst.pk] = items[i]
|
||||
children[items[i].pk] = cst
|
||||
|
||||
for sub in substitutions:
|
||||
original = children[sub.original.pk]
|
||||
replacement = children[sub.substitution.pk]
|
||||
receiver.substitute(original, replacement)
|
||||
|
||||
# TODO: remove duplicates from diamond
|
||||
|
||||
for cst in receiver.constituents():
|
||||
parent = parents.get(cst.id)
|
||||
assert parent is not None
|
||||
Inheritance.objects.create(
|
||||
child=cst,
|
||||
parent=parent
|
||||
)
|
||||
|
||||
receiver.restore_order()
|
||||
receiver.reset_aliases()
|
||||
self.save()
|
||||
return True
|
||||
|
|
|
@ -92,8 +92,10 @@ class OperationUpdateSerializer(serializers.Serializer):
|
|||
if 'substitutions' not in attrs:
|
||||
return attrs
|
||||
schemas = [arg.result.pk for arg in attrs['arguments'] if arg.result is not None]
|
||||
substitutions = attrs['substitutions']
|
||||
to_delete = {x['original'].pk for x in substitutions}
|
||||
deleted = set()
|
||||
for item in attrs['substitutions']:
|
||||
for item in substitutions:
|
||||
original_cst = cast(Constituenta, item['original'])
|
||||
substitution_cst = cast(Constituenta, item['substitution'])
|
||||
if original_cst.schema.pk not in schemas:
|
||||
|
@ -104,7 +106,7 @@ class OperationUpdateSerializer(serializers.Serializer):
|
|||
raise serializers.ValidationError({
|
||||
f'{substitution_cst.id}': msg.constituentaNotFromOperation()
|
||||
})
|
||||
if original_cst.pk in deleted:
|
||||
if original_cst.pk in deleted or substitution_cst.pk in to_delete:
|
||||
raise serializers.ValidationError({
|
||||
f'{original_cst.id}': msg.substituteDouble(original_cst.alias)
|
||||
})
|
||||
|
|
|
@ -23,10 +23,27 @@ class TestOssViewset(EndpointTester):
|
|||
|
||||
|
||||
def populateData(self):
|
||||
self.ks1 = RSForm.create(alias='KS1', title='Test1', owner=self.user)
|
||||
self.ks1x1 = self.ks1.insert_new('X1', term_resolved='X1_1')
|
||||
self.ks2 = RSForm.create(alias='KS2', title='Test2', owner=self.user)
|
||||
self.ks2x1 = self.ks2.insert_new('X2', term_resolved='X1_2')
|
||||
self.ks1 = RSForm.create(
|
||||
alias='KS1',
|
||||
title='Test1',
|
||||
owner=self.user
|
||||
)
|
||||
self.ks1x1 = self.ks1.insert_new(
|
||||
'X1',
|
||||
term_raw='X1_1',
|
||||
term_resolved='X1_1'
|
||||
)
|
||||
self.ks2 = RSForm.create(
|
||||
alias='KS2',
|
||||
title='Test2',
|
||||
owner=self.user
|
||||
)
|
||||
self.ks2x1 = self.ks2.insert_new(
|
||||
'X2',
|
||||
term_raw='X1_2',
|
||||
term_resolved='X1_2'
|
||||
)
|
||||
|
||||
self.operation1 = self.owned.create_operation(
|
||||
alias='1',
|
||||
operation_type=OperationType.INPUT,
|
||||
|
@ -399,3 +416,61 @@ class TestOssViewset(EndpointTester):
|
|||
self.assertEqual(self.operation1.result.alias, data['item_data']['alias'])
|
||||
self.assertEqual(self.operation1.result.title, data['item_data']['title'])
|
||||
self.assertEqual(self.operation1.result.comment, data['item_data']['comment'])
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/update-operation', method='patch')
|
||||
def test_update_operation_invalid_substitution(self):
|
||||
self.populateData()
|
||||
|
||||
self.ks1x2 = self.ks1.insert_new('X2')
|
||||
|
||||
data = {
|
||||
'target': self.operation3.pk,
|
||||
'item_data': {
|
||||
'alias': 'Test3 mod',
|
||||
'title': 'Test title mod',
|
||||
'comment': 'Comment mod'
|
||||
},
|
||||
'positions': [],
|
||||
'arguments': [self.operation1.pk, self.operation2.pk],
|
||||
'substitutions': [
|
||||
{
|
||||
'original': self.ks1x1.pk,
|
||||
'substitution': self.ks2x1.pk
|
||||
},
|
||||
{
|
||||
'original': self.ks2x1.pk,
|
||||
'substitution': self.ks1x2.pk
|
||||
}
|
||||
]
|
||||
}
|
||||
self.executeBadData(data=data, item=self.owned_id)
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/execute-operation', method='post')
|
||||
def test_execute_operation(self):
|
||||
self.populateData()
|
||||
self.executeBadData(item=self.owned_id)
|
||||
|
||||
data = {
|
||||
'positions': [],
|
||||
'target': self.operation1.pk
|
||||
}
|
||||
self.executeBadData(data=data)
|
||||
|
||||
data['target'] = self.operation3.pk
|
||||
self.toggle_admin(True)
|
||||
self.executeBadData(data=data, item=self.unowned_id)
|
||||
self.logout()
|
||||
self.executeForbidden(data=data, item=self.owned_id)
|
||||
|
||||
self.login()
|
||||
self.executeOK(data=data)
|
||||
self.operation3.refresh_from_db()
|
||||
schema = self.operation3.result
|
||||
self.assertEqual(schema.alias, self.operation3.alias)
|
||||
self.assertEqual(schema.comment, self.operation3.comment)
|
||||
self.assertEqual(schema.title, self.operation3.title)
|
||||
self.assertEqual(schema.visible, False)
|
||||
items = list(RSForm(schema).constituents())
|
||||
self.assertEqual(len(items), 1)
|
||||
self.assertEqual(items[0].alias, 'X1')
|
||||
self.assertEqual(items[0].term_resolved, self.ks2x1.term_resolved)
|
||||
|
|
|
@ -10,7 +10,7 @@ from rest_framework.decorators import action
|
|||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
|
||||
from apps.library.models import Editor, LibraryItem, LibraryItemType
|
||||
from apps.library.models import LibraryItem, LibraryItemType
|
||||
from apps.library.serializers import LibraryItemSerializer
|
||||
from shared import messages as msg
|
||||
from shared import permissions
|
||||
|
@ -38,7 +38,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
'create_input',
|
||||
'set_input',
|
||||
'update_operation',
|
||||
'execute_operation',
|
||||
'execute_operation'
|
||||
]:
|
||||
permission_list = [permissions.ItemEditor]
|
||||
elif self.action in ['details']:
|
||||
|
@ -103,28 +103,14 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
oss = m.OperationSchema(self.get_object())
|
||||
with transaction.atomic():
|
||||
oss.update_positions(serializer.validated_data['positions'])
|
||||
data: dict = serializer.validated_data['item_data']
|
||||
if data['operation_type'] == m.OperationType.INPUT and serializer.validated_data['create_schema']:
|
||||
schema = LibraryItem.objects.create(
|
||||
item_type=LibraryItemType.RSFORM,
|
||||
owner=oss.model.owner,
|
||||
alias=data['alias'],
|
||||
title=data['title'],
|
||||
comment=data['comment'],
|
||||
visible=False,
|
||||
access_policy=oss.model.access_policy,
|
||||
location=oss.model.location
|
||||
)
|
||||
Editor.set(schema, oss.model.editors())
|
||||
data['result'] = schema
|
||||
new_operation = oss.create_operation(**data)
|
||||
new_operation = oss.create_operation(**serializer.validated_data['item_data'])
|
||||
if new_operation.operation_type == m.OperationType.INPUT and serializer.validated_data['create_schema']:
|
||||
oss.create_input(new_operation)
|
||||
if new_operation.operation_type != m.OperationType.INPUT and 'arguments' in serializer.validated_data:
|
||||
oss.set_arguments(
|
||||
operation=new_operation,
|
||||
arguments=serializer.validated_data['arguments']
|
||||
)
|
||||
|
||||
oss.refresh_from_db()
|
||||
return Response(
|
||||
status=c.HTTP_201_CREATED,
|
||||
data={
|
||||
|
@ -158,7 +144,6 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
oss.update_positions(serializer.validated_data['positions'])
|
||||
oss.delete_operation(serializer.validated_data['target'])
|
||||
|
||||
oss.refresh_from_db()
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.OperationSchemaSerializer(oss.model).data
|
||||
|
@ -197,25 +182,12 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
oss = m.OperationSchema(self.get_object())
|
||||
with transaction.atomic():
|
||||
oss.update_positions(serializer.validated_data['positions'])
|
||||
schema = LibraryItem.objects.create(
|
||||
item_type=LibraryItemType.RSFORM,
|
||||
owner=oss.model.owner,
|
||||
alias=operation.alias,
|
||||
title=operation.title,
|
||||
comment=operation.comment,
|
||||
visible=False,
|
||||
access_policy=oss.model.access_policy,
|
||||
location=oss.model.location
|
||||
)
|
||||
Editor.set(schema, oss.model.editors())
|
||||
operation.result = schema
|
||||
operation.save()
|
||||
schema = oss.create_input(operation)
|
||||
|
||||
oss.refresh_from_db()
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data={
|
||||
'new_schema': LibraryItemSerializer(schema).data,
|
||||
'new_schema': LibraryItemSerializer(schema.model).data,
|
||||
'oss': s.OperationSchemaSerializer(oss.model).data
|
||||
}
|
||||
)
|
||||
|
@ -241,20 +213,10 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
operation: m.Operation = cast(m.Operation, serializer.validated_data['target'])
|
||||
result = serializer.validated_data['input']
|
||||
oss = m.OperationSchema(self.get_object())
|
||||
with transaction.atomic():
|
||||
oss.update_positions(serializer.validated_data['positions'])
|
||||
operation.result = result
|
||||
if result is not None:
|
||||
operation.title = result.title
|
||||
operation.comment = result.comment
|
||||
operation.alias = result.alias
|
||||
operation.save()
|
||||
|
||||
# update arguments
|
||||
|
||||
oss.refresh_from_db()
|
||||
oss.set_input(operation, serializer.validated_data['input'])
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.OperationSchemaSerializer(oss.model).data
|
||||
|
@ -336,17 +298,10 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
})
|
||||
|
||||
oss = m.OperationSchema(self.get_object())
|
||||
# with transaction.atomic():
|
||||
# oss.update_positions(serializer.validated_data['positions'])
|
||||
# operation.result.refresh_from_db()
|
||||
# operation.result.title = operation.title
|
||||
# operation.result.comment = operation.comment
|
||||
# operation.result.alias = operation.alias
|
||||
# operation.result.save()
|
||||
with transaction.atomic():
|
||||
oss.update_positions(serializer.validated_data['positions'])
|
||||
oss.execute_operation(operation)
|
||||
|
||||
# update arguments
|
||||
|
||||
oss.refresh_from_db()
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.OperationSchemaSerializer(oss.model).data
|
||||
|
|
|
@ -12,7 +12,6 @@ from django.db.models import (
|
|||
TextChoices,
|
||||
TextField
|
||||
)
|
||||
from django.urls import reverse
|
||||
|
||||
from ..utils import apply_pattern
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
cst = m.Constituenta.objects.get(pk=request.data['id'])
|
||||
if cst.schema != schema:
|
||||
raise ValidationError({
|
||||
f'schema': msg.constituentaNotInRSform(schema.title)
|
||||
'schema': msg.constituentaNotInRSform(schema.title)
|
||||
})
|
||||
serializer.update(instance=cst, validated_data=serializer.validated_data)
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@ def operationNotInOSS(title: str):
|
|||
return f'Операция не принадлежит ОСС: {title}'
|
||||
|
||||
|
||||
def previousResultMissing():
|
||||
return 'Отсутствует результат предыдущей операции'
|
||||
|
||||
|
||||
def substitutionNotInList():
|
||||
return 'Отождествляемая конституента отсутствует в списке'
|
||||
|
||||
|
|
|
@ -73,10 +73,3 @@ 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
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import BadgeConstituenta from '@/components/info/BadgeConstituenta';
|
||||
import SelectConstituenta from '@/components/select/SelectConstituenta';
|
||||
|
@ -10,6 +11,7 @@ import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
|||
import { ILibraryItem } from '@/models/library';
|
||||
import { ICstSubstitute, IMultiSubstitution } from '@/models/oss';
|
||||
import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform';
|
||||
import { errors } from '@/utils/labels';
|
||||
|
||||
import { IconPageLeft, IconPageRight, IconRemove, IconReplace } from '../Icons';
|
||||
import NoData from '../ui/NoData';
|
||||
|
@ -98,6 +100,18 @@ function PickSubstitutions({
|
|||
original: deleteRight ? rightCst.id : leftCst.id,
|
||||
substitution: deleteRight ? leftCst.id : rightCst.id
|
||||
};
|
||||
const toDelete = substitutions.map(item => item.original);
|
||||
const replacements = substitutions.map(item => item.substitution);
|
||||
console.log(toDelete, replacements);
|
||||
console.log(newSubstitution);
|
||||
if (
|
||||
toDelete.includes(newSubstitution.original) ||
|
||||
toDelete.includes(newSubstitution.substitution) ||
|
||||
replacements.includes(newSubstitution.original)
|
||||
) {
|
||||
toast.error(errors.reuseOriginal);
|
||||
return;
|
||||
}
|
||||
setSubstitutions(prev => [...prev, newSubstitution]);
|
||||
setLeftCst(undefined);
|
||||
setRightCst(undefined);
|
||||
|
|
|
@ -19,7 +19,6 @@ import {
|
|||
patchUpdateOperation,
|
||||
patchUpdatePositions,
|
||||
postCreateOperation,
|
||||
postExecuteAll,
|
||||
postExecuteOperation
|
||||
} from '@/backend/oss';
|
||||
import { type ErrorData } from '@/components/info/InfoError';
|
||||
|
@ -69,7 +68,6 @@ 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);
|
||||
|
@ -413,28 +411,6 @@ 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={{
|
||||
|
@ -461,8 +437,7 @@ export const OssState = ({ itemID, children }: OssStateProps) => {
|
|||
createInput,
|
||||
setInput,
|
||||
updateOperation,
|
||||
executeOperation,
|
||||
executeAll
|
||||
executeOperation
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -170,12 +170,11 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
|||
);
|
||||
|
||||
const handleExecuteSelected = useCallback(() => {
|
||||
if (controller.selected.length === 1) {
|
||||
handleExecuteOperation(controller.selected[0]);
|
||||
} else {
|
||||
controller.executeAll(getPositions());
|
||||
if (controller.selected.length !== 1) {
|
||||
return;
|
||||
}
|
||||
}, [controller, handleExecuteOperation, getPositions]);
|
||||
handleExecuteOperation(controller.selected[0]);
|
||||
}, [controller, handleExecuteOperation]);
|
||||
|
||||
const handleFitView = useCallback(() => {
|
||||
flow.fitView({ duration: PARAMETER.zoomDuration });
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import clsx from 'clsx';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import {
|
||||
IconAnimation,
|
||||
|
@ -18,6 +21,7 @@ import {
|
|||
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||
import MiniButton from '@/components/ui/MiniButton';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { OperationType } from '@/models/oss';
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
import { prepareTooltip } from '@/utils/labels';
|
||||
|
||||
|
@ -59,6 +63,30 @@ function ToolbarOssGraph({
|
|||
toggleEdgeStraight
|
||||
}: ToolbarOssGraphProps) {
|
||||
const controller = useOssEdit();
|
||||
const selectedOperation = useMemo(
|
||||
() => controller.schema?.operationByID.get(controller.selected[0]),
|
||||
[controller.selected, controller.schema]
|
||||
);
|
||||
const readyForSynthesis = useMemo(() => {
|
||||
if (!selectedOperation || selectedOperation.operation_type !== OperationType.SYNTHESIS) {
|
||||
return false;
|
||||
}
|
||||
if (!controller.schema || selectedOperation.result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const argumentIDs = controller.schema.graph.expandInputs([selectedOperation.id]);
|
||||
if (!argumentIDs || argumentIDs.length < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const argumentOperations = argumentIDs.map(id => controller.schema!.operationByID.get(id)!);
|
||||
if (argumentOperations.some(item => item.result === null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}, [selectedOperation, controller.schema]);
|
||||
|
||||
return (
|
||||
<div className='flex flex-col items-center'>
|
||||
|
@ -120,7 +148,6 @@ function ToolbarOssGraph({
|
|||
</div>
|
||||
{controller.isMutable ? (
|
||||
<div className='cc-icons'>
|
||||
{' '}
|
||||
<MiniButton
|
||||
titleHtml={prepareTooltip('Сохранить изменения', 'Ctrl + S')}
|
||||
icon={<IconSave size='1.25rem' className='icon-primary' />}
|
||||
|
@ -134,14 +161,9 @@ function ToolbarOssGraph({
|
|||
onClick={onCreate}
|
||||
/>
|
||||
<MiniButton
|
||||
title='Выполнить выбранную / все операции'
|
||||
icon={
|
||||
<IconExecute
|
||||
size='1.25rem'
|
||||
className={controller.selected.length === 1 ? 'icon-primary' : 'icon-green'}
|
||||
/>
|
||||
}
|
||||
disabled={controller.isProcessing}
|
||||
title='Выполнить операцию'
|
||||
icon={<IconExecute size='1.25rem' className='icon-green' />}
|
||||
disabled={controller.isProcessing || controller.selected.length !== 1 || !readyForSynthesis}
|
||||
onClick={onExecute}
|
||||
/>
|
||||
<MiniButton
|
||||
|
|
|
@ -57,7 +57,6 @@ export interface IOssEditContext {
|
|||
promptEditInput: (target: OperationID, positions: IOperationPosition[]) => void;
|
||||
promptEditOperation: (target: OperationID, positions: IOperationPosition[]) => void;
|
||||
executeOperation: (target: OperationID, positions: IOperationPosition[]) => void;
|
||||
executeAll: (positions: IOperationPosition[]) => void;
|
||||
}
|
||||
|
||||
const OssEditContext = createContext<IOssEditContext | null>(null);
|
||||
|
@ -290,14 +289,6 @@ export const OssEditState = ({ selected, setSelected, children }: OssEditStatePr
|
|||
[model]
|
||||
);
|
||||
|
||||
const executeAll = useCallback(
|
||||
(positions: IOperationPosition[]) => {
|
||||
const data = { positions: positions };
|
||||
model.executeAll(data, () => toast.success(information.allOperationExecuted));
|
||||
},
|
||||
[model]
|
||||
);
|
||||
|
||||
return (
|
||||
<OssEditContext.Provider
|
||||
value={{
|
||||
|
@ -326,8 +317,7 @@ export const OssEditState = ({ selected, setSelected, children }: OssEditStatePr
|
|||
createInput,
|
||||
promptEditInput,
|
||||
promptEditOperation,
|
||||
executeOperation,
|
||||
executeAll
|
||||
executeOperation
|
||||
}}
|
||||
>
|
||||
{model.schema ? (
|
||||
|
|
|
@ -951,7 +951,8 @@ export const information = {
|
|||
export const errors = {
|
||||
astFailed: 'Невозможно построить дерево разбора',
|
||||
passwordsMismatch: 'Пароли не совпадают',
|
||||
imageFailed: 'Ошибка при создании изображения'
|
||||
imageFailed: 'Ошибка при создании изображения',
|
||||
reuseOriginal: 'Повторное использование удаляемой конституенты при отождествлении'
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue
Block a user