Improve notes list UI:

- Show both sections even on search
- Add new note creation popups with an option to create from annotations
- Hide child notes section if no parent item
This commit is contained in:
Martynas Bagdonas 2021-02-25 14:59:41 +02:00 committed by Dan Stillman
parent d47ec92116
commit 17abf87bcf
4 changed files with 103 additions and 33 deletions

View file

@ -51,11 +51,11 @@ const NoteRow = ({ title, body, date, onClick, parentItemType, parentTitle }) =>
);
};
const NotesList = forwardRef(({ onClick, onNewChild, onNewStandalone }, ref) => {
const NotesList = forwardRef(({ onClick, onAddChildButtonDown, onAddStandaloneButtonDown }, ref) => {
const [notes, setNotes] = useState([]);
const [expanded, setExpanded] = useState(false);
const [searching, setSearching] = useState(false);
useImperativeHandle(ref, () => ({ setNotes, setExpanded, setSearching }));
const [hasParent, setHasParent] = useState(true);
useImperativeHandle(ref, () => ({ setNotes, setExpanded, setHasParent }));
function handleClickMore() {
setExpanded(true);
@ -65,27 +65,27 @@ const NotesList = forwardRef(({ onClick, onNewChild, onNewStandalone }, ref) =>
let allNotes = notes.filter(x => !x.isCurrentChild);
return (
<div className="notes-list">
{(!!childNotes.length || !searching) && <section>
{hasParent && <section>
<div className="header-row">
<h2>{Zotero.getString('pane.context.itemNotes')}</h2>
{!searching && <button onClick={onNewChild}>+</button>}
<button onMouseDown={onAddChildButtonDown}>+</button>
</div>
{!childNotes.length && !searching && <div className="empty-row">{Zotero.getString('pane.context.noNotes')}</div>}
{!childNotes.length && <div className="empty-row">{Zotero.getString('pane.context.noNotes')}</div>}
{childNotes.map(note => <NoteRow key={note.id} {...note} onClick={() => onClick(note.id)}/>)}
</section>}
{(!!allNotes.length || !searching) && <section>
<section>
<div className="header-row">
<h2>{Zotero.getString('pane.context.allNotes')}</h2>
{!searching && <button onClick={onNewStandalone}>+</button>}
<button onMouseDown={onAddStandaloneButtonDown}>+</button>
</div>
{!allNotes.length && !searching && <div className="empty-row">{Zotero.getString('pane.context.noNotes')}</div>}
{!allNotes.length && <div className="empty-row">{Zotero.getString('pane.context.noNotes')}</div>}
{(expanded ? allNotes : allNotes.slice(0, MAX_ALL_NOTES)).map(note => <NoteRow key={note.id} {...note} onClick={() => onClick(note.id)}/>)}
{!expanded && allNotes.length > MAX_ALL_NOTES
&& <div className="more-row" onClick={handleClickMore}>{
Zotero.getString('general.numMore', Zotero.Utilities.numberFormat([allNotes.length - MAX_ALL_NOTES], 0))
}</div>
}
</section>}
</section>
</div>
);
});

View file

@ -370,13 +370,10 @@ var ZoteroContextPane = new function () {
_panesDeck.append(_itemPaneDeck, _notesPaneDeck);
}
function _getCurrentParentItem() {
function _getCurrentAttachment() {
var reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
if (reader) {
var attachment = Zotero.Items.get(reader.itemID);
if (attachment) {
return attachment.parentItem;
}
return Zotero.Items.get(reader.itemID);
}
}
@ -408,19 +405,42 @@ var ZoteroContextPane = new function () {
var head = document.createElement('hbox');
head.style.display = 'flex';
async function _createNoteFromAnnotations(child) {
var attachment = _getCurrentAttachment();
if (!attachment) {
return;
}
var note = await Zotero.EditorInstance.createNoteFromAnnotations(
attachment.getAnnotations(), child && attachment.parentID
);
function _createNote(parentID) {
_updateAddToNote();
input.value = '';
_updateNotesList();
_setPinnedNote(note.id);
}
function _createNote(child) {
contextNode.setAttribute('selectedIndex', 1);
var item = new Zotero.Item('note');
item.libraryID = libraryID;
if (parentID) {
item.parentID = parentID;
if (child) {
var attachment = _getCurrentAttachment();
if (!attachment) {
return;
}
item.parentID = attachment.parentID;
}
editor.mode = 'edit';
editor.item = item;
editor.parentItem = null;
editor.focus();
_updateAddToNote();
input.value = '';
_updateNotesList();
}
var vbox = document.createElement('vbox');
@ -498,11 +518,12 @@ var ZoteroContextPane = new function () {
context.cachedNotes = notes;
}
var readerParentItem = _getCurrentParentItem();
notesListRef.current.setSearching(query.length);
var attachment = _getCurrentAttachment();
var parentID = attachment && attachment.parentID;
notesListRef.current.setHasParent(!!parentID);
notesListRef.current.setNotes(notes.map(note => ({
...note,
isCurrentChild: readerParentItem && note.parentID == readerParentItem.id
isCurrentChild: parentID && note.parentID == parentID
})));
}
@ -516,20 +537,49 @@ var ZoteroContextPane = new function () {
updateFromCache: () => _updateNotesList(true)
};
function _handleAddChildNotePopupClick(event) {
switch (event.originalTarget.id) {
case 'context-pane-add-child-note':
_createNote(true);
break;
case 'context-pane-add-child-note-from-annotations':
_createNoteFromAnnotations(true);
break;
default:
}
}
function _handleAddStandaloneNotePopupClick(event) {
switch (event.originalTarget.id) {
case 'context-pane-add-standalone-note':
_createNote();
break;
case 'context-pane-add-standalone-note-from-annotations':
_createNoteFromAnnotations();
break;
default:
}
}
ReactDOM.render(
<NotesList
ref={notesListRef}
onClick={(id) => {
_setPinnedNote(libraryID, id);
_setPinnedNote(id);
}}
onNewChild={() => {
var parentItem = _getCurrentParentItem();
if (parentItem) {
_createNote(parentItem.id);
}
onAddChildButtonDown={(event) => {
var popup = document.getElementById('context-pane-add-child-note-button-popup');
popup.onclick = _handleAddChildNotePopupClick;
popup.openPopup(event.target, 'after_end');
}}
onNewStandalone={() => {
_createNote();
onAddStandaloneButtonDown={(event) => {
var popup = document.getElementById('context-pane-add-standalone-note-button-popup');
popup.onclick = _handleAddStandaloneNotePopupClick;
popup.openPopup(event.target, 'after_end');
}}
/>,
listInner,
@ -570,10 +620,13 @@ var ZoteroContextPane = new function () {
return true;
}
function _setPinnedNote(libraryID, itemID) {
var editable = _isLibraryEditable(libraryID);
var context = _getNotesContext(libraryID);
function _setPinnedNote(itemID) {
var item = Zotero.Items.get(itemID);
if (!item) {
return;
}
var editable = _isLibraryEditable(item.libraryID);
var context = _getNotesContext(item.libraryID);
if (context) {
var { editor, node } = context;
node.setAttribute('selectedIndex', 1);

View file

@ -632,6 +632,18 @@
<hbox id="zotero-context-pane-inner" flex="1" zotero-persist="height"/>
</vbox>
</box>
<popupset>
<menupopup id="context-pane-add-child-note-button-popup">
<menuitem id="context-pane-add-child-note" label="&zotero.context.addChildNote;"/>
<menuitem id="context-pane-add-child-note-from-annotations" label="&zotero.context.addChildNoteFromAnnotations;"/>
</menupopup>
<menupopup id="context-pane-add-standalone-note-button-popup">
<menuitem id="context-pane-add-standalone-note" label="&zotero.context.addStandaloneNote;"/>
<menuitem id="context-pane-add-standalone-note-from-annotations" label="&zotero.context.addStandaloneNoteFromAnnotations;"/>
</menupopup>
</popupset>
</hbox>
<!-- Barrier to prevent tabbing into Zotero pane when busy -->

View file

@ -329,3 +329,8 @@
<!ENTITY zotero.attachLink.title "Attach Link to URI">
<!ENTITY zotero.attachLink.label.link "Link:">
<!ENTITY zotero.attachLink.label.title "Title:">
<!ENTITY zotero.context.addChildNote "Add Item Note">
<!ENTITY zotero.context.addChildNoteFromAnnotations "Add Item Note from Annotations">
<!ENTITY zotero.context.addStandaloneNote "Add Standalone Note">
<!ENTITY zotero.context.addStandaloneNoteFromAnnotations "Add Standalone Note from Annotations">