mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Update Constituenta editor UI
This commit is contained in:
parent
ae9964de87
commit
9cd682b19f
|
@ -7,18 +7,19 @@ extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'className' | 'title'>
|
||||||
label?: string
|
label?: string
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
dimensions?: string
|
dimensions?: string
|
||||||
|
dense?: boolean
|
||||||
colorClass?: string
|
colorClass?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function TextArea({
|
function TextArea({
|
||||||
id, label, required, tooltip,
|
id, label, required, tooltip, dense,
|
||||||
dimensions = 'w-full',
|
dimensions = 'w-full',
|
||||||
colorClass = 'clr-input',
|
colorClass = 'clr-input',
|
||||||
rows = 4,
|
rows = 4,
|
||||||
...props
|
...props
|
||||||
}: TextAreaProps) {
|
}: TextAreaProps) {
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col items-start gap-2'>
|
<div className={`flex ${dense ? 'items-center gap-4 ' + dimensions : 'flex-col items-start gap-2'}`}>
|
||||||
{label &&
|
{label &&
|
||||||
<Label
|
<Label
|
||||||
text={label}
|
text={label}
|
||||||
|
@ -26,7 +27,7 @@ function TextArea({
|
||||||
/>}
|
/>}
|
||||||
<textarea id={id}
|
<textarea id={id}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
className={`px-3 py-2 leading-tight border shadow clr-outline ${colorClass} ${dimensions}`}
|
className={`px-3 py-2 leading-tight border clr-outline ${colorClass} ${dense ? 'w-full' : dimensions}`}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
required={required}
|
required={required}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
@ -7,19 +7,19 @@ extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'className' | 'title'>
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
dimensions?: string
|
dimensions?: string
|
||||||
colorClass?: string
|
colorClass?: string
|
||||||
singleRow?: boolean
|
dense?: boolean
|
||||||
noBorder?: boolean
|
noBorder?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
function TextInput({
|
function TextInput({
|
||||||
id, required, label, singleRow, tooltip, noBorder,
|
id, required, label, dense, tooltip, noBorder,
|
||||||
dimensions = 'w-full',
|
dimensions = 'w-full',
|
||||||
colorClass = 'clr-input',
|
colorClass = 'clr-input',
|
||||||
...props
|
...props
|
||||||
}: TextInputProps) {
|
}: TextInputProps) {
|
||||||
const borderClass = noBorder ? '': 'border shadow';
|
const borderClass = noBorder ? '': 'border';
|
||||||
return (
|
return (
|
||||||
<div className={`flex ${singleRow ? 'items-center gap-4 ' + dimensions : 'flex-col items-start gap-2'}`}>
|
<div className={`flex ${dense ? 'items-center gap-4 ' + dimensions : 'flex-col items-start gap-2'}`}>
|
||||||
{label &&
|
{label &&
|
||||||
<Label
|
<Label
|
||||||
text={label}
|
text={label}
|
||||||
|
@ -27,7 +27,7 @@ function TextInput({
|
||||||
/>}
|
/>}
|
||||||
<input id={id}
|
<input id={id}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
className={`px-3 py-2 leading-tight ${borderClass} truncate hover:text-clip clr-outline ${colorClass} ${singleRow ? 'w-full' : dimensions}`}
|
className={`px-3 py-2 leading-tight ${borderClass} truncate hover:text-clip clr-outline ${colorClass} ${dense ? 'w-full' : dimensions}`}
|
||||||
required={required}
|
required={required}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { EducationIcon, EyeIcon, GroupIcon } from '../Icons';
|
import { EducationIcon, GroupIcon,SubscribedIcon } from '../Icons';
|
||||||
|
|
||||||
function HelpLibrary() {
|
function HelpLibrary() {
|
||||||
return (
|
return (
|
||||||
|
@ -9,7 +9,7 @@ function HelpLibrary() {
|
||||||
<p>На текущем этапе происходит наполнение Библиотеки концептуальными схемами.</p>
|
<p>На текущем этапе происходит наполнение Библиотеки концептуальными схемами.</p>
|
||||||
<p>Поиск осуществлеяется с помощью инструментов в верхней части страницы.</p>
|
<p>Поиск осуществлеяется с помощью инструментов в верхней части страницы.</p>
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
<EyeIcon size={4}/>
|
<SubscribedIcon size={4}/>
|
||||||
<p>Аттрибут <b>отслеживаемая</b> обозначает отслеживание схемы.</p>
|
<p>Аттрибут <b>отслеживаемая</b> обозначает отслеживание схемы.</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
|
|
|
@ -47,26 +47,49 @@ export function BellIcon(props: IconProps) {
|
||||||
|
|
||||||
export function EyeIcon(props: IconProps) {
|
export function EyeIcon(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<IconSVG viewbox='0 0 1024 1024' {...props}>
|
<IconSVG viewbox='0 0 24 24' {...props}>
|
||||||
<path d='M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z' />
|
<path d='M14 12c-1.095 0-2-.905-2-2 0-.354.103-.683.268-.973C12.178 9.02 12.092 9 12 9a3.02 3.02 0 00-3 3c0 1.642 1.358 3 3 3 1.641 0 3-1.358 3-3 0-.092-.02-.178-.027-.268-.29.165-.619.268-.973.268z' />
|
||||||
|
<path d='M12 5c-7.633 0-9.927 6.617-9.948 6.684L1.946 12l.105.316C2.073 12.383 4.367 19 12 19s9.927-6.617 9.948-6.684l.106-.316-.105-.316C21.927 11.617 19.633 5 12 5zm0 12c-5.351 0-7.424-3.846-7.926-5C4.578 10.842 6.652 7 12 7c5.351 0 7.424 3.846 7.926 5-.504 1.158-2.578 5-7.926 5z' />
|
||||||
</IconSVG>
|
</IconSVG>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EyeOffIcon(props: IconProps) {
|
export function EyeOffIcon(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<IconSVG viewbox='0 0 1024 1024' {...props}>
|
<IconSVG viewbox='0 0 24 24' {...props}>
|
||||||
<path d='M942.2 486.2Q889.47 375.11 816.7 305l-50.88 50.88C807.31 395.53 843.45 447.4 874.7 512 791.5 684.2 673.4 766 512 766q-72.67 0-133.87-22.38L323 798.75Q408 838 512 838q288.3 0 430.2-300.3a60.29 60.29 0 000-51.5zm-63.57-320.64L836 122.88a8 8 0 00-11.32 0L715.31 232.2Q624.86 186 512 186q-288.3 0-430.2 300.3a60.3 60.3 0 000 51.5q56.69 119.4 136.5 191.41L112.48 835a8 8 0 000 11.31L155.17 889a8 8 0 0011.31 0l712.15-712.12a8 8 0 000-11.32zM149.3 512C232.6 339.8 350.7 258 512 258c54.54 0 104.13 9.36 149.12 28.39l-70.3 70.3a176 176 0 00-238.13 238.13l-83.42 83.42C223.1 637.49 183.3 582.28 149.3 512zm246.7 0a112.11 112.11 0 01146.2-106.69L401.31 546.2A112 112 0 01396 512z'/>
|
<path d='M12 19c.946 0 1.81-.103 2.598-.281l-1.757-1.757c-.273.021-.55.038-.841.038-5.351 0-7.424-3.846-7.926-5a8.642 8.642 0 011.508-2.297L4.184 8.305c-1.538 1.667-2.121 3.346-2.132 3.379a.994.994 0 000 .633C2.073 12.383 4.367 19 12 19zm0-14c-1.837 0-3.346.396-4.604.981L3.707 2.293 2.293 3.707l18 18 1.414-1.414-3.319-3.319c2.614-1.951 3.547-4.615 3.561-4.657a.994.994 0 000-.633C21.927 11.617 19.633 5 12 5zm4.972 10.558l-2.28-2.28c.19-.39.308-.819.308-1.278 0-1.641-1.359-3-3-3-.459 0-.888.118-1.277.309L8.915 7.501A9.26 9.26 0 0112 7c5.351 0 7.424 3.846 7.926 5-.302.692-1.166 2.342-2.954 3.558z'/>
|
||||||
<path d='M508 624c-3.46 0-6.87-.16-10.25-.47l-52.82 52.82a176.09 176.09 0 00227.42-227.42l-52.82 52.82c.31 3.38.47 6.79.47 10.25a111.94 111.94 0 01-112 112z' />
|
|
||||||
</IconSVG>
|
</IconSVG>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PenIcon(props: IconProps) {
|
export function SubscribedIcon(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<IconSVG viewbox='-3 -3 21 21' {...props}>
|
<IconSVG viewbox='0 0 24 24' {...props}>
|
||||||
<path d='M15.502 1.94a.5.5 0 010 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 01.707 0l1.293 1.293zm-1.75 2.456l-2-2L4.939 9.21a.5.5 0 00-.121.196l-.805 2.414a.25.25 0 00.316.316l2.414-.805a.5.5 0 00.196-.12l6.813-6.814z' />
|
<path d='M19 13.586V10c0-3.217-2.185-5.927-5.145-6.742C13.562 2.52 12.846 2 12 2s-1.562.52-1.855 1.258C7.185 4.074 5 6.783 5 10v3.586l-1.707 1.707A.996.996 0 003 16v2a1 1 0 001 1h16a1 1 0 001-1v-2a.996.996 0 00-.293-.707L19 13.586zM19 17H5v-.586l1.707-1.707A.996.996 0 007 14v-4c0-2.757 2.243-5 5-5s5 2.243 5 5v4c0 .266.105.52.293.707L19 16.414V17zm-7 5a2.98 2.98 0 002.818-2H9.182A2.98 2.98 0 0012 22z' />
|
||||||
<path d='M1 13.5A1.5 1.5 0 002.5 15h11a1.5 1.5 0 001.5-1.5v-6a.5.5 0 00-1 0v6a.5.5 0 01-.5.5h-11a.5.5 0 01-.5-.5v-11a.5.5 0 01.5-.5H9a.5.5 0 000-1H2.5A1.5 1.5 0 001 2.5v11z' />
|
</IconSVG>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NotSubscribedIcon(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconSVG viewbox='0 0 24 24' {...props}>
|
||||||
|
<path d='M12 22a2.98 2.98 0 002.818-2H9.182A2.98 2.98 0 0012 22zm9-4v-2a.996.996 0 00-.293-.707L19 13.586V10c0-3.217-2.185-5.927-5.145-6.742C13.562 2.52 12.846 2 12 2s-1.562.52-1.855 1.258c-1.323.364-2.463 1.128-3.346 2.127L3.707 2.293 2.293 3.707l18 18 1.414-1.414-1.362-1.362A.993.993 0 0021 18zM12 5c2.757 0 5 2.243 5 5v4c0 .266.105.52.293.707L19 16.414V17h-.586L8.207 6.793C9.12 5.705 10.471 5 12 5zm-5.293 9.707A.996.996 0 007 14v-2.879L5.068 9.189C5.037 9.457 5 9.724 5 10v3.586l-1.707 1.707A.996.996 0 003 16v2a1 1 0 001 1h10.879l-2-2H5v-.586l1.707-1.707z'/>
|
||||||
|
</IconSVG>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ASTNetworkIcon(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconSVG viewbox='0 0 24 24' {...props}>
|
||||||
|
<path d='M21 6c0-1.654-1.346-3-3-3a2.993 2.993 0 00-2.815 2h-6.37A2.993 2.993 0 006 3C4.346 3 3 4.346 3 6c0 1.302.839 2.401 2 2.815v6.369A2.997 2.997 0 003 18c0 1.654 1.346 3 3 3a2.993 2.993 0 002.815-2h6.369a2.994 2.994 0 002.815 2c1.654 0 3-1.346 3-3a2.997 2.997 0 00-2-2.816V8.816A2.996 2.996 0 0021 6zm-3-1a1.001 1.001 0 11-1 1c0-.551.448-1 1-1zm-2.815 12h-6.37A2.99 2.99 0 007 15.184V8.816A2.99 2.99 0 008.815 7h6.369A2.99 2.99 0 0017 8.815v6.369A2.99 2.99 0 0015.185 17zM6 5a1.001 1.001 0 11-1 1c0-.551.448-1 1-1zm0 14a1.001 1.001 0 010-2 1.001 1.001 0 010 2zm12 0a1.001 1.001 0 010-2 1.001 1.001 0 010 2z'/>
|
||||||
|
</IconSVG>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function EditIcon(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconSVG viewbox='0 0 24 24' {...props}>
|
||||||
|
<path d='M6.3 12.3l10-10a1 1 0 011.4 0l4 4a1 1 0 010 1.4l-10 10a1 1 0 01-.7.3H7a1 1 0 01-1-1v-4a1 1 0 01.3-.7zM8 16h2.59l9-9L17 4.41l-9 9V16zm10-2a1 1 0 012 0v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6c0-1.1.9-2 2-2h6a1 1 0 010 2H4v14h14v-6z' />
|
||||||
</IconSVG>
|
</IconSVG>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,7 +258,7 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
||||||
<TextInput id='offset' type='number'
|
<TextInput id='offset' type='number'
|
||||||
label='Смещение'
|
label='Смещение'
|
||||||
dimensions='max-w-[10rem]'
|
dimensions='max-w-[10rem]'
|
||||||
singleRow
|
dense
|
||||||
value={offset}
|
value={offset}
|
||||||
onChange={event => setOffset(event.target.valueAsNumber)}
|
onChange={event => setOffset(event.target.valueAsNumber)}
|
||||||
/>
|
/>
|
||||||
|
@ -266,7 +266,7 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
||||||
Основная ссылка:
|
Основная ссылка:
|
||||||
</div>
|
</div>
|
||||||
<TextInput
|
<TextInput
|
||||||
singleRow
|
dense
|
||||||
disabled
|
disabled
|
||||||
noBorder
|
noBorder
|
||||||
value={mainLink}
|
value={mainLink}
|
||||||
|
@ -319,7 +319,7 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
||||||
label='Отсылаемая конституента'
|
label='Отсылаемая конституента'
|
||||||
dimensions='max-w-[16rem] min-w-[16rem] whitespace-nowrap'
|
dimensions='max-w-[16rem] min-w-[16rem] whitespace-nowrap'
|
||||||
placeholder='Имя'
|
placeholder='Имя'
|
||||||
singleRow
|
dense
|
||||||
value={alias}
|
value={alias}
|
||||||
onChange={event => setAlias(event.target.value)}
|
onChange={event => setAlias(event.target.value)}
|
||||||
/>
|
/>
|
||||||
|
@ -328,7 +328,7 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
||||||
Термин:
|
Термин:
|
||||||
</div>
|
</div>
|
||||||
<TextInput
|
<TextInput
|
||||||
singleRow
|
dense
|
||||||
disabled
|
disabled
|
||||||
noBorder
|
noBorder
|
||||||
value={term}
|
value={term}
|
||||||
|
|
|
@ -30,7 +30,7 @@ function checkTypeConsistency(type: CstType, typification: string, args: IFuncti
|
||||||
}
|
}
|
||||||
|
|
||||||
function adjustResults(parse: IExpressionParse, emptyExpression: boolean, cstType: CstType) {
|
function adjustResults(parse: IExpressionParse, emptyExpression: boolean, cstType: CstType) {
|
||||||
if (!parse.parseResult && parse.errors.length > 0 && parse.errors[0].errorType !== RSErrorType.syntax) {
|
if (!parse.parseResult && parse.errors.length > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cstType === CstType.BASE || cstType === CstType.CONSTANT) {
|
if (cstType === CstType.BASE || cstType === CstType.CONSTANT) {
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
function getStorageValue<ValueType>(key: string, defaultValue: ValueType) {
|
function useLocalStorage<ValueType>(
|
||||||
const saved = localStorage.getItem(key);
|
key: string,
|
||||||
const initial = saved ? JSON.parse(saved) as ValueType : undefined;
|
defaultValue: ValueType | (() => ValueType)
|
||||||
return initial || defaultValue;
|
) {
|
||||||
}
|
const [value, setValue] = useState<ValueType>(
|
||||||
|
() => {
|
||||||
const useLocalStorage =
|
const loadedJson = localStorage.getItem(key);
|
||||||
<ValueType>(key: string, defaultValue: ValueType):
|
if (loadedJson != null) {
|
||||||
[ValueType, React.Dispatch<React.SetStateAction<ValueType>>] => {
|
return JSON.parse(loadedJson) as ValueType;
|
||||||
const [value, setValue] = useState<ValueType>(() => {
|
} else if (typeof defaultValue === 'function') {
|
||||||
return getStorageValue(key, defaultValue);
|
return (defaultValue as () => ValueType)();
|
||||||
|
} else {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -21,7 +24,7 @@ const useLocalStorage =
|
||||||
}
|
}
|
||||||
}, [key, value]);
|
}, [key, value]);
|
||||||
|
|
||||||
return [value, setValue];
|
return [value, setValue] as [ValueType, typeof setValue];
|
||||||
};
|
}
|
||||||
|
|
||||||
export default useLocalStorage;
|
export default useLocalStorage;
|
||||||
|
|
|
@ -315,7 +315,7 @@
|
||||||
.dark & {
|
.dark & {
|
||||||
border-color: var(--cd-bg-40);
|
border-color: var(--cd-bg-40);
|
||||||
}
|
}
|
||||||
@apply border shadow rounded px-1
|
@apply border rounded px-1
|
||||||
}
|
}
|
||||||
.cm-editor.cm-focused {
|
.cm-editor.cm-focused {
|
||||||
border-color: var(--cl-bg-40);
|
border-color: var(--cl-bg-40);
|
||||||
|
@ -324,7 +324,7 @@
|
||||||
border-color: var(--cd-bg-40);
|
border-color: var(--cd-bg-40);
|
||||||
outline-color: var(--cd-prim-bg-100);
|
outline-color: var(--cd-prim-bg-100);
|
||||||
}
|
}
|
||||||
@apply border shadow rounded outline-2 outline
|
@apply border rounded outline-2 outline
|
||||||
}
|
}
|
||||||
|
|
||||||
.rdt_TableCell{
|
.rdt_TableCell{
|
||||||
|
|
|
@ -2,12 +2,6 @@
|
||||||
|
|
||||||
import { IConstituenta, IRSForm } from './rsform'
|
import { IConstituenta, IRSForm } from './rsform'
|
||||||
|
|
||||||
// Constituenta edit mode
|
|
||||||
export enum EditMode {
|
|
||||||
TEXT = 'text',
|
|
||||||
RSLANG = 'rslang'
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dependency mode for schema analysis
|
// Dependency mode for schema analysis
|
||||||
export enum DependencyMode {
|
export enum DependencyMode {
|
||||||
ALL = 0,
|
ALL = 0,
|
||||||
|
|
|
@ -108,7 +108,7 @@ function CreateRSFormPage() {
|
||||||
onChange={event => setTitle(event.target.value)}
|
onChange={event => setTitle(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<TextInput id='alias' label='Сокращение' type='text'
|
<TextInput id='alias' label='Сокращение' type='text'
|
||||||
singleRow
|
dense
|
||||||
required={!file}
|
required={!file}
|
||||||
value={alias}
|
value={alias}
|
||||||
placeholder={file && 'Загрузить из файла'}
|
placeholder={file && 'Загрузить из файла'}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
||||||
import TextURL from '../../components/Common/TextURL';
|
import TextURL from '../../components/Common/TextURL';
|
||||||
import DataTable, { createColumnHelper } from '../../components/DataTable';
|
import DataTable, { createColumnHelper } from '../../components/DataTable';
|
||||||
import HelpLibrary from '../../components/Help/HelpLibrary';
|
import HelpLibrary from '../../components/Help/HelpLibrary';
|
||||||
import { EducationIcon, EyeIcon, GroupIcon, HelpIcon } from '../../components/Icons';
|
import { EducationIcon, GroupIcon, HelpIcon,SubscribedIcon } from '../../components/Icons';
|
||||||
import { useAuth } from '../../context/AuthContext';
|
import { useAuth } from '../../context/AuthContext';
|
||||||
import { useConceptNavigation } from '../../context/NagivationContext';
|
import { useConceptNavigation } from '../../context/NagivationContext';
|
||||||
import { useUsers } from '../../context/UsersContext';
|
import { useUsers } from '../../context/UsersContext';
|
||||||
|
@ -45,7 +45,7 @@ function ViewLibrary({ items, resetQuery: cleanQuery }: ViewLibraryProps) {
|
||||||
className='flex items-center justify-start gap-1 min-w-[2.75rem]'
|
className='flex items-center justify-start gap-1 min-w-[2.75rem]'
|
||||||
id={`${prefixes.library_list}${item.id}`}
|
id={`${prefixes.library_list}${item.id}`}
|
||||||
>
|
>
|
||||||
{user && user.subscriptions.includes(item.id) && <p title='Отслеживаемая'><EyeIcon size={3}/></p>}
|
{user && user.subscriptions.includes(item.id) && <p title='Отслеживаемая'><SubscribedIcon size={3}/></p>}
|
||||||
{item.is_common && <p title='Общедоступная'><GroupIcon size={3}/></p>}
|
{item.is_common && <p title='Общедоступная'><GroupIcon size={3}/></p>}
|
||||||
{item.is_canonical && <p title='Неизменная'><EducationIcon size={3}/></p>}
|
{item.is_canonical && <p title='Неизменная'><EducationIcon size={3}/></p>}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -72,6 +72,7 @@ function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstPro
|
||||||
hideWindow={hideWindow}
|
hideWindow={hideWindow}
|
||||||
canSubmit={validated}
|
canSubmit={validated}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
submitText='Создать'
|
||||||
>
|
>
|
||||||
<div className='h-fit w-[35rem] px-2 mb-2 flex flex-col justify-stretch gap-3'>
|
<div className='h-fit w-[35rem] px-2 mb-2 flex flex-col justify-stretch gap-3'>
|
||||||
<div className='flex justify-center w-full gap-6'>
|
<div className='flex justify-center w-full gap-6'>
|
||||||
|
@ -83,7 +84,7 @@ function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstPro
|
||||||
onChange={data => setSelectedType(data?.value ?? CstType.BASE)}
|
onChange={data => setSelectedType(data?.value ?? CstType.BASE)}
|
||||||
/>
|
/>
|
||||||
<TextInput id='alias' label='Имя'
|
<TextInput id='alias' label='Имя'
|
||||||
singleRow
|
dense
|
||||||
dimensions='w-[7rem]'
|
dimensions='w-[7rem]'
|
||||||
value={alias}
|
value={alias}
|
||||||
onChange={event => setAlias(event.target.value)}
|
onChange={event => setAlias(event.target.value)}
|
||||||
|
|
|
@ -78,7 +78,7 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<TextInput id='alias' label='Имя'
|
<TextInput id='alias' label='Имя'
|
||||||
singleRow
|
dense
|
||||||
dimensions='w-[7rem]'
|
dimensions='w-[7rem]'
|
||||||
value={alias}
|
value={alias}
|
||||||
onChange={event => setAlias(event.target.value)}
|
onChange={event => setAlias(event.target.value)}
|
||||||
|
|
|
@ -6,11 +6,10 @@ 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, HelpIcon, PenIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons';
|
import { 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';
|
||||||
import { EditMode } from '../../models/miscelanious';
|
|
||||||
import { CstType, IConstituenta, ICstCreateData, ICstRenameData, ICstUpdateData } from '../../models/rsform';
|
import { CstType, IConstituenta, ICstCreateData, ICstRenameData, ICstUpdateData } from '../../models/rsform';
|
||||||
import { SyntaxTree } from '../../models/rslang';
|
import { SyntaxTree } from '../../models/rslang';
|
||||||
import { labelCstTypification } from '../../utils/labels';
|
import { labelCstTypification } from '../../utils/labels';
|
||||||
|
@ -20,7 +19,7 @@ import ViewSideConstituents from './elements/ViewSideConstituents';
|
||||||
// Max height of content for left enditor pane
|
// Max height of content for left enditor pane
|
||||||
const UNFOLDED_HEIGHT = '59.1rem';
|
const UNFOLDED_HEIGHT = '59.1rem';
|
||||||
|
|
||||||
const SIDELIST_HIDE_THRESHOLD = 1000;
|
const SIDELIST_HIDE_THRESHOLD = 1100;
|
||||||
|
|
||||||
interface EditorConstituentaProps {
|
interface EditorConstituentaProps {
|
||||||
activeID?: number
|
activeID?: number
|
||||||
|
@ -42,8 +41,6 @@ function EditorConstituenta({
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
const { schema, processing, isEditable, cstUpdate } = useRSForm();
|
const { schema, processing, isEditable, cstUpdate } = useRSForm();
|
||||||
|
|
||||||
const [editMode, setEditMode] = useState(EditMode.TEXT);
|
|
||||||
|
|
||||||
const [alias, setAlias] = useState('');
|
const [alias, setAlias] = useState('');
|
||||||
const [term, setTerm] = useState('');
|
const [term, setTerm] = useState('');
|
||||||
const [textDefinition, setTextDefinition] = useState('');
|
const [textDefinition, setTextDefinition] = useState('');
|
||||||
|
@ -153,7 +150,7 @@ function EditorConstituenta({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex max-w-[1500px] gap-2'>
|
<div className='flex max-w-[1500px] gap-2'>
|
||||||
<form onSubmit={handleSubmit} className='min-w-[50rem] max-w-[50rem] px-4 py-2'>
|
<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'>
|
||||||
{activeCst &&
|
{activeCst &&
|
||||||
|
@ -163,7 +160,7 @@ function EditorConstituenta({
|
||||||
dimensions='w-fit ml-[3.2rem] pt-[0.3rem]'
|
dimensions='w-fit ml-[3.2rem] pt-[0.3rem]'
|
||||||
noHover
|
noHover
|
||||||
onClick={onEditTerm}
|
onClick={onEditTerm}
|
||||||
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
icon={<EditIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
||||||
/>}
|
/>}
|
||||||
<div className='flex items-center justify-center w-full pl-[4rem]'>
|
<div className='flex items-center justify-center w-full pl-[4rem]'>
|
||||||
<div className='font-semibold pointer-events-none w-fit'>
|
<div className='font-semibold pointer-events-none w-fit'>
|
||||||
|
@ -175,7 +172,7 @@ function EditorConstituenta({
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
noHover
|
noHover
|
||||||
onClick={handleRename}
|
onClick={handleRename}
|
||||||
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
icon={<EditIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center justify-end'>
|
<div className='flex items-center justify-end'>
|
||||||
|
@ -215,16 +212,16 @@ function EditorConstituenta({
|
||||||
<div className='flex flex-col gap-2 mt-1'>
|
<div className='flex flex-col gap-2 mt-1'>
|
||||||
<RefsInput id='term' label='Термин'
|
<RefsInput id='term' label='Термин'
|
||||||
placeholder='Обозначение, используемое в текстовых определениях данной схемы'
|
placeholder='Обозначение, используемое в текстовых определениях данной схемы'
|
||||||
height='3.5rem'
|
height='2.1rem'
|
||||||
items={schema?.items}
|
items={schema?.items}
|
||||||
value={term}
|
value={term}
|
||||||
initialValue={activeCst?.term_raw ?? ''}
|
initialValue={activeCst?.term_raw ?? ''}
|
||||||
resolved={activeCst?.term_resolved ?? ''}
|
resolved={activeCst?.term_resolved ?? ''}
|
||||||
editable={isEnabled}
|
editable={isEnabled}
|
||||||
onChange={newValue => setTerm(newValue)}
|
onChange={newValue => setTerm(newValue)}
|
||||||
onFocus={() => setEditMode(EditMode.TEXT)}
|
|
||||||
/>
|
/>
|
||||||
<TextArea id='typification' label='Типизация'
|
<TextArea id='typification' label='Типизация'
|
||||||
|
dense
|
||||||
rows={1}
|
rows={1}
|
||||||
value={typification}
|
value={typification}
|
||||||
colorClass='clr-app'
|
colorClass='clr-app'
|
||||||
|
@ -235,31 +232,27 @@ function EditorConstituenta({
|
||||||
placeholder='Родоструктурное выражение, задающее формальное определение'
|
placeholder='Родоструктурное выражение, задающее формальное определение'
|
||||||
value={expression}
|
value={expression}
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
isActive={editMode === EditMode.RSLANG}
|
|
||||||
toggleEditMode={() => setEditMode(EditMode.RSLANG)}
|
|
||||||
onShowAST={onShowAST}
|
onShowAST={onShowAST}
|
||||||
onChange={newValue => setExpression(newValue)}
|
onChange={newValue => setExpression(newValue)}
|
||||||
setTypification={setTypification}
|
setTypification={setTypification}
|
||||||
/>
|
/>
|
||||||
<RefsInput id='definition' label='Текстовое определение'
|
<RefsInput id='definition' label='Текстовое определение'
|
||||||
placeholder='Лингвистическая интерпретация формального выражения'
|
placeholder='Лингвистическая интерпретация формального выражения'
|
||||||
height='6.3rem'
|
height='4.8rem'
|
||||||
items={schema?.items}
|
items={schema?.items}
|
||||||
value={textDefinition}
|
value={textDefinition}
|
||||||
initialValue={activeCst?.definition_raw ?? ''}
|
initialValue={activeCst?.definition_raw ?? ''}
|
||||||
resolved={activeCst?.definition_resolved ?? ''}
|
resolved={activeCst?.definition_resolved ?? ''}
|
||||||
editable={isEnabled}
|
editable={isEnabled}
|
||||||
onChange={newValue => setTextDefinition(newValue)}
|
onChange={newValue => setTextDefinition(newValue)}
|
||||||
onFocus={() => setEditMode(EditMode.TEXT)}
|
|
||||||
/>
|
/>
|
||||||
<TextArea id='convention' label='Конвенция / Комментарий'
|
<TextArea id='convention' label='Конвенция / Комментарий'
|
||||||
placeholder='Договоренность об интерпретации неопределяемого понятия
Комментарий к производному понятию'
|
placeholder='Договоренность об интерпретации неопределяемого понятия
Комментарий к производному понятию'
|
||||||
rows={4}
|
rows={2}
|
||||||
value={convention}
|
value={convention}
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
spellCheck
|
spellCheck
|
||||||
onChange={event => setConvention(event.target.value)}
|
onChange={event => setConvention(event.target.value)}
|
||||||
onFocus={() => setEditMode(EditMode.TEXT)}
|
|
||||||
/>
|
/>
|
||||||
<div className='flex justify-center w-full mt-2'>
|
<div className='flex justify-center w-full mt-2'>
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
|
@ -271,7 +264,7 @@ function EditorConstituenta({
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{(windowSize.width ?? 0) >= SIDELIST_HIDE_THRESHOLD &&
|
{(windowSize.width ?? 0) >= SIDELIST_HIDE_THRESHOLD &&
|
||||||
<div className='w-full mt-10 border h-fit'>
|
<div className='w-full mt-[2.25rem] border h-fit'>
|
||||||
<ViewSideConstituents
|
<ViewSideConstituents
|
||||||
expression={expression}
|
expression={expression}
|
||||||
baseHeight={UNFOLDED_HEIGHT}
|
baseHeight={UNFOLDED_HEIGHT}
|
||||||
|
|
|
@ -1,39 +1,39 @@
|
||||||
import { ReactCodeMirrorRef } from '@uiw/react-codemirror';
|
import { ReactCodeMirrorRef } from '@uiw/react-codemirror';
|
||||||
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import Button from '../../components/Common/Button';
|
import Button from '../../components/Common/Button';
|
||||||
import { ConceptLoader } from '../../components/Common/ConceptLoader';
|
import { ConceptLoader } from '../../components/Common/ConceptLoader';
|
||||||
|
import MiniButton from '../../components/Common/MiniButton';
|
||||||
|
import { ASTNetworkIcon } from '../../components/Icons';
|
||||||
import RSInput from '../../components/RSInput';
|
import RSInput from '../../components/RSInput';
|
||||||
import { RSTextWrapper } from '../../components/RSInput/textEditing';
|
import { RSTextWrapper } from '../../components/RSInput/textEditing';
|
||||||
import { useRSForm } from '../../context/RSFormContext';
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
import useCheckExpression from '../../hooks/useCheckExpression';
|
import useCheckExpression from '../../hooks/useCheckExpression';
|
||||||
import { IConstituenta } from '../../models/rsform';
|
import { IConstituenta } from '../../models/rsform';
|
||||||
import { IRSErrorDescription, SyntaxTree } from '../../models/rslang';
|
import { IExpressionParse, IRSErrorDescription, SyntaxTree } from '../../models/rslang';
|
||||||
import { TokenID } from '../../models/rslang';
|
import { TokenID } from '../../models/rslang';
|
||||||
import { labelTypification } from '../../utils/labels';
|
import { labelTypification } from '../../utils/labels';
|
||||||
import { getCstExpressionPrefix } from '../../utils/misc';
|
import { getCstExpressionPrefix } from '../../utils/misc';
|
||||||
import ParsingResult from './elements/ParsingResult';
|
import ParsingResult from './elements/ParsingResult';
|
||||||
import RSLocalButton from './elements/RSLocalButton';
|
import RSEditorControls from './elements/RSEditorControls';
|
||||||
import RSTokenButton from './elements/RSTokenButton';
|
|
||||||
import StatusBar from './elements/StatusBar';
|
import StatusBar from './elements/StatusBar';
|
||||||
|
|
||||||
interface EditorRSExpressionProps {
|
interface EditorRSExpressionProps {
|
||||||
id: string
|
id: string
|
||||||
activeCst?: IConstituenta
|
activeCst?: IConstituenta
|
||||||
label: string
|
label: string
|
||||||
isActive: boolean
|
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
onShowAST: (expression: string, ast: SyntaxTree) => void
|
onShowAST: (expression: string, ast: SyntaxTree) => void
|
||||||
toggleEditMode: () => void
|
|
||||||
setTypification: (typificaiton: string) => void
|
setTypification: (typificaiton: string) => void
|
||||||
value: string
|
value: string
|
||||||
onChange: (newValue: string) => void
|
onChange: (newValue: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function EditorRSExpression({
|
function EditorRSExpression({
|
||||||
activeCst, disabled, isActive, value, onShowAST,
|
activeCst, disabled, value, onShowAST,
|
||||||
toggleEditMode, setTypification, onChange, ...props
|
setTypification, onChange, ...props
|
||||||
}: EditorRSExpressionProps) {
|
}: EditorRSExpressionProps) {
|
||||||
const { schema } = useRSForm();
|
const { schema } = useRSForm();
|
||||||
|
|
||||||
|
@ -46,16 +46,12 @@ function EditorRSExpression({
|
||||||
resetParse();
|
resetParse();
|
||||||
}, [activeCst, resetParse]);
|
}, [activeCst, resetParse]);
|
||||||
|
|
||||||
function handleFocusIn() {
|
|
||||||
toggleEditMode()
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleChange(newvalue: string) {
|
function handleChange(newvalue: string) {
|
||||||
onChange(newvalue);
|
onChange(newvalue);
|
||||||
setIsModified(newvalue !== activeCst?.definition_formal);
|
setIsModified(newvalue !== activeCst?.definition_formal);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCheckExpression() {
|
function handleCheckExpression(callback?: (parse: IExpressionParse) => void) {
|
||||||
if (!activeCst) {
|
if (!activeCst) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -73,6 +69,7 @@ function EditorRSExpression({
|
||||||
resultType: parse.typification,
|
resultType: parse.typification,
|
||||||
args: parse.args
|
args: parse.args
|
||||||
}));
|
}));
|
||||||
|
if (callback) callback(parse);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,132 +104,70 @@ function EditorRSExpression({
|
||||||
setIsModified(true);
|
setIsModified(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const EditButtons = useMemo(() => {
|
function handleShowAST() {
|
||||||
return (
|
handleCheckExpression(
|
||||||
<div className='flex items-center justify-between w-full'>
|
(parse) => {
|
||||||
<div className='text-sm w-fit'>
|
if (!parse.astText) {
|
||||||
<div className='flex justify-start'>
|
toast.error('Невозможно построить дерево разбора');
|
||||||
<RSTokenButton token={TokenID.NT_DECLARATIVE_EXPR} onInsert={handleEdit}/>
|
} else {
|
||||||
<RSTokenButton token={TokenID.NT_IMPERATIVE_EXPR} onInsert={handleEdit}/>
|
onShowAST(getCstExpressionPrefix(activeCst!) + value, parse.ast);
|
||||||
<RSTokenButton token={TokenID.NT_RECURSIVE_FULL} onInsert={handleEdit}/>
|
}
|
||||||
<RSTokenButton token={TokenID.BIGPR} onInsert={handleEdit}/>
|
});
|
||||||
<RSTokenButton token={TokenID.SMALLPR} onInsert={handleEdit}/>
|
}
|
||||||
<RSTokenButton token={TokenID.FILTER} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.REDUCE} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.CARD} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.BOOL} onInsert={handleEdit}/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div className='flex justify-start'>
|
|
||||||
<RSTokenButton token={TokenID.BOOLEAN} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.PUNC_PL} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.INTERSECTION} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.LIT_EMPTYSET} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.FORALL} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.NOT} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.IN} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.SUBSET_OR_EQ} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.AND} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.IMPLICATION} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.SET_MINUS} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.PUNC_ITERATE} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.SUBSET} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.DEBOOL} onInsert={handleEdit}/>
|
|
||||||
</div>
|
|
||||||
<div className='flex justify-start'>
|
|
||||||
<RSTokenButton token={TokenID.DECART} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.PUNC_SL} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.UNION} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.LIT_INTSET} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.EXISTS} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.NOTEQUAL} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.NOTIN} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.NOTSUBSET} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.OR} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.EQUIVALENT} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.SYMMINUS} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.PUNC_ASSIGN} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.EQUAL} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.GREATER_OR_EQ} onInsert={handleEdit}/>
|
|
||||||
<RSTokenButton token={TokenID.LESSER_OR_EQ} onInsert={handleEdit}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='text-sm w-fit'>
|
|
||||||
<div className='flex justify-start'>
|
|
||||||
<RSLocalButton text='μ' tooltip='q' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='ω' tooltip='w' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='ε' tooltip='e' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='ρ' tooltip='r' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='τ' tooltip='t' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='π' tooltip='y' onInsert={handleEdit}/>
|
|
||||||
</div>
|
|
||||||
<div className='flex justify-start'>
|
|
||||||
<RSLocalButton text='α' tooltip='a' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='σ' tooltip='s' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='δ' tooltip='d' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='φ' tooltip='f' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='γ' tooltip='g' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='λ' tooltip='h' onInsert={handleEdit}/>
|
|
||||||
</div>
|
|
||||||
<div className='flex justify-start'>
|
|
||||||
<RSLocalButton text='ζ' tooltip='z' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='ξ' tooltip='x' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='ψ' tooltip='c' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='θ' tooltip='v' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='β' tooltip='b' onInsert={handleEdit}/>
|
|
||||||
<RSLocalButton text='η' tooltip='n' onInsert={handleEdit}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>);
|
|
||||||
}, [handleEdit]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col items-start w-full'>
|
<div className='flex flex-col items-start w-full'>
|
||||||
<div className='relative w-full'>
|
<div className='relative w-full'>
|
||||||
<div className='absolute top-[-0.3rem] right-0'>
|
<div className='absolute top-[-0.2rem] left-[10.3rem]'>
|
||||||
|
<MiniButton
|
||||||
|
tooltip='Дерево разбора выражения'
|
||||||
|
noHover
|
||||||
|
onClick={handleShowAST}
|
||||||
|
icon={<ASTNetworkIcon size={5} color='text-primary' />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<RSInput innerref={rsInput}
|
||||||
|
height='4.8rem'
|
||||||
|
value={value}
|
||||||
|
editable={!disabled}
|
||||||
|
onChange={handleChange}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
<RSEditorControls
|
||||||
|
disabled={disabled}
|
||||||
|
onEdit={handleEdit}
|
||||||
|
/>
|
||||||
|
<div className='w-full mt-1 max-h-[5rem] min-h-[5rem] flex gap-2'>
|
||||||
|
<div className='flex flex-col gap-1'>
|
||||||
|
<Button
|
||||||
|
tooltip='Проверить формальное выражение'
|
||||||
|
text='Проверить'
|
||||||
|
dimensions='w-fit h-[3rem]'
|
||||||
|
colorClass='clr-btn-default'
|
||||||
|
onClick={() => handleCheckExpression()}
|
||||||
|
/>
|
||||||
<StatusBar
|
<StatusBar
|
||||||
isModified={isModified}
|
isModified={isModified}
|
||||||
constituenta={activeCst}
|
constituenta={activeCst}
|
||||||
parseData={parseData}
|
parseData={parseData}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className='w-full overflow-y-auto text-sm border'>
|
||||||
<RSInput innerref={rsInput}
|
|
||||||
height='7.6rem'
|
|
||||||
value={value}
|
|
||||||
editable={!disabled}
|
|
||||||
onChange={handleChange}
|
|
||||||
onFocus={handleFocusIn}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
<div className='flex items-stretch w-full gap-4 py-1 mt-1 justify-stretch'>
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
tooltip='Проверить формальное выражение'
|
|
||||||
text='Проверить'
|
|
||||||
dimensions='h-full w-fit'
|
|
||||||
colorClass='clr-btn-default'
|
|
||||||
onClick={handleCheckExpression}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{isActive && !disabled && EditButtons}
|
|
||||||
</div>
|
|
||||||
{ (isActive || loading || parseData) &&
|
|
||||||
<div className='w-full overflow-y-auto border mt-1 max-h-[14rem] min-h-[4.2rem]'>
|
|
||||||
{ loading && <ConceptLoader size={6} />}
|
{ loading && <ConceptLoader size={6} />}
|
||||||
{ !loading && parseData &&
|
{ !loading && parseData &&
|
||||||
<ParsingResult
|
<ParsingResult
|
||||||
data={parseData}
|
data={parseData}
|
||||||
onShowAST={ast => onShowAST(getCstExpressionPrefix(activeCst!) + value, ast)}
|
|
||||||
onShowError={onShowError}
|
onShowError={onShowError}
|
||||||
/>}
|
/>}
|
||||||
{ !loading && !parseData &&
|
{ !loading && !parseData &&
|
||||||
<input
|
<input
|
||||||
disabled={true}
|
disabled={true}
|
||||||
className='w-full h-full px-2 align-middle select-none clr-app'
|
className='w-full px-2 py-1 text-base select-none h-fit clr-app'
|
||||||
placeholder='Результаты проверки выражения'
|
placeholder='Результаты проверки выражения'
|
||||||
/>}
|
/>}
|
||||||
</div>}
|
</div>
|
||||||
|
</div>
|
||||||
</div>);
|
</div>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -374,7 +374,7 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra
|
||||||
/>}
|
/>}
|
||||||
|
|
||||||
<div className='relative w-full z-pop'>
|
<div className='relative w-full z-pop'>
|
||||||
<div className='absolute top-0 right-0 flex items-start justify-center w-full'>
|
<div className='absolute right-0 flex items-start justify-center w-full top-1'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip='Новая конституента'
|
tooltip='Новая конституента'
|
||||||
icon={<SmallPlusIcon color={isEditable ? 'text-success': ''} size={5}/>}
|
icon={<SmallPlusIcon color={isEditable ? 'text-success': ''} size={5}/>}
|
||||||
|
|
|
@ -372,7 +372,7 @@ function RSTabs() {
|
||||||
onSelect={onSelectTab}
|
onSelect={onSelectTab}
|
||||||
defaultFocus={true}
|
defaultFocus={true}
|
||||||
selectedTabClassName='clr-selected'
|
selectedTabClassName='clr-selected'
|
||||||
className='flex flex-col w-full items-center'
|
className='flex flex-col items-center w-full'
|
||||||
>
|
>
|
||||||
<TabList className='flex items-start border-b-2 border-x-2 select-none justify-stretch w-fit clr-controls h-[1.9rem] small-caps font-semibold'>
|
<TabList className='flex items-start border-b-2 border-x-2 select-none justify-stretch w-fit clr-controls h-[1.9rem] small-caps font-semibold'>
|
||||||
<RSTabsMenu
|
<RSTabsMenu
|
||||||
|
@ -391,11 +391,10 @@ function RSTabs() {
|
||||||
Паспорт схемы
|
Паспорт схемы
|
||||||
</ConceptTab>
|
</ConceptTab>
|
||||||
<ConceptTab
|
<ConceptTab
|
||||||
className='border-r-2 w-fit flex justify-between gap-2'
|
className='flex justify-between gap-2 border-r-2 w-fit'
|
||||||
title={`Всего конституент: ${schema.stats?.count_all ?? 0}\nКоличество ошибок: ${schema.stats?.count_errors ?? 0}`}
|
title={`Всего конституент: ${schema.stats?.count_all ?? 0}\nКоличество ошибок: ${schema.stats?.count_errors ?? 0}`}
|
||||||
>
|
>
|
||||||
<span>Конституенты</span>
|
<span>Конституенты</span>
|
||||||
<span>{`${schema.stats?.count_errors ?? 0} | ${schema.stats?.count_all ?? 0}`}</span>
|
|
||||||
</ConceptTab>
|
</ConceptTab>
|
||||||
<ConceptTab className='border-r-2 min-w-[5.2rem]'>
|
<ConceptTab className='border-r-2 min-w-[5.2rem]'>
|
||||||
Редактор
|
Редактор
|
||||||
|
|
|
@ -1,21 +1,16 @@
|
||||||
import { IExpressionParse, IRSErrorDescription, SyntaxTree } from '../../../models/rslang';
|
import { IExpressionParse, IRSErrorDescription } from '../../../models/rslang';
|
||||||
import { describeRSError } from '../../../utils/labels';
|
import { describeRSError } from '../../../utils/labels';
|
||||||
import { getRSErrorPrefix } from '../../../utils/misc';
|
import { getRSErrorPrefix } from '../../../utils/misc';
|
||||||
|
|
||||||
interface ParsingResultProps {
|
interface ParsingResultProps {
|
||||||
data: IExpressionParse
|
data: IExpressionParse
|
||||||
onShowAST: (ast: SyntaxTree) => void
|
|
||||||
onShowError: (error: IRSErrorDescription) => void
|
onShowError: (error: IRSErrorDescription) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function ParsingResult({ data, onShowAST, onShowError }: ParsingResultProps) {
|
function ParsingResult({ data, onShowError }: ParsingResultProps) {
|
||||||
const errorCount = data.errors.reduce((total, error) => (error.isCritical ? total + 1 : total), 0);
|
const errorCount = data.errors.reduce((total, error) => (error.isCritical ? total + 1 : total), 0);
|
||||||
const warningsCount = data.errors.length - errorCount;
|
const warningsCount = data.errors.length - errorCount;
|
||||||
|
|
||||||
function handleShowAST() {
|
|
||||||
onShowAST(data.ast);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='px-3 py-2'>
|
<div className='px-3 py-2'>
|
||||||
<p>Ошибок: <b>{errorCount}</b> | Предупреждений: <b>{warningsCount}</b></p>
|
<p>Ошибок: <b>{errorCount}</b> | Предупреждений: <b>{warningsCount}</b></p>
|
||||||
|
@ -27,17 +22,6 @@ function ParsingResult({ data, onShowAST, onShowError }: ParsingResultProps) {
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{data.astText &&
|
|
||||||
<p>
|
|
||||||
<button type='button'
|
|
||||||
className='font-semibold underline text-primary'
|
|
||||||
title='отобразить дерево разбора'
|
|
||||||
onClick={handleShowAST}
|
|
||||||
tabIndex={-1}
|
|
||||||
>
|
|
||||||
Дерево разбора
|
|
||||||
</button>
|
|
||||||
</p>}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
import { TokenID } from '../../../models/rslang';
|
||||||
|
import { prefixes } from '../../../utils/constants';
|
||||||
|
import RSLocalButton from './RSLocalButton';
|
||||||
|
import RSTokenButton from './RSTokenButton';
|
||||||
|
|
||||||
|
|
||||||
|
const MAIN_FIRST_ROW: TokenID[] = [
|
||||||
|
TokenID.NT_DECLARATIVE_EXPR,
|
||||||
|
TokenID.NT_IMPERATIVE_EXPR,
|
||||||
|
TokenID.NT_RECURSIVE_FULL,
|
||||||
|
TokenID.BIGPR,
|
||||||
|
TokenID.SMALLPR,
|
||||||
|
TokenID.FILTER,
|
||||||
|
TokenID.REDUCE,
|
||||||
|
TokenID.CARD,
|
||||||
|
TokenID.BOOL
|
||||||
|
];
|
||||||
|
|
||||||
|
const MAIN_SECOND_ROW: TokenID[] = [
|
||||||
|
TokenID.BOOLEAN,
|
||||||
|
TokenID.PUNC_PL,
|
||||||
|
TokenID.INTERSECTION,
|
||||||
|
TokenID.LIT_EMPTYSET,
|
||||||
|
TokenID.FORALL,
|
||||||
|
TokenID.NOT,
|
||||||
|
TokenID.IN,
|
||||||
|
TokenID.SUBSET_OR_EQ,
|
||||||
|
TokenID.AND,
|
||||||
|
TokenID.IMPLICATION,
|
||||||
|
TokenID.SET_MINUS,
|
||||||
|
TokenID.PUNC_ITERATE,
|
||||||
|
TokenID.SUBSET,
|
||||||
|
TokenID.DEBOOL
|
||||||
|
];
|
||||||
|
|
||||||
|
const MAIN_THIRD_ROW: TokenID[] = [
|
||||||
|
TokenID.DECART,
|
||||||
|
TokenID.PUNC_SL,
|
||||||
|
TokenID.UNION,
|
||||||
|
TokenID.LIT_INTSET,
|
||||||
|
TokenID.EXISTS,
|
||||||
|
TokenID.NOTEQUAL,
|
||||||
|
TokenID.NOTIN,
|
||||||
|
TokenID.NOTSUBSET,
|
||||||
|
TokenID.OR,
|
||||||
|
TokenID.EQUIVALENT,
|
||||||
|
TokenID.SYMMINUS,
|
||||||
|
TokenID.PUNC_ASSIGN,
|
||||||
|
TokenID.EQUAL,
|
||||||
|
TokenID.GREATER_OR_EQ,
|
||||||
|
TokenID.LESSER_OR_EQ
|
||||||
|
];
|
||||||
|
|
||||||
|
const SECONDARY_FIRST_ROW = [
|
||||||
|
{text: 'μ', tooltip: 'q'},
|
||||||
|
{text: 'ω', tooltip: 'w'},
|
||||||
|
{text: 'ε', tooltip: 'e'},
|
||||||
|
{text: 'ρ', tooltip: 'r'},
|
||||||
|
{text: 'τ', tooltip: 't'},
|
||||||
|
{text: 'π', tooltip: 'y'}
|
||||||
|
];
|
||||||
|
|
||||||
|
const SECONDARY_SECOND_ROW = [
|
||||||
|
{text: 'α', tooltip: 'a'},
|
||||||
|
{text: 'σ', tooltip: 's'},
|
||||||
|
{text: 'δ', tooltip: 'd'},
|
||||||
|
{text: 'φ', tooltip: 'f'},
|
||||||
|
{text: 'γ', tooltip: 'g'},
|
||||||
|
{text: 'λ', tooltip: 'h'}
|
||||||
|
];
|
||||||
|
|
||||||
|
const SECONDARY_THIRD_ROW = [
|
||||||
|
{text: 'ζ', tooltip: 'z'},
|
||||||
|
{text: 'ξ', tooltip: 'x'},
|
||||||
|
{text: 'ψ', tooltip: 'c'},
|
||||||
|
{text: 'θ', tooltip: 'v'},
|
||||||
|
{text: 'β', tooltip: 'b'},
|
||||||
|
{text: 'η', tooltip: 'n'}
|
||||||
|
];
|
||||||
|
|
||||||
|
interface RSEditorControlsProps {
|
||||||
|
onEdit: (id: TokenID, key?: string) => void
|
||||||
|
disabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
function RSEditorControls({ onEdit, disabled }: RSEditorControlsProps) {
|
||||||
|
return (
|
||||||
|
<div className='flex items-center justify-between w-full mt-1 text-sm'>
|
||||||
|
<div className='w-fit'>
|
||||||
|
<div className='flex justify-start'>
|
||||||
|
{MAIN_FIRST_ROW.map(
|
||||||
|
(token) =>
|
||||||
|
<RSTokenButton key={`${prefixes.rsedit_btn}${token}`}
|
||||||
|
token={token} onInsert={onEdit} disabled={disabled}
|
||||||
|
/>)}
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-start'>
|
||||||
|
{MAIN_SECOND_ROW.map(
|
||||||
|
(token) =>
|
||||||
|
<RSTokenButton key={`${prefixes.rsedit_btn}${token}`}
|
||||||
|
token={token} onInsert={onEdit} disabled={disabled}
|
||||||
|
/>)}
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-start'>
|
||||||
|
{MAIN_THIRD_ROW.map(
|
||||||
|
(token) =>
|
||||||
|
<RSTokenButton key={`${prefixes.rsedit_btn}${token}`}
|
||||||
|
token={token} onInsert={onEdit} disabled={disabled}
|
||||||
|
/>)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='w-fit'>
|
||||||
|
<div className='flex justify-start'>
|
||||||
|
{SECONDARY_FIRST_ROW.map(
|
||||||
|
({text, tooltip}) =>
|
||||||
|
<RSLocalButton key={`${prefixes.rsedit_btn}${tooltip}`}
|
||||||
|
text={text} tooltip={tooltip} onInsert={onEdit} disabled={disabled}
|
||||||
|
/>)}
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-start'>
|
||||||
|
{SECONDARY_SECOND_ROW.map(
|
||||||
|
({text, tooltip}) =>
|
||||||
|
<RSLocalButton key={`${prefixes.rsedit_btn}${tooltip}`}
|
||||||
|
text={text} tooltip={tooltip} onInsert={onEdit} disabled={disabled}
|
||||||
|
/>)}
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-start'>
|
||||||
|
{SECONDARY_THIRD_ROW.map(
|
||||||
|
({text, tooltip}) =>
|
||||||
|
<RSLocalButton key={`${prefixes.rsedit_btn}${tooltip}`}
|
||||||
|
text={text} tooltip={tooltip} onInsert={onEdit} disabled={disabled}
|
||||||
|
/>)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RSEditorControls;
|
|
@ -15,7 +15,7 @@ function RSLocalButton({ text, tooltip, disabled, onInsert }: RSLocalButtonProps
|
||||||
onClick={() => onInsert(TokenID.ID_LOCAL, text)}
|
onClick={() => onInsert(TokenID.ID_LOCAL, text)}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className='w-[1.5rem] h-7 cursor-pointer border rounded-none clr-hover clr-btn-clear'
|
className='w-[2.25rem] h-6 cursor-pointer disabled:cursor-default border rounded-none clr-hover clr-btn-clear'
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -5,8 +5,8 @@ import Dropdown from '../../../components/Common/Dropdown';
|
||||||
import DropdownButton from '../../../components/Common/DropdownButton';
|
import DropdownButton from '../../../components/Common/DropdownButton';
|
||||||
import DropdownCheckbox from '../../../components/Common/DropdownCheckbox';
|
import DropdownCheckbox from '../../../components/Common/DropdownCheckbox';
|
||||||
import {
|
import {
|
||||||
CloneIcon, DownloadIcon, DumpBinIcon, EyeIcon, EyeOffIcon,
|
CloneIcon, DownloadIcon, DumpBinIcon, EditIcon, MenuIcon, NotSubscribedIcon,
|
||||||
MenuIcon, OwnerIcon, PenIcon, ShareIcon, SmallPlusIcon, UploadIcon
|
OwnerIcon, ShareIcon, SmallPlusIcon, SubscribedIcon, UploadIcon
|
||||||
} from '../../../components/Icons';
|
} from '../../../components/Icons';
|
||||||
import { useAuth } from '../../../context/AuthContext';
|
import { useAuth } from '../../../context/AuthContext';
|
||||||
import { useRSForm } from '../../../context/RSFormContext';
|
import { useRSForm } from '../../../context/RSFormContext';
|
||||||
|
@ -76,7 +76,7 @@ function RSTabsMenu({
|
||||||
tooltip='Действия'
|
tooltip='Действия'
|
||||||
icon={<MenuIcon color='text-controls' size={5}/>}
|
icon={<MenuIcon color='text-controls' size={5}/>}
|
||||||
borderClass=''
|
borderClass=''
|
||||||
dimensions='h-full w-fit'
|
dimensions='h-full w-fit pl-2'
|
||||||
style={{outlineColor: 'transparent'}}
|
style={{outlineColor: 'transparent'}}
|
||||||
dense
|
dense
|
||||||
onClick={schemaMenu.toggle}
|
onClick={schemaMenu.toggle}
|
||||||
|
@ -128,7 +128,7 @@ function RSTabsMenu({
|
||||||
borderClass=''
|
borderClass=''
|
||||||
dimensions='h-full w-fit'
|
dimensions='h-full w-fit'
|
||||||
style={{outlineColor: 'transparent'}}
|
style={{outlineColor: 'transparent'}}
|
||||||
icon={<PenIcon size={5} color={isEditable ? 'text-success' : 'text-warning'}/>}
|
icon={<EditIcon size={5} color={isEditable ? 'text-success' : 'text-warning'}/>}
|
||||||
dense
|
dense
|
||||||
onClick={editMenu.toggle}
|
onClick={editMenu.toggle}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
|
@ -169,10 +169,10 @@ function RSTabsMenu({
|
||||||
tooltip={'отслеживание: ' + (isTracking ? '[включено]' : '[выключено]')}
|
tooltip={'отслеживание: ' + (isTracking ? '[включено]' : '[выключено]')}
|
||||||
disabled={processing}
|
disabled={processing}
|
||||||
icon={isTracking
|
icon={isTracking
|
||||||
? <EyeIcon color='text-primary' size={5}/>
|
? <SubscribedIcon color='text-primary' size={5}/>
|
||||||
: <EyeOffIcon color='text-controls' size={5}/>
|
: <NotSubscribedIcon color='text-controls' size={5}/>
|
||||||
}
|
}
|
||||||
dimensions='h-full w-fit'
|
dimensions='h-full w-fit pr-2'
|
||||||
borderClass=''
|
borderClass=''
|
||||||
style={{outlineColor: 'transparent'}}
|
style={{outlineColor: 'transparent'}}
|
||||||
dense
|
dense
|
||||||
|
|
|
@ -9,7 +9,7 @@ interface RSTokenButtonProps {
|
||||||
|
|
||||||
function RSTokenButton({ token, disabled, onInsert }: RSTokenButtonProps) {
|
function RSTokenButton({ token, disabled, onInsert }: RSTokenButtonProps) {
|
||||||
const label = labelToken(token);
|
const label = labelToken(token);
|
||||||
const width = label.length > 3 ? 'w-[4rem]' : 'w-[2rem]';
|
const width = label.length > 3 ? 'w-[4.5rem]' : 'w-[2.25rem]';
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type='button'
|
type='button'
|
||||||
|
@ -17,7 +17,7 @@ function RSTokenButton({ token, disabled, onInsert }: RSTokenButtonProps) {
|
||||||
onClick={() => onInsert(token)}
|
onClick={() => onInsert(token)}
|
||||||
title={describeToken(token)}
|
title={describeToken(token)}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className={`px-1 cursor-pointer border rounded-none h-7 ${width} clr-outline clr-hover clr-btn-clear`}
|
className={`px-1 cursor-pointer disabled:cursor-default border rounded-none h-6 ${width} clr-outline clr-hover clr-btn-clear`}
|
||||||
>
|
>
|
||||||
{label && <span className='whitespace-nowrap'>{label}</span>}
|
{label && <span className='whitespace-nowrap'>{label}</span>}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -28,7 +28,7 @@ function StatusBar({ isModified, constituenta, parseData }: StatusBarProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div title={describeExpressionStatus(status)}
|
<div title={describeExpressionStatus(status)}
|
||||||
className='text-sm h-[1.6rem] w-[10rem] font-semibold small-caps inline-flex border items-center select-none justify-center align-middle'
|
className='inline-flex items-center justify-center w-full h-full text-sm font-semibold align-middle border select-none small-caps'
|
||||||
style={{backgroundColor: colorbgCstStatus(status, colors)}}
|
style={{backgroundColor: colorbgCstStatus(status, colors)}}
|
||||||
>
|
>
|
||||||
{labelExpressionStatus(status)}
|
{labelExpressionStatus(status)}
|
||||||
|
|
|
@ -165,7 +165,7 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
|
||||||
id: 'description',
|
id: 'description',
|
||||||
header: 'Описание',
|
header: 'Описание',
|
||||||
size: 1000,
|
size: 1000,
|
||||||
minSize: 350,
|
minSize: 250,
|
||||||
maxSize: 1000,
|
maxSize: 1000,
|
||||||
cell: props =>
|
cell: props =>
|
||||||
<div style={{
|
<div style={{
|
||||||
|
@ -211,12 +211,12 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
|
||||||
}, [noNavigation, baseHeight]);
|
}, [noNavigation, baseHeight]);
|
||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
<div className='sticky top-0 left-0 right-0 flex items-stretch justify-between w-full gap-1 pl-2 border-b clr-input'>
|
<div className='sticky top-0 left-0 right-0 flex items-stretch justify-between gap-1 pl-2 border-b clr-input'>
|
||||||
<div className='absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none text-controls'>
|
<div className='absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none text-controls'>
|
||||||
<MagnifyingGlassIcon />
|
<MagnifyingGlassIcon />
|
||||||
</div>
|
</div>
|
||||||
<input type='text'
|
<input type='text'
|
||||||
className='w-[14rem] pr-2 pl-8 py-1 outline-none select-none hover:text-clip clr-input'
|
className='w-full min-w-[6rem] pr-2 pl-8 py-1 outline-none select-none hover:text-clip clr-input'
|
||||||
placeholder='Поиск'
|
placeholder='Поиск'
|
||||||
value={filterText}
|
value={filterText}
|
||||||
onChange={event => setFilterText(event.target.value)}
|
onChange={event => setFilterText(event.target.value)}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { useMemo, useState } from 'react';
|
||||||
import BackendError from '../../components/BackendError';
|
import BackendError from '../../components/BackendError';
|
||||||
import { ConceptLoader } from '../../components/Common/ConceptLoader';
|
import { ConceptLoader } from '../../components/Common/ConceptLoader';
|
||||||
import MiniButton from '../../components/Common/MiniButton';
|
import MiniButton from '../../components/Common/MiniButton';
|
||||||
import { EyeIcon, EyeOffIcon } from '../../components/Icons';
|
import { NotSubscribedIcon,SubscribedIcon } from '../../components/Icons';
|
||||||
import { useAuth } from '../../context/AuthContext';
|
import { useAuth } from '../../context/AuthContext';
|
||||||
import { useLibrary } from '../../context/LibraryContext';
|
import { useLibrary } from '../../context/LibraryContext';
|
||||||
import { useUserProfile } from '../../context/UserProfileContext';
|
import { useUserProfile } from '../../context/UserProfileContext';
|
||||||
|
@ -35,8 +35,8 @@ function UserTabs() {
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip='Показать/Скрыть список отслеживаний'
|
tooltip='Показать/Скрыть список отслеживаний'
|
||||||
icon={showSubs
|
icon={showSubs
|
||||||
? <EyeIcon color='text-primary' size={5}/>
|
? <SubscribedIcon color='text-primary' size={5}/>
|
||||||
: <EyeOffIcon color='text-primary' size={5}/>
|
: <NotSubscribedIcon color='text-primary' size={5}/>
|
||||||
}
|
}
|
||||||
onClick={() => setShowSubs(prev => !prev)}
|
onClick={() => setShowSubs(prev => !prev)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -38,8 +38,9 @@ export const prefixes = {
|
||||||
cst_status_list: 'cst-status-list-',
|
cst_status_list: 'cst-status-list-',
|
||||||
cst_match_mode_list: 'cst-match-mode-list-',
|
cst_match_mode_list: 'cst-match-mode-list-',
|
||||||
cst_source_list: 'cst-source-list-',
|
cst_source_list: 'cst-source-list-',
|
||||||
library_filters_list: 'library-filters-list',
|
library_filters_list: 'library-filters-list-',
|
||||||
topic_list: 'topic-list-',
|
topic_list: 'topic-list-',
|
||||||
library_list: 'library-list-',
|
library_list: 'library-list-',
|
||||||
wordform_list: 'wordform-list'
|
wordform_list: 'wordform-list-',
|
||||||
|
rsedit_btn: 'rsedit-btn-'
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user