Add item tree and info box refresh API (#4850)
For APIs that have lifecycle control, e.g. item pane section, the `update` is passed in the init hook. For APIs without lifecycle, we can't pass a value. Instead, we provide a method to refresh in the API instance.
This commit is contained in:
parent
8e2ec86e56
commit
f5b653e7fd
5 changed files with 75 additions and 15 deletions
|
@ -488,7 +488,7 @@
|
||||||
//
|
//
|
||||||
notify(event, type, ids) {
|
notify(event, type, ids) {
|
||||||
if (event == 'refresh' && type == 'infobox' && this.item?.id) {
|
if (event == 'refresh' && type == 'infobox' && this.item?.id) {
|
||||||
this.renderCustomRows();
|
this.renderCustomRows(ids);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event == 'modify' && this.item?.id && ids.includes(this.item.id)) {
|
if (event == 'modify' && this.item?.id && ids.includes(this.item.id)) {
|
||||||
|
@ -863,11 +863,6 @@
|
||||||
|
|
||||||
this.restoreCustomRowElements();
|
this.restoreCustomRowElements();
|
||||||
|
|
||||||
// Update custom row data
|
|
||||||
for (let rowElem of this._infoTable.querySelectorAll('.meta-row[data-custom-row-id]')) {
|
|
||||||
this.updateCustomRowData(rowElem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set focus on the last focused field
|
// Set focus on the last focused field
|
||||||
this._restoreFieldFocus();
|
this._restoreFieldFocus();
|
||||||
// Make sure that any opened popup closes
|
// Make sure that any opened popup closes
|
||||||
|
@ -876,8 +871,18 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCustomRows() {
|
renderCustomRows(rowIDs) {
|
||||||
let { options: targetRows, updateID } = Zotero.ItemPaneManager.customInfoRowData;
|
let { options: targetRows, updateID } = Zotero.ItemPaneManager.customInfoRowData;
|
||||||
|
|
||||||
|
// If rowIDs are provided, always update them
|
||||||
|
if (rowIDs?.length > 0) {
|
||||||
|
for (let rowID of rowIDs) {
|
||||||
|
let rowElem = this._infoTable.querySelector(`[data-custom-row-id="${rowID}"]`);
|
||||||
|
if (!rowElem) continue;
|
||||||
|
this.updateCustomRowData(rowElem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this._lastUpdateCustomRows == updateID) return;
|
if (this._lastUpdateCustomRows == updateID) return;
|
||||||
this._lastUpdateCustomRows = updateID;
|
this._lastUpdateCustomRows = updateID;
|
||||||
|
|
||||||
|
@ -890,8 +895,15 @@
|
||||||
|
|
||||||
// Add rows that are in the target rows but not in the current rows
|
// Add rows that are in the target rows but not in the current rows
|
||||||
for (let row of targetRows) {
|
for (let row of targetRows) {
|
||||||
if (this._infoTable.querySelector(`[data-custom-row-id="${row.rowID}"]`)) continue;
|
let rowElem = this._infoTable.querySelector(`[data-custom-row-id="${row.rowID}"]`);
|
||||||
let rowElem = document.createElement("div");
|
if (rowElem) {
|
||||||
|
// If the row is already in the table, and not already updated, update it
|
||||||
|
if (!rowIDs?.includes(row.rowID)) {
|
||||||
|
this.updateCustomRowData(rowElem);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rowElem = document.createElement("div");
|
||||||
rowElem.dataset.customRowId = row.rowID;
|
rowElem.dataset.customRowId = row.rowID;
|
||||||
let position = row.position || "end";
|
let position = row.position || "end";
|
||||||
rowElem.dataset.position = position;
|
rowElem.dataset.position = position;
|
||||||
|
@ -933,6 +945,7 @@
|
||||||
|
|
||||||
this.updateCustomRowProperty(rowElem);
|
this.updateCustomRowProperty(rowElem);
|
||||||
|
|
||||||
|
// The row is new, always update the data
|
||||||
this.updateCustomRowData(rowElem);
|
this.updateCustomRowData(rowElem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,6 +301,13 @@
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refresh(rowID) {
|
||||||
|
if (!this._optionsCache[rowID]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._refresh([rowID]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -329,6 +336,10 @@
|
||||||
return this._infoRowManager.unregister(rowID);
|
return this._infoRowManager.unregister(rowID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshInfoRow(rowID) {
|
||||||
|
return this._infoRowManager.refresh(rowID);
|
||||||
|
}
|
||||||
|
|
||||||
get customInfoRowData() {
|
get customInfoRowData() {
|
||||||
return this._infoRowManager.data;
|
return this._infoRowManager.data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,10 @@ import { COLUMNS } from 'zotero/itemTreeColumns';
|
||||||
|
|
||||||
return super._validate(option);
|
return super._validate(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
this._refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -332,6 +336,10 @@ import { COLUMNS } from 'zotero/itemTreeColumns';
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshColumns() {
|
||||||
|
this._columnManager.refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ class PluginAPIBase {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this._addPluginShutdownObserver();
|
this._addPluginShutdownObserver();
|
||||||
this._update();
|
this._refresh();
|
||||||
return mainKey;
|
return mainKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ class PluginAPIBase {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this._update();
|
this._refresh();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,14 +322,14 @@ class PluginAPIBase {
|
||||||
/**
|
/**
|
||||||
* Notify the receiver to update
|
* Notify the receiver to update
|
||||||
*/
|
*/
|
||||||
async _update() {
|
async _refresh(ids = [], extraData = {}) {
|
||||||
this._lastUpdateID = `${new Date().getTime()}-${lazy.Zotero.Utilities.randomString()}`;
|
this._lastUpdateID = `${new Date().getTime()}-${lazy.Zotero.Utilities.randomString()}`;
|
||||||
await lazy.Zotero.DB.executeTransaction(async () => {
|
await lazy.Zotero.DB.executeTransaction(async () => {
|
||||||
lazy.Zotero.Notifier.queue(
|
lazy.Zotero.Notifier.queue(
|
||||||
this._config.notifyAction,
|
this._config.notifyAction,
|
||||||
this._config.notifyType,
|
this._config.notifyType,
|
||||||
[],
|
ids,
|
||||||
{},
|
extraData,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,7 @@ class PluginAPIBase {
|
||||||
// Remove the registrations one by one
|
// Remove the registrations one by one
|
||||||
paneIDs.forEach(id => this._remove(id));
|
paneIDs.forEach(id => this._remove(id));
|
||||||
this._log(`Registrations for plugin ${pluginID} are unregistered due to shutdown`);
|
this._log(`Registrations for plugin ${pluginID} are unregistered due to shutdown`);
|
||||||
await this._update();
|
await this._refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -359,6 +359,34 @@ describe("Plugin API", function () {
|
||||||
|
|
||||||
await waitForUnregister(rowID);
|
await waitForUnregister(rowID);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should refresh custom row value", async function () {
|
||||||
|
let item = new Zotero.Item('book');
|
||||||
|
await item.saveTx();
|
||||||
|
await ZoteroPane.selectItem(item.id);
|
||||||
|
|
||||||
|
let rowID = await waitForRegister(defaultOption);
|
||||||
|
|
||||||
|
let rowElem = infoSection.querySelector(`[data-custom-row-id="${rowID}"]`);
|
||||||
|
let valueElem = rowElem.querySelector(".value");
|
||||||
|
|
||||||
|
let oldValue = valueElem.value;
|
||||||
|
|
||||||
|
// Since this row does not have `onSetData`, changing value does not do anything
|
||||||
|
// We just want to test if the value can be refreshed by calling `updateInfoRow`
|
||||||
|
let newValue = "TEST CUSTOM ROW EDITED";
|
||||||
|
valueElem.value = newValue;
|
||||||
|
|
||||||
|
let notifyPromise = waitForNotifierEvent("refresh", "infobox");
|
||||||
|
|
||||||
|
// Manually refresh the row
|
||||||
|
Zotero.ItemPaneManager.refreshInfoRow(rowID);
|
||||||
|
await notifyPromise;
|
||||||
|
|
||||||
|
assert.equal(oldValue, valueElem.value);
|
||||||
|
|
||||||
|
await waitForUnregister(rowID);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Item tree custom column", function () {
|
describe("Item tree custom column", function () {
|
||||||
|
|
Loading…
Reference in a new issue