mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Implement frontend text refs
This commit is contained in:
parent
38ffba0af6
commit
890e676a2c
|
@ -3,6 +3,8 @@ from typing import Optional, cast
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
|
from cctext import Resolver, Reference, ReferenceType, EntityReference, SyntacticReference
|
||||||
|
|
||||||
from .utils import fix_old_references
|
from .utils import fix_old_references
|
||||||
from .models import Constituenta, RSForm
|
from .models import Constituenta, RSForm
|
||||||
|
|
||||||
|
@ -23,6 +25,11 @@ class ExpressionSerializer(serializers.Serializer):
|
||||||
expression = serializers.CharField()
|
expression = serializers.CharField()
|
||||||
|
|
||||||
|
|
||||||
|
class TextSerializer(serializers.Serializer):
|
||||||
|
''' Serializer: Text with references. '''
|
||||||
|
text = serializers.CharField()
|
||||||
|
|
||||||
|
|
||||||
class RSFormMetaSerializer(serializers.ModelSerializer):
|
class RSFormMetaSerializer(serializers.ModelSerializer):
|
||||||
''' Serializer: General purpose RSForm data. '''
|
''' Serializer: General purpose RSForm data. '''
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -288,7 +295,7 @@ class CstRenameSerializer(serializers.ModelSerializer):
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class CstListSerlializer(serializers.Serializer):
|
class CstListSerializer(serializers.Serializer):
|
||||||
''' Serializer: List of constituents from one origin. '''
|
''' Serializer: List of constituents from one origin. '''
|
||||||
items = serializers.ListField(
|
items = serializers.ListField(
|
||||||
child=CstStandaloneSerializer()
|
child=CstStandaloneSerializer()
|
||||||
|
@ -307,6 +314,41 @@ class CstListSerlializer(serializers.Serializer):
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class CstMoveSerlializer(CstListSerlializer):
|
class CstMoveSerializer(CstListSerializer):
|
||||||
''' Serializer: Change constituenta position. '''
|
''' Serializer: Change constituenta position. '''
|
||||||
move_to = serializers.IntegerField()
|
move_to = serializers.IntegerField()
|
||||||
|
|
||||||
|
|
||||||
|
class ResolverSerializer(serializers.Serializer):
|
||||||
|
''' Serializer: Resolver results serializer. '''
|
||||||
|
def to_representation(self, instance: Resolver) -> dict:
|
||||||
|
return {
|
||||||
|
'input': instance.input,
|
||||||
|
'output': instance.output,
|
||||||
|
'refs': [{
|
||||||
|
'type': str(ref.ref.get_type()),
|
||||||
|
'data': self._get_reference_data(ref.ref),
|
||||||
|
'resolved': ref.resolved,
|
||||||
|
'pos_input': {
|
||||||
|
'start': ref.pos_input.start,
|
||||||
|
'finish': ref.pos_input.finish
|
||||||
|
},
|
||||||
|
'pos_output': {
|
||||||
|
'start': ref.pos_output.start,
|
||||||
|
'finish': ref.pos_output.finish
|
||||||
|
}
|
||||||
|
} for ref in instance.refs]
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_reference_data(ref: Reference) -> dict:
|
||||||
|
if ref.get_type() == ReferenceType.entity:
|
||||||
|
return {
|
||||||
|
'entity': cast(EntityReference, ref).entity,
|
||||||
|
'form': cast(EntityReference, ref).form
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return {
|
||||||
|
'offset': cast(SyntacticReference, ref).offset,
|
||||||
|
'nominal': cast(SyntacticReference, ref).nominal
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ from zipfile import ZipFile
|
||||||
from rest_framework.test import APITestCase, APIRequestFactory, APIClient
|
from rest_framework.test import APITestCase, APIRequestFactory, APIClient
|
||||||
from rest_framework.exceptions import ErrorDetail
|
from rest_framework.exceptions import ErrorDetail
|
||||||
|
|
||||||
|
from cctext import ReferenceType
|
||||||
|
|
||||||
from apps.users.models import User
|
from apps.users.models import User
|
||||||
from apps.rsform.models import Syntax, RSForm, Constituenta, CstType
|
from apps.rsform.models import Syntax, RSForm, Constituenta, CstType
|
||||||
from apps.rsform.views import (
|
from apps.rsform.views import (
|
||||||
|
@ -20,6 +22,7 @@ def _response_contains(response, schema: RSForm) -> bool:
|
||||||
|
|
||||||
|
|
||||||
class TestConstituentaAPI(APITestCase):
|
class TestConstituentaAPI(APITestCase):
|
||||||
|
''' Testing constituenta view. '''
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.factory = APIRequestFactory()
|
self.factory = APIRequestFactory()
|
||||||
self.user = User.objects.create(username='UserTest')
|
self.user = User.objects.create(username='UserTest')
|
||||||
|
@ -100,6 +103,7 @@ class TestConstituentaAPI(APITestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestRSFormViewset(APITestCase):
|
class TestRSFormViewset(APITestCase):
|
||||||
|
''' Testing RSForm view. '''
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.factory = APIRequestFactory()
|
self.factory = APIRequestFactory()
|
||||||
self.user = User.objects.create(username='UserTest')
|
self.user = User.objects.create(username='UserTest')
|
||||||
|
@ -189,6 +193,34 @@ class TestRSFormViewset(APITestCase):
|
||||||
self.assertEqual(response.data['typification'], 'LOGIC')
|
self.assertEqual(response.data['typification'], 'LOGIC')
|
||||||
self.assertEqual(response.data['valueClass'], 'value')
|
self.assertEqual(response.data['valueClass'], 'value')
|
||||||
|
|
||||||
|
def test_resolve(self):
|
||||||
|
schema = RSForm.objects.create(title='Test')
|
||||||
|
x1 = schema.insert_at(1, 'X1', CstType.BASE)
|
||||||
|
x1.term_resolved = 'синий слон'
|
||||||
|
x1.save()
|
||||||
|
data = json.dumps({'text': '@{1|редкий} @{X1|plur,datv}'})
|
||||||
|
response = self.client.post(f'/api/rsforms/{schema.id}/resolve/', data=data, content_type='application/json')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(response.data['input'], '@{1|редкий} @{X1|plur,datv}')
|
||||||
|
self.assertEqual(response.data['output'], 'редким синим слонам')
|
||||||
|
self.assertEqual(len(response.data['refs']), 2)
|
||||||
|
self.assertEqual(response.data['refs'][0]['type'], str(ReferenceType.syntactic))
|
||||||
|
self.assertEqual(response.data['refs'][0]['resolved'], 'редким')
|
||||||
|
self.assertEqual(response.data['refs'][0]['data']['offset'], 1)
|
||||||
|
self.assertEqual(response.data['refs'][0]['data']['nominal'], 'редкий')
|
||||||
|
self.assertEqual(response.data['refs'][0]['pos_input']['start'], 0)
|
||||||
|
self.assertEqual(response.data['refs'][0]['pos_input']['finish'], 11)
|
||||||
|
self.assertEqual(response.data['refs'][0]['pos_output']['start'], 0)
|
||||||
|
self.assertEqual(response.data['refs'][0]['pos_output']['finish'], 6)
|
||||||
|
self.assertEqual(response.data['refs'][1]['type'], str(ReferenceType.entity))
|
||||||
|
self.assertEqual(response.data['refs'][1]['resolved'], 'синим слонам')
|
||||||
|
self.assertEqual(response.data['refs'][1]['data']['entity'], 'X1')
|
||||||
|
self.assertEqual(response.data['refs'][1]['data']['form'], 'plur,datv')
|
||||||
|
self.assertEqual(response.data['refs'][1]['pos_input']['start'], 12)
|
||||||
|
self.assertEqual(response.data['refs'][1]['pos_input']['finish'], 27)
|
||||||
|
self.assertEqual(response.data['refs'][1]['pos_output']['start'], 7)
|
||||||
|
self.assertEqual(response.data['refs'][1]['pos_output']['finish'], 19)
|
||||||
|
|
||||||
def test_import_trs(self):
|
def test_import_trs(self):
|
||||||
work_dir = os.path.dirname(os.path.abspath(__file__))
|
work_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
with open(f'{work_dir}/data/sample-rsform.trs', 'rb') as file:
|
with open(f'{work_dir}/data/sample-rsform.trs', 'rb') as file:
|
||||||
|
|
|
@ -111,7 +111,7 @@ class RSFormViewSet(viewsets.ModelViewSet):
|
||||||
def cst_multidelete(self, request, pk):
|
def cst_multidelete(self, request, pk):
|
||||||
''' Endpoint: Delete multiple constituents. '''
|
''' Endpoint: Delete multiple constituents. '''
|
||||||
schema = self._get_schema()
|
schema = self._get_schema()
|
||||||
serializer = serializers.CstListSerlializer(data=request.data, context={'schema': schema})
|
serializer = serializers.CstListSerializer(data=request.data, context={'schema': schema})
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
schema.delete_cst(serializer.validated_data['constituents'])
|
schema.delete_cst(serializer.validated_data['constituents'])
|
||||||
schema.refresh_from_db()
|
schema.refresh_from_db()
|
||||||
|
@ -121,7 +121,7 @@ class RSFormViewSet(viewsets.ModelViewSet):
|
||||||
def cst_moveto(self, request, pk):
|
def cst_moveto(self, request, pk):
|
||||||
''' Endpoint: Move multiple constituents. '''
|
''' Endpoint: Move multiple constituents. '''
|
||||||
schema = self._get_schema()
|
schema = self._get_schema()
|
||||||
serializer = serializers.CstMoveSerlializer(data=request.data, context={'schema': schema})
|
serializer = serializers.CstMoveSerializer(data=request.data, context={'schema': schema})
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
schema.move_cst(serializer.validated_data['constituents'], serializer.validated_data['move_to'])
|
schema.move_cst(serializer.validated_data['constituents'], serializer.validated_data['move_to'])
|
||||||
schema.refresh_from_db()
|
schema.refresh_from_db()
|
||||||
|
@ -201,6 +201,17 @@ class RSFormViewSet(viewsets.ModelViewSet):
|
||||||
result = pyconcept.check_expression(json.dumps(schema.data), expression)
|
result = pyconcept.check_expression(json.dumps(schema.data), expression)
|
||||||
return Response(json.loads(result))
|
return Response(json.loads(result))
|
||||||
|
|
||||||
|
@action(detail=True, methods=['post'])
|
||||||
|
def resolve(self, request, pk):
|
||||||
|
''' Endpoint: Resolve refenrces in text against schema terms context. '''
|
||||||
|
schema = self._get_schema()
|
||||||
|
serializer = serializers.TextSerializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
text = serializer.validated_data['text']
|
||||||
|
resolver = schema.resolver()
|
||||||
|
resolver.resolve(text)
|
||||||
|
return Response(status=200, data=serializers.ResolverSerializer(resolver).data)
|
||||||
|
|
||||||
@action(detail=True, methods=['get'], url_path='export-trs')
|
@action(detail=True, methods=['get'], url_path='export-trs')
|
||||||
def export_trs(self, request, pk):
|
def export_trs(self, request, pk):
|
||||||
''' Endpoint: Download Exteor compatible file. '''
|
''' Endpoint: Download Exteor compatible file. '''
|
||||||
|
|
|
@ -5,7 +5,7 @@ from .rumodel import Morphology, SemanticRole, WordTag, morpho, split_grams, com
|
||||||
from .ruparser import PhraseParser, WordToken, Collation
|
from .ruparser import PhraseParser, WordToken, Collation
|
||||||
from .reference import EntityReference, ReferenceType, SyntacticReference, parse_reference
|
from .reference import EntityReference, ReferenceType, SyntacticReference, parse_reference
|
||||||
from .context import TermForm, Entity, TermContext
|
from .context import TermForm, Entity, TermContext
|
||||||
from .resolver import Position, Resolver, ResolvedReference, resolve_entity, resolve_syntactic, extract_entities
|
from .resolver import Reference, Position, Resolver, ResolvedReference, resolve_entity, resolve_syntactic, extract_entities
|
||||||
|
|
||||||
from .conceptapi import (
|
from .conceptapi import (
|
||||||
parse, normalize,
|
parse, normalize,
|
||||||
|
|
|
@ -9,7 +9,7 @@ function MiniButton({ icon, tooltip, children, noHover, ...props }: MiniButtonPr
|
||||||
return (
|
return (
|
||||||
<button type='button'
|
<button type='button'
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
className={`px-1 py-1 font-bold rounded-full cursor-pointer whitespace-nowrap disabled:cursor-not-allowed clr-btn-clear ${noHover ? '' : 'clr-hover'}`}
|
className={`px-1 py-1 font-bold rounded-full cursor-pointer whitespace-nowrap disabled:cursor-not-allowed clr-btn-clear ${noHover ? 'outline-none' : 'clr-hover'}`}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{icon && <span>{icon}</span>}
|
{icon && <span>{icon}</span>}
|
||||||
|
|
76
rsconcept/frontend/src/components/Common/ReferenceInput.tsx
Normal file
76
rsconcept/frontend/src/components/Common/ReferenceInput.tsx
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
|
import useResolveText from '../../hooks/useResolveText';
|
||||||
|
import Modal from './Modal';
|
||||||
|
import PrettyJson from './PrettyJSON';
|
||||||
|
import TextArea, { TextAreaProps } from './TextArea';
|
||||||
|
|
||||||
|
interface ReferenceInputProps
|
||||||
|
extends TextAreaProps {
|
||||||
|
initialValue?: string
|
||||||
|
value?: string
|
||||||
|
resolved?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function ReferenceInput({
|
||||||
|
initialValue, resolved, value,
|
||||||
|
onKeyDown, onChange, onFocus, onBlur, ... props
|
||||||
|
}: ReferenceInputProps) {
|
||||||
|
const { schema } = useRSForm();
|
||||||
|
const { resolveText, refsData } = useResolveText({schema: schema});
|
||||||
|
|
||||||
|
const [showResolve, setShowResolve] = useState(false);
|
||||||
|
const [isFocused, setIsFocused] = useState(false);
|
||||||
|
|
||||||
|
function handleKeyboard(event: React.KeyboardEvent<HTMLTextAreaElement>) {
|
||||||
|
if (event.altKey) {
|
||||||
|
if (event.key === 'r' && value) {
|
||||||
|
event.preventDefault();
|
||||||
|
resolveText(value, () => {
|
||||||
|
setShowResolve(true);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (onKeyDown) onKeyDown(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleChange(event: React.ChangeEvent<HTMLTextAreaElement>) {
|
||||||
|
if (onChange) onChange(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFocusIn(event: React.FocusEvent<HTMLTextAreaElement>) {
|
||||||
|
setIsFocused(true);
|
||||||
|
if (onFocus) onFocus(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFocusOut(event: React.FocusEvent<HTMLTextAreaElement>) {
|
||||||
|
setIsFocused(false);
|
||||||
|
if (onBlur) onBlur(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{ showResolve &&
|
||||||
|
<Modal
|
||||||
|
readonly
|
||||||
|
hideWindow={() => setShowResolve(false)}
|
||||||
|
>
|
||||||
|
<div className='max-h-[60vh] max-w-[80vw] overflow-auto'>
|
||||||
|
<PrettyJson data={refsData} />
|
||||||
|
</div>
|
||||||
|
</Modal>}
|
||||||
|
<TextArea
|
||||||
|
value={isFocused ? value : (value !== initialValue ? value : resolved)}
|
||||||
|
onKeyDown={handleKeyboard}
|
||||||
|
onChange={handleChange}
|
||||||
|
onFocus={handleFocusIn}
|
||||||
|
onBlur={handleFocusOut}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReferenceInput;
|
|
@ -2,7 +2,7 @@ import { TextareaHTMLAttributes } from 'react';
|
||||||
|
|
||||||
import Label from './Label';
|
import Label from './Label';
|
||||||
|
|
||||||
interface TextAreaProps
|
export interface TextAreaProps
|
||||||
extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'className'> {
|
extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'className'> {
|
||||||
label: string
|
label: string
|
||||||
widthClass?: string
|
widthClass?: string
|
||||||
|
|
|
@ -61,7 +61,7 @@ function RSInput({
|
||||||
const thisRef = useMemo(
|
const thisRef = useMemo(
|
||||||
() => {
|
() => {
|
||||||
return innerref ?? internalRef;
|
return innerref ?? internalRef;
|
||||||
}, [internalRef, innerref])
|
}, [internalRef, innerref]);
|
||||||
|
|
||||||
const cursor = useMemo(() => editable ? 'cursor-text': 'cursor-default', [editable]);
|
const cursor = useMemo(() => editable ? 'cursor-text': 'cursor-default', [editable]);
|
||||||
const lightTheme: Extension = useMemo(
|
const lightTheme: Extension = useMemo(
|
||||||
|
|
31
rsconcept/frontend/src/hooks/useResolveText.ts
Normal file
31
rsconcept/frontend/src/hooks/useResolveText.ts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import { useCallback, useState } from 'react'
|
||||||
|
|
||||||
|
import { ErrorInfo } from '../components/BackendError';
|
||||||
|
import { DataCallback, postResolveText } from '../utils/backendAPI';
|
||||||
|
import { IReferenceData,IRSForm } from '../utils/models';
|
||||||
|
|
||||||
|
function useResolveText({ schema }: { schema?: IRSForm }) {
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [error, setError] = useState<ErrorInfo>(undefined);
|
||||||
|
const [refsData, setRefsData] = useState<IReferenceData | undefined>(undefined);
|
||||||
|
|
||||||
|
const resetData = useCallback(() => { setRefsData(undefined); }, []);
|
||||||
|
|
||||||
|
function resolveText(text: string, onSuccess?: DataCallback<IReferenceData>) {
|
||||||
|
setError(undefined);
|
||||||
|
postResolveText(String(schema!.id), {
|
||||||
|
data: { text: text },
|
||||||
|
showError: true,
|
||||||
|
setLoading,
|
||||||
|
onError: error => { setError(error); },
|
||||||
|
onSuccess: data => {
|
||||||
|
setRefsData(data);
|
||||||
|
if (onSuccess) onSuccess(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return { refsData, resolveText, resetData, error, setError, loading };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useResolveText;
|
|
@ -11,7 +11,7 @@ function HomePage() {
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
navigate('/library?filter=common');
|
navigate('/manuals');
|
||||||
}, TIMEOUT_UI_REFRESH);
|
}, TIMEOUT_UI_REFRESH);
|
||||||
} else if(!user.is_staff) {
|
} else if(!user.is_staff) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -22,7 +22,7 @@ function HomePage() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col items-center justify-center w-full py-2'>
|
<div className='flex flex-col items-center justify-center w-full py-2'>
|
||||||
<p>Home page</p>
|
<p>Лендинг находится в разработке. Данная страница видна только пользователям с правами администратора.</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
||||||
import MiniButton from '../../components/Common/MiniButton';
|
import MiniButton from '../../components/Common/MiniButton';
|
||||||
|
import ReferenceInput from '../../components/Common/ReferenceInput';
|
||||||
import SubmitButton from '../../components/Common/SubmitButton';
|
import SubmitButton from '../../components/Common/SubmitButton';
|
||||||
import TextArea from '../../components/Common/TextArea';
|
import TextArea from '../../components/Common/TextArea';
|
||||||
import HelpConstituenta from '../../components/Help/HelpConstituenta';
|
import HelpConstituenta from '../../components/Help/HelpConstituenta';
|
||||||
|
@ -171,10 +172,12 @@ function EditorConstituenta({ activeID, onShowAST, onCreateCst, onRenameCst, onO
|
||||||
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<TextArea id='term' label='Термин'
|
<ReferenceInput id='term' label='Термин'
|
||||||
placeholder='Схемный или предметный термин, обозначающий данное понятие или утверждение'
|
placeholder='Схемный или предметный термин, обозначающий данное понятие или утверждение'
|
||||||
rows={2}
|
rows={2}
|
||||||
value={term}
|
value={term}
|
||||||
|
initialValue={activeCst?.term.raw ?? ''}
|
||||||
|
resolved={activeCst?.term.resolved ?? ''}
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
spellCheck
|
spellCheck
|
||||||
onChange={event => setTerm(event.target.value)}
|
onChange={event => setTerm(event.target.value)}
|
||||||
|
@ -197,10 +200,12 @@ function EditorConstituenta({ activeID, onShowAST, onCreateCst, onRenameCst, onO
|
||||||
setValue={setExpression}
|
setValue={setExpression}
|
||||||
setTypification={setTypification}
|
setTypification={setTypification}
|
||||||
/>
|
/>
|
||||||
<TextArea id='definition' label='Текстовое определение'
|
<ReferenceInput id='definition' label='Текстовое определение'
|
||||||
placeholder='Лингвистическая интерпретация формального выражения'
|
placeholder='Лингвистическая интерпретация формального выражения'
|
||||||
rows={4}
|
rows={4}
|
||||||
value={textDefinition}
|
value={textDefinition}
|
||||||
|
initialValue={activeCst?.definition.text.raw ?? ''}
|
||||||
|
resolved={activeCst?.definition.text.resolved ?? ''}
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
spellCheck
|
spellCheck
|
||||||
onChange={event => { setTextDefinition(event.target.value); }}
|
onChange={event => { setTextDefinition(event.target.value); }}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { config } from './constants'
|
||||||
import {
|
import {
|
||||||
IConstituentaList, IConstituentaMeta,
|
IConstituentaList, IConstituentaMeta,
|
||||||
ICstCreateData, ICstCreatedResponse, ICstMovetoData, ICstRenameData, ICstUpdateData,
|
ICstCreateData, ICstCreatedResponse, ICstMovetoData, ICstRenameData, ICstUpdateData,
|
||||||
ICurrentUser, IExpressionParse, IRSExpression,
|
ICurrentUser, IExpressionParse, IReferenceData, IRefsText, IRSExpression,
|
||||||
IRSFormCreateData, IRSFormData,
|
IRSFormCreateData, IRSFormData,
|
||||||
IRSFormMeta, IRSFormUpdateData, IRSFormUploadData, IUserInfo,
|
IRSFormMeta, IRSFormUpdateData, IRSFormUploadData, IUserInfo,
|
||||||
IUserLoginData, IUserProfile, IUserSignupData, IUserUpdateData, IUserUpdatePassword
|
IUserLoginData, IUserProfile, IUserSignupData, IUserUpdateData, IUserUpdatePassword
|
||||||
|
@ -234,6 +234,14 @@ export function postCheckExpression(schema: string, request: FrontExchange<IRSEx
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function postResolveText(schema: string, request: FrontExchange<IRefsText, IReferenceData>) {
|
||||||
|
AxiosPost({
|
||||||
|
title: `Resolve text references for RSForm id=${schema}: ${request.data.text }`,
|
||||||
|
endpoint: `/api/rsforms/${schema}/resolve/`,
|
||||||
|
request: request
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function patchResetAliases(target: string, request: FrontPull<IRSFormData>) {
|
export function patchResetAliases(target: string, request: FrontPull<IRSFormData>) {
|
||||||
AxiosPatch({
|
AxiosPatch({
|
||||||
title: `Reset alias for RSForm id=${target}`,
|
title: `Reset alias for RSForm id=${target}`,
|
||||||
|
|
|
@ -31,6 +31,10 @@ export interface IUserUpdatePassword {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======== RS Parsing ============
|
// ======== RS Parsing ============
|
||||||
|
export interface IRSExpression {
|
||||||
|
expression: string
|
||||||
|
}
|
||||||
|
|
||||||
export enum Syntax {
|
export enum Syntax {
|
||||||
UNDEF = 'undefined',
|
UNDEF = 'undefined',
|
||||||
ASCII = 'ascii',
|
ASCII = 'ascii',
|
||||||
|
@ -85,8 +89,42 @@ export interface IExpressionParse {
|
||||||
args: IFunctionArg[]
|
args: IFunctionArg[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRSExpression {
|
// ====== Reference resolution =====
|
||||||
expression: string
|
export interface IRefsText {
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ReferenceType {
|
||||||
|
ENTITY = 'entity',
|
||||||
|
SYNTACTIC = 'syntax'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IEntityReference {
|
||||||
|
entity: string
|
||||||
|
form: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISyntacticReference {
|
||||||
|
offset: number
|
||||||
|
nominal: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITextPosition {
|
||||||
|
start: number
|
||||||
|
finish: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IResolvedReference {
|
||||||
|
type: ReferenceType
|
||||||
|
data: IEntityReference | ISyntacticReference
|
||||||
|
pos_input: ITextPosition
|
||||||
|
pos_output: ITextPosition
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IReferenceData {
|
||||||
|
input: string
|
||||||
|
output: string
|
||||||
|
refs: IResolvedReference[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====== Constituenta ==========
|
// ====== Constituenta ==========
|
||||||
|
|
Loading…
Reference in New Issue
Block a user