mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-13 23:18:10 +00:00
Compare commits
6 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7f6237265 | ||
|
|
c2c553461f | ||
|
|
fceacfe4b3 | ||
|
|
3032c09778 | ||
|
|
f1903bcbe8 | ||
|
|
621c108e78 |
7 changed files with 26 additions and 30 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Plugin;
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
return new class extends Migration
|
return new class extends Migration
|
||||||
|
|
@ -13,16 +13,16 @@ return new class extends Migration
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
// Find and handle duplicate (user_id, trmnlp_id) combinations
|
// Find and handle duplicate (user_id, trmnlp_id) combinations
|
||||||
$duplicates = DB::table('plugins')
|
$duplicates = Plugin::query()
|
||||||
->select('user_id', 'trmnlp_id', DB::raw('COUNT(*) as count'))
|
->selectRaw('user_id, trmnlp_id, COUNT(*) as duplicate_count')
|
||||||
->whereNotNull('trmnlp_id')
|
->whereNotNull('trmnlp_id')
|
||||||
->groupBy('user_id', 'trmnlp_id')
|
->groupBy('user_id', 'trmnlp_id')
|
||||||
->having('count', '>', 1)
|
->havingRaw('COUNT(*) > ?', [1])
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
// For each duplicate combination, keep the first one (by id) and set others to null
|
// For each duplicate combination, keep the first one (by id) and set others to null
|
||||||
foreach ($duplicates as $duplicate) {
|
foreach ($duplicates as $duplicate) {
|
||||||
$plugins = DB::table('plugins')
|
$plugins = Plugin::query()
|
||||||
->where('user_id', $duplicate->user_id)
|
->where('user_id', $duplicate->user_id)
|
||||||
->where('trmnlp_id', $duplicate->trmnlp_id)
|
->where('trmnlp_id', $duplicate->trmnlp_id)
|
||||||
->orderBy('id')
|
->orderBy('id')
|
||||||
|
|
@ -37,9 +37,7 @@ return new class extends Migration
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DB::table('plugins')
|
$plugin->update(['trmnlp_id' => null]);
|
||||||
->where('id', $plugin->id)
|
|
||||||
->update(['trmnlp_id' => null]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ class ExampleRecipesSeeder extends Seeder
|
||||||
public function run($user_id = 1): void
|
public function run($user_id = 1): void
|
||||||
{
|
{
|
||||||
Plugin::updateOrCreate(
|
Plugin::updateOrCreate(
|
||||||
|
['uuid' => '9e46c6cf-358c-4bfe-8998-436b3a207fec'],
|
||||||
[
|
[
|
||||||
'uuid' => '9e46c6cf-358c-4bfe-8998-436b3a207fec',
|
|
||||||
'name' => 'ÖBB Departures',
|
'name' => 'ÖBB Departures',
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
'data_payload' => null,
|
'data_payload' => null,
|
||||||
|
|
@ -32,8 +32,8 @@ class ExampleRecipesSeeder extends Seeder
|
||||||
);
|
);
|
||||||
|
|
||||||
Plugin::updateOrCreate(
|
Plugin::updateOrCreate(
|
||||||
|
['uuid' => '3b046eda-34e9-4232-b935-c33b989a284b'],
|
||||||
[
|
[
|
||||||
'uuid' => '3b046eda-34e9-4232-b935-c33b989a284b',
|
|
||||||
'name' => 'Weather',
|
'name' => 'Weather',
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
'data_payload' => null,
|
'data_payload' => null,
|
||||||
|
|
@ -51,8 +51,8 @@ class ExampleRecipesSeeder extends Seeder
|
||||||
);
|
);
|
||||||
|
|
||||||
Plugin::updateOrCreate(
|
Plugin::updateOrCreate(
|
||||||
|
['uuid' => '21464b16-5f5a-4099-a967-f5c915e3da54'],
|
||||||
[
|
[
|
||||||
'uuid' => '21464b16-5f5a-4099-a967-f5c915e3da54',
|
|
||||||
'name' => 'Zen Quotes',
|
'name' => 'Zen Quotes',
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
'data_payload' => null,
|
'data_payload' => null,
|
||||||
|
|
@ -70,8 +70,8 @@ class ExampleRecipesSeeder extends Seeder
|
||||||
);
|
);
|
||||||
|
|
||||||
Plugin::updateOrCreate(
|
Plugin::updateOrCreate(
|
||||||
|
['uuid' => '8d472959-400f-46ee-afb2-4a9f1cfd521f'],
|
||||||
[
|
[
|
||||||
'uuid' => '8d472959-400f-46ee-afb2-4a9f1cfd521f',
|
|
||||||
'name' => 'This Day in History',
|
'name' => 'This Day in History',
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
'data_payload' => null,
|
'data_payload' => null,
|
||||||
|
|
@ -89,8 +89,8 @@ class ExampleRecipesSeeder extends Seeder
|
||||||
);
|
);
|
||||||
|
|
||||||
Plugin::updateOrCreate(
|
Plugin::updateOrCreate(
|
||||||
|
['uuid' => '4349fdad-a273-450b-aa00-3d32f2de788d'],
|
||||||
[
|
[
|
||||||
'uuid' => '4349fdad-a273-450b-aa00-3d32f2de788d',
|
|
||||||
'name' => 'Home Assistant',
|
'name' => 'Home Assistant',
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
'data_payload' => null,
|
'data_payload' => null,
|
||||||
|
|
@ -108,8 +108,8 @@ class ExampleRecipesSeeder extends Seeder
|
||||||
);
|
);
|
||||||
|
|
||||||
Plugin::updateOrCreate(
|
Plugin::updateOrCreate(
|
||||||
|
['uuid' => 'be5f7e1f-3ad8-4d66-93b2-36f7d6dcbd80'],
|
||||||
[
|
[
|
||||||
'uuid' => 'be5f7e1f-3ad8-4d66-93b2-36f7d6dcbd80',
|
|
||||||
'name' => 'Sunrise/Sunset',
|
'name' => 'Sunrise/Sunset',
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
'data_payload' => null,
|
'data_payload' => null,
|
||||||
|
|
@ -127,8 +127,8 @@ class ExampleRecipesSeeder extends Seeder
|
||||||
);
|
);
|
||||||
|
|
||||||
Plugin::updateOrCreate(
|
Plugin::updateOrCreate(
|
||||||
|
['uuid' => '82d3ee14-d578-4969-bda5-2bbf825435fe'],
|
||||||
[
|
[
|
||||||
'uuid' => '82d3ee14-d578-4969-bda5-2bbf825435fe',
|
|
||||||
'name' => 'Pollen Forecast',
|
'name' => 'Pollen Forecast',
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
'data_payload' => null,
|
'data_payload' => null,
|
||||||
|
|
@ -146,8 +146,8 @@ class ExampleRecipesSeeder extends Seeder
|
||||||
);
|
);
|
||||||
|
|
||||||
Plugin::updateOrCreate(
|
Plugin::updateOrCreate(
|
||||||
|
['uuid' => '1d98bca4-837d-4b01-b1a1-e3b6e56eca90'],
|
||||||
[
|
[
|
||||||
'uuid' => '1d98bca4-837d-4b01-b1a1-e3b6e56eca90',
|
|
||||||
'name' => 'Holidays (iCal)',
|
'name' => 'Holidays (iCal)',
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
'data_payload' => null,
|
'data_payload' => null,
|
||||||
|
|
|
||||||
|
|
@ -803,7 +803,7 @@ HTML;
|
||||||
</flux:field>
|
</flux:field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<flux:button variant="primary" icon="cloud-arrow-down" wire:click="updateData" class="w-full mt-4">
|
<flux:button icon="cloud-arrow-down" wire:click="updateData" class="w-full mt-4">
|
||||||
Fetch data now
|
Fetch data now
|
||||||
</flux:button>
|
</flux:button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -950,7 +950,7 @@ HTML;
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
x-data="codeEditorFormComponent({
|
x-data="codeEditorFormComponent({
|
||||||
isDisabled: false,
|
isDisabled: @js((bool)$plugin->render_markup_view),
|
||||||
language: 'liquid',
|
language: 'liquid',
|
||||||
state: $wire.entangle('markup_code'),
|
state: $wire.entangle('markup_code'),
|
||||||
textareaId: @js($textareaId)
|
textareaId: @js($textareaId)
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ new class extends Component {
|
||||||
|
|
||||||
<flux:field>
|
<flux:field>
|
||||||
<flux:checkbox wire:model.live="alias" label="Enable Alias" />
|
<flux:checkbox wire:model.live="alias" label="Enable Alias" />
|
||||||
<flux:description>Enable a public alias URL for this recipe.</flux:description>
|
<flux:description>Enable an Alias URL for this recipe. Your server does not need to be exposed to the internet, but your device must be able to reach the URL. <a href="https://help.usetrmnl.com/en/articles/10701448-alias-plugin">Docs</a></flux:description>
|
||||||
</flux:field>
|
</flux:field>
|
||||||
|
|
||||||
@if($alias)
|
@if($alias)
|
||||||
|
|
@ -87,7 +87,7 @@ new class extends Component {
|
||||||
readonly
|
readonly
|
||||||
copyable
|
copyable
|
||||||
/>
|
/>
|
||||||
<flux:description>Use this URL to access the recipe image directly. Add <code>?device-model=name</code> to specify a device model.</flux:description>
|
<flux:description>Copy this URL to your TRMNL Dashboard. By default, image is created for TRMNL OG; use parameter <code>?device-model=</code> to specify a device model.</flux:description>
|
||||||
</flux:field>
|
</flux:field>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
<x-trmnl::view size="{{ $size }}">
|
<x-trmnl::view size="{{ $size }}">
|
||||||
<x-trmnl::layout>
|
<x-trmnl::layout>
|
||||||
<x-trmnl::layout class="layout--col">
|
<x-trmnl::layout class="layout--col">
|
||||||
<div class="b-h-gray-1">{{$data[0]['a']}}</div>
|
<div class="b-h-gray-1">{{$data['data'][0]['a'] ?? ''}}</div>
|
||||||
@if (strlen($data[0]['q']) < 300 && $size != 'quadrant')
|
@if (strlen($data['data'][0]['q'] ?? '') < 300 && $size != 'quadrant')
|
||||||
<p class="value">{{ $data[0]['q'] }}</p>
|
<p class="value">{{ $data['data'][0]['q'] ?? '' }}</p>
|
||||||
@else
|
@else
|
||||||
<p class="value--small">{{ $data[0]['q'] }}</p>
|
<p class="value--small">{{ $data['data'][0]['q'] ?? '' }}</p>
|
||||||
@endif
|
@endif
|
||||||
</x-trmnl::layout>
|
</x-trmnl::layout>
|
||||||
</x-trmnl::layout>
|
</x-trmnl::layout>
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,13 @@ use Illuminate\Support\Str;
|
||||||
Route::get('/display', function (Request $request) {
|
Route::get('/display', function (Request $request) {
|
||||||
$mac_address = $request->header('id');
|
$mac_address = $request->header('id');
|
||||||
$access_token = $request->header('access-token');
|
$access_token = $request->header('access-token');
|
||||||
$device = Device::where('mac_address', mb_strtoupper($mac_address ?? ''))
|
$device = Device::where('api_key', $access_token)->first();
|
||||||
->where('api_key', $access_token)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
if (! $device) {
|
if (! $device) {
|
||||||
// Check if there's a user with assign_new_devices enabled
|
// Check if there's a user with assign_new_devices enabled
|
||||||
$auto_assign_user = User::where('assign_new_devices', true)->first();
|
$auto_assign_user = User::where('assign_new_devices', true)->first();
|
||||||
|
|
||||||
if ($auto_assign_user) {
|
if ($auto_assign_user && $mac_address) {
|
||||||
// Create a new device and assign it to this user
|
// Create a new device and assign it to this user
|
||||||
$device = Device::create([
|
$device = Device::create([
|
||||||
'mac_address' => mb_strtoupper($mac_address ?? ''),
|
'mac_address' => mb_strtoupper($mac_address ?? ''),
|
||||||
|
|
@ -39,7 +37,7 @@ Route::get('/display', function (Request $request) {
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'MAC Address not registered or invalid access token',
|
'message' => 'MAC Address not registered (or not set), or invalid access token',
|
||||||
], 404);
|
], 404);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ test('invalid device credentials return error', function (): void {
|
||||||
])->get('/api/display');
|
])->get('/api/display');
|
||||||
|
|
||||||
$response->assertNotFound()
|
$response->assertNotFound()
|
||||||
->assertJson(['message' => 'MAC Address not registered or invalid access token']);
|
->assertJson(['message' => 'MAC Address not registered (or not set), or invalid access token']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('log endpoint requires valid device credentials', function (): void {
|
test('log endpoint requires valid device credentials', function (): void {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue