Compare commits
5 Commits
d23f02420a
...
21a304701e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
21a304701e | ||
![]() |
8f29c69b49 | ||
![]() |
d4fe453840 | ||
![]() |
a2882777aa | ||
![]() |
64076ec7d2 |
|
@ -14,7 +14,7 @@ class OperationAdmin(admin.ModelAdmin):
|
||||||
class ArgumentAdmin(admin.ModelAdmin):
|
class ArgumentAdmin(admin.ModelAdmin):
|
||||||
''' Admin model: Operation arguments. '''
|
''' Admin model: Operation arguments. '''
|
||||||
ordering = ['operation']
|
ordering = ['operation']
|
||||||
list_display = ['id', 'operation', 'argument']
|
list_display = ['id', 'order', 'operation', 'argument']
|
||||||
search_fields = ['id', 'operation', 'argument']
|
search_fields = ['id', 'operation', 'argument']
|
||||||
|
|
||||||
|
|
||||||
|
|
18
rsconcept/backend/apps/oss/migrations/0007_argument_order.py
Normal file
18
rsconcept/backend/apps/oss/migrations/0007_argument_order.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 5.1 on 2024-09-04 09:54
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('oss', '0006_alter_operation_oss'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='argument',
|
||||||
|
name='order',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='Позиция'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,5 +1,5 @@
|
||||||
''' Models: Operation Argument in OSS. '''
|
''' Models: Operation Argument in OSS. '''
|
||||||
from django.db.models import CASCADE, ForeignKey, Model
|
from django.db.models import CASCADE, ForeignKey, Model, PositiveIntegerField
|
||||||
|
|
||||||
|
|
||||||
class Argument(Model):
|
class Argument(Model):
|
||||||
|
@ -16,6 +16,10 @@ class Argument(Model):
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
related_name='descendants'
|
related_name='descendants'
|
||||||
)
|
)
|
||||||
|
order: PositiveIntegerField = PositiveIntegerField(
|
||||||
|
verbose_name='Позиция',
|
||||||
|
default=0,
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
''' Model metadata. '''
|
''' Model metadata. '''
|
||||||
|
|
|
@ -137,23 +137,27 @@ class OperationSchema:
|
||||||
self.cache.ensure_loaded()
|
self.cache.ensure_loaded()
|
||||||
operation = self.cache.operation_by_id[target]
|
operation = self.cache.operation_by_id[target]
|
||||||
processed: list[Operation] = []
|
processed: list[Operation] = []
|
||||||
|
updated: list[Argument] = []
|
||||||
deleted: list[Argument] = []
|
deleted: list[Argument] = []
|
||||||
for current in operation.getArguments():
|
for current in operation.getArguments():
|
||||||
if current.argument not in arguments:
|
if current.argument not in arguments:
|
||||||
deleted.append(current)
|
deleted.append(current)
|
||||||
else:
|
else:
|
||||||
processed.append(current.argument)
|
processed.append(current.argument)
|
||||||
|
current.order = arguments.index(current.argument)
|
||||||
|
updated.append(current)
|
||||||
if len(deleted) > 0:
|
if len(deleted) > 0:
|
||||||
self.before_delete_arguments(operation, [x.argument for x in deleted])
|
self.before_delete_arguments(operation, [x.argument for x in deleted])
|
||||||
for deleted_arg in deleted:
|
for deleted_arg in deleted:
|
||||||
self.cache.remove_argument(deleted_arg)
|
self.cache.remove_argument(deleted_arg)
|
||||||
Argument.objects.filter(pk__in=[x.pk for x in deleted]).delete()
|
Argument.objects.filter(pk__in=[x.pk for x in deleted]).delete()
|
||||||
|
Argument.objects.bulk_update(updated, ['order'])
|
||||||
|
|
||||||
added: list[Operation] = []
|
added: list[Operation] = []
|
||||||
for arg in arguments:
|
for order, arg in enumerate(arguments):
|
||||||
if arg not in processed:
|
if arg not in processed:
|
||||||
processed.append(arg)
|
processed.append(arg)
|
||||||
new_arg = Argument.objects.create(operation=operation, argument=arg)
|
new_arg = Argument.objects.create(operation=operation, argument=arg, order=order)
|
||||||
self.cache.insert_argument(new_arg)
|
self.cache.insert_argument(new_arg)
|
||||||
added.append(arg)
|
added.append(arg)
|
||||||
if len(added) > 0:
|
if len(added) > 0:
|
||||||
|
@ -219,7 +223,7 @@ class OperationSchema:
|
||||||
|
|
||||||
def execute_operation(self, operation: Operation) -> bool:
|
def execute_operation(self, operation: Operation) -> bool:
|
||||||
''' Execute target operation. '''
|
''' Execute target operation. '''
|
||||||
schemas: list[LibraryItem] = [arg.argument.result for arg in operation.getArguments().order_by('pk')]
|
schemas: list[LibraryItem] = [arg.argument.result for arg in operation.getArguments().order_by('order')]
|
||||||
if None in schemas:
|
if None in schemas:
|
||||||
return False
|
return False
|
||||||
substitutions = operation.getSubstitutions()
|
substitutions = operation.getSubstitutions()
|
||||||
|
@ -693,7 +697,7 @@ class OssCache:
|
||||||
self.graph = Graph[int]()
|
self.graph = Graph[int]()
|
||||||
for operation in self.operations:
|
for operation in self.operations:
|
||||||
self.graph.add_node(operation.pk)
|
self.graph.add_node(operation.pk)
|
||||||
for argument in self._oss.arguments().only('operation_id', 'argument_id'):
|
for argument in self._oss.arguments().only('operation_id', 'argument_id').order_by('order'):
|
||||||
self.graph.add_edge(argument.argument_id, argument.operation_id)
|
self.graph.add_edge(argument.argument_id, argument.operation_id)
|
||||||
|
|
||||||
self.is_loaded = False
|
self.is_loaded = False
|
||||||
|
|
|
@ -210,7 +210,7 @@ class OperationSchemaSerializer(serializers.ModelSerializer):
|
||||||
for operation in oss.operations().order_by('pk'):
|
for operation in oss.operations().order_by('pk'):
|
||||||
result['items'].append(OperationSerializer(operation).data)
|
result['items'].append(OperationSerializer(operation).data)
|
||||||
result['arguments'] = []
|
result['arguments'] = []
|
||||||
for argument in oss.arguments().order_by('pk'):
|
for argument in oss.arguments().order_by('order'):
|
||||||
result['arguments'].append(ArgumentSerializer(argument).data)
|
result['arguments'].append(ArgumentSerializer(argument).data)
|
||||||
result['substitutions'] = []
|
result['substitutions'] = []
|
||||||
for substitution in oss.substitutions().values(
|
for substitution in oss.substitutions().values(
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
''' Testing models: Argument. '''
|
''' Testing models: Argument. '''
|
||||||
|
from django.db.utils import IntegrityError
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from apps.oss.models import Argument, Operation, OperationSchema, OperationType
|
from apps.oss.models import Argument, Operation, OperationSchema, OperationType
|
||||||
|
@ -36,6 +37,15 @@ class TestArgument(TestCase):
|
||||||
self.assertEqual(str(self.argument), testStr)
|
self.assertEqual(str(self.argument), testStr)
|
||||||
|
|
||||||
|
|
||||||
|
def test_order_positive_integer(self):
|
||||||
|
with self.assertRaises(IntegrityError):
|
||||||
|
Argument.objects.create(
|
||||||
|
operation=self.operation2,
|
||||||
|
argument=self.operation3,
|
||||||
|
order=-1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_cascade_delete_operation(self):
|
def test_cascade_delete_operation(self):
|
||||||
self.assertEqual(Argument.objects.count(), 1)
|
self.assertEqual(Argument.objects.count(), 1)
|
||||||
self.operation2.delete()
|
self.operation2.delete()
|
||||||
|
|
|
@ -387,7 +387,7 @@ class TestOssViewset(EndpointTester):
|
||||||
'comment': 'Comment mod'
|
'comment': 'Comment mod'
|
||||||
},
|
},
|
||||||
'positions': [],
|
'positions': [],
|
||||||
'arguments': [self.operation1.pk, self.operation2.pk],
|
'arguments': [self.operation2.pk, self.operation1.pk],
|
||||||
'substitutions': [
|
'substitutions': [
|
||||||
{
|
{
|
||||||
'original': self.ks1X1.pk,
|
'original': self.ks1X1.pk,
|
||||||
|
@ -409,7 +409,11 @@ class TestOssViewset(EndpointTester):
|
||||||
self.assertEqual(self.operation3.alias, data['item_data']['alias'])
|
self.assertEqual(self.operation3.alias, data['item_data']['alias'])
|
||||||
self.assertEqual(self.operation3.title, data['item_data']['title'])
|
self.assertEqual(self.operation3.title, data['item_data']['title'])
|
||||||
self.assertEqual(self.operation3.comment, data['item_data']['comment'])
|
self.assertEqual(self.operation3.comment, data['item_data']['comment'])
|
||||||
self.assertEqual(set([argument.pk for argument in self.operation3.getArguments()]), set(data['arguments']))
|
args = self.operation3.getArguments().order_by('order')
|
||||||
|
self.assertEqual(args[0].argument.pk, data['arguments'][0])
|
||||||
|
self.assertEqual(args[0].order, 0)
|
||||||
|
self.assertEqual(args[1].argument.pk, data['arguments'][1])
|
||||||
|
self.assertEqual(args[1].order, 1)
|
||||||
sub = self.operation3.getSubstitutions()[0]
|
sub = self.operation3.getSubstitutions()[0]
|
||||||
self.assertEqual(sub.original.pk, data['substitutions'][0]['original'])
|
self.assertEqual(sub.original.pk, data['substitutions'][0]['original'])
|
||||||
self.assertEqual(sub.substitution.pk, data['substitutions'][0]['substitution'])
|
self.assertEqual(sub.substitution.pk, data['substitutions'][0]['substitution'])
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 5.1 on 2024-09-04 09:56
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('rsform', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='constituenta',
|
||||||
|
name='order',
|
||||||
|
field=models.PositiveIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1)], verbose_name='Позиция'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -58,7 +58,7 @@ class Constituenta(Model):
|
||||||
order: PositiveIntegerField = PositiveIntegerField(
|
order: PositiveIntegerField = PositiveIntegerField(
|
||||||
verbose_name='Позиция',
|
verbose_name='Позиция',
|
||||||
validators=[MinValueValidator(1)],
|
validators=[MinValueValidator(1)],
|
||||||
default=-1,
|
default=1,
|
||||||
)
|
)
|
||||||
alias: CharField = CharField(
|
alias: CharField = CharField(
|
||||||
verbose_name='Имя',
|
verbose_name='Имя',
|
||||||
|
|
|
@ -20,11 +20,6 @@ class TestConstituenta(TestCase):
|
||||||
self.assertEqual(str(cst), testStr)
|
self.assertEqual(str(cst), testStr)
|
||||||
|
|
||||||
|
|
||||||
def test_order_not_null(self):
|
|
||||||
with self.assertRaises(IntegrityError):
|
|
||||||
Constituenta.objects.create(alias='X1', schema=self.schema1.model)
|
|
||||||
|
|
||||||
|
|
||||||
def test_order_positive_integer(self):
|
def test_order_positive_integer(self):
|
||||||
with self.assertRaises(IntegrityError):
|
with self.assertRaises(IntegrityError):
|
||||||
Constituenta.objects.create(alias='X1', schema=self.schema1.model, order=-1)
|
Constituenta.objects.create(alias='X1', schema=self.schema1.model, order=-1)
|
||||||
|
|
158
rsconcept/frontend/package-lock.json
generated
158
rsconcept/frontend/package-lock.json
generated
|
@ -14,7 +14,7 @@
|
||||||
"@uiw/react-codemirror": "^4.23.0",
|
"@uiw/react-codemirror": "^4.23.0",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"framer-motion": "^11.3.31",
|
"framer-motion": "^11.5.1",
|
||||||
"html-to-image": "^1.11.11",
|
"html-to-image": "^1.11.11",
|
||||||
"js-file-download": "^0.4.12",
|
"js-file-download": "^0.4.12",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lezer/generator": "^1.7.1",
|
"@lezer/generator": "^1.7.1",
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/node": "^22.5.2",
|
"@types/node": "^22.5.3",
|
||||||
"@types/react": "^18.3.5",
|
"@types/react": "^18.3.5",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.0.1",
|
"@typescript-eslint/eslint-plugin": "^8.0.1",
|
||||||
|
@ -44,16 +44,16 @@
|
||||||
"@vitejs/plugin-react": "^4.3.1",
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.9.1",
|
||||||
"eslint-plugin-react": "^7.35.0",
|
"eslint-plugin-react": "^7.35.2",
|
||||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"postcss": "^8.4.44",
|
"postcss": "^8.4.45",
|
||||||
"tailwindcss": "^3.4.10",
|
"tailwindcss": "^3.4.10",
|
||||||
"ts-jest": "^29.2.5",
|
"ts-jest": "^29.2.5",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"typescript-eslint": "^8.3.0",
|
"typescript-eslint": "^8.4.0",
|
||||||
"vite": "^5.4.2"
|
"vite": "^5.4.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@alloc/quick-lru": {
|
"node_modules/@alloc/quick-lru": {
|
||||||
|
@ -3549,9 +3549,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "22.5.2",
|
"version": "22.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.3.tgz",
|
||||||
"integrity": "sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==",
|
"integrity": "sha512-njripolh85IA9SQGTAqbmnNZTdxv7X/4OYGPz8tgy5JDr8MP+uDBa921GpYEoDDnwm0Hmn5ZPeJgiiSTPoOzkQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -3672,17 +3672,17 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.3.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.4.0.tgz",
|
||||||
"integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==",
|
"integrity": "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.3.0",
|
"@typescript-eslint/scope-manager": "8.4.0",
|
||||||
"@typescript-eslint/type-utils": "8.3.0",
|
"@typescript-eslint/type-utils": "8.4.0",
|
||||||
"@typescript-eslint/utils": "8.3.0",
|
"@typescript-eslint/utils": "8.4.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.3.0",
|
"@typescript-eslint/visitor-keys": "8.4.0",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^5.3.1",
|
"ignore": "^5.3.1",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
|
@ -3706,16 +3706,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.3.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.4.0.tgz",
|
||||||
"integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==",
|
"integrity": "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.3.0",
|
"@typescript-eslint/scope-manager": "8.4.0",
|
||||||
"@typescript-eslint/types": "8.3.0",
|
"@typescript-eslint/types": "8.4.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.3.0",
|
"@typescript-eslint/typescript-estree": "8.4.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.3.0",
|
"@typescript-eslint/visitor-keys": "8.4.0",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3735,14 +3735,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.3.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.4.0.tgz",
|
||||||
"integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==",
|
"integrity": "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.3.0",
|
"@typescript-eslint/types": "8.4.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.3.0"
|
"@typescript-eslint/visitor-keys": "8.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
@ -3753,14 +3753,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.3.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.4.0.tgz",
|
||||||
"integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==",
|
"integrity": "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.3.0",
|
"@typescript-eslint/typescript-estree": "8.4.0",
|
||||||
"@typescript-eslint/utils": "8.3.0",
|
"@typescript-eslint/utils": "8.4.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^1.3.0"
|
"ts-api-utils": "^1.3.0"
|
||||||
},
|
},
|
||||||
|
@ -3778,9 +3778,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.3.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.4.0.tgz",
|
||||||
"integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==",
|
"integrity": "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3792,14 +3792,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.3.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.4.0.tgz",
|
||||||
"integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==",
|
"integrity": "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.3.0",
|
"@typescript-eslint/types": "8.4.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.3.0",
|
"@typescript-eslint/visitor-keys": "8.4.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
|
@ -3821,16 +3821,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.3.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.4.0.tgz",
|
||||||
"integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==",
|
"integrity": "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
"@typescript-eslint/scope-manager": "8.3.0",
|
"@typescript-eslint/scope-manager": "8.4.0",
|
||||||
"@typescript-eslint/types": "8.3.0",
|
"@typescript-eslint/types": "8.4.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.3.0"
|
"@typescript-eslint/typescript-estree": "8.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
@ -3844,13 +3844,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.3.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.4.0.tgz",
|
||||||
"integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==",
|
"integrity": "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.3.0",
|
"@typescript-eslint/types": "8.4.0",
|
||||||
"eslint-visitor-keys": "^3.4.3"
|
"eslint-visitor-keys": "^3.4.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -5942,9 +5942,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-react": {
|
"node_modules/eslint-plugin-react": {
|
||||||
"version": "7.35.0",
|
"version": "7.35.2",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.2.tgz",
|
||||||
"integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==",
|
"integrity": "sha512-Rbj2R9zwP2GYNcIak4xoAMV57hrBh3hTaR0k7hVjwCQgryE/pw5px4b13EYjduOI0hfXyZhwBxaGpOTbWSGzKQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -6495,9 +6495,9 @@
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.6",
|
"version": "1.15.8",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.8.tgz",
|
||||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
"integrity": "sha512-xgrmBhBToVKay1q2Tao5LI26B83UhrB/vM1avwVSDzt8rx3rO6AizBAaF46EgksTVr+rFTQaqZZ9MVBfUe4nig==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
|
@ -6583,9 +6583,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/framer-motion": {
|
"node_modules/framer-motion": {
|
||||||
"version": "11.3.31",
|
"version": "11.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.3.31.tgz",
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.5.1.tgz",
|
||||||
"integrity": "sha512-Xmxs08WBXnc2tNzNZbFSpquI33lvleJg4Y+hmZ+vFkn+laN9ZnR3gbZnNGKDtuz7c/x3u8dLg05OU3EhLobCsg==",
|
"integrity": "sha512-8QI17IxYiqWo+lIXmAopG+6NEi10CgTL1AlQRpcNcSxoyrrcRgXB/tc6pzmeloZ3y4xTdoFCN/s4mJAdTz6Clw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
|
@ -10442,9 +10442,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.0.1",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
|
||||||
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
|
"integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
|
@ -10560,9 +10560,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.44",
|
"version": "8.4.45",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.44.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz",
|
||||||
"integrity": "sha512-Aweb9unOEpQ3ezu4Q00DPvvM2ZTUitJdNKeP/+uQgr1IBIqu574IaZoURId7BKtWMREwzKa9OgzPzezWGPWFQw==",
|
"integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -10694,9 +10694,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-load-config/node_modules/yaml": {
|
"node_modules/postcss-load-config/node_modules/yaml": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz",
|
||||||
"integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==",
|
"integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -12531,15 +12531,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript-eslint": {
|
"node_modules/typescript-eslint": {
|
||||||
"version": "8.3.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.4.0.tgz",
|
||||||
"integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==",
|
"integrity": "sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "8.3.0",
|
"@typescript-eslint/eslint-plugin": "8.4.0",
|
||||||
"@typescript-eslint/parser": "8.3.0",
|
"@typescript-eslint/parser": "8.4.0",
|
||||||
"@typescript-eslint/utils": "8.3.0"
|
"@typescript-eslint/utils": "8.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
@ -12698,14 +12698,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.4.2",
|
"version": "5.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.3.tgz",
|
||||||
"integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==",
|
"integrity": "sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.21.3",
|
"esbuild": "^0.21.3",
|
||||||
"postcss": "^8.4.41",
|
"postcss": "^8.4.43",
|
||||||
"rollup": "^4.20.0"
|
"rollup": "^4.20.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
"@uiw/react-codemirror": "^4.23.0",
|
"@uiw/react-codemirror": "^4.23.0",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"framer-motion": "^11.3.31",
|
"framer-motion": "^11.5.1",
|
||||||
"html-to-image": "^1.11.11",
|
"html-to-image": "^1.11.11",
|
||||||
"js-file-download": "^0.4.12",
|
"js-file-download": "^0.4.12",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lezer/generator": "^1.7.1",
|
"@lezer/generator": "^1.7.1",
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/node": "^22.5.2",
|
"@types/node": "^22.5.3",
|
||||||
"@types/react": "^18.3.5",
|
"@types/react": "^18.3.5",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.0.1",
|
"@typescript-eslint/eslint-plugin": "^8.0.1",
|
||||||
|
@ -48,16 +48,16 @@
|
||||||
"@vitejs/plugin-react": "^4.3.1",
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.9.1",
|
||||||
"eslint-plugin-react": "^7.35.0",
|
"eslint-plugin-react": "^7.35.2",
|
||||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"postcss": "^8.4.44",
|
"postcss": "^8.4.45",
|
||||||
"tailwindcss": "^3.4.10",
|
"tailwindcss": "^3.4.10",
|
||||||
"ts-jest": "^29.2.5",
|
"ts-jest": "^29.2.5",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"typescript-eslint": "^8.3.0",
|
"typescript-eslint": "^8.4.0",
|
||||||
"vite": "^5.4.2"
|
"vite": "^5.4.3"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"preset": "ts-jest",
|
"preset": "ts-jest",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 118 KiB |
|
@ -9,7 +9,7 @@ interface BadgeWordFormProps {
|
||||||
|
|
||||||
function BadgeWordForm({ keyPrefix, form }: BadgeWordFormProps) {
|
function BadgeWordForm({ keyPrefix, form }: BadgeWordFormProps) {
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-wrap justify-start gap-1 select-none'>
|
<div className='flex flex-wrap justify-start gap-1 select-none w-fit'>
|
||||||
{form.grams.map(gram => (
|
{form.grams.map(gram => (
|
||||||
<BadgeGrammeme key={`${keyPrefix}-${gram}`} grammeme={gram} />
|
<BadgeGrammeme key={`${keyPrefix}-${gram}`} grammeme={gram} />
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { IconRemove } from '@/components/Icons';
|
import { IconMoveDown, IconMoveUp, IconRemove } from '@/components/Icons';
|
||||||
import SelectOperation from '@/components/select/SelectOperation';
|
import SelectOperation from '@/components/select/SelectOperation';
|
||||||
import DataTable, { createColumnHelper } from '@/components/ui/DataTable';
|
import DataTable, { createColumnHelper } from '@/components/ui/DataTable';
|
||||||
import MiniButton from '@/components/ui/MiniButton';
|
import MiniButton from '@/components/ui/MiniButton';
|
||||||
|
@ -20,7 +20,10 @@ interface PickMultiOperationProps {
|
||||||
const columnHelper = createColumnHelper<IOperation>();
|
const columnHelper = createColumnHelper<IOperation>();
|
||||||
|
|
||||||
function PickMultiOperation({ rows, items, selected, setSelected }: PickMultiOperationProps) {
|
function PickMultiOperation({ rows, items, selected, setSelected }: PickMultiOperationProps) {
|
||||||
const selectedItems = useMemo(() => items.filter(item => selected.includes(item.id)), [items, selected]);
|
const selectedItems = useMemo(
|
||||||
|
() => selected.map(itemID => items.find(item => item.id === itemID)!),
|
||||||
|
[items, selected]
|
||||||
|
);
|
||||||
const nonSelectedItems = useMemo(() => items.filter(item => !selected.includes(item.id)), [items, selected]);
|
const nonSelectedItems = useMemo(() => items.filter(item => !selected.includes(item.id)), [items, selected]);
|
||||||
const [lastSelected, setLastSelected] = useState<IOperation | undefined>(undefined);
|
const [lastSelected, setLastSelected] = useState<IOperation | undefined>(undefined);
|
||||||
|
|
||||||
|
@ -40,6 +43,36 @@ function PickMultiOperation({ rows, items, selected, setSelected }: PickMultiOpe
|
||||||
[setSelected]
|
[setSelected]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleMoveUp = useCallback(
|
||||||
|
(operation: OperationID) => {
|
||||||
|
const index = selected.indexOf(operation);
|
||||||
|
if (index > 0) {
|
||||||
|
setSelected(prev => {
|
||||||
|
const newSelected = [...prev];
|
||||||
|
newSelected[index] = newSelected[index - 1];
|
||||||
|
newSelected[index - 1] = operation;
|
||||||
|
return newSelected;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[setSelected, selected]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleMoveDown = useCallback(
|
||||||
|
(operation: OperationID) => {
|
||||||
|
const index = selected.indexOf(operation);
|
||||||
|
if (index < selected.length - 1) {
|
||||||
|
setSelected(prev => {
|
||||||
|
const newSelected = [...prev];
|
||||||
|
newSelected[index] = newSelected[index + 1];
|
||||||
|
newSelected[index + 1] = operation;
|
||||||
|
return newSelected;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[setSelected, selected]
|
||||||
|
);
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
columnHelper.accessor('alias', {
|
columnHelper.accessor('alias', {
|
||||||
|
@ -59,17 +92,35 @@ function PickMultiOperation({ rows, items, selected, setSelected }: PickMultiOpe
|
||||||
}),
|
}),
|
||||||
columnHelper.display({
|
columnHelper.display({
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
|
size: 0,
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<MiniButton
|
<div className='flex gap-1 w-fit'>
|
||||||
noHover
|
<MiniButton
|
||||||
title='Удалить'
|
noHover
|
||||||
icon={<IconRemove size='1rem' className='icon-red' />}
|
className='px-0'
|
||||||
onClick={() => handleDelete(props.row.original.id)}
|
title='Удалить'
|
||||||
/>
|
icon={<IconRemove size='1rem' className='icon-red' />}
|
||||||
|
onClick={() => handleDelete(props.row.original.id)}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
noHover
|
||||||
|
className='px-0'
|
||||||
|
title='Выше'
|
||||||
|
icon={<IconMoveUp size='1rem' className='icon-primary' />}
|
||||||
|
onClick={() => handleMoveUp(props.row.original.id)}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
noHover
|
||||||
|
title='Ниже'
|
||||||
|
className='px-0'
|
||||||
|
icon={<IconMoveDown size='1rem' className='icon-primary' />}
|
||||||
|
onClick={() => handleMoveDown(props.row.original.id)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
[handleDelete]
|
[handleDelete, handleMoveUp, handleMoveDown]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -187,7 +187,7 @@ function PickSubstitutions({
|
||||||
}),
|
}),
|
||||||
columnHelper.display({
|
columnHelper.display({
|
||||||
id: 'status',
|
id: 'status',
|
||||||
size: 40,
|
size: 0,
|
||||||
cell: () => <IconPageRight size='1.2rem' />
|
cell: () => <IconPageRight size='1.2rem' />
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor(item => item.original.alias, {
|
columnHelper.accessor(item => item.original.alias, {
|
||||||
|
@ -204,6 +204,7 @@ function PickSubstitutions({
|
||||||
}),
|
}),
|
||||||
columnHelper.display({
|
columnHelper.display({
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
|
size: 0,
|
||||||
cell: props =>
|
cell: props =>
|
||||||
props.row.original.is_suggestion ? (
|
props.row.original.is_suggestion ? (
|
||||||
<div className='max-w-fit'>
|
<div className='max-w-fit'>
|
||||||
|
|
|
@ -260,12 +260,13 @@ export const OssState = ({ itemID, children }: OssStateProps) => {
|
||||||
onError: setProcessingError,
|
onError: setProcessingError,
|
||||||
onSuccess: newData => {
|
onSuccess: newData => {
|
||||||
oss.setData(newData);
|
oss.setData(newData);
|
||||||
library.localUpdateTimestamp(newData.id);
|
library.reloadItems(() => {
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[itemID, library.localUpdateTimestamp, oss.setData]
|
[itemID, library.reloadItems, oss.setData]
|
||||||
);
|
);
|
||||||
|
|
||||||
const createInput = useCallback(
|
const createInput = useCallback(
|
||||||
|
|
|
@ -117,6 +117,7 @@ function TabArguments({ state, schema, partialUpdate }: TabArgumentsProps) {
|
||||||
}),
|
}),
|
||||||
argumentsHelper.display({
|
argumentsHelper.display({
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
|
size: 0,
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<div className='h-[1.25rem] w-[1.25rem]'>
|
<div className='h-[1.25rem] w-[1.25rem]'>
|
||||||
{props.row.original.value ? (
|
{props.row.original.value ? (
|
||||||
|
@ -190,7 +191,7 @@ function TabArguments({ state, schema, partialUpdate }: TabArgumentsProps) {
|
||||||
title='Подставить значение аргумента'
|
title='Подставить значение аргумента'
|
||||||
noHover
|
noHover
|
||||||
className='py-0'
|
className='py-0'
|
||||||
icon={<IconAccept size='2rem' className='icon-green' />}
|
icon={<IconAccept size='1.5rem' className='icon-green' />}
|
||||||
disabled={!argumentValue || !selectedArgument}
|
disabled={!argumentValue || !selectedArgument}
|
||||||
onClick={() => handleAssignArgument(selectedArgument!, argumentValue)}
|
onClick={() => handleAssignArgument(selectedArgument!, argumentValue)}
|
||||||
/>
|
/>
|
||||||
|
@ -200,7 +201,7 @@ function TabArguments({ state, schema, partialUpdate }: TabArgumentsProps) {
|
||||||
className='py-0'
|
className='py-0'
|
||||||
disabled={!isModified}
|
disabled={!isModified}
|
||||||
onClick={handleReset}
|
onClick={handleReset}
|
||||||
icon={<IconReset size='2rem' className='icon-primary' />}
|
icon={<IconReset size='1.5rem' className='icon-primary' />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -29,9 +29,7 @@ function TableUsers({ items, onDelete }: TableUsersProps) {
|
||||||
}),
|
}),
|
||||||
columnHelper.display({
|
columnHelper.display({
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
size: 50,
|
size: 0,
|
||||||
minSize: 50,
|
|
||||||
maxSize: 50,
|
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<div className='h-[1.25rem] w-[1.25rem]'>
|
<div className='h-[1.25rem] w-[1.25rem]'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
|
|
|
@ -56,9 +56,7 @@ function TableVersions({ processing, items, onDelete, selected, onSelect }: Tabl
|
||||||
}),
|
}),
|
||||||
columnHelper.display({
|
columnHelper.display({
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
size: 50,
|
size: 0,
|
||||||
minSize: 50,
|
|
||||||
maxSize: 50,
|
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<div className='h-[1.25rem] w-[1.25rem]'>
|
<div className='h-[1.25rem] w-[1.25rem]'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
|
|
|
@ -41,18 +41,16 @@ function TableWordForms({ forms, setForms, onFormSelect }: TableWordFormsProps)
|
||||||
size: 350,
|
size: 350,
|
||||||
minSize: 500,
|
minSize: 500,
|
||||||
maxSize: 500,
|
maxSize: 500,
|
||||||
cell: props => <div className='min-w-[20rem]'>{props.getValue()}</div>
|
cell: props => <div className='min-w-[25rem]'>{props.getValue()}</div>
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor('grams', {
|
columnHelper.accessor('grams', {
|
||||||
id: 'grams',
|
id: 'grams',
|
||||||
maxSize: 150,
|
size: 0,
|
||||||
cell: props => <BadgeWordForm keyPrefix={props.cell.id} form={props.row.original} />
|
cell: props => <BadgeWordForm keyPrefix={props.cell.id} form={props.row.original} />
|
||||||
}),
|
}),
|
||||||
columnHelper.display({
|
columnHelper.display({
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
size: 50,
|
size: 0,
|
||||||
minSize: 50,
|
|
||||||
maxSize: 50,
|
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<div className='h-[1.25rem] w-[1.25rem]'>
|
<div className='h-[1.25rem] w-[1.25rem]'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
|
|
|
@ -114,24 +114,33 @@ function FormCreateItem() {
|
||||||
handleSelectLocation(initLocation);
|
handleSelectLocation(initLocation);
|
||||||
}, [initLocation, handleSelectLocation]);
|
}, [initLocation, handleSelectLocation]);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (itemType !== LibraryItemType.RSFORM) {
|
||||||
|
setFile(undefined);
|
||||||
|
setFileName('');
|
||||||
|
}
|
||||||
|
}, [itemType]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className={clsx('cc-column', 'min-w-[30rem] max-w-[30rem] mx-auto', 'px-6 py-3')} onSubmit={handleSubmit}>
|
<form className={clsx('cc-column', 'min-w-[30rem] max-w-[30rem] mx-auto', 'px-6 py-3')} onSubmit={handleSubmit}>
|
||||||
<h1>
|
<h1>
|
||||||
<Overlay position='top-0 right-[0.5rem]'>
|
{itemType == LibraryItemType.RSFORM ? (
|
||||||
<input
|
<Overlay position='top-0 right-[0.5rem]'>
|
||||||
id='schema_file'
|
<input
|
||||||
ref={inputRef}
|
id='schema_file'
|
||||||
type='file'
|
ref={inputRef}
|
||||||
style={{ display: 'none' }}
|
type='file'
|
||||||
accept={EXTEOR_TRS_FILE}
|
style={{ display: 'none' }}
|
||||||
onChange={handleFileChange}
|
accept={EXTEOR_TRS_FILE}
|
||||||
/>
|
onChange={handleFileChange}
|
||||||
<MiniButton
|
/>
|
||||||
title='Загрузить из Экстеор'
|
<MiniButton
|
||||||
icon={<IconDownload size='1.25rem' className='icon-primary' />}
|
title='Загрузить из Экстеор'
|
||||||
onClick={() => inputRef.current?.click()}
|
icon={<IconDownload size='1.25rem' className='icon-primary' />}
|
||||||
/>
|
onClick={() => inputRef.current?.click()}
|
||||||
</Overlay>
|
/>
|
||||||
|
</Overlay>
|
||||||
|
) : null}
|
||||||
Создание схемы
|
Создание схемы
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
@ -156,12 +165,10 @@ function FormCreateItem() {
|
||||||
value={alias}
|
value={alias}
|
||||||
onChange={event => setAlias(event.target.value)}
|
onChange={event => setAlias(event.target.value)}
|
||||||
/>
|
/>
|
||||||
{user?.is_staff ? (
|
<div className='flex flex-col items-center gap-2'>
|
||||||
<div className='flex flex-col items-center gap-2'>
|
<Label text='Тип схемы' className='self-center select-none' />
|
||||||
<Label text='Тип схемы' className='self-center select-none' />
|
<SelectItemType value={itemType} onChange={setItemType} />
|
||||||
<SelectItemType value={itemType} onChange={setItemType} />
|
</div>
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<div className='flex flex-col gap-2'>
|
<div className='flex flex-col gap-2'>
|
||||||
<Label text='Доступ' className='self-center select-none' />
|
<Label text='Доступ' className='self-center select-none' />
|
||||||
|
|
|
@ -4,9 +4,9 @@ import { useIntl } from 'react-intl';
|
||||||
import { IconDateCreate, IconDateUpdate, IconEditor, IconFolder, IconOwner } from '@/components/Icons';
|
import { IconDateCreate, IconDateUpdate, IconEditor, IconFolder, IconOwner } from '@/components/Icons';
|
||||||
import InfoUsers from '@/components/info/InfoUsers';
|
import InfoUsers from '@/components/info/InfoUsers';
|
||||||
import SelectUser from '@/components/select/SelectUser';
|
import SelectUser from '@/components/select/SelectUser';
|
||||||
import ValueIcon from '@/components/ui/ValueIcon';
|
|
||||||
import Overlay from '@/components/ui/Overlay';
|
import Overlay from '@/components/ui/Overlay';
|
||||||
import Tooltip from '@/components/ui/Tooltip';
|
import Tooltip from '@/components/ui/Tooltip';
|
||||||
|
import ValueIcon from '@/components/ui/ValueIcon';
|
||||||
import { useAccessMode } from '@/context/AccessModeContext';
|
import { useAccessMode } from '@/context/AccessModeContext';
|
||||||
import { useUsers } from '@/context/UsersContext';
|
import { useUsers } from '@/context/UsersContext';
|
||||||
import useDropdown from '@/hooks/useDropdown';
|
import useDropdown from '@/hooks/useDropdown';
|
||||||
|
|
|
@ -34,7 +34,7 @@ export const PARAMETER = {
|
||||||
statSmallThreshold: 3, // characters - threshold for small labels - small font
|
statSmallThreshold: 3, // characters - threshold for small labels - small font
|
||||||
|
|
||||||
logicLabel: 'LOGIC',
|
logicLabel: 'LOGIC',
|
||||||
exteorVersion: '4.9.3',
|
exteorVersion: '4.9.4',
|
||||||
|
|
||||||
TOOLTIP_WIDTH: 'max-w-[29rem]'
|
TOOLTIP_WIDTH: 'max-w-[29rem]'
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,11 @@ export default {
|
||||||
extend: {}
|
extend: {}
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
experimental: {
|
...(process.env.NODE_ENV === 'production'
|
||||||
optimizeUniversalDefaults: true
|
? {
|
||||||
}
|
experimental: {
|
||||||
|
optimizeUniversalDefaults: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: {})
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user