Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Download CSV table of results #116

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
11 changes: 11 additions & 0 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"dexie": "^3.0.2",
"file-saver": "^2.0.5",
"immer": "^7.0.8",
"pako": "^2.0.4",
"react": "^16.13.1",
Expand Down
55 changes: 51 additions & 4 deletions web/src/componentTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { LazyLoadImage } from 'react-lazy-load-image-component';
import { Link } from 'react-scroll';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import { saveAs } from 'file-saver';
import { SortableTable } from "./sortableTable"
import { quantityComparator, quantityFormatter } from "./units";
import { AttritionInfo, getQuantityPrice } from "./jlc"
Expand Down Expand Up @@ -302,6 +303,47 @@ export class ComponentOverview extends React.Component {
this.setState({stockRequired: stockRequired});
}

// get text content from a react element object
extractText(element) {
// Check if the element is a simple string or number and return it as text
if (typeof element === 'string' || typeof element === 'number') {
return String(element);
}

// If the element has props and children, dive deeper
if (element && element.props && element.props.children) {
if (Array.isArray(element.props.children)) {
// If children is an array, recursively extract text from each child
return element.props.children.map(child => this.extractText(child)).join(' ');
} else {
// If children is a single element, recursively extract its text
return this.extractText(element.props.children);
}
}

// If we reach here, the element does not contain directly extractable text
return '';
}

downloadComponents(components, header) {
let headerContent = header.map(cell => `"${cell.name}"`).join(',');
let csvContent = components.map((row, index) => {
// expandableContent={this.props.expandableContent(row)}>
let csvRow = header.map(cell => {
if (cell.name === "Image") {
return `"${cell.displayGetter(row)?.props?.src || ''}"`;
} else {
return '"' + this.extractText(cell.displayGetter(row)).trim().replace('"', "'") + '"';
}
}).join(',');

return csvRow;
}).join('\n');

const blob = new Blob([`${headerContent}\n${csvContent}`], { type: "text/csv;charset=utf-8" });
saveAs(blob, `components-${components.length}.csv`);
}

render() {
let filterComponents = <>
<CategoryFilter
Expand Down Expand Up @@ -505,11 +547,16 @@ export class ComponentOverview extends React.Component {
? <div className="pt-4" id="results">
<div className="w-full flex py-2">
<p className="flex-none p-2">Components matching query: {filteredComponents.length}</p>
<CopyToClipboard text={filteredComponents.map(c => `wget ${c.datasheet}`).join("\n")}>
<button className="flex-none ml-auto block flex-none bg-blue-500 hover:bg-blue-700 text-black py-1 px-2 rounded" onClick={e => e.stopPropagation()}>
wget all datasheets <FontAwesomeIcon icon="clipboard"/>
<div className="flex-none ml-auto block flex-none">
<CopyToClipboard text={filteredComponents.map(c => `wget ${c.datasheet}`).join("\n")}>
<button className="bg-blue-500 hover:bg-blue-700 text-black py-2 px-2 mr-2 rounded" onClick={e => e.stopPropagation()}>
wget all datasheets <FontAwesomeIcon icon="clipboard"/>
</button>
</CopyToClipboard>
<button className="bg-blue-500 hover:bg-blue-700 text-black py-2 px-2 rounded" onClick={() => this.downloadComponents(filteredComponents, header)}>
Download CSV <FontAwesomeIcon icon="download"/>
</button>
</CopyToClipboard>
</div>
</div>
<SortableTable
className="w-full"
Expand Down