Improve dynamic sizes in ConstituentaEdit

This commit is contained in:
IRBorisov 2023-08-13 13:18:50 +03:00
parent 27f515f5d3
commit e9eed37aee
5 changed files with 129 additions and 101 deletions

View File

@ -1,9 +1,18 @@
import { ThreeDots } from 'react-loader-spinner';
export function Loader() {
interface LoaderProps {
size?: number
}
export function Loader({size=10}: LoaderProps) {
return (
<div className='flex justify-center w-full h-full'>
<ThreeDots color='rgb(96 165 250)' height='100' width='100' radius='10' />
<ThreeDots
color='rgb(96 165 250)'
height={size*10}
width={size*10}
radius={size}
/>
</div>
);
}

View File

@ -13,6 +13,9 @@ import { getCstTypeLabel, getCstTypificationLabel, mapStatusInfo } from '../../u
import EditorRSExpression from './EditorRSExpression';
import ViewSideConstituents from './elements/ViewSideConstituents';
// Max height of content for left enditor pane
const UNFOLDED_HEIGHT = '59.1rem';
interface EditorConstituentaProps {
activeID?: number
onOpenEdit: (cstID: number) => void
@ -109,8 +112,8 @@ function EditorConstituenta({ activeID, onShowAST, onCreateCst, onOpenEdit, onDe
}
return (
<div className='flex items-stretch w-full gap-2 mb-2'>
<form onSubmit={handleSubmit} className='flex-grow min-w-[50rem] max-w-min max-h-fit px-4 py-2 border'>
<div className='flex items-stretch w-full gap-2 mb-2 justify-stretch'>
<form onSubmit={handleSubmit} className='min-w-[50rem] max-w-min px-4 py-2 border'>
<div className='flex items-start justify-between'>
<button type='submit'
title='Сохранить изменения'
@ -238,11 +241,14 @@ function EditorConstituenta({ activeID, onShowAST, onCreateCst, onOpenEdit, onDe
/>
</div>
</form>
<ViewSideConstituents
expression={expression}
activeID={activeID}
onOpenEdit={onOpenEdit}
/>
<div className='self-stretch border w-full pb-1'>
<ViewSideConstituents
expression={expression}
baseHeight={UNFOLDED_HEIGHT}
activeID={activeID}
onOpenEdit={onOpenEdit}
/>
</div>
</div>
);
}

View File

@ -247,9 +247,9 @@ function EditorRSExpression({
</div>
{isActive && !disabled && EditButtons}
</div>
{ (loading || parseData) &&
<div className='w-full overflow-y-auto border mt-2 max-h-[14rem] min-h-[7rem]'>
{ loading && <Loader />}
{ (isActive || loading || parseData) &&
<div className='w-full overflow-y-auto border mt-2 max-h-[14rem] min-h-[4.2rem]'>
{ loading && <Loader size={6} />}
{ !loading && parseData &&
<ParsingResult
data={parseData}

View File

@ -33,9 +33,8 @@ function ParsingResult({ data, onShowAST, onShowError }: ParsingResultProps) {
title='отобразить дерево разбора'
onClick={handleShowAST}
>
Дерево разбора:
Дерево разбора
</button>
<span> {data.astText}</span>
</p>}
</div>
)

View File

@ -11,14 +11,18 @@ import ConstituentaTooltip from './ConstituentaTooltip';
import DependencyModePicker from './DependencyModePicker';
import MatchModePicker from './MatchModePicker';
// Height that should be left to accomodate navigation panel + bottom margin
const LOCAL_NAVIGATION_H = '2.6rem';
interface ViewSideConstituentsProps {
expression: string
baseHeight: string
activeID?: number
onOpenEdit: (cstID: number) => void
}
function ViewSideConstituents({ expression, activeID, onOpenEdit }: ViewSideConstituentsProps) {
const { darkMode } = useConceptTheme();
function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }: ViewSideConstituentsProps) {
const { darkMode, noNavigation } = useConceptTheme();
const { schema } = useRSForm();
const [filterMatch, setFilterMatch] = useLocalStorage('side-filter-match', CstMatchMode.ALL);
@ -27,7 +31,8 @@ function ViewSideConstituents({ expression, activeID, onOpenEdit }: ViewSideCons
const [filteredData, setFilteredData] = useState<IConstituenta[]>(schema?.items ?? []);
useEffect(() => {
useEffect(
() => {
if (!schema?.items) {
setFilteredData([]);
return;
@ -67,8 +72,8 @@ function ViewSideConstituents({ expression, activeID, onOpenEdit }: ViewSideCons
}
}, [onOpenEdit]);
const conditionalRowStyles = useMemo(() =>
[
const conditionalRowStyles = useMemo(
() => [
{
when: (cst: IConstituenta) => cst.id === activeID,
style: {
@ -77,92 +82,101 @@ function ViewSideConstituents({ expression, activeID, onOpenEdit }: ViewSideCons
}
], [activeID, darkMode]);
const columns = useMemo(() =>
[
{
id: 'id',
selector: (cst: IConstituenta) => cst.id,
omit: true
const columns = useMemo(
() => [
{
id: 'id',
selector: (cst: IConstituenta) => cst.id,
omit: true
},
{
name: 'ID',
id: 'alias',
cell: (cst: IConstituenta) => {
const info = mapStatusInfo.get(cst.status)!;
return (<>
<div
id={`${prefixes.cst_list}${cst.alias}`}
className={`w-full rounded-md text-center ${info.color}`}
>
{cst.alias}
</div>
<ConstituentaTooltip data={cst} anchor={`#${prefixes.cst_list}${cst.alias}`} />
</>);
},
{
name: 'ID',
id: 'alias',
cell: (cst: IConstituenta) => {
const info = mapStatusInfo.get(cst.status)!;
return (<>
<div
id={`${prefixes.cst_list}${cst.alias}`}
className={`w-full rounded-md text-center ${info.color}`}
>
{cst.alias}
</div>
<ConstituentaTooltip data={cst} anchor={`#${prefixes.cst_list}${cst.alias}`} />
</>);
},
width: '65px',
maxWidth: '65px',
conditionalCellStyles: [
{
when: (cst: IConstituenta) => cst.id <= 0,
classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]']
}
]
},
{
name: 'Описание',
id: 'description',
selector: (cst: IConstituenta) => getCstDescription(cst),
minWidth: '350px',
wrap: true,
conditionalCellStyles: [
{
when: (cst: IConstituenta) => cst.id <= 0,
classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]']
}
]
},
{
name: 'Выражение',
id: 'expression',
selector: (cst: IConstituenta) => cst.definition?.formal ?? '',
minWidth: '200px',
hide: 1600,
grow: 2,
wrap: true,
conditionalCellStyles: [
{
when: (cst: IConstituenta) => cst.id <= 0,
classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]']
}
]
}
], []
);
width: '65px',
maxWidth: '65px',
conditionalCellStyles: [
{
when: (cst: IConstituenta) => cst.id <= 0,
classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]']
}
]
},
{
name: 'Описание',
id: 'description',
selector: (cst: IConstituenta) => getCstDescription(cst),
minWidth: '350px',
wrap: true,
conditionalCellStyles: [
{
when: (cst: IConstituenta) => cst.id <= 0,
classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]']
}
]
},
{
name: 'Выражение',
id: 'expression',
selector: (cst: IConstituenta) => cst.definition?.formal ?? '',
minWidth: '200px',
hide: 1600,
grow: 2,
wrap: true,
conditionalCellStyles: [
{
when: (cst: IConstituenta) => cst.id <= 0,
classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]']
}
]
}
], []);
return (
<div className='max-h-[calc(100vh-10.3rem)] min-h-[40rem] overflow-y-scroll border flex-grow w-full'>
<div className='sticky top-0 left-0 right-0 z-10 flex items-center justify-between w-full gap-1 px-2 py-1 bg-white border-b rounded clr-bg-pop clr-border'>
<div className='flex items-center justify-between w-full'>
<MatchModePicker value={filterMatch} onChange={setFilterMatch}/>
<input type='text'
className='w-full px-2 bg-white outline-none hover:text-clip clr-bg-pop clr-border'
placeholder='наберите текст фильтра'
value={filterText}
onChange={event => { setFilterText(event.target.value); }}
/>
<DependencyModePicker value={filterSource} onChange={setFilterSource}/>
</div>
</div>
const maxHeight = useMemo(
() => {
const siblingHeight = `${baseHeight} - ${LOCAL_NAVIGATION_H}`
return (noNavigation ?
`calc(min(100vh - 5.2rem, ${siblingHeight}))`
: `calc(min(100vh - 8.7rem, ${siblingHeight}))`);
}, [noNavigation, baseHeight]);
return (<>
<div className='px-2 py-1 sticky top-0 left-0 right-0 z-10 gap-1 flex items-center justify-between w-full bg-white border-b rounded clr-bg-pop clr-border'>
<MatchModePicker
value={filterMatch}
onChange={setFilterMatch}
/>
<input type='text'
className='w-full px-2 bg-white outline-none hover:text-clip clr-bg-pop clr-border'
placeholder='наберите текст фильтра'
value={filterText}
onChange={event => setFilterText(event.target.value)}
/>
<DependencyModePicker value={filterSource} onChange={setFilterSource}/>
</div>
<div className='overflow-y-auto' style={{maxHeight : `${maxHeight}`}}>
<ConceptDataTable
data={filteredData}
columns={columns}
conditionalRowStyles={conditionalRowStyles}
keyField='id'
noContextMenu
noDataComponent={<span className='flex flex-col justify-center p-2 text-center'>
<p>Список конституент пуст</p>
<p>Измените параметры фильтра</p>
</span>}
conditionalRowStyles={conditionalRowStyles}
noDataComponent={
<span className='flex flex-col justify-center p-2 text-center min-h-[5rem]'>
<p>Список конституент пуст</p>
<p>Измените параметры фильтра</p>
</span>
}
striped
highlightOnHover
@ -173,7 +187,7 @@ function ViewSideConstituents({ expression, activeID, onOpenEdit }: ViewSideCons
dense
/>
</div>
);
</>);
}
export default ViewSideConstituents;