mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-14 15:37:53 +00:00
feat(#46): added support for request body in recipes
This commit is contained in:
parent
3673654df6
commit
9929e810d9
7 changed files with 130 additions and 19 deletions
|
|
@ -56,9 +56,19 @@ class Plugin extends Model
|
|||
}
|
||||
}
|
||||
|
||||
$response = Http::withHeaders($headers)
|
||||
->get($this->polling_url)
|
||||
->json();
|
||||
$httpRequest = Http::withHeaders($headers);
|
||||
|
||||
// Add body for POST requests if polling_body is provided
|
||||
if ($this->polling_verb === 'post' && $this->polling_body) {
|
||||
$httpRequest = $httpRequest->withBody($this->polling_body);
|
||||
}
|
||||
|
||||
// Make the request based on the verb
|
||||
if ($this->polling_verb === 'post') {
|
||||
$response = $httpRequest->post($this->polling_url)->json();
|
||||
} else {
|
||||
$response = $httpRequest->get($this->polling_url)->json();
|
||||
}
|
||||
|
||||
$this->update([
|
||||
'data_payload' => $response,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ class PluginFactory extends Factory
|
|||
'polling_url' => $this->faker->url(),
|
||||
'polling_verb' => $this->faker->randomElement(['get', 'post']),
|
||||
'polling_header' => null,
|
||||
'polling_body' => null,
|
||||
'render_markup' => null,
|
||||
'render_markup_view' => null,
|
||||
'detail_view_route' => null,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ return new class extends Migration
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table("plugins", function (Blueprint $table) {
|
||||
Schema::table('plugins', function (Blueprint $table) {
|
||||
$table->string('polling_url', 1024)->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ return new class extends Migration
|
|||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table("plugins", function (Blueprint $table) {
|
||||
Schema::table('plugins', function (Blueprint $table) {
|
||||
// old default string length value in Illuminate
|
||||
$table->string('polling_url', 255)->nullable()->change();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('plugins', function (Blueprint $table) {
|
||||
$table->text('polling_body')->nullable()->after('polling_header');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('plugins', function (Blueprint $table) {
|
||||
$table->dropColumn('polling_body');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -10,6 +10,7 @@ new class extends Component {
|
|||
public string $polling_url;
|
||||
public string $polling_verb = "get";
|
||||
public $polling_header;
|
||||
public $polling_body;
|
||||
public array $plugins;
|
||||
|
||||
public array $native_plugins = [
|
||||
|
|
@ -26,6 +27,7 @@ new class extends Component {
|
|||
'polling_url' => 'required_if:data_strategy,polling|nullable|url',
|
||||
'polling_verb' => 'required|string|in:get,post',
|
||||
'polling_header' => 'nullable|string|max:255',
|
||||
'polling_body' => 'nullable|string',
|
||||
];
|
||||
|
||||
private function refreshPlugins(): void
|
||||
|
|
@ -56,9 +58,10 @@ new class extends Component {
|
|||
'polling_url' => $this->polling_url ?? null,
|
||||
'polling_verb' => $this->polling_verb,
|
||||
'polling_header' => $this->polling_header,
|
||||
'polling_body' => $this->polling_body,
|
||||
]);
|
||||
|
||||
$this->reset(['name', 'data_stale_minutes', 'data_strategy', 'polling_url', 'polling_verb', 'polling_header']);
|
||||
$this->reset(['name', 'data_stale_minutes', 'data_strategy', 'polling_url', 'polling_verb', 'polling_header', 'polling_body']);
|
||||
$this->refreshPlugins();
|
||||
|
||||
Flux::modal('add-plugin')->close();
|
||||
|
|
@ -131,7 +134,7 @@ new class extends Component {
|
|||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<flux:radio.group wire:model="polling_verb" label="Polling Verb" variant="segmented">
|
||||
<flux:radio.group wire:model.live="polling_verb" label="Polling Verb" variant="segmented">
|
||||
<flux:radio value="get" label="GET"/>
|
||||
<flux:radio value="post" label="POST"/>
|
||||
</flux:radio.group>
|
||||
|
|
@ -141,6 +144,20 @@ new class extends Component {
|
|||
<flux:input label="Polling Header" wire:model="polling_header" id="polling_header"
|
||||
class="block mt-1 w-full" type="text" name="polling_header" autofocus/>
|
||||
</div>
|
||||
|
||||
@if($polling_verb === 'post')
|
||||
<div class="mb-4">
|
||||
<flux:textarea
|
||||
label="Polling Body"
|
||||
wire:model="polling_body"
|
||||
id="polling_body"
|
||||
class="block mt-1 w-full font-mono"
|
||||
name="polling_body"
|
||||
rows="4"
|
||||
placeholder=''
|
||||
/>
|
||||
</div>
|
||||
@endif
|
||||
<div class="mb-4">
|
||||
<flux:input label="Data is stale after minutes" wire:model.live="data_stale_minutes"
|
||||
id="data_stale_minutes"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ new class extends Component {
|
|||
public string|null $polling_url;
|
||||
public string $polling_verb;
|
||||
public string|null $polling_header;
|
||||
public string|null $polling_body;
|
||||
public $data_payload;
|
||||
public ?Carbon $data_payload_updated_at;
|
||||
public array $checked_devices = [];
|
||||
|
|
@ -64,6 +65,7 @@ new class extends Component {
|
|||
$this->polling_url = $this->plugin->polling_url;
|
||||
$this->polling_verb = $this->plugin->polling_verb;
|
||||
$this->polling_header = $this->plugin->polling_header;
|
||||
$this->polling_body = $this->plugin->polling_body;
|
||||
$this->data_payload = json_encode($this->plugin->data_payload, JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +83,7 @@ new class extends Component {
|
|||
'polling_url' => 'required_if:data_strategy,polling|nullable|url',
|
||||
'polling_verb' => 'required|string|in:get,post',
|
||||
'polling_header' => 'nullable|string|max:255',
|
||||
'polling_body' => 'nullable|string',
|
||||
'data_payload' => 'required_if:data_strategy,static|nullable|json',
|
||||
'blade_code' => 'nullable|string',
|
||||
'checked_devices' => 'array',
|
||||
|
|
@ -95,11 +98,7 @@ new class extends Component {
|
|||
{
|
||||
abort_unless(auth()->user()->plugins->contains($this->plugin), 403);
|
||||
$validated = $this->validate();
|
||||
|
||||
// If static strategy is selected, parse and save the JSON data
|
||||
if ($this->data_strategy === 'static' && isset($validated['data_payload'])) {
|
||||
$validated['data_payload'] = json_decode($validated['data_payload'], true);
|
||||
}
|
||||
|
||||
$this->plugin->update($validated);
|
||||
}
|
||||
|
|
@ -120,9 +119,20 @@ new class extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
$response = Http::withHeaders($headers)
|
||||
->get($this->plugin->polling_url)
|
||||
->json();
|
||||
// Prepare the HTTP request
|
||||
$httpRequest = Http::withHeaders($headers);
|
||||
|
||||
// Add body for POST requests if polling_body is provided
|
||||
if ($this->plugin->polling_verb === 'post' && $this->plugin->polling_body) {
|
||||
$httpRequest = $httpRequest->withBody($this->plugin->polling_body, 'application/json');
|
||||
}
|
||||
|
||||
// Make the request based on the verb
|
||||
if ($this->plugin->polling_verb === 'post') {
|
||||
$response = $httpRequest->post($this->plugin->polling_url)->json();
|
||||
} else {
|
||||
$response = $httpRequest->get($this->plugin->polling_url)->json();
|
||||
}
|
||||
|
||||
$this->plugin->update([
|
||||
'data_payload' => $response,
|
||||
|
|
@ -480,7 +490,7 @@ HTML;
|
|||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<flux:radio.group wire:model="polling_verb" label="Polling Verb" variant="segmented">
|
||||
<flux:radio.group wire:model.live="polling_verb" label="Polling Verb" variant="segmented">
|
||||
<flux:radio value="get" label="GET"/>
|
||||
<flux:radio value="post" label="POST"/>
|
||||
</flux:radio.group>
|
||||
|
|
@ -497,6 +507,19 @@ HTML;
|
|||
placeholder="Authorization: Bearer ey.******* Content-Type: application/json"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@if($polling_verb === 'post')
|
||||
<div class="mb-4">
|
||||
<flux:textarea
|
||||
label="Polling Body (e.g. for GraphQL queries)"
|
||||
wire:model="polling_body"
|
||||
id="polling_body"
|
||||
class="block mt-1 w-full font-mono"
|
||||
name="polling_body"
|
||||
rows="6"
|
||||
/>
|
||||
</div>
|
||||
@endif
|
||||
<div class="mb-4">
|
||||
<flux:input label="Data is stale after minutes" wire:model="data_stale_minutes"
|
||||
id="data_stale_minutes"
|
||||
|
|
@ -534,13 +557,14 @@ HTML;
|
|||
@isset($this->data_payload_updated_at)
|
||||
<flux:badge icon="clock" size="sm" variant="pill" class="ml-2">{{ $this->data_payload_updated_at?->diffForHumans() ?? 'Never' }}</flux:badge>
|
||||
@endisset
|
||||
<flux:error name="data_payload"/>
|
||||
<flux:textarea wire:model="data_payload" id="data_payload"
|
||||
class="block mt-1 w-full font-mono" type="text" name="data_payload"
|
||||
:readonly="$data_strategy !== 'static'" rows="24"/>
|
||||
</div>
|
||||
</div>
|
||||
<flux:separator/>
|
||||
<div class="mt-5 mb-5 ">
|
||||
<flux:separator class="my-5"/>
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold dark:text-gray-100">Markup</h3>
|
||||
@if($plugin->render_markup_view)
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Plugin;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
uses(Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
|
|
@ -40,3 +41,33 @@ test('plugin data_payload is cast to array', function () {
|
|||
->toBeArray()
|
||||
->toBe($data);
|
||||
});
|
||||
|
||||
test('plugin can have polling body for POST requests', function () {
|
||||
$plugin = Plugin::factory()->create([
|
||||
'polling_verb' => 'post',
|
||||
'polling_body' => '{"query": "query { user { id name } }"}',
|
||||
]);
|
||||
|
||||
expect($plugin->polling_body)->toBe('{"query": "query { user { id name } }"}');
|
||||
});
|
||||
|
||||
test('updateDataPayload sends POST request with body when polling_verb is post', function () {
|
||||
Http::fake([
|
||||
'https://example.com/api' => Http::response(['success' => true], 200),
|
||||
]);
|
||||
|
||||
$plugin = Plugin::factory()->create([
|
||||
'data_strategy' => 'polling',
|
||||
'polling_url' => 'https://example.com/api',
|
||||
'polling_verb' => 'post',
|
||||
'polling_body' => '{"query": "query { user { id name } }"}',
|
||||
]);
|
||||
|
||||
$plugin->updateDataPayload();
|
||||
|
||||
Http::assertSent(function ($request) {
|
||||
return $request->url() === 'https://example.com/api' &&
|
||||
$request->method() === 'POST' &&
|
||||
$request->body() === '{"query": "query { user { id name } }"}';
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue