Compare commits

...

3 Commits

Author SHA1 Message Date
Ivan
b3c8b217c0 B: Fix input min-width
Some checks failed
Backend CI / build (3.12) (push) Has been cancelled
Frontend CI / build (22.x) (push) Has been cancelled
2024-08-30 11:03:31 +03:00
Ivan
afe3ec0adb M: Remove expression column from sideview 2024-08-30 09:58:31 +03:00
Ivan
a4e2d2c25f B: Fix error response to invalid file type 2024-08-30 09:42:21 +03:00
8 changed files with 36 additions and 54 deletions

View File

@ -361,6 +361,11 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
model = self._get_item()
load_metadata = input_serializer.validated_data['load_metadata']
data = utility.read_zipped_json(request.FILES['file'].file, utils.EXTEOR_INNER_FILENAME)
if data is None:
return Response(
status=c.HTTP_400_BAD_REQUEST,
data={'file': msg.exteorFileCorrupted()}
)
data['id'] = model.pk
serializer = s.RSFormTRSSerializer(
@ -486,11 +491,17 @@ class TrsImportView(views.APIView):
request=s.FileSerializer,
responses={
c.HTTP_201_CREATED: LibraryItemSerializer,
c.HTTP_400_BAD_REQUEST: None,
c.HTTP_403_FORBIDDEN: None
}
)
def post(self, request: Request) -> HttpResponse:
data = utility.read_zipped_json(request.FILES['file'].file, utils.EXTEOR_INNER_FILENAME)
if data is None:
return Response(
status=c.HTTP_400_BAD_REQUEST,
data={'file': msg.exteorFileCorrupted()}
)
owner = cast(User, self.request.user)
_prepare_rsform_data(data, request, owner)
serializer = s.RSFormTRSSerializer(
@ -526,6 +537,11 @@ def create_rsform(request: Request) -> HttpResponse:
)
data = utility.read_zipped_json(request.FILES['file'].file, utils.EXTEOR_INNER_FILENAME)
if data is None:
return Response(
status=c.HTTP_400_BAD_REQUEST,
data={'file': msg.exteorFileCorrupted()}
)
_prepare_rsform_data(data, request, owner)
serializer_rsform = s.RSFormTRSSerializer(data=data, context={'load_meta': True})
serializer_rsform.is_valid(raise_exception=True)

View File

@ -14,6 +14,10 @@ def operationNotInOSS(title: str):
return f'Операция не принадлежит ОСС: {title}'
def exteorFileCorrupted():
return 'Файл Экстеор не соответствует ожидаемому формату. Попробуйте сохранить файл в новой версии'
def previousResultMissing():
return 'Отсутствует результат предыдущей операции'

View File

@ -1,13 +1,17 @@
''' Utility functions. '''
import json
from io import BytesIO
from zipfile import ZipFile
from typing import Optional
from zipfile import BadZipFile, ZipFile
def read_zipped_json(data, json_filename: str) -> dict:
''' Read JSON from zipped data '''
with ZipFile(data, 'r') as archive:
json_data = archive.read(json_filename)
def read_zipped_json(data, json_filename: str) -> Optional[dict]:
''' Read JSON from zipped data. '''
try:
with ZipFile(data, 'r') as archive:
json_data = archive.read(json_filename)
except BadZipFile:
return None
result: dict = json.loads(json_data)
return result

View File

@ -41,7 +41,7 @@ function TextInput({
<input
id={id}
className={clsx(
'py-2',
'min-w-0 py-2',
'leading-tight truncate hover:text-clip',
{
'px-3': !noBorder || !disabled,

View File

@ -62,7 +62,7 @@ function FormCreateCst({ schema, state, partialUpdate, setValidated }: FormCreat
id='dlg_cst_alias'
dense
label='Имя'
className='w-[7rem] mr-8'
className='w-[7rem]'
value={state.alias}
onChange={event => partialUpdate({ alias: event.target.value })}
/>

View File

@ -46,7 +46,7 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
hideWindow={hideWindow}
canSubmit={validated}
onSubmit={() => onRename(cstData)}
className={clsx('w-[30rem]', 'py-6 pr-3 pl-6 flex justify-center items-center')}
className={clsx('w-[30rem]', 'py-6 pr-3 pl-6 flex gap-3 justify-center items-center')}
>
<SelectSingle
id='dlg_cst_type'
@ -64,7 +64,7 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
id='dlg_cst_alias'
dense
label='Имя'
className='w-[7rem] ml-3'
className='w-[7rem]'
value={cstData.alias}
onChange={event => updateData({ alias: event.target.value })}
/>

View File

@ -1,12 +1,11 @@
'use client';
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
import { useCallback, useLayoutEffect, useMemo } from 'react';
import BadgeConstituenta from '@/components/info/BadgeConstituenta';
import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '@/components/ui/DataTable';
import DataTable, { createColumnHelper, IConditionalStyle } from '@/components/ui/DataTable';
import NoData from '@/components/ui/NoData';
import { useConceptOptions } from '@/context/ConceptOptionsContext';
import useWindowSize from '@/hooks/useWindowSize';
import { ConstituentaID, IConstituenta } from '@/models/rsform';
import { isMockCst } from '@/models/rsformAPI';
import { PARAMETER, prefixes } from '@/utils/constants';
@ -16,7 +15,6 @@ interface TableSideConstituentsProps {
items: IConstituenta[];
activeCst?: IConstituenta;
onOpenEdit: (cstID: ConstituentaID) => void;
denseThreshold?: number;
autoScroll?: boolean;
maxHeight: string;
}
@ -28,13 +26,9 @@ function TableSideConstituents({
activeCst,
autoScroll = true,
onOpenEdit,
maxHeight,
denseThreshold = 9999
maxHeight
}: TableSideConstituentsProps) {
const { colors } = useConceptOptions();
const windowSize = useWindowSize();
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({ expression: true });
useLayoutEffect(() => {
if (!activeCst) {
@ -54,17 +48,6 @@ function TableSideConstituents({
}
}, [activeCst, autoScroll]);
useLayoutEffect(() => {
setColumnVisibility(prev => {
const newValue = (windowSize.width ?? 0) >= denseThreshold;
if (newValue === prev.expression) {
return prev;
} else {
return { expression: newValue };
}
});
}, [windowSize, denseThreshold]);
const handleRowClicked = useCallback(
(cst: IConstituenta) => {
if (!isMockCst(cst)) {
@ -103,25 +86,6 @@ function TableSideConstituents({
{props.getValue()}
</div>
)
}),
columnHelper.accessor('definition_formal', {
id: 'expression',
header: 'Выражение',
size: 2000,
minSize: 0,
maxSize: 2000,
enableHiding: true,
cell: props => (
<div
style={{
textWrap: 'pretty',
fontSize: 12,
color: isMockCst(props.row.original) ? colors.fgWarning : undefined
}}
>
{props.getValue()}
</div>
)
})
],
[colors]
@ -162,8 +126,6 @@ function TableSideConstituents({
conditionalRowStyles={conditionalRowStyles}
headPosition='0'
enableHiding
columnVisibility={columnVisibility}
onColumnVisibilityChange={setColumnVisibility}
noDataComponent={
<NoData className='min-h-[5rem]'>
<p>Список конституент пуст</p>

View File

@ -14,9 +14,6 @@ import { animateSideView } from '@/styling/animations';
import ConstituentsSearch from './ConstituentsSearch';
import TableSideConstituents from './TableSideConstituents';
// Window width cutoff for expression show
const COLUMN_EXPRESSION_HIDE_THRESHOLD = 1500;
// Window width cutoff for dense search bar
const COLUMN_DENSE_SEARCH_THRESHOLD = 1100;
@ -47,7 +44,6 @@ function ViewConstituents({ expression, schema, activeCst, isBottom, onOpenEdit
activeCst={activeCst}
onOpenEdit={onOpenEdit}
autoScroll={!isBottom}
denseThreshold={COLUMN_EXPRESSION_HIDE_THRESHOLD}
/>
),
[isBottom, filteredData, activeCst, onOpenEdit, calculateHeight, accessLevel]