Improved UI for export options.
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
4a03b7bfd4
commit
1558e93b63
@ -6,7 +6,7 @@
|
||||
<path d="M10.149,67.641L43.438,67.641C50.137,67.641 53.586,64.135 53.586,57.41L53.586,29.058C53.586,24.717 53.028,22.725 50.308,19.954L33.894,3.284C31.282,0.616 29.111,0 25.212,0L10.149,0C3.481,0 0,3.532 0,10.257L0,57.41C0,64.161 3.455,67.641 10.149,67.641ZM10.637,61.519C7.621,61.519 6.122,59.941 6.122,57.029L6.122,10.637C6.122,7.752 7.621,6.122 10.663,6.122L23.984,6.122L23.984,23.261C23.984,27.733 26.167,29.895 30.619,29.895L47.464,29.895L47.464,57.029C47.464,59.941 45.965,61.519 42.929,61.519L10.637,61.519ZM31.198,24.496C29.903,24.496 29.384,23.945 29.384,22.656L29.384,6.973L46.613,24.496L31.198,24.496Z" style="fill-rule:nonzero;"/>
|
||||
<g transform="matrix(12.808657,0,0,12.808657,-40.118025,-49.663642)">
|
||||
<path d="M4.662,8.034C4.545,8.034 4.448,8.015 4.37,7.978C4.293,7.94 4.236,7.89 4.2,7.825C4.163,7.761 4.145,7.69 4.145,7.612C4.145,7.528 4.166,7.454 4.208,7.389C4.25,7.325 4.316,7.274 4.405,7.236C4.495,7.198 4.607,7.178 4.743,7.178L5.084,7.178C5.084,7.115 5.076,7.063 5.06,7.022C5.045,6.981 5.019,6.95 4.984,6.93C4.948,6.909 4.9,6.899 4.838,6.899C4.773,6.899 4.718,6.912 4.673,6.938C4.629,6.964 4.601,7.005 4.59,7.061L4.187,7.061C4.197,6.961 4.23,6.873 4.286,6.798C4.343,6.724 4.419,6.665 4.514,6.622C4.609,6.58 4.718,6.558 4.841,6.558C4.975,6.558 5.092,6.58 5.19,6.624C5.289,6.668 5.366,6.731 5.421,6.815C5.476,6.899 5.503,7.003 5.503,7.128L5.503,8L5.154,8L5.104,7.796C5.083,7.831 5.059,7.864 5.031,7.892C5.003,7.921 4.971,7.946 4.933,7.968C4.896,7.989 4.855,8.006 4.81,8.017C4.766,8.028 4.716,8.034 4.662,8.034ZM4.766,7.715C4.81,7.715 4.849,7.708 4.883,7.693C4.917,7.678 4.945,7.657 4.97,7.631C4.994,7.605 5.014,7.575 5.03,7.54C5.046,7.506 5.057,7.468 5.065,7.427L5.065,7.424L4.794,7.424C4.747,7.424 4.708,7.43 4.678,7.443C4.647,7.455 4.624,7.472 4.609,7.494C4.594,7.517 4.587,7.543 4.587,7.572C4.587,7.604 4.595,7.631 4.611,7.652C4.626,7.674 4.648,7.689 4.675,7.7C4.702,7.71 4.732,7.715 4.766,7.715Z" style="fill-rule:nonzero;"/>
|
||||
<path d="M5.746,8.344L5.906,7.609L6.302,7.609L6.017,8.344L5.746,8.344Z" style="fill-rule:nonzero;"/>
|
||||
<path d="M5.835,7.521L6.43,7.521L6.077,8.432L5.637,8.432L5.835,7.521Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
11
assets/icons/openappicon.svg
Normal file
11
assets/icons/openappicon.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,1.056758,1.088008)">
|
||||
<rect x="0" y="0" width="59.625" height="59.562" style="fill-opacity:0;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.918716,0,0,0.918716,5,4.991502)">
|
||||
<path d="M17.169,58.796L41.597,58.796C47.087,58.796 51.398,57.182 54.261,54.3C57.207,51.396 58.778,47.075 58.778,41.616L58.778,17.19C58.778,11.722 57.207,7.41 54.261,4.496C51.377,1.602 47.087,0 41.597,0L17.169,0C11.7,0 7.358,1.624 4.496,4.496C1.571,7.41 0,11.722 0,17.19L0,41.616C0,47.075 1.55,51.396 4.496,54.3C7.379,57.204 11.7,58.796 17.169,58.796ZM17.487,51.837C13.94,51.837 11.276,50.962 9.566,49.252C7.813,47.53 6.959,44.898 6.959,41.288L6.959,17.508C6.959,13.909 7.813,11.276 9.566,9.545C11.245,7.865 13.94,6.959 17.487,6.959L41.27,6.959C44.848,6.959 47.49,7.844 49.212,9.545C50.965,11.276 51.819,13.909 51.819,17.508L51.819,41.288C51.819,44.898 50.965,47.53 49.212,49.252C47.511,50.941 44.848,51.837 41.27,51.837L17.487,51.837Z" style="fill-rule:nonzero;"/>
|
||||
<path d="M34.245,20.733L28.455,25.929L17.907,36.476C17.311,37.063 16.929,37.896 16.929,38.71C16.929,40.544 18.242,41.748 19.997,41.748C20.916,41.748 21.667,41.417 22.323,40.771L32.821,30.304L37.996,24.505C40.497,21.719 37.205,18.138 34.245,20.733ZM36.354,30.119L36.354,34.789C36.354,36.636 37.45,37.853 39.143,37.853C40.836,37.853 41.911,36.582 41.911,34.767L41.911,20.374C41.911,18.014 40.563,16.868 38.364,16.868L23.898,16.868C22.062,16.868 20.845,17.943 20.845,19.636C20.845,21.329 22.064,22.404 23.91,22.404L28.872,22.404L37.417,21.188L36.354,30.119Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@ -4,6 +4,8 @@ import { Button, Dropdown, Modal } from 'antd'
|
||||
import ExcelIcon from '../../Icons/ExcelIcon'
|
||||
import ODataIcon from '../../Icons/ODataIcon'
|
||||
import CsvIcon from '../../Icons/CsvIcon'
|
||||
import DownloadIcon from '../../Icons/DownloadIcon'
|
||||
import OpenAppIcon from '../../Icons/OpenAppIcon'
|
||||
import ExportIcon from '../../Icons/ExportIcon'
|
||||
import ODataURL from './ODataURL'
|
||||
import { ApiServerContext } from '../context/ApiServerContext'
|
||||
@ -16,7 +18,8 @@ const ExportListButton = ({
|
||||
}) => {
|
||||
const [odataModalOpen, setOdataModalOpen] = useState(false)
|
||||
const [excelLoading, setExcelLoading] = useState(false)
|
||||
const { exportToExcel } = useContext(ApiServerContext)
|
||||
const [csvLoading, setCsvLoading] = useState(false)
|
||||
const { exportToExcel, exportToCsv } = useContext(ApiServerContext)
|
||||
|
||||
const handleExcelExport = async (mode) => {
|
||||
setExcelLoading(true)
|
||||
@ -27,40 +30,48 @@ const ExportListButton = ({
|
||||
}
|
||||
}
|
||||
|
||||
const exportLoading = excelLoading || csvLoading
|
||||
const menuItems = [
|
||||
{
|
||||
key: 'excel',
|
||||
label: excelLoading ? 'Exporting...' : 'Excel',
|
||||
label: excelLoading ? 'Exporting...' : 'Microsoft Excel',
|
||||
icon: <ExcelIcon />,
|
||||
disabled: excelLoading,
|
||||
disabled: exportLoading,
|
||||
children: [
|
||||
{
|
||||
key: 'excel-download',
|
||||
label: 'Download',
|
||||
disabled: excelLoading,
|
||||
label: 'Download File',
|
||||
icon: <DownloadIcon />,
|
||||
disabled: exportLoading,
|
||||
onClick: () => handleExcelExport('download')
|
||||
},
|
||||
{
|
||||
key: 'excel-open',
|
||||
label: 'Open in Excel',
|
||||
disabled: excelLoading,
|
||||
icon: <OpenAppIcon />,
|
||||
disabled: exportLoading,
|
||||
onClick: () => handleExcelExport('open')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'odata',
|
||||
label: 'OData',
|
||||
label: 'OData Connection',
|
||||
icon: <ODataIcon />,
|
||||
onClick: () => setOdataModalOpen(true)
|
||||
},
|
||||
{
|
||||
key: 'csv',
|
||||
label: 'CSV',
|
||||
label: csvLoading ? 'Exporting...' : 'CSV File',
|
||||
icon: <CsvIcon />,
|
||||
disabled: true,
|
||||
onClick: () => {
|
||||
// TODO: implement CSV export
|
||||
disabled: exportLoading,
|
||||
onClick: async () => {
|
||||
setCsvLoading(true)
|
||||
try {
|
||||
await exportToCsv(objectType)
|
||||
} finally {
|
||||
setCsvLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -70,12 +81,13 @@ const ExportListButton = ({
|
||||
<Dropdown
|
||||
menu={{ items: menuItems }}
|
||||
trigger={['hover']}
|
||||
disabled={disabled}
|
||||
disabled={disabled || exportLoading}
|
||||
>
|
||||
<Button
|
||||
icon={<ExportIcon />}
|
||||
disabled={disabled}
|
||||
disabled={disabled || exportLoading}
|
||||
size={size}
|
||||
loading={exportLoading}
|
||||
{...buttonProps}
|
||||
/>
|
||||
</Dropdown>
|
||||
|
||||
@ -13,7 +13,7 @@ const ODataURL = ({ objectType }) => {
|
||||
return (
|
||||
<Flex vertical align='center'>
|
||||
<Result
|
||||
title='OData URL'
|
||||
title='OData Connection'
|
||||
subTitle={
|
||||
<Text>
|
||||
Use this URL to connect Power BI, Excel, or other OData clients. An
|
||||
|
||||
@ -915,6 +915,35 @@ const ApiServerProvider = ({ children }) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Export list data to CSV and download
|
||||
const exportToCsv = async (objectType) => {
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`${config.backendUrl}/csv/${objectType}`,
|
||||
{
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
Accept: 'text/csv',
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
const blob = new Blob([response.data], { type: 'text/csv' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `${objectType}-export-${new Date().toISOString().slice(0, 10)}.csv`
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
URL.revokeObjectURL(url)
|
||||
message.success('CSV file downloaded')
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
showError(err, () => exportToCsv(objectType))
|
||||
}
|
||||
}
|
||||
|
||||
// Export list data to Excel and download or open in Excel
|
||||
const exportToExcel = async (objectType, mode = 'download') => {
|
||||
try {
|
||||
@ -1515,6 +1544,7 @@ const ApiServerProvider = ({ children }) => {
|
||||
showError,
|
||||
fetchFileContent,
|
||||
exportToExcel,
|
||||
exportToCsv,
|
||||
fetchTemplatePreview,
|
||||
fetchTemplatePDF,
|
||||
fetchNotes,
|
||||
|
||||
6
src/components/Icons/OpenAppIcon.jsx
Normal file
6
src/components/Icons/OpenAppIcon.jsx
Normal file
@ -0,0 +1,6 @@
|
||||
import Icon from '@ant-design/icons'
|
||||
import CustomIconSvg from '../../../assets/icons/openappicon.svg?react'
|
||||
|
||||
const OpenAppIcon = (props) => <Icon component={CustomIconSvg} {...props} />
|
||||
|
||||
export default OpenAppIcon
|
||||
Loading…
x
Reference in New Issue
Block a user