Implement RSForm clone

This commit is contained in:
IRBorisov 2023-07-28 01:37:26 +03:00
parent e83ccd63fc
commit ff75bef064
7 changed files with 140 additions and 16 deletions

View File

@ -38,7 +38,7 @@ function Modal({ title, show, hideWindow, onSubmit, onCancel, canSubmit, childre
<>
<div className='fixed top-0 left-0 z-50 w-full h-full opacity-50 clr-modal'>
</div>
<div ref={ref} className='fixed bottom-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2 px-6 py-4 flex flex-col w-fit z-[60] clr-card border shadow-md'>
<div ref={ref} className='fixed bottom-1/2 left-1/2 translate-y-1/2 -translate-x-1/2 px-6 py-4 flex flex-col w-fit h-fit z-[60] clr-card border shadow-md mb-[5rem]'>
{ title && <h1 className='mb-4 text-xl font-bold text-center'>{title}</h1> }
<div className='py-2'>
{children}
@ -46,7 +46,7 @@ function Modal({ title, show, hideWindow, onSubmit, onCancel, canSubmit, childre
<div className='flex justify-between w-full pt-4 mt-2 border-t-4'>
<Button
text={submitText}
widthClass='min-w-[6rem] w-fit h-fit'
widthClass='min-w-[6rem] min-h-[2.6rem] w-fit h-fit'
colorClass='clr-btn-primary'
disabled={!canSubmit}
onClick={handleSubmit}
@ -54,6 +54,7 @@ function Modal({ title, show, hideWindow, onSubmit, onCancel, canSubmit, childre
/>
<Button
text='Отмена'
widthClass='min-w-[6rem] min-h-[2.6rem] w-fit h-fit'
onClick={handleCancel}
/>
</div>

View File

@ -7,10 +7,10 @@ import {
type DataCallback, deleteRSForm, getTRSFile,
patchConstituenta, patchDeleteConstituenta, patchMoveConstituenta, patchResetAliases,
patchRSForm,
patchUploadTRS, postClaimRSForm, postNewConstituenta} from '../utils/backendAPI'
patchUploadTRS, postClaimRSForm, postCloneRSForm,postNewConstituenta} from '../utils/backendAPI'
import {
IConstituenta, IConstituentaList, IConstituentaMeta, ICstCreateData,
ICstMovetoData, ICstUpdateData, IRSForm, IRSFormMeta, IRSFormUpdateData, IRSFormUploadData
ICstMovetoData, ICstUpdateData, IRSForm, IRSFormCreateData, IRSFormData, IRSFormMeta, IRSFormUpdateData, IRSFormUploadData
} from '../utils/models'
import { useAuth } from './AuthContext'
@ -34,12 +34,13 @@ interface IRSFormContext {
toggleForceAdmin: () => void
toggleReadonly: () => void
toggleTracking: () => void
update: (data: IRSFormUpdateData, callback?: DataCallback<IRSFormMeta>) => void
destroy: (callback?: () => void) => void
claim: (callback?: DataCallback<IRSFormMeta>) => void
download: (callback: DataCallback<Blob>) => void
upload: (data: IRSFormUploadData, callback: () => void) => void
clone: (data: IRSFormCreateData, callback: DataCallback<IRSFormData>) => void
resetAliases: (callback: () => void) => void
cstCreate: (data: ICstCreateData, callback?: DataCallback<IConstituentaMeta>) => void
@ -165,6 +166,21 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
});
}, [schemaID, setError, schema, user, setSchema])
const clone = useCallback(
(data: IRSFormCreateData, callback: DataCallback<IRSFormData>) => {
if (!schema || !user) {
return;
}
setError(undefined)
postCloneRSForm(schemaID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: error => { setError(error) },
onSuccess: callback
});
}, [schemaID, setError, schema, user])
const resetAliases = useCallback(
(callback?: () => void) => {
if (!schema || !user) {
@ -262,7 +278,7 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
toggleForceAdmin: () => { setIsForceAdmin(prev => !prev) },
toggleReadonly: () => { setIsReadonly(prev => !prev) },
toggleTracking,
update, download, upload, destroy, claim, resetAliases,
update, download, upload, destroy, claim, resetAliases, clone,
cstUpdate, cstCreate, cstDelete, cstMoveTo
}}>
{ children }

View File

@ -0,0 +1,82 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify';
import Checkbox from '../../components/Common/Checkbox';
import Modal from '../../components/Common/Modal';
import TextArea from '../../components/Common/TextArea';
import TextInput from '../../components/Common/TextInput';
import { useRSForm } from '../../context/RSFormContext';
import { IRSFormCreateData } from '../../utils/models';
import { getCloneTitle } from '../../utils/staticUI';
interface DlgCloneRSFormProps {
show: boolean
hideWindow: () => void
}
function DlgCloneRSForm({ show, hideWindow }: DlgCloneRSFormProps) {
const navigate = useNavigate();
const [title, setTitle] = useState('');
const [alias, setAlias] = useState('');
const [comment, setComment] = useState('');
const [common, setCommon] = useState(false);
const { schema, clone } = useRSForm();
useEffect(() => {
if (schema) {
setTitle(getCloneTitle(schema))
setAlias(schema.alias)
setComment(schema.comment)
setCommon(schema.is_common)
}
}, [schema, schema?.title, schema?.alias, schema?.comment, schema?.is_common]);
const handleSubmit = () => {
hideWindow();
const data: IRSFormCreateData = {
title: title,
alias: alias,
comment: comment,
is_common: common
};
clone(data, newSchema => {
toast.success(`Схема создана: ${newSchema.alias}`);
navigate(`/rsforms/${newSchema.id}`);
});
};
return (
<Modal
title='Создание копии концептуальной схемы'
show={show}
hideWindow={hideWindow}
canSubmit={true}
submitText='Создать'
onSubmit={handleSubmit}
>
<TextInput id='title' label='Полное название' type='text'
required
value={title}
onChange={event => { setTitle(event.target.value); }}
/>
<TextInput id='alias' label='Сокращение' type='text'
required
value={alias}
widthClass='max-w-sm'
onChange={event => { setAlias(event.target.value); }}
/>
<TextArea id='comment' label='Комментарий'
value={comment}
onChange={event => { setComment(event.target.value); }}
/>
<Checkbox id='common' label='Общедоступная схема'
value={common}
onChange={event => { setCommon(event.target.checked); }}
/>
</Modal>
)
}
export default DlgCloneRSForm;

View File

@ -25,7 +25,6 @@ function RSTabs() {
const [init, setInit] = useState(false);
const onEditCst = (cst: IConstituenta) => {
console.log(`Set active cst: ${cst.alias}`);
setActiveID(cst.id);
setTabIndex(RSTabsList.CST_EDIT)
};
@ -38,11 +37,17 @@ function RSTabs() {
if (schema) {
const url = new URL(window.location.href);
const activeQuery = url.searchParams.get('active');
const activeCst = schema?.items?.find((cst) => cst.id === Number(activeQuery));
const activeCst = schema.items.find((cst) => cst.id === Number(activeQuery));
setActiveID(activeCst?.id);
setInit(true);
const oldTitle = document.title
document.title = schema.title
return () => {
document.title = oldTitle
}
}
}, [setActiveID, schema, setInit]);
}, [setActiveID, schema, schema?.title, setInit]);
useEffect(() => {
const url = new URL(window.location.href);

View File

@ -1,6 +1,5 @@
import { useCallback, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify';
import Button from '../../components/Common/Button';
import Checkbox from '../../components/Common/Checkbox';
@ -11,6 +10,7 @@ import { useAuth } from '../../context/AuthContext';
import { useRSForm } from '../../context/RSFormContext';
import useDropdown from '../../hooks/useDropdown';
import { claimOwnershipProc, deleteRSFormProc, downloadRSFormProc, shareCurrentURLProc } from '../../utils/procedures';
import DlgCloneRSForm from './DlgCloneRSForm';
import DlgUploadRSForm from './DlgUploadRSForm';
function RSTabsMenu() {
@ -24,7 +24,8 @@ function RSTabsMenu() {
} = useRSForm();
const schemaMenu = useDropdown();
const editMenu = useDropdown();
const [showUploadModal, setShowUploadModal] = useState(false);
const [showUploadDialog, setShowUploadDialog] = useState(false);
const [showCloneDialog, setShowCloneDialogl] = useState(false);
const handleClaimOwner = useCallback(() => {
editMenu.hide();
@ -44,13 +45,12 @@ function RSTabsMenu() {
const handleUpload = useCallback(() => {
schemaMenu.hide();
setShowUploadModal(true);
setShowUploadDialog(true);
}, [schemaMenu]);
const handleClone = useCallback(() => {
// TODO: implement
schemaMenu.hide();
toast.info('Клонирование РС-формы');
setShowCloneDialogl(true);
}, [schemaMenu]);
const handleShare = useCallback(() => {
@ -61,8 +61,12 @@ function RSTabsMenu() {
return (
<>
<DlgUploadRSForm
show={showUploadModal}
hideWindow={() => { setShowUploadModal(false); }}
show={showUploadDialog}
hideWindow={() => { setShowUploadDialog(false); }}
/>
<DlgCloneRSForm
show={showCloneDialog}
hideWindow={() => { setShowCloneDialogl(false); }}
/>
<div className='flex items-center w-fit'>
<div ref={schemaMenu.ref}>

View File

@ -120,6 +120,14 @@ export function postNewRSForm(request: FrontExchange<IRSFormCreateData, IRSFormM
});
}
export function postCloneRSForm(schema: string, request: FrontExchange<IRSFormCreateData, IRSFormData>) {
AxiosPost({
title: 'clone RSForm',
endpoint: `${config.url.BASE}rsforms/${schema}/clone/`,
request: request
});
}
export function getRSFormDetails(target: string, request: FrontPull<IRSFormData>) {
AxiosGet({
title: `RSForm details for id=${target}`,

View File

@ -313,4 +313,12 @@ export function getMockConstituenta(id: number, alias: string, type: CstType, co
syntaxTree: ''
}
};
}
export function getCloneTitle(schema: IRSForm): string {
if (!schema.title.includes('[клон]')) {
return schema.title + ' [клон]';
} else {
return (schema.title + '+');
}
}