F: Add side panel for schema preview pt1
This commit is contained in:
parent
ac38e9f4b5
commit
5c4149337b
|
@ -10,8 +10,9 @@ export const GlobalTooltips = () => {
|
||||||
float
|
float
|
||||||
id={globalIDs.tooltip}
|
id={globalIDs.tooltip}
|
||||||
layer='z-topmost'
|
layer='z-topmost'
|
||||||
place='right-start'
|
place='bottom-start'
|
||||||
className='mt-8 max-w-80 break-words rounded-lg! select-none'
|
offset={24}
|
||||||
|
className='max-w-80 break-words rounded-lg! select-none'
|
||||||
/>
|
/>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
float
|
float
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
IconExecute,
|
IconExecute,
|
||||||
IconFitImage,
|
IconFitImage,
|
||||||
IconGrid,
|
IconGrid,
|
||||||
|
IconLeftOpen,
|
||||||
IconLineStraight,
|
IconLineStraight,
|
||||||
IconLineWave,
|
IconLineWave,
|
||||||
IconNewItem,
|
IconNewItem,
|
||||||
|
@ -30,7 +31,7 @@ export function HelpOssGraph() {
|
||||||
<div className='flex flex-col'>
|
<div className='flex flex-col'>
|
||||||
<h1 className='sm:pr-24'>Граф синтеза</h1>
|
<h1 className='sm:pr-24'>Граф синтеза</h1>
|
||||||
<div className='flex flex-col sm:flex-row'>
|
<div className='flex flex-col sm:flex-row'>
|
||||||
<div className='sm:w-56'>
|
<div className='sm:w-64'>
|
||||||
<h2>Настройка графа</h2>
|
<h2>Настройка графа</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
|
@ -39,6 +40,9 @@ export function HelpOssGraph() {
|
||||||
<li>
|
<li>
|
||||||
<IconFitImage className='inline-icon' /> Вписать в экран
|
<IconFitImage className='inline-icon' /> Вписать в экран
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<IconLeftOpen className='inline-icon' /> Панель связанной КС
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<IconSettings className='inline-icon' /> Диалог настроек
|
<IconSettings className='inline-icon' /> Диалог настроек
|
||||||
</li>
|
</li>
|
||||||
|
@ -66,7 +70,7 @@ export function HelpOssGraph() {
|
||||||
|
|
||||||
<Divider vertical margins='mx-3 mt-3' className='hidden sm:block' />
|
<Divider vertical margins='mx-3 mt-3' className='hidden sm:block' />
|
||||||
|
|
||||||
<div className='sm:w-84'>
|
<div className='sm:w-76'>
|
||||||
<h2>Изменение узлов</h2>
|
<h2>Изменение узлов</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
|
@ -97,7 +101,7 @@ export function HelpOssGraph() {
|
||||||
<Divider margins='my-2' className='hidden sm:block' />
|
<Divider margins='my-2' className='hidden sm:block' />
|
||||||
|
|
||||||
<div className='flex flex-col-reverse mb-3 sm:flex-row'>
|
<div className='flex flex-col-reverse mb-3 sm:flex-row'>
|
||||||
<div className='sm:w-56'>
|
<div className='sm:w-64'>
|
||||||
<h2>Общие</h2>
|
<h2>Общие</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
|
@ -114,7 +118,7 @@ export function HelpOssGraph() {
|
||||||
|
|
||||||
<Divider vertical margins='mx-3' className='hidden sm:block' />
|
<Divider vertical margins='mx-3' className='hidden sm:block' />
|
||||||
|
|
||||||
<div className='dense w-84'>
|
<div className='dense w-76'>
|
||||||
<h2>Контекстное меню</h2>
|
<h2>Контекстное меню</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -15,9 +15,9 @@ export function IconShowSidebar({
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (value) {
|
if (value) {
|
||||||
return <IconLeftClose size={size} className={className ?? 'icon-primary'} />;
|
|
||||||
} else {
|
|
||||||
return <IconLeftOpen size={size} className={className ?? 'icon-primary'} />;
|
return <IconLeftOpen size={size} className={className ?? 'icon-primary'} />;
|
||||||
|
} else {
|
||||||
|
return <IconLeftClose size={size} className={className ?? 'icon-primary'} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import clsx from 'clsx';
|
||||||
import { DiagramFlow, useReactFlow, useStoreApi } from '@/components/flow/diagram-flow';
|
import { DiagramFlow, useReactFlow, useStoreApi } from '@/components/flow/diagram-flow';
|
||||||
import { useMainHeight } from '@/stores/app-layout';
|
import { useMainHeight } from '@/stores/app-layout';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
import { usePreferencesStore } from '@/stores/preferences';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
import { promptText } from '@/utils/labels';
|
import { promptText } from '@/utils/labels';
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ import { useContextMenu } from './context-menu/use-context-menu';
|
||||||
import { OssNodeTypes } from './graph/oss-node-types';
|
import { OssNodeTypes } from './graph/oss-node-types';
|
||||||
import { CoordinateDisplay } from './coordinate-display';
|
import { CoordinateDisplay } from './coordinate-display';
|
||||||
import { useOssFlow } from './oss-flow-context';
|
import { useOssFlow } from './oss-flow-context';
|
||||||
|
import { SidePanel } from './side-panel';
|
||||||
import { ToolbarOssGraph } from './toolbar-oss-graph';
|
import { ToolbarOssGraph } from './toolbar-oss-graph';
|
||||||
import { useDragging } from './use-dragging';
|
import { useDragging } from './use-dragging';
|
||||||
import { useGetLayout } from './use-get-layout';
|
import { useGetLayout } from './use-get-layout';
|
||||||
|
@ -52,6 +54,7 @@ export function OssFlow() {
|
||||||
|
|
||||||
const showGrid = useOSSGraphStore(state => state.showGrid);
|
const showGrid = useOSSGraphStore(state => state.showGrid);
|
||||||
const showCoordinates = useOSSGraphStore(state => state.showCoordinates);
|
const showCoordinates = useOSSGraphStore(state => state.showCoordinates);
|
||||||
|
const showPanel = usePreferencesStore(state => state.showOssSidePanel);
|
||||||
|
|
||||||
const getLayout = useGetLayout();
|
const getLayout = useGetLayout();
|
||||||
const { updateLayout } = useUpdateLayout();
|
const { updateLayout } = useUpdateLayout();
|
||||||
|
@ -225,6 +228,16 @@ export function OssFlow() {
|
||||||
onNodeDrag={handleDrag}
|
onNodeDrag={handleDrag}
|
||||||
onNodeDragStop={handleDragStop}
|
onNodeDragStop={handleDragStop}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<SidePanel
|
||||||
|
className={clsx(
|
||||||
|
'absolute right-0 top-0 z-sticky w-84 min-h-80',
|
||||||
|
'cc-animate-panel cc-shadow-border',
|
||||||
|
showPanel ? 'translate-x-0' : 'opacity-0 translate-x-full pointer-events-none'
|
||||||
|
)}
|
||||||
|
isMounted={showPanel}
|
||||||
|
selectedItems={selectedItems}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export { SidePanel } from './side-panel';
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { Suspense } from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { useDebounce } from 'use-debounce';
|
||||||
|
|
||||||
|
import { MiniButton } from '@/components/control';
|
||||||
|
import { IconClose } from '@/components/icons';
|
||||||
|
import { Loader } from '@/components/loader';
|
||||||
|
import { cn } from '@/components/utils';
|
||||||
|
import { useMainHeight } from '@/stores/app-layout';
|
||||||
|
import { usePreferencesStore } from '@/stores/preferences';
|
||||||
|
import { PARAMETER } from '@/utils/constants';
|
||||||
|
|
||||||
|
import { type IOssItem, NodeType } from '../../../../models/oss';
|
||||||
|
|
||||||
|
import { ViewSchema } from './view-schema';
|
||||||
|
|
||||||
|
interface SidePanelProps {
|
||||||
|
selectedItems: IOssItem[];
|
||||||
|
className?: string;
|
||||||
|
isMounted: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SidePanel({ selectedItems, isMounted, className }: SidePanelProps) {
|
||||||
|
const selectedOperation =
|
||||||
|
selectedItems.length === 1 && selectedItems[0].nodeType === NodeType.OPERATION ? selectedItems[0] : null;
|
||||||
|
const selectedSchema = selectedOperation?.result ?? null;
|
||||||
|
|
||||||
|
const debouncedMounted = useDebounce(isMounted, PARAMETER.moveDuration);
|
||||||
|
const closePanel = usePreferencesStore(state => state.toggleShowOssSidePanel);
|
||||||
|
const sidePanelHeight = useMainHeight();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
'relative flex flex-col py-2 h-full overflow-hidden',
|
||||||
|
'border-l rounded-none rounded-l-sm bg-background',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
style={{ height: sidePanelHeight }}
|
||||||
|
>
|
||||||
|
<MiniButton
|
||||||
|
titleHtml='Закрыть панель'
|
||||||
|
aria-label='Закрыть'
|
||||||
|
noPadding
|
||||||
|
icon={<IconClose size='1.25rem' />}
|
||||||
|
className='absolute z-pop top-2 right-1'
|
||||||
|
onClick={closePanel}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'mt-0 mb-1',
|
||||||
|
'font-medium text-sm select-none self-center',
|
||||||
|
'transition-transform',
|
||||||
|
selectedSchema && 'translate-x-16'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
Содержание КС
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!selectedOperation ? (
|
||||||
|
<div className='text-center text-sm cc-fade-in'>Выделите операцию для просмотра</div>
|
||||||
|
) : !selectedSchema ? (
|
||||||
|
<div className='text-center text-sm cc-fade-in'>Отсутствует концептуальная схема для выбранной операции</div>
|
||||||
|
) : debouncedMounted ? (
|
||||||
|
<Suspense fallback={<Loader />}>
|
||||||
|
<ViewSchema schemaID={selectedSchema} />
|
||||||
|
</Suspense>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
import { urls, useConceptNavigation } from '@/app';
|
||||||
|
import { type IConstituenta, type IRSForm } from '@/features/rsform';
|
||||||
|
import { CstType, type IConstituentaBasicsDTO, type ICreateConstituentaDTO } from '@/features/rsform/backend/types';
|
||||||
|
import { useCreateConstituenta } from '@/features/rsform/backend/use-create-constituenta';
|
||||||
|
import { useMoveConstituents } from '@/features/rsform/backend/use-move-constituents';
|
||||||
|
import { useMutatingRSForm } from '@/features/rsform/backend/use-mutating-rsform';
|
||||||
|
import { generateAlias } from '@/features/rsform/models/rsform-api';
|
||||||
|
import { useCstSearchStore } from '@/features/rsform/stores/cst-search';
|
||||||
|
|
||||||
|
import { MiniButton } from '@/components/control';
|
||||||
|
import { IconClone, IconDestroy, IconMoveDown, IconMoveUp, IconNewItem, IconRSForm } from '@/components/icons';
|
||||||
|
import { cn } from '@/components/utils';
|
||||||
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
import { PARAMETER, prefixes } from '@/utils/constants';
|
||||||
|
import { type RO } from '@/utils/meta';
|
||||||
|
|
||||||
|
interface ToolbarConstituentsProps {
|
||||||
|
schema: IRSForm;
|
||||||
|
activeCst: IConstituenta | null;
|
||||||
|
setActive: (cstID: number) => void;
|
||||||
|
resetActive: () => void;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ToolbarConstituents({
|
||||||
|
schema,
|
||||||
|
activeCst,
|
||||||
|
setActive,
|
||||||
|
resetActive,
|
||||||
|
className
|
||||||
|
}: ToolbarConstituentsProps) {
|
||||||
|
const router = useConceptNavigation();
|
||||||
|
const isProcessing = useMutatingRSForm();
|
||||||
|
const searchText = useCstSearchStore(state => state.query);
|
||||||
|
const hasSearch = searchText.length > 0;
|
||||||
|
|
||||||
|
const showCreateCst = useDialogsStore(state => state.showCreateCst);
|
||||||
|
const showDeleteCst = useDialogsStore(state => state.showDeleteCst);
|
||||||
|
const { moveConstituents } = useMoveConstituents();
|
||||||
|
const { createConstituenta } = useCreateConstituenta();
|
||||||
|
|
||||||
|
function navigateRSForm() {
|
||||||
|
router.push({ path: urls.schema(schema.id) });
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCreateCst(newCst: RO<IConstituentaBasicsDTO>) {
|
||||||
|
setActive(newCst.id);
|
||||||
|
setTimeout(() => {
|
||||||
|
const element = document.getElementById(`${prefixes.cst_list}${newCst.id}`);
|
||||||
|
if (element) {
|
||||||
|
element.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'nearest',
|
||||||
|
inline: 'end'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, PARAMETER.refreshTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCst() {
|
||||||
|
const targetType = activeCst?.cst_type ?? CstType.BASE;
|
||||||
|
const data: ICreateConstituentaDTO = {
|
||||||
|
insert_after: activeCst?.id ?? null,
|
||||||
|
cst_type: targetType,
|
||||||
|
alias: generateAlias(targetType, schema),
|
||||||
|
term_raw: '',
|
||||||
|
definition_formal: '',
|
||||||
|
definition_raw: '',
|
||||||
|
convention: '',
|
||||||
|
term_forms: []
|
||||||
|
};
|
||||||
|
showCreateCst({ schema: schema, onCreate: onCreateCst, initial: data });
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneCst() {
|
||||||
|
if (!activeCst) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void createConstituenta({
|
||||||
|
itemID: schema.id,
|
||||||
|
data: {
|
||||||
|
insert_after: activeCst.id,
|
||||||
|
cst_type: activeCst.cst_type,
|
||||||
|
alias: generateAlias(activeCst.cst_type, schema),
|
||||||
|
term_raw: activeCst.term_raw,
|
||||||
|
definition_formal: activeCst.definition_formal,
|
||||||
|
definition_raw: activeCst.definition_raw,
|
||||||
|
convention: activeCst.convention,
|
||||||
|
term_forms: activeCst.term_forms
|
||||||
|
}
|
||||||
|
}).then(onCreateCst);
|
||||||
|
}
|
||||||
|
|
||||||
|
function promptDeleteCst() {
|
||||||
|
if (!activeCst) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showDeleteCst({
|
||||||
|
schema: schema,
|
||||||
|
selected: [activeCst.id],
|
||||||
|
afterDelete: resetActive
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveUp() {
|
||||||
|
if (!activeCst) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const currentIndex = schema.items.reduce((prev, cst, index) => {
|
||||||
|
if (activeCst.id !== cst.id) {
|
||||||
|
return prev;
|
||||||
|
} else if (prev === -1) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
return Math.min(prev, index);
|
||||||
|
}, -1);
|
||||||
|
const target = Math.max(0, currentIndex - 1);
|
||||||
|
void moveConstituents({
|
||||||
|
itemID: schema.id,
|
||||||
|
data: {
|
||||||
|
items: [activeCst.id],
|
||||||
|
move_to: target
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveDown() {
|
||||||
|
if (!activeCst) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let count = 0;
|
||||||
|
const currentIndex = schema.items.reduce((prev, cst, index) => {
|
||||||
|
if (activeCst.id !== cst.id) {
|
||||||
|
return prev;
|
||||||
|
} else {
|
||||||
|
count += 1;
|
||||||
|
if (prev === -1) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
return Math.max(prev, index);
|
||||||
|
}
|
||||||
|
}, -1);
|
||||||
|
const target = Math.min(schema.items.length - 1, currentIndex - count + 2);
|
||||||
|
void moveConstituents({
|
||||||
|
itemID: schema.id,
|
||||||
|
data: {
|
||||||
|
items: [activeCst.id],
|
||||||
|
move_to: target
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cn('flex gap-0.5', className)}>
|
||||||
|
<MiniButton
|
||||||
|
title='Перейти к концептуальной схеме'
|
||||||
|
icon={<IconRSForm size='1rem' className='icon-primary' />}
|
||||||
|
onClick={navigateRSForm}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MiniButton
|
||||||
|
title='Создать конституенту'
|
||||||
|
icon={<IconNewItem size='1rem' className='icon-green' />}
|
||||||
|
onClick={createCst}
|
||||||
|
disabled={isProcessing}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
title='Клонировать конституенту'
|
||||||
|
icon={<IconClone size='1rem' className='icon-green' />}
|
||||||
|
onClick={cloneCst}
|
||||||
|
disabled={!activeCst || isProcessing}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MiniButton
|
||||||
|
title='Удалить выделенную конституенту'
|
||||||
|
onClick={promptDeleteCst}
|
||||||
|
icon={<IconDestroy size='1rem' className='icon-red' />}
|
||||||
|
disabled={!activeCst || isProcessing || activeCst?.is_inherited}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MiniButton
|
||||||
|
title='Переместить вверх'
|
||||||
|
icon={<IconMoveUp size='1rem' className='icon-primary' />}
|
||||||
|
onClick={moveUp}
|
||||||
|
disabled={!activeCst || isProcessing || schema.items.length < 2 || hasSearch}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
title='Переместить вниз'
|
||||||
|
icon={<IconMoveDown size='1rem' className='icon-primary' />}
|
||||||
|
onClick={moveDown}
|
||||||
|
disabled={!activeCst || isProcessing || schema.items.length < 2 || hasSearch}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { useRSFormSuspense } from '@/features/rsform/backend/use-rsform';
|
||||||
|
import { RSFormStats } from '@/features/rsform/components/rsform-stats';
|
||||||
|
import { ViewConstituents } from '@/features/rsform/components/view-constituents';
|
||||||
|
|
||||||
|
import { useFitHeight } from '@/stores/app-layout';
|
||||||
|
|
||||||
|
import { ToolbarConstituents } from './toolbar-constituents';
|
||||||
|
|
||||||
|
interface ViewSchemaProps {
|
||||||
|
schemaID: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ViewSchema({ schemaID }: ViewSchemaProps) {
|
||||||
|
const { schema } = useRSFormSuspense({ itemID: schemaID });
|
||||||
|
const [activeID, setActiveID] = useState<number | null>(null);
|
||||||
|
const activeCst = activeID ? schema.cstByID.get(activeID) ?? null : null;
|
||||||
|
|
||||||
|
const listHeight = useFitHeight('19rem', '10rem');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='grid h-full relative cc-fade-in' style={{ gridTemplateRows: '1fr auto' }}>
|
||||||
|
<ToolbarConstituents
|
||||||
|
className='absolute -top-7 left-1'
|
||||||
|
schema={schema}
|
||||||
|
activeCst={activeCst}
|
||||||
|
setActive={setActiveID}
|
||||||
|
resetActive={() => setActiveID(null)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ViewConstituents
|
||||||
|
dense
|
||||||
|
noBorder
|
||||||
|
className='border-y rounded-none'
|
||||||
|
schema={schema}
|
||||||
|
activeCst={activeCst}
|
||||||
|
onActivate={cst => setActiveID(cst.id)}
|
||||||
|
maxListHeight={listHeight}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<RSFormStats className='pr-4 py-2 ml-[-1rem]' stats={schema.stats} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||||
|
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
import { BadgeHelp } from '@/features/help/components/badge-help';
|
import { BadgeHelp } from '@/features/help/components/badge-help';
|
||||||
|
import { IconShowSidebar } from '@/features/library/components/icon-show-sidebar';
|
||||||
import { type OssNode } from '@/features/oss/models/oss-layout';
|
import { type OssNode } from '@/features/oss/models/oss-layout';
|
||||||
|
|
||||||
import { MiniButton } from '@/components/control';
|
import { MiniButton } from '@/components/control';
|
||||||
|
@ -20,6 +21,7 @@ import {
|
||||||
import { type Styling } from '@/components/props';
|
import { type Styling } from '@/components/props';
|
||||||
import { cn } from '@/components/utils';
|
import { cn } from '@/components/utils';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
import { usePreferencesStore } from '@/stores/preferences';
|
||||||
import { isIOS, prepareTooltip } from '@/utils/utils';
|
import { isIOS, prepareTooltip } from '@/utils/utils';
|
||||||
|
|
||||||
import { useMutatingOss } from '../../../backend/use-mutating-oss';
|
import { useMutatingOss } from '../../../backend/use-mutating-oss';
|
||||||
|
@ -64,10 +66,12 @@ export function ToolbarOssGraph({
|
||||||
|
|
||||||
const { updateLayout } = useUpdateLayout();
|
const { updateLayout } = useUpdateLayout();
|
||||||
|
|
||||||
const showOssOptions = useDialogsStore(state => state.showOssOptions);
|
const showOptions = useDialogsStore(state => state.showOssOptions);
|
||||||
|
const showSidePanel = usePreferencesStore(state => state.showOssSidePanel);
|
||||||
|
const toggleShowSidePanel = usePreferencesStore(state => state.toggleShowOssSidePanel);
|
||||||
|
|
||||||
function handleShowOptions() {
|
function handleShowOptions() {
|
||||||
showOssOptions();
|
showOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSavePositions() {
|
function handleSavePositions() {
|
||||||
|
@ -110,6 +114,11 @@ export function ToolbarOssGraph({
|
||||||
icon={<IconFitImage size='1.25rem' className='icon-primary' />}
|
icon={<IconFitImage size='1.25rem' className='icon-primary' />}
|
||||||
onClick={resetView}
|
onClick={resetView}
|
||||||
/>
|
/>
|
||||||
|
<MiniButton
|
||||||
|
title='Панель содержания КС'
|
||||||
|
icon={<IconShowSidebar value={showSidePanel} isBottom={false} size='1.25rem' />}
|
||||||
|
onClick={toggleShowSidePanel}
|
||||||
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Настройки отображения'
|
title='Настройки отображения'
|
||||||
icon={<IconSettings size='1.25rem' className='icon-primary' />}
|
icon={<IconSettings size='1.25rem' className='icon-primary' />}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { ListConstituents } from './list-constituents';
|
||||||
export interface DlgDeleteCstProps {
|
export interface DlgDeleteCstProps {
|
||||||
schema: IRSForm;
|
schema: IRSForm;
|
||||||
selected: number[];
|
selected: number[];
|
||||||
afterDelete: (initialSchema: IRSForm, deleted: number[]) => void;
|
afterDelete?: (initialSchema: IRSForm, deleted: number[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DlgDeleteCst() {
|
export function DlgDeleteCst() {
|
||||||
|
@ -31,7 +31,7 @@ export function DlgDeleteCst() {
|
||||||
|
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
const deleted = expandOut ? selected.concat(expansion) : selected;
|
const deleted = expandOut ? selected.concat(expansion) : selected;
|
||||||
void cstDelete({ itemID: schema.id, data: { items: deleted } }).then(() => afterDelete(schema, deleted));
|
void cstDelete({ itemID: schema.id, data: { items: deleted } }).then(() => afterDelete?.(schema, deleted));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -54,9 +54,7 @@ export function DlgDeleteCst() {
|
||||||
value={expandOut}
|
value={expandOut}
|
||||||
onChange={value => setExpandOut(value)}
|
onChange={value => setExpandOut(value)}
|
||||||
/>
|
/>
|
||||||
{hasInherited ? (
|
{hasInherited ? <p className='text-sm clr-text-red'>Внимание! Конституенты имеют наследников в ОСС</p> : null}
|
||||||
<p className='text-sm clr-text-red'>Внимание! Выбранные конституенты имеют наследников в ОСС</p>
|
|
||||||
) : null}
|
|
||||||
</ModalForm>
|
</ModalForm>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function ListConstituents({ list, schema, title, prefix }: ListConstituen
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{title ? (
|
{title ? (
|
||||||
<p className='pb-1'>
|
<p className='mb-1'>
|
||||||
{title}: <b>{list.length}</b>
|
{title}: <b>{list.length}</b>
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -28,6 +28,9 @@ interface PreferencesStore {
|
||||||
|
|
||||||
showExpressionControls: boolean;
|
showExpressionControls: boolean;
|
||||||
toggleShowExpressionControls: () => void;
|
toggleShowExpressionControls: () => void;
|
||||||
|
|
||||||
|
showOssSidePanel: boolean;
|
||||||
|
toggleShowOssSidePanel: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const usePreferencesStore = create<PreferencesStore>()(
|
export const usePreferencesStore = create<PreferencesStore>()(
|
||||||
|
@ -76,7 +79,10 @@ export const usePreferencesStore = create<PreferencesStore>()(
|
||||||
toggleShowOSSStats: () => set(state => ({ showOSSStats: !state.showOSSStats })),
|
toggleShowOSSStats: () => set(state => ({ showOSSStats: !state.showOSSStats })),
|
||||||
|
|
||||||
showExpressionControls: true,
|
showExpressionControls: true,
|
||||||
toggleShowExpressionControls: () => set(state => ({ showExpressionControls: !state.showExpressionControls }))
|
toggleShowExpressionControls: () => set(state => ({ showExpressionControls: !state.showExpressionControls })),
|
||||||
|
|
||||||
|
showOssSidePanel: false,
|
||||||
|
toggleShowOssSidePanel: () => set(state => ({ showOssSidePanel: !state.showOssSidePanel }))
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
version: 1,
|
version: 1,
|
||||||
|
|
|
@ -148,6 +148,12 @@
|
||||||
transition-duration: var(--duration-transform);
|
transition-duration: var(--duration-transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@utility cc-animate-panel {
|
||||||
|
transition-property: translate, opacity;
|
||||||
|
transition-timing-function: var(--ease-bezier);
|
||||||
|
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