diff --git a/Gemfile b/Gemfile index ebd700ce..a5e1aa0c 100644 --- a/Gemfile +++ b/Gemfile @@ -19,6 +19,7 @@ gem 'material_icons' # Quality of Life gem 'cocoon' +gem 'dateslices' # Javascript gem 'coffee-rails' @@ -36,6 +37,9 @@ gem 'serendipitous', git: 'git://github.com/indentlabs/serendipitous-gem.git' # Editor gem 'medium-editor-rails' +# Graphs & Charts +gem 'chartkick' + group :production do # gem 'less-rails' # gem 'less-rails-fontawesome' diff --git a/Gemfile.lock b/Gemfile.lock index 83886477..b17ed1e2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -65,6 +65,7 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) + chartkick (2.1.1) childprocess (0.5.9) ffi (~> 1.0, >= 1.0.11) climate_control (0.0.3) @@ -104,6 +105,8 @@ GEM railties (>= 3, < 5) cucumber-wire (0.0.1) database_cleaner (1.5.3) + dateslices (0.0.4) + rails (> 4) debug_inspector (0.0.2) devise (3.5.6) bcrypt (~> 3.0) @@ -305,11 +308,13 @@ DEPENDENCIES better_errors binding_of_caller capybara + chartkick cocoon coffee-rails coveralls cucumber-rails database_cleaner + dateslices devise factory_girl_rails guard @@ -340,4 +345,4 @@ DEPENDENCIES uglifier (>= 1.3.0) BUNDLED WITH - 1.12.5 + 1.13.1 diff --git a/app/assets/javascripts/admin.js.coffee b/app/assets/javascripts/admin.js.coffee new file mode 100644 index 00000000..24f83d18 --- /dev/null +++ b/app/assets/javascripts/admin.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 7445094a..67375cc4 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -17,4 +17,6 @@ //= require autocomplete-rails //= require cocoon //= require medium-editor +//= require Chart.bundle +//= require chartkick //= require_tree . diff --git a/app/assets/stylesheets/admin.css.scss b/app/assets/stylesheets/admin.css.scss new file mode 100644 index 00000000..09424b40 --- /dev/null +++ b/app/assets/stylesheets/admin.css.scss @@ -0,0 +1 @@ +h1, h2, h3 { text-align: center; } \ No newline at end of file diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb new file mode 100644 index 00000000..feb7ebb1 --- /dev/null +++ b/app/controllers/admin_controller.rb @@ -0,0 +1,18 @@ +class AdminController < ApplicationController + layout 'admin' + + def dashboard + end + + def universes + end + + def characters + end + + def locations + end + + def items + end +end diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 367d0d9f..aa7f846c 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -1,7 +1,7 @@ # Controller for top-level pages of the site that do not have # an associated model class MainController < ApplicationController - layout "landing", only: [:index, :about_notebook] + layout 'landing', only: [:index, :about_notebook] def index redirect_to :dashboard if user_signed_in? diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb new file mode 100644 index 00000000..d5c6d355 --- /dev/null +++ b/app/helpers/admin_helper.rb @@ -0,0 +1,2 @@ +module AdminHelper +end diff --git a/app/models/user.rb b/app/models/user.rb index 7d68759c..f6902184 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -13,9 +13,7 @@ class User < ActiveRecord::Base has_many :characters has_many :items - has_many :languages has_many :locations - has_many :magics has_many :universes # as_json creates a hash structure, which you then pass to ActiveSupport::json.encode to actually encode the object as a JSON string. @@ -45,9 +43,7 @@ class User < ActiveRecord::Base { characters: characters, items: items, - languages: languages, locations: locations, - magics: magics, universes: universes } end @@ -56,9 +52,7 @@ class User < ActiveRecord::Base [ characters.length, items.length, - languages.length, locations.length, - magics.length, universes.length ].sum end diff --git a/app/views/admin/characters.html.erb b/app/views/admin/characters.html.erb new file mode 100644 index 00000000..011be207 --- /dev/null +++ b/app/views/admin/characters.html.erb @@ -0,0 +1,54 @@ +
+
+

Character creations

+ <%= line_chart Character.group_by_day(:created_at) %> +
+
+ +
+
+

Characters per user

+ <%# bar_chart User.joins(:characters).group("characters.user_id").count() %> + TODO +
+
+

Characters per universe

+ <%# bar_chart Universe.joins(:characters).group("characters.universe_id").count() %> + TODO +
+
+

Character privacy

+ <%= pie_chart Character.group(:privacy).count() %> +
+
+ +

Character usage data

+
+
+

Most common names

+ <%= bar_chart Character.where.not(name: "").group(:name).order('count_all desc').limit(5).count() %> +
+
+

Most common age

+ <%= bar_chart Character.where.not(age: "").group(:age).order('count_all desc').limit(5).count() %> +
+
+

Most common gender

+ <%= pie_chart Character.where.not(gender: "").group(:gender).order('count_all desc').limit(5).count() %> +
+
+ +
+
+

Most common occupation

+ <%= bar_chart Character.where.not(occupation: "").group(:occupation).order('count_all desc').limit(5).count() %> +
+
+

Most-favorite weapons

+ <%= bar_chart Character.where.not(fave_weapon: "").group(:fave_weapon).order('count_all desc').limit(5).count() %> +
+
+

Most common eye color

+ <%= pie_chart Character.where.not(eyecolor: "").group(:eyecolor).order('count_all desc').limit(5).count() %> +
+
\ No newline at end of file diff --git a/app/views/admin/dashboard.html.erb b/app/views/admin/dashboard.html.erb new file mode 100644 index 00000000..3fe57eec --- /dev/null +++ b/app/views/admin/dashboard.html.erb @@ -0,0 +1,26 @@ +

User signups

+<%= area_chart User.group_by_day(:created_at) %> + +
+
+

Universes per user

+ <%= bar_chart User.joins(:universes).group("universes.user_id").count() %> +
+
+ +

Characters per user

+ <%= bar_chart User.joins(:characters).group("characters.user_id").count() %> +
+ +
+ +
+
+

Locations per user

+ <%= bar_chart User.joins(:locations).group("locations.user_id").count() %> +
+
+

Items per user

+ <%= bar_chart User.joins(:items).group("items.user_id").count() %> +
+
\ No newline at end of file diff --git a/app/views/admin/items.html.erb b/app/views/admin/items.html.erb new file mode 100644 index 00000000..08b66b1f --- /dev/null +++ b/app/views/admin/items.html.erb @@ -0,0 +1,50 @@ +
+
+

Item creations

+ <%= line_chart Item.group_by_day(:created_at) %> +
+
+ +
+
+

Items per user

+ <%# bar_chart User.joins(:items).group("items.user_id").count() %> + TODO +
+
+

Items per universe

+ <%# bar_chart Universe.joins(:items).group("items.universe_id").count() %> + TODO +
+
+

Item privacy

+ <%= pie_chart Item.group(:privacy).count() %> +
+
+ +

Item usage data

+
+
+

Most common names

+ <%= bar_chart Item.where.not(name: "").group(:name).order('count_all desc').limit(5).count() %> +
+
+

Most common types

+ <%= bar_chart Item.where.not(item_type: "").group(:item_type).order('count_all desc').limit(5).count() %> +
+
+ +
+
+

Common made years

+ <%= bar_chart Item.where.not(year_made: "").group(:year_made).order('count_all desc').limit(5).count() %> +
+
+

Common makers

+ <%= bar_chart Item.where.not(made_by: "").group(:made_by).order('count_all desc').limit(5).count() %> +
+
+

Most common weights

+ <%= bar_chart Item.where.not(weight: "").group(:weight).order('count_all desc').limit(5).count() %> +
+
\ No newline at end of file diff --git a/app/views/admin/locations.html.erb b/app/views/admin/locations.html.erb new file mode 100644 index 00000000..3cbbcc5d --- /dev/null +++ b/app/views/admin/locations.html.erb @@ -0,0 +1,50 @@ +
+
+

