Compare commits
4 Commits
21a304701e
...
168ff94c42
Author | SHA1 | Date | |
---|---|---|---|
![]() |
168ff94c42 | ||
![]() |
8035a604bd | ||
![]() |
05ef45fac8 | ||
![]() |
68cc96a779 |
|
@ -4,29 +4,32 @@ import { IConstituenta } from '@/models/rsform';
|
||||||
import { isMockCst } from '@/models/rsformAPI';
|
import { isMockCst } from '@/models/rsformAPI';
|
||||||
import { colorFgCstStatus, IColorTheme } from '@/styling/color';
|
import { colorFgCstStatus, IColorTheme } from '@/styling/color';
|
||||||
|
|
||||||
|
import { CProps } from '../props';
|
||||||
import TooltipConstituenta from './TooltipConstituenta';
|
import TooltipConstituenta from './TooltipConstituenta';
|
||||||
|
|
||||||
interface BadgeConstituentaProps {
|
interface BadgeConstituentaProps extends CProps.Styling {
|
||||||
prefixID?: string;
|
prefixID?: string;
|
||||||
value: IConstituenta;
|
value: IConstituenta;
|
||||||
theme: IColorTheme;
|
theme: IColorTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
function BadgeConstituenta({ value, prefixID, theme }: BadgeConstituentaProps) {
|
function BadgeConstituenta({ value, prefixID, className, style, theme }: BadgeConstituentaProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id={`${prefixID}${value.alias}`}
|
id={`${prefixID}${value.alias}`}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'min-w-[3.1rem] max-w-[3.1rem]', // prettier: split lines
|
'min-w-[3.1rem] max-w-[3.1rem]',
|
||||||
'px-1',
|
'px-1',
|
||||||
'border rounded-md',
|
'border rounded-md',
|
||||||
value.is_inherited && 'border-dashed',
|
value.is_inherited && 'border-dashed',
|
||||||
'text-center font-medium whitespace-nowrap'
|
'text-center font-medium whitespace-nowrap',
|
||||||
|
className
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
borderColor: colorFgCstStatus(value.status, theme),
|
borderColor: colorFgCstStatus(value.status, theme),
|
||||||
color: colorFgCstStatus(value.status, theme),
|
color: colorFgCstStatus(value.status, theme),
|
||||||
backgroundColor: isMockCst(value) ? theme.bgWarning : theme.bgInput
|
backgroundColor: isMockCst(value) ? theme.bgWarning : theme.bgInput,
|
||||||
|
...style
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{value.alias}
|
{value.alias}
|
||||||
|
|
|
@ -91,12 +91,14 @@ function Modal({
|
||||||
{header ? <h1 className='px-12 py-2 select-none'>{header}</h1> : null}
|
{header ? <h1 className='px-12 py-2 select-none'>{header}</h1> : null}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={clsx('overflow-auto overscroll-contain', className)}
|
className={clsx(
|
||||||
style={{
|
'overscroll-contain max-h-[calc(100svh-8rem)] max-w-[100svw] xs:max-w-[calc(100svw-2rem)]',
|
||||||
overflow: overflowVisible ? 'visible' : 'auto',
|
{
|
||||||
maxHeight: 'calc(100svh - 8rem)',
|
'overflow-auto': !overflowVisible,
|
||||||
maxWidth: 'calc(100svw - 2rem)'
|
'overflow-visible': overflowVisible
|
||||||
}}
|
},
|
||||||
|
className
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -78,7 +78,7 @@ function FormCreateCst({ schema, state, partialUpdate, setValidated }: FormCreat
|
||||||
fitContent
|
fitContent
|
||||||
spellCheck
|
spellCheck
|
||||||
label='Термин'
|
label='Термин'
|
||||||
placeholder='Обозначение, используемое в текстовых определениях'
|
placeholder='Обозначение для текстовых определений'
|
||||||
className='max-h-[3.6rem]'
|
className='max-h-[3.6rem]'
|
||||||
value={state.term_raw}
|
value={state.term_raw}
|
||||||
onChange={event => partialUpdate({ term_raw: event.target.value })}
|
onChange={event => partialUpdate({ term_raw: event.target.value })}
|
||||||
|
|
|
@ -18,10 +18,11 @@ import { SelectorCstType } from '@/utils/selectors';
|
||||||
|
|
||||||
interface DlgRenameCstProps extends Pick<ModalProps, 'hideWindow'> {
|
interface DlgRenameCstProps extends Pick<ModalProps, 'hideWindow'> {
|
||||||
initial: ICstRenameData;
|
initial: ICstRenameData;
|
||||||
|
allowChangeType: boolean;
|
||||||
onRename: (data: ICstRenameData) => void;
|
onRename: (data: ICstRenameData) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
|
function DlgRenameCst({ hideWindow, initial, allowChangeType, onRename }: DlgRenameCstProps) {
|
||||||
const { schema } = useRSForm();
|
const { schema } = useRSForm();
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
const [cstData, updateData] = usePartialUpdate(initial);
|
const [cstData, updateData] = usePartialUpdate(initial);
|
||||||
|
@ -52,6 +53,7 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
|
||||||
id='dlg_cst_type'
|
id='dlg_cst_type'
|
||||||
placeholder='Выберите тип'
|
placeholder='Выберите тип'
|
||||||
className='min-w-[16rem] self-center'
|
className='min-w-[16rem] self-center'
|
||||||
|
isDisabled={!allowChangeType}
|
||||||
options={SelectorCstType}
|
options={SelectorCstType}
|
||||||
value={{
|
value={{
|
||||||
value: cstData.cst_type,
|
value: cstData.cst_type,
|
||||||
|
|
|
@ -255,7 +255,20 @@ export function isFunctional(type: CstType): boolean {
|
||||||
* Validate new alias against {@link CstType} and {@link IRSForm}.
|
* Validate new alias against {@link CstType} and {@link IRSForm}.
|
||||||
*/
|
*/
|
||||||
export function validateNewAlias(alias: string, type: CstType, schema: IRSForm): boolean {
|
export function validateNewAlias(alias: string, type: CstType, schema: IRSForm): boolean {
|
||||||
return alias.length >= 2 && alias.startsWith(getCstTypePrefix(type)) && !schema.cstByAlias.has(alias);
|
if (alias.length < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const prefix = getCstTypePrefix(type);
|
||||||
|
if (!alias.startsWith(prefix)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (schema.cstByAlias.has(alias)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!/^\d+$/.exec(alias.substring(prefix.length))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
function HelpConceptRelations() {
|
function HelpConceptRelations() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className='text-justify'>
|
||||||
<h1>Связи между конституентами</h1>
|
<h1>Связи между конституентами</h1>
|
||||||
<p>
|
<p>
|
||||||
Конституенты связаны между собой через использование одних конституент при определении других. Такую связь в
|
Конституенты связаны между собой через использование одних конституент при определении других. Такую связь в
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
function HelpConceptSynthesis() {
|
function HelpConceptSynthesis() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className='text-justify'>
|
||||||
<h1>Синтез концептуальных схем</h1>
|
<h1>Синтез концептуальных схем</h1>
|
||||||
<p>
|
<p>
|
||||||
Работа с крупными предметными областями требуют рассмотрения различных точек зрения в рамках одной предметной
|
Работа с крупными предметными областями требуют рассмотрения различных точек зрения в рамках одной предметной
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
|
||||||
function HelpConceptSystem() {
|
function HelpConceptSystem() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className='text-justify'>
|
||||||
<h1>Концептуальная схема – Система определений</h1>
|
<h1>Концептуальная схема – Система определений</h1>
|
||||||
<p>
|
<p>
|
||||||
Данный раздел вводит <b>систему определений</b> как предмет концептуализации предметных областей. Под системой
|
Данный раздел вводит <b>систему определений</b> как предмет концептуализации предметных областей. Под системой
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { external_urls } from '@/utils/constants';
|
||||||
|
|
||||||
function HelpRules() {
|
function HelpRules() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className='text-justify'>
|
||||||
<h1>Правила поведения участников Портала</h1>
|
<h1>Правила поведения участников Портала</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -56,7 +56,11 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
||||||
|
|
||||||
const onSelectionChange = useCallback(
|
const onSelectionChange = useCallback(
|
||||||
({ nodes }: { nodes: Node[] }) => {
|
({ nodes }: { nodes: Node[] }) => {
|
||||||
controller.setSelected(nodes.map(node => Number(node.id)));
|
const ids = nodes.map(node => Number(node.id));
|
||||||
|
controller.setSelected(prev => [
|
||||||
|
...prev.filter(nodeID => ids.includes(nodeID)),
|
||||||
|
...ids.filter(nodeID => !prev.includes(Number(nodeID)))
|
||||||
|
]);
|
||||||
},
|
},
|
||||||
[controller]
|
[controller]
|
||||||
);
|
);
|
||||||
|
|
|
@ -149,7 +149,7 @@ function FormConstituenta({
|
||||||
id='cst_term'
|
id='cst_term'
|
||||||
label='Термин'
|
label='Термин'
|
||||||
maxHeight='8rem'
|
maxHeight='8rem'
|
||||||
placeholder='Обозначение, используемое в текстовых определениях'
|
placeholder='Обозначение для текстовых определений'
|
||||||
schema={schema}
|
schema={schema}
|
||||||
onOpenEdit={onOpenEdit}
|
onOpenEdit={onOpenEdit}
|
||||||
value={term}
|
value={term}
|
||||||
|
@ -240,7 +240,7 @@ function FormConstituenta({
|
||||||
</AnimateFade>
|
</AnimateFade>
|
||||||
|
|
||||||
{!disabled || processing ? (
|
{!disabled || processing ? (
|
||||||
<div className='self-center flex'>
|
<div className='mx-auto flex'>
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
key='cst_form_submit'
|
key='cst_form_submit'
|
||||||
id='cst_form_submit'
|
id='cst_form_submit'
|
||||||
|
|
|
@ -165,7 +165,7 @@ function EditorRSExpression({
|
||||||
toggleControls={() => setShowControls(prev => !prev)}
|
toggleControls={() => setShowControls(prev => !prev)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Overlay position='top-[-0.5rem] pl-[8rem] sm:pl-[4rem] right-1/2 translate-x-1/2 flex'>
|
<Overlay position='top-[-0.5rem]' className='pl-[8.5rem] xs:pl-[2rem] flex justify-center w-full gap-1'>
|
||||||
<StatusBar
|
<StatusBar
|
||||||
processing={parser.processing}
|
processing={parser.processing}
|
||||||
isModified={isModified}
|
isModified={isModified}
|
||||||
|
|
|
@ -92,7 +92,7 @@ function RSEditorControls({ isOpen, disabled, onEdit }: RSEditorControlsProps) {
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'max-w-[38.5rem] sm:max-w-[40rem] sm:min-w-[40rem] md:max-w-fit mx-1 sm:mx-0',
|
'max-w-[28rem] min-w-[28rem] xs:max-w-[38.5rem] xs:min-w-[38.5rem] sm:max-w-[40rem] sm:min-w-[40rem] md:max-w-fit mx-1 sm:mx-0',
|
||||||
'flex-wrap',
|
'flex-wrap',
|
||||||
'divide-solid',
|
'divide-solid',
|
||||||
'text-xs md:text-sm',
|
'text-xs md:text-sm',
|
||||||
|
@ -112,6 +112,7 @@ function RSEditorControls({ isOpen, disabled, onEdit }: RSEditorControlsProps) {
|
||||||
title={title}
|
title={title}
|
||||||
onInsert={onEdit}
|
onInsert={onEdit}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
className='hidden xs:inline'
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
@ -121,6 +122,7 @@ function RSEditorControls({ isOpen, disabled, onEdit }: RSEditorControlsProps) {
|
||||||
{SECONDARY_SECOND_ROW.map(({ text, title }) => (
|
{SECONDARY_SECOND_ROW.map(({ text, title }) => (
|
||||||
<RSLocalButton
|
<RSLocalButton
|
||||||
key={`${prefixes.rsedit_btn}${title}`}
|
key={`${prefixes.rsedit_btn}${title}`}
|
||||||
|
className='hidden xs:inline'
|
||||||
text={text}
|
text={text}
|
||||||
title={title}
|
title={title}
|
||||||
onInsert={onEdit}
|
onInsert={onEdit}
|
||||||
|
@ -134,6 +136,7 @@ function RSEditorControls({ isOpen, disabled, onEdit }: RSEditorControlsProps) {
|
||||||
{SECONDARY_THIRD_ROW.map(({ text, title }) => (
|
{SECONDARY_THIRD_ROW.map(({ text, title }) => (
|
||||||
<RSLocalButton
|
<RSLocalButton
|
||||||
key={`${prefixes.rsedit_btn}${title}`}
|
key={`${prefixes.rsedit_btn}${title}`}
|
||||||
|
className='hidden xs:inline'
|
||||||
text={text}
|
text={text}
|
||||||
title={title}
|
title={title}
|
||||||
onInsert={onEdit}
|
onInsert={onEdit}
|
||||||
|
|
|
@ -4,13 +4,22 @@ import { CProps } from '@/components/props';
|
||||||
import { TokenID } from '@/models/rslang';
|
import { TokenID } from '@/models/rslang';
|
||||||
import { globals } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
interface RSLocalButtonProps extends CProps.Titled {
|
interface RSLocalButtonProps extends CProps.Titled, CProps.Styling {
|
||||||
text: string;
|
text: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
onInsert: (token: TokenID, key?: string) => void;
|
onInsert: (token: TokenID, key?: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function RSLocalButton({ text, title, titleHtml, hideTitle, disabled, onInsert }: RSLocalButtonProps) {
|
function RSLocalButton({
|
||||||
|
text,
|
||||||
|
title,
|
||||||
|
titleHtml,
|
||||||
|
hideTitle,
|
||||||
|
disabled,
|
||||||
|
className,
|
||||||
|
onInsert,
|
||||||
|
...restProps
|
||||||
|
}: RSLocalButtonProps) {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type='button'
|
type='button'
|
||||||
|
@ -25,9 +34,11 @@ function RSLocalButton({ text, title, titleHtml, hideTitle, disabled, onInsert }
|
||||||
'cursor-pointer disabled:cursor-default',
|
'cursor-pointer disabled:cursor-default',
|
||||||
'rounded-none',
|
'rounded-none',
|
||||||
'clr-hover clr-btn-clear',
|
'clr-hover clr-btn-clear',
|
||||||
'font-math'
|
'font-math',
|
||||||
|
className
|
||||||
)}
|
)}
|
||||||
onClick={() => onInsert(TokenID.ID_LOCAL, text)}
|
onClick={() => onInsert(TokenID.ID_LOCAL, text)}
|
||||||
|
{...restProps}
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -41,12 +41,10 @@ function StatusBar({ isModified, processing, activeCst, parseData, onAnalyze }:
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'w-[10rem] h-[1.75rem]',
|
'w-[10rem] h-[1.75rem]',
|
||||||
'scale-75 sm:scale-100 mx-[-2.5rem] sm:m-0',
|
|
||||||
'px-2 flex items-center justify-center gap-2',
|
'px-2 flex items-center justify-center gap-2',
|
||||||
'border',
|
'border',
|
||||||
'select-none',
|
'select-none',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
'translate-x-[-1.5rem]',
|
|
||||||
'focus-frame',
|
'focus-frame',
|
||||||
'duration-500 transition-colors'
|
'duration-500 transition-colors'
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -689,10 +689,11 @@ export const RSEditState = ({
|
||||||
initial={createInitialData}
|
initial={createInitialData}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{showRenameCst && renameInitialData ? (
|
{activeCst && showRenameCst && renameInitialData ? (
|
||||||
<DlgRenameCst
|
<DlgRenameCst
|
||||||
hideWindow={() => setShowRenameCst(false)}
|
hideWindow={() => setShowRenameCst(false)}
|
||||||
onRename={handleRenameCst}
|
onRename={handleRenameCst}
|
||||||
|
allowChangeType={!activeCst.is_inherited}
|
||||||
initial={renameInitialData}
|
initial={renameInitialData}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -69,7 +69,12 @@ function TableSideConstituents({
|
||||||
minSize: 65,
|
minSize: 65,
|
||||||
footer: undefined,
|
footer: undefined,
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<BadgeConstituenta theme={colors} value={props.row.original} prefixID={prefixes.cst_side_table} />
|
<BadgeConstituenta
|
||||||
|
className='mr-[-0.5rem]'
|
||||||
|
theme={colors}
|
||||||
|
value={props.row.original}
|
||||||
|
prefixID={prefixes.cst_side_table}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor(cst => describeConstituenta(cst), {
|
columnHelper.accessor(cst => describeConstituenta(cst), {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user