Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 53 additions & 11 deletions src/Utils/Download.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export default function Download(props) {

// If no dataset information exists, download only the complete CSV
if (!hasDatasetInfo) {
handleDownloadSingleCSV();
await handleDownloadSingleCSV();
return;
}

Expand All @@ -176,14 +176,14 @@ export default function Download(props) {
}

// Add the complete CSV with all data
const completeCSVData = generateOriginalCSV();
const completeCSVData = await generateOriginalCSV();
zip.file(`${title}.csv`, completeCSVData);

const zipBlob = await zip.generateAsync({ type: 'blob' });
const zipArrayBuffer = await zipBlob.arrayBuffer();
exportZipFile(zipArrayBuffer, title);
} catch (error) {
handleDownloadSingleCSV();
await handleDownloadSingleCSV();
}
};

Expand Down Expand Up @@ -235,24 +235,66 @@ export default function Download(props) {
return generateFinalCSV(array, readme, metadataFlags, metadataArrays);
};

const generateOriginalCSV = () => {
const generateOriginalCSV = async () => {
let array = [];
let readme = provider_metadata?.readme ? [provider_metadata?.readme] : [];

Object.entries(dataSources).forEach(([key, items]) => {
items.forEach((item, index) => {
if (!array[index]) array[index] = {};
array[index][key] = item;
// Check if dataSources has any data
const hasDataSources =
dataSources &&
Object.keys(dataSources).some(
(key) => Array.isArray(dataSources[key]) && dataSources[key].length > 0,
);

if (hasDataSources) {
// Use existing dataSources logic
Object.entries(dataSources).forEach(([key, items]) => {
items.forEach((item, index) => {
if (!array[index]) array[index] = {};
array[index][key] = item;
});
});
});
} else if (chartData?.data && Array.isArray(chartData.data)) {
// Extract data from traces when dataSources is empty
const allTraceData = [];
for (const trace of chartData.data) {
const traceData = await processTraceData(trace, dataSources || {});
allTraceData.push(traceData);
}

// Process all trace data
if (
allTraceData.length > 0 &&
!allTraceData.every((data) => data.length === 0)
) {
const maxLength = Math.max(...allTraceData.map((data) => data.length));

for (let i = 0; i < maxLength; i++) {
if (!array[i]) array[i] = {};

allTraceData.forEach((traceData) => {
if (traceData[i]) {
Object.keys(traceData[i]).forEach((key) => {
if (
traceData[i][key] !== null &&
traceData[i][key] !== undefined
) {
array[i][key] = traceData[i][key];
}
});
}
});
}
}
}

const metadataFlags = getMetadataFlags();
const metadataArrays = processMetadataArrays(metadataFlags);
return generateFinalCSV(array, readme, metadataFlags, metadataArrays);
};

const handleDownloadSingleCSV = () => {
const csvData = generateOriginalCSV();
const handleDownloadSingleCSV = async () => {
const csvData = await generateOriginalCSV();
exportCSVFile(csvData, title);
};

Expand Down
144 changes: 94 additions & 50 deletions src/helpers/csvString.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,72 +236,116 @@ function groupDataByDataset(chartData) {
async function processTraceData(trace, dataSources) {
let processedData = [];

// Collect all columns used by the trace
const usedColumns = new Set();

const { getAttrsPath, constants, getSrcAttr } = await import(
'@eeacms/react-chart-editor/lib'
);

// Get all data attributes from constants.TRACE_SRC_ATTRIBUTES
const traceDataAttrs = getAttrsPath(trace, constants.TRACE_SRC_ATTRIBUTES);
// Check if dataSources has any data
const hasDataSources =
dataSources &&
Object.keys(dataSources).some(
(key) => Array.isArray(dataSources[key]) && dataSources[key].length > 0,
);

// For each data attribute, get the corresponding src attribute using getSrcAttr
Object.entries(traceDataAttrs).forEach(([dataAttrPath, dataValue]) => {
const srcAttr = getSrcAttr(trace, dataAttrPath);
if (hasDataSources) {
// Use existing logic when dataSources is available
const usedColumns = new Set();

if (srcAttr && srcAttr.value && dataSources[srcAttr.value]) {
usedColumns.add(srcAttr.value);
}
});
// Get all data attributes from constants.TRACE_SRC_ATTRIBUTES
const traceDataAttrs = getAttrsPath(trace, constants.TRACE_SRC_ATTRIBUTES);

// Add columns from transforms
if (trace.transforms && Array.isArray(trace.transforms)) {
trace.transforms.forEach((transform) => {
if (transform.targetsrc && dataSources[transform.targetsrc]) {
usedColumns.add(transform.targetsrc);
}
});
}
// For each data attribute, get the corresponding src attribute using getSrcAttr
Object.entries(traceDataAttrs).forEach(([dataAttrPath, dataValue]) => {
const srcAttr = getSrcAttr(trace, dataAttrPath);

// If no specific columns found, use all available data sources
if (usedColumns.size === 0) {
Object.keys(dataSources).forEach((key) => {
if (Array.isArray(dataSources[key])) {
usedColumns.add(key);
if (srcAttr && srcAttr.value && dataSources[srcAttr.value]) {
usedColumns.add(srcAttr.value);
}
});
}

const maxLength = Math.max(
...Array.from(usedColumns).map((col) =>
dataSources[col] ? dataSources[col].length : 0,
),
);
// Add columns from transforms
if (trace.transforms && Array.isArray(trace.transforms)) {
trace.transforms.forEach((transform) => {
if (transform.targetsrc && dataSources[transform.targetsrc]) {
usedColumns.add(transform.targetsrc);
}
});
}

for (let i = 0; i < maxLength; i++) {
const row = {};
usedColumns.forEach((col) => {
if (dataSources[col] && dataSources[col][i] !== undefined) {
row[col] = dataSources[col][i];
}
});
processedData.push(row);
}
// If no specific columns found, use all available data sources
if (usedColumns.size === 0) {
Object.keys(dataSources).forEach((key) => {
if (Array.isArray(dataSources[key])) {
usedColumns.add(key);
}
});
}

// Ensure all rows have the same columns (fill missing columns with empty values)
const allColumns = new Set();
processedData.forEach((row) => {
Object.keys(row).forEach((col) => allColumns.add(col));
});
const maxLength = Math.max(
...Array.from(usedColumns).map((col) =>
dataSources[col] ? dataSources[col].length : 0,
),
);

for (let i = 0; i < maxLength; i++) {
const row = {};
usedColumns.forEach((col) => {
if (dataSources[col] && dataSources[col][i] !== undefined) {
row[col] = dataSources[col][i];
}
});
processedData.push(row);
}

processedData.forEach((row) => {
allColumns.forEach((col) => {
if (!(col in row)) {
row[col] = '';
// Ensure all rows have the same columns (fill missing columns with empty values)
const allColumns = new Set();
processedData.forEach((row) => {
Object.keys(row).forEach((col) => allColumns.add(col));
});

processedData.forEach((row) => {
allColumns.forEach((col) => {
if (!(col in row)) {
row[col] = '';
}
});
});
} else {
// Extract data directly from trace using constants when no dataSources
const traceDataAttrs = getAttrsPath(trace, constants.TRACE_SRC_ATTRIBUTES);

// Extract data directly from trace properties
const dataColumns = new Set();
const traceDataValues = {};

Object.entries(traceDataAttrs).forEach(([dataAttrPath, dataValue]) => {
if (dataValue && Array.isArray(dataValue)) {
const columnName = dataAttrPath.replace(/\./g, '_');
dataColumns.add(columnName);
traceDataValues[columnName] = dataValue;
}
});
});

if (dataColumns.size > 0) {
const maxLength = Math.max(
...Array.from(dataColumns).map((col) =>
traceDataValues[col] ? traceDataValues[col].length : 0,
),
);

for (let i = 0; i < maxLength; i++) {
const row = {};
dataColumns.forEach((col) => {
if (traceDataValues[col] && traceDataValues[col][i] !== undefined) {
row[col] = traceDataValues[col][i];
}
});
if (Object.keys(row).length > 0) {
processedData.push(row);
}
}
}
}

// Apply transforms if they exist
if (trace.transforms && Array.isArray(trace.transforms)) {
Expand Down