Don't accept keyboard input before new-collection prompt appears
Fixes #1613
This commit is contained in:
parent
4bc8fab4f5
commit
7575cd8b29
5 changed files with 92 additions and 44 deletions
|
@ -107,14 +107,16 @@ var ZoteroAdvancedSearch = new function() {
|
||||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||||
.getService(Components.interfaces.nsIPromptService);
|
.getService(Components.interfaces.nsIPromptService);
|
||||||
|
|
||||||
var untitled = yield Zotero.DB.getNextName(
|
var libraryID = _searchBox.search.libraryID;
|
||||||
_searchBox.search.libraryID,
|
|
||||||
'savedSearches',
|
var searches = yield Zotero.Searches.getAll(libraryID)
|
||||||
'savedSearchName',
|
var prefix = Zotero.getString('pane.collections.untitled');
|
||||||
Zotero.getString('pane.collections.untitled')
|
var name = Zotero.Utilities.Internal.getNextName(
|
||||||
|
prefix,
|
||||||
|
searches.map(s => s.name).filter(n => n.startsWith(prefix))
|
||||||
);
|
);
|
||||||
|
|
||||||
var name = { value: untitled };
|
var name = { value: name };
|
||||||
var result = promptService.prompt(window,
|
var result = promptService.prompt(window,
|
||||||
Zotero.getString('pane.collections.newSavedSeach'),
|
Zotero.getString('pane.collections.newSavedSeach'),
|
||||||
Zotero.getString('pane.collections.savedSearchName'), name, "", {});
|
Zotero.getString('pane.collections.savedSearchName'), name, "", {});
|
||||||
|
|
|
@ -104,8 +104,8 @@ Zotero.Searches = function() {
|
||||||
|
|
||||||
|
|
||||||
this.getNextName = async function (libraryID, name) {
|
this.getNextName = async function (libraryID, name) {
|
||||||
// Trim '(1)', etc.
|
// Trim '1', etc.
|
||||||
var matches = name.match(/^(.+) \(\d+\)$/);
|
var matches = name.match(/^(.+) \d+$/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
name = matches[1].trim();
|
name = matches[1].trim();
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ Zotero.Searches = function() {
|
||||||
sql,
|
sql,
|
||||||
[libraryID, Zotero.DB.escapeSQLExpression(name) + '%']
|
[libraryID, Zotero.DB.escapeSQLExpression(name) + '%']
|
||||||
);
|
);
|
||||||
return Zotero.Utilities.Internal.getNextName(name, names);
|
return Zotero.Utilities.Internal.getNextName(name, names, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1194,23 +1194,51 @@ Zotero.Utilities.Internal = {
|
||||||
/**
|
/**
|
||||||
* Get the next available numbered name that matches a base name, for use when duplicating
|
* Get the next available numbered name that matches a base name, for use when duplicating
|
||||||
*
|
*
|
||||||
* - Given 'Foo' and ['Foo'], returns 'Foo (1)'.
|
* - Given 'Foo' and ['Foo'], returns 'Foo 1'.
|
||||||
* - Given 'Foo (1)' and ['Foo', 'Foo (1)'], returns 'Foo (2)'
|
* - Given 'Foo' and ['Foo', 'Foo 1'], returns 'Foo 2'.
|
||||||
|
* - Given 'Foo' and ['Foo', 'Foo 1'], returns 'Foo 2'.
|
||||||
|
* - Given 'Foo 1', ['Foo', 'Foo 1'], and trim=true, returns 'Foo 2'
|
||||||
|
* - Given 'Foo' and ['Foo', 'Foo 2'], returns 'Foo 1'
|
||||||
*/
|
*/
|
||||||
getNextName: function (name, existingNames) {
|
getNextName: function (name, existingNames, trim = false) {
|
||||||
// Trim '(1)', etc.
|
// Trim numbers at end of given name
|
||||||
var matches = name.match(/^(.+) \(\d+\)$/);
|
if (trim) {
|
||||||
if (matches) {
|
let matches = name.match(/^(.+) \d+$/);
|
||||||
name = matches[1].trim();
|
if (matches) {
|
||||||
}
|
name = matches[1].trim();
|
||||||
var highest = 0;
|
|
||||||
for (let existingName of existingNames) {
|
|
||||||
let matches = existingName.match(/ \((\d+)\)$/);
|
|
||||||
if (matches && matches[1] > highest) {
|
|
||||||
highest = matches[1];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return name + ' (' + ++highest + ')';
|
|
||||||
|
if (!existingNames.includes(name)) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
var suffixes = existingNames
|
||||||
|
// Get suffix
|
||||||
|
.map(x => x.substr(name.length))
|
||||||
|
// Get "2", "5", etc.
|
||||||
|
.filter(x => x.match(/^ (\d+)$/));
|
||||||
|
|
||||||
|
suffixes.sort(function (a, b) {
|
||||||
|
return parseInt(a) - parseInt(b);
|
||||||
|
});
|
||||||
|
|
||||||
|
// If no existing numbered names found, use 1
|
||||||
|
if (!suffixes.length) {
|
||||||
|
return name + ' ' + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find first available number
|
||||||
|
var i = 0;
|
||||||
|
var num = 1;
|
||||||
|
while (suffixes[i] == num) {
|
||||||
|
while (suffixes[i + 1] && suffixes[i] == suffixes[i + 1]) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
return name + ' ' + num;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -912,17 +912,23 @@ var ZoteroPane = new function()
|
||||||
|
|
||||||
var libraryID = this.getSelectedLibraryID();
|
var libraryID = this.getSelectedLibraryID();
|
||||||
|
|
||||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
// Get a unique "Untitled" name for this level in the collection hierarchy
|
||||||
.getService(Components.interfaces.nsIPromptService);
|
var collections;
|
||||||
var untitled = yield Zotero.DB.getNextName(
|
if (parentKey) {
|
||||||
libraryID,
|
let parent = Zotero.Collections.getIDFromLibraryAndKey(libraryID, parentKey);
|
||||||
'collections',
|
collections = Zotero.Collections.getByParent(parent);
|
||||||
'collectionName',
|
}
|
||||||
Zotero.getString('pane.collections.untitled')
|
else {
|
||||||
|
collections = Zotero.Collections.getByLibrary(libraryID);
|
||||||
|
}
|
||||||
|
var prefix = Zotero.getString('pane.collections.untitled');
|
||||||
|
var name = Zotero.Utilities.Internal.getNextName(
|
||||||
|
prefix,
|
||||||
|
collections.map(c => c.name).filter(n => n.startsWith(prefix))
|
||||||
);
|
);
|
||||||
|
|
||||||
var newName = { value: untitled };
|
var newName = { value: name };
|
||||||
var result = promptService.prompt(window,
|
var result = Services.prompt.prompt(window,
|
||||||
Zotero.getString('pane.collections.newCollection'),
|
Zotero.getString('pane.collections.newCollection'),
|
||||||
Zotero.getString('pane.collections.name'), newName, "", {});
|
Zotero.getString('pane.collections.name'), newName, "", {});
|
||||||
|
|
||||||
|
@ -991,18 +997,20 @@ var ZoteroPane = new function()
|
||||||
yield Zotero.DB.waitForTransaction();
|
yield Zotero.DB.waitForTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var libraryID = this.getSelectedLibraryID();
|
||||||
|
|
||||||
var s = new Zotero.Search();
|
var s = new Zotero.Search();
|
||||||
s.libraryID = this.getSelectedLibraryID();
|
s.libraryID = libraryID;
|
||||||
s.addCondition('title', 'contains', '');
|
s.addCondition('title', 'contains', '');
|
||||||
|
|
||||||
var untitled = Zotero.getString('pane.collections.untitled');
|
var searches = yield Zotero.Searches.getAll(libraryID)
|
||||||
untitled = yield Zotero.DB.getNextName(
|
var prefix = Zotero.getString('pane.collections.untitled');
|
||||||
s.libraryID,
|
var name = Zotero.Utilities.Internal.getNextName(
|
||||||
'savedSearches',
|
prefix,
|
||||||
'savedSearchName',
|
searches.map(s => s.name).filter(n => n.startsWith(prefix))
|
||||||
Zotero.getString('pane.collections.untitled')
|
|
||||||
);
|
);
|
||||||
var io = {dataIn: {search: s, name: untitled}, dataOut: null};
|
|
||||||
|
var io = { dataIn: { search: s, name }, dataOut: null };
|
||||||
window.openDialog('chrome://zotero/content/searchDialog.xul','','chrome,modal',io);
|
window.openDialog('chrome://zotero/content/searchDialog.xul','','chrome,modal',io);
|
||||||
if (!io.dataOut) {
|
if (!io.dataOut) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -203,13 +203,23 @@ describe("Zotero.Utilities.Internal", function () {
|
||||||
|
|
||||||
describe("#getNextName()", function () {
|
describe("#getNextName()", function () {
|
||||||
it("should get the next available numbered name", function () {
|
it("should get the next available numbered name", function () {
|
||||||
var existing = ['Name (1)', 'Name (3)'];
|
var existing = ['Name', 'Name 1', 'Name 3'];
|
||||||
assert.equal(Zotero.Utilities.Internal.getNextName('Name', existing), 'Name (4)');
|
assert.equal(Zotero.Utilities.Internal.getNextName('Name', existing), 'Name 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return 'Name (1)' if no numbered names", function () {
|
it("should return 'Name 1' if no numbered names", function () {
|
||||||
var existing = ['Name'];
|
var existing = ['Name'];
|
||||||
assert.equal(Zotero.Utilities.Internal.getNextName('Name', existing), 'Name (1)');
|
assert.equal(Zotero.Utilities.Internal.getNextName('Name', existing), 'Name 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return 'Name' if only numbered names", function () {
|
||||||
|
var existing = ['Name 1', 'Name 3'];
|
||||||
|
assert.equal(Zotero.Utilities.Internal.getNextName('Name', existing), 'Name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should trim given name if trim=true", function () {
|
||||||
|
var existing = ['Name', 'Name 1', 'Name 2', 'Name 3'];
|
||||||
|
assert.equal(Zotero.Utilities.Internal.getNextName('Name 2', existing, true), 'Name 4');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue