- {props.category.bookmarks.map((bookmark: Bookmark) => {
+ {category.bookmarks.map((bookmark: Bookmark) => {
const redirectUrl = urlParser(bookmark.url)[1];
let iconEl: JSX.Element =
;
diff --git a/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.module.css b/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.module.css
index 8c0d1abc78fccf4fcacb42b0799f9b6b4cfbf67e..9e89f3a5f5dd47de43a868a3e861f85be099a890 100644
--- a/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.module.css
+++ b/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.module.css
@@ -20,12 +20,3 @@
grid-template-columns: repeat(4, 1fr);
}
}
-
-.BookmarksMessage {
- color: var(--color-primary);
-}
-
-.BookmarksMessage a {
- color: var(--color-accent);
- font-weight: 600;
-}
\ No newline at end of file
diff --git a/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx b/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx
index 516c3b2c853234d299ea042c99a521d6b0633be9..7e26c32280774cb2c92beb7860907c3d077419e6 100644
--- a/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx
+++ b/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx
@@ -5,48 +5,57 @@ import classes from './BookmarkGrid.module.css';
import { Category } from '../../../interfaces';
import { BookmarkCard } from '../BookmarkCard/BookmarkCard';
+import { Message } from '../../UI';
interface Props {
categories: Category[];
totalCategories?: number;
searching: boolean;
+ fromHomepage?: boolean;
}
export const BookmarkGrid = (props: Props): JSX.Element => {
+ const {
+ categories,
+ totalCategories,
+ searching,
+ fromHomepage = false,
+ } = props;
+
let bookmarks: JSX.Element;
- if (props.categories.length) {
- if (props.searching && !props.categories[0].bookmarks.length) {
- bookmarks = (
-
- No bookmarks match your search criteria
-
- );
+ if (categories.length) {
+ if (searching && !categories[0].bookmarks.length) {
+ bookmarks =
No bookmarks match your search criteria;
} else {
bookmarks = (
- {props.categories.map(
+ {categories.map(
(category: Category): JSX.Element => (
-
+
)
)}
);
}
} else {
- if (props.totalCategories) {
+ if (totalCategories) {
bookmarks = (
-
+
There are no pinned categories. You can pin them from the{' '}
/bookmarks menu
-
+
);
} else {
bookmarks = (
-
+
You don't have any bookmarks. You can add a new one from{' '}
/bookmarks menu
-
+
);
}
}
diff --git a/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx b/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx
deleted file mode 100644
index 2cc487860b0dc8876f8da91f8a847a1318848fd6..0000000000000000000000000000000000000000
--- a/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx
+++ /dev/null
@@ -1,272 +0,0 @@
-import { KeyboardEvent, useState, useEffect, Fragment } from 'react';
-import {
- DragDropContext,
- Droppable,
- Draggable,
- DropResult,
-} from 'react-beautiful-dnd';
-import { Link } from 'react-router-dom';
-
-// Redux
-import { useDispatch, useSelector } from 'react-redux';
-import { State } from '../../../store/reducers';
-import { bindActionCreators } from 'redux';
-import { actionCreators } from '../../../store';
-
-// Typescript
-import { Bookmark, Category } from '../../../interfaces';
-import { ContentType } from '../Bookmarks';
-
-// CSS
-import classes from './BookmarkTable.module.css';
-
-// UI
-import { Table, Icon } from '../../UI';
-
-interface Props {
- contentType: ContentType;
- categories: Category[];
- updateHandler: (data: Category | Bookmark) => void;
-}
-
-export const BookmarkTable = (props: Props): JSX.Element => {
- const { config } = useSelector((state: State) => state.config);
-
- const dispatch = useDispatch();
- const {
- pinCategory,
- deleteCategory,
- deleteBookmark,
- createNotification,
- reorderCategories,
- } = bindActionCreators(actionCreators, dispatch);
-
- const [localCategories, setLocalCategories] = useState
([]);
- const [isCustomOrder, setIsCustomOrder] = useState(false);
-
- // Copy categories array
- useEffect(() => {
- setLocalCategories([...props.categories]);
- }, [props.categories]);
-
- // Check ordering
- useEffect(() => {
- const order = config.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) {
- deleteCategory(category.id);
- }
- };
-
- const deleteBookmarkHandler = (bookmark: Bookmark): void => {
- const proceed = window.confirm(
- `Are you sure you want to delete ${bookmark.name}?`
- );
-
- if (proceed) {
- deleteBookmark(bookmark.id, bookmark.categoryId);
- }
- };
-
- const keyboardActionHandler = (
- e: KeyboardEvent,
- category: Category,
- handler: Function
- ) => {
- if (e.key === 'Enter') {
- handler(category);
- }
- };
-
- const dragEndHanlder = (result: DropResult): void => {
- if (!isCustomOrder) {
- createNotification({
- title: 'Error',
- message: 'Custom order is disabled',
- });
- return;
- }
-
- if (!result.destination) {
- return;
- }
-
- const tmpCategories = [...localCategories];
- const [movedApp] = tmpCategories.splice(result.source.index, 1);
- tmpCategories.splice(result.destination.index, 0, movedApp);
-
- setLocalCategories(tmpCategories);
- reorderCategories(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 (
-
-
- {category.name}
- |
-
- {category.isPublic ? 'Visible' : 'Hidden'}
- |
- {!snapshot.isDragging && (
-
-
- deleteCategoryHandler(category)
- }
- onKeyDown={(e) =>
- keyboardActionHandler(
- e,
- category,
- deleteCategoryHandler
- )
- }
- tabIndex={0}
- >
-
-
-
- props.updateHandler(category)
- }
- tabIndex={0}
- >
-
-
- pinCategory(category)}
- onKeyDown={(e) =>
- keyboardActionHandler(
- e,
- category,
- pinCategory
- )
- }
- tabIndex={0}
- >
- {category.isPinned ? (
-
- ) : (
-
- )}
-
- |
- )}
-
- );
- }}
-
- );
- }
- )}
-
- )}
-
-
-
- );
- } else {
- const bookmarks: { bookmark: Bookmark; categoryName: string }[] = [];
- props.categories.forEach((category: Category) => {
- category.bookmarks.forEach((bookmark: Bookmark) => {
- bookmarks.push({
- bookmark,
- categoryName: category.name,
- });
- });
- });
-
- return (
-
- {bookmarks.map(
- (bookmark: { bookmark: Bookmark; categoryName: string }) => {
- return (
-
- {bookmark.bookmark.name} |
- {bookmark.bookmark.url} |
- {bookmark.bookmark.icon} |
- {bookmark.bookmark.isPublic ? 'Visible' : 'Hidden'} |
- {bookmark.categoryName} |
-
- deleteBookmarkHandler(bookmark.bookmark)}
- tabIndex={0}
- >
-
-
- props.updateHandler(bookmark.bookmark)}
- tabIndex={0}
- >
-
-
- |
-
- );
- }
- )}
-
- );
- }
-};
diff --git a/client/src/components/Bookmarks/Bookmarks.tsx b/client/src/components/Bookmarks/Bookmarks.tsx
index 62a2e1597f7ed238d2754cd0709025eec9cdaf02..a70899532a0987dbceef1f007757b25b26153c2d 100644
--- a/client/src/components/Bookmarks/Bookmarks.tsx
+++ b/client/src/components/Bookmarks/Bookmarks.tsx
@@ -18,11 +18,8 @@ import { Container, Headline, ActionButton, Spinner, Modal } from '../UI';
// Components
import { BookmarkGrid } from './BookmarkGrid/BookmarkGrid';
-import { BookmarkTable } from './BookmarkTable/BookmarkTable';
import { Form } from './Form/Form';
-
-// Utils
-import { bookmarkTemplate, categoryTemplate } from '../../utility';
+import { Table } from './Table/Table';
interface Props {
searching: boolean;
@@ -34,76 +31,96 @@ export enum ContentType {
}
export const Bookmarks = (props: Props): JSX.Element => {
+ // Get Redux state
const {
- bookmarks: { loading, categories },
+ bookmarks: { loading, categories, categoryInEdit },
auth: { isAuthenticated },
} = useSelector((state: State) => state);
+ // Get Redux action creators
const dispatch = useDispatch();
- const { getCategories } = bindActionCreators(actionCreators, dispatch);
-
- const [modalIsOpen, setModalIsOpen] = useState(false);
- const [formContentType, setFormContentType] = useState(ContentType.category);
- const [isInEdit, setIsInEdit] = useState(false);
- const [tableContentType, setTableContentType] = useState(
- ContentType.category
- );
- const [isInUpdate, setIsInUpdate] = useState(false);
- const [categoryInUpdate, setCategoryInUpdate] =
- useState(categoryTemplate);
- const [bookmarkInUpdate, setBookmarkInUpdate] =
- useState(bookmarkTemplate);
+ const { getCategories, setEditCategory, setEditBookmark } =
+ bindActionCreators(actionCreators, dispatch);
+ // Load categories if array is empty
useEffect(() => {
if (!categories.length) {
getCategories();
}
}, []);
- // observe if user is authenticated -> set default view if not
+ // Form
+ const [modalIsOpen, setModalIsOpen] = useState(false);
+ const [formContentType, setFormContentType] = useState(ContentType.category);
+ const [isInUpdate, setIsInUpdate] = useState(false);
+
+ // Table
+ const [showTable, setShowTable] = useState(false);
+ const [tableContentType, setTableContentType] = useState(
+ ContentType.category
+ );
+
+ // Observe if user is authenticated -> set default view (grid) if not
useEffect(() => {
if (!isAuthenticated) {
- setIsInEdit(false);
+ setShowTable(false);
setModalIsOpen(false);
}
}, [isAuthenticated]);
+ useEffect(() => {
+ if (categoryInEdit && !modalIsOpen) {
+ setTableContentType(ContentType.bookmark);
+ setShowTable(true);
+ }
+ }, [categoryInEdit]);
+
+ useEffect(() => {
+ setShowTable(false);
+ setEditCategory(null);
+ }, []);
+
+ // Form actions
const toggleModal = (): void => {
setModalIsOpen(!modalIsOpen);
};
- const addActionHandler = (contentType: ContentType) => {
+ const openFormForAdding = (contentType: ContentType) => {
setFormContentType(contentType);
setIsInUpdate(false);
toggleModal();
};
- const editActionHandler = (contentType: ContentType) => {
- // We're in the edit mode and the same button was clicked - go back to list
- if (isInEdit && contentType === tableContentType) {
- setIsInEdit(false);
- } else {
- setIsInEdit(true);
- setTableContentType(contentType);
- }
- };
+ const openFormForUpdating = (data: Category | Bookmark): void => {
+ setIsInUpdate(true);
- const instanceOfCategory = (object: any): object is Category => {
- return 'bookmarks' in object;
- };
+ const instanceOfCategory = (object: any): object is Category => {
+ return 'bookmarks' in object;
+ };
- const goToUpdateMode = (data: Category | Bookmark): void => {
- setIsInUpdate(true);
if (instanceOfCategory(data)) {
setFormContentType(ContentType.category);
- setCategoryInUpdate(data);
+ setEditCategory(data);
} else {
setFormContentType(ContentType.bookmark);
- setBookmarkInUpdate(data);
+ setEditBookmark(data);
}
+
toggleModal();
};
+ // Table actions
+ const showTableForEditing = (contentType: ContentType) => {
+ // We're in the edit mode and the same button was clicked - go back to list
+ if (showTable && contentType === tableContentType) {
+ setEditCategory(null);
+ setShowTable(false);
+ } else {
+ setShowTable(true);
+ setTableContentType(contentType);
+ }
+ };
+
return (
@@ -111,8 +128,6 @@ export const Bookmarks = (props: Props): JSX.Element => {
modalHandler={toggleModal}
contentType={formContentType}
inUpdate={isInUpdate}
- category={categoryInUpdate}
- bookmark={bookmarkInUpdate}
/>
@@ -123,35 +138,34 @@ export const Bookmarks = (props: Props): JSX.Element => {
addActionHandler(ContentType.category)}
+ handler={() => openFormForAdding(ContentType.category)}
/>
addActionHandler(ContentType.bookmark)}
+ handler={() => openFormForAdding(ContentType.bookmark)}
/>
editActionHandler(ContentType.category)}
+ handler={() => showTableForEditing(ContentType.category)}
/>
editActionHandler(ContentType.bookmark)}
+ handler={() => showTableForEditing(ContentType.bookmark)}
/>
)}
diff --git a/client/src/components/Bookmarks/Form/BookmarksForm.tsx b/client/src/components/Bookmarks/Form/BookmarksForm.tsx
index f0a3a4370f46e59b74de4a5188ad26ac4925af61..893b3348fbf064f8fd74f4121ca6a4afbd23429f 100644
--- a/client/src/components/Bookmarks/Form/BookmarksForm.tsx
+++ b/client/src/components/Bookmarks/Form/BookmarksForm.tsx
@@ -137,15 +137,15 @@ export const BookmarksForm = ({
}
modalHandler();
-
- setFormData(newBookmarkTemplate);
-
- setCustomIcon(null);
}
+
+ setFormData({ ...newBookmarkTemplate, categoryId: formData.categoryId });
+ setCustomIcon(null);
};
return (