feat: add Excel export, keyboard shortcuts, and print view for CFDIs
- Add export to Excel button with xlsx library for filtered data - Add keyboard shortcuts (Esc to close popovers/forms) - Add print button to invoice viewer modal with optimized print styles Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,8 +12,10 @@ import { useCfdis, useCreateCfdi, useDeleteCfdi } from '@/lib/hooks/use-cfdi';
|
|||||||
import { createManyCfdis, searchEmisores, searchReceptores, type EmisorReceptor } from '@/lib/api/cfdi';
|
import { createManyCfdis, searchEmisores, searchReceptores, type EmisorReceptor } from '@/lib/api/cfdi';
|
||||||
import type { CfdiFilters, TipoCfdi, Cfdi } from '@horux/shared';
|
import type { CfdiFilters, TipoCfdi, Cfdi } from '@horux/shared';
|
||||||
import type { CreateCfdiData } from '@/lib/api/cfdi';
|
import type { CreateCfdiData } from '@/lib/api/cfdi';
|
||||||
import { FileText, Search, ChevronLeft, ChevronRight, Plus, Upload, Trash2, X, FileUp, CheckCircle, AlertCircle, Loader2, Eye, Filter, XCircle, Calendar, User, Building2 } from 'lucide-react';
|
import { FileText, Search, ChevronLeft, ChevronRight, Plus, Upload, Trash2, X, FileUp, CheckCircle, AlertCircle, Loader2, Eye, Filter, XCircle, Calendar, User, Building2, Download, Printer } from 'lucide-react';
|
||||||
import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover';
|
import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover';
|
||||||
|
import * as XLSX from 'xlsx';
|
||||||
|
import { saveAs } from 'file-saver';
|
||||||
import { CfdiViewerModal } from '@/components/cfdi/cfdi-viewer-modal';
|
import { CfdiViewerModal } from '@/components/cfdi/cfdi-viewer-modal';
|
||||||
import { getCfdiById } from '@/lib/api/cfdi';
|
import { getCfdiById } from '@/lib/api/cfdi';
|
||||||
import { useAuthStore } from '@/stores/auth-store';
|
import { useAuthStore } from '@/stores/auth-store';
|
||||||
@@ -274,6 +276,7 @@ export default function CfdiPage() {
|
|||||||
.catch(() => setReceptorSuggestions([]))
|
.catch(() => setReceptorSuggestions([]))
|
||||||
.finally(() => setLoadingReceptor(false));
|
.finally(() => setLoadingReceptor(false));
|
||||||
}, [debouncedReceptor]);
|
}, [debouncedReceptor]);
|
||||||
|
|
||||||
const [showBulkForm, setShowBulkForm] = useState(false);
|
const [showBulkForm, setShowBulkForm] = useState(false);
|
||||||
const [formData, setFormData] = useState<CreateCfdiData>(initialFormData);
|
const [formData, setFormData] = useState<CreateCfdiData>(initialFormData);
|
||||||
const [bulkData, setBulkData] = useState('');
|
const [bulkData, setBulkData] = useState('');
|
||||||
@@ -323,6 +326,54 @@ export default function CfdiPage() {
|
|||||||
setFilters({ ...filters, search: searchTerm, page: 1 });
|
setFilters({ ...filters, search: searchTerm, page: 1 });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Export to Excel
|
||||||
|
const [exporting, setExporting] = useState(false);
|
||||||
|
|
||||||
|
const exportToExcel = async () => {
|
||||||
|
if (!data?.data.length) return;
|
||||||
|
|
||||||
|
setExporting(true);
|
||||||
|
try {
|
||||||
|
const exportData = data.data.map(cfdi => ({
|
||||||
|
'Fecha Emisión': new Date(cfdi.fechaEmision).toLocaleDateString('es-MX'),
|
||||||
|
'Tipo': cfdi.tipo === 'ingreso' ? 'Ingreso' : 'Egreso',
|
||||||
|
'Serie': cfdi.serie || '',
|
||||||
|
'Folio': cfdi.folio || '',
|
||||||
|
'RFC Emisor': cfdi.rfcEmisor,
|
||||||
|
'Nombre Emisor': cfdi.nombreEmisor,
|
||||||
|
'RFC Receptor': cfdi.rfcReceptor,
|
||||||
|
'Nombre Receptor': cfdi.nombreReceptor,
|
||||||
|
'Subtotal': cfdi.subtotal,
|
||||||
|
'IVA': cfdi.iva,
|
||||||
|
'Total': cfdi.total,
|
||||||
|
'Moneda': cfdi.moneda,
|
||||||
|
'Estado': cfdi.estado === 'vigente' ? 'Vigente' : 'Cancelado',
|
||||||
|
'UUID': cfdi.uuidFiscal,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const ws = XLSX.utils.json_to_sheet(exportData);
|
||||||
|
const wb = XLSX.utils.book_new();
|
||||||
|
XLSX.utils.book_append_sheet(wb, ws, 'CFDIs');
|
||||||
|
|
||||||
|
// Auto-size columns
|
||||||
|
const colWidths = Object.keys(exportData[0]).map(key => ({
|
||||||
|
wch: Math.max(key.length, ...exportData.map(row => String(row[key as keyof typeof row]).length))
|
||||||
|
}));
|
||||||
|
ws['!cols'] = colWidths;
|
||||||
|
|
||||||
|
const excelBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
||||||
|
const blob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
||||||
|
|
||||||
|
const fileName = `cfdis_${new Date().toISOString().split('T')[0]}.xlsx`;
|
||||||
|
saveAs(blob, fileName);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error exporting:', error);
|
||||||
|
alert('Error al exportar');
|
||||||
|
} finally {
|
||||||
|
setExporting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const selectEmisor = (emisor: EmisorReceptor) => {
|
const selectEmisor = (emisor: EmisorReceptor) => {
|
||||||
setColumnFilters(prev => ({ ...prev, emisor: emisor.nombre }));
|
setColumnFilters(prev => ({ ...prev, emisor: emisor.nombre }));
|
||||||
setEmisorSuggestions([]);
|
setEmisorSuggestions([]);
|
||||||
@@ -594,6 +645,32 @@ export default function CfdiPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Keyboard shortcuts - Esc to close popovers and forms
|
||||||
|
useEffect(() => {
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
// Close open filter popovers
|
||||||
|
if (openFilter !== null) {
|
||||||
|
setOpenFilter(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Close forms
|
||||||
|
if (showForm) {
|
||||||
|
setShowForm(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (showBulkForm) {
|
||||||
|
setShowBulkForm(false);
|
||||||
|
clearXmlFiles();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('keydown', handleKeyDown);
|
||||||
|
return () => document.removeEventListener('keydown', handleKeyDown);
|
||||||
|
}, [openFilter, showForm, showBulkForm]);
|
||||||
|
|
||||||
const cancelUpload = () => {
|
const cancelUpload = () => {
|
||||||
uploadAbortRef.current = true;
|
uploadAbortRef.current = true;
|
||||||
setUploadProgress(prev => ({ ...prev, status: 'idle' }));
|
setUploadProgress(prev => ({ ...prev, status: 'idle' }));
|
||||||
@@ -681,8 +758,19 @@ export default function CfdiPage() {
|
|||||||
Egresos
|
Egresos
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{canEdit && (
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
|
{data && data.data.length > 0 && (
|
||||||
|
<Button variant="outline" onClick={exportToExcel} disabled={exporting}>
|
||||||
|
{exporting ? (
|
||||||
|
<Loader2 className="h-4 w-4 mr-1 animate-spin" />
|
||||||
|
) : (
|
||||||
|
<Download className="h-4 w-4 mr-1" />
|
||||||
|
)}
|
||||||
|
Exportar
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{canEdit && (
|
||||||
|
<>
|
||||||
<Button onClick={() => { setShowForm(true); setShowBulkForm(false); }}>
|
<Button onClick={() => { setShowForm(true); setShowBulkForm(false); }}>
|
||||||
<Plus className="h-4 w-4 mr-1" />
|
<Plus className="h-4 w-4 mr-1" />
|
||||||
Agregar
|
Agregar
|
||||||
@@ -691,9 +779,10 @@ export default function CfdiPage() {
|
|||||||
<Upload className="h-4 w-4 mr-1" />
|
<Upload className="h-4 w-4 mr-1" />
|
||||||
Carga Masiva
|
Carga Masiva
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/u
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { CfdiInvoice } from './cfdi-invoice';
|
import { CfdiInvoice } from './cfdi-invoice';
|
||||||
import { getCfdiXml } from '@/lib/api/cfdi';
|
import { getCfdiXml } from '@/lib/api/cfdi';
|
||||||
import { Download, FileText, Loader2 } from 'lucide-react';
|
import { Download, FileText, Loader2, Printer } from 'lucide-react';
|
||||||
|
|
||||||
interface CfdiConcepto {
|
interface CfdiConcepto {
|
||||||
descripcion: string;
|
descripcion: string;
|
||||||
@@ -120,6 +120,45 @@ export function CfdiViewerModal({ cfdi, open, onClose }: CfdiViewerModalProps) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handlePrint = () => {
|
||||||
|
if (!invoiceRef.current) return;
|
||||||
|
|
||||||
|
// Create a print-specific stylesheet
|
||||||
|
const printStyles = document.createElement('style');
|
||||||
|
printStyles.innerHTML = `
|
||||||
|
@media print {
|
||||||
|
body * {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
#cfdi-print-area, #cfdi-print-area * {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
#cfdi-print-area {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
@page {
|
||||||
|
size: A4;
|
||||||
|
margin: 15mm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(printStyles);
|
||||||
|
|
||||||
|
// Add ID to the invoice container for print targeting
|
||||||
|
invoiceRef.current.id = 'cfdi-print-area';
|
||||||
|
|
||||||
|
// Trigger print
|
||||||
|
window.print();
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
document.head.removeChild(printStyles);
|
||||||
|
invoiceRef.current.removeAttribute('id');
|
||||||
|
};
|
||||||
|
|
||||||
if (!cfdi) return null;
|
if (!cfdi) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -156,6 +195,16 @@ export function CfdiViewerModal({ cfdi, open, onClose }: CfdiViewerModalProps) {
|
|||||||
)}
|
)}
|
||||||
XML
|
XML
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={handlePrint}
|
||||||
|
disabled={downloading !== null}
|
||||||
|
title="Imprimir factura"
|
||||||
|
>
|
||||||
|
<Printer className="h-4 w-4 mr-1" />
|
||||||
|
Imprimir
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.0",
|
"clsx": "^2.1.0",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
|
"file-saver": "^2.0.5",
|
||||||
"html2pdf.js": "^0.14.0",
|
"html2pdf.js": "^0.14.0",
|
||||||
"lucide-react": "^0.460.0",
|
"lucide-react": "^0.460.0",
|
||||||
"next": "^14.2.0",
|
"next": "^14.2.0",
|
||||||
@@ -35,10 +36,12 @@
|
|||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
"recharts": "^2.12.0",
|
"recharts": "^2.12.0",
|
||||||
"tailwind-merge": "^2.5.0",
|
"tailwind-merge": "^2.5.0",
|
||||||
|
"xlsx": "^0.18.5",
|
||||||
"zod": "^3.23.0",
|
"zod": "^3.23.0",
|
||||||
"zustand": "^5.0.0"
|
"zustand": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/file-saver": "^2.0.7",
|
||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
"@types/react": "^18.3.0",
|
"@types/react": "^18.3.0",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
|
|||||||
81
pnpm-lock.yaml
generated
81
pnpm-lock.yaml
generated
@@ -162,6 +162,9 @@ importers:
|
|||||||
date-fns:
|
date-fns:
|
||||||
specifier: ^3.6.0
|
specifier: ^3.6.0
|
||||||
version: 3.6.0
|
version: 3.6.0
|
||||||
|
file-saver:
|
||||||
|
specifier: ^2.0.5
|
||||||
|
version: 2.0.5
|
||||||
html2pdf.js:
|
html2pdf.js:
|
||||||
specifier: ^0.14.0
|
specifier: ^0.14.0
|
||||||
version: 0.14.0
|
version: 0.14.0
|
||||||
@@ -186,6 +189,9 @@ importers:
|
|||||||
tailwind-merge:
|
tailwind-merge:
|
||||||
specifier: ^2.5.0
|
specifier: ^2.5.0
|
||||||
version: 2.6.0
|
version: 2.6.0
|
||||||
|
xlsx:
|
||||||
|
specifier: ^0.18.5
|
||||||
|
version: 0.18.5
|
||||||
zod:
|
zod:
|
||||||
specifier: ^3.23.0
|
specifier: ^3.23.0
|
||||||
version: 3.25.76
|
version: 3.25.76
|
||||||
@@ -193,6 +199,9 @@ importers:
|
|||||||
specifier: ^5.0.0
|
specifier: ^5.0.0
|
||||||
version: 5.0.10(@types/react@18.3.27)(react@18.3.1)(use-sync-external-store@1.6.0(react@18.3.1))
|
version: 5.0.10(@types/react@18.3.27)(react@18.3.1)(use-sync-external-store@1.6.0(react@18.3.1))
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@types/file-saver':
|
||||||
|
specifier: ^2.0.7
|
||||||
|
version: 2.0.7
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.0.0
|
specifier: ^22.0.0
|
||||||
version: 22.19.7
|
version: 22.19.7
|
||||||
@@ -1070,6 +1079,9 @@ packages:
|
|||||||
'@types/express@5.0.6':
|
'@types/express@5.0.6':
|
||||||
resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==}
|
resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==}
|
||||||
|
|
||||||
|
'@types/file-saver@2.0.7':
|
||||||
|
resolution: {integrity: sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==}
|
||||||
|
|
||||||
'@types/http-errors@2.0.5':
|
'@types/http-errors@2.0.5':
|
||||||
resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==}
|
resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==}
|
||||||
|
|
||||||
@@ -1135,6 +1147,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
adler-32@1.3.1:
|
||||||
|
resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
adm-zip@0.5.16:
|
adm-zip@0.5.16:
|
||||||
resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==}
|
resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==}
|
||||||
engines: {node: '>=12.0'}
|
engines: {node: '>=12.0'}
|
||||||
@@ -1281,6 +1297,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==}
|
resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
|
|
||||||
|
cfb@1.2.2:
|
||||||
|
resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
chainsaw@0.1.0:
|
chainsaw@0.1.0:
|
||||||
resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==}
|
resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==}
|
||||||
|
|
||||||
@@ -1298,6 +1318,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
codepage@1.15.0:
|
||||||
|
resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
combined-stream@1.0.8:
|
combined-stream@1.0.8:
|
||||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@@ -1550,6 +1574,9 @@ packages:
|
|||||||
fflate@0.8.2:
|
fflate@0.8.2:
|
||||||
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
|
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
|
||||||
|
|
||||||
|
file-saver@2.0.5:
|
||||||
|
resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==}
|
||||||
|
|
||||||
fill-range@7.1.1:
|
fill-range@7.1.1:
|
||||||
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -1575,6 +1602,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
frac@1.1.2:
|
||||||
|
resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
fraction.js@5.3.4:
|
fraction.js@5.3.4:
|
||||||
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
|
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
|
||||||
|
|
||||||
@@ -2299,6 +2330,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
|
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
|
||||||
engines: {node: '>= 10.x'}
|
engines: {node: '>= 10.x'}
|
||||||
|
|
||||||
|
ssf@0.11.2:
|
||||||
|
resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
stackblur-canvas@2.7.0:
|
stackblur-canvas@2.7.0:
|
||||||
resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==}
|
resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==}
|
||||||
engines: {node: '>=0.1.14'}
|
engines: {node: '>=0.1.14'}
|
||||||
@@ -2509,9 +2544,22 @@ packages:
|
|||||||
victory-vendor@36.9.2:
|
victory-vendor@36.9.2:
|
||||||
resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==}
|
resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==}
|
||||||
|
|
||||||
|
wmf@1.0.2:
|
||||||
|
resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
|
word@0.3.0:
|
||||||
|
resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
wrappy@1.0.2:
|
wrappy@1.0.2:
|
||||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||||
|
|
||||||
|
xlsx@0.18.5:
|
||||||
|
resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
xmlchars@2.2.0:
|
xmlchars@2.2.0:
|
||||||
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
|
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
|
||||||
|
|
||||||
@@ -3296,6 +3344,8 @@ snapshots:
|
|||||||
'@types/express-serve-static-core': 5.1.1
|
'@types/express-serve-static-core': 5.1.1
|
||||||
'@types/serve-static': 2.2.0
|
'@types/serve-static': 2.2.0
|
||||||
|
|
||||||
|
'@types/file-saver@2.0.7': {}
|
||||||
|
|
||||||
'@types/http-errors@2.0.5': {}
|
'@types/http-errors@2.0.5': {}
|
||||||
|
|
||||||
'@types/jsonwebtoken@9.0.10':
|
'@types/jsonwebtoken@9.0.10':
|
||||||
@@ -3358,6 +3408,8 @@ snapshots:
|
|||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
negotiator: 0.6.3
|
negotiator: 0.6.3
|
||||||
|
|
||||||
|
adler-32@1.3.1: {}
|
||||||
|
|
||||||
adm-zip@0.5.16: {}
|
adm-zip@0.5.16: {}
|
||||||
|
|
||||||
any-promise@1.3.0: {}
|
any-promise@1.3.0: {}
|
||||||
@@ -3542,6 +3594,11 @@ snapshots:
|
|||||||
svg-pathdata: 6.0.3
|
svg-pathdata: 6.0.3
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
cfb@1.2.2:
|
||||||
|
dependencies:
|
||||||
|
adler-32: 1.3.1
|
||||||
|
crc-32: 1.2.2
|
||||||
|
|
||||||
chainsaw@0.1.0:
|
chainsaw@0.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
traverse: 0.3.9
|
traverse: 0.3.9
|
||||||
@@ -3566,6 +3623,8 @@ snapshots:
|
|||||||
|
|
||||||
clsx@2.1.1: {}
|
clsx@2.1.1: {}
|
||||||
|
|
||||||
|
codepage@1.15.0: {}
|
||||||
|
|
||||||
combined-stream@1.0.8:
|
combined-stream@1.0.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream: 1.0.0
|
delayed-stream: 1.0.0
|
||||||
@@ -3846,6 +3905,8 @@ snapshots:
|
|||||||
|
|
||||||
fflate@0.8.2: {}
|
fflate@0.8.2: {}
|
||||||
|
|
||||||
|
file-saver@2.0.5: {}
|
||||||
|
|
||||||
fill-range@7.1.1:
|
fill-range@7.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
to-regex-range: 5.0.1
|
to-regex-range: 5.0.1
|
||||||
@@ -3874,6 +3935,8 @@ snapshots:
|
|||||||
|
|
||||||
forwarded@0.2.0: {}
|
forwarded@0.2.0: {}
|
||||||
|
|
||||||
|
frac@1.1.2: {}
|
||||||
|
|
||||||
fraction.js@5.3.4: {}
|
fraction.js@5.3.4: {}
|
||||||
|
|
||||||
fresh@0.5.2: {}
|
fresh@0.5.2: {}
|
||||||
@@ -4580,6 +4643,10 @@ snapshots:
|
|||||||
|
|
||||||
split2@4.2.0: {}
|
split2@4.2.0: {}
|
||||||
|
|
||||||
|
ssf@0.11.2:
|
||||||
|
dependencies:
|
||||||
|
frac: 1.1.2
|
||||||
|
|
||||||
stackblur-canvas@2.7.0:
|
stackblur-canvas@2.7.0:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -4802,8 +4869,22 @@ snapshots:
|
|||||||
d3-time: 3.1.0
|
d3-time: 3.1.0
|
||||||
d3-timer: 3.0.1
|
d3-timer: 3.0.1
|
||||||
|
|
||||||
|
wmf@1.0.2: {}
|
||||||
|
|
||||||
|
word@0.3.0: {}
|
||||||
|
|
||||||
wrappy@1.0.2: {}
|
wrappy@1.0.2: {}
|
||||||
|
|
||||||
|
xlsx@0.18.5:
|
||||||
|
dependencies:
|
||||||
|
adler-32: 1.3.1
|
||||||
|
cfb: 1.2.2
|
||||||
|
codepage: 1.15.0
|
||||||
|
crc-32: 1.2.2
|
||||||
|
ssf: 0.11.2
|
||||||
|
wmf: 1.0.2
|
||||||
|
word: 0.3.0
|
||||||
|
|
||||||
xmlchars@2.2.0: {}
|
xmlchars@2.2.0: {}
|
||||||
|
|
||||||
xtend@4.0.2: {}
|
xtend@4.0.2: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user