Automatically rename dragged file attachments from parent metadata

Rename happens if only one file is dragged and the parent item has no
existing file attachments.

Closes 
This commit is contained in:
Dan Stillman 2018-01-10 00:39:16 -05:00
parent ea2feadbff
commit 7cb95f4129
3 changed files with 149 additions and 2 deletions
chrome/content/zotero/xpcom
test/tests

View File

@ -40,6 +40,7 @@ Zotero.Attachments = new function(){
* @param {Integer} [options.libraryID] * @param {Integer} [options.libraryID]
* @param {Integer[]|String[]} [options.parentItemID] - Parent item to add item to * @param {Integer[]|String[]} [options.parentItemID] - Parent item to add item to
* @param {Integer[]} [options.collections] - Collection keys or ids to add new item to * @param {Integer[]} [options.collections] - Collection keys or ids to add new item to
* @param {String} [options.fileBaseName]
* @param {String} [options.contentType] * @param {String} [options.contentType]
* @param {String} [options.charset] * @param {String} [options.charset]
* @param {Object} [options.saveOptions] - Options to pass to Zotero.Item::save() * @param {Object} [options.saveOptions] - Options to pass to Zotero.Item::save()
@ -50,15 +51,24 @@ Zotero.Attachments = new function(){
var libraryID = options.libraryID; var libraryID = options.libraryID;
var file = Zotero.File.pathToFile(options.file); var file = Zotero.File.pathToFile(options.file);
var path = file.path;
var leafName = file.leafName;
var parentItemID = options.parentItemID; var parentItemID = options.parentItemID;
var collections = options.collections; var collections = options.collections;
var fileBaseName = options.fileBaseName;
var contentType = options.contentType; var contentType = options.contentType;
var charset = options.charset; var charset = options.charset;
var saveOptions = options.saveOptions; var saveOptions = options.saveOptions;
var newName = Zotero.File.getValidFileName(file.leafName); if (fileBaseName) {
let ext = Zotero.File.getExtension(path);
var newName = fileBaseName + (ext != '' ? '.' + ext : '');
}
else {
var newName = Zotero.File.getValidFileName(OS.Path.basename(leafName));
}
if (file.leafName.endsWith(".lnk")) { if (leafName.endsWith(".lnk")) {
throw new Error("Cannot add Windows shortcut"); throw new Error("Cannot add Windows shortcut");
} }
if (parentItemID && collections) { if (parentItemID && collections) {

View File

@ -3233,9 +3233,26 @@ Zotero.ItemTreeView.prototype.drop = Zotero.Promise.coroutine(function* (row, or
var notifierQueue = new Zotero.Notifier.Queue; var notifierQueue = new Zotero.Notifier.Queue;
try { try {
let parentItem;
let numExistingFileAttachments;
if (parentItemID) {
parentItem = Zotero.Items.get(parentItemID);
numExistingFileAttachments = parentItem.getAttachments()
.map(itemID => Zotero.Items.get(itemID))
.filter(item => item.isFileAttachment())
.length;
}
for (var i=0; i<data.length; i++) { for (var i=0; i<data.length; i++) {
var file = data[i]; var file = data[i];
let fileBaseName;
// If only one item is being dragged and it's the only attachment, run
// "Rename File from Parent Metadata" automatically
if (data.length == 1 && parentItem && !numExistingFileAttachments) {
fileBaseName = Zotero.Attachments.getFileBaseNameFromItem(parentItem);
}
if (dataType == 'text/x-moz-url') { if (dataType == 'text/x-moz-url') {
var url = data[i]; var url = data[i];
if (url.indexOf('file:///') == 0) { if (url.indexOf('file:///') == 0) {
@ -3270,6 +3287,7 @@ Zotero.ItemTreeView.prototype.drop = Zotero.Promise.coroutine(function* (row, or
yield Zotero.Attachments.importFromURL({ yield Zotero.Attachments.importFromURL({
libraryID: targetLibraryID, libraryID: targetLibraryID,
url, url,
fileBaseName,
parentItemID, parentItemID,
saveOptions: { saveOptions: {
notifierQueue notifierQueue
@ -3306,8 +3324,10 @@ Zotero.ItemTreeView.prototype.drop = Zotero.Promise.coroutine(function* (row, or
win.ZoteroPane.displayCannotAddShortcutMessage(file.path); win.ZoteroPane.displayCannotAddShortcutMessage(file.path);
continue; continue;
} }
yield Zotero.Attachments.importFromFile({ yield Zotero.Attachments.importFromFile({
file, file,
fileBaseName,
libraryID: targetLibraryID, libraryID: targetLibraryID,
parentItemID, parentItemID,
collections: parentCollectionID ? [parentCollectionID] : undefined, collections: parentCollectionID ? [parentCollectionID] : undefined,

View File

@ -872,5 +872,122 @@ describe("Zotero.ItemTreeView", function() {
(yield Zotero.File.getBinaryContentsAsync(pdfPath)) (yield Zotero.File.getBinaryContentsAsync(pdfPath))
); );
}); });
it("should rename a child attachment using parent metadata if no existing file attachments", async function () {
var view = zp.itemsView;
var parentTitle = Zotero.Utilities.randomString();
var parentItem = await createDataObject('item', { title: parentTitle });
await Zotero.Attachments.linkFromURL({
url: 'https://example.com',
title: 'Example',
parentItemID: parentItem.id
});
var parentRow = view.getRowIndexByID(parentItem.id);
var file = getTestDataDirectory();
file.append('test.png');
var promise = waitForItemEvent('add');
itemsView.drop(parentRow, 0, {
dropEffect: 'copy',
effectAllowed: 'copy',
types: {
contains: function (type) {
return type == 'application/x-moz-file';
}
},
mozItemCount: 1,
mozGetDataAt: function (type, i) {
if (type == 'application/x-moz-file' && i == 0) {
return file;
}
}
})
var itemIDs = await promise;
var item = Zotero.Items.get(itemIDs[0]);
assert.equal(item.parentItemID, parentItem.id);
var title = item.getField('title');
var path = await item.getFilePathAsync();
assert.equal(title, parentTitle + '.png');
assert.equal(OS.Path.basename(path), parentTitle + '.png');
});
it("shouldn't rename a child attachment using parent metadata if existing file attachments", async function () {
var view = zp.itemsView;
var parentTitle = Zotero.Utilities.randomString();
var parentItem = await createDataObject('item', { title: parentTitle });
await Zotero.Attachments.linkFromFile({
file: OS.Path.join(getTestDataDirectory().path, 'test.png'),
parentItemID: parentItem.id
});
var parentRow = view.getRowIndexByID(parentItem.id);
var file = getTestDataDirectory();
file.append('test.png');
var promise = waitForItemEvent('add');
itemsView.drop(parentRow, 0, {
dropEffect: 'copy',
effectAllowed: 'copy',
types: {
contains: function (type) {
return type == 'application/x-moz-file';
}
},
mozItemCount: 1,
mozGetDataAt: function (type, i) {
if (type == 'application/x-moz-file' && i == 0) {
return file;
}
}
})
var itemIDs = await promise;
var item = Zotero.Items.get(itemIDs[0]);
assert.equal(item.parentItemID, parentItem.id);
var title = item.getField('title');
var path = await item.getFilePathAsync();
assert.equal(title, 'test.png');
assert.equal(OS.Path.basename(path), 'test.png');
});
it("shouldn't rename a child attachment using parent metadata if drag includes multiple files", async function () {
var view = zp.itemsView;
var parentTitle = Zotero.Utilities.randomString();
var parentItem = await createDataObject('item', { title: parentTitle });
var parentRow = view.getRowIndexByID(parentItem.id);
var file = getTestDataDirectory();
file.append('test.png');
var promise = waitForItemEvent('add');
itemsView.drop(parentRow, 0, {
dropEffect: 'copy',
effectAllowed: 'copy',
types: {
contains: function (type) {
return type == 'application/x-moz-file';
}
},
mozItemCount: 2,
mozGetDataAt: function (type, i) {
if (type == 'application/x-moz-file' && i <= 1) {
return file;
}
}
})
var itemIDs = await promise;
var item = Zotero.Items.get(itemIDs[0]);
assert.equal(item.parentItemID, parentItem.id);
var title = item.getField('title');
var path = await item.getFilePathAsync();
assert.equal(title, 'test.png');
assert.equal(OS.Path.basename(path), 'test.png');
});
}); });
}) })