1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-24 13:04:06 +00:00
bramw_baserow/web-frontend/modules/database/utils/view.js

182 lines
5.1 KiB
JavaScript

import { firstBy } from 'thenby'
import BigNumber from 'bignumber.js'
/**
* Generates a sort function based on the provided sortings.
*/
export function getRowSortFunction(
$registry,
sortings,
fields,
primary = null
) {
let sortFunction = firstBy()
sortings.forEach((sort) => {
// Find the field that is related to the sort.
let field = fields.find((f) => f.id === sort.field)
if (field === undefined && primary !== null && primary.id === sort.field) {
field = primary
}
if (field !== undefined) {
const fieldName = `field_${field.id}`
const fieldType = $registry.get('field', field.type)
const fieldSortFunction = fieldType.getSort(fieldName, sort.order, field)
sortFunction = sortFunction.thenBy(fieldSortFunction)
}
})
sortFunction = sortFunction.thenBy((a, b) =>
new BigNumber(a.order).minus(new BigNumber(b.order))
)
sortFunction = sortFunction.thenBy((a, b) => a.id - b.id)
return sortFunction
}
/**
* A helper function that checks if the provided row values match the provided view
* filters. Returning false indicates that the row should not be visible for that
* view.
*/
export const matchSearchFilters = (
$registry,
filterType,
filters,
fields,
values
) => {
// If there aren't any filters then it is not possible to check if the row
// matches any of the filters, so we can mark it as valid.
if (filters.length === 0) {
return true
}
for (const i in filters) {
const filter = filters[i]
const filterValue = filter.value
const rowValue = values[`field_${filter.field}`]
const field = fields.find((f) => f.id === filter.field)
const fieldType = $registry.get('field', field.type)
const matches = $registry
.get('viewFilter', filter.type)
.matches(rowValue, filterValue, field, fieldType)
if (filterType === 'AND' && !matches) {
// With an `AND` filter type, the row must match all the filters, so if
// one of the filters doesn't match we can mark it as isvalid.
return false
} else if (filterType === 'OR' && matches) {
// With an 'OR' filter type, the row only has to match one of the filters,
// that is the case here so we can mark it as valid.
return true
}
}
if (filterType === 'AND') {
// When this point has been reached with an `AND` filter type it means that
// the row matches all the filters and therefore we can mark it as valid.
return true
} else if (filterType === 'OR') {
// When this point has been reached with an `OR` filter type it means that
// the row matches none of the filters and therefore we can mark it as invalid.
return false
}
}
export function valueMatchesActiveSearchTerm(
registry,
field,
value,
activeSearchTerm
) {
return registry
.get('field', field.type)
.containsFilter(value, activeSearchTerm, field)
}
function _findFieldsInRowMatchingSearch(
row,
activeSearchTerm,
fields,
registry,
overrides
) {
const fieldSearchMatches = new Set()
// If the row is loading then a temporary UUID is put in its id. We don't want to
// accidentally match against that UUID as it will be shortly replaced with its
// real id.
if (!row._.loading && row.id.toString().includes(activeSearchTerm)) {
fieldSearchMatches.add('row_id')
}
for (const field of fields) {
const fieldName = `field_${field.id}`
const rowValue =
fieldName in overrides ? overrides[fieldName] : row[fieldName]
if (rowValue) {
const doesMatch = valueMatchesActiveSearchTerm(
registry,
field,
rowValue,
activeSearchTerm
)
if (doesMatch) {
fieldSearchMatches.add(field.id.toString())
}
}
}
return fieldSearchMatches
}
/**
* Helper function which calculates if a given row and which of it's fields matches a
* given search term. The rows values can be overridden by providing an overrides
* object containing a mapping of the field name to override to a value that will be
* used to check for matches instead of the rows real one. The rows values will not be
* changed.
*/
export function calculateSingleRowSearchMatches(
row,
activeSearchTerm,
hideRowsNotMatchingSearch,
fields,
registry,
overrides = {}
) {
const searchIsBlank = activeSearchTerm === ''
const fieldSearchMatches = searchIsBlank
? new Set()
: _findFieldsInRowMatchingSearch(
row,
activeSearchTerm,
fields,
registry,
overrides
)
const matchSearch =
!hideRowsNotMatchingSearch || searchIsBlank || fieldSearchMatches.size > 0
return { row, matchSearch, fieldSearchMatches }
}
/**
* Returns true is the empty value of the provided field matches the active search term.
*/
export function newFieldMatchesActiveSearchTerm(
registry,
newField,
activeSearchTerm
) {
if (newField && activeSearchTerm !== '') {
const fieldType = registry.get('field', newField.type)
const emptyValue = fieldType.getEmptyValue(newField)
return valueMatchesActiveSearchTerm(
registry,
newField,
emptyValue,
activeSearchTerm
)
}
return false
}