mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
Implement RSForm clone
This commit is contained in:
parent
e83ccd63fc
commit
ff75bef064
|
@ -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 className='fixed top-0 left-0 z-50 w-full h-full opacity-50 clr-modal'>
|
||||||
</div>
|
</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> }
|
{ title && <h1 className='mb-4 text-xl font-bold text-center'>{title}</h1> }
|
||||||
<div className='py-2'>
|
<div className='py-2'>
|
||||||
{children}
|
{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'>
|
<div className='flex justify-between w-full pt-4 mt-2 border-t-4'>
|
||||||
<Button
|
<Button
|
||||||
text={submitText}
|
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'
|
colorClass='clr-btn-primary'
|
||||||
disabled={!canSubmit}
|
disabled={!canSubmit}
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
|
@ -54,6 +54,7 @@ function Modal({ title, show, hideWindow, onSubmit, onCancel, canSubmit, childre
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
text='Отмена'
|
text='Отмена'
|
||||||
|
widthClass='min-w-[6rem] min-h-[2.6rem] w-fit h-fit'
|
||||||
onClick={handleCancel}
|
onClick={handleCancel}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,10 +7,10 @@ import {
|
||||||
type DataCallback, deleteRSForm, getTRSFile,
|
type DataCallback, deleteRSForm, getTRSFile,
|
||||||
patchConstituenta, patchDeleteConstituenta, patchMoveConstituenta, patchResetAliases,
|
patchConstituenta, patchDeleteConstituenta, patchMoveConstituenta, patchResetAliases,
|
||||||
patchRSForm,
|
patchRSForm,
|
||||||
patchUploadTRS, postClaimRSForm, postNewConstituenta} from '../utils/backendAPI'
|
patchUploadTRS, postClaimRSForm, postCloneRSForm,postNewConstituenta} from '../utils/backendAPI'
|
||||||
import {
|
import {
|
||||||
IConstituenta, IConstituentaList, IConstituentaMeta, ICstCreateData,
|
IConstituenta, IConstituentaList, IConstituentaMeta, ICstCreateData,
|
||||||
ICstMovetoData, ICstUpdateData, IRSForm, IRSFormMeta, IRSFormUpdateData, IRSFormUploadData
|
ICstMovetoData, ICstUpdateData, IRSForm, IRSFormCreateData, IRSFormData, IRSFormMeta, IRSFormUpdateData, IRSFormUploadData
|
||||||
} from '../utils/models'
|
} from '../utils/models'
|
||||||
import { useAuth } from './AuthContext'
|
import { useAuth } from './AuthContext'
|
||||||
|
|
||||||
|
@ -34,12 +34,13 @@ interface IRSFormContext {
|
||||||
toggleForceAdmin: () => void
|
toggleForceAdmin: () => void
|
||||||
toggleReadonly: () => void
|
toggleReadonly: () => void
|
||||||
toggleTracking: () => void
|
toggleTracking: () => void
|
||||||
|
|
||||||
update: (data: IRSFormUpdateData, callback?: DataCallback<IRSFormMeta>) => void
|
update: (data: IRSFormUpdateData, callback?: DataCallback<IRSFormMeta>) => void
|
||||||
destroy: (callback?: () => void) => void
|
destroy: (callback?: () => void) => void
|
||||||
claim: (callback?: DataCallback<IRSFormMeta>) => void
|
claim: (callback?: DataCallback<IRSFormMeta>) => void
|
||||||
download: (callback: DataCallback<Blob>) => void
|
download: (callback: DataCallback<Blob>) => void
|
||||||
upload: (data: IRSFormUploadData, callback: () => void) => void
|
upload: (data: IRSFormUploadData, callback: () => void) => void
|
||||||
|
clone: (data: IRSFormCreateData, callback: DataCallback<IRSFormData>) => void
|
||||||
resetAliases: (callback: () => void) => void
|
resetAliases: (callback: () => void) => void
|
||||||
|
|
||||||
cstCreate: (data: ICstCreateData, callback?: DataCallback<IConstituentaMeta>) => void
|
cstCreate: (data: ICstCreateData, callback?: DataCallback<IConstituentaMeta>) => void
|
||||||
|
@ -165,6 +166,21 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
|
||||||
});
|
});
|
||||||
}, [schemaID, setError, schema, user, setSchema])
|
}, [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(
|
const resetAliases = useCallback(
|
||||||
(callback?: () => void) => {
|
(callback?: () => void) => {
|
||||||
if (!schema || !user) {
|
if (!schema || !user) {
|
||||||
|
@ -262,7 +278,7 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
|
||||||
toggleForceAdmin: () => { setIsForceAdmin(prev => !prev) },
|
toggleForceAdmin: () => { setIsForceAdmin(prev => !prev) },
|
||||||
toggleReadonly: () => { setIsReadonly(prev => !prev) },
|
toggleReadonly: () => { setIsReadonly(prev => !prev) },
|
||||||
toggleTracking,
|
toggleTracking,
|
||||||
update, download, upload, destroy, claim, resetAliases,
|
update, download, upload, destroy, claim, resetAliases, clone,
|
||||||
cstUpdate, cstCreate, cstDelete, cstMoveTo
|
cstUpdate, cstCreate, cstDelete, cstMoveTo
|
||||||
}}>
|
}}>
|
||||||
{ children }
|
{ children }
|
||||||
|
|
82
rsconcept/frontend/src/pages/RSFormPage/DlgCloneRSForm.tsx
Normal file
82
rsconcept/frontend/src/pages/RSFormPage/DlgCloneRSForm.tsx
Normal 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;
|
|
@ -25,7 +25,6 @@ function RSTabs() {
|
||||||
const [init, setInit] = useState(false);
|
const [init, setInit] = useState(false);
|
||||||
|
|
||||||
const onEditCst = (cst: IConstituenta) => {
|
const onEditCst = (cst: IConstituenta) => {
|
||||||
console.log(`Set active cst: ${cst.alias}`);
|
|
||||||
setActiveID(cst.id);
|
setActiveID(cst.id);
|
||||||
setTabIndex(RSTabsList.CST_EDIT)
|
setTabIndex(RSTabsList.CST_EDIT)
|
||||||
};
|
};
|
||||||
|
@ -38,11 +37,17 @@ function RSTabs() {
|
||||||
if (schema) {
|
if (schema) {
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(window.location.href);
|
||||||
const activeQuery = url.searchParams.get('active');
|
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);
|
setActiveID(activeCst?.id);
|
||||||
setInit(true);
|
setInit(true);
|
||||||
|
|
||||||
|
const oldTitle = document.title
|
||||||
|
document.title = schema.title
|
||||||
|
return () => {
|
||||||
|
document.title = oldTitle
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [setActiveID, schema, setInit]);
|
}, [setActiveID, schema, schema?.title, setInit]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(window.location.href);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { toast } from 'react-toastify';
|
|
||||||
|
|
||||||
import Button from '../../components/Common/Button';
|
import Button from '../../components/Common/Button';
|
||||||
import Checkbox from '../../components/Common/Checkbox';
|
import Checkbox from '../../components/Common/Checkbox';
|
||||||
|
@ -11,6 +10,7 @@ import { useAuth } from '../../context/AuthContext';
|
||||||
import { useRSForm } from '../../context/RSFormContext';
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
import useDropdown from '../../hooks/useDropdown';
|
import useDropdown from '../../hooks/useDropdown';
|
||||||
import { claimOwnershipProc, deleteRSFormProc, downloadRSFormProc, shareCurrentURLProc } from '../../utils/procedures';
|
import { claimOwnershipProc, deleteRSFormProc, downloadRSFormProc, shareCurrentURLProc } from '../../utils/procedures';
|
||||||
|
import DlgCloneRSForm from './DlgCloneRSForm';
|
||||||
import DlgUploadRSForm from './DlgUploadRSForm';
|
import DlgUploadRSForm from './DlgUploadRSForm';
|
||||||
|
|
||||||
function RSTabsMenu() {
|
function RSTabsMenu() {
|
||||||
|
@ -24,7 +24,8 @@ function RSTabsMenu() {
|
||||||
} = useRSForm();
|
} = useRSForm();
|
||||||
const schemaMenu = useDropdown();
|
const schemaMenu = useDropdown();
|
||||||
const editMenu = useDropdown();
|
const editMenu = useDropdown();
|
||||||
const [showUploadModal, setShowUploadModal] = useState(false);
|
const [showUploadDialog, setShowUploadDialog] = useState(false);
|
||||||
|
const [showCloneDialog, setShowCloneDialogl] = useState(false);
|
||||||
|
|
||||||
const handleClaimOwner = useCallback(() => {
|
const handleClaimOwner = useCallback(() => {
|
||||||
editMenu.hide();
|
editMenu.hide();
|
||||||
|
@ -44,13 +45,12 @@ function RSTabsMenu() {
|
||||||
|
|
||||||
const handleUpload = useCallback(() => {
|
const handleUpload = useCallback(() => {
|
||||||
schemaMenu.hide();
|
schemaMenu.hide();
|
||||||
setShowUploadModal(true);
|
setShowUploadDialog(true);
|
||||||
}, [schemaMenu]);
|
}, [schemaMenu]);
|
||||||
|
|
||||||
const handleClone = useCallback(() => {
|
const handleClone = useCallback(() => {
|
||||||
// TODO: implement
|
|
||||||
schemaMenu.hide();
|
schemaMenu.hide();
|
||||||
toast.info('Клонирование РС-формы');
|
setShowCloneDialogl(true);
|
||||||
}, [schemaMenu]);
|
}, [schemaMenu]);
|
||||||
|
|
||||||
const handleShare = useCallback(() => {
|
const handleShare = useCallback(() => {
|
||||||
|
@ -61,8 +61,12 @@ function RSTabsMenu() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DlgUploadRSForm
|
<DlgUploadRSForm
|
||||||
show={showUploadModal}
|
show={showUploadDialog}
|
||||||
hideWindow={() => { setShowUploadModal(false); }}
|
hideWindow={() => { setShowUploadDialog(false); }}
|
||||||
|
/>
|
||||||
|
<DlgCloneRSForm
|
||||||
|
show={showCloneDialog}
|
||||||
|
hideWindow={() => { setShowCloneDialogl(false); }}
|
||||||
/>
|
/>
|
||||||
<div className='flex items-center w-fit'>
|
<div className='flex items-center w-fit'>
|
||||||
<div ref={schemaMenu.ref}>
|
<div ref={schemaMenu.ref}>
|
||||||
|
|
|
@ -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>) {
|
export function getRSFormDetails(target: string, request: FrontPull<IRSFormData>) {
|
||||||
AxiosGet({
|
AxiosGet({
|
||||||
title: `RSForm details for id=${target}`,
|
title: `RSForm details for id=${target}`,
|
||||||
|
|
|
@ -313,4 +313,12 @@ export function getMockConstituenta(id: number, alias: string, type: CstType, co
|
||||||
syntaxTree: ''
|
syntaxTree: ''
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCloneTitle(schema: IRSForm): string {
|
||||||
|
if (!schema.title.includes('[клон]')) {
|
||||||
|
return schema.title + ' [клон]';
|
||||||
|
} else {
|
||||||
|
return (schema.title + '+');
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user