M: Improve stats labels
Some checks are pending
Frontend CI / build (22.x) (push) Waiting to run

This commit is contained in:
Ivan 2024-08-23 12:35:48 +03:00
parent 3381aaa0db
commit 4eebcaef53
11 changed files with 106 additions and 72 deletions

View File

@ -69,9 +69,12 @@ export { IoLibrary as IconLibrary2 } from 'react-icons/io5';
export { BiDiamond as IconTemplates } from 'react-icons/bi';
export { TbHexagons as IconOSS } from 'react-icons/tb';
export { TbHexagon as IconRSForm } from 'react-icons/tb';
export { TbTopologyRing as IconConsolidation } from 'react-icons/tb';
export { LuNewspaper as IconDefinition } from 'react-icons/lu';
export { LuDna as IconTerminology } from 'react-icons/lu';
export { FaRegHandshake as IconConvention } from 'react-icons/fa6';
export { LiaCloneSolid as IconChild } from 'react-icons/lia';
export { RiParentLine as IconParent } from 'react-icons/ri';
export { TbTopologyRing as IconConsolidation } from 'react-icons/tb';
export { BiSpa as IconPredecessor } from 'react-icons/bi';
export { LuArchive as IconArchive } from 'react-icons/lu';
export { LuDatabase as IconDatabase } from 'react-icons/lu';

View File

