Minor UI fixes

This commit is contained in:
IRBorisov 2023-09-30 12:47:27 +03:00
parent 70737410c2
commit 41bb83b784
14 changed files with 132 additions and 94 deletions

View File

@ -17,7 +17,7 @@ function TextInput({
colorClass = 'clr-input',
...props
}: TextInputProps) {
const borderClass = noBorder ? '': 'border';
const borderClass = noBorder ? '': 'border shadow';
return (
<div className={`flex ${singleRow ? 'items-center gap-4 ' + dimensions : 'flex-col items-start gap-2'}`}>
{label &&
@ -28,7 +28,7 @@ function TextInput({
/>}
<input id={id}
title={tooltip}
className={`px-3 py-2 leading-tight ${borderClass} shadow 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} ${singleRow ? 'w-full' : dimensions}`}
required={required}
{...props}
/>

View File

@ -26,6 +26,7 @@ extends Pick<TableOptions<TData>,
'onRowSelectionChange' | 'onColumnVisibilityChange'
> {
dense?: boolean
headPosition?: string
conditionalRowStyles?: IConditionalStyle<TData>[]
onRowClicked?: (rowData: TData, event: React.MouseEvent<Element, MouseEvent>) => void
onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent<Element, MouseEvent>) => void
@ -46,8 +47,14 @@ extends Pick<TableOptions<TData>,
initialSorting?: ColumnSort
}
/**
* UI element: data representation as a table.
*
* @param headPosition - Top position of sticky header (0 if no other sticky elements are present).
* No sticky header if omitted
*/
export default function DataTable<TData extends RowData>({
dense, conditionalRowStyles,
dense, headPosition, conditionalRowStyles,
onRowClicked, onRowDoubleClicked, noDataComponent,
enableRowSelection,
@ -106,7 +113,13 @@ export default function DataTable<TData extends RowData>({
{!isEmpty &&
<table>
<thead>
<thead
className='clr-app shadow-border'
style={{
top: headPosition,
position: 'sticky'
}}
>
{tableImpl.getHeaderGroups().map(
(headerGroup: HeaderGroup<TData>) => (
<tr key={headerGroup.id}>
@ -122,7 +135,7 @@ export default function DataTable<TData extends RowData>({
style={{
textAlign: header.getSize() > 100 ? 'left': 'center',
width: header.getSize(),
cursor: enableSorting && header.column.getCanSort() ? 'pointer': 'auto'
cursor: enableSorting && header.column.getCanSort() ? 'pointer': 'auto',
}}
onClick={enableSorting ? header.column.getToggleSortingHandler() : undefined}
>
@ -144,8 +157,7 @@ export default function DataTable<TData extends RowData>({
key={row.id}
className={
row.getIsSelected() ? 'clr-selected clr-hover' :
index % 2 === 0 ? 'clr-controls clr-hover' :
'clr-app clr-hover'
index % 2 === 0 ? 'clr-controls clr-hover' : 'clr-app clr-hover'
}
style={conditionalRowStyles && getRowStyles(row)}
>

View File

@ -7,7 +7,7 @@ function HelpConstituenta() {
<h1>Подсказки</h1>
<p><b className='text-warning'>Изменения сохраняются ПОСЛЕ нажатия на кнопку снизу или справа вверху</b></p>
<p><b>Клик на формальное выражение</b> - обратите внимание на кнопки снизу<br/>Горячие клавиши указаны в подсказках при наведении</p>
<p><b>Поля Термин и Определение</b> - Ctrl+Пробел открывает диалог редактирования отсылок<br/>Перед открытием диалога переместите текстовый курсор на заменяемое слово или ссылку</p>
<p><b>Поля Термин и Определение</b> - Ctrl + Пробел открывает диалог редактирования отсылок<br/>Перед открытием диалога переместите текстовый курсор на заменяемое слово или ссылку</p>
<p><b>Список конституент справа</b> - обратите внимание на настройки фильтрации</p>
<p>- слева от ввода текста настраивается набор атрибутов конституенты</p>
<p>- справа от ввода текста настраивается список конституент, которые фильтруются</p>

View File

@ -174,7 +174,7 @@ function DlgEditReference({ hideWindow, items, initialRef, initialText, initialT
const cst = props.row.original;
return (<>
<div
id={`${prefixes.cst_list}${cst.alias}`}
id={`${prefixes.cst_wordform_list}${cst.alias}`}
className='min-w-[3.1rem] max-w-[3.1rem] px-1 text-center rounded-md whitespace-nowrap'
style={{
borderWidth: '1px',
@ -185,7 +185,7 @@ function DlgEditReference({ hideWindow, items, initialRef, initialText, initialT
>
{cst.alias}
</div>
<ConstituentaTooltip data={cst} anchor={`#${prefixes.cst_list}${cst.alias}`} />
<ConstituentaTooltip data={cst} anchor={`#${prefixes.cst_wordform_list}${cst.alias}`} />
</>);
}
}),
@ -217,7 +217,7 @@ function DlgEditReference({ hideWindow, items, initialRef, initialText, initialT
onSubmit={handleSubmit}
>
<div className='min-w-[40rem] flex flex-col gap-4 mb-4 mt-2'>
<div className='flex self-center flex-start'>
<div className='flex items-center self-center flex-start'>
<SelectSingle
className='z-modal-top min-w-[20rem] w-fit'
options={SelectorReferenceType}
@ -231,7 +231,7 @@ function DlgEditReference({ hideWindow, items, initialRef, initialText, initialT
</div>
<ConceptTooltip
anchorSelect='#terminology-help'
className='max-w-[30rem]'
className='max-w-[30rem] z-modal-tooltip'
offset={4}
>
<HelpTerminologyControl />
@ -269,6 +269,8 @@ function DlgEditReference({ hideWindow, items, initialRef, initialText, initialT
data={filteredData}
columns={columnsConstituenta}
conditionalRowStyles={conditionalRowStyles}
headPosition='0'
dense
noDataComponent={
@ -289,15 +291,19 @@ function DlgEditReference({ hideWindow, items, initialRef, initialText, initialT
value={alias}
onChange={event => setAlias(event.target.value)}
/>
<TextInput
label='Термин'
singleRow
disabled
noBorder
value={term}
tooltip={term}
dimensions='w-full'
/>
<div className='flex items-center w-full flex-start'>
<div className='self-center text-sm font-semibold'>
Термин:
</div>
<TextInput
singleRow
disabled
noBorder
value={term}
tooltip={term}
dimensions='w-full text-sm'
/>
</div>
</div>
{FormButtons}
<div className='flex items-center gap-10 flex-start'>

View File

@ -122,6 +122,10 @@
.border {
@apply rounded
}
.shadow-border {
@apply shadow-sm shadow-[var(--cl-bg-40)] dark:shadow-[var(--cd-bg-40)]
}
.clr-modal-backdrop {
opacity: 0.75;

View File

@ -69,7 +69,7 @@ function SearchPanel({ total, filtered, query, setQuery, strategy, setStrategy,
}, [strategy, navigateTo]);
return (
<div className='sticky top-0 left-0 right-0 flex items-center justify-start w-full border-b clr-input'>
<div className='sticky top-0 left-0 right-0 flex items-center justify-start w-full border-b clr-input max-h-[2.3rem]'>
<div className='px-2 py-1 select-none whitespace-nowrap min-w-[10rem]'>
Фильтр
<span className='ml-2'>

View File

@ -96,9 +96,9 @@ function ViewLibrary({ items, resetQuery: cleanQuery }: ViewLibraryProps) {
return (
<div>
{items.length > 0 &&
<div className='relative w-full'>
<div className='sticky top-[2.3rem] w-full'>
<div className='absolute top-[-0.125rem] left-0 flex gap-1 ml-3 z-pop'>
<div id='library-help' className='py-2'>
<div id='library-help' className='py-2 '>
<HelpIcon color='text-primary' size={5} />
</div>
<ConceptTooltip anchorSelect='#library-help'>
@ -112,6 +112,7 @@ function ViewLibrary({ items, resetQuery: cleanQuery }: ViewLibraryProps) {
columns={columns}
data={items}
headPosition='2.3rem'
noDataComponent={
<div className='flex flex-col gap-4 justify-center p-2 text-center min-h-[6rem]'>
<p>Список схем пуст</p>

View File

@ -1,7 +1,6 @@
import { useEffect, useLayoutEffect, useMemo, useState } from 'react';
import ConceptTooltip from '../../components/Common/ConceptTooltip';
import Divider from '../../components/Common/Divider';
import MiniButton from '../../components/Common/MiniButton';
import Modal from '../../components/Common/Modal';
import SelectMulti from '../../components/Common/SelectMulti';
@ -107,9 +106,8 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
setInputGrams(SelectorGrammems.filter(gram => form.grams.find(test => test === gram.value)));
}
function handleResetForm() {
setInputText('');
setInputGrams([]);
function handleResetAll() {
setForms([]);
}
function handleInflect() {
@ -199,12 +197,12 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
maxSize: 50,
cell: props =>
<div>
<MiniButton
tooltip='Удалить словоформу'
icon={<CrossIcon size={4} color='text-warning'/>}
noHover
onClick={() => handleDeleteRow(props.row.index)}
/>
<MiniButton
tooltip='Удалить словоформу'
icon={<CrossIcon size={4} color='text-warning'/>}
noHover
onClick={() => handleDeleteRow(props.row.index)}
/>
</div>
})
], [colors]);
@ -232,7 +230,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
</div>
</div>
<div className='min-w-[40rem]'>
<div className='min-w-[40rem] max-w-[40rem]'>
<TextArea id='nominal' label='Начальная форма'
placeholder='Начальная форма'
rows={1}
@ -242,58 +240,38 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
spellCheck
/>
<Divider margins='my-4'/>
<div className='text-sm mt-4 mb-2 font-semibold'>
Параметры словоформы
</div>
<div className='flex items-start gap-2 justify-stretch min-h-[6.3rem]'>
<div className='flex flex-col gap-1'>
<TextArea
placeholder='Введите текст'
rows={2}
dimensions='min-w-[20rem] min-h-[4.2rem]'
<div className='flex items-start justify-between w-full'>
<TextArea
placeholder='Введите текст'
rows={2}
dimensions='min-w-[18rem] w-full min-h-[4.2rem]'
disabled={textProcessor.loading}
value={inputText}
onChange={event => setInputText(event.target.value)}
value={inputText}
onChange={event => setInputText(event.target.value)}
/>
<div className='max-w-min'>
<MiniButton
tooltip='Генерировать словоформу'
icon={<ArrowLeftIcon
size={6}
color={inputGrams.length == 0 ? 'text-disabled' : 'text-primary'}
/>}
disabled={textProcessor.loading || inputGrams.length == 0}
onClick={handleInflect}
/>
<MiniButton
tooltip='Определить граммемы'
icon={<ArrowRightIcon
size={6}
color={!inputText ? 'text-disabled' : 'text-primary'}
/>}
disabled={textProcessor.loading || !inputText}
onClick={handleParse}
/>
<div className='flex items-center justify-between select-none'>
<div className='flex items-center justify-start'>
<MiniButton
tooltip='Добавить словоформу'
icon={<CheckIcon size={6} color={!inputText || inputGrams.length == 0 ? 'text-disabled' : 'text-success'}/>}
disabled={textProcessor.loading || !inputText || inputGrams.length == 0}
onClick={handleAddForm}
/>
<MiniButton
tooltip='Сбросить словоформу'
icon={<CrossIcon size={6} color='text-warning'/>}
disabled={textProcessor.loading}
onClick={handleResetForm}
/>
<MiniButton
tooltip='Генерировать все словоформы'
icon={<ChevronDoubleDownIcon size={6} color='text-primary'/>}
disabled={textProcessor.loading}
onClick={handleGenerateLexeme}
/>
</div>
<div className='text-sm'>
Словоформ: {forms.length}
</div>
<div className='flex items-center justify-start'>
<MiniButton
tooltip='Генерировать словоформу'
icon={<ArrowLeftIcon size={6} color={inputGrams.length == 0 ? 'text-disabled' : 'text-primary'}/>}
disabled={textProcessor.loading || inputGrams.length == 0}
onClick={handleInflect}
/>
<MiniButton
tooltip='Определить граммемы'
icon={<ArrowRightIcon size={6} color={!inputText ? 'text-disabled' : 'text-primary'}/>}
disabled={textProcessor.loading || !inputText}
onClick={handleParse}
/>
</div>
</div>
</div>
<SelectMulti
className='z-modal-top min-w-[20rem] max-w-[20rem] h-full flex-grow'
@ -301,25 +279,58 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
placeholder='Выберите граммемы'
value={inputGrams}
isDisabled={textProcessor.loading}
onChange={newValue => setInputGrams([...newValue].sort(compareGrammemeOptions))}
/>
</div>
<div className='flex flex-start justify-between'>
<div className='flex items-center justify-start'>
<MiniButton
tooltip='Внести словоформу'
icon={<CheckIcon
size={6}
color={!inputText || inputGrams.length == 0 ? 'text-disabled' : 'text-success'}
/>}
disabled={textProcessor.loading || !inputText || inputGrams.length == 0}
onClick={handleAddForm}
/>
<MiniButton
tooltip='Генерировать все словоформы'
icon={<ChevronDoubleDownIcon
size={6}
color={!inputText ? 'text-disabled' : 'text-primary'}
/>}
disabled={textProcessor.loading || !inputText}
onClick={handleGenerateLexeme}
/>
</div>
<div className='text-sm mt-2 mb-1 font-semibold w-full text-center'>
Заданные вручную словоформы: [{forms.length}]
</div>
<MiniButton
tooltip='Сбросить ВСЕ словоформы'
icon={<CrossIcon
size={6}
color={forms.length === 0 ? 'text-disabled' : 'text-warning'}
/>}
disabled={textProcessor.loading || forms.length === 0}
onClick={handleResetAll}
/>
</div>
<div className='border overflow-y-auto max-h-[17.4rem] min-h-[17.4rem]'>
<div className='border overflow-y-auto max-h-[17.4rem] min-h-[17.4rem] mb-2'>
<DataTable
data={forms}
columns={columns}
headPosition='0'
dense
noDataComponent={
<span className='flex flex-col justify-center p-2 text-center min-h-[2rem]'>
<p>Список пуст</p>
<p>Добавьте словоформу</p>
</span>
}
onRowDoubleClicked={handleRowClicked}
onRowClicked={handleRowClicked}
/>
</div>
</div>

View File

@ -361,7 +361,8 @@ function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps)
<div className='w-full h-full text-sm'>
<DataTable
data={schema?.items ?? []}
columns={columns}
columns={columns}
headPosition='2.2rem'
dense
onRowDoubleClicked={handleRowDoubleClicked}

View File

@ -209,6 +209,7 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
data={filteredData}
columns={columns}
conditionalRowStyles={conditionalRowStyles}
headPosition='0'
dense
enableHiding

View File

@ -47,12 +47,13 @@ function ViewSubscriptions({items}: ViewSubscriptionsProps) {
], [intl]);
return (
<div className='h-full overflow-auto text-sm border w-fit'>
<div className='max-h-[23.8rem] overflow-auto text-sm border w-fit'>
<DataTable
columns={columns}
data={items}
headPosition='0'
dense
enableSorting
initialSorting={{
id: 'time_update',

View File

@ -210,7 +210,7 @@ export function domTooltipSyntacticReference(ref: ISyntacticReference, masterRef
dom.className = `${DIMENSIONS} ${LAYOUT} border shadow-md text-sm select-none cursor-auto`;
const title = document.createElement('p');
title.innerHTML = '<b>Синтаксическая ссылка</b>';
title.innerHTML = '<b>Связывание слов</b>';
dom.appendChild(title);
const offset = document.createElement('p');

View File

@ -34,6 +34,7 @@ export const globalIDs = {
export const prefixes = {
cst_list: 'cst-list-',
cst_wordform_list: 'cst-wordform-list-',
cst_status_list: 'cst-status-list-',
topic_list: 'topic-list-',
library_list: 'library-list-',

View File

@ -239,7 +239,7 @@ export function labelCstType(type: CstType): string {
export function labelReferenceType(type: ReferenceType): string {
switch(type) {
case ReferenceType.ENTITY: return 'Использование термина';
case ReferenceType.SYNTACTIC: return 'Синтаксическая зависимость';
case ReferenceType.SYNTACTIC: return 'Связывание слов';
}
}