mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-08-14 12:50:37 +03:00
Implement Schema search
This commit is contained in:
parent
f4af39e62e
commit
a8bbb2b63c
|
@ -15,6 +15,10 @@ from apps.rsform.views import (
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _response_contains(response, schema: RSForm) -> bool:
|
||||||
|
return any(x for x in response.data if x['id'] == schema.id)
|
||||||
|
|
||||||
|
|
||||||
class TestConstituentaAPI(APITestCase):
|
class TestConstituentaAPI(APITestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.factory = APIRequestFactory()
|
self.factory = APIRequestFactory()
|
||||||
|
@ -369,3 +373,29 @@ class TestFunctionalViews(APITestCase):
|
||||||
response = parse_expression(request)
|
response = parse_expression(request)
|
||||||
self.assertEqual(response.status_code, 400)
|
self.assertEqual(response.status_code, 400)
|
||||||
self.assertIsInstance(response.data['expression'][0], ErrorDetail)
|
self.assertIsInstance(response.data['expression'][0], ErrorDetail)
|
||||||
|
|
||||||
|
|
||||||
|
class TestLibraryAPI(APITestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.factory = APIRequestFactory()
|
||||||
|
self.user = User.objects.create(username='UserTest')
|
||||||
|
self.client = APIClient()
|
||||||
|
self.client.force_authenticate(user=self.user)
|
||||||
|
self.rsform_owned: RSForm = RSForm.objects.create(title='Test', alias='T1', owner=self.user)
|
||||||
|
self.rsform_unowned: RSForm = RSForm.objects.create(title='Test2', alias='T2')
|
||||||
|
self.rsform_common: RSForm = RSForm.objects.create(title='Test3', alias='T3', is_common=True)
|
||||||
|
|
||||||
|
def test_retrieve_common(self):
|
||||||
|
self.client.logout()
|
||||||
|
response = self.client.get('/api/library/')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertTrue(_response_contains(response, self.rsform_common))
|
||||||
|
self.assertFalse(_response_contains(response, self.rsform_unowned))
|
||||||
|
self.assertFalse(_response_contains(response, self.rsform_owned))
|
||||||
|
|
||||||
|
def test_retrieve_owned(self):
|
||||||
|
response = self.client.get('/api/library/')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertTrue(_response_contains(response, self.rsform_common))
|
||||||
|
self.assertFalse(_response_contains(response, self.rsform_unowned))
|
||||||
|
self.assertTrue(_response_contains(response, self.rsform_owned))
|
||||||
|
|
|
@ -7,6 +7,7 @@ rsform_router = routers.SimpleRouter()
|
||||||
rsform_router.register(r'rsforms', views.RSFormViewSet)
|
rsform_router.register(r'rsforms', views.RSFormViewSet)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
path('library/', views.LibraryView.as_view(), name='library'),
|
||||||
path('constituents/<int:pk>/', views.ConstituentAPIView.as_view(), name='constituenta-detail'),
|
path('constituents/<int:pk>/', views.ConstituentAPIView.as_view(), name='constituenta-detail'),
|
||||||
path('rsforms/import-trs/', views.TrsImportView.as_view()),
|
path('rsforms/import-trs/', views.TrsImportView.as_view()),
|
||||||
path('rsforms/create-detailed/', views.create_rsform),
|
path('rsforms/create-detailed/', views.create_rsform),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import json
|
import json
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
|
from django.db.models import Q
|
||||||
from rest_framework import views, viewsets, filters, generics, permissions
|
from rest_framework import views, viewsets, filters, generics, permissions
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
@ -12,6 +13,21 @@ from . import serializers
|
||||||
from . import utils
|
from . import utils
|
||||||
|
|
||||||
|
|
||||||
|
class LibraryView(generics.ListAPIView):
|
||||||
|
'''
|
||||||
|
Get list of rsforms available for active user.
|
||||||
|
'''
|
||||||
|
permission_classes = (permissions.AllowAny,)
|
||||||
|
serializer_class = serializers.RSFormSerializer
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
user = self.request.user
|
||||||
|
if not user.is_anonymous:
|
||||||
|
return models.RSForm.objects.filter(Q(is_common=True) | Q(owner=user))
|
||||||
|
else:
|
||||||
|
return models.RSForm.objects.filter(is_common=True)
|
||||||
|
|
||||||
|
|
||||||
class ConstituentAPIView(generics.RetrieveUpdateAPIView):
|
class ConstituentAPIView(generics.RetrieveUpdateAPIView):
|
||||||
queryset = models.Constituenta.objects.all()
|
queryset = models.Constituenta.objects.all()
|
||||||
serializer_class = serializers.ConstituentaSerializer
|
serializer_class = serializers.ConstituentaSerializer
|
||||||
|
|
|
@ -39,7 +39,7 @@ function Navigation () {
|
||||||
<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='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 '>
|
<div className='flex items-start justify-start '>
|
||||||
<Logo title='КонцептПортал' />
|
<Logo title='КонцептПортал' />
|
||||||
<TopSearch placeholder='Поиск схемы...' />
|
<TopSearch />
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center'>
|
<div className='flex items-center'>
|
||||||
{user && <UserTools/>}
|
{user && <UserTools/>}
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { useNavSearch } from '../../context/NavSearchContext';
|
||||||
import { MagnifyingGlassIcon } from '../Icons';
|
import { MagnifyingGlassIcon } from '../Icons';
|
||||||
|
|
||||||
interface TopSearchProps {
|
function TopSearch() {
|
||||||
placeholder: string
|
const navigate = useNavigate();
|
||||||
|
const { query, setQuery } = useNavSearch();
|
||||||
|
|
||||||
|
function handleKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
if (!url.href.includes('/library')) {
|
||||||
|
event.preventDefault();
|
||||||
|
navigate('/library?filter=query');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function TopSearch({ placeholder }: TopSearchProps) {
|
|
||||||
return (
|
return (
|
||||||
<form action='#' method='GET' className='hidden md:block md:pl-2'>
|
<div className='hidden md:block md:pl-2'>
|
||||||
<div className='relative md:w-96'>
|
<div className='relative md:w-96'>
|
||||||
<div className='absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none'>
|
<div className='absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none'>
|
||||||
<MagnifyingGlassIcon />
|
<MagnifyingGlassIcon />
|
||||||
|
@ -15,12 +27,14 @@ function TopSearch({ placeholder }: TopSearchProps) {
|
||||||
type='text'
|
type='text'
|
||||||
name='email'
|
name='email'
|
||||||
id='topbar-search'
|
id='topbar-search'
|
||||||
|
value={query}
|
||||||
className='text-sm block w-full pl-10 p-2.5 text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-600 dark:border-gray-400 dark:placeholder-gray-200 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500'
|
className='text-sm block w-full pl-10 p-2.5 text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-600 dark:border-gray-400 dark:placeholder-gray-200 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500'
|
||||||
placeholder={placeholder}
|
placeholder='Поиск схемы...'
|
||||||
// onChange={}
|
onChange={data => setQuery(data.target.value)}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
76
rsconcept/frontend/src/context/LibraryContext.tsx
Normal file
76
rsconcept/frontend/src/context/LibraryContext.tsx
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { ErrorInfo } from '../components/BackendError';
|
||||||
|
import { getLibrary } from '../utils/backendAPI';
|
||||||
|
import { ILibraryFilter, IRSFormMeta, matchRSFormMeta } from '../utils/models';
|
||||||
|
|
||||||
|
interface ILibraryContext {
|
||||||
|
items: IRSFormMeta[]
|
||||||
|
loading: boolean
|
||||||
|
error: ErrorInfo
|
||||||
|
setError: (error: ErrorInfo) => void
|
||||||
|
|
||||||
|
reload: () => void
|
||||||
|
filter: (params: ILibraryFilter) => IRSFormMeta[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const LibraryContext = createContext<ILibraryContext | null>(null)
|
||||||
|
export const useLibrary = (): ILibraryContext => {
|
||||||
|
const context = useContext(LibraryContext);
|
||||||
|
if (context == null) {
|
||||||
|
throw new Error(
|
||||||
|
'useLibrary has to be used within <LibraryState.Provider>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LibraryStateProps {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LibraryState = ({ children }: LibraryStateProps) => {
|
||||||
|
const [items, setItems] = useState<IRSFormMeta[]>([])
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [error, setError] = useState<ErrorInfo>(undefined);
|
||||||
|
|
||||||
|
const filter = useCallback(
|
||||||
|
(params: ILibraryFilter) => {
|
||||||
|
let result = items;
|
||||||
|
if (params.ownedBy) {
|
||||||
|
result = result.filter(schema => schema.owner === params.ownedBy);
|
||||||
|
}
|
||||||
|
if (params.is_common !== undefined) {
|
||||||
|
result = result.filter(schema => schema.is_common === params.is_common);
|
||||||
|
}
|
||||||
|
if (params.queryMeta) {
|
||||||
|
result = result.filter(schema => matchRSFormMeta(params.queryMeta!, schema));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, [items]);
|
||||||
|
|
||||||
|
const reload = useCallback(
|
||||||
|
() => {
|
||||||
|
setItems([]);
|
||||||
|
setError(undefined);
|
||||||
|
getLibrary({
|
||||||
|
setLoading: setLoading,
|
||||||
|
showError: true,
|
||||||
|
onError: (error) => setError(error),
|
||||||
|
onSuccess: newData => { setItems(newData); }
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
reload();
|
||||||
|
}, [reload])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LibraryContext.Provider value={{
|
||||||
|
items, loading, error, setError,
|
||||||
|
reload, filter
|
||||||
|
}}>
|
||||||
|
{ children }
|
||||||
|
</LibraryContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
38
rsconcept/frontend/src/context/NavSearchContext.tsx
Normal file
38
rsconcept/frontend/src/context/NavSearchContext.tsx
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { createContext, useCallback, useContext, useState } from 'react';
|
||||||
|
|
||||||
|
interface INavSearchContext {
|
||||||
|
query: string
|
||||||
|
setQuery: (value: string) => void
|
||||||
|
cleanQuery: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const NavSearchContext = createContext<INavSearchContext | null>(null);
|
||||||
|
export const useNavSearch = () => {
|
||||||
|
const context = useContext(NavSearchContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error(
|
||||||
|
'useNavSearch has to be used within <NavSearchState.Provider>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NavSearchStateProps {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NavSearchState = ({ children }: NavSearchStateProps) => {
|
||||||
|
const [query, setQuery] = useState('');
|
||||||
|
|
||||||
|
const cleanQuery = useCallback(() => setQuery(''), []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavSearchContext.Provider value={{
|
||||||
|
query,
|
||||||
|
setQuery,
|
||||||
|
cleanQuery
|
||||||
|
}}>
|
||||||
|
{children}
|
||||||
|
</NavSearchContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
|
@ -45,9 +45,9 @@ export const ThemeState = ({ children }: ThemeStateProps) => {
|
||||||
return (
|
return (
|
||||||
<ThemeContext.Provider value={{
|
<ThemeContext.Provider value={{
|
||||||
darkMode,
|
darkMode,
|
||||||
toggleDarkMode: () => { setDarkMode(prev => !prev); },
|
toggleDarkMode: () => setDarkMode(prev => !prev),
|
||||||
noNavigation,
|
noNavigation,
|
||||||
toggleNoNavigation: () => { setNoNavigation(prev => !prev); }
|
toggleNoNavigation: () => setNoNavigation(prev => !prev)
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
</ThemeContext.Provider>
|
</ThemeContext.Provider>
|
||||||
|
|
|
@ -27,7 +27,7 @@ interface UsersStateProps {
|
||||||
export const UsersState = ({ children }: UsersStateProps) => {
|
export const UsersState = ({ children }: UsersStateProps) => {
|
||||||
const [users, setUsers] = useState<IUserInfo[]>([])
|
const [users, setUsers] = useState<IUserInfo[]>([])
|
||||||
|
|
||||||
const getUserLabel = (userID: number | null) => {
|
function getUserLabel(userID: number | null) {
|
||||||
const user = users.find(({ id }) => id === userID)
|
const user = users.find(({ id }) => id === userID)
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return (userID ? userID.toString() : 'Отсутствует');
|
return (userID ? userID.toString() : 'Отсутствует');
|
||||||
|
@ -53,12 +53,11 @@ export const UsersState = ({ children }: UsersStateProps) => {
|
||||||
onError: () => { setUsers([]); },
|
onError: () => { setUsers([]); },
|
||||||
onSuccess: newData => { setUsers(newData); }
|
onSuccess: newData => { setUsers(newData); }
|
||||||
});
|
});
|
||||||
}, [setUsers]
|
}, [setUsers]);
|
||||||
)
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
reload();
|
reload();
|
||||||
}, [reload])
|
}, [reload]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UsersContext.Provider value={{
|
<UsersContext.Provider value={{
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
import { useCallback, useState } from 'react'
|
|
||||||
|
|
||||||
import { type ErrorInfo } from '../components/BackendError';
|
|
||||||
import { getRSForms } from '../utils/backendAPI';
|
|
||||||
import { IRSFormMeta } from '../utils/models'
|
|
||||||
|
|
||||||
export enum FilterType {
|
|
||||||
PERSONAL = 'personal',
|
|
||||||
COMMON = 'common'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RSFormsFilter {
|
|
||||||
type: FilterType
|
|
||||||
data?: number | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useRSForms() {
|
|
||||||
const [rsforms, setRSForms] = useState<IRSFormMeta[]>([]);
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [error, setError] = useState<ErrorInfo>(undefined);
|
|
||||||
|
|
||||||
const loadList = useCallback((filter: RSFormsFilter) => {
|
|
||||||
getRSForms(filter, {
|
|
||||||
showError: true,
|
|
||||||
setLoading,
|
|
||||||
onError: error => { setError(error); },
|
|
||||||
onSuccess: newData => { setRSForms(newData); }
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return { rsforms, error, loading, loadList };
|
|
||||||
}
|
|
|
@ -9,6 +9,8 @@ import { BrowserRouter } from 'react-router-dom';
|
||||||
import App from './App.tsx'
|
import App from './App.tsx'
|
||||||
import ErrorFallback from './components/ErrorFallback.tsx';
|
import ErrorFallback from './components/ErrorFallback.tsx';
|
||||||
import { AuthState } from './context/AuthContext.tsx';
|
import { AuthState } from './context/AuthContext.tsx';
|
||||||
|
import { LibraryState } from './context/LibraryContext.tsx';
|
||||||
|
import { NavSearchState } from './context/NavSearchContext.tsx';
|
||||||
import { ThemeState } from './context/ThemeContext.tsx';
|
import { ThemeState } from './context/ThemeContext.tsx';
|
||||||
import { UsersState } from './context/UsersContext.tsx';
|
import { UsersState } from './context/UsersContext.tsx';
|
||||||
import { initBackend } from './utils/backendAPI.ts';
|
import { initBackend } from './utils/backendAPI.ts';
|
||||||
|
@ -34,11 +36,17 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||||
>
|
>
|
||||||
<IntlProvider locale='ru' defaultLocale='ru'>
|
<IntlProvider locale='ru' defaultLocale='ru'>
|
||||||
<ThemeState>
|
<ThemeState>
|
||||||
|
<NavSearchState>
|
||||||
<AuthState>
|
<AuthState>
|
||||||
<UsersState>
|
<UsersState>
|
||||||
|
<LibraryState>
|
||||||
|
|
||||||
<App />
|
<App />
|
||||||
|
|
||||||
|
</LibraryState>
|
||||||
</UsersState>
|
</UsersState>
|
||||||
</AuthState>
|
</AuthState>
|
||||||
|
</NavSearchState>
|
||||||
</ThemeState>
|
</ThemeState>
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
|
|
@ -1,32 +1,47 @@
|
||||||
import { useEffect } from 'react';
|
import { useLayoutEffect, useState } from 'react';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import BackendError from '../../components/BackendError'
|
import BackendError from '../../components/BackendError'
|
||||||
import { Loader } from '../../components/Common/Loader'
|
import { Loader } from '../../components/Common/Loader'
|
||||||
import { useAuth } from '../../context/AuthContext';
|
import { useAuth } from '../../context/AuthContext';
|
||||||
import { FilterType, type RSFormsFilter, useRSForms } from '../../hooks/useRSForms'
|
import { useLibrary } from '../../context/LibraryContext';
|
||||||
|
import { useNavSearch } from '../../context/NavSearchContext';
|
||||||
|
import { ILibraryFilter, IRSFormMeta } from '../../utils/models';
|
||||||
import ViewLibrary from './ViewLibrary';
|
import ViewLibrary from './ViewLibrary';
|
||||||
|
|
||||||
function LibraryPage() {
|
function LibraryPage() {
|
||||||
const search = useLocation().search;
|
const search = useLocation().search;
|
||||||
|
const { query, cleanQuery } = useNavSearch();
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { rsforms, error, loading, loadList } = useRSForms();
|
const library = useLibrary();
|
||||||
|
|
||||||
useEffect(() => {
|
const [ filterParams, setFilterParams ] = useState<ILibraryFilter>({});
|
||||||
const filterQuery = new URLSearchParams(search).get('filter');
|
const [ items, setItems ] = useState<IRSFormMeta[]>([]);
|
||||||
const type = (!user || !filterQuery ? FilterType.COMMON : filterQuery as FilterType);
|
|
||||||
const filter: RSFormsFilter = { type };
|
useLayoutEffect(() => {
|
||||||
if (type === FilterType.PERSONAL) {
|
const filterType = new URLSearchParams(search).get('filter');
|
||||||
filter.data = user?.id;
|
if (filterType === 'common') {
|
||||||
|
setFilterParams({
|
||||||
|
is_common: true
|
||||||
|
});
|
||||||
|
} else if (filterType === 'personal' && user) {
|
||||||
|
setFilterParams({
|
||||||
|
ownedBy: user.id!
|
||||||
|
});
|
||||||
}
|
}
|
||||||
loadList(filter);
|
}, [user, search, cleanQuery]);
|
||||||
}, [search, user, loadList]);
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const filter = filterParams;
|
||||||
|
filterParams.queryMeta = query ? query: undefined;
|
||||||
|
setItems(library.filter(filter));
|
||||||
|
}, [query, library, filterParams]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='w-full'>
|
<div className='w-full'>
|
||||||
{ loading && <Loader /> }
|
{ library.loading && <Loader /> }
|
||||||
{ error && <BackendError error={error} />}
|
{ library.error && <BackendError error={library.error} />}
|
||||||
{ !loading && rsforms && <ViewLibrary schemas={rsforms} /> }
|
{ !library.loading && library.items && <ViewLibrary schemas={items} /> }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import axios, { AxiosRequestConfig } from 'axios'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
|
|
||||||
import { type ErrorInfo } from '../components/BackendError'
|
import { type ErrorInfo } from '../components/BackendError'
|
||||||
import { FilterType, RSFormsFilter } from '../hooks/useRSForms'
|
|
||||||
import { config } from './constants'
|
import { config } from './constants'
|
||||||
import {
|
import {
|
||||||
IConstituentaList, IConstituentaMeta,
|
IConstituentaList, IConstituentaMeta,
|
||||||
|
@ -65,7 +64,7 @@ export function getAuth(request: FrontPull<ICurrentUser>) {
|
||||||
export function postLogin(request: FrontPush<IUserLoginData>) {
|
export function postLogin(request: FrontPush<IUserLoginData>) {
|
||||||
AxiosPost({
|
AxiosPost({
|
||||||
title: 'Login',
|
title: 'Login',
|
||||||
endpoint: `/users/api/login`,
|
endpoint: '/users/api/login',
|
||||||
request: request
|
request: request
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -73,7 +72,7 @@ export function postLogin(request: FrontPush<IUserLoginData>) {
|
||||||
export function postLogout(request: FrontAction) {
|
export function postLogout(request: FrontAction) {
|
||||||
AxiosPost({
|
AxiosPost({
|
||||||
title: 'Logout',
|
title: 'Logout',
|
||||||
endpoint: `/users/api/logout`,
|
endpoint: '/users/api/logout',
|
||||||
request: request
|
request: request
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -81,7 +80,7 @@ export function postLogout(request: FrontAction) {
|
||||||
export function postSignup(request: FrontExchange<IUserSignupData, IUserProfile>) {
|
export function postSignup(request: FrontExchange<IUserSignupData, IUserProfile>) {
|
||||||
AxiosPost({
|
AxiosPost({
|
||||||
title: 'Register user',
|
title: 'Register user',
|
||||||
endpoint: `/users/api/signup`,
|
endpoint: '/users/api/signup',
|
||||||
request: request
|
request: request
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -89,7 +88,7 @@ export function postSignup(request: FrontExchange<IUserSignupData, IUserProfile>
|
||||||
export function getProfile(request: FrontPull<IUserProfile>) {
|
export function getProfile(request: FrontPull<IUserProfile>) {
|
||||||
AxiosGet({
|
AxiosGet({
|
||||||
title: 'Current user profile',
|
title: 'Current user profile',
|
||||||
endpoint: `/users/api/profile`,
|
endpoint: '/users/api/profile',
|
||||||
request: request
|
request: request
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -97,7 +96,7 @@ export function getProfile(request: FrontPull<IUserProfile>) {
|
||||||
export function patchProfile(request: FrontExchange<IUserUpdateData, IUserProfile>) {
|
export function patchProfile(request: FrontExchange<IUserUpdateData, IUserProfile>) {
|
||||||
AxiosPatch({
|
AxiosPatch({
|
||||||
title: 'Current user profile',
|
title: 'Current user profile',
|
||||||
endpoint: `/users/api/profile`,
|
endpoint: '/users/api/profile',
|
||||||
request: request
|
request: request
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -105,19 +104,15 @@ export function patchProfile(request: FrontExchange<IUserUpdateData, IUserProfil
|
||||||
export function getActiveUsers(request: FrontPull<IUserInfo[]>) {
|
export function getActiveUsers(request: FrontPull<IUserInfo[]>) {
|
||||||
AxiosGet({
|
AxiosGet({
|
||||||
title: 'Active users list',
|
title: 'Active users list',
|
||||||
endpoint: `/users/api/active-users`,
|
endpoint: '/users/api/active-users',
|
||||||
request: request
|
request: request
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRSForms(filter: RSFormsFilter, request: FrontPull<IRSFormMeta[]>) {
|
export function getLibrary(request: FrontPull<IRSFormMeta[]>) {
|
||||||
const endpoint =
|
|
||||||
filter.type === FilterType.PERSONAL
|
|
||||||
? `/api/rsforms?owner=${filter.data as number}`
|
|
||||||
: `/api/rsforms?is_common=true`;
|
|
||||||
AxiosGet({
|
AxiosGet({
|
||||||
title: 'RSForms list',
|
title: 'Available RSForms (Library) list',
|
||||||
endpoint: endpoint,
|
endpoint: '/api/library/',
|
||||||
request: request
|
request: request
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -125,7 +120,7 @@ export function getRSForms(filter: RSFormsFilter, request: FrontPull<IRSFormMeta
|
||||||
export function postNewRSForm(request: FrontExchange<IRSFormCreateData, IRSFormMeta>) {
|
export function postNewRSForm(request: FrontExchange<IRSFormCreateData, IRSFormMeta>) {
|
||||||
AxiosPost({
|
AxiosPost({
|
||||||
title: 'New RSForm',
|
title: 'New RSForm',
|
||||||
endpoint: `/api/rsforms/create-detailed/`,
|
endpoint: '/api/rsforms/create-detailed/',
|
||||||
request: request,
|
request: request,
|
||||||
options: {
|
options: {
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
@ -199,6 +199,13 @@ export interface IRSFormUploadData {
|
||||||
fileName: string
|
fileName: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== Library =====
|
||||||
|
export interface ILibraryFilter {
|
||||||
|
ownedBy?: number
|
||||||
|
is_common?: boolean
|
||||||
|
queryMeta?: string
|
||||||
|
}
|
||||||
|
|
||||||
// ================ Misc types ================
|
// ================ Misc types ================
|
||||||
// Constituenta edit mode
|
// Constituenta edit mode
|
||||||
export enum EditMode {
|
export enum EditMode {
|
||||||
|
@ -312,13 +319,24 @@ export function matchConstituenta(query: string, target?: IConstituenta) {
|
||||||
return false;
|
return false;
|
||||||
} else if (target.alias.match(query)) {
|
} else if (target.alias.match(query)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (target.term?.resolved?.match(query)) {
|
} else if (target.term.resolved.match(query)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (target.definition?.formal.match(query)) {
|
} else if (target.definition.formal.match(query)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (target.definition?.text.resolved?.match(query)) {
|
} else if (target.definition.text.resolved.match(query)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (target.convention?.match(query)) {
|
} else if (target.convention.match(query)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function matchRSFormMeta(query: string, target: IRSFormMeta) {
|
||||||
|
const queryI = query.toUpperCase();
|
||||||
|
if (target.alias.toUpperCase().match(queryI)) {
|
||||||
|
return true;
|
||||||
|
} else if (target.title.toUpperCase().match(queryI)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user