diff --git a/app/controllers/achievements_controller.rb b/app/controllers/achievements_controller.rb
new file mode 100644
index 0000000..a227c96
--- /dev/null
+++ b/app/controllers/achievements_controller.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class AchievementsController < ProtectedController
+ def index
+ @wow_achievement_categories = WowAchievementCategory.base_categories.order(display_order: :asc)
+ @wow_achievements = nil
+ @wow_last_completed_achievements = CompletedWowAchievement.where(
+ wow_character: current_user.wow_characters
+ ).includes(:wow_character, wow_achievement: :wow_achievement_criterium).order(completed_timestamp: :desc).first(5)
+ @wow_achievement_category = nil
+ end
+
+ def show
+ @wow_achievement_category = WowAchievementCategory.find(params[:id])
+ @wow_achievement_categories = @wow_achievement_category.child_categories.order(display_order: :asc)
+ @wow_achievements = @wow_achievement_category.wow_achievements.includes(
+ wow_achievement_criterium: :child_criteria
+ ).order(display_order: :asc)
+ end
+end
+
+# TODO
+# Find a way to get the last achievement accomplished that were not already achievement by another character
+# This will return all WowAchievement only completed by one character of the current user
+# achievements = WowAchievement.joins(:completed_wow_achievements).where('completed_wow_achievements.wow_character_id': current_user.wow_characters).group(:id).having("count(completed_wow_achievements.id) < 2")
+#
+# This will return all the CompletedWowAchievement of the previous list
+# completed_achievements = CompletedWowAchievement.where(wow_character: current_user.wow_characters, wow_achievement: achievements)
+#
+# The problem is that these completed_achivements all have a completed_timestamp at Thu, 01 Jan 1970 00:00:00.000000000 UTC +00:00
+#
+# It's probably required to use the WowAchievementCriterium to sort that
diff --git a/app/helpers/achievements_helper.rb b/app/helpers/achievements_helper.rb
new file mode 100644
index 0000000..b36044d
--- /dev/null
+++ b/app/helpers/achievements_helper.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module AchievementsHelper
+ def achievement_completed(achievement_id, user)
+ CompletedWowAchievement.where(wow_achievement_id: achievement_id, wow_character: user.wow_characters).exists?
+ end
+end
diff --git a/app/models/wow_achievement.rb b/app/models/wow_achievement.rb
index bbdba4c..7d673c6 100644
--- a/app/models/wow_achievement.rb
+++ b/app/models/wow_achievement.rb
@@ -19,4 +19,6 @@ class WowAchievement < ApplicationRecord
validates :name, presence: true
validates :achievement_id, presence: true, uniqueness: true
+
+ scope :base_achievements, -> { where(prerequisite_achievement: nil) }
end
diff --git a/app/models/wow_achievement_category.rb b/app/models/wow_achievement_category.rb
index d95e531..9136b5a 100644
--- a/app/models/wow_achievement_category.rb
+++ b/app/models/wow_achievement_category.rb
@@ -4,8 +4,16 @@ class WowAchievementCategory < ApplicationRecord
extend Mobility
translates :name
+ belongs_to :parent_category, class_name: 'WowAchievementCategory', optional: true
+ has_many :child_categories,
+ class_name: 'WowAchievementCategory',
+ foreign_key: 'parent_category_id',
+ dependent: :nullify,
+ inverse_of: :parent_category
has_many :wow_achievements, dependent: :destroy
validates :name, presence: true
validates :category_id, presence: true, uniqueness: true
+
+ scope :base_categories, -> { where(parent_category: nil) }
end
diff --git a/app/models/wow_achievement_criterium.rb b/app/models/wow_achievement_criterium.rb
index 9f0d55d..89c658b 100644
--- a/app/models/wow_achievement_criterium.rb
+++ b/app/models/wow_achievement_criterium.rb
@@ -11,6 +11,7 @@ class WowAchievementCriterium < ApplicationRecord
dependent: :destroy,
inverse_of: :parent_criterium
belongs_to :parent_criterium, class_name: 'WowAchievementCriterium', optional: true
+
has_many :completed_wow_achievement_criteria, dependent: :destroy
has_many :wow_characters, through: :completed_wow_achievement_criteria
diff --git a/app/views/achievements/_achievements.html.erb b/app/views/achievements/_achievements.html.erb
new file mode 100644
index 0000000..52c7bc7
--- /dev/null
+++ b/app/views/achievements/_achievements.html.erb
@@ -0,0 +1,76 @@
+
+
+
+
+ <% if wow_achievement_category %>
Achievement category: <%= wow_achievement_category.name %>
<% end %>
+
+ <% wow_achievement_categories.each do |category| %>
+ <%= link_to category.name, "/#{locale}/achievements/#{category.id}", class: "btn btn-outline-dark" %>
+ <% end %>
+
+
+
+
+
+
+ <% if wow_achievement_category&.parent_category %>
+ <%= link_to "Back", "/#{locale}/achievements/#{wow_achievement_category.parent_category.id}", class: "btn btn-outline-dark" %>
+ <% elsif wow_achievement_category %>
+ <%= link_to "Back", "/#{locale}/achievements", class: "btn btn-outline-dark" %>
+ <% end %>
+
+
+
+ <% if wow_achievements %>
+
+
Achievement:
+
+ <% wow_achievements.each do |achievement| %>
+
+
+
+
Description: <%= achievement.description %>
+
Criterium: <%= achievement&.wow_achievement_criterium&.description %>
+
+ <% achievement&.wow_achievement_criterium&.child_criteria&.each do |criterium| %>
+
+
<%= criterium&.description %>
+
+ <% end %>
+
+
+
+ <% end %>
+
+
+ <% elsif wow_last_completed_achievements %>
+
+
Last achievement:
+
+ <% wow_last_completed_achievements.each do |achievement| %>
+
+
+
+
Description: <%= achievement.wow_achievement.description %>
+
Criterium: <%= achievement&.wow_achievement.wow_achievement_criterium&.description %>
+ <% if achievement&.wow_achievement.wow_achievement_criterium.child_criteria %>
+
+ <% achievement&.wow_achievement.wow_achievement_criterium.child_criteria.each do |criterium| %>
+
+
<%= criterium&.description %>
+
+ <% end %>
+
+ <% end %>
+
Completed by: <%= link_to achievement.wow_character.name, achievement.wow_character, data: { turbo: false } %>
+
+
+ <% end %>
+
+
+ <% end %>
+
diff --git a/app/views/achievements/index.html.erb b/app/views/achievements/index.html.erb
new file mode 100644
index 0000000..fe10d1f
--- /dev/null
+++ b/app/views/achievements/index.html.erb
@@ -0,0 +1,5 @@
+Achievement list
+
+<%= turbo_frame_tag 'achievements' do %>
+ <%= render partial: 'achievements/achievements', locals: { wow_achievement_category: @wow_achievement_category, wow_achievement_categories: @wow_achievement_categories, wow_achievements: @wow_achievements, wow_last_completed_achievements: @wow_last_completed_achievements } %>
+<% end %>
diff --git a/app/views/achievements/show.html.erb b/app/views/achievements/show.html.erb
new file mode 100644
index 0000000..7779a21
--- /dev/null
+++ b/app/views/achievements/show.html.erb
@@ -0,0 +1,5 @@
+Achievement list
+
+<%= turbo_frame_tag 'achievements' do %>
+ <%= render partial: 'achievements/achievements', locals: { wow_achievement_category: @wow_achievement_category, wow_achievement_categories: @wow_achievement_categories, wow_achievements: @wow_achievements, wow_last_completed_achievements: nil } %>
+<% end %>
diff --git a/app/views/layouts/_navbar.html.erb b/app/views/layouts/_navbar.html.erb
index 9386f1a..6d91199 100644
--- a/app/views/layouts/_navbar.html.erb
+++ b/app/views/layouts/_navbar.html.erb
@@ -19,6 +19,9 @@
<%= t('layouts.navbar.worlds') %>
+
+ <%= t('layouts.navbar.achievements') %>
+
<%= render 'layouts/locales' %>
diff --git a/app/views/wow_characters/show.html.erb b/app/views/wow_characters/show.html.erb
index 630246c..cb404a9 100644
--- a/app/views/wow_characters/show.html.erb
+++ b/app/views/wow_characters/show.html.erb
@@ -18,7 +18,7 @@
- <%= render partial: 'wow_characters/reputations', locals: { standings: @wow_character.wow_standings.group_by { |standing| standing.wow_reputation.meta_wow_reputation_id }, meta_wow_reputations: @meta_wow_reputations } %>
+ <%= render partial: 'wow_characters/reputations', locals: { standings: @wow_character.wow_standings.group_by { |standing| standing.wow_reputation.meta_wow_reputation_id}, meta_wow_reputations: @meta_wow_reputations } %>
diff --git a/app/workers/wow_achievement_categories_worker.rb b/app/workers/wow_achievement_categories_worker.rb
index b637063..064f811 100644
--- a/app/workers/wow_achievement_categories_worker.rb
+++ b/app/workers/wow_achievement_categories_worker.rb
@@ -17,6 +17,8 @@ class WowAchievementCategoriesWorker < WowSidekiqWorker
end
wow_category.save
+
+ WowAchievementCategoryDetailWorker.perform_async(wow_category.category_id) if wow_category.persisted?
end
end
end
diff --git a/app/workers/wow_achievement_category_detail_worker.rb b/app/workers/wow_achievement_category_detail_worker.rb
new file mode 100644
index 0000000..67047fc
--- /dev/null
+++ b/app/workers/wow_achievement_category_detail_worker.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class WowAchievementCategoryDetailWorker < WowSidekiqWorker
+ def perform(category_id)
+ return unless (wow_achievement_category = WowAchievementCategory.find_by(category_id: category_id))
+
+ RBattlenet.set_options(locale: 'en_GB')
+ result = RBattlenet::Wow::AchievementCategory.find(category_id)
+
+ return unless result.status_code == 200
+
+ wow_achievement_category.is_guild_category = result.is_guild_category
+ wow_achievement_category.display_order = result.display_order
+
+ if result.parent_category
+ wow_achievement_category.parent_category = WowAchievementCategory.find_by(category_id: result.parent_category.id)
+ end
+
+ wow_achievement_category.save
+ end
+end
diff --git a/app/workers/wow_achievement_detail_worker.rb b/app/workers/wow_achievement_detail_worker.rb
index cda5095..05e3bf7 100644
--- a/app/workers/wow_achievement_detail_worker.rb
+++ b/app/workers/wow_achievement_detail_worker.rb
@@ -25,7 +25,11 @@ class WowAchievementDetailWorker < WowSidekiqWorker
wow_achievement.prerequisite_achievement = WowAchievement.find_by(achievement_id: result.prerequisite_achievement.id) if result.prerequisite_achievement
wow_achievement.wow_achievement_category = WowAchievementCategory.find_by(category_id: result.category.id) if result.category
wow_achievement.wow_achievement_criterium = find_or_create_wow_achievement_criterium(result.criteria) if result.criteria
- wow_achievement.icon = RBattlenet::Wow::AchievementMedia.find(result.media.id).assets[0].value if result.media
+
+ if result.media
+ icon = RBattlenet::Wow::AchievementMedia.find(result.media.id)
+ wow_achievement.icon = icon.assets.first.value if icon.assets.first
+ end
wow_achievement.save
end
@@ -34,8 +38,10 @@ class WowAchievementDetailWorker < WowSidekiqWorker
wow_achievement_criterium = WowAchievementCriterium.find_or_initialize_by(criterium_id: criteria.id)
wow_achievement_criterium.amount = criteria.amount
- locales.each do |locale|
- Mobility.with_locale(locale[0]) { wow_achievement_criterium.description = criteria.description[locale[1]] }
+ if criteria.description
+ locales.each do |locale|
+ Mobility.with_locale(locale[0]) { wow_achievement_criterium.description = criteria.description[locale[1]] }
+ end
end
if criteria.operator
@@ -51,9 +57,13 @@ class WowAchievementDetailWorker < WowSidekiqWorker
wow_child_achievement_criterium = WowAchievementCriterium.find_or_initialize_by(criterium_id: child_criterium.id)
wow_child_achievement_criterium.parent_criterium = wow_achievement_criterium
wow_child_achievement_criterium.amount = child_criterium.amount
- locales.each do |locale|
- Mobility.with_locale(locale[0]) { wow_child_achievement_criterium.description = child_criterium.description[locale[1]] }
+
+ if child_criterium.description
+ locales.each do |locale|
+ Mobility.with_locale(locale[0]) { wow_child_achievement_criterium.description = child_criterium.description[locale[1]] }
+ end
end
+
wow_child_achievement_criterium.save
end
diff --git a/app/workers/wow_characters_worker.rb b/app/workers/wow_characters_worker.rb
index 5a09bf6..007bc5b 100644
--- a/app/workers/wow_characters_worker.rb
+++ b/app/workers/wow_characters_worker.rb
@@ -40,7 +40,7 @@ class WowCharactersWorker < WowSidekiqWorker
WowCharacterDetailWorker.perform_async(wow_char.character_id)
WowCharacterPositionsWorker.perform_async(wow_char.character_id)
WowStandingWorker.perform_async(wow_char.character_id)
- WowCharacterAchievementsWorker.perform_async(wow_char.character_id)
+ # WowCharacterAchievementsWorker.perform_async(wow_char.character_id)
end
end
end
diff --git a/config/routes.rb b/config/routes.rb
index 944d29b..90061c0 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -14,6 +14,7 @@ Rails.application.routes.draw do
resources :wow_mounts, only: [:index, :show]
resources :wow_pets, only: [:index, :show]
resources :wow_reputations, only: [:index, :show]
+ resources :achievements, only: [:index, :show]
resources :rp_worlds
end
end
diff --git a/db/migrate/20210815182601_add_wow_achievement_category_self_join.rb b/db/migrate/20210815182601_add_wow_achievement_category_self_join.rb
new file mode 100644
index 0000000..8ca76a2
--- /dev/null
+++ b/db/migrate/20210815182601_add_wow_achievement_category_self_join.rb
@@ -0,0 +1,5 @@
+class AddWowAchievementCategorySelfJoin < ActiveRecord::Migration[6.1]
+ def change
+ add_reference :wow_achievement_categories, :parent_category, foreign_key: { to_table: :wow_achievement_categories }
+ end
+end
diff --git a/db/migrate/20210815182820_add_columns_to_wow_achievement_category.rb b/db/migrate/20210815182820_add_columns_to_wow_achievement_category.rb
new file mode 100644
index 0000000..f21dfc4
--- /dev/null
+++ b/db/migrate/20210815182820_add_columns_to_wow_achievement_category.rb
@@ -0,0 +1,6 @@
+class AddColumnsToWowAchievementCategory < ActiveRecord::Migration[6.1]
+ def change
+ add_column :wow_achievement_categories, :is_guild_category, :boolean
+ add_column :wow_achievement_categories, :display_order, :integer
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 18c56b7..27b7faa 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2021_08_15_130405) do
+ActiveRecord::Schema.define(version: 2021_08_15_182820) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -118,7 +118,11 @@ ActiveRecord::Schema.define(version: 2021_08_15_130405) do
t.jsonb "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
+ t.bigint "parent_category_id"
+ t.boolean "is_guild_category"
+ t.integer "display_order"
t.index ["category_id"], name: "index_wow_achievement_categories_on_category_id", unique: true
+ t.index ["parent_category_id"], name: "index_wow_achievement_categories_on_parent_category_id"
end
create_table "wow_achievement_criteria", force: :cascade do |t|
@@ -531,6 +535,7 @@ ActiveRecord::Schema.define(version: 2021_08_15_130405) do
t.index ["wow_reputation_id"], name: "index_wow_standings_on_wow_reputation_id"
end
+ add_foreign_key "wow_achievement_categories", "wow_achievement_categories", column: "parent_category_id"
add_foreign_key "wow_achievement_criteria", "wow_achievement_criteria", column: "parent_criterium_id"
add_foreign_key "wow_achievements", "wow_achievements", column: "prerequisite_achievement_id"
add_foreign_key "wow_characters", "wow_geo_positions", column: "bind_position_id"