forked from MapComplete/MapComplete
Refactoring: Histogram now uses chartJS, simplify code
This commit is contained in:
parent
3918e5ec04
commit
6ae258c48d
9 changed files with 92 additions and 314 deletions
|
|
@ -119,7 +119,7 @@ export class WikimediaImageProvider extends ImageProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceIcon(): BaseUIElement {
|
SourceIcon(): BaseUIElement {
|
||||||
return new SvelteUIElement(Wikimedia_commons_white).SetStyle("width:2em;height: 2em")
|
return new SvelteUIElement(Wikimedia_commons_white)
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrepUrl(value: NonNullable<string>): ProvidedImage
|
public PrepUrl(value: NonNullable<string>): ProvidedImage
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,10 @@ import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
|
||||||
import { TagUtils } from "../../Logic/Tags/TagUtils"
|
import { TagUtils } from "../../Logic/Tags/TagUtils"
|
||||||
import { OsmFeature } from "../../Models/OsmFeature"
|
import { OsmFeature } from "../../Models/OsmFeature"
|
||||||
import { Utils } from "../../Utils"
|
import { Utils } from "../../Utils"
|
||||||
|
import { labels } from "wikibase-sdk/dist/src/helpers/simplify"
|
||||||
|
import { isInteger } from "tailwind-merge/dist/lib/validators"
|
||||||
|
|
||||||
export class ChartJsColours {
|
class ChartJsColours {
|
||||||
public static readonly unknownColor = "rgba(128, 128, 128, 0.2)"
|
public static readonly unknownColor = "rgba(128, 128, 128, 0.2)"
|
||||||
public static readonly unknownBorderColor = "rgba(128, 128, 128, 0.2)"
|
public static readonly unknownBorderColor = "rgba(128, 128, 128, 0.2)"
|
||||||
|
|
||||||
|
|
@ -205,7 +207,7 @@ export class ChartJsUtils {
|
||||||
hideUnknown?: boolean
|
hideUnknown?: boolean
|
||||||
hideNotApplicable?: boolean
|
hideNotApplicable?: boolean
|
||||||
}
|
}
|
||||||
) {
|
): ChartConfiguration {
|
||||||
const { labels, data } = ChartJsUtils.extractDataAndLabels(tr, features, {
|
const { labels, data } = ChartJsUtils.extractDataAndLabels(tr, features, {
|
||||||
sort: true,
|
sort: true,
|
||||||
groupToOtherCutoff: options?.groupToOtherCutoff,
|
groupToOtherCutoff: options?.groupToOtherCutoff,
|
||||||
|
|
@ -336,7 +338,7 @@ export class ChartJsUtils {
|
||||||
* @returns undefined if not enough parameters
|
* @returns undefined if not enough parameters
|
||||||
*/
|
*/
|
||||||
static createConfigForTagRendering<T extends { properties: Record<string, string> }>(tagRendering: TagRenderingConfig, features: T[],
|
static createConfigForTagRendering<T extends { properties: Record<string, string> }>(tagRendering: TagRenderingConfig, features: T[],
|
||||||
options?: TagRenderingChartOptions){
|
options?: TagRenderingChartOptions): ChartConfiguration{
|
||||||
if (tagRendering.mappings?.length === 0 && tagRendering.freeform?.key === undefined) {
|
if (tagRendering.mappings?.length === 0 && tagRendering.freeform?.key === undefined) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
@ -380,7 +382,7 @@ export class ChartJsUtils {
|
||||||
barchartMode = true
|
barchartMode = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = <ChartConfiguration>{
|
return <ChartConfiguration>{
|
||||||
type: options?.chartType ?? (barchartMode ? "bar" : "pie"),
|
type: options?.chartType ?? (barchartMode ? "bar" : "pie"),
|
||||||
data: {
|
data: {
|
||||||
labels,
|
labels,
|
||||||
|
|
@ -402,7 +404,49 @@ export class ChartJsUtils {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return config
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static createHistogramConfig(keys: string[], counts: Map<string, number>){
|
||||||
|
|
||||||
|
const borderColor = [
|
||||||
|
]
|
||||||
|
const backgroundColor = [
|
||||||
|
]
|
||||||
|
|
||||||
|
while (borderColor.length < keys.length) {
|
||||||
|
borderColor.push(...ChartJsColours.borderColors)
|
||||||
|
backgroundColor.push(...ChartJsColours.backgroundColors)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <ChartConfiguration>{
|
||||||
|
type: "bar",
|
||||||
|
data: {
|
||||||
|
labels: keys,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
data: keys.map((k) => counts.get(k)),
|
||||||
|
backgroundColor,
|
||||||
|
borderColor,
|
||||||
|
borderWidth: 1,
|
||||||
|
label: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: { scales: {
|
||||||
|
y: {
|
||||||
|
ticks: {
|
||||||
|
stepSize: 1,
|
||||||
|
callback: (value) =>Number(value).toFixed(0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,20 +10,6 @@ export class FixedUiElement extends BaseUIElement {
|
||||||
super()
|
super()
|
||||||
this.content = html ?? ""
|
this.content = html ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
AsMarkdown(): string {
|
|
||||||
if (this.HasClass("code")) {
|
|
||||||
if (this.content.indexOf("\n") > 0 || this.HasClass("block")) {
|
|
||||||
return "\n```\n" + this.content + "\n```\n"
|
|
||||||
}
|
|
||||||
return "`" + this.content + "`"
|
|
||||||
}
|
|
||||||
if (this.HasClass("font-bold")) {
|
|
||||||
return "*" + this.content + "*"
|
|
||||||
}
|
|
||||||
return this.content
|
|
||||||
}
|
|
||||||
|
|
||||||
protected InnerConstructElement(): HTMLElement {
|
protected InnerConstructElement(): HTMLElement {
|
||||||
const e = document.createElement("span")
|
const e = document.createElement("span")
|
||||||
e.innerHTML = Utils.purify(this.content)
|
e.innerHTML = Utils.purify(this.content)
|
||||||
|
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
import BaseUIElement from "../BaseUIElement"
|
|
||||||
import { Utils } from "../../Utils"
|
|
||||||
import Translations from "../i18n/Translations"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export default class Table extends BaseUIElement {
|
|
||||||
private readonly _header: BaseUIElement[]
|
|
||||||
private readonly _contents: BaseUIElement[][]
|
|
||||||
private readonly _contentStyle: string[][]
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
header: (BaseUIElement | string)[],
|
|
||||||
contents: (BaseUIElement | string)[][],
|
|
||||||
options?: {
|
|
||||||
contentStyle?: string[][]
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
super()
|
|
||||||
this._contentStyle = options?.contentStyle ?? [["min-width: 9rem"]]
|
|
||||||
this._header = header?.map(Translations.W)
|
|
||||||
this._contents = contents.map((row) => row.map(Translations.W))
|
|
||||||
}
|
|
||||||
|
|
||||||
protected InnerConstructElement(): HTMLElement {
|
|
||||||
const table = document.createElement("table")
|
|
||||||
|
|
||||||
const headerElems = Utils.NoNull(
|
|
||||||
(this._header ?? []).map((elem) => elem.ConstructElement())
|
|
||||||
)
|
|
||||||
if (headerElems.length > 0) {
|
|
||||||
const thead = document.createElement("thead")
|
|
||||||
|
|
||||||
const tr = document.createElement("tr")
|
|
||||||
headerElems.forEach((headerElem) => {
|
|
||||||
const td = document.createElement("th")
|
|
||||||
td.appendChild(headerElem)
|
|
||||||
tr.appendChild(td)
|
|
||||||
})
|
|
||||||
thead.appendChild(tr)
|
|
||||||
table.appendChild(thead)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < this._contents.length; i++) {
|
|
||||||
const row = this._contents[i]
|
|
||||||
const tr = document.createElement("tr")
|
|
||||||
for (let j = 0; j < row.length; j++) {
|
|
||||||
try {
|
|
||||||
const elem = row[j]
|
|
||||||
if (elem?.ConstructElement === undefined) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const htmlElem = elem?.ConstructElement()
|
|
||||||
if (htmlElem === undefined) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
let style = undefined
|
|
||||||
if (
|
|
||||||
this._contentStyle !== undefined &&
|
|
||||||
this._contentStyle[i] !== undefined &&
|
|
||||||
this._contentStyle[j] !== undefined
|
|
||||||
) {
|
|
||||||
style = this._contentStyle[i][j]
|
|
||||||
}
|
|
||||||
|
|
||||||
const td = document.createElement("td")
|
|
||||||
td.style.cssText = style
|
|
||||||
td.appendChild(htmlElem)
|
|
||||||
tr.appendChild(td)
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Could not render an element in a table due to", e, row[j])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
table.appendChild(tr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return table
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -13,16 +13,6 @@ export default abstract class BaseUIElement {
|
||||||
protected readonly clss: Set<string> = new Set<string>()
|
protected readonly clss: Set<string> = new Set<string>()
|
||||||
protected style: string
|
protected style: string
|
||||||
private _onClick: () => void | Promise<void>
|
private _onClick: () => void | Promise<void>
|
||||||
|
|
||||||
public onClick(f: () => void) {
|
|
||||||
this._onClick = f
|
|
||||||
this.SetClass("cursor-pointer")
|
|
||||||
if (this._constructedHtmlElement !== undefined) {
|
|
||||||
this._constructedHtmlElement.onclick = f
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
AttachTo(divId: string) {
|
AttachTo(divId: string) {
|
||||||
const element = document.getElementById(divId)
|
const element = document.getElementById(divId)
|
||||||
if (element === null) {
|
if (element === null) {
|
||||||
|
|
@ -75,11 +65,6 @@ export default abstract class BaseUIElement {
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
public HasClass(clss: string): boolean {
|
|
||||||
return this.clss.has(clss)
|
|
||||||
}
|
|
||||||
|
|
||||||
public SetStyle(style: string): this {
|
public SetStyle(style: string): this {
|
||||||
this.style = style
|
this.style = style
|
||||||
if (this._constructedHtmlElement !== undefined) {
|
if (this._constructedHtmlElement !== undefined) {
|
||||||
|
|
|
||||||
35
src/UI/BigComponents/Histogram.svelte
Normal file
35
src/UI/BigComponents/Histogram.svelte
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { Utils } from "../../Utils"
|
||||||
|
import type { ChartConfiguration } from "chart.js"
|
||||||
|
import ChartJs from "../Base/ChartJs.svelte"
|
||||||
|
import { ChartJsUtils } from "../Base/ChartJsUtils"
|
||||||
|
|
||||||
|
export let values: Store<string[]>
|
||||||
|
let counts: Store<Map<string, number>> = values.map(
|
||||||
|
(values) => {
|
||||||
|
if (values === undefined) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
values = Utils.NoNull(values)
|
||||||
|
const counts = new Map<string, number>()
|
||||||
|
for (const value of values) {
|
||||||
|
const c = counts.get(value) ?? 0
|
||||||
|
counts.set(value, c + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return counts
|
||||||
|
})
|
||||||
|
|
||||||
|
let max: Store<number> = counts.mapD(counts => Math.max(...Array.from(counts.values())))
|
||||||
|
let keys: Store<string> = counts.mapD(counts => {
|
||||||
|
const keys = Utils.Dedup(counts.keys())
|
||||||
|
keys.sort(/*inplace sort*/)
|
||||||
|
return keys
|
||||||
|
})
|
||||||
|
let config: Store<ChartConfiguration> = keys.mapD(keys => ChartJsUtils.createHistogramConfig(keys, counts.data), [counts])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $config}
|
||||||
|
<ChartJs config={$config} />
|
||||||
|
{/if}
|
||||||
|
|
@ -1,157 +0,0 @@
|
||||||
import { VariableUiElement } from "../Base/VariableUIElement"
|
|
||||||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
|
||||||
import Table from "../Base/Table"
|
|
||||||
import Combine from "../Base/Combine"
|
|
||||||
import { FixedUiElement } from "../Base/FixedUiElement"
|
|
||||||
import { Utils } from "../../Utils"
|
|
||||||
import BaseUIElement from "../BaseUIElement"
|
|
||||||
import SvelteUIElement from "../Base/SvelteUIElement"
|
|
||||||
import Circle from "../../assets/svg/Circle.svelte"
|
|
||||||
import ChevronUp from "@babeard/svelte-heroicons/solid/ChevronUp"
|
|
||||||
import ChevronDown from "@babeard/svelte-heroicons/solid/ChevronDown"
|
|
||||||
|
|
||||||
export default class Histogram extends VariableUiElement {
|
|
||||||
private static defaultPalette = [
|
|
||||||
"#ff5858",
|
|
||||||
"#ffad48",
|
|
||||||
"#ffff59",
|
|
||||||
"#56bd56",
|
|
||||||
"#63a9ff",
|
|
||||||
"#9d62d9",
|
|
||||||
"#fa61fa",
|
|
||||||
]
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
values: Store<string[]>,
|
|
||||||
title: string | BaseUIElement,
|
|
||||||
countTitle: string | BaseUIElement,
|
|
||||||
options?: {
|
|
||||||
assignColor?: (t0: string) => string
|
|
||||||
sortMode?: "name" | "name-rev" | "count" | "count-rev"
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
const sortMode = new UIEventSource<"name" | "name-rev" | "count" | "count-rev">(
|
|
||||||
options?.sortMode ?? "name"
|
|
||||||
)
|
|
||||||
const sortName = new VariableUiElement(
|
|
||||||
sortMode.map((m) => {
|
|
||||||
switch (m) {
|
|
||||||
case "name":
|
|
||||||
return new SvelteUIElement(ChevronUp)
|
|
||||||
case "name-rev":
|
|
||||||
return new SvelteUIElement(ChevronDown)
|
|
||||||
default:
|
|
||||||
return new SvelteUIElement(Circle)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
const titleHeader = new Combine([sortName.SetClass("w-4 mr-2"), title])
|
|
||||||
.SetClass("flex")
|
|
||||||
.onClick(() => {
|
|
||||||
if (sortMode.data === "name") {
|
|
||||||
sortMode.setData("name-rev")
|
|
||||||
} else {
|
|
||||||
sortMode.setData("name")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const sortCount = new VariableUiElement(
|
|
||||||
sortMode.map((m) => {
|
|
||||||
switch (m) {
|
|
||||||
case "count":
|
|
||||||
return new SvelteUIElement(ChevronUp)
|
|
||||||
case "count-rev":
|
|
||||||
return new SvelteUIElement(ChevronDown)
|
|
||||||
default:
|
|
||||||
return new SvelteUIElement(Circle)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
const countHeader = new Combine([sortCount.SetClass("w-4 mr-2"), countTitle])
|
|
||||||
.SetClass("flex")
|
|
||||||
.onClick(() => {
|
|
||||||
if (sortMode.data === "count-rev") {
|
|
||||||
sortMode.setData("count")
|
|
||||||
} else {
|
|
||||||
sortMode.setData("count-rev")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const header = [titleHeader, countHeader]
|
|
||||||
|
|
||||||
super(
|
|
||||||
values.map(
|
|
||||||
(values) => {
|
|
||||||
if (values === undefined) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
values = Utils.NoNull(values)
|
|
||||||
|
|
||||||
const counts = new Map<string, number>()
|
|
||||||
for (const value of values) {
|
|
||||||
const c = counts.get(value) ?? 0
|
|
||||||
counts.set(value, c + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const keys = Array.from(counts.keys())
|
|
||||||
|
|
||||||
switch (sortMode.data) {
|
|
||||||
case "name":
|
|
||||||
keys.sort()
|
|
||||||
break
|
|
||||||
case "name-rev":
|
|
||||||
keys.sort().reverse(/*Copy of array, inplace reverse if fine*/)
|
|
||||||
break
|
|
||||||
case "count":
|
|
||||||
keys.sort((k0, k1) => counts.get(k0) - counts.get(k1))
|
|
||||||
break
|
|
||||||
case "count-rev":
|
|
||||||
keys.sort((k0, k1) => counts.get(k1) - counts.get(k0))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
const max = Math.max(...Array.from(counts.values()))
|
|
||||||
|
|
||||||
const fallbackColor = (keyValue: string) => {
|
|
||||||
const index = keys.indexOf(keyValue)
|
|
||||||
return Histogram.defaultPalette[index % Histogram.defaultPalette.length]
|
|
||||||
}
|
|
||||||
let actualAssignColor = undefined
|
|
||||||
if (options?.assignColor === undefined) {
|
|
||||||
actualAssignColor = fallbackColor
|
|
||||||
} else {
|
|
||||||
actualAssignColor = (keyValue: string) => {
|
|
||||||
return options.assignColor(keyValue) ?? fallbackColor(keyValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Table(
|
|
||||||
header,
|
|
||||||
keys.map((key) => [
|
|
||||||
key,
|
|
||||||
new Combine([
|
|
||||||
new Combine([
|
|
||||||
new FixedUiElement("" + counts.get(key)).SetClass(
|
|
||||||
"font-bold rounded-full block"
|
|
||||||
),
|
|
||||||
])
|
|
||||||
.SetClass("flex justify-center rounded border border-black")
|
|
||||||
.SetStyle(
|
|
||||||
`background: ${actualAssignColor(key)}; width: ${
|
|
||||||
(100 * counts.get(key)) / max
|
|
||||||
}%`
|
|
||||||
),
|
|
||||||
]).SetClass("block w-full"),
|
|
||||||
]),
|
|
||||||
{
|
|
||||||
contentStyle: keys.map(() => ["width: 20%"]),
|
|
||||||
}
|
|
||||||
).SetClass("w-full zebra-table")
|
|
||||||
},
|
|
||||||
[sortMode]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||||
import { SpecialVisualization, SpecialVisualizationState } from "../SpecialVisualization"
|
import { SpecialVisualization, SpecialVisualizationState } from "../SpecialVisualization"
|
||||||
import Histogram from "../BigComponents/Histogram"
|
|
||||||
import { Feature } from "geojson"
|
import { Feature } from "geojson"
|
||||||
|
import SvelteUIElement from "../Base/SvelteUIElement"
|
||||||
|
import Histogram from "../BigComponents/Histogram.svelte"
|
||||||
|
|
||||||
export class HistogramViz extends SpecialVisualization {
|
export class HistogramViz extends SpecialVisualization {
|
||||||
funcName = "histogram"
|
funcName = "histogram"
|
||||||
|
|
@ -15,21 +16,8 @@ export class HistogramViz extends SpecialVisualization {
|
||||||
name: "key",
|
name: "key",
|
||||||
doc: "The key to be read and to generate a histogram from",
|
doc: "The key to be read and to generate a histogram from",
|
||||||
required: true,
|
required: true,
|
||||||
},
|
}
|
||||||
{
|
|
||||||
name: "title",
|
|
||||||
doc: "This text will be placed above the texts (in the first column of the visulasition)",
|
|
||||||
defaultValue: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "countHeader",
|
|
||||||
doc: "This text will be placed above the bars",
|
|
||||||
defaultValue: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "colors*",
|
|
||||||
doc: "(Matches all resting arguments - optional) Matches a regex onto a color value, e.g. `3[a-zA-Z+-]*:#33cc33`",
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
structuredExamples(): { feature: Feature; args: string[] }[] {
|
structuredExamples(): { feature: Feature; args: string[] }[] {
|
||||||
|
|
@ -53,27 +41,7 @@ export class HistogramViz extends SpecialVisualization {
|
||||||
tagSource: UIEventSource<Record<string, string>>,
|
tagSource: UIEventSource<Record<string, string>>,
|
||||||
args: string[]
|
args: string[]
|
||||||
) {
|
) {
|
||||||
let assignColors = undefined
|
const values: Store<string[]> = tagSource.map((tags) => {
|
||||||
if (args.length >= 3) {
|
|
||||||
const colors = [...args]
|
|
||||||
colors.splice(0, 3)
|
|
||||||
const mapping = colors.map((c) => {
|
|
||||||
const splitted = c.split(":")
|
|
||||||
const value = splitted.pop()
|
|
||||||
const regex = splitted.join(":")
|
|
||||||
return { regex: "^" + regex + "$", color: value }
|
|
||||||
})
|
|
||||||
assignColors = (key) => {
|
|
||||||
for (const kv of mapping) {
|
|
||||||
if (key.match(kv.regex) !== null) {
|
|
||||||
return kv.color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const listSource: Store<string[]> = tagSource.map((tags) => {
|
|
||||||
const value = tags[args[0]]
|
const value = tags[args[0]]
|
||||||
try {
|
try {
|
||||||
if (value === "" || value === undefined) {
|
if (value === "" || value === undefined) {
|
||||||
|
|
@ -88,8 +56,6 @@ export class HistogramViz extends SpecialVisualization {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return new Histogram(listSource, args[1], args[2], {
|
return new SvelteUIElement(Histogram, { values })
|
||||||
assignColor: assignColors,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -295,7 +295,7 @@ export class Translation extends BaseUIElement {
|
||||||
tr["_context"] = this.context
|
tr["_context"] = this.context
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Translation(tr, copyContext ? this.context : null)
|
return new Translation(tr, copyContext ? this.context : undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue