Compare commits
6 Commits
2a30661355
...
27ba4a5da8
Author | SHA1 | Date | |
---|---|---|---|
![]() |
27ba4a5da8 | ||
![]() |
e29f7409c1 | ||
![]() |
62cb9a5eeb | ||
![]() |
967eabde51 | ||
![]() |
e5977d259b | ||
![]() |
057850678a |
6
TODO.txt
6
TODO.txt
|
@ -2,10 +2,8 @@
|
||||||
For more specific TODOs see comments in code
|
For more specific TODOs see comments in code
|
||||||
|
|
||||||
[Functionality - PROGRESS]
|
[Functionality - PROGRESS]
|
||||||
- Operational synthesis schema as LibraryItem ?
|
- Design first user experience
|
||||||
|
- Private projects. Consider cooperative editing
|
||||||
- Library organization, search and exploration. Consider new user experience
|
|
||||||
- Private projects and permissions. Consider cooperative editing
|
|
||||||
|
|
||||||
|
|
||||||
[Functionality - PENDING]
|
[Functionality - PENDING]
|
||||||
|
|
|
@ -5,6 +5,7 @@ from .data_access import (
|
||||||
LibraryItemBaseSerializer,
|
LibraryItemBaseSerializer,
|
||||||
LibraryItemCloneSerializer,
|
LibraryItemCloneSerializer,
|
||||||
LibraryItemDetailsSerializer,
|
LibraryItemDetailsSerializer,
|
||||||
|
LibraryItemReferenceSerializer,
|
||||||
LibraryItemSerializer,
|
LibraryItemSerializer,
|
||||||
UsersListSerializer,
|
UsersListSerializer,
|
||||||
UserTargetSerializer,
|
UserTargetSerializer,
|
||||||
|
|
|
@ -17,6 +17,14 @@ class LibraryItemBaseSerializer(serializers.ModelSerializer):
|
||||||
read_only_fields = ('id',)
|
read_only_fields = ('id',)
|
||||||
|
|
||||||
|
|
||||||
|
class LibraryItemReferenceSerializer(serializers.ModelSerializer):
|
||||||
|
''' Serializer: reference to LibraryItem. '''
|
||||||
|
class Meta:
|
||||||
|
''' serializer metadata. '''
|
||||||
|
model = LibraryItem
|
||||||
|
fields = 'id', 'alias'
|
||||||
|
|
||||||
|
|
||||||
class LibraryItemSerializer(serializers.ModelSerializer):
|
class LibraryItemSerializer(serializers.ModelSerializer):
|
||||||
''' Serializer: LibraryItem entry limited access. '''
|
''' Serializer: LibraryItem entry limited access. '''
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
''' Models: OSS API. '''
|
''' Models: OSS API. '''
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
|
|
||||||
from apps.library.models import Editor, LibraryItem, LibraryItemType
|
from apps.library.models import Editor, LibraryItem, LibraryItemType
|
||||||
from apps.rsform.models import RSForm
|
from apps.rsform.models import RSForm
|
||||||
from shared import messages as msg
|
|
||||||
|
|
||||||
from .Argument import Argument
|
from .Argument import Argument
|
||||||
from .Inheritance import Inheritance
|
from .Inheritance import Inheritance
|
||||||
|
@ -66,8 +64,6 @@ class OperationSchema:
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def create_operation(self, **kwargs) -> Operation:
|
def create_operation(self, **kwargs) -> Operation:
|
||||||
''' Insert new operation. '''
|
''' Insert new operation. '''
|
||||||
if kwargs['alias'] != '' and self.operations().filter(alias=kwargs['alias']).exists():
|
|
||||||
raise ValidationError(msg.aliasTaken(kwargs['alias']))
|
|
||||||
result = Operation.objects.create(oss=self.model, **kwargs)
|
result = Operation.objects.create(oss=self.model, **kwargs)
|
||||||
self.save()
|
self.save()
|
||||||
result.refresh_from_db()
|
result.refresh_from_db()
|
||||||
|
@ -198,7 +194,7 @@ class OperationSchema:
|
||||||
# TODO: remove duplicates from diamond
|
# TODO: remove duplicates from diamond
|
||||||
|
|
||||||
for cst in receiver.constituents():
|
for cst in receiver.constituents():
|
||||||
parent = parents.get(cst.id)
|
parent = parents.get(cst.pk)
|
||||||
assert parent is not None
|
assert parent is not None
|
||||||
Inheritance.objects.create(
|
Inheritance.objects.create(
|
||||||
child=cst,
|
child=cst,
|
||||||
|
|
|
@ -10,4 +10,4 @@ from .data_access import (
|
||||||
OperationUpdateSerializer,
|
OperationUpdateSerializer,
|
||||||
SetOperationInputSerializer
|
SetOperationInputSerializer
|
||||||
)
|
)
|
||||||
from .responses import NewOperationResponse, NewSchemaResponse
|
from .responses import ConstituentaReferenceResponse, NewOperationResponse, NewSchemaResponse
|
||||||
|
|
|
@ -84,33 +84,33 @@ class OperationUpdateSerializer(serializers.Serializer):
|
||||||
|
|
||||||
oss = cast(LibraryItem, self.context['oss'])
|
oss = cast(LibraryItem, self.context['oss'])
|
||||||
for operation in attrs['arguments']:
|
for operation in attrs['arguments']:
|
||||||
if operation.oss != oss:
|
if operation.oss_id != oss.pk:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
'arguments': msg.operationNotInOSS(oss.title)
|
'arguments': msg.operationNotInOSS(oss.title)
|
||||||
})
|
})
|
||||||
|
|
||||||
if 'substitutions' not in attrs:
|
if 'substitutions' not in attrs:
|
||||||
return attrs
|
return attrs
|
||||||
schemas = [arg.result.pk for arg in attrs['arguments'] if arg.result is not None]
|
schemas = [arg.result_id for arg in attrs['arguments'] if arg.result is not None]
|
||||||
substitutions = attrs['substitutions']
|
substitutions = attrs['substitutions']
|
||||||
to_delete = {x['original'].pk for x in substitutions}
|
to_delete = {x['original'].pk for x in substitutions}
|
||||||
deleted = set()
|
deleted = set()
|
||||||
for item in substitutions:
|
for item in substitutions:
|
||||||
original_cst = cast(Constituenta, item['original'])
|
original_cst = cast(Constituenta, item['original'])
|
||||||
substitution_cst = cast(Constituenta, item['substitution'])
|
substitution_cst = cast(Constituenta, item['substitution'])
|
||||||
if original_cst.schema.pk not in schemas:
|
if original_cst.schema_id not in schemas:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{original_cst.id}': msg.constituentaNotFromOperation()
|
f'{original_cst.pk}': msg.constituentaNotFromOperation()
|
||||||
})
|
})
|
||||||
if substitution_cst.schema.pk not in schemas:
|
if substitution_cst.schema_id not in schemas:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{substitution_cst.id}': msg.constituentaNotFromOperation()
|
f'{substitution_cst.pk}': msg.constituentaNotFromOperation()
|
||||||
})
|
})
|
||||||
if original_cst.pk in deleted or substitution_cst.pk in to_delete:
|
if original_cst.pk in deleted or substitution_cst.pk in to_delete:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{original_cst.id}': msg.substituteDouble(original_cst.alias)
|
f'{original_cst.pk}': msg.substituteDouble(original_cst.alias)
|
||||||
})
|
})
|
||||||
if original_cst.schema == substitution_cst.schema:
|
if original_cst.schema_id == substitution_cst.schema_id:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
'alias': msg.substituteTrivial(original_cst.alias)
|
'alias': msg.substituteTrivial(original_cst.alias)
|
||||||
})
|
})
|
||||||
|
@ -131,7 +131,7 @@ class OperationTargetSerializer(serializers.Serializer):
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
oss = cast(LibraryItem, self.context['oss'])
|
oss = cast(LibraryItem, self.context['oss'])
|
||||||
operation = cast(Operation, attrs['target'])
|
operation = cast(Operation, attrs['target'])
|
||||||
if oss and operation.oss != oss:
|
if oss and operation.oss_id != oss.pk:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
'target': msg.operationNotInOSS(oss.title)
|
'target': msg.operationNotInOSS(oss.title)
|
||||||
})
|
})
|
||||||
|
@ -155,7 +155,7 @@ class SetOperationInputSerializer(serializers.Serializer):
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
oss = cast(LibraryItem, self.context['oss'])
|
oss = cast(LibraryItem, self.context['oss'])
|
||||||
operation = cast(Operation, attrs['target'])
|
operation = cast(Operation, attrs['target'])
|
||||||
if oss and operation.oss != oss:
|
if oss and operation.oss_id != oss.pk:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
'target': msg.operationNotInOSS(oss.title)
|
'target': msg.operationNotInOSS(oss.title)
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,3 +16,9 @@ class NewSchemaResponse(serializers.Serializer):
|
||||||
''' Serializer: Create RSForm for input operation response. '''
|
''' Serializer: Create RSForm for input operation response. '''
|
||||||
new_schema = LibraryItemSerializer()
|
new_schema = LibraryItemSerializer()
|
||||||
oss = OperationSchemaSerializer()
|
oss = OperationSchemaSerializer()
|
||||||
|
|
||||||
|
|
||||||
|
class ConstituentaReferenceResponse(serializers.Serializer):
|
||||||
|
''' Serializer: Constituenta reference. '''
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
schema = serializers.IntegerField()
|
||||||
|
|
|
@ -12,6 +12,8 @@ from rest_framework.response import Response
|
||||||
|
|
||||||
from apps.library.models import LibraryItem, LibraryItemType
|
from apps.library.models import LibraryItem, LibraryItemType
|
||||||
from apps.library.serializers import LibraryItemSerializer
|
from apps.library.serializers import LibraryItemSerializer
|
||||||
|
from apps.rsform.models import Constituenta
|
||||||
|
from apps.rsform.serializers import CstTargetSerializer
|
||||||
from shared import messages as msg
|
from shared import messages as msg
|
||||||
from shared import permissions
|
from shared import permissions
|
||||||
|
|
||||||
|
@ -43,6 +45,8 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
||||||
permission_list = [permissions.ItemEditor]
|
permission_list = [permissions.ItemEditor]
|
||||||
elif self.action in ['details']:
|
elif self.action in ['details']:
|
||||||
permission_list = [permissions.ItemAnyone]
|
permission_list = [permissions.ItemAnyone]
|
||||||
|
elif self.action in ['get_predecessor']:
|
||||||
|
permission_list = [permissions.Anyone]
|
||||||
else:
|
else:
|
||||||
permission_list = [permissions.Anyone]
|
permission_list = [permissions.Anyone]
|
||||||
return [permission() for permission in permission_list]
|
return [permission() for permission in permission_list]
|
||||||
|
@ -253,7 +257,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
||||||
|
|
||||||
if operation.result is not None:
|
if operation.result is not None:
|
||||||
can_edit = permissions.can_edit_item(request.user, operation.result)
|
can_edit = permissions.can_edit_item(request.user, operation.result)
|
||||||
if can_edit:
|
if can_edit or operation.operation_type == m.OperationType.SYNTHESIS:
|
||||||
operation.result.alias = operation.alias
|
operation.result.alias = operation.alias
|
||||||
operation.result.title = operation.title
|
operation.result.title = operation.title
|
||||||
operation.result.comment = operation.comment
|
operation.result.comment = operation.comment
|
||||||
|
@ -306,3 +310,34 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
||||||
status=c.HTTP_200_OK,
|
status=c.HTTP_200_OK,
|
||||||
data=s.OperationSchemaSerializer(oss.model).data
|
data=s.OperationSchemaSerializer(oss.model).data
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
summary='get predecessor for target constituenta',
|
||||||
|
tags=['OSS'],
|
||||||
|
request=CstTargetSerializer(),
|
||||||
|
responses={
|
||||||
|
c.HTTP_200_OK: s.ConstituentaReferenceResponse,
|
||||||
|
c.HTTP_400_BAD_REQUEST: None,
|
||||||
|
c.HTTP_403_FORBIDDEN: None,
|
||||||
|
c.HTTP_404_NOT_FOUND: None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@action(detail=False, methods=['post'], url_path='get-predecessor')
|
||||||
|
def get_predecessor(self, request: Request):
|
||||||
|
''' Get predecessor. '''
|
||||||
|
# TODO: add tests for this method
|
||||||
|
serializer = CstTargetSerializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
cst = cast(Constituenta, serializer.validated_data['target'])
|
||||||
|
inheritance = m.Inheritance.objects.filter(child=cst)
|
||||||
|
while inheritance.exists():
|
||||||
|
cst = cast(m.Inheritance, inheritance.first()).parent
|
||||||
|
inheritance = m.Inheritance.objects.filter(child=cst)
|
||||||
|
|
||||||
|
return Response(
|
||||||
|
status=c.HTTP_200_OK,
|
||||||
|
data={
|
||||||
|
'id': cst.pk,
|
||||||
|
'schema': cst.schema_id
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
|
@ -142,7 +142,7 @@ class RSForm:
|
||||||
result.definition_resolved = resolver.resolve(result.definition_raw)
|
result.definition_resolved = resolver.resolve(result.definition_raw)
|
||||||
|
|
||||||
result.save()
|
result.save()
|
||||||
self.on_term_change([result.id])
|
self.on_term_change([result.pk])
|
||||||
result.refresh_from_db()
|
result.refresh_from_db()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ class RSForm:
|
||||||
count_bot = 0
|
count_bot = 0
|
||||||
size = len(listCst)
|
size = len(listCst)
|
||||||
update_list = []
|
update_list = []
|
||||||
for cst in self.constituents().only('id', 'order').order_by('order'):
|
for cst in self.constituents().only('order').order_by('order'):
|
||||||
if cst not in listCst:
|
if cst not in listCst:
|
||||||
if count_top + 1 < target:
|
if count_top + 1 < target:
|
||||||
cst.order = count_top + 1
|
cst.order = count_top + 1
|
||||||
|
@ -248,7 +248,7 @@ class RSForm:
|
||||||
mapping = {original.alias: substitution.alias}
|
mapping = {original.alias: substitution.alias}
|
||||||
self.apply_mapping(mapping)
|
self.apply_mapping(mapping)
|
||||||
original.delete()
|
original.delete()
|
||||||
self.on_term_change([substitution.id])
|
self.on_term_change([substitution.pk])
|
||||||
|
|
||||||
def restore_order(self):
|
def restore_order(self):
|
||||||
''' Restore order based on types and term graph. '''
|
''' Restore order based on types and term graph. '''
|
||||||
|
@ -335,7 +335,7 @@ class RSForm:
|
||||||
definition_formal=text,
|
definition_formal=text,
|
||||||
cst_type=cst_type
|
cst_type=cst_type
|
||||||
)
|
)
|
||||||
result.append(new_item.id)
|
result.append(new_item.pk)
|
||||||
free_index = free_index + 1
|
free_index = free_index + 1
|
||||||
position = position + 1
|
position = position + 1
|
||||||
|
|
||||||
|
@ -347,7 +347,7 @@ class RSForm:
|
||||||
return
|
return
|
||||||
update_list = \
|
update_list = \
|
||||||
Constituenta.objects \
|
Constituenta.objects \
|
||||||
.only('id', 'order', 'schema') \
|
.only('order') \
|
||||||
.filter(schema=self.model, order__gte=start)
|
.filter(schema=self.model, order__gte=start)
|
||||||
for cst in update_list:
|
for cst in update_list:
|
||||||
cst.order += shift
|
cst.order += shift
|
||||||
|
@ -372,7 +372,7 @@ class RSForm:
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def _reset_order(self):
|
def _reset_order(self):
|
||||||
order = 1
|
order = 1
|
||||||
for cst in self.constituents().only('id', 'order').order_by('order'):
|
for cst in self.constituents().only('order').order_by('order'):
|
||||||
if cst.order != order:
|
if cst.order != order:
|
||||||
cst.order = order
|
cst.order = order
|
||||||
cst.save()
|
cst.save()
|
||||||
|
@ -383,15 +383,15 @@ class RSForm:
|
||||||
result: Graph[int] = Graph()
|
result: Graph[int] = Graph()
|
||||||
cst_list = \
|
cst_list = \
|
||||||
self.constituents() \
|
self.constituents() \
|
||||||
.only('id', 'order', 'alias', 'definition_formal') \
|
.only('alias', 'definition_formal') \
|
||||||
.order_by('order')
|
.order_by('order')
|
||||||
for cst in cst_list:
|
for cst in cst_list:
|
||||||
result.add_node(cst.id)
|
result.add_node(cst.pk)
|
||||||
for cst in cst_list:
|
for cst in cst_list:
|
||||||
for alias in extract_globals(cst.definition_formal):
|
for alias in extract_globals(cst.definition_formal):
|
||||||
try:
|
try:
|
||||||
child = cst_list.get(alias=alias)
|
child = cst_list.get(alias=alias)
|
||||||
result.add_edge(src=child.id, dest=cst.id)
|
result.add_edge(src=child.pk, dest=cst.pk)
|
||||||
except Constituenta.DoesNotExist:
|
except Constituenta.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
return result
|
return result
|
||||||
|
@ -401,15 +401,15 @@ class RSForm:
|
||||||
result: Graph[int] = Graph()
|
result: Graph[int] = Graph()
|
||||||
cst_list = \
|
cst_list = \
|
||||||
self.constituents() \
|
self.constituents() \
|
||||||
.only('id', 'order', 'alias', 'term_raw') \
|
.only('alias', 'term_raw') \
|
||||||
.order_by('order')
|
.order_by('order')
|
||||||
for cst in cst_list:
|
for cst in cst_list:
|
||||||
result.add_node(cst.id)
|
result.add_node(cst.pk)
|
||||||
for cst in cst_list:
|
for cst in cst_list:
|
||||||
for alias in extract_entities(cst.term_raw):
|
for alias in extract_entities(cst.term_raw):
|
||||||
try:
|
try:
|
||||||
child = cst_list.get(alias=alias)
|
child = cst_list.get(alias=alias)
|
||||||
result.add_edge(src=child.id, dest=cst.id)
|
result.add_edge(src=child.pk, dest=cst.pk)
|
||||||
except Constituenta.DoesNotExist:
|
except Constituenta.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
return result
|
return result
|
||||||
|
@ -419,15 +419,15 @@ class RSForm:
|
||||||
result: Graph[int] = Graph()
|
result: Graph[int] = Graph()
|
||||||
cst_list = \
|
cst_list = \
|
||||||
self.constituents() \
|
self.constituents() \
|
||||||
.only('id', 'order', 'alias', 'definition_raw') \
|
.only('alias', 'definition_raw') \
|
||||||
.order_by('order')
|
.order_by('order')
|
||||||
for cst in cst_list:
|
for cst in cst_list:
|
||||||
result.add_node(cst.id)
|
result.add_node(cst.pk)
|
||||||
for cst in cst_list:
|
for cst in cst_list:
|
||||||
for alias in extract_entities(cst.definition_raw):
|
for alias in extract_entities(cst.definition_raw):
|
||||||
try:
|
try:
|
||||||
child = cst_list.get(alias=alias)
|
child = cst_list.get(alias=alias)
|
||||||
result.add_edge(src=child.id, dest=cst.id)
|
result.add_edge(src=child.pk, dest=cst.pk)
|
||||||
except Constituenta.DoesNotExist:
|
except Constituenta.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
return result
|
return result
|
||||||
|
@ -440,16 +440,16 @@ class SemanticInfo:
|
||||||
self._graph = schema._graph_formal()
|
self._graph = schema._graph_formal()
|
||||||
self._items = list(
|
self._items = list(
|
||||||
schema.constituents()
|
schema.constituents()
|
||||||
.only('id', 'alias', 'cst_type', 'definition_formal')
|
.only('alias', 'cst_type', 'definition_formal')
|
||||||
.order_by('order')
|
.order_by('order')
|
||||||
)
|
)
|
||||||
self._cst_by_alias = {cst.alias: cst for cst in self._items}
|
self._cst_by_alias = {cst.alias: cst for cst in self._items}
|
||||||
self._cst_by_ID = {cst.id: cst for cst in self._items}
|
self._cst_by_ID = {cst.pk: cst for cst in self._items}
|
||||||
self.info = {
|
self.info = {
|
||||||
cst.id: {
|
cst.pk: {
|
||||||
'is_simple': False,
|
'is_simple': False,
|
||||||
'is_template': False,
|
'is_template': False,
|
||||||
'parent': cst.id,
|
'parent': cst.pk,
|
||||||
'children': []
|
'children': []
|
||||||
}
|
}
|
||||||
for cst in self._items
|
for cst in self._items
|
||||||
|
@ -491,7 +491,7 @@ class SemanticInfo:
|
||||||
if target.cst_type == CstType.STRUCTURED or is_base_set(target.cst_type):
|
if target.cst_type == CstType.STRUCTURED or is_base_set(target.cst_type):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
dependencies = self._graph.inputs[target.id]
|
dependencies = self._graph.inputs[target.pk]
|
||||||
has_complex_dependency = any(
|
has_complex_dependency = any(
|
||||||
self.is_template(cst_id) and
|
self.is_template(cst_id) and
|
||||||
not self.is_simple_expression(cst_id) for cst_id in dependencies
|
not self.is_simple_expression(cst_id) for cst_id in dependencies
|
||||||
|
@ -507,18 +507,18 @@ class SemanticInfo:
|
||||||
def _infer_parent(self, target: Constituenta) -> int:
|
def _infer_parent(self, target: Constituenta) -> int:
|
||||||
sources = self._extract_sources(target)
|
sources = self._extract_sources(target)
|
||||||
if len(sources) != 1:
|
if len(sources) != 1:
|
||||||
return target.id
|
return target.pk
|
||||||
|
|
||||||
parent_id = next(iter(sources))
|
parent_id = next(iter(sources))
|
||||||
parent = self._cst_by_ID[parent_id]
|
parent = self._cst_by_ID[parent_id]
|
||||||
if is_base_set(parent.cst_type):
|
if is_base_set(parent.cst_type):
|
||||||
return target.id
|
return target.pk
|
||||||
return parent_id
|
return parent_id
|
||||||
|
|
||||||
def _extract_sources(self, target: Constituenta) -> set[int]:
|
def _extract_sources(self, target: Constituenta) -> set[int]:
|
||||||
sources: set[int] = set()
|
sources: set[int] = set()
|
||||||
if not is_functional(target.cst_type):
|
if not is_functional(target.cst_type):
|
||||||
for parent_id in self._graph.inputs[target.id]:
|
for parent_id in self._graph.inputs[target.pk]:
|
||||||
parent_info = self[parent_id]
|
parent_info = self[parent_id]
|
||||||
if not parent_info['is_template'] or not parent_info['is_simple']:
|
if not parent_info['is_template'] or not parent_info['is_simple']:
|
||||||
sources.add(parent_info['parent'])
|
sources.add(parent_info['parent'])
|
||||||
|
@ -531,7 +531,7 @@ class SemanticInfo:
|
||||||
if not parent:
|
if not parent:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
parent_info = self[parent.id]
|
parent_info = self[parent.pk]
|
||||||
if not parent_info['is_template'] or not parent_info['is_simple']:
|
if not parent_info['is_template'] or not parent_info['is_simple']:
|
||||||
sources.add(parent_info['parent'])
|
sources.add(parent_info['parent'])
|
||||||
|
|
||||||
|
@ -542,7 +542,7 @@ class SemanticInfo:
|
||||||
if not parent:
|
if not parent:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
parent_info = self[parent.id]
|
parent_info = self[parent.pk]
|
||||||
if not is_base_set(parent.cst_type) and \
|
if not is_base_set(parent.cst_type) and \
|
||||||
(not parent_info['is_template'] or not parent_info['is_simple']):
|
(not parent_info['is_template'] or not parent_info['is_simple']):
|
||||||
sources.add(parent_info['parent'])
|
sources.add(parent_info['parent'])
|
||||||
|
@ -567,10 +567,10 @@ class _OrderManager:
|
||||||
self._graph = schema._graph_formal()
|
self._graph = schema._graph_formal()
|
||||||
self._items = list(
|
self._items = list(
|
||||||
schema.constituents()
|
schema.constituents()
|
||||||
.only('id', 'order', 'alias', 'cst_type', 'definition_formal')
|
.only('order', 'alias', 'cst_type', 'definition_formal')
|
||||||
.order_by('order')
|
.order_by('order')
|
||||||
)
|
)
|
||||||
self._cst_by_ID = {cst.id: cst for cst in self._items}
|
self._cst_by_ID = {cst.pk: cst for cst in self._items}
|
||||||
|
|
||||||
def restore_order(self) -> None:
|
def restore_order(self) -> None:
|
||||||
''' Implement order restoration process. '''
|
''' Implement order restoration process. '''
|
||||||
|
@ -582,20 +582,20 @@ class _OrderManager:
|
||||||
self._save_order()
|
self._save_order()
|
||||||
|
|
||||||
def _fix_topological(self) -> None:
|
def _fix_topological(self) -> None:
|
||||||
sorted_ids = self._graph.sort_stable([cst.id for cst in self._items])
|
sorted_ids = self._graph.sort_stable([cst.pk for cst in self._items])
|
||||||
sorted_items = [next(cst for cst in self._items if cst.id == id) for id in sorted_ids]
|
sorted_items = [next(cst for cst in self._items if cst.pk == id) for id in sorted_ids]
|
||||||
self._items = sorted_items
|
self._items = sorted_items
|
||||||
|
|
||||||
def _fix_kernel(self) -> None:
|
def _fix_kernel(self) -> None:
|
||||||
result = [cst for cst in self._items if cst.cst_type == CstType.BASE]
|
result = [cst for cst in self._items if cst.cst_type == CstType.BASE]
|
||||||
result = result + [cst for cst in self._items if cst.cst_type == CstType.CONSTANT]
|
result = result + [cst for cst in self._items if cst.cst_type == CstType.CONSTANT]
|
||||||
kernel = [
|
kernel = [
|
||||||
cst.id for cst in self._items if
|
cst.pk for cst in self._items if
|
||||||
cst.cst_type in [CstType.STRUCTURED, CstType.AXIOM] or
|
cst.cst_type in [CstType.STRUCTURED, CstType.AXIOM] or
|
||||||
self._cst_by_ID[self._semantic.parent(cst.id)].cst_type == CstType.STRUCTURED
|
self._cst_by_ID[self._semantic.parent(cst.pk)].cst_type == CstType.STRUCTURED
|
||||||
]
|
]
|
||||||
kernel = kernel + self._graph.expand_inputs(kernel)
|
kernel = kernel + self._graph.expand_inputs(kernel)
|
||||||
result = result + [cst for cst in self._items if result.count(cst) == 0 and cst.id in kernel]
|
result = result + [cst for cst in self._items if result.count(cst) == 0 and cst.pk in kernel]
|
||||||
result = result + [cst for cst in self._items if result.count(cst) == 0]
|
result = result + [cst for cst in self._items if result.count(cst) == 0]
|
||||||
self._items = result
|
self._items = result
|
||||||
|
|
||||||
|
@ -606,11 +606,11 @@ class _OrderManager:
|
||||||
if cst in marked:
|
if cst in marked:
|
||||||
continue
|
continue
|
||||||
result.append(cst)
|
result.append(cst)
|
||||||
children = self._semantic[cst.id]['children']
|
children = self._semantic[cst.pk]['children']
|
||||||
if len(children) == 0:
|
if len(children) == 0:
|
||||||
continue
|
continue
|
||||||
for child in self._items:
|
for child in self._items:
|
||||||
if child.id in children:
|
if child.pk in children:
|
||||||
marked.add(child)
|
marked.add(child)
|
||||||
result.append(child)
|
result.append(child)
|
||||||
self._items = result
|
self._items = result
|
||||||
|
|
|
@ -4,11 +4,17 @@ from typing import Optional, cast
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
from django.db.models import Q
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.serializers import PrimaryKeyRelatedField as PKField
|
from rest_framework.serializers import PrimaryKeyRelatedField as PKField
|
||||||
|
|
||||||
from apps.library.models import LibraryItem
|
from apps.library.models import LibraryItem
|
||||||
from apps.library.serializers import LibraryItemBaseSerializer, LibraryItemDetailsSerializer
|
from apps.library.serializers import (
|
||||||
|
LibraryItemBaseSerializer,
|
||||||
|
LibraryItemDetailsSerializer,
|
||||||
|
LibraryItemReferenceSerializer
|
||||||
|
)
|
||||||
|
from apps.oss.models import Inheritance
|
||||||
from shared import messages as msg
|
from shared import messages as msg
|
||||||
|
|
||||||
from ..models import Constituenta, CstType, RSForm
|
from ..models import Constituenta, CstType, RSForm
|
||||||
|
@ -48,7 +54,7 @@ class CstSerializer(serializers.ModelSerializer):
|
||||||
term_changed = data['term_resolved'] != instance.term_resolved
|
term_changed = data['term_resolved'] != instance.term_resolved
|
||||||
result: Constituenta = super().update(instance, data)
|
result: Constituenta = super().update(instance, data)
|
||||||
if term_changed:
|
if term_changed:
|
||||||
schema.on_term_change([result.id])
|
schema.on_term_change([result.pk])
|
||||||
result.refresh_from_db()
|
result.refresh_from_db()
|
||||||
schema.save()
|
schema.save()
|
||||||
return result
|
return result
|
||||||
|
@ -90,6 +96,12 @@ class RSFormSerializer(serializers.ModelSerializer):
|
||||||
items = serializers.ListField(
|
items = serializers.ListField(
|
||||||
child=CstSerializer()
|
child=CstSerializer()
|
||||||
)
|
)
|
||||||
|
inheritance = serializers.ListField(
|
||||||
|
child=serializers.ListField(child=serializers.IntegerField())
|
||||||
|
)
|
||||||
|
oss = serializers.ListField(
|
||||||
|
child=LibraryItemReferenceSerializer()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
''' serializer metadata. '''
|
''' serializer metadata. '''
|
||||||
|
@ -101,6 +113,15 @@ class RSFormSerializer(serializers.ModelSerializer):
|
||||||
result['items'] = []
|
result['items'] = []
|
||||||
for cst in RSForm(instance).constituents().order_by('order'):
|
for cst in RSForm(instance).constituents().order_by('order'):
|
||||||
result['items'].append(CstSerializer(cst).data)
|
result['items'].append(CstSerializer(cst).data)
|
||||||
|
result['inheritance'] = []
|
||||||
|
for link in Inheritance.objects.filter(Q(child__schema=instance) | Q(parent__schema=instance)):
|
||||||
|
result['inheritance'].append([link.child.pk, link.parent.pk])
|
||||||
|
result['oss'] = []
|
||||||
|
for oss in LibraryItem.objects.filter(items__result=instance).only('alias'):
|
||||||
|
result['oss'].append({
|
||||||
|
'id': oss.pk,
|
||||||
|
'alias': oss.alias
|
||||||
|
})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def to_versioned_data(self) -> dict:
|
def to_versioned_data(self) -> dict:
|
||||||
|
@ -109,6 +130,8 @@ class RSFormSerializer(serializers.ModelSerializer):
|
||||||
del result['versions']
|
del result['versions']
|
||||||
del result['subscribers']
|
del result['subscribers']
|
||||||
del result['editors']
|
del result['editors']
|
||||||
|
del result['inheritance']
|
||||||
|
del result['oss']
|
||||||
|
|
||||||
del result['owner']
|
del result['owner']
|
||||||
del result['visible']
|
del result['visible']
|
||||||
|
@ -208,23 +231,19 @@ class CstTargetSerializer(serializers.Serializer):
|
||||||
target = PKField(many=False, queryset=Constituenta.objects.all())
|
target = PKField(many=False, queryset=Constituenta.objects.all())
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
schema = cast(LibraryItem, self.context['schema'])
|
if 'schema' in self.context:
|
||||||
cst = cast(Constituenta, attrs['target'])
|
schema = cast(LibraryItem, self.context['schema'])
|
||||||
if schema and cst.schema != schema:
|
cst = cast(Constituenta, attrs['target'])
|
||||||
raise serializers.ValidationError({
|
if schema and cst.schema_id != schema.pk:
|
||||||
f'{cst.id}': msg.constituentaNotInRSform(schema.title)
|
raise serializers.ValidationError({
|
||||||
})
|
f'{cst.pk}': msg.constituentaNotInRSform(schema.title)
|
||||||
if cst.cst_type not in [CstType.FUNCTION, CstType.STRUCTURED, CstType.TERM]:
|
})
|
||||||
raise serializers.ValidationError({
|
|
||||||
f'{cst.id}': msg.constituentaNoStructure()
|
|
||||||
})
|
|
||||||
self.instance = cst
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class CstRenameSerializer(serializers.Serializer):
|
class CstRenameSerializer(serializers.Serializer):
|
||||||
''' Serializer: Constituenta renaming. '''
|
''' Serializer: Constituenta renaming. '''
|
||||||
target = PKField(many=False, queryset=Constituenta.objects.all())
|
target = PKField(many=False, queryset=Constituenta.objects.only('alias', 'schema'))
|
||||||
alias = serializers.CharField()
|
alias = serializers.CharField()
|
||||||
cst_type = serializers.CharField()
|
cst_type = serializers.CharField()
|
||||||
|
|
||||||
|
@ -232,9 +251,9 @@ class CstRenameSerializer(serializers.Serializer):
|
||||||
attrs = super().validate(attrs)
|
attrs = super().validate(attrs)
|
||||||
schema = cast(LibraryItem, self.context['schema'])
|
schema = cast(LibraryItem, self.context['schema'])
|
||||||
cst = cast(Constituenta, attrs['target'])
|
cst = cast(Constituenta, attrs['target'])
|
||||||
if cst.schema != schema:
|
if cst.schema_id != schema.pk:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{cst.id}': msg.constituentaNotInRSform(schema.title)
|
f'{cst.pk}': msg.constituentaNotInRSform(schema.title)
|
||||||
})
|
})
|
||||||
new_alias = self.initial_data['alias']
|
new_alias = self.initial_data['alias']
|
||||||
if cst.alias == new_alias:
|
if cst.alias == new_alias:
|
||||||
|
@ -258,9 +277,9 @@ class CstListSerializer(serializers.Serializer):
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
for item in attrs['items']:
|
for item in attrs['items']:
|
||||||
if item.schema != schema:
|
if item.schema_id != schema.pk:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{item.id}': msg.constituentaNotInRSform(schema.title)
|
f'{item.pk}': msg.constituentaNotInRSform(schema.title)
|
||||||
})
|
})
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
@ -272,8 +291,8 @@ class CstMoveSerializer(CstListSerializer):
|
||||||
|
|
||||||
class SubstitutionSerializerBase(serializers.Serializer):
|
class SubstitutionSerializerBase(serializers.Serializer):
|
||||||
''' Serializer: Basic substitution. '''
|
''' Serializer: Basic substitution. '''
|
||||||
original = PKField(many=False, queryset=Constituenta.objects.all())
|
original = PKField(many=False, queryset=Constituenta.objects.only('alias', 'schema'))
|
||||||
substitution = PKField(many=False, queryset=Constituenta.objects.all())
|
substitution = PKField(many=False, queryset=Constituenta.objects.only('alias', 'schema'))
|
||||||
|
|
||||||
|
|
||||||
class CstSubstituteSerializer(serializers.Serializer):
|
class CstSubstituteSerializer(serializers.Serializer):
|
||||||
|
@ -291,17 +310,17 @@ class CstSubstituteSerializer(serializers.Serializer):
|
||||||
substitution_cst = cast(Constituenta, item['substitution'])
|
substitution_cst = cast(Constituenta, item['substitution'])
|
||||||
if original_cst.pk in deleted:
|
if original_cst.pk in deleted:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{original_cst.id}': msg.substituteDouble(original_cst.alias)
|
f'{original_cst.pk}': msg.substituteDouble(original_cst.alias)
|
||||||
})
|
})
|
||||||
if original_cst.alias == substitution_cst.alias:
|
if original_cst.alias == substitution_cst.alias:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
'alias': msg.substituteTrivial(original_cst.alias)
|
'alias': msg.substituteTrivial(original_cst.alias)
|
||||||
})
|
})
|
||||||
if original_cst.schema != schema:
|
if original_cst.schema_id != schema.pk:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
'original': msg.constituentaNotInRSform(schema.title)
|
'original': msg.constituentaNotInRSform(schema.title)
|
||||||
})
|
})
|
||||||
if substitution_cst.schema != schema:
|
if substitution_cst.schema_id != schema.pk:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
'substitution': msg.constituentaNotInRSform(schema.title)
|
'substitution': msg.constituentaNotInRSform(schema.title)
|
||||||
})
|
})
|
||||||
|
@ -325,39 +344,39 @@ class InlineSynthesisSerializer(serializers.Serializer):
|
||||||
if user.is_anonymous or (schema_out.owner != user and not user.is_staff):
|
if user.is_anonymous or (schema_out.owner != user and not user.is_staff):
|
||||||
raise PermissionDenied({
|
raise PermissionDenied({
|
||||||
'message': msg.schemaForbidden(),
|
'message': msg.schemaForbidden(),
|
||||||
'object_id': schema_in.id
|
'object_id': schema_in.pk
|
||||||
})
|
})
|
||||||
constituents = cast(list[Constituenta], attrs['items'])
|
constituents = cast(list[Constituenta], attrs['items'])
|
||||||
for cst in constituents:
|
for cst in constituents:
|
||||||
if cst.schema != schema_in:
|
if cst.schema_id != schema_in.pk:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{cst.id}': msg.constituentaNotInRSform(schema_in.title)
|
f'{cst.pk}': msg.constituentaNotInRSform(schema_in.title)
|
||||||
})
|
})
|
||||||
deleted = set()
|
deleted = set()
|
||||||
for item in attrs['substitutions']:
|
for item in attrs['substitutions']:
|
||||||
original_cst = cast(Constituenta, item['original'])
|
original_cst = cast(Constituenta, item['original'])
|
||||||
substitution_cst = cast(Constituenta, item['substitution'])
|
substitution_cst = cast(Constituenta, item['substitution'])
|
||||||
if original_cst.schema == schema_in:
|
if original_cst.schema_id == schema_in.pk:
|
||||||
if original_cst not in constituents:
|
if original_cst not in constituents:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{original_cst.id}': msg.substitutionNotInList()
|
f'{original_cst.pk}': msg.substitutionNotInList()
|
||||||
})
|
})
|
||||||
if substitution_cst.schema != schema_out:
|
if substitution_cst.schema_id != schema_out.pk:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{substitution_cst.id}': msg.constituentaNotInRSform(schema_out.title)
|
f'{substitution_cst.pk}': msg.constituentaNotInRSform(schema_out.title)
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
if substitution_cst not in constituents:
|
if substitution_cst not in constituents:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{substitution_cst.id}': msg.substitutionNotInList()
|
f'{substitution_cst.pk}': msg.substitutionNotInList()
|
||||||
})
|
})
|
||||||
if original_cst.schema != schema_out:
|
if original_cst.schema_id != schema_out.pk:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{original_cst.id}': msg.constituentaNotInRSform(schema_out.title)
|
f'{original_cst.pk}': msg.constituentaNotInRSform(schema_out.title)
|
||||||
})
|
})
|
||||||
if original_cst.pk in deleted:
|
if original_cst.pk in deleted:
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{original_cst.id}': msg.substituteDouble(original_cst.alias)
|
f'{original_cst.pk}': msg.substituteDouble(original_cst.alias)
|
||||||
})
|
})
|
||||||
deleted.add(original_cst.pk)
|
deleted.add(original_cst.pk)
|
||||||
return attrs
|
return attrs
|
||||||
|
|
|
@ -102,6 +102,8 @@ class TestRSFormViewset(EndpointTester):
|
||||||
self.assertEqual(response.data['items'][1]['term_resolved'], x2.term_resolved)
|
self.assertEqual(response.data['items'][1]['term_resolved'], x2.term_resolved)
|
||||||
self.assertEqual(response.data['subscribers'], [self.user.pk])
|
self.assertEqual(response.data['subscribers'], [self.user.pk])
|
||||||
self.assertEqual(response.data['editors'], [])
|
self.assertEqual(response.data['editors'], [])
|
||||||
|
self.assertEqual(response.data['inheritance'], [])
|
||||||
|
self.assertEqual(response.data['oss'], [])
|
||||||
|
|
||||||
self.executeOK(item=self.unowned_id)
|
self.executeOK(item=self.unowned_id)
|
||||||
self.executeForbidden(item=self.private_id)
|
self.executeForbidden(item=self.private_id)
|
||||||
|
|
|
@ -147,13 +147,17 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
||||||
serializer = s.CstTargetSerializer(data=request.data, context={'schema': schema})
|
serializer = s.CstTargetSerializer(data=request.data, context={'schema': schema})
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
cst = cast(m.Constituenta, serializer.validated_data['target'])
|
cst = cast(m.Constituenta, serializer.validated_data['target'])
|
||||||
|
if cst.cst_type not in [m.CstType.FUNCTION, m.CstType.STRUCTURED, m.CstType.TERM]:
|
||||||
|
raise ValidationError({
|
||||||
|
f'{cst.pk}': msg.constituentaNoStructure()
|
||||||
|
})
|
||||||
|
|
||||||
schema_details = s.RSFormParseSerializer(schema).data['items']
|
schema_details = s.RSFormParseSerializer(schema).data['items']
|
||||||
cst_parse = next(item for item in schema_details if item['id'] == cst.id)['parse']
|
cst_parse = next(item for item in schema_details if item['id'] == cst.pk)['parse']
|
||||||
if not cst_parse['typification']:
|
if not cst_parse['typification']:
|
||||||
return Response(
|
return Response(
|
||||||
status=c.HTTP_400_BAD_REQUEST,
|
status=c.HTTP_400_BAD_REQUEST,
|
||||||
data={f'{cst.id}': msg.constituentaNoStructure()}
|
data={f'{cst.pk}': msg.constituentaNoStructure()}
|
||||||
)
|
)
|
||||||
|
|
||||||
result = m.RSForm(schema).produce_structure(cst, cst_parse)
|
result = m.RSForm(schema).produce_structure(cst, cst_parse)
|
||||||
|
|
|
@ -28,7 +28,7 @@ def _extract_item(obj: Any) -> LibraryItem:
|
||||||
return cast(LibraryItem, obj.item)
|
return cast(LibraryItem, obj.item)
|
||||||
raise PermissionDenied({
|
raise PermissionDenied({
|
||||||
'message': 'Invalid type error. Please contact developers',
|
'message': 'Invalid type error. Please contact developers',
|
||||||
'object_id': obj.id
|
'object_id': obj.pk
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
466
rsconcept/frontend/package-lock.json
generated
466
rsconcept/frontend/package-lock.json
generated
|
@ -8,13 +8,13 @@
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/lr": "^1.4.1",
|
"@lezer/lr": "^1.4.2",
|
||||||
"@tanstack/react-table": "^8.19.3",
|
"@tanstack/react-table": "^8.19.3",
|
||||||
"@uiw/codemirror-themes": "^4.23.0",
|
"@uiw/codemirror-themes": "^4.23.0",
|
||||||
"@uiw/react-codemirror": "^4.23.0",
|
"@uiw/react-codemirror": "^4.23.0",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"framer-motion": "^11.3.17",
|
"framer-motion": "^11.3.19",
|
||||||
"html-to-image": "^1.11.11",
|
"html-to-image": "^1.11.11",
|
||||||
"js-file-download": "^0.4.12",
|
"js-file-download": "^0.4.12",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
@ -32,16 +32,16 @@
|
||||||
"react-zoom-pan-pinch": "^3.6.1",
|
"react-zoom-pan-pinch": "^3.6.1",
|
||||||
"reactflow": "^11.11.4",
|
"reactflow": "^11.11.4",
|
||||||
"reagraph": "^4.19.2",
|
"reagraph": "^4.19.2",
|
||||||
"use-debounce": "^10.0.1"
|
"use-debounce": "^10.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lezer/generator": "^1.7.1",
|
"@lezer/generator": "^1.7.1",
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/node": "^20.14.12",
|
"@types/node": "^20.14.13",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.17.0",
|
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||||
"@typescript-eslint/parser": "^7.17.0",
|
"@typescript-eslint/parser": "^7.18.0",
|
||||||
"@vitejs/plugin-react": "^4.3.1",
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"postcss": "^8.4.40",
|
"postcss": "^8.4.40",
|
||||||
"tailwindcss": "^3.4.7",
|
"tailwindcss": "^3.4.7",
|
||||||
"ts-jest": "^29.2.3",
|
"ts-jest": "^29.2.4",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"vite": "^5.3.5"
|
"vite": "^5.3.5"
|
||||||
}
|
}
|
||||||
|
@ -98,9 +98,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/compat-data": {
|
"node_modules/@babel/compat-data": {
|
||||||
"version": "7.24.9",
|
"version": "7.25.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz",
|
||||||
"integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==",
|
"integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -108,22 +108,22 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/core": {
|
"node_modules/@babel/core": {
|
||||||
"version": "7.24.9",
|
"version": "7.25.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz",
|
||||||
"integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==",
|
"integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.2.0",
|
"@ampproject/remapping": "^2.2.0",
|
||||||
"@babel/code-frame": "^7.24.7",
|
"@babel/code-frame": "^7.24.7",
|
||||||
"@babel/generator": "^7.24.9",
|
"@babel/generator": "^7.25.0",
|
||||||
"@babel/helper-compilation-targets": "^7.24.8",
|
"@babel/helper-compilation-targets": "^7.25.2",
|
||||||
"@babel/helper-module-transforms": "^7.24.9",
|
"@babel/helper-module-transforms": "^7.25.2",
|
||||||
"@babel/helpers": "^7.24.8",
|
"@babel/helpers": "^7.25.0",
|
||||||
"@babel/parser": "^7.24.8",
|
"@babel/parser": "^7.25.0",
|
||||||
"@babel/template": "^7.24.7",
|
"@babel/template": "^7.25.0",
|
||||||
"@babel/traverse": "^7.24.8",
|
"@babel/traverse": "^7.25.2",
|
||||||
"@babel/types": "^7.24.9",
|
"@babel/types": "^7.25.2",
|
||||||
"convert-source-map": "^2.0.0",
|
"convert-source-map": "^2.0.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"gensync": "^1.0.0-beta.2",
|
"gensync": "^1.0.0-beta.2",
|
||||||
|
@ -149,12 +149,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/generator": {
|
"node_modules/@babel/generator": {
|
||||||
"version": "7.24.10",
|
"version": "7.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz",
|
||||||
"integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==",
|
"integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.24.9",
|
"@babel/types": "^7.25.0",
|
||||||
"@jridgewell/gen-mapping": "^0.3.5",
|
"@jridgewell/gen-mapping": "^0.3.5",
|
||||||
"@jridgewell/trace-mapping": "^0.3.25",
|
"@jridgewell/trace-mapping": "^0.3.25",
|
||||||
"jsesc": "^2.5.1"
|
"jsesc": "^2.5.1"
|
||||||
|
@ -164,13 +164,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-compilation-targets": {
|
"node_modules/@babel/helper-compilation-targets": {
|
||||||
"version": "7.24.8",
|
"version": "7.25.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz",
|
||||||
"integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==",
|
"integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/compat-data": "^7.24.8",
|
"@babel/compat-data": "^7.25.2",
|
||||||
"@babel/helper-validator-option": "^7.24.8",
|
"@babel/helper-validator-option": "^7.24.8",
|
||||||
"browserslist": "^4.23.1",
|
"browserslist": "^4.23.1",
|
||||||
"lru-cache": "^5.1.1",
|
"lru-cache": "^5.1.1",
|
||||||
|
@ -190,43 +190,6 @@
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-environment-visitor": {
|
|
||||||
"version": "7.24.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz",
|
|
||||||
"integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/types": "^7.24.7"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/helper-function-name": {
|
|
||||||
"version": "7.24.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz",
|
|
||||||
"integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/template": "^7.24.7",
|
|
||||||
"@babel/types": "^7.24.7"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/helper-hoist-variables": {
|
|
||||||
"version": "7.24.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz",
|
|
||||||
"integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/types": "^7.24.7"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/helper-module-imports": {
|
"node_modules/@babel/helper-module-imports": {
|
||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz",
|
||||||
|
@ -241,17 +204,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-module-transforms": {
|
"node_modules/@babel/helper-module-transforms": {
|
||||||
"version": "7.24.9",
|
"version": "7.25.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz",
|
||||||
"integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==",
|
"integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-environment-visitor": "^7.24.7",
|
|
||||||
"@babel/helper-module-imports": "^7.24.7",
|
"@babel/helper-module-imports": "^7.24.7",
|
||||||
"@babel/helper-simple-access": "^7.24.7",
|
"@babel/helper-simple-access": "^7.24.7",
|
||||||
"@babel/helper-split-export-declaration": "^7.24.7",
|
"@babel/helper-validator-identifier": "^7.24.7",
|
||||||
"@babel/helper-validator-identifier": "^7.24.7"
|
"@babel/traverse": "^7.25.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
|
@ -284,18 +246,6 @@
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-split-export-declaration": {
|
|
||||||
"version": "7.24.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz",
|
|
||||||
"integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/types": "^7.24.7"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/helper-string-parser": {
|
"node_modules/@babel/helper-string-parser": {
|
||||||
"version": "7.24.8",
|
"version": "7.24.8",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz",
|
||||||
|
@ -325,14 +275,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helpers": {
|
"node_modules/@babel/helpers": {
|
||||||
"version": "7.24.8",
|
"version": "7.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz",
|
||||||
"integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==",
|
"integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/template": "^7.24.7",
|
"@babel/template": "^7.25.0",
|
||||||
"@babel/types": "^7.24.8"
|
"@babel/types": "^7.25.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
|
@ -354,10 +304,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.24.8",
|
"version": "7.25.3",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz",
|
||||||
"integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==",
|
"integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/types": "^7.25.2"
|
||||||
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
},
|
},
|
||||||
|
@ -589,9 +542,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.24.8",
|
"version": "7.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz",
|
||||||
"integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==",
|
"integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"regenerator-runtime": "^0.14.0"
|
"regenerator-runtime": "^0.14.0"
|
||||||
|
@ -601,33 +554,30 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/template": {
|
"node_modules/@babel/template": {
|
||||||
"version": "7.24.7",
|
"version": "7.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz",
|
||||||
"integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==",
|
"integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.24.7",
|
"@babel/code-frame": "^7.24.7",
|
||||||
"@babel/parser": "^7.24.7",
|
"@babel/parser": "^7.25.0",
|
||||||
"@babel/types": "^7.24.7"
|
"@babel/types": "^7.25.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse": {
|
"node_modules/@babel/traverse": {
|
||||||
"version": "7.24.8",
|
"version": "7.25.3",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz",
|
||||||
"integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==",
|
"integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.24.7",
|
"@babel/code-frame": "^7.24.7",
|
||||||
"@babel/generator": "^7.24.8",
|
"@babel/generator": "^7.25.0",
|
||||||
"@babel/helper-environment-visitor": "^7.24.7",
|
"@babel/parser": "^7.25.3",
|
||||||
"@babel/helper-function-name": "^7.24.7",
|
"@babel/template": "^7.25.0",
|
||||||
"@babel/helper-hoist-variables": "^7.24.7",
|
"@babel/types": "^7.25.2",
|
||||||
"@babel/helper-split-export-declaration": "^7.24.7",
|
|
||||||
"@babel/parser": "^7.24.8",
|
|
||||||
"@babel/types": "^7.24.8",
|
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"globals": "^11.1.0"
|
"globals": "^11.1.0"
|
||||||
},
|
},
|
||||||
|
@ -636,9 +586,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.24.9",
|
"version": "7.25.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz",
|
||||||
"integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==",
|
"integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.24.8",
|
"@babel/helper-string-parser": "^7.24.8",
|
||||||
|
@ -741,9 +691,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/view": {
|
"node_modules/@codemirror/view": {
|
||||||
"version": "6.29.0",
|
"version": "6.29.1",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.29.1.tgz",
|
||||||
"integrity": "sha512-ED4ims4fkf7eOA+HYLVP8VVg3NMllt1FPm9PEJBfYFnidKlRITBaua38u68L1F60eNtw2YNcDN5jsIzhKZwWQA==",
|
"integrity": "sha512-7r+DlO/QFwPqKp73uq5mmrS4TuLPUVotbNOKYzN3OLP5ScrOVXcm4g13/48b6ZXGhdmzMinzFYqH0vo+qihIkQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^6.4.0",
|
"@codemirror/state": "^6.4.0",
|
||||||
|
@ -2562,9 +2512,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@lezer/lr": {
|
"node_modules/@lezer/lr": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
|
||||||
"integrity": "sha512-CHsKq8DMKBf9b3yXPDIU4DbH+ZJd/sJdYOW2llbW/HudP5u0VS6Bfq1hLYfgU7uAYGFIyGGQIsSOXGPEErZiJw==",
|
"integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/common": "^1.0.0"
|
"@lezer/common": "^1.0.0"
|
||||||
|
@ -2970,9 +2920,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.2.tgz",
|
||||||
"integrity": "sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w==",
|
"integrity": "sha512-OHflWINKtoCFSpm/WmuQaWW4jeX+3Qt3XQDepkkiFTsoxFc5BpF3Z5aDxFZgBqRjO6ATP5+b1iilp4kGIZVWlA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
@ -2984,9 +2934,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.2.tgz",
|
||||||
"integrity": "sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw==",
|
"integrity": "sha512-k0OC/b14rNzMLDOE6QMBCjDRm3fQOHAL8Ldc9bxEWvMo4Ty9RY6rWmGetNTWhPo+/+FNd1lsQYRd0/1OSix36A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -2998,9 +2948,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.2.tgz",
|
||||||
"integrity": "sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA==",
|
"integrity": "sha512-IIARRgWCNWMTeQH+kr/gFTHJccKzwEaI0YSvtqkEBPj7AshElFq89TyreKNFAGh5frLfDCbodnq+Ye3dqGKPBw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -3012,9 +2962,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.2.tgz",
|
||||||
"integrity": "sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg==",
|
"integrity": "sha512-52udDMFDv54BTAdnw+KXNF45QCvcJOcYGl3vQkp4vARyrcdI/cXH8VXTEv/8QWfd6Fru8QQuw1b2uNersXOL0g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -3026,9 +2976,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.2.tgz",
|
||||||
"integrity": "sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==",
|
"integrity": "sha512-r+SI2t8srMPYZeoa1w0o/AfoVt9akI1ihgazGYPQGRilVAkuzMGiTtexNZkrPkQsyFrvqq/ni8f3zOnHw4hUbA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
@ -3040,9 +2990,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.2.tgz",
|
||||||
"integrity": "sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==",
|
"integrity": "sha512-+tYiL4QVjtI3KliKBGtUU7yhw0GMcJJuB9mLTCEauHEsqfk49gtUBXGtGP3h1LW8MbaTY6rSFIQV1XOBps1gBA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
@ -3054,9 +3004,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.2.tgz",
|
||||||
"integrity": "sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==",
|
"integrity": "sha512-OR5DcvZiYN75mXDNQQxlQPTv4D+uNCUsmSCSY2FolLf9W5I4DSoJyg7z9Ea3TjKfhPSGgMJiey1aWvlWuBzMtg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -3068,9 +3018,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.2.tgz",
|
||||||
"integrity": "sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==",
|
"integrity": "sha512-Hw3jSfWdUSauEYFBSFIte6I8m6jOj+3vifLg8EU3lreWulAUpch4JBjDMtlKosrBzkr0kwKgL9iCfjA8L3geoA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -3082,9 +3032,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.2.tgz",
|
||||||
"integrity": "sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==",
|
"integrity": "sha512-rhjvoPBhBwVnJRq/+hi2Q3EMiVF538/o9dBuj9TVLclo9DuONqt5xfWSaE6MYiFKpo/lFPJ/iSI72rYWw5Hc7w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
|
@ -3096,9 +3046,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.2.tgz",
|
||||||
"integrity": "sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==",
|
"integrity": "sha512-EAz6vjPwHHs2qOCnpQkw4xs14XJq84I81sDRGPEjKPFVPBw7fwvtwhVjcZR6SLydCv8zNK8YGFblKWd/vRmP8g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
|
@ -3110,9 +3060,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.2.tgz",
|
||||||
"integrity": "sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==",
|
"integrity": "sha512-IJSUX1xb8k/zN9j2I7B5Re6B0NNJDJ1+soezjNojhT8DEVeDNptq2jgycCOpRhyGj0+xBn7Cq+PK7Q+nd2hxLA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
|
@ -3124,9 +3074,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.2.tgz",
|
||||||
"integrity": "sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==",
|
"integrity": "sha512-OgaToJ8jSxTpgGkZSkwKE+JQGihdcaqnyHEFOSAU45utQ+yLruE1dkonB2SDI8t375wOKgNn8pQvaWY9kPzxDQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -3138,9 +3088,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.2.tgz",
|
||||||
"integrity": "sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==",
|
"integrity": "sha512-5V3mPpWkB066XZZBgSd1lwozBk7tmOkKtquyCJ6T4LN3mzKENXyBwWNQn8d0Ci81hvlBw5RoFgleVpL6aScLYg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -3152,9 +3102,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.2.tgz",
|
||||||
"integrity": "sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==",
|
"integrity": "sha512-ayVstadfLeeXI9zUPiKRVT8qF55hm7hKa+0N1V6Vj+OTNFfKSoUxyZvzVvgtBxqSb5URQ8sK6fhwxr9/MLmxdA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -3166,9 +3116,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.2.tgz",
|
||||||
"integrity": "sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q==",
|
"integrity": "sha512-Mda7iG4fOLHNsPqjWSjANvNZYoW034yxgrndof0DwCy0D3FvTjeNo+HGE6oGWgvcLZNLlcp0hLEFcRs+UGsMLg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
@ -3180,9 +3130,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.2.tgz",
|
||||||
"integrity": "sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag==",
|
"integrity": "sha512-DPi0ubYhSow/00YqmG1jWm3qt1F8aXziHc/UNy8bo9cpCacqhuWu+iSq/fp2SyEQK7iYTZ60fBU9cat3MXTjIQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -3635,9 +3585,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.14.12",
|
"version": "20.14.13",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.13.tgz",
|
||||||
"integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==",
|
"integrity": "sha512-+bHoGiZb8UiQ0+WEtmph2IWQCjIqg8MDZMAV+ppRRhUZnquF5mQkP/9vpSwJClEiSM/C7fZZExPzfU0vJTyp8w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -3720,9 +3670,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/three": {
|
"node_modules/@types/three": {
|
||||||
"version": "0.167.0",
|
"version": "0.167.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.167.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.167.1.tgz",
|
||||||
"integrity": "sha512-BC+Vbm0d6yMzct7dhTBe9ZjEh6ygupyn1k/UcZncIIS/5aNIbfvF77gQw1IFP09Oyj1UxWj0EUBBqc1GkqzsOw==",
|
"integrity": "sha512-OCd2Uv/8/4TbmSaIRFawrCOnDMLdpaa+QGJdhlUBmdfbHjLY8k6uFc0tde2/UvcaHQ6NtLl28onj/vJfofV+Tg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -3757,17 +3707,17 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "7.17.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz",
|
||||||
"integrity": "sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==",
|
"integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "7.17.0",
|
"@typescript-eslint/scope-manager": "7.18.0",
|
||||||
"@typescript-eslint/type-utils": "7.17.0",
|
"@typescript-eslint/type-utils": "7.18.0",
|
||||||
"@typescript-eslint/utils": "7.17.0",
|
"@typescript-eslint/utils": "7.18.0",
|
||||||
"@typescript-eslint/visitor-keys": "7.17.0",
|
"@typescript-eslint/visitor-keys": "7.18.0",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^5.3.1",
|
"ignore": "^5.3.1",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
|
@ -3791,16 +3741,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "7.17.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz",
|
||||||
"integrity": "sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==",
|
"integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "7.17.0",
|
"@typescript-eslint/scope-manager": "7.18.0",
|
||||||
"@typescript-eslint/types": "7.17.0",
|
"@typescript-eslint/types": "7.18.0",
|
||||||
"@typescript-eslint/typescript-estree": "7.17.0",
|
"@typescript-eslint/typescript-estree": "7.18.0",
|
||||||
"@typescript-eslint/visitor-keys": "7.17.0",
|
"@typescript-eslint/visitor-keys": "7.18.0",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3820,14 +3770,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "7.17.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz",
|
||||||
"integrity": "sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==",
|
"integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "7.17.0",
|
"@typescript-eslint/types": "7.18.0",
|
||||||
"@typescript-eslint/visitor-keys": "7.17.0"
|
"@typescript-eslint/visitor-keys": "7.18.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || >=20.0.0"
|
"node": "^18.18.0 || >=20.0.0"
|
||||||
|
@ -3838,14 +3788,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "7.17.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz",
|
||||||
"integrity": "sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==",
|
"integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "7.17.0",
|
"@typescript-eslint/typescript-estree": "7.18.0",
|
||||||
"@typescript-eslint/utils": "7.17.0",
|
"@typescript-eslint/utils": "7.18.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^1.3.0"
|
"ts-api-utils": "^1.3.0"
|
||||||
},
|
},
|
||||||
|
@ -3866,9 +3816,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "7.17.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz",
|
||||||
"integrity": "sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==",
|
"integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3880,14 +3830,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "7.17.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz",
|
||||||
"integrity": "sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==",
|
"integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "7.17.0",
|
"@typescript-eslint/types": "7.18.0",
|
||||||
"@typescript-eslint/visitor-keys": "7.17.0",
|
"@typescript-eslint/visitor-keys": "7.18.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"globby": "^11.1.0",
|
"globby": "^11.1.0",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
|
@ -3909,16 +3859,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "7.17.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz",
|
||||||
"integrity": "sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==",
|
"integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
"@typescript-eslint/scope-manager": "7.17.0",
|
"@typescript-eslint/scope-manager": "7.18.0",
|
||||||
"@typescript-eslint/types": "7.17.0",
|
"@typescript-eslint/types": "7.18.0",
|
||||||
"@typescript-eslint/typescript-estree": "7.17.0"
|
"@typescript-eslint/typescript-estree": "7.18.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || >=20.0.0"
|
"node": "^18.18.0 || >=20.0.0"
|
||||||
|
@ -3932,13 +3882,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "7.17.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz",
|
||||||
"integrity": "sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==",
|
"integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "7.17.0",
|
"@typescript-eslint/types": "7.18.0",
|
||||||
"eslint-visitor-keys": "^3.4.3"
|
"eslint-visitor-keys": "^3.4.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -4676,9 +4626,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001643",
|
"version": "1.0.30001646",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001646.tgz",
|
||||||
"integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==",
|
"integrity": "sha512-dRg00gudiBDDTmUhClSdv3hqRfpbOnU28IpI1T6PBTLWa+kOj0681C8uML3PifYfREuBrVjDGhL3adYpBT6spw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -5363,9 +5313,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.5",
|
"version": "4.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
|
||||||
"integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
|
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
|
@ -5450,9 +5400,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/detect-gpu": {
|
"node_modules/detect-gpu": {
|
||||||
"version": "5.0.40",
|
"version": "5.0.41",
|
||||||
"resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.40.tgz",
|
"resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.41.tgz",
|
||||||
"integrity": "sha512-5v4jDN/ERdZZitD29UiLjV9Q9+lDfw2OhEJACIqnvdWulVZCy2K6EwonZ/VKyo4YMqvSIzGIDmojX3jGL3dLpA==",
|
"integrity": "sha512-0avjQwm8zyDPLmmp2PlaUxOWp/CNLbOU4t61x1IOTmBvC7UO+NMWDlEJcIjtbRBSnulC2ote81Xyillssam0CA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"webgl-constants": "^1.1.1"
|
"webgl-constants": "^1.1.1"
|
||||||
|
@ -5568,9 +5518,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz",
|
||||||
"integrity": "sha512-FKbOCOQ5QRB3VlIbl1LZQefWIYwszlBloaXcY2rbfpu9ioJnNh3TK03YtIDKDo3WKBi8u+YV4+Fn2CkEozgf4w==",
|
"integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
@ -6326,9 +6276,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/framer-motion": {
|
"node_modules/framer-motion": {
|
||||||
"version": "11.3.17",
|
"version": "11.3.19",
|
||||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.3.17.tgz",
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.3.19.tgz",
|
||||||
"integrity": "sha512-LZcckvZL8Rjod03bud8LQcp+R0PLmWIlOSu+NVc+v6Uh43fQr4IBsEAX7sSn7CdBQ1L0fZ/IqSXZVPnGFSMxHw==",
|
"integrity": "sha512-+luuQdx4AsamyMcvzW7jUAJYIKvQs1KE7oHvKkW3eNzmo0S+3PSDWjBuQkuIP9WyneGnKGMLUSuHs8OP7jKpQg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
|
@ -10797,9 +10747,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.19.0",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.19.2.tgz",
|
||||||
"integrity": "sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA==",
|
"integrity": "sha512-6/jgnN1svF9PjNYJ4ya3l+cqutg49vOZ4rVgsDKxdl+5gpGPnByFXWGyfH9YGx9i3nfBwSu1Iyu6vGwFFA0BdQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -10813,22 +10763,22 @@
|
||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.19.0",
|
"@rollup/rollup-android-arm-eabi": "4.19.2",
|
||||||
"@rollup/rollup-android-arm64": "4.19.0",
|
"@rollup/rollup-android-arm64": "4.19.2",
|
||||||
"@rollup/rollup-darwin-arm64": "4.19.0",
|
"@rollup/rollup-darwin-arm64": "4.19.2",
|
||||||
"@rollup/rollup-darwin-x64": "4.19.0",
|
"@rollup/rollup-darwin-x64": "4.19.2",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.19.0",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.19.2",
|
||||||
"@rollup/rollup-linux-arm-musleabihf": "4.19.0",
|
"@rollup/rollup-linux-arm-musleabihf": "4.19.2",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.19.0",
|
"@rollup/rollup-linux-arm64-gnu": "4.19.2",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.19.0",
|
"@rollup/rollup-linux-arm64-musl": "4.19.2",
|
||||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.19.0",
|
"@rollup/rollup-linux-powerpc64le-gnu": "4.19.2",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.19.0",
|
"@rollup/rollup-linux-riscv64-gnu": "4.19.2",
|
||||||
"@rollup/rollup-linux-s390x-gnu": "4.19.0",
|
"@rollup/rollup-linux-s390x-gnu": "4.19.2",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.19.0",
|
"@rollup/rollup-linux-x64-gnu": "4.19.2",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.19.0",
|
"@rollup/rollup-linux-x64-musl": "4.19.2",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.19.0",
|
"@rollup/rollup-win32-arm64-msvc": "4.19.2",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.19.0",
|
"@rollup/rollup-win32-ia32-msvc": "4.19.2",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.19.0",
|
"@rollup/rollup-win32-x64-msvc": "4.19.2",
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -11514,9 +11464,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/three-stdlib": {
|
"node_modules/three-stdlib": {
|
||||||
"version": "2.30.4",
|
"version": "2.30.5",
|
||||||
"resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.30.4.tgz",
|
"resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.30.5.tgz",
|
||||||
"integrity": "sha512-E7sN8UkaorSq2uRZU14AE7wXkdCBa2oFwPkPt92zaecuzrgd98BXkTt+2tFQVF1tPJRvfs7aMZV5dSOq4/vNVg==",
|
"integrity": "sha512-BBZkKnTDmUacXU9mv7fA5R7Brb89uUbOUWXXZKNrzdx6JEozJt3e6I5zPMRbb1FC2aw/2QFtgwPi1PI8VjX6FQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/draco3d": "^1.4.0",
|
"@types/draco3d": "^1.4.0",
|
||||||
|
@ -11629,9 +11579,9 @@
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/ts-jest": {
|
"node_modules/ts-jest": {
|
||||||
"version": "29.2.3",
|
"version": "29.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz",
|
||||||
"integrity": "sha512-yCcfVdiBFngVz9/keHin9EnsrQtQtEu3nRykNy9RVp+FiPFFbPJ3Sg6Qg4+TkmH0vMP5qsTKgXSsk80HRwvdgQ==",
|
"integrity": "sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -11791,9 +11741,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/use-debounce": {
|
"node_modules/use-debounce": {
|
||||||
"version": "10.0.1",
|
"version": "10.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.2.tgz",
|
||||||
"integrity": "sha512-0uUXjOfm44e6z4LZ/woZvkM8FwV1wiuoB6xnrrOmeAEjRDDzTLQNRFtYHvqUsJdrz1X37j0rVGIVp144GLHGKg==",
|
"integrity": "sha512-MwBiJK2dk+2qhMDVDCPRPeLuIekKfH2t1UYMnrW9pwcJJGFDbTLliSMBz2UKGmE1PJs8l3XoMqbIU1MemMAJ8g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 16.0.0"
|
"node": ">= 16.0.0"
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lezer/lr": "^1.4.1",
|
"@lezer/lr": "^1.4.2",
|
||||||
"@tanstack/react-table": "^8.19.3",
|
"@tanstack/react-table": "^8.19.3",
|
||||||
"@uiw/codemirror-themes": "^4.23.0",
|
"@uiw/codemirror-themes": "^4.23.0",
|
||||||
"@uiw/react-codemirror": "^4.23.0",
|
"@uiw/react-codemirror": "^4.23.0",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"framer-motion": "^11.3.17",
|
"framer-motion": "^11.3.19",
|
||||||
"html-to-image": "^1.11.11",
|
"html-to-image": "^1.11.11",
|
||||||
"js-file-download": "^0.4.12",
|
"js-file-download": "^0.4.12",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
@ -36,16 +36,16 @@
|
||||||
"react-zoom-pan-pinch": "^3.6.1",
|
"react-zoom-pan-pinch": "^3.6.1",
|
||||||
"reactflow": "^11.11.4",
|
"reactflow": "^11.11.4",
|
||||||
"reagraph": "^4.19.2",
|
"reagraph": "^4.19.2",
|
||||||
"use-debounce": "^10.0.1"
|
"use-debounce": "^10.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lezer/generator": "^1.7.1",
|
"@lezer/generator": "^1.7.1",
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/node": "^20.14.12",
|
"@types/node": "^20.14.13",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.17.0",
|
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||||
"@typescript-eslint/parser": "^7.17.0",
|
"@typescript-eslint/parser": "^7.18.0",
|
||||||
"@vitejs/plugin-react": "^4.3.1",
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"postcss": "^8.4.40",
|
"postcss": "^8.4.40",
|
||||||
"tailwindcss": "^3.4.7",
|
"tailwindcss": "^3.4.7",
|
||||||
"ts-jest": "^29.2.3",
|
"ts-jest": "^29.2.4",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"vite": "^5.3.5"
|
"vite": "^5.3.5"
|
||||||
},
|
},
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 121 KiB |
|
@ -12,6 +12,7 @@ import {
|
||||||
IPositionsData,
|
IPositionsData,
|
||||||
ITargetOperation
|
ITargetOperation
|
||||||
} from '@/models/oss';
|
} from '@/models/oss';
|
||||||
|
import { IConstituentaReference, ITargetCst } from '@/models/rsform';
|
||||||
|
|
||||||
import { AxiosGet, AxiosPatch, AxiosPost, FrontExchange, FrontPull, FrontPush } from './apiTransport';
|
import { AxiosGet, AxiosPatch, AxiosPost, FrontExchange, FrontPull, FrontPush } from './apiTransport';
|
||||||
|
|
||||||
|
@ -73,3 +74,10 @@ export function postExecuteOperation(oss: string, request: FrontExchange<ITarget
|
||||||
request: request
|
request: request
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function postFindPredecessor(request: FrontExchange<ITargetCst, IConstituentaReference>) {
|
||||||
|
AxiosPost({
|
||||||
|
endpoint: `/api/oss/get-predecessor`,
|
||||||
|
request: request
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -62,6 +62,9 @@ export { VscLibrary as IconLibrary } from 'react-icons/vsc';
|
||||||
export { IoLibrary as IconLibrary2 } from 'react-icons/io5';
|
export { IoLibrary as IconLibrary2 } from 'react-icons/io5';
|
||||||
export { BiDiamond as IconTemplates } from 'react-icons/bi';
|
export { BiDiamond as IconTemplates } from 'react-icons/bi';
|
||||||
export { GiHoneycomb as IconOSS } from 'react-icons/gi';
|
export { GiHoneycomb as IconOSS } from 'react-icons/gi';
|
||||||
|
export { LuBaby as IconChild } from 'react-icons/lu';
|
||||||
|
export { RiParentLine as IconParent } from 'react-icons/ri';
|
||||||
|
export { BiSpa as IconPredecessor } from 'react-icons/bi';
|
||||||
export { RiHexagonLine as IconRSForm } from 'react-icons/ri';
|
export { RiHexagonLine as IconRSForm } from 'react-icons/ri';
|
||||||
export { LuArchive as IconArchive } from 'react-icons/lu';
|
export { LuArchive as IconArchive } from 'react-icons/lu';
|
||||||
export { LuDatabase as IconDatabase } from 'react-icons/lu';
|
export { LuDatabase as IconDatabase } from 'react-icons/lu';
|
||||||
|
|
|
@ -20,6 +20,7 @@ function BadgeConstituenta({ value, prefixID, theme }: BadgeConstituentaProps) {
|
||||||
'min-w-[3.1rem] max-w-[3.1rem]', // prettier: split lines
|
'min-w-[3.1rem] max-w-[3.1rem]', // prettier: split lines
|
||||||
'px-1',
|
'px-1',
|
||||||
'border rounded-md',
|
'border rounded-md',
|
||||||
|
value.is_inherited && 'border-dashed',
|
||||||
'text-center font-medium whitespace-nowrap'
|
'text-center font-medium whitespace-nowrap'
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
|
|
|
@ -13,7 +13,10 @@ interface InfoConstituentaProps extends CProps.Div {
|
||||||
function InfoConstituenta({ data, className, ...restProps }: InfoConstituentaProps) {
|
function InfoConstituenta({ data, className, ...restProps }: InfoConstituentaProps) {
|
||||||
return (
|
return (
|
||||||
<div className={clsx('dense min-w-[15rem]', className)} {...restProps}>
|
<div className={clsx('dense min-w-[15rem]', className)} {...restProps}>
|
||||||
<h2>Конституента {data.alias}</h2>
|
<h2>
|
||||||
|
Конституента {data.alias}
|
||||||
|
{data.is_inherited ? ' (наследуется)' : ''}
|
||||||
|
</h2>
|
||||||
{data.term_resolved ? (
|
{data.term_resolved ? (
|
||||||
<p>
|
<p>
|
||||||
<b>Термин: </b>
|
<b>Термин: </b>
|
||||||
|
|
|
@ -1,13 +1,66 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { createColumnHelper } from '@tanstack/react-table';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import Tooltip from '@/components/ui/Tooltip';
|
import Tooltip from '@/components/ui/Tooltip';
|
||||||
import { OssNodeInternal } from '@/models/miscellaneous';
|
import { OssNodeInternal } from '@/models/miscellaneous';
|
||||||
|
import { ICstSubstituteEx } from '@/models/oss';
|
||||||
import { labelOperationType } from '@/utils/labels';
|
import { labelOperationType } from '@/utils/labels';
|
||||||
|
|
||||||
|
import { IconPageRight } from '../Icons';
|
||||||
|
import DataTable from '../ui/DataTable';
|
||||||
|
|
||||||
interface TooltipOperationProps {
|
interface TooltipOperationProps {
|
||||||
node: OssNodeInternal;
|
node: OssNodeInternal;
|
||||||
anchor: string;
|
anchor: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const columnHelper = createColumnHelper<ICstSubstituteEx>();
|
||||||
|
|
||||||
function TooltipOperation({ node, anchor }: TooltipOperationProps) {
|
function TooltipOperation({ node, anchor }: TooltipOperationProps) {
|
||||||
|
const columns = useMemo(
|
||||||
|
() => [
|
||||||
|
columnHelper.accessor('substitution_term', {
|
||||||
|
id: 'substitution_term',
|
||||||
|
size: 200
|
||||||
|
}),
|
||||||
|
columnHelper.accessor('substitution_alias', {
|
||||||
|
id: 'substitution_alias',
|
||||||
|
size: 50
|
||||||
|
}),
|
||||||
|
columnHelper.display({
|
||||||
|
id: 'status',
|
||||||
|
header: '',
|
||||||
|
size: 40,
|
||||||
|
cell: () => <IconPageRight size='1.2rem' />
|
||||||
|
}),
|
||||||
|
columnHelper.accessor('original_alias', {
|
||||||
|
id: 'original_alias',
|
||||||
|
size: 50
|
||||||
|
}),
|
||||||
|
columnHelper.accessor('original_term', {
|
||||||
|
id: 'original_term',
|
||||||
|
size: 200
|
||||||
|
})
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const table = useMemo(
|
||||||
|
() => (
|
||||||
|
<DataTable
|
||||||
|
dense
|
||||||
|
noHeader
|
||||||
|
noFooter
|
||||||
|
className='w-full text-sm border select-none mb-2'
|
||||||
|
data={node.data.operation.substitutions}
|
||||||
|
columns={columns}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[columns, node]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip layer='z-modalTooltip' anchorSelect={anchor} className='max-w-[35rem] max-h-[40rem] dense my-3'>
|
<Tooltip layer='z-modalTooltip' anchorSelect={anchor} className='max-w-[35rem] max-h-[40rem] dense my-3'>
|
||||||
<h2>{node.data.operation.alias}</h2>
|
<h2>{node.data.operation.alias}</h2>
|
||||||
|
@ -29,6 +82,7 @@ function TooltipOperation({ node, anchor }: TooltipOperationProps) {
|
||||||
<p>
|
<p>
|
||||||
<b>Положение:</b> [{node.xPos}, {node.yPos}]
|
<b>Положение:</b> [{node.xPos}, {node.yPos}]
|
||||||
</p>
|
</p>
|
||||||
|
{node.data.operation.substitutions.length > 0 ? table : null}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
43
rsconcept/frontend/src/components/select/MiniSelectorOSS.tsx
Normal file
43
rsconcept/frontend/src/components/select/MiniSelectorOSS.tsx
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { IconOSS } from '@/components/Icons';
|
||||||
|
import { CProps } from '@/components/props';
|
||||||
|
import Dropdown from '@/components/ui/Dropdown';
|
||||||
|
import DropdownButton from '@/components/ui/DropdownButton';
|
||||||
|
import Label from '@/components/ui/Label';
|
||||||
|
import MiniButton from '@/components/ui/MiniButton';
|
||||||
|
import useDropdown from '@/hooks/useDropdown';
|
||||||
|
import { ILibraryItemReference } from '@/models/library';
|
||||||
|
import { prefixes } from '@/utils/constants';
|
||||||
|
|
||||||
|
interface MiniSelectorOSSProps {
|
||||||
|
items: ILibraryItemReference[];
|
||||||
|
onSelect: (event: CProps.EventMouse, newValue: ILibraryItemReference) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MiniSelectorOSS({ items, onSelect }: MiniSelectorOSSProps) {
|
||||||
|
const ossMenu = useDropdown();
|
||||||
|
return (
|
||||||
|
<div ref={ossMenu.ref} className='flex items-center'>
|
||||||
|
<MiniButton
|
||||||
|
icon={<IconOSS size='1.25rem' className='icon-primary' />}
|
||||||
|
title='Связанные операционные схемы'
|
||||||
|
hideTitle={ossMenu.isOpen}
|
||||||
|
onClick={() => ossMenu.toggle()}
|
||||||
|
/>
|
||||||
|
<Dropdown isOpen={ossMenu.isOpen}>
|
||||||
|
<Label text='Список ОСС' className='border-b px-3 py-1' />
|
||||||
|
{items.map((reference, index) => (
|
||||||
|
<DropdownButton
|
||||||
|
className='min-w-[5rem]'
|
||||||
|
key={`${prefixes.oss_list}${index}`}
|
||||||
|
text={reference.alias}
|
||||||
|
onClick={event => onSelect(event, reference)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MiniSelectorOSS;
|
|
@ -102,8 +102,6 @@ function PickSubstitutions({
|
||||||
};
|
};
|
||||||
const toDelete = substitutions.map(item => item.original);
|
const toDelete = substitutions.map(item => item.original);
|
||||||
const replacements = substitutions.map(item => item.substitution);
|
const replacements = substitutions.map(item => item.substitution);
|
||||||
console.log(toDelete, replacements);
|
|
||||||
console.log(newSubstitution);
|
|
||||||
if (
|
if (
|
||||||
toDelete.includes(newSubstitution.original) ||
|
toDelete.includes(newSubstitution.original) ||
|
||||||
toDelete.includes(newSubstitution.substitution) ||
|
toDelete.includes(newSubstitution.substitution) ||
|
||||||
|
@ -112,6 +110,12 @@ function PickSubstitutions({
|
||||||
toast.error(errors.reuseOriginal);
|
toast.error(errors.reuseOriginal);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (leftArgument === rightArgument) {
|
||||||
|
if ((deleteRight && rightCst?.is_inherited) || (!deleteRight && leftCst?.is_inherited)) {
|
||||||
|
toast.error(errors.substituteInherited);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
setSubstitutions(prev => [...prev, newSubstitution]);
|
setSubstitutions(prev => [...prev, newSubstitution]);
|
||||||
setLeftCst(undefined);
|
setLeftCst(undefined);
|
||||||
setRightCst(undefined);
|
setRightCst(undefined);
|
||||||
|
|
|
@ -32,7 +32,7 @@ function SelectConstituenta({
|
||||||
return (
|
return (
|
||||||
items?.map(cst => ({
|
items?.map(cst => ({
|
||||||
value: cst.id,
|
value: cst.id,
|
||||||
label: `${cst.alias}: ${describeConstituenta(cst)}`
|
label: `${cst.alias}${cst.is_inherited ? '*' : ''}: ${describeConstituenta(cst)}`
|
||||||
})) ?? []
|
})) ?? []
|
||||||
);
|
);
|
||||||
}, [items]);
|
}, [items]);
|
||||||
|
|
|
@ -25,8 +25,8 @@ import { type ErrorData } from '@/components/info/InfoError';
|
||||||
import { AccessPolicy, ILibraryItem } from '@/models/library';
|
import { AccessPolicy, ILibraryItem } from '@/models/library';
|
||||||
import { ILibraryUpdateData } from '@/models/library';
|
import { ILibraryUpdateData } from '@/models/library';
|
||||||
import {
|
import {
|
||||||
IOperation,
|
|
||||||
IOperationCreateData,
|
IOperationCreateData,
|
||||||
|
IOperationData,
|
||||||
IOperationSchema,
|
IOperationSchema,
|
||||||
IOperationSchemaData,
|
IOperationSchemaData,
|
||||||
IOperationSetInputData,
|
IOperationSetInputData,
|
||||||
|
@ -62,7 +62,7 @@ interface IOssContext {
|
||||||
setEditors: (newEditors: UserID[], callback?: () => void) => void;
|
setEditors: (newEditors: UserID[], callback?: () => void) => void;
|
||||||
|
|
||||||
savePositions: (data: IPositionsData, callback?: () => void) => void;
|
savePositions: (data: IPositionsData, callback?: () => void) => void;
|
||||||
createOperation: (data: IOperationCreateData, callback?: DataCallback<IOperation>) => void;
|
createOperation: (data: IOperationCreateData, callback?: DataCallback<IOperationData>) => void;
|
||||||
deleteOperation: (data: ITargetOperation, callback?: () => void) => void;
|
deleteOperation: (data: ITargetOperation, callback?: () => void) => void;
|
||||||
createInput: (data: ITargetOperation, callback?: DataCallback<ILibraryItem>) => void;
|
createInput: (data: ITargetOperation, callback?: DataCallback<ILibraryItem>) => void;
|
||||||
setInput: (data: IOperationSetInputData, callback?: () => void) => void;
|
setInput: (data: IOperationSetInputData, callback?: () => void) => void;
|
||||||
|
@ -292,7 +292,7 @@ export const OssState = ({ itemID, children }: OssStateProps) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const createOperation = useCallback(
|
const createOperation = useCallback(
|
||||||
(data: IOperationCreateData, callback?: DataCallback<IOperation>) => {
|
(data: IOperationCreateData, callback?: DataCallback<IOperationData>) => {
|
||||||
setProcessingError(undefined);
|
setProcessingError(undefined);
|
||||||
postCreateOperation(itemID, {
|
postCreateOperation(itemID, {
|
||||||
data: data,
|
data: data,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
postCreateVersion,
|
postCreateVersion,
|
||||||
postSubscribe
|
postSubscribe
|
||||||
} from '@/backend/library';
|
} from '@/backend/library';
|
||||||
|
import { postFindPredecessor } from '@/backend/oss';
|
||||||
import {
|
import {
|
||||||
getTRSFile,
|
getTRSFile,
|
||||||
patchDeleteConstituenta,
|
patchDeleteConstituenta,
|
||||||
|
@ -37,6 +38,7 @@ import {
|
||||||
ConstituentaID,
|
ConstituentaID,
|
||||||
IConstituentaList,
|
IConstituentaList,
|
||||||
IConstituentaMeta,
|
IConstituentaMeta,
|
||||||
|
IConstituentaReference,
|
||||||
ICstCreateData,
|
ICstCreateData,
|
||||||
ICstMovetoData,
|
ICstMovetoData,
|
||||||
ICstRenameData,
|
ICstRenameData,
|
||||||
|
@ -89,6 +91,7 @@ interface IRSFormContext {
|
||||||
cstUpdate: (data: ICstUpdateData, callback?: DataCallback<IConstituentaMeta>) => void;
|
cstUpdate: (data: ICstUpdateData, callback?: DataCallback<IConstituentaMeta>) => void;
|
||||||
cstDelete: (data: IConstituentaList, callback?: () => void) => void;
|
cstDelete: (data: IConstituentaList, callback?: () => void) => void;
|
||||||
cstMoveTo: (data: ICstMovetoData, callback?: () => void) => void;
|
cstMoveTo: (data: ICstMovetoData, callback?: () => void) => void;
|
||||||
|
findPredecessor: (data: ITargetCst, callback: (reference: IConstituentaReference) => void) => void;
|
||||||
|
|
||||||
versionCreate: (data: IVersionData, callback?: (version: VersionID) => void) => void;
|
versionCreate: (data: IVersionData, callback?: (version: VersionID) => void) => void;
|
||||||
versionUpdate: (target: VersionID, data: IVersionData, callback?: () => void) => void;
|
versionUpdate: (target: VersionID, data: IVersionData, callback?: () => void) => void;
|
||||||
|
@ -526,6 +529,17 @@ export const RSFormState = ({ itemID, versionID, children }: RSFormStateProps) =
|
||||||
[itemID, library, setSchema]
|
[itemID, library, setSchema]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const findPredecessor = useCallback((data: ITargetCst, callback: (reference: IConstituentaReference) => void) => {
|
||||||
|
setProcessingError(undefined);
|
||||||
|
postFindPredecessor({
|
||||||
|
data: data,
|
||||||
|
showError: true,
|
||||||
|
setLoading: setProcessing,
|
||||||
|
onError: setProcessingError,
|
||||||
|
onSuccess: callback
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
const versionUpdate = useCallback(
|
const versionUpdate = useCallback(
|
||||||
(target: number, data: IVersionData, callback?: () => void) => {
|
(target: number, data: IVersionData, callback?: () => void) => {
|
||||||
setProcessingError(undefined);
|
setProcessingError(undefined);
|
||||||
|
@ -638,6 +652,8 @@ export const RSFormState = ({ itemID, versionID, children }: RSFormStateProps) =
|
||||||
cstSubstitute,
|
cstSubstitute,
|
||||||
cstDelete,
|
cstDelete,
|
||||||
cstMoveTo,
|
cstMoveTo,
|
||||||
|
findPredecessor,
|
||||||
|
|
||||||
versionCreate,
|
versionCreate,
|
||||||
versionUpdate,
|
versionUpdate,
|
||||||
versionDelete,
|
versionDelete,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useLayoutEffect, useMemo, useState } from 'react';
|
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||||
import { TabList, TabPanel, Tabs } from 'react-tabs';
|
import { TabList, TabPanel, Tabs } from 'react-tabs';
|
||||||
|
|
||||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||||
|
@ -22,6 +22,7 @@ interface DlgCreateOperationProps {
|
||||||
hideWindow: () => void;
|
hideWindow: () => void;
|
||||||
oss: IOperationSchema;
|
oss: IOperationSchema;
|
||||||
onCreate: (data: IOperationCreateData) => void;
|
onCreate: (data: IOperationCreateData) => void;
|
||||||
|
initialInputs: OperationID[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TabID {
|
export enum TabID {
|
||||||
|
@ -29,21 +30,31 @@ export enum TabID {
|
||||||
SYNTHESIS = 1
|
SYNTHESIS = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function DlgCreateOperation({ hideWindow, oss, onCreate }: DlgCreateOperationProps) {
|
function DlgCreateOperation({ hideWindow, oss, onCreate, initialInputs }: DlgCreateOperationProps) {
|
||||||
const library = useLibrary();
|
const library = useLibrary();
|
||||||
const [activeTab, setActiveTab] = useState(TabID.INPUT);
|
const [activeTab, setActiveTab] = useState(initialInputs.length > 0 ? TabID.SYNTHESIS : TabID.INPUT);
|
||||||
|
|
||||||
const [alias, setAlias] = useState('');
|
const [alias, setAlias] = useState('');
|
||||||
const [title, setTitle] = useState('');
|
const [title, setTitle] = useState('');
|
||||||
const [comment, setComment] = useState('');
|
const [comment, setComment] = useState('');
|
||||||
const [inputs, setInputs] = useState<OperationID[]>([]);
|
const [inputs, setInputs] = useState<OperationID[]>(initialInputs);
|
||||||
const [attachedID, setAttachedID] = useState<LibraryItemID | undefined>(undefined);
|
const [attachedID, setAttachedID] = useState<LibraryItemID | undefined>(undefined);
|
||||||
const [createSchema, setCreateSchema] = useState(false);
|
const [createSchema, setCreateSchema] = useState(false);
|
||||||
|
|
||||||
const isValid = useMemo(
|
const isValid = useMemo(() => {
|
||||||
() => (alias !== '' && activeTab === TabID.INPUT) || inputs.length != 1,
|
if (alias === '') {
|
||||||
[alias, activeTab, inputs]
|
return false;
|
||||||
);
|
}
|
||||||
|
if (activeTab === TabID.SYNTHESIS && inputs.length === 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (activeTab === TabID.INPUT && !attachedID) {
|
||||||
|
if (oss.items.some(operation => operation.alias === alias)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}, [alias, activeTab, inputs, attachedID, oss.items]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (attachedID) {
|
if (attachedID) {
|
||||||
|
@ -74,6 +85,21 @@ function DlgCreateOperation({ hideWindow, oss, onCreate }: DlgCreateOperationPro
|
||||||
onCreate(data);
|
onCreate(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSelectTab = useCallback(
|
||||||
|
(newTab: TabID, last: TabID) => {
|
||||||
|
if (last === newTab) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newTab === TabID.INPUT) {
|
||||||
|
setAttachedID(undefined);
|
||||||
|
} else {
|
||||||
|
setInputs(initialInputs);
|
||||||
|
}
|
||||||
|
setActiveTab(newTab);
|
||||||
|
},
|
||||||
|
[setActiveTab, initialInputs]
|
||||||
|
);
|
||||||
|
|
||||||
const inputPanel = useMemo(
|
const inputPanel = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
|
@ -131,7 +157,7 @@ function DlgCreateOperation({ hideWindow, oss, onCreate }: DlgCreateOperationPro
|
||||||
selectedTabClassName='clr-selected'
|
selectedTabClassName='clr-selected'
|
||||||
className='flex flex-col'
|
className='flex flex-col'
|
||||||
selectedIndex={activeTab}
|
selectedIndex={activeTab}
|
||||||
onSelect={setActiveTab}
|
onSelect={handleSelectTab}
|
||||||
>
|
>
|
||||||
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none')}>
|
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none')}>
|
||||||
<TabLabel
|
<TabLabel
|
||||||
|
|
|
@ -50,7 +50,7 @@ function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperatio
|
||||||
() => inputOperations.map(operation => operation.result).filter(id => id !== null),
|
() => inputOperations.map(operation => operation.result).filter(id => id !== null),
|
||||||
[inputOperations]
|
[inputOperations]
|
||||||
);
|
);
|
||||||
const [substitutions, setSubstitutions] = useState<ICstSubstitute[]>(oss.substitutions);
|
const [substitutions, setSubstitutions] = useState<ICstSubstitute[]>(target.substitutions);
|
||||||
const cache = useRSFormCache();
|
const cache = useRSFormCache();
|
||||||
const schemas = useMemo(
|
const schemas = useMemo(
|
||||||
() => schemasIDs.map(id => cache.getSchema(id)).filter(item => item !== undefined),
|
() => schemasIDs.map(id => cache.getSchema(id)).filter(item => item !== undefined),
|
||||||
|
|
|
@ -32,6 +32,7 @@ export class OssLoader {
|
||||||
this.prepareLookups();
|
this.prepareLookups();
|
||||||
this.createGraph();
|
this.createGraph();
|
||||||
this.extractSchemas();
|
this.extractSchemas();
|
||||||
|
this.inferOperationAttributes();
|
||||||
|
|
||||||
result.operationByID = this.operationByID;
|
result.operationByID = this.operationByID;
|
||||||
result.graph = this.graph;
|
result.graph = this.graph;
|
||||||
|
@ -42,7 +43,7 @@ export class OssLoader {
|
||||||
|
|
||||||
private prepareLookups() {
|
private prepareLookups() {
|
||||||
this.oss.items.forEach(operation => {
|
this.oss.items.forEach(operation => {
|
||||||
this.operationByID.set(operation.id, operation);
|
this.operationByID.set(operation.id, operation as IOperation);
|
||||||
this.graph.addNode(operation.id);
|
this.graph.addNode(operation.id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -55,6 +56,16 @@ export class OssLoader {
|
||||||
this.schemas = this.oss.items.map(operation => operation.result as LibraryItemID).filter(item => item !== null);
|
this.schemas = this.oss.items.map(operation => operation.result as LibraryItemID).filter(item => item !== null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inferOperationAttributes() {
|
||||||
|
this.graph.topologicalOrder().forEach(operationID => {
|
||||||
|
const operation = this.operationByID.get(operationID)!;
|
||||||
|
operation.substitutions = this.oss.substitutions.filter(item => item.operation === operationID);
|
||||||
|
operation.arguments = this.oss.arguments
|
||||||
|
.filter(item => item.operation === operationID)
|
||||||
|
.map(item => item.argument);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private calculateStats(): IOperationSchemaStats {
|
private calculateStats(): IOperationSchemaStats {
|
||||||
const items = this.oss.items;
|
const items = this.oss.items;
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -59,6 +59,8 @@ export class RSFormLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private inferCstAttributes() {
|
private inferCstAttributes() {
|
||||||
|
const inherit_children = new Set(this.schema.inheritance.map(item => item[0]));
|
||||||
|
const inherit_parents = new Set(this.schema.inheritance.map(item => item[1]));
|
||||||
this.graph.topologicalOrder().forEach(cstID => {
|
this.graph.topologicalOrder().forEach(cstID => {
|
||||||
const cst = this.cstByID.get(cstID)!;
|
const cst = this.cstByID.get(cstID)!;
|
||||||
cst.status = inferStatus(cst.parse.status, cst.parse.valueClass);
|
cst.status = inferStatus(cst.parse.status, cst.parse.valueClass);
|
||||||
|
@ -66,6 +68,8 @@ export class RSFormLoader {
|
||||||
cst.cst_class = inferClass(cst.cst_type, cst.is_template);
|
cst.cst_class = inferClass(cst.cst_type, cst.is_template);
|
||||||
cst.children = [];
|
cst.children = [];
|
||||||
cst.children_alias = [];
|
cst.children_alias = [];
|
||||||
|
cst.is_inherited = inherit_children.has(cst.id);
|
||||||
|
cst.is_inherited_parent = inherit_parents.has(cst.id);
|
||||||
cst.is_simple_expression = this.inferSimpleExpression(cst);
|
cst.is_simple_expression = this.inferSimpleExpression(cst);
|
||||||
if (!cst.is_simple_expression || cst.cst_type === CstType.STRUCTURED) {
|
if (!cst.is_simple_expression || cst.cst_type === CstType.STRUCTURED) {
|
||||||
return;
|
return;
|
||||||
|
@ -165,6 +169,7 @@ export class RSFormLoader {
|
||||||
sum + (cst.parse.status === ParsingStatus.VERIFIED && cst.parse.valueClass === ValueClass.INVALID ? 1 : 0),
|
sum + (cst.parse.status === ParsingStatus.VERIFIED && cst.parse.valueClass === ValueClass.INVALID ? 1 : 0),
|
||||||
0
|
0
|
||||||
),
|
),
|
||||||
|
count_inherited: items.reduce((sum, cst) => sum + ((cst as IConstituenta).is_inherited ? 1 : 0), 0),
|
||||||
|
|
||||||
count_text_term: items.reduce((sum, cst) => sum + (cst.term_raw ? 1 : 0), 0),
|
count_text_term: items.reduce((sum, cst) => sum + (cst.term_raw ? 1 : 0), 0),
|
||||||
count_definition: items.reduce((sum, cst) => sum + (cst.definition_raw ? 1 : 0), 0),
|
count_definition: items.reduce((sum, cst) => sum + (cst.definition_raw ? 1 : 0), 0),
|
||||||
|
|
|
@ -75,7 +75,7 @@ export interface ILibraryItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents library item constant data loaded for both OSS and RSForm.
|
* Represents {@link ILibraryItem} constant data loaded for both OSS and RSForm.
|
||||||
*/
|
*/
|
||||||
export interface ILibraryItemData extends ILibraryItem {
|
export interface ILibraryItemData extends ILibraryItem {
|
||||||
subscribers: UserID[];
|
subscribers: UserID[];
|
||||||
|
@ -83,7 +83,12 @@ export interface ILibraryItemData extends ILibraryItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents library item extended data with versions.
|
* Represents {@link ILibraryItem} minimal reference data.
|
||||||
|
*/
|
||||||
|
export interface ILibraryItemReference extends Pick<ILibraryItem, 'id' | 'alias'> {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link ILibraryItem} extended data with versions.
|
||||||
*/
|
*/
|
||||||
export interface ILibraryItemVersioned extends ILibraryItemData {
|
export interface ILibraryItemVersioned extends ILibraryItemData {
|
||||||
version?: VersionID;
|
version?: VersionID;
|
||||||
|
@ -91,7 +96,7 @@ export interface ILibraryItemVersioned extends ILibraryItemData {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents common library item editor controller.
|
* Represents common {@link ILibraryItem} editor controller.
|
||||||
*/
|
*/
|
||||||
export interface ILibraryItemEditor {
|
export interface ILibraryItemEditor {
|
||||||
schema?: ILibraryItemData;
|
schema?: ILibraryItemData;
|
||||||
|
|
|
@ -35,8 +35,16 @@ export interface IOperation {
|
||||||
position_y: number;
|
position_y: number;
|
||||||
|
|
||||||
result: LibraryItemID | null;
|
result: LibraryItemID | null;
|
||||||
|
|
||||||
|
substitutions: ICstSubstituteEx[];
|
||||||
|
arguments: OperationID[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IOperation} data from server.
|
||||||
|
*/
|
||||||
|
export interface IOperationData extends Omit<IOperation, 'substitutions' | 'arguments'> {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents {@link IOperation} position.
|
* Represents {@link IOperation} position.
|
||||||
*/
|
*/
|
||||||
|
@ -121,6 +129,7 @@ export interface IMultiSubstitution {
|
||||||
* Represents {@link ICstSubstitute} extended data.
|
* Represents {@link ICstSubstitute} extended data.
|
||||||
*/
|
*/
|
||||||
export interface ICstSubstituteEx extends ICstSubstitute {
|
export interface ICstSubstituteEx extends ICstSubstitute {
|
||||||
|
operation: OperationID;
|
||||||
original_alias: string;
|
original_alias: string;
|
||||||
original_term: string;
|
original_term: string;
|
||||||
substitution_alias: string;
|
substitution_alias: string;
|
||||||
|
@ -141,7 +150,7 @@ export interface IOperationSchemaStats {
|
||||||
* Represents backend data for {@link IOperationSchema}.
|
* Represents backend data for {@link IOperationSchema}.
|
||||||
*/
|
*/
|
||||||
export interface IOperationSchemaData extends ILibraryItemData {
|
export interface IOperationSchemaData extends ILibraryItemData {
|
||||||
items: IOperation[];
|
items: IOperationData[];
|
||||||
arguments: IArgument[];
|
arguments: IArgument[];
|
||||||
substitutions: ICstSubstituteEx[];
|
substitutions: ICstSubstituteEx[];
|
||||||
}
|
}
|
||||||
|
@ -150,6 +159,7 @@ export interface IOperationSchemaData extends ILibraryItemData {
|
||||||
* Represents OperationSchema.
|
* Represents OperationSchema.
|
||||||
*/
|
*/
|
||||||
export interface IOperationSchema extends IOperationSchemaData {
|
export interface IOperationSchema extends IOperationSchemaData {
|
||||||
|
items: IOperation[];
|
||||||
graph: Graph;
|
graph: Graph;
|
||||||
schemas: LibraryItemID[];
|
schemas: LibraryItemID[];
|
||||||
stats: IOperationSchemaStats;
|
stats: IOperationSchemaStats;
|
||||||
|
@ -160,7 +170,7 @@ export interface IOperationSchema extends IOperationSchemaData {
|
||||||
* Represents data response when creating {@link IOperation}.
|
* Represents data response when creating {@link IOperation}.
|
||||||
*/
|
*/
|
||||||
export interface IOperationCreatedResponse {
|
export interface IOperationCreatedResponse {
|
||||||
new_operation: IOperation;
|
new_operation: IOperationData;
|
||||||
oss: IOperationSchemaData;
|
oss: IOperationSchemaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
import { Graph } from '@/models/Graph';
|
import { Graph } from '@/models/Graph';
|
||||||
|
|
||||||
import { ILibraryItem, ILibraryItemVersioned, LibraryItemID } from './library';
|
import { ILibraryItem, ILibraryItemReference, ILibraryItemVersioned, LibraryItemID } from './library';
|
||||||
import { ICstSubstitute } from './oss';
|
import { ICstSubstitute } from './oss';
|
||||||
import { IArgumentInfo, ParsingStatus, ValueClass } from './rslang';
|
import { IArgumentInfo, ParsingStatus, ValueClass } from './rslang';
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ export interface ITargetCst {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents Constituenta data from server.
|
* Represents {@link IConstituenta} data from server.
|
||||||
*/
|
*/
|
||||||
export interface IConstituentaData extends IConstituentaMeta {
|
export interface IConstituentaData extends IConstituentaMeta {
|
||||||
parse: {
|
parse: {
|
||||||
|
@ -111,12 +111,19 @@ export interface IConstituenta extends IConstituentaData {
|
||||||
status: ExpressionStatus;
|
status: ExpressionStatus;
|
||||||
is_template: boolean;
|
is_template: boolean;
|
||||||
is_simple_expression: boolean;
|
is_simple_expression: boolean;
|
||||||
|
is_inherited: boolean;
|
||||||
|
is_inherited_parent: boolean;
|
||||||
parent?: ConstituentaID;
|
parent?: ConstituentaID;
|
||||||
parent_alias?: string;
|
parent_alias?: string;
|
||||||
children: number[];
|
children: number[];
|
||||||
children_alias: string[];
|
children_alias: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents {@link IConstituenta} reference.
|
||||||
|
*/
|
||||||
|
export interface IConstituentaReference extends Pick<IConstituentaMeta, 'id' | 'schema'> {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents Constituenta list.
|
* Represents Constituenta list.
|
||||||
*/
|
*/
|
||||||
|
@ -183,6 +190,7 @@ export interface IRSFormStats {
|
||||||
count_errors: number;
|
count_errors: number;
|
||||||
count_property: number;
|
count_property: number;
|
||||||
count_incalculable: number;
|
count_incalculable: number;
|
||||||
|
count_inherited: number;
|
||||||
|
|
||||||
count_text_term: number;
|
count_text_term: number;
|
||||||
count_definition: number;
|
count_definition: number;
|
||||||
|
@ -198,10 +206,19 @@ export interface IRSFormStats {
|
||||||
count_theorem: number;
|
count_theorem: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data for {@link IRSForm} provided by backend.
|
||||||
|
*/
|
||||||
|
export interface IRSFormData extends ILibraryItemVersioned {
|
||||||
|
items: IConstituentaData[];
|
||||||
|
inheritance: ConstituentaID[][];
|
||||||
|
oss: ILibraryItemReference[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents formal explication for set of concepts.
|
* Represents formal explication for set of concepts.
|
||||||
*/
|
*/
|
||||||
export interface IRSForm extends ILibraryItemVersioned {
|
export interface IRSForm extends IRSFormData {
|
||||||
items: IConstituenta[];
|
items: IConstituenta[];
|
||||||
stats: IRSFormStats;
|
stats: IRSFormStats;
|
||||||
graph: Graph;
|
graph: Graph;
|
||||||
|
@ -209,13 +226,6 @@ export interface IRSForm extends ILibraryItemVersioned {
|
||||||
cstByID: Map<ConstituentaID, IConstituenta>;
|
cstByID: Map<ConstituentaID, IConstituenta>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents data for {@link IRSForm} provided by backend.
|
|
||||||
*/
|
|
||||||
export interface IRSFormData extends ILibraryItemVersioned {
|
|
||||||
items: IConstituentaData[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents data, used for cloning {@link IRSForm}.
|
* Represents data, used for cloning {@link IRSForm}.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -133,6 +133,8 @@ export function createMockConstituenta(id: ConstituentaID, alias: string, commen
|
||||||
definition_resolved: '',
|
definition_resolved: '',
|
||||||
status: ExpressionStatus.INCORRECT,
|
status: ExpressionStatus.INCORRECT,
|
||||||
is_template: false,
|
is_template: false,
|
||||||
|
is_inherited: false,
|
||||||
|
is_inherited_parent: false,
|
||||||
cst_class: CstClass.DERIVED,
|
cst_class: CstClass.DERIVED,
|
||||||
parse: {
|
parse: {
|
||||||
status: ParsingStatus.INCORRECT,
|
status: ParsingStatus.INCORRECT,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { urls } from '@/app/urls';
|
import { urls } from '@/app/urls';
|
||||||
|
@ -22,10 +22,11 @@ import TextInput from '@/components/ui/TextInput';
|
||||||
import { useAuth } from '@/context/AuthContext';
|
import { useAuth } from '@/context/AuthContext';
|
||||||
import { useLibrary } from '@/context/LibraryContext';
|
import { useLibrary } from '@/context/LibraryContext';
|
||||||
import { useConceptNavigation } from '@/context/NavigationContext';
|
import { useConceptNavigation } from '@/context/NavigationContext';
|
||||||
|
import useLocalStorage from '@/hooks/useLocalStorage';
|
||||||
import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library';
|
import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library';
|
||||||
import { ILibraryCreateData } from '@/models/library';
|
import { ILibraryCreateData } from '@/models/library';
|
||||||
import { combineLocation, validateLocation } from '@/models/libraryAPI';
|
import { combineLocation, validateLocation } from '@/models/libraryAPI';
|
||||||
import { EXTEOR_TRS_FILE, limits, patterns } from '@/utils/constants';
|
import { EXTEOR_TRS_FILE, limits, patterns, storage } from '@/utils/constants';
|
||||||
import { information } from '@/utils/labels';
|
import { information } from '@/utils/labels';
|
||||||
|
|
||||||
function FormCreateItem() {
|
function FormCreateItem() {
|
||||||
|
@ -45,6 +46,7 @@ function FormCreateItem() {
|
||||||
|
|
||||||
const location = useMemo(() => combineLocation(head, body), [head, body]);
|
const location = useMemo(() => combineLocation(head, body), [head, body]);
|
||||||
const isValid = useMemo(() => validateLocation(location), [location]);
|
const isValid = useMemo(() => validateLocation(location), [location]);
|
||||||
|
const [initLocation] = useLocalStorage<string>(storage.librarySearchLocation, '');
|
||||||
|
|
||||||
const [fileName, setFileName] = useState('');
|
const [fileName, setFileName] = useState('');
|
||||||
const [file, setFile] = useState<File | undefined>();
|
const [file, setFile] = useState<File | undefined>();
|
||||||
|
@ -104,6 +106,13 @@ function FormCreateItem() {
|
||||||
setBody(newValue.length > 3 ? newValue.substring(3) : '');
|
setBody(newValue.length > 3 ? newValue.substring(3) : '');
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (!initLocation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handleSelectLocation(initLocation);
|
||||||
|
}, [initLocation, handleSelectLocation]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className={clsx('cc-column', 'min-w-[30rem] max-w-[30rem] mx-auto', 'px-6 py-3')} onSubmit={handleSubmit}>
|
<form className={clsx('cc-column', 'min-w-[30rem] max-w-[30rem] mx-auto', 'px-6 py-3')} onSubmit={handleSubmit}>
|
||||||
<h1>
|
<h1>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
import LinkTopic from '../../../components/ui/LinkTopic';
|
import LinkTopic from '@/components/ui/LinkTopic';
|
||||||
|
|
||||||
function HelpCstAttributes() {
|
function HelpCstAttributes() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
IconMoveDown,
|
IconMoveDown,
|
||||||
IconMoveUp,
|
IconMoveUp,
|
||||||
IconNewItem,
|
IconNewItem,
|
||||||
|
IconOSS,
|
||||||
IconReset,
|
IconReset,
|
||||||
IconSave,
|
IconSave,
|
||||||
IconStatusOK,
|
IconStatusOK,
|
||||||
|
@ -22,6 +23,9 @@ function HelpCstEditor() {
|
||||||
return (
|
return (
|
||||||
<div className='dense'>
|
<div className='dense'>
|
||||||
<h1>Редактор конституенты</h1>
|
<h1>Редактор конституенты</h1>
|
||||||
|
<li>
|
||||||
|
<IconOSS className='inline-icon' /> переход к связанной <LinkTopic text='ОСС' topic={HelpTopic.CC_OSS} />
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconSave className='inline-icon' /> сохранить изменения: Ctrl + S
|
<IconSave className='inline-icon' /> сохранить изменения: Ctrl + S
|
||||||
</li>
|
</li>
|
||||||
|
@ -74,7 +78,6 @@ function HelpCstEditor() {
|
||||||
<IconMoveUp className='inline-icon' /> Alt + вверх/вниз – перемещение
|
<IconMoveUp className='inline-icon' /> Alt + вверх/вниз – перемещение
|
||||||
</li>
|
</li>
|
||||||
<li>фильтрация в верхней части</li>
|
<li>фильтрация в верхней части</li>
|
||||||
<li>при наведении на имя конституенты отображаются атрибуты</li>
|
|
||||||
<li>
|
<li>
|
||||||
<span style={{ backgroundColor: colors.bgSelected }}>цветом фона</span> выделена текущая конституента
|
<span style={{ backgroundColor: colors.bgSelected }}>цветом фона</span> выделена текущая конституента
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { urls } from '@/app/urls';
|
import { urls } from '@/app/urls';
|
||||||
import { IconLibrary2, IconManuals, IconUser2 } from '@/components/Icons';
|
import { IconLibrary2, IconManuals, IconUser2 } from '@/components/Icons';
|
||||||
|
import LinkTopic from '@/components/ui/LinkTopic';
|
||||||
import TextURL from '@/components/ui/TextURL';
|
import TextURL from '@/components/ui/TextURL';
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
import { external_urls, prefixes } from '@/utils/constants';
|
import { external_urls, prefixes } from '@/utils/constants';
|
||||||
|
|
||||||
import LinkTopic from '../../../components/ui/LinkTopic';
|
|
||||||
import TopicItem from '../TopicItem';
|
import TopicItem from '../TopicItem';
|
||||||
|
|
||||||
function HelpPortal() {
|
function HelpPortal() {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IconClone,
|
IconClone,
|
||||||
IconDestroy,
|
IconDestroy,
|
||||||
|
@ -7,11 +5,13 @@ import {
|
||||||
IconEditor,
|
IconEditor,
|
||||||
IconFollow,
|
IconFollow,
|
||||||
IconImmutable,
|
IconImmutable,
|
||||||
|
IconOSS,
|
||||||
IconOwner,
|
IconOwner,
|
||||||
IconPublic,
|
IconPublic,
|
||||||
IconSave
|
IconSave
|
||||||
} from '../../../components/Icons';
|
} from '@/components/Icons';
|
||||||
import LinkTopic from '../../../components/ui/LinkTopic';
|
import LinkTopic from '@/components/ui/LinkTopic';
|
||||||
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
function HelpRSFormCard() {
|
function HelpRSFormCard() {
|
||||||
return (
|
return (
|
||||||
|
@ -30,6 +30,9 @@ function HelpRSFormCard() {
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Управление</h2>
|
<h2>Управление</h2>
|
||||||
|
<li>
|
||||||
|
<IconOSS className='inline-icon' /> переход к связанной <LinkTopic text='ОСС' topic={HelpTopic.CC_OSS} />
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconSave className='inline-icon' /> сохранить изменения: Ctrl + S
|
<IconSave className='inline-icon' /> сохранить изменения: Ctrl + S
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
import InfoCstStatus from '@/components/info/InfoCstStatus';
|
|
||||||
import Divider from '@/components/ui/Divider';
|
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IconAlias,
|
IconAlias,
|
||||||
IconClone,
|
IconClone,
|
||||||
|
@ -10,20 +6,31 @@ import {
|
||||||
IconMoveUp,
|
IconMoveUp,
|
||||||
IconNewItem,
|
IconNewItem,
|
||||||
IconOpenList,
|
IconOpenList,
|
||||||
|
IconOSS,
|
||||||
IconReset
|
IconReset
|
||||||
} from '../../../components/Icons';
|
} from '@/components/Icons';
|
||||||
import LinkTopic from '../../../components/ui/LinkTopic';
|
import InfoCstStatus from '@/components/info/InfoCstStatus';
|
||||||
|
import Divider from '@/components/ui/Divider';
|
||||||
|
import LinkTopic from '@/components/ui/LinkTopic';
|
||||||
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
function HelpRSFormItems() {
|
function HelpRSFormItems() {
|
||||||
return (
|
return (
|
||||||
<div className='dense'>
|
<div className='dense'>
|
||||||
<h1>Список конституент</h1>
|
<h1>Список конституент</h1>
|
||||||
<p>
|
<li>
|
||||||
<IconAlias className='inline-icon' />
|
<IconAlias className='inline-icon' />
|
||||||
Конституенты обладают уникальным <LinkTopic text='Именем' topic={HelpTopic.CC_CONSTITUENTA} />
|
Конституенты обладают уникальным <LinkTopic text='Именем' topic={HelpTopic.CC_CONSTITUENTA} />
|
||||||
</p>
|
</li>
|
||||||
|
<li>при наведении на имя отображаются атрибуты</li>
|
||||||
|
<li>
|
||||||
|
пунктиром отображаются <LinkTopic text='наследованные' topic={HelpTopic.CC_OSS} /> конституенты
|
||||||
|
</li>
|
||||||
|
|
||||||
<h2>Управление списком</h2>
|
<h2>Управление списком</h2>
|
||||||
|
<li>
|
||||||
|
<IconOSS className='inline-icon' /> переход к связанной <LinkTopic text='ОСС' topic={HelpTopic.CC_OSS} />
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconReset className='inline-icon' /> сбросить выделение: ESC
|
<IconReset className='inline-icon' /> сбросить выделение: ESC
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
import LinkTopic from '@/components/ui/LinkTopic';
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
import LinkTopic from '../../../components/ui/LinkTopic';
|
|
||||||
|
|
||||||
function HelpRSLangCorrect() {
|
function HelpRSLangCorrect() {
|
||||||
return (
|
return (
|
||||||
<div className='text-justify'>
|
<div className='text-justify'>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
import LinkTopic from '@/components/ui/LinkTopic';
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
import LinkTopic from '../../../components/ui/LinkTopic';
|
|
||||||
|
|
||||||
function HelpRSLangInterpret() {
|
function HelpRSLangInterpret() {
|
||||||
return (
|
return (
|
||||||
<div className='text-justify'>
|
<div className='text-justify'>
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IconGenerateNames,
|
IconGenerateNames,
|
||||||
IconGenerateStructure,
|
IconGenerateStructure,
|
||||||
|
@ -7,8 +5,9 @@ import {
|
||||||
IconReplace,
|
IconReplace,
|
||||||
IconSortList,
|
IconSortList,
|
||||||
IconTemplates
|
IconTemplates
|
||||||
} from '../../../components/Icons';
|
} from '@/components/Icons';
|
||||||
import LinkTopic from '../../../components/ui/LinkTopic';
|
import LinkTopic from '@/components/ui/LinkTopic';
|
||||||
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
function HelpRSLangOperations() {
|
function HelpRSLangOperations() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,8 +1,3 @@
|
||||||
import Divider from '@/components/ui/Divider';
|
|
||||||
import LinkTopic from '@/components/ui/LinkTopic';
|
|
||||||
import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IconClustering,
|
IconClustering,
|
||||||
IconDestroy,
|
IconDestroy,
|
||||||
|
@ -17,10 +12,15 @@ import {
|
||||||
IconGraphOutputs,
|
IconGraphOutputs,
|
||||||
IconImage,
|
IconImage,
|
||||||
IconNewItem,
|
IconNewItem,
|
||||||
|
IconOSS,
|
||||||
IconReset,
|
IconReset,
|
||||||
IconRotate3D,
|
IconRotate3D,
|
||||||
IconText
|
IconText
|
||||||
} from '../../../components/Icons';
|
} from '@/components/Icons';
|
||||||
|
import Divider from '@/components/ui/Divider';
|
||||||
|
import LinkTopic from '@/components/ui/LinkTopic';
|
||||||
|
import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
||||||
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
function HelpTermGraph() {
|
function HelpTermGraph() {
|
||||||
const { colors } = useConceptOptions();
|
const { colors } = useConceptOptions();
|
||||||
|
@ -71,6 +71,9 @@ function HelpTermGraph() {
|
||||||
<div className='flex flex-col-reverse mb-3 sm:flex-row'>
|
<div className='flex flex-col-reverse mb-3 sm:flex-row'>
|
||||||
<div className='w-full sm:w-[14rem]'>
|
<div className='w-full sm:w-[14rem]'>
|
||||||
<h1>Общие</h1>
|
<h1>Общие</h1>
|
||||||
|
<li>
|
||||||
|
<IconOSS className='inline-icon' /> переход к связанной <LinkTopic text='ОСС' topic={HelpTopic.CC_OSS} />
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconFilter className='inline-icon' /> Открыть настройки
|
<IconFilter className='inline-icon' /> Открыть настройки
|
||||||
</li>
|
</li>
|
||||||
|
@ -80,6 +83,9 @@ function HelpTermGraph() {
|
||||||
<li>
|
<li>
|
||||||
<IconImage className='inline-icon' /> Сохранить в формат PNG
|
<IconImage className='inline-icon' /> Сохранить в формат PNG
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
* <LinkTopic text='наследованные' topic={HelpTopic.CC_OSS} /> в ОСС
|
||||||
|
</li>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Divider vertical margins='mx-3' className='hidden sm:block' />
|
<Divider vertical margins='mx-3' className='hidden sm:block' />
|
||||||
|
|
|
@ -21,7 +21,7 @@ function InputNode(node: OssNodeInternal) {
|
||||||
<>
|
<>
|
||||||
<Handle type='source' position={Position.Bottom} />
|
<Handle type='source' position={Position.Bottom} />
|
||||||
|
|
||||||
<Overlay position='top-[-0.2rem] right-[-0.2rem]' className='cc-icons'>
|
<Overlay position='top-[-0.2rem] right-[-0.2rem]'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
icon={<IconRSForm className={hasFile ? 'clr-text-green' : 'clr-text-red'} size='0.75rem' />}
|
icon={<IconRSForm className={hasFile ? 'clr-text-green' : 'clr-text-red'} size='0.75rem' />}
|
||||||
noHover
|
noHover
|
||||||
|
|
|
@ -101,11 +101,11 @@ function NodeContextMenu({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className='absolute' style={{ top: cursorY, left: cursorX, width: 10, height: 10 }}>
|
<div ref={ref} className='absolute select-none' style={{ top: cursorY, left: cursorX, width: 10, height: 10 }}>
|
||||||
<Dropdown isOpen={isOpen} stretchLeft={cursorX >= window.innerWidth - PARAMETER.ossContextMenuWidth}>
|
<Dropdown isOpen={isOpen} stretchLeft={cursorX >= window.innerWidth - PARAMETER.ossContextMenuWidth}>
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Редактировать'
|
text='Редактировать'
|
||||||
titleHtml={prepareTooltip('Редактировать операцию', 'Ctrl + клик')}
|
titleHtml={prepareTooltip('Редактировать операцию', 'Двойной клик')}
|
||||||
icon={<IconEdit2 size='1rem' className='icon-primary' />}
|
icon={<IconEdit2 size='1rem' className='icon-primary' />}
|
||||||
disabled={controller.isProcessing}
|
disabled={controller.isProcessing}
|
||||||
onClick={handleEditOperation}
|
onClick={handleEditOperation}
|
||||||
|
|
|
@ -22,7 +22,7 @@ function OperationNode(node: OssNodeInternal) {
|
||||||
<>
|
<>
|
||||||
<Handle type='source' position={Position.Bottom} />
|
<Handle type='source' position={Position.Bottom} />
|
||||||
|
|
||||||
<Overlay position='top-[-0.2rem] right-[-0.2rem]' className='cc-icons'>
|
<Overlay position='top-[-0.2rem] right-[-0.2rem]'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
icon={<IconRSForm className={hasFile ? 'clr-text-green' : 'clr-text-red'} size='0.75rem' />}
|
icon={<IconRSForm className={hasFile ? 'clr-text-green' : 'clr-text-red'} size='0.75rem' />}
|
||||||
noHover
|
noHover
|
||||||
|
|
|
@ -122,10 +122,43 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
||||||
controller.savePositions(getPositions(), () => setIsModified(false));
|
controller.savePositions(getPositions(), () => setIsModified(false));
|
||||||
}, [controller, getPositions, setIsModified]);
|
}, [controller, getPositions, setIsModified]);
|
||||||
|
|
||||||
const handleCreateOperation = useCallback(() => {
|
const handleCreateOperation = useCallback(
|
||||||
const center = flow.project({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
|
(inputs: OperationID[]) => () => {
|
||||||
controller.promptCreateOperation(center.x, center.y, getPositions());
|
if (!controller.schema) {
|
||||||
}, [controller, getPositions, flow]);
|
return;
|
||||||
|
}
|
||||||
|
let target = { x: 0, y: 0 };
|
||||||
|
const positions = getPositions();
|
||||||
|
|
||||||
|
if (inputs.length <= 1) {
|
||||||
|
target = flow.project({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
|
||||||
|
} else {
|
||||||
|
const inputsNodes = positions.filter(pos => inputs.includes(pos.id));
|
||||||
|
const maxY = Math.max(...inputsNodes.map(node => node.position_y));
|
||||||
|
const minX = Math.min(...inputsNodes.map(node => node.position_x));
|
||||||
|
const maxX = Math.max(...inputsNodes.map(node => node.position_x));
|
||||||
|
|
||||||
|
target.y = maxY + 100;
|
||||||
|
target.x = Math.ceil((maxX + minX) / 2 / PARAMETER.ossGridSize) * PARAMETER.ossGridSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
let flagIntersect = false;
|
||||||
|
do {
|
||||||
|
flagIntersect = positions.some(
|
||||||
|
position =>
|
||||||
|
Math.abs(position.position_x - target.x) < PARAMETER.ossMinDistance &&
|
||||||
|
Math.abs(position.position_y - target.y) < PARAMETER.ossMinDistance
|
||||||
|
);
|
||||||
|
if (flagIntersect) {
|
||||||
|
target.x += PARAMETER.ossMinDistance;
|
||||||
|
target.y += PARAMETER.ossMinDistance;
|
||||||
|
}
|
||||||
|
} while (flagIntersect);
|
||||||
|
|
||||||
|
controller.promptCreateOperation(target.x, target.y, inputs, positions);
|
||||||
|
},
|
||||||
|
[controller, getPositions, flow]
|
||||||
|
);
|
||||||
|
|
||||||
const handleDeleteSelected = useCallback(() => {
|
const handleDeleteSelected = useCallback(() => {
|
||||||
if (controller.selected.length !== 1) {
|
if (controller.selected.length !== 1) {
|
||||||
|
@ -241,13 +274,11 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
||||||
handleContextMenuHide();
|
handleContextMenuHide();
|
||||||
}, [handleContextMenuHide]);
|
}, [handleContextMenuHide]);
|
||||||
|
|
||||||
const handleNodeClick = useCallback(
|
const handleNodeDoubleClick = useCallback(
|
||||||
(event: CProps.EventMouse, node: OssNode) => {
|
(event: CProps.EventMouse, node: OssNode) => {
|
||||||
if (event.ctrlKey || event.metaKey) {
|
event.preventDefault();
|
||||||
event.preventDefault();
|
event.stopPropagation();
|
||||||
event.stopPropagation();
|
handleEditOperation(Number(node.id));
|
||||||
handleEditOperation(Number(node.id));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[handleEditOperation]
|
[handleEditOperation]
|
||||||
);
|
);
|
||||||
|
@ -268,7 +299,7 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
||||||
if ((event.ctrlKey || event.metaKey) && event.key === 'q') {
|
if ((event.ctrlKey || event.metaKey) && event.key === 'q') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
handleCreateOperation();
|
handleCreateOperation(controller.selected);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.key === 'Delete') {
|
if (event.key === 'Delete') {
|
||||||
|
@ -297,7 +328,7 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
||||||
edges={edges}
|
edges={edges}
|
||||||
onNodesChange={handleNodesChange}
|
onNodesChange={handleNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onNodeClick={handleNodeClick}
|
onNodeDoubleClick={handleNodeDoubleClick}
|
||||||
proOptions={{ hideAttribution: true }}
|
proOptions={{ hideAttribution: true }}
|
||||||
fitView
|
fitView
|
||||||
nodeTypes={OssNodeTypes}
|
nodeTypes={OssNodeTypes}
|
||||||
|
@ -305,11 +336,11 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
||||||
minZoom={0.75}
|
minZoom={0.75}
|
||||||
nodesConnectable={false}
|
nodesConnectable={false}
|
||||||
snapToGrid={true}
|
snapToGrid={true}
|
||||||
snapGrid={[10, 10]}
|
snapGrid={[PARAMETER.ossGridSize, PARAMETER.ossGridSize]}
|
||||||
onNodeContextMenu={handleContextMenu}
|
onNodeContextMenu={handleContextMenu}
|
||||||
onClick={handleClickCanvas}
|
onClick={handleClickCanvas}
|
||||||
>
|
>
|
||||||
{showGrid ? <Background gap={10} /> : null}
|
{showGrid ? <Background gap={PARAMETER.ossGridSize} /> : null}
|
||||||
</ReactFlow>
|
</ReactFlow>
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
|
@ -319,7 +350,7 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
||||||
handleContextMenu,
|
handleContextMenu,
|
||||||
handleClickCanvas,
|
handleClickCanvas,
|
||||||
onEdgesChange,
|
onEdgesChange,
|
||||||
handleNodeClick,
|
handleNodeDoubleClick,
|
||||||
OssNodeTypes,
|
OssNodeTypes,
|
||||||
showGrid
|
showGrid
|
||||||
]
|
]
|
||||||
|
@ -334,7 +365,7 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
||||||
edgeAnimate={edgeAnimate}
|
edgeAnimate={edgeAnimate}
|
||||||
edgeStraight={edgeStraight}
|
edgeStraight={edgeStraight}
|
||||||
onFitView={handleFitView}
|
onFitView={handleFitView}
|
||||||
onCreate={handleCreateOperation}
|
onCreate={handleCreateOperation(controller.selected)}
|
||||||
onDelete={handleDeleteSelected}
|
onDelete={handleDeleteSelected}
|
||||||
onEdit={() => handleEditOperation(controller.selected[0])}
|
onEdit={() => handleEditOperation(controller.selected[0])}
|
||||||
onExecute={handleExecuteSelected}
|
onExecute={handleExecuteSelected}
|
||||||
|
|
|
@ -167,7 +167,7 @@ function ToolbarOssGraph({
|
||||||
onClick={onExecute}
|
onClick={onExecute}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
titleHtml={prepareTooltip('Редактировать выбранную', 'Ctrl + клик')}
|
titleHtml={prepareTooltip('Редактировать выбранную', 'Двойной клик')}
|
||||||
icon={<IconEdit2 size='1.25rem' className='icon-primary' />}
|
icon={<IconEdit2 size='1.25rem' className='icon-primary' />}
|
||||||
disabled={controller.selected.length !== 1 || controller.isProcessing}
|
disabled={controller.selected.length !== 1 || controller.isProcessing}
|
||||||
onClick={onEdit}
|
onClick={onEdit}
|
||||||
|
|
|
@ -51,7 +51,7 @@ export interface IOssEditContext {
|
||||||
openOperationSchema: (target: OperationID) => void;
|
openOperationSchema: (target: OperationID) => void;
|
||||||
|
|
||||||
savePositions: (positions: IOperationPosition[], callback?: () => void) => void;
|
savePositions: (positions: IOperationPosition[], callback?: () => void) => void;
|
||||||
promptCreateOperation: (x: number, y: number, positions: IOperationPosition[]) => void;
|
promptCreateOperation: (x: number, y: number, inputs: OperationID[], positions: IOperationPosition[]) => void;
|
||||||
deleteOperation: (target: OperationID, positions: IOperationPosition[]) => void;
|
deleteOperation: (target: OperationID, positions: IOperationPosition[]) => void;
|
||||||
createInput: (target: OperationID, positions: IOperationPosition[]) => void;
|
createInput: (target: OperationID, positions: IOperationPosition[]) => void;
|
||||||
promptEditInput: (target: OperationID, positions: IOperationPosition[]) => void;
|
promptEditInput: (target: OperationID, positions: IOperationPosition[]) => void;
|
||||||
|
@ -96,6 +96,7 @@ export const OssEditState = ({ selected, setSelected, children }: OssEditStatePr
|
||||||
|
|
||||||
const [showCreateOperation, setShowCreateOperation] = useState(false);
|
const [showCreateOperation, setShowCreateOperation] = useState(false);
|
||||||
const [insertPosition, setInsertPosition] = useState<Position2D>({ x: 0, y: 0 });
|
const [insertPosition, setInsertPosition] = useState<Position2D>({ x: 0, y: 0 });
|
||||||
|
const [initialInputs, setInitialInputs] = useState<OperationID[]>([]);
|
||||||
const [positions, setPositions] = useState<IOperationPosition[]>([]);
|
const [positions, setPositions] = useState<IOperationPosition[]>([]);
|
||||||
const [targetOperationID, setTargetOperationID] = useState<OperationID | undefined>(undefined);
|
const [targetOperationID, setTargetOperationID] = useState<OperationID | undefined>(undefined);
|
||||||
const targetOperation = useMemo(
|
const targetOperation = useMemo(
|
||||||
|
@ -208,11 +209,15 @@ export const OssEditState = ({ selected, setSelected, children }: OssEditStatePr
|
||||||
[model]
|
[model]
|
||||||
);
|
);
|
||||||
|
|
||||||
const promptCreateOperation = useCallback((x: number, y: number, positions: IOperationPosition[]) => {
|
const promptCreateOperation = useCallback(
|
||||||
setInsertPosition({ x: x, y: y });
|
(x: number, y: number, inputs: OperationID[], positions: IOperationPosition[]) => {
|
||||||
setPositions(positions);
|
setInsertPosition({ x: x, y: y });
|
||||||
setShowCreateOperation(true);
|
setInitialInputs(inputs);
|
||||||
}, []);
|
setPositions(positions);
|
||||||
|
setShowCreateOperation(true);
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const handleCreateOperation = useCallback(
|
const handleCreateOperation = useCallback(
|
||||||
(data: IOperationCreateData) => {
|
(data: IOperationCreateData) => {
|
||||||
|
@ -341,6 +346,7 @@ export const OssEditState = ({ selected, setSelected, children }: OssEditStatePr
|
||||||
hideWindow={() => setShowCreateOperation(false)}
|
hideWindow={() => setShowCreateOperation(false)}
|
||||||
oss={model.schema}
|
oss={model.schema}
|
||||||
onCreate={handleCreateOperation}
|
onCreate={handleCreateOperation}
|
||||||
|
initialInputs={initialInputs}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{showEditInput ? (
|
{showEditInput ? (
|
||||||
|
|
|
@ -80,21 +80,15 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='overflow-y-auto' style={{ maxHeight: panelHeight }}>
|
<div className='overflow-y-auto' style={{ maxHeight: panelHeight }}>
|
||||||
{controller.isContentEditable ? (
|
<ToolbarConstituenta
|
||||||
<ToolbarConstituenta
|
activeCst={activeCst}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
modified={isModified}
|
modified={isModified}
|
||||||
showList={showList}
|
showList={showList}
|
||||||
onMoveUp={controller.moveUp}
|
onSubmit={initiateSubmit}
|
||||||
onMoveDown={controller.moveDown}
|
onReset={() => setToggleReset(prev => !prev)}
|
||||||
onSubmit={initiateSubmit}
|
onToggleList={() => setShowList(prev => !prev)}
|
||||||
onReset={() => setToggleReset(prev => !prev)}
|
/>
|
||||||
onDelete={controller.deleteCst}
|
|
||||||
onClone={controller.cloneCst}
|
|
||||||
onCreate={() => controller.createCst(activeCst?.cst_type, false)}
|
|
||||||
onToggleList={() => setShowList(prev => !prev)}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
<div
|
<div
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
|
|
@ -5,8 +5,10 @@ import { AnimatePresence } from 'framer-motion';
|
||||||
import { useEffect, useLayoutEffect, useMemo, useState } from 'react';
|
import { useEffect, useLayoutEffect, useMemo, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { IconSave } from '@/components/Icons';
|
import { IconChild, IconParent, IconSave } from '@/components/Icons';
|
||||||
import RefsInput from '@/components/RefsInput';
|
import RefsInput from '@/components/RefsInput';
|
||||||
|
import MiniButton from '@/components/ui/MiniButton';
|
||||||
|
import Overlay from '@/components/ui/Overlay';
|
||||||
import SubmitButton from '@/components/ui/SubmitButton';
|
import SubmitButton from '@/components/ui/SubmitButton';
|
||||||
import TextArea from '@/components/ui/TextArea';
|
import TextArea from '@/components/ui/TextArea';
|
||||||
import AnimateFade from '@/components/wrap/AnimateFade';
|
import AnimateFade from '@/components/wrap/AnimateFade';
|
||||||
|
@ -182,7 +184,7 @@ function FormConstituenta({
|
||||||
}
|
}
|
||||||
value={expression}
|
value={expression}
|
||||||
activeCst={state}
|
activeCst={state}
|
||||||
disabled={disabled}
|
disabled={disabled || state?.is_inherited}
|
||||||
toggleReset={toggleReset}
|
toggleReset={toggleReset}
|
||||||
onChange={newValue => setExpression(newValue)}
|
onChange={newValue => setExpression(newValue)}
|
||||||
setTypification={setTypification}
|
setTypification={setTypification}
|
||||||
|
@ -229,15 +231,33 @@ function FormConstituenta({
|
||||||
Добавить комментарий
|
Добавить комментарий
|
||||||
</button>
|
</button>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{!disabled || processing ? (
|
{!disabled || processing ? (
|
||||||
<SubmitButton
|
<div className='self-center flex'>
|
||||||
key='cst_form_submit'
|
<SubmitButton
|
||||||
id='cst_form_submit'
|
key='cst_form_submit'
|
||||||
text='Сохранить изменения'
|
id='cst_form_submit'
|
||||||
className='self-center'
|
text='Сохранить изменения'
|
||||||
disabled={disabled || !isModified}
|
disabled={disabled || !isModified}
|
||||||
icon={<IconSave size='1.25rem' />}
|
icon={<IconSave size='1.25rem' />}
|
||||||
/>
|
/>
|
||||||
|
<Overlay position='top-[0.1rem] left-[0.4rem]' className='cc-icons'>
|
||||||
|
{state?.is_inherited_parent ? (
|
||||||
|
<MiniButton
|
||||||
|
icon={<IconChild size='1.25rem' className='clr-text-red' />}
|
||||||
|
disabled
|
||||||
|
titleHtml='Внимание!</br> Конституента имеет потомков<br/> в операционной схеме синтеза'
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
{state?.is_inherited ? (
|
||||||
|
<MiniButton
|
||||||
|
icon={<IconParent size='1.25rem' className='clr-text-red' />}
|
||||||
|
disabled
|
||||||
|
titleHtml='Внимание!</br> Конституента является наследником<br/>'
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</Overlay>
|
||||||
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IconClone,
|
IconClone,
|
||||||
IconDestroy,
|
IconDestroy,
|
||||||
|
@ -6,95 +8,116 @@ import {
|
||||||
IconMoveDown,
|
IconMoveDown,
|
||||||
IconMoveUp,
|
IconMoveUp,
|
||||||
IconNewItem,
|
IconNewItem,
|
||||||
|
IconPredecessor,
|
||||||
IconReset,
|
IconReset,
|
||||||
IconSave
|
IconSave
|
||||||
} from '@/components/Icons';
|
} from '@/components/Icons';
|
||||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||||
|
import MiniSelectorOSS from '@/components/select/MiniSelectorOSS';
|
||||||
import MiniButton from '@/components/ui/MiniButton';
|
import MiniButton from '@/components/ui/MiniButton';
|
||||||
import Overlay from '@/components/ui/Overlay';
|
import Overlay from '@/components/ui/Overlay';
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
import { IConstituenta } from '@/models/rsform';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
import { prepareTooltip, tooltips } from '@/utils/labels';
|
import { prepareTooltip, tooltips } from '@/utils/labels';
|
||||||
|
|
||||||
|
import { useRSEdit } from '../RSEditContext';
|
||||||
|
|
||||||
interface ToolbarConstituentaProps {
|
interface ToolbarConstituentaProps {
|
||||||
|
activeCst?: IConstituenta;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
modified: boolean;
|
modified: boolean;
|
||||||
showList: boolean;
|
showList: boolean;
|
||||||
|
|
||||||
onSubmit: () => void;
|
onSubmit: () => void;
|
||||||
onReset: () => void;
|
onReset: () => void;
|
||||||
|
|
||||||
onMoveUp: () => void;
|
|
||||||
onMoveDown: () => void;
|
|
||||||
onDelete: () => void;
|
|
||||||
onClone: () => void;
|
|
||||||
onCreate: () => void;
|
|
||||||
onToggleList: () => void;
|
onToggleList: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarConstituenta({
|
function ToolbarConstituenta({
|
||||||
|
activeCst,
|
||||||
disabled,
|
disabled,
|
||||||
modified,
|
modified,
|
||||||
showList,
|
showList,
|
||||||
|
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onReset,
|
onReset,
|
||||||
onMoveUp,
|
|
||||||
onMoveDown,
|
|
||||||
onDelete,
|
|
||||||
onClone,
|
|
||||||
onCreate,
|
|
||||||
onToggleList
|
onToggleList
|
||||||
}: ToolbarConstituentaProps) {
|
}: ToolbarConstituentaProps) {
|
||||||
|
const controller = useRSEdit();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Overlay position='top-1 right-4' className='cc-icons sm:right-1/2 sm:translate-x-1/2'>
|
<Overlay position='top-1 right-4' className='cc-icons sm:right-1/2 sm:translate-x-1/2'>
|
||||||
<MiniButton
|
{controller.schema && controller.schema?.oss.length > 0 ? (
|
||||||
titleHtml={prepareTooltip('Сохранить изменения', 'Ctrl + S')}
|
<MiniSelectorOSS
|
||||||
icon={<IconSave size='1.25rem' className='icon-primary' />}
|
items={controller.schema.oss}
|
||||||
disabled={disabled || !modified}
|
onSelect={(event, value) => controller.viewOSS(value.id, event.ctrlKey || event.metaKey)}
|
||||||
onClick={onSubmit}
|
/>
|
||||||
/>
|
) : null}
|
||||||
<MiniButton
|
{activeCst && activeCst.is_inherited ? (
|
||||||
title='Сбросить несохраненные изменения'
|
<MiniButton
|
||||||
icon={<IconReset size='1.25rem' className='icon-primary' />}
|
title='Перейти к исходной конституенте в ОСС'
|
||||||
disabled={disabled || !modified}
|
onClick={() => controller.viewPredecessor(activeCst.id)}
|
||||||
onClick={onReset}
|
icon={<IconPredecessor size='1.25rem' className='icon-primary' />}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
) : null}
|
||||||
title='Создать конституенту после данной'
|
{controller.isContentEditable ? (
|
||||||
icon={<IconNewItem size={'1.25rem'} className='icon-green' />}
|
<>
|
||||||
disabled={disabled}
|
<MiniButton
|
||||||
onClick={onCreate}
|
titleHtml={prepareTooltip('Сохранить изменения', 'Ctrl + S')}
|
||||||
/>
|
icon={<IconSave size='1.25rem' className='icon-primary' />}
|
||||||
<MiniButton
|
disabled={disabled || !modified}
|
||||||
titleHtml={modified ? tooltips.unsaved : prepareTooltip('Клонировать конституенту', 'Alt + V')}
|
onClick={onSubmit}
|
||||||
icon={<IconClone size='1.25rem' className='icon-green' />}
|
/>
|
||||||
disabled={disabled || modified}
|
<MiniButton
|
||||||
onClick={onClone}
|
title='Сбросить несохраненные изменения'
|
||||||
/>
|
icon={<IconReset size='1.25rem' className='icon-primary' />}
|
||||||
<MiniButton
|
disabled={disabled || !modified}
|
||||||
title='Удалить редактируемую конституенту'
|
onClick={onReset}
|
||||||
disabled={disabled}
|
/>
|
||||||
onClick={onDelete}
|
<MiniButton
|
||||||
icon={<IconDestroy size='1.25rem' className='icon-red' />}
|
title='Создать конституенту после данной'
|
||||||
/>
|
icon={<IconNewItem size={'1.25rem'} className='icon-green' />}
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={() => controller.createCst(activeCst?.cst_type, false)}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
titleHtml={modified ? tooltips.unsaved : prepareTooltip('Клонировать конституенту', 'Alt + V')}
|
||||||
|
icon={<IconClone size='1.25rem' className='icon-green' />}
|
||||||
|
disabled={disabled || modified}
|
||||||
|
onClick={controller.cloneCst}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
title='Удалить редактируемую конституенту'
|
||||||
|
disabled={disabled || !controller.canDeleteSelected}
|
||||||
|
onClick={controller.promptDeleteCst}
|
||||||
|
icon={<IconDestroy size='1.25rem' className='icon-red' />}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Отображение списка конституент'
|
title='Отображение списка конституент'
|
||||||
icon={showList ? <IconList size='1.25rem' className='icon-primary' /> : <IconListOff size='1.25rem' />}
|
icon={showList ? <IconList size='1.25rem' className='icon-primary' /> : <IconListOff size='1.25rem' />}
|
||||||
onClick={onToggleList}
|
onClick={onToggleList}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
|
||||||
titleHtml={prepareTooltip('Переместить вверх', 'Alt + вверх')}
|
{controller.isContentEditable ? (
|
||||||
icon={<IconMoveUp size='1.25rem' className='icon-primary' />}
|
<>
|
||||||
disabled={disabled || modified}
|
<MiniButton
|
||||||
onClick={onMoveUp}
|
titleHtml={prepareTooltip('Переместить вверх', 'Alt + вверх')}
|
||||||
/>
|
icon={<IconMoveUp size='1.25rem' className='icon-primary' />}
|
||||||
<MiniButton
|
disabled={disabled || modified}
|
||||||
titleHtml={prepareTooltip('Переместить вниз', 'Alt + вниз')}
|
onClick={controller.moveUp}
|
||||||
icon={<IconMoveDown size='1.25rem' className='icon-primary' />}
|
/>
|
||||||
disabled={disabled || modified}
|
<MiniButton
|
||||||
onClick={onMoveDown}
|
titleHtml={prepareTooltip('Переместить вниз', 'Alt + вниз')}
|
||||||
/>
|
icon={<IconMoveDown size='1.25rem' className='icon-primary' />}
|
||||||
|
disabled={disabled || modified}
|
||||||
|
onClick={controller.moveDown}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
<BadgeHelp topic={HelpTopic.UI_RS_EDITOR} offset={4} className={PARAMETER.TOOLTIP_WIDTH} />
|
<BadgeHelp topic={HelpTopic.UI_RS_EDITOR} offset={4} className={PARAMETER.TOOLTIP_WIDTH} />
|
||||||
</Overlay>
|
</Overlay>
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { UserID, UserLevel } from '@/models/user';
|
||||||
import { prefixes } from '@/utils/constants';
|
import { prefixes } from '@/utils/constants';
|
||||||
import { prompts } from '@/utils/labels';
|
import { prompts } from '@/utils/labels';
|
||||||
|
|
||||||
import LabeledValue from '../../../components/ui/LabeledValue';
|
import LabeledValue from '@/components/ui/LabeledValue';
|
||||||
|
|
||||||
interface EditorLibraryItemProps {
|
interface EditorLibraryItemProps {
|
||||||
item?: ILibraryItemData;
|
item?: ILibraryItemData;
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useEffect, useLayoutEffect, useState } from 'react';
|
import { useEffect, useLayoutEffect, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
|
||||||
|
|
||||||
import { IconSave } from '@/components/Icons';
|
import { IconSave } from '@/components/Icons';
|
||||||
import SelectVersion from '@/components/select/SelectVersion';
|
import SelectVersion from '@/components/select/SelectVersion';
|
||||||
|
@ -10,10 +9,8 @@ import Label from '@/components/ui/Label';
|
||||||
import SubmitButton from '@/components/ui/SubmitButton';
|
import SubmitButton from '@/components/ui/SubmitButton';
|
||||||
import TextArea from '@/components/ui/TextArea';
|
import TextArea from '@/components/ui/TextArea';
|
||||||
import TextInput from '@/components/ui/TextInput';
|
import TextInput from '@/components/ui/TextInput';
|
||||||
import { useRSForm } from '@/context/RSFormContext';
|
|
||||||
import { ILibraryUpdateData, LibraryItemType } from '@/models/library';
|
import { ILibraryUpdateData, LibraryItemType } from '@/models/library';
|
||||||
import { limits, patterns } from '@/utils/constants';
|
import { limits, patterns } from '@/utils/constants';
|
||||||
import { information } from '@/utils/labels';
|
|
||||||
|
|
||||||
import { useRSEdit } from '../RSEditContext';
|
import { useRSEdit } from '../RSEditContext';
|
||||||
import ToolbarItemAccess from './ToolbarItemAccess';
|
import ToolbarItemAccess from './ToolbarItemAccess';
|
||||||
|
@ -26,8 +23,8 @@ interface FormRSFormProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {
|
function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {
|
||||||
const { schema, update, processing } = useRSForm();
|
|
||||||
const controller = useRSEdit();
|
const controller = useRSEdit();
|
||||||
|
const schema = controller.schema;
|
||||||
|
|
||||||
const [title, setTitle] = useState('');
|
const [title, setTitle] = useState('');
|
||||||
const [alias, setAlias] = useState('');
|
const [alias, setAlias] = useState('');
|
||||||
|
@ -85,7 +82,7 @@ function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {
|
||||||
visible: visible,
|
visible: visible,
|
||||||
read_only: readOnly
|
read_only: readOnly
|
||||||
};
|
};
|
||||||
update(data, () => toast.success(information.changesSaved));
|
controller.updateSchema(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -112,7 +109,7 @@ function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {
|
||||||
onChange={event => setAlias(event.target.value)}
|
onChange={event => setAlias(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<div className='flex flex-col'>
|
<div className='flex flex-col'>
|
||||||
<ToolbarVersioning />
|
<ToolbarVersioning blockReload={schema && schema?.oss.length > 0} />
|
||||||
<ToolbarItemAccess
|
<ToolbarItemAccess
|
||||||
visible={visible}
|
visible={visible}
|
||||||
toggleVisible={() => setVisible(prev => !prev)}
|
toggleVisible={() => setVisible(prev => !prev)}
|
||||||
|
@ -143,7 +140,7 @@ function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
text='Сохранить изменения'
|
text='Сохранить изменения'
|
||||||
className='self-center mt-4'
|
className='self-center mt-4'
|
||||||
loading={processing}
|
loading={controller.isProcessing}
|
||||||
disabled={!isModified}
|
disabled={!isModified}
|
||||||
icon={<IconSave size='1.25rem' />}
|
icon={<IconSave size='1.25rem' />}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -14,13 +14,16 @@ function RSFormStats({ stats }: RSFormStatsProps) {
|
||||||
<div className='flex flex-col sm:gap-1 sm:ml-6 sm:mt-8 sm:w-[16rem]'>
|
<div className='flex flex-col sm:gap-1 sm:ml-6 sm:mt-8 sm:w-[16rem]'>
|
||||||
<Divider margins='my-2' className='sm:hidden' />
|
<Divider margins='my-2' className='sm:hidden' />
|
||||||
|
|
||||||
<LabeledValue id='count_all' label='Всего конституент ' text={stats.count_all} />
|
<LabeledValue id='count_all' label='Всего конституент' text={stats.count_all} />
|
||||||
<LabeledValue id='count_errors' label='Некорректных' text={stats.count_errors} />
|
{stats.count_inherited !== 0 ? (
|
||||||
|
<LabeledValue id='count_inherited' label='Наследованные' text={stats.count_inherited} />
|
||||||
|
) : null}
|
||||||
|
<LabeledValue id='count_errors' label='Некорректные' text={stats.count_errors} />
|
||||||
{stats.count_property !== 0 ? (
|
{stats.count_property !== 0 ? (
|
||||||
<LabeledValue id='count_property' label='Неразмерных' text={stats.count_property} />
|
<LabeledValue id='count_property' label='Неразмерные' text={stats.count_property} />
|
||||||
) : null}
|
) : null}
|
||||||
{stats.count_incalculable !== 0 ? (
|
{stats.count_incalculable !== 0 ? (
|
||||||
<LabeledValue id='count_incalculable' label='Невычислимых' text={stats.count_incalculable} />
|
<LabeledValue id='count_incalculable' label='Невычислимые' text={stats.count_incalculable} />
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<Divider margins='my-2' />
|
<Divider margins='my-2' />
|
||||||
|
|
|
@ -29,7 +29,7 @@ function ToolbarItemAccess({ visible, toggleVisible, readOnly, toggleReadOnly, c
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Overlay position='top-[4.5rem] right-0 w-[12rem] pr-2' className='flex'>
|
<Overlay position='top-[4.5rem] right-0 w-[12rem] pr-2' className='flex' layer='z-bottom'>
|
||||||
<Label text='Доступ' className='self-center select-none' />
|
<Label text='Доступ' className='self-center select-none' />
|
||||||
<div className='ml-auto cc-icons'>
|
<div className='ml-auto cc-icons'>
|
||||||
<SelectAccessPolicy
|
<SelectAccessPolicy
|
||||||
|
|
|
@ -5,15 +5,19 @@ import { useMemo } from 'react';
|
||||||
import { SubscribeIcon } from '@/components/DomainIcons';
|
import { SubscribeIcon } from '@/components/DomainIcons';
|
||||||
import { IconDestroy, IconSave, IconShare } from '@/components/Icons';
|
import { IconDestroy, IconSave, IconShare } from '@/components/Icons';
|
||||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||||
|
import MiniSelectorOSS from '@/components/select/MiniSelectorOSS';
|
||||||
import MiniButton from '@/components/ui/MiniButton';
|
import MiniButton from '@/components/ui/MiniButton';
|
||||||
import Overlay from '@/components/ui/Overlay';
|
import Overlay from '@/components/ui/Overlay';
|
||||||
import { useAccessMode } from '@/context/AccessModeContext';
|
import { useAccessMode } from '@/context/AccessModeContext';
|
||||||
import { AccessPolicy, ILibraryItemEditor } from '@/models/library';
|
import { AccessPolicy, ILibraryItemEditor, LibraryItemType } from '@/models/library';
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
import { IRSForm } from '@/models/rsform';
|
||||||
import { UserLevel } from '@/models/user';
|
import { UserLevel } from '@/models/user';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
import { prepareTooltip, tooltips } from '@/utils/labels';
|
import { prepareTooltip, tooltips } from '@/utils/labels';
|
||||||
|
|
||||||
|
import { IRSEditContext } from '../RSEditContext';
|
||||||
|
|
||||||
interface ToolbarRSFormCardProps {
|
interface ToolbarRSFormCardProps {
|
||||||
modified: boolean;
|
modified: boolean;
|
||||||
subscribed: boolean;
|
subscribed: boolean;
|
||||||
|
@ -33,8 +37,26 @@ function ToolbarRSFormCard({
|
||||||
}: ToolbarRSFormCardProps) {
|
}: ToolbarRSFormCardProps) {
|
||||||
const { accessLevel } = useAccessMode();
|
const { accessLevel } = useAccessMode();
|
||||||
const canSave = useMemo(() => modified && !controller.isProcessing, [modified, controller.isProcessing]);
|
const canSave = useMemo(() => modified && !controller.isProcessing, [modified, controller.isProcessing]);
|
||||||
|
|
||||||
|
const ossSelector = useMemo(() => {
|
||||||
|
if (!controller.schema || controller.schema?.item_type !== LibraryItemType.RSFORM) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const schema = controller.schema as IRSForm;
|
||||||
|
if (schema.oss.length <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<MiniSelectorOSS
|
||||||
|
items={schema.oss}
|
||||||
|
onSelect={(event, value) => (controller as IRSEditContext).viewOSS(value.id, event.ctrlKey || event.metaKey)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}, [controller]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Overlay position='top-1 right-1/2 translate-x-1/2' className='cc-icons'>
|
<Overlay position='top-1 right-1/2 translate-x-1/2' className='cc-icons'>
|
||||||
|
{ossSelector}
|
||||||
{controller.isMutable || modified ? (
|
{controller.isMutable || modified ? (
|
||||||
<MiniButton
|
<MiniButton
|
||||||
titleHtml={prepareTooltip('Сохранить изменения', 'Ctrl + S')}
|
titleHtml={prepareTooltip('Сохранить изменения', 'Ctrl + S')}
|
||||||
|
|
|
@ -7,17 +7,25 @@ import { PARAMETER } from '@/utils/constants';
|
||||||
|
|
||||||
import { useRSEdit } from '../RSEditContext';
|
import { useRSEdit } from '../RSEditContext';
|
||||||
|
|
||||||
function ToolbarVersioning() {
|
interface ToolbarVersioningProps {
|
||||||
|
blockReload?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ToolbarVersioning({ blockReload }: ToolbarVersioningProps) {
|
||||||
const controller = useRSEdit();
|
const controller = useRSEdit();
|
||||||
return (
|
return (
|
||||||
<Overlay position='top-[-0.4rem] right-[0rem]' className='pr-2 cc-icons'>
|
<Overlay position='top-[-0.4rem] right-[0rem]' className='pr-2 cc-icons' layer='z-bottom'>
|
||||||
{controller.isMutable ? (
|
{controller.isMutable ? (
|
||||||
<>
|
<>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
titleHtml={
|
titleHtml={
|
||||||
!controller.isContentEditable ? 'Откатить к версии' : 'Переключитесь на <br/>неактуальную версию'
|
blockReload
|
||||||
|
? 'Невозможно откатить КС, прикрепленную к операционной схеме'
|
||||||
|
: !controller.isContentEditable
|
||||||
|
? 'Откатить к версии'
|
||||||
|
: 'Переключитесь на <br/>неактуальную версию'
|
||||||
}
|
}
|
||||||
disabled={controller.isContentEditable}
|
disabled={controller.isContentEditable || blockReload}
|
||||||
onClick={() => controller.restoreVersion()}
|
onClick={() => controller.restoreVersion()}
|
||||||
icon={<IconUpload size='1.25rem' className='icon-red' />}
|
icon={<IconUpload size='1.25rem' className='icon-red' />}
|
||||||
/>
|
/>
|
||||||
|
@ -30,7 +38,7 @@ function ToolbarVersioning() {
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title={controller.schema?.versions.length === 0 ? 'Список версий пуст' : 'Редактировать версии'}
|
title={controller.schema?.versions.length === 0 ? 'Список версий пуст' : 'Редактировать версии'}
|
||||||
disabled={!controller.schema || controller.schema?.versions.length === 0}
|
disabled={!controller.schema || controller.schema?.versions.length === 0}
|
||||||
onClick={controller.editVersions}
|
onClick={controller.promptEditVersions}
|
||||||
icon={<IconVersions size='1.25rem' className='icon-primary' />}
|
icon={<IconVersions size='1.25rem' className='icon-primary' />}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -59,10 +59,10 @@ function EditorRSList({ onOpenEdit }: EditorRSListProps) {
|
||||||
if (!controller.isContentEditable || controller.isProcessing) {
|
if (!controller.isContentEditable || controller.isProcessing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.key === 'Delete' && controller.selected.length > 0) {
|
if (event.key === 'Delete' && controller.canDeleteSelected) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
controller.deleteCst();
|
controller.promptDeleteCst();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!event.altKey || event.shiftKey) {
|
if (!event.altKey || event.shiftKey) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
IconReset
|
IconReset
|
||||||
} from '@/components/Icons';
|
} from '@/components/Icons';
|
||||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||||
|
import MiniSelectorOSS from '@/components/select/MiniSelectorOSS';
|
||||||
import Dropdown from '@/components/ui/Dropdown';
|
import Dropdown from '@/components/ui/Dropdown';
|
||||||
import DropdownButton from '@/components/ui/DropdownButton';
|
import DropdownButton from '@/components/ui/DropdownButton';
|
||||||
import MiniButton from '@/components/ui/MiniButton';
|
import MiniButton from '@/components/ui/MiniButton';
|
||||||
|
@ -27,6 +28,12 @@ function ToolbarRSList() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Overlay position='top-1 right-1/2 translate-x-1/2' className='items-start cc-icons'>
|
<Overlay position='top-1 right-1/2 translate-x-1/2' className='items-start cc-icons'>
|
||||||
|
{controller.schema && controller.schema?.oss.length > 0 ? (
|
||||||
|
<MiniSelectorOSS
|
||||||
|
items={controller.schema.oss}
|
||||||
|
onSelect={(event, value) => controller.viewOSS(value.id, event.ctrlKey || event.metaKey)}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
<MiniButton
|
<MiniButton
|
||||||
titleHtml={prepareTooltip('Сбросить выделение', 'ESC')}
|
titleHtml={prepareTooltip('Сбросить выделение', 'ESC')}
|
||||||
icon={<IconReset size='1.25rem' className='icon-primary' />}
|
icon={<IconReset size='1.25rem' className='icon-primary' />}
|
||||||
|
@ -79,8 +86,8 @@ function ToolbarRSList() {
|
||||||
<MiniButton
|
<MiniButton
|
||||||
titleHtml={prepareTooltip('Удалить выбранные', 'Delete')}
|
titleHtml={prepareTooltip('Удалить выбранные', 'Delete')}
|
||||||
icon={<IconDestroy size='1.25rem' className='icon-red' />}
|
icon={<IconDestroy size='1.25rem' className='icon-red' />}
|
||||||
disabled={controller.isProcessing || controller.nothingSelected}
|
disabled={controller.isProcessing || !controller.canDeleteSelected}
|
||||||
onClick={controller.deleteCst}
|
onClick={controller.promptDeleteCst}
|
||||||
/>
|
/>
|
||||||
<BadgeHelp topic={HelpTopic.UI_RS_LIST} offset={5} />
|
<BadgeHelp topic={HelpTopic.UI_RS_LIST} offset={5} />
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
|
@ -105,7 +105,7 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
result.push({
|
result.push({
|
||||||
id: String(node.id),
|
id: String(node.id),
|
||||||
fill: focusCst === cst ? colors.bgPurple : colorBgGraphNode(cst, coloring, colors),
|
fill: focusCst === cst ? colors.bgPurple : colorBgGraphNode(cst, coloring, colors),
|
||||||
label: cst.alias,
|
label: `${cst.alias}${cst.is_inherited ? '*' : ''}`,
|
||||||
subLabel: !filterParams.noText ? cst.term_resolved : undefined,
|
subLabel: !filterParams.noText ? cst.term_resolved : undefined,
|
||||||
size: applyNodeSizing(cst, sizing)
|
size: applyNodeSizing(cst, sizing)
|
||||||
});
|
});
|
||||||
|
@ -141,10 +141,10 @@ function EditorTermGraph({ onOpenEdit }: EditorTermGraphProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDeleteCst() {
|
function handleDeleteCst() {
|
||||||
if (!controller.schema || controller.nothingSelected) {
|
if (!controller.schema || !controller.canDeleteSelected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
controller.deleteCst();
|
controller.promptDeleteCst();
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeLayout = useCallback(
|
const handleChangeLayout = useCallback(
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
IconTextOff
|
IconTextOff
|
||||||
} from '@/components/Icons';
|
} from '@/components/Icons';
|
||||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||||
|
import MiniSelectorOSS from '@/components/select/MiniSelectorOSS';
|
||||||
import MiniButton from '@/components/ui/MiniButton';
|
import MiniButton from '@/components/ui/MiniButton';
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
|
@ -55,6 +56,12 @@ function ToolbarTermGraph({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='cc-icons'>
|
<div className='cc-icons'>
|
||||||
|
{controller.schema && controller.schema?.oss.length > 0 ? (
|
||||||
|
<MiniSelectorOSS
|
||||||
|
items={controller.schema.oss}
|
||||||
|
onSelect={(event, value) => controller.viewOSS(value.id, event.ctrlKey || event.metaKey)}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Настройки фильтрации узлов и связей'
|
title='Настройки фильтрации узлов и связей'
|
||||||
icon={<IconFilter size='1.25rem' className='icon-primary' />}
|
icon={<IconFilter size='1.25rem' className='icon-primary' />}
|
||||||
|
@ -105,7 +112,7 @@ function ToolbarTermGraph({
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Удалить выбранные'
|
title='Удалить выбранные'
|
||||||
icon={<IconDestroy size='1.25rem' className='icon-red' />}
|
icon={<IconDestroy size='1.25rem' className='icon-red' />}
|
||||||
disabled={controller.nothingSelected || controller.isProcessing}
|
disabled={!controller.canDeleteSelected || controller.isProcessing}
|
||||||
onClick={onDelete}
|
onClick={onDelete}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -105,12 +105,19 @@ function ViewHidden({ items, selected, toggleSelection, setFocus, schema, colori
|
||||||
className='min-w-[3rem] rounded-md text-center select-none'
|
className='min-w-[3rem] rounded-md text-center select-none'
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: colorBgGraphNode(cst, adjustedColoring, colors),
|
backgroundColor: colorBgGraphNode(cst, adjustedColoring, colors),
|
||||||
...(localSelected.includes(cstID) ? { outlineWidth: '2px', outlineStyle: 'solid' } : {})
|
...(localSelected.includes(cstID)
|
||||||
|
? {
|
||||||
|
outlineWidth: '2px',
|
||||||
|
outlineStyle: cst.is_inherited ? 'dashed' : 'solid',
|
||||||
|
outlineColor: colors.fgDefault
|
||||||
|
}
|
||||||
|
: {})
|
||||||
}}
|
}}
|
||||||
onClick={event => handleClick(cstID, event)}
|
onClick={event => handleClick(cstID, event)}
|
||||||
onDoubleClick={() => onEdit(cstID)}
|
onDoubleClick={() => onEdit(cstID)}
|
||||||
>
|
>
|
||||||
{cst.alias}
|
{cst.alias}
|
||||||
|
{cst.is_inherited ? '*' : ''}
|
||||||
</button>
|
</button>
|
||||||
<TooltipConstituenta data={cst} anchor={`#${id}`} />
|
<TooltipConstituenta data={cst} anchor={`#${id}`} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -163,9 +163,9 @@ function MenuRSTabs({ onDestroy }: MenuRSTabsProps) {
|
||||||
/>
|
/>
|
||||||
{controller.isContentEditable ? (
|
{controller.isContentEditable ? (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Загрузить из Экстеора'
|
text='Загрузить из Экстеор'
|
||||||
icon={<IconUpload size='1rem' className='icon-red' />}
|
icon={<IconUpload size='1rem' className='icon-red' />}
|
||||||
disabled={controller.isProcessing}
|
disabled={controller.isProcessing || controller.schema?.oss.length !== 0}
|
||||||
onClick={handleUpload}
|
onClick={handleUpload}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -24,7 +24,14 @@ import DlgInlineSynthesis from '@/dialogs/DlgInlineSynthesis';
|
||||||
import DlgRenameCst from '@/dialogs/DlgRenameCst';
|
import DlgRenameCst from '@/dialogs/DlgRenameCst';
|
||||||
import DlgSubstituteCst from '@/dialogs/DlgSubstituteCst';
|
import DlgSubstituteCst from '@/dialogs/DlgSubstituteCst';
|
||||||
import DlgUploadRSForm from '@/dialogs/DlgUploadRSForm';
|
import DlgUploadRSForm from '@/dialogs/DlgUploadRSForm';
|
||||||
import { AccessPolicy, IVersionData, LocationHead, VersionID } from '@/models/library';
|
import {
|
||||||
|
AccessPolicy,
|
||||||
|
ILibraryUpdateData,
|
||||||
|
IVersionData,
|
||||||
|
LibraryItemID,
|
||||||
|
LocationHead,
|
||||||
|
VersionID
|
||||||
|
} from '@/models/library';
|
||||||
import { ICstSubstituteData } from '@/models/oss';
|
import { ICstSubstituteData } from '@/models/oss';
|
||||||
import {
|
import {
|
||||||
ConstituentaID,
|
ConstituentaID,
|
||||||
|
@ -46,6 +53,8 @@ import { EXTEOR_TRS_FILE } from '@/utils/constants';
|
||||||
import { information, prompts } from '@/utils/labels';
|
import { information, prompts } from '@/utils/labels';
|
||||||
import { promptUnsaved } from '@/utils/utils';
|
import { promptUnsaved } from '@/utils/utils';
|
||||||
|
|
||||||
|
import { RSTabID } from './RSTabs';
|
||||||
|
|
||||||
export interface IRSEditContext {
|
export interface IRSEditContext {
|
||||||
schema?: IRSForm;
|
schema?: IRSForm;
|
||||||
selected: ConstituentaID[];
|
selected: ConstituentaID[];
|
||||||
|
@ -55,6 +64,9 @@ export interface IRSEditContext {
|
||||||
isProcessing: boolean;
|
isProcessing: boolean;
|
||||||
canProduceStructure: boolean;
|
canProduceStructure: boolean;
|
||||||
nothingSelected: boolean;
|
nothingSelected: boolean;
|
||||||
|
canDeleteSelected: boolean;
|
||||||
|
|
||||||
|
updateSchema: (data: ILibraryUpdateData) => void;
|
||||||
|
|
||||||
setOwner: (newOwner: UserID) => void;
|
setOwner: (newOwner: UserID) => void;
|
||||||
setAccessPolicy: (newPolicy: AccessPolicy) => void;
|
setAccessPolicy: (newPolicy: AccessPolicy) => void;
|
||||||
|
@ -68,17 +80,19 @@ export interface IRSEditContext {
|
||||||
toggleSelect: (target: ConstituentaID) => void;
|
toggleSelect: (target: ConstituentaID) => void;
|
||||||
deselectAll: () => void;
|
deselectAll: () => void;
|
||||||
|
|
||||||
|
viewOSS: (target: LibraryItemID, newTab?: boolean) => void;
|
||||||
viewVersion: (version?: VersionID, newTab?: boolean) => void;
|
viewVersion: (version?: VersionID, newTab?: boolean) => void;
|
||||||
|
viewPredecessor: (target: ConstituentaID) => void;
|
||||||
createVersion: () => void;
|
createVersion: () => void;
|
||||||
restoreVersion: () => void;
|
restoreVersion: () => void;
|
||||||
editVersions: () => void;
|
promptEditVersions: () => void;
|
||||||
|
|
||||||
moveUp: () => void;
|
moveUp: () => void;
|
||||||
moveDown: () => void;
|
moveDown: () => void;
|
||||||
createCst: (type: CstType | undefined, skipDialog: boolean, definition?: string) => void;
|
createCst: (type: CstType | undefined, skipDialog: boolean, definition?: string) => void;
|
||||||
renameCst: () => void;
|
renameCst: () => void;
|
||||||
cloneCst: () => void;
|
cloneCst: () => void;
|
||||||
deleteCst: () => void;
|
promptDeleteCst: () => void;
|
||||||
editTermForms: () => void;
|
editTermForms: () => void;
|
||||||
|
|
||||||
promptTemplate: () => void;
|
promptTemplate: () => void;
|
||||||
|
@ -135,6 +149,10 @@ export const RSEditState = ({
|
||||||
);
|
);
|
||||||
const isContentEditable = useMemo(() => isMutable && !model.isArchive, [isMutable, model.isArchive]);
|
const isContentEditable = useMemo(() => isMutable && !model.isArchive, [isMutable, model.isArchive]);
|
||||||
const nothingSelected = useMemo(() => selected.length === 0, [selected]);
|
const nothingSelected = useMemo(() => selected.length === 0, [selected]);
|
||||||
|
const canDeleteSelected = useMemo(
|
||||||
|
() => !nothingSelected && selected.every(id => !model.schema?.cstByID.get(id)?.is_inherited),
|
||||||
|
[selected, nothingSelected, model.schema]
|
||||||
|
);
|
||||||
|
|
||||||
const [showUpload, setShowUpload] = useState(false);
|
const [showUpload, setShowUpload] = useState(false);
|
||||||
const [showClone, setShowClone] = useState(false);
|
const [showClone, setShowClone] = useState(false);
|
||||||
|
@ -177,11 +195,35 @@ export const RSEditState = ({
|
||||||
[model.schema, setAccessLevel, model.isOwned, user, adminMode]
|
[model.schema, setAccessLevel, model.isOwned, user, adminMode]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const updateSchema = useCallback(
|
||||||
|
(data: ILibraryUpdateData) => model.update(data, () => toast.success(information.changesSaved)),
|
||||||
|
[model]
|
||||||
|
);
|
||||||
|
|
||||||
const viewVersion = useCallback(
|
const viewVersion = useCallback(
|
||||||
(version?: VersionID, newTab?: boolean) => router.push(urls.schema(model.itemID, version), newTab),
|
(version?: VersionID, newTab?: boolean) => router.push(urls.schema(model.itemID, version), newTab),
|
||||||
[router, model]
|
[router, model]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const viewPredecessor = useCallback(
|
||||||
|
(target: ConstituentaID) =>
|
||||||
|
model.findPredecessor({ target: target }, reference =>
|
||||||
|
router.push(
|
||||||
|
urls.schema_props({
|
||||||
|
id: reference.schema,
|
||||||
|
active: reference.id,
|
||||||
|
tab: RSTabID.CST_EDIT
|
||||||
|
})
|
||||||
|
)
|
||||||
|
),
|
||||||
|
[router, model]
|
||||||
|
);
|
||||||
|
|
||||||
|
const viewOSS = useCallback(
|
||||||
|
(target: LibraryItemID, newTab?: boolean) => router.push(urls.oss(target), newTab),
|
||||||
|
[router]
|
||||||
|
);
|
||||||
|
|
||||||
const createVersion = useCallback(() => {
|
const createVersion = useCallback(() => {
|
||||||
if (isModified && !promptUnsaved()) {
|
if (isModified && !promptUnsaved()) {
|
||||||
return;
|
return;
|
||||||
|
@ -571,12 +613,14 @@ export const RSEditState = ({
|
||||||
<RSEditContext.Provider
|
<RSEditContext.Provider
|
||||||
value={{
|
value={{
|
||||||
schema: model.schema,
|
schema: model.schema,
|
||||||
|
updateSchema,
|
||||||
selected,
|
selected,
|
||||||
isMutable,
|
isMutable,
|
||||||
isContentEditable,
|
isContentEditable,
|
||||||
isProcessing: model.processing,
|
isProcessing: model.processing,
|
||||||
canProduceStructure,
|
canProduceStructure,
|
||||||
nothingSelected,
|
nothingSelected,
|
||||||
|
canDeleteSelected,
|
||||||
|
|
||||||
toggleSubscribe,
|
toggleSubscribe,
|
||||||
setOwner,
|
setOwner,
|
||||||
|
@ -591,17 +635,19 @@ export const RSEditState = ({
|
||||||
setSelected(prev => (prev.includes(target) ? prev.filter(id => id !== target) : [...prev, target])),
|
setSelected(prev => (prev.includes(target) ? prev.filter(id => id !== target) : [...prev, target])),
|
||||||
deselectAll: () => setSelected([]),
|
deselectAll: () => setSelected([]),
|
||||||
|
|
||||||
|
viewOSS,
|
||||||
viewVersion,
|
viewVersion,
|
||||||
|
viewPredecessor,
|
||||||
createVersion,
|
createVersion,
|
||||||
restoreVersion,
|
restoreVersion,
|
||||||
editVersions: () => setShowEditVersions(true),
|
promptEditVersions: () => setShowEditVersions(true),
|
||||||
|
|
||||||
moveUp,
|
moveUp,
|
||||||
moveDown,
|
moveDown,
|
||||||
createCst,
|
createCst,
|
||||||
cloneCst,
|
cloneCst,
|
||||||
renameCst,
|
renameCst,
|
||||||
deleteCst: () => setShowDeleteCst(true),
|
promptDeleteCst: () => setShowDeleteCst(true),
|
||||||
editTermForms,
|
editTermForms,
|
||||||
|
|
||||||
promptTemplate,
|
promptTemplate,
|
||||||
|
|
|
@ -62,7 +62,7 @@ function ConstituentsSearch({ schema, activeID, activeExpression, dense, setFilt
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex border-b clr-input overflow-hidden'>
|
<div className='flex border-b clr-input'>
|
||||||
<SearchBar
|
<SearchBar
|
||||||
id='constituents_search'
|
id='constituents_search'
|
||||||
noBorder
|
noBorder
|
||||||
|
|
|
@ -15,6 +15,8 @@ export const PARAMETER = {
|
||||||
ossImageWidth: 1280, // pixels - size of OSS image
|
ossImageWidth: 1280, // pixels - size of OSS image
|
||||||
ossImageHeight: 960, // pixels - size of OSS image
|
ossImageHeight: 960, // pixels - size of OSS image
|
||||||
ossContextMenuWidth: 200, // pixels - width of OSS context menu
|
ossContextMenuWidth: 200, // pixels - width of OSS context menu
|
||||||
|
ossGridSize: 10, // pixels - size of OSS grid
|
||||||
|
ossMinDistance: 20, // pixels - minimum distance between node centers
|
||||||
|
|
||||||
graphHoverXLimit: 0.4, // ratio to clientWidth used to determine which side of screen popup should be
|
graphHoverXLimit: 0.4, // ratio to clientWidth used to determine which side of screen popup should be
|
||||||
graphHoverYLimit: 0.6, // ratio to clientHeight used to determine which side of screen popup should be
|
graphHoverYLimit: 0.6, // ratio to clientHeight used to determine which side of screen popup should be
|
||||||
|
@ -139,6 +141,7 @@ export const globals = {
|
||||||
*/
|
*/
|
||||||
export const prefixes = {
|
export const prefixes = {
|
||||||
page_size: 'page_size_',
|
page_size: 'page_size_',
|
||||||
|
oss_list: 'oss_list_',
|
||||||
cst_list: 'cst_list_',
|
cst_list: 'cst_list_',
|
||||||
cst_inline_synth_list: 'cst_inline_synth_list_',
|
cst_inline_synth_list: 'cst_inline_synth_list_',
|
||||||
cst_inline_synth_substitutes: 'cst_inline_synth_substitutes_',
|
cst_inline_synth_substitutes: 'cst_inline_synth_substitutes_',
|
||||||
|
|
|
@ -952,7 +952,8 @@ export const errors = {
|
||||||
astFailed: 'Невозможно построить дерево разбора',
|
astFailed: 'Невозможно построить дерево разбора',
|
||||||
passwordsMismatch: 'Пароли не совпадают',
|
passwordsMismatch: 'Пароли не совпадают',
|
||||||
imageFailed: 'Ошибка при создании изображения',
|
imageFailed: 'Ошибка при создании изображения',
|
||||||
reuseOriginal: 'Повторное использование удаляемой конституенты при отождествлении'
|
reuseOriginal: 'Повторное использование удаляемой конституенты при отождествлении',
|
||||||
|
substituteInherited: 'Нельзя удалять наследованные конституенты при отождествлении'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue
Block a user