Coder Social home page Coder Social logo

himynameisdave / svelte-frappe-charts Goto Github PK

View Code? Open in Web Editor NEW
301.0 8.0 16.0 1.16 MB

📈 Svelte bindings for frappe-charts.

Home Page: https://frappe.io/charts

License: MIT License

JavaScript 42.21% Svelte 57.79%
svelte frappe-charts svelte-component svg-charts charting-library charts

svelte-frappe-charts's Introduction

svelte-frappe-charts

📈 Svelte bindings for frappe-charts.


Makes it easy to use frappe-charts in your Svelte project.

Installation

yarn add svelte svelte-frappe-charts

npm i -S svelte svelte-frappe-charts

Note: Assumes you are using >= [email protected].

Usage

Use the chart in your Svelte project with ease:

<script>
  import Chart from 'svelte-frappe-charts';

  let data = {
    labels: ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'],
    datasets: [
      {
        values: [10, 12, 3, 9, 8, 15, 9]
      }
    ]
  };
</script>

<Chart data={data} type="line" />

The component API directly matches the the configuration of frappe-charts.

Updating data

There are two ways to update data in a chart: either in adding and removing individual points, or updating the existing data with an entirely new set of data points.

Updating individual data points

addDataPoint

Add a data point to the chart, increasing the length of the dataset.

<script>
  import Chart from 'svelte-frappe-charts';

  let data = {
    labels: ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'],
    datasets: [
      {
        values: [10, 12, 3, 9, 8, 15, 9]
      }
    ]
  };

  let chartRef;

  function addDataPoint() {
    chartRef.addDataPoint('Wed', [30], 1);
  }
</script>

<Chart data={data} type="line" bind:this={chartRef} />

<button on:click={addDataPoint}>Add data point</button>

More info on addDataPoint.

removeDataPoint

Remove a data point from the chart, reducing the length of the dataset.

<script>
  import Chart from 'svelte-frappe-charts';

  let data = {
    labels: ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'],
    datasets: [
      {
        values: [10, 12, 3, 9, 8, 15, 9]
      }
    ]
  };

  let chartRef;

  function removeDataPoint() {
    chartRef.removeDataPoint(3); // Index of the item to remove
  }
</script>

<Chart data={data} type="line" bind:this={chartRef} />

<button on:click={removeDataPoint}>Remove data point</button>

More info on removeDataPoint.

Updating full data

Update the entire data, including annotations, by passing the entire new data object to update.

<script>
  import Chart from 'svelte-frappe-charts';

  let data = {
    labels: ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'],
    datasets: [
      {
        values: [10, 12, 3, 9, 8, 15, 9]
      }
    ]
  };

  let chartRef;

  function updateData() {
    data = {
      labels: ['Friday', 'Saturday', 'Sunday'],
      datasets: [
        {
          values: [300, 380, 275]
        }
      ]
    };
  }
</script>

<Chart data={data} type="line" bind:this={chartRef} />

<button on:click={updateData}>Update Chart</button>

Chart navigation

Chart navigation can be used when the isNavigable prop is set on the Chart component. Once it is set, the data-select event is propagated and can be handled in Svelte's standard ways (see the Events section of the tutorial and examples, and the API docs).

<script>
  import Chart from "svelte-frappe-charts";

  let data = {
    labels: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon" ],
    datasets: [
      { values: [ 300, 250, 720, 560, 370, 610, 690, 410, 370, 480, 620, 260, 170, 510, 630, 710 ] },
    ],
  };

  const onDataSelect = (event) => {
    console.log("Data select event fired!", event);
    selected = event;
  };
  let selected;
</script>

<h1>Svelte Frappe charts navigation demo</h1>
<Chart {data} on:data-select={onDataSelect} isNavigable type="bar" />

Exporting charts

You can easily export a chart (see Exporting) as an SVG by storing a reference to the <Chart /> component, and then calling exportChart on it:

<script>
  // ...

  let chartRef;
  const onExport = () => chartRef.exportChart();
</script>

