Web app: new entities (Image, RenderedAsset, SharedImage, Token, DeviceImageHistory), enums, repositories, controllers, message handlers, migrations, tests, frontend upload/library/sticker UI, Vue components. Firmware: EPD background screen binaries + gen scripts, setup_bg header. Infra: ddev config, test bundle, gitignore coverage dir. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Device;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\User;
|
||||
use App\Enum\Orientation;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
@@ -58,8 +59,21 @@ class DeviceApiController extends AbstractController
|
||||
$device->setOrientation($orientation);
|
||||
}
|
||||
|
||||
if (isset($body['rotationIntervalHours'])) {
|
||||
$device->setRotationIntervalHours(max(1, (int) $body['rotationIntervalHours']));
|
||||
if (isset($body['rotationIntervalMinutes'])) {
|
||||
$device->setRotationIntervalMinutes(max(1, (int) $body['rotationIntervalMinutes']));
|
||||
}
|
||||
|
||||
if (array_key_exists('wakeHour', $body)) {
|
||||
$device->setWakeHour($body['wakeHour'] === null ? null : (int) $body['wakeHour']);
|
||||
}
|
||||
|
||||
if (isset($body['timezone'])) {
|
||||
try {
|
||||
new \DateTimeZone((string) $body['timezone']);
|
||||
$device->setTimezone((string) $body['timezone']);
|
||||
} catch (\Exception) {
|
||||
return $this->json(['error' => 'Invalid timezone identifier'], Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($body['uniquenessWindow'])) {
|
||||
@@ -71,16 +85,70 @@ class DeviceApiController extends AbstractController
|
||||
return $this->json($this->serialize($device));
|
||||
}
|
||||
|
||||
#[Route('/{id}/lock', name: 'api_device_lock', methods: ['PUT'])]
|
||||
public function lock(int $id, Request $request, EntityManagerInterface $em): JsonResponse
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
$device = $em->getRepository(Device::class)->findOneBy(['id' => $id, 'user' => $user]);
|
||||
|
||||
if (!$device) {
|
||||
return $this->json(['error' => 'Device not found'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$body = json_decode($request->getContent(), true) ?? [];
|
||||
$imageId = $body['imageId'] ?? null;
|
||||
|
||||
if (!$imageId) {
|
||||
return $this->json(['error' => 'imageId required'], Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
$image = $em->getRepository(Image::class)->find($imageId);
|
||||
if (!$image || $image->getUser() !== $user) {
|
||||
return $this->json(['error' => 'Image not found'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!$image->isApprovedForDevice($device)) {
|
||||
return $this->json(['error' => 'Image is not approved for this device'], Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
$device->setLockedImage($image);
|
||||
$em->flush();
|
||||
|
||||
return $this->json($this->serialize($device));
|
||||
}
|
||||
|
||||
#[Route('/{id}/lock', name: 'api_device_unlock', methods: ['DELETE'])]
|
||||
public function unlock(int $id, EntityManagerInterface $em): JsonResponse
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
$device = $em->getRepository(Device::class)->findOneBy(['id' => $id, 'user' => $user]);
|
||||
|
||||
if (!$device) {
|
||||
return $this->json(['error' => 'Device not found'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$device->setLockedImage(null);
|
||||
$em->flush();
|
||||
|
||||
return $this->json($this->serialize($device));
|
||||
}
|
||||
|
||||
private function serialize(Device $d): array
|
||||
{
|
||||
return [
|
||||
'id' => $d->getId(),
|
||||
'mac' => $d->getMac(),
|
||||
'name' => $d->getName(),
|
||||
'orientation' => $d->getOrientation()->value,
|
||||
'rotationIntervalHours' => $d->getRotationIntervalHours(),
|
||||
'uniquenessWindow' => $d->getUniquenessWindow(),
|
||||
'linkedAt' => $d->getLinkedAt()->format(\DateTimeInterface::ATOM),
|
||||
'id' => $d->getId(),
|
||||
'mac' => $d->getMac(),
|
||||
'name' => $d->getName(),
|
||||
'orientation' => $d->getOrientation()->value,
|
||||
'rotationIntervalMinutes' => $d->getRotationIntervalMinutes(),
|
||||
'wakeHour' => $d->getWakeHour(),
|
||||
'timezone' => $d->getTimezone(),
|
||||
'uniquenessWindow' => $d->getUniquenessWindow(),
|
||||
'linkedAt' => $d->getLinkedAt()->format(\DateTimeInterface::ATOM),
|
||||
'lastSeenAt' => $d->getLastSeenAt()?->format(\DateTimeInterface::ATOM),
|
||||
'lockedImageId' => $d->getLockedImage()?->getId(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user