commit 80a0826eb61c3844e67d501e0533cfc9424051bd
parent 2fe756c1c9d29202e995191ec9fcdcd10d70ead8
Author: Dan Stillman <dstillman@zotero.org>
Date: Fri, 24 Feb 2017 02:31:08 -0500
Add archived group handling to sync runner
- Archive remotely missing that user chooses to keep
- Ignore archived groups that don't existing remotely
- Unarchive groups that become available again
Diffstat:
2 files changed, 113 insertions(+), 14 deletions(-)
diff --git a/chrome/content/zotero/xpcom/sync/syncRunner.js b/chrome/content/zotero/xpcom/sync/syncRunner.js
@@ -371,9 +371,9 @@ Zotero.Sync.Runner_Module = function (options = {}) {
let group = Zotero.Groups.get(id);
if (syncAllLibraries) {
- // If syncing all libraries, mark any that don't exist or are outdated
- // locally for update. Group is added to the library list after downloading
- if (!group || group.version < remoteGroupVersions[id]) {
+ // If syncing all libraries, mark any that don't exist, are outdated, or are
+ // archived locally for update. Group is added to the library list after downloading.
+ if (!group || group.version < remoteGroupVersions[id] || group.archived) {
groupsToDownload.push(id);
}
// If not outdated, just add to library list
@@ -421,6 +421,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
// TODO: What about explicit deletions?
let removedGroups = [];
+ let keptGroups = [];
let ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
@@ -433,6 +434,12 @@ Zotero.Sync.Runner_Module = function (options = {}) {
//
// TODO: Localize
for (let group of remotelyMissingGroups) {
+ // Ignore archived groups
+ if (group.archived) {
+ groupsToDownload.splice(groupsToDownload.indexOf(group.id), 1);
+ continue;
+ }
+
let msg;
// If all-groups access but group is missing, user left it
if (access.groups && access.groups.all) {
@@ -467,18 +474,25 @@ Zotero.Sync.Runner_Module = function (options = {}) {
return [];
}
else if (index == 2) {
- // TODO: Mark groups to be ignored
+ keptGroups.push(group);
}
}
let removedLibraryIDs = [];
for (let group of removedGroups) {
removedLibraryIDs.push(group.libraryID);
- yield Zotero.DB.executeTransaction(function* () {
- return group.erase();
- });
+ yield group.eraseTx();
}
libraries = Zotero.Utilities.arrayDiff(libraries, removedLibraryIDs);
+
+ let keptLibraryIDs = [];
+ for (let group of keptGroups) {
+ keptLibraryIDs.push(group.libraryID);
+ group.editable = false;
+ group.archived = true;
+ yield group.saveTx();
+ }
+ libraries = Zotero.Utilities.arrayDiff(libraries, keptLibraryIDs);
}
// Update metadata and permissions on missing or outdated groups
@@ -508,6 +522,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
group.id = groupID;
}
group.version = info.version;
+ group.archived = false;
group.fromJSON(info.data, Zotero.Users.getCurrentUserID());
yield group.saveTx();
@@ -515,6 +530,8 @@ Zotero.Sync.Runner_Module = function (options = {}) {
libraries.push(group.libraryID);
}
+ // Note: If any non-group library types become archivable, they'll need to be unarchived here.
+
return [...new Set(libraries)];
});
diff --git a/test/tests/syncRunnerTest.js b/test/tests/syncRunnerTest.js
@@ -296,6 +296,64 @@ describe("Zotero.Sync.Runner", function () {
assert.equal(skippedGroup.version, responses.groups.memberGroup.json.version - 1);
});
+ it("should filter out remotely missing archived libraries if library list not provided", function* () {
+ var syncedGroupID = responses.groups.ownerGroup.json.id;
+ var archivedGroupID = 162512451; // nonexistent group id
+
+ var syncedGroup = yield createGroup({
+ id: syncedGroupID,
+ version: responses.groups.ownerGroup.json.version - 1
+ });
+ var archivedGroup = yield createGroup({
+ id: archivedGroupID,
+ editable: false,
+ archived: true
+ });
+
+ setResponse('userGroups.groupVersions');
+ setResponse('groups.ownerGroup');
+ var libraries = yield runner.checkLibraries(
+ runner.getAPIClient({ apiKey }),
+ false,
+ responses.keyInfo.fullAccess.json
+ );
+
+ assert.lengthOf(libraries, 3);
+ assert.sameMembers(libraries, [userLibraryID, publicationsLibraryID, syncedGroup.libraryID]);
+ });
+
+ it("should unarchive library if available remotely", function* () {
+ var syncedGroupID = responses.groups.ownerGroup.json.id;
+ var archivedGroupID = responses.groups.memberGroup.json.id;
+
+ var syncedGroup = yield createGroup({
+ id: syncedGroupID,
+ version: responses.groups.ownerGroup.json.version
+ });
+ var archivedGroup = yield createGroup({
+ id: archivedGroupID,
+ version: responses.groups.memberGroup.json.version - 1,
+ editable: false,
+ archived: true
+ });
+
+ setResponse('userGroups.groupVersions');
+ setResponse('groups.ownerGroup');
+ setResponse('groups.memberGroup');
+ var libraries = yield runner.checkLibraries(
+ runner.getAPIClient({ apiKey }),
+ false,
+ responses.keyInfo.fullAccess.json
+ );
+
+ assert.lengthOf(libraries, 4);
+ assert.sameMembers(
+ libraries,
+ [userLibraryID, publicationsLibraryID, syncedGroup.libraryID, archivedGroup.libraryID]
+ );
+ assert.isFalse(archivedGroup.archived);
+ });
+
it("shouldn't filter out skipped libraries if library list is provided", function* () {
var groupData = responses.groups.memberGroup;
var group = yield createGroup({
@@ -453,21 +511,45 @@ describe("Zotero.Sync.Runner", function () {
assert.isTrue(Zotero.Groups.exists(groupData2.json.id));
})
- it.skip("should keep remotely missing groups", function* () {
- var groupData = responses.groups.ownerGroup;
- var group = yield createGroup({ id: groupData.json.id, version: groupData.json.version });
+ it("should keep remotely missing groups", function* () {
+ var group1 = yield createGroup({ editable: true, filesEditable: true });
+ var group2 = yield createGroup({ editable: true, filesEditable: true });
setResponse('userGroups.groupVersionsEmpty');
+ var called = 0;
+ var otherGroup;
waitForDialog(function (dialog) {
+ called++;
var text = dialog.document.documentElement.textContent;
- assert.include(text, group.name);
+ if (text.includes(group1.name)) {
+ otherGroup = group2;
+ }
+ else if (text.includes(group2.name)) {
+ otherGroup = group1;
+ }
+ else {
+ throw new Error("Dialog text does not include either group name");
+ }
+
+ waitForDialog(function (dialog) {
+ called++;
+ var text = dialog.document.documentElement.textContent;
+ assert.include(text, otherGroup.name);
+ }, "extra1");
}, "extra1");
var libraries = yield runner.checkLibraries(
runner.getAPIClient({ apiKey }), false, responses.keyInfo.fullAccess.json
);
- assert.lengthOf(libraries, 3);
- assert.sameMembers(libraries, [userLibraryID, publicationsLibraryID, group.libraryID]);
- assert.isTrue(Zotero.Groups.exists(groupData.json.id));
+ assert.equal(called, 2);
+ assert.lengthOf(libraries, 2);
+ assert.sameMembers(libraries, [userLibraryID, publicationsLibraryID]);
+ // Groups should still exist but be read-only and archived
+ [group1, group2].forEach((group) => {
+ assert.isTrue(Zotero.Groups.exists(group.id));
+ assert.isTrue(group.archived);
+ assert.isFalse(group.editable);
+ assert.isFalse(group.filesEditable);
+ });
})
it("should cancel sync with remotely missing groups", function* () {