From fe19593f6eff8e79edbadcbbe49484f9cc486822 Mon Sep 17 00:00:00 2001 From: Gregor Vostrak Date: Wed, 16 Oct 2024 14:50:56 +0200 Subject: [PATCH] add Export download buttons --- .../Api/V1/TimeEntryController.php | 2 + resources/js/Pages/Reporting.vue | 67 +++++++- .../packages/api/src/openapi.json.client.ts | 149 +++++++++++++++--- 3 files changed, 192 insertions(+), 26 deletions(-) diff --git a/app/Http/Controllers/Api/V1/TimeEntryController.php b/app/Http/Controllers/Api/V1/TimeEntryController.php index 0cd69621..c27dd9c2 100644 --- a/app/Http/Controllers/Api/V1/TimeEntryController.php +++ b/app/Http/Controllers/Api/V1/TimeEntryController.php @@ -147,6 +147,8 @@ private function getTimeEntriesQuery(Organization $organization, TimeEntryIndexR /** * @throws AuthorizationException + * + * @operationId exportTimeEntries */ public function indexExport(Organization $organization, TimeEntryIndexExportRequest $request): JsonResponse { diff --git a/resources/js/Pages/Reporting.vue b/resources/js/Pages/Reporting.vue index edc6ecbc..aec899de 100644 --- a/resources/js/Pages/Reporting.vue +++ b/resources/js/Pages/Reporting.vue @@ -8,10 +8,12 @@ import { UserGroupIcon, CheckCircleIcon, TagIcon, + ArrowDownTrayIcon, } from '@heroicons/vue/20/solid'; import DateRangePicker from '@/packages/ui/src/Input/DateRangePicker.vue'; import ReportingChart from '@/Components/Common/Reporting/ReportingChart.vue'; import BillableIcon from '@/packages/ui/src/Icons/BillableIcon.vue'; + import { onMounted, ref } from 'vue'; import { formatHumanReadableDuration, @@ -21,7 +23,7 @@ import { import { type GroupingOption, useReportingStore } from '@/utils/useReporting'; import { storeToRefs } from 'pinia'; import TagDropdown from '@/packages/ui/src/Tag/TagDropdown.vue'; -import type { AggregatedTimeEntriesQueryParams } from '@/packages/api/src'; +import { type AggregatedTimeEntriesQueryParams, api } from '@/packages/api/src'; import ReportingFilterBadge from '@/Components/Common/Reporting/ReportingFilterBadge.vue'; import ProjectMultiselectDropdown from '@/Components/Common/Project/ProjectMultiselectDropdown.vue'; import MemberMultiselectDropdown from '@/Components/Common/Member/MemberMultiselectDropdown.vue'; @@ -31,7 +33,11 @@ import ReportingGroupBySelect from '@/Components/Common/Reporting/ReportingGroup import ReportingRow from '@/Components/Common/Reporting/ReportingRow.vue'; import { getOrganizationCurrencyString } from '@/utils/money'; import ReportingPieChart from '@/Components/Common/Reporting/ReportingPieChart.vue'; -import { getCurrentMembershipId, getCurrentRole } from '@/utils/useUser'; +import { + getCurrentMembershipId, + getCurrentOrganizationId, + getCurrentRole, +} from '@/utils/useUser'; import ClientMultiselectDropdown from '@/Components/Common/Client/ClientMultiselectDropdown.vue'; import { useTagsStore } from '@/utils/useTags'; import { formatCents } from '@/packages/ui/src/utils/money'; @@ -39,6 +45,10 @@ import { useSessionStorage, useStorage } from '@vueuse/core'; import TabBar from '@/Components/Common/TabBar/TabBar.vue'; import TabBarItem from '@/Components/Common/TabBar/TabBarItem.vue'; import { router } from '@inertiajs/vue3'; +import { SecondaryButton } from '@/packages/ui/src'; +import Dropdown from '@/packages/ui/src/Input/Dropdown.vue'; +import { useNotificationsStore } from '@/utils/notification'; +const { handleApiRequestNotifications } = useNotificationsStore(); const startDate = useSessionStorage( 'reporting-start-date', @@ -149,6 +159,29 @@ const { tags } = storeToRefs(useTagsStore()); async function createTag(tag: string) { return await useTagsStore().createTag(tag); } + +type ExportFormat = 'xlsx' | 'csv' | 'ods'; + +async function downloadExport(format: ExportFormat) { + const organizationId = getCurrentOrganizationId(); + if (organizationId) { + const response = await handleApiRequestNotifications( + () => + api.exportTimeEntries({ + params: { + organization: organizationId, + }, + queries: { + ...getFilterAttributes(), + format: format, + }, + }), + 'Export successful', + 'Export failed' + ); + window.open(response.download_url, '_self')?.focus(); + } +}