mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Improve navigation. Ctrl + click - open in new tab
This commit is contained in:
parent
f041bd172e
commit
a5ca411cb5
|
@ -4,6 +4,7 @@ import { FaSquarePlus } from 'react-icons/fa6';
|
||||||
import { IoLibrary } from 'react-icons/io5';
|
import { IoLibrary } from 'react-icons/io5';
|
||||||
|
|
||||||
import { IconManuals } from '@/components/Icons';
|
import { IconManuals } from '@/components/Icons';
|
||||||
|
import { CProps } from '@/components/props';
|
||||||
import { useConceptNavigation } from '@/context/NavigationContext';
|
import { useConceptNavigation } from '@/context/NavigationContext';
|
||||||
import { useConceptOptions } from '@/context/OptionsContext';
|
import { useConceptOptions } from '@/context/OptionsContext';
|
||||||
import { animateNavigation } from '@/styling/animations';
|
import { animateNavigation } from '@/styling/animations';
|
||||||
|
@ -18,10 +19,10 @@ function Navigation() {
|
||||||
const router = useConceptNavigation();
|
const router = useConceptNavigation();
|
||||||
const { noNavigationAnimation } = useConceptOptions();
|
const { noNavigationAnimation } = useConceptOptions();
|
||||||
|
|
||||||
const navigateHome = () => router.push(urls.home);
|
const navigateHome = (event: CProps.EventMouse) => router.push(urls.home, event.ctrlKey);
|
||||||
const navigateLibrary = () => router.push(urls.library);
|
const navigateLibrary = (event: CProps.EventMouse) => router.push(urls.library, event.ctrlKey);
|
||||||
const navigateHelp = () => router.push(urls.manuals);
|
const navigateHelp = (event: CProps.EventMouse) => router.push(urls.manuals, event.ctrlKey);
|
||||||
const navigateCreateNew = () => router.push(urls.create_schema);
|
const navigateCreateNew = (event: CProps.EventMouse) => router.push(urls.create_schema, event.ctrlKey);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { globals } from '@/utils/constants';
|
||||||
interface NavigationButtonProps extends CProps.Titled {
|
interface NavigationButtonProps extends CProps.Titled {
|
||||||
text?: string;
|
text?: string;
|
||||||
icon: React.ReactNode;
|
icon: React.ReactNode;
|
||||||
onClick?: () => void;
|
onClick?: (event: CProps.EventMouse) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function NavigationButton({ icon, title, titleHtml, hideTitle, onClick, text }: NavigationButtonProps) {
|
function NavigationButton({ icon, title, titleHtml, hideTitle, onClick, text }: NavigationButtonProps) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { LuLogOut, LuMoon, LuSun } from 'react-icons/lu';
|
import { LuLogOut, LuMoon, LuSun } from 'react-icons/lu';
|
||||||
|
|
||||||
import { IconHelp, IconHelpOff, IconUser } from '@/components/Icons';
|
import { IconHelp, IconHelpOff, IconUser } from '@/components/Icons';
|
||||||
|
import { CProps } from '@/components/props';
|
||||||
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 { useAuth } from '@/context/AuthContext';
|
import { useAuth } from '@/context/AuthContext';
|
||||||
|
@ -19,9 +20,9 @@ function UserDropdown({ isOpen, hideDropdown }: UserDropdownProps) {
|
||||||
const router = useConceptNavigation();
|
const router = useConceptNavigation();
|
||||||
const { user, logout } = useAuth();
|
const { user, logout } = useAuth();
|
||||||
|
|
||||||
function navigateProfile() {
|
function navigateProfile(event: CProps.EventMouse) {
|
||||||
hideDropdown();
|
hideDropdown();
|
||||||
router.push(urls.profile);
|
router.push(urls.profile, event.ctrlKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
function logoutAndRedirect() {
|
function logoutAndRedirect() {
|
||||||
|
|
2
rsconcept/frontend/src/components/props.d.ts
vendored
2
rsconcept/frontend/src/components/props.d.ts
vendored
|
@ -43,4 +43,6 @@ export namespace CProps {
|
||||||
|
|
||||||
export type AnimatedButton = Titled & Omit<HTMLMotionProps<'button'>, 'type'>;
|
export type AnimatedButton = Titled & Omit<HTMLMotionProps<'button'>, 'type'>;
|
||||||
export type AnimatedDiv = HTMLMotionProps<'div'>;
|
export type AnimatedDiv = HTMLMotionProps<'div'>;
|
||||||
|
|
||||||
|
export type EventMouse = React.MouseEvent<Element, MouseEvent>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ function Checkbox({
|
||||||
}
|
}
|
||||||
}, [disabled, setValue]);
|
}, [disabled, setValue]);
|
||||||
|
|
||||||
function handleClick(event: React.MouseEvent<HTMLButtonElement, MouseEvent>): void {
|
function handleClick(event: CProps.EventMouse): void {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (disabled || !setValue) {
|
if (disabled || !setValue) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { useMemo } from 'react';
|
||||||
import { globals } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
import { CheckboxChecked, CheckboxNull } from '../Icons';
|
import { CheckboxChecked, CheckboxNull } from '../Icons';
|
||||||
|
import { CProps } from '../props';
|
||||||
import { CheckboxProps } from './Checkbox';
|
import { CheckboxProps } from './Checkbox';
|
||||||
|
|
||||||
export interface CheckboxTristateProps extends Omit<CheckboxProps, 'value' | 'setValue'> {
|
export interface CheckboxTristateProps extends Omit<CheckboxProps, 'value' | 'setValue'> {
|
||||||
|
@ -32,7 +33,7 @@ function CheckboxTristate({
|
||||||
}
|
}
|
||||||
}, [disabled, setValue]);
|
}, [disabled, setValue]);
|
||||||
|
|
||||||
function handleClick(event: React.MouseEvent<HTMLButtonElement, MouseEvent>): void {
|
function handleClick(event: CProps.EventMouse): void {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (disabled || !setValue) {
|
if (disabled || !setValue) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -44,8 +44,8 @@ export interface DataTableProps<TData extends RowData>
|
||||||
conditionalRowStyles?: IConditionalStyle<TData>[];
|
conditionalRowStyles?: IConditionalStyle<TData>[];
|
||||||
noDataComponent?: React.ReactNode;
|
noDataComponent?: React.ReactNode;
|
||||||
|
|
||||||
onRowClicked?: (rowData: TData, event: React.MouseEvent<Element, MouseEvent>) => void;
|
onRowClicked?: (rowData: TData, event: CProps.EventMouse) => void;
|
||||||
onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent<Element, MouseEvent>) => void;
|
onRowDoubleClicked?: (rowData: TData, event: CProps.EventMouse) => void;
|
||||||
|
|
||||||
enableRowSelection?: boolean;
|
enableRowSelection?: boolean;
|
||||||
rowSelection?: RowSelectionState;
|
rowSelection?: RowSelectionState;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { Cell, flexRender, Row, Table } from '@tanstack/react-table';
|
import { Cell, flexRender, Row, Table } from '@tanstack/react-table';
|
||||||
|
|
||||||
|
import { CProps } from '@/components/props';
|
||||||
|
|
||||||
import { IConditionalStyle } from '.';
|
import { IConditionalStyle } from '.';
|
||||||
import SelectRow from './SelectRow';
|
import SelectRow from './SelectRow';
|
||||||
|
|
||||||
|
@ -12,8 +14,8 @@ interface TableBodyProps<TData> {
|
||||||
lastSelected: string | undefined;
|
lastSelected: string | undefined;
|
||||||
setLastSelected: React.Dispatch<React.SetStateAction<string | undefined>>;
|
setLastSelected: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||||
|
|
||||||
onRowClicked?: (rowData: TData, event: React.MouseEvent<Element, MouseEvent>) => void;
|
onRowClicked?: (rowData: TData, event: CProps.EventMouse) => void;
|
||||||
onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent<Element, MouseEvent>) => void;
|
onRowDoubleClicked?: (rowData: TData, event: CProps.EventMouse) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableBody<TData>({
|
function TableBody<TData>({
|
||||||
|
@ -26,7 +28,7 @@ function TableBody<TData>({
|
||||||
onRowClicked,
|
onRowClicked,
|
||||||
onRowDoubleClicked
|
onRowDoubleClicked
|
||||||
}: TableBodyProps<TData>) {
|
}: TableBodyProps<TData>) {
|
||||||
function handleRowClicked(target: Row<TData>, event: React.MouseEvent<Element, MouseEvent>) {
|
function handleRowClicked(target: Row<TData>, event: CProps.EventMouse) {
|
||||||
if (onRowClicked) {
|
if (onRowClicked) {
|
||||||
onRowClicked(target.original, event);
|
onRowClicked(target.original, event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { globals } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
interface INavigationContext {
|
interface INavigationContext {
|
||||||
push: (path: string) => void;
|
push: (path: string, newTab?: boolean) => void;
|
||||||
replace: (path: string) => void;
|
replace: (path: string) => void;
|
||||||
back: () => void;
|
back: () => void;
|
||||||
forward: () => void;
|
forward: () => void;
|
||||||
|
@ -50,7 +50,11 @@ export const NavigationState = ({ children }: NavigationStateProps) => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const push = useCallback(
|
const push = useCallback(
|
||||||
(path: string) => {
|
(path: string, newTab?: boolean) => {
|
||||||
|
if (newTab) {
|
||||||
|
window.open(`${path}`, '_blank');
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (validate()) {
|
if (validate()) {
|
||||||
scrollTop();
|
scrollTop();
|
||||||
router(path);
|
router(path);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { urls } from '@/app/urls';
|
import { urls } from '@/app/urls';
|
||||||
import BadgeHelp from '@/components/man/BadgeHelp';
|
import BadgeHelp from '@/components/man/BadgeHelp';
|
||||||
|
import { CProps } from '@/components/props';
|
||||||
import DataTable, { createColumnHelper, VisibilityState } from '@/components/ui/DataTable';
|
import DataTable, { createColumnHelper, VisibilityState } from '@/components/ui/DataTable';
|
||||||
import FlexColumn from '@/components/ui/FlexColumn';
|
import FlexColumn from '@/components/ui/FlexColumn';
|
||||||
import TextURL from '@/components/ui/TextURL';
|
import TextURL from '@/components/ui/TextURL';
|
||||||
|
@ -34,7 +35,9 @@ function ViewLibrary({ items, resetQuery }: ViewLibraryProps) {
|
||||||
const { getUserLabel } = useUsers();
|
const { getUserLabel } = useUsers();
|
||||||
const [itemsPerPage, setItemsPerPage] = useLocalStorage<number>(storage.libraryPagination, 50);
|
const [itemsPerPage, setItemsPerPage] = useLocalStorage<number>(storage.libraryPagination, 50);
|
||||||
|
|
||||||
const handleOpenItem = (item: ILibraryItem) => router.push(urls.schema(item.id));
|
function handleOpenItem(item: ILibraryItem, event: CProps.EventMouse) {
|
||||||
|
router.push(urls.schema(item.id), event.ctrlKey);
|
||||||
|
}
|
||||||
|
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import clsx from 'clsx';
|
||||||
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import ConstituentaBadge from '@/components/info/ConstituentaBadge';
|
import ConstituentaBadge from '@/components/info/ConstituentaBadge';
|
||||||
|
import { CProps } from '@/components/props';
|
||||||
import DataTable, { createColumnHelper, RowSelectionState, VisibilityState } from '@/components/ui/DataTable';
|
import DataTable, { createColumnHelper, RowSelectionState, VisibilityState } from '@/components/ui/DataTable';
|
||||||
import FlexColumn from '@/components/ui/FlexColumn';
|
import FlexColumn from '@/components/ui/FlexColumn';
|
||||||
import { useConceptOptions } from '@/context/OptionsContext';
|
import { useConceptOptions } from '@/context/OptionsContext';
|
||||||
|
@ -45,7 +46,7 @@ function RSTable({ items, maxHeight, enableSelection, selected, setSelected, onE
|
||||||
}, [windowSize]);
|
}, [windowSize]);
|
||||||
|
|
||||||
const handleRowClicked = useCallback(
|
const handleRowClicked = useCallback(
|
||||||
(cst: IConstituenta, event: React.MouseEvent<Element, MouseEvent>) => {
|
(cst: IConstituenta, event: CProps.EventMouse) => {
|
||||||
if (event.altKey) {
|
if (event.altKey) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
onEdit(cst.id);
|
onEdit(cst.id);
|
||||||
|
@ -55,7 +56,7 @@ function RSTable({ items, maxHeight, enableSelection, selected, setSelected, onE
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleRowDoubleClicked = useCallback(
|
const handleRowDoubleClicked = useCallback(
|
||||||
(cst: IConstituenta, event: React.MouseEvent<Element, MouseEvent>) => {
|
(cst: IConstituenta, event: CProps.EventMouse) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
onEdit(cst.id);
|
onEdit(cst.id);
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user