grafana/public/app/features/dataframe-import/utils.ts
Oscar Kilhed 8048a66e90
Dashboard: Add a feature that creates a table panel when a spreadsheet file is dropped on the dashboard. (#62688)
* drag files to dashboard

* use file name as panel title

* add file size limitation, file type limitation and error handling

* Refactor file parsing for code sharing

move accepted types and max size to file-import constants
show which file types are allowed in file type error

* update codeowners

* Adjust max size to 1mb
2023-02-09 15:16:17 +01:00

51 lines
1.6 KiB
TypeScript

import { Accept } from 'react-dropzone';
import { Observable } from 'rxjs';
import { toDataFrame } from '@grafana/data';
import { readSpreadsheet } from 'app/core/utils/sheet';
import { FileImportResult } from './types';
function getFileExtensions(acceptedFiles: Accept) {
const fileExtentions = new Set<string>();
Object.keys(acceptedFiles).forEach((v) => {
acceptedFiles[v].forEach((extension) => {
fileExtentions.add(extension);
});
});
return fileExtentions;
}
export function formatFileTypes(acceptedFiles: Accept) {
const fileExtentions = Array.from(getFileExtensions(acceptedFiles));
if (fileExtentions.length === 1) {
return fileExtentions[0];
}
return `${fileExtentions.slice(0, -1).join(', ')} or ${fileExtentions.slice(-1)}`;
}
export function filesToDataframes(files: File[]): Observable<FileImportResult> {
return new Observable<FileImportResult>((subscriber) => {
let completedFiles = 0;
files.forEach((file) => {
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = () => {
const result = reader.result;
if (result && result instanceof ArrayBuffer) {
if (file.type === 'application/json') {
const decoder = new TextDecoder('utf-8');
const json = JSON.parse(decoder.decode(result));
subscriber.next({ dataFrames: [toDataFrame(json)], file: file });
} else {
subscriber.next({ dataFrames: readSpreadsheet(result), file: file });
}
if (++completedFiles >= files.length) {
subscriber.complete();
}
}
};
});
});
}