Add "Create Note from Annotations" option to items list context menu
To allow creation of a standalone note with annotations from all the selected top-level items and/or attachments. Annotations will be sorted by the order of the items in the items list. "Add Note from Annotations" remains when a single regular item or one or more attachments under a single regular item are selected.
This commit is contained in:
parent
894309d061
commit
66fccec6b4
4 changed files with 371 additions and 39 deletions
|
@ -3150,7 +3150,6 @@ var ZoteroPane = new function()
|
||||||
'sep1',
|
'sep1',
|
||||||
'addNote',
|
'addNote',
|
||||||
'createNoteFromAnnotations',
|
'createNoteFromAnnotations',
|
||||||
'createNoteFromAnnotationsMenu',
|
|
||||||
'addAttachments',
|
'addAttachments',
|
||||||
'sep2',
|
'sep2',
|
||||||
'findPDF',
|
'findPDF',
|
||||||
|
@ -3286,12 +3285,33 @@ var ZoteroPane = new function()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Add Notes from Annotation" and "Find Available PDFs"
|
// "Add/Create Note from Annotations" and "Find Available PDFs"
|
||||||
if (collectionTreeRow.filesEditable
|
if (collectionTreeRow.filesEditable
|
||||||
&& !collectionTreeRow.isDuplicates()
|
&& !collectionTreeRow.isDuplicates()
|
||||||
&& !collectionTreeRow.isFeed()) {
|
&& !collectionTreeRow.isFeed()) {
|
||||||
if (items.some(item => attachmentsWithExtractableAnnotations(item).length)) {
|
if (items.some(item => attachmentsWithExtractableAnnotations(item).length)
|
||||||
|
|| items.some(item => isAttachmentWithExtractableAnnotations(item))) {
|
||||||
|
let menuitem = menu.childNodes[m.createNoteFromAnnotations];
|
||||||
show.add(m.createNoteFromAnnotations);
|
show.add(m.createNoteFromAnnotations);
|
||||||
|
let key;
|
||||||
|
// If all from a single item, show "Add Note from Annotations"
|
||||||
|
if (Zotero.Items.getTopLevel(items).length == 1) {
|
||||||
|
key = 'addNoteFromAnnotations';
|
||||||
|
menuitem.onclick = async () => {
|
||||||
|
return this.addNoteFromAnnotationsFromSelected();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Otherwise show "Create Note from Annotations"
|
||||||
|
else {
|
||||||
|
key = 'createNoteFromAnnotations';
|
||||||
|
menuitem.onclick = async () => {
|
||||||
|
return this.createStandaloneNoteFromAnnotationsFromSelected();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
menuitem.setAttribute(
|
||||||
|
'label',
|
||||||
|
Zotero.getString('pane.items.menu.' + key)
|
||||||
|
);
|
||||||
show.add(m.sep3);
|
show.add(m.sep3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3351,43 +3371,42 @@ var ZoteroPane = new function()
|
||||||
show.add(m.sep1);
|
show.add(m.sep1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show "Add Note from Annotations" on parent item with any extractable annotations
|
||||||
if (item.isRegularItem() && !item.isFeedItem) {
|
if (item.isRegularItem() && !item.isFeedItem) {
|
||||||
show.add(m.addNote);
|
show.add(m.addNote);
|
||||||
show.add(m.addAttachments);
|
show.add(m.addAttachments);
|
||||||
show.add(m.sep2);
|
show.add(m.sep2);
|
||||||
|
|
||||||
// Create Note from Annotations
|
let attachmentsWithAnnotations = Zotero.Items.get(item.getAttachments())
|
||||||
let popup = document.getElementById('create-note-from-annotations-popup');
|
|
||||||
popup.textContent = '';
|
|
||||||
let eligibleAttachments = Zotero.Items.get(item.getAttachments())
|
|
||||||
.filter(item => item.isPDFAttachment());
|
|
||||||
let attachmentsWithAnnotations = eligibleAttachments
|
|
||||||
.filter(item => isAttachmentWithExtractableAnnotations(item));
|
.filter(item => isAttachmentWithExtractableAnnotations(item));
|
||||||
if (attachmentsWithAnnotations.length) {
|
if (attachmentsWithAnnotations.length) {
|
||||||
// Display submenu if there's more than one PDF attachment, even if
|
|
||||||
// there's only attachment with annotations, so it's clear which one
|
|
||||||
// the annotations are coming from
|
|
||||||
if (eligibleAttachments.length > 1) {
|
|
||||||
show.add(m.createNoteFromAnnotationsMenu);
|
|
||||||
for (let attachment of attachmentsWithAnnotations) {
|
|
||||||
let menuitem = document.createElement('menuitem');
|
|
||||||
menuitem.setAttribute('label', attachment.getDisplayTitle());
|
|
||||||
menuitem.onclick = () => {
|
|
||||||
ZoteroPane.createNoteFromAnnotationsForAttachment(attachment);
|
|
||||||
};
|
|
||||||
popup.appendChild(menuitem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Single attachment with annotations
|
|
||||||
else {
|
|
||||||
show.add(m.createNoteFromAnnotations);
|
show.add(m.createNoteFromAnnotations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// Show "(Create|Add) Note from Annotations" on attachment with extractable annotations
|
||||||
else if (isAttachmentWithExtractableAnnotations(item) && !item.isTopLevelItem()) {
|
else if (isAttachmentWithExtractableAnnotations(item)) {
|
||||||
show.add(m.createNoteFromAnnotations);
|
show.add(m.createNoteFromAnnotations);
|
||||||
show.add(m.sep2);
|
show.add(m.sep2);
|
||||||
}
|
}
|
||||||
|
if (show.has(m.createNoteFromAnnotations)) {
|
||||||
|
let menuitem = menu.childNodes[m.createNoteFromAnnotations];
|
||||||
|
let str;
|
||||||
|
// Show "Create" on standalone attachments
|
||||||
|
if (item.isAttachment() && item.isTopLevelItem()) {
|
||||||
|
str = 'pane.items.menu.createNoteFromAnnotations';
|
||||||
|
menuitem.onclick = async () => {
|
||||||
|
return this.createStandaloneNoteFromAnnotationsFromSelected();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// And "Add" otherwise
|
||||||
|
else {
|
||||||
|
str = 'pane.items.menu.addNoteFromAnnotations';
|
||||||
|
menuitem.onclick = async () => {
|
||||||
|
return this.addNoteFromAnnotationsFromSelected();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
menuitem.setAttribute('label', Zotero.getString(str));
|
||||||
|
}
|
||||||
|
|
||||||
if (Zotero.Attachments.canFindPDFForItem(item)) {
|
if (Zotero.Attachments.canFindPDFForItem(item)) {
|
||||||
show.add(m.findPDF);
|
show.add(m.findPDF);
|
||||||
|
@ -3553,8 +3572,6 @@ var ZoteroPane = new function()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set labels, plural if necessary
|
// Set labels, plural if necessary
|
||||||
menu.childNodes[m.createNoteFromAnnotations].setAttribute('label', Zotero.getString('pane.items.menu.addNoteFromAnnotations' + multiple));
|
|
||||||
menu.childNodes[m.createNoteFromAnnotationsMenu].setAttribute('label', Zotero.getString('pane.items.menu.addNoteFromAnnotations' + multiple));
|
|
||||||
menu.childNodes[m.findPDF].setAttribute('label', Zotero.getString('pane.items.menu.findAvailablePDF' + multiple));
|
menu.childNodes[m.findPDF].setAttribute('label', Zotero.getString('pane.items.menu.findAvailablePDF' + multiple));
|
||||||
menu.childNodes[m.moveToTrash].setAttribute('label', Zotero.getString('pane.items.menu.moveToTrash' + multiple));
|
menu.childNodes[m.moveToTrash].setAttribute('label', Zotero.getString('pane.items.menu.moveToTrash' + multiple));
|
||||||
menu.childNodes[m.deleteFromLibrary].setAttribute('label', Zotero.getString('pane.items.menu.delete'));
|
menu.childNodes[m.deleteFromLibrary].setAttribute('label', Zotero.getString('pane.items.menu.delete'));
|
||||||
|
@ -4952,7 +4969,7 @@ var ZoteroPane = new function()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.createNoteFromAnnotationsForAttachment = async function (attachment, { skipSelect } = {}) {
|
this.addNoteFromAnnotationsForAttachment = async function (attachment, { skipSelect } = {}) {
|
||||||
if (!this.canEdit()) {
|
if (!this.canEdit()) {
|
||||||
this.displayCannotEditLibraryMessage();
|
this.displayCannotEditLibraryMessage();
|
||||||
return;
|
return;
|
||||||
|
@ -4975,7 +4992,75 @@ var ZoteroPane = new function()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.createNoteFromAnnotationsFromSelected = async function () {
|
/**
|
||||||
|
* Add a single child note with the annotations from all selected items, including from all
|
||||||
|
* child attachments of a selected regular item
|
||||||
|
*
|
||||||
|
* Selected items must all have the same top-level item
|
||||||
|
*/
|
||||||
|
this.addNoteFromAnnotationsFromSelected = async function () {
|
||||||
|
if (!this.canEdit()) {
|
||||||
|
this.displayCannotEditLibraryMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var items = this.getSelectedItems();
|
||||||
|
var topLevelItems = [...new Set(Zotero.Items.getTopLevel(items))];
|
||||||
|
if (topLevelItems.length > 1) {
|
||||||
|
throw new Error("Can't create child attachment from different top-level items");
|
||||||
|
}
|
||||||
|
var topLevelItem = topLevelItems[0];
|
||||||
|
if (!topLevelItem.isRegularItem()) {
|
||||||
|
throw new Error("Can't add note to standalone attachment");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore top-level item if specific child items are also selected
|
||||||
|
if (items.length > 1) {
|
||||||
|
items = items.filter(item => !item.isRegularItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
var attachments = [];
|
||||||
|
for (let item of items) {
|
||||||
|
if (item.isRegularItem()) {
|
||||||
|
// Find all child items with extractable annotations
|
||||||
|
attachments.push(
|
||||||
|
...Zotero.Items.get(item.getAttachments())
|
||||||
|
.filter(item => isAttachmentWithExtractableAnnotations(item))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (isAttachmentWithExtractableAnnotations(item)) {
|
||||||
|
attachments.push(item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!attachments.length) {
|
||||||
|
Zotero.debug("No attachments found", 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var annotations = [];
|
||||||
|
for (let attachment of attachments) {
|
||||||
|
annotations.push(...attachment.getAnnotations());
|
||||||
|
}
|
||||||
|
var note = await Zotero.EditorInstance.createNoteFromAnnotations(
|
||||||
|
annotations,
|
||||||
|
{
|
||||||
|
parentID: topLevelItem.id
|
||||||
|
}
|
||||||
|
);
|
||||||
|
await this.selectItem(note.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create separate child notes for each selected item, including all child attachments of
|
||||||
|
* selected regular items
|
||||||
|
*
|
||||||
|
* No longer exposed via UI
|
||||||
|
*/
|
||||||
|
this.addNotesFromAnnotationsFromSelected = async function () {
|
||||||
if (!this.canEdit()) {
|
if (!this.canEdit()) {
|
||||||
this.displayCannotEditLibraryMessage();
|
this.displayCannotEditLibraryMessage();
|
||||||
return;
|
return;
|
||||||
|
@ -5001,7 +5086,7 @@ var ZoteroPane = new function()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (let attachment of attachments) {
|
for (let attachment of attachments) {
|
||||||
let note = await this.createNoteFromAnnotationsForAttachment(
|
let note = await this.addNoteFromAnnotationsForAttachment(
|
||||||
attachment,
|
attachment,
|
||||||
{ skipSelect: true }
|
{ skipSelect: true }
|
||||||
);
|
);
|
||||||
|
@ -5013,6 +5098,59 @@ var ZoteroPane = new function()
|
||||||
await this.selectItems(itemIDsToSelect);
|
await this.selectItems(itemIDsToSelect);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
this.createStandaloneNoteFromAnnotationsFromSelected = async function () {
|
||||||
|
if (!this.canEdit()) {
|
||||||
|
this.displayCannotEditLibraryMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var items = this.getSelectedItems();
|
||||||
|
|
||||||
|
// Ignore selected top-level items if any descendant items are also selected
|
||||||
|
var topLevelOfSelectedDescendants = new Set();
|
||||||
|
for (let item of items) {
|
||||||
|
if (!item.isTopLevelItem()) {
|
||||||
|
topLevelOfSelectedDescendants.add(item.topLevelItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
items = items.filter(item => !topLevelOfSelectedDescendants.has(item));
|
||||||
|
|
||||||
|
var annotations = [];
|
||||||
|
for (let item of items) {
|
||||||
|
let attachments = [];
|
||||||
|
if (item.isRegularItem()) {
|
||||||
|
// Find all child attachments with extractable annotations
|
||||||
|
attachments.push(
|
||||||
|
...Zotero.Items.get(item.getAttachments())
|
||||||
|
.filter(item => isAttachmentWithExtractableAnnotations(item))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (isAttachmentWithExtractableAnnotations(item)) {
|
||||||
|
attachments.push(item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (let attachment of attachments) {
|
||||||
|
annotations.push(...attachment.getAnnotations());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!annotations.length) {
|
||||||
|
Zotero.debug("No annotations found", 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var note = await Zotero.EditorInstance.createNoteFromAnnotations(
|
||||||
|
annotations,
|
||||||
|
{
|
||||||
|
collectionID: this.getSelectedCollection(true)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
await this.selectItem(note.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
this.createEmptyParent = async function (item) {
|
this.createEmptyParent = async function (item) {
|
||||||
await Zotero.DB.executeTransaction(async function () {
|
await Zotero.DB.executeTransaction(async function () {
|
||||||
// TODO: remove once there are no top-level web attachments
|
// TODO: remove once there are no top-level web attachments
|
||||||
|
|
|
@ -293,11 +293,7 @@
|
||||||
<!-- with icon: <menuitem class="menuitem-iconic" id="zotero-menuitem-note" label="&zotero.items.menu.attach.note;" oncommand="ZoteroPane_Local.newNote(false, this.parentNode.getAttribute('itemID'))"/>-->
|
<!-- with icon: <menuitem class="menuitem-iconic" id="zotero-menuitem-note" label="&zotero.items.menu.attach.note;" oncommand="ZoteroPane_Local.newNote(false, this.parentNode.getAttribute('itemID'))"/>-->
|
||||||
<menuitem class="menuitem-iconic zotero-menuitem-attach-note" label="&zotero.items.menu.attach.note;" oncommand="ZoteroPane_Local.newNote(false, this.parentNode.getAttribute('itemKey'))"/>
|
<menuitem class="menuitem-iconic zotero-menuitem-attach-note" label="&zotero.items.menu.attach.note;" oncommand="ZoteroPane_Local.newNote(false, this.parentNode.getAttribute('itemKey'))"/>
|
||||||
|
|
||||||
<menuitem class="menuitem-iconic zotero-menuitem-create-note-from-annotations"
|
<menuitem class="menuitem-iconic zotero-menuitem-create-note-from-annotations"/>
|
||||||
oncommand="ZoteroPane.createNoteFromAnnotationsFromSelected()"/>
|
|
||||||
<menu class="menuitem-iconic zotero-menuitem-create-note-from-annotations">
|
|
||||||
<menupopup id="create-note-from-annotations-popup"/>
|
|
||||||
</menu>
|
|
||||||
|
|
||||||
<menu class="menu-iconic zotero-menuitem-attach" label="&zotero.items.menu.attach;">
|
<menu class="menu-iconic zotero-menuitem-attach" label="&zotero.items.menu.attach;">
|
||||||
<menupopup id="zotero-add-attachment-popup">
|
<menupopup id="zotero-add-attachment-popup">
|
||||||
|
|
|
@ -333,7 +333,7 @@ pane.items.removeRecursive.title = Remove from Collection and Subcollections
|
||||||
pane.items.removeRecursive = Are you sure you want to remove the selected item from this collection and all subcollections?
|
pane.items.removeRecursive = Are you sure you want to remove the selected item from this collection and all subcollections?
|
||||||
pane.items.removeRecursive.multiple = Are you sure you want to remove the selected items from this collection and all subcollections?
|
pane.items.removeRecursive.multiple = Are you sure you want to remove the selected items from this collection and all subcollections?
|
||||||
pane.items.menu.addNoteFromAnnotations = Add Note from Annotations
|
pane.items.menu.addNoteFromAnnotations = Add Note from Annotations
|
||||||
pane.items.menu.addNoteFromAnnotations.multiple = Add Notes from Annotations
|
pane.items.menu.createNoteFromAnnotations = Create Note from Annotations
|
||||||
pane.items.menu.findAvailablePDF = Find Available PDF
|
pane.items.menu.findAvailablePDF = Find Available PDF
|
||||||
pane.items.menu.findAvailablePDF.multiple = Find Available PDFs
|
pane.items.menu.findAvailablePDF.multiple = Find Available PDFs
|
||||||
pane.items.menu.addToCollection = Add to Collection
|
pane.items.menu.addToCollection = Add to Collection
|
||||||
|
|
|
@ -338,6 +338,204 @@ describe("ZoteroPane", function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
describe("#addNoteFromAnnotationsFromSelected()", function () {
|
||||||
|
it("should create a single note within a selected regular item for all child attachments", async function () {
|
||||||
|
var item = await createDataObject('item');
|
||||||
|
var attachment1 = await importPDFAttachment(item);
|
||||||
|
var attachment2 = await importPDFAttachment(item);
|
||||||
|
var annotation1 = await createAnnotation('highlight', attachment1);
|
||||||
|
var annotation2 = await createAnnotation('highlight', attachment1);
|
||||||
|
var annotation3 = await createAnnotation('highlight', attachment2);
|
||||||
|
var annotation4 = await createAnnotation('highlight', attachment2);
|
||||||
|
await zp.selectItems([item.id]);
|
||||||
|
await zp.addNoteFromAnnotationsFromSelected();
|
||||||
|
var newItems = zp.getSelectedItems();
|
||||||
|
assert.lengthOf(newItems, 1);
|
||||||
|
var note = newItems[0];
|
||||||
|
assert.equal(note.itemType, 'note');
|
||||||
|
assert.equal(note.parentID, item.id);
|
||||||
|
var dp = new DOMParser();
|
||||||
|
var doc = dp.parseFromString(note.getNote(), 'text/html');
|
||||||
|
assert.sameMembers(
|
||||||
|
[...doc.querySelectorAll('h3')].map(x => x.textContent),
|
||||||
|
[attachment1.attachmentFilename, attachment2.attachmentFilename]
|
||||||
|
);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('h3 + p')], 2);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('span.highlight')], 4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create a single note within the parent for all selected sibling attachments", async function () {
|
||||||
|
var item = await createDataObject('item');
|
||||||
|
var attachment1 = await importPDFAttachment(item);
|
||||||
|
var attachment2 = await importPDFAttachment(item);
|
||||||
|
var annotation1 = await createAnnotation('highlight', attachment1);
|
||||||
|
var annotation2 = await createAnnotation('highlight', attachment1);
|
||||||
|
var annotation3 = await createAnnotation('highlight', attachment2);
|
||||||
|
var annotation4 = await createAnnotation('highlight', attachment2);
|
||||||
|
await zp.selectItems([attachment1.id, attachment2.id]);
|
||||||
|
await zp.addNoteFromAnnotationsFromSelected();
|
||||||
|
var newItems = zp.getSelectedItems();
|
||||||
|
assert.lengthOf(newItems, 1);
|
||||||
|
var note = newItems[0];
|
||||||
|
assert.equal(note.parentID, item.id);
|
||||||
|
var dp = new DOMParser();
|
||||||
|
var doc = dp.parseFromString(note.getNote(), 'text/html');
|
||||||
|
assert.sameMembers(
|
||||||
|
[...doc.querySelectorAll('h3')].map(x => x.textContent),
|
||||||
|
[attachment1.attachmentFilename, attachment2.attachmentFilename]
|
||||||
|
);
|
||||||
|
// No item titles
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('h2 + p')], 0);
|
||||||
|
// Just attachment titles
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('h3 + p')], 2);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('span.highlight')], 4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should ignore top-level item if child attachment is also selected", async function () {
|
||||||
|
var item = await createDataObject('item');
|
||||||
|
var attachment1 = await importPDFAttachment(item);
|
||||||
|
var attachment2 = await importPDFAttachment(item);
|
||||||
|
await createAnnotation('highlight', attachment1);
|
||||||
|
await createAnnotation('highlight', attachment1);
|
||||||
|
await createAnnotation('highlight', attachment2);
|
||||||
|
await zp.selectItems([item.id, attachment1.id]);
|
||||||
|
await zp.addNoteFromAnnotationsFromSelected();
|
||||||
|
var newItems = zp.getSelectedItems();
|
||||||
|
assert.lengthOf(newItems, 1);
|
||||||
|
var note = newItems[0];
|
||||||
|
var dp = new DOMParser();
|
||||||
|
var doc = dp.parseFromString(note.getNote(), 'text/html');
|
||||||
|
// No titles
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('h2 + p')], 0);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('h3 + p')], 0);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('span.highlight')], 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shouldn't do anything if parent item and child note is selected", async function () {
|
||||||
|
var item = await createDataObject('item');
|
||||||
|
var attachment = await importPDFAttachment(item);
|
||||||
|
var note = await createDataObject('item', { itemType: 'note', parentID: item.id });
|
||||||
|
await createAnnotation('highlight', attachment);
|
||||||
|
await zp.selectItems([item.id, note.id]);
|
||||||
|
await zp.addNoteFromAnnotationsFromSelected();
|
||||||
|
var selectedItems = zp.getSelectedItems();
|
||||||
|
assert.lengthOf(selectedItems, 2);
|
||||||
|
assert.sameMembers(selectedItems, [item, note]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe("#createStandaloneNoteFromAnnotationsFromSelected()", function () {
|
||||||
|
it("should create a single standalone note for all child attachments of selected regular items", async function () {
|
||||||
|
var collection = await createDataObject('collection');
|
||||||
|
var item1 = await createDataObject('item', { setTitle: true, collections: [collection.id] });
|
||||||
|
var item2 = await createDataObject('item', { setTitle: true, collections: [collection.id] });
|
||||||
|
var attachment1 = await importPDFAttachment(item1);
|
||||||
|
var attachment2 = await importPDFAttachment(item1);
|
||||||
|
var attachment3 = await importPDFAttachment(item2);
|
||||||
|
var attachment4 = await importPDFAttachment(item2);
|
||||||
|
await createAnnotation('highlight', attachment1);
|
||||||
|
await createAnnotation('highlight', attachment1);
|
||||||
|
await createAnnotation('highlight', attachment2);
|
||||||
|
await createAnnotation('highlight', attachment2);
|
||||||
|
await createAnnotation('highlight', attachment3);
|
||||||
|
await createAnnotation('highlight', attachment3);
|
||||||
|
await createAnnotation('highlight', attachment4);
|
||||||
|
await createAnnotation('highlight', attachment4);
|
||||||
|
await zp.selectItems([item1.id, item2.id]);
|
||||||
|
await zp.createStandaloneNoteFromAnnotationsFromSelected();
|
||||||
|
var newItems = zp.getSelectedItems();
|
||||||
|
assert.lengthOf(newItems, 1);
|
||||||
|
var note = newItems[0];
|
||||||
|
assert.equal(note.itemType, 'note');
|
||||||
|
assert.isFalse(note.parentID);
|
||||||
|
assert.isTrue(collection.hasItem(note));
|
||||||
|
var dp = new DOMParser();
|
||||||
|
var doc = dp.parseFromString(note.getNote(), 'text/html');
|
||||||
|
assert.sameMembers(
|
||||||
|
[...doc.querySelectorAll('h2')].map(x => x.textContent),
|
||||||
|
[item1.getDisplayTitle(), item2.getDisplayTitle()]
|
||||||
|
);
|
||||||
|
assert.sameMembers(
|
||||||
|
[...doc.querySelectorAll('h3')].map(x => x.textContent),
|
||||||
|
[
|
||||||
|
attachment1.attachmentFilename,
|
||||||
|
attachment2.attachmentFilename,
|
||||||
|
attachment3.attachmentFilename,
|
||||||
|
attachment4.attachmentFilename
|
||||||
|
]
|
||||||
|
);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('h3 + p')], 4);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('span.highlight')], 8);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create a single standalone note for all selected attachments", async function () {
|
||||||
|
var collection = await createDataObject('collection');
|
||||||
|
var item1 = await createDataObject('item', { setTitle: true, collections: [collection.id] });
|
||||||
|
var item2 = await createDataObject('item', { setTitle: true, collections: [collection.id] });
|
||||||
|
var attachment1 = await importPDFAttachment(item1);
|
||||||
|
var attachment2 = await importPDFAttachment(item1);
|
||||||
|
var attachment3 = await importPDFAttachment(item2);
|
||||||
|
var attachment4 = await importPDFAttachment(item2);
|
||||||
|
await createAnnotation('highlight', attachment1);
|
||||||
|
await createAnnotation('highlight', attachment1);
|
||||||
|
await createAnnotation('highlight', attachment2);
|
||||||
|
await createAnnotation('highlight', attachment2);
|
||||||
|
await createAnnotation('highlight', attachment3);
|
||||||
|
await createAnnotation('highlight', attachment3);
|
||||||
|
await createAnnotation('highlight', attachment4);
|
||||||
|
await createAnnotation('highlight', attachment4);
|
||||||
|
await zp.selectItems([attachment1.id, attachment3.id]);
|
||||||
|
await zp.createStandaloneNoteFromAnnotationsFromSelected();
|
||||||
|
var newItems = zp.getSelectedItems();
|
||||||
|
assert.lengthOf(newItems, 1);
|
||||||
|
var note = newItems[0];
|
||||||
|
assert.isFalse(note.parentID);
|
||||||
|
assert.isTrue(collection.hasItem(note));
|
||||||
|
var dp = new DOMParser();
|
||||||
|
var doc = dp.parseFromString(note.getNote(), 'text/html');
|
||||||
|
assert.sameMembers(
|
||||||
|
[...doc.querySelectorAll('h2')].map(x => x.textContent),
|
||||||
|
[item1.getDisplayTitle(), item2.getDisplayTitle()]
|
||||||
|
);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('h2 + p')], 2);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('h3')], 0);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('span.highlight')], 4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should ignore top-level item if child attachment is also selected", async function () {
|
||||||
|
var item1 = await createDataObject('item', { setTitle: true });
|
||||||
|
var item2 = await createDataObject('item', { setTitle: true });
|
||||||
|
var attachment1 = await importPDFAttachment(item1);
|
||||||
|
var attachment2 = await importPDFAttachment(item1);
|
||||||
|
var attachment3 = await importPDFAttachment(item2);
|
||||||
|
var attachment4 = await importPDFAttachment(item2);
|
||||||
|
await createAnnotation('highlight', attachment1);
|
||||||
|
await createAnnotation('highlight', attachment1);
|
||||||
|
await createAnnotation('highlight', attachment2);
|
||||||
|
await createAnnotation('highlight', attachment2);
|
||||||
|
await createAnnotation('highlight', attachment3);
|
||||||
|
await createAnnotation('highlight', attachment3);
|
||||||
|
await createAnnotation('highlight', attachment4);
|
||||||
|
await createAnnotation('highlight', attachment4);
|
||||||
|
await zp.selectItems([item1.id, attachment1.id, attachment3.id]);
|
||||||
|
await zp.createStandaloneNoteFromAnnotationsFromSelected();
|
||||||
|
var newItems = zp.getSelectedItems();
|
||||||
|
assert.lengthOf(newItems, 1);
|
||||||
|
var note = newItems[0];
|
||||||
|
var dp = new DOMParser();
|
||||||
|
var doc = dp.parseFromString(note.getNote(), 'text/html');
|
||||||
|
assert.sameMembers(
|
||||||
|
[...doc.querySelectorAll('h2')].map(x => x.textContent),
|
||||||
|
[item1.getDisplayTitle(), item2.getDisplayTitle()]
|
||||||
|
);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('h2 + p')], 2);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('h3')], 0);
|
||||||
|
assert.lengthOf([...doc.querySelectorAll('span.highlight')], 4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
describe("#renameSelectedAttachmentsFromParents()", function () {
|
describe("#renameSelectedAttachmentsFromParents()", function () {
|
||||||
it("should rename a linked file", async function () {
|
it("should rename a linked file", async function () {
|
||||||
var oldFilename = 'old.png';
|
var oldFilename = 'old.png';
|
||||||
|
|
Loading…
Reference in a new issue