Merge pull request #3159 from omnivore-app/fix/nested-labels
feat: wildcard search for labels and nested labels
This commit is contained in:
@ -171,22 +171,61 @@ const buildWhereClause = (
|
||||
if (includeLabels && includeLabels.length > 0) {
|
||||
includeLabels.forEach((includeLabel, i) => {
|
||||
const param = `includeLabels_${i}`
|
||||
queryBuilder.andWhere(
|
||||
`lower(array_cat(library_item.label_names, library_item.highlight_labels)::text)::text[] && ARRAY[:...${param}]::text[]`,
|
||||
{
|
||||
[param]: includeLabel.labels,
|
||||
}
|
||||
const hasWildcard = includeLabel.labels.some((label) =>
|
||||
label.includes('*')
|
||||
)
|
||||
if (hasWildcard) {
|
||||
queryBuilder.andWhere(
|
||||
new Brackets((qb) => {
|
||||
includeLabel.labels.forEach((label, j) => {
|
||||
const param = `includeLabels_${i}_${j}`
|
||||
qb.orWhere(
|
||||
`array_to_string(array_cat(library_item.label_names, library_item.highlight_labels)::text[], ',') ILIKE :${param}`,
|
||||
{
|
||||
[param]: label.replace(/\*/g, '%'),
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
)
|
||||
} else {
|
||||
queryBuilder.andWhere(
|
||||
`lower(array_cat(library_item.label_names, library_item.highlight_labels)::text)::text[] && ARRAY[:...${param}]::text[]`,
|
||||
{
|
||||
[param]: includeLabel.labels,
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (excludeLabels && excludeLabels.length > 0) {
|
||||
queryBuilder.andWhere(
|
||||
'NOT lower(array_cat(library_item.label_names, library_item.highlight_labels)::text)::text[] && ARRAY[:...excludeLabels]::text[]',
|
||||
{
|
||||
excludeLabels: excludeLabels.flatMap((filter) => filter.labels),
|
||||
}
|
||||
)
|
||||
const labels = excludeLabels.flatMap((filter) => filter.labels)
|
||||
|
||||
const hasWildcard = labels.some((label) => label.includes('*'))
|
||||
|
||||
if (hasWildcard) {
|
||||
queryBuilder.andWhere(
|
||||
new Brackets((qb) => {
|
||||
labels.forEach((label, i) => {
|
||||
const param = `excludeLabels_${i}`
|
||||
qb.andWhere(
|
||||
`array_to_string(array_cat(library_item.label_names, library_item.highlight_labels)::text[], ',') NOT ILIKE :${param}`,
|
||||
{
|
||||
[param]: label.replace(/\*/g, '%'),
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
)
|
||||
} else {
|
||||
queryBuilder.andWhere(
|
||||
'NOT lower(array_cat(library_item.label_names, library_item.highlight_labels)::text)::text[] && ARRAY[:...excludeLabels]::text[]',
|
||||
{
|
||||
excludeLabels: labels,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1208,6 +1208,61 @@ describe('Article API', () => {
|
||||
})
|
||||
})
|
||||
|
||||
context('when wildcard search for labels', () => {
|
||||
let items: LibraryItem[] = []
|
||||
let labelIds: string[]
|
||||
|
||||
before(async () => {
|
||||
keyword = 'label:test/*'
|
||||
// Create some test items
|
||||
const label1 = await createLabel('test/one', '', user.id)
|
||||
const label2 = await createLabel('test/two', '', user.id)
|
||||
labelIds = [label1.id, label2.id]
|
||||
|
||||
items = await createLibraryItems(
|
||||
[
|
||||
{
|
||||
user,
|
||||
title: 'test title wildcard',
|
||||
readableContent: '<p>test wildcard</p>',
|
||||
slug: 'test slug wildcard',
|
||||
originalUrl: `${url}/wildcard`,
|
||||
},
|
||||
{
|
||||
user,
|
||||
title: 'test title wildcard 1',
|
||||
readableContent: '<p>test wildcard</p>',
|
||||
slug: 'test slug wildcard 1',
|
||||
originalUrl: `${url}/wildcard_1`,
|
||||
},
|
||||
{
|
||||
user,
|
||||
title: 'test title wildcard 2',
|
||||
readableContent: '<p>test wildcard</p>',
|
||||
slug: 'test slug wildcard 2',
|
||||
originalUrl: `${url}/wildcard_2`,
|
||||
},
|
||||
],
|
||||
user.id
|
||||
)
|
||||
await saveLabelsInLibraryItem([label1], items[0].id, user.id)
|
||||
await saveLabelsInLibraryItem([label2], items[1].id, user.id)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteLabels(labelIds, user.id)
|
||||
await deleteLibraryItems(items, user.id)
|
||||
})
|
||||
|
||||
it('returns library items with label test/one and test/two', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
|
||||
expect(res.body.data.search.pageInfo.totalCount).to.eq(2)
|
||||
expect(res.body.data.search.edges[0].node.id).to.eq(items[0].id)
|
||||
expect(res.body.data.search.edges[1].node.id).to.eq(items[1].id)
|
||||
})
|
||||
})
|
||||
|
||||
context('when type:file label:test is in the query', () => {
|
||||
let items: LibraryItem[] = []
|
||||
let label: Label
|
||||
|
||||
Reference in New Issue
Block a user