Britecharts work so far

This commit is contained in:
cmack 2020-07-26 11:54:55 +01:00
parent 26fa5f37d1
commit 98318a8805
14 changed files with 704 additions and 73 deletions

View File

@ -273,7 +273,7 @@ const setCurrentPage = store => pageName => {
* @param {string} componentToAdd - name of the component to add to the application * @param {string} componentToAdd - name of the component to add to the application
* @param {string} presetName - name of the component preset if defined * @param {string} presetName - name of the component preset if defined
*/ */
const addChildComponent = store => (componentToAdd, presetName) => { const addChildComponent = store => (componentToAdd, presetProps = {}) => {
store.update(state => { store.update(state => {
function findSlot(component_array) { function findSlot(component_array) {
for (let i = 0; i < component_array.length; i += 1) { for (let i = 0; i < component_array.length; i += 1) {
@ -296,8 +296,6 @@ const addChildComponent = store => (componentToAdd, presetName) => {
const component = getComponentDefinition(state, componentToAdd) const component = getComponentDefinition(state, componentToAdd)
const presetProps = presetName ? component.presets[presetName] : {}
const instanceId = get(backendUiStore).selectedDatabase._id const instanceId = get(backendUiStore).selectedDatabase._id
const instanceName = get_capitalised_name(componentToAdd) const instanceName = get_capitalised_name(componentToAdd)

View File

@ -32,7 +32,7 @@
let selectedCategory = categories[0] let selectedCategory = categories[0]
const onComponentChosen = component => { const onComponentChosen = component => {
store.addChildComponent(component._component) store.addChildComponent(component._component, component.presetProps)
toggleTab("Navigate") toggleTab("Navigate")

View File

@ -32,7 +32,7 @@
{ value: "active", text: "Active" }, { value: "active", text: "Active" },
] ]
$: propertyGroupNames = Object.keys(panelDefinition) $: propertyGroupNames = panelDefinition ? Object.keys(panelDefinition) : []
</script> </script>
<div class="design-view-container"> <div class="design-view-container">

View File

@ -9,14 +9,15 @@
export let onChange = () => {} export let onChange = () => {}
function handleChange(key, v) { function handleChange(key, v) {
if (v.target) { let innerVal = v
let val = props.valueKey ? v.target[props.valueKey] : v.target.value if (typeof v === "object") {
onChange(key, val) if ("detail" in v) {
} else if (v.detail) { innerVal = v.detail
onChange(key, v.detail) } else if ("target" in v) {
} else { innerVal = props.valueKey ? v.target[props.valueKey] : v.target.value
onChange(key, v) }
} }
onChange(key, innerVal)
} }
const safeValue = () => { const safeValue = () => {

View File

@ -4,6 +4,11 @@ import Checkbox from "../common/Checkbox.svelte"
import ModelSelect from "components/userInterface/ModelSelect.svelte" import ModelSelect from "components/userInterface/ModelSelect.svelte"
import { all } from "./propertyCategories.js" import { all } from "./propertyCategories.js"
/*
{ label: "N/A ", value: "N/A" },
{ label: "Flex", value: "flex" },
{ label: "Inline Flex", value: "inline-flex" },
*/
export default { export default {
categories: [ categories: [
@ -362,35 +367,422 @@ export default {
}, },
{ {
name: "Chart", name: "Chart",
_component: "@budibase/standard-components/datachart",
description: "Shiny chart", description: "Shiny chart",
icon: "ri-bar-chart-fill", icon: "ri-bar-chart-fill",
properties: { children: [
design: { ...all }, {
settings: [ name: "Donut",
{ label: "Table", key: "model", control: ModelSelect }, _component: "@budibase/standard-components/donut",
{ description: "Donut chart",
label: "Chart Type", icon: "ri-donut-chart-line",
key: "type", presetProps: {
control: OptionSelect, data: [
options: [ {
"column2d", quantity: 1,
"column3d", percentage: 50,
"line", name: "glittering",
"area2d", id: 1,
"bar2d", },
"bar3d", {
"pie2d", quantity: 1,
"pie3d", percentage: 50,
"doughnut2d", name: "luminous",
"doughnut3d", id: 2,
"pareto2d", },
"pareto3d",
], ],
}, },
], properties: {
}, settings: [
children: [], {
label: "Fix Highlight Slice",
key: "hasFixedHighlightedSlice",
valueKey: "checked",
control: Checkbox,
},
{
label: "Hover highlight",
key: "hasLastHoverSliceHighlighted",
valueKey: "checked",
control: Checkbox,
},
{
label: "Is Animated",
key: "isAnimated",
valueKey: "checked",
control: Checkbox,
},
{
label: "Colors",
key: "color",
control: OptionSelect,
options: [
"britecharts",
"blueGreen",
"green",
"grey",
"orange",
"pink",
"purple",
"red",
"teal",
"yellow",
],
},
{
label: "Height",
key: "height",
control: Input,
},
{
label: "Width",
key: "width",
control: Input,
},
{
label: "External Radius",
key: "externalRadius",
control: Input,
},
{
label: "Internal Radius",
key: "internalRadius",
control: Input,
},
{
label: "Radius Offset",
key: "radiusHoverOffset ",
control: Input,
},
{
label: "Show Legend",
key: "useLegend ",
control: Checkbox,
},
],
},
},
{
name: "Bar",
_component: "@budibase/standard-components/bar",
description: "Bar chart",
icon: "ri-bar-chart-fill",
presetProps: {
data: [
{
value: 1,
name: "glittering",
},
{
value: 1,
name: "luminous",
},
],
},
properties: {
settings: [
{
label: "Y Axis Label",
key: "yAxisLabel",
control: Input,
},
{
label: "X Axis Label",
key: "xAxisLabel",
control: Input,
},
{
label: "Bar Padding",
key: "betweenBarsPadding",
control: Input,
},
{
label: "Colors",
key: "color",
control: OptionSelect,
options: [
{ label: "Normal", value: "britecharts" },
{ label: "Blue Green", value: "blueGreen" },
{ label: "Green", value: "green" },
{ label: "Grey", value: "grey" },
{ label: "Orange", value: "orange" },
{ label: "Pink", value: "pink" },
{ label: "Purple", value: "purple" },
{ label: "Red", value: "red" },
{ label: "Teal", value: "teal" },
{ label: "Yellow", value: "yellow" },
],
},
{
label: "Gradients",
key: "gradient",
control: OptionSelect,
options: [
{ value: "", label: "None" },
{ value: "bluePurple", label: "Blue Purple" },
{ value: "greenBlue", label: "Green Blue" },
{ value: "orangePink", label: "Orange Pink" },
],
},
{
label: "Enable Labels",
key: "enableLabels",
control: Checkbox,
valueKey: "checked",
},
{
label: "Highlight Single Bar",
key: "hasSingleBarHighlight",
control: Checkbox,
valueKey: "checked",
},
{
label: "Width",
key: "width",
control: Input,
},
{
label: "Height",
key: "height",
control: Input,
},
{
label: "Animate",
key: "isAnimate",
control: Checkbox,
valueKey: "checked",
},
{
label: "Horizontal",
key: "isHorizontal",
control: Checkbox,
valueKey: "checked",
},
{
label: "Label Offset",
key: "labelOffset",
control: Input,
},
{
label: "Label Number Format",
key: "labelsNumberFormat",
control: Input,
},
{
label: "Label Size",
key: "labelSize",
control: Input,
},
{
label: "Locale",
key: "locale",
control: Input,
},
{
label: "Name Label",
key: "nameLabel",
control: Input,
},
{
label: "Number Format",
key: "numberFormat",
control: Input,
},
{
label: "Use Legend",
key: "useLegend",
control: Checkbox,
},
],
},
},
{
name: "Line",
_component: "@budibase/standard-components/line",
description: "Line chart",
icon: "ri-bar-chart-fill",
presetProps: {
data: {
data: [
{
topicName: "San Francisco",
name: 1,
date: "2020-01-16",
value: 1,
},
{
topicName: "San Fran",
name: 2,
date: "2020-01-17",
value: 2,
},
{
topicName: "LA",
name: 3,
date: "2020-01-18",
value: 3,
},
{
topicName: "Toronto",
name: 4,
date: "2020-01-19",
value: 7,
},
{
topicName: "Van",
name: 4,
date: "2020-01-20",
value: 12,
},
{
topicName: "Dundee",
name: 4,
date: "2020-01-21",
value: 16,
},
{
topicName: "Dublin",
name: 4,
date: "2020-01-22",
value: 31,
},
],
},
aspectRatio: 0.5,
grid: "horizontal",
dateLabel: "fullDate",
shouldShowAllDataPoints: true,
},
properties: {
settings: [
{
label: "X Axis Combo",
key: "axisTimeCombinations",
control: Input,
},
{
label: "X Axis Combo",
key: "axisTimeCombinations",
control: Input,
},
{
label: "Colors",
key: "color",
control: OptionSelect,
options: [
"britecharts",
"blueGreen",
"green",
"grey",
"orange",
"pink",
"purple",
"red",
"teal",
"yellow",
],
},
{
label: "Grid",
key: "grid",
control: OptionSelect,
options: ["vertical", "horizontal", "full"],
},
{
label: "Aspect Ratio",
key: "aspectRatio",
control: Input,
},
{
label: "Date Label",
key: "dateLabel",
control: Input,
},
{
label: "Width",
key: "width",
control: Input,
},
{
label: "Height",
key: "height",
control: Input,
},
{
label: "Is Animated",
key: "isAnimated",
control: Checkbox,
valueKey: "checked",
},
{
label: "Line Curve",
key: "lineCurve",
control: OptionSelect,
options: [
"linear",
"basis",
"natural",
"monotoneX",
"monotoneY",
"step",
"stepAfter",
"stepBefore",
"cardinal",
"catmullRom",
],
},
{
label: "Locale",
key: "locale",
control: Input,
},
{
label: "Topic Label",
key: "topicLabel",
control: Input,
},
{
label: "Value Label",
key: "valueLabel",
control: Input,
},
{
label: "X Axis Label",
key: "xAxisLabel",
control: Input,
},
{
label: "X Axis Value Type",
key: "xAxisValueType",
control: OptionSelect,
options: ["date", "number"],
},
{
label: "X Axis Scale",
key: "xAxisScale",
control: OptionSelect,
options: ["linear", "logarithmic"],
},
{
label: "X Axis Format",
key: "xAxisFormat",
control: OptionSelect,
options: [
"day-month",
"minute-hour",
"hour-daymonth",
"month-year",
"custom",
],
},
{
label: "X Axis Custom Format",
key: "xAxisCustomFormat",
control: Input,
},
],
},
},
],
}, },
{ {
name: "Data List", name: "Data List",
@ -412,7 +804,14 @@ export default {
design: { ...all }, design: { ...all },
settings: [{ label: "Table", key: "model", control: ModelSelect }], settings: [{ label: "Table", key: "model", control: ModelSelect }],
}, },
children: [], children: [
{
_component: "@budibase/standard-components/heading",
name: "Headline",
description: "A component for displaying heading text",
icon: "ri-heading",
},
],
}, },
{ {
name: "Record Detail", name: "Record Detail",

View File

@ -252,6 +252,71 @@
"model": "models" "model": "models"
} }
}, },
"donut": {
"description": "Donut Chart",
"data": true,
"props": {
"color": "string",
"height": "number",
"width": "number",
"hasFixedHighlightedSlice": "bool",
"hasLastHoverSliceHighlighted": "bool",
"isAnimated": "bool",
"externalRadius": "number",
"internalRadius": "number",
"radiusHoverOffset": "number",
"useLegend": "bool"
}
},
"bar": {
"description": "Bar Chart",
"data": true,
"props": {
"betweenBarsPadding": "number",
"gradient": "string",
"color": "string",
"enableLabels": "bool",
"hasSingleBarHighlight": "bool",
"height": "number",
"width": "number",
"isAnimated": "bool",
"isHorizontal": "bool",
"labelOffset": "number",
"labelNumberFormat": "number",
"labelSize": "number",
"locale": "string",
"nameLabel": "string",
"numberLabel": "string",
"xAxisLabel": "string",
"yAxisLabel": "string",
"useLegend": "bool"
}
},
"line": {
"description": "Line Chart",
"data": true,
"props": {
"width": "number",
"height": "number",
"axisTimeCombinations": "string",
"color": "string",
"grid": "string",
"aspectRatio": "number",
"dateLabel": "string",
"isAnimated": "bool",
"lineCurve": "string",
"locale": "string",
"numberFormat": "string",
"shouldShowAllDataPoints": "bool",
"topicLabel": "string",
"valueLabel": "string",
"xAxisLabel": "string",
"xAxisValueType": "string",
"xAxisScale": "string",
"xAxisFormat": "string",
"xAxisCustomFormat": "string"
}
},
"datachart": { "datachart": {
"description": "shiny chart", "description": "shiny chart",
"data": true, "data": true,

View File

@ -38,6 +38,8 @@
"gitHead": "b1f4f90927d9e494e513220ef060af28d2d42455", "gitHead": "b1f4f90927d9e494e513220ef060af28d2d42455",
"dependencies": { "dependencies": {
"@beyonk/svelte-googlemaps": "^2.2.0", "@beyonk/svelte-googlemaps": "^2.2.0",
"britecharts": "^2.16.0",
"d3-selection": "^1.4.1",
"fusioncharts": "^3.15.1-sr.1", "fusioncharts": "^3.15.1-sr.1",
"svelte-fusioncharts": "^1.0.0" "svelte-fusioncharts": "^1.0.0"
} }

View File

@ -0,0 +1,67 @@
<script>
import Chart, { getColorSchema, getChartGradient } from "./Chart.svelte"
/*
ISSUES:
nameLabel, valueLabel - what are these? Seem to break whenever passed a string or number. What type?
https://github.com/britecharts/britecharts/blob/a2c45ab023112b36e14f47c278e3a1e1c05f8383/src/charts/bar.js#L145
*/
let type = "bar"
let tooltip
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
export let data = []
export let xAxisLabel = ""
export let yAxisLabel = ""
export let betweenBarsPadding = 5
export let gradient = null
export let color = "britecharts"
export let enableLabels = true
export let hasSingleBarHighlight = true
export let height = 200
export let width = 300
export let isAnimated = true
export let isHorizontal = true
export let labelOffset = null
export let labelsNumberFormat = null
export let labelSize = null
export let locale = null
export let nameLabel = null
export let numberFormat = null
export let useLegend = true
$: colorSchema = getColorSchema(color)
$: chartGradient = getChartGradient(gradient)
</script>
<Chart
bind:tooltip
{type}
{data}
on={{ customClick, customMouseMove, customMouseOut, customMouseOver }}
useTooltip
{useLegend}
{betweenBarsPadding}
{chartGradient}
{colorSchema}
{enableLabels}
{hasSingleBarHighlight}
{height}
{width}
{isAnimated}
{isHorizontal}
{labelOffset}
{labelsNumberFormat}
{labelSize}
{locale}
{nameLabel}
{numberFormat}
{xAxisLabel}
{yAxisLabel} />

View File

@ -11,9 +11,16 @@
export const colorGradients = britecharts export const colorGradients = britecharts
? britecharts.colors.colorGradients ? britecharts.colors.colorGradients
: null : null
export const getColorSchema = color =>
color ? colorSchemas[color] : colorSchemas["britecharts"]
export const getChartGradient = gradient =>
gradient ? colorGradients[gradient] : null
</script> </script>
<script> <script>
import { beforeUpdate } from "svelte"
import britecharts from "britecharts" import britecharts from "britecharts"
import { select } from "d3-selection" import { select } from "d3-selection"
@ -29,8 +36,6 @@
export let useTooltip = false export let useTooltip = false
export let useLegend = false export let useLegend = false
export let colors = colorSchemas ? colorSchemas.britecharts : null
export let gradients = colorGradients ? colorGradients.bluePurple : null
export let tooltip = null //can bind to outside the component and therefore access export let tooltip = null //can bind to outside the component and therefore access
let chartElement = null let chartElement = null
@ -47,7 +52,6 @@
onMount(() => { onMount(() => {
if (chart) { if (chart) {
chartContainer = select(`.${chartClass}`) chartContainer = select(`.${chartClass}`)
bindChartColors()
bindChartUIProps() bindChartUIProps()
bindChartEvents() bindChartEvents()
chartContainer.datum(data).call(chart) chartContainer.datum(data).call(chart)
@ -58,23 +62,13 @@
} }
}) })
function bindChartColors() {
if (chart.colorSchema) {
chart.colorSchema(colors)
} else if (chart.gradient) {
chart.gradient(gradients)
}
}
function bindChartTooltip() { function bindChartTooltip() {
if (canUseTooltip) { if (useTooltip) {
tooltip = britecharts.tooltip() tooltip = britecharts.miniTooltip()
bindProps(tooltip, tooltipProps) bindProps(tooltip, tooltipProps)
tooltipContainer = select( tooltipContainer = select(`.${chartClass} .metadata-group`)
`.${chartClass} .metadata-group .vertical-marker-container`
)
tooltipContainer.datum([]).call(tooltip) tooltipContainer.datum([]).call(tooltip)
} }
} }
@ -108,7 +102,9 @@
if ($$props.on) { if ($$props.on) {
const events = Object.entries($$props.on) const events = Object.entries($$props.on)
for (let [type, fn] of events) { for (let [type, fn] of events) {
chart.on(type, fn) if (fn) {
chart.on(type, fn)
}
} }
} }
} }
@ -116,9 +112,7 @@
function bindChartUIProps() { function bindChartUIProps() {
const excludeProps = [ const excludeProps = [
"data", "data",
"colors",
"type", "type",
"gradients",
"on", "on",
"useTooltip", "useTooltip",
"tooltip", "tooltip",
@ -135,19 +129,23 @@
} }
function bindProps(element, elProps, excludeArray) { function bindProps(element, elProps, excludeArray) {
const props = excludeArray if (elProps) {
? Object.entries(excludeProps(elProps, excludeArray)) const props = excludeArray
: Object.entries(elProps) ? Object.entries(excludeProps(elProps, excludeArray))
: Object.entries(elProps)
const validElementProps = Object.getOwnPropertyNames(element) const validElementProps = Object.getOwnPropertyNames(element)
for (let [prop, value] of props) { for (let [prop, value] of props) {
if (validElementProps.includes(prop)) { if (validElementProps.includes(prop)) {
chart[prop](value) if (!!value) {
} else { chart[prop](value)
console.warn( }
`${type} - ${prop} is an unrecognised chart prop and wont be applied` } else {
) console.warn(
`${type} - ${prop} is an unrecognised chart prop and wont be applied`
)
}
} }
} }
} }
@ -163,7 +161,6 @@
} }
$: validChartProps = chart ? Object.getOwnPropertyNames(chart) : null $: validChartProps = chart ? Object.getOwnPropertyNames(chart) : null
$: canUseTooltip = tooltipProps && useTooltip
</script> </script>
<div bind:this={chartElement} class={chartClass} /> <div bind:this={chartElement} class={chartClass} />

View File

@ -1,10 +1,10 @@
<script> <script>
import { colors } from "britecharts" import Chart, { getColorSchema } from "./Chart.svelte"
import Chart, { colorSchemas } from "./Chart"
let type = "donut" let type = "donut"
export let colorSchema = colorSchemas.britecharts export let data = []
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 = { top: 0, right: 0, bottom: 0, left: 0 }
@ -15,6 +15,22 @@
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
$: colorSchema = getColorSchema(color)
</script> </script>
<Chart {type} {...$$props} /> <Chart
{type}
{useLegend}
{data}
{colorSchema}
{height}
{width}
{margin}
{externalRadius}
{hasFixedHighlightedSlice}
{hasLastHoverSliceHighlighted}
{internalRadius}
{isAnimated}
{radiusHoverOffset} />

View File

@ -0,0 +1,82 @@
<script>
import Chart, { getColorSchema, getChartGradient } from "./Chart.svelte"
/*
ISSUES:
*/
let type = "line"
let tooltip
export let data = []
export let axisTimeCombinations = ""
export let color = "britecharts"
export let grid = "horizontal"
export let aspectRatio = 0.5
export let dateLabel = "date"
export let width = null
export let height = null
export let isAnimated = true
export let lineCurve = "linear" //see api for possible opts
export let locale = "en-GB"
export let numberFormat = ""
export let shouldShowAllDataPoints = true
export let topicLabel = null
export let valueLabel = null
export let xAxisLabel = ""
export let xAxisValueType = "date"
export let xAxisScale = "linear"
export let xAxisFormat = "day-month"
export let xAxisCustomFormat = "%H"
$: colorSchema = getColorSchema(color)
$: console.log($$props)
</script>
<Chart
{type}
{data}
{colorSchema}
{axisTimeCombinations}
{lineCurve}
{numberFormat}
{height}
{topicLabel}
{shouldShowAllDataPoints}
{xAxisLabel}
{valueLabel}
{xAxisValueType}
{xAxisScale}
{xAxisCustomFormat}
{aspectRatio}
{grid}
tooltipThreshold={600}
{width}
{dateLabel} />
<!--
isAnimated={true}
aspectRatio={0.5}
grid='horizontal'
tooltipThreshold={600}
width={600}
dateLabel='fullDate'
{type}
{data}
{colorSchema}
{axisTimeCombinations}
{lineCurve}
{numberFormat}
{height}
{topicLabel}
{shouldShowAllDataPoints}
{xAxisLabel}
{valueLabel}
{xAxisValueType}
{xAxisScale}
{xAxisCustomFormat}
-->

View File

@ -0,0 +1,3 @@
export { default as donut } from "./Donut.svelte"
export { default as bar } from "./Bar.svelte"
export { default as line } from "./Line.svelte"

View File

@ -24,3 +24,4 @@ export { default as datasearch } from "./DataSearch.svelte"
export { default as datamap } from "./DataMap.svelte" export { default as datamap } from "./DataMap.svelte"
export { default as embed } from "./Embed.svelte" export { default as embed } from "./Embed.svelte"
export { default as recorddetail } from "./RecordDetail.svelte" export { default as recorddetail } from "./RecordDetail.svelte"
export * from "./Chart"