import { Fragment, KeyboardEvent, useEffect, useState } from 'react'; import { DragDropContext, Draggable, Droppable, DropResult } from 'react-beautiful-dnd'; import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; import { Bookmark, Category, NewNotification } from '../../../interfaces'; import { createNotification, deleteBookmark, deleteBookmarkCategory, pinBookmark, pinBookmarkCategory, reorderBookmarkCategories, reorderBookmarks, updateConfig, } from '../../../store/actions'; import { searchConfig } from '../../../utility'; import Icon from '../../UI/Icons/Icon/Icon'; import Table from '../../UI/Table/Table'; import { ContentType } from '../Bookmarks'; import classes from './BookmarkTable.module.css'; interface ComponentProps { contentType: ContentType; categories: Category[]; bookmarks: Bookmark[]; pinBookmarkCategory: (category: Category) => void; deleteBookmarkCategory: (id: number) => void; reorderBookmarkCategories: (categories: Category[]) => void; updateHandler: (data: Category | Bookmark) => void; pinBookmark: (bookmark: Bookmark) => void; deleteBookmark: (id: number, categoryId: number) => void; reorderBookmarks: (bookmarks: Bookmark[]) => void; updateConfig: (formData: any) => void; createNotification: (notification: NewNotification) => void; } const BookmarkTable = (props: ComponentProps): JSX.Element => { const [localCategories, setLocalCategories] = useState([]); const [localBookmarks, setLocalBookmarks] = useState([]); const [isCustomOrder, setIsCustomOrder] = useState(false); // Copy categories array useEffect(() => { setLocalCategories([...props.categories]); }, [props.categories]); // Copy bookmarks array useEffect(() => { setLocalBookmarks([...props.bookmarks]); }, [props.bookmarks]); // Check ordering useEffect(() => { const order = searchConfig("useOrdering", ""); if (order === "orderId") { setIsCustomOrder(true); } }, []); const deleteCategoryHandler = (category: Category): void => { const proceed = window.confirm( `Are you sure you want to delete ${category.name}? It will delete ALL assigned bookmarks` ); if (proceed) { props.deleteBookmarkCategory(category.id); } }; const deleteBookmarkHandler = (bookmark: Bookmark): void => { const proceed = window.confirm( `Are you sure you want to delete ${bookmark.name}?` ); if (proceed) { props.deleteBookmark(bookmark.id, bookmark.categoryId); } }; // Support keyboard navigation for actions const keyboardActionHandler = ( e: KeyboardEvent, object: any, handler: Function ) => { if (e.key === "Enter") { handler(object); } }; const dragEndHandler = (result: DropResult): void => { if (!isCustomOrder) { props.createNotification({ title: "Error", message: "Custom order is disabled", }); return; } if (!result.destination) { return; } if (props.contentType === ContentType.bookmark) { const tmpBookmarks = [...localBookmarks]; const [movedBookmark] = tmpBookmarks.splice(result.source.index, 1); tmpBookmarks.splice(result.destination.index, 0, movedBookmark); setLocalBookmarks(tmpBookmarks); props.reorderBookmarks(tmpBookmarks); } else if (props.contentType === ContentType.category) { const tmpCategories = [...localCategories]; const [movedCategory] = tmpCategories.splice(result.source.index, 1); tmpCategories.splice(result.destination.index, 0, movedCategory); setLocalCategories(tmpCategories); props.reorderBookmarkCategories(tmpCategories); } }; if (props.contentType === ContentType.category) { return (
{isCustomOrder ? (

You can drag and drop single rows to reorder categories

) : (

Custom order is disabled. You can change it in{" "} settings

)}
{(provided) => ( {localCategories.map( (category: Category, index): JSX.Element => { return ( {(provided, snapshot) => { const style = { border: snapshot.isDragging ? "1px solid var(--color-accent)" : "none", borderRadius: "4px", ...provided.draggableProps.style, }; return ( {!snapshot.isDragging && ( )} ); }} ); } )}
{category.name}
deleteCategoryHandler(category) } onKeyDown={(e) => keyboardActionHandler( e, category, deleteCategoryHandler ) } tabIndex={0} >
props.updateHandler(category) } tabIndex={0} >
props.pinBookmarkCategory(category) } onKeyDown={(e) => keyboardActionHandler( e, category, props.pinBookmarkCategory ) } tabIndex={0} > {category.isPinned ? ( ) : ( )}
)}
); } else { return (
{isCustomOrder ? (

You can drag and drop single rows to reorder bookmark

) : (

Custom order is disabled. You can change it in{" "} settings

)}
{(provided) => ( {localBookmarks.map( (bookmark: Bookmark, index): JSX.Element => { return ( {(provided, snapshot) => { const style = { border: snapshot.isDragging ? "1px solid var(--color-accent)" : "none", borderRadius: "4px", ...provided.draggableProps.style, }; const category = localCategories.find( (category: Category) => category.id === bookmark.categoryId ); const categoryName = category?.name; return ( {!snapshot.isDragging && ( )} ); }} ); } )}
{bookmark.name} {bookmark.url} {bookmark.icon} {categoryName}
deleteBookmarkHandler(bookmark) } onKeyDown={(e) => keyboardActionHandler( e, bookmark, deleteBookmarkHandler ) } tabIndex={0} >
props.updateHandler(bookmark) } onKeyDown={(e) => keyboardActionHandler( e, bookmark, props.updateHandler ) } tabIndex={0} >
props.pinBookmark(bookmark)} onKeyDown={(e) => keyboardActionHandler( e, bookmark, props.pinBookmark ) } tabIndex={0} > {bookmark.isPinned ? ( ) : ( )}
)}
); } }; const actions = { pinBookmarkCategory, deleteBookmarkCategory, reorderBookmarkCategories, pinBookmark, deleteBookmark, reorderBookmarks, updateConfig, createNotification, }; export default connect(null, actions)(BookmarkTable);