diff --git a/app/controllers/api/v1/grid_artifacts_controller.rb b/app/controllers/api/v1/grid_artifacts_controller.rb index b960589..122ff85 100644 --- a/app/controllers/api/v1/grid_artifacts_controller.rb +++ b/app/controllers/api/v1/grid_artifacts_controller.rb @@ -3,11 +3,11 @@ module Api module V1 class GridArtifactsController < Api::V1::ApiController - before_action :find_grid_artifact, only: %i[update destroy] - before_action :find_party, only: %i[create update destroy] + before_action :find_grid_artifact, only: %i[update destroy sync] + before_action :find_party, only: %i[create update destroy sync] before_action :find_grid_character, only: %i[create] before_action :find_artifact, only: %i[create] - before_action :authorize_party_edit!, only: %i[create update destroy] + before_action :authorize_party_edit!, only: %i[create update destroy sync] # POST /grid_artifacts def create @@ -50,6 +50,20 @@ module Api end end + # POST /grid_artifacts/:id/sync + def sync + unless @grid_artifact.collection_artifact.present? + return render_unprocessable_entity_response( + Api::V1::GranblueError.new('No collection artifact linked') + ) + end + + @grid_artifact.sync_from_collection! + render json: GridArtifactBlueprint.render(@grid_artifact.reload, + root: :grid_artifact, + view: :nested) + end + private def find_grid_artifact @@ -107,7 +121,8 @@ module Api def grid_artifact_params params.require(:grid_artifact).permit( - :grid_character_id, :artifact_id, :element, :proficiency, :level, :reroll_slot, + :grid_character_id, :artifact_id, :collection_artifact_id, + :element, :proficiency, :level, :reroll_slot, skill1: %i[modifier strength level], skill2: %i[modifier strength level], skill3: %i[modifier strength level], diff --git a/app/controllers/api/v1/grid_characters_controller.rb b/app/controllers/api/v1/grid_characters_controller.rb index 966b988..1aecc63 100644 --- a/app/controllers/api/v1/grid_characters_controller.rb +++ b/app/controllers/api/v1/grid_characters_controller.rb @@ -15,10 +15,10 @@ module Api class GridCharactersController < Api::V1::ApiController include IdResolvable - before_action :find_grid_character, only: %i[update update_uncap_level update_position destroy resolve] - before_action :find_party, only: %i[create resolve update update_uncap_level update_position swap destroy] + before_action :find_grid_character, only: %i[update update_uncap_level update_position destroy resolve sync] + before_action :find_party, only: %i[create resolve update update_uncap_level update_position swap destroy sync] before_action :find_incoming_character, only: :create - before_action :authorize_party_edit!, only: %i[create resolve update update_uncap_level update_position swap destroy] + before_action :authorize_party_edit!, only: %i[create resolve update update_uncap_level update_position swap destroy sync] ## # Creates a new grid character. @@ -226,6 +226,26 @@ module Api end end + ## + # Syncs a grid character from its linked collection character. + # + # Copies all customizations from the collection character to this grid character. + # Returns 422 if no collection character is linked. + # + # @return [void] + def sync + unless @grid_character.collection_character.present? + return render_unprocessable_entity_response( + Api::V1::GranblueError.new('No collection character linked') + ) + end + + @grid_character.sync_from_collection! + render json: GridCharacterBlueprint.render(@grid_character.reload, + root: :grid_character, + view: :nested) + end + private ## @@ -526,6 +546,7 @@ module Api :id, :party_id, :character_id, + :collection_character_id, :position, :uncap_level, :transcendence_step, diff --git a/app/controllers/api/v1/grid_summons_controller.rb b/app/controllers/api/v1/grid_summons_controller.rb index f30e6f7..9f2cda5 100644 --- a/app/controllers/api/v1/grid_summons_controller.rb +++ b/app/controllers/api/v1/grid_summons_controller.rb @@ -14,10 +14,10 @@ module Api attr_reader :party, :incoming_summon - before_action :find_grid_summon, only: %i[update update_uncap_level update_quick_summon update_position resolve destroy] - before_action :find_party, only: %i[create update update_uncap_level update_quick_summon update_position swap resolve destroy] + before_action :find_grid_summon, only: %i[update update_uncap_level update_quick_summon update_position resolve destroy sync] + before_action :find_party, only: %i[create update update_uncap_level update_quick_summon update_position swap resolve destroy sync] before_action :find_incoming_summon, only: :create - before_action :authorize_party_edit!, only: %i[create update update_uncap_level update_quick_summon update_position swap destroy] + before_action :authorize_party_edit!, only: %i[create update update_uncap_level update_quick_summon update_position swap destroy sync] ## # Creates a new grid summon. @@ -228,6 +228,23 @@ module Api end end + ## + # Syncs a grid summon from its linked collection summon. + # + # @return [void] + def sync + unless @grid_summon.collection_summon.present? + return render_unprocessable_entity_response( + Api::V1::GranblueError.new('No collection summon linked') + ) + end + + @grid_summon.sync_from_collection! + render json: GridSummonBlueprint.render(@grid_summon.reload, + root: :grid_summon, + view: :nested) + end + ## # Saves the provided grid summon. # @@ -454,8 +471,9 @@ module Api # # @return [ActionController::Parameters] The permitted parameters. def summon_params - params.require(:summon).permit(:id, :party_id, :summon_id, :position, :main, :friend, - :quick_summon, :uncap_level, :transcendence_step) + params.require(:summon).permit(:id, :party_id, :summon_id, :collection_summon_id, + :position, :main, :friend, :quick_summon, + :uncap_level, :transcendence_step) end ## diff --git a/app/controllers/api/v1/grid_weapons_controller.rb b/app/controllers/api/v1/grid_weapons_controller.rb index f6499ed..e9247ac 100644 --- a/app/controllers/api/v1/grid_weapons_controller.rb +++ b/app/controllers/api/v1/grid_weapons_controller.rb @@ -12,10 +12,10 @@ module Api class GridWeaponsController < Api::V1::ApiController include IdResolvable - before_action :find_grid_weapon, only: %i[update update_uncap_level update_position resolve destroy] - before_action :find_party, only: %i[create update update_uncap_level update_position swap resolve destroy] + before_action :find_grid_weapon, only: %i[update update_uncap_level update_position resolve destroy sync] + before_action :find_party, only: %i[create update update_uncap_level update_position swap resolve destroy sync] before_action :find_incoming_weapon, only: %i[create resolve] - before_action :authorize_party_edit!, only: %i[create update update_uncap_level update_position swap resolve destroy] + before_action :authorize_party_edit!, only: %i[create update update_uncap_level update_position swap resolve destroy sync] ## # Creates a new GridWeapon. @@ -222,6 +222,23 @@ module Api end end + ## + # Syncs a grid weapon from its linked collection weapon. + # + # @return [void] + def sync + unless @grid_weapon.collection_weapon.present? + return render_unprocessable_entity_response( + Api::V1::GranblueError.new('No collection weapon linked') + ) + end + + @grid_weapon.sync_from_collection! + render json: GridWeaponBlueprint.render(@grid_weapon.reload, + root: :grid_weapon, + view: :full) + end + private ## @@ -476,7 +493,7 @@ module Api # @return [ActionController::Parameters] the permitted parameters. def weapon_params params.require(:weapon).permit( - :id, :party_id, :weapon_id, + :id, :party_id, :weapon_id, :collection_weapon_id, :position, :mainhand, :uncap_level, :transcendence_step, :element, :weapon_key1_id, :weapon_key2_id, :weapon_key3_id, :ax_modifier1, :ax_modifier2, :ax_strength1, :ax_strength2, diff --git a/app/controllers/api/v1/parties_controller.rb b/app/controllers/api/v1/parties_controller.rb index 272cd19..d8c6ac2 100644 --- a/app/controllers/api/v1/parties_controller.rb +++ b/app/controllers/api/v1/parties_controller.rb @@ -142,6 +142,47 @@ module Api ) end + # Syncs all linked grid items from their collection sources. + # + # POST /parties/:id/sync_all + def sync_all + @party = Party.find_by(id: params[:id]) + return render_not_found_response('party') unless @party + return render_unauthorized_response unless authorized_to_edit? + + synced = { characters: 0, weapons: 0, summons: 0, artifacts: 0 } + + ActiveRecord::Base.transaction do + @party.characters.where.not(collection_character_id: nil).each do |gc| + gc.sync_from_collection! + synced[:characters] += 1 + end + + @party.weapons.where.not(collection_weapon_id: nil).each do |gw| + gw.sync_from_collection! + synced[:weapons] += 1 + end + + @party.summons.where.not(collection_summon_id: nil).each do |gs| + gs.sync_from_collection! + synced[:summons] += 1 + end + + GridArtifact.joins(:grid_character) + .where(grid_characters: { party_id: @party.id }) + .where.not(collection_artifact_id: nil) + .each do |ga| + ga.sync_from_collection! + synced[:artifacts] += 1 + end + end + + render json: { + party: PartyBlueprint.render_as_hash(@party.reload, view: :full), + synced: synced + }, status: :ok + end + # Lists parties based on query parameters. def index query = build_filtered_query(build_common_base_query) diff --git a/config/routes.rb b/config/routes.rb index 983a7ae..48e1015 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -119,7 +119,17 @@ Rails.application.routes.draw do end # Grid artifacts - resources :grid_artifacts, only: %i[create update destroy] + resources :grid_artifacts, only: %i[create update destroy] do + member do + post :sync + end + end + + # Sync endpoints for grid items + post 'grid_characters/:id/sync', to: 'grid_characters#sync' + post 'grid_weapons/:id/sync', to: 'grid_weapons#sync' + post 'grid_summons/:id/sync', to: 'grid_summons#sync' + post 'parties/:id/sync_all', to: 'parties#sync_all' # Grid endpoints - new prefixed versions post 'grid_characters/resolve', to: 'grid_characters#resolve'