From 9fc76bbe51231988257071798a909154e59cb16d Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Fri, 6 Dec 2024 20:30:04 +0530 Subject: [PATCH 1/8] add 'key' and 'path' properties to table in airtable config --- inc/Integrations/Airtable/AirtableDataSource.php | 13 +++++++++---- src/data-sources/airtable/AirtableSettings.tsx | 9 +++++---- src/data-sources/types.ts | 8 ++++++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/inc/Integrations/Airtable/AirtableDataSource.php b/inc/Integrations/Airtable/AirtableDataSource.php index 0f1d8c7d..c0bb9f07 100644 --- a/inc/Integrations/Airtable/AirtableDataSource.php +++ b/inc/Integrations/Airtable/AirtableDataSource.php @@ -44,11 +44,16 @@ class AirtableDataSource extends HttpDataSource { 'items' => [ 'type' => 'object', 'properties' => [ - 'name' => [ 'type' => 'string' ], + 'key' => [ 'type' => 'string' ], + 'name' => [ 'type' => 'string', 'required' => false ], 'type' => [ 'type' => 'string', 'required' => false, ], + 'path' => [ + 'type' => 'string', + 'required' => false, + ], ], ], ], @@ -121,9 +126,9 @@ public function ___temp_get_query(): AirtableGetItemQuery|\WP_Error { ]; foreach ( $this->config['tables'][0]['output_query_mappings'] as $mapping ) { - $output_schema['mappings'][ ucfirst( $mapping['name'] ) ] = [ - 'name' => $mapping['name'], - 'path' => '$.fields.' . $mapping['name'], + $output_schema['mappings'][ $mapping['key'] ] = [ + 'name' => $mapping['name'] ?? $mapping['key'], + 'path' => $mapping['path'] ?? '$.fields.' . $mapping['key'], 'type' => $mapping['type'] ?? 'string', ]; } diff --git a/src/data-sources/airtable/AirtableSettings.tsx b/src/data-sources/airtable/AirtableSettings.tsx index 3df12ade..9a9763b5 100644 --- a/src/data-sources/airtable/AirtableSettings.tsx +++ b/src/data-sources/airtable/AirtableSettings.tsx @@ -51,7 +51,7 @@ const getInitialStateFromConfig = ( config?: AirtableConfig ): AirtableFormState name: table.name, }; initialStateFromConfig.table_fields = new Set( - table.output_query_mappings.map( ( { name } ) => name ) + table.output_query_mappings.map( ( { key } ) => key ) ); } } @@ -114,9 +114,10 @@ export const AirtableSettings = ( { { id: state.table.id, name: state.table.name, - output_query_mappings: Array.from( state.table_fields ).map( name => ( { - name, - type: name.endsWith( '.url' ) ? 'image_url' : 'string', + output_query_mappings: Array.from( state.table_fields ).map( key => ( { + key, + name: key, + type: key.endsWith( '.url' ) ? 'image_url' : 'string', } ) ), }, ], diff --git a/src/data-sources/types.ts b/src/data-sources/types.ts index 2c7bba12..68297358 100644 --- a/src/data-sources/types.ts +++ b/src/data-sources/types.ts @@ -12,9 +12,10 @@ interface BaseDataSourceConfig { } export interface DataSourceQueryMappingValue { + key: string; name: string; path: string; - type: 'id' | 'string'; + type: string; } export type DataSourceQueryMapping = Record< string, DataSourceQueryMappingValue >; @@ -30,7 +31,10 @@ export interface DataSourceQuery { * - `type` is always string for now. */ export interface AirtableOutputQueryMappingValue { - name: string; + key: string; + name?: string; + path?: string; + type?: string; } export interface AirtableTableConfig extends StringIdName { From c60703a4d5874a218567076f5f8f607810ccf510 Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Fri, 6 Dec 2024 21:38:01 +0530 Subject: [PATCH 2/8] refactor: AirtableDataSource output query mappings to improve path handling - Updated the path generation for output query mappings to use bracket notation for keys, ensuring compatibility with keys that may contain special characters. - Introduced a variable for the mapping key to enhance code readability. --- inc/Integrations/Airtable/AirtableDataSource.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/inc/Integrations/Airtable/AirtableDataSource.php b/inc/Integrations/Airtable/AirtableDataSource.php index c0bb9f07..12f7cb6f 100644 --- a/inc/Integrations/Airtable/AirtableDataSource.php +++ b/inc/Integrations/Airtable/AirtableDataSource.php @@ -126,9 +126,10 @@ public function ___temp_get_query(): AirtableGetItemQuery|\WP_Error { ]; foreach ( $this->config['tables'][0]['output_query_mappings'] as $mapping ) { - $output_schema['mappings'][ $mapping['key'] ] = [ - 'name' => $mapping['name'] ?? $mapping['key'], - 'path' => $mapping['path'] ?? '$.fields.' . $mapping['key'], + $mapping_key = $mapping['key']; + $output_schema['mappings'][ $mapping_key ] = [ + 'name' => $mapping['name'] ?? $mapping_key, + 'path' => $mapping['path'] ?? '$.fields["' . $mapping_key . '"]', 'type' => $mapping['type'] ?? 'string', ]; } From 6498e7da89aed17b1203a0b49d5d72dc97e0d055 Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Fri, 6 Dec 2024 21:58:36 +0530 Subject: [PATCH 3/8] feat: add support for all airtable field types - Automatically assign output mapping types to airtable fields - Improved field mapping logic to filter unsupported fields and handle selected table fields more effectively. --- .../airtable/AirtableSettings.tsx | 48 ++++++++------ src/data-sources/airtable/constants.ts | 53 +++++++++++++++ src/data-sources/airtable/types.ts | 26 +++++++- src/data-sources/airtable/utils.ts | 64 +++++++++++++++++++ 4 files changed, 171 insertions(+), 20 deletions(-) create mode 100644 src/data-sources/airtable/constants.ts create mode 100644 src/data-sources/airtable/utils.ts diff --git a/src/data-sources/airtable/AirtableSettings.tsx b/src/data-sources/airtable/AirtableSettings.tsx index 9a9763b5..1646c75e 100644 --- a/src/data-sources/airtable/AirtableSettings.tsx +++ b/src/data-sources/airtable/AirtableSettings.tsx @@ -4,7 +4,9 @@ import { useEffect, useMemo, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { ChangeEvent } from 'react'; +import { SUPPORTED_AIRTABLE_TYPES } from '@/data-sources/airtable/constants'; import { AirtableFormState } from '@/data-sources/airtable/types'; +import { getAirtableOutputQueryMappingValue } from '@/data-sources/airtable/utils'; import { DataSourceForm } from '@/data-sources/components/DataSourceForm'; import { DataSourceFormActions } from '@/data-sources/components/DataSourceFormActions'; import PasswordInputControl from '@/data-sources/components/PasswordInputControl'; @@ -15,7 +17,11 @@ import { useAirtableApiUserId, } from '@/data-sources/hooks/useAirtable'; import { useDataSources } from '@/data-sources/hooks/useDataSources'; -import { AirtableConfig, SettingsComponentProps } from '@/data-sources/types'; +import { + AirtableConfig, + AirtableOutputQueryMappingValue, + SettingsComponentProps, +} from '@/data-sources/types'; import { getConnectionMessage } from '@/data-sources/utils'; import { useForm } from '@/hooks/useForm'; import { useSettingsContext } from '@/settings/hooks/useSettingsNav'; @@ -105,6 +111,11 @@ export const AirtableSettings = ( { return; } + const selectedTable = tables?.find( table => table.id === state.table?.id ); + if ( ! selectedTable ) { + return; + } + const airtableConfig: AirtableConfig = { uuid: uuidFromProps ?? '', service: 'airtable', @@ -114,11 +125,18 @@ export const AirtableSettings = ( { { id: state.table.id, name: state.table.name, - output_query_mappings: Array.from( state.table_fields ).map( key => ( { - key, - name: key, - type: key.endsWith( '.url' ) ? 'image_url' : 'string', - } ) ), + output_query_mappings: Array.from( state.table_fields ) + .map( key => { + const field = selectedTable.fields.find( tableField => tableField.name === key ); + if ( field ) { + return getAirtableOutputQueryMappingValue( field ); + } + /** + * Remove any fields which are not from this table or not supported. + */ + return null; + } ) + .filter( Boolean ) as AirtableOutputQueryMappingValue[], }, ], slug: state.slug, @@ -149,6 +167,11 @@ export const AirtableSettings = ( { } else if ( id === 'table' ) { const selectedTable = tables?.find( table => table.id === value ); newValue = { id: value, name: selectedTable?.name ?? '' }; + + if ( value !== state.table?.id ) { + // Reset the selected fields when the table changes. + handleOnChange( 'table_fields', new Set< string >() ); + } } handleOnChange( id, newValue ); } @@ -285,19 +308,8 @@ export const AirtableSettings = ( { if ( selectedTable ) { selectedTable.fields.forEach( field => { - const simpleFieldTypes = [ - 'singleLineText', - 'multilineText', - 'email', - 'phoneNumber', - 'url', - 'number', - ]; - - if ( simpleFieldTypes.includes( field.type ) ) { + if ( SUPPORTED_AIRTABLE_TYPES.includes( field.type ) ) { newAvailableTableFields.push( field.name ); - } else if ( field.type === 'multipleAttachments' ) { - newAvailableTableFields.push( `${ field.name }[0].url` ); } } ); } diff --git a/src/data-sources/airtable/constants.ts b/src/data-sources/airtable/constants.ts new file mode 100644 index 00000000..6f193213 --- /dev/null +++ b/src/data-sources/airtable/constants.ts @@ -0,0 +1,53 @@ +export const STRING_TYPES = Object.freeze( + new Set( [ + 'singleLineText', + 'multilineText', + 'email', + 'phoneNumber', + 'richText', + 'barcode', + 'singleSelect', + 'multipleSelect', + 'date', + 'dateTime', + 'lastModifiedTime', + 'createdTime', + ] ) +); + +export const NUMBER_TYPES = Object.freeze( + new Set( [ 'number', 'autoNumber', 'rating', 'duration', 'count' ] ) +); + +export const SUPPORTED_AIRTABLE_TYPES = Object.freeze( [ + // String types + 'singleLineText', + 'multilineText', + 'email', + 'phoneNumber', + 'richText', + 'barcode', + 'singleSelect', + 'multipleSelect', + 'date', + 'dateTime', + 'lastModifiedTime', + 'createdTime', + // Number types + 'number', + 'autoNumber', + 'rating', + 'duration', + 'count', + // Other types + 'url', + 'button', + 'currency', + 'checkbox', + 'multipleAttachments', + 'singleCollaborator', + 'multipleCollaborator', + 'formula', + 'rollup', + 'lookup', +] ); diff --git a/src/data-sources/airtable/types.ts b/src/data-sources/airtable/types.ts index 8d6f7010..33410d36 100644 --- a/src/data-sources/airtable/types.ts +++ b/src/data-sources/airtable/types.ts @@ -34,13 +34,35 @@ export interface AirtableTable { syncStatus: 'complete' | 'pending'; } -interface AirtableField { +/** + * Represents an Airtable field configuration. + * @see https://airtable.com/developers/web/api/model/table-model#fields + */ +export interface AirtableField { id: string; name: string; type: string; description: string | null; options?: { - [ key: string ]: unknown; + choices?: Array< { + id: string; + name: string; + color?: string; + } >; + precision?: number; + symbol?: string; + format?: string; + foreignTableId?: string; + relationship?: 'many' | 'one'; + symmetricColumnId?: string; + result?: { + type: string; + options?: { + precision?: number; + symbol?: string; + format?: string; + }; + }; }; } diff --git a/src/data-sources/airtable/utils.ts b/src/data-sources/airtable/utils.ts new file mode 100644 index 00000000..ed1d67c0 --- /dev/null +++ b/src/data-sources/airtable/utils.ts @@ -0,0 +1,64 @@ +import { STRING_TYPES, NUMBER_TYPES } from '@/data-sources/airtable/constants'; +import { AirtableField } from '@/data-sources/airtable/types'; +import { AirtableOutputQueryMappingValue } from '@/data-sources/types'; + +export const getAirtableOutputQueryMappingValue = ( + field: AirtableField +): AirtableOutputQueryMappingValue => { + const baseField = { + path: `$.fields["${ field.name }"]`, + name: field.name, + key: field.name, + }; + + if ( STRING_TYPES.has( field.type ) ) { + return { ...baseField, type: 'string' }; + } + + if ( NUMBER_TYPES.has( field.type ) ) { + return { ...baseField, type: 'number' }; + } + + switch ( field.type ) { + case 'url': + case 'button': + return { ...baseField, type: 'button_url' }; + + case 'currency': + return { ...baseField, type: 'price' }; + + case 'checkbox': + return { ...baseField, type: 'boolean' }; + + case 'multipleAttachments': + return { + path: `$.fields["${ field.name }"][0].url`, + name: `${ field.name } URL`, + key: `${ field.name }_url`, + type: 'image_url', + }; + + case 'singleCollaborator': + case 'multipleCollaborator': + return { + path: `$.fields["${ field.name }"].name`, + name: `${ field.name } Name`, + key: `${ field.name }_name`, + type: 'string', + }; + + case 'formula': + case 'rollup': + case 'lookup': + if ( field.options?.result?.type ) { + return getAirtableOutputQueryMappingValue( { + ...field, + type: field.options.result.type, + } ); + } + return { ...baseField, type: 'string' }; + + default: + return { ...baseField, type: 'string' }; + } +}; From 4b9042efb435671a72916cca3021b2a338b9f496 Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Sat, 7 Dec 2024 02:13:17 +0530 Subject: [PATCH 4/8] feat: add support for string array field type in QueryRunner - Implemented handling for 'string_array' field type, allowing for the conversion of array values into a comma-separated string format. --- inc/Config/QueryRunner/QueryRunner.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/inc/Config/QueryRunner/QueryRunner.php b/inc/Config/QueryRunner/QueryRunner.php index 49e21d3b..0035616b 100644 --- a/inc/Config/QueryRunner/QueryRunner.php +++ b/inc/Config/QueryRunner/QueryRunner.php @@ -254,6 +254,9 @@ protected function get_field_value( array|string $field_value, string $default_v case 'price': return sprintf( '$%s', number_format( (float) $field_value_single, 2 ) ); + case 'string_array': + return implode( ', ', $field_value ); + case 'string': return wp_strip_all_tags( $field_value_single ); } From 62bd7bac7bb5b6e0a5900483fa68c7cdf9031886 Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Sat, 7 Dec 2024 02:44:36 +0530 Subject: [PATCH 5/8] refactor: update field type handling to use 'currency' instead of 'price' and add 'string_array' support - Changed field type from 'price' to 'currency' in multiple queries and configurations to standardize currency handling. - Updated the QueryRunner to accept a mapping array for field values, enhancing flexibility in field type management. - Added 'string_array' to the list of supported text field types, allowing for better data handling in queries. - Adjusted documentation to reflect these changes. --- docs/extending/query.md | 3 ++- inc/Config/QueryRunner/QueryRunner.php | 12 ++++++++---- inc/Editor/BlockPatterns/BlockPatterns.php | 3 ++- .../Shopify/Queries/ShopifyGetProductQuery.php | 2 +- .../Shopify/Queries/ShopifySearchProductsQuery.php | 2 +- src/blocks/remote-data-container/config/constants.ts | 2 +- src/data-sources/types.ts | 1 + 7 files changed, 16 insertions(+), 9 deletions(-) diff --git a/docs/extending/query.md b/docs/extending/query.md index 31e740f6..00124c88 100644 --- a/docs/extending/query.md +++ b/docs/extending/query.md @@ -74,8 +74,9 @@ The `get_input_schema` method defines the input data expected by the query. The - `image_alt` - `image_url` - `number` - - `price` + - `currency` - `string` + - `string_array` #### Example diff --git a/inc/Config/QueryRunner/QueryRunner.php b/inc/Config/QueryRunner/QueryRunner.php index 0035616b..1ce160ed 100644 --- a/inc/Config/QueryRunner/QueryRunner.php +++ b/inc/Config/QueryRunner/QueryRunner.php @@ -241,7 +241,10 @@ public function execute( array $input_variables ): array|WP_Error { * @param string $field_type The field type. * @return string The field value. */ - protected function get_field_value( array|string $field_value, string $default_value = '', string $field_type = 'string' ): string { + protected function get_field_value( array|string $field_value, array $mapping ): string { + $default_value = $mapping['default_value'] ?? ''; + $field_type = $mapping['type']; + $field_value_single = is_array( $field_value ) && count( $field_value ) > 1 ? $field_value : ( $field_value[0] ?? $default_value ); switch ( $field_type ) { @@ -251,8 +254,9 @@ protected function get_field_value( array|string $field_value, string $default_v case 'html': return $field_value_single; - case 'price': - return sprintf( '$%s', number_format( (float) $field_value_single, 2 ) ); + case 'currency': + $currency_symbol = $mapping['prefix'] ?? '$'; + return sprintf( '%s%s', $currency_symbol, number_format( (float) $field_value_single, 2 ) ); case 'string_array': return implode( ', ', $field_value ); @@ -307,7 +311,7 @@ protected function map_fields( string|array|object|null $response_data, bool $is // JSONPath always returns values in an array, even if there's only one value. // Because we're mostly interested in single values for field mapping, unwrap the array if it's only one item. - $field_value_single = self::get_field_value( $field_value, $mapping['default_value'] ?? '', $mapping['type'] ); + $field_value_single = self::get_field_value( $field_value, $mapping ); } return array_merge( $mapping, [ diff --git a/inc/Editor/BlockPatterns/BlockPatterns.php b/inc/Editor/BlockPatterns/BlockPatterns.php index efb24f8c..c536f64f 100644 --- a/inc/Editor/BlockPatterns/BlockPatterns.php +++ b/inc/Editor/BlockPatterns/BlockPatterns.php @@ -108,8 +108,9 @@ public static function register_default_block_pattern( string $block_name, strin ]; break; + case 'string_array': case 'base64': - case 'price': + case 'currency': $bindings['paragraphs'][] = [ 'content' => [ $field, $name ], ]; diff --git a/inc/Integrations/Shopify/Queries/ShopifyGetProductQuery.php b/inc/Integrations/Shopify/Queries/ShopifyGetProductQuery.php index 183fc47a..1f743701 100644 --- a/inc/Integrations/Shopify/Queries/ShopifyGetProductQuery.php +++ b/inc/Integrations/Shopify/Queries/ShopifyGetProductQuery.php @@ -47,7 +47,7 @@ public function get_output_schema(): array { 'price' => [ 'name' => 'Item price', 'path' => '$.data.product.priceRange.maxVariantPrice.amount', - 'type' => 'price', + 'type' => 'currency', ], 'variant_id' => [ 'name' => 'Variant ID', diff --git a/inc/Integrations/Shopify/Queries/ShopifySearchProductsQuery.php b/inc/Integrations/Shopify/Queries/ShopifySearchProductsQuery.php index 1c1baabd..2aeaceb5 100644 --- a/inc/Integrations/Shopify/Queries/ShopifySearchProductsQuery.php +++ b/inc/Integrations/Shopify/Queries/ShopifySearchProductsQuery.php @@ -31,7 +31,7 @@ public function get_output_schema(): array { 'price' => [ 'name' => 'Item price', 'path' => '$.node.priceRange.maxVariantPrice.amount', - 'type' => 'price', + 'type' => 'currency', ], 'image_url' => [ 'name' => 'Item image URL', diff --git a/src/blocks/remote-data-container/config/constants.ts b/src/blocks/remote-data-container/config/constants.ts index 07c3ec2f..86a0a445 100644 --- a/src/blocks/remote-data-container/config/constants.ts +++ b/src/blocks/remote-data-container/config/constants.ts @@ -15,5 +15,5 @@ export const REMOTE_DATA_REST_API_URL = getRestUrl(); export const CONTAINER_CLASS_NAME = getClassName( 'container' ); export const IMAGE_FIELD_TYPES = [ 'image_alt', 'image_url' ]; -export const TEXT_FIELD_TYPES = [ 'number', 'base64', 'price', 'string' ]; +export const TEXT_FIELD_TYPES = [ 'number', 'base64', 'currency', 'string', 'string_array' ]; export const BUTTON_FIELD_TYPES = [ 'button_url' ]; diff --git a/src/data-sources/types.ts b/src/data-sources/types.ts index 68297358..38e9edd2 100644 --- a/src/data-sources/types.ts +++ b/src/data-sources/types.ts @@ -35,6 +35,7 @@ export interface AirtableOutputQueryMappingValue { name?: string; path?: string; type?: string; + prefix?: string; } export interface AirtableTableConfig extends StringIdName { From 80a143212bedb3e871a690ffbb49da1dd9b5a59d Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Sat, 7 Dec 2024 02:49:57 +0530 Subject: [PATCH 6/8] refine airtable type handling --- .../Airtable/AirtableDataSource.php | 8 ++++ src/data-sources/airtable/constants.ts | 28 +++++++---- src/data-sources/airtable/utils.ts | 46 ++++++++++++++----- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/inc/Integrations/Airtable/AirtableDataSource.php b/inc/Integrations/Airtable/AirtableDataSource.php index 12f7cb6f..5ef91b44 100644 --- a/inc/Integrations/Airtable/AirtableDataSource.php +++ b/inc/Integrations/Airtable/AirtableDataSource.php @@ -54,6 +54,10 @@ class AirtableDataSource extends HttpDataSource { 'type' => 'string', 'required' => false, ], + 'prefix' => [ + 'type' => 'string', + 'required' => false, + ], ], ], ], @@ -132,6 +136,10 @@ public function ___temp_get_query(): AirtableGetItemQuery|\WP_Error { 'path' => $mapping['path'] ?? '$.fields["' . $mapping_key . '"]', 'type' => $mapping['type'] ?? 'string', ]; + + if ( $mapping['type'] === 'currency' && isset( $mapping['prefix'] ) ) { + $output_schema['mappings'][ $mapping_key ]['prefix'] = $mapping['prefix']; + } } return AirtableGetItemQuery::from_array([ diff --git a/src/data-sources/airtable/constants.ts b/src/data-sources/airtable/constants.ts index 6f193213..366ed11d 100644 --- a/src/data-sources/airtable/constants.ts +++ b/src/data-sources/airtable/constants.ts @@ -1,4 +1,4 @@ -export const STRING_TYPES = Object.freeze( +export const AIRTABLE_STRING_TYPES = Object.freeze( new Set( [ 'singleLineText', 'multilineText', @@ -7,16 +7,22 @@ export const STRING_TYPES = Object.freeze( 'richText', 'barcode', 'singleSelect', - 'multipleSelect', 'date', 'dateTime', 'lastModifiedTime', 'createdTime', + 'multipleRecordLinks', + 'rollup', + 'externalSyncSource', ] ) ); -export const NUMBER_TYPES = Object.freeze( - new Set( [ 'number', 'autoNumber', 'rating', 'duration', 'count' ] ) +export const AIRTABLE_NUMBER_TYPES = Object.freeze( + new Set( [ 'number', 'autoNumber', 'rating', 'duration', 'count', 'percent' ] ) +); + +export const AIRTABLE_USER_TYPES = Object.freeze( + new Set( [ 'createdBy', 'lastModifiedBy', 'singleCollaborator' ] ) ); export const SUPPORTED_AIRTABLE_TYPES = Object.freeze( [ @@ -28,26 +34,32 @@ export const SUPPORTED_AIRTABLE_TYPES = Object.freeze( [ 'richText', 'barcode', 'singleSelect', - 'multipleSelect', + 'multipleSelects', 'date', 'dateTime', 'lastModifiedTime', 'createdTime', + 'multipleRecordLinks', + 'rollup', + 'externalSyncSource', // Number types 'number', 'autoNumber', 'rating', 'duration', 'count', + 'percent', + // User types + 'createdBy', + 'lastModifiedBy', + 'singleCollaborator', // Other types + 'multipleCollaborator', 'url', 'button', 'currency', 'checkbox', 'multipleAttachments', - 'singleCollaborator', - 'multipleCollaborator', 'formula', - 'rollup', 'lookup', ] ); diff --git a/src/data-sources/airtable/utils.ts b/src/data-sources/airtable/utils.ts index ed1d67c0..2d5fd04f 100644 --- a/src/data-sources/airtable/utils.ts +++ b/src/data-sources/airtable/utils.ts @@ -1,4 +1,8 @@ -import { STRING_TYPES, NUMBER_TYPES } from '@/data-sources/airtable/constants'; +import { + AIRTABLE_STRING_TYPES, + AIRTABLE_NUMBER_TYPES, + AIRTABLE_USER_TYPES, +} from '@/data-sources/airtable/constants'; import { AirtableField } from '@/data-sources/airtable/types'; import { AirtableOutputQueryMappingValue } from '@/data-sources/types'; @@ -11,44 +15,62 @@ export const getAirtableOutputQueryMappingValue = ( key: field.name, }; - if ( STRING_TYPES.has( field.type ) ) { + if ( AIRTABLE_STRING_TYPES.has( field.type ) ) { return { ...baseField, type: 'string' }; } - if ( NUMBER_TYPES.has( field.type ) ) { + if ( AIRTABLE_NUMBER_TYPES.has( field.type ) ) { return { ...baseField, type: 'number' }; } + if ( AIRTABLE_USER_TYPES.has( field.type ) ) { + return { ...baseField, path: `$.fields["${ field.name }"].name`, type: 'string' }; + } + switch ( field.type ) { case 'url': case 'button': return { ...baseField, type: 'button_url' }; case 'currency': - return { ...baseField, type: 'price' }; + return { + ...baseField, + type: 'currency', + prefix: field.options?.symbol, + }; case 'checkbox': return { ...baseField, type: 'boolean' }; + case 'multipleSelects': + return { + ...baseField, + path: `$.fields["${ field.name }"][*]`, + type: 'string_array', + }; + + case 'multipleRecordLinks': + return { + ...baseField, + path: `$.fields["${ field.name }"][*].id`, + type: 'string_array', + }; + case 'multipleAttachments': return { + ...baseField, path: `$.fields["${ field.name }"][0].url`, - name: `${ field.name } URL`, - key: `${ field.name }_url`, type: 'image_url', }; - case 'singleCollaborator': case 'multipleCollaborator': return { - path: `$.fields["${ field.name }"].name`, - name: `${ field.name } Name`, - key: `${ field.name }_name`, - type: 'string', + ...baseField, + path: `$.fields["${ field.name }"][*].name`, + type: 'string_array', }; case 'formula': - case 'rollup': case 'lookup': if ( field.options?.result?.type ) { return getAirtableOutputQueryMappingValue( { From 7c056b0d988deabca0dd810bbc297eb0ca4a7b0a Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Sat, 7 Dec 2024 02:53:43 +0530 Subject: [PATCH 7/8] lint fixes --- inc/Integrations/Airtable/AirtableDataSource.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/inc/Integrations/Airtable/AirtableDataSource.php b/inc/Integrations/Airtable/AirtableDataSource.php index 5ef91b44..59e0ae3e 100644 --- a/inc/Integrations/Airtable/AirtableDataSource.php +++ b/inc/Integrations/Airtable/AirtableDataSource.php @@ -45,7 +45,10 @@ class AirtableDataSource extends HttpDataSource { 'type' => 'object', 'properties' => [ 'key' => [ 'type' => 'string' ], - 'name' => [ 'type' => 'string', 'required' => false ], + 'name' => [ + 'type' => 'string', + 'required' => false, + ], 'type' => [ 'type' => 'string', 'required' => false, @@ -137,7 +140,7 @@ public function ___temp_get_query(): AirtableGetItemQuery|\WP_Error { 'type' => $mapping['type'] ?? 'string', ]; - if ( $mapping['type'] === 'currency' && isset( $mapping['prefix'] ) ) { + if ( 'currency' === $mapping['type'] && isset( $mapping['prefix'] ) ) { $output_schema['mappings'][ $mapping_key ]['prefix'] = $mapping['prefix']; } } From aa6b5e3afedc494df69f33b0b01be21680306c45 Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Tue, 10 Dec 2024 15:16:06 +0530 Subject: [PATCH 8/8] remove 'string_array' type in favour of 'string' type --- docs/extending/query.md | 1 - inc/Config/QueryRunner/QueryRunner.php | 10 +++++++--- inc/Editor/BlockPatterns/BlockPatterns.php | 1 - src/blocks/remote-data-container/config/constants.ts | 2 +- src/data-sources/airtable/utils.ts | 6 +++--- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/extending/query.md b/docs/extending/query.md index 00124c88..c55b07b7 100644 --- a/docs/extending/query.md +++ b/docs/extending/query.md @@ -76,7 +76,6 @@ The `get_input_schema` method defines the input data expected by the query. The - `number` - `currency` - `string` - - `string_array` #### Example diff --git a/inc/Config/QueryRunner/QueryRunner.php b/inc/Config/QueryRunner/QueryRunner.php index 1ce160ed..b868cedf 100644 --- a/inc/Config/QueryRunner/QueryRunner.php +++ b/inc/Config/QueryRunner/QueryRunner.php @@ -258,10 +258,14 @@ protected function get_field_value( array|string $field_value, array $mapping ): $currency_symbol = $mapping['prefix'] ?? '$'; return sprintf( '%s%s', $currency_symbol, number_format( (float) $field_value_single, 2 ) ); - case 'string_array': - return implode( ', ', $field_value ); - case 'string': + if ( is_array( $field_value_single ) ) { + // Ensure all elements are strings and filter out non-string values + $string_values = array_filter( $field_value_single, '\is_string' ); + if ( ! empty( $string_values ) ) { + return wp_strip_all_tags( implode( ', ', $string_values ) ); + } + } return wp_strip_all_tags( $field_value_single ); } diff --git a/inc/Editor/BlockPatterns/BlockPatterns.php b/inc/Editor/BlockPatterns/BlockPatterns.php index c536f64f..e2160aec 100644 --- a/inc/Editor/BlockPatterns/BlockPatterns.php +++ b/inc/Editor/BlockPatterns/BlockPatterns.php @@ -108,7 +108,6 @@ public static function register_default_block_pattern( string $block_name, strin ]; break; - case 'string_array': case 'base64': case 'currency': $bindings['paragraphs'][] = [ diff --git a/src/blocks/remote-data-container/config/constants.ts b/src/blocks/remote-data-container/config/constants.ts index 86a0a445..64441c8b 100644 --- a/src/blocks/remote-data-container/config/constants.ts +++ b/src/blocks/remote-data-container/config/constants.ts @@ -15,5 +15,5 @@ export const REMOTE_DATA_REST_API_URL = getRestUrl(); export const CONTAINER_CLASS_NAME = getClassName( 'container' ); export const IMAGE_FIELD_TYPES = [ 'image_alt', 'image_url' ]; -export const TEXT_FIELD_TYPES = [ 'number', 'base64', 'currency', 'string', 'string_array' ]; +export const TEXT_FIELD_TYPES = [ 'number', 'base64', 'currency', 'string' ]; export const BUTTON_FIELD_TYPES = [ 'button_url' ]; diff --git a/src/data-sources/airtable/utils.ts b/src/data-sources/airtable/utils.ts index 2d5fd04f..f36b5663 100644 --- a/src/data-sources/airtable/utils.ts +++ b/src/data-sources/airtable/utils.ts @@ -46,14 +46,14 @@ export const getAirtableOutputQueryMappingValue = ( return { ...baseField, path: `$.fields["${ field.name }"][*]`, - type: 'string_array', + type: 'string', }; case 'multipleRecordLinks': return { ...baseField, path: `$.fields["${ field.name }"][*].id`, - type: 'string_array', + type: 'string', }; case 'multipleAttachments': @@ -67,7 +67,7 @@ export const getAirtableOutputQueryMappingValue = ( return { ...baseField, path: `$.fields["${ field.name }"][*].name`, - type: 'string_array', + type: 'string', }; case 'formula':