mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
F: Add hide button for stats
This commit is contained in:
parent
dae47716ea
commit
2d2c0290e3
|
@ -25,6 +25,10 @@ export { LuQrCode as IconQR } from 'react-icons/lu';
|
||||||
export { LuFilterX as IconFilterReset } from 'react-icons/lu';
|
export { LuFilterX as IconFilterReset } from 'react-icons/lu';
|
||||||
export {BiDownArrowCircle as IconOpenList } from 'react-icons/bi';
|
export {BiDownArrowCircle as IconOpenList } from 'react-icons/bi';
|
||||||
export { LuTriangleAlert as IconAlert } from 'react-icons/lu';
|
export { LuTriangleAlert as IconAlert } from 'react-icons/lu';
|
||||||
|
export { LuPanelLeftOpen as IconLeftOpen } from 'react-icons/lu';
|
||||||
|
export { LuPanelLeftClose as IconLeftClose } from 'react-icons/lu';
|
||||||
|
export { LuPanelBottomOpen as IconBottomOpen } from 'react-icons/lu';
|
||||||
|
export { LuPanelBottomClose as IconBottomClose } from 'react-icons/lu';
|
||||||
|
|
||||||
// ===== UI elements =======
|
// ===== UI elements =======
|
||||||
export { BiX as IconClose } from 'react-icons/bi';
|
export { BiX as IconClose } from 'react-icons/bi';
|
||||||
|
@ -97,9 +101,7 @@ export { LuDatabase as IconDatabase } from 'react-icons/lu';
|
||||||
export { LuView as IconDBStructure } from 'react-icons/lu';
|
export { LuView as IconDBStructure } from 'react-icons/lu';
|
||||||
export { LuPlaneTakeoff as IconRESTapi } from 'react-icons/lu';
|
export { LuPlaneTakeoff as IconRESTapi } from 'react-icons/lu';
|
||||||
export { LuImage as IconImage } from 'react-icons/lu';
|
export { LuImage as IconImage } from 'react-icons/lu';
|
||||||
export { TbColumns as IconList } from 'react-icons/tb';
|
|
||||||
export { GoVersions as IconVersions } from 'react-icons/go';
|
export { GoVersions as IconVersions } from 'react-icons/go';
|
||||||
export { TbColumnsOff as IconListOff } from 'react-icons/tb';
|
|
||||||
export { LuAtSign as IconTerm } from 'react-icons/lu';
|
export { LuAtSign as IconTerm } from 'react-icons/lu';
|
||||||
export { LuSubscript as IconAlias } from 'react-icons/lu';
|
export { LuSubscript as IconAlias } from 'react-icons/lu';
|
||||||
export { TbMathFunction as IconFormula } from 'react-icons/tb';
|
export { TbMathFunction as IconFormula } from 'react-icons/tb';
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import {
|
import {
|
||||||
IconClone,
|
|
||||||
IconDestroy,
|
IconDestroy,
|
||||||
IconDownload,
|
|
||||||
IconEditor,
|
IconEditor,
|
||||||
IconImmutable,
|
IconImmutable,
|
||||||
|
IconLeftOpen,
|
||||||
IconOSS,
|
IconOSS,
|
||||||
IconOwner,
|
IconOwner,
|
||||||
IconPublic,
|
IconPublic,
|
||||||
|
@ -49,15 +48,12 @@ export function HelpRSCard() {
|
||||||
<li>
|
<li>
|
||||||
<IconImmutable className='inline-icon' /> Неизменные схемы
|
<IconImmutable className='inline-icon' /> Неизменные схемы
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<IconClone className='inline-icon icon-green' /> Клонировать – создать копию схемы
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<IconDownload className='inline-icon' /> Загрузить/Выгрузить – взаимодействие с Экстеор
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<IconDestroy className='inline-icon icon-red' /> Удалить – полностью удаляет схему из базы Портала
|
<IconDestroy className='inline-icon icon-red' /> Удалить – полностью удаляет схему из базы Портала
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<IconLeftOpen className='inline-icon' /> Отображение статистики
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
IconEdit,
|
IconEdit,
|
||||||
IconFilter,
|
IconFilter,
|
||||||
IconKeyboard,
|
IconKeyboard,
|
||||||
IconList,
|
IconLeftOpen,
|
||||||
IconMoveDown,
|
IconMoveDown,
|
||||||
IconMoveUp,
|
IconMoveUp,
|
||||||
IconNewItem,
|
IconNewItem,
|
||||||
|
@ -37,7 +37,7 @@ export function HelpRSEditor() {
|
||||||
<IconPredecessor className='inline-icon' /> переход к исходной
|
<IconPredecessor className='inline-icon' /> переход к исходной
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconList className='inline-icon' /> список конституент
|
<IconLeftOpen className='inline-icon' /> список конституент
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconSave className='inline-icon' /> сохранить: <kbd>Ctrl + S</kbd>
|
<IconSave className='inline-icon' /> сохранить: <kbd>Ctrl + S</kbd>
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { type DomIconProps, IconBottomClose, IconBottomOpen, IconLeftClose, IconLeftOpen } from '@/components/icons';
|
||||||
|
|
||||||
|
/** Icon for sidebar visibility. */
|
||||||
|
export function IconShowSidebar({
|
||||||
|
value,
|
||||||
|
size = '1.25rem',
|
||||||
|
className,
|
||||||
|
isBottom
|
||||||
|
}: DomIconProps<boolean> & { isBottom: boolean }) {
|
||||||
|
if (isBottom) {
|
||||||
|
if (value) {
|
||||||
|
return <IconBottomClose size={size} className={className ?? 'icon-primary'} />;
|
||||||
|
} else {
|
||||||
|
return <IconBottomOpen size={size} className={className ?? 'icon-primary'} />;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (value) {
|
||||||
|
return <IconLeftClose size={size} className={className ?? 'icon-primary'} />;
|
||||||
|
} else {
|
||||||
|
return <IconLeftOpen size={size} className={className ?? 'icon-primary'} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,29 +10,46 @@ import { MiniButton } from '@/components/control';
|
||||||
import { IconDestroy, IconSave, IconShare } from '@/components/icons';
|
import { IconDestroy, IconSave, IconShare } from '@/components/icons';
|
||||||
import { cn } from '@/components/utils';
|
import { cn } from '@/components/utils';
|
||||||
import { useModificationStore } from '@/stores/modification';
|
import { useModificationStore } from '@/stores/modification';
|
||||||
|
import { usePreferencesStore } from '@/stores/preferences';
|
||||||
import { tooltipText } from '@/utils/labels';
|
import { tooltipText } from '@/utils/labels';
|
||||||
import { prepareTooltip, sharePage } from '@/utils/utils';
|
import { prepareTooltip, sharePage } from '@/utils/utils';
|
||||||
|
|
||||||
import { AccessPolicy, type ILibraryItem, LibraryItemType } from '../backend/types';
|
import { AccessPolicy, type ILibraryItem, LibraryItemType } from '../backend/types';
|
||||||
import { useMutatingLibrary } from '../backend/use-mutating-library';
|
import { useMutatingLibrary } from '../backend/use-mutating-library';
|
||||||
|
|
||||||
|
import { IconShowSidebar } from './icon-show-sidebar';
|
||||||
import { MiniSelectorOSS } from './mini-selector-oss';
|
import { MiniSelectorOSS } from './mini-selector-oss';
|
||||||
|
|
||||||
interface ToolbarItemCardProps {
|
interface ToolbarItemCardProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
isNarrow: boolean;
|
||||||
onSubmit: () => void;
|
onSubmit: () => void;
|
||||||
isMutable: boolean;
|
isMutable: boolean;
|
||||||
schema: ILibraryItem;
|
schema: ILibraryItem;
|
||||||
deleteSchema: () => void;
|
deleteSchema: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ToolbarItemCard({ className, schema, onSubmit, isMutable, deleteSchema }: ToolbarItemCardProps) {
|
export function ToolbarItemCard({
|
||||||
|
className,
|
||||||
|
isNarrow,
|
||||||
|
schema,
|
||||||
|
onSubmit,
|
||||||
|
isMutable,
|
||||||
|
deleteSchema
|
||||||
|
}: ToolbarItemCardProps) {
|
||||||
const role = useRoleStore(state => state.role);
|
const role = useRoleStore(state => state.role);
|
||||||
const router = useConceptNavigation();
|
const router = useConceptNavigation();
|
||||||
const { isModified } = useModificationStore();
|
const { isModified } = useModificationStore();
|
||||||
const isProcessing = useMutatingLibrary();
|
const isProcessing = useMutatingLibrary();
|
||||||
const canSave = isModified && !isProcessing;
|
const canSave = isModified && !isProcessing;
|
||||||
|
|
||||||
|
const showRSFormStats = usePreferencesStore(state => state.showRSFormStats);
|
||||||
|
const toggleShowRSFormStats = usePreferencesStore(state => state.toggleShowRSFormStats);
|
||||||
|
const showOSSStats = usePreferencesStore(state => state.showOSSStats);
|
||||||
|
const toggleShowOSSStats = usePreferencesStore(state => state.toggleShowOSSStats);
|
||||||
|
const isRSForm = schema.item_type === LibraryItemType.RSFORM;
|
||||||
|
const isOSS = schema.item_type === LibraryItemType.OSS;
|
||||||
|
|
||||||
const ossSelector = (() => {
|
const ossSelector = (() => {
|
||||||
if (schema.item_type !== LibraryItemType.RSFORM) {
|
if (schema.item_type !== LibraryItemType.RSFORM) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -76,6 +93,15 @@ export function ToolbarItemCard({ className, schema, onSubmit, isMutable, delete
|
||||||
disabled={!isMutable || isProcessing || role < UserRole.OWNER}
|
disabled={!isMutable || isProcessing || role < UserRole.OWNER}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
{(isRSForm || isOSS) && (
|
||||||
|
<MiniButton
|
||||||
|
title='Отображение статистики'
|
||||||
|
icon={
|
||||||
|
<IconShowSidebar value={isRSForm ? showRSFormStats : showOSSStats} isBottom={isNarrow} size='1.25rem' />
|
||||||
|
}
|
||||||
|
onClick={isRSForm ? toggleShowRSFormStats : toggleShowOSSStats}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<BadgeHelp topic={HelpTopic.UI_RS_CARD} offset={4} />
|
<BadgeHelp topic={HelpTopic.UI_RS_CARD} offset={4} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,7 +4,9 @@ import clsx from 'clsx';
|
||||||
|
|
||||||
import { EditorLibraryItem, ToolbarItemCard } from '@/features/library/components';
|
import { EditorLibraryItem, ToolbarItemCard } from '@/features/library/components';
|
||||||
|
|
||||||
|
import { useWindowSize } from '@/hooks/use-window-size';
|
||||||
import { useModificationStore } from '@/stores/modification';
|
import { useModificationStore } from '@/stores/modification';
|
||||||
|
import { usePreferencesStore } from '@/stores/preferences';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globalIDs } from '@/utils/constants';
|
||||||
|
|
||||||
import { useOssEdit } from '../oss-edit-context';
|
import { useOssEdit } from '../oss-edit-context';
|
||||||
|
@ -12,9 +14,14 @@ import { useOssEdit } from '../oss-edit-context';
|
||||||
import { FormOSS } from './form-oss';
|
import { FormOSS } from './form-oss';
|
||||||
import { OssStats } from './oss-stats';
|
import { OssStats } from './oss-stats';
|
||||||
|
|
||||||
|
const SIDELIST_LAYOUT_THRESHOLD = 768; // px
|
||||||
|
|
||||||
export function EditorOssCard() {
|
export function EditorOssCard() {
|
||||||
const { schema, isMutable, deleteSchema } = useOssEdit();
|
const { schema, isMutable, deleteSchema } = useOssEdit();
|
||||||
const { isModified } = useModificationStore();
|
const { isModified } = useModificationStore();
|
||||||
|
const showOSSStats = usePreferencesStore(state => state.showOSSStats);
|
||||||
|
const windowSize = useWindowSize();
|
||||||
|
const isNarrow = !!windowSize.width && windowSize.width <= SIDELIST_LAYOUT_THRESHOLD;
|
||||||
|
|
||||||
function initiateSubmit() {
|
function initiateSubmit() {
|
||||||
const element = document.getElementById(globalIDs.library_item_editor) as HTMLFormElement;
|
const element = document.getElementById(globalIDs.library_item_editor) as HTMLFormElement;
|
||||||
|
@ -33,25 +40,29 @@ export function EditorOssCard() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div
|
||||||
|
onKeyDown={handleInput}
|
||||||
|
className={clsx(
|
||||||
|
'relative md:w-fit md:max-w-fit max-w-128',
|
||||||
|
'flex px-6 pt-8',
|
||||||
|
isNarrow && 'flex-col md:items-center'
|
||||||
|
)}
|
||||||
|
>
|
||||||
<ToolbarItemCard
|
<ToolbarItemCard
|
||||||
className='cc-tab-tools'
|
className='cc-tab-tools'
|
||||||
onSubmit={initiateSubmit}
|
onSubmit={initiateSubmit}
|
||||||
schema={schema}
|
schema={schema}
|
||||||
isMutable={isMutable}
|
isMutable={isMutable}
|
||||||
deleteSchema={deleteSchema}
|
deleteSchema={deleteSchema}
|
||||||
|
isNarrow={isNarrow}
|
||||||
/>
|
/>
|
||||||
<div
|
|
||||||
onKeyDown={handleInput}
|
<div className='cc-column px-3 mx-0 md:mx-auto'>
|
||||||
className={clsx('md:max-w-fit max-w-128 min-w-fit', 'flex flex-row flex-wrap pt-8 px-6 justify-center')}
|
|
||||||
>
|
|
||||||
<div className='cc-column px-3'>
|
|
||||||
<FormOSS key={schema.id} />
|
<FormOSS key={schema.id} />
|
||||||
<EditorLibraryItem schema={schema} isAttachedToOSS={false} />
|
<EditorLibraryItem schema={schema} isAttachedToOSS={false} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<OssStats className='mt-3 md:mt-8 md:ml-5 w-80 md:w-56 mx-auto h-min' stats={schema.stats} />
|
<OssStats className='w-80 md:w-56 mt-3 md:mt-8 md:ml-5 mx-auto' stats={schema.stats} isMounted={showOSSStats} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,20 @@ import { type IOperationSchemaStats } from '../../../models/oss';
|
||||||
|
|
||||||
interface OssStatsProps {
|
interface OssStatsProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
isMounted: boolean;
|
||||||
stats: IOperationSchemaStats;
|
stats: IOperationSchemaStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OssStats({ className, stats }: OssStatsProps) {
|
export function OssStats({ className, isMounted, stats }: OssStatsProps) {
|
||||||
return (
|
return (
|
||||||
<div className={cn('grid grid-cols-4 gap-1 justify-items-end', className)}>
|
<aside
|
||||||
|
className={cn(
|
||||||
|
'grid grid-cols-4 gap-1 justify-items-end h-min',
|
||||||
|
'cc-animate-sidebar',
|
||||||
|
isMounted ? 'max-w-full' : 'opacity-0 max-w-0',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
<div id='count_operations' className='w-fit flex gap-3 hover:cursor-default '>
|
<div id='count_operations' className='w-fit flex gap-3 hover:cursor-default '>
|
||||||
<span>Всего</span>
|
<span>Всего</span>
|
||||||
<span>{stats.count_all}</span>
|
<span>{stats.count_all}</span>
|
||||||
|
@ -55,6 +63,6 @@ export function OssStats({ className, stats }: OssStatsProps) {
|
||||||
icon={<IconRSFormImported size='1.25rem' />}
|
icon={<IconRSFormImported size='1.25rem' />}
|
||||||
value={stats.count_schemas - stats.count_owned}
|
value={stats.count_schemas - stats.count_owned}
|
||||||
/>
|
/>
|
||||||
</div>
|
</aside>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@ export function EditorConstituenta() {
|
||||||
onSubmit={initiateSubmit}
|
onSubmit={initiateSubmit}
|
||||||
onReset={() => setToggleReset(prev => !prev)}
|
onReset={() => setToggleReset(prev => !prev)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
isNarrow={isNarrow}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='mx-0 md:mx-auto pt-8 md:w-195 shrink-0 xs:pt-0'>
|
<div className='mx-0 md:mx-auto pt-8 md:w-195 shrink-0 xs:pt-0'>
|
||||||
|
@ -112,7 +113,7 @@ export function EditorConstituenta() {
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<ViewConstituents
|
<ViewConstituents
|
||||||
className={isNarrow ? 'mt-3 mx-6 overflow-hidden' : 'mt-9 h-fit overflow-visible'}
|
className={isNarrow ? 'mt-3 mx-6 overflow-hidden' : 'mt-9 overflow-visible'}
|
||||||
isMounted={showList}
|
isMounted={showList}
|
||||||
isBottom={isNarrow}
|
isBottom={isNarrow}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { urls, useConceptNavigation } from '@/app';
|
import { urls, useConceptNavigation } from '@/app';
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
import { BadgeHelp } from '@/features/help/components';
|
import { BadgeHelp } from '@/features/help/components';
|
||||||
import { MiniSelectorOSS } from '@/features/library/components';
|
import { MiniSelectorOSS } from '@/features/library/components';
|
||||||
|
import { IconShowSidebar } from '@/features/library/components/icon-show-sidebar';
|
||||||
import { useFindPredecessor } from '@/features/oss/backend/use-find-predecessor';
|
import { useFindPredecessor } from '@/features/oss/backend/use-find-predecessor';
|
||||||
|
|
||||||
import { MiniButton } from '@/components/control';
|
import { MiniButton } from '@/components/control';
|
||||||
import {
|
import {
|
||||||
IconClone,
|
IconClone,
|
||||||
IconDestroy,
|
IconDestroy,
|
||||||
IconList,
|
|
||||||
IconListOff,
|
|
||||||
IconMoveDown,
|
IconMoveDown,
|
||||||
IconMoveUp,
|
IconMoveUp,
|
||||||
IconNewItem,
|
IconNewItem,
|
||||||
|
@ -21,6 +18,7 @@ import {
|
||||||
IconReset,
|
IconReset,
|
||||||
IconSave
|
IconSave
|
||||||
} from '@/components/icons';
|
} from '@/components/icons';
|
||||||
|
import { cn } from '@/components/utils';
|
||||||
import { useModificationStore } from '@/stores/modification';
|
import { useModificationStore } from '@/stores/modification';
|
||||||
import { usePreferencesStore } from '@/stores/preferences';
|
import { usePreferencesStore } from '@/stores/preferences';
|
||||||
import { tooltipText } from '@/utils/labels';
|
import { tooltipText } from '@/utils/labels';
|
||||||
|
@ -34,6 +32,7 @@ interface ToolbarConstituentaProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
activeCst: IConstituenta | null;
|
activeCst: IConstituenta | null;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
isNarrow: boolean;
|
||||||
|
|
||||||
onSubmit: () => void;
|
onSubmit: () => void;
|
||||||
onReset: () => void;
|
onReset: () => void;
|
||||||
|
@ -43,6 +42,7 @@ export function ToolbarConstituenta({
|
||||||
className,
|
className,
|
||||||
activeCst,
|
activeCst,
|
||||||
disabled,
|
disabled,
|
||||||
|
isNarrow,
|
||||||
|
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onReset
|
onReset
|
||||||
|
@ -80,7 +80,7 @@ export function ToolbarConstituenta({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx('px-1 rounded-b-2xl backdrop-blur-xs cc-icons cc-animate-position outline-hidden', className)}>
|
<div className={cn('px-1 rounded-b-2xl backdrop-blur-xs cc-icons outline-hidden', className)}>
|
||||||
{schema.oss.length > 0 ? (
|
{schema.oss.length > 0 ? (
|
||||||
<MiniSelectorOSS
|
<MiniSelectorOSS
|
||||||
items={schema.oss}
|
items={schema.oss}
|
||||||
|
@ -152,13 +152,7 @@ export function ToolbarConstituenta({
|
||||||
|
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Отображение списка конституент'
|
title='Отображение списка конституент'
|
||||||
icon={
|
icon={<IconShowSidebar size='1.25rem' value={showList} isBottom={isNarrow} />}
|
||||||
showList ? (
|
|
||||||
<IconList size='1.25rem' className='icon-primary' />
|
|
||||||
) : (
|
|
||||||
<IconListOff size='1.25rem' className='icon-primary' />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onClick={toggleList}
|
onClick={toggleList}
|
||||||
/>
|
/>
|
||||||
<BadgeHelp topic={HelpTopic.UI_RS_EDITOR} offset={4} contentClass='sm:max-w-160' />
|
<BadgeHelp topic={HelpTopic.UI_RS_EDITOR} offset={4} contentClass='sm:max-w-160' />
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { EditorLibraryItem, ToolbarItemCard } from '@/features/library/components';
|
import { EditorLibraryItem, ToolbarItemCard } from '@/features/library/components';
|
||||||
|
|
||||||
|
import { useWindowSize } from '@/hooks/use-window-size';
|
||||||
import { useModificationStore } from '@/stores/modification';
|
import { useModificationStore } from '@/stores/modification';
|
||||||
|
import { usePreferencesStore } from '@/stores/preferences';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globalIDs } from '@/utils/constants';
|
||||||
|
|
||||||
import { useRSEdit } from '../rsedit-context';
|
import { useRSEdit } from '../rsedit-context';
|
||||||
|
@ -10,9 +14,14 @@ import { useRSEdit } from '../rsedit-context';
|
||||||
import { FormRSForm } from './form-rsform';
|
import { FormRSForm } from './form-rsform';
|
||||||
import { RSFormStats } from './rsform-stats';
|
import { RSFormStats } from './rsform-stats';
|
||||||
|
|
||||||
|
const SIDELIST_LAYOUT_THRESHOLD = 768; // px
|
||||||
|
|
||||||
export function EditorRSFormCard() {
|
export function EditorRSFormCard() {
|
||||||
const { schema, isArchive, isMutable, deleteSchema, isAttachedToOSS } = useRSEdit();
|
const { schema, isArchive, isMutable, deleteSchema, isAttachedToOSS } = useRSEdit();
|
||||||
const { isModified } = useModificationStore();
|
const { isModified } = useModificationStore();
|
||||||
|
const showRSFormStats = usePreferencesStore(state => state.showRSFormStats);
|
||||||
|
const windowSize = useWindowSize();
|
||||||
|
const isNarrow = !!windowSize.width && windowSize.width <= SIDELIST_LAYOUT_THRESHOLD;
|
||||||
|
|
||||||
function initiateSubmit() {
|
function initiateSubmit() {
|
||||||
const element = document.getElementById(globalIDs.library_item_editor) as HTMLFormElement;
|
const element = document.getElementById(globalIDs.library_item_editor) as HTMLFormElement;
|
||||||
|
@ -31,24 +40,33 @@ export function EditorRSFormCard() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onKeyDown={handleInput} className='relative md:w-fit md:max-w-fit max-w-128 flex flex-row flex-wrap px-6 pt-8'>
|
<div
|
||||||
|
onKeyDown={handleInput}
|
||||||
|
className={clsx(
|
||||||
|
'relative md:w-fit md:max-w-fit max-w-128',
|
||||||
|
'flex px-6 pt-8',
|
||||||
|
isNarrow && 'flex-col md:items-center'
|
||||||
|
)}
|
||||||
|
>
|
||||||
<ToolbarItemCard
|
<ToolbarItemCard
|
||||||
className='cc-tab-tools'
|
className='cc-tab-tools'
|
||||||
onSubmit={initiateSubmit}
|
onSubmit={initiateSubmit}
|
||||||
schema={schema}
|
schema={schema}
|
||||||
isMutable={isMutable}
|
isMutable={isMutable}
|
||||||
deleteSchema={deleteSchema}
|
deleteSchema={deleteSchema}
|
||||||
|
isNarrow={isNarrow}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='cc-column shrink'>
|
<div className='cc-column mx-0 md:mx-auto'>
|
||||||
<FormRSForm key={schema.id} />
|
<FormRSForm key={schema.id} />
|
||||||
<EditorLibraryItem schema={schema} isAttachedToOSS={isAttachedToOSS} />
|
<EditorLibraryItem schema={schema} isAttachedToOSS={isAttachedToOSS} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RSFormStats
|
<RSFormStats
|
||||||
className='mt-3 md:mt-8 md:ml-5 w-80 md:w-56 mx-auto h-min'
|
className='w-80 md:w-56 mt-3 md:mt-8 md:ml-5 mx-auto'
|
||||||
stats={schema.stats}
|
stats={schema.stats}
|
||||||
isArchive={isArchive}
|
isArchive={isArchive}
|
||||||
|
isMounted={showRSFormStats}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IconChild,
|
IconChild,
|
||||||
IconConvention,
|
IconConvention,
|
||||||
|
@ -19,6 +17,7 @@ import {
|
||||||
IconStatusProperty,
|
IconStatusProperty,
|
||||||
IconTerminology
|
IconTerminology
|
||||||
} from '@/components/icons';
|
} from '@/components/icons';
|
||||||
|
import { cn } from '@/components/utils';
|
||||||
import { ValueStats } from '@/components/view';
|
import { ValueStats } from '@/components/view';
|
||||||
|
|
||||||
import { type IRSFormStats } from '../../../models/rsform';
|
import { type IRSFormStats } from '../../../models/rsform';
|
||||||
|
@ -26,12 +25,21 @@ import { type IRSFormStats } from '../../../models/rsform';
|
||||||
interface RSFormStatsProps {
|
interface RSFormStatsProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
isArchive: boolean;
|
isArchive: boolean;
|
||||||
|
isMounted: boolean;
|
||||||
stats: IRSFormStats;
|
stats: IRSFormStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RSFormStats({ className, stats, isArchive }: RSFormStatsProps) {
|
export function RSFormStats({ className, stats, isArchive, isMounted }: RSFormStatsProps) {
|
||||||
return (
|
return (
|
||||||
<div className={clsx('grid grid-cols-4 gap-1 justify-items-end', className)}>
|
<aside
|
||||||
|
className={cn(
|
||||||
|
'cc-animate-sidebar',
|
||||||
|
'h-min',
|
||||||
|
'grid grid-cols-4 gap-1 justify-items-end ',
|
||||||
|
isMounted ? 'max-w-full' : 'opacity-0 max-w-0',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
<div id='count_all' className='col-span-2 w-fit flex gap-3 hover:cursor-default'>
|
<div id='count_all' className='col-span-2 w-fit flex gap-3 hover:cursor-default'>
|
||||||
<span>Всего</span>
|
<span>Всего</span>
|
||||||
<span>{stats.count_all}</span>
|
<span>{stats.count_all}</span>
|
||||||
|
@ -140,6 +148,6 @@ export function RSFormStats({ className, stats, isArchive }: RSFormStatsProps) {
|
||||||
}
|
}
|
||||||
value={stats.count_convention}
|
value={stats.count_convention}
|
||||||
/>
|
/>
|
||||||
</div>
|
</aside>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import clsx from 'clsx';
|
'use client';
|
||||||
|
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
import { BadgeHelp } from '@/features/help/components';
|
import { BadgeHelp } from '@/features/help/components';
|
||||||
|
@ -15,6 +15,7 @@ import {
|
||||||
IconOpenList,
|
IconOpenList,
|
||||||
IconReset
|
IconReset
|
||||||
} from '@/components/icons';
|
} from '@/components/icons';
|
||||||
|
import { cn } from '@/components/utils';
|
||||||
import { prefixes } from '@/utils/constants';
|
import { prefixes } from '@/utils/constants';
|
||||||
import { prepareTooltip } from '@/utils/utils';
|
import { prepareTooltip } from '@/utils/utils';
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ export function ToolbarRSList({ className }: ToolbarRSListProps) {
|
||||||
} = useRSEdit();
|
} = useRSEdit();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx('cc-icons items-start outline-hidden', className)}>
|
<div className={cn('cc-icons items-start outline-hidden', className)}>
|
||||||
{schema.oss.length > 0 ? (
|
{schema.oss.length > 0 ? (
|
||||||
<MiniSelectorOSS
|
<MiniSelectorOSS
|
||||||
items={schema.oss}
|
items={schema.oss}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { useRoleStore, UserRole } from '@/features/users';
|
import { useRoleStore, UserRole } from '@/features/users';
|
||||||
|
|
||||||
|
import { cn } from '@/components/utils';
|
||||||
import { useWindowSize } from '@/hooks/use-window-size';
|
import { useWindowSize } from '@/hooks/use-window-size';
|
||||||
import { useFitHeight } from '@/stores/app-layout';
|
import { useFitHeight } from '@/stores/app-layout';
|
||||||
|
|
||||||
|
@ -26,11 +25,11 @@ export function ViewConstituents({ className, isBottom, isMounted }: ViewConstit
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside
|
<aside
|
||||||
className={clsx(
|
className={cn(
|
||||||
|
'cc-animate-sidebar',
|
||||||
'border',
|
'border',
|
||||||
isBottom ? 'rounded-md' : 'rounded-l-md rounded-r-none',
|
isBottom ? 'rounded-md' : 'rounded-l-md rounded-r-none h-fit',
|
||||||
isMounted ? 'max-w-full' : 'opacity-0 max-w-0',
|
isMounted ? 'max-w-full' : 'opacity-0 max-w-0',
|
||||||
'ease-in-out duration-1000 transition-[opacity,max-width]',
|
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -91,6 +91,7 @@
|
||||||
--duration-modal: 300ms;
|
--duration-modal: 300ms;
|
||||||
--duration-fade: 300ms;
|
--duration-fade: 300ms;
|
||||||
--duration-move: 500ms;
|
--duration-move: 500ms;
|
||||||
|
--duration-transform: 1000ms;
|
||||||
--duration-cycle: 1000ms;
|
--duration-cycle: 1000ms;
|
||||||
|
|
||||||
/* Custom animations */
|
/* Custom animations */
|
||||||
|
|
|
@ -20,6 +20,12 @@ interface PreferencesStore {
|
||||||
showCstSideList: boolean;
|
showCstSideList: boolean;
|
||||||
toggleShowCstSideList: () => void;
|
toggleShowCstSideList: () => void;
|
||||||
|
|
||||||
|
showRSFormStats: boolean;
|
||||||
|
toggleShowRSFormStats: () => void;
|
||||||
|
|
||||||
|
showOSSStats: boolean;
|
||||||
|
toggleShowOSSStats: () => void;
|
||||||
|
|
||||||
showExpressionControls: boolean;
|
showExpressionControls: boolean;
|
||||||
toggleShowExpressionControls: () => void;
|
toggleShowExpressionControls: () => void;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +69,12 @@ export const usePreferencesStore = create<PreferencesStore>()(
|
||||||
showCstSideList: true,
|
showCstSideList: true,
|
||||||
toggleShowCstSideList: () => set(state => ({ showCstSideList: !state.showCstSideList })),
|
toggleShowCstSideList: () => set(state => ({ showCstSideList: !state.showCstSideList })),
|
||||||
|
|
||||||
|
showRSFormStats: true,
|
||||||
|
toggleShowRSFormStats: () => set(state => ({ showRSFormStats: !state.showRSFormStats })),
|
||||||
|
|
||||||
|
showOSSStats: true,
|
||||||
|
toggleShowOSSStats: () => set(state => ({ showOSSStats: !state.showOSSStats })),
|
||||||
|
|
||||||
showExpressionControls: true,
|
showExpressionControls: true,
|
||||||
toggleShowExpressionControls: () => set(state => ({ showExpressionControls: !state.showExpressionControls }))
|
toggleShowExpressionControls: () => set(state => ({ showExpressionControls: !state.showExpressionControls }))
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -142,6 +142,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@utility cc-animate-sidebar {
|
||||||
|
transition-property: max-width, opacity;
|
||||||
|
transition-timing-function: var(--ease-in-out);
|
||||||
|
transition-duration: var(--duration-transform);
|
||||||
|
}
|
||||||
|
|
||||||
@utility cc-animate-position {
|
@utility cc-animate-position {
|
||||||
transition-property: transform top left bottom right margin padding;
|
transition-property: transform top left bottom right margin padding;
|
||||||
transition-timing-function: var(--ease-bezier);
|
transition-timing-function: var(--ease-bezier);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user