diff --git a/packages/client/manifest.json b/packages/client/manifest.json index a1dc294e0aa..3f36b17ea5a 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -8375,6 +8375,12 @@ "key": "autocomplete", "defaultValue": true }, + { + "type": "boolean", + "label": "Workspace users", + "key": "workspaceUsersOnly", + "defaultValue": false + }, { "type": "boolean", "label": "Disabled", @@ -8491,6 +8497,12 @@ "key": "autocomplete", "defaultValue": true }, + { + "type": "boolean", + "label": "Workspace users", + "key": "workspaceUsersOnly", + "defaultValue": false + }, { "type": "boolean", "label": "Disabled", diff --git a/packages/client/src/components/app/forms/RelationshipField.svelte b/packages/client/src/components/app/forms/RelationshipField.svelte index a41c959fd53..087c9ebe06a 100644 --- a/packages/client/src/components/app/forms/RelationshipField.svelte +++ b/packages/client/src/components/app/forms/RelationshipField.svelte @@ -17,8 +17,9 @@ type RelationshipFieldMetadata, type Row, type UIFieldValidationRule, + type DataFetchDatasource, } from "@budibase/types" - import { fetchData, Utils } from "@budibase/frontend-core" + import { fetchData, Utils, Constants } from "@budibase/frontend-core" import { getContext } from "svelte" import Field from "./Field.svelte" import type { FieldApi, FieldState } from "@/types" @@ -48,6 +49,9 @@ export let tableId: string | undefined = undefined export let defaultRows: Row[] | undefined = [] + // Limit datasourceType "user" to app users only + export let workspaceUsersOnly: boolean | undefined = false + const { API } = getContext("sdk") const dispatch = createEventDispatcher() @@ -67,7 +71,7 @@ let loadingMissingOptions: boolean = false // Reset the available options when our base filter changes - $: filter, (optionsMap = {}) + $: filter, workspaceUsersOnly, (optionsMap = {}) // Determine if we can select multiple rows or not $: multiselect = multi ?? @@ -87,12 +91,17 @@ writable, datasourceType, migratedFilter, - linkedTableId + linkedTableId, + workspaceUsersOnly ) // Attempt to determine the primary display field to use $: tableDefinition = $fetch?.definition - $: primaryDisplayField = primaryDisplay || tableDefinition?.primaryDisplay + $: primaryDisplayField = + primaryDisplay || + (tableDefinition && "primaryDisplay" in tableDefinition + ? tableDefinition.primaryDisplay + : undefined) // Build our options map $: rows = $fetch?.rows || [] @@ -137,16 +146,17 @@ writable: boolean, dsType: typeof datasourceType, filter: UISearchFilter | undefined, - linkedTableId?: string + linkedTableId?: string, + workspaceUsersOnly?: boolean ) => { - const datasource = + const datasource: DataFetchDatasource = dsType === "table" ? { type: dsType, tableId: linkedTableId!, } : { - type: dsType, + type: workspaceUsersOnly ? "table" : dsType, tableId: InternalTable.USER_METADATA, } return fetchData({ @@ -200,6 +210,14 @@ optionsMap = optionsMap } + const parseId = (id: string) => { + // Normalise app table users to the global format. + if (datasourceType === "user" && workspaceUsersOnly) { + return id.replace(`ro_${Constants.TableNames.USERS}_`, "") + } + return id + } + // Parses a row-like structure into a properly shaped option const parseOption = ( option: string | BasicRelatedRow | Row, @@ -219,21 +237,21 @@ // that if (Object.keys(option).length === 2 && "primaryDisplay" in option) { return { - _id: option._id, + _id: parseId(option._id), primaryDisplay: ensureString(option.primaryDisplay), } } // Otherwise use the primary display field specified if (primaryDisplay) { return { - _id: option._id, + _id: parseId(option._id), primaryDisplay: ensureString( option[primaryDisplay as keyof typeof option] ), } } else { return { - _id: option._id, + _id: parseId(option._id), primaryDisplay: option._id, } }