Compare commits
No commits in common. "7f067772376bb5df8a7ec37aae90ca2fdb8d5d67" and "0149f98c8b9cdc49039504813f1c0327e3a2bd80" have entirely different histories.
7f06777237
...
0149f98c8b
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -216,7 +216,6 @@
|
||||||
"Терминологизация",
|
"Терминологизация",
|
||||||
"троллинг",
|
"троллинг",
|
||||||
"Тулисов",
|
"Тулисов",
|
||||||
"Хаданович",
|
|
||||||
"Цермелло",
|
"Цермелло",
|
||||||
"ЦИВТ",
|
"ЦИВТ",
|
||||||
"Чувашов",
|
"Чувашов",
|
||||||
|
|
|
@ -16,7 +16,7 @@ interface BadgeConstituentaProps extends CProps.Styling {
|
||||||
function BadgeConstituenta({ value, prefixID, className, style, theme }: BadgeConstituentaProps) {
|
function BadgeConstituenta({ value, prefixID, className, style, theme }: BadgeConstituentaProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id={`${prefixID}${value.id}`}
|
id={`${prefixID}${value.alias}`}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'min-w-[3.1rem] max-w-[3.1rem]',
|
'min-w-[3.1rem] max-w-[3.1rem]',
|
||||||
'px-1',
|
'px-1',
|
||||||
|
@ -33,7 +33,7 @@ function BadgeConstituenta({ value, prefixID, className, style, theme }: BadgeCo
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{value.alias}
|
{value.alias}
|
||||||
<TooltipConstituenta anchor={`#${prefixID}${value.id}`} data={value} />
|
<TooltipConstituenta anchor={`#${prefixID}${value.alias}`} data={value} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,11 +182,7 @@ function PickSubstitutions({
|
||||||
id: 'left_alias',
|
id: 'left_alias',
|
||||||
size: 65,
|
size: 65,
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<BadgeConstituenta
|
<BadgeConstituenta theme={colors} value={props.row.original.substitution} prefixID={`${prefixID}_1_`} />
|
||||||
theme={colors}
|
|
||||||
value={props.row.original.substitution}
|
|
||||||
prefixID={`${prefixID}_${props.row.index}_1_`}
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
columnHelper.display({
|
columnHelper.display({
|
||||||
|
@ -198,11 +194,7 @@ function PickSubstitutions({
|
||||||
id: 'right_alias',
|
id: 'right_alias',
|
||||||
size: 65,
|
size: 65,
|
||||||
cell: props => (
|
cell: props => (
|
||||||
<BadgeConstituenta
|
<BadgeConstituenta theme={colors} value={props.row.original.original} prefixID={`${prefixID}_2_`} />
|
||||||
theme={colors}
|
|
||||||
value={props.row.original.original}
|
|
||||||
prefixID={`${prefixID}_${props.row.index}_2_`}
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor(item => item.original_source.alias, {
|
columnHelper.accessor(item => item.original_source.alias, {
|
||||||
|
|
|
@ -34,12 +34,6 @@ interface IOptionsContext {
|
||||||
showHelp: boolean;
|
showHelp: boolean;
|
||||||
toggleShowHelp: () => void;
|
toggleShowHelp: () => void;
|
||||||
|
|
||||||
folderMode: boolean;
|
|
||||||
setFolderMode: React.Dispatch<React.SetStateAction<boolean>>;
|
|
||||||
|
|
||||||
location: string;
|
|
||||||
setLocation: React.Dispatch<React.SetStateAction<string>>;
|
|
||||||
|
|
||||||
calculateHeight: (offset: string, minimum?: string) => string;
|
calculateHeight: (offset: string, minimum?: string) => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,9 +56,6 @@ export const OptionsState = ({ children }: OptionsStateProps) => {
|
||||||
const [showHelp, setShowHelp] = useLocalStorage(storage.optionsHelp, true);
|
const [showHelp, setShowHelp] = useLocalStorage(storage.optionsHelp, true);
|
||||||
const [noNavigation, setNoNavigation] = useState(false);
|
const [noNavigation, setNoNavigation] = useState(false);
|
||||||
|
|
||||||
const [folderMode, setFolderMode] = useLocalStorage<boolean>(storage.librarySearchFolderMode, true);
|
|
||||||
const [location, setLocation] = useLocalStorage<string>(storage.librarySearchLocation, '');
|
|
||||||
|
|
||||||
const [colors, setColors] = useState<IColorTheme>(lightT);
|
const [colors, setColors] = useState<IColorTheme>(lightT);
|
||||||
|
|
||||||
const [noNavigationAnimation, setNoNavigationAnimation] = useState(false);
|
const [noNavigationAnimation, setNoNavigationAnimation] = useState(false);
|
||||||
|
@ -140,10 +131,6 @@ export const OptionsState = ({ children }: OptionsStateProps) => {
|
||||||
noNavigationAnimation,
|
noNavigationAnimation,
|
||||||
noNavigation,
|
noNavigation,
|
||||||
noFooter,
|
noFooter,
|
||||||
folderMode,
|
|
||||||
setFolderMode,
|
|
||||||
location,
|
|
||||||
setLocation,
|
|
||||||
showScroll,
|
showScroll,
|
||||||
showHelp,
|
showHelp,
|
||||||
toggleDarkMode: toggleDarkMode,
|
toggleDarkMode: toggleDarkMode,
|
||||||
|
|
|
@ -301,13 +301,12 @@ export const OssState = ({ itemID, children }: OssStateProps) => {
|
||||||
onError: setProcessingError,
|
onError: setProcessingError,
|
||||||
onSuccess: newData => {
|
onSuccess: newData => {
|
||||||
oss.setData(newData);
|
oss.setData(newData);
|
||||||
library.reloadItems(() => {
|
library.localUpdateTimestamp(newData.id);
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[itemID, model, library.reloadItems, oss.setData]
|
[itemID, model, library.localUpdateTimestamp, oss.setData]
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateOperation = useCallback(
|
const updateOperation = useCallback(
|
||||||
|
|
|
@ -39,7 +39,7 @@ function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstPro
|
||||||
canSubmit={validated}
|
canSubmit={validated}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
submitText='Создать'
|
submitText='Создать'
|
||||||
className='cc-column w-[35rem] max-h-[30rem] py-2 px-6'
|
className='cc-column w-[35rem] h-[30rem] py-2 px-6'
|
||||||
>
|
>
|
||||||
<FormCreateCst schema={schema} state={cstData} partialUpdate={updateCstData} setValidated={setValidated} />
|
<FormCreateCst schema={schema} state={cstData} partialUpdate={updateCstData} setValidated={setValidated} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -45,7 +45,7 @@ function DlgCreateOperation({ hideWindow, oss, onCreate, initialInputs }: DlgCre
|
||||||
if (alias === '') {
|
if (alias === '') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (activeTab === TabID.SYNTHESIS && inputs.length === 0) {
|
if (activeTab === TabID.SYNTHESIS && inputs.length === 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (activeTab === TabID.INPUT && !attachedID) {
|
if (activeTab === TabID.INPUT && !attachedID) {
|
||||||
|
|
|
@ -48,8 +48,7 @@ function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperatio
|
||||||
const [isCorrect, setIsCorrect] = useState(true);
|
const [isCorrect, setIsCorrect] = useState(true);
|
||||||
const [validationText, setValidationText] = useState('');
|
const [validationText, setValidationText] = useState('');
|
||||||
|
|
||||||
const initialInputs = useMemo(() => oss.graph.expandInputs([target.id]), [oss.graph, target.id]);
|
const [inputs, setInputs] = useState<OperationID[]>(oss.graph.expandInputs([target.id]));
|
||||||
const [inputs, setInputs] = useState<OperationID[]>(initialInputs);
|
|
||||||
const inputOperations = useMemo(() => inputs.map(id => oss.operationByID.get(id)!), [inputs, oss.operationByID]);
|
const inputOperations = useMemo(() => inputs.map(id => oss.operationByID.get(id)!), [inputs, oss.operationByID]);
|
||||||
const schemasIDs = useMemo(
|
const schemasIDs = useMemo(
|
||||||
() => inputOperations.map(operation => operation.result).filter(id => id !== null),
|
() => inputOperations.map(operation => operation.result).filter(id => id !== null),
|
||||||
|
@ -65,28 +64,7 @@ function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperatio
|
||||||
[schemasIDs, cache.getSchema]
|
[schemasIDs, cache.getSchema]
|
||||||
);
|
);
|
||||||
|
|
||||||
const isModified = useMemo(
|
const canSubmit = useMemo(() => alias !== '', [alias]);
|
||||||
() =>
|
|
||||||
alias !== target.alias ||
|
|
||||||
title !== target.title ||
|
|
||||||
comment !== target.comment ||
|
|
||||||
JSON.stringify(initialInputs) !== JSON.stringify(inputs) ||
|
|
||||||
JSON.stringify(substitutions) !== JSON.stringify(target.substitutions),
|
|
||||||
[
|
|
||||||
alias,
|
|
||||||
title,
|
|
||||||
comment,
|
|
||||||
target.alias,
|
|
||||||
target.title,
|
|
||||||
target.comment,
|
|
||||||
initialInputs,
|
|
||||||
inputs,
|
|
||||||
substitutions,
|
|
||||||
target.substitutions
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
const canSubmit = useMemo(() => isModified && alias !== '', [isModified, alias]);
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
cache.preload(schemasIDs);
|
cache.preload(schemasIDs);
|
||||||
|
|
|
@ -23,14 +23,6 @@ function TabSchema({ selected, receiver, setSelected }: TabSchemaProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnimateFade className='flex flex-col'>
|
<AnimateFade className='flex flex-col'>
|
||||||
<PickSchema
|
|
||||||
id='dlg_schema_picker' // prettier: split lines
|
|
||||||
items={sortedItems}
|
|
||||||
itemType={LibraryItemType.RSFORM}
|
|
||||||
rows={14}
|
|
||||||
value={selected}
|
|
||||||
onSelectValue={setSelected}
|
|
||||||
/>
|
|
||||||
<div className='flex items-center gap-6'>
|
<div className='flex items-center gap-6'>
|
||||||
<span className='select-none'>Выбрана</span>
|
<span className='select-none'>Выбрана</span>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
@ -43,6 +35,14 @@ function TabSchema({ selected, receiver, setSelected }: TabSchemaProps) {
|
||||||
dense
|
dense
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<PickSchema
|
||||||
|
id='dlg_schema_picker' // prettier: split lines
|
||||||
|
items={sortedItems}
|
||||||
|
itemType={LibraryItemType.RSFORM}
|
||||||
|
rows={14}
|
||||||
|
value={selected}
|
||||||
|
onSelectValue={setSelected}
|
||||||
|
/>
|
||||||
</AnimateFade>
|
</AnimateFade>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,18 +20,17 @@ import SubmitButton from '@/components/ui/SubmitButton';
|
||||||
import TextArea from '@/components/ui/TextArea';
|
import TextArea from '@/components/ui/TextArea';
|
||||||
import TextInput from '@/components/ui/TextInput';
|
import TextInput from '@/components/ui/TextInput';
|
||||||
import { useAuth } from '@/context/AuthContext';
|
import { useAuth } from '@/context/AuthContext';
|
||||||
import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
|
||||||
import { useLibrary } from '@/context/LibraryContext';
|
import { useLibrary } from '@/context/LibraryContext';
|
||||||
import { useConceptNavigation } from '@/context/NavigationContext';
|
import { useConceptNavigation } from '@/context/NavigationContext';
|
||||||
|
import useLocalStorage from '@/hooks/useLocalStorage';
|
||||||
import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library';
|
import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library';
|
||||||
import { ILibraryCreateData } from '@/models/library';
|
import { ILibraryCreateData } from '@/models/library';
|
||||||
import { combineLocation, validateLocation } from '@/models/libraryAPI';
|
import { combineLocation, validateLocation } from '@/models/libraryAPI';
|
||||||
import { EXTEOR_TRS_FILE } from '@/utils/constants';
|
import { EXTEOR_TRS_FILE, storage } from '@/utils/constants';
|
||||||
import { information } from '@/utils/labels';
|
import { information } from '@/utils/labels';
|
||||||
|
|
||||||
function FormCreateItem() {
|
function FormCreateItem() {
|
||||||
const router = useConceptNavigation();
|
const router = useConceptNavigation();
|
||||||
const options = useConceptOptions();
|
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { createItem, processingError, setProcessingError, processing, folders } = useLibrary();
|
const { createItem, processingError, setProcessingError, processing, folders } = useLibrary();
|
||||||
|
|
||||||
|
@ -47,6 +46,7 @@ function FormCreateItem() {
|
||||||
|
|
||||||
const location = useMemo(() => combineLocation(head, body), [head, body]);
|
const location = useMemo(() => combineLocation(head, body), [head, body]);
|
||||||
const isValid = useMemo(() => validateLocation(location), [location]);
|
const isValid = useMemo(() => validateLocation(location), [location]);
|
||||||
|
const [initLocation, setInitLocation] = useLocalStorage<string>(storage.librarySearchLocation, '');
|
||||||
|
|
||||||
const [fileName, setFileName] = useState('');
|
const [fileName, setFileName] = useState('');
|
||||||
const [file, setFile] = useState<File | undefined>();
|
const [file, setFile] = useState<File | undefined>();
|
||||||
|
@ -81,7 +81,7 @@ function FormCreateItem() {
|
||||||
file: file,
|
file: file,
|
||||||
fileName: file?.name
|
fileName: file?.name
|
||||||
};
|
};
|
||||||
options.setLocation(location);
|
setInitLocation(location);
|
||||||
createItem(data, newItem => {
|
createItem(data, newItem => {
|
||||||
toast.success(information.newLibraryItem);
|
toast.success(information.newLibraryItem);
|
||||||
if (itemType == LibraryItemType.RSFORM) {
|
if (itemType == LibraryItemType.RSFORM) {
|
||||||
|
@ -108,11 +108,11 @@ function FormCreateItem() {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (!options.location) {
|
if (!initLocation) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handleSelectLocation(options.location);
|
handleSelectLocation(initLocation);
|
||||||
}, [options.location, handleSelectLocation]);
|
}, [initLocation, handleSelectLocation]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (itemType !== LibraryItemType.RSFORM) {
|
if (itemType !== LibraryItemType.RSFORM) {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import MiniButton from '@/components/ui/MiniButton';
|
||||||
import Overlay from '@/components/ui/Overlay';
|
import Overlay from '@/components/ui/Overlay';
|
||||||
import DataLoader from '@/components/wrap/DataLoader';
|
import DataLoader from '@/components/wrap/DataLoader';
|
||||||
import { useAuth } from '@/context/AuthContext';
|
import { useAuth } from '@/context/AuthContext';
|
||||||
import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
|
||||||
import { useLibrary } from '@/context/LibraryContext';
|
import { useLibrary } from '@/context/LibraryContext';
|
||||||
import DlgChangeLocation from '@/dialogs/DlgChangeLocation';
|
import DlgChangeLocation from '@/dialogs/DlgChangeLocation';
|
||||||
import useLocalStorage from '@/hooks/useLocalStorage';
|
import useLocalStorage from '@/hooks/useLocalStorage';
|
||||||
|
@ -28,13 +27,14 @@ function LibraryPage() {
|
||||||
const library = useLibrary();
|
const library = useLibrary();
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const [items, setItems] = useState<ILibraryItem[]>([]);
|
const [items, setItems] = useState<ILibraryItem[]>([]);
|
||||||
const options = useConceptOptions();
|
|
||||||
|
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
const [path, setPath] = useState('');
|
const [path, setPath] = useState('');
|
||||||
|
|
||||||
const [head, setHead] = useLocalStorage<LocationHead | undefined>(storage.librarySearchHead, undefined);
|
const [head, setHead] = useLocalStorage<LocationHead | undefined>(storage.librarySearchHead, undefined);
|
||||||
|
const [folderMode, setFolderMode] = useLocalStorage<boolean>(storage.librarySearchFolderMode, true);
|
||||||
const [subfolders, setSubfolders] = useLocalStorage<boolean>(storage.librarySearchSubfolders, false);
|
const [subfolders, setSubfolders] = useLocalStorage<boolean>(storage.librarySearchSubfolders, false);
|
||||||
|
const [location, setLocation] = useLocalStorage<string>(storage.librarySearchLocation, '');
|
||||||
const [isVisible, setIsVisible] = useLocalStorage<boolean | undefined>(storage.librarySearchVisible, true);
|
const [isVisible, setIsVisible] = useLocalStorage<boolean | undefined>(storage.librarySearchVisible, true);
|
||||||
const [isOwned, setIsOwned] = useLocalStorage<boolean | undefined>(storage.librarySearchEditor, undefined);
|
const [isOwned, setIsOwned] = useLocalStorage<boolean | undefined>(storage.librarySearchEditor, undefined);
|
||||||
const [isEditor, setIsEditor] = useLocalStorage<boolean | undefined>(storage.librarySearchEditor, undefined);
|
const [isEditor, setIsEditor] = useLocalStorage<boolean | undefined>(storage.librarySearchEditor, undefined);
|
||||||
|
@ -48,11 +48,11 @@ function LibraryPage() {
|
||||||
isEditor: user ? isEditor : undefined,
|
isEditor: user ? isEditor : undefined,
|
||||||
isOwned: user ? isOwned : undefined,
|
isOwned: user ? isOwned : undefined,
|
||||||
isVisible: user ? isVisible : true,
|
isVisible: user ? isVisible : true,
|
||||||
folderMode: options.folderMode,
|
folderMode: folderMode,
|
||||||
subfolders: subfolders,
|
subfolders: subfolders,
|
||||||
location: options.location
|
location: location
|
||||||
}),
|
}),
|
||||||
[head, path, query, isEditor, isOwned, isVisible, user, options.folderMode, options.location, subfolders]
|
[head, path, query, isEditor, isOwned, isVisible, user, folderMode, location, subfolders]
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasCustomFilter = useMemo(
|
const hasCustomFilter = useMemo(
|
||||||
|
@ -74,7 +74,7 @@ function LibraryPage() {
|
||||||
const toggleVisible = useCallback(() => setIsVisible(prev => toggleTristateFlag(prev)), [setIsVisible]);
|
const toggleVisible = useCallback(() => setIsVisible(prev => toggleTristateFlag(prev)), [setIsVisible]);
|
||||||
const toggleOwned = useCallback(() => setIsOwned(prev => toggleTristateFlag(prev)), [setIsOwned]);
|
const toggleOwned = useCallback(() => setIsOwned(prev => toggleTristateFlag(prev)), [setIsOwned]);
|
||||||
const toggleEditor = useCallback(() => setIsEditor(prev => toggleTristateFlag(prev)), [setIsEditor]);
|
const toggleEditor = useCallback(() => setIsEditor(prev => toggleTristateFlag(prev)), [setIsEditor]);
|
||||||
const toggleFolderMode = useCallback(() => options.setFolderMode(prev => !prev), [options.setFolderMode]);
|
const toggleFolderMode = useCallback(() => setFolderMode(prev => !prev), [setFolderMode]);
|
||||||
const toggleSubfolders = useCallback(() => setSubfolders(prev => !prev), [setSubfolders]);
|
const toggleSubfolders = useCallback(() => setSubfolders(prev => !prev), [setSubfolders]);
|
||||||
|
|
||||||
const resetFilter = useCallback(() => {
|
const resetFilter = useCallback(() => {
|
||||||
|
@ -84,8 +84,8 @@ function LibraryPage() {
|
||||||
setIsVisible(true);
|
setIsVisible(true);
|
||||||
setIsOwned(undefined);
|
setIsOwned(undefined);
|
||||||
setIsEditor(undefined);
|
setIsEditor(undefined);
|
||||||
options.setLocation('');
|
setLocation('');
|
||||||
}, [setHead, setIsVisible, setIsOwned, setIsEditor, options.setLocation]);
|
}, [setHead, setIsVisible, setIsOwned, setIsEditor, setLocation]);
|
||||||
|
|
||||||
const promptRenameLocation = useCallback(() => {
|
const promptRenameLocation = useCallback(() => {
|
||||||
setShowRenameLocation(true);
|
setShowRenameLocation(true);
|
||||||
|
@ -94,11 +94,11 @@ function LibraryPage() {
|
||||||
const handleRenameLocation = useCallback(
|
const handleRenameLocation = useCallback(
|
||||||
(newLocation: string) => {
|
(newLocation: string) => {
|
||||||
const data: IRenameLocationData = {
|
const data: IRenameLocationData = {
|
||||||
target: options.location,
|
target: location,
|
||||||
new_location: newLocation
|
new_location: newLocation
|
||||||
};
|
};
|
||||||
library.renameLocation(data, () => {
|
library.renameLocation(data, () => {
|
||||||
options.setLocation(newLocation);
|
setLocation(newLocation);
|
||||||
toast.success(information.locationRenamed);
|
toast.success(information.locationRenamed);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -123,18 +123,18 @@ function LibraryPage() {
|
||||||
<TableLibraryItems
|
<TableLibraryItems
|
||||||
resetQuery={resetFilter}
|
resetQuery={resetFilter}
|
||||||
items={items}
|
items={items}
|
||||||
folderMode={options.folderMode}
|
folderMode={folderMode}
|
||||||
toggleFolderMode={toggleFolderMode}
|
toggleFolderMode={toggleFolderMode}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[resetFilter, items, options.folderMode, toggleFolderMode]
|
[resetFilter, items, folderMode, toggleFolderMode]
|
||||||
);
|
);
|
||||||
|
|
||||||
const viewLocations = useMemo(
|
const viewLocations = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<ViewSideLocation
|
<ViewSideLocation
|
||||||
active={options.location}
|
active={location}
|
||||||
setActive={options.setLocation}
|
setActive={setLocation}
|
||||||
subfolders={subfolders}
|
subfolders={subfolders}
|
||||||
folderTree={library.folders}
|
folderTree={library.folders}
|
||||||
toggleFolderMode={toggleFolderMode}
|
toggleFolderMode={toggleFolderMode}
|
||||||
|
@ -142,7 +142,7 @@ function LibraryPage() {
|
||||||
onRenameLocation={promptRenameLocation}
|
onRenameLocation={promptRenameLocation}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[options.location, library.folders, options.setLocation, toggleFolderMode, subfolders]
|
[location, library.folders, setLocation, toggleFolderMode, subfolders]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -154,16 +154,12 @@ function LibraryPage() {
|
||||||
>
|
>
|
||||||
{showRenameLocation ? (
|
{showRenameLocation ? (
|
||||||
<DlgChangeLocation
|
<DlgChangeLocation
|
||||||
initial={options.location}
|
initial={location}
|
||||||
onChangeLocation={handleRenameLocation}
|
onChangeLocation={handleRenameLocation}
|
||||||
hideWindow={() => setShowRenameLocation(false)}
|
hideWindow={() => setShowRenameLocation(false)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<Overlay
|
<Overlay position='top-[0.25rem] right-0' layer='z-tooltip'>
|
||||||
position={options.noNavigation ? 'top-[0.25rem] right-[3rem]' : 'top-[0.25rem] right-0'}
|
|
||||||
layer='z-tooltip'
|
|
||||||
className='transition-all'
|
|
||||||
>
|
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Выгрузить в формате CSV'
|
title='Выгрузить в формате CSV'
|
||||||
icon={<IconCSV size='1.25rem' className='icon-green' />}
|
icon={<IconCSV size='1.25rem' className='icon-green' />}
|
||||||
|
@ -187,12 +183,12 @@ function LibraryPage() {
|
||||||
isEditor={isEditor}
|
isEditor={isEditor}
|
||||||
toggleEditor={toggleEditor}
|
toggleEditor={toggleEditor}
|
||||||
resetFilter={resetFilter}
|
resetFilter={resetFilter}
|
||||||
folderMode={options.folderMode}
|
folderMode={folderMode}
|
||||||
toggleFolderMode={toggleFolderMode}
|
toggleFolderMode={toggleFolderMode}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='flex'>
|
<div className='flex'>
|
||||||
<AnimatePresence initial={false}>{options.folderMode ? viewLocations : null}</AnimatePresence>
|
<AnimatePresence initial={false}>{folderMode ? viewLocations : null}</AnimatePresence>
|
||||||
{viewLibrary}
|
{viewLibrary}
|
||||||
</div>
|
</div>
|
||||||
</DataLoader>
|
</DataLoader>
|
||||||
|
|
|
@ -96,20 +96,15 @@ function ToolbarSearch({
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'sticky top-0', // prettier: split lines
|
'sticky top-0', // prettier: split lines
|
||||||
'h-[2.2rem]',
|
'w-full h-[2.2rem]',
|
||||||
'flex items-center gap-3',
|
'flex items-center',
|
||||||
'border-b',
|
'border-b',
|
||||||
'text-sm',
|
'text-sm',
|
||||||
'clr-input'
|
'clr-input'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx('px-3 pt-1 self-center', 'min-w-[6rem] sm:min-w-[7rem]', 'select-none', 'whitespace-nowrap')}
|
||||||
'ml-3 pt-1 self-center',
|
|
||||||
'min-w-[4.5rem] sm:min-w-[5.5rem]',
|
|
||||||
'select-none',
|
|
||||||
'whitespace-nowrap'
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{filtered} из {total}
|
{filtered} из {total}
|
||||||
</div>
|
</div>
|
||||||
|
@ -143,7 +138,7 @@ function ToolbarSearch({
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div className='flex h-full'>
|
<div className='flex items-center h-full mx-auto'>
|
||||||
<SearchBar
|
<SearchBar
|
||||||
id='library_search'
|
id='library_search'
|
||||||
placeholder='Поиск'
|
placeholder='Поиск'
|
||||||
|
|
|
@ -15,8 +15,8 @@ function HelpMain() {
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Такие системы называются <LinkTopic text='Концептуальными схемами' topic={HelpTopic.CC_SYSTEM} /> и состоят из
|
Такие системы называются <LinkTopic text='Концептуальными схемами' topic={HelpTopic.CC_SYSTEM} /> и состоят из
|
||||||
отдельных <LinkTopic text='Конституент' topic={HelpTopic.CC_CONSTITUENTA} />, которым даны формальные
|
отдельных <LinkTopic text='Конституент' topic={HelpTopic.CC_CONSTITUENTA} />, обладающих уникальными
|
||||||
определения. Концептуальные схемы могут связываться путем синтеза в{' '}
|
обозначениями и формальными определениями. Концептуальные схемы могут быть получены в рамках операций синтеза в{' '}
|
||||||
<LinkTopic text='Операционной схеме синтеза' topic={HelpTopic.CC_OSS} />.
|
<LinkTopic text='Операционной схеме синтеза' topic={HelpTopic.CC_OSS} />.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -51,8 +51,7 @@ function HelpMain() {
|
||||||
|
|
||||||
<h2>Поддержка</h2>
|
<h2>Поддержка</h2>
|
||||||
<p>
|
<p>
|
||||||
Портал разрабатывается <TextURL text='Центром Концепт' href={external_urls.concept} /> и вобрал в себя{' '}
|
Портал разрабатывается <TextURL text='Центром Концепт' href={external_urls.concept} />
|
||||||
<LinkTopic text='многолетнюю работу' topic={HelpTopic.INFO_CONTRIB} /> над средствами экспликации.
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Портал поддерживает актуальные версии браузеров Chrome, Firefox, Safari, включая мобильные устройства.
|
Портал поддерживает актуальные версии браузеров Chrome, Firefox, Safari, включая мобильные устройства.
|
||||||
|
|
|
@ -281,11 +281,6 @@ function HelpInfo() {
|
||||||
<TextURL text='pyconcept' href={external_urls.git_core} />.
|
<TextURL text='pyconcept' href={external_urls.git_core} />.
|
||||||
</i>
|
</i>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
2024 Борисов И.Р., Хаданович Б.А. Исследование механизмов проведения сквозных изменений в операционной схеме
|
|
||||||
синтеза. Разработка прототипа веб-интерфейса синтеза концептуальных схем.
|
|
||||||
<i> Прототип графического интерфейса для синтеза концептуальных схем.</i>
|
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -50,7 +50,7 @@ function NodeContextMenu({
|
||||||
}
|
}
|
||||||
|
|
||||||
const argumentIDs = controller.schema.graph.expandInputs([operation.id]);
|
const argumentIDs = controller.schema.graph.expandInputs([operation.id]);
|
||||||
if (!argumentIDs || argumentIDs.length < 1) {
|
if (!argumentIDs || argumentIDs.length < 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
||||||
import { useOSS } from '@/context/OssContext';
|
import { useOSS } from '@/context/OssContext';
|
||||||
import useLocalStorage from '@/hooks/useLocalStorage';
|
import useLocalStorage from '@/hooks/useLocalStorage';
|
||||||
import { OssNode } from '@/models/miscellaneous';
|
import { OssNode } from '@/models/miscellaneous';
|
||||||
import { OperationID } from '@/models/oss';
|
import { OperationID, OperationType } from '@/models/oss';
|
||||||
import { PARAMETER, storage } from '@/utils/constants';
|
import { PARAMETER, storage } from '@/utils/constants';
|
||||||
import { errors } from '@/utils/labels';
|
import { errors } from '@/utils/labels';
|
||||||
|
|
||||||
|
@ -132,11 +132,48 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let target = { x: 0, y: 0 };
|
||||||
const positions = getPositions();
|
const positions = getPositions();
|
||||||
const target = flow.project({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
|
if (positions.length == 0) {
|
||||||
|
target = flow.project({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
|
||||||
|
} else if (inputs.length <= 1) {
|
||||||
|
let inputsNodes = positions.filter(pos =>
|
||||||
|
controller.schema!.items.find(
|
||||||
|
operation => operation.operation_type === OperationType.INPUT && operation.id === pos.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (inputsNodes.length > 0) {
|
||||||
|
inputsNodes = positions;
|
||||||
|
}
|
||||||
|
const maxX = Math.max(...inputsNodes.map(node => node.position_x));
|
||||||
|
const minY = Math.min(...inputsNodes.map(node => node.position_y));
|
||||||
|
target.x = maxX + 180;
|
||||||
|
target.y = minY;
|
||||||
|
} else {
|
||||||
|
const inputsNodes = positions.filter(pos => inputs.includes(pos.id));
|
||||||
|
const maxY = Math.max(...inputsNodes.map(node => node.position_y));
|
||||||
|
const minX = Math.min(...inputsNodes.map(node => node.position_x));
|
||||||
|
const maxX = Math.max(...inputsNodes.map(node => node.position_x));
|
||||||
|
target.x = Math.ceil((maxX + minX) / 2 / PARAMETER.ossGridSize) * PARAMETER.ossGridSize;
|
||||||
|
target.y = maxY + 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
let flagIntersect = false;
|
||||||
|
do {
|
||||||
|
flagIntersect = positions.some(
|
||||||
|
position =>
|
||||||
|
Math.abs(position.position_x - target.x) < PARAMETER.ossMinDistance &&
|
||||||
|
Math.abs(position.position_y - target.y) < PARAMETER.ossMinDistance
|
||||||
|
);
|
||||||
|
if (flagIntersect) {
|
||||||
|
target.x += PARAMETER.ossMinDistance;
|
||||||
|
target.y += PARAMETER.ossMinDistance;
|
||||||
|
}
|
||||||
|
} while (flagIntersect);
|
||||||
|
|
||||||
controller.promptCreateOperation({
|
controller.promptCreateOperation({
|
||||||
defaultX: target.x,
|
x: target.x,
|
||||||
defaultY: target.y,
|
y: target.y,
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
positions: positions,
|
positions: positions,
|
||||||
callback: () => flow.fitView({ duration: PARAMETER.zoomDuration })
|
callback: () => flow.fitView({ duration: PARAMETER.zoomDuration })
|
||||||
|
|
|
@ -76,7 +76,7 @@ function ToolbarOssGraph({
|
||||||
}
|
}
|
||||||
|
|
||||||
const argumentIDs = controller.schema.graph.expandInputs([selectedOperation.id]);
|
const argumentIDs = controller.schema.graph.expandInputs([selectedOperation.id]);
|
||||||
if (!argumentIDs || argumentIDs.length < 1) {
|
if (!argumentIDs || argumentIDs.length < 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@ import {
|
||||||
IconShare
|
IconShare
|
||||||
} from '@/components/Icons';
|
} from '@/components/Icons';
|
||||||
import Button from '@/components/ui/Button';
|
import Button from '@/components/ui/Button';
|
||||||
|
import DropdownDivider from '@/components/ui/DropdownDivider';
|
||||||
import Dropdown from '@/components/ui/Dropdown';
|
import Dropdown from '@/components/ui/Dropdown';
|
||||||
import DropdownButton from '@/components/ui/DropdownButton';
|
import DropdownButton from '@/components/ui/DropdownButton';
|
||||||
import DropdownDivider from '@/components/ui/DropdownDivider';
|
|
||||||
import { useAccessMode } from '@/context/AccessModeContext';
|
import { useAccessMode } from '@/context/AccessModeContext';
|
||||||
import { useAuth } from '@/context/AuthContext';
|
import { useAuth } from '@/context/AuthContext';
|
||||||
import { useConceptNavigation } from '@/context/NavigationContext';
|
import { useConceptNavigation } from '@/context/NavigationContext';
|
||||||
|
|
|
@ -36,8 +36,8 @@ import { errors, information } from '@/utils/labels';
|
||||||
import { RSTabID } from '../RSFormPage/RSTabs';
|
import { RSTabID } from '../RSFormPage/RSTabs';
|
||||||
|
|
||||||
export interface ICreateOperationPrompt {
|
export interface ICreateOperationPrompt {
|
||||||
defaultX: number;
|
x: number;
|
||||||
defaultY: number;
|
y: number;
|
||||||
inputs: OperationID[];
|
inputs: OperationID[];
|
||||||
positions: IOperationPosition[];
|
positions: IOperationPosition[];
|
||||||
callback: (newID: OperationID) => void;
|
callback: (newID: OperationID) => void;
|
||||||
|
@ -221,58 +221,19 @@ export const OssEditState = ({ selected, setSelected, children }: OssEditStatePr
|
||||||
[model]
|
[model]
|
||||||
);
|
);
|
||||||
|
|
||||||
const promptCreateOperation = useCallback(
|
const promptCreateOperation = useCallback(({ x, y, inputs, positions, callback }: ICreateOperationPrompt) => {
|
||||||
({ defaultX, defaultY, inputs, positions, callback }: ICreateOperationPrompt) => {
|
setInsertPosition({ x: x, y: y });
|
||||||
setInsertPosition({ x: defaultX, y: defaultY });
|
|
||||||
setInitialInputs(inputs);
|
setInitialInputs(inputs);
|
||||||
setPositions(positions);
|
setPositions(positions);
|
||||||
setCreateCallback(() => callback);
|
setCreateCallback(() => callback);
|
||||||
setShowCreateOperation(true);
|
setShowCreateOperation(true);
|
||||||
},
|
}, []);
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleCreateOperation = useCallback(
|
const handleCreateOperation = useCallback(
|
||||||
(data: IOperationCreateData) => {
|
(data: IOperationCreateData) => {
|
||||||
const target = insertPosition;
|
|
||||||
if (data.item_data.operation_type === OperationType.INPUT) {
|
|
||||||
let inputsNodes = positions.filter(pos =>
|
|
||||||
model.schema!.items.find(
|
|
||||||
operation => operation.operation_type === OperationType.INPUT && operation.id === pos.id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
if (inputsNodes.length > 0) {
|
|
||||||
inputsNodes = positions;
|
|
||||||
}
|
|
||||||
const maxX = Math.max(...inputsNodes.map(node => node.position_x));
|
|
||||||
const minY = Math.min(...inputsNodes.map(node => node.position_y));
|
|
||||||
target.x = maxX + PARAMETER.ossDistanceX;
|
|
||||||
target.y = minY;
|
|
||||||
} else {
|
|
||||||
const argNodes = positions.filter(pos => data.arguments!.includes(pos.id));
|
|
||||||
const maxY = Math.max(...argNodes.map(node => node.position_y));
|
|
||||||
const minX = Math.min(...argNodes.map(node => node.position_x));
|
|
||||||
const maxX = Math.max(...argNodes.map(node => node.position_x));
|
|
||||||
target.x = Math.ceil((maxX + minX) / 2 / PARAMETER.ossGridSize) * PARAMETER.ossGridSize;
|
|
||||||
target.y = maxY + PARAMETER.ossDistanceY;
|
|
||||||
}
|
|
||||||
|
|
||||||
let flagIntersect = false;
|
|
||||||
do {
|
|
||||||
flagIntersect = positions.some(
|
|
||||||
position =>
|
|
||||||
Math.abs(position.position_x - target.x) < PARAMETER.ossMinDistance &&
|
|
||||||
Math.abs(position.position_y - target.y) < PARAMETER.ossMinDistance
|
|
||||||
);
|
|
||||||
if (flagIntersect) {
|
|
||||||
target.x += PARAMETER.ossMinDistance;
|
|
||||||
target.y += PARAMETER.ossMinDistance;
|
|
||||||
}
|
|
||||||
} while (flagIntersect);
|
|
||||||
|
|
||||||
data.positions = positions;
|
data.positions = positions;
|
||||||
data.item_data.position_x = target.x;
|
data.item_data.position_x = insertPosition.x;
|
||||||
data.item_data.position_y = target.y;
|
data.item_data.position_y = insertPosition.y;
|
||||||
model.createOperation(data, operation => {
|
model.createOperation(data, operation => {
|
||||||
toast.success(information.newOperation(operation.alias));
|
toast.success(information.newOperation(operation.alias));
|
||||||
if (createCallback) {
|
if (createCallback) {
|
||||||
|
|
|
@ -1,25 +1,13 @@
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { urls } from '@/app/urls';
|
import { IconDateCreate, IconDateUpdate, IconEditor, IconFolder, IconOwner } from '@/components/Icons';
|
||||||
import {
|
|
||||||
IconDateCreate,
|
|
||||||
IconDateUpdate,
|
|
||||||
IconEditor,
|
|
||||||
IconFolderEdit,
|
|
||||||
IconFolderOpened,
|
|
||||||
IconOwner
|
|
||||||
} from '@/components/Icons';
|
|
||||||
import InfoUsers from '@/components/info/InfoUsers';
|
import InfoUsers from '@/components/info/InfoUsers';
|
||||||
import { CProps } from '@/components/props';
|
|
||||||
import SelectUser from '@/components/select/SelectUser';
|
import SelectUser from '@/components/select/SelectUser';
|
||||||
import MiniButton from '@/components/ui/MiniButton';
|
|
||||||
import Overlay from '@/components/ui/Overlay';
|
import Overlay from '@/components/ui/Overlay';
|
||||||
import Tooltip from '@/components/ui/Tooltip';
|
import Tooltip from '@/components/ui/Tooltip';
|
||||||
import ValueIcon from '@/components/ui/ValueIcon';
|
import ValueIcon from '@/components/ui/ValueIcon';
|
||||||
import { useAccessMode } from '@/context/AccessModeContext';
|
import { useAccessMode } from '@/context/AccessModeContext';
|
||||||
import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
|
||||||
import { useConceptNavigation } from '@/context/NavigationContext';
|
|
||||||
import { useUsers } from '@/context/UsersContext';
|
import { useUsers } from '@/context/UsersContext';
|
||||||
import useDropdown from '@/hooks/useDropdown';
|
import useDropdown from '@/hooks/useDropdown';
|
||||||
import { ILibraryItemData, ILibraryItemEditor } from '@/models/library';
|
import { ILibraryItemData, ILibraryItemEditor } from '@/models/library';
|
||||||
|
@ -37,8 +25,6 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
|
||||||
const { getUserLabel, users } = useUsers();
|
const { getUserLabel, users } = useUsers();
|
||||||
const { accessLevel } = useAccessMode();
|
const { accessLevel } = useAccessMode();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const router = useConceptNavigation();
|
|
||||||
const options = useConceptOptions();
|
|
||||||
|
|
||||||
const ownerSelector = useDropdown();
|
const ownerSelector = useDropdown();
|
||||||
const onSelectUser = useCallback(
|
const onSelectUser = useCallback(
|
||||||
|
@ -55,43 +41,20 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
|
||||||
[controller, item?.owner, ownerSelector]
|
[controller, item?.owner, ownerSelector]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleOpenLibrary = useCallback(
|
|
||||||
(event: CProps.EventMouse) => {
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
options.setLocation(item.location);
|
|
||||||
options.setFolderMode(true);
|
|
||||||
router.push(urls.library, event.ctrlKey || event.metaKey);
|
|
||||||
},
|
|
||||||
[options.setLocation, options.setFolderMode, item, router]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col'>
|
<div className='flex flex-col'>
|
||||||
<div className='flex justify-stretch sm:mb-1 max-w-[30rem] gap-3'>
|
|
||||||
<MiniButton
|
|
||||||
noHover
|
|
||||||
noPadding
|
|
||||||
title='Открыть в библиотеке'
|
|
||||||
icon={<IconFolderOpened size='1.25rem' className='icon-primary' />}
|
|
||||||
onClick={handleOpenLibrary}
|
|
||||||
/>
|
|
||||||
<ValueIcon
|
<ValueIcon
|
||||||
className='text-ellipsis flex-grow'
|
className='sm:mb-1 text-ellipsis max-w-[30rem]'
|
||||||
icon={<IconFolderEdit size='1.25rem' className='icon-primary' />}
|
icon={<IconFolder size='1.25rem' className='icon-primary' />}
|
||||||
value={item.location}
|
value={item.location}
|
||||||
title={controller.isAttachedToOSS ? 'Путь наследуется от ОСС' : 'Путь'}
|
title={controller.isAttachedToOSS ? 'Путь наследуется от ОСС' : 'Путь'}
|
||||||
onClick={controller.promptLocation}
|
onClick={controller.promptLocation}
|
||||||
disabled={
|
disabled={isModified || controller.isProcessing || controller.isAttachedToOSS || accessLevel < UserLevel.OWNER}
|
||||||
isModified || controller.isProcessing || controller.isAttachedToOSS || accessLevel < UserLevel.OWNER
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
{ownerSelector.isOpen ? (
|
{ownerSelector.isOpen ? (
|
||||||
<Overlay position='top-[-0.5rem] left-[2.5rem] cc-icons'>
|
<Overlay position='top-[-0.5rem] left-[2.5rem] cc-icons'>
|
||||||
|
|
|
@ -27,9 +27,9 @@ import {
|
||||||
IconUpload
|
IconUpload
|
||||||
} from '@/components/Icons';
|
} from '@/components/Icons';
|
||||||
import Button from '@/components/ui/Button';
|
import Button from '@/components/ui/Button';
|
||||||
|
import DropdownDivider from '@/components/ui/DropdownDivider';
|
||||||
import Dropdown from '@/components/ui/Dropdown';
|
import Dropdown from '@/components/ui/Dropdown';
|
||||||
import DropdownButton from '@/components/ui/DropdownButton';
|
import DropdownButton from '@/components/ui/DropdownButton';
|
||||||
import DropdownDivider from '@/components/ui/DropdownDivider';
|
|
||||||
import { useAccessMode } from '@/context/AccessModeContext';
|
import { useAccessMode } from '@/context/AccessModeContext';
|
||||||
import { useAuth } from '@/context/AuthContext';
|
import { useAuth } from '@/context/AuthContext';
|
||||||
import { useGlobalOss } from '@/context/GlobalOssContext';
|
import { useGlobalOss } from '@/context/GlobalOssContext';
|
||||||
|
@ -85,11 +85,6 @@ function MenuRSTabs({ onDestroy }: MenuRSTabsProps) {
|
||||||
controller.share();
|
controller.share();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCreateVersion() {
|
|
||||||
schemaMenu.hide();
|
|
||||||
controller.createVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleReindex() {
|
function handleReindex() {
|
||||||
editMenu.hide();
|
editMenu.hide();
|
||||||
controller.reindex();
|
controller.reindex();
|
||||||
|
@ -166,7 +161,7 @@ function MenuRSTabs({ onDestroy }: MenuRSTabsProps) {
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Сохранить версию'
|
text='Сохранить версию'
|
||||||
disabled={!controller.isContentEditable}
|
disabled={!controller.isContentEditable}
|
||||||
onClick={handleCreateVersion}
|
onClick={controller.createVersion}
|
||||||
icon={<IconNewVersion size='1rem' className='icon-green' />}
|
icon={<IconNewVersion size='1rem' className='icon-green' />}
|
||||||
/>
|
/>
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
|
|
Loading…
Reference in New Issue
Block a user