Skip to content

Commit

Permalink
Add charts
Browse files Browse the repository at this point in the history
  • Loading branch information
hoblin committed Oct 7, 2023
1 parent 7d23739 commit b047425
Show file tree
Hide file tree
Showing 13 changed files with 324 additions and 29 deletions.
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ gem "tzinfo-data", platforms: %i[mingw mswin x64_mingw jruby]

gem "awesome_print", "~> 1.9"
gem "data_migrate", "~> 9.2"
gem "draper", "~> 4.0"
gem "pry", "~> 0.14.2"
gem "slim", "~> 5.1"
gem "sqlite3", "~> 1.6"
Expand All @@ -57,3 +58,7 @@ group :development do
# Use console on exceptions pages [https://github.com/rails/web-console]
gem "web-console"
end

gem "chartkick", "~> 5.0"

gem "groupdate", "~> 6.4"
19 changes: 19 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ GEM
globalid (>= 0.3.6)
activemodel (7.1.0)
activesupport (= 7.1.0)
activemodel-serializers-xml (1.0.2)
activemodel (> 5.x)
activesupport (> 5.x)
builder (~> 3.1)
activerecord (7.1.0)
activemodel (= 7.1.0)
activesupport (= 7.1.0)
Expand Down Expand Up @@ -89,6 +93,7 @@ GEM
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
builder (3.2.4)
chartkick (5.0.4)
coderay (1.1.3)
concurrent-ruby (1.2.2)
connection_pool (2.4.1)
Expand All @@ -104,6 +109,13 @@ GEM
reline (>= 0.3.1)
debug_inspector (1.1.0)
diff-lcs (1.5.0)
draper (4.0.2)
actionpack (>= 5.0)
activemodel (>= 5.0)
activemodel-serializers-xml (>= 1.0)
activesupport (>= 5.0)
request_store (>= 1.0)
ruby2_keywords
drb (2.1.1)
ruby2_keywords
erubi (1.12.0)
Expand All @@ -118,6 +130,8 @@ GEM
ruby-progressbar (~> 1.4)
globalid (1.2.1)
activesupport (>= 6.1)
groupdate (6.4.0)
activesupport (>= 6.1)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
io-console (0.6.0)
Expand Down Expand Up @@ -218,6 +232,8 @@ GEM
regexp_parser (2.8.1)
reline (0.3.9)
io-console (~> 0.5)
request_store (1.5.1)
rack (>= 1.4)
rexml (3.2.6)
rouge (4.1.3)
rspec-core (3.12.2)
Expand Down Expand Up @@ -318,12 +334,15 @@ DEPENDENCIES
awesome_print (~> 1.9)
better_errors (~> 2.10)
binding_of_caller (~> 1.0)
chartkick (~> 5.0)
cssbundling-rails
data_migrate (~> 9.2)
debug
draper (~> 4.0)
factory_bot_rails (~> 6.2)
ffaker (~> 2.23)
fuubar (~> 2.5)
groupdate (~> 6.4)
jsbundling-rails
ordinare (~> 0.4.0)
pg (~> 1.1)
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/tweets_controller.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
class TweetsController < ApplicationController
def index
@tweets = Tweet.all
@tweets = Tweet.first(10).map(&:decorate)

respond_to do |format|
format.html # renders index.html.slim
end
end

def show
@tweet = Tweet.find(params[:id])
@tweet = Tweet.find(params[:id]).decorate

respond_to do |format|
format.html # renders show.html.slim
Expand Down
8 changes: 8 additions & 0 deletions app/decorators/application_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class ApplicationDecorator < Draper::Decorator
# Define methods for all decorated objects.
# Helpers are accessed through `helpers` (aka `h`). For example:
#
# def percent_amount
# h.number_to_percentage object.amount, precision: 2
# end
end
120 changes: 120 additions & 0 deletions app/decorators/tweet_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
class TweetDecorator < Draper::Decorator
delegate_all

def combined_chart
h.area_chart combined_metrics_series, height: "20vh",library: chart_options
end

def likes_chart
h.line_chart(
likes_metric[:data],
min: min_y(likes_metric),
max: max_y(likes_metric),
height: "70vh",
library: single_metric_chart_options("Likes")
)
end

def replies_chart
h.line_chart(
replies_metric[:data],
min: min_y(replies_metric),
max: max_y(replies_metric),
height: "70vh",
library: single_metric_chart_options("Replies")
)
end

def reposts_chart
h.line_chart(
reposts_metric[:data],
min: min_y(reposts_metric),
max: max_y(reposts_metric),
height: "70vh",
library: single_metric_chart_options("Reposts")
)
end

def bookmarks_chart
h.line_chart(
bookmarks_metric[:data],
min: min_y(bookmarks_metric),
max: max_y(bookmarks_metric),
height: "70vh",
library: single_metric_chart_options("Bookmarks")
)
end

def views_chart
h.line_chart(
views_metric[:data],
min: min_y(views_metric),
max: max_y(views_metric),
height: "70vh",
library: single_metric_chart_options("Views")
)
end

private

def min_y(metric)
metric[:data].min_by { |k, v| k.to_i }&.last
end

def max_y(metric)
metric[:data].max_by { |k, v| k.to_i }&.last
end

def single_metric_chart_options(title)
chart_options.merge(
yAxis: {
title: {
text: title
}
}
)
end

def chart_options
{
chart: {
zoomType: "xy"
},
resetZoomButton: {
theme: {
display: "flex"
}
}
}
end

def combined_metrics_series
[
likes_metric,
replies_metric,
reposts_metric,
bookmarks_metric,
views_metric
]
end

def likes_metric
@likes_metric ||= {name: "Likes", data: object.tweet_metrics.group_by_minute(:created_at).maximum(:likes)}
end

