Make various collection methods synchronous
- Collection::getDescendents() - Collections.getByLibrary() - Collections.getByParent() And various things that depend on those. (View with -w.)
This commit is contained in:
parent
7dfb62b8fc
commit
15a9fd5494
11 changed files with 275 additions and 237 deletions
|
@ -401,128 +401,126 @@
|
|||
</constructor>
|
||||
<method name="onConditionSelected">
|
||||
<body><![CDATA[
|
||||
return Zotero.spawn(function* () {
|
||||
// Skip if correct condition already selected
|
||||
if (this.id('conditionsmenu').value==this.selectedCondition){
|
||||
return;
|
||||
}
|
||||
var conditionsMenu = this.id('conditionsmenu');
|
||||
var operatorsList = this.id('operatorsmenu');
|
||||
|
||||
this.selectedCondition = conditionsMenu.value;
|
||||
this.selectedOperator = operatorsList.value;
|
||||
|
||||
var condition = Zotero.SearchConditions.get(conditionsMenu.value);
|
||||
var operators = condition['operators'];
|
||||
|
||||
// Display appropriate operators for condition
|
||||
var selectThis;
|
||||
for(var i = 0, len = operatorsList.firstChild.childNodes.length; i < len; i++)
|
||||
// Skip if correct condition already selected
|
||||
if (this.id('conditionsmenu').value==this.selectedCondition){
|
||||
return;
|
||||
}
|
||||
var conditionsMenu = this.id('conditionsmenu');
|
||||
var operatorsList = this.id('operatorsmenu');
|
||||
|
||||
this.selectedCondition = conditionsMenu.value;
|
||||
this.selectedOperator = operatorsList.value;
|
||||
|
||||
var condition = Zotero.SearchConditions.get(conditionsMenu.value);
|
||||
var operators = condition['operators'];
|
||||
|
||||
// Display appropriate operators for condition
|
||||
var selectThis;
|
||||
for(var i = 0, len = operatorsList.firstChild.childNodes.length; i < len; i++)
|
||||
{
|
||||
var val = operatorsList.firstChild.childNodes[i].getAttribute('value');
|
||||
var hidden = !operators[val];
|
||||
operatorsList.firstChild.childNodes[i].setAttribute('hidden', hidden);
|
||||
if (!hidden && (selectThis == null || this.selectedOperator == val))
|
||||
{
|
||||
var val = operatorsList.firstChild.childNodes[i].getAttribute('value');
|
||||
var hidden = !operators[val];
|
||||
operatorsList.firstChild.childNodes[i].setAttribute('hidden', hidden);
|
||||
if (!hidden && (selectThis == null || this.selectedOperator == val))
|
||||
{
|
||||
selectThis = i;
|
||||
selectThis = i;
|
||||
}
|
||||
}
|
||||
operatorsList.selectedIndex = selectThis;
|
||||
|
||||
// Generate drop-down menu instead of textbox for certain conditions
|
||||
switch (conditionsMenu.value){
|
||||
case 'collection':
|
||||
var rows = [];
|
||||
|
||||
var libraryID = this.parent.search.libraryID;
|
||||
var cols = Zotero.Collections.getByLibrary(libraryID, true);
|
||||
for (var i in cols) {
|
||||
// Indent subcollections
|
||||
var indent = '';
|
||||
if (cols[i].level) {
|
||||
for (var j=1; j<cols[i].level; j++) {
|
||||
indent += ' ';
|
||||
}
|
||||
indent += '- ';
|
||||
}
|
||||
rows.push([indent + cols[i].name, 'C' + cols[i].key]);
|
||||
}
|
||||
}
|
||||
operatorsList.selectedIndex = selectThis;
|
||||
this.createValueMenu(rows);
|
||||
break;
|
||||
|
||||
// Generate drop-down menu instead of textbox for certain conditions
|
||||
switch (conditionsMenu.value){
|
||||
case 'collection':
|
||||
var rows = [];
|
||||
|
||||
var libraryID = this.parent.search.libraryID;
|
||||
var cols = yield Zotero.Collections.getByLibrary(libraryID, true);
|
||||
for (var i in cols) {
|
||||
// Indent subcollections
|
||||
var indent = '';
|
||||
if (cols[i].level) {
|
||||
for (var j=1; j<cols[i].level; j++) {
|
||||
indent += ' ';
|
||||
}
|
||||
indent += '- ';
|
||||
}
|
||||
rows.push([indent + cols[i].name, 'C' + cols[i].key]);
|
||||
case 'savedSearch':
|
||||
var rows = [];
|
||||
var libraryID = this.parent.search.libraryID;
|
||||
var searches = Zotero.Searches.getAll(libraryID);
|
||||
for (var i in searches) {
|
||||
if (searches[i].id != this.parent.search.id) {
|
||||
rows.push([searches[i].name, 'S' + searches[i].key]);
|
||||
}
|
||||
this.createValueMenu(rows);
|
||||
break;
|
||||
}
|
||||
this.createValueMenu(rows);
|
||||
break;
|
||||
|
||||
case 'itemType':
|
||||
var t = Zotero.ItemTypes.getTypes();
|
||||
|
||||
case 'savedSearch':
|
||||
var rows = [];
|
||||
var libraryID = this.parent.search.libraryID;
|
||||
var searches = Zotero.Searches.getAll(libraryID);
|
||||
for (var i in searches) {
|
||||
if (searches[i].id != this.parent.search.id) {
|
||||
rows.push([searches[i].name, 'S' + searches[i].key]);
|
||||
}
|
||||
}
|
||||
this.createValueMenu(rows);
|
||||
break;
|
||||
|
||||
case 'itemType':
|
||||
var t = Zotero.ItemTypes.getTypes();
|
||||
|
||||
// Sort by localized name
|
||||
var types = [];
|
||||
for (var i=0; i<t.length; i++) {
|
||||
types.push({
|
||||
id: t[i].id,
|
||||
name: t[i].name,
|
||||
localized: Zotero.ItemTypes.getLocalizedString(t[i].id)
|
||||
});
|
||||
}
|
||||
var collation = Zotero.getLocaleCollation();
|
||||
types.sort(function(a, b) {
|
||||
return collation.compareString(1, a.localized, b.localized);
|
||||
// Sort by localized name
|
||||
var types = [];
|
||||
for (var i=0; i<t.length; i++) {
|
||||
types.push({
|
||||
id: t[i].id,
|
||||
name: t[i].name,
|
||||
localized: Zotero.ItemTypes.getLocalizedString(t[i].id)
|
||||
});
|
||||
|
||||
for (var i in types) {
|
||||
types[i][0] = types[i].localized;
|
||||
types[i][1] = types[i].name;
|
||||
delete types[i]['name'];
|
||||
delete types[i]['id'];
|
||||
}
|
||||
this.createValueMenu(types);
|
||||
break;
|
||||
}
|
||||
var collation = Zotero.getLocaleCollation();
|
||||
types.sort(function(a, b) {
|
||||
return collation.compareString(1, a.localized, b.localized);
|
||||
});
|
||||
|
||||
case 'fileTypeID':
|
||||
var types = Zotero.FileTypes.getTypes();
|
||||
for (var i in types) {
|
||||
types[i][0] = Zotero.getString('fileTypes.' + types[i]['name']);
|
||||
types[i][1] = types[i]['id'];
|
||||
delete types[i]['name'];
|
||||
delete types[i]['id'];
|
||||
}
|
||||
this.createValueMenu(types);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (operatorsList.value=='isInTheLast')
|
||||
{
|
||||
this.id('value-date-age').value = this.value;
|
||||
}
|
||||
|
||||
// Textbox
|
||||
else {
|
||||
// If switching from menu to textbox, clear value
|
||||
if (this.id('valuefield').hidden){
|
||||
this.id('valuefield').value = '';
|
||||
}
|
||||
// If switching between textbox conditions, get loaded value for new one
|
||||
else {
|
||||
this.id('valuefield').value = this.value;
|
||||
}
|
||||
|
||||
// Update field drop-down if applicable
|
||||
this.id('valuefield').update(conditionsMenu.value, this.mode);
|
||||
}
|
||||
}
|
||||
for (var i in types) {
|
||||
types[i][0] = types[i].localized;
|
||||
types[i][1] = types[i].name;
|
||||
delete types[i]['name'];
|
||||
delete types[i]['id'];
|
||||
}
|
||||
this.createValueMenu(types);
|
||||
break;
|
||||
|
||||
this.onOperatorSelected();
|
||||
}.bind(this));
|
||||
case 'fileTypeID':
|
||||
var types = Zotero.FileTypes.getTypes();
|
||||
for (var i in types) {
|
||||
types[i][0] = Zotero.getString('fileTypes.' + types[i]['name']);
|
||||
types[i][1] = types[i]['id'];
|
||||
delete types[i]['name'];
|
||||
delete types[i]['id'];
|
||||
}
|
||||
this.createValueMenu(types);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (operatorsList.value=='isInTheLast')
|
||||
{
|
||||
this.id('value-date-age').value = this.value;
|
||||
}
|
||||
|
||||
// Textbox
|
||||
else {
|
||||
// If switching from menu to textbox, clear value
|
||||
if (this.id('valuefield').hidden){
|
||||
this.id('valuefield').value = '';
|
||||
}
|
||||
// If switching between textbox conditions, get loaded value for new one
|
||||
else {
|
||||
this.id('valuefield').value = this.value;
|
||||
}
|
||||
|
||||
// Update field drop-down if applicable
|
||||
this.id('valuefield').update(conditionsMenu.value, this.mode);
|
||||
}
|
||||
}
|
||||
|
||||
this.onOperatorSelected();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="onOperatorSelected">
|
||||
|
@ -593,50 +591,48 @@
|
|||
<parameter name="parent"/>
|
||||
<parameter name="condition"/>
|
||||
<body><![CDATA[
|
||||
return Zotero.spawn(function* () {
|
||||
this.parent = parent;
|
||||
this.conditionID = condition['id'];
|
||||
this.parent = parent;
|
||||
this.conditionID = condition['id'];
|
||||
|
||||
if(this.parent.search)
|
||||
{
|
||||
this.dontupdate = true; //so that the search doesn't get updated while we are creating controls.
|
||||
var prefix = '';
|
||||
|
||||
if(this.parent.search)
|
||||
{
|
||||
this.dontupdate = true; //so that the search doesn't get updated while we are creating controls.
|
||||
var prefix = '';
|
||||
// Handle special conditions
|
||||
switch (condition.condition) {
|
||||
case 'savedSearch':
|
||||
prefix = 'S';
|
||||
break;
|
||||
|
||||
// Handle special conditions
|
||||
switch (condition.condition) {
|
||||
case 'savedSearch':
|
||||
prefix = 'S';
|
||||
break;
|
||||
|
||||
case 'collection':
|
||||
prefix = 'C';
|
||||
break;
|
||||
}
|
||||
|
||||
this.id('conditionsmenu').value = condition.condition;
|
||||
|
||||
// Convert datetimes from UTC to localtime
|
||||
if ((condition['condition']=='accessDate' ||
|
||||
condition['condition']=='dateAdded' ||
|
||||
condition['condition']=='dateModified') &&
|
||||
Zotero.Date.isSQLDateTime(condition['value'])){
|
||||
|
||||
condition['value'] =
|
||||
Zotero.Date.dateToSQL(Zotero.Date.sqlToDate(condition['value'], true));
|
||||
}
|
||||
|
||||
this.mode = condition['mode'];
|
||||
this.id('operatorsmenu').value = condition['operator'];
|
||||
this.value = prefix +
|
||||
(condition.value ? condition.value : '');
|
||||
|
||||
this.dontupdate = false;
|
||||
case 'collection':
|
||||
prefix = 'C';
|
||||
break;
|
||||
}
|
||||
|
||||
yield this.onConditionSelected();
|
||||
this.id('conditionsmenu').value = condition.condition;
|
||||
|
||||
this.id('conditionsmenu').focus();
|
||||
}.bind(this));
|
||||
// Convert datetimes from UTC to localtime
|
||||
if ((condition['condition']=='accessDate' ||
|
||||
condition['condition']=='dateAdded' ||
|
||||
condition['condition']=='dateModified') &&
|
||||
Zotero.Date.isSQLDateTime(condition['value'])){
|
||||
|
||||
condition['value'] =
|
||||
Zotero.Date.dateToSQL(Zotero.Date.sqlToDate(condition['value'], true));
|
||||
}
|
||||
|
||||
this.mode = condition['mode'];
|
||||
this.id('operatorsmenu').value = condition['operator'];
|
||||
this.value = prefix +
|
||||
(condition.value ? condition.value : '');
|
||||
|
||||
this.dontupdate = false;
|
||||
}
|
||||
|
||||
this.onConditionSelected();
|
||||
|
||||
this.id('conditionsmenu').focus();
|
||||
]]></body>
|
||||
</method>
|
||||
<!-- Gets the value from the field and updates the associated search condition -->
|
||||
|
|
|
@ -304,7 +304,7 @@ var Zotero_File_Interface = new function() {
|
|||
let leafName = translation.location.leafName;
|
||||
collectionName = (translation.location.isDirectory() || leafName.indexOf(".") === -1 ? leafName
|
||||
: leafName.substr(0, leafName.lastIndexOf(".")));
|
||||
let allCollections = yield Zotero.Collections.getByLibrary(libraryID);
|
||||
let allCollections = Zotero.Collections.getByLibrary(libraryID);
|
||||
for(var i=0; i<allCollections.length; i++) {
|
||||
if(allCollections[i].name == collectionName) {
|
||||
collectionName += " "+(new Date()).toLocaleString();
|
||||
|
|
|
@ -46,12 +46,12 @@ Zotero.API = {
|
|||
switch (params.scopeObject) {
|
||||
case 'collections':
|
||||
if (params.scopeObjectKey) {
|
||||
var col = yield Zotero.Collections.getByLibraryAndKeyAsync(
|
||||
var col = Zotero.Collections.getByLibraryAndKeyAsync(
|
||||
params.libraryID, params.scopeObjectKey
|
||||
);
|
||||
}
|
||||
else {
|
||||
var col = yield Zotero.Collections.getAsync(params.scopeObjectID);
|
||||
var col = Zotero.Collections.get(params.scopeObjectID);
|
||||
}
|
||||
if (!col) {
|
||||
throw new Error('Invalid collection ID or key');
|
||||
|
|
|
@ -1153,10 +1153,10 @@ Zotero.CollectionTreeView.prototype._expandRow = Zotero.Promise.coroutine(functi
|
|||
}
|
||||
|
||||
if (isLibrary) {
|
||||
var collections = yield Zotero.Collections.getByLibrary(libraryID, treeRow.ref.id);
|
||||
var collections = Zotero.Collections.getByLibrary(libraryID, treeRow.ref.id);
|
||||
}
|
||||
else if (isCollection) {
|
||||
var collections = yield Zotero.Collections.getByParent(treeRow.ref.id);
|
||||
var collections = Zotero.Collections.getByParent(treeRow.ref.id);
|
||||
}
|
||||
|
||||
if (isLibrary) {
|
||||
|
@ -1549,10 +1549,9 @@ Zotero.CollectionTreeView.prototype.canDropCheck = function (row, orient, dataTr
|
|||
}
|
||||
|
||||
// Nor in their children
|
||||
// TODO: figure out synchronously from tree
|
||||
/*if (yield col.hasDescendent('collection', treeRow.ref.id)) {
|
||||
if (col.hasDescendent('collection', treeRow.ref.id)) {
|
||||
return false;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
// Dragging a collection to a different library
|
||||
else {
|
||||
|
@ -1657,9 +1656,9 @@ Zotero.CollectionTreeView.prototype.canDropCheckAsync = Zotero.Promise.coroutine
|
|||
return false;
|
||||
}
|
||||
|
||||
var descendents = yield col.getDescendents(false, 'collection');
|
||||
var descendents = col.getDescendents(false, 'collection');
|
||||
for each(var descendent in descendents) {
|
||||
descendent = yield Zotero.Collections.getAsync(descendent.id);
|
||||
descendent = Zotero.Collections.get(descendent.id);
|
||||
// Disallow if linked collection already exists for any subcollections
|
||||
//
|
||||
// If this is allowed in the future for the root collection,
|
||||
|
|
|
@ -242,7 +242,7 @@ Zotero.Collection.prototype._initSave = Zotero.Promise.coroutine(function* (env)
|
|||
throw new Error('Cannot move collection into itself!');
|
||||
}
|
||||
|
||||
if (this.id && (yield this.hasDescendent('collection', newParent.id))) {
|
||||
if (this.id && this.hasDescendent('collection', newParent.id)) {
|
||||
throw ('Cannot move collection "' + this.name + '" into one of its own descendents');
|
||||
}
|
||||
|
||||
|
@ -440,15 +440,15 @@ Zotero.Collection.prototype.hasItem = function(itemID) {
|
|||
}
|
||||
|
||||
|
||||
Zotero.Collection.prototype.hasDescendent = Zotero.Promise.coroutine(function* (type, id) {
|
||||
var descendents = yield this.getDescendents();
|
||||
Zotero.Collection.prototype.hasDescendent = function (type, id) {
|
||||
var descendents = this.getDescendents();
|
||||
for (var i=0, len=descendents.length; i<len; i++) {
|
||||
if (descendents[i].type == type && descendents[i].id == id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
@ -551,7 +551,7 @@ Zotero.Collection.prototype._eraseData = Zotero.Promise.coroutine(function* (env
|
|||
|
||||
var collections = [this.id];
|
||||
|
||||
var descendents = yield this.getDescendents(false, null, true);
|
||||
var descendents = this.getDescendents(false, null, true);
|
||||
var items = [];
|
||||
|
||||
var del = [];
|
||||
|
@ -701,7 +701,6 @@ Zotero.Collection.prototype.toJSON = function (options = {}) {
|
|||
/**
|
||||
* Returns an array of descendent collections and items
|
||||
*
|
||||
* @param {Boolean} [recursive=false] Descend into subcollections
|
||||
* @param {Boolean} [nested=false] Return multidimensional array with 'children'
|
||||
* nodes instead of flat array
|
||||
* @param {String} [type] 'item', 'collection', or NULL for both
|
||||
|
@ -709,13 +708,11 @@ Zotero.Collection.prototype.toJSON = function (options = {}) {
|
|||
* @return {Promise<Object[]>} - A promise for an array of objects with 'id', 'key',
|
||||
* 'type' ('item' or 'collection'), 'parent', and, if collection, 'name' and the nesting 'level'
|
||||
*/
|
||||
Zotero.Collection.prototype.getChildren = Zotero.Promise.coroutine(function* (recursive, nested, type, includeDeletedItems, level) {
|
||||
Zotero.Collection.prototype.getDescendents = function (nested, type, includeDeletedItems, level) {
|
||||
if (!this.id) {
|
||||
throw new Error('Cannot be called on an unsaved item');
|
||||
}
|
||||
|
||||
var toReturn = [];
|
||||
|
||||
if (!level) {
|
||||
level = 1;
|
||||
}
|
||||
|
@ -726,39 +723,40 @@ Zotero.Collection.prototype.getChildren = Zotero.Promise.coroutine(function* (re
|
|||
case 'collection':
|
||||
break;
|
||||
default:
|
||||
throw ("Invalid type '" + type + "' in Collection.getChildren()");
|
||||
throw new (`Invalid type '${type}'`);
|
||||
}
|
||||
}
|
||||
|
||||
// 0 == collection
|
||||
// 1 == item
|
||||
var sql = 'SELECT collectionID AS id, collectionName AS name, '
|
||||
+ "0 AS type, collectionName AS collectionName, key "
|
||||
+ 'FROM collections WHERE parentCollectionID=?1';
|
||||
var collections = Zotero.Collections.getByParent(this.id);
|
||||
var children = collections.map(c => ({
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
type: 0,
|
||||
key: c.key
|
||||
}));
|
||||
if (!type || type == 'item') {
|
||||
sql += ' UNION SELECT itemID AS id, NULL AS name, 1 AS type, NULL AS collectionName, key '
|
||||
+ 'FROM collectionItems JOIN items USING (itemID) WHERE collectionID=?1';
|
||||
if (!includeDeletedItems) {
|
||||
sql += " AND itemID NOT IN (SELECT itemID FROM deletedItems)";
|
||||
}
|
||||
let items = this.getChildItems(false, includeDeletedItems);
|
||||
children = children.concat(items.map(i => ({
|
||||
id: i.id,
|
||||
name: null,
|
||||
type: 1,
|
||||
key: i.key
|
||||
})));
|
||||
}
|
||||
var children = yield Zotero.DB.queryAsync(sql, this.id);
|
||||
|
||||
children.sort(function (a, b) {
|
||||
if (a.name === null || b.name === null) return 0;
|
||||
return Zotero.localeCompare(a.name, b.name)
|
||||
});
|
||||
|
||||
var toReturn = [];
|
||||
for(var i=0, len=children.length; i<len; i++) {
|
||||
// This seems to not work without parseInt() even though
|
||||
// typeof children[i]['type'] == 'number' and
|
||||
// children[i]['type'] === parseInt(children[i]['type']),
|
||||
// which sure seems like a bug to me
|
||||
switch (parseInt(children[i].type)) {
|
||||
switch (children[i].type) {
|
||||
case 0:
|
||||
if (!type || type=='collection') {
|
||||
toReturn.push({
|
||||
id: children[i].id,
|
||||
name: children[i].collectionName,
|
||||
name: children[i].name,
|
||||
key: children[i].key,
|
||||
type: 'collection',
|
||||
level: level,
|
||||
|
@ -766,19 +764,17 @@ Zotero.Collection.prototype.getChildren = Zotero.Promise.coroutine(function* (re
|
|||
});
|
||||
}
|
||||
|
||||
if (recursive) {
|
||||
let child = yield this.ObjectsClass.getAsync(children[i].id);
|
||||
let descendents = yield child.getChildren(
|
||||
true, nested, type, includeDeletedItems, level+1
|
||||
);
|
||||
|
||||
if (nested) {
|
||||
toReturn[toReturn.length-1].children = descendents;
|
||||
}
|
||||
else {
|
||||
for (var j=0, len2=descendents.length; j<len2; j++) {
|
||||
toReturn.push(descendents[j]);
|
||||
}
|
||||
let child = this.ObjectsClass.get(children[i].id);
|
||||
let descendents = child.getDescendents(
|
||||
nested, type, includeDeletedItems, level + 1
|
||||
);
|
||||
|
||||
if (nested) {
|
||||
toReturn[toReturn.length-1].children = descendents;
|
||||
}
|
||||
else {
|
||||
for (var j=0, len2=descendents.length; j<len2; j++) {
|
||||
toReturn.push(descendents[j]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -797,17 +793,7 @@ Zotero.Collection.prototype.getChildren = Zotero.Promise.coroutine(function* (re
|
|||
}
|
||||
|
||||
return toReturn;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Alias for the recursive mode of getChildren()
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
Zotero.Collection.prototype.getDescendents = function (nested, type, includeDeletedItems) {
|
||||
return this.getChildren(true, nested, type, includeDeletedItems);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -62,7 +62,7 @@ Zotero.Collections = function() {
|
|||
*
|
||||
* @param {Integer} libraryID
|
||||
* @param {Boolean} [recursive=false]
|
||||
* @return {Promise<Zotero.Collection[]>}
|
||||
* @return {Zotero.Collection[]}
|
||||
*/
|
||||
this.getByLibrary = function (libraryID, recursive) {
|
||||
return _getByContainer(libraryID, null, recursive);
|
||||
|
@ -74,24 +74,26 @@ Zotero.Collections = function() {
|
|||
*
|
||||
* @param {Integer} parentCollectionID
|
||||
* @param {Boolean} [recursive=false]
|
||||
* @return {Promise<Zotero.Collection[]>}
|
||||
* @return {Zotero.Collection[]}
|
||||
*/
|
||||
this.getByParent = function (parentCollectionID, recursive) {
|
||||
return _getByContainer(null, parentCollectionID, recursive);
|
||||
}
|
||||
|
||||
|
||||
var _getByContainer = Zotero.Promise.coroutine(function* (libraryID, parentID, recursive) {
|
||||
let children;
|
||||
var _getByContainer = function (libraryID, parentID, recursive) {
|
||||
let children = [];
|
||||
|
||||
if (parentID) {
|
||||
let parent = Zotero.Collections.get(parentID);
|
||||
children = parent.getChildCollections();
|
||||
} else if (libraryID) {
|
||||
let sql = "SELECT collectionID AS id FROM collections "
|
||||
+ "WHERE libraryID=? AND parentCollectionID IS NULL";
|
||||
let ids = yield Zotero.DB.columnQueryAsync(sql, [libraryID]);
|
||||
children = yield this.getAsync(ids);
|
||||
for (let id in this._objectCache) {
|
||||
let c = this._objectCache[id];
|
||||
if (c.libraryID == libraryID && !c.parentKey) {
|
||||
children.push(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Error("Either library ID or parent collection ID must be provided");
|
||||
}
|
||||
|
@ -110,9 +112,9 @@ Zotero.Collections = function() {
|
|||
var obj = children[i];
|
||||
toReturn.push(obj);
|
||||
|
||||
var desc = yield obj.getDescendents(false, 'collection');
|
||||
var desc = obj.getDescendents(false, 'collection');
|
||||
for (var j in desc) {
|
||||
var obj2 = yield this.getAsync(desc[j]['id']);
|
||||
var obj2 = this.get(desc[j].id);
|
||||
if (!obj2) {
|
||||
throw new Error('Collection ' + desc[j] + ' not found');
|
||||
}
|
||||
|
@ -130,7 +132,7 @@ Zotero.Collections = function() {
|
|||
}
|
||||
|
||||
return toReturn;
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
|
||||
|
||||
this.getCollectionsContainingItems = function (itemIDs, asIDs) {
|
||||
|
|
|
@ -2315,7 +2315,7 @@ Zotero.Translate.Export.prototype._prepareTranslation = Zotero.Promise.coroutine
|
|||
getCollections = configOptions.getCollections || false;
|
||||
switch (this._export.type) {
|
||||
case 'collection':
|
||||
yield this._itemGetter.setCollection(this._export.collection, getCollections);
|
||||
this._itemGetter.setCollection(this._export.collection, getCollections);
|
||||
break;
|
||||
case 'items':
|
||||
this._itemGetter.setItems(this._export.items);
|
||||
|
|
|
@ -657,13 +657,13 @@ Zotero.Translate.ItemGetter.prototype = {
|
|||
this.numItems = this._itemsLeft.length;
|
||||
},
|
||||
|
||||
"setCollection": Zotero.Promise.coroutine(function* (collection, getChildCollections) {
|
||||
"setCollection": function (collection, getChildCollections) {
|
||||
// get items in this collection
|
||||
var items = new Set(collection.getChildItems());
|
||||
|
||||
if(getChildCollections) {
|
||||
// get child collections
|
||||
this._collectionsLeft = yield Zotero.Collections.getByParent(collection.id, true);
|
||||
this._collectionsLeft = Zotero.Collections.getByParent(collection.id, true);
|
||||
|
||||
// get items in child collections
|
||||
for (let collection of this._collectionsLeft) {
|
||||
|
@ -674,13 +674,13 @@ Zotero.Translate.ItemGetter.prototype = {
|
|||
|
||||
this._itemsLeft = Array.from(items.values());
|
||||
this.numItems = this._itemsLeft.length;
|
||||
}),
|
||||
},
|
||||
|
||||
"setAll": Zotero.Promise.coroutine(function* (libraryID, getChildCollections) {
|
||||
this._itemsLeft = yield Zotero.Items.getAll(libraryID, true);
|
||||
|
||||
if(getChildCollections) {
|
||||
this._collectionsLeft = yield Zotero.Collections.getByLibrary(libraryID, true);
|
||||
this._collectionsLeft = Zotero.Collections.getByLibrary(libraryID, true);
|
||||
}
|
||||
|
||||
this.numItems = this._itemsLeft.length;
|
||||
|
|
|
@ -200,4 +200,57 @@ describe("Zotero.Collection", function() {
|
|||
assert.lengthOf(collection.getChildItems(false, true), 1);
|
||||
})
|
||||
})
|
||||
|
||||
describe("#getDescendents()", function () {
|
||||
var collection0, collection1, collection2, collection3, item1, item2, item3;
|
||||
|
||||
before(function* () {
|
||||
collection0 = yield createDataObject('collection');
|
||||
item1 = yield createDataObject('item', { collections: [collection0.id] });
|
||||
collection1 = yield createDataObject('collection', { parentKey: collection0.key });
|
||||
item2 = yield createDataObject('item', { collections: [collection1.id] });
|
||||
collection2 = yield createDataObject('collection', { parentKey: collection1.key });
|
||||
collection3 = yield createDataObject('collection', { parentKey: collection1.key });
|
||||
item3 = yield createDataObject('item', { collections: [collection2.id] });
|
||||
item3.deleted = true;
|
||||
yield item3.saveTx();
|
||||
});
|
||||
|
||||
it("should return a flat array of collections and items", function* () {
|
||||
var desc = collection0.getDescendents();
|
||||
assert.lengthOf(desc, 5);
|
||||
assert.sameMembers(
|
||||
desc.map(x => x.type + ':' + x.id + ':' + (x.name || '') + ':' + x.parent),
|
||||
[
|
||||
'item:' + item1.id + '::' + collection0.id,
|
||||
'item:' + item2.id + '::' + collection1.id,
|
||||
'collection:' + collection1.id + ':' + collection1.name + ':' + collection0.id,
|
||||
'collection:' + collection2.id + ':' + collection2.name + ':' + collection1.id,
|
||||
'collection:' + collection3.id + ':' + collection3.name + ':' + collection1.id
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it("should return nested arrays of collections and items", function* () {
|
||||
var desc = collection0.getDescendents(true);
|
||||
assert.lengthOf(desc, 2);
|
||||
assert.sameMembers(
|
||||
desc.map(x => x.type + ':' + x.id + ':' + (x.name || '') + ':' + x.parent),
|
||||
[
|
||||
'item:' + item1.id + '::' + collection0.id,
|
||||
'collection:' + collection1.id + ':' + collection1.name + ':' + collection0.id,
|
||||
]
|
||||
);
|
||||
var c = desc[0].type == 'collection' ? desc[0] : desc[1];
|
||||
assert.lengthOf(c.children, 3);
|
||||
assert.sameMembers(
|
||||
c.children.map(x => x.type + ':' + x.id + ':' + (x.name || '') + ':' + x.parent),
|
||||
[
|
||||
'item:' + item2.id + '::' + collection1.id,
|
||||
'collection:' + collection2.id + ':' + collection2.name + ':' + collection1.id,
|
||||
'collection:' + collection3.id + ':' + collection3.name + ':' + collection1.id
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
||||
})
|
||||
|
|
|
@ -4,7 +4,7 @@ describe("Zotero.Collections", function () {
|
|||
var col1 = yield createDataObject('collection');
|
||||
var col2 = yield createDataObject('collection');
|
||||
var col3 = yield createDataObject('collection', { parentID: col2.id });
|
||||
var cols = yield Zotero.Collections.getByLibrary(Zotero.Libraries.userLibraryID);
|
||||
var cols = Zotero.Collections.getByLibrary(Zotero.Libraries.userLibraryID);
|
||||
assert.isAbove(cols.length, 1);
|
||||
assert.includeMembers(cols.map(col => col.id), [col1.id, col2.id]);
|
||||
assert.ok(cols.every(col =>
|
||||
|
@ -23,7 +23,7 @@ describe("Zotero.Collections", function () {
|
|||
var col5 = yield createDataObject('collection', { name: "E", parentID: col2.id });
|
||||
var col6 = yield createDataObject('collection', { name: "G", parentID: col3.id });
|
||||
var col7 = yield createDataObject('collection', { name: "F", parentID: col3.id });
|
||||
var cols = yield Zotero.Collections.getByLibrary(libraryID, true);
|
||||
var cols = Zotero.Collections.getByLibrary(libraryID, true);
|
||||
assert.isAbove(cols.length, 6);
|
||||
var ids = cols.map(col => col.id);
|
||||
assert.includeMembers(
|
||||
|
@ -44,8 +44,8 @@ describe("Zotero.Collections", function () {
|
|||
var col1 = yield createDataObject('collection');
|
||||
var col2 = yield createDataObject('collection');
|
||||
var col3 = yield createDataObject('collection', { parentID: col2.id });
|
||||
assert.lengthOf((yield Zotero.Collections.getByParent(col1.id)), 0);
|
||||
var cols = yield Zotero.Collections.getByParent(col2.id);
|
||||
assert.lengthOf(Zotero.Collections.getByParent(col1.id), 0);
|
||||
var cols = Zotero.Collections.getByParent(col2.id);
|
||||
assert.lengthOf(cols, 1);
|
||||
assert.sameMembers(cols.map(col => col.id), [col3.id]);
|
||||
})
|
||||
|
@ -55,8 +55,8 @@ describe("Zotero.Collections", function () {
|
|||
var col2 = yield createDataObject('collection');
|
||||
var col3 = yield createDataObject('collection', { parentID: col2.id });
|
||||
var col4 = yield createDataObject('collection', { parentID: col3.id });
|
||||
assert.lengthOf((yield Zotero.Collections.getByParent(col1.id)), 0);
|
||||
var cols = yield Zotero.Collections.getByParent(col2.id, true);
|
||||
assert.lengthOf(Zotero.Collections.getByParent(col1.id), 0);
|
||||
var cols = Zotero.Collections.getByParent(col2.id, true);
|
||||
assert.lengthOf(cols, 2);
|
||||
assert.includeMembers(cols.map(col => col.id), [col3.id, col4.id]);
|
||||
})
|
||||
|
|
|
@ -16,7 +16,9 @@ describe("Zotero_File_Interface", function() {
|
|||
testFile.append("allTypesAndFields.js");
|
||||
yield win.Zotero_File_Interface.importFile(testFile);
|
||||
|
||||
let importedCollection = yield Zotero.Collections.getByLibrary(Zotero.Libraries.userLibraryID).filter(x => x.name == 'allTypesAndFields');
|
||||
let importedCollection = Zotero.Collections.getByLibrary(
|
||||
Zotero.Libraries.userLibraryID
|
||||
).filter(x => x.name == 'allTypesAndFields');
|
||||
assert.equal(importedCollection.length, 1);
|
||||
let childItems = importedCollection[0].getChildItems();
|
||||
let savedItems = {};
|
||||
|
|
Loading…
Add table
Reference in a new issue