mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-27 05:20:36 +03:00
Fix UI bugs and styles + refactor contexts
This commit is contained in:
parent
920a7baff4
commit
747ce126ae
|
@ -106,7 +106,8 @@ class RSForm(models.Model):
|
|||
)
|
||||
self._update_from_core()
|
||||
self.save()
|
||||
return Constituenta.objects.get(pk=result.pk)
|
||||
result.refresh_from_db()
|
||||
return result
|
||||
|
||||
@transaction.atomic
|
||||
def move_cst(self, listCst: list['Constituenta'], target: int):
|
||||
|
|
|
@ -200,26 +200,27 @@ class TestRSFormViewset(APITestCase):
|
|||
def test_delete_constituenta(self):
|
||||
schema = self.rsform_owned
|
||||
data = json.dumps({'items': [{'id': 1337}]})
|
||||
response = self.client.post(f'/api/rsforms/{schema.id}/cst-multidelete/',
|
||||
data=data, content_type='application/json')
|
||||
response = self.client.patch(f'/api/rsforms/{schema.id}/cst-multidelete/',
|
||||
data=data, content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
x1 = Constituenta.objects.create(schema=schema, alias='X1', csttype='basic', order=1)
|
||||
x2 = Constituenta.objects.create(schema=schema, alias='X2', csttype='basic', order=2)
|
||||
data = json.dumps({'items': [{'id': x1.id}]})
|
||||
response = self.client.post(f'/api/rsforms/{schema.id}/cst-multidelete/',
|
||||
data=data, content_type='application/json')
|
||||
response = self.client.patch(f'/api/rsforms/{schema.id}/cst-multidelete/',
|
||||
data=data, content_type='application/json')
|
||||
x2.refresh_from_db()
|
||||
schema.refresh_from_db()
|
||||
self.assertEqual(response.status_code, 202)
|
||||
self.assertEqual(len(response.data['items']), 1)
|
||||
self.assertEqual(schema.constituents().count(), 1)
|
||||
self.assertEqual(x2.alias, 'X2')
|
||||
self.assertEqual(x2.order, 1)
|
||||
|
||||
x3 = Constituenta.objects.create(schema=self.rsform_unowned, alias='X1', csttype='basic', order=1)
|
||||
data = json.dumps({'items': [{'id': x3.id}]})
|
||||
response = self.client.post(f'/api/rsforms/{schema.id}/cst-multidelete/',
|
||||
data=data, content_type='application/json')
|
||||
response = self.client.patch(f'/api/rsforms/{schema.id}/cst-multidelete/',
|
||||
data=data, content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_move_constituenta(self):
|
||||
|
|
|
@ -69,14 +69,16 @@ class RSFormViewSet(viewsets.ModelViewSet):
|
|||
response['Location'] = constituenta.get_absolute_url()
|
||||
return response
|
||||
|
||||
@action(detail=True, methods=['post'], url_path='cst-multidelete')
|
||||
@action(detail=True, methods=['patch'], url_path='cst-multidelete')
|
||||
def cst_multidelete(self, request, pk):
|
||||
''' Delete multiple constituents '''
|
||||
schema: models.RSForm = self.get_object()
|
||||
serializer = serializers.CstListSerlializer(data=request.data, context={'schema': schema})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
schema.delete_cst(serializer.validated_data['constituents'])
|
||||
return Response(status=202)
|
||||
schema.refresh_from_db()
|
||||
outSerializer = serializers.RSFormDetailsSerlializer(schema)
|
||||
return Response(status=202, data=outSerializer.data)
|
||||
|
||||
@action(detail=True, methods=['patch'], url_path='cst-moveto')
|
||||
def cst_moveto(self, request, pk):
|
||||
|
|
|
@ -7,7 +7,7 @@ interface CardProps {
|
|||
function Card({title, widthClass='min-w-fit', children}: CardProps) {
|
||||
return (
|
||||
<div className={`border shadow-md py-2 clr-card px-6 ${widthClass}`}>
|
||||
{ title && <h1 className='mb-2 text-xl font-bold'>{title}</h1> }
|
||||
{ title && <h1 className='mb-2 text-xl font-bold whitespace-nowrap'>{title}</h1> }
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import DataTable, { createTheme, TableProps } from 'react-data-table-component';
|
||||
import { useTheme } from '../../context/ThemeContext';
|
||||
import { useConceptTheme } from '../../context/ThemeContext';
|
||||
|
||||
export interface SelectionInfo<T> {
|
||||
allSelected: boolean;
|
||||
|
@ -38,7 +38,7 @@ createTheme('customDark', {
|
|||
}, 'dark');
|
||||
|
||||
function DataTableThemed<T>({theme, ...props}: TableProps<T>) {
|
||||
const { darkMode } = useTheme();
|
||||
const { darkMode } = useConceptTheme();
|
||||
|
||||
return (
|
||||
<DataTable<T>
|
||||
|
|
|
@ -6,35 +6,35 @@ import UserMenu from './UserMenu';
|
|||
import { useAuth } from '../../context/AuthContext';
|
||||
import UserTools from './UserTools';
|
||||
import Logo from './Logo';
|
||||
import { useState } from 'react';
|
||||
import { useConceptTheme } from '../../context/ThemeContext';
|
||||
|
||||
function Navigation() {
|
||||
const {user} = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const [isActive, setActive] = useState(true);
|
||||
const { noNavigation, toggleNoNavigation } = useConceptTheme();
|
||||
|
||||
const navigateCommon = () => navigate('/rsforms?filter=common');
|
||||
const navigateHelp = () => navigate('/manuals');
|
||||
|
||||
return (
|
||||
<nav className='sticky top-0 left-0 right-0 z-50'>
|
||||
{isActive &&
|
||||
{!noNavigation &&
|
||||
<button
|
||||
title='Скрыть навигацию'
|
||||
className='absolute top-0 right-0 z-[60] w-[1.2rem] h-[4rem] border-b-2 border-l-2 clr-nav rounded-none'
|
||||
onClick={() => setActive(!isActive)}
|
||||
onClick={toggleNoNavigation}
|
||||
>
|
||||
<p>{'>'}</p><p>{'>'}</p>
|
||||
</button>}
|
||||
{!isActive &&
|
||||
{noNavigation &&
|
||||
<button
|
||||
title='Показать навигацию'
|
||||
className='absolute top-0 right-0 z-[60] w-[4rem] h-[1.6rem] border-b-2 border-l-2 clr-nav rounded-none'
|
||||
onClick={() => setActive(!isActive)}
|
||||
onClick={toggleNoNavigation}
|
||||
>
|
||||
{'∨∨∨'}
|
||||
</button>}
|
||||
{isActive &&
|
||||
{!noNavigation &&
|
||||
<div className='pr-6 pl-2 py-2.5 h-[4rem] flex items-center justify-between border-b-2 clr-nav rounded-none'>
|
||||
<div className='flex items-start justify-start '>
|
||||
<Logo title='КонцептПортал' />
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { useTheme } from '../../context/ThemeContext';
|
||||
import { useConceptTheme } from '../../context/ThemeContext';
|
||||
import { DarkThemeIcon, LightThemeIcon } from '../Icons';
|
||||
import NavigationButton from './NavigationButton';
|
||||
|
||||
function ThemeSwitcher() {
|
||||
const {darkMode, toggleDarkMode} = useTheme();
|
||||
const {darkMode, toggleDarkMode} = useConceptTheme();
|
||||
return (
|
||||
<>
|
||||
{darkMode && <NavigationButton icon={<LightThemeIcon />} description='Светлая тема' onClick={toggleDarkMode} />}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAuth } from '../../context/AuthContext';
|
||||
import DropdownButton from '../Common/DropdownButton';
|
||||
import { useTheme } from '../../context/ThemeContext';
|
||||
import { useConceptTheme } from '../../context/ThemeContext';
|
||||
import Dropdown from '../Common/Dropdown';
|
||||
|
||||
interface UserDropdownProps {
|
||||
|
@ -9,7 +9,7 @@ interface UserDropdownProps {
|
|||
}
|
||||
|
||||
function UserDropdown({hideDropdown}: UserDropdownProps) {
|
||||
const {darkMode, toggleDarkMode} = useTheme();
|
||||
const {darkMode, toggleDarkMode} = useConceptTheme();
|
||||
const navigate = useNavigate();
|
||||
const {user, logout} = useAuth();
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { ToastContainer, ToastContainerProps } from 'react-toastify';
|
||||
import { useTheme } from '../context/ThemeContext';
|
||||
import { useConceptTheme } from '../context/ThemeContext';
|
||||
|
||||
function ToasterThemed({theme, ...props}: ToastContainerProps) {
|
||||
const { darkMode } = useTheme();
|
||||
const { darkMode } = useConceptTheme();
|
||||
|
||||
return (
|
||||
<ToastContainer
|
||||
|
|
|
@ -1,29 +1,30 @@
|
|||
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useState } from 'react';
|
||||
import { ICurrentUser, IUserSignupData } from '../utils/models';
|
||||
import { ErrorInfo } from '../components/BackendError';
|
||||
import useLocalStorage from '../hooks/useLocalStorage';
|
||||
import { getAuth, postLogin, postLogout, postSignup } from '../utils/backendAPI';
|
||||
import { BackendCallback, getAuth, postLogin, postLogout, postSignup } from '../utils/backendAPI';
|
||||
|
||||
|
||||
interface IAuthContext {
|
||||
user: ICurrentUser | undefined
|
||||
login: (username: string, password: string) => Promise<void>
|
||||
logout: (onSuccess?: () => void) => Promise<void>
|
||||
signup: (data: IUserSignupData) => Promise<void>
|
||||
login: (username: string, password: string, callback?: BackendCallback) => Promise<void>
|
||||
logout: (callback?: BackendCallback) => Promise<void>
|
||||
signup: (data: IUserSignupData, callback?: BackendCallback) => Promise<void>
|
||||
loading: boolean
|
||||
error: ErrorInfo
|
||||
setError: (error: ErrorInfo) => void
|
||||
}
|
||||
|
||||
export const AuthContext = createContext<IAuthContext>({
|
||||
user: undefined,
|
||||
login: async () => {},
|
||||
logout: async () => {},
|
||||
signup: async () => {},
|
||||
loading: false,
|
||||
error: '',
|
||||
setError: () => {}
|
||||
});
|
||||
const AuthContext = createContext<IAuthContext | null>(null);
|
||||
export const useAuth = () => {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useAuth has to be used within <AuthState.Provider>'
|
||||
);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
interface AuthStateProps {
|
||||
children: React.ReactNode
|
||||
|
@ -49,44 +50,49 @@ export const AuthState = ({ children }: AuthStateProps) => {
|
|||
}, [setUser]
|
||||
);
|
||||
|
||||
async function login(uname: string, pw: string, onSuccess?: () => void) {
|
||||
async function login(uname: string, pw: string, callback?: BackendCallback) {
|
||||
setError(undefined);
|
||||
postLogin({
|
||||
data: {username: uname, password: pw},
|
||||
showError: true,
|
||||
setLoading: setLoading,
|
||||
onError: error => setError(error),
|
||||
onSucccess: response => {
|
||||
loadCurrentUser();
|
||||
if(onSuccess) onSuccess();
|
||||
onSucccess:
|
||||
async (response) => {
|
||||
await loadCurrentUser();
|
||||
if(callback) callback(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
async function logout(callback?: BackendCallback) {
|
||||
setError(undefined);
|
||||
postLogout({
|
||||
showError: true,
|
||||
onSucccess: response => {
|
||||
loadCurrentUser();
|
||||
onSucccess:
|
||||
async (response) => {
|
||||
await loadCurrentUser();
|
||||
if (callback) callback(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function signup(data: IUserSignupData) {
|
||||
async function signup(data: IUserSignupData, callback?: BackendCallback) {
|
||||
setError(undefined);
|
||||
postSignup({
|
||||
data: data,
|
||||
showError: true,
|
||||
setLoading: setLoading,
|
||||
onError: error => setError(error),
|
||||
onSucccess: response => {
|
||||
loadCurrentUser();
|
||||
onSucccess:
|
||||
async (response) => {
|
||||
await loadCurrentUser();
|
||||
if (callback) callback(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
useLayoutEffect(() => {
|
||||
loadCurrentUser();
|
||||
}, [loadCurrentUser])
|
||||
|
||||
|
@ -98,5 +104,3 @@ export const AuthState = ({ children }: AuthStateProps) => {
|
|||
</AuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useAuth = () => useContext(AuthContext);
|
|
@ -6,7 +6,7 @@ import { useAuth } from './AuthContext';
|
|||
import {
|
||||
BackendCallback, deleteRSForm, getTRSFile,
|
||||
patchConstituenta, patchMoveConstituenta, patchRSForm,
|
||||
postClaimRSForm, postDeleteConstituenta, postNewConstituenta
|
||||
postClaimRSForm, patchDeleteConstituenta, postNewConstituenta
|
||||
} from '../utils/backendAPI';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
|
@ -175,17 +175,17 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
|
|||
const cstDelete = useCallback(
|
||||
async (data: any, callback?: BackendCallback) => {
|
||||
setError(undefined);
|
||||
postDeleteConstituenta(schemaID, {
|
||||
patchDeleteConstituenta(schemaID, {
|
||||
data: data,
|
||||
showError: true,
|
||||
setLoading: setProcessing,
|
||||
onError: error => setError(error),
|
||||
onSucccess: async (response) => {
|
||||
await reload();
|
||||
setSchema(response.data);
|
||||
if (callback) callback(response);
|
||||
}
|
||||
});
|
||||
}, [schemaID, setError, reload]);
|
||||
}, [schemaID, setError, setSchema]);
|
||||
|
||||
const cstMoveTo = useCallback(
|
||||
async (data: any, callback?: BackendCallback) => {
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
import { createContext, useContext, useEffect } from 'react';
|
||||
import { createContext, useContext, useEffect, useState } from 'react';
|
||||
import useLocalStorage from '../hooks/useLocalStorage';
|
||||
|
||||
|
||||
interface IThemeContext {
|
||||
darkMode: boolean
|
||||
noNavigation: boolean
|
||||
toggleDarkMode: () => void
|
||||
toggleNoNavigation: () => void
|
||||
}
|
||||
|
||||
export const ThemeContext = createContext<IThemeContext>({
|
||||
darkMode: true,
|
||||
toggleDarkMode: () => {}
|
||||
})
|
||||
const ThemeContext = createContext<IThemeContext | null>(null);
|
||||
export const useConceptTheme = () => {
|
||||
const context = useContext(ThemeContext);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useConceptTheme has to be used within <ThemeState.Provider>'
|
||||
);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
interface ThemeStateProps {
|
||||
children: React.ReactNode
|
||||
|
@ -18,6 +26,7 @@ interface ThemeStateProps {
|
|||
|
||||
export const ThemeState = ({ children }: ThemeStateProps) => {
|
||||
const [darkMode, setDarkMode] = useLocalStorage('darkMode', false);
|
||||
const [noNavigation, setNoNavigation] = useState(false);
|
||||
|
||||
const setDarkClass = (isDark: boolean) => {
|
||||
const root = window.document.documentElement;
|
||||
|
@ -29,21 +38,16 @@ export const ThemeState = ({ children }: ThemeStateProps) => {
|
|||
root.setAttribute('data-color-scheme', !isDark ? 'light' : 'dark');
|
||||
};
|
||||
|
||||
const toggleDarkMode = () => {
|
||||
setDarkMode(!darkMode)
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setDarkClass(darkMode)
|
||||
}, [darkMode]);
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{
|
||||
darkMode, toggleDarkMode
|
||||
darkMode, toggleDarkMode: () => setDarkMode(prev => !prev),
|
||||
noNavigation, toggleNoNavigation: () => setNoNavigation(prev => !prev),
|
||||
}}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const useTheme = () => useContext(ThemeContext);
|
|
@ -9,11 +9,16 @@ interface IUsersContext {
|
|||
getUserLabel: (userID?: number) => string
|
||||
}
|
||||
|
||||
export const UsersContext = createContext<IUsersContext>({
|
||||
users: [],
|
||||
reload: async () => {},
|
||||
getUserLabel: () => ''
|
||||
})
|
||||
const UsersContext = createContext<IUsersContext | null>(null);
|
||||
export const useUsers = () => {
|
||||
const context = useContext(UsersContext);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useUsers has to be used within <UsersState.Provider>'
|
||||
);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
interface UsersStateProps {
|
||||
children: React.ReactNode
|
||||
|
@ -64,5 +69,3 @@ export const UsersState = ({ children }: UsersStateProps) => {
|
|||
</UsersContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const useUsers = () => useContext(UsersContext);
|
|
@ -30,8 +30,7 @@ function LoginPage() {
|
|||
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
if (!loading) {
|
||||
login(username, password)
|
||||
.then(() => navigate('/rsforms?filter=personal'));
|
||||
login(username, password, () => navigate('/rsforms?filter=personal'));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ function ConstituentEditor() {
|
|||
'forms': activeCst?.term?.forms || [],
|
||||
}
|
||||
};
|
||||
cstUpdate(data).then(() => toast.success('Изменения сохранены'));
|
||||
cstUpdate(data, () => toast.success('Изменения сохранены'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -74,13 +74,13 @@ function ConstituentEditor() {
|
|||
return;
|
||||
}
|
||||
const data = {
|
||||
'items': [activeID]
|
||||
'items': [{'id': activeID}]
|
||||
}
|
||||
const index = schema.items.findIndex((cst) => cst.id === activeID);
|
||||
if (index !== -1 && index + 1 < schema.items.length) {
|
||||
setActiveID(schema.items[index + 1].id);
|
||||
}
|
||||
cstDelete(data).then(() => toast.success('Конституента удалена'));
|
||||
cstDelete(data, () => toast.success('Конституента удалена'));
|
||||
}, [activeID, schema, setActiveID, cstDelete]);
|
||||
|
||||
const handleAddNew = useCallback(
|
||||
|
|
|
@ -9,6 +9,7 @@ import Divider from '../../components/Common/Divider';
|
|||
import { createAliasFor, getCstTypeLabel, getCstTypePrefix, getStatusInfo, getTypeLabel } from '../../utils/staticUI';
|
||||
import CreateCstModal from './CreateCstModal';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { useConceptTheme } from '../../context/ThemeContext';
|
||||
|
||||
interface ConstituentsTableProps {
|
||||
onOpenEdit: (cst: IConstituenta) => void
|
||||
|
@ -19,6 +20,7 @@ function ConstituentsTable({onOpenEdit}: ConstituentsTableProps) {
|
|||
schema, isEditable,
|
||||
cstCreate, cstDelete, cstMoveTo
|
||||
} = useRSForm();
|
||||
const { noNavigation } = useConceptTheme();
|
||||
const [selected, setSelected] = useState<number[]>([]);
|
||||
const nothingSelected = useMemo(() => selected.length === 0, [selected]);
|
||||
|
||||
|
@ -71,7 +73,7 @@ function ConstituentsTable({onOpenEdit}: ConstituentsTableProps) {
|
|||
'items': selected.map(id => { return {'id': id }; }),
|
||||
'move_to': insertIndex
|
||||
}
|
||||
cstMoveTo(data).then(() => toast.info('Перемещение вверх ' + insertIndex));
|
||||
cstMoveTo(data);
|
||||
}, [selected, schema?.items, cstMoveTo]);
|
||||
|
||||
|
||||
|
@ -81,20 +83,24 @@ function ConstituentsTable({onOpenEdit}: ConstituentsTableProps) {
|
|||
if (!schema?.items || selected.length === 0) {
|
||||
return;
|
||||
}
|
||||
let count = 0;
|
||||
const currentIndex = schema.items.reduce((prev, cst, index) => {
|
||||
if (selected.indexOf(cst.id) < 0) {
|
||||
return prev;
|
||||
} else if (prev === -1) {
|
||||
return index;
|
||||
} else {
|
||||
count += 1;
|
||||
if (prev === -1) {
|
||||
return index;
|
||||
}
|
||||
return Math.max(prev, index);
|
||||
}
|
||||
return Math.max(prev, index);
|
||||
}, -1);
|
||||
const insertIndex = Math.min(schema.items.length - 1, currentIndex + 1) + 1
|
||||
const insertIndex = Math.min(schema.items.length - 1, currentIndex - count + 2) + 1
|
||||
const data = {
|
||||
'items': selected.map(id => { return {'id': id }; }),
|
||||
'move_to': insertIndex
|
||||
}
|
||||
cstMoveTo(data).then(() => toast.info('Перемещение вниз ' + insertIndex));
|
||||
cstMoveTo(data);
|
||||
}, [selected, schema?.items, cstMoveTo]);
|
||||
|
||||
// Generate new names for all constituents
|
||||
|
@ -131,7 +137,6 @@ function ConstituentsTable({onOpenEdit}: ConstituentsTableProps) {
|
|||
case 'ArrowUp': handleMoveUp(); return;
|
||||
case 'ArrowDown': handleMoveDown(); return;
|
||||
}
|
||||
console.log(event);
|
||||
}, [isEditable, selected, handleMoveUp, handleMoveDown]);
|
||||
|
||||
const columns = useMemo(() =>
|
||||
|
@ -253,7 +258,10 @@ function ConstituentsTable({onOpenEdit}: ConstituentsTableProps) {
|
|||
onCreate={handleAddNew}
|
||||
/>
|
||||
<div className='w-full'>
|
||||
<div className='sticky top-[4rem] z-10 flex justify-start w-full gap-1 px-2 py-1 border-y items-center h-[2.2rem] clr-app'>
|
||||
<div
|
||||
className={'flex justify-start w-full gap-1 px-2 py-1 border-y items-center h-[2.2rem] clr-app'
|
||||
+ (!noNavigation ? ' sticky z-10 top-[4rem]' : ' sticky z-10 top-[0rem]')}
|
||||
>
|
||||
<div className='mr-3 whitespace-nowrap'>Выбраны <span className='ml-2'><b>{selected.length}</b> из {schema?.stats?.count_all || 0}</span></div>
|
||||
{isEditable && <div className='flex justify-start w-full gap-1'>
|
||||
<Button
|
||||
|
|
|
@ -43,7 +43,7 @@ function RSFormCard() {
|
|||
'comment': comment,
|
||||
'is_common': common,
|
||||
};
|
||||
update(data).then(() => toast.success('Изменения сохранены'));
|
||||
update(data, () => toast.success('Изменения сохранены'));
|
||||
};
|
||||
|
||||
const handleDelete =
|
||||
|
|
|
@ -35,7 +35,7 @@ function RegisterPage() {
|
|||
'first_name': firstName,
|
||||
'last_name': lastName,
|
||||
};
|
||||
signup(data).then(() => setSuccess(true));
|
||||
signup(data, () => setSuccess(true));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -158,8 +158,8 @@ export async function postNewConstituenta(schema: string, request?: IFrontReques
|
|||
});
|
||||
}
|
||||
|
||||
export async function postDeleteConstituenta(schema: string, request?: IFrontRequest) {
|
||||
AxiosPost({
|
||||
export async function patchDeleteConstituenta(schema: string, request?: IFrontRequest) {
|
||||
AxiosPatch<IRSForm>({
|
||||
title: `Delete Constituents for RSForm id=${schema}: ${request?.data['items'].toString()}`,
|
||||
endpoint: `${config.url.BASE}rsforms/${schema}/cst-multidelete/`,
|
||||
request: request
|
||||
|
|
|
@ -207,7 +207,7 @@ export function getCstTypePrefix(type: CstType) {
|
|||
case CstType.CONSTANT: return 'C';
|
||||
case CstType.STRUCTURED: return 'S';
|
||||
case CstType.AXIOM: return 'A';
|
||||
case CstType.TERM: return 'T';
|
||||
case CstType.TERM: return 'D';
|
||||
case CstType.FUNCTION: return 'F';
|
||||
case CstType.PREDICATE: return 'P';
|
||||
case CstType.THEOREM: return 'T';
|
||||
|
@ -259,17 +259,16 @@ export function extractGlobals(expression: string): Set<string> {
|
|||
}
|
||||
|
||||
export function createAliasFor(type: CstType, schema: IRSForm): string {
|
||||
let index = 1;
|
||||
let prefix = getCstTypePrefix(type);
|
||||
let name = prefix + index;
|
||||
if (schema.items && schema.items.length > 0) {
|
||||
for (let i = 0; i < schema.items.length; ++i) {
|
||||
if (schema.items[i].alias === name) {
|
||||
++index;
|
||||
name = prefix + index;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
if (!schema.items || schema.items.length <= 0) {
|
||||
return `${prefix}1`;
|
||||
}
|
||||
return name;
|
||||
const index = schema.items.reduce((prev, cst, index) => {
|
||||
if (cst.cstType !== type) {
|
||||
return prev;
|
||||
}
|
||||
index = Number(cst.alias.slice(1 - cst.alias.length)) + 1;
|
||||
return Math.max(prev, index);
|
||||
}, 1);
|
||||
return `${prefix}${index}`;
|
||||
}
|
Loading…
Reference in New Issue
Block a user