diff --git a/client/src/components/Apps/Apps.tsx b/client/src/components/Apps/Apps.tsx
index 9eaf97f..a062c56 100644
--- a/client/src/components/Apps/Apps.tsx
+++ b/client/src/components/Apps/Apps.tsx
@@ -90,12 +90,6 @@ const Apps = (props: ComponentProps): JSX.Element => {
icon='mdiPencil'
handler={toggleEdit}
/>
- {isInEdit &&
-
- }
diff --git a/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx b/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx
index caccbcc..4b39b14 100644
--- a/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx
+++ b/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx
@@ -3,9 +3,9 @@ import { connect } from 'react-redux';
import ModalForm from '../../UI/Forms/ModalForm/ModalForm';
import InputGroup from '../../UI/Forms/InputGroup/InputGroup';
-import { Category, GlobalState, NewBookmark, NewCategory, NewNotification } from '../../../interfaces';
+import { Bookmark, Category, GlobalState, NewBookmark, NewCategory, NewNotification } from '../../../interfaces';
import { ContentType } from '../Bookmarks';
-import { getCategories, addCategory, addBookmark, updateCategory, createNotification } from '../../../store/actions';
+import { getCategories, addCategory, addBookmark, updateCategory, updateBookmark, createNotification } from '../../../store/actions';
import Button from '../../UI/Buttons/Button/Button';
interface ComponentProps {
@@ -13,9 +13,11 @@ interface ComponentProps {
contentType: ContentType;
categories: Category[];
category?: Category;
+ bookmark?: Bookmark;
addCategory: (formData: NewCategory) => void;
addBookmark: (formData: NewBookmark) => void;
updateCategory: (id: number, formData: NewCategory) => void;
+ updateBookmark: (id: number, formData: NewBookmark) => void;
createNotification: (notification: NewNotification) => void;
}
@@ -38,15 +40,33 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
}
}, [props.category])
+ useEffect(() => {
+ if (props.bookmark) {
+ setFormData({
+ name: props.bookmark.name,
+ url: props.bookmark.url,
+ categoryId: props.bookmark.categoryId
+ })
+ } else {
+ setFormData({
+ name: '',
+ url: '',
+ categoryId: -1
+ })
+ }
+ }, [props.bookmark])
+
const formSubmitHandler = (e: SyntheticEvent): void => {
e.preventDefault();
- if (!props.category) {
+ if (!props.category && !props.bookmark) {
// Add new
if (props.contentType === ContentType.category) {
+ // Add category
props.addCategory(categoryName);
setCategoryName({ name: '' });
} else if (props.contentType === ContentType.bookmark) {
+ // Add bookmark
if (formData.categoryId === -1) {
props.createNotification({
title: 'Error',
@@ -64,9 +84,18 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
}
} else {
// Update
- if (props.contentType === ContentType.category) {
+ if (props.contentType === ContentType.category && props.category) {
+ // Update category
props.updateCategory(props.category.id, categoryName);
setCategoryName({ name: '' });
+ } else if (props.contentType === ContentType.bookmark && props.bookmark) {
+ // Update bookmark
+ props.updateBookmark(props.bookmark.id, formData);
+ setFormData({
+ name: '',
+ url: '',
+ categoryId: -1
+ })
}
props.modalHandler();
@@ -87,6 +116,20 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
})
}
+ let button =
+
+ if (!props.category && !props.bookmark) {
+ if (props.contentType === ContentType.category) {
+ button = ;
+ } else {
+ button = ;
+ }
+ } else if (props.category) {
+ button =
+ } else if (props.bookmark) {
+ button =
+ }
+
return (
{
id='categoryId'
required
onChange={(e) => selectChangeHandler(e)}
+ value={formData.categoryId}
>
{props.categories.map((category: Category): JSX.Element => {
@@ -159,10 +203,7 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => {
)
}
- {!props.category
- ?
- :
- }
+ {button}
)
}
@@ -178,6 +219,7 @@ const dispatchMap = {
addCategory,
addBookmark,
updateCategory,
+ updateBookmark,
createNotification
}
diff --git a/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx b/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx
index 29ee7d1..b674bea 100644
--- a/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx
+++ b/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx
@@ -1,7 +1,7 @@
import { ContentType } from '../Bookmarks';
import classes from './BookmarkTable.module.css';
import { connect } from 'react-redux';
-import { pinCategory, deleteCategory } from '../../../store/actions';
+import { pinCategory, deleteCategory, deleteBookmark } from '../../../store/actions';
import { KeyboardEvent } from 'react';
import Table from '../../UI/Table/Table';
@@ -13,7 +13,8 @@ interface ComponentProps {
categories: Category[];
pinCategory: (category: Category) => void;
deleteCategory: (id: number) => void;
- updateCategoryHandler: (category: Category) => void;
+ updateHandler: (data: Category | Bookmark) => void;
+ deleteBookmark: (bookmarkId: number, categoryId: number) => void;
}
const BookmarkTable = (props: ComponentProps): JSX.Element => {
@@ -25,6 +26,14 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => {
}
}
+ 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);
+ }
+ }
+
const keyboardActionHandler = (e: KeyboardEvent, category: Category, handler: Function) => {
if (e.key === 'Enter') {
handler(category);
@@ -51,7 +60,7 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => {
props.updateCategoryHandler(category)}
+ onClick={() => props.updateHandler(category)}
// onKeyDown={(e) => keyboardActionHandler(e, app, props.updateAppHandler)}
tabIndex={0}>
@@ -99,14 +108,14 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => {
deleteAppHandler(app)}
+ onClick={() => deleteBookmarkHandler(bookmark.bookmark)}
// onKeyDown={(e) => keyboardActionHandler(e, app, deleteAppHandler)}
tabIndex={0}>
props.updateAppHandler(app)}
+ onClick={() => props.updateHandler(bookmark.bookmark)}
// onKeyDown={(e) => keyboardActionHandler(e, app, props.updateAppHandler)}
tabIndex={0}>
@@ -120,4 +129,4 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => {
}
}
-export default connect(null, { pinCategory, deleteCategory })(BookmarkTable);
\ No newline at end of file
+export default connect(null, { pinCategory, deleteCategory, deleteBookmark })(BookmarkTable);
\ No newline at end of file
diff --git a/client/src/components/Bookmarks/Bookmarks.tsx b/client/src/components/Bookmarks/Bookmarks.tsx
index 9346262..b5f7b9b 100644
--- a/client/src/components/Bookmarks/Bookmarks.tsx
+++ b/client/src/components/Bookmarks/Bookmarks.tsx
@@ -10,7 +10,7 @@ import Headline from '../UI/Headlines/Headline/Headline';
import ActionButton from '../UI/Buttons/ActionButton/ActionButton';
import BookmarkGrid from './BookmarkGrid/BookmarkGrid';
-import { Category, GlobalState } from '../../interfaces';
+import { Category, GlobalState, Bookmark } from '../../interfaces';
import Spinner from '../UI/Spinner/Spinner';
import Modal from '../UI/Modal/Modal';
import BookmarkForm from './BookmarkForm/BookmarkForm';
@@ -41,6 +41,14 @@ const Bookmarks = (props: ComponentProps): JSX.Element => {
createdAt: new Date(),
updatedAt: new Date()
})
+ const [bookmarkInUpdate, setBookmarkInUpdate] = useState ({
+ name: '',
+ url: '',
+ categoryId: -1,
+ id: -1,
+ createdAt: new Date(),
+ updatedAt: new Date()
+ })
useEffect(() => {
if (props.categories.length === 0) {
@@ -58,10 +66,6 @@ const Bookmarks = (props: ComponentProps): JSX.Element => {
toggleModal();
}
- const toggleEdit = (): void => {
- setIsInEdit(!isInEdit);
- }
-
const editActionHandler = (contentType: ContentType) => {
// We're in the edit mode and the same button was clicked - go back to list
if (isInEdit && contentType === tableContentType) {
@@ -72,20 +76,30 @@ const Bookmarks = (props: ComponentProps): JSX.Element => {
}
}
- const goToUpdateMode = (category: Category): void => {
- setIsInUpdate(true);
- setCategoryInUpdate(category);
- toggleModal();
+ const instanceOfCategory = (object: any): object is Category => {
+ return 'bookmarks' in object;
}
- let modalForm: JSX.Element;
+ const goToUpdateMode = (data: Category | Bookmark): void => {
+ setIsInUpdate(true);
+ if (instanceOfCategory(data)) {
+ setFormContentType(ContentType.category);
+ setCategoryInUpdate(data);
+ } else {
+ setFormContentType(ContentType.bookmark);
+ setBookmarkInUpdate(data);
+ }
+ toggleModal();
+ }
return (
{!isInUpdate
?
- :
+ : formContentType === ContentType.category
+ ?
+ :
}
@@ -126,7 +140,7 @@ const Bookmarks = (props: ComponentProps): JSX.Element => {
: ()
)
}
diff --git a/client/src/store/actions/actionTypes.ts b/client/src/store/actions/actionTypes.ts
index 8b8b523..4ff088c 100644
--- a/client/src/store/actions/actionTypes.ts
+++ b/client/src/store/actions/actionTypes.ts
@@ -10,10 +10,13 @@ import {
// Categories
GetCategoriesAction,
AddCategoryAction,
- AddBookmarkAction,
PinCategoryAction,
DeleteCategoryAction,
UpdateCategoryAction,
+ // Bookmarks
+ AddBookmarkAction,
+ DeleteBookmarkAction,
+ UpdateBookmarkAction,
// Notifications
CreateNotificationAction,
ClearNotificationAction
@@ -36,10 +39,13 @@ export enum ActionTypes {
getCategoriesSuccess = 'GET_CATEGORIES_SUCCESS',
getCategoriesError = 'GET_CATEGORIES_ERROR',
addCategory = 'ADD_CATEGORY',
- addBookmark = 'ADD_BOOKMARK',
pinCategory = 'PIN_CATEGORY',
deleteCategory = 'DELETE_CATEGORY',
updateCategory = 'UPDATE_CATEGORY',
+ // Bookmarks
+ addBookmark = 'ADD_BOOKMARK',
+ deleteBookmark = 'DELETE_BOOKMARK',
+ updateBookmark = 'UPDATE_BOOKMARK',
// Notifications
createNotification = 'CREATE_NOTIFICATION',
clearNotification = 'CLEAR_NOTIFICATION'
@@ -57,10 +63,13 @@ export type Action =
// Categories
GetCategoriesAction |
AddCategoryAction |
- AddBookmarkAction |
PinCategoryAction |
DeleteCategoryAction |
UpdateCategoryAction |
+ // Bookmarks
+ AddBookmarkAction |
+ DeleteBookmarkAction |
+ UpdateBookmarkAction |
// Notifications
CreateNotificationAction |
ClearNotificationAction;
\ No newline at end of file
diff --git a/client/src/store/actions/bookmark.ts b/client/src/store/actions/bookmark.ts
index 279d740..013846b 100644
--- a/client/src/store/actions/bookmark.ts
+++ b/client/src/store/actions/bookmark.ts
@@ -176,4 +176,68 @@ export const updateCategory = (id: number, formData: NewCategory) => async (disp
} catch (err) {
console.log(err);
}
+}
+
+/**
+ * DELETE BOOKMARK
+ */
+export interface DeleteBookmarkAction {
+ type: ActionTypes.deleteBookmark,
+ payload: {
+ bookmarkId: number,
+ categoryId: number
+ }
+}
+
+export const deleteBookmark = (bookmarkId: number, categoryId: number) => async (dispatch: Dispatch) => {
+ try {
+ const res = await axios.delete>(`/api/bookmarks/${bookmarkId}`);
+
+ dispatch({
+ type: ActionTypes.createNotification,
+ payload: {
+ title: 'Success',
+ message: 'Bookmark deleted'
+ }
+ })
+
+ dispatch({
+ type: ActionTypes.deleteBookmark,
+ payload: {
+ bookmarkId,
+ categoryId
+ }
+ })
+ } catch (err) {
+ console.log(err);
+ }
+}
+
+/**
+ * UPDATE BOOKMARK
+ */
+export interface UpdateBookmarkAction {
+ type: ActionTypes.updateBookmark,
+ payload: Bookmark
+}
+
+export const updateBookmark = (bookmarkId: number, formData: NewBookmark) => async (dispatch: Dispatch) => {
+ try {
+ const res = await axios.put>(`/api/bookmarks/${bookmarkId}`, formData);
+
+ dispatch({
+ type: ActionTypes.createNotification,
+ payload: {
+ title: 'Success',
+ message: `Bookmark ${formData.name} updated`
+ }
+ })
+
+ dispatch({
+ type: ActionTypes.updateBookmark,
+ payload: res.data.data
+ })
+ } catch (err) {
+ console.log(err);
+ }
}
\ No newline at end of file
diff --git a/client/src/store/reducers/bookmark.ts b/client/src/store/reducers/bookmark.ts
index 4a75491..d650a1a 100644
--- a/client/src/store/reducers/bookmark.ts
+++ b/client/src/store/reducers/bookmark.ts
@@ -92,6 +92,26 @@ const updateCategory = (state: State, action: Action): State => {
}
}
+const deleteBookmark = (state: State, action: Action): State => {
+ const tmpCategories = [...state.categories];
+ const categoryInUpdate = tmpCategories.find((category: Category) => category.id === action.payload.categoryId);
+
+ if (categoryInUpdate) {
+ categoryInUpdate.bookmarks = categoryInUpdate.bookmarks.filter((bookmark: Bookmark) => bookmark.id !== action.payload.bookmarkId);
+ }
+
+ return {
+ ...state,
+ categories: tmpCategories
+ }
+}
+
+const updateBookmark = (state: State, action: Action): State => {
+ return {
+ ...state
+ }
+}
+
const bookmarkReducer = (state = initialState, action: Action) => {
switch (action.type) {
case ActionTypes.getCategories: return getCategories(state, action);
@@ -101,6 +121,8 @@ const bookmarkReducer = (state = initialState, action: Action) => {
case ActionTypes.pinCategory: return pinCategory(state, action);
case ActionTypes.deleteCategory: return deleteCategory(state, action);
case ActionTypes.updateCategory: return updateCategory(state, action);
+ case ActionTypes.deleteBookmark: return deleteBookmark(state, action);
+ case ActionTypes.updateBookmark: return updateBookmark(state, action);
default: return state;
}
}
|