Compare commits
No commits in common. "d7ee1db6a91967a960e77818e2edaa05e827be3d" and "f3f9c419d419b62b870299938646fd70da604a9d" have entirely different histories.
d7ee1db6a9
...
f3f9c419d4
|
@ -32,10 +32,9 @@ export { RiMenuUnfoldFill as IconMenuUnfold } from 'react-icons/ri';
|
||||||
export { LuMoon as IconDarkTheme } from 'react-icons/lu';
|
export { LuMoon as IconDarkTheme } from 'react-icons/lu';
|
||||||
export { LuSun as IconLightTheme } from 'react-icons/lu';
|
export { LuSun as IconLightTheme } from 'react-icons/lu';
|
||||||
export { LuFolderTree as IconFolderTree } from 'react-icons/lu';
|
export { LuFolderTree as IconFolderTree } from 'react-icons/lu';
|
||||||
export { LuFolder as IconFolder } from 'react-icons/lu';
|
export { FaRegFolder as IconFolder } from 'react-icons/fa6';
|
||||||
export { LuFolderOpen as IconFolderOpened } from 'react-icons/lu';
|
export { FaRegFolderOpen as IconFolderOpened } from 'react-icons/fa6';
|
||||||
export { LuFolderClosed as IconFolderClosed } from 'react-icons/lu';
|
export { FaRegFolderClosed as IconFolderClosed } from 'react-icons/fa6';
|
||||||
export { LuFolderDot as IconFolderEmpty } from 'react-icons/lu';
|
|
||||||
export { LuLightbulb as IconHelp } from 'react-icons/lu';
|
export { LuLightbulb as IconHelp } from 'react-icons/lu';
|
||||||
export { LuLightbulbOff as IconHelpOff } from 'react-icons/lu';
|
export { LuLightbulbOff as IconHelpOff } from 'react-icons/lu';
|
||||||
export { RiPushpinFill as IconPin } from 'react-icons/ri';
|
export { RiPushpinFill as IconPin } from 'react-icons/ri';
|
||||||
|
|
|
@ -77,12 +77,11 @@ export const LibraryState = ({ children }: LibraryStateProps) => {
|
||||||
const [cachedTemplates, setCachedTemplates] = useState<IRSForm[]>([]);
|
const [cachedTemplates, setCachedTemplates] = useState<IRSForm[]>([]);
|
||||||
|
|
||||||
const folders = useMemo(() => {
|
const folders = useMemo(() => {
|
||||||
const result = new FolderTree();
|
const result = new FolderTree(items.map(item => item.location));
|
||||||
result.addPath(LocationHead.USER, 0);
|
result.addPath(LocationHead.USER, 0);
|
||||||
result.addPath(LocationHead.COMMON, 0);
|
result.addPath(LocationHead.COMMON, 0);
|
||||||
result.addPath(LocationHead.LIBRARY, 0);
|
result.addPath(LocationHead.LIBRARY, 0);
|
||||||
result.addPath(LocationHead.PROJECTS, 0);
|
result.addPath(LocationHead.PROJECTS, 0);
|
||||||
items.forEach(item => result.addPath(item.location));
|
|
||||||
return result;
|
return result;
|
||||||
}, [items]);
|
}, [items]);
|
||||||
|
|
||||||
|
|
|
@ -102,9 +102,7 @@ export class FolderTree {
|
||||||
|
|
||||||
private visitNode(target: FolderNode, result: FolderNode[]) {
|
private visitNode(target: FolderNode, result: FolderNode[]) {
|
||||||
result.push(target);
|
result.push(target);
|
||||||
[...target.children.keys()]
|
target.children.forEach(child => this.visitNode(child, result));
|
||||||
.sort((a, b) => a.localeCompare(b))
|
|
||||||
.forEach(key => this.visitNode(target.children.get(key)!, result));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addPath(path: string, filesCount: number = 1): FolderNode {
|
addPath(path: string, filesCount: number = 1): FolderNode {
|
||||||
|
|
|
@ -4,14 +4,12 @@ import clsx from 'clsx';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { IconFolder, IconFolderClosed, IconFolderEmpty, IconFolderOpened, IconFolderTree } from '@/components/Icons';
|
import { IconFolder, IconFolderClosed, IconFolderOpened, IconFolderTree } from '@/components/Icons';
|
||||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
|
||||||
import { CProps } from '@/components/props';
|
import { CProps } from '@/components/props';
|
||||||
import MiniButton from '@/components/ui/MiniButton';
|
import MiniButton from '@/components/ui/MiniButton';
|
||||||
import { FolderNode, FolderTree } from '@/models/FolderTree';
|
import { FolderNode, FolderTree } from '@/models/FolderTree';
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
|
||||||
import { animateSideAppear, animateSideView } from '@/styling/animations';
|
import { animateSideAppear, animateSideView } from '@/styling/animations';
|
||||||
import { globals, PARAMETER, prefixes } from '@/utils/constants';
|
import { globals, prefixes } from '@/utils/constants';
|
||||||
import { describeFolderNode, labelFolderNode } from '@/utils/labels';
|
import { describeFolderNode, labelFolderNode } from '@/utils/labels';
|
||||||
|
|
||||||
interface LibraryTableProps {
|
interface LibraryTableProps {
|
||||||
|
@ -74,16 +72,10 @@ function LibraryFolders({ folders, currentFolder, setFolder, toggleFolderMode }:
|
||||||
animate={{ ...animateSideView.animate }}
|
animate={{ ...animateSideView.animate }}
|
||||||
exit={{ ...animateSideView.exit }}
|
exit={{ ...animateSideView.exit }}
|
||||||
>
|
>
|
||||||
<div className='h-[2.08rem] flex justify-between items-center pr-1'>
|
<div className='h-[2.08rem] flex justify-end pr-1'>
|
||||||
<BadgeHelp
|
|
||||||
topic={HelpTopic.UI_LIBRARY}
|
|
||||||
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'text-sm')}
|
|
||||||
offset={5}
|
|
||||||
place='right-start'
|
|
||||||
/>
|
|
||||||
<MiniButton
|
<MiniButton
|
||||||
icon={<IconFolderTree size='1.25rem' className='icon-green' />}
|
icon={<IconFolderTree size='1.25rem' className='icon-green' />}
|
||||||
title='Переключение в режим Поиск'
|
title='Режим: проводник'
|
||||||
onClick={toggleFolderMode}
|
onClick={toggleFolderMode}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -122,11 +114,7 @@ function LibraryFolders({ folders, currentFolder, setFolder, toggleFolderMode }:
|
||||||
noHover
|
noHover
|
||||||
icon={
|
icon={
|
||||||
folded.includes(item) ? (
|
folded.includes(item) ? (
|
||||||
item.filesInside ? (
|
<IconFolderClosed size='1rem' className='icon-primary' />
|
||||||
<IconFolderClosed size='1rem' className='icon-primary' />
|
|
||||||
) : (
|
|
||||||
<IconFolderEmpty size='1rem' className='icon-primary' />
|
|
||||||
)
|
|
||||||
) : (
|
) : (
|
||||||
<IconFolderOpened size='1rem' className='icon-green' />
|
<IconFolderOpened size='1rem' className='icon-green' />
|
||||||
)
|
)
|
||||||
|
@ -135,11 +123,7 @@ function LibraryFolders({ folders, currentFolder, setFolder, toggleFolderMode }:
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
{item.filesInside ? (
|
<IconFolder size='1rem' />
|
||||||
<IconFolder size='1rem' className='clr-text-default' />
|
|
||||||
) : (
|
|
||||||
<IconFolderEmpty size='1rem' className='clr-text-controls' />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className='self-center'>{labelFolderNode(item)}</div>
|
<div className='self-center'>{labelFolderNode(item)}</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { urls } from '@/app/urls';
|
import { urls } from '@/app/urls';
|
||||||
import { IconFolderTree } from '@/components/Icons';
|
import { IconFolder } from '@/components/Icons';
|
||||||
import BadgeLocation from '@/components/info/BadgeLocation';
|
import BadgeLocation from '@/components/info/BadgeLocation';
|
||||||
import { CProps } from '@/components/props';
|
import { CProps } from '@/components/props';
|
||||||
import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '@/components/ui/DataTable';
|
import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '@/components/ui/DataTable';
|
||||||
|
@ -56,9 +56,11 @@ function LibraryTable({ items, resetQuery, folderMode, toggleFolderMode }: Libra
|
||||||
|
|
||||||
const handleToggleFolder = useCallback(
|
const handleToggleFolder = useCallback(
|
||||||
(event: CProps.EventMouse) => {
|
(event: CProps.EventMouse) => {
|
||||||
event.preventDefault();
|
if (event.ctrlKey) {
|
||||||
event.stopPropagation();
|
event.preventDefault();
|
||||||
toggleFolderMode();
|
event.stopPropagation();
|
||||||
|
toggleFolderMode();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[toggleFolderMode]
|
[toggleFolderMode]
|
||||||
);
|
);
|
||||||
|
@ -72,12 +74,12 @@ function LibraryTable({ items, resetQuery, folderMode, toggleFolderMode }: Libra
|
||||||
id: 'location',
|
id: 'location',
|
||||||
header: () => (
|
header: () => (
|
||||||
<MiniButton
|
<MiniButton
|
||||||
noPadding
|
|
||||||
noHover
|
noHover
|
||||||
|
noPadding
|
||||||
className='pl-2 max-h-[1rem] translate-y-[-0.125rem]'
|
className='pl-2 max-h-[1rem] translate-y-[-0.125rem]'
|
||||||
onClick={handleToggleFolder}
|
onClick={handleToggleFolder}
|
||||||
titleHtml='Переключение в режим Проводник'
|
titleHtml='Ctrl + клик для переключения </br>в режим папок'
|
||||||
icon={<IconFolderTree size='1.25rem' className='clr-text-controls' />}
|
icon={<IconFolder size='1.25rem' className='clr-text-controls' />}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
size: 50,
|
size: 50,
|
||||||
|
|
|
@ -176,12 +176,6 @@ function SearchPanel({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Dropdown isOpen={headMenu.isOpen} stretchLeft className='z-modalTooltip'>
|
<Dropdown isOpen={headMenu.isOpen} stretchLeft className='z-modalTooltip'>
|
||||||
<DropdownButton className='w-[10rem]' title='Переключение в режим Проводник' onClick={handleToggleFolder}>
|
|
||||||
<div className='inline-flex items-center gap-3'>
|
|
||||||
<IconFolderTree size='1rem' className='clr-text-controls' />
|
|
||||||
<span>проводник...</span>
|
|
||||||
</div>
|
|
||||||
</DropdownButton>
|
|
||||||
<DropdownButton className='w-[10rem]' onClick={() => handleChange(undefined)}>
|
<DropdownButton className='w-[10rem]' onClick={() => handleChange(undefined)}>
|
||||||
<div className='inline-flex items-center gap-3'>
|
<div className='inline-flex items-center gap-3'>
|
||||||
<IconFolder size='1rem' className='clr-text-controls' />
|
<IconFolder size='1rem' className='clr-text-controls' />
|
||||||
|
@ -203,6 +197,16 @@ function SearchPanel({
|
||||||
</DropdownButton>
|
</DropdownButton>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
<DropdownButton
|
||||||
|
className='w-[10rem]'
|
||||||
|
title='переключение в режим выбора папок'
|
||||||
|
onClick={handleToggleFolder}
|
||||||
|
>
|
||||||
|
<div className='inline-flex items-center gap-3'>
|
||||||
|
<IconFolderTree size='1rem' className='clr-text-controls' />
|
||||||
|
<span>проводник...</span>
|
||||||
|
</div>
|
||||||
|
</DropdownButton>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -1,14 +1,4 @@
|
||||||
import {
|
import { IconFolder, IconSearch, IconShow, IconSortAsc, IconSortDesc } from '@/components/Icons';
|
||||||
IconFolder,
|
|
||||||
IconFolderClosed,
|
|
||||||
IconFolderEmpty,
|
|
||||||
IconFolderOpened,
|
|
||||||
IconFolderTree,
|
|
||||||
IconSearch,
|
|
||||||
IconShow,
|
|
||||||
IconSortAsc,
|
|
||||||
IconSortDesc
|
|
||||||
} from '@/components/Icons';
|
|
||||||
|
|
||||||
function HelpLibrary() {
|
function HelpLibrary() {
|
||||||
return (
|
return (
|
||||||
|
@ -31,28 +21,6 @@ function HelpLibrary() {
|
||||||
<li>
|
<li>
|
||||||
<IconFolder size='1rem' className='inline-icon' /> фильтр по расположению
|
<IconFolder size='1rem' className='inline-icon' /> фильтр по расположению
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<h2>Проводник</h2>
|
|
||||||
<li>клик по папке отображает справа файлы в ней</li>
|
|
||||||
<li>клик по иконке сворачивает/разворачивает вложенные</li>
|
|
||||||
<li>
|
|
||||||
<IconFolderTree size='1rem' className='inline-icon' /> переключение между Проводник и Поиск
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<IconFolderEmpty size='1rem' className='inline-icon clr-text-default' /> папка без файлов
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<IconFolderEmpty size='1rem' className='inline-icon' /> папка с вложенными без файлов
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<IconFolder size='1rem' className='inline-icon' /> папка без вложенных
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<IconFolderClosed size='1rem' className='inline-icon' /> папка с вложенными и файлами
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<IconFolderOpened size='1rem' className='inline-icon icon-green' /> развернутая папка
|
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ function FormConstituenta({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnimateFade className='mx-0 md:mx-auto'>
|
<AnimateFade>
|
||||||
<ControlsOverlay
|
<ControlsOverlay
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
modified={isModified}
|
modified={isModified}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { GraphLayout } from '@/components/ui/GraphUI';
|
||||||
import { FolderNode } from '@/models/FolderTree';
|
import { FolderNode } from '@/models/FolderTree';
|
||||||
import { GramData, Grammeme, ReferenceType } from '@/models/language';
|
import { GramData, Grammeme, ReferenceType } from '@/models/language';
|
||||||
import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library';
|
import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library';
|
||||||
import { validateLocation } from '@/models/libraryAPI';
|
|
||||||
import { CstMatchMode, DependencyMode, GraphColoring, GraphSizing, HelpTopic } from '@/models/miscellaneous';
|
import { CstMatchMode, DependencyMode, GraphColoring, GraphSizing, HelpTopic } from '@/models/miscellaneous';
|
||||||
import { CstClass, CstType, ExpressionStatus, IConstituenta, IRSForm } from '@/models/rsform';
|
import { CstClass, CstType, ExpressionStatus, IConstituenta, IRSForm } from '@/models/rsform';
|
||||||
import {
|
import {
|
||||||
|
@ -272,10 +271,10 @@ export function describeCstSource(mode: DependencyMode): string {
|
||||||
export function labelLocationHead(head: LocationHead): string {
|
export function labelLocationHead(head: LocationHead): string {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
switch (head) {
|
switch (head) {
|
||||||
case LocationHead.USER: return '/U : личные';
|
case LocationHead.USER: return 'личные (/U)';
|
||||||
case LocationHead.COMMON: return '/S : общие';
|
case LocationHead.COMMON: return 'общие (/S)';
|
||||||
case LocationHead.LIBRARY: return '/L : примеры';
|
case LocationHead.LIBRARY: return 'примеры (/L)';
|
||||||
case LocationHead.PROJECTS: return '/P : проекты';
|
case LocationHead.PROJECTS: return 'проекты (/P)';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,11 +825,7 @@ export function describeAccessMode(mode: UserLevel): string {
|
||||||
* Retrieves label for {@link FolderNode}.
|
* Retrieves label for {@link FolderNode}.
|
||||||
*/
|
*/
|
||||||
export function labelFolderNode(node: FolderNode): string {
|
export function labelFolderNode(node: FolderNode): string {
|
||||||
if (node.parent || !validateLocation('/' + node.text)) {
|
return node.text;
|
||||||
return node.text;
|
|
||||||
} else {
|
|
||||||
return labelLocationHead(('/' + node.text) as LocationHead);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue
Block a user