mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-08-14 04:40:36 +03:00
F: Implementing Nominal cst_type
This commit is contained in:
parent
876a98ea8c
commit
c63144e78b
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -216,6 +216,8 @@
|
||||||
"неинтерпретируемый",
|
"неинтерпретируемый",
|
||||||
"неитерируемого",
|
"неитерируемого",
|
||||||
"Никанорова",
|
"Никанорова",
|
||||||
|
"Номеноид",
|
||||||
|
"Номеноиды",
|
||||||
"операционализации",
|
"операционализации",
|
||||||
"операционализированных",
|
"операционализированных",
|
||||||
"Оргтеор",
|
"Оргтеор",
|
||||||
|
|
|
@ -27,7 +27,7 @@ class AssociationSerializer(StrictModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
''' serializer metadata. '''
|
''' serializer metadata. '''
|
||||||
model = Association
|
model = Association
|
||||||
fields = ('argument', 'operation')
|
fields = ('container', 'associate')
|
||||||
|
|
||||||
|
|
||||||
class CstBaseSerializer(StrictModelSerializer):
|
class CstBaseSerializer(StrictModelSerializer):
|
||||||
|
@ -121,11 +121,6 @@ class CstCreateSerializer(StrictModelSerializer):
|
||||||
)
|
)
|
||||||
alias = serializers.CharField(max_length=8)
|
alias = serializers.CharField(max_length=8)
|
||||||
cst_type = serializers.ChoiceField(CstType.choices)
|
cst_type = serializers.ChoiceField(CstType.choices)
|
||||||
associations = PKField(
|
|
||||||
many=True,
|
|
||||||
required=False,
|
|
||||||
queryset=Constituenta.objects.all().only('schema_id', 'pk')
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
''' serializer metadata. '''
|
''' serializer metadata. '''
|
||||||
|
@ -133,7 +128,7 @@ class CstCreateSerializer(StrictModelSerializer):
|
||||||
fields = \
|
fields = \
|
||||||
'alias', 'cst_type', 'convention', 'crucial', \
|
'alias', 'cst_type', 'convention', 'crucial', \
|
||||||
'term_raw', 'definition_raw', 'definition_formal', \
|
'term_raw', 'definition_raw', 'definition_formal', \
|
||||||
'insert_after', 'term_forms', 'associations'
|
'insert_after', 'term_forms'
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
schema = cast(LibraryItem, self.context['schema'])
|
schema = cast(LibraryItem, self.context['schema'])
|
||||||
|
@ -142,12 +137,6 @@ class CstCreateSerializer(StrictModelSerializer):
|
||||||
raise serializers.ValidationError({
|
raise serializers.ValidationError({
|
||||||
'insert_after': msg.constituentaNotInRSform(schema.title)
|
'insert_after': msg.constituentaNotInRSform(schema.title)
|
||||||
})
|
})
|
||||||
associations = attrs.get('associations', [])
|
|
||||||
for assoc in associations:
|
|
||||||
if assoc.schema_id != schema.pk:
|
|
||||||
raise serializers.ValidationError({
|
|
||||||
'associations': msg.constituentaNotInRSform(schema.title)
|
|
||||||
})
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
|
@ -322,6 +311,8 @@ class RSFormParseSerializer(StrictModelSerializer):
|
||||||
def _parse_data(self, data: dict) -> dict:
|
def _parse_data(self, data: dict) -> dict:
|
||||||
parse = PyConceptAdapter(data).parse()
|
parse = PyConceptAdapter(data).parse()
|
||||||
for cst_data in data['items']:
|
for cst_data in data['items']:
|
||||||
|
if cst_data['cst_type'] == CstType.NOMINAL:
|
||||||
|
continue
|
||||||
cst_data['parse'] = next(
|
cst_data['parse'] = next(
|
||||||
cst['parse'] for cst in parse['items']
|
cst['parse'] for cst in parse['items']
|
||||||
if cst['id'] == cst_data['id']
|
if cst['id'] == cst_data['id']
|
||||||
|
|
|
@ -6,7 +6,7 @@ import pyconcept
|
||||||
|
|
||||||
from shared import messages as msg
|
from shared import messages as msg
|
||||||
|
|
||||||
from ..models import Constituenta
|
from ..models import Constituenta, CstType
|
||||||
|
|
||||||
|
|
||||||
class PyConceptAdapter:
|
class PyConceptAdapter:
|
||||||
|
@ -34,7 +34,7 @@ class PyConceptAdapter:
|
||||||
result: dict = {
|
result: dict = {
|
||||||
'items': []
|
'items': []
|
||||||
}
|
}
|
||||||
items = Constituenta.objects.filter(schema_id=schemaID).order_by('order')
|
items = Constituenta.objects.filter(schema_id=schemaID).exclude(cst_type=CstType.NOMINAL).order_by('order')
|
||||||
for cst in items:
|
for cst in items:
|
||||||
result['items'].append({
|
result['items'].append({
|
||||||
'entityUID': cst.pk,
|
'entityUID': cst.pk,
|
||||||
|
@ -51,6 +51,8 @@ class PyConceptAdapter:
|
||||||
'items': []
|
'items': []
|
||||||
}
|
}
|
||||||
for cst in data['items']:
|
for cst in data['items']:
|
||||||
|
if cst['cst_type'] == CstType.NOMINAL:
|
||||||
|
continue
|
||||||
result['items'].append({
|
result['items'].append({
|
||||||
'entityUID': cst['id'],
|
'entityUID': cst['id'],
|
||||||
'cstType': cst['cst_type'],
|
'cstType': cst['cst_type'],
|
||||||
|
|
|
@ -12,7 +12,7 @@ class TestConstituentaAPI(EndpointTester):
|
||||||
self.owned_id = self.owned.model.pk
|
self.owned_id = self.owned.model.pk
|
||||||
self.unowned = RSForm.create(title='Test2', alias='T2')
|
self.unowned = RSForm.create(title='Test2', alias='T2')
|
||||||
self.unowned_id = self.unowned.model.pk
|
self.unowned_id = self.unowned.model.pk
|
||||||
self.cst1 = Constituenta.objects.create(
|
self.x1 = Constituenta.objects.create(
|
||||||
alias='X1',
|
alias='X1',
|
||||||
cst_type=CstType.BASE,
|
cst_type=CstType.BASE,
|
||||||
schema=self.owned.model,
|
schema=self.owned.model,
|
||||||
|
@ -21,119 +21,175 @@ class TestConstituentaAPI(EndpointTester):
|
||||||
term_raw='Test1',
|
term_raw='Test1',
|
||||||
term_resolved='Test1R',
|
term_resolved='Test1R',
|
||||||
term_forms=[{'text': 'form1', 'tags': 'sing,datv'}])
|
term_forms=[{'text': 'form1', 'tags': 'sing,datv'}])
|
||||||
self.cst2 = Constituenta.objects.create(
|
self.x2 = Constituenta.objects.create(
|
||||||
alias='X2',
|
alias='X2',
|
||||||
cst_type=CstType.BASE,
|
cst_type=CstType.BASE,
|
||||||
schema=self.unowned.model,
|
schema=self.owned.model,
|
||||||
order=0,
|
order=1,
|
||||||
convention='Test1',
|
convention='Test1',
|
||||||
term_raw='Test2',
|
term_raw='Test2',
|
||||||
term_resolved='Test2R'
|
term_resolved='Test2R'
|
||||||
)
|
)
|
||||||
self.cst3 = Constituenta.objects.create(
|
self.x3 = Constituenta.objects.create(
|
||||||
alias='X3',
|
alias='X3',
|
||||||
schema=self.owned.model,
|
schema=self.owned.model,
|
||||||
order=1,
|
order=2,
|
||||||
term_raw='Test3',
|
term_raw='Test3',
|
||||||
term_resolved='Test3',
|
term_resolved='Test3',
|
||||||
definition_raw='Test1',
|
definition_raw='Test1',
|
||||||
definition_resolved='Test2'
|
definition_resolved='Test2'
|
||||||
)
|
)
|
||||||
self.invalid_cst = self.cst3.pk + 1337
|
self.unowned_cst = self.unowned.insert_last(alias='X1', cst_type=CstType.BASE)
|
||||||
|
self.invalid_cst = self.x3.pk + 1337
|
||||||
|
|
||||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
@decl_endpoint('/api/rsforms/{item}/update-cst', method='patch')
|
||||||
def test_partial_update(self):
|
def test_partial_update(self):
|
||||||
data = {'target': self.cst1.pk, 'item_data': {'convention': 'tt'}}
|
data = {'target': self.x1.pk, 'item_data': {'convention': 'tt'}}
|
||||||
self.executeForbidden(data, schema=self.unowned_id)
|
self.executeForbidden(data, item=self.unowned_id)
|
||||||
|
|
||||||
self.logout()
|
self.logout()
|
||||||
self.executeForbidden(data, schema=self.owned_id)
|
self.executeForbidden(data, item=self.owned_id)
|
||||||
|
|
||||||
self.login()
|
self.login()
|
||||||
self.executeOK(data)
|
self.executeOK(data)
|
||||||
self.cst1.refresh_from_db()
|
self.x1.refresh_from_db()
|
||||||
self.assertEqual(self.cst1.convention, 'tt')
|
self.assertEqual(self.x1.convention, 'tt')
|
||||||
|
|
||||||
self.executeOK(data)
|
self.executeOK(data)
|
||||||
|
|
||||||
|
|
||||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
@decl_endpoint('/api/rsforms/{item}/update-cst', method='patch')
|
||||||
def test_partial_update_rename(self):
|
def test_partial_update_rename(self):
|
||||||
data = {'target': self.cst1.pk, 'item_data': {'alias': self.cst3.alias}}
|
data = {'target': self.x1.pk, 'item_data': {'alias': self.x3.alias}}
|
||||||
self.executeBadData(data, schema=self.owned_id)
|
self.executeBadData(data, item=self.owned_id)
|
||||||
|
|
||||||
d1 = self.owned.insert_last(
|
d1 = self.owned.insert_last(
|
||||||
alias='D1',
|
alias='D1',
|
||||||
term_raw='@{X1|plur}',
|
term_raw='@{X1|plur}',
|
||||||
definition_formal='X1'
|
definition_formal='X1'
|
||||||
)
|
)
|
||||||
self.assertEqual(self.cst1.order, 0)
|
self.assertEqual(self.x1.order, 0)
|
||||||
self.assertEqual(self.cst1.alias, 'X1')
|
self.assertEqual(self.x1.alias, 'X1')
|
||||||
self.assertEqual(self.cst1.cst_type, CstType.BASE)
|
self.assertEqual(self.x1.cst_type, CstType.BASE)
|
||||||
|
|
||||||
data = {'target': self.cst1.pk, 'item_data': {'alias': 'D2', 'cst_type': CstType.TERM}}
|
data = {'target': self.x1.pk, 'item_data': {'alias': 'D2', 'cst_type': CstType.TERM}}
|
||||||
self.executeOK(data, schema=self.owned_id)
|
self.executeOK(data, item=self.owned_id)
|
||||||
d1.refresh_from_db()
|
d1.refresh_from_db()
|
||||||
self.cst1.refresh_from_db()
|
self.x1.refresh_from_db()
|
||||||
self.assertEqual(d1.term_resolved, '')
|
self.assertEqual(d1.term_resolved, '')
|
||||||
self.assertEqual(d1.term_raw, '@{D2|plur}')
|
self.assertEqual(d1.term_raw, '@{D2|plur}')
|
||||||
self.assertEqual(self.cst1.order, 0)
|
self.assertEqual(self.x1.order, 0)
|
||||||
self.assertEqual(self.cst1.alias, 'D2')
|
self.assertEqual(self.x1.alias, 'D2')
|
||||||
self.assertEqual(self.cst1.cst_type, CstType.TERM)
|
self.assertEqual(self.x1.cst_type, CstType.TERM)
|
||||||
|
|
||||||
|
|
||||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
@decl_endpoint('/api/rsforms/{item}/update-cst', method='patch')
|
||||||
def test_update_resolved_no_refs(self):
|
def test_update_resolved_no_refs(self):
|
||||||
data = {
|
data = {
|
||||||
'target': self.cst3.pk,
|
'target': self.x3.pk,
|
||||||
'item_data': {
|
'item_data': {
|
||||||
'term_raw': 'New term',
|
'term_raw': 'New term',
|
||||||
'definition_raw': 'New def'
|
'definition_raw': 'New def'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.executeOK(data, schema=self.owned_id)
|
self.executeOK(data, item=self.owned_id)
|
||||||
self.cst3.refresh_from_db()
|
self.x3.refresh_from_db()
|
||||||
self.assertEqual(self.cst3.term_resolved, 'New term')
|
self.assertEqual(self.x3.term_resolved, 'New term')
|
||||||
self.assertEqual(self.cst3.definition_resolved, 'New def')
|
self.assertEqual(self.x3.definition_resolved, 'New def')
|
||||||
|
|
||||||
|
|
||||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
@decl_endpoint('/api/rsforms/{item}/update-cst', method='patch')
|
||||||
def test_update_resolved_refs(self):
|
def test_update_resolved_refs(self):
|
||||||
data = {
|
data = {
|
||||||
'target': self.cst3.pk,
|
'target': self.x3.pk,
|
||||||
'item_data': {
|
'item_data': {
|
||||||
'term_raw': '@{X1|nomn,sing}',
|
'term_raw': '@{X1|nomn,sing}',
|
||||||
'definition_raw': '@{X1|nomn,sing} @{X1|sing,datv}'
|
'definition_raw': '@{X1|nomn,sing} @{X1|sing,datv}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.executeOK(data, schema=self.owned_id)
|
self.executeOK(data, item=self.owned_id)
|
||||||
self.cst3.refresh_from_db()
|
self.x3.refresh_from_db()
|
||||||
self.assertEqual(self.cst3.term_resolved, self.cst1.term_resolved)
|
self.assertEqual(self.x3.term_resolved, self.x1.term_resolved)
|
||||||
self.assertEqual(self.cst3.definition_resolved, f'{self.cst1.term_resolved} form1')
|
self.assertEqual(self.x3.definition_resolved, f'{self.x1.term_resolved} form1')
|
||||||
|
|
||||||
@decl_endpoint('/api/rsforms/{schema}/update-cst', method='patch')
|
|
||||||
|
@decl_endpoint('/api/rsforms/{item}/update-cst', method='patch')
|
||||||
def test_update_term_forms(self):
|
def test_update_term_forms(self):
|
||||||
data = {
|
data = {
|
||||||
'target': self.cst3.pk,
|
'target': self.x3.pk,
|
||||||
'item_data': {
|
'item_data': {
|
||||||
'definition_raw': '@{X3|sing,datv}',
|
'definition_raw': '@{X3|sing,datv}',
|
||||||
'term_forms': [{'text': 'form1', 'tags': 'sing,datv'}]
|
'term_forms': [{'text': 'form1', 'tags': 'sing,datv'}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.executeOK(data, schema=self.owned_id)
|
self.executeOK(data, item=self.owned_id)
|
||||||
self.cst3.refresh_from_db()
|
self.x3.refresh_from_db()
|
||||||
self.assertEqual(self.cst3.definition_resolved, 'form1')
|
self.assertEqual(self.x3.definition_resolved, 'form1')
|
||||||
self.assertEqual(self.cst3.term_forms, data['item_data']['term_forms'])
|
self.assertEqual(self.x3.term_forms, data['item_data']['term_forms'])
|
||||||
|
|
||||||
@decl_endpoint('/api/rsforms/{schema}/update-crucial', method='patch')
|
|
||||||
|
@decl_endpoint('/api/rsforms/{item}/update-crucial', method='patch')
|
||||||
def test_update_crucial(self):
|
def test_update_crucial(self):
|
||||||
data = {'target': [self.cst1.pk], 'value': True}
|
data = {'target': [self.x1.pk], 'value': True}
|
||||||
self.executeForbidden(data, schema=self.unowned_id)
|
self.executeForbidden(data, item=self.unowned_id)
|
||||||
|
|
||||||
self.logout()
|
self.logout()
|
||||||
self.executeForbidden(data, schema=self.owned_id)
|
self.executeForbidden(data, item=self.owned_id)
|
||||||
|
|
||||||
self.login()
|
self.login()
|
||||||
self.executeOK(data, schema=self.owned_id)
|
self.executeOK(data, item=self.owned_id)
|
||||||
self.cst1.refresh_from_db()
|
self.x1.refresh_from_db()
|
||||||
self.assertEqual(self.cst1.crucial, True)
|
self.assertEqual(self.x1.crucial, True)
|
||||||
|
|
||||||
|
|
||||||
|
@decl_endpoint('/api/rsforms/{item}/create-cst', method='post')
|
||||||
|
def test_create_constituenta(self):
|
||||||
|
data = {'alias': 'X4', 'cst_type': CstType.BASE}
|
||||||
|
self.executeForbidden(data, item=self.unowned_id)
|
||||||
|
|
||||||
|
data = {'alias': 'X4'}
|
||||||
|
self.executeBadData(item=self.owned_id)
|
||||||
|
self.executeBadData(data)
|
||||||
|
|
||||||
|
data['cst_type'] = 'invalid'
|
||||||
|
self.executeBadData(data)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'alias': 'X4',
|
||||||
|
'cst_type': CstType.BASE,
|
||||||
|
'term_raw': 'test',
|
||||||
|
'term_forms': [{'text': 'form1', 'tags': 'sing,datv'}],
|
||||||
|
'definition_formal': 'invalid',
|
||||||
|
'crucial': True
|
||||||
|
}
|
||||||
|
response = self.executeCreated(data)
|
||||||
|
self.assertEqual(response.data['new_cst']['alias'], data['alias'])
|
||||||
|
x4 = Constituenta.objects.get(alias=response.data['new_cst']['alias'])
|
||||||
|
self.assertEqual(x4.order, 3)
|
||||||
|
self.assertEqual(x4.term_raw, data['term_raw'])
|
||||||
|
self.assertEqual(x4.term_forms, data['term_forms'])
|
||||||
|
self.assertEqual(x4.definition_formal, data['definition_formal'])
|
||||||
|
self.assertEqual(x4.crucial, data['crucial'])
|
||||||
|
|
||||||
|
|
||||||
|
@decl_endpoint('/api/rsforms/{item}/create-cst', method='post')
|
||||||
|
def test_create_constituenta_after(self):
|
||||||
|
self.set_params(item=self.owned_id)
|
||||||
|
|
||||||
|
data = {'alias': 'X4', 'cst_type': CstType.BASE, 'insert_after': self.invalid_cst}
|
||||||
|
self.executeBadData(data)
|
||||||
|
|
||||||
|
data['insert_after'] = self.unowned_cst.pk
|
||||||
|
self.executeBadData(data)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'alias': 'X4',
|
||||||
|
'cst_type': CstType.BASE,
|
||||||
|
'insert_after': self.x2.pk,
|
||||||
|
}
|
||||||
|
response = self.executeCreated(data)
|
||||||
|
self.assertEqual(response.data['new_cst']['alias'], data['alias'])
|
||||||
|
x4 = Constituenta.objects.get(alias=response.data['new_cst']['alias'])
|
||||||
|
self.x3.refresh_from_db()
|
||||||
|
self.assertEqual(x4.order, 2)
|
||||||
|
self.assertEqual(self.x3.order, 3)
|
||||||
|
|
|
@ -200,54 +200,6 @@ class TestRSFormViewset(EndpointTester):
|
||||||
self.assertIn('document.json', zipped_file.namelist())
|
self.assertIn('document.json', zipped_file.namelist())
|
||||||
|
|
||||||
|
|
||||||
@decl_endpoint('/api/rsforms/{item}/create-cst', method='post')
|
|
||||||
def test_create_constituenta(self):
|
|
||||||
data = {'alias': 'X3', 'cst_type': CstType.BASE}
|
|
||||||
self.executeForbidden(data, item=self.unowned_id)
|
|
||||||
|
|
||||||
data = {'alias': 'X3'}
|
|
||||||
self.owned.insert_last('X1')
|
|
||||||
x2 = self.owned.insert_last('X2')
|
|
||||||
self.executeBadData(item=self.owned_id)
|
|
||||||
self.executeBadData(data)
|
|
||||||
|
|
||||||
data['cst_type'] = 'invalid'
|
|
||||||
self.executeBadData(data)
|
|
||||||
|
|
||||||
data['cst_type'] = CstType.BASE
|
|
||||||
response = self.executeCreated(data)
|
|
||||||
self.assertEqual(response.data['new_cst']['alias'], 'X3')
|
|
||||||
x3 = Constituenta.objects.get(alias=response.data['new_cst']['alias'])
|
|
||||||
self.assertEqual(x3.order, 2)
|
|
||||||
|
|
||||||
data = {
|
|
||||||
'alias': 'X4',
|
|
||||||
'cst_type': CstType.BASE,
|
|
||||||
'insert_after': x2.pk,
|
|
||||||
'term_raw': 'test',
|
|
||||||
'term_forms': [{'text': 'form1', 'tags': 'sing,datv'}],
|
|
||||||
'definition_formal': 'invalid',
|
|
||||||
'crucial': True
|
|
||||||
}
|
|
||||||
response = self.executeCreated(data)
|
|
||||||
self.assertEqual(response.data['new_cst']['alias'], data['alias'])
|
|
||||||
x4 = Constituenta.objects.get(alias=response.data['new_cst']['alias'])
|
|
||||||
self.assertEqual(x4.order, 2)
|
|
||||||
self.assertEqual(x4.term_raw, data['term_raw'])
|
|
||||||
self.assertEqual(x4.term_forms, data['term_forms'])
|
|
||||||
self.assertEqual(x4.definition_formal, data['definition_formal'])
|
|
||||||
self.assertEqual(x4.crucial, data['crucial'])
|
|
||||||
|
|
||||||
data = {
|
|
||||||
'alias': 'X5',
|
|
||||||
'cst_type': CstType.BASE,
|
|
||||||
'insert_after': None,
|
|
||||||
'term_raw': 'test5'
|
|
||||||
}
|
|
||||||
response = self.executeCreated(data)
|
|
||||||
self.assertEqual(response.data['new_cst']['alias'], data['alias'])
|
|
||||||
|
|
||||||
|
|
||||||
@decl_endpoint('/api/rsforms/{item}/substitute', method='patch')
|
@decl_endpoint('/api/rsforms/{item}/substitute', method='patch')
|
||||||
def test_substitute_multiple(self):
|
def test_substitute_multiple(self):
|
||||||
self.set_params(item=self.owned_id)
|
self.set_params(item=self.owned_id)
|
||||||
|
|
|
@ -12,7 +12,7 @@ export { BiX as IconRemove } from 'react-icons/bi';
|
||||||
export { BiTrash as IconDestroy } from 'react-icons/bi';
|
export { BiTrash as IconDestroy } from 'react-icons/bi';
|
||||||
export { BiReset as IconReset } from 'react-icons/bi';
|
export { BiReset as IconReset } from 'react-icons/bi';
|
||||||
export { TbArrowsDiagonal2 as IconResize } from 'react-icons/tb';
|
export { TbArrowsDiagonal2 as IconResize } from 'react-icons/tb';
|
||||||
export { FiEdit as IconEdit } from 'react-icons/fi';
|
export { FiEdit as IconEdit } from 'react-icons/fi';
|
||||||
export { AiOutlineEdit as IconEdit2 } from 'react-icons/ai';
|
export { AiOutlineEdit as IconEdit2 } from 'react-icons/ai';
|
||||||
export { BiSearchAlt2 as IconSearch } from 'react-icons/bi';
|
export { BiSearchAlt2 as IconSearch } from 'react-icons/bi';
|
||||||
export { BiDownload as IconDownload } from 'react-icons/bi';
|
export { BiDownload as IconDownload } from 'react-icons/bi';
|
||||||
|
@ -87,6 +87,7 @@ export { MdOutlineSelectAll as IconConceptBlock } from 'react-icons/md';
|
||||||
export { TbHexagon as IconRSForm } from 'react-icons/tb';
|
export { TbHexagon as IconRSForm } from 'react-icons/tb';
|
||||||
export { TbAssembly as IconRSFormOwned } from 'react-icons/tb';
|
export { TbAssembly as IconRSFormOwned } from 'react-icons/tb';
|
||||||
export { TbBallFootball as IconRSFormImported } from 'react-icons/tb';
|
export { TbBallFootball as IconRSFormImported } from 'react-icons/tb';
|
||||||
|
export { TbHexagonLetterN as IconCstNominal } from 'react-icons/tb';
|
||||||
export { TbHexagonLetterX as IconCstBaseSet } from 'react-icons/tb';
|
export { TbHexagonLetterX as IconCstBaseSet } from 'react-icons/tb';
|
||||||
export { TbHexagonLetterC as IconCstConstSet } from 'react-icons/tb';
|
export { TbHexagonLetterC as IconCstConstSet } from 'react-icons/tb';
|
||||||
export { TbHexagonLetterS as IconCstStructured } from 'react-icons/tb';
|
export { TbHexagonLetterS as IconCstStructured } from 'react-icons/tb';
|
||||||
|
@ -125,7 +126,7 @@ export { RiOpenSourceLine as IconPublic } from 'react-icons/ri';
|
||||||
export { RiShieldLine as IconProtected } from 'react-icons/ri';
|
export { RiShieldLine as IconProtected } from 'react-icons/ri';
|
||||||
export { RiShieldKeyholeLine as IconPrivate } from 'react-icons/ri';
|
export { RiShieldKeyholeLine as IconPrivate } from 'react-icons/ri';
|
||||||
export { BiBug as IconStatusError } from 'react-icons/bi';
|
export { BiBug as IconStatusError } from 'react-icons/bi';
|
||||||
export { BiCheckCircle as IconStatusOK } from 'react-icons/bi';
|
export { LuThumbsUp as IconStatusOK } from 'react-icons/lu';
|
||||||
export { BiHelpCircle as IconStatusUnknown } from 'react-icons/bi';
|
export { BiHelpCircle as IconStatusUnknown } from 'react-icons/bi';
|
||||||
export { BiStopCircle as IconStatusIncalculable } from 'react-icons/bi';
|
export { BiStopCircle as IconStatusIncalculable } from 'react-icons/bi';
|
||||||
export { BiPauseCircle as IconStatusProperty } from 'react-icons/bi';
|
export { BiPauseCircle as IconStatusProperty } from 'react-icons/bi';
|
||||||
|
|
|
@ -89,7 +89,9 @@ export function varSchemaGraph(schema: IRSForm): string {
|
||||||
/** Generates a prompt for a schema type graph variable. */
|
/** Generates a prompt for a schema type graph variable. */
|
||||||
export function varSchemaTypeGraph(schema: IRSForm): string {
|
export function varSchemaTypeGraph(schema: IRSForm): string {
|
||||||
const graph = new TypificationGraph();
|
const graph = new TypificationGraph();
|
||||||
schema.items.forEach(item => graph.addConstituenta(item.alias, item.parse.typification, item.parse.args));
|
schema.items.forEach(item => {
|
||||||
|
if (item.parse) graph.addConstituenta(item.alias, item.parse.typification, item.parse.args);
|
||||||
|
});
|
||||||
|
|
||||||
let result = `Название концептуальной схемы: ${schema.title}\n`;
|
let result = `Название концептуальной схемы: ${schema.title}\n`;
|
||||||
result += `[${schema.alias}] Описание: "${schema.description}"\n\n`;
|
result += `[${schema.alias}] Описание: "${schema.description}"\n\n`;
|
||||||
|
@ -154,6 +156,6 @@ export function varSyntaxTree(cst: IConstituenta): string {
|
||||||
let result = `Конституента: ${cst.alias}\n`;
|
let result = `Конституента: ${cst.alias}\n`;
|
||||||
result += `Формальное выражение: ${cst.definition_formal}\n`;
|
result += `Формальное выражение: ${cst.definition_formal}\n`;
|
||||||
result += `Дерево синтаксического разбора:\n`;
|
result += `Дерево синтаксического разбора:\n`;
|
||||||
result += JSON.stringify(cst.parse.syntaxTree, null, PARAMETER.indentJSON);
|
result += cst.parse ? JSON.stringify(cst.parse.syntaxTree, null, PARAMETER.indentJSON) : 'не определено';
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
IconCstBaseSet,
|
IconCstBaseSet,
|
||||||
IconCstConstSet,
|
IconCstConstSet,
|
||||||
IconCstFunction,
|
IconCstFunction,
|
||||||
|
IconCstNominal,
|
||||||
IconCstPredicate,
|
IconCstPredicate,
|
||||||
IconCstStructured,
|
IconCstStructured,
|
||||||
IconCstTerm,
|
IconCstTerm,
|
||||||
|
@ -118,6 +119,11 @@ export function HelpThesaurus() {
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<b>Типы конституент</b>
|
<b>Типы конституент</b>
|
||||||
|
<li>
|
||||||
|
<IconCstNominal size='1rem' className='inline-icon' />
|
||||||
|
{'\u2009'}Номеноид (N#) – предметная сущность, не имеющая четкого определения, используемая для ассоциативной
|
||||||
|
группировки конституент и предварительной фиксации содержательных отношений.
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconCstBaseSet size='1rem' className='inline-icon' />
|
<IconCstBaseSet size='1rem' className='inline-icon' />
|
||||||
{'\u2009'}Базисное множество (X#) – неопределяемое понятие, представленное множеством различимых элементов.
|
{'\u2009'}Базисное множество (X#) – неопределяемое понятие, представленное множеством различимых элементов.
|
||||||
|
|
|
@ -60,7 +60,7 @@ export const schemaLibraryItemType = z.enum(Object.values(LibraryItemType) as [L
|
||||||
export const schemaAccessPolicy = z.enum(Object.values(AccessPolicy) as [AccessPolicy, ...AccessPolicy[]]);
|
export const schemaAccessPolicy = z.enum(Object.values(AccessPolicy) as [AccessPolicy, ...AccessPolicy[]]);
|
||||||
|
|
||||||
export const schemaLibraryItem = z.strictObject({
|
export const schemaLibraryItem = z.strictObject({
|
||||||
id: z.coerce.number(),
|
id: z.number(),
|
||||||
item_type: schemaLibraryItemType,
|
item_type: schemaLibraryItemType,
|
||||||
|
|
||||||
alias: z.string().nonempty(),
|
alias: z.string().nonempty(),
|
||||||
|
@ -72,9 +72,9 @@ export const schemaLibraryItem = z.strictObject({
|
||||||
location: z.string(),
|
location: z.string(),
|
||||||
access_policy: schemaAccessPolicy,
|
access_policy: schemaAccessPolicy,
|
||||||
|
|
||||||
time_create: z.string().datetime({ offset: true }),
|
time_create: z.iso.datetime({ offset: true }),
|
||||||
time_update: z.string().datetime({ offset: true }),
|
time_update: z.iso.datetime({ offset: true }),
|
||||||
owner: z.coerce.number().nullable()
|
owner: z.number().nullable()
|
||||||
});
|
});
|
||||||
|
|
||||||
export const schemaLibraryItemArray = z.array(schemaLibraryItem);
|
export const schemaLibraryItemArray = z.array(schemaLibraryItem);
|
||||||
|
@ -126,10 +126,10 @@ export const schemaUpdateLibraryItem = schemaInputLibraryItem
|
||||||
});
|
});
|
||||||
|
|
||||||
export const schemaVersionInfo = z.strictObject({
|
export const schemaVersionInfo = z.strictObject({
|
||||||
id: z.coerce.number(),
|
id: z.number(),
|
||||||
version: z.string(),
|
version: z.string(),
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
time_create: z.string().datetime({ offset: true })
|
time_create: z.iso.datetime({ offset: true })
|
||||||
});
|
});
|
||||||
|
|
||||||
const schemaVersionInput = z.strictObject({
|
const schemaVersionInput = z.strictObject({
|
||||||
|
|
|
@ -175,7 +175,11 @@ export class SubstitutionValidator {
|
||||||
if (!original || !substitution) {
|
if (!original || !substitution) {
|
||||||
return this.reportError(SubstitutionErrorType.invalidIDs, []);
|
return this.reportError(SubstitutionErrorType.invalidIDs, []);
|
||||||
}
|
}
|
||||||
if (original.parse.status === ParsingStatus.INCORRECT || substitution.parse.status === ParsingStatus.INCORRECT) {
|
if (
|
||||||
|
substitution.parse &&
|
||||||
|
original.parse &&
|
||||||
|
(original.parse.status === ParsingStatus.INCORRECT || substitution.parse.status === ParsingStatus.INCORRECT)
|
||||||
|
) {
|
||||||
return this.reportError(SubstitutionErrorType.incorrectCst, [substitution.alias, original.alias]);
|
return this.reportError(SubstitutionErrorType.incorrectCst, [substitution.alias, original.alias]);
|
||||||
}
|
}
|
||||||
switch (substitution.cst_type) {
|
switch (substitution.cst_type) {
|
||||||
|
@ -247,6 +251,9 @@ export class SubstitutionValidator {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
graph.addNode(cst.id);
|
graph.addNode(cst.id);
|
||||||
|
if (!cst.parse) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const parents = extractGlobals(cst.parse.typification);
|
const parents = extractGlobals(cst.parse.typification);
|
||||||
for (const arg of cst.parse.args) {
|
for (const arg of cst.parse.args) {
|
||||||
for (const alias of extractGlobals(arg.typification)) {
|
for (const alias of extractGlobals(arg.typification)) {
|
||||||
|
@ -299,6 +306,13 @@ export class SubstitutionValidator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!!original.parse !== !!substitution.parse) {
|
||||||
|
return this.reportError(SubstitutionErrorType.unequalTypification, [substitution.alias, original.alias]);
|
||||||
|
}
|
||||||
|
if (!original.parse || !substitution.parse) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const originalType = applyTypificationMapping(
|
const originalType = applyTypificationMapping(
|
||||||
applyAliasMapping(original.parse.typification, baseMappings.get(original.schema)!),
|
applyAliasMapping(original.parse.typification, baseMappings.get(original.schema)!),
|
||||||
typeMappings
|
typeMappings
|
||||||
|
@ -365,7 +379,7 @@ export class SubstitutionValidator {
|
||||||
|
|
||||||
const substitution = this.cstByID.get(item.substitution)!;
|
const substitution = this.cstByID.get(item.substitution)!;
|
||||||
let substitutionText = '';
|
let substitutionText = '';
|
||||||
if (substitution.cst_type === original.cst_type) {
|
if (substitution.cst_type === original.cst_type || !substitution.parse) {
|
||||||
substitutionText = baseMappings.get(substitution.schema)![substitution.alias];
|
substitutionText = baseMappings.get(substitution.schema)![substitution.alias];
|
||||||
} else {
|
} else {
|
||||||
substitutionText = applyAliasMapping(substitution.parse.typification, baseMappings.get(substitution.schema)!);
|
substitutionText = applyAliasMapping(substitution.parse.typification, baseMappings.get(substitution.schema)!);
|
||||||
|
|
|
@ -181,11 +181,13 @@ export function ToolbarSchema({
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleShowTypeGraph() {
|
function handleShowTypeGraph() {
|
||||||
const typeInfo = schema.items.map(item => ({
|
const typeInfo = schema.items
|
||||||
alias: item.alias,
|
.filter(item => !!item.parse)
|
||||||
result: item.parse.typification,
|
.map(item => ({
|
||||||
args: item.parse.args
|
alias: item.alias,
|
||||||
}));
|
result: item.parse!.typification,
|
||||||
|
args: item.parse!.args
|
||||||
|
}));
|
||||||
showTypeGraph({ items: typeInfo });
|
showTypeGraph({ items: typeInfo });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
import { Graph } from '@/models/graph';
|
import { Graph } from '@/models/graph';
|
||||||
import { type RO } from '@/utils/meta';
|
import { type RO } from '@/utils/meta';
|
||||||
|
|
||||||
import { type IConstituenta, type IRSForm, type IRSFormStats } from '../models/rsform';
|
import { ExpressionStatus, type IConstituenta, type IRSForm, type IRSFormStats } from '../models/rsform';
|
||||||
import { inferClass, inferStatus, inferTemplate, isBaseSet, isFunctional } from '../models/rsform-api';
|
import { inferClass, inferStatus, inferTemplate, isBaseSet, isFunctional } from '../models/rsform-api';
|
||||||
import { extractGlobals, isSimpleExpression, splitTemplateDefinition } from '../models/rslang-api';
|
import { extractGlobals, isSimpleExpression, splitTemplateDefinition } from '../models/rslang-api';
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ export class RSFormLoader {
|
||||||
private cstByID = new Map<number, IConstituenta>();
|
private cstByID = new Map<number, IConstituenta>();
|
||||||
|
|
||||||
constructor(input: RO<IRSFormDTO>) {
|
constructor(input: RO<IRSFormDTO>) {
|
||||||
this.schema = structuredClone(input) as IRSForm;
|
this.schema = structuredClone(input) as unknown as IRSForm;
|
||||||
this.schema.version = input.version ?? 'latest';
|
this.schema.version = input.version ?? 'latest';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ export class RSFormLoader {
|
||||||
order.forEach(cstID => {
|
order.forEach(cstID => {
|
||||||
const cst = this.cstByID.get(cstID)!;
|
const cst = this.cstByID.get(cstID)!;
|
||||||
cst.schema = this.schema.id;
|
cst.schema = this.schema.id;
|
||||||
cst.status = inferStatus(cst.parse.status, cst.parse.valueClass);
|
cst.status = cst.parse ? inferStatus(cst.parse.status, cst.parse.valueClass) : ExpressionStatus.UNKNOWN;
|
||||||
cst.is_template = inferTemplate(cst.definition_formal);
|
cst.is_template = inferTemplate(cst.definition_formal);
|
||||||
cst.cst_class = inferClass(cst.cst_type, cst.is_template);
|
cst.cst_class = inferClass(cst.cst_type, cst.is_template);
|
||||||
cst.spawn = [];
|
cst.spawn = [];
|
||||||
|
@ -184,11 +184,20 @@ export class RSFormLoader {
|
||||||
return {
|
return {
|
||||||
count_all: items.length,
|
count_all: items.length,
|
||||||
count_crucial: items.reduce((sum, cst) => sum + (cst.crucial ? 1 : 0), 0),
|
count_crucial: items.reduce((sum, cst) => sum + (cst.crucial ? 1 : 0), 0),
|
||||||
count_errors: items.reduce((sum, cst) => sum + (cst.parse.status === ParsingStatus.INCORRECT ? 1 : 0), 0),
|
count_errors: items.reduce(
|
||||||
count_property: items.reduce((sum, cst) => sum + (cst.parse.valueClass === ValueClass.PROPERTY ? 1 : 0), 0),
|
(sum, cst) => sum + (cst.parse && cst.parse.status === ParsingStatus.INCORRECT ? 1 : 0),
|
||||||
|
0
|
||||||
|
),
|
||||||
|
count_property: items.reduce(
|
||||||
|
(sum, cst) => sum + (cst.parse && cst.parse.valueClass === ValueClass.PROPERTY ? 1 : 0),
|
||||||
|
0
|
||||||
|
),
|
||||||
count_incalculable: items.reduce(
|
count_incalculable: items.reduce(
|
||||||
(sum, cst) =>
|
(sum, cst) =>
|
||||||
sum + (cst.parse.status === ParsingStatus.VERIFIED && cst.parse.valueClass === ValueClass.INVALID ? 1 : 0),
|
sum +
|
||||||
|
(cst.parse && cst.parse.status === ParsingStatus.VERIFIED && cst.parse.valueClass === ValueClass.INVALID
|
||||||
|
? 1
|
||||||
|
: 0),
|
||||||
0
|
0
|
||||||
),
|
),
|
||||||
count_inherited: items.reduce((sum, cst) => sum + (cst.is_inherited ? 1 : 0), 0),
|
count_inherited: items.reduce((sum, cst) => sum + (cst.is_inherited ? 1 : 0), 0),
|
||||||
|
@ -204,7 +213,8 @@ export class RSFormLoader {
|
||||||
count_term: items.reduce((sum, cst) => sum + (cst.cst_type === CstType.TERM ? 1 : 0), 0),
|
count_term: items.reduce((sum, cst) => sum + (cst.cst_type === CstType.TERM ? 1 : 0), 0),
|
||||||
count_function: items.reduce((sum, cst) => sum + (cst.cst_type === CstType.FUNCTION ? 1 : 0), 0),
|
count_function: items.reduce((sum, cst) => sum + (cst.cst_type === CstType.FUNCTION ? 1 : 0), 0),
|
||||||
count_predicate: items.reduce((sum, cst) => sum + (cst.cst_type === CstType.PREDICATE ? 1 : 0), 0),
|
count_predicate: items.reduce((sum, cst) => sum + (cst.cst_type === CstType.PREDICATE ? 1 : 0), 0),
|
||||||
count_theorem: items.reduce((sum, cst) => sum + (cst.cst_type === CstType.THEOREM ? 1 : 0), 0)
|
count_theorem: items.reduce((sum, cst) => sum + (cst.cst_type === CstType.THEOREM ? 1 : 0), 0),
|
||||||
|
count_nominal: items.reduce((sum, cst) => sum + (cst.cst_type === CstType.NOMINAL ? 1 : 0), 0)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { errorMsg } from '@/utils/labels';
|
||||||
|
|
||||||
/** Represents {@link IConstituenta} type. */
|
/** Represents {@link IConstituenta} type. */
|
||||||
export const CstType = {
|
export const CstType = {
|
||||||
|
NOMINAL: 'nominal',
|
||||||
BASE: 'basic',
|
BASE: 'basic',
|
||||||
STRUCTURED: 'structure',
|
STRUCTURED: 'structure',
|
||||||
TERM: 'term',
|
TERM: 'term',
|
||||||
|
@ -276,7 +277,7 @@ export const schemaTokenID = z.enum(TokenID);
|
||||||
export const schemaRSErrorType = z.enum(RSErrorType);
|
export const schemaRSErrorType = z.enum(RSErrorType);
|
||||||
|
|
||||||
export const schemaConstituentaBasics = z.strictObject({
|
export const schemaConstituentaBasics = z.strictObject({
|
||||||
id: z.coerce.number(),
|
id: z.number(),
|
||||||
alias: z.string().nonempty(errorMsg.requiredField),
|
alias: z.string().nonempty(errorMsg.requiredField),
|
||||||
convention: z.string(),
|
convention: z.string(),
|
||||||
crucial: z.boolean(),
|
crucial: z.boolean(),
|
||||||
|
@ -290,31 +291,34 @@ export const schemaConstituentaBasics = z.strictObject({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const schemaConstituenta = schemaConstituentaBasics.extend({
|
export const schemaConstituenta = schemaConstituentaBasics.extend({
|
||||||
parse: z.strictObject({
|
parse: z
|
||||||
status: schemaParsingStatus,
|
.strictObject({
|
||||||
valueClass: schemaValueClass,
|
status: schemaParsingStatus,
|
||||||
typification: z.string(),
|
valueClass: schemaValueClass,
|
||||||
syntaxTree: z.string(),
|
typification: z.string(),
|
||||||
args: z.array(z.strictObject({ alias: z.string(), typification: z.string() }))
|
syntaxTree: z.string(),
|
||||||
})
|
args: z.array(z.strictObject({ alias: z.string(), typification: z.string() }))
|
||||||
|
})
|
||||||
|
.optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export const schemaRSForm = schemaLibraryItem.extend({
|
export const schemaRSForm = schemaLibraryItem.extend({
|
||||||
editors: z.array(z.coerce.number()),
|
editors: z.array(z.number()),
|
||||||
|
|
||||||
version: z.coerce.number().optional(),
|
version: z.number().optional(),
|
||||||
versions: z.array(schemaVersionInfo),
|
versions: z.array(schemaVersionInfo),
|
||||||
|
|
||||||
items: z.array(schemaConstituenta),
|
items: z.array(schemaConstituenta),
|
||||||
|
association: z.array(z.strictObject({ container: z.number(), associate: z.number() })),
|
||||||
inheritance: z.array(
|
inheritance: z.array(
|
||||||
z.strictObject({
|
z.strictObject({
|
||||||
child: z.coerce.number(),
|
child: z.number(),
|
||||||
child_source: z.coerce.number(),
|
child_source: z.number(),
|
||||||
parent: z.coerce.number(),
|
parent: z.number(),
|
||||||
parent_source: z.coerce.number()
|
parent_source: z.number()
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
oss: z.array(z.strictObject({ id: z.coerce.number(), alias: z.string() }))
|
oss: z.array(z.strictObject({ id: z.number(), alias: z.string() }))
|
||||||
});
|
});
|
||||||
|
|
||||||
export const schemaVersionCreatedResponse = z.strictObject({
|
export const schemaVersionCreatedResponse = z.strictObject({
|
||||||
|
|
|
@ -196,6 +196,7 @@ export function colorFgCstStatus(status: ExpressionStatus): string {
|
||||||
export function colorBgCstClass(cstClass: CstClass): string {
|
export function colorBgCstClass(cstClass: CstClass): string {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
switch (cstClass) {
|
switch (cstClass) {
|
||||||
|
case CstClass.NOMINAL: return APP_COLORS.bgOrange;
|
||||||
case CstClass.BASIC: return APP_COLORS.bgGreen;
|
case CstClass.BASIC: return APP_COLORS.bgGreen;
|
||||||
case CstClass.DERIVED: return APP_COLORS.bgBlue;
|
case CstClass.DERIVED: return APP_COLORS.bgBlue;
|
||||||
case CstClass.STATEMENT: return APP_COLORS.bgRed;
|
case CstClass.STATEMENT: return APP_COLORS.bgRed;
|
||||||
|
@ -203,6 +204,15 @@ export function colorBgCstClass(cstClass: CstClass): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Determines background color for {@link IConstituenta} badge. */
|
||||||
|
export function colorBgBadge(item: IConstituenta) {
|
||||||
|
switch (item.cst_class) {
|
||||||
|
case CstClass.BASIC:
|
||||||
|
return 'bg-accent-green25';
|
||||||
|
}
|
||||||
|
return 'bg-input';
|
||||||
|
}
|
||||||
|
|
||||||
/** Determines background color for {@link IConstituenta} depending on its parent schema index. */
|
/** Determines background color for {@link IConstituenta} depending on its parent schema index. */
|
||||||
export function colorBgSchemas(schema_index: number): string {
|
export function colorBgSchemas(schema_index: number): string {
|
||||||
if (schema_index === 0) {
|
if (schema_index === 0) {
|
||||||
|
|
|
@ -4,8 +4,8 @@ import clsx from 'clsx';
|
||||||
|
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globalIDs } from '@/utils/constants';
|
||||||
|
|
||||||
import { colorFgCstStatus } from '../colors';
|
import { colorBgBadge, colorFgCstStatus } from '../colors';
|
||||||
import { CstClass, type IConstituenta } from '../models/rsform';
|
import { type IConstituenta } from '../models/rsform';
|
||||||
import { useCstTooltipStore } from '../stores/cst-tooltip';
|
import { useCstTooltipStore } from '../stores/cst-tooltip';
|
||||||
|
|
||||||
interface BadgeConstituentaProps {
|
interface BadgeConstituentaProps {
|
||||||
|
@ -29,7 +29,7 @@ export function BadgeConstituenta({ value, prefixID }: BadgeConstituentaProps) {
|
||||||
'cc-badge-constituenta',
|
'cc-badge-constituenta',
|
||||||
value.is_inherited && 'border-dashed',
|
value.is_inherited && 'border-dashed',
|
||||||
value.crucial && 'cc-badge-inner-shadow',
|
value.crucial && 'cc-badge-inner-shadow',
|
||||||
value.cst_class === CstClass.BASIC ? 'bg-accent-green25' : 'bg-input'
|
colorBgBadge(value)
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
borderColor: colorFgCstStatus(value.status),
|
borderColor: colorFgCstStatus(value.status),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { type DomIconProps } from '@/components/icons';
|
import { type DomIconProps, IconCstNominal } from '@/components/icons';
|
||||||
import {
|
import {
|
||||||
IconCstAxiom,
|
IconCstAxiom,
|
||||||
IconCstBaseSet,
|
IconCstBaseSet,
|
||||||
|
@ -15,6 +15,8 @@ import { CstType } from '../backend/types';
|
||||||
/** Icon for constituenta type. */
|
/** Icon for constituenta type. */
|
||||||
export function IconCstType({ value, size = '1.25rem', className }: DomIconProps<CstType>) {
|
export function IconCstType({ value, size = '1.25rem', className }: DomIconProps<CstType>) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
|
case CstType.NOMINAL:
|
||||||
|
return <IconCstNominal size={size} className={className ?? 'text-primary'} />;
|
||||||
case CstType.BASE:
|
case CstType.BASE:
|
||||||
return <IconCstBaseSet size={size} className={className ?? 'text-constructive'} />;
|
return <IconCstBaseSet size={size} className={className ?? 'text-constructive'} />;
|
||||||
case CstType.CONSTANT:
|
case CstType.CONSTANT:
|
||||||
|
|
|
@ -23,10 +23,12 @@ export function InfoConstituenta({ data, className, ...restProps }: InfoConstitu
|
||||||
{data.term_resolved || data.term_raw}
|
{data.term_resolved || data.term_raw}
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
<p className='break-all'>
|
{data.parse ? (
|
||||||
<b>Типизация: </b>
|
<p className='break-all'>
|
||||||
<span className='font-math'>{labelCstTypification(data)}</span>
|
<b>Типизация: </b>
|
||||||
</p>
|
<span className='font-math'>{labelCstTypification(data)}</span>
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
{data.definition_formal ? (
|
{data.definition_formal ? (
|
||||||
<p className='break-all'>
|
<p className='break-all'>
|
||||||
<b>Выражение: </b>
|
<b>Выражение: </b>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
IconCstBaseSet,
|
IconCstBaseSet,
|
||||||
IconCstConstSet,
|
IconCstConstSet,
|
||||||
IconCstFunction,
|
IconCstFunction,
|
||||||
|
IconCstNominal,
|
||||||
IconCstPredicate,
|
IconCstPredicate,
|
||||||
IconCstStructured,
|
IconCstStructured,
|
||||||
IconCstTerm,
|
IconCstTerm,
|
||||||
|
@ -14,7 +15,6 @@ import {
|
||||||
IconPredecessor,
|
IconPredecessor,
|
||||||
IconStatusError,
|
IconStatusError,
|
||||||
IconStatusIncalculable,
|
IconStatusIncalculable,
|
||||||
IconStatusOK,
|
|
||||||
IconStatusProperty,
|
IconStatusProperty,
|
||||||
IconTerminology
|
IconTerminology
|
||||||
} from '@/components/icons';
|
} from '@/components/icons';
|
||||||
|
@ -48,18 +48,11 @@ export function RSFormStats({ className, stats }: RSFormStatsProps) {
|
||||||
titleHtml='Наследованные'
|
titleHtml='Наследованные'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ValueStats
|
|
||||||
id='count_ok'
|
|
||||||
title='Корректные'
|
|
||||||
className='col-start-1'
|
|
||||||
icon={<IconStatusOK size='1.25rem' />}
|
|
||||||
value={stats.count_all - stats.count_errors - stats.count_property - stats.count_incalculable}
|
|
||||||
/>
|
|
||||||
<ValueStats
|
<ValueStats
|
||||||
id='count_property'
|
id='count_property'
|
||||||
title='Неразмерные'
|
title='Неразмерные'
|
||||||
icon={<IconStatusProperty size='1.25rem' />}
|
icon={<IconStatusProperty size='1.25rem' />}
|
||||||
value={stats.count_errors}
|
value={stats.count_property}
|
||||||
/>
|
/>
|
||||||
<ValueStats
|
<ValueStats
|
||||||
id='count_incalculable'
|
id='count_incalculable'
|
||||||
|
@ -73,6 +66,12 @@ export function RSFormStats({ className, stats }: RSFormStatsProps) {
|
||||||
icon={<IconStatusError size='1.25rem' className={stats.count_errors > 0 ? 'text-destructive' : undefined} />}
|
icon={<IconStatusError size='1.25rem' className={stats.count_errors > 0 ? 'text-destructive' : undefined} />}
|
||||||
value={stats.count_errors}
|
value={stats.count_errors}
|
||||||
/>
|
/>
|
||||||
|
<ValueStats
|
||||||
|
id='count_nominal'
|
||||||
|
title='Номеноиды'
|
||||||
|
icon={<IconCstNominal size='1.25rem' className={stats.count_nominal > 0 ? 'text-destructive' : undefined} />}
|
||||||
|
value={stats.count_nominal}
|
||||||
|
/>
|
||||||
|
|
||||||
<ValueStats
|
<ValueStats
|
||||||
id='count_base'
|
id='count_base'
|
||||||
|
|
|
@ -75,7 +75,7 @@ function describeCstNode(cst: IConstituenta) {
|
||||||
? cst.convention
|
? cst.convention
|
||||||
: cst.definition_resolved || cst.definition_formal || cst.convention;
|
: cst.definition_resolved || cst.definition_formal || cst.convention;
|
||||||
const typification = labelCstTypification(cst);
|
const typification = labelCstTypification(cst);
|
||||||
return `${cst.alias}: ${cst.term_resolved}</br><b>Типизация:</b> ${typification}</br><b>Содержание:</b> ${
|
return `${cst.alias}: ${cst.term_resolved}</br>${
|
||||||
contents ? contents : 'отсутствует'
|
cst.parse ? `<b>Типизация:</b> ${typification}</br>` : ''
|
||||||
}`;
|
}<b>Содержание:</b> ${contents ? contents : 'отсутствует'}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ import { CstType, type ICreateConstituentaDTO } from '../../backend/types';
|
||||||
import { IconCrucialValue } from '../../components/icon-crucial-value';
|
import { IconCrucialValue } from '../../components/icon-crucial-value';
|
||||||
import { RSInput } from '../../components/rs-input';
|
import { RSInput } from '../../components/rs-input';
|
||||||
import { SelectCstType } from '../../components/select-cst-type';
|
import { SelectCstType } from '../../components/select-cst-type';
|
||||||
import { getRSDefinitionPlaceholder } from '../../labels';
|
import { getRSDefinitionPlaceholder, labelRSExpression } from '../../labels';
|
||||||
import { type IRSForm } from '../../models/rsform';
|
import { type IRSForm } from '../../models/rsform';
|
||||||
import { generateAlias, isBaseSet, isBasicConcept, isFunctional } from '../../models/rsform-api';
|
import { generateAlias, isBaseSet, isBasicConcept } from '../../models/rsform-api';
|
||||||
|
|
||||||
interface FormCreateCstProps {
|
interface FormCreateCstProps {
|
||||||
schema: IRSForm;
|
schema: IRSForm;
|
||||||
|
@ -33,9 +33,8 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
|
||||||
const cst_type = useWatch({ control, name: 'cst_type' });
|
const cst_type = useWatch({ control, name: 'cst_type' });
|
||||||
const convention = useWatch({ control, name: 'convention' });
|
const convention = useWatch({ control, name: 'convention' });
|
||||||
const crucial = useWatch({ control, name: 'crucial' });
|
const crucial = useWatch({ control, name: 'crucial' });
|
||||||
const isBasic = isBasicConcept(cst_type);
|
const isBasic = isBasicConcept(cst_type) || cst_type === CstType.NOMINAL;
|
||||||
const isElementary = isBaseSet(cst_type);
|
const isElementary = isBaseSet(cst_type);
|
||||||
const isFunction = isFunctional(cst_type);
|
|
||||||
const showConvention = !!convention || forceComment || isBasic;
|
const showConvention = !!convention || forceComment || isBasic;
|
||||||
|
|
||||||
function handleTypeChange(target: CstType) {
|
function handleTypeChange(target: CstType) {
|
||||||
|
@ -91,13 +90,7 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
|
||||||
<RSInput
|
<RSInput
|
||||||
id='dlg_cst_expression'
|
id='dlg_cst_expression'
|
||||||
noTooltip
|
noTooltip
|
||||||
label={
|
label={labelRSExpression(cst_type)}
|
||||||
cst_type === CstType.STRUCTURED
|
|
||||||
? 'Область определения'
|
|
||||||
: isFunction
|
|
||||||
? 'Определение функции'
|
|
||||||
: 'Формальное определение'
|
|
||||||
}
|
|
||||||
placeholder={getRSDefinitionPlaceholder(cst_type)}
|
placeholder={getRSDefinitionPlaceholder(cst_type)}
|
||||||
value={field.value}
|
value={field.value}
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
|
|
|
@ -37,7 +37,7 @@ export const TemplateState = ({ children }: React.PropsWithChildren) => {
|
||||||
function onChangePrototype(newPrototype: IConstituenta) {
|
function onChangePrototype(newPrototype: IConstituenta) {
|
||||||
setPrototype(newPrototype);
|
setPrototype(newPrototype);
|
||||||
setArguments(
|
setArguments(
|
||||||
newPrototype.parse.args.map(arg => ({
|
newPrototype.parse!.args.map(arg => ({
|
||||||
alias: arg.alias,
|
alias: arg.alias,
|
||||||
typification: arg.typification,
|
typification: arg.typification,
|
||||||
value: ''
|
value: ''
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Controller, useFormContext, useWatch } from 'react-hook-form';
|
import { Controller, useFormContext, useWatch } from 'react-hook-form';
|
||||||
|
|
||||||
|
import { HelpTopic } from '@/features/help';
|
||||||
|
import { BadgeHelp } from '@/features/help/components/badge-help';
|
||||||
|
|
||||||
import { MiniButton } from '@/components/control';
|
import { MiniButton } from '@/components/control';
|
||||||
import { TextArea, TextInput } from '@/components/input';
|
import { TextArea, TextInput } from '@/components/input';
|
||||||
|
|
||||||
|
@ -8,9 +11,9 @@ import { CstType, type IUpdateConstituentaDTO } from '../../backend/types';
|
||||||
import { IconCrucialValue } from '../../components/icon-crucial-value';
|
import { IconCrucialValue } from '../../components/icon-crucial-value';
|
||||||
import { RSInput } from '../../components/rs-input';
|
import { RSInput } from '../../components/rs-input';
|
||||||
import { SelectCstType } from '../../components/select-cst-type';
|
import { SelectCstType } from '../../components/select-cst-type';
|
||||||
import { getRSDefinitionPlaceholder, labelCstTypification } from '../../labels';
|
import { getRSDefinitionPlaceholder, labelCstTypification, labelRSExpression } from '../../labels';
|
||||||
import { type IConstituenta, type IRSForm } from '../../models/rsform';
|
import { type IConstituenta, type IRSForm } from '../../models/rsform';
|
||||||
import { generateAlias, isBaseSet, isBasicConcept, isFunctional } from '../../models/rsform-api';
|
import { generateAlias, isBaseSet, isBasicConcept } from '../../models/rsform-api';
|
||||||
|
|
||||||
interface FormEditCstProps {
|
interface FormEditCstProps {
|
||||||
schema: IRSForm;
|
schema: IRSForm;
|
||||||
|
@ -30,9 +33,8 @@ export function FormEditCst({ target, schema }: FormEditCstProps) {
|
||||||
const cst_type = useWatch({ control, name: 'item_data.cst_type' }) ?? CstType.BASE;
|
const cst_type = useWatch({ control, name: 'item_data.cst_type' }) ?? CstType.BASE;
|
||||||
const convention = useWatch({ control, name: 'item_data.convention' });
|
const convention = useWatch({ control, name: 'item_data.convention' });
|
||||||
const crucial = useWatch({ control, name: 'item_data.crucial' }) ?? false;
|
const crucial = useWatch({ control, name: 'item_data.crucial' }) ?? false;
|
||||||
const isBasic = isBasicConcept(cst_type);
|
const isBasic = isBasicConcept(cst_type) || cst_type === CstType.NOMINAL;
|
||||||
const isElementary = isBaseSet(cst_type);
|
const isElementary = isBaseSet(cst_type);
|
||||||
const isFunction = isFunctional(cst_type);
|
|
||||||
const showConvention = !!convention || forceComment || isBasic;
|
const showConvention = !!convention || forceComment || isBasic;
|
||||||
|
|
||||||
function handleTypeChange(newValue: CstType) {
|
function handleTypeChange(newValue: CstType) {
|
||||||
|
@ -67,6 +69,7 @@ export function FormEditCst({ target, schema }: FormEditCstProps) {
|
||||||
{...register('item_data.alias')}
|
{...register('item_data.alias')}
|
||||||
error={errors.item_data?.alias}
|
error={errors.item_data?.alias}
|
||||||
/>
|
/>
|
||||||
|
<BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} contentClass='sm:max-w-160' />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TextArea
|
<TextArea
|
||||||
|
@ -75,23 +78,26 @@ export function FormEditCst({ target, schema }: FormEditCstProps) {
|
||||||
spellCheck
|
spellCheck
|
||||||
label='Термин'
|
label='Термин'
|
||||||
className='max-h-15 disabled:min-h-9'
|
className='max-h-15 disabled:min-h-9'
|
||||||
|
placeholder='Обозначение для текстовых определений'
|
||||||
{...register('item_data.term_raw')}
|
{...register('item_data.term_raw')}
|
||||||
error={errors.item_data?.term_raw}
|
error={errors.item_data?.term_raw}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextArea
|
{cst_type !== CstType.NOMINAL ? (
|
||||||
id='cst_typification'
|
<TextArea
|
||||||
fitContent
|
id='cst_typification'
|
||||||
dense
|
fitContent
|
||||||
noResize
|
dense
|
||||||
noBorder
|
noResize
|
||||||
noOutline
|
noBorder
|
||||||
transparent
|
noOutline
|
||||||
readOnly
|
transparent
|
||||||
label='Типизация'
|
readOnly
|
||||||
value={labelCstTypification(target)}
|
label='Типизация'
|
||||||
className='cursor-default'
|
value={labelCstTypification(target)}
|
||||||
/>
|
className='cursor-default'
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
@ -101,13 +107,7 @@ export function FormEditCst({ target, schema }: FormEditCstProps) {
|
||||||
<RSInput
|
<RSInput
|
||||||
id='dlg_cst_expression'
|
id='dlg_cst_expression'
|
||||||
noTooltip
|
noTooltip
|
||||||
label={
|
label={labelRSExpression(cst_type)}
|
||||||
cst_type === CstType.STRUCTURED
|
|
||||||
? 'Область определения'
|
|
||||||
: isFunction
|
|
||||||
? 'Определение функции'
|
|
||||||
: 'Формальное определение'
|
|
||||||
}
|
|
||||||
placeholder={getRSDefinitionPlaceholder(cst_type)}
|
placeholder={getRSDefinitionPlaceholder(cst_type)}
|
||||||
className='max-h-15'
|
className='max-h-15'
|
||||||
schema={schema}
|
schema={schema}
|
||||||
|
@ -131,6 +131,7 @@ export function FormEditCst({ target, schema }: FormEditCstProps) {
|
||||||
fitContent
|
fitContent
|
||||||
spellCheck
|
spellCheck
|
||||||
label='Текстовое определение'
|
label='Текстовое определение'
|
||||||
|
placeholder='Текстовая интерпретация формального выражения'
|
||||||
className='max-h-15'
|
className='max-h-15'
|
||||||
value={field.value}
|
value={field.value}
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
|
@ -158,6 +159,7 @@ export function FormEditCst({ target, schema }: FormEditCstProps) {
|
||||||
fitContent
|
fitContent
|
||||||
spellCheck
|
spellCheck
|
||||||
label={isBasic ? 'Конвенция' : 'Комментарий'}
|
label={isBasic ? 'Конвенция' : 'Комментарий'}
|
||||||
|
placeholder={isBasic ? 'Договоренность об интерпретации' : 'Пояснение разработчика'}
|
||||||
className='max-h-20 disabled:min-h-9'
|
className='max-h-20 disabled:min-h-9'
|
||||||
{...register('item_data.convention')}
|
{...register('item_data.convention')}
|
||||||
error={errors.item_data?.convention}
|
error={errors.item_data?.convention}
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
|
||||||
|
import { MiniButton } from '@/components/control';
|
||||||
import { Checkbox } from '@/components/input';
|
import { Checkbox } from '@/components/input';
|
||||||
import { ModalForm } from '@/components/modal';
|
import { ModalForm } from '@/components/modal';
|
||||||
|
|
||||||
import { CstType } from '../backend/types';
|
import { CstType } from '../backend/types';
|
||||||
|
import { IconCstType } from '../components/icon-cst-type';
|
||||||
import { labelCstType } from '../labels';
|
import { labelCstType } from '../labels';
|
||||||
import { type GraphFilterParams, useTermGraphStore } from '../stores/term-graph';
|
import { cstTypeToFilterKey, type GraphFilterParams, useTermGraphStore } from '../stores/term-graph';
|
||||||
|
|
||||||
export function DlgGraphParams() {
|
export function DlgGraphParams() {
|
||||||
const params = useTermGraphStore(state => state.filter);
|
const params = useTermGraphStore(state => state.filter);
|
||||||
|
@ -71,47 +73,32 @@ export function DlgGraphParams() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-col gap-1'>
|
<div className='flex flex-col gap-1'>
|
||||||
<h1 className='mb-2'>Типы конституент</h1>
|
<h1 className='mb-1'>Типы конституент</h1>
|
||||||
<Controller
|
<div>
|
||||||
control={control}
|
{Object.values(CstType).map(cstType => {
|
||||||
name='allowBase'
|
const fieldName = cstTypeToFilterKey[cstType];
|
||||||
render={({ field }) => <Checkbox {...field} label={labelCstType(CstType.BASE)} />}
|
return (
|
||||||
/>
|
<Controller
|
||||||
<Controller
|
key={fieldName}
|
||||||
control={control}
|
control={control}
|
||||||
name='allowStruct'
|
name={fieldName}
|
||||||
render={({ field }) => <Checkbox {...field} label={labelCstType(CstType.STRUCTURED)} />}
|
render={({ field }) => (
|
||||||
/>
|
<MiniButton
|
||||||
<Controller
|
onClick={() => field.onChange(!field.value)}
|
||||||
control={control}
|
title={labelCstType(cstType)}
|
||||||
name='allowTerm'
|
icon={
|
||||||
render={({ field }) => <Checkbox {...field} label={labelCstType(CstType.TERM)} />}
|
<IconCstType
|
||||||
/>
|
size='2rem'
|
||||||
<Controller
|
value={cstType}
|
||||||
control={control}
|
className={field.value ? 'text-constructive' : 'text-destructive'}
|
||||||
name='allowAxiom'
|
/>
|
||||||
render={({ field }) => <Checkbox {...field} label={labelCstType(CstType.AXIOM)} />}
|
}
|
||||||
/>
|
/>
|
||||||
<Controller
|
)}
|
||||||
control={control}
|
/>
|
||||||
name='allowFunction'
|
);
|
||||||
render={({ field }) => <Checkbox {...field} label={labelCstType(CstType.FUNCTION)} />}
|
})}
|
||||||
/>
|
</div>
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name='allowPredicate'
|
|
||||||
render={({ field }) => <Checkbox {...field} label={labelCstType(CstType.PREDICATE)} />}
|
|
||||||
/>
|
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name='allowConstant'
|
|
||||||
render={({ field }) => <Checkbox {...field} label={labelCstType(CstType.CONSTANT)} />}
|
|
||||||
/>
|
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name='allowTheorem'
|
|
||||||
render={({ field }) => <Checkbox {...field} label={labelCstType(CstType.THEOREM)} />}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</ModalForm>
|
</ModalForm>
|
||||||
);
|
);
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { type GraphColoring } from './stores/term-graph';
|
||||||
|
|
||||||
// --- Records for label/describe functions ---
|
// --- Records for label/describe functions ---
|
||||||
const labelCstTypeRecord: Record<CstType, string> = {
|
const labelCstTypeRecord: Record<CstType, string> = {
|
||||||
|
[CstType.NOMINAL]: 'Номеноид',
|
||||||
[CstType.BASE]: 'Базисное множество',
|
[CstType.BASE]: 'Базисное множество',
|
||||||
[CstType.CONSTANT]: 'Константное множество',
|
[CstType.CONSTANT]: 'Константное множество',
|
||||||
[CstType.STRUCTURED]: 'Родовая структура',
|
[CstType.STRUCTURED]: 'Родовая структура',
|
||||||
|
@ -34,6 +35,7 @@ const labelReferenceTypeRecord: Record<ReferenceType, string> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const labelCstClassRecord: Record<CstClass, string> = {
|
const labelCstClassRecord: Record<CstClass, string> = {
|
||||||
|
[CstClass.NOMINAL]: 'номинальный',
|
||||||
[CstClass.BASIC]: 'базовый',
|
[CstClass.BASIC]: 'базовый',
|
||||||
[CstClass.DERIVED]: 'производный',
|
[CstClass.DERIVED]: 'производный',
|
||||||
[CstClass.STATEMENT]: 'утверждение',
|
[CstClass.STATEMENT]: 'утверждение',
|
||||||
|
@ -41,6 +43,7 @@ const labelCstClassRecord: Record<CstClass, string> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const describeCstClassRecord: Record<CstClass, string> = {
|
const describeCstClassRecord: Record<CstClass, string> = {
|
||||||
|
[CstClass.NOMINAL]: 'номинальная сущность',
|
||||||
[CstClass.BASIC]: 'неопределяемое понятие',
|
[CstClass.BASIC]: 'неопределяемое понятие',
|
||||||
[CstClass.DERIVED]: 'определяемое понятие',
|
[CstClass.DERIVED]: 'определяемое понятие',
|
||||||
[CstClass.STATEMENT]: 'логическое утверждение',
|
[CstClass.STATEMENT]: 'логическое утверждение',
|
||||||
|
@ -158,15 +161,28 @@ const labelGrammemeRecord: Partial<Record<Grammeme, string>> = {
|
||||||
[Grammeme.Litr]: 'Стиль: литературный'
|
[Grammeme.Litr]: 'Стиль: литературный'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const labelRSExpressionsRecord: Record<CstType, string> = {
|
||||||
|
[CstType.NOMINAL]: 'Определяющие конституенты',
|
||||||
|
[CstType.BASE]: 'Формальное определение',
|
||||||
|
[CstType.CONSTANT]: 'Формальное определение',
|
||||||
|
[CstType.STRUCTURED]: 'Область определения',
|
||||||
|
[CstType.TERM]: 'Формальное определение',
|
||||||
|
[CstType.THEOREM]: 'Формальное определение',
|
||||||
|
[CstType.AXIOM]: 'Формальное определение',
|
||||||
|
[CstType.FUNCTION]: 'Определение функции',
|
||||||
|
[CstType.PREDICATE]: 'Определение функции'
|
||||||
|
};
|
||||||
|
|
||||||
const rsDefinitionPlaceholderRecord: Record<CstType, string> = {
|
const rsDefinitionPlaceholderRecord: Record<CstType, string> = {
|
||||||
|
[CstType.NOMINAL]: 'Например, X1 D1 N1',
|
||||||
|
[CstType.BASE]: 'Не предусмотрено',
|
||||||
|
[CstType.CONSTANT]: 'Не предусмотрено',
|
||||||
[CstType.STRUCTURED]: 'Пример: ℬ(X1×D2)',
|
[CstType.STRUCTURED]: 'Пример: ℬ(X1×D2)',
|
||||||
[CstType.TERM]: 'Пример: D{ξ∈S1 | Pr1(ξ)∩Pr2(ξ)=∅}',
|
[CstType.TERM]: 'Пример: D{ξ∈S1 | Pr1(ξ)∩Pr2(ξ)=∅}',
|
||||||
[CstType.THEOREM]: 'Пример: D11=∅',
|
[CstType.THEOREM]: 'Пример: D11=∅',
|
||||||
[CstType.AXIOM]: 'Пример: D11=∅',
|
[CstType.AXIOM]: 'Пример: D11=∅',
|
||||||
[CstType.FUNCTION]: 'Пример: [α∈X1, β∈ℬ(X1×X2)] Pr2(Fi1[{α}](β))',
|
[CstType.FUNCTION]: 'Пример: [α∈X1, β∈ℬ(X1×X2)] Pr2(Fi1[{α}](β))',
|
||||||
[CstType.PREDICATE]: 'Пример: [α∈X1, β∈ℬ(X1)] α∈β & card(β)>1',
|
[CstType.PREDICATE]: 'Пример: [α∈X1, β∈ℬ(X1)] α∈β & card(β)>1'
|
||||||
[CstType.CONSTANT]: 'Формальное выражение',
|
|
||||||
[CstType.BASE]: 'Формальное выражение'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const cstTypeShortcutKeyRecord: Record<CstType, string> = {
|
const cstTypeShortcutKeyRecord: Record<CstType, string> = {
|
||||||
|
@ -177,7 +193,8 @@ const cstTypeShortcutKeyRecord: Record<CstType, string> = {
|
||||||
[CstType.FUNCTION]: 'Q',
|
[CstType.FUNCTION]: 'Q',
|
||||||
[CstType.PREDICATE]: 'W',
|
[CstType.PREDICATE]: 'W',
|
||||||
[CstType.CONSTANT]: '5',
|
[CstType.CONSTANT]: '5',
|
||||||
[CstType.THEOREM]: '6'
|
[CstType.THEOREM]: '6',
|
||||||
|
[CstType.NOMINAL]: '7'
|
||||||
};
|
};
|
||||||
|
|
||||||
const labelTokenRecord: Partial<Record<TokenID, string>> = {
|
const labelTokenRecord: Partial<Record<TokenID, string>> = {
|
||||||
|
@ -331,6 +348,11 @@ export function getCstTypeShortcut(type: CstType) {
|
||||||
return key ? `${labelCstType(type)} [Alt + ${key}]` : labelCstType(type);
|
return key ? `${labelCstType(type)} [Alt + ${key}]` : labelCstType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Generates label for RS expression based on {@link CstType}. */
|
||||||
|
export function labelRSExpression(type: CstType): string {
|
||||||
|
return labelRSExpressionsRecord[type] ?? 'Формальное выражение';
|
||||||
|
}
|
||||||
|
|
||||||
/** Generates placeholder for RS definition based on {@link CstType}. */
|
/** Generates placeholder for RS definition based on {@link CstType}. */
|
||||||
export function getRSDefinitionPlaceholder(type: CstType): string {
|
export function getRSDefinitionPlaceholder(type: CstType): string {
|
||||||
return rsDefinitionPlaceholderRecord[type] ?? 'Формальное выражение';
|
return rsDefinitionPlaceholderRecord[type] ?? 'Формальное выражение';
|
||||||
|
@ -445,6 +467,9 @@ export function labelTypification({
|
||||||
* Generates label for {@link IConstituenta} typification.
|
* Generates label for {@link IConstituenta} typification.
|
||||||
*/
|
*/
|
||||||
export function labelCstTypification(cst: RO<IConstituenta>): string {
|
export function labelCstTypification(cst: RO<IConstituenta>): string {
|
||||||
|
if (!cst.parse) {
|
||||||
|
return 'N/A';
|
||||||
|
}
|
||||||
return labelTypification({
|
return labelTypification({
|
||||||
isValid: cst.parse.status === ParsingStatus.VERIFIED,
|
isValid: cst.parse.status === ParsingStatus.VERIFIED,
|
||||||
resultType: cst.parse.typification,
|
resultType: cst.parse.typification,
|
||||||
|
|
|
@ -69,6 +69,7 @@ export function produceFilteredGraph(schema: IRSForm, params: GraphFilterParams,
|
||||||
if (params.allowPredicate) result.push(CstType.PREDICATE);
|
if (params.allowPredicate) result.push(CstType.PREDICATE);
|
||||||
if (params.allowConstant) result.push(CstType.CONSTANT);
|
if (params.allowConstant) result.push(CstType.CONSTANT);
|
||||||
if (params.allowTheorem) result.push(CstType.THEOREM);
|
if (params.allowTheorem) result.push(CstType.THEOREM);
|
||||||
|
if (params.allowNominal) result.push(CstType.NOMINAL);
|
||||||
return result;
|
return result;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ export function inferClass(type: CstType, isTemplate: boolean = false): CstClass
|
||||||
}
|
}
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case CstType.NOMINAL: return CstClass.NOMINAL;
|
||||||
case CstType.BASE: return CstClass.BASIC;
|
case CstType.BASE: return CstClass.BASIC;
|
||||||
case CstType.CONSTANT: return CstClass.BASIC;
|
case CstType.CONSTANT: return CstClass.BASIC;
|
||||||
case CstType.STRUCTURED: return CstClass.BASIC;
|
case CstType.STRUCTURED: return CstClass.BASIC;
|
||||||
|
@ -124,6 +125,7 @@ export function applyFilterCategory(start: IConstituenta, schema: IRSForm): ICon
|
||||||
}
|
}
|
||||||
|
|
||||||
const cstTypePrefixRecord: Record<CstType, string> = {
|
const cstTypePrefixRecord: Record<CstType, string> = {
|
||||||
|
[CstType.NOMINAL]: 'N',
|
||||||
[CstType.BASE]: 'X',
|
[CstType.BASE]: 'X',
|
||||||
[CstType.CONSTANT]: 'C',
|
[CstType.CONSTANT]: 'C',
|
||||||
[CstType.STRUCTURED]: 'S',
|
[CstType.STRUCTURED]: 'S',
|
||||||
|
@ -148,6 +150,7 @@ export function guessCstType(hint: string, defaultType: CstType = CstType.TERM):
|
||||||
}
|
}
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
switch (hint) {
|
switch (hint) {
|
||||||
|
case 'N': return CstType.NOMINAL;
|
||||||
case 'X': return CstType.BASE;
|
case 'X': return CstType.BASE;
|
||||||
case 'C': return CstType.CONSTANT;
|
case 'C': return CstType.CONSTANT;
|
||||||
case 'S': return CstType.STRUCTURED;
|
case 'S': return CstType.STRUCTURED;
|
||||||
|
@ -166,6 +169,7 @@ export function guessCstType(hint: string, defaultType: CstType = CstType.TERM):
|
||||||
export function isBasicConcept(type: CstType): boolean {
|
export function isBasicConcept(type: CstType): boolean {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case CstType.NOMINAL: return true;
|
||||||
case CstType.BASE: return true;
|
case CstType.BASE: return true;
|
||||||
case CstType.CONSTANT: return true;
|
case CstType.CONSTANT: return true;
|
||||||
case CstType.STRUCTURED: return true;
|
case CstType.STRUCTURED: return true;
|
||||||
|
@ -183,6 +187,7 @@ export function isBasicConcept(type: CstType): boolean {
|
||||||
export function isBaseSet(type: CstType): boolean {
|
export function isBaseSet(type: CstType): boolean {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case CstType.NOMINAL: return false;
|
||||||
case CstType.BASE: return true;
|
case CstType.BASE: return true;
|
||||||
case CstType.CONSTANT: return true;
|
case CstType.CONSTANT: return true;
|
||||||
case CstType.STRUCTURED: return false;
|
case CstType.STRUCTURED: return false;
|
||||||
|
@ -200,6 +205,7 @@ export function isBaseSet(type: CstType): boolean {
|
||||||
export function isFunctional(type: CstType): boolean {
|
export function isFunctional(type: CstType): boolean {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case CstType.NOMINAL: return false;
|
||||||
case CstType.BASE: return false;
|
case CstType.BASE: return false;
|
||||||
case CstType.CONSTANT: return false;
|
case CstType.CONSTANT: return false;
|
||||||
case CstType.STRUCTURED: return false;
|
case CstType.STRUCTURED: return false;
|
||||||
|
@ -215,7 +221,13 @@ export function isFunctional(type: CstType): boolean {
|
||||||
* Evaluate if {@link IConstituenta} can be used produce structure.
|
* Evaluate if {@link IConstituenta} can be used produce structure.
|
||||||
*/
|
*/
|
||||||
export function canProduceStructure(cst: RO<IConstituenta>): boolean {
|
export function canProduceStructure(cst: RO<IConstituenta>): boolean {
|
||||||
return !!cst.parse.typification && cst.cst_type !== CstType.BASE && cst.cst_type !== CstType.CONSTANT;
|
return (
|
||||||
|
!!cst.parse &&
|
||||||
|
!!cst.parse.typification &&
|
||||||
|
cst.cst_type !== CstType.BASE &&
|
||||||
|
cst.cst_type !== CstType.CONSTANT &&
|
||||||
|
cst.cst_type !== CstType.NOMINAL
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,6 +20,7 @@ export const CATEGORY_CST_TYPE = CstType.THEOREM;
|
||||||
|
|
||||||
/** Represents Constituenta classification in terms of system of concepts. */
|
/** Represents Constituenta classification in terms of system of concepts. */
|
||||||
export const CstClass = {
|
export const CstClass = {
|
||||||
|
NOMINAL: 'nominal',
|
||||||
BASIC: 'basic',
|
BASIC: 'basic',
|
||||||
DERIVED: 'derived',
|
DERIVED: 'derived',
|
||||||
STATEMENT: 'statement',
|
STATEMENT: 'statement',
|
||||||
|
@ -58,7 +59,7 @@ export interface IConstituenta {
|
||||||
term_resolved: string;
|
term_resolved: string;
|
||||||
term_forms: TermForm[];
|
term_forms: TermForm[];
|
||||||
|
|
||||||
parse: {
|
parse?: {
|
||||||
status: ParsingStatus;
|
status: ParsingStatus;
|
||||||
valueClass: ValueClass;
|
valueClass: ValueClass;
|
||||||
typification: string;
|
typification: string;
|
||||||
|
@ -122,6 +123,7 @@ export interface IRSFormStats {
|
||||||
count_function: number;
|
count_function: number;
|
||||||
count_predicate: number;
|
count_predicate: number;
|
||||||
count_theorem: number;
|
count_theorem: number;
|
||||||
|
count_nominal: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents inheritance data for {@link IRSForm}. */
|
/** Represents inheritance data for {@link IRSForm}. */
|
||||||
|
|
|
@ -30,9 +30,14 @@ import {
|
||||||
import { useMutatingRSForm } from '../../../backend/use-mutating-rsform';
|
import { useMutatingRSForm } from '../../../backend/use-mutating-rsform';
|
||||||
import { useUpdateConstituenta } from '../../../backend/use-update-constituenta';
|
import { useUpdateConstituenta } from '../../../backend/use-update-constituenta';
|
||||||
import { RefsInput } from '../../../components/refs-input';
|
import { RefsInput } from '../../../components/refs-input';
|
||||||
import { getRSDefinitionPlaceholder, labelCstTypification, labelTypification } from '../../../labels';
|
import {
|
||||||
|
getRSDefinitionPlaceholder,
|
||||||
|
labelCstTypification,
|
||||||
|
labelRSExpression,
|
||||||
|
labelTypification
|
||||||
|
} from '../../../labels';
|
||||||
import { type IConstituenta, type IRSForm } from '../../../models/rsform';
|
import { type IConstituenta, type IRSForm } from '../../../models/rsform';
|
||||||
import { isBaseSet, isBasicConcept, isFunctional } from '../../../models/rsform-api';
|
import { isBaseSet, isBasicConcept } from '../../../models/rsform-api';
|
||||||
import { EditorRSExpression } from '../editor-rsexpression';
|
import { EditorRSExpression } from '../editor-rsexpression';
|
||||||
|
|
||||||
interface FormConstituentaProps {
|
interface FormConstituentaProps {
|
||||||
|
@ -90,15 +95,18 @@ export function FormConstituenta({ disabled, id, toggleReset, schema, activeCst,
|
||||||
);
|
);
|
||||||
|
|
||||||
const typeInfo = useMemo(
|
const typeInfo = useMemo(
|
||||||
() => ({
|
() =>
|
||||||
alias: activeCst.alias,
|
activeCst.parse
|
||||||
result: localParse ? localParse.typification : activeCst.parse.typification,
|
? {
|
||||||
args: localParse ? localParse.args : activeCst.parse.args
|
alias: activeCst.alias,
|
||||||
}),
|
result: localParse ? localParse.typification : activeCst.parse.typification,
|
||||||
|
args: localParse ? localParse.args : activeCst.parse.args
|
||||||
|
}
|
||||||
|
: null,
|
||||||
[activeCst, localParse]
|
[activeCst, localParse]
|
||||||
);
|
);
|
||||||
|
|
||||||
const isBasic = isBasicConcept(activeCst.cst_type);
|
const isBasic = isBasicConcept(activeCst.cst_type) || activeCst.cst_type === CstType.NOMINAL;
|
||||||
const isElementary = isBaseSet(activeCst.cst_type);
|
const isElementary = isBaseSet(activeCst.cst_type);
|
||||||
const showConvention = !!activeCst.convention || forceComment || isBasic;
|
const showConvention = !!activeCst.convention || forceComment || isBasic;
|
||||||
|
|
||||||
|
@ -140,7 +148,11 @@ export function FormConstituenta({ disabled, id, toggleReset, schema, activeCst,
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTypeGraph(event: React.MouseEvent<Element>) {
|
function handleTypeGraph(event: React.MouseEvent<Element>) {
|
||||||
if ((localParse && !localParse.parseResult) || activeCst.parse.status !== ParsingStatus.VERIFIED) {
|
if (
|
||||||
|
(localParse && !localParse.parseResult) ||
|
||||||
|
!activeCst.parse ||
|
||||||
|
activeCst.parse.status !== ParsingStatus.VERIFIED
|
||||||
|
) {
|
||||||
toast.error(errorMsg.typeStructureFailed);
|
toast.error(errorMsg.typeStructureFailed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -227,19 +239,21 @@ export function FormConstituenta({ disabled, id, toggleReset, schema, activeCst,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextArea
|
{activeCst.cst_type !== CstType.NOMINAL ? (
|
||||||
id='cst_typification'
|
<TextArea
|
||||||
fitContent
|
id='cst_typification'
|
||||||
dense
|
fitContent
|
||||||
noResize
|
dense
|
||||||
noBorder
|
noResize
|
||||||
noOutline
|
noBorder
|
||||||
transparent
|
noOutline
|
||||||
readOnly
|
transparent
|
||||||
label='Типизация'
|
readOnly
|
||||||
value={typification}
|
label='Типизация'
|
||||||
className='cursor-default'
|
value={typification}
|
||||||
/>
|
className='cursor-default'
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
{!!activeCst.definition_formal || !isElementary ? (
|
{!!activeCst.definition_formal || !isElementary ? (
|
||||||
<Controller
|
<Controller
|
||||||
|
@ -248,13 +262,7 @@ export function FormConstituenta({ disabled, id, toggleReset, schema, activeCst,
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<EditorRSExpression
|
<EditorRSExpression
|
||||||
id='cst_expression'
|
id='cst_expression'
|
||||||
label={
|
label={labelRSExpression(activeCst.cst_type)}
|
||||||
activeCst.cst_type === CstType.STRUCTURED
|
|
||||||
? 'Область определения'
|
|
||||||
: isFunctional(activeCst.cst_type)
|
|
||||||
? 'Определение функции'
|
|
||||||
: 'Формальное определение'
|
|
||||||
}
|
|
||||||
placeholder={disabled ? '' : getRSDefinitionPlaceholder(activeCst.cst_type)}
|
placeholder={disabled ? '' : getRSDefinitionPlaceholder(activeCst.cst_type)}
|
||||||
value={field.value ?? ''}
|
value={field.value ?? ''}
|
||||||
activeCst={activeCst}
|
activeCst={activeCst}
|
||||||
|
|
|
@ -155,6 +155,21 @@ export function EditorRSExpression({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!activeCst.parse) {
|
||||||
|
return (
|
||||||
|
<RSInput
|
||||||
|
value={value}
|
||||||
|
schema={schema}
|
||||||
|
minHeight='3.75rem'
|
||||||
|
maxHeight='8rem'
|
||||||
|
onChange={handleChange}
|
||||||
|
onOpenEdit={onOpenEdit}
|
||||||
|
disabled={disabled}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative'>
|
<div className='relative'>
|
||||||
<ToolbarRSExpression
|
<ToolbarRSExpression
|
||||||
|
|
|
@ -30,7 +30,7 @@ interface StatusBarProps {
|
||||||
|
|
||||||
export function StatusBar({ className, isModified, processing, activeCst, parseData, onAnalyze }: StatusBarProps) {
|
export function StatusBar({ className, isModified, processing, activeCst, parseData, onAnalyze }: StatusBarProps) {
|
||||||
const status = (() => {
|
const status = (() => {
|
||||||
if (isModified) {
|
if (isModified || !activeCst.parse) {
|
||||||
return ExpressionStatus.UNKNOWN;
|
return ExpressionStatus.UNKNOWN;
|
||||||
}
|
}
|
||||||
if (parseData) {
|
if (parseData) {
|
||||||
|
|
|
@ -96,6 +96,7 @@ export function EditorRSList() {
|
||||||
case 'KeyW': createCst(CstType.PREDICATE, true); return true;
|
case 'KeyW': createCst(CstType.PREDICATE, true); return true;
|
||||||
case 'Digit5': createCst(CstType.CONSTANT, true); return true;
|
case 'Digit5': createCst(CstType.CONSTANT, true); return true;
|
||||||
case 'Digit6': createCst(CstType.THEOREM, true); return true;
|
case 'Digit6': createCst(CstType.THEOREM, true); return true;
|
||||||
|
case 'Digit7': createCst(CstType.NOMINAL, true); return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,11 +63,13 @@ export function ToolbarTermGraph({ className }: ToolbarTermGraphProps) {
|
||||||
const { addSelectedNodes } = store.getState();
|
const { addSelectedNodes } = store.getState();
|
||||||
|
|
||||||
function handleShowTypeGraph() {
|
function handleShowTypeGraph() {
|
||||||
const typeInfo = schema.items.map(item => ({
|
const typeInfo = schema.items
|
||||||
alias: item.alias,
|
.filter(item => !!item.parse)
|
||||||
result: item.parse.typification,
|
.map(item => ({
|
||||||
args: item.parse.args
|
alias: item.alias,
|
||||||
}));
|
result: item.parse!.typification,
|
||||||
|
args: item.parse!.args
|
||||||
|
}));
|
||||||
showTypeGraph({ items: typeInfo });
|
showTypeGraph({ items: typeInfo });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { persist } from 'zustand/middleware';
|
import { persist } from 'zustand/middleware';
|
||||||
|
|
||||||
|
import { CstType } from '../backend/types';
|
||||||
|
|
||||||
export const graphColorings = ['none', 'status', 'type', 'schemas'] as const;
|
export const graphColorings = ['none', 'status', 'type', 'schemas'] as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,8 +31,21 @@ export interface GraphFilterParams {
|
||||||
allowPredicate: boolean;
|
allowPredicate: boolean;
|
||||||
allowConstant: boolean;
|
allowConstant: boolean;
|
||||||
allowTheorem: boolean;
|
allowTheorem: boolean;
|
||||||
|
allowNominal: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const cstTypeToFilterKey: Record<CstType, keyof GraphFilterParams> = {
|
||||||
|
[CstType.BASE]: 'allowBase',
|
||||||
|
[CstType.STRUCTURED]: 'allowStruct',
|
||||||
|
[CstType.TERM]: 'allowTerm',
|
||||||
|
[CstType.AXIOM]: 'allowAxiom',
|
||||||
|
[CstType.FUNCTION]: 'allowFunction',
|
||||||
|
[CstType.PREDICATE]: 'allowPredicate',
|
||||||
|
[CstType.CONSTANT]: 'allowConstant',
|
||||||
|
[CstType.THEOREM]: 'allowTheorem',
|
||||||
|
[CstType.NOMINAL]: 'allowNominal'
|
||||||
|
};
|
||||||
|
|
||||||
interface TermGraphStore {
|
interface TermGraphStore {
|
||||||
filter: GraphFilterParams;
|
filter: GraphFilterParams;
|
||||||
setFilter: (value: GraphFilterParams) => void;
|
setFilter: (value: GraphFilterParams) => void;
|
||||||
|
@ -66,7 +81,8 @@ export const useTermGraphStore = create<TermGraphStore>()(
|
||||||
allowFunction: true,
|
allowFunction: true,
|
||||||
allowPredicate: true,
|
allowPredicate: true,
|
||||||
allowConstant: true,
|
allowConstant: true,
|
||||||
allowTheorem: true
|
allowTheorem: true,
|
||||||
|
allowNominal: true
|
||||||
},
|
},
|
||||||
setFilter: value => set({ filter: value }),
|
setFilter: value => set({ filter: value }),
|
||||||
toggleFocusInputs: () =>
|
toggleFocusInputs: () =>
|
||||||
|
|
|
@ -17,7 +17,7 @@ export type IUpdateProfileDTO = z.infer<typeof schemaUpdateProfile>;
|
||||||
|
|
||||||
// ========= SCHEMAS ========
|
// ========= SCHEMAS ========
|
||||||
export const schemaUser = z.strictObject({
|
export const schemaUser = z.strictObject({
|
||||||
id: z.coerce.number(),
|
id: z.number(),
|
||||||
username: z.string().nonempty(errorMsg.requiredField),
|
username: z.string().nonempty(errorMsg.requiredField),
|
||||||
is_staff: z.boolean(),
|
is_staff: z.boolean(),
|
||||||
email: z.email(errorMsg.emailField),
|
email: z.email(errorMsg.emailField),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user