Added excel support.
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
This commit is contained in:
parent
1e2adb2b28
commit
4a03b7bfd4
@ -1,11 +1,12 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { useState } from 'react'
|
||||
import { useState, useContext } from 'react'
|
||||
import { Button, Dropdown, Modal } from 'antd'
|
||||
import ExcelIcon from '../../Icons/ExcelIcon'
|
||||
import ODataIcon from '../../Icons/ODataIcon'
|
||||
import CsvIcon from '../../Icons/CsvIcon'
|
||||
import ExportIcon from '../../Icons/ExportIcon'
|
||||
import ODataURL from './ODataURL'
|
||||
import { ApiServerContext } from '../context/ApiServerContext'
|
||||
|
||||
const ExportListButton = ({
|
||||
objectType,
|
||||
@ -14,16 +15,38 @@ const ExportListButton = ({
|
||||
...buttonProps
|
||||
}) => {
|
||||
const [odataModalOpen, setOdataModalOpen] = useState(false)
|
||||
const [excelLoading, setExcelLoading] = useState(false)
|
||||
const { exportToExcel } = useContext(ApiServerContext)
|
||||
|
||||
const handleExcelExport = async (mode) => {
|
||||
setExcelLoading(true)
|
||||
try {
|
||||
await exportToExcel(objectType, mode)
|
||||
} finally {
|
||||
setExcelLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
key: 'excel',
|
||||
label: 'Excel',
|
||||
label: excelLoading ? 'Exporting...' : 'Excel',
|
||||
icon: <ExcelIcon />,
|
||||
disabled: true,
|
||||
onClick: () => {
|
||||
// TODO: implement Excel export
|
||||
disabled: excelLoading,
|
||||
children: [
|
||||
{
|
||||
key: 'excel-download',
|
||||
label: 'Download',
|
||||
disabled: excelLoading,
|
||||
onClick: () => handleExcelExport('download')
|
||||
},
|
||||
{
|
||||
key: 'excel-open',
|
||||
label: 'Open in Excel',
|
||||
disabled: excelLoading,
|
||||
onClick: () => handleExcelExport('open')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'odata',
|
||||
|
||||
@ -120,8 +120,7 @@ const ApiServerProvider = ({ children }) => {
|
||||
newSocket.on('notification', (data) => {
|
||||
let notification
|
||||
try {
|
||||
notification =
|
||||
typeof data === 'string' ? JSON.parse(data) : data
|
||||
notification = typeof data === 'string' ? JSON.parse(data) : data
|
||||
} catch (err) {
|
||||
logger.error('Failed to parse notification:', err)
|
||||
return
|
||||
@ -916,6 +915,60 @@ const ApiServerProvider = ({ children }) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Export list data to Excel and download or open in Excel
|
||||
const exportToExcel = async (objectType, mode = 'download') => {
|
||||
try {
|
||||
if (mode === 'open') {
|
||||
// Open in Excel: get a temporary https URL (Excel fetches it when opening)
|
||||
const response = await axios.post(
|
||||
`${config.backendUrl}/excel/${objectType}/open`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
const url = response.data?.url
|
||||
if (!url || typeof url !== 'string') {
|
||||
throw new Error('No URL received from server')
|
||||
}
|
||||
const excelUri = `ms-excel:ofe|u|${url}`
|
||||
window.location.href = excelUri
|
||||
message.success('Opening in Excel')
|
||||
} else if (mode === 'download') {
|
||||
const response = await axios.get(
|
||||
`${config.backendUrl}/excel/${objectType}`,
|
||||
{
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
Accept:
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
const blob = new Blob([response.data], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
})
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `${objectType}-export-${new Date().toISOString().slice(0, 10)}.xlsx`
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
message.success('Excel file downloaded')
|
||||
} else {
|
||||
throw new Error('Invalid mode')
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
showError(err, () => exportToExcel(objectType))
|
||||
}
|
||||
}
|
||||
|
||||
// Download GCode file content
|
||||
const fetchFileContent = async (file, download = false) => {
|
||||
try {
|
||||
@ -1002,7 +1055,10 @@ const ApiServerProvider = ({ children }) => {
|
||||
}
|
||||
}
|
||||
)
|
||||
spotlightCache.set(query, { data: response.data, timestamp: Date.now() })
|
||||
spotlightCache.set(query, {
|
||||
data: response.data,
|
||||
timestamp: Date.now()
|
||||
})
|
||||
return response.data
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
@ -1458,6 +1514,7 @@ const ApiServerProvider = ({ children }) => {
|
||||
fetchLoading,
|
||||
showError,
|
||||
fetchFileContent,
|
||||
exportToExcel,
|
||||
fetchTemplatePreview,
|
||||
fetchTemplatePDF,
|
||||
fetchNotes,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user