mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
UI fixes and synthesis table unification
This commit is contained in:
parent
54da2f4871
commit
102f8c2baf
|
@ -1,12 +1,12 @@
|
||||||
''' Utility: Graph implementation. '''
|
''' Utility: Graph implementation. '''
|
||||||
from typing import Dict, Iterable, Optional, cast
|
from typing import Iterable, Optional, cast
|
||||||
|
|
||||||
|
|
||||||
class Graph:
|
class Graph:
|
||||||
''' Directed graph. '''
|
''' Directed graph. '''
|
||||||
def __init__(self, graph: Optional[Dict[str, list[str]]]=None):
|
def __init__(self, graph: Optional[dict[str, list[str]]]=None):
|
||||||
if graph is None:
|
if graph is None:
|
||||||
self._graph = cast(Dict[str, list[str]], {})
|
self._graph = cast(dict[str, list[str]], {})
|
||||||
else:
|
else:
|
||||||
self._graph = graph
|
self._graph = graph
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ def renameTrivial(name: str):
|
||||||
def substituteTrivial(name: str):
|
def substituteTrivial(name: str):
|
||||||
return f'Отождествление конституенты с собой не корректно: {name}'
|
return f'Отождествление конституенты с собой не корректно: {name}'
|
||||||
|
|
||||||
|
def substituteDouble(name: str):
|
||||||
|
return f'Повторное отождествление: {name}'
|
||||||
|
|
||||||
def aliasTaken(name: str):
|
def aliasTaken(name: str):
|
||||||
return f'Имя уже используется: {name}'
|
return f'Имя уже используется: {name}'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
''' Models: RSForm API. '''
|
''' Models: RSForm API. '''
|
||||||
from typing import Dict, Iterable, Optional, Union, cast
|
from typing import Iterable, Optional, Union, cast
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
|
@ -53,6 +53,7 @@ class RSForm:
|
||||||
''' Trigger cascade resolutions when term changes. '''
|
''' Trigger cascade resolutions when term changes. '''
|
||||||
graph_terms = self._term_graph()
|
graph_terms = self._term_graph()
|
||||||
expansion = graph_terms.expand_outputs(changed)
|
expansion = graph_terms.expand_outputs(changed)
|
||||||
|
expanded_change = list(changed) + expansion
|
||||||
resolver = self.resolver()
|
resolver = self.resolver()
|
||||||
if len(expansion) > 0:
|
if len(expansion) > 0:
|
||||||
for alias in graph_terms.topological_order():
|
for alias in graph_terms.topological_order():
|
||||||
|
@ -67,7 +68,7 @@ class RSForm:
|
||||||
resolver.context[cst.alias] = Entity(cst.alias, resolved)
|
resolver.context[cst.alias] = Entity(cst.alias, resolved)
|
||||||
|
|
||||||
graph_defs = self._definition_graph()
|
graph_defs = self._definition_graph()
|
||||||
update_defs = set(expansion + graph_defs.expand_outputs(expansion + changed)).union(changed)
|
update_defs = set(expansion + graph_defs.expand_outputs(expanded_change)).union(changed)
|
||||||
if len(update_defs) == 0:
|
if len(update_defs) == 0:
|
||||||
return
|
return
|
||||||
for alias in update_defs:
|
for alias in update_defs:
|
||||||
|
@ -126,11 +127,11 @@ class RSForm:
|
||||||
position = self._get_insert_position(position)
|
position = self._get_insert_position(position)
|
||||||
self._shift_positions(position, count)
|
self._shift_positions(position, count)
|
||||||
|
|
||||||
indices: Dict[str, int] = {}
|
indices: dict[str, int] = {}
|
||||||
for (value, _) in CstType.choices:
|
for (value, _) in CstType.choices:
|
||||||
indices[value] = self.get_max_index(cast(CstType, value))
|
indices[value] = self.get_max_index(cast(CstType, value))
|
||||||
|
|
||||||
mapping: Dict[str, str] = {}
|
mapping: dict[str, str] = {}
|
||||||
for cst in items:
|
for cst in items:
|
||||||
indices[cst.cst_type] = indices[cst.cst_type] + 1
|
indices[cst.cst_type] = indices[cst.cst_type] + 1
|
||||||
newAlias = f'{get_type_prefix(cst.cst_type)}{indices[cst.cst_type]}'
|
newAlias = f'{get_type_prefix(cst.cst_type)}{indices[cst.cst_type]}'
|
||||||
|
|
|
@ -194,34 +194,6 @@ class RSFormParseSerializer(serializers.ModelSerializer):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
class CstSubstituteSerializerBase(serializers.Serializer):
|
|
||||||
''' Serializer: Basic substitution. '''
|
|
||||||
original = PKField(many=False, queryset=Constituenta.objects.all())
|
|
||||||
substitution = PKField(many=False, queryset=Constituenta.objects.all())
|
|
||||||
transfer_term = serializers.BooleanField(required=False, default=False)
|
|
||||||
|
|
||||||
|
|
||||||
class CstSubstituteSerializer(CstSubstituteSerializerBase):
|
|
||||||
''' Serializer: Constituenta substitution. '''
|
|
||||||
def validate(self, attrs):
|
|
||||||
schema = cast(LibraryItem, self.context['schema'])
|
|
||||||
original_cst = cast(Constituenta, attrs['original'])
|
|
||||||
substitution_cst = cast(Constituenta, attrs['substitution'])
|
|
||||||
if original_cst.alias == substitution_cst.alias:
|
|
||||||
raise serializers.ValidationError({
|
|
||||||
'alias': msg.substituteTrivial(original_cst.alias)
|
|
||||||
})
|
|
||||||
if original_cst.schema != schema:
|
|
||||||
raise serializers.ValidationError({
|
|
||||||
'original': msg.constituentaNotOwned(schema.title)
|
|
||||||
})
|
|
||||||
if substitution_cst.schema != schema:
|
|
||||||
raise serializers.ValidationError({
|
|
||||||
'substitution': msg.constituentaNotOwned(schema.title)
|
|
||||||
})
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
|
|
||||||
class CstTargetSerializer(serializers.Serializer):
|
class CstTargetSerializer(serializers.Serializer):
|
||||||
''' Serializer: Target single Constituenta. '''
|
''' Serializer: Target single Constituenta. '''
|
||||||
target = PKField(many=False, queryset=Constituenta.objects.all())
|
target = PKField(many=False, queryset=Constituenta.objects.all())
|
||||||
|
@ -289,6 +261,46 @@ class CstMoveSerializer(CstListSerializer):
|
||||||
move_to = serializers.IntegerField()
|
move_to = serializers.IntegerField()
|
||||||
|
|
||||||
|
|
||||||
|
class CstSubstituteSerializerBase(serializers.Serializer):
|
||||||
|
''' Serializer: Basic substitution. '''
|
||||||
|
original = PKField(many=False, queryset=Constituenta.objects.all())
|
||||||
|
substitution = PKField(many=False, queryset=Constituenta.objects.all())
|
||||||
|
transfer_term = serializers.BooleanField(required=False, default=False)
|
||||||
|
|
||||||
|
|
||||||
|
class CstSubstituteSerializer(serializers.Serializer):
|
||||||
|
''' Serializer: Constituenta substitution. '''
|
||||||
|
substitutions = serializers.ListField(
|
||||||
|
child=CstSubstituteSerializerBase(),
|
||||||
|
min_length=1
|
||||||
|
)
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
schema = cast(LibraryItem, self.context['schema'])
|
||||||
|
deleted = set()
|
||||||
|
for item in attrs['substitutions']:
|
||||||
|
original_cst = cast(Constituenta, item['original'])
|
||||||
|
substitution_cst = cast(Constituenta, item['substitution'])
|
||||||
|
if original_cst.pk in deleted:
|
||||||
|
raise serializers.ValidationError({
|
||||||
|
f'{original_cst.id}': msg.substituteDouble(original_cst.alias)
|
||||||
|
})
|
||||||
|
if original_cst.alias == substitution_cst.alias:
|
||||||
|
raise serializers.ValidationError({
|
||||||
|
'alias': msg.substituteTrivial(original_cst.alias)
|
||||||
|
})
|
||||||
|
if original_cst.schema != schema:
|
||||||
|
raise serializers.ValidationError({
|
||||||
|
'original': msg.constituentaNotOwned(schema.title)
|
||||||
|
})
|
||||||
|
if substitution_cst.schema != schema:
|
||||||
|
raise serializers.ValidationError({
|
||||||
|
'substitution': msg.constituentaNotOwned(schema.title)
|
||||||
|
})
|
||||||
|
deleted.add(original_cst.pk)
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class InlineSynthesisSerializer(serializers.Serializer):
|
class InlineSynthesisSerializer(serializers.Serializer):
|
||||||
''' Serializer: Inline synthesis operation input. '''
|
''' Serializer: Inline synthesis operation input. '''
|
||||||
receiver = PKField(many=False, queryset=LibraryItem.objects.all())
|
receiver = PKField(many=False, queryset=LibraryItem.objects.all())
|
||||||
|
@ -313,6 +325,7 @@ class InlineSynthesisSerializer(serializers.Serializer):
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{cst.id}': msg.constituentaNotOwned(schema_in.title)
|
f'{cst.id}': msg.constituentaNotOwned(schema_in.title)
|
||||||
})
|
})
|
||||||
|
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'])
|
||||||
|
@ -334,4 +347,9 @@ class InlineSynthesisSerializer(serializers.Serializer):
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
f'{original_cst.id}': msg.constituentaNotOwned(schema_out.title)
|
f'{original_cst.id}': msg.constituentaNotOwned(schema_out.title)
|
||||||
})
|
})
|
||||||
|
if original_cst.pk in deleted:
|
||||||
|
raise serializers.ValidationError({
|
||||||
|
f'{original_cst.id}': msg.substituteDouble(original_cst.alias)
|
||||||
|
})
|
||||||
|
deleted.add(original_cst.pk)
|
||||||
return attrs
|
return attrs
|
||||||
|
|
|
@ -260,7 +260,7 @@ class TestRSFormViewset(EndpointTester):
|
||||||
|
|
||||||
|
|
||||||
@decl_endpoint('/api/rsforms/{item}/cst-substitute', method='patch')
|
@decl_endpoint('/api/rsforms/{item}/cst-substitute', method='patch')
|
||||||
def test_substitute_constituenta(self):
|
def test_substitute_single(self):
|
||||||
x1 = self.schema.insert_new(
|
x1 = self.schema.insert_new(
|
||||||
alias='X1',
|
alias='X1',
|
||||||
term_raw='Test1',
|
term_raw='Test1',
|
||||||
|
@ -273,14 +273,14 @@ class TestRSFormViewset(EndpointTester):
|
||||||
)
|
)
|
||||||
unowned = self.unowned.insert_new('X2')
|
unowned = self.unowned.insert_new('X2')
|
||||||
|
|
||||||
data = {'original': x1.pk, 'substitution': unowned.pk, 'transfer_term': True}
|
data = {'substitutions': [{'original': x1.pk, 'substitution': unowned.pk, 'transfer_term': True}]}
|
||||||
self.assertForbidden(data, item=self.unowned_id)
|
self.assertForbidden(data, item=self.unowned_id)
|
||||||
self.assertBadData(data, item=self.schema_id)
|
self.assertBadData(data, item=self.schema_id)
|
||||||
|
|
||||||
data = {'original': unowned.pk, 'substitution': x1.pk, 'transfer_term': True}
|
data = {'substitutions': [{'original': unowned.pk, 'substitution': x1.pk, 'transfer_term': True}]}
|
||||||
self.assertBadData(data, item=self.schema_id)
|
self.assertBadData(data, item=self.schema_id)
|
||||||
|
|
||||||
data = {'original': x1.pk, 'substitution': x1.pk, 'transfer_term': True}
|
data = {'substitutions': [{'original': x1.pk, 'substitution': x1.pk, 'transfer_term': True}]}
|
||||||
self.assertBadData(data, item=self.schema_id)
|
self.assertBadData(data, item=self.schema_id)
|
||||||
|
|
||||||
d1 = self.schema.insert_new(
|
d1 = self.schema.insert_new(
|
||||||
|
@ -288,7 +288,7 @@ class TestRSFormViewset(EndpointTester):
|
||||||
term_raw='@{X2|sing,datv}',
|
term_raw='@{X2|sing,datv}',
|
||||||
definition_formal='X1'
|
definition_formal='X1'
|
||||||
)
|
)
|
||||||
data = {'original': x1.pk, 'substitution': x2.pk, 'transfer_term': True}
|
data = {'substitutions': [{'original': x1.pk, 'substitution': x2.pk, 'transfer_term': True}]}
|
||||||
response = self.execute(data, item=self.schema_id)
|
response = self.execute(data, item=self.schema_id)
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
|
||||||
|
@ -298,6 +298,53 @@ class TestRSFormViewset(EndpointTester):
|
||||||
self.assertEqual(d1.term_resolved, 'form1')
|
self.assertEqual(d1.term_resolved, 'form1')
|
||||||
self.assertEqual(d1.definition_formal, 'X2')
|
self.assertEqual(d1.definition_formal, 'X2')
|
||||||
|
|
||||||
|
@decl_endpoint('/api/rsforms/{item}/cst-substitute', method='patch')
|
||||||
|
def test_substitute_multiple(self):
|
||||||
|
self.set_params(item=self.schema_id)
|
||||||
|
x1 = self.schema.insert_new('X1')
|
||||||
|
x2 = self.schema.insert_new('X2')
|
||||||
|
d1 = self.schema.insert_new('D1')
|
||||||
|
d2 = self.schema.insert_new('D2')
|
||||||
|
d3 = self.schema.insert_new(
|
||||||
|
alias='D3',
|
||||||
|
definition_formal='X1 \ X2'
|
||||||
|
)
|
||||||
|
|
||||||
|
data = {'substitutions': []}
|
||||||
|
self.assertBadData(data)
|
||||||
|
|
||||||
|
data = {'substitutions': [
|
||||||
|
{
|
||||||
|
'original': x1.pk,
|
||||||
|
'substitution': d1.pk,
|
||||||
|
'transfer_term': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'original': x1.pk,
|
||||||
|
'substitution': d2.pk,
|
||||||
|
'transfer_term': True
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
self.assertBadData(data)
|
||||||
|
|
||||||
|
data = {'substitutions': [
|
||||||
|
{
|
||||||
|
'original': x1.pk,
|
||||||
|
'substitution': d1.pk,
|
||||||
|
'transfer_term': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'original': x2.pk,
|
||||||
|
'substitution': d2.pk,
|
||||||
|
'transfer_term': True
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
response = self.execute(data, item=self.schema_id)
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
|
||||||
|
d3.refresh_from_db()
|
||||||
|
self.assertEqual(d3.definition_formal, 'D1 \ D2')
|
||||||
|
|
||||||
|
|
||||||
@decl_endpoint('/api/rsforms/{item}/cst-create', method='post')
|
@decl_endpoint('/api/rsforms/{item}/cst-create', method='post')
|
||||||
def test_create_constituenta_data(self):
|
def test_create_constituenta_data(self):
|
||||||
|
|
|
@ -147,11 +147,10 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
||||||
context={'schema': schema.item}
|
context={'schema': schema.item}
|
||||||
)
|
)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
schema.substitute(
|
for substitution in serializer.validated_data['substitutions']:
|
||||||
original=serializer.validated_data['original'],
|
original = cast(m.Constituenta, substitution['original'])
|
||||||
substitution=serializer.validated_data['substitution'],
|
replacement = cast(m.Constituenta, substitution['substitution'])
|
||||||
transfer_term=serializer.validated_data['transfer_term']
|
schema.substitute(original, replacement, substitution['transfer_term'])
|
||||||
)
|
|
||||||
schema.item.refresh_from_db()
|
schema.item.refresh_from_db()
|
||||||
return Response(
|
return Response(
|
||||||
status=c.HTTP_200_OK,
|
status=c.HTTP_200_OK,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
''' Term context for reference resolution. '''
|
''' Term context for reference resolution. '''
|
||||||
from typing import Iterable, Dict, Optional, TypedDict
|
from typing import Iterable, Optional, TypedDict
|
||||||
|
|
||||||
from .ruparser import PhraseParser
|
from .ruparser import PhraseParser
|
||||||
from .rumodel import WordTag
|
from .rumodel import WordTag
|
||||||
|
@ -81,4 +81,4 @@ class Entity:
|
||||||
|
|
||||||
|
|
||||||
# Represents term context for resolving entity references.
|
# Represents term context for resolving entity references.
|
||||||
TermContext = Dict[str, Entity]
|
TermContext = dict[str, Entity]
|
||||||
|
|
|
@ -2,7 +2,7 @@ function HelpRSTemplates() {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Банк выражений</h1>
|
<h1>Шаблоны</h1>
|
||||||
<p>Портал предоставляет быстрый доступ к часто используемым выражениям с помощью функции создания конституенты из шаблона</p>
|
<p>Портал предоставляет быстрый доступ к часто используемым выражениям с помощью функции создания конституенты из шаблона</p>
|
||||||
<p>Источником шаблонов является <b>Банк выражений</b>, содержащий параметризованные понятия и утверждения, сгруппированные по разделам</p>
|
<p>Источником шаблонов является <b>Банк выражений</b>, содержащий параметризованные понятия и утверждения, сгруппированные по разделам</p>
|
||||||
<p>Сначала выбирается шаблон выражения (вкладка Шаблон)</p>
|
<p>Сначала выбирается шаблон выражения (вкладка Шаблон)</p>
|
||||||
|
|
|
@ -100,15 +100,15 @@ function ConstituentaMultiPicker({ id, schema, prefixID, rows, selected, setSele
|
||||||
</span>
|
</span>
|
||||||
<div className='flex w-full gap-6 text-sm'>
|
<div className='flex w-full gap-6 text-sm'>
|
||||||
<Button
|
<Button
|
||||||
text='Поставщики'
|
text='Влияющие'
|
||||||
title='Добавить все конституенты, от которых зависят выбранные'
|
title='Добавить все конституенты, от которых зависят выбранные'
|
||||||
className='w-[7rem]'
|
className='w-[7rem] text-sm'
|
||||||
onClick={selectBasis}
|
onClick={selectBasis}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
text='Потребители'
|
text='Зависимые'
|
||||||
title='Добавить все конституенты, которые зависят от выбранных'
|
title='Добавить все конституенты, которые зависят от выбранных'
|
||||||
className='w-[7rem]'
|
className='w-[7rem] text-sm'
|
||||||
onClick={selectDependant}
|
onClick={selectDependant}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -154,11 +154,11 @@ function SubstitutionsPicker({
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col'>
|
<div className='flex flex-col w-full'>
|
||||||
<div className='flex items-end gap-3 justify-stretch'>
|
<div className='flex items-end gap-3 justify-stretch'>
|
||||||
<div className='flex-grow basis-1/2'>
|
<div className='flex-grow basis-1/2'>
|
||||||
<div className='flex items-center justify-between'>
|
<div className='flex items-center justify-between'>
|
||||||
<Label text={schema1?.alias ?? 'Схема 1'} />
|
<Label text={schema1 !== schema2 ? schema1?.alias ?? 'Схема 1' : ''} />
|
||||||
<div>
|
<div>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Сохранить конституенту'
|
title='Сохранить конституенту'
|
||||||
|
@ -204,7 +204,7 @@ function SubstitutionsPicker({
|
||||||
|
|
||||||
<div className='flex-grow basis-1/2'>
|
<div className='flex-grow basis-1/2'>
|
||||||
<div className='flex items-center justify-between'>
|
<div className='flex items-center justify-between'>
|
||||||
<Label text={schema2?.alias ?? 'Схема 2'} />
|
<Label text={schema1 !== schema2 ? schema2?.alias ?? 'Схема 2' : ''} />
|
||||||
<div>
|
<div>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Сохранить конституенту'
|
title='Сохранить конституенту'
|
||||||
|
@ -242,8 +242,9 @@ function SubstitutionsPicker({
|
||||||
|
|
||||||
<DataTable
|
<DataTable
|
||||||
dense
|
dense
|
||||||
|
noHeader
|
||||||
noFooter
|
noFooter
|
||||||
className='overflow-y-auto border select-none'
|
className='w-full overflow-y-auto text-sm border select-none'
|
||||||
rows={rows}
|
rows={rows}
|
||||||
contentHeight='1.3rem'
|
contentHeight='1.3rem'
|
||||||
data={items}
|
data={items}
|
||||||
|
|
|
@ -7,11 +7,13 @@ import { CProps } from '../props';
|
||||||
interface MiniButtonProps extends CProps.Button {
|
interface MiniButtonProps extends CProps.Button {
|
||||||
icon: React.ReactNode;
|
icon: React.ReactNode;
|
||||||
noHover?: boolean;
|
noHover?: boolean;
|
||||||
|
noPadding?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MiniButton({
|
function MiniButton({
|
||||||
icon,
|
icon,
|
||||||
noHover,
|
noHover,
|
||||||
|
noPadding,
|
||||||
tabIndex,
|
tabIndex,
|
||||||
title,
|
title,
|
||||||
titleHtml,
|
titleHtml,
|
||||||
|
@ -24,11 +26,11 @@ function MiniButton({
|
||||||
type='button'
|
type='button'
|
||||||
tabIndex={tabIndex ?? -1}
|
tabIndex={tabIndex ?? -1}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'px-1 py-1',
|
|
||||||
'rounded-full',
|
'rounded-full',
|
||||||
'clr-btn-clear',
|
'clr-btn-clear',
|
||||||
'cursor-pointer disabled:cursor-not-allowed',
|
'cursor-pointer disabled:cursor-not-allowed',
|
||||||
{
|
{
|
||||||
|
'px-1 py-1': !noPadding,
|
||||||
'outline-none': noHover,
|
'outline-none': noHover,
|
||||||
'clr-hover': !noHover
|
'clr-hover': !noHover
|
||||||
},
|
},
|
||||||
|
|
|
@ -71,8 +71,9 @@ function Modal({
|
||||||
exit={{ ...animateModal.exit }}
|
exit={{ ...animateModal.exit }}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
<Overlay position='right-[0.3rem] top-2'>
|
<Overlay position='right-2 top-2'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
|
noPadding
|
||||||
titleHtml={prepareTooltip('Закрыть диалоговое окно', 'ESC')}
|
titleHtml={prepareTooltip('Закрыть диалоговое окно', 'ESC')}
|
||||||
icon={<BiX size='1.25rem' />}
|
icon={<BiX size='1.25rem' />}
|
||||||
onClick={handleCancel}
|
onClick={handleCancel}
|
||||||
|
|
|
@ -34,7 +34,7 @@ import {
|
||||||
patchProduceStructure,
|
patchProduceStructure,
|
||||||
patchRenameConstituenta,
|
patchRenameConstituenta,
|
||||||
patchResetAliases,
|
patchResetAliases,
|
||||||
patchSubstituteConstituenta,
|
patchSubstituteConstituents,
|
||||||
patchUploadTRS,
|
patchUploadTRS,
|
||||||
patchVersion,
|
patchVersion,
|
||||||
postClaimLibraryItem,
|
postClaimLibraryItem,
|
||||||
|
@ -374,7 +374,7 @@ export const RSFormState = ({ schemaID, versionID, children }: RSFormStateProps)
|
||||||
const cstSubstitute = useCallback(
|
const cstSubstitute = useCallback(
|
||||||
(data: ICstSubstituteData, callback?: () => void) => {
|
(data: ICstSubstituteData, callback?: () => void) => {
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
patchSubstituteConstituenta(schemaID, {
|
patchSubstituteConstituents(schemaID, {
|
||||||
data: data,
|
data: data,
|
||||||
showError: true,
|
showError: true,
|
||||||
setLoading: setProcessing,
|
setLoading: setProcessing,
|
||||||
|
|
|
@ -35,10 +35,6 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
||||||
|
|
||||||
const [argumentValue, setArgumentValue] = useState('');
|
const [argumentValue, setArgumentValue] = useState('');
|
||||||
|
|
||||||
const selectedClearable = useMemo(() => {
|
|
||||||
return argumentValue && !!selectedArgument && !!selectedArgument.value;
|
|
||||||
}, [argumentValue, selectedArgument]);
|
|
||||||
|
|
||||||
const isModified = useMemo(
|
const isModified = useMemo(
|
||||||
() => selectedArgument && argumentValue !== selectedArgument.value,
|
() => selectedArgument && argumentValue !== selectedArgument.value,
|
||||||
[selectedArgument, argumentValue]
|
[selectedArgument, argumentValue]
|
||||||
|
@ -92,7 +88,6 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
||||||
() => [
|
() => [
|
||||||
argumentsHelper.accessor('alias', {
|
argumentsHelper.accessor('alias', {
|
||||||
id: 'alias',
|
id: 'alias',
|
||||||
header: 'Имя',
|
|
||||||
size: 40,
|
size: 40,
|
||||||
minSize: 40,
|
minSize: 40,
|
||||||
maxSize: 40,
|
maxSize: 40,
|
||||||
|
@ -100,14 +95,12 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
||||||
}),
|
}),
|
||||||
argumentsHelper.accessor(arg => arg.value || 'свободный аргумент', {
|
argumentsHelper.accessor(arg => arg.value || 'свободный аргумент', {
|
||||||
id: 'value',
|
id: 'value',
|
||||||
header: 'Значение',
|
|
||||||
size: 200,
|
size: 200,
|
||||||
minSize: 200,
|
minSize: 200,
|
||||||
maxSize: 200
|
maxSize: 200
|
||||||
}),
|
}),
|
||||||
argumentsHelper.accessor(arg => arg.typification, {
|
argumentsHelper.accessor(arg => arg.typification, {
|
||||||
id: 'type',
|
id: 'type',
|
||||||
header: 'Типизация',
|
|
||||||
enableHiding: true,
|
enableHiding: true,
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<div
|
<div
|
||||||
|
@ -122,16 +115,14 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
||||||
}),
|
}),
|
||||||
argumentsHelper.display({
|
argumentsHelper.display({
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
size: 50,
|
|
||||||
minSize: 50,
|
|
||||||
maxSize: 50,
|
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<div className='max-h-[1.2rem]'>
|
<div className='h-[1.25rem] w-[1.25rem]'>
|
||||||
{props.row.original.value ? (
|
{props.row.original.value ? (
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Очистить значение'
|
title='Очистить значение'
|
||||||
icon={<BiX size='0.75rem' className='icon-red' />}
|
noPadding
|
||||||
noHover
|
noHover
|
||||||
|
icon={<BiX size='1.25rem' className='icon-red' />}
|
||||||
onClick={() => handleClearArgument(props.row.original)}
|
onClick={() => handleClearArgument(props.row.original)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -157,6 +148,7 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
||||||
<DataTable
|
<DataTable
|
||||||
dense
|
dense
|
||||||
noFooter
|
noFooter
|
||||||
|
noHeader
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'max-h-[5.8rem] min-h-[5.8rem]', // prettier: split lines
|
'max-h-[5.8rem] min-h-[5.8rem]', // prettier: split lines
|
||||||
'overflow-y-auto',
|
'overflow-y-auto',
|
||||||
|
@ -194,21 +186,19 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
||||||
<div className='flex'>
|
<div className='flex'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Подставить значение аргумента'
|
title='Подставить значение аргумента'
|
||||||
icon={<BiCheck size='1.25rem' className='icon-green' />}
|
noHover
|
||||||
|
className='py-0'
|
||||||
|
icon={<BiCheck size='2rem' className='icon-green' />}
|
||||||
disabled={!argumentValue || !selectedArgument}
|
disabled={!argumentValue || !selectedArgument}
|
||||||
onClick={() => handleAssignArgument(selectedArgument!, argumentValue)}
|
onClick={() => handleAssignArgument(selectedArgument!, argumentValue)}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Откатить значение'
|
title='Очистить поле'
|
||||||
|
noHover
|
||||||
|
className='py-0'
|
||||||
disabled={!isModified}
|
disabled={!isModified}
|
||||||
onClick={handleReset}
|
onClick={handleReset}
|
||||||
icon={<BiRefresh size='1.25rem' className='icon-primary' />}
|
icon={<BiRefresh size='2rem' className='icon-primary' />}
|
||||||
/>
|
|
||||||
<MiniButton
|
|
||||||
title='Очистить значение аргумента'
|
|
||||||
disabled={!selectedClearable}
|
|
||||||
icon={<BiX size='1.25rem' className='icon-red' />}
|
|
||||||
onClick={() => (selectedArgument ? handleClearArgument(selectedArgument) : undefined)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -114,7 +114,7 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }:
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
<Overlay position='top-0 right-[6rem]'>
|
<Overlay position='top-0 right-[6rem]'>
|
||||||
<HelpButton topic={HelpTopic.RSTEMPLATES} className='max-w-[35rem]' />
|
<HelpButton topic={HelpTopic.RSTEMPLATES} className='max-w-[40rem]' offset={12} />
|
||||||
</Overlay>
|
</Overlay>
|
||||||
<Tabs
|
<Tabs
|
||||||
forceRenderTabPanel
|
forceRenderTabPanel
|
||||||
|
|
|
@ -60,13 +60,16 @@ function VersionsTable({ processing, items, onDelete, selected, onSelect }: Vers
|
||||||
minSize: 50,
|
minSize: 50,
|
||||||
maxSize: 50,
|
maxSize: 50,
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<MiniButton
|
<div className='h-[1.25rem] w-[1.25rem]'>
|
||||||
noHover
|
<MiniButton
|
||||||
title='Удалить версию'
|
title='Удалить версию'
|
||||||
disabled={processing}
|
noHover
|
||||||
icon={<BiX size='1rem' className='icon-red' />}
|
noPadding
|
||||||
onClick={() => onDelete(props.row.original.id)}
|
disabled={processing}
|
||||||
/>
|
icon={<BiX size='1.25rem' className='icon-red' />}
|
||||||
|
onClick={() => onDelete(props.row.original.id)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
|
|
@ -129,7 +129,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className='flex flex-col w-[40rem] px-6'
|
className='flex flex-col w-[40rem] px-6'
|
||||||
>
|
>
|
||||||
<Overlay position='top-[-0.2rem] left-[7.5rem]'>
|
<Overlay position='top-[-0.2rem] left-[8rem]'>
|
||||||
<HelpButton topic={HelpTopic.TERM_CONTROL} className='max-w-[38rem]' offset={3} />
|
<HelpButton topic={HelpTopic.TERM_CONTROL} className='max-w-[38rem]' offset={3} />
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
|
@ -182,14 +182,14 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
|
||||||
<MiniButton
|
<MiniButton
|
||||||
noHover
|
noHover
|
||||||
title='Внести словоформу'
|
title='Внести словоформу'
|
||||||
icon={<BiCheck size='1.25rem' className='icon-green' />}
|
icon={<BiCheck size='1.5rem' className='icon-green' />}
|
||||||
disabled={textProcessor.loading || !inputText || inputGrams.length == 0}
|
disabled={textProcessor.loading || !inputText || inputGrams.length == 0}
|
||||||
onClick={handleAddForm}
|
onClick={handleAddForm}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
noHover
|
noHover
|
||||||
title='Генерировать стандартные словоформы'
|
title='Генерировать стандартные словоформы'
|
||||||
icon={<BiChevronsDown size='1.25rem' className='icon-primary' />}
|
icon={<BiChevronsDown size='1.5rem' className='icon-primary' />}
|
||||||
disabled={textProcessor.loading || !inputText}
|
disabled={textProcessor.loading || !inputText}
|
||||||
onClick={handleGenerateLexeme}
|
onClick={handleGenerateLexeme}
|
||||||
/>
|
/>
|
||||||
|
@ -200,7 +200,8 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
|
||||||
<MiniButton
|
<MiniButton
|
||||||
noHover
|
noHover
|
||||||
title='Сбросить все словоформы'
|
title='Сбросить все словоформы'
|
||||||
icon={<BiX size='1rem' className='icon-red' />}
|
className='py-0'
|
||||||
|
icon={<BiX size='1.5rem' className='icon-red' />}
|
||||||
disabled={textProcessor.loading || forms.length === 0}
|
disabled={textProcessor.loading || forms.length === 0}
|
||||||
onClick={handleResetAll}
|
onClick={handleResetAll}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -39,16 +39,14 @@ function WordFormsTable({ forms, setForms, onFormSelect }: WordFormsTableProps)
|
||||||
id: 'text',
|
id: 'text',
|
||||||
header: 'Текст',
|
header: 'Текст',
|
||||||
size: 350,
|
size: 350,
|
||||||
minSize: 350,
|
minSize: 500,
|
||||||
maxSize: 350,
|
maxSize: 500,
|
||||||
cell: props => <div className='min-w-[20rem]'>{props.getValue()}</div>
|
cell: props => <div className='min-w-[20rem]'>{props.getValue()}</div>
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor('grams', {
|
columnHelper.accessor('grams', {
|
||||||
id: 'grams',
|
id: 'grams',
|
||||||
header: 'Граммемы',
|
header: 'Граммемы',
|
||||||
size: 250,
|
maxSize: 150,
|
||||||
minSize: 250,
|
|
||||||
maxSize: 250,
|
|
||||||
cell: props => <WordFormBadge keyPrefix={props.cell.id} form={props.row.original} />
|
cell: props => <WordFormBadge keyPrefix={props.cell.id} form={props.row.original} />
|
||||||
}),
|
}),
|
||||||
columnHelper.display({
|
columnHelper.display({
|
||||||
|
@ -57,12 +55,15 @@ function WordFormsTable({ forms, setForms, onFormSelect }: WordFormsTableProps)
|
||||||
minSize: 50,
|
minSize: 50,
|
||||||
maxSize: 50,
|
maxSize: 50,
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<MiniButton
|
<div className='h-[1.25rem] w-[1.25rem]'>
|
||||||
noHover
|
<MiniButton
|
||||||
title='Удалить словоформу'
|
noHover
|
||||||
icon={<BiX size='1rem' className='icon-red' />}
|
noPadding
|
||||||
onClick={() => handleDeleteRow(props.row.index)}
|
title='Удалить словоформу'
|
||||||
/>
|
icon={<BiX size='1.25rem' className='icon-red' />}
|
||||||
|
onClick={() => handleDeleteRow(props.row.index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
@ -73,7 +74,7 @@ function WordFormsTable({ forms, setForms, onFormSelect }: WordFormsTableProps)
|
||||||
<DataTable
|
<DataTable
|
||||||
dense
|
dense
|
||||||
noFooter
|
noFooter
|
||||||
className={clsx('mb-2', 'max-h-[17.4rem] min-h-[17.4rem]', 'border', 'overflow-y-auto')}
|
className={clsx('mb-2', 'max-h-[17.4rem] min-h-[17.4rem]', 'border', 'text-sm', 'overflow-y-auto')}
|
||||||
data={forms}
|
data={forms}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
headPosition='0'
|
headPosition='0'
|
||||||
|
|
|
@ -2,15 +2,12 @@
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { LuReplace } from 'react-icons/lu';
|
|
||||||
|
|
||||||
import ConstituentaSelector from '@/components/select/ConstituentaSelector';
|
import SubstitutionsPicker from '@/components/select/SubstitutionsPicker';
|
||||||
import Checkbox from '@/components/ui/Checkbox';
|
|
||||||
import FlexColumn from '@/components/ui/FlexColumn';
|
|
||||||
import Label from '@/components/ui/Label';
|
|
||||||
import Modal, { ModalProps } from '@/components/ui/Modal';
|
import Modal, { ModalProps } from '@/components/ui/Modal';
|
||||||
import { useRSForm } from '@/context/RSFormContext';
|
import { useRSForm } from '@/context/RSFormContext';
|
||||||
import { IConstituenta, ICstSubstituteData } from '@/models/rsform';
|
import { ICstSubstituteData, ISubstitution } from '@/models/rsform';
|
||||||
|
import { prefixes } from '@/utils/constants';
|
||||||
|
|
||||||
interface DlgSubstituteCstProps extends Pick<ModalProps, 'hideWindow'> {
|
interface DlgSubstituteCstProps extends Pick<ModalProps, 'hideWindow'> {
|
||||||
onSubstitute: (data: ICstSubstituteData) => void;
|
onSubstitute: (data: ICstSubstituteData) => void;
|
||||||
|
@ -19,59 +16,38 @@ interface DlgSubstituteCstProps extends Pick<ModalProps, 'hideWindow'> {
|
||||||
function DlgSubstituteCst({ hideWindow, onSubstitute }: DlgSubstituteCstProps) {
|
function DlgSubstituteCst({ hideWindow, onSubstitute }: DlgSubstituteCstProps) {
|
||||||
const { schema } = useRSForm();
|
const { schema } = useRSForm();
|
||||||
|
|
||||||
const [original, setOriginal] = useState<IConstituenta | undefined>(undefined);
|
const [substitutions, setSubstitutions] = useState<ISubstitution[]>([]);
|
||||||
const [substitution, setSubstitution] = useState<IConstituenta | undefined>(undefined);
|
|
||||||
const [transferTerm, setTransferTerm] = useState(false);
|
|
||||||
|
|
||||||
const canSubmit = useMemo(() => {
|
const canSubmit = useMemo(() => substitutions.length > 0, [substitutions]);
|
||||||
return !!original && !!substitution && substitution.id !== original.id;
|
|
||||||
}, [original, substitution]);
|
|
||||||
|
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
const data: ICstSubstituteData = {
|
const data: ICstSubstituteData = {
|
||||||
original: original!.id,
|
substitutions: substitutions.map(item => ({
|
||||||
substitution: substitution!.id,
|
original: item.deleteRight ? item.rightCst.id : item.leftCst.id,
|
||||||
transfer_term: transferTerm
|
substitution: item.deleteRight ? item.leftCst.id : item.rightCst.id,
|
||||||
|
transfer_term: !item.deleteRight && item.takeLeftTerm
|
||||||
|
}))
|
||||||
};
|
};
|
||||||
onSubstitute(data);
|
onSubstitute(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
header='Отождествление конституенты'
|
header='Отождествление'
|
||||||
submitText='Отождествить'
|
submitText='Отождествить'
|
||||||
submitInvalidTooltip={'Выберите две различные конституенты'}
|
submitInvalidTooltip={'Выберите две различные конституенты'}
|
||||||
hideWindow={hideWindow}
|
hideWindow={hideWindow}
|
||||||
canSubmit={canSubmit}
|
canSubmit={canSubmit}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className={clsx('w-[25rem]', 'px-6 py-3 flex flex-col gap-3 justify-center items-center')}
|
className={clsx('w-[40rem]', 'px-6 pb-3')}
|
||||||
>
|
>
|
||||||
<FlexColumn>
|
<SubstitutionsPicker
|
||||||
<Label text='Удаляемая конституента' />
|
items={substitutions}
|
||||||
<ConstituentaSelector
|
setItems={setSubstitutions}
|
||||||
className='w-[20rem]'
|
rows={6}
|
||||||
items={schema?.items}
|
prefixID={prefixes.dlg_cst_substitutes_list}
|
||||||
value={original}
|
schema1={schema}
|
||||||
onSelectValue={setOriginal}
|
schema2={schema}
|
||||||
/>
|
|
||||||
</FlexColumn>
|
|
||||||
|
|
||||||
<LuReplace size='3rem' className='icon-primary' />
|
|
||||||
|
|
||||||
<FlexColumn>
|
|
||||||
<Label text='Подставляемая конституента' />
|
|
||||||
<ConstituentaSelector
|
|
||||||
className='w-[20rem]'
|
|
||||||
items={schema?.items}
|
|
||||||
value={substitution}
|
|
||||||
onSelectValue={setSubstitution}
|
|
||||||
/>
|
|
||||||
</FlexColumn>
|
|
||||||
<Checkbox
|
|
||||||
className='mt-3'
|
|
||||||
label='Сохранить термин удаляемой конституенты'
|
|
||||||
value={transferTerm}
|
|
||||||
setValue={setTransferTerm}
|
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|
|
@ -148,14 +148,21 @@ export interface ICstUpdateData
|
||||||
export interface ICstRenameData extends ICstTarget, Pick<IConstituentaMeta, 'alias' | 'cst_type'> {}
|
export interface ICstRenameData extends ICstTarget, Pick<IConstituentaMeta, 'alias' | 'cst_type'> {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents data, used in merging {@link IConstituenta}.
|
* Represents data, used in merging single {@link IConstituenta}.
|
||||||
*/
|
*/
|
||||||
export interface ICstSubstituteData {
|
export interface ICstSubstitute {
|
||||||
original: ConstituentaID;
|
original: ConstituentaID;
|
||||||
substitution: ConstituentaID;
|
substitution: ConstituentaID;
|
||||||
transfer_term: boolean;
|
transfer_term: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents data, used in merging multiple {@link IConstituenta}.
|
||||||
|
*/
|
||||||
|
export interface ICstSubstituteData {
|
||||||
|
substitutions: ICstSubstitute[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents single substitution for synthesis table.
|
* Represents single substitution for synthesis table.
|
||||||
*/
|
*/
|
||||||
|
@ -251,5 +258,5 @@ export interface IInlineSynthesisData {
|
||||||
receiver: LibraryItemID;
|
receiver: LibraryItemID;
|
||||||
source: LibraryItemID;
|
source: LibraryItemID;
|
||||||
items: ConstituentaID[];
|
items: ConstituentaID[];
|
||||||
substitutions: ICstSubstituteData[];
|
substitutions: ICstSubstitute[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,7 +209,7 @@ function RSTabsMenu({ onDestroy }: RSTabsMenuProps) {
|
||||||
<Dropdown isOpen={editMenu.isOpen}>
|
<Dropdown isOpen={editMenu.isOpen}>
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
disabled={!controller.isContentEditable}
|
disabled={!controller.isContentEditable}
|
||||||
text='Банк выражений'
|
text='Шаблоны'
|
||||||
title='Создать конституенту из шаблона'
|
title='Создать конституенту из шаблона'
|
||||||
icon={<BiDiamond size='1rem' className='icon-green' />}
|
icon={<BiDiamond size='1rem' className='icon-green' />}
|
||||||
onClick={handleTemplates}
|
onClick={handleTemplates}
|
||||||
|
|
|
@ -334,9 +334,9 @@ export function patchProduceStructure(schema: string, request: FrontExchange<ICs
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function patchSubstituteConstituenta(schema: string, request: FrontExchange<ICstSubstituteData, IRSFormData>) {
|
export function patchSubstituteConstituents(schema: string, request: FrontExchange<ICstSubstituteData, IRSFormData>) {
|
||||||
AxiosPatch({
|
AxiosPatch({
|
||||||
title: `Substitution for constituenta id=${request.data.original} for schema id=${schema}`,
|
title: `Substitution for constituents schema id=${schema}`,
|
||||||
endpoint: `/api/rsforms/${schema}/cst-substitute`,
|
endpoint: `/api/rsforms/${schema}/cst-substitute`,
|
||||||
request: request
|
request: request
|
||||||
});
|
});
|
||||||
|
|
|
@ -133,5 +133,6 @@ export const prefixes = {
|
||||||
topic_list: 'topic_list_',
|
topic_list: 'topic_list_',
|
||||||
library_list: 'library_list_',
|
library_list: 'library_list_',
|
||||||
wordform_list: 'wordform_list_',
|
wordform_list: 'wordform_list_',
|
||||||
rsedit_btn: 'rsedit_btn_'
|
rsedit_btn: 'rsedit_btn_',
|
||||||
|
dlg_cst_substitutes_list: 'dlg_cst_substitutes_list_'
|
||||||
};
|
};
|
||||||
|
|
|
@ -345,11 +345,11 @@ export function labelHelpTopic(topic: HelpTopic): string {
|
||||||
switch (topic) {
|
switch (topic) {
|
||||||
case HelpTopic.MAIN: return 'Портал';
|
case HelpTopic.MAIN: return 'Портал';
|
||||||
case HelpTopic.LIBRARY: return 'Библиотека';
|
case HelpTopic.LIBRARY: return 'Библиотека';
|
||||||
case HelpTopic.RSFORM: return '- паспорт схемы';
|
case HelpTopic.RSFORM: return '- карточка схемы';
|
||||||
case HelpTopic.CSTLIST: return '- список конституент';
|
case HelpTopic.CSTLIST: return '- список конституент';
|
||||||
case HelpTopic.CONSTITUENTA: return '- конституента';
|
case HelpTopic.CONSTITUENTA: return '- конституента';
|
||||||
case HelpTopic.GRAPH_TERM: return '- граф термов';
|
case HelpTopic.GRAPH_TERM: return '- граф термов';
|
||||||
case HelpTopic.RSTEMPLATES: return '- Банк выражений';
|
case HelpTopic.RSTEMPLATES: return '- шаблоны выражений';
|
||||||
case HelpTopic.RSLANG: return 'Экспликация';
|
case HelpTopic.RSLANG: return 'Экспликация';
|
||||||
case HelpTopic.TERM_CONTROL: return 'Терминологизация';
|
case HelpTopic.TERM_CONTROL: return 'Терминологизация';
|
||||||
case HelpTopic.VERSIONS: return 'Версионирование';
|
case HelpTopic.VERSIONS: return 'Версионирование';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user