This commit is contained in:
IRBorisov 2023-10-14 23:46:36 +03:00
parent 2ab01cda42
commit 1cc41320ac
14 changed files with 91 additions and 84 deletions

View File

@ -7,7 +7,6 @@ export interface CheckboxProps
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'children' | 'title' | 'value' | 'onClick' > { extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'children' | 'title' | 'value' | 'onClick' > {
id?: string id?: string
label?: string label?: string
required?: boolean
disabled?: boolean disabled?: boolean
dimensions?: string dimensions?: string
tooltip?: string tooltip?: string
@ -17,7 +16,7 @@ extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'child
} }
function Checkbox({ function Checkbox({
id, required, disabled, tooltip, label, id, disabled, tooltip, label,
dimensions = 'w-fit', value, setValue, ...props dimensions = 'w-fit', value, setValue, ...props
}: CheckboxProps) { }: CheckboxProps) {
const cursor = useMemo( const cursor = useMemo(
@ -59,7 +58,6 @@ function Checkbox({
<Label <Label
className={`${cursor} px-2 text-start`} className={`${cursor} px-2 text-start`}
text={label} text={label}
required={required}
htmlFor={id} htmlFor={id}
/>} />}
</button> </button>

View File

@ -1,19 +1,19 @@
import { LabelHTMLAttributes } from 'react'; import { LabelHTMLAttributes } from 'react';
interface LabelProps interface LabelProps
extends Omit<React.DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, 'children'> { extends Omit<React.DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, 'children' | 'title'> {
text: string text: string
required?: boolean tooltip?: string
} }
function Label({ text, required, title, className, ...props }: LabelProps) { function Label({ text, tooltip, className, ...props }: LabelProps) {
return ( return (
<label <label
className={`text-sm font-semibold ${className}`} className={`text-sm font-semibold ${className}`}
title={ (required && !title) ? 'обязательное поле' : title } title={tooltip}
{...props} {...props}
> >
{text + (required ? '*' : '')} {text}
</label> </label>
); );
} }

View File

@ -19,9 +19,9 @@ function TextArea({
}: TextAreaProps) { }: TextAreaProps) {
return ( return (
<div className='flex flex-col items-start gap-2'> <div className='flex flex-col items-start gap-2'>
{label && <Label {label &&
<Label
text={label} text={label}
required={!props.disabled && required}
htmlFor={id} htmlFor={id}
/>} />}
<textarea id={id} <textarea id={id}

View File

@ -23,7 +23,6 @@ function TextInput({
{label && {label &&
<Label <Label
text={label} text={label}
required={!props.disabled && required}
htmlFor={id} htmlFor={id}
/>} />}
<input id={id} <input id={id}

View File

@ -12,7 +12,7 @@ extends Omit<CheckboxProps, 'value' | 'setValue'> {
} }
function Tristate({ function Tristate({
id, required, disabled, tooltip, label, id, disabled, tooltip, label,
dimensions = 'w-fit', value, setValue, ...props dimensions = 'w-fit', value, setValue, ...props
}: TristateProps) { }: TristateProps) {
const cursor = useMemo( const cursor = useMemo(
@ -61,7 +61,6 @@ function Tristate({
<Label <Label
className={`${cursor} px-2 text-start`} className={`${cursor} px-2 text-start`}
text={label} text={label}
required={required}
htmlFor={id} htmlFor={id}
/>} />}
</button> </button>

View File

@ -109,15 +109,14 @@ export default function DataTable<TData extends RowData>({
return ( return (
<div className='w-full'> <div className='w-full'>
{isEmpty && (noDataComponent ?? <DefaultNoData />)}
{!isEmpty &&
<div className='flex flex-col items-stretch'> <div className='flex flex-col items-stretch'>
<table> <table>
<thead <thead
className='clr-app shadow-border' className={`clr-app shadow-border`}
style={{ style={{
top: headPosition, top: headPosition,
position: 'sticky' position: 'sticky',
visibility: !isEmpty ? 'visible' : 'hidden'
}} }}
> >
{tableImpl.getHeaderGroups().map( {tableImpl.getHeaderGroups().map(
@ -149,7 +148,7 @@ export default function DataTable<TData extends RowData>({
</tr> </tr>
))} ))}
</thead> </thead>
<tbody> <tbody>
{tableImpl.getRowModel().rows.map( {tableImpl.getRowModel().rows.map(
(row: Row<TData>, index) => ( (row: Row<TData>, index) => (
@ -202,12 +201,13 @@ export default function DataTable<TData extends RowData>({
</tfoot> </tfoot>
</table> </table>
{enablePagination && {enablePagination && !isEmpty &&
<PaginationTools <PaginationTools
table={tableImpl} table={tableImpl}
paginationOptions={paginationOptions} paginationOptions={paginationOptions}
onChangePaginationOption={onChangePaginationOption} onChangePaginationOption={onChangePaginationOption}
/>} />}
</div>} </div>
{isEmpty && (noDataComponent ?? <DefaultNoData />)}
</div>); </div>);
} }

View File

@ -134,7 +134,6 @@ function RSInput({
{label && {label &&
<Label <Label
text={label} text={label}
required={false}
htmlFor={id} htmlFor={id}
className='mb-2' className='mb-2'
/>} />}

View File

@ -203,7 +203,6 @@ function RefsInput({
{label && {label &&
<Label <Label
text={label} text={label}
required={false}
htmlFor={id} htmlFor={id}
className='mb-2' className='mb-2'
/>} />}

View File

@ -111,7 +111,7 @@
.dark & { .dark & {
background: var(--cd-prim-bg-60); background: var(--cd-prim-bg-60);
} }
:hover& { tr :hover& {
background: var(--cl-red-bg-100); background: var(--cl-red-bg-100);
.dark & { .dark & {
background: var(--cd-red-bg-100); background: var(--cd-red-bg-100);

View File

@ -15,7 +15,7 @@ function TopicsList({ activeTopic, onChangeTopic }: TopicsListProps) {
(topic, index) => { (topic, index) => {
return ( return (
<div key={`${prefixes.topic_list}${index}`} <div key={`${prefixes.topic_list}${index}`}
className={`px-3 py-1 border-y cursor-pointer clr-hover ${activeTopic === topic ? 'font-semibold clr-selected ' : ''}`} className={`px-3 py-1 border-y cursor-pointer clr-hover ${activeTopic === topic ? 'clr-selected ' : ''}`}
title={describeHelpTopic(topic)} title={describeHelpTopic(topic)}
onClick={() => onChangeTopic(topic)} onClick={() => onChangeTopic(topic)}
> >

View File

@ -150,9 +150,9 @@ function EditorConstituenta({
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />} icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
/>} />}
<div className='flex items-center justify-center w-full'> <div className='flex items-center justify-center w-full'>
<div className='font-semibold w-fit'> <div className='font-semibold w-fit pointer-events-none'>
<span className='small-caps'>Конституента</span> <span className='small-caps'>Конституента </span>
<span className='ml-2 small-caps'>{alias}</span> <span className='ml-1 small-caps'>{alias}</span>
</div> </div>
<MiniButton <MiniButton
tooltip='Переименовать конституенту' tooltip='Переименовать конституенту'

View File

@ -397,10 +397,10 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra
</div> </div>
<div className='flex items-center w-full gap-1'> <div className='flex items-center w-full gap-1'>
<Button <Button
icon={<FilterCogIcon size={7} />} icon={<FilterCogIcon size={6} />}
dense dense
tooltip='Настройки фильтрации узлов и связей' tooltip='Настройки фильтрации узлов и связей'
dimensions='h-full' dimensions='min-h-[2.3rem] min-w-[2.3rem]'
onClick={() => setShowOptions(true)} onClick={() => setShowOptions(true)}
/> />
<SelectSingle <SelectSingle
@ -411,7 +411,6 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra
value={coloringScheme ? { value: coloringScheme, label: mapLabelColoring.get(coloringScheme) } : null} value={coloringScheme ? { value: coloringScheme, label: mapLabelColoring.get(coloringScheme) } : null}
onChange={data => setColoringScheme(data?.value ?? SelectorGraphColoring[0].value)} onChange={data => setColoringScheme(data?.value ?? SelectorGraphColoring[0].value)}
/> />
</div> </div>
<SelectSingle <SelectSingle
className='w-full mt-1' className='w-full mt-1'

View File

@ -384,13 +384,25 @@ function RSTabs() {
showCloneDialog={promptClone} showCloneDialog={promptClone}
showUploadDialog={() => setShowUpload(true)} showUploadDialog={() => setShowUpload(true)}
/> />
<ConceptTab className='border-x-2 min-w-[7.8rem]'>Паспорт схемы</ConceptTab> <ConceptTab
<ConceptTab className='border-r-2 min-w-[10rem] flex justify-between gap-2'> className='border-x-2 min-w-[7.8rem]'
title={`Название схемы: ${schema.title ?? ''}`}
>
Паспорт схемы
</ConceptTab>
<ConceptTab
className='border-r-2 w-fit flex justify-between gap-2'
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> <span>{`${schema.stats?.count_errors ?? 0} | ${schema.stats?.count_all ?? 0}`}</span>
</ConceptTab> </ConceptTab>
<ConceptTab className='border-r-2 min-w-[5.2rem]'>Редактор</ConceptTab> <ConceptTab className='border-r-2 min-w-[5.2rem]'>
<ConceptTab className='min-w-[6.5rem]'>Граф термов</ConceptTab> Редактор
</ConceptTab>
<ConceptTab className='min-w-[6.5rem]'>
Граф термов
</ConceptTab>
</TabList> </TabList>
<div className='overflow-y-auto' style={{ maxHeight: panelHeight}}> <div className='overflow-y-auto' style={{ maxHeight: panelHeight}}>

View File

@ -211,7 +211,7 @@ 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-start w-full gap-1 px-2 border-b rounded clr-input'> <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='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>
@ -221,56 +221,58 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
value={filterText} value={filterText}
onChange={event => setFilterText(event.target.value)} onChange={event => setFilterText(event.target.value)}
/> />
<div ref={matchModeMenu.ref}> <div className='flex'>
<SelectorButton <div ref={matchModeMenu.ref}>
tooltip='Настройка атрибутов для фильтрации' <SelectorButton
dimensions='w-fit h-full' tooltip='Настройка атрибутов для фильтрации'
transparent dimensions='w-fit h-full'
icon={<FilterCogIcon size={5} />} transparent
text={labelCstMathchMode(filterMatch)} icon={<FilterCogIcon size={5} />}
tabIndex={-1} text={labelCstMathchMode(filterMatch)}
onClick={matchModeMenu.toggle} tabIndex={-1}
/> onClick={matchModeMenu.toggle}
{ matchModeMenu.isActive && />
<Dropdown stretchLeft> { matchModeMenu.isActive &&
{ Object.values(CstMatchMode).filter(value => !isNaN(Number(value))).map( <Dropdown stretchLeft>
(value, index) => { { Object.values(CstMatchMode).filter(value => !isNaN(Number(value))).map(
const matchMode = value as CstMatchMode; (value, index) => {
return ( const matchMode = value as CstMatchMode;
<DropdownButton return (
key={`${prefixes.cst_match_mode_list}${index}`} <DropdownButton
onClick={() => handleMatchModeChange(matchMode)} key={`${prefixes.cst_match_mode_list}${index}`}
> onClick={() => handleMatchModeChange(matchMode)}
<p><span className='font-semibold'>{labelCstMathchMode(matchMode)}:</span> {describeCstMathchMode(matchMode)}</p> >
</DropdownButton>); <p><span className='font-semibold'>{labelCstMathchMode(matchMode)}:</span> {describeCstMathchMode(matchMode)}</p>
})} </DropdownButton>);
</Dropdown>} })}
</div> </Dropdown>}
</div>
<div ref={sourceMenu.ref}> <div ref={sourceMenu.ref}>
<SelectorButton <SelectorButton
tooltip='Настройка фильтрации по графу термов' tooltip='Настройка фильтрации по графу термов'
dimensions='w-fit h-full' dimensions='w-fit h-full'
transparent transparent
icon={<CogIcon size={4} />} icon={<CogIcon size={4} />}
text={labelCstSource(filterSource)} text={labelCstSource(filterSource)}
tabIndex={-1} tabIndex={-1}
onClick={sourceMenu.toggle} onClick={sourceMenu.toggle}
/> />
{ sourceMenu.isActive && { sourceMenu.isActive &&
<Dropdown stretchLeft> <Dropdown stretchLeft>
{ Object.values(CstSource).filter(value => !isNaN(Number(value))).map( { Object.values(CstSource).filter(value => !isNaN(Number(value))).map(
(value, index) => { (value, index) => {
const source = value as CstSource; const source = value as CstSource;
return ( return (
<DropdownButton <DropdownButton
key={`${prefixes.cst_source_list}${index}`} key={`${prefixes.cst_source_list}${index}`}
onClick={() => handleSourceChange(source)} onClick={() => handleSourceChange(source)}
> >
<p><span className='font-semibold'>{labelCstSource(source)}:</span> {describeCstSource(source)}</p> <p><span className='font-semibold'>{labelCstSource(source)}:</span> {describeCstSource(source)}</p>
</DropdownButton>); </DropdownButton>);
})} })}
</Dropdown>} </Dropdown>}
</div>
</div> </div>
</div> </div>
<div className='overflow-y-auto text-sm' style={{maxHeight : `${maxHeight}`}}> <div className='overflow-y-auto text-sm' style={{maxHeight : `${maxHeight}`}}>