<Chart data={data} type="line" bind:this={chartRef} />
<button on:click={onExport}>
  Export
</button>

Contributing

Issues and pull requests are greatly welcome!


✌️Created by Dave. Licenced under MIT.

svelte-frappe-charts's People

Contributors

bry-an avatar dependabot[bot] avatar djole87 avatar fossabot avatar himynameisdave avatar jadedblueeyes avatar mehdiraized avatar nripendra avatar torstendittmann avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svelte-frappe-charts's Issues

Uncaught DOMException: Failed to execute 'removeChild' on 'Node'

When updating the data of a charts I have the following error:

Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

Even with this code from the README:

<script>
  import Chart from 'svelte-frappe-charts';

  let data = {
    labels: ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'],
    datasets: [
      {
        values: [10, 12, 3, 9, 8, 15, 9]
      }
    ]
  };

  let chartRef;

  function updateData() {
    data = {
      labels: ['Friday', 'Saturday', 'Sunday'],
      datasets: [
        {
          values: [300, 380, 275]
        }
      ]
    };
  }
</script>

<Chart data={data} type="line" bind:this={chartRef} />

<button on:click={updateData}>Update Chart</button>

Using Sapper: <Chart> is not a valid SSR component

Using the example:

<script>
  import Chart from 'svelte-frappe-charts';

  let data = {
    labels: ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'],
    datasets: [
      {
        values: [10, 12, 3, 9, 8, 15, 9]
      }
    ]
  };
</script>

<Chart data={data} type="line" />

It gives me a 500 error:

<Chart> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules

Is there an easy fix for this? Is it possible to use SSR with this package?

Font size options?

Having issues with overlapping labels, I can't target the text inside the svg using CSS, I'd like to customize my FONT_SIZE, instead of the usual 10

Why doesn't axisOptions work?

