diff --git a/packages/bbui/src/Form/Core/DatePicker/NumberInput.svelte b/packages/bbui/src/Form/Core/DatePicker/NumberInput.svelte index 84b55c403f..794984c4b6 100644 --- a/packages/bbui/src/Form/Core/DatePicker/NumberInput.svelte +++ b/packages/bbui/src/Form/Core/DatePicker/NumberInput.svelte @@ -7,6 +7,8 @@ export let type = "number" $: style = width ? `width:${width}px;` : "" + + const selectAll = event => event.target.select() diff --git a/packages/bbui/src/Form/Core/DateRangePicker.svelte b/packages/bbui/src/Form/Core/DateRangePicker.svelte index a1f1a55d13..af4f67679b 100644 --- a/packages/bbui/src/Form/Core/DateRangePicker.svelte +++ b/packages/bbui/src/Form/Core/DateRangePicker.svelte @@ -34,7 +34,12 @@ } const onChangeFrom = (utc: string) => { - fromDate = utc ? dayjs(utc).startOf("day") : null + // Preserve the time if its editable + const fromDate = utc + ? enableTime + ? dayjs(utc) + : dayjs(utc).startOf("day") + : null if (fromDate && (!toDate || fromDate.isAfter(toDate))) { toDate = !enableTime ? fromDate.endOf("day") : fromDate } else if (!fromDate) { @@ -44,9 +49,13 @@ dispatch("change", [fromDate, toDate]) } - // Pass the raw date not the event const onChangeTo = (utc: string) => { - toDate = utc ? dayjs(utc).endOf("day") : null + // Preserve the time if its editable + const toDate = utc + ? enableTime + ? dayjs(utc) + : dayjs(utc).startOf("day") + : null if (toDate && (!fromDate || toDate.isBefore(fromDate))) { fromDate = !enableTime ? toDate.startOf("day") : toDate } else if (!toDate) { diff --git a/packages/builder/src/components/design/settings/controls/FilterConfiguration/FilterConfiguration.svelte b/packages/builder/src/components/design/settings/controls/FilterConfiguration/FilterConfiguration.svelte index df2a360a7c..5d6202b32c 100644 --- a/packages/builder/src/components/design/settings/controls/FilterConfiguration/FilterConfiguration.svelte +++ b/packages/builder/src/components/design/settings/controls/FilterConfiguration/FilterConfiguration.svelte @@ -85,7 +85,11 @@ schema: TableSchema | undefined, tableList: Table[] ) => { - return search.getFields(tableList, Object.values(schema || {}), { + // Omit calculated fields + const filtered = Object.values(schema || {}).filter( + field => !("calculationType" in field) + ) + return search.getFields(tableList, filtered, { allowLinks: true, }) } diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 7fd0547db4..46b1251da1 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -5578,6 +5578,7 @@ ] }, "dynamicfilter": { + "deprecated": true, "name": "Dynamic Filter", "icon": "Filter", "size": { diff --git a/packages/client/src/components/app/filter/Filter.svelte b/packages/client/src/components/app/filter/Filter.svelte index 14b0c212e6..0fce4e7a01 100644 --- a/packages/client/src/components/app/filter/Filter.svelte +++ b/packages/client/src/components/app/filter/Filter.svelte @@ -21,7 +21,6 @@ import Container from "../container/Container.svelte" import { getAction } from "@/utils/getAction" import { ActionTypes } from "@/constants" - import { fetchDatasourceSchema } from "@/utils/schema" import { QueryUtils, fetchData, memo } from "@budibase/frontend-core" import FilterButton from "./FilterButton.svelte" import { onDestroy } from "svelte" @@ -36,7 +35,8 @@ const memoFilters = memo({} as Record) const component = getContext("component") - const { API } = getContext("sdk") + const { API, fetchDatasourceSchema, getRelationshipSchemaAdditions } = + getContext("sdk") const rowCache = writable({}) setContext("rows", rowCache) @@ -236,17 +236,29 @@ async function fetchSchema(datasource: any) { if (datasource) { - const fetchedSchema = await fetchDatasourceSchema(datasource, { - enrichRelationships: true, - formSchema: false, - }) + const fetchedSchema: TableSchema | null = await fetchDatasourceSchema( + datasource, + { + enrichRelationships: true, + formSchema: false, + } + ) - const filteredSchema = Object.entries(fetchedSchema || {}).filter( + const filteredSchemaEntries = Object.entries(fetchedSchema || {}).filter( ([_, field]: [string, FieldSchema]) => { return !excludedTypes.includes(field.type) } ) - schema = Object.fromEntries(filteredSchema) + + const filteredSchema = Object.fromEntries(filteredSchemaEntries) + + // Necessary to ensure that link fields possess all config required + // to render their respective UX + const enrichedSchema = await getRelationshipSchemaAdditions( + filteredSchema as Record + ) + + schema = { ...filteredSchema, ...enrichedSchema } } else { schema = null } diff --git a/packages/client/src/components/app/filter/FilterPopover.svelte b/packages/client/src/components/app/filter/FilterPopover.svelte index 056bf98c1f..8a578cf2b0 100644 --- a/packages/client/src/components/app/filter/FilterPopover.svelte +++ b/packages/client/src/components/app/filter/FilterPopover.svelte @@ -30,6 +30,10 @@ import { type Writable } from "svelte/store" import { getContext } from "svelte" import { isArrayOperator } from "@/utils/filtering" + import dayjs from "dayjs" + import utc from "dayjs/plugin/utc" + + dayjs.extend(utc) export const show = () => popover?.show() export const hide = () => popover?.hide() @@ -268,22 +272,29 @@ value={parseDateRange(editableFilter.value)} on:change={e => { const [from, to] = e.detail - const parsedFrom = Helpers.stringifyDate(from, { - enableTime, - timeOnly, - ignoreTimezones, - }) + const parsedFrom = enableTime + ? from.utc().format() + : Helpers.stringifyDate(from, { + enableTime, + timeOnly, + ignoreTimezones, + }) - const parsedTo = Helpers.stringifyDate(to, { - enableTime, - timeOnly, - ignoreTimezones, - }) + const parsedTo = enableTime + ? to.utc().format() + : Helpers.stringifyDate(to, { + enableTime, + timeOnly, + ignoreTimezones, + }) if (!editableFilter) return editableFilter = sanitizeOperator({ ...editableFilter, - value: { low: parsedFrom, high: parsedTo }, + value: { + low: parsedFrom, + high: parsedTo, + }, }) }} /> diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 44e88f3414..6ee844efc6 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -96,6 +96,7 @@ export interface SDK { ActionTypes: typeof ActionTypes fetchDatasourceSchema: any fetchDatasourceDefinition: (datasource: DataFetchDatasource) => Promise + getRelationshipSchemaAdditions: (schema: Record) => Promise enrichButtonActions: any generateGoldenSample: any createContextStore: any diff --git a/packages/client/src/sdk.js b/packages/client/src/sdk.js index 15b88d3123..e9ef6a8505 100644 --- a/packages/client/src/sdk.js +++ b/packages/client/src/sdk.js @@ -29,6 +29,7 @@ import { ActionTypes } from "./constants" import { fetchDatasourceSchema, fetchDatasourceDefinition, + getRelationshipSchemaAdditions, } from "./utils/schema" import { getAPIKey } from "./utils/api.js" import { enrichButtonActions } from "./utils/buttonActions.js" @@ -71,6 +72,7 @@ export default { getAction, fetchDatasourceSchema, fetchDatasourceDefinition, + getRelationshipSchemaAdditions, fetchData, QueryUtils, ContextScopes: Constants.ContextScopes, diff --git a/packages/client/src/utils/schema.ts b/packages/client/src/utils/schema.ts index 5d68ddc5cc..3e637b4579 100644 --- a/packages/client/src/utils/schema.ts +++ b/packages/client/src/utils/schema.ts @@ -121,6 +121,7 @@ export const getRelationshipSchemaAdditions = async ( relationshipAdditions[`${fieldKey}.${linkKey}`] = { type: linkSchema[linkKey].type, externalType: linkSchema[linkKey].externalType, + constraints: linkSchema[linkKey].constraints, } }) } diff --git a/packages/shared-core/src/filters.ts b/packages/shared-core/src/filters.ts index 3630ab90ce..e4ad413aed 100644 --- a/packages/shared-core/src/filters.ts +++ b/packages/shared-core/src/filters.ts @@ -103,8 +103,6 @@ export const getValidOperatorsForType = ( ops = [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty, Op.In] } else if (type === FieldType.BB_REFERENCE) { ops = [Op.Contains, Op.NotContains, Op.ContainsAny, Op.Empty, Op.NotEmpty] - } else if (type === FieldType.LINK) { - ops = [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty, Op.In] } // Only allow equal/not equal for _id in SQL tables