mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
UI: Improve editing experience
This commit is contained in:
parent
bdbf77faa2
commit
4cd8b31b59
|
@ -1,5 +1,5 @@
|
||||||
interface FormProps {
|
interface FormProps {
|
||||||
title: string
|
title?: string
|
||||||
dimensions?: string
|
dimensions?: string
|
||||||
onSubmit: (event: React.FormEvent<HTMLFormElement>) => void
|
onSubmit: (event: React.FormEvent<HTMLFormElement>) => void
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
|
|
@ -3,20 +3,20 @@ import InfoCstStatus from './InfoCstStatus';
|
||||||
|
|
||||||
function HelpConstituenta() {
|
function HelpConstituenta() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className='leading-tight'>
|
||||||
<h1>Подсказки</h1>
|
<h1>Подсказки</h1>
|
||||||
<p><b className='text-warning'>Изменения сохраняются ПОСЛЕ нажатия на соответствующую кнопку снизу или по центру</b></p>
|
<p><b>Сохранить изменения</b>: Ctrl + S или клик по кнопке Сохранить</p>
|
||||||
<p><b>Формальное определение</b> - обратите внимание на кнопки снизу<br/>Горячие клавиши указаны в подсказках при наведении</p>
|
<p className='mt-1'><b>Формальное определение</b>: обратите внимание на кнопки снизу<br/>Горячие клавиши указаны в подсказках при наведении</p>
|
||||||
<p><b>Поля Термин и Определение</b> - Ctrl + Пробел открывает диалог редактирования отсылок<br/>Перед открытием диалога переместите текстовый курсор на заменяемое слово или ссылку</p>
|
<p className='mt-1'><b>Поля Термин и Определение</b>: Ctrl + Пробел открывает диалог редактирования отсылок<br/>Перед открытием диалога переместите текстовый курсор на заменяемое слово или ссылку</p>
|
||||||
<p><b>Список конституент справа</b> - обратите внимание на настройки фильтрации</p>
|
<p className='mt-1'><b>Список конституент справа</b>: обратите внимание на настройки фильтрации</p>
|
||||||
<p>- слева от ввода текста настраивается набор атрибутов конституенты</p>
|
<p>- первая настройка - атрибуты конституенты</p>
|
||||||
<p>- справа от ввода текста настраивается список конституент, которые фильтруются</p>
|
<p>- вторая настройка - принцип отбора конституент по графу термов</p>
|
||||||
<p>- текущая конституента выделена цветом строки</p>
|
<p>- текущая конституента выделена цветом строки</p>
|
||||||
<p>- двойной клик / Alt + клик - выбор редактируемой конституенты</p>
|
<p>- двойной клик / Alt + клик - выбор редактируемой конституенты</p>
|
||||||
<p>- при наведении на ID конституенты отображаются ее атрибуты</p>
|
<p>- при наведении на имя конституенты отображаются ее атрибуты</p>
|
||||||
<p>- столбец "Описание" содержит один из непустых текстовых атрибутов</p>
|
<p>- столбец "Описание" содержит один из непустых текстовых атрибутов</p>
|
||||||
|
|
||||||
<Divider margins='mt-2' />
|
<Divider margins='mt-4' />
|
||||||
|
|
||||||
<InfoCstStatus title='Статусы' />
|
<InfoCstStatus title='Статусы' />
|
||||||
</div>);
|
</div>);
|
||||||
|
|
|
@ -2,6 +2,7 @@ function HelpRSFormMeta() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Паспорт схемы</h1>
|
<h1>Паспорт схемы</h1>
|
||||||
|
<p><b>Сохранить изменения</b>: Ctrl + S или клик по кнопке Сохранить</p>
|
||||||
<p><b>Владелец</b> - пользователь, обладающий правом редактирования</p>
|
<p><b>Владелец</b> - пользователь, обладающий правом редактирования</p>
|
||||||
<p>Для <b>общедоступных</b> схем владельцем может стать любой пользователь</p>
|
<p>Для <b>общедоступных</b> схем владельцем может стать любой пользователь</p>
|
||||||
<p>Для <b>неизменных</b> схем правом редактирования обладают только администраторы</p>
|
<p>Для <b>неизменных</b> схем правом редактирования обладают только администраторы</p>
|
||||||
|
|
|
@ -19,7 +19,7 @@ function InfoCstClass({ title }: InfoCstClassProps) {
|
||||||
return (
|
return (
|
||||||
<p key={`${prefixes.cst_status_list}${index}`}>
|
<p key={`${prefixes.cst_status_list}${index}`}>
|
||||||
<span
|
<span
|
||||||
className='px-1 inline-block font-semibold min-w-[7rem] text-center border text-sm'
|
className='px-1 inline-block font-semibold min-w-[7rem] text-center border text-sm small-caps'
|
||||||
style={{backgroundColor: colorbgCstClass(cclass, colors)}}
|
style={{backgroundColor: colorbgCstClass(cclass, colors)}}
|
||||||
>
|
>
|
||||||
{labelCstClass(cclass)}
|
{labelCstClass(cclass)}
|
||||||
|
|
|
@ -21,7 +21,7 @@ function InfoCstStatus({ title }: InfoCstStatusProps) {
|
||||||
return (
|
return (
|
||||||
<p key={`${prefixes.cst_status_list}${index}`}>
|
<p key={`${prefixes.cst_status_list}${index}`}>
|
||||||
<span
|
<span
|
||||||
className='px-1 inline-block font-semibold min-w-[7rem] text-center border text-sm'
|
className='px-1 inline-block font-semibold min-w-[7rem] text-center border text-sm small-caps'
|
||||||
style={{backgroundColor: colorbgCstStatus(status, colors)}}
|
style={{backgroundColor: colorbgCstStatus(status, colors)}}
|
||||||
>
|
>
|
||||||
{labelExpressionStatus(status)}
|
{labelExpressionStatus(status)}
|
||||||
|
|
|
@ -104,29 +104,24 @@ function RSInput({
|
||||||
if (event.key === '*') {
|
if (event.key === '*') {
|
||||||
text.insertToken(TokenID.DECART);
|
text.insertToken(TokenID.DECART);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return;
|
} else if (event.code === 'KeyB') {
|
||||||
}
|
|
||||||
if (event.code === 'KeyB') {
|
|
||||||
text.insertChar('ℬ');
|
text.insertChar('ℬ');
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return;
|
} else if (event.code === 'KeyZ') {
|
||||||
|
text.insertChar('Z');
|
||||||
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
} else if (event.altKey) {
|
||||||
|
if (text.processAltKey(event.code, event.shiftKey)) {
|
||||||
if (event.altKey) {
|
event.preventDefault();
|
||||||
if (!text.processAltKey(event.code, event.shiftKey)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else if (!event.ctrlKey) {
|
} else if (!event.ctrlKey) {
|
||||||
const newSymbol = getSymbolSubstitute(event.code, event.shiftKey);
|
const newSymbol = getSymbolSubstitute(event.code, event.shiftKey);
|
||||||
if (!newSymbol) {
|
if (newSymbol) {
|
||||||
return;
|
text.replaceWith(newSymbol);
|
||||||
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
text.replaceWith(newSymbol);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
|
||||||
}, [thisRef]);
|
}, [thisRef]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -66,7 +66,7 @@ function LoginPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex items-start justify-center w-full pt-4 select-none' style={{minHeight: mainHeight}}>
|
<div className='flex items-start justify-center w-full pt-8 select-none' style={{minHeight: mainHeight}}>
|
||||||
{ user &&
|
{ user &&
|
||||||
<div className='flex flex-col items-center gap-2'>
|
<div className='flex flex-col items-center gap-2'>
|
||||||
<p className='font-semibold'>{`Вы вошли в систему как ${user.username}`}</p>
|
<p className='font-semibold'>{`Вы вошли в систему как ${user.username}`}</p>
|
||||||
|
@ -87,10 +87,13 @@ function LoginPage() {
|
||||||
</div>}
|
</div>}
|
||||||
{ !user &&
|
{ !user &&
|
||||||
<Form
|
<Form
|
||||||
title='Вход в Портал'
|
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
dimensions='w-[24rem]'
|
dimensions='w-[24rem]'
|
||||||
>
|
>
|
||||||
|
<img alt='Концепт Портал'
|
||||||
|
src='/logo_full.svg'
|
||||||
|
className='max-h-[2.5rem] min-w-[2.5rem] mt-2 mb-4'
|
||||||
|
/>
|
||||||
<TextInput id='username' type='text'
|
<TextInput id='username' type='text'
|
||||||
label='Имя пользователя'
|
label='Имя пользователя'
|
||||||
required
|
required
|
||||||
|
@ -107,7 +110,7 @@ function LoginPage() {
|
||||||
onChange={event => setPassword(event.target.value)}
|
onChange={event => setPassword(event.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='flex justify-center w-full gap-2 py-2'>
|
<div className='flex justify-center w-full py-2'>
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
text='Войти'
|
text='Войти'
|
||||||
dimensions='w-[12rem]'
|
dimensions='w-[12rem]'
|
||||||
|
|
|
@ -6,7 +6,7 @@ import MiniButton from '../../components/Common/MiniButton';
|
||||||
import SubmitButton from '../../components/Common/SubmitButton';
|
import SubmitButton from '../../components/Common/SubmitButton';
|
||||||
import TextArea from '../../components/Common/TextArea';
|
import TextArea from '../../components/Common/TextArea';
|
||||||
import HelpConstituenta from '../../components/Help/HelpConstituenta';
|
import HelpConstituenta from '../../components/Help/HelpConstituenta';
|
||||||
import { CloneIcon, DumpBinIcon, EditIcon, HelpIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons';
|
import { ArrowsRotateIcon, CloneIcon, DumpBinIcon, EditIcon, HelpIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons';
|
||||||
import RefsInput from '../../components/RefsInput';
|
import RefsInput from '../../components/RefsInput';
|
||||||
import { useRSForm } from '../../context/RSFormContext';
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/useWindowSize';
|
||||||
|
@ -47,6 +47,7 @@ function EditorConstituenta({
|
||||||
const [expression, setExpression] = useState('');
|
const [expression, setExpression] = useState('');
|
||||||
const [convention, setConvention] = useState('');
|
const [convention, setConvention] = useState('');
|
||||||
const [typification, setTypification] = useState('N/A');
|
const [typification, setTypification] = useState('N/A');
|
||||||
|
const [toggleReset, setToggleReset] = useState(false);
|
||||||
|
|
||||||
const isEnabled = useMemo(() => activeCst && isEditable, [activeCst, isEditable]);
|
const isEnabled = useMemo(() => activeCst && isEditable, [activeCst, isEditable]);
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ function EditorConstituenta({
|
||||||
setExpression(activeCst.definition_formal || '');
|
setExpression(activeCst.definition_formal || '');
|
||||||
setTypification(activeCst ? labelCstTypification(activeCst) : 'N/A');
|
setTypification(activeCst ? labelCstTypification(activeCst) : 'N/A');
|
||||||
}
|
}
|
||||||
}, [activeCst, onOpenEdit, schema]);
|
}, [activeCst, onOpenEdit, schema, toggleReset]);
|
||||||
|
|
||||||
function handleSubmit(event?: React.FormEvent<HTMLFormElement>) {
|
function handleSubmit(event?: React.FormEvent<HTMLFormElement>) {
|
||||||
if (event) {
|
if (event) {
|
||||||
|
@ -150,8 +151,17 @@ function EditorConstituenta({
|
||||||
onRenameCst(data);
|
onRenameCst(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleInput(event: React.KeyboardEvent<HTMLDivElement>) {
|
||||||
|
if (event.ctrlKey && event.code === 'KeyS') {
|
||||||
|
if (isModified) {
|
||||||
|
handleSubmit();
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex max-w-[1500px] gap-2'>
|
<div className='flex max-w-[1500px] gap-2' tabIndex={0} onKeyDown={handleInput}>
|
||||||
<form onSubmit={handleSubmit} className='min-w-[50rem] max-w-[50rem] px-4 py-1'>
|
<form onSubmit={handleSubmit} className='min-w-[50rem] max-w-[50rem] px-4 py-1'>
|
||||||
<div className='relative w-full'>
|
<div className='relative w-full'>
|
||||||
<div className='absolute top-0 right-0 flex items-start justify-between w-full'>
|
<div className='absolute top-0 right-0 flex items-start justify-between w-full'>
|
||||||
|
@ -184,6 +194,12 @@ function EditorConstituenta({
|
||||||
icon={<SaveIcon size={5} color={isModified && isEnabled ? 'text-primary' : ''}/>}
|
icon={<SaveIcon size={5} color={isModified && isEnabled ? 'text-primary' : ''}/>}
|
||||||
onClick={() => handleSubmit()}
|
onClick={() => handleSubmit()}
|
||||||
/>
|
/>
|
||||||
|
<MiniButton
|
||||||
|
tooltip='Сборсить несохраненные изменения'
|
||||||
|
disabled={!isEnabled || !isModified}
|
||||||
|
onClick={() => setToggleReset(prev => !prev)}
|
||||||
|
icon={<ArrowsRotateIcon size={5} color={isEnabled && isModified ? 'text-primary' : ''} />}
|
||||||
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip='Создать конституенту после данной'
|
tooltip='Создать конституенту после данной'
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
|
@ -234,6 +250,7 @@ function EditorConstituenta({
|
||||||
placeholder='Родоструктурное выражение, задающее формальное определение'
|
placeholder='Родоструктурное выражение, задающее формальное определение'
|
||||||
value={expression}
|
value={expression}
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
|
toggleReset={toggleReset}
|
||||||
onShowAST={onShowAST}
|
onShowAST={onShowAST}
|
||||||
onChange={newValue => setExpression(newValue)}
|
onChange={newValue => setExpression(newValue)}
|
||||||
setTypification={setTypification}
|
setTypification={setTypification}
|
||||||
|
|
|
@ -24,6 +24,7 @@ interface EditorRSExpressionProps {
|
||||||
activeCst?: IConstituenta
|
activeCst?: IConstituenta
|
||||||
label: string
|
label: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
toggleReset?: boolean
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
onShowAST: (expression: string, ast: SyntaxTree) => void
|
onShowAST: (expression: string, ast: SyntaxTree) => void
|
||||||
setTypification: (typificaiton: string) => void
|
setTypification: (typificaiton: string) => void
|
||||||
|
@ -32,7 +33,7 @@ interface EditorRSExpressionProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function EditorRSExpression({
|
function EditorRSExpression({
|
||||||
activeCst, disabled, value, onShowAST,
|
activeCst, disabled, value, onShowAST, toggleReset,
|
||||||
setTypification, onChange, ...props
|
setTypification, onChange, ...props
|
||||||
}: EditorRSExpressionProps) {
|
}: EditorRSExpressionProps) {
|
||||||
const { schema } = useRSForm();
|
const { schema } = useRSForm();
|
||||||
|
@ -44,7 +45,7 @@ function EditorRSExpression({
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
setIsModified(false);
|
setIsModified(false);
|
||||||
resetParse();
|
resetParse();
|
||||||
}, [activeCst, resetParse]);
|
}, [activeCst, resetParse, toggleReset]);
|
||||||
|
|
||||||
function handleChange(newvalue: string) {
|
function handleChange(newvalue: string) {
|
||||||
onChange(newvalue);
|
onChange(newvalue);
|
||||||
|
|
|
@ -69,8 +69,10 @@ function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified,
|
||||||
}
|
}
|
||||||
}, [schema]);
|
}, [schema]);
|
||||||
|
|
||||||
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
const handleSubmit = (event?: React.FormEvent<HTMLFormElement>) => {
|
||||||
event.preventDefault();
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
const data: IRSFormCreateData = {
|
const data: IRSFormCreateData = {
|
||||||
item_type: LibraryItemType.RSFORM,
|
item_type: LibraryItemType.RSFORM,
|
||||||
title: title,
|
title: title,
|
||||||
|
@ -82,8 +84,17 @@ function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified,
|
||||||
update(data, () => toast.success('Изменения сохранены'));
|
update(data, () => toast.success('Изменения сохранены'));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function handleInput(event: React.KeyboardEvent<HTMLDivElement>) {
|
||||||
|
if (event.ctrlKey && event.code === 'KeyS') {
|
||||||
|
if (isModified) {
|
||||||
|
handleSubmit();
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div tabIndex={0} onKeyDown={handleInput}>
|
||||||
<div className='relative flex items-start justify-center w-full'>
|
<div className='relative flex items-start justify-center w-full'>
|
||||||
<div className='absolute flex mt-1'>
|
<div className='absolute flex mt-1'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
|
|
|
@ -66,12 +66,14 @@ function EditorPassword() {
|
||||||
<TextInput id='old_password'
|
<TextInput id='old_password'
|
||||||
type='password'
|
type='password'
|
||||||
label='Старый пароль'
|
label='Старый пароль'
|
||||||
|
allowEnter
|
||||||
value={oldPassword}
|
value={oldPassword}
|
||||||
onChange={event => setOldPassword(event.target.value)}
|
onChange={event => setOldPassword(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<TextInput id='new_password' type='password'
|
<TextInput id='new_password' type='password'
|
||||||
colors={passwordColor}
|
colors={passwordColor}
|
||||||
label='Новый пароль'
|
label='Новый пароль'
|
||||||
|
allowEnter
|
||||||
value={newPassword}
|
value={newPassword}
|
||||||
onChange={event => {
|
onChange={event => {
|
||||||
setNewPassword(event.target.value);
|
setNewPassword(event.target.value);
|
||||||
|
@ -80,6 +82,7 @@ function EditorPassword() {
|
||||||
<TextInput id='new_password_repeat' type='password'
|
<TextInput id='new_password_repeat' type='password'
|
||||||
colors={passwordColor}
|
colors={passwordColor}
|
||||||
label='Повторите новый'
|
label='Повторите новый'
|
||||||
|
allowEnter
|
||||||
value={newPasswordRepeat}
|
value={newPasswordRepeat}
|
||||||
onChange={event => {
|
onChange={event => {
|
||||||
setNewPasswordRepeat(event.target.value);
|
setNewPasswordRepeat(event.target.value);
|
||||||
|
|
|
@ -55,17 +55,27 @@ function EditorProfile() {
|
||||||
<TextInput id='username'
|
<TextInput id='username'
|
||||||
label='Логин'
|
label='Логин'
|
||||||
tooltip='Логин изменить нельзя'
|
tooltip='Логин изменить нельзя'
|
||||||
disabled={true}
|
disabled
|
||||||
value={username}
|
value={username}
|
||||||
onChange={event => setUsername(event.target.value)}
|
|
||||||
/>
|
/>
|
||||||
<TextInput id='first_name'
|
<TextInput id='first_name'
|
||||||
label='Имя'
|
label='Имя'
|
||||||
value={first_name}
|
value={first_name}
|
||||||
|
allowEnter
|
||||||
onChange={event => setFirstName(event.target.value)}
|
onChange={event => setFirstName(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<TextInput id='last_name' label='Фамилия' value={last_name} onChange={event => setLastName(event.target.value)}/>
|
<TextInput id='last_name'
|
||||||
<TextInput id='email' label='Электронная почта' value={email} onChange={event => setEmail(event.target.value)}/>
|
label='Фамилия'
|
||||||
|
value={last_name}
|
||||||
|
allowEnter
|
||||||
|
onChange={event => setLastName(event.target.value)}
|
||||||
|
/>
|
||||||
|
<TextInput id='email'
|
||||||
|
label='Электронная почта'
|
||||||
|
allowEnter
|
||||||
|
value={email}
|
||||||
|
onChange={event => setEmail(event.target.value)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex justify-center w-full'>
|
<div className='flex justify-center w-full'>
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
|
|
|
@ -152,8 +152,8 @@ export function labelCstSource(mode: DependencyMode): string {
|
||||||
case DependencyMode.EXPRESSION: return 'выражение';
|
case DependencyMode.EXPRESSION: return 'выражение';
|
||||||
case DependencyMode.OUTPUTS: return 'потребители';
|
case DependencyMode.OUTPUTS: return 'потребители';
|
||||||
case DependencyMode.INPUTS: return 'поставщики';
|
case DependencyMode.INPUTS: return 'поставщики';
|
||||||
case DependencyMode.EXPAND_INPUTS: return 'влияющие';
|
|
||||||
case DependencyMode.EXPAND_OUTPUTS: return 'зависимые';
|
case DependencyMode.EXPAND_OUTPUTS: return 'зависимые';
|
||||||
|
case DependencyMode.EXPAND_INPUTS: return 'влияющие';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,10 +161,10 @@ export function describeCstSource(mode: DependencyMode): string {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case DependencyMode.ALL: return 'все конституенты';
|
case DependencyMode.ALL: return 'все конституенты';
|
||||||
case DependencyMode.EXPRESSION: return 'идентификаторы из выражения';
|
case DependencyMode.EXPRESSION: return 'идентификаторы из выражения';
|
||||||
case DependencyMode.OUTPUTS: return 'конституенты, ссылающиеся на данную';
|
case DependencyMode.OUTPUTS: return 'прямые ссылки на текущую';
|
||||||
case DependencyMode.INPUTS: return 'конституенты, на которые ссылается данная';
|
case DependencyMode.INPUTS: return 'пярмые ссылки из текущей';
|
||||||
case DependencyMode.EXPAND_INPUTS: return 'конституенты, зависящие по цепочке';
|
case DependencyMode.EXPAND_OUTPUTS: return 'опосредованные ссылки на текущую';
|
||||||
case DependencyMode.EXPAND_OUTPUTS: return 'конституенты, влияющие на данную по цепочке';
|
case DependencyMode.EXPAND_INPUTS: return 'опосредованные ссылки из текущей';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user