<script> import Chart from "svelte-frappe-charts"; let data = { labels: ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"], datasets: [ { values: [10, 12, 3, 9, 8, 15, 9], }, ], }; let axisOptions = { xIsSeries: true, // default: false }; let lineOptions = { hideDots: 1, // default: 0 spline: 1, }; </script>

<Chart {data} type="line" colors={["red"]} axisOptions={axisOptions} lineOptions={lineOptions} />``

TypeScript definitions

Currently, the package does not provide TypeScript definitions. It would be nice if the package provided TypeScript definitions to avoid this kind of error:

Error: Could not find a declaration file for module 'svelte-frappe-charts'. '/node_modules/svelte-frappe-charts/lib/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/svelte-frappe-charts` if it exists or add a new declaration (.d.ts) file containing `declare module 'svelte-frappe-charts';` (ts)

This should be pretty simple to do since the @types/frappe-gantt package is already available.

Update chart after props change

I'm new to svelte so I may be missing something. I have code like this

    let reducedData = regionalData.reduce(foldfn, {});
    let vals = Object.values(reducedData);
    let datasets = [];
    let data = {
        labels: [],
        datasets,
    };

    afterUpdate(() => {
        datasets = selectedRegions.map((item) => {
            const fqn = item[0] + "-" + item[1];
            return { name: item[1], values: vals.map((r) => r[fqn]) };
        });
        data = {
            labels: Object.keys(reducedData),
            datasets,
        };
        if (chartRef) chartRef.update(data);
    });
</script>

    <Chart
        type="line"
        height="500"
        {data}
        {lineOptions}
        {axisOptions}
        bind:this={chartRef} />

selectedRegions is set by the props and can change. But although I see data changing (use @debug) the chart does not redraw.

I noticed that you add bind:this={chartRef} through the examples when they are supposed to be updatable, and use chartRef in the example. But the use of chartRef is missing in the update all example. It seemed as though .update should have worked but I am getting TypeError: chartRef.update is not a function

Could we have more examples?

This may just be an oversight on my part - but I am not understanding how I can pass a series of configs to the Chart item?

Instead of passing type="line" in the <Chart> item, is it possible to just pass <Chart config={config}> where let config = {type: 'line'}?

Error: <path> attribute d: Expected number, "…10 C 1381.8,510 NaN,NaN 1551,510…".

Hi, I am getting this error twice in Chrome Browser developer tools
Here is some code to reproduce it

<script lang="ts">
	import Chart from 'svelte-frappe-charts';

	interface YRange {
		start: number;
		end: number;
	}

	export let xticks: string[];
	export let data: number[];
	export let threshold: number;
	export let yrange: YRange;
	export let height: number = 200;

	const lineOptions:object = {		
		dotSize: 3,
		hideDots: 0,
		spline: 1,
		regionFill: 1	
	};

	const axisOptions = {
		xAxisMode: 'tick'
		// xIsSeries: true
	};

	const tooltipOptions = {
		formatTooltipX: (d: string) => 'Segment:' + d,
		formatTooltipY: (d: number) => d + ' pts'
	};

	let chartData = {
		labels: xticks,
		datasets: [
			{
				values: data
			}
		],
		yMarkers: [
			{
				label: 'Threshold',
				value: threshold,
				options: { labelPos: 'left' } // default: 'right'
			}
		],
		yRegions: [
			{
				label: 'Optimum Range',
				start: yrange.start,
				end: yrange.end,
				options: { labelPos: 'right' }
			}
		]
	};
</script>

<Chart
	type="line"
	height={height}
	title="My Awesome Chart"	
	data={chartData}
	lineOptions={lineOptions}
	axisOptions={axisOptions}
	tooltipOptions={tooltipOptions}
/>

I managed to locate the source of the problem, those two lineOptions
spline: 1 and regionFill: 1 produce this error

Error: attribute d: Expected number, "…10 C 1381.8,510 NaN,NaN 1551,510…".
selte-frappe-charts.js?v=b86eed3b:177

This is how far I can examine this issue. Do notice that the display with spline, and regionFill is drawn correctly. It's probably an issue with Chrome Browser Version 112.0.5615.165 (Official Build) (64-bit) and my configuration options.

I use svelte-frappe-charts v1.10.0

Dynamically adding dataset leads to error

If I have e.g. one dataset in the beginning and add another dataset to the data object by assigning the full object (in accordance to the documentation) the following error is thrown:

Uncaught (in promise) TypeError: Cannot set properties of undefined (setting 'textContent')
    at e.value (AxisChart.js:426:20)
    at e.value (BaseChart.js:241:8)
    at base.svelte:59:54
    at ifChart (base.svelte:41:16)
    at $$self.$$.update (base.svelte:60:6)
    at update (index.mjs:1089:12)
    at flush (index.mjs:1060:13)

The issue only appears if the initial data holds 1 or less datasets. If changing the number of datasets from 2 to 3 no error is thrown, but the third line is not updated like the initial 2 datasets.

Code to replicate:

<script>
  import Chart from 'svelte-frappe-charts';

  let numberOfDatapoints = 25;

  let data = {
    labels: Array.from({length: numberOfDatapoints}, (x, i) => i),
    datasets: [
      {
          values: Array.from({length: numberOfDatapoints}, () => Math.floor(Math.random() * 40))
      }
    ]
  };

  let chartRef;

  function updateData() {
    data = {
      labels: Array.from({length: numberOfDatapoints}, (x, i) => i),
      datasets: [
        {
          values: Array.from({length: numberOfDatapoints}, () => Math.floor(Math.random() * 40))
        },
        {
          values: Array.from({length: numberOfDatapoints}, () => Math.floor(Math.random() * 40))
        },
      ]
    };
  }
</script>
<div style="600px">
  <Chart data={data} type="line" bind:this={chartRef} />
</div>


<button on:click={updateData}>Update Chart</button>

IsNavigable Uncaught Type errors

When copying and pasting the code for the navigable bar chart:

<script>
  import Chart from "svelte-frappe-charts";

  let data = {
    labels: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon" ],
    datasets: [
      { values: [ 300, 250, 720, 560, 370, 610, 690, 410, 370, 480, 620, 260, 170, 510, 630, 710 ] },
    ],
  };

  const onDataSelect = (event) => {
    console.log("Data select event fired!", event);
    selected = event;
  };
  let selected;
</script>

<Chart {data} on:data-select={onDataSelect} isNavigable type="bar" />

I am getting these errors:
Uncaught TypeError: Cannot read property 'nodeName' of undefined and
Uncaught TypeError: Cannot read property 'parentNode' of undefined

image

Error when refreshing the page

Hi,
I'm getting Error: attribute width: A negative value is not valid. ("-3.1999999999999993") when refreshing the page or redirecting from another page.
I tried to render it in accordion as well in normal html body, but getting same issue.
image
Please help.

It does not work

Following the documentation, I have initialized the instance but it doesn't work.

<div class="card">
    <div id="chart"></div>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/frappe-charts.min.iife.js"></script>
<script>
    var users  = @json(array_values($usersPerMonth));
    var months = @json(array_keys($usersPerMonth));

    var data = {
        labels: [
            "12am-3am", "3am-6pm", "6am-9am", "9am-12am",
            "12pm-3pm", "3pm-6pm", "6pm-9pm", "9am-12am"
        ],
        datasets: [
            {
                name: "Some Data", type: "bar",
                values: [25, 40, 30, 35, 8, 52, 17, -4]
            },
            {
                name: "Another Set", type: "line",
                values: [25, 50, -10, 15, 18, 32, 27, 14]
            }
        ]
    };

    var chart = new frappe.Chart("#chart", {
        title: "My Awesome Chart",
        data: data,
        type: 'axis-mixed',
        height: 250,
        colors: ['#7cd6fd', '#743ee2']
    });
</script>

Uncaught (in promise) Error: No `parent` element to render on was provided.

Hi, thanks for this adapter. It didn’t work for me, i use svelte > 3.0

<script>
  import Chart from "svelte-frappe-charts";

  let data = {
    labels: ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"],
    datasets: [
      {
        values: [10, 12, 3, 9, 8, 15, 9]
      }
    ]
  };
</script>

browser log

Uncaught (in promise) Error: No parent element to render on was provided. at e.t (index.mjs:241) at new e (index.mjs:241) at getChartByType (index.mjs:241) at new t (index.mjs:241) at onMount (index.mjs:303) at run (index.mjs:18) at Array.map (<anonymous>) at add_render_callback (index.mjs:1353) at flush (index.mjs:689) at <anonymous>

Plot not not updating when setting all new data

I can show a plot and append new data points to it with "chartRef.addDataPoint".

For some reason I cant set all data new. Below is how my plot module is made:

init() is for upload data for the plot, server side.
data_updated() is for when new data should be appended the current plot
data_changed() is for creating a new plot. It is using init() to update the data variable.

Can anyone see what I am doing wrong, or a work around?

<script context="module">
        import Chart from 'svelte-frappe-charts';

        let active_tid = 0;
        let data = {};

        export async function init(msg){
                console.log("Create data for plot")
                active_tid = msg.tid;
                data = {
                        labels: msg.timestamps.map((epoch) => {
                                let d = new Date(epoch*1000).toLocaleTimeString(); //toLocaleString();
                                return d;
                        }),
                        datasets: [
                                {
                                        values: msg.values.map((dp) =>{
                                                return dp.toFixed(2);
                                        })
                                }
                        ],
                }
                return msg.timestamps[msg.timestamps.length - 1];
        }
</script>

<script>
        export let plotHeader = '';
        import {tid, ended, consumption_kwh, last_plotindex} from '../../transaction_store'
        import { onMount } from 'svelte';
        import {page} from '$app/stores';

        let tooltipOptions = {
                formatTooltipX: (d) => (d + "").toUpperCase(),
                formatTooltipY: (d) => (d + " kW")
        }
        let axisOptions = {
                xAxisMode: "tick",
                xIsSeries: true,
                yAxisMode: 'span'
        }
        let lineOptions = {
                dotSize: 3, // default: 4
                hideDots: 1,
                spline: 0
        }
        let chartRef;


        function addDataPoint(timestamp, value) {
                chartRef.addDataPoint(timestamp, [value]);
        }

        async function data_updated(consumption){
                if(consumption == 0){
                        return;
                }

                let plot_response = await fetch(`/${$page.params.stationid}/control/station_plotdata.json?tid=${$tid}&from=${$last_plotindex+1}`);
                let tinfo = {};
                try{
                        let msg = await plot_response.json();
                        if(msg.timestamps.length == 0){
                                return;
                        }
                        for (let i=0; i<msg.timestamps.length; i++){
                                addDataPoint(new Date(msg.timestamps[i]*1000).toLocaleTimeString(), msg.values[i].toFixed(2));
                        }
                        $last_plotindex = msg.timestamps[msg.timestamps.length - 1];
                }
                catch (err){
                        console.log("Request plot", err)
                }
        }

        async function data_changed(tid){
                console.log("Change plot data for TID:", tid);
                let plot_response = await fetch(`/${$page.params.stationid}/control/station_plotdata.json?tid=${tid}`);
                let tinfo = {};
                try{
                        let msg = await plot_response.json();
                        if(msg.timestamps.length == 0){
                                return;
                        }
                        init(msg);
                        $last_plotindex = msg.timestamps[msg.timestamps.length - 1];;
                }
                catch (err){
                        console.log("Request plot", err)
                }
        }


        onMount(async () => {
                //console.log("On mount", $page.params.stationid)

        });

        //Update the plot when the consumption changes
        //$: data_updated($consumption_kwh);
        $: $tid && $tid != active_tid && data_changed($tid);

</script>

<div id="chart">
        <Chart id="plotDiv" data={data} title={plotHeader} tooltipOptions={tooltipOptions} axisOptions={axisOptions} lineOptions={lineOptions} bind:this={chartRef}/>
</div>

Cannot handle large datasets?

What is the largest dataset that can be handled? I tried putting in 8000 data points in the array and it didn't work. Limiting that same dataset to less worked though...

Doesn't fill the chart with zero values when data is missing

according to the documentation, the chart should fill up missing values with 0 as long as the labels are set:
i have 3 arrays with an amount for every weekday, today is wednesday, so the array has 3 items:
image
the chart is as following:

let chartData = {
		labels: ['MO', 'DI', 'MI', 'DO', 'FR'],
		datasets: [
			{ name: 'Closed', values: myClosedTickets },
			{ name: 'Worked', values: myWorkedTickets },
			{ name: 'Minutes', values: myLoggedMinutes }
		],
		title: 'Tickets'
	};

so the chart should show zero values for thursday and friday, since they are item 4 and 5 in the area, but it does not:
image

How to set Chart Title, Axis Labels?

Per the Frappe configuration documentation, you should be able to set a title. I'm not able to see if or how this is being done in the base component. Could you add this to the wrapper?

Error from Svelte Intellisense Languague Server

Good day - I've got the following error when using the module with SvelteKit:

[Error - 11:47:33 AM] Request textDocument/hover failed.
  Message: Request textDocument/hover failed with message: EISDIR: illegal operation on a directory, read
  Code: -32603 

The chart component seems to be rendered correctly so I'm not sure what to make of the issue. If it helps, there's also a warning in VS Code as below:

Could not find a declaration file for module 'svelte-frappe-charts'. '......../node_modules/svelte-frappe-charts/lib/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/svelte-frappe-charts` if it exists or add a new declaration (.d.ts) file containing `declare module 'svelte-frappe-charts';`js(7016)

Thanks!

<Chart> is not a valid SSR component

Any solution for this issue?

<Chart> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules

How can I set container for frappe charts

As I know frappe chart's width depends on its container. So in svelte-frappe-charts how can I control charts width through container. like

. I try to reset div width but it seems it is not charts container. How can I set a container for frappe chart in svelte like
const container = document.querySelector('#chart');
const chart = new Chart(container, options)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.