F: Implement react-query for backend interactions
This commit is contained in:
parent
519b5f6634
commit
fe65dcd574
|
@ -1,8 +1,7 @@
|
||||||
import { useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query';
|
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { useLibrary, useLibrarySuspense } from '@/backend/library/useLibrary';
|
import { useLibrary, useLibrarySuspense } from '@/backend/library/useLibrary';
|
||||||
import { LibraryItemID } from '@/models/library';
|
import { LibraryItemID } from '@/models/library';
|
||||||
import { IOperationSchema, IOperationSchemaData } from '@/models/oss';
|
|
||||||
import { OssLoader } from '@/models/OssLoader';
|
import { OssLoader } from '@/models/OssLoader';
|
||||||
|
|
||||||
import { ossApi } from './api';
|
import { ossApi } from './api';
|
||||||
|
@ -25,23 +24,3 @@ export function useOssSuspense({ itemID }: { itemID: LibraryItemID }) {
|
||||||
const schema = new OssLoader(data!, libraryItems).produceOSS();
|
const schema = new OssLoader(data!, libraryItems).produceOSS();
|
||||||
return { schema };
|
return { schema };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useOssUpdate({ itemID }: { itemID?: LibraryItemID }) {
|
|
||||||
const { items: libraryItems } = useLibrary();
|
|
||||||
const client = useQueryClient();
|
|
||||||
const queryKey = [ossApi.getOssQueryOptions({ itemID }).queryKey];
|
|
||||||
return {
|
|
||||||
update: (data: IOperationSchemaData) =>
|
|
||||||
client.setQueryData(queryKey, new OssLoader(data, libraryItems).produceOSS()),
|
|
||||||
partialUpdate: (data: Partial<IOperationSchema>) =>
|
|
||||||
client.setQueryData(queryKey, (prev: IOperationSchema) => (prev ? { ...prev, ...data } : prev))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useOssInvalidate({ itemID }: { itemID?: LibraryItemID }) {
|
|
||||||
const client = useQueryClient();
|
|
||||||
const queryKey = [ossApi.getOssQueryOptions({ itemID }).queryKey];
|
|
||||||
return {
|
|
||||||
invalidate: () => client.invalidateQueries({ queryKey })
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ export const useCheckConstituenta = () => {
|
||||||
onSuccess?: DataCallback<IExpressionParse>
|
onSuccess?: DataCallback<IExpressionParse>
|
||||||
) => mutation.mutate(data, { onSuccess }),
|
) => mutation.mutate(data, { onSuccess }),
|
||||||
isPending: mutation.isPending,
|
isPending: mutation.isPending,
|
||||||
error: mutation.error,
|
error: mutation.error
|
||||||
reset: mutation.reset
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
import { useCallback, useState } from 'react';
|
|
||||||
|
|
||||||
import { DataCallback } from '@/backend/apiTransport';
|
|
||||||
import { ICheckConstituentaDTO } from '@/backend/rsform/api';
|
|
||||||
import { useCheckConstituenta } from '@/backend/rsform/useCheckConstituenta';
|
|
||||||
import { IConstituenta, type IRSForm } from '@/models/rsform';
|
|
||||||
import { IExpressionParse } from '@/models/rslang';
|
|
||||||
|
|
||||||
function useRSParse({ schema }: { schema?: IRSForm }) {
|
|
||||||
const [parseData, setParseData] = useState<IExpressionParse | undefined>(undefined);
|
|
||||||
|
|
||||||
const resetParse = useCallback(() => setParseData(undefined), []);
|
|
||||||
const { checkConstituenta: checkInternal, isPending, error, reset } = useCheckConstituenta();
|
|
||||||
|
|
||||||
function checkConstituenta(expression: string, activeCst: IConstituenta, onSuccess?: DataCallback<IExpressionParse>) {
|
|
||||||
const data: ICheckConstituentaDTO = {
|
|
||||||
definition_formal: expression,
|
|
||||||
alias: activeCst.alias,
|
|
||||||
cst_type: activeCst.cst_type
|
|
||||||
};
|
|
||||||
checkInternal({ itemID: schema!.id, data }, parse => {
|
|
||||||
setParseData(parse);
|
|
||||||
onSuccess?.(parse);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return { parseData, checkConstituenta, resetParse, error, reset, isPending };
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useRSParse;
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
import { createContext, useContext, useEffect, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||||
|
@ -130,16 +130,13 @@ export const OssEditState = ({ itemID, children }: React.PropsWithChildren<OssEd
|
||||||
router.push(url);
|
router.push(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigateOperationSchema = useCallback(
|
function navigateOperationSchema(target: OperationID) {
|
||||||
(target: OperationID) => {
|
|
||||||
const node = schema.operationByID.get(target);
|
const node = schema.operationByID.get(target);
|
||||||
if (!node?.result) {
|
if (!node?.result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
router.push(urls.schema_props({ id: node.result, tab: RSTabID.CST_LIST }));
|
router.push(urls.schema_props({ id: node.result, tab: RSTabID.CST_LIST }));
|
||||||
},
|
}
|
||||||
[router, schema]
|
|
||||||
);
|
|
||||||
|
|
||||||
function deleteSchema() {
|
function deleteSchema() {
|
||||||
if (!schema || !window.confirm(prompts.deleteOSS)) {
|
if (!schema || !window.confirm(prompts.deleteOSS)) {
|
||||||
|
|
|
@ -4,6 +4,9 @@ import { ReactCodeMirrorRef } from '@uiw/react-codemirror';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
import { DataCallback } from '@/backend/apiTransport';
|
||||||
|
import { ICheckConstituentaDTO } from '@/backend/rsform/api';
|
||||||
|
import { useCheckConstituenta } from '@/backend/rsform/useCheckConstituenta';
|
||||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||||
import { CProps } from '@/components/props';
|
import { CProps } from '@/components/props';
|
||||||
|
@ -11,7 +14,6 @@ import RSInput from '@/components/RSInput';
|
||||||
import { parser as rslangParser } from '@/components/RSInput/rslang/parserAST';
|
import { parser as rslangParser } from '@/components/RSInput/rslang/parserAST';
|
||||||
import { RSTextWrapper } from '@/components/RSInput/textEditing';
|
import { RSTextWrapper } from '@/components/RSInput/textEditing';
|
||||||
import Overlay from '@/components/ui/Overlay';
|
import Overlay from '@/components/ui/Overlay';
|
||||||
import useRSParse from '@/hooks/useRSParse';
|
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
import { ConstituentaID, IConstituenta } from '@/models/rsform';
|
import { ConstituentaID, IConstituenta } from '@/models/rsform';
|
||||||
import { getDefinitionPrefix } from '@/models/rsformAPI';
|
import { getDefinitionPrefix } from '@/models/rsformAPI';
|
||||||
|
@ -60,17 +62,31 @@ function EditorRSExpression({
|
||||||
const controller = useRSEdit();
|
const controller = useRSEdit();
|
||||||
|
|
||||||
const [isModified, setIsModified] = useState(false);
|
const [isModified, setIsModified] = useState(false);
|
||||||
const parser = useRSParse({ schema: controller.schema });
|
|
||||||
const rsInput = useRef<ReactCodeMirrorRef>(null);
|
const rsInput = useRef<ReactCodeMirrorRef>(null);
|
||||||
|
const [parseData, setParseData] = useState<IExpressionParse | undefined>(undefined);
|
||||||
|
|
||||||
const isProcessing = useIsProcessingRSForm();
|
const isProcessing = useIsProcessingRSForm();
|
||||||
const showControls = usePreferencesStore(state => state.showExpressionControls);
|
const showControls = usePreferencesStore(state => state.showExpressionControls);
|
||||||
const showAST = useDialogsStore(state => state.showShowAST);
|
const showAST = useDialogsStore(state => state.showShowAST);
|
||||||
|
|
||||||
|
const { checkConstituenta: checkInternal, isPending } = useCheckConstituenta();
|
||||||
|
|
||||||
|
function checkConstituenta(expression: string, activeCst: IConstituenta, onSuccess?: DataCallback<IExpressionParse>) {
|
||||||
|
const data: ICheckConstituentaDTO = {
|
||||||
|
definition_formal: expression,
|
||||||
|
alias: activeCst.alias,
|
||||||
|
cst_type: activeCst.cst_type
|
||||||
|
};
|
||||||
|
checkInternal({ itemID: controller.schema.id, data }, parse => {
|
||||||
|
setParseData(parse);
|
||||||
|
onSuccess?.(parse);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsModified(false);
|
setIsModified(false);
|
||||||
parser.resetParse();
|
setParseData(undefined);
|
||||||
}, [activeCst, parser, toggleReset]);
|
}, [activeCst, toggleReset]);
|
||||||
|
|
||||||
function handleChange(newValue: string) {
|
function handleChange(newValue: string) {
|
||||||
onChangeExpression(newValue);
|
onChangeExpression(newValue);
|
||||||
|
@ -78,7 +94,7 @@ function EditorRSExpression({
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCheckExpression(callback?: (parse: IExpressionParse) => void) {
|
function handleCheckExpression(callback?: (parse: IExpressionParse) => void) {
|
||||||
parser.checkConstituenta(value, activeCst, parse => {
|
checkConstituenta(value, activeCst, parse => {
|
||||||
onChangeLocalParse(parse);
|
onChangeLocalParse(parse);
|
||||||
if (parse.errors.length > 0) {
|
if (parse.errors.length > 0) {
|
||||||
onShowError(parse.errors[0], parse.prefixLen);
|
onShowError(parse.errors[0], parse.prefixLen);
|
||||||
|
@ -152,10 +168,10 @@ function EditorRSExpression({
|
||||||
className='w-fit pl-[8.5rem] xs:pl-[2rem] flex gap-1'
|
className='w-fit pl-[8.5rem] xs:pl-[2rem] flex gap-1'
|
||||||
>
|
>
|
||||||
<StatusBar
|
<StatusBar
|
||||||
processing={parser.isPending}
|
processing={isPending}
|
||||||
isModified={isModified}
|
isModified={isModified}
|
||||||
activeCst={activeCst}
|
activeCst={activeCst}
|
||||||
parseData={parser.parseData}
|
parseData={parseData}
|
||||||
onAnalyze={() => handleCheckExpression()}
|
onAnalyze={() => handleCheckExpression()}
|
||||||
/>
|
/>
|
||||||
<BadgeHelp topic={HelpTopic.UI_CST_STATUS} offset={4} />
|
<BadgeHelp topic={HelpTopic.UI_CST_STATUS} offset={4} />
|
||||||
|
@ -181,10 +197,10 @@ function EditorRSExpression({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ParsingResult
|
<ParsingResult
|
||||||
isOpen={!!parser.parseData && parser.parseData.errors.length > 0}
|
isOpen={!!parseData && parseData.errors.length > 0}
|
||||||
data={parser.parseData}
|
data={parseData}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onShowError={error => onShowError(error, parser.parseData?.prefixLen ?? 0)}
|
onShowError={error => onShowError(error, parseData?.prefixLen ?? 0)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -381,7 +381,6 @@ function MenuRSTabs() {
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
router.push(urls.schema(itemID, version), newTab);
|
|
||||||
{controller.isArchive && user ? (
|
{controller.isArchive && user ? (
|
||||||
<Button
|
<Button
|
||||||
dense
|
dense
|
||||||
|
|
|
@ -99,13 +99,7 @@ export const RSEditState = ({ itemID, versionID, activeTab, children }: React.Pr
|
||||||
const [selected, setSelected] = useState<ConstituentaID[]>([]);
|
const [selected, setSelected] = useState<ConstituentaID[]>([]);
|
||||||
const canDeleteSelected = selected.length > 0 && selected.every(id => !schema.cstByID.get(id)?.is_inherited);
|
const canDeleteSelected = selected.length > 0 && selected.every(id => !schema.cstByID.get(id)?.is_inherited);
|
||||||
|
|
||||||
const activeCst: IConstituenta | undefined = (() => {
|
const activeCst = selected.length === 0 ? undefined : schema.cstByID.get(selected[selected.length - 1]);
|
||||||
if (!schema || selected.length === 0) {
|
|
||||||
return undefined;
|
|
||||||
} else {
|
|
||||||
return schema.cstByID.get(selected[-1]);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
const { cstCreate } = useCstCreate();
|
const { cstCreate } = useCstCreate();
|
||||||
const { cstMove } = useCstMove();
|
const { cstMove } = useCstMove();
|
||||||
|
|
|
@ -37,14 +37,14 @@ function RSTabs() {
|
||||||
return () => {
|
return () => {
|
||||||
document.title = oldTitle;
|
document.title = oldTitle;
|
||||||
};
|
};
|
||||||
}, [schema?.title]);
|
}, [schema.title]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
hideFooter(activeTab !== RSTabID.CARD);
|
hideFooter(activeTab !== RSTabID.CARD);
|
||||||
setIsModified(false);
|
setIsModified(false);
|
||||||
if (activeTab === RSTabID.CST_EDIT) {
|
if (activeTab === RSTabID.CST_EDIT) {
|
||||||
const cstID = Number(cstQuery);
|
const cstID = Number(cstQuery);
|
||||||
if (cstID && schema?.cstByID.has(cstID)) {
|
if (cstID && schema.cstByID.has(cstID)) {
|
||||||
setSelected([cstID]);
|
setSelected([cstID]);
|
||||||
} else {
|
} else {
|
||||||
setSelected([]);
|
setSelected([]);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export { default } from './RSTabs';
|
export { default } from './RSFormPage';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user