diff --git a/chrome/content/zotero/xpcom/server/server_connector.js b/chrome/content/zotero/xpcom/server/server_connector.js index 301be412a3..60b3ee1bbb 100644 --- a/chrome/content/zotero/xpcom/server/server_connector.js +++ b/chrome/content/zotero/xpcom/server/server_connector.js @@ -774,6 +774,18 @@ Zotero.Server.Connector.UpdateSession.prototype = { await session.update(data.target, tags, note); + if (data.updatedMetadata) { + let item = session.getItemByConnectorKey(data.updatedMetadata.id); + if (item) { + for (let field of data.updatedMetadata.fields) { + if (field.name === 'itemType') continue; + item.setField(field.name, field.value); + } + item.setCreators(data.updatedMetadata.creators || []); + await item.saveTx(); + } + } + return [200, "application/json", JSON.stringify({})]; } }; @@ -1112,6 +1124,7 @@ Zotero.Server.Connector.Ping.prototype = { downloadAssociatedFiles: Zotero.Prefs.get("downloadAssociatedFiles"), supportsAttachmentUpload: true, supportsTagsAutocomplete: true, + supportsMetadataUpdates: true, googleDocsAddNoteEnabled: true, googleDocsAddAnnotationEnabled: true, canUserAddNote: true, diff --git a/test/tests/server_connectorTest.js b/test/tests/server_connectorTest.js index ca19f95b97..b0ca5c1ba7 100644 --- a/test/tests/server_connectorTest.js +++ b/test/tests/server_connectorTest.js @@ -1181,6 +1181,115 @@ describe("Connector Server", function () { assert.equal(note.getNote(), "Test note"); }); + it("should update metadata of item saved via /saveItems", async function () { + var collection = await createDataObject('collection'); + await select(win, collection); + + const id = Zotero.Utilities.randomString(); + var sessionID = Zotero.Utilities.randomString(); + var body = { + sessionID, + items: [ + { + itemType: "newspaperArticle", + title: "Title", + id, + creators: [ + { + firstName: "First", + lastName: "Last", + creatorType: "author" + } + ] + } + ], + uri: "http://example.com" + }; + + var reqPromise = httpRequest( + 'POST', + connectorServerPath + "/connector/saveItems", + { + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(body) + } + ); + + var ids = await waitForItemEvent('add'); + var item = Zotero.Items.get(ids[0]); + var req = await reqPromise; + assert.equal(req.status, 201); + assert.equal(item.getField('title'), "Title"); + + // Update metadata + req = await httpRequest( + 'POST', + connectorServerPath + "/connector/updateSession", + { + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + sessionID, + target: collection.treeViewID, + tags: "", + note: "", + updatedMetadata: { + id, + fields: [ + { + name: "itemType", + label: "Item Type", + value: "newspaperArticle" + }, + { + name: "title", + label: "Title", + value: "Updated Title" + }, + { + name: "abstractNote", + label: "Abstract", + value: "Updated abstract" + }, + { + name: "date", + label: "Date", + value: "2026-04-08" + }, + { + name: "url", + label: "URL", + value: "http://example.com/updated" + } + ], + creators: [ + { + firstName: "New First", + lastName: "New Last", + creatorType: "author" + } + ] + } + }) + } + ); + + assert.equal(req.status, 200); + assert.equal(item.getField('title'), "Updated Title"); + assert.equal(item.getField('abstractNote'), "Updated abstract"); + assert.equal(item.getField('date'), "2026-04-08"); + assert.equal(item.getField('url'), "http://example.com/updated"); + var creators = item.getCreators(); + assert.equal(creators.length, 1); + assert.equal(creators[0].firstName, "New First"); + assert.equal(creators[0].lastName, "New Last"); + // Verify collection is preserved + assert.isTrue(collection.hasItem(item.id)); + }); + it("should update collections and tags of a PDF saved via /saveStandaloneAttachment", async function () { const sessionID = Zotero.Utilities.randomString();