mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
Add OSS creation and fix access policy implementation
This commit is contained in:
parent
93d56ef4fa
commit
9e02d809a0
|
@ -60,3 +60,7 @@ def invalidPosition():
|
|||
|
||||
def constituentaNoStructure():
|
||||
return 'Указанная конституента не обладает теоретико-множественной типизацией'
|
||||
|
||||
|
||||
def missingFile():
|
||||
return 'Отсутствует прикрепленный файл'
|
||||
|
|
|
@ -57,6 +57,8 @@ class ItemEditor(ItemOwner):
|
|||
''' Item permission: Editor or higher. '''
|
||||
|
||||
def has_object_permission(self, request: Request, view: APIView, obj: Any) -> bool:
|
||||
if request.user.is_anonymous:
|
||||
return False
|
||||
item = _extract_item(obj)
|
||||
if m.Editor.objects.filter(
|
||||
item=item,
|
||||
|
@ -69,6 +71,9 @@ class ItemEditor(ItemOwner):
|
|||
class ItemAnyone(ItemEditor):
|
||||
''' Item permission: Anyone if public. '''
|
||||
|
||||
def has_permission(self, request: Request, view: APIView) -> bool:
|
||||
return True
|
||||
|
||||
def has_object_permission(self, request: Request, view: APIView, obj: Any) -> bool:
|
||||
item = _extract_item(obj)
|
||||
if item.access_policy == m.AccessPolicy.PUBLIC:
|
||||
|
|
|
@ -20,7 +20,7 @@ from .data_access import (
|
|||
CstSubstituteSerializer,
|
||||
CstTargetSerializer,
|
||||
InlineSynthesisSerializer,
|
||||
LibraryItemBase,
|
||||
LibraryItemBaseSerializer,
|
||||
LibraryItemCloneSerializer,
|
||||
LibraryItemSerializer,
|
||||
RSFormParseSerializer,
|
||||
|
|
|
@ -13,13 +13,13 @@ from .basics import CstParseSerializer
|
|||
from .io_pyconcept import PyConceptAdapter
|
||||
|
||||
|
||||
class LibraryItemBase(serializers.ModelSerializer):
|
||||
class LibraryItemBaseSerializer(serializers.ModelSerializer):
|
||||
''' Serializer: LibraryItem entry full access. '''
|
||||
class Meta:
|
||||
''' serializer metadata. '''
|
||||
model = LibraryItem
|
||||
fields = '__all__'
|
||||
read_only_fields = ('id', 'item_type')
|
||||
read_only_fields = ('id',)
|
||||
|
||||
|
||||
class LibraryItemSerializer(serializers.ModelSerializer):
|
||||
|
@ -31,6 +31,16 @@ class LibraryItemSerializer(serializers.ModelSerializer):
|
|||
read_only_fields = ('id', 'item_type', 'owner', 'location', 'access_policy')
|
||||
|
||||
|
||||
class LibraryItemCloneSerializer(serializers.ModelSerializer):
|
||||
''' Serializer: LibraryItem cloning. '''
|
||||
items = PKField(many=True, required=False, queryset=Constituenta.objects.all())
|
||||
|
||||
class Meta:
|
||||
''' serializer metadata. '''
|
||||
model = LibraryItem
|
||||
exclude = ['id', 'item_type', 'owner']
|
||||
|
||||
|
||||
class VersionSerializer(serializers.ModelSerializer):
|
||||
''' Serializer: Version data. '''
|
||||
class Meta:
|
||||
|
@ -220,7 +230,7 @@ class RSFormSerializer(serializers.ModelSerializer):
|
|||
validated_data=new_cst.validated_data
|
||||
)
|
||||
|
||||
loaded_item = LibraryItemBase(data=data)
|
||||
loaded_item = LibraryItemBaseSerializer(data=data)
|
||||
loaded_item.is_valid(raise_exception=True)
|
||||
loaded_item.update(
|
||||
instance=cast(LibraryItem, self.instance),
|
||||
|
@ -337,11 +347,6 @@ class CstListSerializer(serializers.Serializer):
|
|||
return attrs
|
||||
|
||||
|
||||
class LibraryItemCloneSerializer(LibraryItemBase):
|
||||
''' Serializer: LibraryItem cloning. '''
|
||||
items = PKField(many=True, required=False, queryset=Constituenta.objects.all())
|
||||
|
||||
|
||||
class CstMoveSerializer(CstListSerializer):
|
||||
''' Serializer: Change constituenta position. '''
|
||||
move_to = serializers.IntegerField()
|
||||
|
|
|
@ -45,10 +45,28 @@ class TestLibraryViewset(EndpointTester):
|
|||
|
||||
@decl_endpoint('/api/library', method='post')
|
||||
def test_create(self):
|
||||
data = {'title': 'Title'}
|
||||
data = {
|
||||
'title': 'Title',
|
||||
'alias': 'alias',
|
||||
}
|
||||
self.executeBadData(data)
|
||||
|
||||
data = {
|
||||
'item_type': LibraryItemType.OPERATIONS_SCHEMA,
|
||||
'title': 'Title',
|
||||
'alias': 'alias',
|
||||
'access_policy': AccessPolicy.PROTECTED,
|
||||
'visible': False,
|
||||
'read_only': True
|
||||
}
|
||||
response = self.executeCreated(data)
|
||||
self.assertEqual(response.data['title'], 'Title')
|
||||
self.assertEqual(response.data['owner'], self.user.pk)
|
||||
self.assertEqual(response.data['item_type'], data['item_type'])
|
||||
self.assertEqual(response.data['title'], data['title'])
|
||||
self.assertEqual(response.data['alias'], data['alias'])
|
||||
self.assertEqual(response.data['access_policy'], data['access_policy'])
|
||||
self.assertEqual(response.data['visible'], data['visible'])
|
||||
self.assertEqual(response.data['read_only'], data['read_only'])
|
||||
|
||||
self.logout()
|
||||
data = {'title': 'Title2'}
|
||||
|
@ -273,6 +291,16 @@ class TestLibraryViewset(EndpointTester):
|
|||
self.assertFalse(response_contains(response, self.unowned))
|
||||
self.assertFalse(response_contains(response, self.owned))
|
||||
|
||||
@decl_endpoint('/api/library', method='get')
|
||||
def test_library_get(self):
|
||||
non_schema = LibraryItem.objects.create(
|
||||
item_type=LibraryItemType.OPERATIONS_SCHEMA,
|
||||
title='Test4'
|
||||
)
|
||||
response = self.executeOK()
|
||||
self.assertTrue(response_contains(response, non_schema))
|
||||
self.assertTrue(response_contains(response, self.unowned))
|
||||
self.assertTrue(response_contains(response, self.owned))
|
||||
|
||||
@decl_endpoint('/api/library/all', method='get')
|
||||
def test_retrieve_all(self):
|
||||
|
|
|
@ -25,27 +25,17 @@ class TestRSFormViewset(EndpointTester):
|
|||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.schema = RSForm.create(title='Test', alias='T1', owner=self.user)
|
||||
self.schema_id = self.schema.item.pk
|
||||
self.owned = RSForm.create(title='Test', alias='T1', owner=self.user)
|
||||
self.owned_id = self.owned.item.pk
|
||||
self.unowned = RSForm.create(title='Test2', alias='T2')
|
||||
self.unowned_id = self.unowned.item.pk
|
||||
self.private = RSForm.create(title='Test2', alias='T2', access_policy=AccessPolicy.PRIVATE)
|
||||
self.private_id = self.private.item.pk
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/create-detailed', method='post')
|
||||
def test_create_rsform_file(self):
|
||||
work_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
with open(f'{work_dir}/data/sample-rsform.trs', 'rb') as file:
|
||||
data = {'file': file, 'title': 'Test123', 'comment': '123', 'alias': 'ks1'}
|
||||
response = self.client.post(self.endpoint, data=data, format='multipart')
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['owner'], self.user.pk)
|
||||
self.assertEqual(response.data['title'], 'Test123')
|
||||
self.assertEqual(response.data['alias'], 'ks1')
|
||||
self.assertEqual(response.data['comment'], '123')
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/create-detailed', method='post')
|
||||
def test_create_rsform_json(self):
|
||||
data = {
|
||||
'title': 'Test123',
|
||||
'comment': '123',
|
||||
|
@ -54,17 +44,20 @@ class TestRSFormViewset(EndpointTester):
|
|||
'access_policy': AccessPolicy.PROTECTED,
|
||||
'visible': False
|
||||
}
|
||||
response = self.executeCreated(data)
|
||||
self.executeBadData(data)
|
||||
|
||||
with open(f'{work_dir}/data/sample-rsform.trs', 'rb') as file:
|
||||
data['file'] = file
|
||||
response = self.client.post(self.endpoint, data=data, format='multipart')
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response.data['owner'], self.user.pk)
|
||||
self.assertEqual(response.data['title'], data['title'])
|
||||
self.assertEqual(response.data['alias'], data['alias'])
|
||||
self.assertEqual(response.data['location'], data['location'])
|
||||
self.assertEqual(response.data['access_policy'], data['access_policy'])
|
||||
self.assertEqual(response.data['visible'], data['visible'])
|
||||
self.assertEqual(response.data['comment'], data['comment'])
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms', method='get')
|
||||
def test_list(self):
|
||||
def test_list_rsforms(self):
|
||||
non_schema = LibraryItem.objects.create(
|
||||
item_type=LibraryItemType.OPERATIONS_SCHEMA,
|
||||
title='Test3'
|
||||
|
@ -72,38 +65,41 @@ class TestRSFormViewset(EndpointTester):
|
|||
response = self.executeOK()
|
||||
self.assertFalse(response_contains(response, non_schema))
|
||||
self.assertTrue(response_contains(response, self.unowned.item))
|
||||
self.assertTrue(response_contains(response, self.schema.item))
|
||||
|
||||
response = self.client.get('/api/library')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response_contains(response, non_schema))
|
||||
self.assertTrue(response_contains(response, self.unowned.item))
|
||||
self.assertTrue(response_contains(response, self.schema.item))
|
||||
self.assertTrue(response_contains(response, self.owned.item))
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/contents', method='get')
|
||||
def test_contents(self):
|
||||
schema = RSForm.create(title='Title1')
|
||||
schema.insert_new('X1')
|
||||
self.executeOK(item=schema.item.pk)
|
||||
response = self.executeOK(item=self.owned_id)
|
||||
self.assertEqual(response.data['owner'], self.owned.item.owner.pk)
|
||||
self.assertEqual(response.data['title'], self.owned.item.title)
|
||||
self.assertEqual(response.data['alias'], self.owned.item.alias)
|
||||
self.assertEqual(response.data['location'], self.owned.item.location)
|
||||
self.assertEqual(response.data['access_policy'], self.owned.item.access_policy)
|
||||
self.assertEqual(response.data['visible'], self.owned.item.visible)
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/details', method='get')
|
||||
def test_details(self):
|
||||
schema = RSForm.create(title='Test', owner=self.user)
|
||||
x1 = schema.insert_new(
|
||||
x1 = self.owned.insert_new(
|
||||
alias='X1',
|
||||
term_raw='человек',
|
||||
term_resolved='человек'
|
||||
)
|
||||
x2 = schema.insert_new(
|
||||
x2 = self.owned.insert_new(
|
||||
alias='X2',
|
||||
term_raw='@{X1|plur}',
|
||||
term_resolved='люди'
|
||||
)
|
||||
|
||||
response = self.executeOK(item=schema.item.pk)
|
||||
self.assertEqual(response.data['title'], 'Test')
|
||||
response = self.executeOK(item=self.owned_id)
|
||||
self.assertEqual(response.data['owner'], self.owned.item.owner.pk)
|
||||
self.assertEqual(response.data['title'], self.owned.item.title)
|
||||
self.assertEqual(response.data['alias'], self.owned.item.alias)
|
||||
self.assertEqual(response.data['location'], self.owned.item.location)
|
||||
self.assertEqual(response.data['access_policy'], self.owned.item.access_policy)
|
||||
self.assertEqual(response.data['visible'], self.owned.item.visible)
|
||||
|
||||
self.assertEqual(len(response.data['items']), 2)
|
||||
self.assertEqual(response.data['items'][0]['id'], x1.pk)
|
||||
self.assertEqual(response.data['items'][0]['parse']['status'], 'verified')
|
||||
|
@ -115,13 +111,20 @@ class TestRSFormViewset(EndpointTester):
|
|||
self.assertEqual(response.data['subscribers'], [self.user.pk])
|
||||
self.assertEqual(response.data['editors'], [])
|
||||
|
||||
self.executeOK(item=self.unowned_id)
|
||||
self.executeForbidden(item=self.private_id)
|
||||
|
||||
self.logout()
|
||||
self.executeOK(item=self.owned_id)
|
||||
self.executeOK(item=self.unowned_id)
|
||||
self.executeForbidden(item=self.private_id)
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/check', method='post')
|
||||
def test_check(self):
|
||||
schema = RSForm.create(title='Test')
|
||||
schema.insert_new('X1')
|
||||
self.owned.insert_new('X1')
|
||||
data = {'expression': 'X1=X1'}
|
||||
response = self.executeOK(data, item=schema.item.pk)
|
||||
response = self.executeOK(data, item=self.owned_id)
|
||||
self.assertEqual(response.data['parseResult'], True)
|
||||
self.assertEqual(response.data['syntax'], 'math')
|
||||
self.assertEqual(response.data['astText'], '[=[X1][X1]]')
|
||||
|
@ -133,14 +136,13 @@ class TestRSFormViewset(EndpointTester):
|
|||
|
||||
@decl_endpoint('/api/rsforms/{item}/resolve', method='post')
|
||||
def test_resolve(self):
|
||||
schema = RSForm.create(title='Test')
|
||||
x1 = schema.insert_new(
|
||||
x1 = self.owned.insert_new(
|
||||
alias='X1',
|
||||
term_resolved='синий слон'
|
||||
)
|
||||
|
||||
data = {'text': '@{1|редкий} @{X1|plur,datv}'}
|
||||
response = self.executeOK(data, item=schema.item.pk)
|
||||
response = self.executeOK(data, item=self.owned_id)
|
||||
self.assertEqual(response.data['input'], '@{1|редкий} @{X1|plur,datv}')
|
||||
self.assertEqual(response.data['output'], 'редким синим слонам')
|
||||
self.assertEqual(len(response.data['refs']), 2)
|
||||
|
@ -190,10 +192,10 @@ class TestRSFormViewset(EndpointTester):
|
|||
data = {'alias': 'X3', 'cst_type': CstType.BASE}
|
||||
self.executeForbidden(data, item=self.unowned_id)
|
||||
|
||||
self.schema.insert_new('X1')
|
||||
x2 = self.schema.insert_new('X2')
|
||||
self.owned.insert_new('X1')
|
||||
x2 = self.owned.insert_new('X2')
|
||||
|
||||
response = self.executeCreated(data, item=self.schema_id)
|
||||
response = self.executeCreated(data, item=self.owned_id)
|
||||
self.assertEqual(response.data['new_cst']['alias'], 'X3')
|
||||
x3 = Constituenta.objects.get(alias=response.data['new_cst']['alias'])
|
||||
self.assertEqual(x3.order, 3)
|
||||
|
@ -205,7 +207,7 @@ class TestRSFormViewset(EndpointTester):
|
|||
'term_raw': 'test',
|
||||
'term_forms': [{'text': 'form1', 'tags': 'sing,datv'}]
|
||||
}
|
||||
response = self.executeCreated(data, item=self.schema_id)
|
||||
response = self.executeCreated(data, item=self.owned_id)
|
||||
self.assertEqual(response.data['new_cst']['alias'], data['alias'])
|
||||
x4 = Constituenta.objects.get(alias=response.data['new_cst']['alias'])
|
||||
self.assertEqual(x4.order, 3)
|
||||
|
@ -215,7 +217,7 @@ class TestRSFormViewset(EndpointTester):
|
|||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-rename', method='patch')
|
||||
def test_rename_constituenta(self):
|
||||
x1 = self.schema.insert_new(
|
||||
x1 = self.owned.insert_new(
|
||||
alias='X1',
|
||||
convention='Test',
|
||||
term_raw='Test1',
|
||||
|
@ -223,7 +225,7 @@ class TestRSFormViewset(EndpointTester):
|
|||
term_forms=[{'text': 'form1', 'tags': 'sing,datv'}]
|
||||
)
|
||||
x2_2 = self.unowned.insert_new('X2')
|
||||
x3 = self.schema.insert_new(
|
||||
x3 = self.owned.insert_new(
|
||||
alias='X3',
|
||||
term_raw='Test3',
|
||||
term_resolved='Test3',
|
||||
|
@ -233,15 +235,15 @@ class TestRSFormViewset(EndpointTester):
|
|||
|
||||
data = {'target': x2_2.pk, 'alias': 'D2', 'cst_type': CstType.TERM}
|
||||
self.executeForbidden(data, item=self.unowned_id)
|
||||
self.executeBadData(data, item=self.schema_id)
|
||||
self.executeBadData(data, item=self.owned_id)
|
||||
|
||||
data = {'target': x1.pk, 'alias': x1.alias, 'cst_type': CstType.TERM}
|
||||
self.executeBadData(data, item=self.schema_id)
|
||||
self.executeBadData(data, item=self.owned_id)
|
||||
|
||||
data = {'target': x1.pk, 'alias': x3.alias}
|
||||
self.executeBadData(data, item=self.schema_id)
|
||||
self.executeBadData(data, item=self.owned_id)
|
||||
|
||||
d1 = self.schema.insert_new(
|
||||
d1 = self.owned.insert_new(
|
||||
alias='D1',
|
||||
term_raw='@{X1|plur}',
|
||||
definition_formal='X1'
|
||||
|
@ -251,7 +253,7 @@ class TestRSFormViewset(EndpointTester):
|
|||
self.assertEqual(x1.cst_type, CstType.BASE)
|
||||
|
||||
data = {'target': x1.pk, 'alias': 'D2', 'cst_type': CstType.TERM}
|
||||
response = self.executeOK(data, item=self.schema_id)
|
||||
response = self.executeOK(data, item=self.owned_id)
|
||||
self.assertEqual(response.data['new_cst']['alias'], 'D2')
|
||||
self.assertEqual(response.data['new_cst']['cst_type'], CstType.TERM)
|
||||
d1.refresh_from_db()
|
||||
|
@ -265,13 +267,13 @@ class TestRSFormViewset(EndpointTester):
|
|||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-substitute', method='patch')
|
||||
def test_substitute_single(self):
|
||||
x1 = self.schema.insert_new(
|
||||
x1 = self.owned.insert_new(
|
||||
alias='X1',
|
||||
term_raw='Test1',
|
||||
term_resolved='Test1',
|
||||
term_forms=[{'text': 'form1', 'tags': 'sing,datv'}]
|
||||
)
|
||||
x2 = self.schema.insert_new(
|
||||
x2 = self.owned.insert_new(
|
||||
alias='X2',
|
||||
term_raw='Test2'
|
||||
)
|
||||
|
@ -279,21 +281,21 @@ class TestRSFormViewset(EndpointTester):
|
|||
|
||||
data = {'substitutions': [{'original': x1.pk, 'substitution': unowned.pk, 'transfer_term': True}]}
|
||||
self.executeForbidden(data, item=self.unowned_id)
|
||||
self.executeBadData(data, item=self.schema_id)
|
||||
self.executeBadData(data, item=self.owned_id)
|
||||
|
||||
data = {'substitutions': [{'original': unowned.pk, 'substitution': x1.pk, 'transfer_term': True}]}
|
||||
self.executeBadData(data, item=self.schema_id)
|
||||
self.executeBadData(data, item=self.owned_id)
|
||||
|
||||
data = {'substitutions': [{'original': x1.pk, 'substitution': x1.pk, 'transfer_term': True}]}
|
||||
self.executeBadData(data, item=self.schema_id)
|
||||
self.executeBadData(data, item=self.owned_id)
|
||||
|
||||
d1 = self.schema.insert_new(
|
||||
d1 = self.owned.insert_new(
|
||||
alias='D1',
|
||||
term_raw='@{X2|sing,datv}',
|
||||
definition_formal='X1'
|
||||
)
|
||||
data = {'substitutions': [{'original': x1.pk, 'substitution': x2.pk, 'transfer_term': True}]}
|
||||
response = self.executeOK(data, item=self.schema_id)
|
||||
response = self.executeOK(data, item=self.owned_id)
|
||||
d1.refresh_from_db()
|
||||
x2.refresh_from_db()
|
||||
self.assertEqual(x2.term_raw, 'Test1')
|
||||
|
@ -302,12 +304,12 @@ class TestRSFormViewset(EndpointTester):
|
|||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-substitute', method='patch')
|
||||
def test_substitute_multiple(self):
|
||||
self.set_params(item=self.schema_id)
|
||||
x1 = self.schema.insert_new('X1')
|
||||
x2 = self.schema.insert_new('X2')
|
||||
d1 = self.schema.insert_new('D1')
|
||||
d2 = self.schema.insert_new('D2')
|
||||
d3 = self.schema.insert_new(
|
||||
self.set_params(item=self.owned_id)
|
||||
x1 = self.owned.insert_new('X1')
|
||||
x2 = self.owned.insert_new('X2')
|
||||
d1 = self.owned.insert_new('D1')
|
||||
d2 = self.owned.insert_new('D2')
|
||||
d3 = self.owned.insert_new(
|
||||
alias='D3',
|
||||
definition_formal=r'X1 \ X2'
|
||||
)
|
||||
|
@ -341,7 +343,7 @@ class TestRSFormViewset(EndpointTester):
|
|||
'transfer_term': True
|
||||
}
|
||||
]}
|
||||
response = self.executeOK(data, item=self.schema_id)
|
||||
response = self.executeOK(data, item=self.owned_id)
|
||||
d3.refresh_from_db()
|
||||
self.assertEqual(d3.definition_formal, r'D1 \ D2')
|
||||
|
||||
|
@ -356,7 +358,7 @@ class TestRSFormViewset(EndpointTester):
|
|||
'definition_formal': '3',
|
||||
'definition_raw': '4'
|
||||
}
|
||||
response = self.executeCreated(data, item=self.schema_id)
|
||||
response = self.executeCreated(data, item=self.owned_id)
|
||||
self.assertEqual(response.data['new_cst']['alias'], 'X3')
|
||||
self.assertEqual(response.data['new_cst']['cst_type'], CstType.BASE)
|
||||
self.assertEqual(response.data['new_cst']['convention'], '1')
|
||||
|
@ -369,43 +371,43 @@ class TestRSFormViewset(EndpointTester):
|
|||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-delete-multiple', method='patch')
|
||||
def test_delete_constituenta(self):
|
||||
self.set_params(item=self.schema_id)
|
||||
self.set_params(item=self.owned_id)
|
||||
|
||||
data = {'items': [1337]}
|
||||
self.executeBadData(data)
|
||||
|
||||
x1 = self.schema.insert_new('X1')
|
||||
x2 = self.schema.insert_new('X2')
|
||||
x1 = self.owned.insert_new('X1')
|
||||
x2 = self.owned.insert_new('X2')
|
||||
|
||||
data = {'items': [x1.pk]}
|
||||
response = self.executeOK(data)
|
||||
x2.refresh_from_db()
|
||||
self.schema.item.refresh_from_db()
|
||||
self.owned.item.refresh_from_db()
|
||||
self.assertEqual(len(response.data['items']), 1)
|
||||
self.assertEqual(self.schema.constituents().count(), 1)
|
||||
self.assertEqual(self.owned.constituents().count(), 1)
|
||||
self.assertEqual(x2.alias, 'X2')
|
||||
self.assertEqual(x2.order, 1)
|
||||
|
||||
x3 = self.unowned.insert_new('X1')
|
||||
data = {'items': [x3.pk]}
|
||||
self.executeBadData(data, item=self.schema_id)
|
||||
self.executeBadData(data, item=self.owned_id)
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-moveto', method='patch')
|
||||
def test_move_constituenta(self):
|
||||
self.set_params(item=self.schema_id)
|
||||
self.set_params(item=self.owned_id)
|
||||
|
||||
data = {'items': [1337], 'move_to': 1}
|
||||
self.executeBadData(data)
|
||||
|
||||
x1 = self.schema.insert_new('X1')
|
||||
x2 = self.schema.insert_new('X2')
|
||||
x1 = self.owned.insert_new('X1')
|
||||
x2 = self.owned.insert_new('X2')
|
||||
|
||||
data = {'items': [x2.pk], 'move_to': 1}
|
||||
response = self.executeOK(data)
|
||||
x1.refresh_from_db()
|
||||
x2.refresh_from_db()
|
||||
self.assertEqual(response.data['id'], self.schema_id)
|
||||
self.assertEqual(response.data['id'], self.owned_id)
|
||||
self.assertEqual(x1.order, 2)
|
||||
self.assertEqual(x2.order, 1)
|
||||
|
||||
|
@ -416,14 +418,14 @@ class TestRSFormViewset(EndpointTester):
|
|||
|
||||
@decl_endpoint('/api/rsforms/{item}/reset-aliases', method='patch')
|
||||
def test_reset_aliases(self):
|
||||
self.set_params(item=self.schema_id)
|
||||
self.set_params(item=self.owned_id)
|
||||
|
||||
response = self.executeOK()
|
||||
self.assertEqual(response.data['id'], self.schema_id)
|
||||
self.assertEqual(response.data['id'], self.owned_id)
|
||||
|
||||
x2 = self.schema.insert_new('X2')
|
||||
x1 = self.schema.insert_new('X1')
|
||||
d11 = self.schema.insert_new('D11')
|
||||
x2 = self.owned.insert_new('X2')
|
||||
x1 = self.owned.insert_new('X1')
|
||||
d11 = self.owned.insert_new('D11')
|
||||
|
||||
response = self.executeOK()
|
||||
x1.refresh_from_db()
|
||||
|
@ -441,43 +443,43 @@ class TestRSFormViewset(EndpointTester):
|
|||
|
||||
@decl_endpoint('/api/rsforms/{item}/load-trs', method='patch')
|
||||
def test_load_trs(self):
|
||||
self.set_params(item=self.schema_id)
|
||||
self.schema.item.title = 'Test11'
|
||||
self.schema.item.save()
|
||||
x1 = self.schema.insert_new('X1')
|
||||
self.set_params(item=self.owned_id)
|
||||
self.owned.item.title = 'Test11'
|
||||
self.owned.item.save()
|
||||
x1 = self.owned.insert_new('X1')
|
||||
work_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
with open(f'{work_dir}/data/sample-rsform.trs', 'rb') as file:
|
||||
data = {'file': file, 'load_metadata': False}
|
||||
response = self.client.patch(self.endpoint, data=data, format='multipart')
|
||||
self.schema.item.refresh_from_db()
|
||||
self.owned.item.refresh_from_db()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(self.schema.item.title, 'Test11')
|
||||
self.assertEqual(self.owned.item.title, 'Test11')
|
||||
self.assertEqual(len(response.data['items']), 25)
|
||||
self.assertEqual(self.schema.constituents().count(), 25)
|
||||
self.assertEqual(self.owned.constituents().count(), 25)
|
||||
self.assertFalse(Constituenta.objects.filter(pk=x1.pk).exists())
|
||||
|
||||
|
||||
@decl_endpoint('/api/rsforms/{item}/cst-produce-structure', method='patch')
|
||||
def test_produce_structure(self):
|
||||
self.set_params(item=self.schema_id)
|
||||
x1 = self.schema.insert_new('X1')
|
||||
s1 = self.schema.insert_new(
|
||||
self.set_params(item=self.owned_id)
|
||||
x1 = self.owned.insert_new('X1')
|
||||
s1 = self.owned.insert_new(
|
||||
alias='S1',
|
||||
definition_formal='ℬ(X1×X1)'
|
||||
)
|
||||
s2 = self.schema.insert_new(
|
||||
s2 = self.owned.insert_new(
|
||||
alias='S2',
|
||||
definition_formal='invalid'
|
||||
)
|
||||
s3 = self.schema.insert_new(
|
||||
s3 = self.owned.insert_new(
|
||||
alias='S3',
|
||||
definition_formal='X1×(X1×ℬℬ(X1))×ℬ(X1×X1)'
|
||||
)
|
||||
a1 = self.schema.insert_new(
|
||||
a1 = self.owned.insert_new(
|
||||
alias='A1',
|
||||
definition_formal='1=1'
|
||||
)
|
||||
f1 = self.schema.insert_new(
|
||||
f1 = self.owned.insert_new(
|
||||
alias='F10',
|
||||
definition_formal='[α∈X1, β∈X1] Fi1[{α,β}](S1)'
|
||||
)
|
||||
|
|
|
@ -18,74 +18,22 @@ from .. import permissions
|
|||
from .. import serializers as s
|
||||
|
||||
|
||||
@extend_schema(tags=['Library'])
|
||||
@extend_schema_view()
|
||||
class LibraryActiveView(generics.ListAPIView):
|
||||
''' Endpoint: Get list of library items available for active user. '''
|
||||
permission_classes = (permissions.Anyone,)
|
||||
serializer_class = s.LibraryItemSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_anonymous:
|
||||
return m.LibraryItem.objects.filter(
|
||||
Q(access_policy=m.AccessPolicy.PUBLIC),
|
||||
).filter(
|
||||
Q(location__startswith=m.LocationHead.COMMON) |
|
||||
Q(location__startswith=m.LocationHead.LIBRARY)
|
||||
).order_by('-time_update')
|
||||
else:
|
||||
user = cast(m.User, self.request.user)
|
||||
# pylint: disable=unsupported-binary-operation
|
||||
return m.LibraryItem.objects.filter(
|
||||
(
|
||||
Q(access_policy=m.AccessPolicy.PUBLIC) &
|
||||
(
|
||||
Q(location__startswith=m.LocationHead.COMMON) |
|
||||
Q(location__startswith=m.LocationHead.LIBRARY)
|
||||
)
|
||||
) |
|
||||
Q(owner=user) |
|
||||
Q(editor__editor=user) |
|
||||
Q(subscription__user=user)
|
||||
).distinct().order_by('-time_update')
|
||||
|
||||
|
||||
@extend_schema(tags=['Library'])
|
||||
@extend_schema_view()
|
||||
class LibraryAdminView(generics.ListAPIView):
|
||||
''' Endpoint: Get list of all library items. Admin only '''
|
||||
permission_classes = (permissions.GlobalAdmin,)
|
||||
serializer_class = s.LibraryItemSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return m.LibraryItem.objects.all().order_by('-time_update')
|
||||
|
||||
|
||||
@extend_schema(tags=['Library'])
|
||||
@extend_schema_view()
|
||||
class LibraryTemplatesView(generics.ListAPIView):
|
||||
''' Endpoint: Get list of templates. '''
|
||||
permission_classes = (permissions.Anyone,)
|
||||
serializer_class = s.LibraryItemSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
template_ids = m.LibraryTemplate.objects.values_list('lib_source', flat=True)
|
||||
return m.LibraryItem.objects.filter(pk__in=template_ids)
|
||||
|
||||
|
||||
# pylint: disable=too-many-ancestors
|
||||
@extend_schema(tags=['Library'])
|
||||
@extend_schema_view()
|
||||
class LibraryViewSet(viewsets.ModelViewSet):
|
||||
''' Endpoint: Library operations. '''
|
||||
queryset = m.LibraryItem.objects.all()
|
||||
serializer_class = s.LibraryItemSerializer
|
||||
|
||||
filter_backends = (DjangoFilterBackend, filters.OrderingFilter)
|
||||
filterset_fields = ['item_type', 'owner']
|
||||
ordering_fields = ('item_type', 'owner', 'alias', 'title', 'time_update')
|
||||
ordering = '-time_update'
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'create':
|
||||
return s.LibraryItemBaseSerializer
|
||||
return s.LibraryItemSerializer
|
||||
|
||||
def perform_create(self, serializer):
|
||||
if not self.request.user.is_anonymous and 'owner' not in self.request.POST:
|
||||
return serializer.save(owner=self.request.user)
|
||||
|
@ -103,7 +51,7 @@ class LibraryViewSet(viewsets.ModelViewSet):
|
|||
elif self.action in ['create', 'clone', 'subscribe', 'unsubscribe']:
|
||||
permission_list = [permissions.GlobalUser]
|
||||
else:
|
||||
permission_list = [permissions.Anyone]
|
||||
permission_list = [permissions.ItemAnyone]
|
||||
return [permission() for permission in permission_list]
|
||||
|
||||
def _get_item(self) -> m.LibraryItem:
|
||||
|
@ -308,3 +256,58 @@ class LibraryViewSet(viewsets.ModelViewSet):
|
|||
editors = serializer.validated_data['users']
|
||||
m.Editor.set(item=item, users=editors)
|
||||
return Response(status=c.HTTP_200_OK)
|
||||
|
||||
|
||||
@extend_schema(tags=['Library'])
|
||||
@extend_schema_view()
|
||||
class LibraryActiveView(generics.ListAPIView):
|
||||
''' Endpoint: Get list of library items available for active user. '''
|
||||
permission_classes = (permissions.Anyone,)
|
||||
serializer_class = s.LibraryItemSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_anonymous:
|
||||
return m.LibraryItem.objects.filter(
|
||||
Q(access_policy=m.AccessPolicy.PUBLIC),
|
||||
).filter(
|
||||
Q(location__startswith=m.LocationHead.COMMON) |
|
||||
Q(location__startswith=m.LocationHead.LIBRARY)
|
||||
).order_by('-time_update')
|
||||
else:
|
||||
user = cast(m.User, self.request.user)
|
||||
# pylint: disable=unsupported-binary-operation
|
||||
return m.LibraryItem.objects.filter(
|
||||
(
|
||||
Q(access_policy=m.AccessPolicy.PUBLIC) &
|
||||
(
|
||||
Q(location__startswith=m.LocationHead.COMMON) |
|
||||
Q(location__startswith=m.LocationHead.LIBRARY)
|
||||
)
|
||||
) |
|
||||
Q(owner=user) |
|
||||
Q(editor__editor=user) |
|
||||
Q(subscription__user=user)
|
||||
).distinct().order_by('-time_update')
|
||||
|
||||
|
||||
@extend_schema(tags=['Library'])
|
||||
@extend_schema_view()
|
||||
class LibraryAdminView(generics.ListAPIView):
|
||||
''' Endpoint: Get list of all library items. Admin only '''
|
||||
permission_classes = (permissions.GlobalAdmin,)
|
||||
serializer_class = s.LibraryItemSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return m.LibraryItem.objects.all().order_by('-time_update')
|
||||
|
||||
|
||||
@extend_schema(tags=['Library'])
|
||||
@extend_schema_view()
|
||||
class LibraryTemplatesView(generics.ListAPIView):
|
||||
''' Endpoint: Get list of templates. '''
|
||||
permission_classes = (permissions.Anyone,)
|
||||
serializer_class = s.LibraryItemSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
template_ids = m.LibraryTemplate.objects.values_list('lib_source', flat=True)
|
||||
return m.LibraryItem.objects.filter(pk__in=template_ids)
|
||||
|
|
|
@ -441,6 +441,7 @@ class TrsImportView(views.APIView):
|
|||
request=s.LibraryItemSerializer,
|
||||
responses={
|
||||
c.HTTP_201_CREATED: s.LibraryItemSerializer,
|
||||
c.HTTP_400_BAD_REQUEST: None,
|
||||
c.HTTP_403_FORBIDDEN: None
|
||||
}
|
||||
)
|
||||
|
@ -449,17 +450,9 @@ def create_rsform(request: Request):
|
|||
''' Endpoint: Create RSForm from user input and/or trs file. '''
|
||||
owner = cast(m.User, request.user) if not request.user.is_anonymous else None
|
||||
if 'file' not in request.FILES:
|
||||
serializer = s.LibraryItemBase(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
schema = m.RSForm.create(
|
||||
title=serializer.validated_data['title'],
|
||||
owner=owner,
|
||||
alias=serializer.validated_data.get('alias', ''),
|
||||
comment=serializer.validated_data.get('comment', ''),
|
||||
visible=serializer.validated_data.get('visible', True),
|
||||
read_only=serializer.validated_data.get('read_only', False),
|
||||
access_policy=serializer.validated_data.get('access_policy', m.AccessPolicy.PUBLIC),
|
||||
location=serializer.validated_data.get('location', m.LocationHead.USER),
|
||||
return Response(
|
||||
status=c.HTTP_400_BAD_REQUEST,
|
||||
data={f'file': msg.missingFile()}
|
||||
)
|
||||
else:
|
||||
data = utils.read_zipped_json(request.FILES['file'].file, utils.EXTEOR_INNER_FILENAME)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { createBrowserRouter } from 'react-router-dom';
|
||||
|
||||
import CreateItemPage from '@/pages/CreateRSFormPage';
|
||||
import CreateItemPage from '@/pages/CreateItemPage';
|
||||
import HomePage from '@/pages/HomePage';
|
||||
import LibraryPage from '@/pages/LibraryPage';
|
||||
import LoginPage from '@/pages/LoginPage';
|
||||
|
|
|
@ -198,7 +198,7 @@ export function getTemplates(request: FrontPull<ILibraryItem[]>) {
|
|||
});
|
||||
}
|
||||
|
||||
export function postNewRSForm(request: FrontExchange<ILibraryCreateData, ILibraryItem>) {
|
||||
export function postRSFormFromFile(request: FrontExchange<ILibraryCreateData, ILibraryItem>) {
|
||||
AxiosPost({
|
||||
endpoint: '/api/rsforms/create-detailed',
|
||||
request: request,
|
||||
|
@ -210,6 +210,13 @@ export function postNewRSForm(request: FrontExchange<ILibraryCreateData, ILibrar
|
|||
});
|
||||
}
|
||||
|
||||
export function postCreateLibraryItem(request: FrontExchange<ILibraryCreateData, ILibraryItem>) {
|
||||
AxiosPost({
|
||||
endpoint: '/api/library',
|
||||
request: request
|
||||
});
|
||||
}
|
||||
|
||||
export function postCloneLibraryItem(target: string, request: FrontExchange<IRSFormCloneData, IRSFormData>) {
|
||||
AxiosPost({
|
||||
endpoint: `/api/library/${target}/clone`,
|
||||
|
|
|
@ -44,6 +44,7 @@ export const urls = {
|
|||
help_topic: (topic: string) => `/manuals?topic=${topic}`,
|
||||
schema: (id: number | string, version?: number | string) =>
|
||||
`/rsforms/${id}` + (version !== undefined ? `?v=${version}` : ''),
|
||||
oss: (id: number | string) => `/oss/${id}`,
|
||||
schema_props: ({ id, tab, version, active }: SchemaProps) => {
|
||||
const versionStr = version !== undefined ? `v=${version}&` : '';
|
||||
const activeStr = active !== undefined ? `&active=${active}` : '';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { AccessPolicy, LocationHead } from '@/models/library';
|
||||
import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library';
|
||||
import { CstMatchMode, DependencyMode } from '@/models/miscellaneous';
|
||||
|
||||
import {
|
||||
|
@ -13,10 +13,12 @@ import {
|
|||
IconGraphInputs,
|
||||
IconGraphOutputs,
|
||||
IconHide,
|
||||
IconOSS,
|
||||
IconPrivate,
|
||||
IconProps,
|
||||
IconProtected,
|
||||
IconPublic,
|
||||
IconRSForm,
|
||||
IconSettings,
|
||||
IconShow,
|
||||
IconTemplates,
|
||||
|
@ -29,6 +31,15 @@ export interface DomIconProps<RequestData> extends IconProps {
|
|||
value: RequestData;
|
||||
}
|
||||
|
||||
export function ItemTypeIcon({ value, size = '1.25rem', className }: DomIconProps<LibraryItemType>) {
|
||||
switch (value) {
|
||||
case LibraryItemType.RSFORM:
|
||||
return <IconRSForm size={size} className={className ?? 'clr-text-primary'} />;
|
||||
case LibraryItemType.OSS:
|
||||
return <IconOSS size={size} className={className ?? 'clr-text-green'} />;
|
||||
}
|
||||
}
|
||||
|
||||
export function PolicyIcon({ value, size = '1.25rem', className }: DomIconProps<AccessPolicy>) {
|
||||
switch (value) {
|
||||
case AccessPolicy.PRIVATE:
|
||||
|
|
|
@ -56,6 +56,8 @@ export { TbBriefcase as IconBusiness } from 'react-icons/tb';
|
|||
export { VscLibrary as IconLibrary } from 'react-icons/vsc';
|
||||
export { IoLibrary as IconLibrary2 } from 'react-icons/io5';
|
||||
export { BiDiamond as IconTemplates } from 'react-icons/bi';
|
||||
export { FaRegObjectGroup as IconOSS } from 'react-icons/fa';
|
||||
export { RiHexagonLine as IconRSForm } from 'react-icons/ri';
|
||||
export { LuArchive as IconArchive } from 'react-icons/lu';
|
||||
export { LuDatabase as IconDatabase } from 'react-icons/lu';
|
||||
export { LuImage as IconImage } from 'react-icons/lu';
|
||||
|
|
62
rsconcept/frontend/src/components/select/SelectItemType.tsx
Normal file
62
rsconcept/frontend/src/components/select/SelectItemType.tsx
Normal file
|
@ -0,0 +1,62 @@
|
|||
'use client';
|
||||
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import Dropdown from '@/components/ui/Dropdown';
|
||||
import useDropdown from '@/hooks/useDropdown';
|
||||
import { LibraryItemType } from '@/models/library';
|
||||
import { prefixes } from '@/utils/constants';
|
||||
import { describeLibraryItemType, labelLibraryItemType } from '@/utils/labels';
|
||||
|
||||
import { ItemTypeIcon } from '../DomainIcons';
|
||||
import DropdownButton from '../ui/DropdownButton';
|
||||
import SelectorButton from '../ui/SelectorButton';
|
||||
|
||||
interface SelectItemTypeProps {
|
||||
value: LibraryItemType;
|
||||
onChange: (value: LibraryItemType) => void;
|
||||
disabled?: boolean;
|
||||
stretchLeft?: boolean;
|
||||
}
|
||||
|
||||
function SelectItemType({ value, disabled, stretchLeft, onChange }: SelectItemTypeProps) {
|
||||
const menu = useDropdown();
|
||||
|
||||
const handleChange = useCallback(
|
||||
(newValue: LibraryItemType) => {
|
||||
menu.hide();
|
||||
if (newValue !== value) {
|
||||
onChange(newValue);
|
||||
}
|
||||
},
|
||||
[menu, value, onChange]
|
||||
);
|
||||
|
||||
return (
|
||||
<div ref={menu.ref}>
|
||||
<SelectorButton
|
||||
transparent
|
||||
title={describeLibraryItemType(value)}
|
||||
hideTitle={menu.isOpen}
|
||||
className='h-full py-1 px-2 disabled:cursor-auto rounded-lg'
|
||||
icon={<ItemTypeIcon value={value} size='1.25rem' />}
|
||||
text={labelLibraryItemType(value)}
|
||||
onClick={menu.toggle}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Dropdown isOpen={menu.isOpen} stretchLeft={stretchLeft}>
|
||||
{Object.values(LibraryItemType).map((item, index) => (
|
||||
<DropdownButton
|
||||
key={`${prefixes.policy_list}${index}`}
|
||||
text={labelLibraryItemType(item)}
|
||||
title={describeLibraryItemType(item)}
|
||||
icon={<ItemTypeIcon value={item} size='1rem' />}
|
||||
onClick={() => handleChange(item)}
|
||||
/>
|
||||
))}
|
||||
</Dropdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SelectItemType;
|
|
@ -34,7 +34,6 @@ function SelectMatchMode({ value, onChange }: SelectMatchModeProps) {
|
|||
<div ref={menu.ref}>
|
||||
<SelectorButton
|
||||
transparent
|
||||
tabIndex={-1}
|
||||
title='Настройка фильтрации по проверяемым атрибутам'
|
||||
hideTitle={menu.isOpen}
|
||||
className='h-full pr-2'
|
||||
|
|
|
@ -26,6 +26,7 @@ function SelectorButton({
|
|||
return (
|
||||
<button
|
||||
type='button'
|
||||
tabIndex={-1}
|
||||
className={clsx(
|
||||
'px-1 flex flex-start items-center gap-1',
|
||||
'text-sm font-controls select-none',
|
||||
|
|
|
@ -10,7 +10,8 @@ import {
|
|||
getRSFormDetails,
|
||||
getTemplates,
|
||||
postCloneLibraryItem,
|
||||
postNewRSForm
|
||||
postCreateLibraryItem,
|
||||
postRSFormFromFile
|
||||
} from '@/app/backendAPI';
|
||||
import { ErrorData } from '@/components/info/InfoError';
|
||||
import { ILibraryItem, LibraryItemID } from '@/models/library';
|
||||
|
@ -181,20 +182,31 @@ export const LibraryState = ({ children }: LibraryStateProps) => {
|
|||
|
||||
const createItem = useCallback(
|
||||
(data: ILibraryCreateData, callback?: DataCallback<ILibraryItem>) => {
|
||||
const onSuccess = (newSchema: ILibraryItem) =>
|
||||
reloadItems(() => {
|
||||
if (user && !user.subscriptions.includes(newSchema.id)) {
|
||||
user.subscriptions.push(newSchema.id);
|
||||
}
|
||||
if (callback) callback(newSchema);
|
||||
});
|
||||
setError(undefined);
|
||||
postNewRSForm({
|
||||
data: data,
|
||||
showError: true,
|
||||
setLoading: setProcessing,
|
||||
onError: setError,
|
||||
onSuccess: newSchema =>
|
||||
reloadItems(() => {
|
||||
if (user && !user.subscriptions.includes(newSchema.id)) {
|
||||
user.subscriptions.push(newSchema.id);
|
||||
}
|
||||
if (callback) callback(newSchema);
|
||||
})
|
||||
});
|
||||
if (data.file) {
|
||||
postRSFormFromFile({
|
||||
data: data,
|
||||
showError: true,
|
||||
setLoading: setProcessing,
|
||||
onError: setError,
|
||||
onSuccess: onSuccess
|
||||
});
|
||||
} else {
|
||||
postCreateLibraryItem({
|
||||
data: data,
|
||||
showError: true,
|
||||
setLoading: setProcessing,
|
||||
onError: setError,
|
||||
onSuccess: onSuccess
|
||||
});
|
||||
}
|
||||
},
|
||||
[reloadItems, user]
|
||||
);
|
||||
|
|
|
@ -9,7 +9,7 @@ import { UserID } from './user';
|
|||
*/
|
||||
export enum LibraryItemType {
|
||||
RSFORM = 'rsform',
|
||||
OPERATIONS_SCHEMA = 'oss'
|
||||
OSS = 'oss'
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,7 @@ import { VisibilityIcon } from '@/components/DomainIcons';
|
|||
import { IconDownload } from '@/components/Icons';
|
||||
import InfoError from '@/components/info/InfoError';
|
||||
import SelectAccessPolicy from '@/components/select/SelectAccessPolicy';
|
||||
import SelectItemType from '@/components/select/SelectItemType';
|
||||
import SelectLocationHead from '@/components/select/SelectLocationHead';
|
||||
import Button from '@/components/ui/Button';
|
||||
import Label from '@/components/ui/Label';
|
||||
|
@ -30,6 +31,7 @@ function FormCreateItem() {
|
|||
const { user } = useAuth();
|
||||
const { createItem, error, setError, processing } = useLibrary();
|
||||
|
||||
const [itemType, setItemType] = useState(LibraryItemType.RSFORM);
|
||||
const [title, setTitle] = useState('');
|
||||
const [alias, setAlias] = useState('');
|
||||
const [comment, setComment] = useState('');
|
||||
|
@ -64,7 +66,7 @@ function FormCreateItem() {
|
|||
return;
|
||||
}
|
||||
const data: ILibraryCreateData = {
|
||||
item_type: LibraryItemType.RSFORM,
|
||||
item_type: itemType,
|
||||
title: title,
|
||||
alias: alias,
|
||||
comment: comment,
|
||||
|
@ -75,9 +77,13 @@ function FormCreateItem() {
|
|||
file: file,
|
||||
fileName: file?.name
|
||||
};
|
||||
createItem(data, newSchema => {
|
||||
createItem(data, newItem => {
|
||||
toast.success('Схема успешно создана');
|
||||
router.push(urls.schema(newSchema.id));
|
||||
if (itemType == LibraryItemType.RSFORM) {
|
||||
router.push(urls.schema(newItem.id));
|
||||
} else {
|
||||
router.push(urls.oss(newItem.id));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -109,8 +115,8 @@ function FormCreateItem() {
|
|||
/>
|
||||
</Overlay>
|
||||
|
||||
<form className={clsx('cc-column', 'min-w-[30rem]', 'px-6 py-3')} onSubmit={handleSubmit}>
|
||||
<h1>Создание концептуальной схемы</h1>
|
||||
<form className={clsx('cc-column', 'min-w-[30rem] max-w-[30rem]', 'px-6 py-3')} onSubmit={handleSubmit}>
|
||||
<h1>Создание схемы</h1>
|
||||
|
||||
{fileName ? <Label text={`Загружен файл: ${fileName}`} /> : null}
|
||||
|
||||
|
@ -135,11 +141,14 @@ function FormCreateItem() {
|
|||
value={alias}
|
||||
onChange={event => setAlias(event.target.value)}
|
||||
/>
|
||||
<div className='flex flex-col items-center gap-2'>
|
||||
<Label text='Тип схемы' className='self-center select-none' />
|
||||
<SelectItemType value={itemType} onChange={setItemType} />
|
||||
</div>
|
||||
<div className='flex flex-col gap-2'>
|
||||
<Label text='Доступ' className='self-center select-none' />
|
||||
<div className='ml-auto cc-icons'>
|
||||
<SelectAccessPolicy value={policy} onChange={newPolicy => setPolicy(newPolicy)} />
|
||||
|
||||
<SelectAccessPolicy value={policy} onChange={setPolicy} />
|
||||
<MiniButton
|
||||
className='disabled:cursor-auto'
|
||||
title={visible ? 'Библиотека: отображать' : 'Библиотека: скрывать'}
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import clsx from 'clsx';
|
||||
|
||||
import Divider from '@/components/ui/Divider';
|
||||
import FlexColumn from '@/components/ui/FlexColumn';
|
||||
import AnimateFade from '@/components/wrap/AnimateFade';
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
|
@ -52,9 +51,6 @@ function EditorRSForm({ isModified, onDestroy, setIsModified }: EditorRSFormProp
|
|||
<AnimateFade onKeyDown={handleInput} className={clsx('sm:w-fit mx-auto', 'flex flex-col sm:flex-row')}>
|
||||
<FlexColumn className='px-3'>
|
||||
<FormRSForm id={globals.library_item_editor} isModified={isModified} setIsModified={setIsModified} />
|
||||
|
||||
<Divider margins='my-1' />
|
||||
|
||||
<EditorLibraryItem item={schema} isModified={isModified} />
|
||||
</FlexColumn>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
import { GraphLayout } from '@/components/ui/GraphUI';
|
||||
import { GramData, Grammeme, ReferenceType } from '@/models/language';
|
||||
import { AccessPolicy, LocationHead } from '@/models/library';
|
||||
import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library';
|
||||
import { CstMatchMode, DependencyMode, GraphColoring, GraphSizing, HelpTopic } from '@/models/miscellaneous';
|
||||
import { CstClass, CstType, ExpressionStatus, IConstituenta, IRSForm } from '@/models/rsform';
|
||||
import {
|
||||
|
@ -821,6 +821,28 @@ export function describeAccessPolicy(policy: AccessPolicy): string {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves label for {@link LibraryItemType}.
|
||||
*/
|
||||
export function labelLibraryItemType(itemType: LibraryItemType): string {
|
||||
// prettier-ignore
|
||||
switch (itemType) {
|
||||
case LibraryItemType.RSFORM: return 'КС';
|
||||
case LibraryItemType.OSS: return 'ОСС';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves description for {@link LibraryItemType}.
|
||||
*/
|
||||
export function describeLibraryItemType(itemType: LibraryItemType): string {
|
||||
// prettier-ignore
|
||||
switch (itemType) {
|
||||
case LibraryItemType.RSFORM: return 'Концептуальная схема';
|
||||
case LibraryItemType.OSS: return 'Операционная схема синтеза';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI shared messages.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue
Block a user