diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2015-08-29 23:16:43 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2015-08-29 23:16:43 +0900 |
commit | 1eb63c9784e2c5017045f55580ac94604f326dd5 (patch) | |
tree | 327b135715d11516e4ce306b8131336bab26ad8f /app | |
parent | 472bc32aa7b674b86293f02be6350c049f4c316c (diff) | |
download | aclog-1eb63c9784e2c5017045f55580ac94604f326dd5.tar.gz |
web: users#status: better chart (donut chart)
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/application.js.erb | 2 | ||||
-rw-r--r-- | app/assets/javascripts/controllers/users.js | 108 | ||||
-rw-r--r-- | app/assets/stylesheets/application.scss | 1 | ||||
-rw-r--r-- | app/assets/stylesheets/users.scss | 127 | ||||
-rw-r--r-- | app/views/users/stats.html.haml | 15 |
5 files changed, 119 insertions, 134 deletions
diff --git a/app/assets/javascripts/application.js.erb b/app/assets/javascripts/application.js.erb index 5418429..f8765ce 100644 --- a/app/assets/javascripts/application.js.erb +++ b/app/assets/javascripts/application.js.erb @@ -4,6 +4,8 @@ //= require twitter-text-1.11.0 //= require superagent-1.2.0 //= require vue-0.12.9-csp +//= require d3 +//= require nvd3 //= require init //= require_tree ./shared diff --git a/app/assets/javascripts/controllers/users.js b/app/assets/javascripts/controllers/users.js index 332285a..02b1b1a 100644 --- a/app/assets/javascripts/controllers/users.js +++ b/app/assets/javascripts/controllers/users.js @@ -1,49 +1,73 @@ Views.users = { stats: function() { var drawgraph = function(target, data_raw, det) { - var vm = new Vue({ - el: target, - data: { - users: data_raw.users, - users_count: data_raw.users_count, - reactions_count: data_raw.reactions_count, - colors: ["#393b79", "#5254a3", "#6b6ecf", "#9c9ede", "#637939", "#8ca252", "#b5cf6b", "#cedb9c", "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#e7969c", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6"], - loading: false, - showTweets: false, - statuses: [], - lastUser: null - }, - computed: { - tweetsUrl: function() { - var d = det(this.lastUser); - return "/" + d[0] + "/favorited_by/" + d[1]; - }, - tweetsApi: function() { - var d = det(this.lastUser); - return "/i/api/tweets/user_favorited_by.json?screen_name=" + d[0] + "&source_screen_name=" + d[1]; - } - }, - methods: { - openTweets: function(user, e) { - if (!this.showTweets || user === this.lastUser) { - this.showTweets = !this.showTweets; + nv.addGraph(function() { + var size = document.querySelector(target).offsetWidth * 0.6; + var iconSize = 48; + var chart = nv.models.pieChart() + .x(function(d) { return d.screen_name; }) + .y(function(d) { return d.count; }) + .showLabels(true) + .showLegend(false) + .donut(true) + .title("100 tweets / " + data_raw.reactions_count.toString() + " favs") + .labelsOutside(true); + var tooltip = chart.tooltip; + tooltip.contentGenerator(function(d) { + if (d.data.screen_name) { + var container, count, iconimg, leftcon, rightcon, screen_name; + iconimg = document.createElement("img"); + iconimg.setAttribute("src", d.data.profile_image_url); + leftcon = document.createElement("div"); + leftcon.className = "icon"; + leftcon.appendChild(iconimg); + screen_name = document.createElement("span"); + screen_name.appendChild(document.createTextNode("@" + d.data.screen_name)); + count = document.createElement("span"); + count.appendChild(document.createTextNode(d.data.count)); + rightcon = document.createElement("div"); + rightcon.className = "meta"; + rightcon.appendChild(screen_name); + rightcon.appendChild(count); + container = document.createElement("div"); + container.appendChild(leftcon); + container.appendChild(rightcon); + return container.outerHTML; + } else { + var container, count, iconimg, rightcon, screen_name; + screen_name = document.createElement("span"); + screen_name.appendChild(document.createTextNode("Other " + (data_raw.users_count - data_raw.users.length).toString() + " users")); + count = document.createElement("span"); + count.appendChild(document.createTextNode(d.data.count)); + rightcon = document.createElement("div"); + rightcon.className = "meta"; + rightcon.appendChild(screen_name); + rightcon.appendChild(count); + container = document.createElement("div"); + container.appendChild(rightcon); + return container.outerHTML; } - if (this.showTweets) { - this.lastUser = user; - vm = this; - superagent - .get(vm.tweetsApi) - .query({ count: 3 }) - .accept("json") - .end(function(err, res) { - var json = res.body; - vm.statuses = json.statuses; - }); - } - }, - }, - }); - }; + }); + var svg = d3.select(target + " .chart") + .attr("height", size) + .datum(data_raw.users.concat([{ count: (data_raw.reactions_count - data_raw.users.reduce(function(sum, c) { return sum + c.count; }, 0)) }])) + .transition() + .call(chart); + svg.selectAll(".nv-label").each(function(d, i) { + var group, text; + group = d3.select(this); + text = group.select("text").remove(); + return group.append("image").attr("xlink:href", function(d) { + return d.data.profile_image_url; + }).attr("width", iconSize).attr("height", iconSize).attr("transform", "translate(-" + iconSize / 2 + ", -" + iconSize / 2 + ")").on("click", function(d) { + var d = det(d.data); + return "/" + d[0] + "/favorited_by/" + d[1]; + }); + }); + nv.utils.windowResize(chart.update); + return chart; + }); + }; superagent .get("/i/api/users/favorited_by.json") diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 948f4c7..119a0a2 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -1,5 +1,6 @@ @import "bootstrap-sprockets"; @import "bootstrap"; +@import "nvd3"; @import "base"; @import "*"; diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss index 0beb9c3..22536fa 100644 --- a/app/assets/stylesheets/users.scss +++ b/app/assets/stylesheets/users.scss @@ -1,82 +1,53 @@ .chart { - width: 100%; - margin: 30px 0; - display: flex; - flex-direction: row-reverse; - - .chart-item { - margin-top: 100px; - height: 50px; - - &.other { - flex-grow: 1; - } - - > span { - display: block; - line-height: 50px; - width: 100%; - height: 100%; - text-align: center; - overflow: hidden; - } - - .popout { - display: inline-block; - white-space: nowrap; - position: relative; - top: -100px; - padding: 5px; - text-align: center; - background-color: #eeeeee; - border: 1px solid #999999; - border-radius: 3px; - z-index: 1; - - .count span { - font-size: larger; - font-weight: bold; - } - } - - &:hover { - .popout { - z-index: 2; - } - } - } + // margin: 30px 0; + // display: flex; + // flex-direction: row-reverse; + + // .chart-item { + // margin-top: 100px; + // height: 50px; + + // &.other { + // flex-grow: 1; + // } + + // > span { + // display: block; + // line-height: 50px; + // width: 100%; + // height: 100%; + // text-align: center; + // overflow: hidden; + // } + + // .popout { + // display: inline-block; + // white-space: nowrap; + // position: relative; + // top: -100px; + // padding: 5px; + // text-align: center; + // background-color: #eeeeee; + // border: 1px solid #999999; + // border-radius: 3px; + // z-index: 1; + + // .count span { + // font-size: larger; + // font-weight: bold; + // } + // } + + // &:hover { + // .popout { + // z-index: 2; + // } + // } + // } + height: 300px; } -ul.user-list { - padding: 15px 0; - padding-left: 0; - list-style: none; - - li { - display: inline-block; - } - - li a { - display: block; - padding: 10px 20px; - color: #333; - font-size: 18px; - text-decoration: none; - text-align: right; - } - - li a:hover { - background-color: #cecac7; - } - - li a img { - width: 48px; - height: 48px; - margin-bottom: 5px; - } - li a span { - display: block; - margin-bottom: 0; - font-family: Helvetica Neue, Helvetica, Arial, sans-serif; - } +.nvtooltip { + .icon {} + .meta {} } diff --git a/app/views/users/stats.html.haml b/app/views/users/stats.html.haml index 52fc9ba..7c913e1 100644 --- a/app/views/users/stats.html.haml +++ b/app/views/users/stats.html.haml @@ -12,19 +12,6 @@ - [["favorited_by", "Favorited by.."], ["favorited_users", "Favoriting.."]].each do |graph_id, graph_title| %div{id: graph_id} %h2= graph_title - %template{data: {"v-if" => "!loading"}} - .chart - .chart-item.other{data: {"v-if" => "users_count > users.length", "v-style" => "background-color: colors[users.length % colors.length]"}} - %span Other {{ users_count - users.length }} People - .chart-item{data: {"v-repeat" => "users | orderBy 'count'", "v-style" => "width: (100 * count / reactions_count) + '%', background-color: colors[(users.length - $index - 1) % colors.length]", "v-on" => "click: openTweets(this)"}} - .popout - %img{data: {"v-attr" => "src: profile_image_url"}} - .count - %span {{ count }} - favs - .statuses{data: {"v-if" => "showTweets"}} - = render "tweets/tweets_template" - .refresh-box< - %a{href: "{{ tweetsUrl }}"} » + %svg.chart{xmlns: "http://www.w3.org/2000/svg"} .loading-box{data: {"v-if" => "loading"}} %img.loading-image{src: image_path("loading.gif")} |