@ -1,35 +1,47 @@
import clsx from 'clsx';
import { useMemo } from 'react';
import { globals } from '@/utils/constants';
import { CProps } from '../props';
import MiniButton from './MiniButton';
interface IconValueProps extends CProps.Styling, CProps.Titled {
interface ValueIconProps extends CProps.Styling, CProps.Titled {
id?: string;
icon: React.ReactNode;
value: string | number;
textClassName?: string;
onClick?: (event: CProps.EventMouse) => void;
smallThreshold?: number;
dense?: boolean;
disabled?: boolean;
}
function IconValue({
function ValueIcon({
id,
dense,
value,
icon,
value,
textClassName,
disabled = true,
title,
titleHtml,
hideTitle,
className,
smallThreshold,
onClick,
...restProps
}: IconValueProps) {
}: ValueIconProps) {
const isSmall = useMemo(() => !smallThreshold || String(value).length < smallThreshold, [value, smallThreshold]);
return (
<div
className={clsx('flex items-center text-right', { 'justify-between gap-6': !dense, 'gap-1': dense }, className)}
className={clsx(
'flex items-center',
'text-right',
'hover:cursor-default',
{ 'justify-between gap-6': !dense, 'gap-1': dense },
className
)}
{...restProps}
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
data-tooltip-html={titleHtml}
@ -37,11 +49,11 @@ function IconValue({
data-tooltip-hidden={hideTitle}
>
<MiniButton noHover noPadding icon={icon} disabled={disabled} onClick={onClick} />
<span id={id} className='min-w-[1.2rem]'>
<span id={id} className={clsx({ 'text-xs': !isSmall }, textClassName)}>
{value}
</span>
</div>
);
}
export default IconValue;
export default ValueIcon;

View File

@ -2,14 +2,14 @@ import clsx from 'clsx';
import { CProps } from '../props';
interface LabeledValueProps extends CProps.Styling {
interface ValueLabeledProps extends CProps.Styling {
id?: string;
label: string;
text: string | number;
title?: string;
}
function LabeledValue({ id, label, text, title, className, ...restProps }: LabeledValueProps) {
function ValueLabeled({ id, label, text, title, className, ...restProps }: ValueLabeledProps) {
return (
<div className={clsx('flex justify-between gap-6', className)} {...restProps}>
<span title={title}>{label}</span>
@ -18,4 +18,4 @@ function LabeledValue({ id, label, text, title, className, ...restProps }: Label
);
}
export default LabeledValue;
export default ValueLabeled;

View File

@ -0,0 +1,16 @@
import { PARAMETER } from '@/utils/constants';
import { CProps } from '../props';
import ValueIcon from './ValueIcon';
interface ValueStatsProps extends CProps.Styling, CProps.Titled {
id: string;
icon: React.ReactNode;
value: string | number;
}
function ValueStats(props: ValueStatsProps) {
return <ValueIcon dense smallThreshold={PARAMETER.statSmallThreshold} textClassName='min-w-[1.4rem]' {...props} />;
}
export default ValueStats;

View File

@ -1,5 +1,5 @@
import Divider from '@/components/ui/Divider';
import LabeledValue from '@/components/ui/LabeledValue';
import ValueLabeled from '@/components/ui/ValueLabeled';
import { IOperationSchemaStats } from '@/models/oss';
interface OssStatsProps {
@ -14,13 +14,13 @@ function OssStats({ stats }: OssStatsProps) {
<div className='flex flex-col sm:gap-1 sm:ml-6 sm:mt-8 sm:w-[16rem]'>
<Divider margins='my-2' className='sm:hidden' />
<LabeledValue id='count_all' label='Всего операций' text={stats.count_operations} />
<LabeledValue id='count_inputs' label='Загрузка' text={stats.count_inputs} />
<LabeledValue id='count_synthesis' label='Синтез' text={stats.count_synthesis} />
<ValueLabeled id='count_all' label='Всего операций' text={stats.count_operations} />
<ValueLabeled id='count_inputs' label='Загрузка' text={stats.count_inputs} />
<ValueLabeled id='count_synthesis' label='Синтез' text={stats.count_synthesis} />
<Divider margins='my-2' />
<LabeledValue id='count_schemas' label='Прикрепленные схемы' text={stats.count_schemas} />
<ValueLabeled id='count_schemas' label='Прикрепленные схемы' text={stats.count_schemas} />
</div>
);
}

View File

@ -79,7 +79,7 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
}
return (
<div className='overflow-y-auto' style={{ maxHeight: panelHeight }}>
<div className='overflow-y-auto min-h-[20rem]' style={{ maxHeight: panelHeight }}>
<ToolbarConstituenta
activeCst={activeCst}
disabled={disabled}

View File

@ -80,7 +80,7 @@ function ToolbarConstituenta({
<MiniButton
title='Создать конституенту после данной'
icon={<IconNewItem size={'1.25rem'} className='icon-green' />}
disabled={disabled}
disabled={!controller.isContentEditable || controller.isProcessing}
onClick={() => controller.createCst(activeCst?.cst_type, false)}
/>
<MiniButton

View File

@ -4,7 +4,7 @@ import { useIntl } from 'react-intl';
import { IconDateCreate, IconDateUpdate, IconEditor, IconFolder, IconOwner } from '@/components/Icons';
import InfoUsers from '@/components/info/InfoUsers';
import SelectUser from '@/components/select/SelectUser';
import IconValue from '@/components/ui/IconValue';
import ValueIcon from '@/components/ui/ValueIcon';
import Overlay from '@/components/ui/Overlay';
import Tooltip from '@/components/ui/Tooltip';
import { useAccessMode } from '@/context/AccessModeContext';
@ -47,7 +47,7 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
return (
<div className='flex flex-col'>
<IconValue
<ValueIcon
className='sm:mb-1 text-ellipsis max-w-[30rem]'
icon={<IconFolder size='1.25rem' className='icon-primary' />}
value={item.location}
@ -68,7 +68,7 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
) : null}
</Overlay>
) : null}
<IconValue
<ValueIcon
className='sm:mb-1'
icon={<IconOwner size='1.25rem' className='icon-primary' />}
value={getUserLabel(item.owner)}
@ -78,7 +78,7 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
/>
<div className='sm:mb-1 flex justify-between items-center'>
<IconValue
<ValueIcon
id='editor_stats'
dense
icon={<IconEditor size='1.25rem' className='icon-primary' />}
@ -90,7 +90,7 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
<InfoUsers items={item?.editors ?? []} prefix={prefixes.user_editors} />
</Tooltip>
<IconValue
<ValueIcon
dense
disabled
icon={<IconDateUpdate size='1.25rem' className='clr-text-green' />}
@ -98,7 +98,7 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
title='Дата обновления'
/>
<IconValue
<ValueIcon
dense
disabled
icon={<IconDateCreate size='1.25rem' className='clr-text-green' />}

View File

@ -49,7 +49,7 @@ function EditorRSFormCard({ isModified, onDestroy, setIsModified }: EditorRSForm
/>
<AnimateFade
onKeyDown={handleInput}
className={clsx('sm:w-fit sm:max-w-fit max-w-[32rem]', 'mx-auto ', 'flex flex-col sm:flex-row px-6')}
className={clsx('md:w-fit md:max-w-fit max-w-[32rem]', 'mx-auto ', 'flex flex-col md:flex-row px-6')}
>
<FlexColumn className='flex-shrink'>
<FormRSForm id={globals.library_item_editor} isModified={isModified} setIsModified={setIsModified} />

View File

@ -1,13 +1,15 @@
import {
IconChild,
IconConvention,
IconDefinition,
IconPredecessor,
IconStatusError,
IconStatusIncalculable,
IconStatusOK,
IconStatusProperty
IconStatusProperty,
IconTerminology
} from '@/components/Icons';
import IconValue from '@/components/ui/IconValue';
import LabeledValue from '@/components/ui/LabeledValue';
import ValueStats from '@/components/ui/ValueStats';
import { type IRSFormStats } from '@/models/rsform';
interface RSFormStatsProps {
@ -19,120 +21,119 @@ function RSFormStats({ stats }: RSFormStatsProps) {
return null;
}
return (
<div className='flex flex-col mt-3 sm:gap-1 sm:ml-6 sm:mt-8 sm:w-[16rem]'>
<div className='grid grid-cols-4 gap-1 mb-3 justify-items-start sm:justify-items-end'>
<div className='col-span-2 text-left w-full flex gap-3 sm:pl-3'>
<div className='flex flex-col mt-3 md:gap-1 md:ml-6 md:mt-8 md:w-[18rem] w-[25rem]'>
<div className='grid grid-cols-4 gap-1 mb-3 justify-items-end'>
<div className='col-span-2 w-fit flex gap-3'>
<span>Всего</span>
<span>{stats.count_all}</span>
</div>
<IconValue
<ValueStats
id='count_owned'
dense
icon={<IconPredecessor size='1.25rem' className='clr-text-primary' />}
value={stats.count_all - stats.count_inherited}
title='Собственные'
/>
<IconValue
<ValueStats
id='count_inherited'
dense
icon={<IconChild size='1.25rem' className='clr-text-primary' />}
value={stats.count_inherited}
title='Наследованные'
/>
<IconValue
<ValueStats
className='col-start-1'
id='count_ok'
dense
icon={<IconStatusOK size='1.25rem' className='clr-text-green' />}
value={stats.count_all - stats.count_errors - stats.count_property - stats.count_incalculable}
title='Корректные'
/>
<IconValue
<ValueStats
id='count_property'
dense
icon={<IconStatusProperty size='1.25rem' className='clr-text-primary' />}
value={stats.count_errors}
title='Неразмерные'
/>
<IconValue
<ValueStats
id='count_incalculable'
dense
icon={<IconStatusIncalculable size='1.25rem' className='clr-text-red' />}
value={stats.count_incalculable}
title='Невычислимые'
/>
<IconValue
<ValueStats
id='count_errors'
dense
icon={<IconStatusError size='1.25rem' className='clr-text-red' />}
value={stats.count_errors}
title='Некорректные'
/>
<IconValue
<ValueStats
id='count_base'
dense
icon={<span className='font-math clr-text-default'>X#</span>}
icon={<span className='font-math clr-text-default md:pr-1 pl-1 md:pl-0'>X</span>}
value={stats.count_base}
title='Базисные множества'
/>
<IconValue
<ValueStats
id='count_constant'
dense
icon={<span className='font-math clr-text-default'>C#</span>}
icon={<span className='font-math clr-text-default md:pr-1 pl-1 md:pl-0'>C</span>}
value={stats.count_constant}
title='Константные множества'
/>
<IconValue
<ValueStats
id='count_structured'
dense
icon={<span className='font-math clr-text-default'>S#</span>}
icon={<span className='font-math clr-text-default md:pr-1 pl-1 md:pl-0'>S</span>}
value={stats.count_structured}
title='Родовые структуры'
/>
<IconValue
<ValueStats
id='count_axiom'
dense
icon={<span className='font-math clr-text-default'>A#</span>}
icon={<span className='font-math clr-text-default md:pr-1 pl-1 md:pl-0'>A</span>}
value={stats.count_axiom}
title='Аксиомы'
/>
<IconValue
<ValueStats
id='count_term'
dense
icon={<span className='font-math clr-text-default'>D#</span>}
icon={<span className='font-math clr-text-default md:pr-1 pl-1 md:pl-0'>D</span>}
value={stats.count_term}
title='Термы'
/>
<IconValue
<ValueStats
id='count_function'
dense
icon={<span className='font-math clr-text-default'>F#</span>}
icon={<span className='font-math clr-text-default md:pr-1 pl-1 md:pl-0'>F</span>}
value={stats.count_function}
title='Терм-функции'
/>
<IconValue
<ValueStats
id='count_predicate'
dense
icon={<span className='font-math clr-text-default'>P#</span>}
icon={<span className='font-math clr-text-default md:pr-1 pl-1 md:pl-0'>P</span>}
value={stats.count_predicate}
title='Предикат-функции'
/>
<IconValue
<ValueStats
id='count_theorem'
dense
icon={<span className='font-math clr-text-default'>T#</span>}
icon={<span className='font-math clr-text-default md:pr-1 pl-1 md:pl-0'>T</span>}
value={stats.count_theorem}
title='Теоремы'
/>
</div>
<div className='sm:pl-3 max-w-[10rem] sm:max-w-[12rem]'>
<LabeledValue id='count_text_term' label='Термины' text={stats.count_text_term} />
<LabeledValue id='count_definition' label='Определения' text={stats.count_definition} />
<LabeledValue id='count_convention' label='Конвенции' text={stats.count_convention} />
<ValueStats
id='count_text_term'
icon={<IconTerminology size='1.25rem' className='clr-text-primary' />}
value={stats.count_text_term}
title='Термины'
/>
<ValueStats
id='count_definition'
icon={<IconDefinition size='1.25rem' className='clr-text-primary' />}
value={stats.count_definition}
title='Определения'
/>
<ValueStats
id='count_convention'
icon={<IconConvention size='1.25rem' className='clr-text-primary' />}
value={stats.count_convention}
title='Конвенции'
/>
</div>
</div>
);

View File

@ -30,6 +30,8 @@ export const PARAMETER = {
ossLongLabel: 14, // characters - threshold for long labels - small font
ossTruncateLabel: 28, // characters - threshold for long labels - truncate
statSmallThreshold: 3, // characters - threshold for small labels - small font
logicLabel: 'LOGIC',
exteorVersion: '4.9.3',