Fix: add root tag filtering for tag list page consistency, fix toggle all (#11208)

This commit is contained in:
shamoon
2025-10-28 11:04:22 -07:00
committed by GitHub
parent ce112cda0e
commit d718d7d29f
6 changed files with 117 additions and 3 deletions

View File

@@ -361,4 +361,11 @@ describe('ManagementListComponent', () => {
const original = component.getOriginalObject({ id: 4 } as Tag)
expect(original).toEqual(childTag)
})
it('getSelectableIDs should return flat ids when not overridden', () => {
const ids = (
ManagementListComponent.prototype as any
).getSelectableIDs.call({}, [{ id: 1 }, { id: 5 }] as any)
expect(ids).toEqual([1, 5])
})
})

View File

@@ -297,13 +297,19 @@ export abstract class ManagementListComponent<T extends MatchingModel>
}
toggleAll(event: PointerEvent) {
if ((event.target as HTMLInputElement).checked) {
this.selectedObjects = new Set(this.data.map((o) => o.id))
const checked = (event.target as HTMLInputElement).checked
this.togggleAll = checked
if (checked) {
this.selectedObjects = new Set(this.getSelectableIDs(this.data))
} else {
this.clearSelection()
}
}
protected getSelectableIDs(objects: T[]): number[] {
return objects.map((o) => o.id)
}
clearSelection() {
this.togggleAll = false
this.selectedObjects.clear()

View File

@@ -17,6 +17,7 @@ describe('TagListComponent', () => {
let component: TagListComponent
let fixture: ComponentFixture<TagListComponent>
let tagService: TagService
let listFilteredSpy: jest.SpyInstance
beforeEach(async () => {
TestBed.configureTestingModule({
@@ -39,7 +40,7 @@ describe('TagListComponent', () => {
}).compileComponents()
tagService = TestBed.inject(TagService)
jest.spyOn(tagService, 'listFiltered').mockReturnValue(
listFilteredSpy = jest.spyOn(tagService, 'listFiltered').mockReturnValue(
of({
count: 3,
all: [1, 2, 3],
@@ -87,4 +88,57 @@ describe('TagListComponent', () => {
const filteredWithName = component.filterData(tags as any)
expect(filteredWithName.length).toBe(3)
})
it('should request only parent tags when no name filter is applied', () => {
expect(tagService.listFiltered).toHaveBeenCalledWith(
1,
null,
undefined,
undefined,
undefined,
true,
{ is_root: true }
)
})
it('should include child tags when a name filter is applied', () => {
listFilteredSpy.mockClear()
component['_nameFilter'] = 'Tag'
component.reloadData()
expect(tagService.listFiltered).toHaveBeenCalledWith(
1,
null,
undefined,
undefined,
'Tag',
true,
null
)
})
it('should include child tags when selecting all', () => {
const parent = {
id: 10,
name: 'Parent',
children: [
{
id: 11,
name: 'Child',
},
],
}
component.data = [parent as any]
const selectEvent = { target: { checked: true } } as unknown as PointerEvent
component.toggleAll(selectEvent)
expect(component.selectedObjects.has(10)).toBe(true)
expect(component.selectedObjects.has(11)).toBe(true)
const deselectEvent = {
target: { checked: false },
} as unknown as PointerEvent
component.toggleAll(deselectEvent)
expect(component.selectedObjects.size).toBe(0)
})
})

View File

@@ -61,9 +61,29 @@ export class TagListComponent extends ManagementListComponent<Tag> {
return $localize`Do you really want to delete the tag "${object.name}"?`
}
override reloadData(extraParams: { [key: string]: any } = null) {
const params = this.nameFilter?.length
? extraParams
: { ...extraParams, is_root: true }
super.reloadData(params)
}
filterData(data: Tag[]) {
return this.nameFilter?.length
? [...data]
: data.filter((tag) => !tag.parent)
}
protected override getSelectableIDs(tags: Tag[]): number[] {
const ids: number[] = []
for (const tag of tags.filter(Boolean)) {
if (tag.id != null) {
ids.push(tag.id)
}
if (Array.isArray(tag.children) && tag.children.length) {
ids.push(...this.getSelectableIDs(tag.children))
}
}
return ids
}
}