From 8a735818d4b29c962b972126c25c9e42e3ad56ed Mon Sep 17 00:00:00 2001 From: Nizreen Ana Zulkiflee Date: Tue, 28 May 2024 16:41:25 +0200 Subject: [PATCH] FEATURE: Add a document created by other to one's bookshelf (closes #150). --- backend/src/views/all_documents/map.js | 5 +++ backend/src/views/bookmark/map.js | 5 +++ frontend/src/components/Bookmark.js | 52 ++++++++++++++++++++++ frontend/src/components/OpenedDocuments.js | 9 ++-- frontend/src/hyperglosae.js | 14 ++++++ frontend/src/styles/Lectern.css | 4 ++ 6 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 backend/src/views/bookmark/map.js create mode 100644 frontend/src/components/Bookmark.js diff --git a/backend/src/views/all_documents/map.js b/backend/src/views/all_documents/map.js index 47ac7594..2f473b10 100644 --- a/backend/src/views/all_documents/map.js +++ b/backend/src/views/all_documents/map.js @@ -1,5 +1,10 @@ function (metadata) { + if (metadata.bookmark) { + emit([metadata.editors[0], metadata.bookmark], {_id: metadata.bookmark}); + return; + } + if (!metadata.dc_title) return; const editors = metadata.editors || ['PUBLIC']; diff --git a/backend/src/views/bookmark/map.js b/backend/src/views/bookmark/map.js new file mode 100644 index 00000000..39bbb000 --- /dev/null +++ b/backend/src/views/bookmark/map.js @@ -0,0 +1,5 @@ +function (doc) { + if (doc.bookmark) { + emit([doc.editors[0], doc.bookmark]); + } +} diff --git a/frontend/src/components/Bookmark.js b/frontend/src/components/Bookmark.js new file mode 100644 index 00000000..d6b1de75 --- /dev/null +++ b/frontend/src/components/Bookmark.js @@ -0,0 +1,52 @@ +import { useState, useEffect } from 'react'; +import { BookmarkFill } from 'react-bootstrap-icons'; +import { v4 as uuid } from 'uuid'; + +function Bookmark({backend, id}) { + const [isBookmarked, setIsBookmarked] = useState(false); + let user = backend.credentials.name; + + const getBookmark = (id, user) => + backend.getView({view: 'bookmark', id: user, options: ['include_docs']}) + .then(rows => rows.find(row => row.doc.bookmark === id)); + + useEffect(() => { + if (user) { + getBookmark(id, user) + .then(bookmark => setIsBookmarked(!!bookmark)) + .catch(console.error); + } + }, [user, id, backend]); + + const createBookmark = () => + backend.putDocument({ + _id: uuid(), + editors: [user], + bookmark: id + }); + + const removeBookmark = () => + getBookmark(id, user) + .then(bookmark => bookmark.doc) + .then(backend.deleteDocument); + + const onBookmarkToggle = () => { + if (!isBookmarked) { + createBookmark(user, id) + .then(() => setIsBookmarked(true)) + .catch(console.error); + } else { + removeBookmark(id, user) + .then(() => setIsBookmarked(false)) + .catch(console.error); + } + }; + + return ( + + ); +} + +export default Bookmark; diff --git a/frontend/src/components/OpenedDocuments.js b/frontend/src/components/OpenedDocuments.js index cdd6b598..e973a13a 100644 --- a/frontend/src/components/OpenedDocuments.js +++ b/frontend/src/components/OpenedDocuments.js @@ -1,18 +1,18 @@ import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; -import { BookmarkFill } from 'react-bootstrap-icons'; import BrowseTools from './BrowseTools'; import Metadata from './Metadata'; import Type, { TypeBadge } from './Type'; import Passage from './Passage'; import License from './License'; import More from './More'; +import Bookmark from './Bookmark'; function OpenedDocuments({backend, lectern, metadata, sourceMetadata, margin, hasSources, id, setLastUpdate}) { return ( - + (x._id === margin)) } /> @@ -36,10 +36,11 @@ function OpenedDocuments({backend, lectern, metadata, sourceMetadata, margin, ha ); } -function RunningHeadSource({metadata, hasSources}) { +function RunningHeadSource({metadata, hasSources, backend}) { + let id = metadata?._id; return ( - + diff --git a/frontend/src/hyperglosae.js b/frontend/src/hyperglosae.js index bdf65e5e..758dad99 100644 --- a/frontend/src/hyperglosae.js +++ b/frontend/src/hyperglosae.js @@ -46,6 +46,20 @@ function Hyperglosae(logger) { return x; }); + this.deleteDocument = ({_id, _rev}) => + fetch(`${service}/${_id}?rev=${_rev}`, { + method: 'DELETE', + headers: basicAuthentication({ force: false }) + }) + .then(x => x.json()) + .then(x => { + if (x.reason) { + logger(x.reason); + throw new Error(x.reason); + } + return x; + }); + this.getDocumentMetadata = (id) => fetch(`${service}/${id}`, { method: 'HEAD', diff --git a/frontend/src/styles/Lectern.css b/frontend/src/styles/Lectern.css index 4fde20f8..ad700dd1 100644 --- a/frontend/src/styles/Lectern.css +++ b/frontend/src/styles/Lectern.css @@ -81,3 +81,7 @@ dd { padding-left: 30px; } +.icon.bookmarked { + color: gold; /* or any color that indicates an active bookmark */ +} +