def replies_metric
@replies_metric ||= {name: "Replies", data: object.tweet_metrics.group_by_minute(:created_at).maximum(:replies)}
end

def reposts_metric
@reposts_metric ||= {name: "Reposts", data: object.tweet_metrics.group_by_minute(:created_at).maximum(:reposts)}
end

def bookmarks_metric
@bookmarks_metric ||= {name: "Bookmarks", data: object.tweet_metrics.group_by_minute(:created_at).maximum(:bookmarks)}
end

def views_metric
@views_metric ||= {name: "Views", data: object.tweet_metrics.group_by_minute(:created_at).maximum(:views)}
end
end
1 change: 1 addition & 0 deletions app/javascript/application.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Entry point for the build script in your package.json
import "@hotwired/turbo-rails"
import "./controllers"
import "chartkick/highcharts"
8 changes: 4 additions & 4 deletions app/views/tweets/index.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ section.hero.is-info
p class="subtitle is-6"
= tweet.body.truncate(280)
.content
/ TODO: render a small chart here
= tweet.combined_chart
footer.card-footer
= link_to tweet_path(tweet), class: "card-footer-item" do
= link_to tweet_path(tweet), class: "card-footer-item primary" do
span View Metrics
span.icon
i class="fa fa-chevron-right"
i class="fa fa-chart-line"
= link_to tweet.url, class: "card-footer-item", target: "_blank" do
span View Tweet
span.icon
i class="fa fa-chevron-right"
i class="fa fa-twitter"
.column.is-1
71 changes: 51 additions & 20 deletions app/views/tweets/show.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,55 @@ section.hero.is-info
.content
.columns.is-centered
.column.is-6
.box
h2.title.is-4.has-text-dark
| Tweet
.content
p= @tweet.body
h2.title.is-4.has-text-dark
| Tweet
.content
p= @tweet.body
.column.is-6
.box
h2.title.is-4.has-text-dark
| Metrics
.content
p
| Likes: #{number_with_delimiter(@tweet.likes)}
p
| Retweets: #{number_with_delimiter(@tweet.reposts)}
p
| Comments: #{number_with_delimiter(@tweet.replies)}
p
| Views: #{number_with_delimiter(@tweet.views)}
.section
h4.title.is-4.has-text-dark
| Charts
h2.title.is-4.has-text-dark
| Metrics
.content
p
| Likes: #{number_with_delimiter(@tweet.likes)}
p
| Retweets: #{number_with_delimiter(@tweet.reposts)}
p
| Comments: #{number_with_delimiter(@tweet.replies)}
p
| Views: #{number_with_delimiter(@tweet.views)}
hr
.content
.card
.card-content
.content
h4.title.is-4.has-text-dark
| Likes
= @tweet.likes_chart
.content
.card
.card-content
.content
h4.title.is-4.has-text-dark
| Retweets
= @tweet.reposts_chart
.content
.card
.card-content
.content
h4.title.is-4.has-text-dark
| Comments
= @tweet.replies_chart
.content
.card
.card-content
.content
h4.title.is-4.has-text-dark
| Bookmarks
= @tweet.bookmarks_chart
.content
.card
.card-content
.content
h4.title.is-4.has-text-dark
| Views
= @tweet.views_chart
59 changes: 59 additions & 0 deletions lib/tasks/auto_annotate_models.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# NOTE: only doing this in development as some production environments (Heroku)
# NOTE: are sensitive to local FS writes, and besides -- it's just not proper
# NOTE: to have a dev-mode tool do its thing in production.
if Rails.env.development?
require 'annotate'
task :set_annotation_options do
# You can override any of these by setting an environment variable of the
# same name.
Annotate.set_defaults(
'active_admin' => 'false',
'additional_file_patterns' => [],
'routes' => 'false',
'models' => 'true',
'position_in_routes' => 'before',
'position_in_class' => 'before',
'position_in_test' => 'before',
'position_in_fixture' => 'before',
'position_in_factory' => 'before',
'position_in_serializer' => 'before',
'show_foreign_keys' => 'true',
'show_complete_foreign_keys' => 'false',
'show_indexes' => 'true',
'simple_indexes' => 'false',
'model_dir' => 'app/models',
'root_dir' => '',
'include_version' => 'false',
'require' => '',
'exclude_tests' => 'false',
'exclude_fixtures' => 'false',
'exclude_factories' => 'false',
'exclude_serializers' => 'false',
'exclude_scaffolds' => 'true',
'exclude_controllers' => 'true',
'exclude_helpers' => 'true',
'exclude_sti_subclasses' => 'false',
'ignore_model_sub_dir' => 'false',
'ignore_columns' => nil,
'ignore_routes' => nil,
'ignore_unknown_models' => 'false',
'hide_limit_column_types' => 'integer,bigint,boolean',
'hide_default_column_types' => 'json,jsonb,hstore',
'skip_on_db_migrate' => 'false',
'format_bare' => 'true',
'format_rdoc' => 'false',
'format_yard' => 'false',
'format_markdown' => 'false',
'sort' => 'false',
'force' => 'false',
'frozen' => 'false',
'classified_sort' => 'true',
'trace' => 'false',
'wrapper_open' => nil,
'wrapper_close' => nil,
'with_comment' => 'true'
)
end

Annotate.load_tasks
end
2 changes: 1 addition & 1 deletion lib/tasks/tweet_metrics_importer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def self.import_batch(batch)
def self.transform_row(row)
{
tweet_id: tweet.id,
likes: row["likes"],
likes: row["count"],
created_at: row["created_at"],
updated_at: row["updated_at"]
}
Expand Down
Loading

0 comments on commit b047425

Please sign in to comment.