|
| 1 | +import ControlsHandler from "../../pages/view/toolbar/ControlsHandler.js"; |
| 2 | +import ExportHandler from "../../pages/view/toolbar/ExportHandler.js"; |
| 3 | +import { getGeneratorOptions } from "../../pages/editor/utils/editorActions.js"; |
| 4 | + |
| 5 | +export default class ScrollTable { |
| 6 | + static defaultConfig = { |
| 7 | + type: "ScrollTable", |
| 8 | + title: "Table", |
| 9 | + generator: { id: "" }, |
| 10 | + options: { |
| 11 | + numbers: true, |
| 12 | + }, |
| 13 | + icon: "bi bi-table", |
| 14 | + w: 6, |
| 15 | + h: 6, |
| 16 | + }; |
| 17 | + static formConfig = { |
| 18 | + title: { |
| 19 | + type: "text", |
| 20 | + label: "Title", |
| 21 | + }, |
| 22 | + "generator.id": { |
| 23 | + type: "select", |
| 24 | + label: "Generator", |
| 25 | + options: () => getGeneratorOptions("CategoryNumber"), |
| 26 | + }, |
| 27 | + "options.numbers": { |
| 28 | + type: "switch", |
| 29 | + label: "Row numbers", |
| 30 | + }, |
| 31 | + }; |
| 32 | + static previewData = [ |
| 33 | + ["Heading 1", "Heading 2", "Heading 3"], |
| 34 | + ["Cell 4", "Cell 5", "Cell 6"], |
| 35 | + ["Cell 7", "Cell 8", "Cell 9"], |
| 36 | + ["Cell 10", "Cell 11", "Cell 12"], |
| 37 | + ["Cell 13", "Cell 14", "Cell 15"], |
| 38 | + ["Cell 16", "Cell 17", "Cell 18"], |
| 39 | + ["Cell 19", "Cell 20", "Cell 21"], |
| 40 | + ["Cell 22", "Cell 23", "Cell 24"], |
| 41 | + ["Cell 25", "Cell 26", "Cell 27"], |
| 42 | + ["Cell 28", "Cell 29", "Cell 30"], |
| 43 | + ["Cell 31", "Cell 32", "Cell 33"], |
| 44 | + ]; |
| 45 | + |
| 46 | + constructor(root, config) { |
| 47 | + this.root = d3.select(root); |
| 48 | + this.config = config; |
| 49 | + |
| 50 | + this.setTitle(this.config.title); |
| 51 | + |
| 52 | + this.div = this.root.select(".dv-chart-area").append("div"); |
| 53 | + this.data = null; |
| 54 | + |
| 55 | + this.filter = {}; |
| 56 | + this.controls = new ControlsHandler(this); |
| 57 | + this.exports = new ExportHandler(this); |
| 58 | + |
| 59 | + this.numbers = config.options.numbers || true; |
| 60 | + } |
| 61 | + |
| 62 | + setTitle(title) { |
| 63 | + this.root.select(".dv-toolbar-title").attr("title", title).text(title); |
| 64 | + } |
| 65 | + |
| 66 | + async fetch() { |
| 67 | + return await d3.json("/data/table.json"); |
| 68 | + } |
| 69 | + |
| 70 | + clear() { |
| 71 | + this.div.selectAll("*").remove(); |
| 72 | + this.div |
| 73 | + .style("width", "100%") |
| 74 | + .style("height", "100%") |
| 75 | + .style("overflow-y", "auto"); |
| 76 | + } |
| 77 | + |
| 78 | + async init() { |
| 79 | + const data = await this.fetch(); |
| 80 | + this.render(data); |
| 81 | + |
| 82 | + this.filter = { |
| 83 | + sort: data[0][0], |
| 84 | + desc: true, |
| 85 | + }; |
| 86 | + this.controls.append([ |
| 87 | + { |
| 88 | + type: "select", |
| 89 | + label: "Sort by", |
| 90 | + value: this.filter.sort, |
| 91 | + options: data[0], |
| 92 | + onchange: (event) => { |
| 93 | + this.filter.sort = event.target.value; |
| 94 | + this.fetch().then((data) => this.render(data)); |
| 95 | + }, |
| 96 | + }, |
| 97 | + { |
| 98 | + type: "switch", |
| 99 | + label: "Desc", |
| 100 | + value: this.filter.desc, |
| 101 | + onchange: (event) => { |
| 102 | + this.filter.desc = event.target.checked; |
| 103 | + this.fetch().then((data) => this.render(data)); |
| 104 | + }, |
| 105 | + }, |
| 106 | + ]); |
| 107 | + } |
| 108 | + |
| 109 | + render(data) { |
| 110 | + this.clear(); |
| 111 | + |
| 112 | + let rows = data; |
| 113 | + if (this.numbers) { |
| 114 | + rows = data.map((row, i) => [i, ...row]); |
| 115 | + rows[0][0] = "#"; |
| 116 | + } |
| 117 | + |
| 118 | + const table = this.div.append("table").attr("class", "dv-scroll-table"); |
| 119 | + |
| 120 | + // Append table head (first row) |
| 121 | + table |
| 122 | + .append("thead") |
| 123 | + .append("tr") |
| 124 | + .selectAll("th") |
| 125 | + .data(rows[0]) |
| 126 | + .join("th") |
| 127 | + .text((d) => d); |
| 128 | + |
| 129 | + // Append table body (remaining rows) |
| 130 | + table |
| 131 | + .append("tbody") |
| 132 | + .selectAll("tr") |
| 133 | + .data(rows.slice(1)) // skip header |
| 134 | + .join("tr") |
| 135 | + .selectAll("td") |
| 136 | + .data((d) => d) |
| 137 | + .join("td") |
| 138 | + .text((d) => d); |
| 139 | + |
| 140 | + // Cache rendered data |
| 141 | + this.data = data; |
| 142 | + } |
| 143 | +} |
0 commit comments