From 63d34162e5f11d9dfcd406712da5ab764a860d38 Mon Sep 17 00:00:00 2001 From: Jacob Burenstam Date: Thu, 1 Oct 2015 01:33:11 +0200 Subject: [PATCH] Initial commit --- .gitignore | 5 ++ README.md | 4 ++ config/config.exs | 24 ++++++++ lib/chartkick.ex | 77 ++++++++++++++++++++++++++ mix.exs | 33 +++++++++++ mix.lock | 2 + test/chartkick_test.exs | 120 ++++++++++++++++++++++++++++++++++++++++ test/test_helper.exs | 1 + 8 files changed, 266 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 config/config.exs create mode 100644 lib/chartkick.ex create mode 100644 mix.exs create mode 100644 mix.lock create mode 100644 test/chartkick_test.exs create mode 100644 test/test_helper.exs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e6a60a6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/_build +/deps +erl_crash.dump +*.ez +/tmp diff --git a/README.md b/README.md new file mode 100644 index 0000000..257addc --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +Chartkick +========= + +** TODO: Add description ** diff --git a/config/config.exs b/config/config.exs new file mode 100644 index 0000000..6dfa82f --- /dev/null +++ b/config/config.exs @@ -0,0 +1,24 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +use Mix.Config + +# This configuration is loaded before any dependency and is restricted +# to this project. If another project depends on this project, this +# file won't be loaded nor affect the parent project. For this reason, +# if you want to provide default values for your application for third- +# party users, it should be done in your mix.exs file. + +# Sample configuration: +# +# config :logger, :console, +# level: :info, +# format: "$date $time [$level] $metadata$message\n", +# metadata: [:user_id] + +# It is also possible to import configuration files, relative to this +# directory. For example, you can emulate configuration per environment +# by uncommenting the line below and defining dev.exs, test.exs and such. +# Configuration from the imported file will override the ones defined +# here (which is why it is important to import them last). +# +# import_config "#{Mix.env}.exs" diff --git a/lib/chartkick.ex b/lib/chartkick.ex new file mode 100644 index 0000000..27805be --- /dev/null +++ b/lib/chartkick.ex @@ -0,0 +1,77 @@ +defmodule Chartkick do + defmodule ChartOptions do + @derive [Poison.Encoder] + defstruct [:min, :max, :colors, :stacked, :discrete, :xtitle, :ytitle] + end + + def line_chart(data_source, options \\ []) do + chartkick_chart("LineChart", data_source, options) + end + + def pie_chart(data_source, options \\ []) do + chartkick_chart("PieChart", data_source, options) + end + + def column_chart(data_source, options \\ []) do + chartkick_chart("ColumnChart", data_source, options) + end + + def bar_chart(data_source, options \\ []) do + chartkick_chart("BarChart", data_source, options) + end + + def area_chart(data_source, options \\ []) do + chartkick_chart("AreaChart", data_source, options) + end + + def combo_chart(data_source, options \\ []) do + chartkick_chart("ComboChart", data_source, options) + end + + def geo_chart(data_source, options \\ []) do + chartkick_chart("GeoChart", data_source, options) + end + + def scatter_chart(data_source, options \\ []) do + chartkick_chart("ScatterChart", data_source, options) + end + + def timeline(data_source, options \\ []) do + chartkick_chart("Timeline", data_source, options) + end + + def chartkick_chart(klass, data_source, options \\ []) do + id = options[:id] || generate_element_id + height = options[:height] || "300px" + only = options[:only] + """ + #{unless only == :script, do: chartkick_tag(id, height)} + #{unless only == :html, do: chartkick_script(klass, id, data_source, options_json(options))} + """ + end + + def chartkick_script(klass, id, data_source, options_json) do + "" + end + + def chartkick_tag(id, height) do + "
Loading...
" + end + + defp generate_element_id do + UUID.uuid4() + end + + defp options_json(opts) do + Poison.encode!(%ChartOptions{ + min: opts[:min], + max: opts[:max], + colors: opts[:colors], + stacked: opts[:stacked], + discrete: opts[:discrete], + xtitle: opts[:xtitle], + ytitle: opts[:ytitle] + }) + end + +end diff --git a/mix.exs b/mix.exs new file mode 100644 index 0000000..4fb7b2e --- /dev/null +++ b/mix.exs @@ -0,0 +1,33 @@ +defmodule Chartkick.Mixfile do + use Mix.Project + + def project do + [app: :chartkick, + version: "0.0.1", + elixir: "~> 1.0", + build_embedded: Mix.env == :prod, + start_permanent: Mix.env == :prod, + deps: deps] + end + + # Configuration for the OTP application + # + # Type `mix help compile.app` for more information + def application do + [applications: [:logger]] + end + + # Dependencies can be Hex packages: + # + # {:mydep, "~> 0.3.0"} + # + # Or git/path repositories: + # + # {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"} + # + # Type `mix help deps` for more examples and options + defp deps do + [{ :uuid, "~> 1.0" }, + {:poison, "~> 1.5"}] + end +end diff --git a/mix.lock b/mix.lock new file mode 100644 index 0000000..2d5d881 --- /dev/null +++ b/mix.lock @@ -0,0 +1,2 @@ +%{"poison": {:hex, :poison, "1.5.0"}, + "uuid": {:hex, :uuid, "1.0.1"}} diff --git a/test/chartkick_test.exs b/test/chartkick_test.exs new file mode 100644 index 0000000..7e02d66 --- /dev/null +++ b/test/chartkick_test.exs @@ -0,0 +1,120 @@ +defmodule ChartkickTest do + use ExUnit.Case + + test "pie_chart" do + script = Chartkick.pie_chart("{}") + expected = "new Chartkick.PieChart(" + assert String.contains?(script, expected) + end + + test "column_chart" do + script = Chartkick.column_chart("{}") + expected = "new Chartkick.ColumnChart(" + assert String.contains?(script, expected) + end + + test "bar_chart" do + script = Chartkick.bar_chart("{}") + expected = "new Chartkick.BarChart(" + assert String.contains?(script, expected) + end + + test "area_chart" do + script = Chartkick.area_chart("{}") + expected = "new Chartkick.AreaChart(" + assert String.contains?(script, expected) + end + + test "combo_chart" do + script = Chartkick.combo_chart("{}") + expected = "new Chartkick.ComboChart(" + assert String.contains?(script, expected) + end + + test "geo_chart" do + script = Chartkick.geo_chart("{}") + expected = "new Chartkick.GeoChart(" + assert String.contains?(script, expected) + end + + test "scatter_chart" do + script = Chartkick.scatter_chart("{}") + expected = "new Chartkick.ScatterChart(" + assert String.contains?(script, expected) + end + + test "timeline" do + script = Chartkick.timeline("{}") + expected = "new Chartkick.Timeline(" + assert String.contains?(script, expected) + end + + + test "line_chart returns LineChart" do + script = Chartkick.line_chart("{}") + expected = "new Chartkick.LineChart(" + assert String.contains?(script, expected) + end + + test "chartkick_chart contains HTML-tag styling" do + height = "42px" + script = Chartkick.chartkick_chart("", "{}", height: height) + expected = "style=\"height: #{height}; text-align: center; color: #999; line-height: #{height};" + assert String.contains?(script, expected) + end + + test "chartkick_chart returns with default height set" do + script = Chartkick.chartkick_chart("", "{}") + expected = "height: 300px" + assert String.contains?(script, expected) + end + + test "chartkick_chart returns with custom height set" do + script = Chartkick.chartkick_chart("", "{}", height: "400px") + expected = "height: 400px" + assert String.contains?(script, expected) + end + + test "chartkick_chart with only script option does not render html-tag" do + script = Chartkick.chartkick_chart("", "{}", only: :script) + expected = "" + assert !String.contains?(script, expected) + end + + test "chartkick_chart with only html option does not render script-tag" do + html = Chartkick.chartkick_chart("", "{}", only: :html) + expected = "" + assert String.ends_with?(script, expected) + end + + test "chartkick_script returns script with correct chart class" do + script = Chartkick.chartkick_script("LineChart", "", "{}", "{}") + expected = "new Chartkick.LineChart" + assert String.contains?(script, expected) + end + + test "chartkick_script returns script with custom id set" do + id = "my-chart-id" + script = Chartkick.chartkick_script("klass", id, "{}", "{}") + expected = "new Chartkick.klass('#{id}" + assert String.contains?(script, expected) + end + + # test "DEBUG" do + # script = Chartkick.chartkick_chart("", "{}", stacked: true) + # expected = "1298312381askjdjaskdjaskdas2098" + # assert script == expected + # end +end diff --git a/test/test_helper.exs b/test/test_helper.exs new file mode 100644 index 0000000..4b8b246 --- /dev/null +++ b/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start