webwriter-chart
Version:
ww-chart is an interactive data visualization widget for the WebWriter tool that implements various charts and diagrams for static and exploratory data visualization.
226 lines (220 loc) • 9.78 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { html } from "lit";
import { customElement } from "lit/decorators.js";
import { csvToDataset, randomColor, randomNumber, randomString, readFileInput, } from "../../functions";
import style from "./DatasetInput.style";
import SlIconButton from "@shoelace-style/shoelace/dist/components/icon-button/icon-button.js";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
import SlColorPicker from "@shoelace-style/shoelace/dist/components/color-picker/color-picker.js";
import IconTrash from "bootstrap-icons/icons/trash.svg";
import IconPlusCircle from "bootstrap-icons/icons/plus-circle.svg";
import { SharedTestStateMixin } from "../../state";
import { FileUploadButton } from "../FileUploadButton";
import { LitElementWw } from "@webwriter/lit";
let DatasetInput = class DatasetInput extends SharedTestStateMixin(LitElementWw) {
addDataset() {
this.sharedState.chart.datasets.sets.push({
name: randomString(),
color: randomColor(),
colors: this.sharedState.chart.datasets.sets[0].colors,
data: Array(this.sharedState.chart.datasets.sets[0].data.length)
.fill("")
.map(() => randomNumber()),
});
}
addColumn() {
this.sharedState.chart.datasets.labels.push(randomString());
this.sharedState.chart.datasets.sets =
this.sharedState.chart.datasets.sets.map((dataset) => {
dataset.data.push(randomNumber());
dataset.colors.push(randomColor());
return dataset;
});
}
deleteColumn(i) {
this.sharedState.chart.datasets.labels.splice(i, 1);
this.sharedState.chart.datasets.sets =
this.sharedState.chart.datasets.sets.map((dataset) => {
dataset.data.splice(i, 1);
dataset.colors.splice(i, 1);
return dataset;
});
}
deleteDataset(i) {
this.sharedState.chart.datasets.sets.splice(i, 1);
}
render() {
if (this.sharedState.chart.datasets.sets.length === 0)
return html `<sl-button =${this.addDataset}>Add Dataset</sl-button>`;
return html `<div class="table-wrapper">
<div class="table-scroll-container">
<div class="table-layout-container">
<table>
<thead>
<tr>
<th>Labels</th>
${this.sharedState.chart.datasets.labels.map((label, i) => html `<th>
<div
style="display: flex; flex-direction: row; align-items: center"
>
<div class="input-wrapper">
<sl-input
?disabled=${!(this.sharedState.editable ||
this.sharedState.teacherOptions.changeData)}
type="text"
class="input"
value="${label}"
-input=${(e) => (this.sharedState.chart.datasets.labels[i] =
e.target.value)}
></sl-input>
</div>
${!this.sharedState.printable
? html `<sl-icon-button
?disabled=${!(this.sharedState.editable ||
this.sharedState.teacherOptions.addRemoveData)}
src=${IconTrash}
label="Settings"
=${() => this.deleteColumn(i)}
></sl-icon-button>`
: html ``}
</div>
</th>`)}
</tr>
</thead>
<tbody>
${this.sharedState.chart.datasets.sets.map((dataset, i) => html `
<tr>
<td>
<div
style="display: flex; flex-direction: row; align-items: center"
>
${!this.sharedState.printable
? html ` <sl-icon-button
?disabled=${!(this.sharedState.editable ||
this.sharedState.teacherOptions.addRemoveData)}
src=${IconTrash}
label="Settings"
=${() => this.deleteDataset(i)}
></sl-icon-button>`
: html ``}
<div class="input-wrapper">
<sl-input
?disabled=${!(this.sharedState.editable ||
this.sharedState.teacherOptions.changeData)}
id="input"
type="text"
class="input"
value="${dataset.name}"
-input=${(e) => (this.sharedState.chart.datasets.sets[i].name =
e.target.value)}
></sl-input>
</div>
${!this.sharedState.printable
? html `
<sl-color-picker
?disabled=${!(this.sharedState.editable ||
this.sharedState.teacherOptions.changeData)}
value="${this.sharedState.chart.datasets.sets[i]
.color}"
-input=${(e) => (this.sharedState.chart.datasets.sets[i].color = e.target.value)}
></sl-color-picker>
`
: html ``}
</div>
</td>
${dataset.data.map((value, j) => html `<td>
<div
style="display: flex; flex-direction: row; align-items: center"
>
<div class="input-wrapper">
<sl-input
?disabled=${!(this.sharedState.editable ||
this.sharedState.teacherOptions.changeData)}
id="input-${i}-${j}"
type="number"
class="input"
value="${value}"
-input=${(e) => (this.sharedState.chart.datasets.sets[i].data[j] = Number(e.target.value))}
></sl-input>
</div>
${!this.sharedState.printable
? html `<sl-color-picker
?disabled=${!(this.sharedState.editable ||
this.sharedState.teacherOptions.changeData)}
value="${this.sharedState.chart.datasets.sets[i].colors[j]}"
-input=${(e) => (this.sharedState.chart.datasets.sets[i].colors[j] = e.target.value)}
></sl-color-picker>`
: html ``}
</div>
</td>`)}
</tr>
`)}
</tbody>
</table>
${this.sharedState.editable ||
(this.sharedState.teacherOptions.addRemoveData &&
!this.sharedState.printable)
? html `
<sl-icon-button
=${this.addColumn}
src=${IconPlusCircle}
label="Add Column"
></sl-icon-button>
<sl-icon-button
=${this.addDataset}
src=${IconPlusCircle}
label="Add Dataset"
></sl-icon-button>
<br />
<wwci-file-upload-button
=${async (e) => {
const fileContent = await readFileInput(e.detail.value);
const { datasets, title } = csvToDataset(fileContent);
this.sharedState.chart.datasets = datasets;
if (title)
this.dispatchTitleUpdateEvent(title);
}}
></wwci-file-upload-button>
`
: html ``}
</div>
</div>
</div>`;
}
dispatchUpdateEvent() {
this.dispatchEvent(new CustomEvent("wwci-change", {
detail: {
value: this.sharedState.chart.datasets,
},
bubbles: false,
composed: true,
}));
}
dispatchTitleUpdateEvent(title) {
this.dispatchEvent(new CustomEvent("wwci-title-change", {
detail: {
value: title,
},
bubbles: false,
composed: true,
}));
}
static styles = style;
static get scopedElements() {
return {
"sl-icon-button": SlIconButton,
"sl-input": SlInput,
"sl-color-picker": SlColorPicker,
"wwci-file-upload-button": FileUploadButton,
};
}
};
DatasetInput = __decorate([
customElement("wwci-dataset-input")
], DatasetInput);
export { DatasetInput };