Merge branch 'master' into budi-8730-views-filter-by-current-user_id-does-not-work
This commit is contained in:
commit
13424218eb
|
@ -273,6 +273,7 @@ class InternalBuilder {
|
||||||
const col = parts.pop()!
|
const col = parts.pop()!
|
||||||
const schema = this.table.schema[col]
|
const schema = this.table.schema[col]
|
||||||
let identifier = this.quotedIdentifier(field)
|
let identifier = this.quotedIdentifier(field)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
schema.type === FieldType.STRING ||
|
schema.type === FieldType.STRING ||
|
||||||
schema.type === FieldType.LONGFORM ||
|
schema.type === FieldType.LONGFORM ||
|
||||||
|
@ -957,6 +958,13 @@ class InternalBuilder {
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isAggregateField(field: string): boolean {
|
||||||
|
const found = this.query.resource?.aggregations?.find(
|
||||||
|
aggregation => aggregation.name === field
|
||||||
|
)
|
||||||
|
return !!found
|
||||||
|
}
|
||||||
|
|
||||||
addSorting(query: Knex.QueryBuilder): Knex.QueryBuilder {
|
addSorting(query: Knex.QueryBuilder): Knex.QueryBuilder {
|
||||||
let { sort, resource } = this.query
|
let { sort, resource } = this.query
|
||||||
const primaryKey = this.table.primary
|
const primaryKey = this.table.primary
|
||||||
|
@ -979,13 +987,17 @@ class InternalBuilder {
|
||||||
nulls = value.direction === SortOrder.ASCENDING ? "first" : "last"
|
nulls = value.direction === SortOrder.ASCENDING ? "first" : "last"
|
||||||
}
|
}
|
||||||
|
|
||||||
let composite = `${aliased}.${key}`
|
if (this.isAggregateField(key)) {
|
||||||
if (this.client === SqlClient.ORACLE) {
|
query = query.orderBy(key, direction, nulls)
|
||||||
query = query.orderByRaw(
|
|
||||||
`${this.convertClobs(composite)} ${direction} nulls ${nulls}`
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
query = query.orderBy(composite, direction, nulls)
|
let composite = `${aliased}.${key}`
|
||||||
|
if (this.client === SqlClient.ORACLE) {
|
||||||
|
query = query.orderByRaw(
|
||||||
|
`${this.convertClobs(composite)} ${direction} nulls ${nulls}`
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
query = query.orderBy(composite, direction, nulls)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
InternalTable,
|
InternalTable,
|
||||||
tenancy,
|
tenancy,
|
||||||
features,
|
features,
|
||||||
|
utils,
|
||||||
} from "@budibase/backend-core"
|
} from "@budibase/backend-core"
|
||||||
import { quotas } from "@budibase/pro"
|
import { quotas } from "@budibase/pro"
|
||||||
import {
|
import {
|
||||||
|
@ -757,6 +758,37 @@ describe.each([
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("user column", () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
table = await config.api.table.save(
|
||||||
|
saveTableRequest({
|
||||||
|
schema: {
|
||||||
|
user: {
|
||||||
|
name: "user",
|
||||||
|
type: FieldType.BB_REFERENCE_SINGLE,
|
||||||
|
subtype: BBReferenceFieldSubType.USER,
|
||||||
|
default: "{{ [Current User]._id }}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("creates a new row with a default value successfully", async () => {
|
||||||
|
const row = await config.api.row.save(table._id!, {})
|
||||||
|
expect(row.user._id).toEqual(config.getUser()._id)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("does not use default value if value specified", async () => {
|
||||||
|
const id = `us_${utils.newid()}`
|
||||||
|
await config.createUser({ _id: id })
|
||||||
|
const row = await config.api.row.save(table._id!, {
|
||||||
|
user: id,
|
||||||
|
})
|
||||||
|
expect(row.user._id).toEqual(id)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("bindings", () => {
|
describe("bindings", () => {
|
||||||
describe("string column", () => {
|
describe("string column", () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
|
|
@ -3381,6 +3381,124 @@ describe.each([
|
||||||
expect(rows).toHaveLength(1)
|
expect(rows).toHaveLength(1)
|
||||||
expect(rows[0].sum).toEqual(3)
|
expect(rows[0].sum).toEqual(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should be able to sort by group by field", async () => {
|
||||||
|
const table = await config.api.table.save(
|
||||||
|
saveTableRequest({
|
||||||
|
schema: {
|
||||||
|
quantity: {
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
name: "quantity",
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
name: "price",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const view = await config.api.viewV2.create({
|
||||||
|
tableId: table._id!,
|
||||||
|
name: generator.guid(),
|
||||||
|
type: ViewV2Type.CALCULATION,
|
||||||
|
schema: {
|
||||||
|
quantity: { visible: true },
|
||||||
|
sum: {
|
||||||
|
visible: true,
|
||||||
|
calculationType: CalculationType.SUM,
|
||||||
|
field: "price",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
await config.api.row.bulkImport(table._id!, {
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
quantity: 1,
|
||||||
|
price: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
quantity: 1,
|
||||||
|
price: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
quantity: 2,
|
||||||
|
price: 10,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const { rows } = await config.api.viewV2.search(view.id, {
|
||||||
|
query: {},
|
||||||
|
sort: "quantity",
|
||||||
|
sortOrder: SortOrder.DESCENDING,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(rows).toEqual([
|
||||||
|
expect.objectContaining({ quantity: 2, sum: 10 }),
|
||||||
|
expect.objectContaining({ quantity: 1, sum: 3 }),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should be able to sort by a calculation", async () => {
|
||||||
|
const table = await config.api.table.save(
|
||||||
|
saveTableRequest({
|
||||||
|
schema: {
|
||||||
|
quantity: {
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
name: "quantity",
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
name: "price",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
await config.api.row.bulkImport(table._id!, {
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
quantity: 1,
|
||||||
|
price: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
quantity: 1,
|
||||||
|
price: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
quantity: 2,
|
||||||
|
price: 10,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const view = await config.api.viewV2.create({
|
||||||
|
tableId: table._id!,
|
||||||
|
name: generator.guid(),
|
||||||
|
type: ViewV2Type.CALCULATION,
|
||||||
|
schema: {
|
||||||
|
quantity: { visible: true },
|
||||||
|
sum: {
|
||||||
|
visible: true,
|
||||||
|
calculationType: CalculationType.SUM,
|
||||||
|
field: "price",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { rows } = await config.api.viewV2.search(view.id, {
|
||||||
|
query: {},
|
||||||
|
sort: "sum",
|
||||||
|
sortOrder: SortOrder.DESCENDING,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(rows).toEqual([
|
||||||
|
expect.objectContaining({ quantity: 2, sum: 10 }),
|
||||||
|
expect.objectContaining({ quantity: 1, sum: 3 }),
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
!isLucene &&
|
!isLucene &&
|
||||||
|
|
|
@ -418,13 +418,26 @@ export async function search(
|
||||||
|
|
||||||
if (params.sort) {
|
if (params.sort) {
|
||||||
const sortField = table.schema[params.sort]
|
const sortField = table.schema[params.sort]
|
||||||
const sortType =
|
const isAggregateField = aggregations.some(agg => agg.name === params.sort)
|
||||||
sortField.type === FieldType.NUMBER ? SortType.NUMBER : SortType.STRING
|
|
||||||
request.sort = {
|
if (isAggregateField) {
|
||||||
[mapToUserColumn(sortField.name)]: {
|
request.sort = {
|
||||||
direction: params.sortOrder || SortOrder.ASCENDING,
|
[params.sort]: {
|
||||||
type: sortType as SortType,
|
direction: params.sortOrder || SortOrder.ASCENDING,
|
||||||
},
|
type: SortType.NUMBER,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else if (sortField) {
|
||||||
|
const sortType =
|
||||||
|
sortField.type === FieldType.NUMBER ? SortType.NUMBER : SortType.STRING
|
||||||
|
request.sort = {
|
||||||
|
[mapToUserColumn(sortField.name)]: {
|
||||||
|
direction: params.sortOrder || SortOrder.ASCENDING,
|
||||||
|
type: sortType as SortType,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unable to sort by ${params.sort}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ const allowDefaultColumnByType: Record<FieldType, boolean> = {
|
||||||
[FieldType.SIGNATURE_SINGLE]: false,
|
[FieldType.SIGNATURE_SINGLE]: false,
|
||||||
[FieldType.LINK]: false,
|
[FieldType.LINK]: false,
|
||||||
[FieldType.BB_REFERENCE]: false,
|
[FieldType.BB_REFERENCE]: false,
|
||||||
[FieldType.BB_REFERENCE_SINGLE]: false,
|
[FieldType.BB_REFERENCE_SINGLE]: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canBeDisplayColumn(type: FieldType): boolean {
|
export function canBeDisplayColumn(type: FieldType): boolean {
|
||||||
|
|
|
@ -172,7 +172,7 @@ export const processSearchFilters = (
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return a.localeCompare(b)
|
return a.localeCompare(b)
|
||||||
})
|
})
|
||||||
.filter(key => key in filter)
|
.filter(key => filter[key])
|
||||||
|
|
||||||
if (filterPropertyKeys.length == 1) {
|
if (filterPropertyKeys.length == 1) {
|
||||||
const key = filterPropertyKeys[0],
|
const key = filterPropertyKeys[0],
|
||||||
|
|
|
@ -126,6 +126,7 @@ export interface BBReferenceSingleFieldMetadata
|
||||||
extends Omit<BaseFieldSchema, "subtype"> {
|
extends Omit<BaseFieldSchema, "subtype"> {
|
||||||
type: FieldType.BB_REFERENCE_SINGLE
|
type: FieldType.BB_REFERENCE_SINGLE
|
||||||
subtype: Exclude<BBReferenceFieldSubType, BBReferenceFieldSubType.USERS>
|
subtype: Exclude<BBReferenceFieldSubType, BBReferenceFieldSubType.USERS>
|
||||||
|
default?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AttachmentFieldMetadata extends BaseFieldSchema {
|
export interface AttachmentFieldMetadata extends BaseFieldSchema {
|
||||||
|
|
Loading…
Reference in New Issue