Minor UI fixes

This commit is contained in:
IRBorisov 2023-08-31 17:25:42 +03:00
parent 03fb9e3fd0
commit b84bc82c02
11 changed files with 54 additions and 29 deletions

View File

@ -18,7 +18,7 @@ function HelpLibrary() {
</div>
<div className='flex items-center gap-2'>
<EducationIcon size={4}/>
<p>Аттрибут <b>библиотечная</b> выделяет неизменяемые стандартные схемы.</p>
<p>Аттрибут <b>неизменная</b> выделяет неизменяемые стандартные схемы.</p>
</div>
</div>
);

View File

@ -4,7 +4,7 @@ function HelpRSFormMeta() {
<h1>Концептуальная схема</h1>
<p><b>Владелец</b> - пользователь, обладающий правом редактирования</p>
<p>Для <b>общедоступных</b> схем владельцем может стать любой пользователь</p>
<p>Для <b>библиотечных</b> схем правом редактирования обладают только администраторы</p>
<p>Для <b>не</b> схем правом редактирования обладают только администраторы</p>
<p><b>Клонировать</b> - создать копию схемы для дальнейшего редактирования</p>
<p><b>Отслеживание</b> - возможность видеть схему в Библиотеке и использовать фильтры</p>
<p><b>Загрузить/Выгрузить схему</b> - взаимодействие с Экстеор через файлы формата TRS</p>

View File

@ -13,7 +13,7 @@ import Label from '../Common/Label';
import { ccBracketMatching } from './bracketMatching';
import { RSLanguage } from './rslang';
import { getSymbolSubstitute,TextWrapper } from './textEditing';
import { rshoverTooltip } from './tooltip';
import { rshoverTooltip as rsHoverTooltip } from './tooltip';
const editorSetup: BasicSetupOptions = {
highlightSpecialChars: false,
@ -111,7 +111,7 @@ function RSInput({
EditorView.lineWrapping,
RSLanguage,
ccBracketMatching(darkMode),
rshoverTooltip(schema?.items || []),
rsHoverTooltip(schema?.items || []),
], [darkMode, schema?.items]);
const handleInput = useCallback(

View File

@ -6,10 +6,9 @@ import { getCstTypificationLabel } from '../../utils/staticUI';
function createTooltipFor(cst: IConstituenta) {
const dom = document.createElement('div');
dom.className = 'overflow-y-auto border shadow-md max-h-[25rem] max-w-[25rem] min-w-[10rem] w-fit z-20 text-sm';
const alias = document.createElement('h1');
alias.className = 'text-sm text-left';
alias.textContent = `${cst.alias}: ${getCstTypificationLabel(cst)}`;
dom.className = 'overflow-y-auto border shadow-md max-h-[25rem] max-w-[25rem] min-w-[10rem] w-fit z-20 text-sm clr-border px-2 py-2';
const alias = document.createElement('p');
alias.innerHTML = `<b>${cst.alias}:</b> ${getCstTypificationLabel(cst)}`;
dom.appendChild(alias);
if (cst.term_resolved) {
const term = document.createElement('p');

View File

@ -54,9 +54,9 @@ function PickerStrategy({ value, onChange }: PickerStrategyProps) {
<DropdownButton onClick={() => handleChange(LibraryFilterStrategy.CANONICAL)}>
<Checkbox
value={value === LibraryFilterStrategy.CANONICAL}
label='Библиотечные'
label='Неизменные'
widthClass='w-fit px-2'
tooltip='Отображать только библиотечные схемы'
tooltip='Отображать только неизменные схемы'
/>
</DropdownButton>
<DropdownButton onClick={() => handleChange(LibraryFilterStrategy.PERSONAL)}>

View File

@ -64,7 +64,7 @@ function SearchPanel({ total, filtered, setFilter }: SearchPanelProps) {
}, [strategy, navigate]);
return (
<div className='sticky top-0 left-0 right-0 z-10 flex items-center justify-start w-full border-b clr-input'>
<div className='sticky top-0 left-0 right-0 z-30 flex items-center justify-start w-full border-b clr-input'>
<div className='px-2 py-1 select-none whitespace-nowrap min-w-[10rem]'>
Фильтр
<span className='ml-2'>

View File

@ -1,4 +1,4 @@
import { useLayoutEffect, useMemo, useState } from 'react';
import { Dispatch, SetStateAction, useLayoutEffect, useMemo, useState } from 'react';
import { toast } from 'react-toastify';
import ConceptTooltip from '../../components/Common/ConceptTooltip';
@ -9,7 +9,6 @@ import TextArea from '../../components/Common/TextArea';
import HelpConstituenta from '../../components/Help/HelpConstituenta';
import { DumpBinIcon, HelpIcon, PenIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons';
import { useRSForm } from '../../context/RSFormContext';
import useModificationPrompt from '../../hooks/useModificationPrompt';
import { CstType, EditMode, ICstCreateData, ICstRenameData, ICstUpdateData, SyntaxTree } from '../../utils/models';
import { getCstTypificationLabel } from '../../utils/staticUI';
import EditorRSExpression from './EditorRSExpression';
@ -25,17 +24,20 @@ interface EditorConstituentaProps {
onCreateCst: (initial: ICstCreateData, skipDialog?: boolean) => void
onRenameCst: (initial: ICstRenameData) => void
onDeleteCst: (selected: number[], callback?: (items: number[]) => void) => void
isModified: boolean
setIsModified: Dispatch<SetStateAction<boolean>>
}
function EditorConstituenta({ activeID, onShowAST, onCreateCst, onRenameCst, onOpenEdit, onDeleteCst }: EditorConstituentaProps) {
function EditorConstituenta({
isModified, setIsModified, activeID,
onShowAST, onCreateCst, onRenameCst, onOpenEdit, onDeleteCst
}: EditorConstituentaProps) {
const { schema, processing, isEditable, cstUpdate } = useRSForm();
const activeCst = useMemo(
() => {
return schema?.items?.find((cst) => cst.id === activeID);
}, [schema?.items, activeID]);
const { isModified, setIsModified } = useModificationPrompt();
const [editMode, setEditMode] = useState(EditMode.TEXT);
const [alias, setAlias] = useState('');
@ -59,6 +61,7 @@ function EditorConstituenta({ activeID, onShowAST, onCreateCst, onRenameCst, onO
activeCst.convention !== convention ||
activeCst.definition_formal !== expression
);
return () => setIsModified(false);
}, [activeCst, activeCst?.term_raw, activeCst?.definition_formal,
activeCst?.definition_raw, activeCst?.convention,
term, textDefinition, expression, convention, setIsModified]);

View File

@ -1,4 +1,4 @@
import { useLayoutEffect, useState } from 'react';
import { Dispatch, SetStateAction, useLayoutEffect, useState } from 'react';
import { useIntl } from 'react-intl';
import { toast } from 'react-toastify';
@ -13,7 +13,6 @@ import { CrownIcon, DownloadIcon, DumpBinIcon, HelpIcon, SaveIcon, ShareIcon } f
import { useAuth } from '../../context/AuthContext';
import { useRSForm } from '../../context/RSFormContext';
import { useUsers } from '../../context/UsersContext';
import useModificationPrompt from '../../hooks/useModificationPrompt';
import { IRSFormCreateData, LibraryItemType } from '../../utils/models';
interface EditorRSFormProps {
@ -21,9 +20,11 @@ interface EditorRSFormProps {
onClaim: () => void
onShare: () => void
onDownload: () => void
isModified: boolean
setIsModified: Dispatch<SetStateAction<boolean>>
}
function EditorRSForm({ onDestroy, onClaim, onShare, onDownload }: EditorRSFormProps) {
function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified, onDownload }: EditorRSFormProps) {
const intl = useIntl();
const { getUserLabel } = useUsers();
const {
@ -38,8 +39,6 @@ function EditorRSForm({ onDestroy, onClaim, onShare, onDownload }: EditorRSFormP
const [common, setCommon] = useState(false);
const [canonical, setCanonical] = useState(false);
const { isModified, setIsModified } = useModificationPrompt();
useLayoutEffect(() => {
if (!schema) {
setIsModified(false);
@ -52,6 +51,7 @@ function EditorRSForm({ onDestroy, onClaim, onShare, onDownload }: EditorRSFormP
schema.is_common !== common ||
schema.is_canonical !== canonical
);
return () => setIsModified(false);
}, [schema, schema?.title, schema?.alias, schema?.comment,
schema?.is_common, schema?.is_canonical,
title, alias, comment, common, canonical, setIsModified]);
@ -138,10 +138,10 @@ function EditorRSForm({ onDestroy, onClaim, onShare, onDownload }: EditorRSFormP
disabled={!isEditable}
onChange={event => setCommon(event.target.checked)}
/>
<Checkbox id='canonical' label='Библиотечная схема'
<Checkbox id='canonical' label='Неизменная схема'
widthClass='w-fit'
value={canonical}
tooltip='Только администраторы могут присваивать схемам библиотечный статус'
tooltip='Только администраторы могут присваивать схемам неизменный статус'
disabled={!isEditable || !isForceAdmin}
onChange={event => setCanonical(event.target.checked)}
/>

View File

@ -10,6 +10,7 @@ import { Loader } from '../../components/Common/Loader';
import { useLibrary } from '../../context/LibraryContext';
import { useRSForm } from '../../context/RSFormContext';
import { useConceptTheme } from '../../context/ThemeContext';
import useModificationPrompt from '../../hooks/useModificationPrompt';
import { prefixes, TIMEOUT_UI_REFRESH } from '../../utils/constants';
import { ICstCreateData, ICstRenameData, LibraryFilterStrategy, SyntaxTree } from '../../utils/models';
import { createAliasFor } from '../../utils/staticUI';
@ -43,6 +44,8 @@ function RSTabs() {
const { destroySchema } = useLibrary();
const { setNoFooter } = useConceptTheme();
const { isModified, setIsModified } = useModificationPrompt();
const [activeTab, setActiveTab] = useState<RSTabID>(RSTabID.CARD);
const [activeID, setActiveID] = useState<number | undefined>(undefined);
@ -226,6 +229,11 @@ function RSTabs() {
const onDownloadSchema = useCallback(
() => {
if (isModified) {
if (!window.confirm('Присутствуют несохраненные изменения. Продолжить без их учета?')) {
return;
}
}
const fileName = (schema?.alias ?? 'Schema') + '.trs';
download(
(data) => {
@ -235,7 +243,17 @@ function RSTabs() {
console.error(error);
}
});
}, [schema?.alias, download]);
}, [schema?.alias, download, isModified]);
const handleShowClone = useCallback(
() => {
if (isModified) {
if (!window.confirm('Присутствуют несохраненные изменения. Продолжить без их учета?')) {
return;
}
}
setShowClone(true);
}, [isModified]);
const handleToggleSubscribe = useCallback(
() => {
@ -302,7 +320,7 @@ function RSTabs() {
onClaim={onClaimSchema}
onShare={onShareSchema}
onToggleSubscribe={handleToggleSubscribe}
showCloneDialog={() => setShowClone(true)}
showCloneDialog={handleShowClone}
showUploadDialog={() => setShowUpload(true)}
/>
<ConceptTab className='border-r-2 min-w-[7.8rem]'>Паспорт схемы</ConceptTab>
@ -316,6 +334,8 @@ function RSTabs() {
<TabPanel className='flex w-full gap-4'>
<EditorRSForm
isModified={isModified}
setIsModified={setIsModified}
onDownload={onDownloadSchema}
onDestroy={onDestroySchema}
onClaim={onClaimSchema}
@ -334,6 +354,8 @@ function RSTabs() {
<TabPanel>
<EditorConstituenta
isModified={isModified}
setIsModified={setIsModified}
activeID={activeID}
onOpenEdit={onOpenCst}
onShowAST={onShowAST}

View File

@ -131,7 +131,7 @@ function RSTabsMenu({
<DropdownButton
disabled={!user || !isClaimable}
onClick={!isOwned ? handleClaimOwner : undefined}
description={!user || !isClaimable ? 'Стать владельцем можно только для общей небиблиотечной схемы' : ''}
description={!user || !isClaimable ? 'Стать владельцем можно только для общей изменяемой схемы' : ''}
>
<div className='inline-flex items-center gap-1 justify-normal'>
<span className={isOwned ? 'text-green' : ''}><CrownIcon size={4} /></span>

View File

@ -624,6 +624,7 @@ export function getNodeLabel(node: ISyntaxTreeNode): string {
case TokenID.NT_ENUM_DECL: return 'ENUM_DECLARATION'
case TokenID.NT_TUPLE_DECL: return 'TUPLE_DECLARATION'
case TokenID.PUNC_DEFINE: return 'DEFINITION'
case TokenID.PUNC_STRUCT: return 'STRUCTURE_DEFITION'
case TokenID.NT_ARG_DECL: return 'ARG'
case TokenID.NT_FUNC_CALL: return 'CALL'