diff --git a/resources/views/livewire/plugins/recipe.blade.php b/resources/views/livewire/plugins/recipe.blade.php index 0edee8a..7a73358 100644 --- a/resources/views/livewire/plugins/recipe.blade.php +++ b/resources/views/livewire/plugins/recipe.blade.php @@ -6,6 +6,7 @@ use Keepsuit\Liquid\Exceptions\LiquidException; use Livewire\Volt\Component; use Illuminate\Support\Facades\Blade; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Http; new class extends Component { public Plugin $plugin; @@ -32,6 +33,8 @@ new class extends Component { public array $mashup_plugins = []; public array $configuration_template = []; public array $configuration = []; + public array $xhrSelectOptions = []; + public array $searchQueries = []; public function mount(): void { @@ -345,6 +348,41 @@ HTML; $this->plugin->delete(); $this->redirect(route('plugins.index')); } + + public function loadXhrSelectOptions(string $fieldKey, string $endpoint, ?string $query = null): void + { + abort_unless(auth()->user()->plugins->contains($this->plugin), 403); + + try { + $requestData = []; + if ($query !== null) { + $requestData = [ + 'function' => $fieldKey, + 'query' => $query + ]; + } + + $response = $query !== null + ? Http::post($endpoint, $requestData) + : Http::post($endpoint); + + if ($response->successful()) { + $this->xhrSelectOptions[$fieldKey] = $response->json(); + } else { + $this->xhrSelectOptions[$fieldKey] = []; + } + } catch (\Exception $e) { + $this->xhrSelectOptions[$fieldKey] = []; + } + } + + public function searchXhrSelect(string $fieldKey, string $endpoint): void + { + $query = $this->searchQueries[$fieldKey] ?? ''; + if (!empty($query)) { + $this->loadXhrSelectOptions($fieldKey, $endpoint, $query); + } + } } ?> @@ -644,6 +682,76 @@ HTML; @endif @endif + @elseif($field['field_type'] === 'xhrSelect') + + + @if(isset($xhrSelectOptions[$fieldKey]) && is_array($xhrSelectOptions[$fieldKey])) + @foreach($xhrSelectOptions[$fieldKey] as $option) + @if(is_array($option)) + @if(isset($option['id']) && isset($option['name'])) + {{-- xhrSelectSearch format: { 'id' => 'db-456', 'name' => 'Team Goals' } --}} + + @else + {{-- xhrSelect format: { 'Braves' => 123 } --}} + @foreach($option as $label => $value) + + @endforeach + @endif + @else + + @endif + @endforeach + @endif + + @elseif($field['field_type'] === 'xhrSelectSearch') +
+ + {{ $field['name'] }} + {{ $field['description'] ?? '' }} + + + + + + @if((isset($xhrSelectOptions[$fieldKey]) && is_array($xhrSelectOptions[$fieldKey]) && count($xhrSelectOptions[$fieldKey]) > 0) || !empty($currentValue)) + + + @if(isset($xhrSelectOptions[$fieldKey]) && is_array($xhrSelectOptions[$fieldKey])) + @foreach($xhrSelectOptions[$fieldKey] as $option) + @if(is_array($option)) + @if(isset($option['id']) && isset($option['name'])) + {{-- xhrSelectSearch format: { 'id' => 'db-456', 'name' => 'Team Goals' } --}} + + @else + {{-- xhrSelect format: { 'Braves' => 123 } --}} + @foreach($option as $label => $value) + + @endforeach + @endif + @else + + @endif + @endforeach + @endif + @if(!empty($currentValue) && (!isset($xhrSelectOptions[$fieldKey]) || empty($xhrSelectOptions[$fieldKey]))) + {{-- Show current value even if no options are loaded --}} + + @endif + + @endif +
@else

{{ $field['name'] }}: Field type "{{ $field['field_type'] }}" not yet supported

@endif diff --git a/tests/Feature/PluginRequiredConfigurationTest.php b/tests/Feature/PluginRequiredConfigurationTest.php index 9d378ba..552b996 100644 --- a/tests/Feature/PluginRequiredConfigurationTest.php +++ b/tests/Feature/PluginRequiredConfigurationTest.php @@ -23,17 +23,17 @@ test('hasMissingRequiredConfigurationFields returns true when required field is 'field_type' => 'time_zone', 'name' => 'Timezone', 'description' => 'Select your timezone', - 'optional' => true // Marked as optional - ] - ] + 'optional' => true, // Marked as optional + ], + ], ]; $plugin = Plugin::factory()->create([ 'user_id' => $user->id, 'configuration_template' => $configurationTemplate, 'configuration' => [ - 'timezone' => 'UTC' // Only timezone is set, api_key is missing - ] + 'timezone' => 'UTC', // Only timezone is set, api_key is missing + ], ]); expect($plugin->hasMissingRequiredConfigurationFields())->toBeTrue(); @@ -56,9 +56,9 @@ test('hasMissingRequiredConfigurationFields returns false when all required fiel 'field_type' => 'time_zone', 'name' => 'Timezone', 'description' => 'Select your timezone', - 'optional' => true // Marked as optional - ] - ] + 'optional' => true, // Marked as optional + ], + ], ]; $plugin = Plugin::factory()->create([ @@ -66,8 +66,8 @@ test('hasMissingRequiredConfigurationFields returns false when all required fiel 'configuration_template' => $configurationTemplate, 'configuration' => [ 'api_key' => 'test-api-key', // Required field is set - 'timezone' => 'UTC' - ] + 'timezone' => 'UTC', + ], ]); expect($plugin->hasMissingRequiredConfigurationFields())->toBeFalse(); @@ -79,7 +79,7 @@ test('hasMissingRequiredConfigurationFields returns false when no custom fields $plugin = Plugin::factory()->create([ 'user_id' => $user->id, 'configuration_template' => [], - 'configuration' => [] + 'configuration' => [], ]); expect($plugin->hasMissingRequiredConfigurationFields())->toBeFalse(); @@ -96,16 +96,16 @@ test('hasMissingRequiredConfigurationFields returns true when explicitly require 'name' => 'API Key', 'description' => 'Your API key', // Not marked as optional, so it's required - ] - ] + ], + ], ]; $plugin = Plugin::factory()->create([ 'user_id' => $user->id, 'configuration_template' => $configurationTemplate, 'configuration' => [ - 'api_key' => null // Explicitly set to null - ] + 'api_key' => null, // Explicitly set to null + ], ]); expect($plugin->hasMissingRequiredConfigurationFields())->toBeTrue(); @@ -122,16 +122,16 @@ test('hasMissingRequiredConfigurationFields returns true when required field is 'name' => 'API Key', 'description' => 'Your API key', // Not marked as optional, so it's required - ] - ] + ], + ], ]; $plugin = Plugin::factory()->create([ 'user_id' => $user->id, 'configuration_template' => $configurationTemplate, 'configuration' => [ - 'api_key' => '' // Empty string - ] + 'api_key' => '', // Empty string + ], ]); expect($plugin->hasMissingRequiredConfigurationFields())->toBeTrue(); @@ -149,16 +149,16 @@ test('hasMissingRequiredConfigurationFields returns true when required array fie 'description' => 'Select items', 'multiple' => true, // Not marked as optional, so it's required - ] - ] + ], + ], ]; $plugin = Plugin::factory()->create([ 'user_id' => $user->id, 'configuration_template' => $configurationTemplate, 'configuration' => [ - 'selected_items' => [] // Empty array - ] + 'selected_items' => [], // Empty array + ], ]); expect($plugin->hasMissingRequiredConfigurationFields())->toBeTrue(); @@ -178,16 +178,16 @@ test('hasMissingRequiredConfigurationFields returns false when author_bio field 'keyname' => 'plugin_field', 'name' => 'Field Name', 'field_type' => 'string', - ] - ] + ], + ], ]; $plugin = Plugin::factory()->create([ 'user_id' => $user->id, 'configuration_template' => $configurationTemplate, 'configuration' => [ - 'plugin_field' => 'set' // Required field is set - ] + 'plugin_field' => 'set', // Required field is set + ], ]); expect($plugin->hasMissingRequiredConfigurationFields())->toBeFalse(); @@ -203,15 +203,67 @@ test('hasMissingRequiredConfigurationFields returns false when field has default 'field_type' => 'string', 'name' => 'API Key', 'description' => 'Your API key', - 'default' => 'default-api-key' // Has default value - ] - ] + 'default' => 'default-api-key', // Has default value + ], + ], ]; $plugin = Plugin::factory()->create([ 'user_id' => $user->id, 'configuration_template' => $configurationTemplate, - 'configuration' => [] // Empty configuration, but field has default + 'configuration' => [], // Empty configuration, but field has default + ]); + + expect($plugin->hasMissingRequiredConfigurationFields())->toBeFalse(); +}); + +test('hasMissingRequiredConfigurationFields returns true when required xhrSelect field is missing', function () { + $user = User::factory()->create(); + + $configurationTemplate = [ + 'custom_fields' => [ + [ + 'keyname' => 'team', + 'field_type' => 'xhrSelect', + 'name' => 'Baseball Team', + 'description' => 'Select your team', + 'endpoint' => 'https://usetrmnl.com/custom_plugin_example_xhr_select.json', + // Not marked as optional, so it's required + ], + ], + ]; + + $plugin = Plugin::factory()->create([ + 'user_id' => $user->id, + 'configuration_template' => $configurationTemplate, + 'configuration' => [], // Empty configuration + ]); + + expect($plugin->hasMissingRequiredConfigurationFields())->toBeTrue(); +}); + +test('hasMissingRequiredConfigurationFields returns false when required xhrSelect field is set', function () { + $user = User::factory()->create(); + + $configurationTemplate = [ + 'custom_fields' => [ + [ + 'keyname' => 'team', + 'field_type' => 'xhrSelect', + 'name' => 'Baseball Team', + 'description' => 'Select your team', + 'endpoint' => 'https://usetrmnl.com/custom_plugin_example_xhr_select.json', + // Not marked as optional, so it's required + ], + ], + ]; + + $plugin = Plugin::factory()->create([ + 'user_id' => $user->id, + 'configuration_template' => $configurationTemplate, + 'configuration' => [ + 'team' => '123', // Required field is set + ], ]); expect($plugin->hasMissingRequiredConfigurationFields())->toBeFalse();