Completed Groupedbar and work on Tooltip

This commit is contained in:
cmack 2020-08-10 15:33:32 +01:00
parent 911ba8b7d5
commit d7e47d67e3
7 changed files with 186 additions and 44 deletions

View File

@ -1290,15 +1290,6 @@ export default {
_component: "@budibase/standard-components/groupedbar", _component: "@budibase/standard-components/groupedbar",
description: "Groupedbar chart", description: "Groupedbar chart",
icon: "ri-bar-chart-fill", icon: "ri-bar-chart-fill",
presetProps: {
data: [
{
name: "2011-01",
group: "Direct",
value: 0,
},
],
},
properties: { properties: {
settings: [ settings: [
{ {
@ -1338,11 +1329,6 @@ export default {
key: "aspectRatio", key: "aspectRatio",
control: Input, control: Input,
}, },
{
label: "Height",
key: "height",
control: Input,
},
{ {
label: "Grid", label: "Grid",
key: "grid", key: "grid",
@ -1359,6 +1345,11 @@ export default {
key: "nameLabel", key: "nameLabel",
control: Input, control: Input,
}, },
{
label: "Value Label",
key: "valueLabel",
control: Input,
},
{ {
label: "Y Ticks", label: "Y Ticks",
key: "yTicks", key: "yTicks",

View File

@ -9,6 +9,8 @@
<link href="https://cdn.jsdelivr.net/npm/remixicon@2.3.0/fonts/remixicon.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/remixicon@2.3.0/fonts/remixicon.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/britecharts/dist/css/britecharts.min.css" type="text/css" />
<link rel='icon' type='image/png' href='/_builder/favicon.png'> <link rel='icon' type='image/png' href='/_builder/favicon.png'>
<link rel='stylesheet' href='/_builder/global.css'> <link rel='stylesheet' href='/_builder/global.css'>
<link rel='stylesheet' href='/_builder/codemirror.css'> <link rel='stylesheet' href='/_builder/codemirror.css'>
@ -22,6 +24,10 @@
<body id="app"> <body id="app">
<script src='/_builder/bundle.js'></script> <script src='/_builder/bundle.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.7.4/d3.js"></script>
<script src="https://cdn.jsdelivr.net/npm/britecharts@2/dist/bundled/britecharts.min.js"></script>
</body> </body>
</html> </html>

View File

@ -509,7 +509,6 @@
"height": "string", "height": "string",
"width": "string", "width": "string",
"margin":"string", "margin":"string",
"aspectRatio": "number",
"grid":"string", "grid":"string",
"groupLabel": "string", "groupLabel": "string",
"isAnimated": "bool", "isAnimated": "bool",
@ -517,7 +516,6 @@
"nameLabel": "string", "nameLabel": "string",
"valueLabel":"string", "valueLabel":"string",
"yTicks": "string", "yTicks": "string",
"yTickTextOffset": "string",
"useLegend": "bool" "useLegend": "bool"
} }
}, },

View File

@ -30,7 +30,7 @@
export let orderingFunction = null export let orderingFunction = null
export let data = model ? $store[model] : [] let data = []
export let color = "britecharts" export let color = "britecharts"
export let height = 200 export let height = 200
export let width = 200 export let width = 200
@ -47,7 +47,9 @@
export let internalRadius = 25 export let internalRadius = 25
export let isAnimated = true export let isAnimated = true
export let radiusHoverOffset = 0 export let radiusHoverOffset = 0
export let useLegend = true export let nameKey = null
export let valueKey = null
// export let useLegend = true
export let horizontalLegend = false export let horizontalLegend = false
export let legendWidth = null export let legendWidth = null
export let legendHeight = null export let legendHeight = null
@ -70,19 +72,60 @@
if (chart) { if (chart) {
if (model) { if (model) {
await fetchData() await fetchData()
data = checkAndReformatData($store[model])
if (data.length === 0) {
console.error(
"Donut - please provide a valid name and value field for the chart"
)
}
} }
chart.emptyDataConfig({ chart.emptyDataConfig({
showEmptySlice: true, showEmptySlice: true,
emptySliceColor: "#000000", emptySliceColor: "#F0F0F0",
}) })
chartContainer = select(`.${chartClass}`) chartContainer = select(`.${chartClass}`)
bindChartUIProps() bindChartUIProps()
bindChartEvents() bindChartEvents()
chartContainer.datum(_data).call(chart) chartContainer.datum(data).call(chart)
} }
}) })
function checkAndReformatData(data) {
let _data = [...data]
if (valueKey) {
_data = reformatDataKey(_data, valueKey, "quantity")
}
if (nameKey) {
_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 clonedRecord = { ...d }
if (clonedRecord[formatKey]) {
delete clonedRecord[formatKey]
}
let value = clonedRecord[dataKey]
if (!ignoreList.includes(dataKey)) {
delete clonedRecord[dataKey]
}
clonedRecord[formatKey] = value
return clonedRecord
})
} else {
return data
}
}
function bindChartUIProps() { function bindChartUIProps() {
chart.percentageFormat(".0f") chart.percentageFormat(".0f")
@ -134,7 +177,7 @@
if (notNull(orderingFunction)) { if (notNull(orderingFunction)) {
chart.orderingFunction(orderingFunction) chart.orderingFunction(orderingFunction)
} }
chartContainer.datum(_data).call(chart) chartContainer.datum(data).call(chart)
chartSvg = document.querySelector(`.${chartClass} .britechart`) chartSvg = document.querySelector(`.${chartClass} .britechart`)
} }
@ -159,17 +202,15 @@
$: if (!width && chartSvg) { $: if (!width && chartSvg) {
width = chartSvg.clientWidth width = chartSvg.clientWidth
chart.width(width) chart.width(width)
chartContainer.datum(_data).call(chart) chartContainer.datum(data).call(chart)
} }
$: _data = model ? $store[model] : data
$: colorSchema = getColorSchema(color) $: colorSchema = getColorSchema(color)
</script> </script>
<div> <div>
<div bind:this={chartElement} class={chartClass} /> <div bind:this={chartElement} class={chartClass} />
{#if useLegend} {#if data.length > 0}
<Legend <Legend
bind:legend={legendChart} bind:legend={legendChart}
{colorSchema} {colorSchema}
@ -178,6 +219,6 @@
width={legendWidth || width} width={legendWidth || width}
height={legendHeight} height={legendHeight}
{chartClass} {chartClass}
data={_data} /> {data} />
{/if} {/if}
</div> </div>

View File

@ -1,16 +1,15 @@
<script> <script>
import { getColorSchema, getChartGradient, notNull } from "./utils" import { getColorSchema, getChartGradient, notNull } from "./utils"
import Tooltip from "./Tooltip.svelte"
import britecharts from "britecharts" import britecharts from "britecharts"
import { onMount } from "svelte" import { onMount } from "svelte"
import { select } from "d3-selection"
import shortid from "shortid"
/* /*
ISSUES ISSUES
- Renders but seems to be a problem with tooltip hover - Renders but seems to be a problem with tooltip hover
*/ */
import { select } from "d3-selection"
import shortid from "shortid"
const _id = shortid.generate() const _id = shortid.generate()
export let _bb export let _bb
@ -33,11 +32,11 @@
export let customMouseOut = () => tooltip.hide() export let customMouseOut = () => tooltip.hide()
export let customClick = null export let customClick = null
export let data = [] let data = []
export let color = "britecharts" export let color = "britecharts"
export let height = 200 export let height = 200
export let width = 200 export let width = 200
export let margin = { top: 0, right: 0, bottom: 0, left: 0 } export let margin = null
export let aspectRatio = null export let aspectRatio = null
export let grid = null export let grid = null
export let groupLabel = null export let groupLabel = null
@ -51,18 +50,22 @@
export let yAxisLabelOffset = null export let yAxisLabelOffset = null
export let yTicks = null export let yTicks = null
export let yTickTextOffset = null export let yTickTextOffset = null
export let useLegend = true
$: console.log("DATA", data)
let chartDrawn = false
onMount(async () => { onMount(async () => {
if (chart) { if (chart) {
if (model) { if (model) {
await fetchData() await fetchData()
data = $store[model]
} }
chartContainer = select(`.${chartClass}`) chartContainer = select(`.${chartClass}`)
bindChartUIProps() bindChartUIProps()
// bindChartEvents() bindChartEvents()
chartContainer.datum(data).call(chart) chartContainer.datum(data).call(chart)
// bindChartTooltip() chartDrawn = true
} }
}) })
@ -90,6 +93,9 @@
if (notNull(width)) { if (notNull(width)) {
chart.width(width) chart.width(width)
} }
if (notNull(margin)) {
chart.margin(margin)
}
if (notNull(aspectRatio)) { if (notNull(aspectRatio)) {
chart.aspectRatio(aspectRatio) chart.aspectRatio(aspectRatio)
} }
@ -131,12 +137,6 @@
} }
} }
function bindChartTooltip() {
tooltip = britecharts.miniTooltip()
tooltipContainer = select(`.${chartClass} .metadata-group`)
tooltipContainer.datum([]).call(tooltip)
}
function bindChartEvents() { function bindChartEvents() {
if (customClick) { if (customClick) {
chart.on("customClick", customClick) chart.on("customClick", customClick)
@ -158,6 +158,6 @@
</script> </script>
<div bind:this={chartElement} class={chartClass} /> <div bind:this={chartElement} class={chartClass} />
{#if useLegend} {#if chartDrawn}
<div class={legendClass} /> <Tooltip bind:tooltip {chartDrawn} {chartClass} {data} />
{/if} {/if}

View File

@ -0,0 +1,86 @@
<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 data = []
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 = null
export let title = "My tooltip"
export let tooltipOffset = null
export let topicLabel = "Topics"
export let topicsOrder = null
export let valueLabel = null
export let xAxisValueType = null
onMount(() => {
tooltipContainer = select(`.${chartClass} .metadata-group`)
tooltipContainer.datum([]).call(tooltip)
})
// $: if (chartDrawn) {
// tooltipContainer = select(`.${chartClass} .metadata-group`)
// 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>

View File

@ -17,3 +17,23 @@ export const getColorSchema = color =>
export const getChartGradient = gradient => export const getChartGradient = gradient =>
gradient ? colorGradients[gradient] : null 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 clonedRecord = { ...d }
if (clonedRecord[formatKey]) {
delete clonedRecord[formatKey]
}
let value = clonedRecord[dataKey]
if (!ignoreList.includes(dataKey)) {
delete clonedRecord[dataKey]
}
clonedRecord[formatKey] = value
return clonedRecord
})
} else {
return data
}
}