Fix manual tags missing from tag selector with automatic tags hidden

If a view contained manual and automatic tags with the same name, only
one was kept, and it would disappear with "Show Automatic" off.

https://forums.zotero.org/discussion/133869/
This commit is contained in:
Dan Stillman 2026-09-30 11:41:34 -04:00
parent ae50d52589
commit d8382c5c11
2 changed files with 37 additions and 3 deletions

View file

@ -140,7 +140,7 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent {
? await rows[0].getTags(...args)
: await Zotero.CollectionTreeRow.getTagsAcrossRows(rows, ...args);
// Multiple rows (collections, or collections across libraries) can return
// the same tag, so dedupe by name
// the same tag, so dedupe by name and type
return this._dedupeTags(tags);
}
catch (e) {
@ -163,8 +163,9 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent {
let seen = new Set();
let result = [];
for (let tag of tags) {
if (!seen.has(tag.tag)) {
seen.add(tag.tag);
let key = tag.type + ':' + tag.tag;
if (!seen.has(key)) {
seen.add(key);
result.push(tag);
}
}
@ -173,6 +174,7 @@ Zotero.TagSelector = class TagSelectorContainer extends React.PureComponent {
/**
* Get all tags across the selected libraries (for "Display All Tags"), deduped by name
* and type
*
* @param {Number[]} [tagIDs] - Limit to the given tag IDs
*/

View file

@ -95,6 +95,38 @@ describe("Tag Selector", function () {
assert.sameMembers(getRegularTags(), ['A', 'B']);
});
it("should show a manual tag when automatic tags are hidden and an automatic tag has the same name", async function () {
var collection = await createDataObject('collection');
var item1 = createUnsavedDataObject('item', { collections: [collection.id] });
item1.setTags([{ tag: "A", type: 1 }]);
var item2 = createUnsavedDataObject('item', { collections: [collection.id] });
item2.setTags(["A"]);
await Zotero.DB.executeTransaction(async function () {
await item1.save();
await item2.save();
});
var emptyCollection = await createDataObject('collection');
await select(win, emptyCollection);
await waitForCallback(() => !tagSelector.state.tags.length);
// Same-name tags come back in no particular order, so return the automatic one first
var getAllWithin = Zotero.Tags.getAllWithin;
var stub = sinon.stub(Zotero.Tags, 'getAllWithin').callsFake(async function (...args) {
let tags = await getAllWithin.apply(this, args);
return tags.sort((a, b) => b.type - a.type);
});
tagSelector.toggleShowAutomatic(false);
try {
await select(win, collection);
await waitForCallback(() => tagSelector.state.tags.length);
assert.sameMembers(getRegularTags(), ['A']);
}
finally {
stub.restore();
tagSelector.toggleShowAutomatic(true);
}
});
it("should show tags from annotations for attachments in scope", async function () {
var collection = await createDataObject('collection');
await select(win, collection);