mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-08-14 12:50:37 +03:00
M: Small UI fixes
This commit is contained in:
parent
35faeb580b
commit
709471356f
|
@ -62,7 +62,7 @@ function domTooltipVariable(varName: string, isAvailable: boolean): TooltipView
|
||||||
dom.className = clsx(
|
dom.className = clsx(
|
||||||
'max-h-100 max-w-100 min-w-40',
|
'max-h-100 max-w-100 min-w-40',
|
||||||
'dense',
|
'dense',
|
||||||
'px-2 py-1 flex flex-col',
|
'p-2 flex flex-col',
|
||||||
'rounded-md shadow-md',
|
'rounded-md shadow-md',
|
||||||
'cc-scroll-y',
|
'cc-scroll-y',
|
||||||
'text-sm bg-card',
|
'text-sm bg-card',
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
|
|
||||||
import { type IBlock, type IOperationSchema } from '@/features/oss/models/oss';
|
import { type IBlock, type IOperation, type IOperationSchema } from '@/features/oss/models/oss';
|
||||||
import { type IConstituenta, type IRSForm } from '@/features/rsform';
|
import { type IConstituenta, type IRSForm } from '@/features/rsform';
|
||||||
|
|
||||||
import { PromptVariableType } from '../models/prompting';
|
import { PromptVariableType } from '../models/prompting';
|
||||||
|
@ -25,6 +25,9 @@ interface AIContextStore {
|
||||||
currentBlock: IBlock | null;
|
currentBlock: IBlock | null;
|
||||||
setCurrentBlock: (value: IBlock | null) => void;
|
setCurrentBlock: (value: IBlock | null) => void;
|
||||||
|
|
||||||
|
currentOperation: IOperation | null;
|
||||||
|
setCurrentOperation: (value: IOperation | null) => void;
|
||||||
|
|
||||||
currentConstituenta: IConstituenta | null;
|
currentConstituenta: IConstituenta | null;
|
||||||
setCurrentConstituenta: (value: IConstituenta | null) => void;
|
setCurrentConstituenta: (value: IConstituenta | null) => void;
|
||||||
}
|
}
|
||||||
|
@ -39,6 +42,9 @@ export const useAIStore = create<AIContextStore>()(set => ({
|
||||||
currentBlock: null,
|
currentBlock: null,
|
||||||
setCurrentBlock: value => set({ currentBlock: value }),
|
setCurrentBlock: value => set({ currentBlock: value }),
|
||||||
|
|
||||||
|
currentOperation: null,
|
||||||
|
setCurrentOperation: value => set({ currentOperation: value }),
|
||||||
|
|
||||||
currentConstituenta: null,
|
currentConstituenta: null,
|
||||||
setCurrentConstituenta: value => set({ currentConstituenta: value })
|
setCurrentConstituenta: value => set({ currentConstituenta: value })
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -119,10 +119,10 @@ export function DlgRelocateConstituents() {
|
||||||
helpTopic={HelpTopic.UI_RELOCATE_CST}
|
helpTopic={HelpTopic.UI_RELOCATE_CST}
|
||||||
>
|
>
|
||||||
<div className='flex flex-col border'>
|
<div className='flex flex-col border'>
|
||||||
<div className='flex gap-1 items-center bg-input border-b rounded-t-md'>
|
<div className='flex justify-between gap-1 items-center bg-input border-b rounded-t-md max-w-full'>
|
||||||
<SelectLibraryItem
|
<SelectLibraryItem
|
||||||
noBorder
|
noBorder
|
||||||
className='w-1/2 shrink-1'
|
className='w-69'
|
||||||
placeholder='Исходная схема'
|
placeholder='Исходная схема'
|
||||||
items={sourceSchemas}
|
items={sourceSchemas}
|
||||||
value={source}
|
value={source}
|
||||||
|
@ -135,7 +135,7 @@ export function DlgRelocateConstituents() {
|
||||||
/>
|
/>
|
||||||
<SelectLibraryItem
|
<SelectLibraryItem
|
||||||
noBorder
|
noBorder
|
||||||
className='w-1/2 shrink-1'
|
className='w-69'
|
||||||
placeholder='Целевая схема'
|
placeholder='Целевая схема'
|
||||||
items={destinationSchemas}
|
items={destinationSchemas}
|
||||||
value={destinationItem}
|
value={destinationItem}
|
||||||
|
|
|
@ -180,7 +180,7 @@ export class LayoutManager {
|
||||||
const rootElements = this.oss.hierarchy.rootNodes();
|
const rootElements = this.oss.hierarchy.rootNodes();
|
||||||
const positions = this.layout.filter(pos => rootElements.includes(pos.nodeID));
|
const positions = this.layout.filter(pos => rootElements.includes(pos.nodeID));
|
||||||
preventOverlap(newPosition, positions);
|
preventOverlap(newPosition, positions);
|
||||||
} else if (!rectanglesOverlap(target, parent)) {
|
} else if (!rectanglesStrictOverlap(target, parent)) {
|
||||||
newPosition.x = parent.x + MIN_DISTANCE;
|
newPosition.x = parent.x + MIN_DISTANCE;
|
||||||
newPosition.y = parent.y + MIN_DISTANCE;
|
newPosition.y = parent.y + MIN_DISTANCE;
|
||||||
|
|
||||||
|
@ -202,6 +202,10 @@ function rectanglesOverlap(a: Rectangle2D, b: Rectangle2D): boolean {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rectanglesStrictOverlap(a: Rectangle2D, b: Rectangle2D): boolean {
|
||||||
|
return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y);
|
||||||
|
}
|
||||||
|
|
||||||
function preventOverlap(
|
function preventOverlap(
|
||||||
target: Rectangle2D,
|
target: Rectangle2D,
|
||||||
fixedRectangles: Rectangle2D[],
|
fixedRectangles: Rectangle2D[],
|
||||||
|
|
|
@ -34,6 +34,8 @@ export interface OperationInternalNode {
|
||||||
data: {
|
data: {
|
||||||
label: string;
|
label: string;
|
||||||
operation: IOperation;
|
operation: IOperation;
|
||||||
|
isParent: boolean;
|
||||||
|
isChild: boolean;
|
||||||
};
|
};
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
dragging: boolean;
|
dragging: boolean;
|
||||||
|
@ -47,6 +49,8 @@ export interface BlockInternalNode {
|
||||||
data: {
|
data: {
|
||||||
label: string;
|
label: string;
|
||||||
block: IBlock;
|
block: IBlock;
|
||||||
|
isParent: boolean;
|
||||||
|
isChild: boolean;
|
||||||
};
|
};
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
dragging: boolean;
|
dragging: boolean;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { useAIStore } from '@/features/ai/stores/ai-context';
|
||||||
import { type IConstituenta } from '@/features/rsform';
|
import { type IConstituenta } from '@/features/rsform';
|
||||||
import { useRSFormSuspense } from '@/features/rsform/backend/use-rsform';
|
import { useRSFormSuspense } from '@/features/rsform/backend/use-rsform';
|
||||||
import { RSFormStats } from '@/features/rsform/components/rsform-stats';
|
import { RSFormStats } from '@/features/rsform/components/rsform-stats';
|
||||||
|
@ -20,9 +21,15 @@ export function ViewSchema({ schemaID, isMutable }: ViewSchemaProps) {
|
||||||
const [activeID, setActiveID] = useState<number | null>(null);
|
const [activeID, setActiveID] = useState<number | null>(null);
|
||||||
const activeCst = activeID ? schema.cstByID.get(activeID) ?? null : null;
|
const activeCst = activeID ? schema.cstByID.get(activeID) ?? null : null;
|
||||||
const showEditCst = useDialogsStore(state => state.showEditCst);
|
const showEditCst = useDialogsStore(state => state.showEditCst);
|
||||||
|
const setCurrentSchema = useAIStore(state => state.setCurrentSchema);
|
||||||
|
|
||||||
const listHeight = useFitHeight('14.5rem', '10rem');
|
const listHeight = useFitHeight('14.5rem', '10rem');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentSchema(schema);
|
||||||
|
return () => setCurrentSchema(null);
|
||||||
|
}, [schema, setCurrentSchema]);
|
||||||
|
|
||||||
function handleEditCst(cst: IConstituenta) {
|
function handleEditCst(cst: IConstituenta) {
|
||||||
showEditCst({ schema: schema, target: cst });
|
showEditCst({ schema: schema, target: cst });
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ export const OssEditState = ({ itemID, children }: React.PropsWithChildren<OssEd
|
||||||
const searchLocation = useLibrarySearchStore(state => state.location);
|
const searchLocation = useLibrarySearchStore(state => state.location);
|
||||||
const setCurrentOSS = useAIStore(state => state.setCurrentOSS);
|
const setCurrentOSS = useAIStore(state => state.setCurrentOSS);
|
||||||
const setCurrentBlock = useAIStore(state => state.setCurrentBlock);
|
const setCurrentBlock = useAIStore(state => state.setCurrentBlock);
|
||||||
|
const setCurrentOperation = useAIStore(state => state.setCurrentOperation);
|
||||||
|
|
||||||
const { user } = useAuthSuspense();
|
const { user } = useAuthSuspense();
|
||||||
const { schema } = useOssSuspense({ itemID: itemID });
|
const { schema } = useOssSuspense({ itemID: itemID });
|
||||||
|
@ -67,6 +68,15 @@ export const OssEditState = ({ itemID, children }: React.PropsWithChildren<OssEd
|
||||||
setCurrentBlock(null);
|
setCurrentBlock(null);
|
||||||
}, [selectedItems, setCurrentBlock]);
|
}, [selectedItems, setCurrentBlock]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const selectedOperation = selectedItems.find(item => item.nodeType === NodeType.OPERATION);
|
||||||
|
if (selectedOperation) {
|
||||||
|
setCurrentOperation(selectedOperation);
|
||||||
|
return () => setCurrentOperation(null);
|
||||||
|
}
|
||||||
|
setCurrentOperation(null);
|
||||||
|
}, [selectedItems, setCurrentOperation]);
|
||||||
|
|
||||||
function navigateTab(tab: OssTabID) {
|
function navigateTab(tab: OssTabID) {
|
||||||
const url = urls.oss_props({
|
const url = urls.oss_props({
|
||||||
id: schema.id,
|
id: schema.id,
|
||||||
|
|
|
@ -166,7 +166,7 @@ export function TGFlow() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative' tabIndex={-1} onKeyDown={handleKeyDown}>
|
<div className='relative' tabIndex={-1} onKeyDown={handleKeyDown}>
|
||||||
<div className='flex flex-col items-center rounded-b-2xl backdrop-blur-xs'>
|
<div className='cc-tab-tools flex flex-col items-center rounded-b-2xl backdrop-blur-xs'>
|
||||||
<ToolbarTermGraph />
|
<ToolbarTermGraph />
|
||||||
<ToolbarFocusedCst focus={focusCst} resetFocus={() => setFocus(null)} />
|
<ToolbarFocusedCst focus={focusCst} resetFocus={() => setFocus(null)} />
|
||||||
{!focusCst ? (
|
{!focusCst ? (
|
||||||
|
|
Loading…
Reference in New Issue
Block a user