From c9b7e45c8549c93180d9452c52c50607044e71cf Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:06:52 +0300 Subject: [PATCH] UI improvements --- TODO.txt | 13 ++++--- .../src/app/Navigation/NavigationButton.tsx | 1 + rsconcept/frontend/src/components/Icons.tsx | 3 +- .../src/dialogs/DlgDeleteCst/DlgDeleteCst.tsx | 7 +++- .../src/pages/LibraryPage/LibraryPage.tsx | 18 ++++++++-- .../src/pages/LibraryPage/SearchPanel.tsx | 34 +++++++++++++------ .../EditorRSFormCard/RSFormToolbar.tsx | 6 ++-- .../src/pages/RSFormPage/RSTabsMenu.tsx | 5 ++- rsconcept/frontend/src/utils/labels.ts | 4 ++- 9 files changed, 68 insertions(+), 23 deletions(-) diff --git a/TODO.txt b/TODO.txt index 5da26944..171a23fa 100644 --- a/TODO.txt +++ b/TODO.txt @@ -2,25 +2,26 @@ For more specific TODOs see comments in code [Functionality - PROGRESS] -- Landing page -- Home page (user specific) - - Operational synthesis schema as LibraryItem ? -- Draggable rows in constituents table - Clickable IDs in RSEditor tooltips - Library organization, search and exploration. Consider new user experience - Private projects and permissions. Consider cooperative editing -- Rework access setup: project-based, user-based, enable sharing. Prevent enumerating access to private schemas by default [Functionality - PENDING] +- Search functionality for manuals - User notifications on edit - consider spam prevention and change aggregation - Static analyzer for RSForm - Content based search in Library - User profile: Settings + settings persistency +- Landing page +- Home page (user specific) + +- Draggable rows in constituents table + - Export PDF (Items list, Graph) - ARIA (accessibility considerations) - for now machine reading not supported - Internationalization - at least english version. Consider react.intl @@ -42,6 +43,8 @@ For more specific TODOs see comments in code [Security] - password-reset leaks info of email being used - improve nginx config. Consider DDOS and other types of attacks on infrastructure +- recaptcha for create user and rest password +https://yandex.cloud/ru/docs/smartcaptcha [Research] diff --git a/rsconcept/frontend/src/app/Navigation/NavigationButton.tsx b/rsconcept/frontend/src/app/Navigation/NavigationButton.tsx index 8961af85..b3be6950 100644 --- a/rsconcept/frontend/src/app/Navigation/NavigationButton.tsx +++ b/rsconcept/frontend/src/app/Navigation/NavigationButton.tsx @@ -24,6 +24,7 @@ function NavigationButton({ icon, title, titleHtml, hideTitle, onClick, text }: 'flex items-center gap-1', 'clr-btn-nav', 'rounded-xl', + 'transition duration-500', 'font-controls whitespace-nowrap', { 'px-2': text, diff --git a/rsconcept/frontend/src/components/Icons.tsx b/rsconcept/frontend/src/components/Icons.tsx index 425f95bf..623c0bb1 100644 --- a/rsconcept/frontend/src/components/Icons.tsx +++ b/rsconcept/frontend/src/components/Icons.tsx @@ -18,7 +18,8 @@ export { BiCog as IconSettings } from 'react-icons/bi'; export { TbEye as IconShow } from 'react-icons/tb'; export { TbEyeX as IconHide } from 'react-icons/tb'; export { BiShareAlt as IconShare } from 'react-icons/bi'; -export { BiFilterAlt as IconFilter } from 'react-icons/bi'; +export { LuFilter as IconFilter } from 'react-icons/lu'; +export { LuFilterX as IconFilterReset } from 'react-icons/lu'; export {BiDownArrowCircle as IconOpenList } from 'react-icons/bi'; export { LuAlertTriangle as IconAlert } from 'react-icons/lu'; diff --git a/rsconcept/frontend/src/dialogs/DlgDeleteCst/DlgDeleteCst.tsx b/rsconcept/frontend/src/dialogs/DlgDeleteCst/DlgDeleteCst.tsx index 7cae9043..535d985b 100644 --- a/rsconcept/frontend/src/dialogs/DlgDeleteCst/DlgDeleteCst.tsx +++ b/rsconcept/frontend/src/dialogs/DlgDeleteCst/DlgDeleteCst.tsx @@ -48,7 +48,12 @@ function DlgDeleteCst({ hideWindow, selected, schema, onDelete }: DlgDeleteCstPr schema={schema} prefix={prefixes.cst_dependant_list} /> - setExpandOut(value)} /> + setExpandOut(value)} + /> ); } diff --git a/rsconcept/frontend/src/pages/LibraryPage/LibraryPage.tsx b/rsconcept/frontend/src/pages/LibraryPage/LibraryPage.tsx index 9070a0e3..e79719e5 100644 --- a/rsconcept/frontend/src/pages/LibraryPage/LibraryPage.tsx +++ b/rsconcept/frontend/src/pages/LibraryPage/LibraryPage.tsx @@ -44,6 +44,18 @@ function LibraryPage() { [head, path, query, isEditor, isOwned, isSubscribed, isVisible, user] ); + const hasCustomFilter = useMemo( + () => + !!filter.path || + !!filter.query || + filter.head !== undefined || + filter.isEditor !== undefined || + filter.isOwned !== undefined || + filter.isSubscribed !== undefined || + filter.isVisible !== true, + [filter] + ); + useLayoutEffect(() => { setItems(library.applyFilter(filter)); }, [library, filter, filter.query]); @@ -81,14 +93,15 @@ function LibraryPage() { hasNoData={library.items.length === 0} > {view} diff --git a/rsconcept/frontend/src/pages/LibraryPage/SearchPanel.tsx b/rsconcept/frontend/src/pages/LibraryPage/SearchPanel.tsx index f58719cb..70cc528d 100644 --- a/rsconcept/frontend/src/pages/LibraryPage/SearchPanel.tsx +++ b/rsconcept/frontend/src/pages/LibraryPage/SearchPanel.tsx @@ -4,11 +4,12 @@ import clsx from 'clsx'; import { useCallback } from 'react'; import { LocationIcon, SubscribeIcon, VisibilityIcon } from '@/components/DomainIcons'; -import { IconEditor, IconFolder, IconOwner } from '@/components/Icons'; +import { IconEditor, IconFilterReset, IconFolder, IconOwner } from '@/components/Icons'; import BadgeHelp from '@/components/info/BadgeHelp'; import Dropdown from '@/components/ui/Dropdown'; import DropdownButton from '@/components/ui/DropdownButton'; import MiniButton from '@/components/ui/MiniButton'; +import Overlay from '@/components/ui/Overlay'; import SearchBar from '@/components/ui/SearchBar'; import SelectorButton from '@/components/ui/SelectorButton'; import { useAuth } from '@/context/AuthContext'; @@ -22,6 +23,7 @@ import { tripleToggleColor } from '@/utils/utils'; interface SearchPanelProps { total: number; filtered: number; + hasCustomFilter: boolean; query: string; setQuery: React.Dispatch>; @@ -38,11 +40,14 @@ interface SearchPanelProps { toggleSubscribed: () => void; isEditor: boolean | undefined; toggleEditor: () => void; + resetFilter: () => void; } function SearchPanel({ total, filtered, + hasCustomFilter, + query, setQuery, path, @@ -57,7 +62,8 @@ function SearchPanel({ isSubscribed, toggleSubscribed, isEditor, - toggleEditor + toggleEditor, + resetFilter }: SearchPanelProps) { const { user } = useAuth(); const headMenu = useDropdown(); @@ -109,6 +115,13 @@ function SearchPanel({ icon={} onClick={toggleEditor} /> + + } + onClick={resetFilter} + disabled={!hasCustomFilter} + /> ) : null} @@ -169,18 +182,19 @@ function SearchPanel({ placeholder='Путь' noIcon noBorder - className='min-w-[5rem]' + className='min-w-[4.5rem] sm:min-w-[5rem]' value={path} onChange={setPath} /> - - + + + ); } diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/RSFormToolbar.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/RSFormToolbar.tsx index 664a061b..5dfb3147 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/RSFormToolbar.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/RSFormToolbar.tsx @@ -8,10 +8,11 @@ import BadgeHelp from '@/components/info/BadgeHelp'; import MiniButton from '@/components/ui/MiniButton'; import Overlay from '@/components/ui/Overlay'; import { useAccessMode } from '@/context/AccessModeContext'; +import { AccessPolicy } from '@/models/library'; import { HelpTopic } from '@/models/miscellaneous'; import { UserLevel } from '@/models/user'; import { PARAMETER } from '@/utils/constants'; -import { prepareTooltip } from '@/utils/labels'; +import { prepareTooltip, tooltips } from '@/utils/labels'; import { useRSEdit } from '../RSEditContext'; @@ -38,9 +39,10 @@ function RSFormToolbar({ modified, anonymous, subscribed, onSubmit, onDestroy }: /> ) : null} } onClick={controller.share} + disabled={controller.schema?.access_policy !== AccessPolicy.PUBLIC} /> {!anonymous ? ( } onClick={handleShare} + disabled={controller.schema?.access_policy !== AccessPolicy.PUBLIC} /> {user ? ( + policy === AccessPolicy.PUBLIC ? 'Поделиться схемой' : 'Поделиться можно только
открытой схемой' }; /**