140 lines
5.0 KiB
React
140 lines
5.0 KiB
React
import {Flex, Button, Spinner, Text} from "@chakra-ui/react";
|
|
import useBuildUrl from "../../hooks/useBuildUrl.js";
|
|
import VdapApi from '../../hooks/useVdapApi.js';
|
|
import { useRef, useEffect } from 'react';
|
|
import {useDashboardStore} from "../../store/useDashboardStore.jsx";
|
|
|
|
export default function CommCoorReport({ settings, widgetID }) {
|
|
const reportRef = useRef(null);
|
|
|
|
const updateSettings = useDashboardStore(state => state.updateWidgetSettings);
|
|
|
|
// build url, defaults to 7 days past
|
|
const url = useBuildUrl('/api/v2/comm_coor_report', settings?.startDate, settings?.endDate);
|
|
console.log(url);
|
|
|
|
// VdapApi hook only calls api if the url changes and apiData remains stable since vdapApi uses state to track the data
|
|
const {data: apiData, isLoading, error} = VdapApi(url);
|
|
console.log(apiData);
|
|
|
|
const handleDownloadReport = () => {
|
|
if (apiData.length === 0) return;
|
|
const element = document.createElement('a');
|
|
element.style.display = 'none';
|
|
// Appends HTML right inside the element, after its last child
|
|
element.insertAdjacentHTML('afterbegin', apiData?.report_html);
|
|
|
|
// 1. Create a blob object with text content and text/plain mime type
|
|
const blob = new Blob([element.textContent || ""], { type: 'text/plain' });
|
|
|
|
// 2. Generate a temporary URL pointing to that blob
|
|
const fileUrl = URL.createObjectURL(blob);
|
|
|
|
// 3. Create a hidden anchor element
|
|
const linkElement = document.createElement('a');
|
|
linkElement.href = fileUrl;
|
|
linkElement.download = `comm_coor_report_${apiData?.start_date}_${apiData?.end_date}`; // Sets the target file name
|
|
linkElement.style.display = 'none';
|
|
|
|
// 4. Append to body, trigger click, and remove it immediately
|
|
document.body.appendChild(linkElement);
|
|
linkElement.click();
|
|
document.body.removeChild(linkElement);
|
|
document.body.removeChild(element);
|
|
|
|
// 5. Free up memory by revoking the blob URL
|
|
URL.revokeObjectURL(fileUrl);
|
|
}
|
|
|
|
const handleCopyReport = () => {
|
|
if (apiData.length === 0) return;
|
|
const element = document.createElement('a');
|
|
element.style.display = 'none';
|
|
// Appends HTML right inside the element, after its last child
|
|
element.insertAdjacentHTML('afterbegin', apiData?.report_html);
|
|
|
|
navigator.clipboard.writeText(element.textContent || "")
|
|
.then(() => {
|
|
alert('Copied to clipboard!');
|
|
})
|
|
.catch((err => {
|
|
console.error('Failed to copy: ', err);
|
|
}));
|
|
|
|
document.body.removeChild(element);
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (reportRef.current) {
|
|
reportRef.current.innerHTML = apiData?.report_html;
|
|
const p = reportRef.current.querySelectorAll('p');
|
|
const b = reportRef.current.querySelectorAll('b');
|
|
p[0].remove();
|
|
b[0].remove();
|
|
}
|
|
}, [apiData]);
|
|
|
|
// copy data to clipboard in formatted way when user clicks on copy btn in widget settings
|
|
useEffect(() => {
|
|
if (settings?.copyToClipboard === true && reportRef.current) {
|
|
navigator.clipboard.writeText(reportRef.current.innerText)
|
|
.then(() => {
|
|
alert('Copied to clipboard!');
|
|
})
|
|
.catch((err => {
|
|
console.error('Failed to copy: ', err);
|
|
}));
|
|
updateSettings(widgetID, {copyToClipboard: false});
|
|
}
|
|
}, [settings, widgetID, updateSettings]);
|
|
|
|
// download report
|
|
useEffect(() => {
|
|
if (settings?.downloadReport === true && reportRef.current) {
|
|
// 1. Create a blob object with text content and text/plain mime type
|
|
const blob = new Blob([reportRef.current.innerText || ""], { type: 'text/plain' });
|
|
|
|
// 2. Generate a temporary URL pointing to that blob
|
|
const fileUrl = URL.createObjectURL(blob);
|
|
|
|
// 3. Create a hidden anchor element
|
|
const linkElement = document.createElement('a');
|
|
linkElement.href = fileUrl;
|
|
linkElement.download = `comm_coor_report_${apiData?.start_date}_${apiData?.end_date}`; // Sets the target file name
|
|
linkElement.style.display = 'none';
|
|
|
|
// 4. Append to body, trigger click, and remove it immediately
|
|
document.body.appendChild(linkElement);
|
|
linkElement.click();
|
|
document.body.removeChild(linkElement);
|
|
|
|
// 5. Free up memory by revoking the blob URL
|
|
URL.revokeObjectURL(fileUrl);
|
|
updateSettings(widgetID, {downloadReport: false});
|
|
}
|
|
}, [settings, widgetID, updateSettings, apiData]);
|
|
|
|
if (isLoading) return (
|
|
<Flex w="100%" h="100%" align="center" justify="center" borderRadius="lg" bg="gray.800">
|
|
<Spinner size="xl" color="blue.400" thickness="4px"/>
|
|
</Flex>
|
|
);
|
|
|
|
if (error) return (
|
|
<Flex w="100%" h="100%" align="center" justify="center" textAlign="center" borderRadius="lg" bg="gray.800">
|
|
<Text color="red.400">{error}</Text>
|
|
</Flex>
|
|
);
|
|
|
|
if (!apiData) return (
|
|
<Flex w="100%" h="100%" align="center" justify="center" borderRadius="lg" bg="gray.800">
|
|
<Text textAlign="center" color="gray.400">No data</Text>
|
|
</Flex>
|
|
);
|
|
|
|
return (
|
|
<Flex direction="row" w="100%" h="100%" p={1} overflowY="auto">
|
|
<Text ref={reportRef}></Text>
|
|
</Flex>
|
|
)
|
|
} |