piko-sharp-rb 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,655 @@
1
+ # Chartkick
2
+
3
+ Create beautiful JavaScript charts with one line of Ruby. No more fighting with charting libraries!
4
+
5
+ [See it in action](https://chartkick.com)
6
+
7
+ :fire: For admin charts and dashboards, check out [Blazer](https://github.com/ankane/blazer/), and for advanced visualizations, check out [Vega](https://github.com/ankane/vega)
8
+
9
+ :two_hearts: A perfect companion to [Groupdate](https://github.com/ankane/groupdate), [Hightop](https://github.com/ankane/hightop), and [ActiveMedian](https://github.com/ankane/active_median)
10
+
11
+ [![Build Status](https://github.com/ankane/chartkick/actions/workflows/build.yml/badge.svg)](https://github.com/ankane/chartkick/actions)
12
+
13
+ ## Quick Start
14
+
15
+ Add this line to your application’s Gemfile:
16
+
17
+ ```ruby
18
+ gem "chartkick"
19
+ ```
20
+
21
+ Then follow the instructions for your JavaScript setup:
22
+
23
+ - [Importmap](#importmap) (Rails 7+ default)
24
+ - [Bun, esbuild, rollup.js, or Webpack](#bun-esbuild-rollupjs-or-webpack)
25
+ - [Sprockets](#sprockets)
26
+
27
+ This sets up Chartkick with [Chart.js](https://www.chartjs.org/). For other charting libraries and frameworks, see [these instructions](#additional-charting-libraries).
28
+
29
+ ### Importmap
30
+
31
+ In `config/importmap.rb`, add:
32
+
33
+ ```ruby
34
+ pin "chartkick", to: "chartkick.js"
35
+ pin "Chart.bundle", to: "Chart.bundle.js"
36
+ ```
37
+
38
+ And in `app/javascript/application.js`, add:
39
+
40
+ ```js
41
+ import "chartkick"
42
+ import "Chart.bundle"
43
+ ```
44
+
45
+ ### Bun, esbuild, rollup.js, or Webpack
46
+
47
+ Run:
48
+
49
+ ```sh
50
+ bun add chartkick chart.js
51
+ # or
52
+ yarn add chartkick chart.js
53
+ ```
54
+
55
+ And in `app/javascript/application.js`, add:
56
+
57
+ ```js
58
+ import "chartkick/chart.js"
59
+ ```
60
+
61
+ ### Sprockets
62
+
63
+ In `app/assets/javascripts/application.js`, add:
64
+
65
+ ```js
66
+ //= require chartkick
67
+ //= require Chart.bundle
68
+ ```
69
+
70
+ ## Charts
71
+
72
+ Line chart
73
+
74
+ ```erb
75
+ <%= line_chart User.group_by_day(:created_at).count %>
76
+ ```
77
+
78
+ Pie chart
79
+
80
+ ```erb
81
+ <%= pie_chart Goal.group(:name).count %>
82
+ ```
83
+
84
+ Column chart
85
+
86
+ ```erb
87
+ <%= column_chart Task.group_by_hour_of_day(:created_at, format: "%l %P").count %>
88
+ ```
89
+
90
+ Bar chart
91
+
92
+ ```erb
93
+ <%= bar_chart Shirt.group(:size).sum(:price) %>
94
+ ```
95
+
96
+ Area chart
97
+
98
+ ```erb
99
+ <%= area_chart Visit.group_by_minute(:created_at).maximum(:load_time) %>
100
+ ```
101
+
102
+ Scatter chart
103
+
104
+ ```erb
105
+ <%= scatter_chart City.pluck(:size, :population) %>
106
+ ```
107
+
108
+ Geo chart - *Google Charts*
109
+
110
+ ```erb
111
+ <%= geo_chart Medal.group(:country).count %>
112
+ ```
113
+
114
+ Timeline - *Google Charts*
115
+
116
+ ```erb
117
+ <%= timeline [
118
+ ["Washington", "1789-04-29", "1797-03-03"],
119
+ ["Adams", "1797-03-03", "1801-03-03"],
120
+ ["Jefferson", "1801-03-03", "1809-03-03"]
121
+ ] %>
122
+ ```
123
+
124
+ Multiple series
125
+
126
+ ```erb
127
+ <%= line_chart [
128
+ {name: "Workout", data: {"2025-01-01" => 3, "2025-01-02" => 4}},
129
+ {name: "Call parents", data: {"2025-01-01" => 5, "2025-01-02" => 3}}
130
+ ] %>
131
+ ```
132
+
133
+ or
134
+
135
+ ```erb
136
+ <%= line_chart Feat.group(:goal_id).group_by_week(:created_at).count %>
137
+ ```
138
+
139
+ ## Data
140
+
141
+ Data can be a hash, array, or URL.
142
+
143
+ #### Hash
144
+
145
+ ```erb
146
+ <%= line_chart({"2025-01-01" => 2, "2025-01-02" => 3}) %>
147
+ ```
148
+
149
+ #### Array
150
+
151
+ ```erb
152
+ <%= line_chart [["2025-01-01", 2], ["2025-01-02", 3]] %>
153
+ ```
154
+
155
+ #### URL
156
+
157
+ Make your pages load super fast and stop worrying about timeouts. Give each chart its own endpoint.
158
+
159
+ ```erb
160
+ <%= line_chart completed_tasks_charts_path %>
161
+ ```
162
+
163
+ And in your controller, pass the data as JSON.
164
+
165
+ ```ruby
166
+ class ChartsController < ApplicationController
167
+ def completed_tasks
168
+ render json: Task.group_by_day(:completed_at).count
169
+ end
170
+ end
171
+ ```
172
+
173
+ For multiple series, add `chart_json` at the end.
174
+
175
+ ```ruby
176
+ render json: Task.group(:goal_id).group_by_day(:completed_at).count.chart_json
177
+ ```
178
+
179
+ ## Options
180
+
181
+ Id, width, and height
182
+
183
+ ```erb
184
+ <%= line_chart data, id: "users-chart", width: "800px", height: "500px" %>
185
+ ```
186
+
187
+ Min and max values
188
+
189
+ ```erb
190
+ <%= line_chart data, min: 1000, max: 5000 %>
191
+ ```
192
+
193
+ `min` defaults to 0 for charts with non-negative values. Use `nil` to let the charting library decide.
194
+
195
+ Min and max for x-axis - *Chart.js*
196
+
197
+ ```erb
198
+ <%= line_chart data, xmin: "2025-01-01", xmax: "2025-02-01" %>
199
+ ```
200
+
201
+ Colors
202
+
203
+ ```erb
204
+ <%= line_chart data, colors: ["#b00", "#666"] %>
205
+ ```
206
+
207
+ Stacked columns or bars
208
+
209
+ ```erb
210
+ <%= column_chart data, stacked: true %>
211
+ ```
212
+
213
+ Discrete axis
214
+
215
+ ```erb
216
+ <%= line_chart data, discrete: true %>
217
+ ```
218
+
219
+ Label (for single series)
220
+
221
+ ```erb
222
+ <%= line_chart data, label: "Value" %>
223
+ ```
224
+
225
+ Axis titles
226
+
227
+ ```erb
228
+ <%= line_chart data, xtitle: "Time", ytitle: "Population" %>
229
+ ```
230
+
231
+ Straight lines between points instead of a curve
232
+
233
+ ```erb
234
+ <%= line_chart data, curve: false %>
235
+ ```
236
+
237
+ Hide points
238
+
239
+ ```erb
240
+ <%= line_chart data, points: false %>
241
+ ```
242
+
243
+ Show or hide legend
244
+
245
+ ```erb
246
+ <%= line_chart data, legend: false %>
247
+ ```
248
+
249
+ Specify legend position
250
+
251
+ ```erb
252
+ <%= line_chart data, legend: "bottom" %>
253
+ ```
254
+
255
+ Donut chart
256
+
257
+ ```erb
258
+ <%= pie_chart data, donut: true %>
259
+ ```
260
+
261
+ Prefix, useful for currency - *Chart.js, Highcharts*
262
+
263
+ ```erb
264
+ <%= line_chart data, prefix: "$" %>
265
+ ```
266
+
267
+ Suffix, useful for percentages - *Chart.js, Highcharts*
268
+
269
+ ```erb
270
+ <%= line_chart data, suffix: "%" %>
271
+ ```
272
+
273
+ Set a thousands separator - *Chart.js, Highcharts*
274
+
275
+ ```erb
276
+ <%= line_chart data, thousands: "," %>
277
+ ```
278
+
279
+ Set a decimal separator - *Chart.js, Highcharts*
280
+
281
+ ```erb
282
+ <%= line_chart data, decimal: "," %>
283
+ ```
284
+
285
+ Set significant digits - *Chart.js, Highcharts*
286
+
287
+ ```erb
288
+ <%= line_chart data, precision: 3 %>
289
+ ```
290
+
291
+ Set rounding - *Chart.js, Highcharts*
292
+
293
+ ```erb
294
+ <%= line_chart data, round: 2 %>
295
+ ```
296
+
297
+ Show insignificant zeros, useful for currency - *Chart.js, Highcharts*
298
+
299
+ ```erb
300
+ <%= line_chart data, round: 2, zeros: true %>
301
+ ```
302
+
303
+ Friendly byte sizes - *Chart.js*
304
+
305
+ ```erb
306
+ <%= line_chart data, bytes: true %>
307
+ ```
308
+
309
+ Specify the message when data is loading
310
+
311
+ ```erb
312
+ <%= line_chart data, loading: "Loading..." %>
313
+ ```
314
+
315
+ Specify the message when data is empty
316
+
317
+ ```erb
318
+ <%= line_chart data, empty: "No data" %>
319
+ ```
320
+
321
+ Refresh data from a remote source every `n` seconds
322
+
323
+ ```erb
324
+ <%= line_chart url, refresh: 60 %>
325
+ ```
326
+
327
+ You can pass options directly to the charting library with:
328
+
329
+ ```erb
330
+ <%= line_chart data, library: {backgroundColor: "#eee"} %>
331
+ ```
332
+
333
+ See the documentation for [Chart.js](https://www.chartjs.org/docs/), [Google Charts](https://developers.google.com/chart/interactive/docs/gallery), and [Highcharts](https://api.highcharts.com/highcharts) for more info. For Chart.js plugins, check out [this guide](guides/Chartjs-Plugins.md).
334
+
335
+ To customize datasets in Chart.js, use:
336
+
337
+ ```erb
338
+ <%= line_chart data, dataset: {borderWidth: 10} %>
339
+ ```
340
+
341
+ You can pass this option to individual series as well.
342
+
343
+ ### Global Options
344
+
345
+ To set options for all of your charts, create an initializer `config/initializers/chartkick.rb` with:
346
+
347
+ ```ruby
348
+ Chartkick.options = {
349
+ height: "400px",
350
+ colors: ["#b00", "#666"]
351
+ }
352
+ ```
353
+
354
+ Customize the html
355
+
356
+ ```ruby
357
+ Chartkick.options[:html] = '<div id="%{id}" style="height: %{height};">%{loading}</div>'
358
+ ```
359
+
360
+ You capture the JavaScript in a content block with:
361
+
362
+ ```ruby
363
+ Chartkick.options[:content_for] = :charts_js
364
+ ```
365
+
366
+ Then, in your layout, use:
367
+
368
+ ```erb
369
+ <%= yield :charts_js %>
370
+ ```
371
+
372
+ For Padrino, use `yield_content` instead of `yield`.
373
+
374
+ This is great for including all of your JavaScript at the bottom of the page.
375
+
376
+ ### Multiple Series
377
+
378
+ You can pass a few options with a series:
379
+
380
+ - `name`
381
+ - `data`
382
+ - `color`
383
+ - `dataset` - *Chart.js only*
384
+ - `points` - *Chart.js only*
385
+ - `curve` - *Chart.js only*
386
+
387
+ ### Code
388
+
389
+ If you want to use the charting library directly, get the code with:
390
+
391
+ ```erb
392
+ <%= line_chart data, code: true %>
393
+ ```
394
+
395
+ The code will be logged to the JavaScript console. JavaScript functions cannot be logged, so it may not be identical.
396
+
397
+ ### Download Charts
398
+
399
+ *Chart.js only*
400
+
401
+ Give users the ability to download charts. It all happens in the browser - no server-side code needed.
402
+
403
+ ```erb
404
+ <%= line_chart data, download: true %>
405
+ ```
406
+
407
+ Safari will open the image in a new window instead of downloading.
408
+
409
+ Set the filename
410
+
411
+ ```erb
412
+ <%= line_chart data, download: {filename: "boom"} %>
413
+ ```
414
+
415
+ Set the background color
416
+
417
+ ```erb
418
+ <%= line_chart data, download: {background: "#ffffff"} %>
419
+ ```
420
+
421
+ Set title
422
+
423
+ ```erb
424
+ <%= line_chart data, title: "Awesome chart" %>
425
+ ```
426
+
427
+ ## Additional Charting Libraries
428
+
429
+ - [Google Charts](#google-charts)
430
+ - [Highcharts](#highcharts)
431
+
432
+ ### Google Charts
433
+
434
+ In your layout or views, add:
435
+
436
+ ```erb
437
+ <%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>
438
+ ```
439
+
440
+ For Importmap (Rails 7+ default), in `config/importmap.rb`, add:
441
+
442
+ ```ruby
443
+ pin "chartkick", to: "chartkick.js"
444
+ ```
445
+
446
+ And in `app/javascript/application.js`, add:
447
+
448
+ ```js
449
+ import "chartkick"
450
+ ```
451
+
452
+ For Bun, esbuild, rollup.js, or Webpack, run:
453
+
454
+ ```sh
455
+ bun add chartkick
456
+ # or
457
+ yarn add chartkick
458
+ ```
459
+
460
+ And in `app/javascript/packs/application.js`, add:
461
+
462
+ ```js
463
+ import "chartkick"
464
+ ```
465
+
466
+ For Sprockets, in `app/assets/javascripts/application.js`, add:
467
+
468
+ ```js
469
+ //= require chartkick
470
+ ```
471
+
472
+ To specify a language or Google Maps API key, use:
473
+
474
+ ```js
475
+ Chartkick.configure({language: "de", mapsApiKey: "..."})
476
+ ```
477
+
478
+ before your charts.
479
+
480
+ ### Highcharts
481
+
482
+ For Importmap (Rails 7+ default), run:
483
+
484
+ ```sh
485
+ bin/importmap pin highcharts --download
486
+ ```
487
+
488
+ And in `config/importmap.rb`, add:
489
+
490
+ ```ruby
491
+ pin "chartkick", to: "chartkick.js"
492
+ ```
493
+
494
+ And in `app/javascript/application.js`, add:
495
+
496
+ ```js
497
+ import "chartkick"
498
+ import Highcharts from "highcharts"
499
+
500
+ window.Highcharts = Highcharts
501
+ ```
502
+
503
+ For Bun, esbuild, rollup.js, or Webpack, run:
504
+
505
+ ```sh
506
+ bun add chartkick highcharts
507
+ # or
508
+ yarn add chartkick highcharts
509
+ ```
510
+
511
+ And in `app/javascript/packs/application.js`, add:
512
+
513
+ ```js
514
+ import "chartkick/highcharts"
515
+ ```
516
+
517
+ For Sprockets, download [highcharts.js](https://code.highcharts.com/highcharts.js) into `vendor/assets/javascripts` (or use `yarn add highcharts`), and in `app/assets/javascripts/application.js`, add:
518
+
519
+ ```js
520
+ //= require chartkick
521
+ //= require highcharts
522
+ ```
523
+
524
+ ### Multiple Libraries
525
+
526
+ If more than one charting library is loaded, choose between them with:
527
+
528
+ ```erb
529
+ <%= line_chart data, adapter: "google" %> <!-- or highcharts or chartjs -->
530
+ ```
531
+
532
+ ## Sinatra and Padrino
533
+
534
+ Download [chartkick.js](https://raw.githubusercontent.com/ankane/chartkick/master/vendor/assets/javascripts/chartkick.js) and include it manually.
535
+
536
+ ```html
537
+ <script src="chartkick.js"></script>
538
+ ```
539
+
540
+ Then include the charting library.
541
+
542
+ Chart.js - download [Chart.js](https://unpkg.com/chart.js@4/dist/chart.umd.js) and the [date-fns adapter bundle](https://unpkg.com/chartjs-adapter-date-fns@3/dist/chartjs-adapter-date-fns.bundle.js)
543
+
544
+ ```html
545
+ <script src="chart.js"></script>
546
+ <script src="chartjs-adapter-date-fns.bundle.js"></script>
547
+ ```
548
+
549
+ Google Charts
550
+
551
+ ```html
552
+ <script src="https://www.gstatic.com/charts/loader.js"></script>
553
+ ```
554
+
555
+ Highcharts - download [highcharts.js](https://code.highcharts.com/highcharts.js)
556
+
557
+ ```html
558
+ <script src="highcharts.js"></script>
559
+ ```
560
+
561
+ ## JavaScript API
562
+
563
+ Access a chart with:
564
+
565
+ ```javascript
566
+ var chart = Chartkick.charts["chart-id"]
567
+ ```
568
+
569
+ Get the underlying chart object with:
570
+
571
+ ```javascript
572
+ chart.getChartObject()
573
+ ```
574
+
575
+ You can also use:
576
+
577
+ ```javascript
578
+ chart.getElement()
579
+ chart.getData()
580
+ chart.getOptions()
581
+ chart.getAdapter()
582
+ ```
583
+
584
+ Update the data with:
585
+
586
+ ```javascript
587
+ chart.updateData(newData)
588
+ ```
589
+
590
+ You can also specify new options:
591
+
592
+ ```javascript
593
+ chart.setOptions(newOptions)
594
+ // or
595
+ chart.updateData(newData, newOptions)
596
+ ```
597
+
598
+ Refresh the data from a remote source:
599
+
600
+ ```javascript
601
+ chart.refreshData()
602
+ ```
603
+
604
+ Redraw the chart with:
605
+
606
+ ```javascript
607
+ chart.redraw()
608
+ ```
609
+
610
+ Destroy the chart with:
611
+
612
+ ```javascript
613
+ chart.destroy()
614
+ ```
615
+
616
+ Loop over charts with:
617
+
618
+ ```javascript
619
+ Chartkick.eachChart(function (chart) {
620
+ // do something
621
+ })
622
+ ```
623
+
624
+ ## Content Security Policy (CSP)
625
+
626
+ Check out [how to configure CSP](https://github.com/ankane/chartkick/blob/master/guides/Content-Security-Policy.md)
627
+
628
+ ## Tutorials
629
+
630
+ - [Charts with Chartkick and Groupdate](https://gorails.com/episodes/charts-with-chartkick-and-groupdate)
631
+ - [Creando gráficos en Ruby on Rails con Chartkick y Chart.js](https://www.youtube.com/watch?v=W92AlkwQn3M)
632
+ - [Make Easy Graphs and Charts on Rails with Chartkick](https://www.sitepoint.com/make-easy-graphs-and-charts-on-rails-with-chartkick/)
633
+ - [Practical Graphs on Rails: Chartkick in Practice](https://www.sitepoint.com/graphs-on-rails-chartkick-in-practice/)
634
+
635
+ ## History
636
+
637
+ View the [changelog](https://github.com/ankane/chartkick/blob/master/CHANGELOG.md)
638
+
639
+ ## Contributing
640
+
641
+ Everyone is encouraged to help improve this project. Here are a few ways you can help:
642
+
643
+ - [Report bugs](https://github.com/ankane/chartkick/issues)
644
+ - Fix bugs and [submit pull requests](https://github.com/ankane/chartkick/pulls)
645
+ - Write, clarify, or fix documentation
646
+ - Suggest or add new features
647
+
648
+ To get started with development:
649
+
650
+ ```sh
651
+ git clone https://github.com/ankane/chartkick.git
652
+ cd chartkick
653
+ bundle install
654
+ bundle exec rake test
655
+ ```
@@ -0,0 +1,26 @@
1
+ # for both multiple series and
2
+ # making sure hash order is preserved in JavaScript
3
+
4
+ class Array
5
+ def chart_json
6
+ map do |v|
7
+ if v.is_a?(Hash) && v[:data].is_a?(Hash)
8
+ v = v.dup
9
+ v[:data] = v[:data].to_a
10
+ end
11
+ v
12
+ end.to_json
13
+ end
14
+ end
15
+
16
+ class Hash
17
+ def chart_json
18
+ if (key = keys.first) && key.is_a?(Array) && key.size == 2
19
+ group_by { |k, _v| k[0] }.map do |name, data|
20
+ {name: name, data: data.map { |k, v| [k[1], v] }}
21
+ end
22
+ else
23
+ to_a
24
+ end.to_json
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ module Chartkick
2
+ class Engine < ::Rails::Engine
3
+ # for assets
4
+
5
+ # for importmap
6
+ initializer "chartkick.importmap" do |app|
7
+ if app.config.respond_to?(:assets) && defined?(Importmap) && defined?(Sprockets)
8
+ app.config.assets.precompile << "chartkick.js"
9
+ app.config.assets.precompile << "Chart.bundle.js"
10
+ end
11
+ end
12
+ end
13
+ end