mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-08-14 04:40:36 +03:00
F: Add block stats to side panel
This commit is contained in:
parent
442a18a795
commit
dc5ff50175
|
@ -41,7 +41,7 @@ export function HelpOssGraph() {
|
|||
<IconFitImage className='inline-icon' /> Вписать в экран
|
||||
</li>
|
||||
<li>
|
||||
<IconLeftOpen className='inline-icon' /> Панель связанной КС
|
||||
<IconLeftOpen className='inline-icon' /> Панель содержания
|
||||
</li>
|
||||
<li>
|
||||
<IconSettings className='inline-icon' /> Диалог настроек
|
||||
|
|
|
@ -236,7 +236,6 @@ export function OssFlow() {
|
|||
showPanel ? 'translate-x-0' : 'opacity-0 translate-x-full pointer-events-none'
|
||||
)}
|
||||
isMounted={showPanel}
|
||||
selectedItems={selectedItems}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import { OperationType } from '../../../../backend/types';
|
||||
import { OssStats } from '../../../../components/oss-stats';
|
||||
import { type IBlock, type IOperationSchema, NodeType } from '../../../../models/oss';
|
||||
|
||||
interface BlockStatsProps {
|
||||
target: IBlock;
|
||||
oss: IOperationSchema;
|
||||
}
|
||||
|
||||
export function BlockStats({ target, oss }: BlockStatsProps) {
|
||||
const contents = oss.hierarchy.expandAllOutputs([target.nodeID]);
|
||||
const items = contents.map(item => oss.itemByNodeID.get(item)).filter(item => !!item);
|
||||
const operations = items.filter(item => item.nodeType === NodeType.OPERATION);
|
||||
const blockStats = {
|
||||
count_all: contents.length,
|
||||
count_inputs: operations.filter(item => item.operation_type === OperationType.INPUT).length,
|
||||
count_synthesis: operations.filter(item => item.operation_type === OperationType.SYNTHESIS).length,
|
||||
count_schemas: operations.filter(item => !!item.result).length,
|
||||
count_owned: operations.filter(item => !!item.result && item.is_owned).length,
|
||||
count_block: contents.length - operations.length
|
||||
};
|
||||
|
||||
return <OssStats stats={blockStats} className='pr-3' />;
|
||||
}
|
|
@ -10,19 +10,23 @@ import { useMainHeight } from '@/stores/app-layout';
|
|||
import { usePreferencesStore } from '@/stores/preferences';
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
|
||||
import { type IOssItem, NodeType } from '../../../../models/oss';
|
||||
import { NodeType } from '../../../../models/oss';
|
||||
import { useOssEdit } from '../../oss-edit-context';
|
||||
|
||||
import { BlockStats } from './block-stats';
|
||||
import { ViewSchema } from './view-schema';
|
||||
|
||||
interface SidePanelProps {
|
||||
selectedItems: IOssItem[];
|
||||
className?: string;
|
||||
isMounted: boolean;
|
||||
}
|
||||
|
||||
export function SidePanel({ selectedItems, isMounted, className }: SidePanelProps) {
|
||||
export function SidePanel({ isMounted, className }: SidePanelProps) {
|
||||
const { schema, isMutable, selectedItems } = useOssEdit();
|
||||
const selectedOperation =
|
||||
selectedItems.length === 1 && selectedItems[0].nodeType === NodeType.OPERATION ? selectedItems[0] : null;
|
||||
const selectedBlock =
|
||||
selectedItems.length === 1 && selectedItems[0].nodeType === NodeType.BLOCK ? selectedItems[0] : null;
|
||||
const selectedSchema = selectedOperation?.result ?? null;
|
||||
|
||||
const debouncedMounted = useDebounce(isMounted, PARAMETER.moveDuration);
|
||||
|
@ -52,21 +56,23 @@ export function SidePanel({ selectedItems, isMounted, className }: SidePanelProp
|
|||
'mt-0 mb-1',
|
||||
'font-medium text-sm select-none self-center',
|
||||
'transition-transform',
|
||||
selectedSchema && 'translate-x-16'
|
||||
selectedSchema && 'translate-x-20'
|
||||
)}
|
||||
>
|
||||
Содержание КС
|
||||
Содержание
|
||||
</div>
|
||||
|
||||
{!selectedOperation ? (
|
||||
<div className='text-center text-sm cc-fade-in'>Выделите операцию для просмотра</div>
|
||||
) : !selectedSchema ? (
|
||||
{!selectedOperation && !selectedBlock ? (
|
||||
<div className='text-center text-sm cc-fade-in'>Выделите операцию или блок для просмотра</div>
|
||||
) : null}
|
||||
{selectedOperation && !selectedSchema ? (
|
||||
<div className='text-center text-sm cc-fade-in'>Отсутствует концептуальная схема для выбранной операции</div>
|
||||
) : debouncedMounted ? (
|
||||
) : selectedOperation && selectedSchema && debouncedMounted ? (
|
||||
<Suspense fallback={<Loader />}>
|
||||
<ViewSchema schemaID={selectedSchema} />
|
||||
<ViewSchema schemaID={selectedSchema} isMutable={isMutable && selectedOperation.is_owned} />
|
||||
</Suspense>
|
||||
) : null}
|
||||
{selectedBlock ? <BlockStats target={selectedBlock} oss={schema} /> : null}
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import { type RO } from '@/utils/meta';
|
|||
|
||||
interface ToolbarConstituentsProps {
|
||||
schema: IRSForm;
|
||||
isMutable: boolean;
|
||||
activeCst: IConstituenta | null;
|
||||
setActive: (cstID: number) => void;
|
||||
resetActive: () => void;
|
||||
|
@ -27,6 +28,7 @@ export function ToolbarConstituents({
|
|||
activeCst,
|
||||
setActive,
|
||||
resetActive,
|
||||
isMutable,
|
||||
className
|
||||
}: ToolbarConstituentsProps) {
|
||||
const router = useConceptNavigation();
|
||||
|
@ -162,33 +164,33 @@ export function ToolbarConstituents({
|
|||
title='Создать конституенту'
|
||||
icon={<IconNewItem size='1rem' className='icon-green' />}
|
||||
onClick={createCst}
|
||||
disabled={isProcessing}
|
||||
disabled={!isMutable || isProcessing}
|
||||
/>
|
||||
<MiniButton
|
||||
title='Клонировать конституенту'
|
||||
icon={<IconClone size='1rem' className='icon-green' />}
|
||||
onClick={cloneCst}
|
||||
disabled={!activeCst || isProcessing}
|
||||
disabled={!isMutable || !activeCst || isProcessing}
|
||||
/>
|
||||
|
||||
<MiniButton
|
||||
title='Удалить выделенную конституенту'
|
||||
onClick={promptDeleteCst}
|
||||
icon={<IconDestroy size='1rem' className='icon-red' />}
|
||||
disabled={!activeCst || isProcessing || activeCst?.is_inherited}
|
||||
disabled={!isMutable || !activeCst || isProcessing || activeCst?.is_inherited}
|
||||
/>
|
||||
|
||||
<MiniButton
|
||||
title='Переместить вверх'
|
||||
icon={<IconMoveUp size='1rem' className='icon-primary' />}
|
||||
onClick={moveUp}
|
||||
disabled={!activeCst || isProcessing || schema.items.length < 2 || hasSearch}
|
||||
disabled={!isMutable || !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}
|
||||
disabled={!isMutable || !activeCst || isProcessing || schema.items.length < 2 || hasSearch}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -10,9 +10,10 @@ import { ToolbarConstituents } from './toolbar-constituents';
|
|||
|
||||
interface ViewSchemaProps {
|
||||
schemaID: number;
|
||||
isMutable: boolean;
|
||||
}
|
||||
|
||||
export function ViewSchema({ schemaID }: ViewSchemaProps) {
|
||||
export function ViewSchema({ schemaID, isMutable }: ViewSchemaProps) {
|
||||
const { schema } = useRSFormSuspense({ itemID: schemaID });
|
||||
const [activeID, setActiveID] = useState<number | null>(null);
|
||||
const activeCst = activeID ? schema.cstByID.get(activeID) ?? null : null;
|
||||
|
@ -25,6 +26,7 @@ export function ViewSchema({ schemaID }: ViewSchemaProps) {
|
|||
className='absolute -top-7 left-1'
|
||||
schema={schema}
|
||||
activeCst={activeCst}
|
||||
isMutable={isMutable}
|
||||
setActive={setActiveID}
|
||||
resetActive={() => setActiveID(null)}
|
||||
/>
|
||||
|
|
|
@ -115,7 +115,7 @@ export function ToolbarOssGraph({
|
|||
onClick={resetView}
|
||||
/>
|
||||
<MiniButton
|
||||
title='Панель содержания КС'
|
||||
title='Панель содержания'
|
||||
icon={<IconShowSidebar value={showSidePanel} isBottom={false} size='1.25rem' />}
|
||||
onClick={toggleShowSidePanel}
|
||||
/>
|
||||
|
|
|
@ -98,7 +98,7 @@ export function TableSideConstituents({
|
|||
noDataComponent={
|
||||
<NoData className='min-h-20'>
|
||||
<p>Список конституент пуст</p>
|
||||
<p>Измените параметры фильтра</p>
|
||||
<p>Измените параметры фильтра или создайте конституенту</p>
|
||||
</NoData>
|
||||
}
|
||||
onRowClicked={onActivate ? cst => onActivate(cst) : undefined}
|
||||
|
|
Loading…
Reference in New Issue
Block a user