本番デプロイ設定: SSL, Kamal, API環境変数化, テスト修正
This commit is contained in:
@@ -7,8 +7,8 @@ class BoardPostsController < ApplicationController
|
||||
before_action :set_current_participant
|
||||
|
||||
def create
|
||||
# 参加チェック
|
||||
unless @board.member?(@current_participant) && @game.status == "in_progress"
|
||||
# 参加チェック(国選択フェーズでも共通掲示板への投稿を許可)
|
||||
unless @board.member?(@current_participant) && @game.status.in?(%w[power_selection in_progress])
|
||||
return redirect_to game_board_path(@game, @board), alert: "投稿権限がありません"
|
||||
end
|
||||
|
||||
|
||||
@@ -22,14 +22,19 @@ class BoardsController < ApplicationController
|
||||
else
|
||||
return redirect_to game_path(@game), alert: "参加者ではないためアクセスできません" unless @current_participant
|
||||
|
||||
# 進行中:参加中の掲示板のみ(eager load で N+1 防止)
|
||||
@boards = @current_participant.boards.includes(:participants, :board_posts, :board_memberships).order(created_at: :desc)
|
||||
# 共通掲示板のフォールバック
|
||||
global_board = @game.boards.global.first
|
||||
if global_board && !@boards.include?(global_board)
|
||||
@boards = [ global_board ] + @boards
|
||||
if @game.status == "power_selection"
|
||||
# 国選択フェーズ:共通掲示板のみ表示
|
||||
@boards = @game.boards.global.includes(:participants, :board_posts, :board_memberships).to_a
|
||||
else
|
||||
# 進行中:参加中の掲示板のみ(eager load で N+1 防止)
|
||||
@boards = @current_participant.boards.includes(:participants, :board_posts, :board_memberships).order(created_at: :desc)
|
||||
# 共通掲示板のフォールバック
|
||||
global_board = @game.boards.global.first
|
||||
if global_board && !@boards.include?(global_board)
|
||||
@boards = [ global_board ] + @boards
|
||||
end
|
||||
@boards = @boards.sort_by { |b| b.global? ? 0 : 1 }
|
||||
end
|
||||
@boards = @boards.sort_by { |b| b.global? ? 0 : 1 }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -70,11 +75,11 @@ class BoardsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
@posts = @board.board_posts.includes(:participant).order(created_at: :desc)
|
||||
@posts = @board.board_posts.includes(participant: :user).order(created_at: :desc)
|
||||
@proposals = @board.board_proposals.includes(:proposer).order(created_at: :desc)
|
||||
@new_post = BoardPost.new
|
||||
@new_proposal = BoardProposal.new
|
||||
@active_members = @board.active_memberships.includes(:participant).map(&:participant)
|
||||
@active_members = @board.active_memberships.includes(participant: :user).map(&:participant)
|
||||
|
||||
# メンバー追加用:招待可能なプレイヤー一覧
|
||||
if @board.negotiation? && !@board.history_mode?
|
||||
|
||||
@@ -75,8 +75,11 @@ class GamesController < ApplicationController
|
||||
# 全7カ国(固定)
|
||||
powers = %w[AUSTRIA ENGLAND FRANCE GERMANY ITALY RUSSIA TURKEY]
|
||||
|
||||
# N+1 防止のためparticipantsをキャッシュ
|
||||
participants_cache = @game.participants.includes(:user).index_by(&:power)
|
||||
|
||||
@country_statuses = powers.map do |power|
|
||||
participant = @game.participants.find_by(power: power)
|
||||
participant = participants_cache[power]
|
||||
# 終了済みなら全員完了扱い、そうでなければターンごとの提出状況
|
||||
submitted = @game_finished ? true : @display_turn.orders_submitted_for?(power)
|
||||
|
||||
|
||||
@@ -38,15 +38,15 @@ export default class extends Controller {
|
||||
<div class="flex ${isMe ? 'justify-end' : 'justify-start'} mb-4 message-item" id="post_${data.post_id}">
|
||||
${!isMe ? `
|
||||
<div class="flex-shrink-0 mr-3">
|
||||
<span class="inline-flex items-center justify-center h-8 w-8 rounded-full text-xs font-bold border border-gray-300 bg-white text-gray-700 shadow-sm" title="${data.power}">
|
||||
${data.power ? data.power.substring(0, 2) : '?'}
|
||||
<span class="inline-flex items-center justify-center h-8 w-8 rounded-full text-xs font-bold border border-gray-300 bg-white text-gray-700 shadow-sm" title="${data.display_name || data.power || '?'}">
|
||||
${(data.display_name || data.power || '?').substring(0, 2)}
|
||||
</span>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<div class="max-w-lg ${isMe ? 'order-1' : 'order-2'}">
|
||||
<div class="flex items-baseline space-x-2 mb-1 ${isMe ? 'justify-end' : 'justify-start'}">
|
||||
${!isMe ? `<span class="text-xs font-bold text-gray-900">${data.power}</span>` : ''}
|
||||
${!isMe ? `<span class="text-xs font-bold text-gray-900">${data.display_name || data.power || '?'}</span>` : ''}
|
||||
<span class="text-xs text-gray-500">${data.created_at}</span>
|
||||
${data.phase ? `<span class="text-xs bg-gray-100 px-1 rounded text-gray-600 border border-gray-200">${data.phase}</span>` : ''}
|
||||
</div>
|
||||
|
||||
@@ -17,6 +17,7 @@ class BoardPost < ApplicationRecord
|
||||
post_id: id,
|
||||
participant_id: participant.id,
|
||||
power: participant.power, # 国名
|
||||
display_name: participant.display_name, # 国名 or ユーザー名
|
||||
body: body,
|
||||
phase: phase, # フェーズ情報
|
||||
created_at: created_at.in_time_zone("Asia/Tokyo").strftime("%Y-%m-%d %H:%M")
|
||||
|
||||
@@ -21,4 +21,9 @@ class Participant < ApplicationRecord
|
||||
in: %w[AUSTRIA ENGLAND FRANCE GERMANY ITALY RUSSIA TURKEY],
|
||||
message: "無効な国です"
|
||||
}, allow_nil: true
|
||||
|
||||
# 表示名:国名が設定済みなら国名、未設定ならユーザー名
|
||||
def display_name
|
||||
power.present? ? power : user.username
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ require "faraday"
|
||||
require "json"
|
||||
|
||||
class GameApiClient
|
||||
BASE_URL = "http://0.0.0.0:8000"
|
||||
BASE_URL = ENV.fetch("DIPLOMACY_API_URL", "http://0.0.0.0:8000")
|
||||
|
||||
def initialize
|
||||
@connection = Faraday.new(url: BASE_URL) do |f|
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<% unless is_me %>
|
||||
<div class="flex-shrink-0 mr-3">
|
||||
<!-- アバター代わりの国名バッジ -->
|
||||
<span class="inline-flex items-center justify-center h-8 w-8 rounded-full text-xs font-bold border border-gray-300 bg-white text-gray-700 shadow-sm" title="<%= post.participant.power %>">
|
||||
<%= post.participant.power ? post.participant.power[0..1] : '?' %>
|
||||
<span class="inline-flex items-center justify-center h-8 w-8 rounded-full text-xs font-bold border border-gray-300 bg-white text-gray-700 shadow-sm" title="<%= post.participant.display_name %>">
|
||||
<%= post.participant.display_name[0..1] %>
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="max-w-lg <%= is_me ? 'order-1' : 'order-2' %>">
|
||||
<div class="flex items-baseline space-x-2 mb-1 <%= is_me ? 'justify-end' : 'justify-start' %>">
|
||||
<% unless is_me %>
|
||||
<span class="text-xs font-bold text-gray-900"><%= post.participant.power %></span>
|
||||
<span class="text-xs font-bold text-gray-900"><%= post.participant.display_name %></span>
|
||||
<% end %>
|
||||
<span class="text-xs text-gray-500"><%= l post.created_at, format: :short %></span>
|
||||
<% if post.phase.present? %>
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
<% if last_post %>
|
||||
<i class="fa-solid fa-comment-dots flex-shrink-0 mr-1.5 text-gray-400"></i>
|
||||
<span class="truncate max-w-xs"><%= last_post.body.truncate(30) %></span>
|
||||
<span class="ml-2 text-xs text-gray-400">- <%= last_post.participant.power %></span>
|
||||
<span class="ml-2 text-xs text-gray-400">- <%= last_post.participant.display_name %></span>
|
||||
<% else %>
|
||||
<span class="text-gray-400">投稿なし</span>
|
||||
<% end %>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
メンバー:
|
||||
<% @active_members.each do |m| %>
|
||||
<span class="ml-1 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium border <%= power_color_class(m.power) %>">
|
||||
<%= m.power %>
|
||||
<%= m.display_name %>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -69,7 +69,7 @@
|
||||
<div class="flex-1 flex flex-col bg-white border border-gray-200 rounded-lg shadow-sm mr-4 overflow-hidden">
|
||||
|
||||
<!-- 投稿フォーム (上部に移動) -->
|
||||
<% if @board.member?(@current_participant) && !@board.history_mode? %>
|
||||
<% if @board.member?(@current_participant) && !@board.history_mode? && @game.status.in?(%w[power_selection in_progress]) %>
|
||||
<div class="p-4 bg-gray-50 border-b border-gray-200">
|
||||
<%= form_with model: [@game, @board, @new_post], local: true, class: "flex items-end space-x-2" do |f| %>
|
||||
<div class="flex-1">
|
||||
@@ -200,7 +200,7 @@
|
||||
<li class="px-3 py-2 flex items-center justify-between text-sm">
|
||||
<div class="flex items-center">
|
||||
<span class="<%= 'line-through text-gray-400' if membership.left_at %>">
|
||||
<%= membership.participant.power %>
|
||||
<%= membership.participant.display_name %>
|
||||
</span>
|
||||
<% if membership.participant.user == current_user %>
|
||||
<span class="ml-1 text-xs text-indigo-500">(YOU)</span>
|
||||
|
||||
@@ -189,6 +189,22 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 掲示板リンク(国選択の相談用) -->
|
||||
<div class="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-md">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<i class="fa-solid fa-comments text-blue-600 text-lg mr-3"></i>
|
||||
<div>
|
||||
<p class="text-sm font-medium text-blue-800">国選択を相談しませんか?</p>
|
||||
<p class="text-xs text-blue-600">掲示板で他のプレイヤーと相談できます</p>
|
||||
</div>
|
||||
</div>
|
||||
<%= link_to game_boards_path(@game), class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" do %>
|
||||
<i class="fa-solid fa-comment-dots mr-2"></i> 掲示板へ
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ゲーム管理者用コントロール -->
|
||||
<% if (current_user&.admin? || @game.administrator == current_user) && @game.all_powers_assigned? %>
|
||||
<div class="mt-6 pt-6 border-t border-gray-200">
|
||||
@@ -475,6 +491,11 @@
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-sm font-bold border border-gray-200 shadow-sm <%= power_color_class(status[:power]) %>">
|
||||
<%= status[:power] %>
|
||||
</span>
|
||||
<% if status[:participant] %>
|
||||
<span class="ml-2 text-xs text-gray-500">
|
||||
(<%= status[:participant].user.username %>)
|
||||
</span>
|
||||
<% end %>
|
||||
<% if status[:is_user] %>
|
||||
<span class="ml-2 inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-indigo-100 text-indigo-800">YOU</span>
|
||||
<% elsif status[:participant].nil? %>
|
||||
|
||||
Reference in New Issue
Block a user