This commit is contained in:
David Larlet 2024-07-08 18:58:57 +00:00 committed by GitHub
commit bb803921c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 50 additions and 2 deletions

View file

@ -118,6 +118,10 @@
.icon-upload { .icon-upload {
background-position: -144px -97px; background-position: -144px -97px;
} }
.icon-download {
transform: rotate(180deg);
background-position: -146px -95px;
}
.icon-zoom { .icon-zoom {
background-position: -1px -49px; background-position: -1px -49px;
} }

View file

@ -1,7 +1,7 @@
import { DomEvent, DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js' import { DomEvent, DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js'
import { translate } from './i18n.js' import { translate } from './i18n.js'
import ContextMenu from './ui/contextmenu.js' import ContextMenu from './ui/contextmenu.js'
import { WithTemplate, loadTemplate } from './utils.js' import { WithTemplate, loadTemplate, downloadBlob } from './utils.js'
const TEMPLATE = ` const TEMPLATE = `
<table> <table>
@ -201,6 +201,13 @@ export default class TableEditor extends WithTemplate {
filterButton.addEventListener('click', () => this.map.browser.open('filters')) filterButton.addEventListener('click', () => this.map.browser.open('filters'))
actions.push(filterButton) actions.push(filterButton)
const downloadButton = loadTemplate(`
<button class="flat" type="button" data-ref="download">
<i class="icon icon-16 icon-download"></i>${translate('Download data')}
</button>`)
downloadButton.addEventListener('click', () => this.exportAsCSV())
actions.push(downloadButton)
this.map.fullPanel.open({ this.map.fullPanel.open({
content: this.table, content: this.table,
className: 'umap-table-editor', className: 'umap-table-editor',
@ -295,7 +302,7 @@ export default class TableEditor extends WithTemplate {
getSelectedRows() { getSelectedRows() {
return Array.from( return Array.from(
this.elements.body.querySelectorAll('input[type=checkbox]:checked') this.elements.body.querySelectorAll('input[type=checkbox]:checked')
).map((checkbox) => checkbox.parentNode.parentNode) ).map((checkbox) => checkbox.closest('tr'))
} }
getFocus() { getFocus() {
@ -331,4 +338,32 @@ export default class TableEditor extends WithTemplate {
} }
}) })
} }
_rowToCSV(row) {
console.log(row)
return row
.map((content) => content.replaceAll('"', '""')) // escape double quotes
.map((content) => `"${content}"`) // quote it
.join(',') // comma-separated
}
exportAsCSV() {
const headers = this._rowToCSV(
Array.from(this.elements.header.querySelectorAll('th'))
.slice(1) // Remove initial select-all checkbox column
.map((header) => header.textContent)
.map((header) => header.slice(0, -1)) // Remove trailing `…`
)
const rows = Array.from(this.elements.body.querySelectorAll('tr'))
.map((line) =>
Array.from(line.querySelectorAll('td')).map((cell) => cell.textContent)
)
.map(this._rowToCSV)
const csv = [headers, ...rows].join('\r\n')
downloadBlob(
csv,
`umap-export-${this.datalayer.umap_id}-${this.map.options.umap_id}.csv`,
'text/csv;charset=utf-8;'
)
}
} }

View file

@ -397,3 +397,12 @@ export class WithTemplate {
return this.element return this.element
} }
} }
export function downloadBlob(content, filename, contentType) {
const blob = new Blob([content], { type: contentType })
const url = URL.createObjectURL(blob)
const tmp = document.createElement('a')
tmp.href = url
tmp.setAttribute('download', filename)
tmp.click()
}