Location creations

+ <%= line_chart Location.group_by_day(:created_at) %> +
+
+ +
+
+

Locations per user

+ <%# bar_chart User.joins(:locations).group("locations.user_id").count() %> + TODO +
+
+

Locations per universe

+ <%# bar_chart Universe.joins(:locations).group("locations.universe_id").count() %> + TODO +
+
+

Location privacy

+ <%= pie_chart Location.group(:privacy).count() %> +
+
+ +

Location usage data

+
+
+

Most common names

+ <%= bar_chart Location.where.not(name: "").group(:name).order('count_all desc').limit(5).count() %> +
+
+

Most common types

+ <%= bar_chart Location.where.not(type_of: "").group(:type_of).order('count_all desc').limit(5).count() %> +
+
+ +
+
+

Common estab. years

+ <%= bar_chart Location.where.not(established_year: "").group(:established_year).order('count_all desc').limit(5).count() %> +
+
+

Most common currencies

+ <%= pie_chart Location.where.not(currency: "").group(:currency).order('count_all desc').limit(5).count() %> +
+
+

Most common languages

+ <%= pie_chart Location.where.not(language: "").where.not(language: nil).group(:language).order('count_all desc').limit(5).count() %> +
+
\ No newline at end of file diff --git a/app/views/admin/universes.html.erb b/app/views/admin/universes.html.erb new file mode 100644 index 00000000..b314a2c7 --- /dev/null +++ b/app/views/admin/universes.html.erb @@ -0,0 +1,36 @@ +
+
+

Universe creations

+ <%= line_chart Universe.group_by_day(:created_at) %> +
+
+ +
+
+

Universes per user

+ <%# bar_chart User.joins(:items).group("items.user_id").count() %> + TODO +
+
+

Privacy per universe

+ <%= pie_chart Universe.group(:privacy) %> +
+
+ +
+
+

Characters per universe

+ <%# bar_chart Universe.joins(:items).group("items.universe_id").count() %> + TODO +
+
+

Locations per universe

+ <%# bar_chart Universe.joins(:items).group("items.universe_id").count() %> + TODO +
+
+

Items per universe

+ <%# bar_chart Universe.joins(:items).group("items.universe_id").count() %> + TODO +
+
diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb new file mode 100644 index 00000000..824c232f --- /dev/null +++ b/app/views/layouts/admin.html.erb @@ -0,0 +1,24 @@ + + + + <%= content_for?(:title) ? yield(:title) : 'Notebook' %> + <%= stylesheet_link_tag 'application' %> + <%= javascript_include_tag 'application' %> + <%= csrf_meta_tags %> + + + + + + + + + <%= render 'layouts/navbar' %> + +
+ <%= yield %> + +
+ + + diff --git a/config/routes.rb b/config/routes.rb index 8a7a0ff8..1c6c1123 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -43,6 +43,14 @@ Rails.application.routes.draw do get 'editor', to: 'write#editor' end + scope 'admin' do + get '/', to: 'admin#dashboard' + get '/universes', to: 'admin#universes' + get '/characters', to: 'admin#characters' + get '/locations', to: 'admin#locations' + get '/items', to: 'admin#items' + end + # API Endpoints scope '/generate' do # General information diff --git a/test/controllers/admin_controller_test.rb b/test/controllers/admin_controller_test.rb new file mode 100644 index 00000000..b8e0acfa --- /dev/null +++ b/test/controllers/admin_controller_test.rb @@ -0,0 +1,29 @@ +require 'test_helper' + +class AdminControllerTest < ActionController::TestCase + test "should get dashboard" do + get :dashboard + assert_response :success + end + + test "should get universes" do + get :universes + assert_response :success + end + + test "should get characters" do + get :characters + assert_response :success + end + + test "should get locations" do + get :locations + assert_response :success + end + + test "should get items" do + get :items + assert_response :success + end + +end