From a45c8a89f69c5cf046636af49b2f4d809a31fc77 Mon Sep 17 00:00:00 2001 From: Gregor Vostrak Date: Tue, 24 Jun 2025 16:57:12 +0200 Subject: [PATCH] fix datepicker for report create/update, fix public_until update --- .../Controllers/Api/V1/ReportController.php | 2 ++ .../Common/Report/ReportCreateModal.vue | 12 ++++++-- .../Common/Report/ReportEditModal.vue | 17 ++++++++--- .../js/packages/ui/src/Input/DatePicker.vue | 19 +++++++----- .../Endpoint/Api/V1/ReportEndpointTest.php | 29 +++++++++++++++++++ 5 files changed, 66 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/Api/V1/ReportController.php b/app/Http/Controllers/Api/V1/ReportController.php index 46fe7208..5a53fb64 100644 --- a/app/Http/Controllers/Api/V1/ReportController.php +++ b/app/Http/Controllers/Api/V1/ReportController.php @@ -148,6 +148,8 @@ class ReportController extends Controller $report->share_secret = null; $report->public_until = null; } + } elseif ($report->is_public && $request->has('public_until')) { + $report->public_until = $request->getPublicUntil(); } $report->save(); diff --git a/resources/js/Components/Common/Report/ReportCreateModal.vue b/resources/js/Components/Common/Report/ReportCreateModal.vue index 1d4ecd7b..c21f1693 100644 --- a/resources/js/Components/Common/Report/ReportCreateModal.vue +++ b/resources/js/Components/Common/Report/ReportCreateModal.vue @@ -15,6 +15,7 @@ import { api } from '@/packages/api/src'; import { Checkbox } from '@/packages/ui/src'; import DatePicker from '@/packages/ui/src/Input/DatePicker.vue'; import { useNotificationsStore } from '@/utils/notification'; +import { getLocalizedDayJs } from '@/packages/ui/src/utils/time'; const show = defineModel('show', { default: false }); const saving = ref(false); @@ -47,10 +48,14 @@ const report = ref({ const { handleApiRequestNotifications } = useNotificationsStore(); async function submit() { + const { public_until, ...reportProperties } = report.value; await handleApiRequestNotifications( () => createReportMutation.mutateAsync({ - ...report.value, + ...reportProperties, + public_until: public_until + ? getLocalizedDayJs(public_until).utc().format() + : null, properties: { ...props.properties }, }), 'Success', @@ -109,7 +114,10 @@ async function submit() { (optional) - + diff --git a/resources/js/Components/Common/Report/ReportEditModal.vue b/resources/js/Components/Common/Report/ReportEditModal.vue index 3224fd55..cbef9692 100644 --- a/resources/js/Components/Common/Report/ReportEditModal.vue +++ b/resources/js/Components/Common/Report/ReportEditModal.vue @@ -13,6 +13,7 @@ import { Checkbox } from '@/packages/ui/src'; import DatePicker from '@/packages/ui/src/Input/DatePicker.vue'; import { useNotificationsStore } from '@/utils/notification'; import type { Report } from '@/packages/api/src'; +import { getLocalizedDayJs } from '@/packages/ui/src/utils/time'; const show = defineModel('show', { default: false }); const saving = ref(false); @@ -64,8 +65,15 @@ watch( const { handleApiRequestNotifications } = useNotificationsStore(); async function submit() { + const { public_until, ...reportProperties } = report.value; await handleApiRequestNotifications( - () => updateReportMutation.mutateAsync(report.value), + () => + updateReportMutation.mutateAsync({ + ...reportProperties, + public_until: public_until + ? getLocalizedDayJs(public_until).utc().format() + : null, + }), 'Success', 'Error', () => { @@ -118,9 +126,10 @@ async function submit() { v-if="report.is_public" class="flex items-center space-x-4"> - + diff --git a/resources/js/packages/ui/src/Input/DatePicker.vue b/resources/js/packages/ui/src/Input/DatePicker.vue index 7259e0e7..1ea265b5 100644 --- a/resources/js/packages/ui/src/Input/DatePicker.vue +++ b/resources/js/packages/ui/src/Input/DatePicker.vue @@ -30,7 +30,9 @@ const handleChange = (date: DateValue | undefined) => { return; } - const dayjs = getLocalizedDayJs(model.value); + const dayjs = model.value + ? getLocalizedDayJs(model.value) + : getLocalizedDayJs(); model.value = dayjs .year(date.year) .month(date.month - 1) // CalendarDate uses 1-based months @@ -62,12 +64,15 @@ const organization = inject>('organization'); ]" :tabindex="tabindex"> + :class="[ + size === 'xs' + ? 'h-3 w-3' + : size === 'sm' + ? 'h-3 w-3' + : size === 'lg' + ? 'h-4.5 w-4.5' + : 'h-4 w-4', + ]" /> {{ model diff --git a/tests/Unit/Endpoint/Api/V1/ReportEndpointTest.php b/tests/Unit/Endpoint/Api/V1/ReportEndpointTest.php index 0239e050..8c54c346 100644 --- a/tests/Unit/Endpoint/Api/V1/ReportEndpointTest.php +++ b/tests/Unit/Endpoint/Api/V1/ReportEndpointTest.php @@ -340,6 +340,35 @@ class ReportEndpointTest extends ApiEndpointTestAbstract ); } + public function test_update_endpoint_can_update_public_until_without_changing_secret(): void + { + // Arrange + $data = $this->createUserWithPermission([ + 'reports:update', + ]); + $report = Report::factory()->public()->forOrganization($data->organization)->create(); + $secret = $report->share_secret; + $newPublicUntil = Carbon::now()->addDays(30)->toIso8601ZuluString(); + Passport::actingAs($data->user); + + // Act + $response = $this->putJson(route('api.v1.reports.update', [$data->organization->getKey(), $report->getKey()]), [ + 'public_until' => $newPublicUntil, + ]); + + // Assert + $report->refresh(); + $this->assertTrue($report->is_public); + $this->assertSame($secret, $report->share_secret); + $this->assertSame($newPublicUntil, $report->public_until->toIso8601ZuluString()); + $response->assertStatus(200); + $response->assertJson(fn (AssertableJson $json) => $json + ->has('data') + ->where('data.is_public', true) + ->where('data.shareable_link', $report->getShareableLink()) + ); + } + public function test_update_endpoint_can_update_the_report_all_properties_set(): void { // Arrange