mirror of https://github.com/Budibase/budibase.git
45 changed files with 1229 additions and 3239 deletions
@ -0,0 +1,42 @@ |
|||
<script> |
|||
import { Multiselect } from "@budibase/bbui" |
|||
|
|||
export let options = [] |
|||
export let value = [] |
|||
export let styleBindingProperty |
|||
export let onChange = () => {} |
|||
|
|||
let boundValue = getValidOptions(value, options) |
|||
$: setValue(boundValue) |
|||
$: sanitiseOptions(options) |
|||
|
|||
function getValidOptions(selectedOptions, allOptions) { |
|||
// Fix the hardcoded default string value |
|||
if (!Array.isArray(selectedOptions)) { |
|||
selectedOptions = [] |
|||
} |
|||
return selectedOptions.filter(val => allOptions.indexOf(val) !== -1) |
|||
} |
|||
|
|||
function setValue(val) { |
|||
onChange(val) |
|||
} |
|||
|
|||
function sanitiseOptions(options) { |
|||
boundValue = getValidOptions(value, options) |
|||
} |
|||
</script> |
|||
|
|||
<div> |
|||
<Multiselect extraThin secondary bind:value={boundValue}> |
|||
{#each options as option} |
|||
<option value={option}>{option}</option> |
|||
{/each} |
|||
</Multiselect> |
|||
</div> |
|||
|
|||
<style> |
|||
div { |
|||
flex: 1 1 auto; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,5 @@ |
|||
<script> |
|||
import TableViewFieldSelect from "./TableViewFieldSelect.svelte" |
|||
</script> |
|||
|
|||
<TableViewFieldSelect {...$$props} multiselect /> |
|||
@ -0,0 +1,18 @@ |
|||
<script> |
|||
import { chart } from "svelte-apexcharts" |
|||
|
|||
export let options |
|||
</script> |
|||
|
|||
{#if options} |
|||
<div use:chart={options} /> |
|||
{:else if options === false} |
|||
<div>Invalid chart options</div> |
|||
{/if} |
|||
|
|||
<style> |
|||
div :global(.apexcharts-legend-series) { |
|||
display: flex !important; |
|||
text-transform: capitalize; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,154 @@ |
|||
export class ApexOptionsBuilder { |
|||
formatters = { |
|||
["Default"]: val => Math.round(val * 100) / 100, |
|||
["Thousands"]: val => `${Math.round(val / 1000)}K`, |
|||
["Millions"]: val => `${Math.round(val / 1000000)}M`, |
|||
} |
|||
options = { |
|||
series: [], |
|||
legend: { |
|||
show: false, |
|||
position: "top", |
|||
horizontalAlign: "right", |
|||
showForSingleSeries: true, |
|||
showForNullSeries: true, |
|||
showForZeroSeries: true, |
|||
}, |
|||
chart: { |
|||
toolbar: { |
|||
show: false, |
|||
}, |
|||
zoom: { |
|||
enabled: false, |
|||
}, |
|||
}, |
|||
yaxis: { |
|||
labels: { |
|||
formatter: this.formatters.Default, |
|||
}, |
|||
}, |
|||
} |
|||
|
|||
setOption(path, value) { |
|||
if (value == null || value === "") { |
|||
return this |
|||
} |
|||
let tmp = this.options |
|||
for (let i = 0; i < path.length - 1; i++) { |
|||
const step = path[i] |
|||
if (!tmp[step]) { |
|||
tmp[step] = {} |
|||
} |
|||
tmp = tmp[step] |
|||
} |
|||
tmp[path[path.length - 1]] = value |
|||
return this |
|||
} |
|||
|
|||
getOptions() { |
|||
return this.options |
|||
} |
|||
|
|||
type(type) { |
|||
return this.setOption(["chart", "type"], type) |
|||
} |
|||
|
|||
title(title) { |
|||
return this.setOption(["title", "text"], title) |
|||
} |
|||
|
|||
color(color) { |
|||
return this.setOption(["colors"], [color]) |
|||
} |
|||
|
|||
width(width) { |
|||
return this.setOption(["chart", "width"], width || undefined) |
|||
} |
|||
|
|||
height(height) { |
|||
return this.setOption(["chart", "height"], height || undefined) |
|||
} |
|||
|
|||
xLabel(label) { |
|||
return this.setOption(["xaxis", "title", "text"], label) |
|||
} |
|||
|
|||
yLabel(label) { |
|||
return this.setOption(["yaxis", "title", "text"], label) |
|||
} |
|||
|
|||
categories(categories) { |
|||
return this.setOption(["xaxis", "categories"], categories) |
|||
} |
|||
|
|||
series(series) { |
|||
return this.setOption(["series"], series) |
|||
} |
|||
|
|||
horizontal(horizontal) { |
|||
return this.setOption(["plotOptions", "bar", "horizontal"], horizontal) |
|||
} |
|||
|
|||
dataLabels(dataLabels) { |
|||
return this.setOption(["dataLabels", "enabled"], dataLabels) |
|||
} |
|||
|
|||
animate(animate) { |
|||
return this.setOption(["chart", "animations", "enabled"], animate) |
|||
} |
|||
|
|||
curve(curve) { |
|||
return this.setOption(["stroke", "curve"], curve) |
|||
} |
|||
|
|||
gradient(gradient) { |
|||
const fill = { |
|||
type: "gradient", |
|||
gradient: { |
|||
shadeIntensity: 1, |
|||
opacityFrom: 0.7, |
|||
opacityTo: 0.9, |
|||
stops: [0, 90, 100], |
|||
}, |
|||
} |
|||
return this.setOption(["fill"], gradient ? fill : undefined) |
|||
} |
|||
|
|||
legend(legend) { |
|||
return this.setOption(["legend", "show"], legend) |
|||
} |
|||
|
|||
legendPosition(position) { |
|||
return this.setOption(["legend", "position"], position) |
|||
} |
|||
|
|||
stacked(stacked) { |
|||
return this.setOption(["chart", "stacked"], stacked) |
|||
} |
|||
|
|||
labels(labels) { |
|||
return this.setOption(["labels"], labels) |
|||
} |
|||
|
|||
yUnits(units) { |
|||
return this.setOption( |
|||
["yaxis", "labels", "formatter"], |
|||
this.formatters[units || "Default"] |
|||
) |
|||
} |
|||
|
|||
xType(type) { |
|||
return this.setOption(["xaxis", "type"], type) |
|||
} |
|||
|
|||
yTooltip(yTooltip) { |
|||
return this.setOption(["yaxis", "tooltip", "enabled"], yTooltip) |
|||
} |
|||
|
|||
palette(palette) { |
|||
return this.setOption( |
|||
["theme", "palette"], |
|||
palette.toLowerCase().replace(/[\W]/g, "") |
|||
) |
|||
} |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
<script> |
|||
import LineChart from "./LineChart.svelte" |
|||
</script> |
|||
|
|||
<LineChart {...$$props} area /> |
|||
@ -1,187 +0,0 @@ |
|||
<script> |
|||
import { |
|||
getColorSchema, |
|||
getChartGradient, |
|||
notNull, |
|||
hasProp, |
|||
} from "./utils.js" |
|||
import britecharts from "britecharts" |
|||
import fetchData from "../fetchData.js" |
|||
import { onMount } from "svelte" |
|||
import { isEmpty } from "lodash/fp" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
let tooltip |
|||
const _id = shortid.generate() |
|||
const chart = britecharts.bar() |
|||
const chartClass = `bar-container-${_id}` |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
let tooltipContainer = null |
|||
|
|||
export let customMouseOver = () => tooltip.show() |
|||
export let customMouseMove = (datapoint, colorMapping, x, y) => |
|||
tooltip.update(datapoint, colorMapping, x, y) |
|||
export let customMouseOut = () => tooltip.hide() |
|||
export let customClick = null |
|||
|
|||
let data = [] |
|||
export let datasource = null |
|||
export let xAxisLabel = "" |
|||
export let yAxisLabel = "" |
|||
export let betweenBarsPadding = 0.1 //takes decimal values 0.1, 0.5 etc |
|||
export let gradient = null |
|||
export let color = "britecharts" |
|||
export let enableLabels = false |
|||
export let hasPercentage = null |
|||
export let hasSingleBarHighlight = true |
|||
export let highlightBarFunction = null |
|||
export let height = 200 |
|||
export let width = 300 |
|||
export let labelsMargin = null |
|||
export let isAnimated = true |
|||
export let isHorizontal = true |
|||
export let xAxisLabelOffset = null |
|||
export let yAxisLabelOffset = null |
|||
export let labelsNumberFormat = null |
|||
export let locale = null |
|||
export let valueLabel = null |
|||
export let nameLabel = null |
|||
export let numberFormat = null |
|||
export let labelsSize = null |
|||
export let xTicks = null |
|||
export let yTicks = null |
|||
export let percentageAxisToMaxRatio = null |
|||
|
|||
onMount(async () => { |
|||
if (!isEmpty(datasource)) { |
|||
data = await fetchData(datasource) |
|||
|
|||
if (schemaIsValid()) { |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(data).call(chart) |
|||
bindChartTooltip() |
|||
} else { |
|||
console.error("Bar Chart - Please provide a valid name and value label") |
|||
} |
|||
} |
|||
}) |
|||
|
|||
const schemaIsValid = () => |
|||
(hasProp(data, "name") || hasProp(data, nameLabel)) && |
|||
(hasProp(data, "value") || hasProp(data, valueLabel)) |
|||
|
|||
function bindChartUIProps() { |
|||
chart.numberFormat(".0f") |
|||
chart.labelsNumberFormat(".1f") |
|||
|
|||
if (notNull(color)) { |
|||
chart.colorSchema(colorSchema) |
|||
} |
|||
if (notNull(gradient)) { |
|||
chart.chartGradient(chartGradient) |
|||
} |
|||
if (notNull(xAxisLabel)) { |
|||
chart.xAxisLabel(xAxisLabel) |
|||
} |
|||
if (notNull(yAxisLabel)) { |
|||
chart.yAxisLabel(yAxisLabel) |
|||
} |
|||
if (notNull(betweenBarsPadding)) { |
|||
chart.betweenBarsPadding(Number(betweenBarsPadding)) |
|||
} |
|||
if (notNull(enableLabels)) { |
|||
chart.enableLabels(enableLabels) |
|||
} |
|||
if (notNull(hasPercentage)) { |
|||
chart.hasPercentage(hasPercentage) |
|||
} |
|||
if (notNull(hasSingleBarHighlight)) { |
|||
chart.hasSingleBarHighlight(hasSingleBarHighlight) |
|||
} |
|||
if (notNull(labelsMargin)) { |
|||
chart.labelsMargin(labelsMargin) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(highlightBarFunction)) { |
|||
chart.highlightBarFunction(highlightBarFunction) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(isAnimated)) { |
|||
chart.isAnimated(isAnimated) |
|||
} |
|||
if (notNull(isHorizontal)) { |
|||
chart.isHorizontal(isHorizontal) |
|||
} |
|||
if (notNull(yAxisLabelOffset)) { |
|||
chart.yAxisLabelOffset(yAxisLabelOffset) |
|||
} |
|||
if (notNull(xAxisLabelOffset)) { |
|||
chart.xAxisLabelOffset(Number(xAxisLabelOffset)) |
|||
} |
|||
if (notNull(labelsNumberFormat)) { |
|||
chart.labelsNumberFormat(labelsNumberFormat) |
|||
} |
|||
if (notNull(valueLabel)) { |
|||
chart.valueLabel(valueLabel) |
|||
} |
|||
if (notNull(locale)) { |
|||
chart.locale(locale) |
|||
} |
|||
if (notNull(nameLabel)) { |
|||
chart.nameLabel(nameLabel) |
|||
} |
|||
if (notNull(numberFormat)) { |
|||
chart.numberFormat(numberFormat) |
|||
} |
|||
if (notNull(labelsSize)) { |
|||
chart.labelsSize(labelsSize) |
|||
} |
|||
if (notNull(xTicks)) { |
|||
chart.xTicks(xTicks) |
|||
} |
|||
if (notNull(yTicks)) { |
|||
chart.yTicks(yTicks) |
|||
} |
|||
if (notNull(percentageAxisToMaxRatio)) { |
|||
chart.percentageAxisToMaxRatio(percentageAxisToMaxRatio) |
|||
} |
|||
chartContainer.datum(data).call(chart) |
|||
} |
|||
|
|||
function bindChartEvents() { |
|||
if (customMouseMove) { |
|||
chart.on("customMouseMove", customMouseMove) |
|||
} |
|||
if (customMouseOut) { |
|||
chart.on("customMouseOut", customMouseOut) |
|||
} |
|||
if (customMouseOver) { |
|||
chart.on("customMouseOver", customMouseOver) |
|||
} |
|||
if (customClick) { |
|||
chart.on("customClick", customClick) |
|||
} |
|||
} |
|||
|
|||
function bindChartTooltip() { |
|||
tooltip = britecharts.miniTooltip() |
|||
tooltip.numberFormat(".0f") |
|||
tooltipContainer = select(`.${chartClass} .metadata-group`) |
|||
tooltipContainer.datum([]).call(tooltip) |
|||
} |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
$: chartGradient = getChartGradient(gradient) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
@ -0,0 +1,99 @@ |
|||
<script> |
|||
import { onMount } from "svelte" |
|||
import fetchData, { fetchSchema } from "../fetchData" |
|||
import { ApexOptionsBuilder } from "./ApexOptionsBuilder" |
|||
import ApexChart from "./ApexChart.svelte" |
|||
import { isEmpty } from "lodash/fp" |
|||
import { |
|||
closeColumn, |
|||
dateColumn, |
|||
highColumn, |
|||
lowColumn, |
|||
openColumn, |
|||
} from "./CandleStickChart.svelte" |
|||
|
|||
export let _bb |
|||
export let title |
|||
export let datasource |
|||
export let labelColumn |
|||
export let valueColumns |
|||
export let xAxisLabel |
|||
export let yAxisLabel |
|||
export let height |
|||
export let width |
|||
export let color |
|||
export let dataLabels |
|||
export let animate |
|||
export let legend |
|||
export let stacked |
|||
export let yAxisUnits |
|||
export let palette |
|||
|
|||
const store = _bb.store |
|||
let options |
|||
|
|||
// Fetch data on mount |
|||
onMount(async () => { |
|||
const allCols = [labelColumn, ...(valueColumns || [])] |
|||
if (isEmpty(datasource) || allCols.find(x => x == null)) { |
|||
options = false |
|||
return |
|||
} |
|||
|
|||
// Fetch, filter and sort data |
|||
const schema = await fetchSchema(datasource.tableId) |
|||
const result = await fetchData(datasource, $store) |
|||
const reducer = row => (valid, column) => valid && row[column] != null |
|||
const hasAllColumns = row => allCols.reduce(reducer(row), true) |
|||
const data = result |
|||
.filter(row => hasAllColumns(row)) |
|||
.slice(0, 20) |
|||
.sort((a, b) => (a[labelColumn] > b[labelColumn] ? 1 : -1)) |
|||
if (!schema || !data.length) { |
|||
options = false |
|||
return |
|||
} |
|||
|
|||
// Initialise default chart |
|||
let builder = new ApexOptionsBuilder() |
|||
.type("bar") |
|||
.title(title) |
|||
.width(width) |
|||
.height(height) |
|||
.xLabel(xAxisLabel) |
|||
.yLabel(yAxisLabel) |
|||
.dataLabels(dataLabels) |
|||
.animate(animate) |
|||
.legend(legend) |
|||
.stacked(stacked) |
|||
.yUnits(yAxisUnits) |
|||
.palette(palette) |
|||
|
|||
// Add data |
|||
let useDates = false |
|||
if (datasource.type !== "view" && schema[labelColumn]) { |
|||
const labelFieldType = schema[labelColumn].type |
|||
builder = builder.xType(labelFieldType) |
|||
useDates = labelFieldType === "datetime" |
|||
} |
|||
const series = valueColumns.map(column => ({ |
|||
name: column, |
|||
data: data.map(row => { |
|||
if (!useDates) { |
|||
return row[column] |
|||
} else { |
|||
return [row[labelColumn], row[column]] |
|||
} |
|||
}), |
|||
})) |
|||
builder = builder.series(series) |
|||
if (!useDates) { |
|||
builder = builder.categories(data.map(row => row[labelColumn])) |
|||
} |
|||
|
|||
// Build chart options |
|||
options = builder.getOptions() |
|||
}) |
|||
</script> |
|||
|
|||
<ApexChart {options} /> |
|||
@ -1,118 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull } from "./utils" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
/* |
|||
ISSUES |
|||
- Chart gradient doesn't seem to do anything |
|||
*/ |
|||
|
|||
export let _bb |
|||
export let table |
|||
|
|||
let store = _bb.store |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
const chart = britecharts.brush() |
|||
const chartClass = `brush-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
|
|||
export let customBrushEnd = null |
|||
export let customBrushStart = null |
|||
|
|||
export let data = [] |
|||
export let gradient = null |
|||
export let height = 200 |
|||
export let width = 200 |
|||
export let margin = { top: 0, right: 0, bottom: 0, left: 0 } |
|||
|
|||
export let dateRange = null |
|||
export let locale = null |
|||
export let roundingTimeInterval = null |
|||
export let xAxisFormat = null |
|||
export let xTicks = null |
|||
export let xAxisCustomFormat = null |
|||
|
|||
onMount(async () => { |
|||
if (chart) { |
|||
if (table) { |
|||
await fetchData() |
|||
} |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(_data).call(chart) |
|||
} |
|||
}) |
|||
|
|||
async function fetchData() { |
|||
const FETCH_ROWS_URL = `/api/views/all_${table}` |
|||
const response = await _bb.api.get(FETCH_ROWS_URL) |
|||
if (response.status === 200) { |
|||
const json = await response.json() |
|||
store.update(state => { |
|||
state[table] = json |
|||
return state |
|||
}) |
|||
} else { |
|||
throw new Error("Failed to fetch rows.", response) |
|||
} |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
if (notNull(gradient)) { |
|||
chart.gradient(chartGradient) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(margin)) { |
|||
chart.margin(margin) |
|||
} |
|||
if (notNull(dateRange)) { |
|||
chart.dateRange(dateRange) |
|||
} |
|||
if (notNull(locale)) { |
|||
chart.locale(locale) |
|||
} |
|||
if (notNull(roundingTimeInterval)) { |
|||
chart.roundingTimeInterval(roundingTimeInterval) |
|||
} |
|||
if (notNull(xAxisFormat)) { |
|||
chart.xAxisFormat(xAxisFormat) |
|||
} |
|||
if (notNull(xTicks)) { |
|||
chart.xTicks(xTicks) |
|||
} |
|||
if (notNull(xAxisCustomFormat)) { |
|||
chart.xAxisCustomFormat(xAxisCustomFormat) |
|||
} |
|||
} |
|||
|
|||
function bindChartEvents() { |
|||
if (customBrushEnd) { |
|||
chart.on("customBrushEnd", customBrushEnd) |
|||
} |
|||
if (customBrushStart) { |
|||
chart.on("customBrushStart", customBrushStart) |
|||
} |
|||
} |
|||
|
|||
$: _data = table ? $store[table] : data |
|||
|
|||
$: chartGradient = getChartGradient(gradient) |
|||
$: console.log(chartGradient) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
@ -1,103 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull } from "./utils" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
export let _bb |
|||
export let table |
|||
|
|||
let store = _bb.store |
|||
|
|||
const chart = britecharts.bullet() |
|||
const chartClass = `bullet-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
|
|||
export let data = [] |
|||
export let aspectRatio = null |
|||
export let color = "britecharts" |
|||
export let customSubtitle = null |
|||
export let customTitle = null |
|||
export let numberFormat = null |
|||
export let paddingBetweenAxisAndChart = null |
|||
export let startMaxRangeOpacity = null |
|||
export let ticks = null |
|||
export let isReverse = false |
|||
export let height = 200 |
|||
export let width = 200 |
|||
export let margin = { top: 0, right: 0, bottom: 0, left: 0 } |
|||
|
|||
onMount(async () => { |
|||
if (chart) { |
|||
if (table) { |
|||
await fetchData() |
|||
} |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
chartContainer.datum(_data).call(chart) |
|||
} |
|||
}) |
|||
|
|||
async function fetchData() { |
|||
const FETCH_ROWS_URL = `/api/views/all_${table}` |
|||
const response = await _bb.api.get(FETCH_ROWS_URL) |
|||
if (response.status === 200) { |
|||
const json = await response.json() |
|||
store.update(state => { |
|||
state[table] = json |
|||
return state |
|||
}) |
|||
} else { |
|||
throw new Error("Failed to fetch rows.", response) |
|||
} |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
if (notNull(color)) { |
|||
chart.colorSchema(colorSchema) |
|||
} |
|||
if (notNull(aspectRatio)) { |
|||
chart.aspectRatio(aspectRatio) |
|||
} |
|||
if (notNull(customSubtitle)) { |
|||
chart.customSubtitle(customSubtitle) |
|||
} |
|||
if (notNull(customTitle)) { |
|||
chart.customTitle(customTitle) |
|||
} |
|||
if (notNull(numberFormat)) { |
|||
chart.numberFormat(numberFormat) |
|||
} |
|||
if (notNull(paddingBetweenAxisAndChart)) { |
|||
chart.paddingBetweenAxisAndChart(paddingBetweenAxisAndChart) |
|||
} |
|||
if (notNull(startMaxRangeOpacity)) { |
|||
chart.startMaxRangeOpacity(startMaxRangeOpacity) |
|||
} |
|||
if (notNull(ticks)) { |
|||
chart.ticks(ticks) |
|||
} |
|||
if (notNull(isReverse)) { |
|||
chart.isReverse(isReverse) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
} |
|||
|
|||
$: _data = table ? $store[table] : data |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
@ -0,0 +1,74 @@ |
|||
<script> |
|||
import { onMount } from "svelte" |
|||
import fetchData, { fetchSchema } from "../fetchData" |
|||
import { ApexOptionsBuilder } from "./ApexOptionsBuilder" |
|||
import ApexChart from "./ApexChart.svelte" |
|||
import { isEmpty } from "lodash/fp" |
|||
|
|||
export let _bb |
|||
export let title |
|||
export let datasource |
|||
export let dateColumn |
|||
export let openColumn |
|||
export let highColumn |
|||
export let lowColumn |
|||
export let closeColumn |
|||
export let xAxisLabel |
|||
export let yAxisLabel |
|||
export let height |
|||
export let width |
|||
export let animate |
|||
export let yAxisUnits |
|||
|
|||
const store = _bb.store |
|||
let options |
|||
|
|||
// Fetch data on mount |
|||
onMount(async () => { |
|||
const allCols = [dateColumn, openColumn, highColumn, lowColumn, closeColumn] |
|||
if (isEmpty(datasource) || allCols.find(x => x == null)) { |
|||
options = false |
|||
return |
|||
} |
|||
|
|||
// Fetch, filter and sort data |
|||
const schema = await fetchSchema(datasource.tableId) |
|||
const result = await fetchData(datasource, $store) |
|||
const reducer = row => (valid, column) => valid && row[column] != null |
|||
const hasAllColumns = row => allCols.reduce(reducer(row), true) |
|||
const data = result |
|||
.filter(row => hasAllColumns(row)) |
|||
.slice(0, 100) |
|||
.sort((a, b) => (a[dateColumn] > b[dateColumn] ? 1 : -1)) |
|||
if (!schema || !data.length) { |
|||
options = false |
|||
return |
|||
} |
|||
|
|||
// Initialise default chart |
|||
let builder = new ApexOptionsBuilder() |
|||
.type("candlestick") |
|||
.title(title) |
|||
.width(width) |
|||
.height(height) |
|||
.xLabel(xAxisLabel) |
|||
.yLabel(yAxisLabel) |
|||
.animate(animate) |
|||
.yUnits(yAxisUnits) |
|||
.yTooltip(true) |
|||
.xType("datetime") |
|||
|
|||
// Add data |
|||
const parseDate = d => (isNaN(d) ? Date.parse(d).valueOf() : parseInt(d)) |
|||
const chartData = data.map(row => ({ |
|||
x: parseDate(row[dateColumn]), |
|||
y: [row[openColumn], row[highColumn], row[lowColumn], row[closeColumn]], |
|||
})) |
|||
builder = builder.series([{ data: chartData }]) |
|||
|
|||
// Build chart options |
|||
options = builder.getOptions() |
|||
}) |
|||
</script> |
|||
|
|||
<ApexChart {options} /> |
|||
@ -1,169 +0,0 @@ |
|||
<script context="module"> |
|||
//expose chart types for use or reference outside compnent |
|||
export const chartTypes = britecharts ? Object.keys(britecharts) : null |
|||
|
|||
//expose chart color schemas for use or reference outside compnent |
|||
export const colorSchemas = britecharts |
|||
? britecharts.colors.colorSchemas |
|||
: null |
|||
|
|||
//export color gradients for use or reference outside the component |
|||
export const colorGradients = britecharts |
|||
? britecharts.colors.colorGradients |
|||
: null |
|||
|
|||
export const getColorSchema = color => |
|||
color ? colorSchemas[color] : colorSchemas["britecharts"] |
|||
|
|||
export const getChartGradient = gradient => |
|||
gradient ? colorGradients[gradient] : null |
|||
</script> |
|||
|
|||
<script> |
|||
import { beforeUpdate } from "svelte" |
|||
import britecharts from "britecharts" |
|||
import { select } from "d3-selection" |
|||
|
|||
import { onMount } from "svelte" |
|||
import shortid from "shortid" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
export let type = "bar" |
|||
export let data = [] |
|||
export let tooltipProps = null |
|||
export let legendProps = null |
|||
export let useTooltip = false |
|||
export let useLegend = false |
|||
|
|||
export let tooltip = null //can bind to outside the component and therefore access |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
let tooltipContainer = null |
|||
let legendContainer = null |
|||
let legend = null |
|||
|
|||
let chart = chartTypes.includes(type) ? britecharts[type]() : null |
|||
|
|||
const chartClass = `chart-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
onMount(() => { |
|||
if (chart) { |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(data).call(chart) |
|||
bindChartTooltip() |
|||
bindChartLegend() |
|||
} else { |
|||
console.error("Britecharts could not be found") |
|||
} |
|||
}) |
|||
|
|||
function bindChartTooltip() { |
|||
if (useTooltip) { |
|||
tooltip = britecharts.miniTooltip() |
|||
|
|||
bindProps(tooltip, tooltipProps) |
|||
|
|||
tooltipContainer = select(`.${chartClass} .metadata-group`) |
|||
tooltipContainer.datum([]).call(tooltip) |
|||
} |
|||
} |
|||
|
|||
function bindChartLegend() { |
|||
if (useLegend) { |
|||
if (!Array.isArray(data)) { |
|||
console.warn("Cannot use legend as data is not an array") |
|||
return |
|||
} |
|||
|
|||
let excludeProps = [] |
|||
|
|||
legend = britecharts.legend() |
|||
|
|||
if (!legendProps || !legendProps.width) { |
|||
excludeProps = ["width"] |
|||
legend.width(chart.width()) |
|||
} |
|||
|
|||
if (legendProps) { |
|||
bindProps(legend, legendProps, excludeProps) |
|||
} |
|||
|
|||
legendContainer = select(`.${legendClass}`) |
|||
legendContainer.datum(data).call(legend) |
|||
} |
|||
} |
|||
|
|||
function bindChartEvents() { |
|||
if ($$props.on) { |
|||
const events = Object.entries($$props.on) |
|||
for (let [type, fn] of events) { |
|||
if (fn) { |
|||
chart.on(type, fn) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
const excludeProps = [ |
|||
"data", |
|||
"type", |
|||
"on", |
|||
"useTooltip", |
|||
"tooltip", |
|||
"tooltipProps", |
|||
"legendProps", |
|||
"useLegend", |
|||
] |
|||
|
|||
if (!$$props.width) { |
|||
chart.width(chartElement.getBoundingClientRect().width) |
|||
} |
|||
|
|||
bindProps(chart, $$props, excludeProps) |
|||
} |
|||
|
|||
function bindProps(element, elProps, excludeArray) { |
|||
if (elProps) { |
|||
const props = excludeArray |
|||
? Object.entries(excludeProps(elProps, excludeArray)) |
|||
: Object.entries(elProps) |
|||
|
|||
const validElementProps = Object.getOwnPropertyNames(element) |
|||
|
|||
for (let [prop, value] of props) { |
|||
if (validElementProps.includes(prop)) { |
|||
if (!!value) { |
|||
chart[prop](value) |
|||
} |
|||
} else { |
|||
console.warn( |
|||
`${type} - ${prop} is an unrecognised chart prop and wont be applied` |
|||
) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
function excludeProps(props, propsToExclude) { |
|||
const modifiedProps = {} |
|||
for (const prop in props) { |
|||
if (!propsToExclude.includes(prop)) { |
|||
modifiedProps[prop] = props[prop] |
|||
} |
|||
} |
|||
return modifiedProps |
|||
} |
|||
|
|||
$: validChartProps = chart ? Object.getOwnPropertyNames(chart) : null |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
{#if useLegend} |
|||
<div class={legendClass} /> |
|||
{/if} |
|||
@ -1,213 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, notNull } from "./utils.js" |
|||
import fetchData from "../fetchData.js" |
|||
import Legend from "./Legend.svelte" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
import { isEmpty } from "lodash/fp" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
const chart = britecharts.donut() |
|||
const chartClass = `donut-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
let legendChart |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
|
|||
let chartSvgWidth = 0 |
|||
let chartSvg = null |
|||
|
|||
export let _bb |
|||
|
|||
let store = _bb.store |
|||
|
|||
export let customMouseMove = null |
|||
export let customClick = null |
|||
|
|||
export let orderingFunction = null |
|||
|
|||
let data = [] |
|||
export let datasource = {} |
|||
|
|||
export let color = "britecharts" |
|||
export let height = 200 |
|||
export let width = 200 |
|||
export let margin = null |
|||
|
|||
export let centeredTextFunction = null |
|||
export let externalRadius = 25 |
|||
export let percentageFormat = null |
|||
export let hasFixedHighlightedSlice = false |
|||
export let hasLastHoverSliceHighlighted = false |
|||
export let hasHoverAnimation = true |
|||
export let highlightSliceById = null |
|||
export let numberFormat = null |
|||
export let internalRadius = 25 |
|||
export let isAnimated = true |
|||
export let radiusHoverOffset = 0 |
|||
export let nameKey = null |
|||
export let valueKey = null |
|||
// export let useLegend = true |
|||
export let horizontalLegend = false |
|||
export let legendWidth = null |
|||
export let legendHeight = null |
|||
|
|||
onMount(async () => { |
|||
if (chart) { |
|||
if (!isEmpty(datasource)) { |
|||
let _data = await fetchData(datasource) |
|||
data = checkAndReformatData(_data) |
|||
if (data.length === 0) { |
|||
console.error( |
|||
"Donut - please provide a valid name and value field for the chart" |
|||
) |
|||
} |
|||
} |
|||
|
|||
chart.emptyDataConfig({ |
|||
showEmptySlice: true, |
|||
emptySliceColor: "#F0F0F0", |
|||
}) |
|||
|
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(data).call(chart) |
|||
} |
|||
}) |
|||
|
|||
function checkAndReformatData(data) { |
|||
let _data = [...data] |
|||
|
|||
if (valueKey && valueKey !== "quantity") { |
|||
_data = reformatDataKey(_data, valueKey, "quantity") |
|||
} |
|||
|
|||
if (nameKey && nameKey !== "name") { |
|||
_data = reformatDataKey(_data, nameKey, "name") |
|||
} |
|||
|
|||
return _data.every(d => d.quantity) && _data.every(d => d.name) ? _data : [] |
|||
} |
|||
|
|||
function reformatDataKey(data = [], dataKey = null, formatKey = null) { |
|||
let ignoreList = ["_id", "_rev", "id"] |
|||
if (dataKey && data.every(d => d[dataKey])) { |
|||
return data.map(d => { |
|||
let clonedRow = { ...d } |
|||
if (clonedRow[formatKey]) { |
|||
delete clonedRow[formatKey] |
|||
} |
|||
let value = clonedRow[dataKey] |
|||
if (!ignoreList.includes(dataKey)) { |
|||
delete clonedRow[dataKey] |
|||
} |
|||
clonedRow[formatKey] = value |
|||
return clonedRow |
|||
}) |
|||
} else { |
|||
return data |
|||
} |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
chart.percentageFormat(".0f") |
|||
|
|||
if (notNull(color)) { |
|||
chart.colorSchema(getColorSchema(color)) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(margin)) { |
|||
chart.margin(margin) |
|||
} |
|||
if (notNull(centeredTextFunction)) { |
|||
chart.centeredTextFunction(centeredTextFunction) |
|||
} |
|||
if (notNull(externalRadius)) { |
|||
chart.externalRadius(externalRadius) |
|||
} |
|||
if (notNull(percentageFormat)) { |
|||
chart.percentageFormat(percentageFormat) |
|||
} |
|||
if (notNull(hasFixedHighlightedSlice)) { |
|||
chart.hasFixedHighlightedSlice(hasFixedHighlightedSlice) |
|||
} |
|||
if (notNull(hasLastHoverSliceHighlighted)) { |
|||
chart.hasLastHoverSliceHighlighted(hasLastHoverSliceHighlighted) |
|||
} |
|||
if (notNull(hasHoverAnimation)) { |
|||
chart.hasHoverAnimation(hasHoverAnimation) |
|||
} |
|||
if (notNull(highlightSliceById)) { |
|||
chart.highlightSliceById(highlightSliceById) |
|||
} |
|||
if (notNull(numberFormat)) { |
|||
chart.numberFormat(numberFormat) |
|||
} |
|||
if (notNull(internalRadius)) { |
|||
chart.internalRadius(internalRadius) |
|||
} |
|||
if (notNull(isAnimated)) { |
|||
chart.isAnimated(isAnimated) |
|||
} |
|||
if (notNull(radiusHoverOffset)) { |
|||
chart.radiusHoverOffset(radiusHoverOffset) |
|||
} |
|||
if (notNull(orderingFunction)) { |
|||
chart.orderingFunction(orderingFunction) |
|||
} |
|||
chartContainer.datum(data).call(chart) |
|||
chartSvg = document.querySelector(`.${chartClass} .britechart`) |
|||
} |
|||
|
|||
function bindChartEvents() { |
|||
if (customClick) { |
|||
chart.on("customClick", customClick) |
|||
} |
|||
if (customMouseMove) { |
|||
chart.on("customMouseMove", customMouseMove) |
|||
} |
|||
|
|||
if (legendChart) { |
|||
chart.on("customMouseOut", function() { |
|||
legendChart.clearHighlight() |
|||
}) |
|||
chart.on("customMouseOver", function(data) { |
|||
legendChart.highlight(data.data.id) |
|||
}) |
|||
} |
|||
} |
|||
|
|||
$: if (!width && chartSvg) { |
|||
width = chartSvg.clientWidth |
|||
chart.width(width) |
|||
chartContainer.datum(data).call(chart) |
|||
} |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
</script> |
|||
|
|||
<div> |
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
{#if data.length > 0} |
|||
<Legend |
|||
bind:legend={legendChart} |
|||
{colorSchema} |
|||
useLegend |
|||
isHorizontal={horizontalLegend} |
|||
width={legendWidth || width} |
|||
height={legendHeight} |
|||
{chartClass} |
|||
{data} /> |
|||
{/if} |
|||
</div> |
|||
@ -0,0 +1,5 @@ |
|||
<script> |
|||
import PieChart from "./PieChart.svelte" |
|||
</script> |
|||
|
|||
<PieChart {...$$props} donut /> |
|||
@ -1,145 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull, hasProp } from "./utils" |
|||
import Tooltip from "./Tooltip.svelte" |
|||
import fetchData from "../fetchData.js" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
import { isEmpty } from "lodash/fp" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
const chart = britecharts.groupedBar() |
|||
const chartClass = `groupedbar-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
let tooltip = britecharts.tooltip() |
|||
let tooltipContainer |
|||
let chartElement = null |
|||
let chartContainer = null |
|||
|
|||
export let customClick = null |
|||
|
|||
let data = [] |
|||
export let datasource = {} |
|||
export let color = "britecharts" |
|||
export let height = 200 |
|||
export let width = 200 |
|||
export let margin = null |
|||
export let aspectRatio = null |
|||
export let grid = null |
|||
export let groupLabel = null |
|||
export let isAnimated = null |
|||
export let isHorizontal = null |
|||
export let nameLabel = null |
|||
export let valueLabel = null |
|||
export let valueLabelFormat = null |
|||
export let xTicks = null |
|||
export let yAxisLabel = null |
|||
export let yAxisLabelOffset = null |
|||
export let yTicks = null |
|||
export let yTickTextOffset = null |
|||
export let tooltipTitle = "" |
|||
|
|||
const schemaIsValid = () => |
|||
(hasProp(data, "name") || hasProp(data, nameLabel)) && |
|||
(hasProp(data, "group") || hasProp(data, groupLabel)) && |
|||
(hasProp(data, "value") || hasProp(data, valueLabel)) |
|||
|
|||
onMount(async () => { |
|||
if (!isEmpty(datasource)) { |
|||
data = await fetchData(datasource) |
|||
if (schemaIsValid()) { |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(data).call(chart) |
|||
bindTooltip() |
|||
} else { |
|||
console.error( |
|||
"Grouped bar - Please provide valid name, value and group labels" |
|||
) |
|||
} |
|||
} |
|||
}) |
|||
|
|||
function bindTooltip() { |
|||
tooltipContainer = select(`.${chartClass} .metadata-group`) |
|||
tooltip.topicLabel("values") |
|||
tooltip.shouldShowDateInTitle(false) |
|||
tooltipContainer.datum([]).call(tooltip) |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
if (notNull(color)) { |
|||
chart.colorSchema(colorSchema) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(margin)) { |
|||
chart.margin(margin) |
|||
} |
|||
if (notNull(aspectRatio)) { |
|||
chart.aspectRatio(aspectRatio) |
|||
} |
|||
if (notNull(grid)) { |
|||
chart.grid(grid) |
|||
} |
|||
if (notNull(groupLabel)) { |
|||
chart.groupLabel(groupLabel) |
|||
} |
|||
if (notNull(isAnimated)) { |
|||
chart.isAnimated(isAnimated) |
|||
} |
|||
if (notNull(isHorizontal)) { |
|||
chart.isHorizontal(isHorizontal) |
|||
} |
|||
if (notNull(nameLabel)) { |
|||
chart.nameLabel(nameLabel) |
|||
} |
|||
if (notNull(valueLabel)) { |
|||
chart.valueLabel(valueLabel) |
|||
} |
|||
if (notNull(valueLabelFormat)) { |
|||
chart.valueLabelFormat(valueLabelFormat) |
|||
} |
|||
if (notNull(xTicks)) { |
|||
chart.xTicks(xTicks) |
|||
} |
|||
if (notNull(yAxisLabel)) { |
|||
chart.yAxisLabel(yAxisLabel) |
|||
} |
|||
if (notNull(yAxisLabelOffset)) { |
|||
chart.yAxisLabelOffset(yAxisLabelOffset) |
|||
} |
|||
if (notNull(yTicks)) { |
|||
chart.yTicks(yTicks) |
|||
} |
|||
if (notNull(yTickTextOffset)) { |
|||
chart.yTickTextOffset(yTickTextOffset) |
|||
} |
|||
if (notNull(tooltipTitle)) { |
|||
tooltip.title(tooltipTitle) |
|||
} else if (datasource.label) { |
|||
tooltip.title(datasource.label) |
|||
} |
|||
} |
|||
|
|||
function bindChartEvents() { |
|||
if (customClick) { |
|||
chart.on("customClick", customClick) |
|||
} |
|||
chart.on("customMouseMove", tooltip.update) |
|||
chart.on("customMouseOut", tooltip.hide) |
|||
chart.on("customMouseOver", tooltip.show) |
|||
} |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
@ -1,83 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull } from "./utils" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
export let _bb |
|||
export let table |
|||
|
|||
let store = _bb.store |
|||
|
|||
const chart = britecharts.heatmap() |
|||
const chartClass = `heatmap-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
|
|||
export let data = [] |
|||
export let color = "britecharts" |
|||
export let height = 200 |
|||
export let width = 200 |
|||
export let margin = { top: 0, right: 0, bottom: 0, left: 0 } |
|||
export let useLegend = true |
|||
export let yAxisLabels = null |
|||
export let boxSize = null |
|||
|
|||
onMount(async () => { |
|||
if (chart) { |
|||
if (table) { |
|||
await fetchData() |
|||
} |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
chartContainer.datum(data).call(chart) |
|||
} |
|||
}) |
|||
|
|||
async function fetchData() { |
|||
const FETCH_ROWS_URL = `/api/views/all_${table}` |
|||
const response = await _bb.api.get(FETCH_ROWS_URL) |
|||
if (response.status === 200) { |
|||
const json = await response.json() |
|||
store.update(state => { |
|||
state[table] = json |
|||
return state |
|||
}) |
|||
} else { |
|||
throw new Error("Failed to fetch rows.", response) |
|||
} |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
if (notNull(color)) { |
|||
chart.colorSchema(colorSchema) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(boxSize)) { |
|||
chart.boxSize(boxSize) |
|||
} |
|||
if (notNull(yAxisLabels)) { |
|||
chart.yAxisLabels(yAxisLabels) |
|||
} |
|||
} |
|||
|
|||
$: _data = table ? $store[table] : data |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
{#if useLegend} |
|||
<div class={legendClass} /> |
|||
{/if} |
|||
@ -1,86 +0,0 @@ |
|||
<script> |
|||
import britecharts from "britecharts" |
|||
import { notNull } from "./utils" |
|||
import { select } from "d3-selection" |
|||
import { onMount } from "svelte" |
|||
|
|||
export let useLegend = true |
|||
export let data = [] |
|||
export let width = null |
|||
export let height = null |
|||
export let colorSchema = null |
|||
export let highlight = null |
|||
export let highlightByEntryId = null |
|||
export let isHorizontal = false |
|||
export let margin = null |
|||
export let marginRatio = null |
|||
export let markerSize = null |
|||
export let numberFormat = null |
|||
export let unit = null |
|||
|
|||
export let legend = britecharts.legend() //exported it can be bound to |
|||
let legendContainer = null |
|||
let legendElement = null |
|||
|
|||
$: { |
|||
if (legendElement) { |
|||
legendContainer = select(legendElement) |
|||
legend.numberFormat(".0f") |
|||
|
|||
if (width) { |
|||
legend.width(width) |
|||
} |
|||
|
|||
if (notNull(height)) { |
|||
legend.height(height) |
|||
} |
|||
|
|||
if (notNull(colorSchema)) { |
|||
legend.colorSchema(colorSchema) |
|||
} |
|||
|
|||
if (notNull(highlight)) { |
|||
legend.highlight(highlight) |
|||
} |
|||
|
|||
if (notNull(highlightByEntryId)) { |
|||
legend.highlightByEntryId(highlightByEntryId) |
|||
} |
|||
|
|||
if (notNull(isHorizontal)) { |
|||
legend.isHorizontal(isHorizontal) |
|||
} |
|||
|
|||
if (notNull(margin)) { |
|||
legend.margin(margin) |
|||
} |
|||
|
|||
if (notNull(marginRatio)) { |
|||
legend.marginRatio(marginRatio) |
|||
} |
|||
|
|||
if (notNull(markerSize)) { |
|||
legend.markerSize(markerSize) |
|||
} |
|||
|
|||
if (notNull(numberFormat)) { |
|||
legend.numberFormat(numberFormat) |
|||
} |
|||
|
|||
if (notNull(unit)) { |
|||
legend.unit(unit) |
|||
} |
|||
|
|||
legendContainer.datum(data).call(legend) |
|||
} |
|||
} |
|||
|
|||
const legendClass = `legend-container` |
|||
</script> |
|||
|
|||
{#if useLegend} |
|||
<div |
|||
bind:this={legendElement} |
|||
style={`width: ${width}px`} |
|||
class={legendClass} /> |
|||
{/if} |
|||
@ -1,256 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull, hasProp } from "./utils" |
|||
import fetchData from "../fetchData.js" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
import { isEmpty } from "lodash/fp" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
export let datasource = {} |
|||
|
|||
const chart = britecharts.line() |
|||
const chartClass = `line-container-${_id}` |
|||
|
|||
let data = { dataByTopic: [] } |
|||
|
|||
let chartElement |
|||
let chartContainer |
|||
let tooltipContainer |
|||
|
|||
let tooltip = britecharts.tooltip() |
|||
|
|||
export let customMouseOver = () => tooltip.show() |
|||
export let customMouseMove = ( |
|||
dataPoint, |
|||
topicColorMap, |
|||
dataPointXPosition, |
|||
yPosition |
|||
) => { |
|||
tooltip.update(dataPoint, topicColorMap, dataPointXPosition, yPosition) |
|||
} |
|||
export let customMouseOut = () => tooltip.hide() |
|||
|
|||
export let customDataEntryClick = null |
|||
export let customTouchMove = null |
|||
|
|||
export let color = "britecharts" |
|||
export let axisTimeCombinations = "" |
|||
export let grid = "horizontal" |
|||
export let aspectRatio = 0.5 |
|||
export let width = null |
|||
export let height = null |
|||
export let isAnimated = true |
|||
export let lineCurve = "linear" //see api for possible opts |
|||
export let lineGradient = null |
|||
export let locale = "en-GB" |
|||
export let numberFormat = "" |
|||
export let shouldShowAllDataPoints = true |
|||
export let topicLabel = null |
|||
export let dateLabel = "date" |
|||
export let valueLabel = null |
|||
export let xAxisLabel = "" |
|||
export let xAxisValueType = "date" |
|||
export let xAxisScale = "linear" |
|||
export let xAxisFormat = "day-month" |
|||
export let xAxisCustomFormat = "%H" |
|||
export let yAxisLabel = null |
|||
export let yAxisLabelPadding = null |
|||
export let lines = null //not handled by setting prop |
|||
export let tooltipThreshold = null |
|||
export let tooltipTitle = "" |
|||
export let xTicks = "" |
|||
export let yTicks = "" |
|||
|
|||
onMount(async () => { |
|||
if (!isEmpty(datasource)) { |
|||
data = await getAndPrepareData() |
|||
|
|||
if (data.dataByTopic.length > 0) { |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(data).call(chart) |
|||
|
|||
// Hack 🤮 X Axis Label and last tick label gets cut off unless we do this 👇 |
|||
const chartSvg = document.querySelector(`.${chartClass} .britechart`) |
|||
if (chartSvg) { |
|||
let height = chartSvg.getAttribute("height") |
|||
let width = chartSvg.getAttribute("width") |
|||
height = parseInt(height) + 35 |
|||
width = parseInt(width) + 15 |
|||
chartSvg.setAttribute("height", height) |
|||
chartSvg.setAttribute("width", width) |
|||
} |
|||
|
|||
bindTooltip() |
|||
} else { |
|||
console.error( |
|||
"Line Chart - Please provide valid name, value and topic labels" |
|||
) |
|||
} |
|||
} |
|||
}) |
|||
|
|||
function bindTooltip() { |
|||
tooltipContainer = select( |
|||
`.${chartClass} .metadata-group .vertical-marker-container` |
|||
) |
|||
tooltip.topicLabel("topics") |
|||
tooltipContainer.datum([]).call(tooltip) |
|||
} |
|||
|
|||
const schemaIsValid = data => |
|||
hasProp(data, valueLabel) && |
|||
hasProp(data, dateLabel) && |
|||
hasProp(data, topicLabel) |
|||
|
|||
async function getAndPrepareData() { |
|||
let dataByTopic = [] |
|||
let _data = [] |
|||
|
|||
if (!topicLabel) { |
|||
topicLabel = "topicName" |
|||
} |
|||
|
|||
if (!valueLabel) { |
|||
valueLabel = "value" |
|||
} |
|||
|
|||
if (!dateLabel) { |
|||
dateLabel = "date" |
|||
} |
|||
|
|||
_data = await fetchData(datasource) |
|||
|
|||
if (schemaIsValid(_data)) { |
|||
_data.forEach((data, idx, arr) => { |
|||
let topicName = data[topicLabel] |
|||
if (!dataByTopic.some(dt => dt.topicName === topicName)) { |
|||
let d = { |
|||
topicName, |
|||
topic: dataByTopic.length + 1, |
|||
dates: arr |
|||
.filter(d => d[topicLabel] === topicName) |
|||
.map(d => ({ |
|||
date: new Date(d[dateLabel]), |
|||
value: d[valueLabel], |
|||
})) |
|||
.sort((a, b) => a.date - b.date), |
|||
} |
|||
dataByTopic.push(d) |
|||
} |
|||
}) |
|||
} |
|||
|
|||
return { dataByTopic } |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
chart.tooltipThreshold(800) |
|||
chart.aspectRatio(0.5) |
|||
chart.xAxisCustomFormat("%e %b %Y") |
|||
chart.xTicks(data.dataByTopic.length) |
|||
|
|||
if (notNull(color)) { |
|||
chart.colorSchema(colorSchema) |
|||
} |
|||
if (notNull(lineGradient)) { |
|||
chart.lineGradient(chartGradient) |
|||
} |
|||
if (notNull(axisTimeCombinations)) { |
|||
chart.axisTimeCombinations(axisTimeCombinations) |
|||
} |
|||
if (notNull(grid)) { |
|||
chart.grid(grid) |
|||
} |
|||
if (notNull(aspectRatio)) { |
|||
chart.aspectRatio(aspectRatio) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(isAnimated)) { |
|||
chart.isAnimated(isAnimated) |
|||
} |
|||
if (notNull(lineCurve)) { |
|||
chart.lineCurve(lineCurve) |
|||
} |
|||
if (notNull(locale)) { |
|||
chart.locale(locale) |
|||
} |
|||
if (notNull(numberFormat)) { |
|||
chart.numberFormat(numberFormat) |
|||
} |
|||
if (notNull(shouldShowAllDataPoints)) { |
|||
chart.shouldShowAllDataPoints(shouldShowAllDataPoints) |
|||
} |
|||
if (notNull(xAxisLabel)) { |
|||
chart.xAxisLabel(xAxisLabel) |
|||
} |
|||
if (notNull(xAxisValueType)) { |
|||
chart.xAxisValueType(xAxisValueType) |
|||
} |
|||
if (notNull(xAxisScale)) { |
|||
chart.xAxisScale(xAxisScale) |
|||
} |
|||
if (notNull(xAxisFormat)) { |
|||
chart.xAxisFormat(xAxisFormat) |
|||
} |
|||
if (notNull(xAxisCustomFormat)) { |
|||
chart.xAxisCustomFormat(xAxisCustomFormat) |
|||
} |
|||
if (notNull(yAxisLabel)) { |
|||
chart.yAxisLabel(yAxisLabel) |
|||
} |
|||
if (notNull(yAxisLabelPadding)) { |
|||
chart.yAxisLabelPadding(yAxisLabelPadding) |
|||
} |
|||
if (notNull(tooltipThreshold)) { |
|||
chart.tooltipThreshold(tooltipThreshold) |
|||
} |
|||
if (notNull(lines)) { |
|||
chart.lines(lines) |
|||
} |
|||
if (notNull(xTicks)) { |
|||
chart.xTicks(Number(xTicks)) |
|||
} |
|||
if (notNull(yTicks)) { |
|||
chart.yTicks(Number(yTicks)) |
|||
} |
|||
if (notNull(tooltipTitle)) { |
|||
tooltip.title(tooltipTitle) |
|||
} else if (datasource.label) { |
|||
tooltip.title(datasource.label) |
|||
} |
|||
} |
|||
|
|||
function bindChartEvents() { |
|||
if (customMouseOver) { |
|||
chart.on("customMouseOver", tooltip.show) |
|||
} |
|||
if (customMouseMove) { |
|||
chart.on("customMouseMove", tooltip.update) |
|||
} |
|||
if (customMouseOut) { |
|||
chart.on("customMouseOut", tooltip.hide) |
|||
} |
|||
if (customDataEntryClick) { |
|||
chart.on("customDataEntryClick", customDataEntryClick) |
|||
} |
|||
if (customTouchMove) { |
|||
chart.on("customTouchMove", customTouchMove) |
|||
} |
|||
} |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
$: chartGradient = getChartGradient(lineGradient) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
@ -0,0 +1,100 @@ |
|||
<script> |
|||
import { onMount } from "svelte" |
|||
import fetchData, { fetchSchema } from "../fetchData" |
|||
import { ApexOptionsBuilder } from "./ApexOptionsBuilder" |
|||
import ApexChart from "./ApexChart.svelte" |
|||
import { isEmpty } from "lodash/fp" |
|||
|
|||
// Common props |
|||
export let _bb |
|||
export let title |
|||
export let datasource |
|||
export let labelColumn |
|||
export let valueColumns |
|||
export let xAxisLabel |
|||
export let yAxisLabel |
|||
export let height |
|||
export let width |
|||
export let color |
|||
export let animate |
|||
export let dataLabels |
|||
export let curve |
|||
export let legend |
|||
export let yAxisUnits |
|||
export let palette |
|||
|
|||
// Area specific props |
|||
export let area |
|||
export let stacked |
|||
export let gradient |
|||
|
|||
const store = _bb.store |
|||
let options |
|||
|
|||
// Fetch data on mount |
|||
onMount(async () => { |
|||
const allCols = [labelColumn, ...(valueColumns || [])] |
|||
if (isEmpty(datasource) || allCols.find(x => x == null)) { |
|||
options = false |
|||
return |
|||
} |
|||
|
|||
// Fetch, filter and sort data |
|||
const schema = await fetchSchema(datasource.tableId) |
|||
const result = await fetchData(datasource, $store) |
|||
const reducer = row => (valid, column) => valid && row[column] != null |
|||
const hasAllColumns = row => allCols.reduce(reducer(row), true) |
|||
const data = result |
|||
.filter(row => hasAllColumns(row)) |
|||
.slice(0, 100) |
|||
.sort((a, b) => (a[labelColumn] > b[labelColumn] ? 1 : -1)) |
|||
if (!schema || !data.length) { |
|||
options = false |
|||
return |
|||
} |
|||
|
|||
// Initialise default chart |
|||
let builder = new ApexOptionsBuilder() |
|||
.title(title) |
|||
.type(area ? "area" : "line") |
|||
.width(width) |
|||
.height(height) |
|||
.xLabel(xAxisLabel) |
|||
.yLabel(yAxisLabel) |
|||
.dataLabels(dataLabels) |
|||
.animate(animate) |
|||
.curve(curve.toLowerCase()) |
|||
.gradient(gradient) |
|||
.stacked(stacked) |
|||
.legend(legend) |
|||
.yUnits(yAxisUnits) |
|||
.palette(palette) |
|||
|
|||
// Add data |
|||
let useDates = false |
|||
if (datasource.type !== "view" && schema[labelColumn]) { |
|||
const labelFieldType = schema[labelColumn].type |
|||
builder = builder.xType(labelFieldType) |
|||
useDates = labelFieldType === "datetime" |
|||
} |
|||
const series = valueColumns.map(column => ({ |
|||
name: column, |
|||
data: data.map(row => { |
|||
if (!useDates) { |
|||
return row[column] |
|||
} else { |
|||
return [row[labelColumn], row[column]] |
|||
} |
|||
}), |
|||
})) |
|||
builder = builder.series(series) |
|||
if (!useDates) { |
|||
builder = builder.categories(data.map(row => row[labelColumn])) |
|||
} |
|||
|
|||
// Build chart options |
|||
options = builder.getOptions() |
|||
}) |
|||
</script> |
|||
|
|||
<ApexChart {options} /> |
|||
@ -0,0 +1,66 @@ |
|||
<script> |
|||
import { onMount } from "svelte" |
|||
import fetchData, { fetchSchema } from "../fetchData" |
|||
import { ApexOptionsBuilder } from "./ApexOptionsBuilder" |
|||
import ApexChart from "./ApexChart.svelte" |
|||
import { isEmpty } from "lodash/fp" |
|||
|
|||
export let _bb |
|||
export let title |
|||
export let datasource |
|||
export let labelColumn |
|||
export let valueColumn |
|||
export let height |
|||
export let width |
|||
export let color |
|||
export let dataLabels |
|||
export let animate |
|||
export let legend |
|||
export let donut |
|||
export let palette |
|||
|
|||
const store = _bb.store |
|||
let options |
|||
|
|||
// Fetch data on mount |
|||
onMount(async () => { |
|||
if (isEmpty(datasource) || !labelColumn || !valueColumn) { |
|||
options = false |
|||
return |
|||
} |
|||
|
|||
// Fetch, filter and sort data |
|||
const schema = await fetchSchema(datasource.tableId) |
|||
const result = await fetchData(datasource, $store) |
|||
const data = result |
|||
.filter(row => row[labelColumn] != null && row[valueColumn] != null) |
|||
.slice(0, 20) |
|||
.sort((a, b) => (a[labelColumn] > b[labelColumn] ? 1 : -1)) |
|||
if (!schema || !data.length) { |
|||
options = false |
|||
return |
|||
} |
|||
|
|||
// Initialise default chart |
|||
let builder = new ApexOptionsBuilder() |
|||
.title(title) |
|||
.type(donut ? "donut" : "pie") |
|||
.width(width) |
|||
.height(height) |
|||
.dataLabels(dataLabels) |
|||
.animate(animate) |
|||
.legend(legend) |
|||
.legendPosition("right") |
|||
.palette(palette) |
|||
|
|||
// Add data if valid datasource |
|||
const series = data.map(row => parseFloat(row[valueColumn])) |
|||
const labels = data.map(row => row[labelColumn]) |
|||
builder = builder.series(series).labels(labels) |
|||
|
|||
// Build chart options |
|||
options = builder.getOptions() |
|||
}) |
|||
</script> |
|||
|
|||
<ApexChart {options} /> |
|||
@ -1,187 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull } from "./utils" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
export let _bb |
|||
export let table |
|||
|
|||
let store = _bb.store |
|||
|
|||
const chart = britecharts.scatterPlot() |
|||
const chartClass = `scatterplot-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
let tooltip |
|||
let tooltipContainer |
|||
|
|||
export let customClick = null |
|||
export let customMouseOut = () => tooltip.hide() |
|||
export let customMouseOver = () => tooltip.show() |
|||
export let customMouseMove = ( |
|||
dataPoint, |
|||
colorMapping, |
|||
xPosition, |
|||
yPosition = null |
|||
) => tooltip.update(dataPoint, colorMapping, xPosition, (yPosition = null)) |
|||
|
|||
export let data = [] |
|||
export let color = "britecharts" |
|||
export let height = null |
|||
export let width = null |
|||
export let margin = null |
|||
export let aspectRatio = null |
|||
export let circleOpacity = null |
|||
export let grid = null |
|||
export let hasCrossHairs = null |
|||
export let hasHollowCircles = null |
|||
export let hasTrendline = null |
|||
export let highlightTextLegendOffset = null |
|||
export let isAnimated = null |
|||
export let maxCircleArea = null |
|||
export let xAxisFormat = null |
|||
export let xAxisLabel = null |
|||
export let xAxisLabelOffset = null |
|||
export let xTicks = null |
|||
export let yAxisFormat = null |
|||
export let yAxisLabel = null |
|||
export let yAxisLabelOffset = null |
|||
export let yTicks = null |
|||
export let useLegend = true |
|||
|
|||
onMount(async () => { |
|||
if (chart) { |
|||
if (table) { |
|||
await fetchData() |
|||
} |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(_data).call(chart) |
|||
bindChartTooltip() |
|||
} |
|||
}) |
|||
|
|||
async function fetchData() { |
|||
const FETCH_ROWS_URL = `/api/views/all_${table}` |
|||
const response = await _bb.api.get(FETCH_ROWS_URL) |
|||
if (response.status === 200) { |
|||
const json = await response.json() |
|||
store.update(state => { |
|||
state[table] = json |
|||
return state |
|||
}) |
|||
} else { |
|||
throw new Error("Failed to fetch rows.", response) |
|||
} |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
if (notNull(color)) { |
|||
chart.colorSchema(colorSchema) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(margin)) { |
|||
chart.width(margin) |
|||
} |
|||
if (notNull(aspectRatio)) { |
|||
chart.aspectRatio(aspectRatio) |
|||
} |
|||
if (notNull(circleOpacity)) { |
|||
chart.circleOpacity(circleOpacity) |
|||
} |
|||
if (notNull(grid)) { |
|||
chart.grid(grid) |
|||
} |
|||
if (notNull(hasCrossHairs)) { |
|||
chart.hasCrossHairs(hasCrossHairs) |
|||
} |
|||
if (notNull(hasHollowCircles)) { |
|||
chart.hasHollowCircles(hasHollowCircles) |
|||
} |
|||
if (notNull(hasTrendline)) { |
|||
chart.hasTrendline(hasTrendline) |
|||
} |
|||
if (notNull(highlightTextLegendOffset)) { |
|||
chart.highlightTextLegendOffset(highlightTextLegendOffset) |
|||
} |
|||
if (notNull(isAnimated)) { |
|||
chart.isAnimated(isAnimated) |
|||
} |
|||
if (notNull(maxCircleArea)) { |
|||
chart.maxCircleArea(maxCircleArea) |
|||
} |
|||
if (notNull(xAxisFormat)) { |
|||
chart.xAxisFormat(xAxisFormat) |
|||
} |
|||
if (notNull(xAxisLabel)) { |
|||
chart.xAxisLabel(xAxisLabel) |
|||
} |
|||
if (notNull(xAxisLabelOffset)) { |
|||
chart.xAxisLabelOffset(xAxisLabelOffset) |
|||
} |
|||
if (notNull(xTicks)) { |
|||
chart.xTicks(xTicks) |
|||
} |
|||
if (notNull(yAxisFormat)) { |
|||
chart.yAxisFormat(yAxisFormat) |
|||
} |
|||
if (notNull(yAxisLabel)) { |
|||
chart.yAxisLabel(yAxisLabel) |
|||
} |
|||
if (notNull(yAxisLabelOffset)) { |
|||
chart.yAxisLabelOffset(yAxisLabelOffset) |
|||
} |
|||
if (notNull(yTicks)) { |
|||
chart.yTicks(yTicks) |
|||
} |
|||
} |
|||
|
|||
function bindChartEvents() { |
|||
if (customClick) { |
|||
chart.on("customClick", customClick) |
|||
} |
|||
if (customMouseMove) { |
|||
chart.on("customMouseMove", customMouseMove) |
|||
} |
|||
if (customMouseOut) { |
|||
chart.on("customMouseOut", customMouseOut) |
|||
} |
|||
if (customMouseOver) { |
|||
chart.on("customMouseOver", customMouseOver) |
|||
} |
|||
} |
|||
|
|||
function bindChartTooltip() { |
|||
//TODO: May be more apt to use tooltip() here. Currently erroring however |
|||
tooltip = britecharts.miniTooltip() |
|||
tooltipContainer = select(`.${chartClass} .metadata-group`) |
|||
// tooltip |
|||
// .title("Temperature") |
|||
// .valueLabel("y") |
|||
// .nameLabel("x") |
|||
// .numberFormat("$") |
|||
tooltipContainer.datum([]).call(tooltip) |
|||
} |
|||
|
|||
$: _data = table ? $store[table] : data |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
{#if useLegend} |
|||
<div class={legendClass} /> |
|||
{/if} |
|||
@ -1,103 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull } from "./utils" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
export let _bb |
|||
export let table |
|||
|
|||
let store = _bb.store |
|||
|
|||
const chart = britecharts.sparkline() |
|||
const chartClass = `sparkline-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
|
|||
export let data = [] |
|||
export let areaGradient = null |
|||
export let height = null |
|||
export let width = null |
|||
export let dateLabel = null |
|||
export let duration = null |
|||
export let isAnimated = null |
|||
export let lineGradient = null |
|||
export let titleText = null |
|||
export let titleTextStyle = null |
|||
export let valueLabel = null |
|||
export let useLegend = true |
|||
|
|||
onMount(async () => { |
|||
if (chart) { |
|||
if (table) { |
|||
await fetchData() |
|||
} |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
chartContainer.datum(_data).call(chart) |
|||
} |
|||
}) |
|||
|
|||
async function fetchData() { |
|||
const FETCH_ROWS_URL = `/api/views/all_${table}` |
|||
const response = await _bb.api.get(FETCH_ROWS_URL) |
|||
if (response.status === 200) { |
|||
const json = await response.json() |
|||
store.update(state => { |
|||
state[table] = json |
|||
return state |
|||
}) |
|||
} else { |
|||
throw new Error("Failed to fetch rows.", response) |
|||
} |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
if (notNull(areaGradient)) { |
|||
chart.areaGradient(aGradient) |
|||
} |
|||
if (notNull(lineGradient)) { |
|||
chart.lineGradient(lGradient) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(dateLabel)) { |
|||
chart.dateLabel(dateLabel) |
|||
} |
|||
if (notNull(duration)) { |
|||
chart.duration(duration) |
|||
} |
|||
if (notNull(isAnimated)) { |
|||
chart.isAnimated(isAnimated) |
|||
} |
|||
if (notNull(titleText)) { |
|||
chart.titleText(titleText) |
|||
} |
|||
if (notNull(titleTextStyle)) { |
|||
chart.titleTextStyle(titleTextStyle) |
|||
} |
|||
if (notNull(valueLabel)) { |
|||
chart.valueLabel(valueLabel) |
|||
} |
|||
} |
|||
|
|||
$: _data = table ? $store[table] : data |
|||
|
|||
$: aGradient = getChartGradient(areaGradient) |
|||
$: lGradient = getChartGradient(lineGradient) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
{#if useLegend} |
|||
<div class={legendClass} /> |
|||
{/if} |
|||
@ -1,181 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull } from "./utils" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
export let _bb |
|||
export let table |
|||
|
|||
let store = _bb.store |
|||
|
|||
const chart = britecharts.stackedArea() |
|||
const chartClass = `stackedarea-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
|
|||
export let customMouseOver = () => tooltip.show() |
|||
export let customMouseMove = ( |
|||
dataPoint, |
|||
colorMapping, |
|||
xPosition, |
|||
yPosition = null |
|||
) => tooltip.update(dataPoint, colorMapping, xPosition, (yPosition = null)) |
|||
export let customMouseOut = () => tooltip.hide() |
|||
|
|||
export let data = [] |
|||
export let color = "britecharts" |
|||
export let height = null |
|||
export let width = null |
|||
export let margin = null |
|||
export let areaCurve = null |
|||
export let areaOpacity = null |
|||
export let aspectRatio = null |
|||
export let dateLabel = null |
|||
export let grid = null |
|||
export let isAnimated = null |
|||
export let keyLabel = null |
|||
export let locale = null |
|||
export let tooltipThreshold = null |
|||
export let topicsOrder = null |
|||
export let valueLabel = null |
|||
export let xAxisCustomFormat = null |
|||
export let xAxisFormat = null |
|||
export let xAxisScale = null |
|||
export let xAxisValueType = null |
|||
export let xTicks = null |
|||
export let yAxisBaseline = null |
|||
export let yAxisLabel = null |
|||
export let yAxisLabelOffset = null |
|||
export let yTicks = null |
|||
export let useLegend = true |
|||
|
|||
onMount(async () => { |
|||
if (chart) { |
|||
if (table) { |
|||
await fetchData() |
|||
} |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(_data).call(chart) |
|||
bindChartTooltip() |
|||
} |
|||
}) |
|||
|
|||
async function fetchData() { |
|||
const FETCH_ROWS_URL = `/api/views/all_${table}` |
|||
const response = await _bb.api.get(FETCH_ROWS_URL) |
|||
if (response.status === 200) { |
|||
const json = await response.json() |
|||
store.update(state => { |
|||
state[table] = json |
|||
return state |
|||
}) |
|||
} else { |
|||
throw new Error("Failed to fetch rows.", response) |
|||
} |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
if (notNull(color)) { |
|||
chart.colorSchema(colorSchema) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(margin)) { |
|||
chart.margin(margin) |
|||
} |
|||
if (notNull(areaCurve)) { |
|||
chart.areaCurve(areaCurve) |
|||
} |
|||
if (notNull(areaOpacity)) { |
|||
chart.areaOpacity(areaOpacity) |
|||
} |
|||
if (notNull(aspectRatio)) { |
|||
chart.aspectRatio(aspectRatio) |
|||
} |
|||
if (notNull(dateLabel)) { |
|||
chart.dateLabel(dateLabel) |
|||
} |
|||
if (notNull(grid)) { |
|||
chart.grid(grid) |
|||
} |
|||
if (notNull(isAnimated)) { |
|||
chart.isAnimated(isAnimated) |
|||
} |
|||
if (notNull(keyLabel)) { |
|||
chart.keyLabel(keyLabel) |
|||
} |
|||
if (notNull(locale)) { |
|||
chart.locale(locale) |
|||
} |
|||
if (notNull(tooltipThreshold)) { |
|||
chart.tooltipThreshold(tooltipThreshold) |
|||
} |
|||
if (notNull(topicsOrder)) { |
|||
chart.topicsOrder(topicsOrder) |
|||
} |
|||
if (notNull(valueLabel)) { |
|||
chart.valueLabel(valueLabel) |
|||
} |
|||
if (notNull(xAxisCustomFormat)) { |
|||
chart.xAxisCustomFormat(xAxisCustomFormat) |
|||
} |
|||
if (notNull(xAxisFormat)) { |
|||
chart.xAxisFormat(xAxisFormat) |
|||
} |
|||
if (notNull(xAxisScale)) { |
|||
chart.xAxisScale(xAxisScale) |
|||
} |
|||
if (notNull(xAxisValueType)) { |
|||
chart.xAxisValueType(xAxisValueType) |
|||
} |
|||
if (notNull(xTicks)) { |
|||
chart.xTicks(xTicks) |
|||
} |
|||
if (notNull(yAxisBaseline)) { |
|||
chart.yAxisBaseline(yAxisBaseline) |
|||
} |
|||
if (notNull(yAxisLabel)) { |
|||
chart.yAxisLabel(yAxisLabel) |
|||
} |
|||
if (notNull(yAxisLabelOffset)) { |
|||
chart.yAxisLabelOffset(yAxisLabelOffset) |
|||
} |
|||
if (notNull(yTicks)) { |
|||
chart.yTicks(yTicks) |
|||
} |
|||
} |
|||
|
|||
function bindChartEvents() { |
|||
if (customMouseMove) { |
|||
chart.on("customMouseMove", customMouseMove) |
|||
} |
|||
if (customMouseOut) { |
|||
chart.on("customMouseOut", customMouseOut) |
|||
} |
|||
if (customMouseOver) { |
|||
chart.on("customMouseOver", customMouseOver) |
|||
} |
|||
} |
|||
|
|||
$: _data = table ? $store[table] : data |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
{#if useLegend} |
|||
<div class={legendClass} /> |
|||
{/if} |
|||
@ -1,176 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull } from "./utils" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
const chart = britecharts.stackedBar() |
|||
const chartClass = `stackedbar-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
export let _bb |
|||
export let table |
|||
|
|||
let store = _bb.store |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
let tooltip |
|||
let tooltipContainer |
|||
|
|||
export let customMouseOver = () => tooltip.show() |
|||
export let customMouseMove = (dataPoint, colorMapping, xPosition) => |
|||
tooltip.update(dataPoint, colorMapping, xPosition) |
|||
export let customMouseOut = () => tooltip.hide() |
|||
|
|||
export let data = [] |
|||
export let color = "britecharts" |
|||
export let height = null |
|||
export let width = null |
|||
export let margin = null |
|||
export let aspectRatio = null |
|||
export let betweenBarsPadding = null |
|||
export let grid = null |
|||
export let hasPercentage = null |
|||
export let hasReversedStacks = null |
|||
export let isAnimated = null |
|||
export let isHorizontal = null |
|||
export let locale = null |
|||
export let nameLabel = null |
|||
export let percentageAxisToMaxRatio = null |
|||
export let stackLabel = null |
|||
export let valueLabel = null |
|||
export let valueLabelFormat = null |
|||
export let xTicks = null |
|||
export let yTicks = null |
|||
export let yAxisLabel = null |
|||
export let yAxisLabelOffset = null |
|||
export let useLegend = true |
|||
|
|||
onMount(async () => { |
|||
if (chart) { |
|||
if (table) { |
|||
await fetchData() |
|||
} |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(_data).call(chart) |
|||
// bindChartTooltip() |
|||
} |
|||
}) |
|||
|
|||
async function fetchData() { |
|||
const FETCH_ROWS_URL = `/api/views/all_${table}` |
|||
const response = await _bb.api.get(FETCH_ROWS_URL) |
|||
if (response.status === 200) { |
|||
const json = await response.json() |
|||
store.update(state => { |
|||
state[table] = json |
|||
return state |
|||
}) |
|||
} else { |
|||
throw new Error("Failed to fetch rows.", response) |
|||
} |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
//UI PROPS |
|||
if (notNull(color)) { |
|||
chart.colorSchema(colorSchema) |
|||
} |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(margin)) { |
|||
chart.margin(margin) |
|||
} |
|||
if (notNull(aspectRatio)) { |
|||
chart.aspectRatio(aspectRatio) |
|||
} |
|||
if (notNull(betweenBarsPadding)) { |
|||
chart.betweenBarsPadding(betweenBarsPadding) |
|||
} |
|||
if (notNull(grid)) { |
|||
chart.grid(grid) |
|||
} |
|||
if (notNull(hasPercentage)) { |
|||
chart.hasPercentage(hasPercentage) |
|||
} |
|||
if (notNull(hasReversedStacks)) { |
|||
chart.hasReversedStacks(hasReversedStacks) |
|||
} |
|||
if (notNull(isAnimated)) { |
|||
chart.isAnimated(isAnimated) |
|||
} |
|||
if (notNull(isHorizontal)) { |
|||
chart.isHorizontal(isHorizontal) |
|||
} |
|||
if (notNull(locale)) { |
|||
chart.locale(locale) |
|||
} |
|||
if (notNull(nameLabel)) { |
|||
chart.nameLabel(nameLabel) |
|||
} |
|||
if (notNull(percentageAxisToMaxRatio)) { |
|||
chart.percentageAxisToMaxRatio(percentageAxisToMaxRatio) |
|||
} |
|||
if (notNull(stackLabel)) { |
|||
chart.stackLabel(stackLabel) |
|||
} |
|||
if (notNull(valueLabel)) { |
|||
chart.valueLabel(valueLabel) |
|||
} |
|||
if (notNull(valueLabelFormat)) { |
|||
chart.valueLabelFormat(valueLabelFormat) |
|||
} |
|||
if (notNull(xTicks)) { |
|||
chart.xTicks(xTicks) |
|||
} |
|||
if (notNull(yTicks)) { |
|||
chart.yTicks(yTicks) |
|||
} |
|||
if (notNull(yAxisLabel)) { |
|||
chart.yAxisLabel(yAxisLabel) |
|||
} |
|||
if (notNull(yAxisLabelOffset)) { |
|||
chart.yAxisLabelOffset(yAxisLabelOffset) |
|||
} |
|||
} |
|||
|
|||
function bindChartEvents() { |
|||
if (customMouseMove) { |
|||
chart.on("customMouseMove", customMouseMove) |
|||
} |
|||
if (customMouseOut) { |
|||
chart.on("customMouseOut", customMouseOut) |
|||
} |
|||
if (customMouseOver) { |
|||
chart.on("customMouseOver", customMouseOver) |
|||
} |
|||
} |
|||
|
|||
function bindChartTooltip() { |
|||
tooltip = britecharts.tooltip() |
|||
// tooltip.topicLabel("Hi Im the topic") |
|||
// tooltip.topicsOrder(["x", "y"]) |
|||
tooltipContainer = select(`.${chartClass} .metadata-group`) |
|||
tooltipContainer.datum([]).call(tooltip) |
|||
} |
|||
|
|||
$: _data = table ? $store[table] : data |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
{#if useLegend} |
|||
<div class={legendClass} /> |
|||
{/if} |
|||
@ -1,129 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull } from "./utils" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
/* |
|||
ISSUES - Doesn't seem to allow color change. Chart is colored black by default |
|||
*/ |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
export let _bb |
|||
export let table |
|||
|
|||
let store = _bb.store |
|||
|
|||
const chart = britecharts.step() |
|||
const chartClass = `step-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
let tooltip |
|||
let tooltipContainer |
|||
|
|||
export let customMouseOver = () => tooltip.show() |
|||
export let customMouseMove = ( |
|||
dataPoint, |
|||
colorMapping, |
|||
xPosition, |
|||
yPosition = null |
|||
) => tooltip.update(dataPoint, colorMapping, xPosition, (yPosition = null)) |
|||
export let customMouseOut = () => tooltip.hide() |
|||
|
|||
export let data = [] |
|||
export let height = null |
|||
export let width = null |
|||
export let margin = null |
|||
export let xAxisLabel = null |
|||
export let xAxisLabelOffset = null |
|||
export let yAxisLabel = null |
|||
export let yAxisLabelOffset = null |
|||
export let yTicks = null |
|||
export let useLegend = true |
|||
|
|||
onMount(async () => { |
|||
if (chart) { |
|||
if (table) { |
|||
await fetchData() |
|||
} |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(_data).call(chart) |
|||
bindChartTooltip() |
|||
} |
|||
}) |
|||
|
|||
async function fetchData() { |
|||
const FETCH_ROWS_URL = `/api/views/all_${table}` |
|||
const response = await _bb.api.get(FETCH_ROWS_URL) |
|||
if (response.status === 200) { |
|||
const json = await response.json() |
|||
store.update(state => { |
|||
state[table] = json |
|||
return state |
|||
}) |
|||
} else { |
|||
throw new Error("Failed to fetch rows.", response) |
|||
} |
|||
} |
|||
|
|||
function bindChartUIProps() { |
|||
if (notNull(height)) { |
|||
chart.height(height) |
|||
} |
|||
if (notNull(width)) { |
|||
chart.width(width) |
|||
} |
|||
if (notNull(margin)) { |
|||
chart.margin(margin) |
|||
} |
|||
if (notNull(xAxisLabel)) { |
|||
chart.xAxisLabel(xAxisLabel) |
|||
} |
|||
if (notNull(xAxisLabelOffset)) { |
|||
chart.xAxisLabelOffset(xAxisLabelOffset) |
|||
} |
|||
if (notNull(yAxisLabel)) { |
|||
chart.yAxisLabel(yAxisLabel) |
|||
} |
|||
if (notNull(yAxisLabelOffset)) { |
|||
chart.yAxisLabelOffset(yAxisLabelOffset) |
|||
} |
|||
if (notNull(yTicks)) { |
|||
chart.yTicks(yTicks) |
|||
} |
|||
} |
|||
|
|||
function bindChartEvents() { |
|||
if (customMouseMove) { |
|||
chart.on("customMouseMove", customMouseMove) |
|||
} |
|||
if (customMouseOut) { |
|||
chart.on("customMouseOut", customMouseOut) |
|||
} |
|||
if (customMouseOver) { |
|||
chart.on("customMouseOver", customMouseOver) |
|||
} |
|||
} |
|||
|
|||
function bindChartTooltip() { |
|||
tooltip = britecharts.miniTooltip() |
|||
tooltipContainer = select(`.${chartClass} .metadata-group`) |
|||
tooltipContainer.datum([]).call(tooltip) |
|||
} |
|||
|
|||
$: _data = table ? $store[table] : data |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
{#if useLegend} |
|||
<div class={legendClass} /> |
|||
{/if} |
|||
@ -1,41 +0,0 @@ |
|||
<script> |
|||
import { getColorSchema, getChartGradient, notNull } from "./utils" |
|||
import britecharts from "britecharts" |
|||
import { onMount } from "svelte" |
|||
|
|||
import { select } from "d3-selection" |
|||
import shortid from "shortid" |
|||
|
|||
const _id = shortid.generate() |
|||
|
|||
const chart = britecharts.chartname() |
|||
const chartClass = `donut-container-${_id}` |
|||
const legendClass = `legend-container-${_id}` |
|||
|
|||
let chartElement = null |
|||
let chartContainer = null |
|||
|
|||
export let data = [] |
|||
export let color = "britecharts" |
|||
export let height = 200 |
|||
export let width = 200 |
|||
export let margin = { top: 0, right: 0, bottom: 0, left: 0 } |
|||
export let useLegend = true |
|||
|
|||
onMount(() => { |
|||
if (chart) { |
|||
chartContainer = select(`.${chartClass}`) |
|||
bindChartUIProps() |
|||
bindChartEvents() |
|||
chartContainer.datum(data).call(chart) |
|||
bindChartTooltip() |
|||
} |
|||
}) |
|||
|
|||
$: colorSchema = getColorSchema(color) |
|||
</script> |
|||
|
|||
<div bind:this={chartElement} class={chartClass} /> |
|||
{#if useLegend} |
|||
<div class={legendClass} /> |
|||
{/if} |
|||
@ -1,81 +0,0 @@ |
|||
<script> |
|||
import { notNull } from "./utils" |
|||
import { onMount } from "svelte" |
|||
import { select } from "d3-selection" |
|||
|
|||
import britecharts from "britecharts" |
|||
|
|||
export const tooltip = britecharts.tooltip() |
|||
|
|||
export let chartClass = "" |
|||
let tooltipContainer |
|||
|
|||
export let axisTimeCombinations = null |
|||
export let dateCustomFormat = null |
|||
export let dateFormat = null |
|||
export let dateLabel = null |
|||
export let locale = null |
|||
export let nameLabel = null |
|||
export let numberFormat = null |
|||
export let shouldShowDateInTitle = false |
|||
export let title = "My Tooltip" |
|||
export let tooltipOffset = null |
|||
export let topicLabel = "values" |
|||
export let topicsOrder = null |
|||
export let valueLabel = null |
|||
export let xAxisValueType = null |
|||
|
|||
onMount(() => { |
|||
tooltipContainer = select( |
|||
`.${chartClass} .metadata-group .vertical-marker-container` |
|||
) |
|||
tooltipContainer.datum([]).call(tooltip) |
|||
}) |
|||
|
|||
$: if (tooltipContainer) { |
|||
if (notNull(axisTimeCombinations)) { |
|||
tooltip.axisTimeCombinations(axisTimeCombinations) |
|||
} |
|||
if (notNull(dateCustomFormat)) { |
|||
tooltip.dateCustomFormat(dateCustomFormat) |
|||
} |
|||
if (notNull(dateFormat)) { |
|||
tooltip.dateFormat(dateFormat) |
|||
} |
|||
if (notNull(dateLabel)) { |
|||
tooltip.dateLabel(dateLabel) |
|||
} |
|||
if (notNull(locale)) { |
|||
tooltip.locale(locale) |
|||
} |
|||
if (notNull(nameLabel)) { |
|||
tooltip.nameLabel(nameLabel) |
|||
} |
|||
if (notNull(numberFormat)) { |
|||
tooltip.numberFormat(numberFormat) |
|||
} |
|||
if (notNull(shouldShowDateInTitle)) { |
|||
tooltip.shouldShowDateInTitle(shouldShowDateInTitle) |
|||
} |
|||
if (notNull(title)) { |
|||
tooltip.title(title) |
|||
} |
|||
if (notNull(tooltipOffset)) { |
|||
tooltip.tooltipOffset(tooltipOffset) |
|||
} |
|||
if (notNull(topicLabel)) { |
|||
tooltip.topicLabel(topicLabel) |
|||
} |
|||
if (notNull(topicsOrder)) { |
|||
tooltip.topicsOrder(topicsOrder) |
|||
} |
|||
if (notNull(valueLabel)) { |
|||
tooltip.valueLabel(valueLabel) |
|||
} |
|||
if (notNull(xAxisValueType)) { |
|||
tooltip.xAxisValueType(xAxisValueType) |
|||
} |
|||
|
|||
tooltipContainer.datum([]).call(tooltip) |
|||
} |
|||
</script> |
|||
@ -1,14 +1,6 @@ |
|||
import "britecharts/dist/css/britecharts.min.css" |
|||
|
|||
export { default as donut } from "./Donut.svelte" |
|||
export { default as bar } from "./Bar.svelte" |
|||
export { default as line } from "./Line.svelte" |
|||
export { default as brush } from "./Brush.svelte" |
|||
export { default as bullet } from "./Bullet.svelte" |
|||
export { default as groupedbar } from "./GroupedBar.svelte" |
|||
export { default as heatmap } from "./Heatmap.svelte" |
|||
export { default as sparkline } from "./Sparkline.svelte" |
|||
export { default as scatterplot } from "./ScatterPlot.svelte" |
|||
export { default as step } from "./Step.svelte" |
|||
export { default as stackedarea } from "./StackedArea.svelte" |
|||
export { default as stackedbar } from "./StackedBar.svelte" |
|||
export { default as bar } from "./BarChart.svelte" |
|||
export { default as line } from "./LineChart.svelte" |
|||
export { default as pie } from "./PieChart.svelte" |
|||
export { default as donut } from "./DonutChart.svelte" |
|||
export { default as area } from "./AreaChart.svelte" |
|||
export { default as candlestick } from "./CandleStickChart.svelte" |
|||
|
|||
@ -1,72 +0,0 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|||
<title>Document</title> |
|||
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-selection/1.2.0/d3-selection.js"></script> |
|||
|
|||
<script src="../../../node_modules/britecharts/dist/umd/bar.min.js" type="text/javascript"></script> |
|||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/britecharts/dist/css/britecharts.min.css" type="text/css" /> |
|||
|
|||
</head> |
|||
<body> |
|||
|
|||
<article> |
|||
<h2 class="tutorial__heading">Bar Chart</h2> |
|||
<div class="bar-chart"></div> |
|||
</article> |
|||
|
|||
<script> |
|||
|
|||
const dataset = [ |
|||
{ |
|||
"name": "Radiating", |
|||
"value": 2 |
|||
}, |
|||
{ |
|||
"name": "Opalescent", |
|||
"value": 4 |
|||
}, |
|||
{ |
|||
"name": "Shining", |
|||
"value": 3 |
|||
}, |
|||
{ |
|||
"name": "Vibrant", |
|||
"value": 6 |
|||
}, |
|||
{ |
|||
"name": "Vivid", |
|||
"value": 6 |
|||
}, |
|||
{ |
|||
"name": "Brilliant", |
|||
"value": 1 |
|||
} |
|||
] |
|||
|
|||
const barContainer = d3.select('.bar-chart'); |
|||
|
|||
const barChart = britecharts.bar() |
|||
|
|||
barChart |
|||
.width(700) |
|||
.height(300) |
|||
.enableLabels(true) |
|||
.labelsNumberFormat('.0%') |
|||
.isAnimated(true) |
|||
.yAxisLabel("Quantity") |
|||
.xAxisLabel("Color") |
|||
.betweenBarsPadding("0.8") |
|||
|
|||
// .on('customMouseOver', tooltip.show) |
|||
// .on('customMouseMove', tooltip.update) |
|||
// .on('customMouseOut', tooltip.hide); |
|||
|
|||
barContainer.datum(dataset).call(barChart); |
|||
|
|||
</script> |
|||
</body> |
|||
</html> |
|||
@ -1,235 +0,0 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|||
<title>HTML Line</title> |
|||
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-selection/1.2.0/d3-selection.js"></script> |
|||
<!-- <script src="https://cdn.jsdelivr.net/npm/britecharts@2.10.0/dist/umd/line.min.js" |
|||
type="text/javascript"></script> --> |
|||
|
|||
<script src="../../../node_modules/britecharts/dist/umd/line.min.js" type="text/javascript"></script> |
|||
<script src="../../../node_modules/britecharts/dist/umd/tooltip.min.js" type="text/javascript"></script> |
|||
|
|||
|
|||
|
|||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/britecharts/dist/css/britecharts.min.css" type="text/css" /> |
|||
</head> |
|||
<body> |
|||
|
|||
<article> |
|||
<div class="js-line-chart-container line-chart-container card--chart"></div> |
|||
</article> |
|||
|
|||
<script> |
|||
|
|||
const testData = { |
|||
data: [ |
|||
{ |
|||
amount: 8, |
|||
audited: new Date("2020-01-01T16:00:00-08:00"), |
|||
city: "Belfast", |
|||
name: 1, |
|||
tableId: "2334751ac0764c1a931bff5b6b6767eb", |
|||
type: "row", |
|||
_id: "ceb87054790f480e80512368545755bb", |
|||
_rev: "2-56e401ebaf59e6310b85fb0c6c2fece5", |
|||
}, |
|||
{ |
|||
amount: 12, |
|||
audited: new Date("2020-01-03T16:00:00-08:00"), |
|||
city: "Belfast", |
|||
name: 1, |
|||
tableId: "2334751ac0764c1a931bff5b6b6767eb", |
|||
type: "row", |
|||
_id: "0a36103b55124f348a23d10b2f3ed0e3", |
|||
_rev: "2-50d62530b2edfc63d5fd0b3719dbb286", |
|||
}, |
|||
{ |
|||
amount: 6, |
|||
audited: new Date("2020-01-04T16:00:00-08:00"), |
|||
city: "Belfast", |
|||
name: 1, |
|||
tableId: "2334751ac0764c1a931bff5b6b6767eb", |
|||
type: "row", |
|||
_id: "68ade2bb94754caa8fc62c7084e3cef7", |
|||
_rev: "2-a03fe02f3595920adfbcd9c70564fe9d", |
|||
}, |
|||
{ |
|||
amount: 2, |
|||
audited: new Date("2020-01-01T16:00:00-08:00"), |
|||
city: "Dublin", |
|||
name: 2, |
|||
tableId: "2334751ac0764c1a931bff5b6b6767eb", |
|||
type: "row", |
|||
_id: "2ab6dabf833f4d99b3438fa4353ba429", |
|||
_rev: "2-45b190489e76842981902cc9f04369ec", |
|||
}, |
|||
{ |
|||
amount: 16, |
|||
audited: new Date("2020-01-02T16:00:00-08:00"), |
|||
city: "Dublin", |
|||
name: 2, |
|||
tableId: "2334751ac0764c1a931bff5b6b6767eb", |
|||
type: "row", |
|||
_id: "1b2ca36db1724427a98ba95547f946e0", |
|||
_rev: "2-c43def17ada959948b9af5484ad5b6b7", |
|||
}, |
|||
{ |
|||
amount: 7, |
|||
audited: new Date("2020-01-03T16:00:00-08:00"), |
|||
city: "Dublin", |
|||
name: 2, |
|||
tableId: "2334751ac0764c1a931bff5b6b6767eb", |
|||
type: "row", |
|||
_id: "d9235d884a224ca68ac30cefdbb8ae53", |
|||
_rev: "2-695e426a261a25474cbf6b1f069dccb4", |
|||
}, |
|||
{ |
|||
amount: 3, |
|||
audited: new Date("2020-01-04T16:00:00-08:00"), |
|||
city: "Dublin", |
|||
name: 2, |
|||
tableId: "2334751ac0764c1a931bff5b6b6767eb", |
|||
type: "row", |
|||
_id: "9f8bc39a9cfb4f779da8c998d7622927", |
|||
_rev: "2-8ae1aff82e1ffc6ffa75f6b9d074e003", |
|||
}, |
|||
{ |
|||
amount: 4, |
|||
audited: new Date("2020-01-02T16:00:00-08:00"), |
|||
city: "London", |
|||
name: 3, |
|||
tableId: "2334751ac0764c1a931bff5b6b6767eb", |
|||
type: "row", |
|||
_id: "75274e906073493bbf75cda8656e8db0", |
|||
_rev: "2-6cfc6bb2fccb83c92b50aa5507f2a092" |
|||
}, |
|||
{ |
|||
amount: 22, |
|||
audited: new Date("2020-01-06T16:00:00-08:00"), |
|||
city: "London", |
|||
name: 3, |
|||
tableId: "2334751ac0764c1a931bff5b6b6767eb", |
|||
type: "row", |
|||
_id: "da3d4b151bc641f4ace487a2314d2550", |
|||
_rev: "2-ac18490eaa016be0e71bd4c4ea332981", |
|||
} |
|||
] |
|||
} |
|||
|
|||
const topicLabel = "city" |
|||
const valueLabel = "amount" |
|||
const dateLabel = "audited" |
|||
|
|||
function prepareData() { |
|||
let dataByTopic = [] |
|||
testData.data.forEach((data, idx, arr) => { |
|||
let topicName = data[topicLabel] |
|||
if(!dataByTopic.some(dt => dt.topicName === topicName)) { |
|||
let d = {topicName, topic: dataByTopic.length + 1, dates: arr.filter(d => d[topicLabel] === topicName).map(d => ({date: d[dateLabel], value: d[valueLabel]}))} |
|||
dataByTopic.push(d) |
|||
} |
|||
}) |
|||
return {dataByTopic} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
const newData = prepareData() |
|||
|
|||
const dataByTopic = { |
|||
dataByTopic: [ |
|||
{ |
|||
topicName: 'San Francisco', |
|||
topic: 123, |
|||
dates: [ |
|||
{ |
|||
date: '2017-01-16T16:00:00-08:00', |
|||
value: 1 |
|||
}, |
|||
{ |
|||
date: '2017-01-16T17:00:00-08:00', |
|||
value: 2 |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
topicName: 'Belfast', |
|||
topic: 456, |
|||
dates: [ |
|||
{ |
|||
date: '2017-01-16T16:00:00-08:00', |
|||
value: 5 |
|||
}, |
|||
{ |
|||
date: '2017-01-16T17:00:00-08:00', |
|||
value: 8 |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
|
|||
const data = { |
|||
data: [ |
|||
{ |
|||
topicName: "Oakland", |
|||
name: 2, |
|||
date: "2017-01-16T16:00:00-08:00", |
|||
value: 3, |
|||
}, |
|||
{ |
|||
topicName: "Oakland", |
|||
name: 2, |
|||
date: "2017-01-17T16:00:00-08:00", |
|||
value: 7, |
|||
}, |
|||
{ |
|||
topicName: "Oakland", |
|||
name: 2, |
|||
date: "2017-01-18T16:00:00-08:00", |
|||
value: 5, |
|||
}, |
|||
{ |
|||
topicName: "Oakland", |
|||
name: 2, |
|||
date: "2017-01-19T16:00:00-08:00", |
|||
value: 6, |
|||
}, |
|||
{ |
|||
topicName: "Oakland", |
|||
name: 2, |
|||
date: "2017-01-20T16:00:00-08:00", |
|||
value: 1, |
|||
}, |
|||
], |
|||
} |
|||
|
|||
const lineContainer = d3.select('.js-line-chart-container'); |
|||
|
|||
const lineChart = britecharts.line() |
|||
const tooltip = britecharts.tooltip() |
|||
|
|||
lineChart.grid("horizontal").aspectRatio(0.5).isAnimated(true).shouldShowAllDataPoints(true) |
|||
|
|||
lineContainer.datum(newData).call(lineChart); |
|||
|
|||
const tooltipContainer = d3.select(`.js-line-chart-container .metadata-group .vertical-marker-container`) |
|||
|
|||
tooltip.title("yeooo") |
|||
tooltip.topicLabel("topics") |
|||
lineChart.on("customMouseOver", tooltip.show) |
|||
lineChart.on("customMouseMove", tooltip.update) |
|||
lineChart.on("customMouseOut", tooltip.hide) |
|||
|
|||
|
|||
tooltipContainer.datum([]).call(tooltip) |
|||
|
|||
|
|||
</script> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -1,41 +0,0 @@ |
|||
import britecharts from "britecharts" |
|||
|
|||
export const notNull = value => value || value === false |
|||
|
|||
export const hasProp = (data, prop) => data.every(d => prop in d) |
|||
|
|||
export const chartTypes = britecharts ? Object.keys(britecharts) : null |
|||
|
|||
//expose chart color schemas for use or reference outside compnent
|
|||
export const colorSchemas = britecharts ? britecharts.colors.colorSchemas : null |
|||
|
|||
//export color gradients for use or reference outside the component
|
|||
export const colorGradients = britecharts |
|||
? britecharts.colors.colorGradients |
|||
: null |
|||
|
|||
export const getColorSchema = color => |
|||
color ? colorSchemas[color] : colorSchemas["britecharts"] |
|||
|
|||
export const getChartGradient = gradient => |
|||
gradient ? colorGradients[gradient] : null |
|||
|
|||
export function reformatDataKey(data = [], dataKey = null, formatKey = null) { |
|||
let ignoreList = ["_id", "_rev", "id"] |
|||
if (dataKey && data.every(d => d[dataKey])) { |
|||
return data.map(d => { |
|||
let clonedRow = { ...d } |
|||
if (clonedRow[formatKey]) { |
|||
delete clonedRow[formatKey] |
|||
} |
|||
let value = clonedRow[dataKey] |
|||
if (!ignoreList.includes(dataKey)) { |
|||
delete clonedRow[dataKey] |
|||
} |
|||
clonedRow[formatKey] = value |
|||
return clonedRow |
|||
}) |
|||
} else { |
|||
return data |
|||
} |
|||
} |
|||
@ -1,49 +0,0 @@ |
|||
<script> |
|||
import { onMount } from "svelte" |
|||
import FusionCharts from "fusioncharts" |
|||
import Charts from "fusioncharts/fusioncharts.charts" |
|||
import FusionTheme from "fusioncharts/themes/fusioncharts.theme.fusion" |
|||
import SvelteFC, { fcRoot } from "svelte-fusioncharts" |
|||
|
|||
fcRoot(FusionCharts, Charts, FusionTheme) |
|||
|
|||
export let _bb |
|||
export let table |
|||
export let type = "column2d" |
|||
|
|||
let store = _bb.store |
|||
|
|||
$: chartConfigs = { |
|||
type, |
|||
width: "600", |
|||
height: "400", |
|||
dataFormat: "json", |
|||
dataSource: { |
|||
data: $store[table] || [], |
|||
}, |
|||
} |
|||
|
|||
$: console.log("CHART CONFIGS", chartConfigs) |
|||
|
|||
async function fetchData() { |
|||
const FETCH_ROWS_URL = `/api/views/all_${table}` |
|||
const response = await _bb.api.get(FETCH_ROWS_URL) |
|||
if (response.status === 200) { |
|||
const json = await response.json() |
|||
store.update(state => { |
|||
state[table] = json |
|||
return state |
|||
}) |
|||
} else { |
|||
throw new Error("Failed to fetch rows.", response) |
|||
} |
|||
} |
|||
|
|||
onMount(async () => { |
|||
await fetchData() |
|||
}) |
|||
</script> |
|||
|
|||
<div id="container"> |
|||
<SvelteFC {...chartConfigs} /> |
|||
</div> |
|||
Loading…
Reference in new issue