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.
268 lines (245 loc) • 8.26 kB
text/typescript
import { PropertyValueMap, html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { DatasetInput } from "./helper-components/DatasetInput/DatasetInput";
import { Settings } from "./helper-components/Settings";
import { ScatterDatasetInput } from "./helper-components/ScatterDatasetInput/ScatterDatasetInput";
import "@shoelace-style/shoelace/dist/themes/light.css";
import SlSwitch from "@shoelace-style/shoelace/dist/components/switch/switch.js";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
import SlButton from "@shoelace-style/shoelace/dist/components/button/button.js";
import SlCheckbox from "@shoelace-style/shoelace/dist/components/checkbox/checkbox.js";
import SlAlert from "@shoelace-style/shoelace/dist/components/alert/alert.component.js";
import style from "./widget.style";
import {
ChartType,
getChart,
getOptionsDefinition,
} from "./helper-components/Charts/imports";
import { LitElementWw } from "@webwriter/lit";
import { BarChart } from "./helper-components/Charts/Bar/chart";
import { DoughnutChart } from "./helper-components/Charts/Doughnut/chart";
import { LineChart } from "./helper-components/Charts/Line/chart";
import { PieChart } from "./helper-components/Charts/Pie/chart";
import { PolarChart } from "./helper-components/Charts/PolarArea/chart";
import { RadarChart } from "./helper-components/Charts/Radar/chart";
import { ScatterplotChart } from "./helper-components/Charts/Scatterplot/scatterplot";
import SlTabGroup from "@shoelace-style/shoelace/dist/components/tab-group/tab-group.component.js";
import SlTab from "@shoelace-style/shoelace/dist/components/tab/tab.component.js";
import { ChartState } from "./interfaces";
("webwriter-chart")
export class WwChart extends LitElementWw {
constructor() {
super();
console.debug("Constructor: webwriter-chart created");
}
({ type: Object, attribute: true, reflect: true })
accessor sharedState: ChartState = {
teacherOptions: {
showOptions: true,
showData: true,
showLockedOptions: true,
changeData: true,
changeOptions: true,
addRemoveData: true,
},
lineDatasets: {
sets: [],
},
scatterDatasets: {
title: "My Scatterplot",
sets: [],
selected: {
axis: {
x: "None",
y: "None",
},
dataset_indexes: [],
},
},
regressionType: "none",
chart: {
selectedType: "Scatterplot",
title: "My fancy Chart",
datasets: {
labels: ["Red", "Blue", "Free", "Green", "Purple", "Orange"],
sets: [
{
name: "My First Dataset",
color: "#ff00d0",
colors: [
"#FF6384",
"#36A2EB",
"#FFCE56",
"#4BC0C0",
"#9966FF",
"rgb(255, 159, 64)",
],
data: [12, 19, 8, 5, 20, 13],
},
],
},
options: {},
optionsLocked: {},
optionDefinition: {},
},
editable: true,
};
/**WebWriter API: If true, emit DOM events enriched with xAPI statements. */
({ type: Boolean, attribute: true, reflect: true })
accessor analyzable: boolean;
({ type: Boolean, attribute: true, reflect: true })
accessor showChart: boolean;
({ type: Boolean, attribute: true, reflect: true })
accessor showData: boolean;
()
accessor lastChartType: ChartType = this.sharedState.chart.selectedType;
({ type: Boolean, attribute: true, reflect: true })
accessor showErrorMessage = false;
connectedCallback(): void {
super.connectedCallback();
this.addEventListener("wwci-state-change", (e: CustomEvent) => {
this.onStateChange(e);
});
}
disconnectedCallback(): void {
super.disconnectedCallback();
this.removeEventListener("wwci-state-change", this.onStateChange);
}
protected firstUpdated(
_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>
): void {
//this.addEventListener("click", (ev) => this.focus());
this.initializeDefaultOptions();
this.tabIndex = -1;
}
initializeDefaultOptions() {
this.showChart = true;
this.showData = false;
}
protected onStateChange(e: CustomEvent) {
if (!e.detail || !e.detail.state) {
console.debug("No state to update. Detail is missing or incomplete.");
return;
}
this.sharedState = {
...this.sharedState,
...e.detail.state,
};
e.stopPropagation();
e.cancelBubble = true;
}
render() {
this.sharedState.editable = this.isContentEditable;
this.sharedState.chart.optionDefinition = getOptionsDefinition(
this.sharedState.chart.selectedType
);
return html` <div
part="options"
id="settings"
style=${this.isContentEditable ? "" : "display: none;"}
>
<div id="settings-wrapper">
<h2>Settings</h2>
<wwci-chart-settings
.sharedState=${this.sharedState}
@wwci-state-change=${this.onStateChange}
style="display: contents;"
></wwci-chart-settings>
</div>
</div>
<div
id="main"
@selectstart=${(e: any) => {
e.stopPropagation();
}}
@dragstart=${(e: any) => {
e.stopPropagation();
}}
@click=${() =>
this.dispatchEvent(new FocusEvent("focus", { bubbles: true }))}
>
<!-- <div id="button-group"> -->
<sl-tab-group>
<sl-tab
slot="nav"
panel="chart"
@click=${() => {
this.showChart = true;
this.showData = false;
requestAnimationFrame(() => {
window.getSelection().empty();
});
}}
.active=${this.showChart}
>Chart</sl-tab
>
<sl-tab
slot="nav"
panel="data"
@click=${() => {
this.showChart = false;
this.showData = true;
requestAnimationFrame(() => {
window.getSelection().empty();
});
}}
>Data</sl-tab
>
</sl-tab-group>
<!-- </div> -->
${this.showData &&
(this.sharedState.editable || this.sharedState.teacherOptions.showData)
? html`<div id="data-panel">
${this.sharedState.chart.selectedType === "Scatterplot"
? html`<wwci-scatterdataset-input
.sharedState=${this.sharedState}
@wwci-state-change=${this.onStateChange}
></wwci-scatterdataset-input>`
: html`<wwci-dataset-input
.sharedState=${this.sharedState}
@wwci-state-change=${this.onStateChange}
></wwci-dataset-input>`}
</div>`
: html`
<div id="display-chart">
${getChart(
this.sharedState.chart.selectedType,
this.sharedState.chart.datasets,
this.sharedState.chart.title,
this.sharedState.chart.options,
this.sharedState.teacherOptions,
this.onStateChange,
this.sharedState
)}
</div>
`}
</div>`;
}
static styles = style;
public static get scopedElements() {
return {
"sl-button": SlButton,
"sl-switch": SlSwitch,
"sl-input": SlInput,
"sl-checkbox": SlCheckbox,
"wwci-dataset-input": DatasetInput,
"wwci-chart-settings": Settings,
"bar-chart": BarChart,
"doughnut-chart": DoughnutChart,
"line-chart": LineChart,
"pie-chart": PieChart,
"polar-chart": PolarChart,
"radar-chart": RadarChart,
"scatterplot-chart": ScatterplotChart,
"wwci-scatterdataset-input": ScatterDatasetInput,
"sl-tab-group": SlTabGroup,
"sl-tab": SlTab,
"sl-alert": SlAlert,
};
}
}
declare global {
interface HTMLElementTagNameMap {
"webwriter-chart": WwChart;
}
}