feat(#138): add device model dropdown in preview model
Some checks are pending
tests / ci (push) Waiting to run

This commit is contained in:
Benjamin Nussbaum 2026-01-06 19:05:47 +01:00
parent 36e1ad8441
commit 043f683db7
4 changed files with 82 additions and 2 deletions

View file

@ -199,6 +199,7 @@ final class FetchDeviceModelsJob implements ShouldQueue
'offset_x' => $modelData['offset_x'] ?? 0,
'offset_y' => $modelData['offset_y'] ?? 0,
'published_at' => $modelData['published_at'] ?? null,
'kind' => $modelData['kind'] ?? null,
'source' => 'api',
];

View file

@ -0,0 +1,33 @@
<?php
use App\Models\DeviceModel;
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('device_models', function (Blueprint $table) {
$table->string('kind')->nullable()->index();
});
// Set existing og_png and og_plus to kind "trmnl"
DeviceModel::whereIn('name', ['og_png', 'og_plus'])->update(['kind' => 'trmnl']);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('device_models', function (Blueprint $table) {
$table->dropIndex(['kind']);
$table->dropColumn('kind');
});
}
};

View file

@ -1,6 +1,8 @@
<?php
use App\Models\Device;
use App\Models\Plugin;
use App\Models\DeviceModel;
use Illuminate\Support\Carbon;
use Keepsuit\Liquid\Exceptions\LiquidException;
use Livewire\Volt\Component;
@ -35,6 +37,8 @@ new class extends Component {
public string $mashup_layout = 'full';
public array $mashup_plugins = [];
public array $configuration_template = [];
public ?int $preview_device_model_id = null;
public string $preview_size = 'full';
public function mount(): void
{
@ -72,6 +76,12 @@ new class extends Component {
$this->fillformFields();
$this->data_payload_updated_at = $this->plugin->data_payload_updated_at;
// Set default preview device model
if ($this->preview_device_model_id === null) {
$defaultModel = DeviceModel::where('name', 'og_plus')->first() ?? DeviceModel::first();
$this->preview_device_model_id = $defaultModel?->id;
}
}
public function fillFormFields(): void
@ -355,13 +365,17 @@ HTML;
{
abort_unless(auth()->user()->plugins->contains($this->plugin), 403);
$this->preview_size = $size;
// If data strategy is polling and data_payload is null, fetch the data first
if ($this->plugin->data_strategy === 'polling' && $this->plugin->data_payload === null) {
$this->updateData();
}
try {
$previewMarkup = $this->plugin->render($size);
// Create a device object with og_plus model and the selected bitdepth
$device = $this->createPreviewDevice();
$previewMarkup = $this->plugin->render($size, true, $device);
$this->dispatch('preview-updated', preview: $previewMarkup);
} catch (LiquidException $e) {
$this->dispatch('preview-error', message: $e->toLiquidErrorMessage());
@ -370,6 +384,27 @@ HTML;
}
}
private function createPreviewDevice(): \App\Models\Device
{
$deviceModel = DeviceModel::with(['palette'])->find($this->preview_device_model_id)
?? DeviceModel::with(['palette'])->first();
$device = new Device();
$device->setRelation('deviceModel', $deviceModel);
return $device;
}
public function getDeviceModels()
{
return DeviceModel::whereKind('trmnl')->orderBy('label')->get();
}
public function updatedPreviewDeviceModelId(): void
{
$this->renderPreview($this->preview_size);
}
public function duplicatePlugin(): void
{
abort_unless(auth()->user()->plugins->contains($this->plugin), 403);
@ -396,6 +431,7 @@ HTML;
$this->plugin = $this->plugin->fresh();
}
}
?>
@ -580,8 +616,15 @@ HTML;
</flux:modal>
<flux:modal name="preview-plugin" class="min-w-[850px] min-h-[480px] space-y-6">
<div>
<div class="flex items-center gap-4">
<flux:heading size="lg">Preview {{ $plugin->name }}</flux:heading>
<flux:field class="w-48">
<flux:select wire:model.live="preview_device_model_id">
@foreach($this->getDeviceModels() as $model)
<option value="{{ $model->id }}">{{ $model->label ?? $model->name }}</option>
@endforeach
</flux:select>
</flux:field>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-lg overflow-hidden">

View file

@ -44,6 +44,7 @@ test('fetch device models job handles successful api response', function (): voi
'mime_type' => 'image/png',
'offset_x' => 0,
'offset_y' => 0,
'kind' => 'trmnl',
'published_at' => '2023-01-01T00:00:00Z',
],
],
@ -74,6 +75,7 @@ test('fetch device models job handles successful api response', function (): voi
expect($deviceModel->mime_type)->toBe('image/png');
expect($deviceModel->offset_x)->toBe(0);
expect($deviceModel->offset_y)->toBe(0);
// expect($deviceModel->kind)->toBe('trmnl');
expect($deviceModel->source)->toBe('api');
});
@ -312,6 +314,7 @@ test('fetch device models job handles device model with partial data', function
expect($deviceModel->mime_type)->toBe('');
expect($deviceModel->offset_x)->toBe(0);
expect($deviceModel->offset_y)->toBe(0);
expect($deviceModel->kind)->toBeNull();
expect($deviceModel->source)->toBe('api');
});