From 55051fcb2626a837e0255231b58d0c79cd22a43c Mon Sep 17 00:00:00 2001 From: saengel Date: Wed, 20 Nov 2024 10:44:36 +0200 Subject: [PATCH 1/9] feat(integrating notes): first pass --- sefaria/urls.py | 1 + static/js/ReaderApp.jsx | 7 +++++++ static/js/ReaderPanel.jsx | 2 +- static/js/UserHistoryPanel.jsx | 25 +++++++++++++++++++------ 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/sefaria/urls.py b/sefaria/urls.py index eb5acc6dd2..91ad4c959a 100644 --- a/sefaria/urls.py +++ b/sefaria/urls.py @@ -30,6 +30,7 @@ url(r'^$', reader_views.home, name="home"), url(r'^texts/?$', reader_views.texts_list, name="table_of_contents"), url(r'^texts/saved/?$', reader_views.saved), + url(r'^texts/notes/?$', reader_views.notes), url(r'^texts/history/?$', reader_views.user_history), url(r'^texts/recent/?$', reader_views.old_recent_redirect), url(r'^texts/(?P.+)?$', reader_views.texts_category_list), diff --git a/static/js/ReaderApp.jsx b/static/js/ReaderApp.jsx index edc2438b13..0e922f7c89 100644 --- a/static/js/ReaderApp.jsx +++ b/static/js/ReaderApp.jsx @@ -1114,6 +1114,10 @@ toggleSignUpModal(modalContentKind = SignUpModalKind.Default) { } else if (path === "/texts/saved") { this.showSaved(); + } + else if (path === "/texts/notes") { + this.showNotes(); + } else if (path.match(/\/texts\/.+/)) { this.showLibrary(path.slice(7).split("/")); @@ -1740,6 +1744,9 @@ toggleSignUpModal(modalContentKind = SignUpModalKind.Default) { showSaved() { this.setSinglePanelState({menuOpen: "saved"}); } + showNotes() { + this.setSinglePanelState({menuOpen: "notes"}); + } showHistory() { this.setSinglePanelState({menuOpen: "history"}); } diff --git a/static/js/ReaderPanel.jsx b/static/js/ReaderPanel.jsx index bdfc71c30c..a6e36dd274 100644 --- a/static/js/ReaderPanel.jsx +++ b/static/js/ReaderPanel.jsx @@ -1038,7 +1038,7 @@ class ReaderPanel extends Component { interfaceLang={this.props.interfaceLang} /> ); - } else if (this.state.menuOpen === "saved" || this.state.menuOpen === "history") { + } else if (this.state.menuOpen === "saved" || this.state.menuOpen === "history" || this.state.menuOpen === "notes") { menu = ( { const store = menuOpen === "saved" ? Sefaria.saved : Sefaria.userHistory; + const notes = Sefaria.allPrivateNotes(); const contentRef = useRef(); const title = ( @@ -34,6 +35,10 @@ const UserHistoryPanel = ({menuOpen, toggleLanguage, openDisplaySettings, openNa History + {/**Add URL */} + {/**Change icon */} + Notes + ); @@ -55,12 +60,20 @@ const UserHistoryPanel = ({menuOpen, toggleLanguage, openDisplaySettings, openNa {Sefaria.interfaceLang !== "hebrew" && Sefaria._siteSettings.TORAH_SPECIFIC ? : null} - + { menuOpen === "notes" ? + (notes.length ? + notes.map(function(item, i) { + return + }.bind(this)) + : ) + : + + } From 7c348a3bb40a0941438c02a574435b5907add19c Mon Sep 17 00:00:00 2001 From: saengel Date: Thu, 21 Nov 2024 15:39:10 +0200 Subject: [PATCH 2/9] chore(notes integration): continued wiring, console --- reader/views.py | 5 +++++ static/js/NoteListing.jsx | 2 ++ static/js/UserHistoryPanel.jsx | 28 +++++++++++++++++++++++++--- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/reader/views.py b/reader/views.py index 947651463b..9e2fd84f66 100644 --- a/reader/views.py +++ b/reader/views.py @@ -1069,6 +1069,11 @@ def user_history(request): desc = _("See your user history on Sefaria") return menu_page(request, props, page="history", title=title, desc=desc) +def notes(request): + title = _("My Notes") + desc = _("See your notes on Sefaria") + props = {"saved": {"loaded": True, "items": []}} + return menu_page(request, None, page="notes", title=title, desc=desc) @login_required def user_stats(request): diff --git a/static/js/NoteListing.jsx b/static/js/NoteListing.jsx index 188ce844af..7943a7a954 100644 --- a/static/js/NoteListing.jsx +++ b/static/js/NoteListing.jsx @@ -37,6 +37,8 @@ class NoteListing extends Component { var data = this.props.data; var url = "/" + Sefaria.normRef(data.ref) + "?with=Notes"; + console.log(data.ref, data.text); + return (
diff --git a/static/js/UserHistoryPanel.jsx b/static/js/UserHistoryPanel.jsx index d2301a8768..340f97efc0 100644 --- a/static/js/UserHistoryPanel.jsx +++ b/static/js/UserHistoryPanel.jsx @@ -22,9 +22,30 @@ import { const UserHistoryPanel = ({menuOpen, toggleLanguage, openDisplaySettings, openNav, compare, toggleSignUpModal}) => { const store = menuOpen === "saved" ? Sefaria.saved : Sefaria.userHistory; - const notes = Sefaria.allPrivateNotes(); + + let flattenedNotes = []; + let notes = null; + +// Call the allPrivateNotes function + Sefaria.allPrivateNotes((data) => { + if (Array.isArray(data)) { + // Map the data to extract 'ref' and 'text' pairs + flattenedNotes = data.map(note => ({ + ref: note.ref, + text: note.text + })); + + console.log("Flattened notes:", flattenedNotes); // Log the result + notes = flattenedNotes; + } else { + console.error("Unexpected data format:", data); + } +}); + const contentRef = useRef(); + console.log(notes); + const title = ( @@ -35,7 +56,7 @@ const UserHistoryPanel = ({menuOpen, toggleLanguage, openDisplaySettings, openNa History - {/**Add URL */} + {/**Change icon */} Notes @@ -61,8 +82,9 @@ const UserHistoryPanel = ({menuOpen, toggleLanguage, openDisplaySettings, openNa : null}
{ menuOpen === "notes" ? - (notes.length ? + (notes && notes.length ? notes.map(function(item, i) { + {console.log(`item ${item}, i: ${i}`);} return }.bind(this)) : ) From 685ad957f882295f1c017c1d2b5aea1ed8def856 Mon Sep 17 00:00:00 2001 From: saengel Date: Tue, 26 Nov 2024 15:37:51 +0200 Subject: [PATCH 3/9] feat(notes): Fix async issues, make separate NoteList component --- static/js/NoteListing.jsx | 10 +++++++ static/js/UserHistoryPanel.jsx | 51 ++++++++++++++-------------------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/static/js/NoteListing.jsx b/static/js/NoteListing.jsx index 7943a7a954..adf5420fe4 100644 --- a/static/js/NoteListing.jsx +++ b/static/js/NoteListing.jsx @@ -76,4 +76,14 @@ NoteListing.defaultProps = { showText: true }; +const NotesList = ({notes}) => { + return ( + notes && notes.length ? + notes.map((item, i) => ( + + )) + : )}; + + export default NoteListing; +export { NotesList }; diff --git a/static/js/UserHistoryPanel.jsx b/static/js/UserHistoryPanel.jsx index 340f97efc0..df72d2c6c2 100644 --- a/static/js/UserHistoryPanel.jsx +++ b/static/js/UserHistoryPanel.jsx @@ -5,6 +5,7 @@ import Component from 'react-class'; import Sefaria from './sefaria/sefaria'; import { useScrollToLoad } from "./Hooks"; import { NavSidebar } from './NavSidebar'; +import { NotesList } from './NoteListing'; import { SheetBlock, TextPassage @@ -21,30 +22,23 @@ import { const UserHistoryPanel = ({menuOpen, toggleLanguage, openDisplaySettings, openNav, compare, toggleSignUpModal}) => { - const store = menuOpen === "saved" ? Sefaria.saved : Sefaria.userHistory; - - let flattenedNotes = []; - let notes = null; - -// Call the allPrivateNotes function - Sefaria.allPrivateNotes((data) => { - if (Array.isArray(data)) { - // Map the data to extract 'ref' and 'text' pairs - flattenedNotes = data.map(note => ({ - ref: note.ref, - text: note.text - })); - - console.log("Flattened notes:", flattenedNotes); // Log the result - notes = flattenedNotes; - } else { - console.error("Unexpected data format:", data); - } -}); - + const [notes, setNotes] = useState(null); // State to manage notes const contentRef = useRef(); - console.log(notes); + useEffect(() => { + // Fetch private notes asynchronously + Sefaria.allPrivateNotes((data) => { + if (Array.isArray(data)) { + const flattenedNotes = data.map(note => ({ + ref: note.ref, + text: note.text + })); + setNotes(flattenedNotes); // Update state with notes + } else { + console.error("Unexpected data format:", data); + } + }); + }, []); // Empty dependency array ensures this runs once on mount const title = ( @@ -82,15 +76,10 @@ const UserHistoryPanel = ({menuOpen, toggleLanguage, openDisplaySettings, openNa : null}
{ menuOpen === "notes" ? - (notes && notes.length ? - notes.map(function(item, i) { - {console.log(`item ${item}, i: ${i}`);} - return - }.bind(this)) - : ) + : - ); + ); }; + UserHistoryPanel.propTypes = { toggleLanguage: PropTypes.func.isRequired, openDisplaySettings: PropTypes.func.isRequired, @@ -112,6 +102,7 @@ UserHistoryPanel.propTypes = { }; + const UserHistoryList = ({store, scrollableRef, menuOpen, toggleSignUpModal}) => { const [items, setItems] = useState(store.loaded ? store.items : null); From 88ed9f2fb1e935eb42597922477b321a3084ab32 Mon Sep 17 00:00:00 2001 From: saengel Date: Wed, 27 Nov 2024 13:40:22 +0200 Subject: [PATCH 4/9] feat(notes): Wire up URLs, import clean ups --- reader/views.py | 3 +-- static/js/NoteListing.jsx | 2 +- static/js/ReaderApp.jsx | 6 ++++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/reader/views.py b/reader/views.py index 9e2fd84f66..4b6f645752 100644 --- a/reader/views.py +++ b/reader/views.py @@ -1072,8 +1072,7 @@ def user_history(request): def notes(request): title = _("My Notes") desc = _("See your notes on Sefaria") - props = {"saved": {"loaded": True, "items": []}} - return menu_page(request, None, page="notes", title=title, desc=desc) + return menu_page(request, page="notes", title=title, desc=desc) @login_required def user_stats(request): diff --git a/static/js/NoteListing.jsx b/static/js/NoteListing.jsx index adf5420fe4..3d53af67bf 100644 --- a/static/js/NoteListing.jsx +++ b/static/js/NoteListing.jsx @@ -3,7 +3,7 @@ import $ from './sefaria/sefariaJquery'; import Sefaria from './sefaria/sefaria'; import TextRange from './TextRange'; import { AddToSourceSheetWindow } from './AddToSourceSheet'; -import { Note } from './Misc'; +import { Note, LoadingMessage } from './Misc'; import PropTypes from 'prop-types'; import Component from 'react-class'; diff --git a/static/js/ReaderApp.jsx b/static/js/ReaderApp.jsx index 0e922f7c89..648b3d2439 100644 --- a/static/js/ReaderApp.jsx +++ b/static/js/ReaderApp.jsx @@ -571,6 +571,12 @@ class ReaderApp extends Component { hist.title = Sefaria._("My Reading History"); hist.url = "texts/history"; hist.mode = "history"; + break; + case "notes": + hist.title = Sefaria._("My Notes"); + hist.url = "texts/notes"; + hist.mode = "notes"; + break; } hist.url = addTab(hist.url) } else if (state.mode === "Text") { From a8745476abbc5864f4b4652fac5643d8e4e25d49 Mon Sep 17 00:00:00 2001 From: saengel Date: Wed, 27 Nov 2024 13:46:06 +0200 Subject: [PATCH 5/9] chore(notes): Code clean up, streamline comments, remove console.log --- static/js/NoteListing.jsx | 2 -- static/js/UserHistoryPanel.jsx | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/static/js/NoteListing.jsx b/static/js/NoteListing.jsx index 3d53af67bf..fce667e0e7 100644 --- a/static/js/NoteListing.jsx +++ b/static/js/NoteListing.jsx @@ -37,8 +37,6 @@ class NoteListing extends Component { var data = this.props.data; var url = "/" + Sefaria.normRef(data.ref) + "?with=Notes"; - console.log(data.ref, data.text); - return (
diff --git a/static/js/UserHistoryPanel.jsx b/static/js/UserHistoryPanel.jsx index df72d2c6c2..4c1e0b06a6 100644 --- a/static/js/UserHistoryPanel.jsx +++ b/static/js/UserHistoryPanel.jsx @@ -22,18 +22,17 @@ import { const UserHistoryPanel = ({menuOpen, toggleLanguage, openDisplaySettings, openNav, compare, toggleSignUpModal}) => { - const [notes, setNotes] = useState(null); // State to manage notes + const [notes, setNotes] = useState(null); const contentRef = useRef(); useEffect(() => { - // Fetch private notes asynchronously Sefaria.allPrivateNotes((data) => { if (Array.isArray(data)) { const flattenedNotes = data.map(note => ({ ref: note.ref, text: note.text })); - setNotes(flattenedNotes); // Update state with notes + setNotes(flattenedNotes); } else { console.error("Unexpected data format:", data); } @@ -106,7 +105,6 @@ UserHistoryPanel.propTypes = { const UserHistoryList = ({store, scrollableRef, menuOpen, toggleSignUpModal}) => { const [items, setItems] = useState(store.loaded ? store.items : null); - // Store changes when switching tabs, reset items useEffect(() => { setItems(store.loaded ? store.items : null); }, [store]); From 23373b534b42c3d5bb0bccea27b62dbd72a0ce47 Mon Sep 17 00:00:00 2001 From: saengel Date: Wed, 27 Nov 2024 14:18:34 +0200 Subject: [PATCH 6/9] feat(notes): Update icon --- static/icons/notes-icon.svg | 3 +++ static/js/UserHistoryPanel.jsx | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 static/icons/notes-icon.svg diff --git a/static/icons/notes-icon.svg b/static/icons/notes-icon.svg new file mode 100644 index 0000000000..ca78771d8f --- /dev/null +++ b/static/icons/notes-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/js/UserHistoryPanel.jsx b/static/js/UserHistoryPanel.jsx index 4c1e0b06a6..8116b53fa7 100644 --- a/static/js/UserHistoryPanel.jsx +++ b/static/js/UserHistoryPanel.jsx @@ -50,7 +50,7 @@ const UserHistoryPanel = ({menuOpen, toggleLanguage, openDisplaySettings, openNa History - {/**Change icon */} + {/**Change icon */} Notes From 4d8ce33396e2bf64c8a4d30ac906832c14c26c32 Mon Sep 17 00:00:00 2001 From: saengel Date: Wed, 27 Nov 2024 14:19:06 +0200 Subject: [PATCH 7/9] chore(notes): Remove todo --- static/js/UserHistoryPanel.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/js/UserHistoryPanel.jsx b/static/js/UserHistoryPanel.jsx index 8116b53fa7..3a081041c5 100644 --- a/static/js/UserHistoryPanel.jsx +++ b/static/js/UserHistoryPanel.jsx @@ -50,7 +50,7 @@ const UserHistoryPanel = ({menuOpen, toggleLanguage, openDisplaySettings, openNa History - {/**Change icon */} + Notes From f1192b40528507eb3d87069b511ea9abf10d5cf8 Mon Sep 17 00:00:00 2001 From: saengel Date: Thu, 28 Nov 2024 11:06:46 +0200 Subject: [PATCH 8/9] chore(notes): Updating and smoothing over design fixes since updated note component merged into modularization-main --- static/css/s2.css | 1 + static/js/NoteListing.jsx | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/static/css/s2.css b/static/css/s2.css index b016bf6c9d..99fc62dfa3 100644 --- a/static/css/s2.css +++ b/static/css/s2.css @@ -9180,6 +9180,7 @@ div.aboutSheetMetadata span:not(:first-child)::before{ .noteListing { margin-bottom: 30px; border-bottom: 1px solid #ccc; + padding-bottom: 10px; } .noteListing a:hover { text-decoration: none; diff --git a/static/js/NoteListing.jsx b/static/js/NoteListing.jsx index 20f2d39781..3c793fe125 100644 --- a/static/js/NoteListing.jsx +++ b/static/js/NoteListing.jsx @@ -59,18 +59,14 @@ class NoteListing extends Component { } NoteListing.propTypes = { data: PropTypes.object.isRequired, - showText: PropTypes.bool, onDeleteNote: PropTypes.func, }; -NoteListing.defaultProps = { - showText: true -}; const NotesList = ({notes}) => { return ( notes && notes.length ? notes.map((item, i) => ( - + )) : )}; From acfd76a1f81270c3a3b56ed4ca428efcd690b858 Mon Sep 17 00:00:00 2001 From: saengel Date: Wed, 11 Dec 2024 13:50:18 +0200 Subject: [PATCH 9/9] chore(note): Addressing PR feedback --- reader/views.py | 1 + static/js/ReaderApp.jsx | 3 +-- static/js/ReaderPanel.jsx | 2 +- static/js/UserHistoryPanel.jsx | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/reader/views.py b/reader/views.py index 1ee85fff57..bf3b255fcd 100644 --- a/reader/views.py +++ b/reader/views.py @@ -1072,6 +1072,7 @@ def user_history(request): desc = _("See your user history on Sefaria") return menu_page(request, props, page="history", title=title, desc=desc) +@login_required def notes(request): title = _("My Notes") desc = _("See your notes on Sefaria") diff --git a/static/js/ReaderApp.jsx b/static/js/ReaderApp.jsx index fdfa2444db..5fa03328b6 100644 --- a/static/js/ReaderApp.jsx +++ b/static/js/ReaderApp.jsx @@ -1137,8 +1137,7 @@ toggleSignUpModal(modalContentKind = SignUpModalKind.Default) { } else if (path === "/texts/saved") { this.showSaved(); - } - else if (path === "/texts/notes") { + } else if (path === "/texts/notes") { this.showNotes(); } else if (path.match(/\/texts\/.+/)) { diff --git a/static/js/ReaderPanel.jsx b/static/js/ReaderPanel.jsx index 9c720dc2f8..74e08ce76d 100644 --- a/static/js/ReaderPanel.jsx +++ b/static/js/ReaderPanel.jsx @@ -1064,7 +1064,7 @@ class ReaderPanel extends Component { interfaceLang={this.props.interfaceLang} /> ); - } else if (this.state.menuOpen === "saved" || this.state.menuOpen === "history" || this.state.menuOpen === "notes") { + } else if (["saved", "history", "notes"].includes(this.state.menuOpen)) { menu = ( @@ -101,10 +101,10 @@ UserHistoryPanel.propTypes = { }; - const UserHistoryList = ({store, scrollableRef, menuOpen, toggleSignUpModal}) => { const [items, setItems] = useState(store.loaded ? store.items : null); + // Store changes when switching tabs, reset items useEffect(() => { setItems(store.loaded ? store.items : null); }, [store]);