diff --git a/app/assets/stylesheets/custom.scss b/app/assets/stylesheets/custom.scss index 010b4b6ed..c064c9f10 100644 --- a/app/assets/stylesheets/custom.scss +++ b/app/assets/stylesheets/custom.scss @@ -1075,7 +1075,34 @@ section { /* Stats and Dojos table styling */ .stats-table { - td.inactive-item { - background-color: gainsboro; + table-layout: auto; + + th { + padding: 10px; + text-align: center; + } + + td { + padding: 1px 10px 1px 10px; + text-align: right; + font-size: smaller; + + &.url-cell { + white-space: normal; /* 改行を許可 */ + word-wrap: break-word; /* 古めのブラウザ向け */ + overflow-wrap: break-word; /* 新しめのブラウザ向け */ + word-break: break-all; /* 英数字が続く場合の保険 (必要に応じて) */ + text-align: left; + } + + &.inactive-item { + background-color: gainsboro; + } + } + + // Activity page specific style for expired events + span.expired a { + color: red; + background-color: #ffe5e5; /* 薄い赤背景 */ } } diff --git a/app/controllers/docs_controller.rb b/app/controllers/docs_controller.rb index 9cd3b25ab..9b6d9b3ca 100644 --- a/app/controllers/docs_controller.rb +++ b/app/controllers/docs_controller.rb @@ -25,6 +25,19 @@ def show @doc.content.gsub! "{{ NUM_OF_TOTAL_EVENTS }}", Dojo::NUM_OF_TOTAL_EVENTS @doc.content.gsub! "{{ NUM_OF_TOTAL_NINJAS }}", Dojo::NUM_OF_TOTAL_NINJAS end + + # INACTIVE_THRESHOLD を日本語の期間表記に変換 + if @doc.content.include? "INACTIVE_THRESHOLD" + # 1.year → "1年間", 6.months → "6ヶ月間" のように変換 + threshold_in_months = Dojo::INACTIVE_THRESHOLD.to_i / 1.month.to_i + threshold_text = if threshold_in_months >= 12 + years = threshold_in_months / 12 + "#{years.to_s.tr('0-9', '0-9')}年間" + else + "#{threshold_in_months.to_s.tr('0-9', '0-9')}ヶ月間" + end + @doc.content.gsub! "{{ INACTIVE_THRESHOLD }}", threshold_text + end @content = Kramdown::Document.new(@doc.content, input: 'GFM').to_html @url = request.url diff --git a/app/controllers/dojos_controller.rb b/app/controllers/dojos_controller.rb index bd20e735c..4cf8389be 100644 --- a/app/controllers/dojos_controller.rb +++ b/app/controllers/dojos_controller.rb @@ -105,4 +105,41 @@ def show format.csv { send_data render_to_string, type: :csv } end end + + # GET /dojos/activity + # 道場の活動状況を表示(旧 /events/latest から移行) + def activity + # ビューで使用するための閾値をインスタンス変数に設定(モデルから取得) + @inactive_threshold = Dojo::INACTIVE_THRESHOLD + + @latest_event_by_dojos = [] + Dojo.active.each do |dojo| + link_in_note = dojo.note.match(URI.regexp) + date_in_note = dojo.note.match(/(\d{4}-\d{1,2}-\d{1,2})/) # YYYY-MM-DD + + latest_event = dojo.event_histories.newest.first + + @latest_event_by_dojos << { + id: dojo.id, + name: dojo.name, + note: dojo.note, + url: dojo.url, + created_at: dojo.created_at, # 掲載日(/dojos と同じ) + + # 直近の開催日(イベント履歴がある場合のみ) + latest_event_at: latest_event.nil? ? nil : latest_event.evented_at, + latest_event_url: latest_event.nil? ? nil : latest_event.event_url, + + # note内の日付とリンク(fallback用) + note_date: date_in_note.nil? ? nil : Time.zone.parse(date_in_note.to_s), + note_link: link_in_note.nil? ? nil : link_in_note.to_s + } + end + + # Sort by latest event date (or created_at if no events) && Dojo's order if same date + @latest_event_by_dojos.sort_by! do |dojo| + sort_date = dojo[:latest_event_at] || dojo[:note_date] || dojo[:created_at] + [sort_date, dojo[:order]] + end + end end diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 4e8cb9fb4..25b30666a 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -13,42 +13,4 @@ def index } end end - - def latest - # 現在はノートで細かな確認ができるため不要? (念のため残しています) - # @active_dojos_verified = [ - # '和歌山', '市川真間', '泉', '石垣', '南紀田辺', '三好', '市川', 'ひばりヶ丘', '伊勢', - # '徳島', '柏', '富山', 'ももち', '木曽', '熊本' - # ] - @latest_event_by_dojos = [] - Dojo.active.each do |dojo| - link_in_note = dojo.note.match(URI.regexp) - date_in_note = dojo.note.match(/(\d{4}-\d{1,2}-\d{1,2})/) # YYYY-MM-DD - last_session_link = link_in_note.nil? ? dojo_path(dojo.id) : link_in_note.to_s - last_session_date = date_in_note.nil? ? dojo.created_at : Time.zone.parse(date_in_note.to_s) - - latest_event = dojo.event_histories.newest.first - latest_event_at = latest_event.nil? ? Time.zone.parse('2000-01-23') : latest_event.evented_at - @latest_event_by_dojos << { - id: dojo.id, - name: dojo.name, - note: dojo.note, - url: dojo.url, - has_event_histories: latest_event.nil?, - - # 過去のイベント開催日と note 内の日付を比較し、新しい方の日付を表示 - event_at: (latest_event_at < last_session_date) ? - last_session_date.strftime("%Y-%m-%d") : - latest_event.evented_at.strftime("%Y-%m-%d"), - - # 過去のイベント開催日と note 内の日付を比較し、新しい方のリンクを表示 - event_url: (latest_event_at < last_session_date) ? - last_session_link : - latest_event.event_url - } - end - - # Sort by older events first && older Dojo ID first if same event date. - @latest_event_by_dojos.sort_by!{ |dojo| [dojo[:event_at], dojo[:id]] } - end end diff --git a/app/models/dojo.rb b/app/models/dojo.rb index 2bc580417..429b19cef 100644 --- a/app/models/dojo.rb +++ b/app/models/dojo.rb @@ -5,6 +5,9 @@ class Dojo < ApplicationRecord NUM_OF_TOTAL_EVENTS = "10,000" NUM_OF_TOTAL_NINJAS = "62,000" DOJO_INFO_YAML_PATH = Rails.root.join('db', 'dojos.yml') + + # 1年以上イベント開催していない道場を判定する閾値 + INACTIVE_THRESHOLD = 1.year belongs_to :prefecture has_many :dojo_event_services, dependent: :destroy diff --git a/app/views/dojos/activity.html.erb b/app/views/dojos/activity.html.erb new file mode 100644 index 000000000..32208fe9f --- /dev/null +++ b/app/views/dojos/activity.html.erb @@ -0,0 +1,114 @@ +<% provide(:title, '道場情報 - 活動状況まとめ') %> +<% provide(:desc, '道場別の掲載日と直近開催日をまとめたページです。') %> +<% provide(:url, activity_dojos_url) %> +<% provide(:meta_image, '/img/ogp-events.jpeg') %> + +
+ <%= lazy_image_tag('/events_cover.jpg', alt: 'Cover Photo on Upcoming Events', min: true) %> +
+ +
+
+

☯️ 道場別の活動状況まとめ

+
+

+ 主にデータ分析や + Active/Inactive + の判断などの用途で使われています。 +
+

+ +
+

+ +
+ + + + + + + + <% @latest_event_by_dojos.each do |dojo| %> + + + + + + + <% end %> +
+ + ☯️ +
+ 道場名 (ID 番号) +
+
+ + 🗓 +
+ 掲載日 +
+
+ + 👥 +
+ 開催日 +
+
+ + 📝 +
+ ノート +
+
+ + <%= link_to dojo_path(dojo[:id]) do %> + <%= dojo[:name] %>
+ (ID: <%= dojo[:id] %>) + <% end %> +
+
+ <%= dojo[:created_at].strftime("%Y-%m-%d") %> + + + <% if dojo[:latest_event_at] %> + + <% expired = dojo[:latest_event_at] <= Time.current - @inactive_threshold && !dojo[:note].include?('Active') %> + + <%= link_to dojo[:latest_event_at].strftime("%Y-%m-%d"), dojo[:latest_event_url] %> + + <% elsif dojo[:note_date] %> + + <% expired = dojo[:note_date] <= Time.current - @inactive_threshold && !dojo[:note].include?('Active') %> + + <% if dojo[:note_link] %> + <%= link_to dojo[:note_date].strftime("%Y-%m-%d"), dojo[:note_link] %> + <% else %> + <%= dojo[:note_date].strftime("%Y-%m-%d") %> + <% end %> + + <% else %> + + - + <% end %> + + + + + <% truncated_note = truncate(dojo[:note], length: 60) %> + <%= raw Addressable::URI.unescape(Rinku.auto_link(truncated_note)) %> + + +
+
+ +

+

本ページにある開催日は 
Doorkeeperconnpass にのみ対応しています。
+

+
↑ 上に戻る
+
diff --git a/app/views/dojos/index.html.erb b/app/views/dojos/index.html.erb index 4ecf89c15..e0cd2d805 100644 --- a/app/views/dojos/index.html.erb +++ b/app/views/dojos/index.html.erb @@ -62,27 +62,6 @@

- -
diff --git a/app/views/events/latest.html.erb b/app/views/events/latest.html.erb deleted file mode 100644 index d9685dca7..000000000 --- a/app/views/events/latest.html.erb +++ /dev/null @@ -1,107 +0,0 @@ -<% provide(:title, '道場情報 - 直近の開催日まとめ') %> -<% provide(:desc, '道場別の直近開催日をまとめたページです。') %> -<% provide(:url, events_latest_url) %> -<% provide(:meta_image, '/img/ogp-events.jpeg') %> - -
- <%= lazy_image_tag('/events_cover.jpg', alt: 'Cover Photo on Upcoming Events', min: true) %> -
- -
-
-

☯️ 道場別の直近の開催日まとめ

-
-

- 主にデータ分析や - Active/Inactive - の判断などの用途で使われています。 -
-

-
    -
  • <%= link_to '近日開催', events_path %>のデータは含まず、<%= link_to '過去開催', stats_path %>のデータを使っています。
  • -
  • 開催データは Doorkeeperconnpass にのみ対応しています。
  • -
  • 上記以外でイベント管理している場合は掲載日を表示しています。
  • -
-
-

- - - -
-
- - - - - - <% @latest_event_by_dojos.each do |dojo| %> - - - - - - <% end %> -
- ☯️ 道場名 - - - 🗓 直近の開催日または掲載日 - - - 📝 ノート -
- - <%= dojo[:name] %> - - - - <% if dojo[:has_event_histories] %> - - > - <%= link_to dojo[:event_at], dojo[:event_url] %> - - <% else %> - - - > - <%= link_to dojo[:event_at], dojo[:event_url] %> - - <% end %> - - - - <%= raw Addressable::URI.unescape(Rinku.auto_link(dojo[:note])) %> - -
-
- -

-

本ページにある開催日は 
Doorkeeperconnpass にのみ対応しています。
-

-
↑ 上に戻る
- diff --git a/config/routes.rb b/config/routes.rb index 06b00c353..0eb3e73fe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -64,7 +64,11 @@ get "/kata" => "docs#kata" #get "/debug/kata" => "docs#kata" - resources :dojos, only: %i(index show) # GET /dojos.json returns dojo data as JSON + resources :dojos, only: %i(index show) do # GET /dojos.json returns dojo data as JSON + collection do + get :activity # GET /dojos/activity - 道場活動状況(旧 /events/latest) + end + end resources :docs, only: %i(index show) resources :podcasts, only: %i(index show) resources :spaces, only: %i(index) @@ -84,9 +88,11 @@ #resources :stats, only: %i(show) #resources :pokemons, only: %i(index create) - # Upcoming Events & Latest Events + # Upcoming Events get '/events' => 'events#index' - get '/events/latest' => 'events#latest' + + # Legacy redirect: /events/latest moved to /dojos/activity + get '/events/latest', to: redirect('/dojos/activity') # Redirects get "/releases/2016/12/12/new-backend", to: redirect('/docs/post-backend-update-history') diff --git a/public/docs/signup.md b/public/docs/signup.md index 1ea9550f9..1da134e5c 100644 --- a/public/docs/signup.md +++ b/public/docs/signup.md @@ -41,7 +41,7 @@ CoderDojo の立ち上げ申請がまだお済みでない場合は、下記ペ 1. 文字数やタグ数に上限があるため、申請内容を一部変更して掲載する場合があります 🙏 - 📝 例: scratch→Scratch,月1回開催→毎月開催,HTML5→HTML,マイクラ→Minecraft など -
-1. 財団により非アクティブと判断された場合、もしくは一定期間 (現時点では1年間) 活動状況が確認できない場合は非表示になります 😴 +1. 財団により非アクティブと判断された場合、もしくは一定期間 (現時点では{{ INACTIVE_THRESHOLD }}) 活動状況が確認できない場合は非表示になります 😴 - 📜️ [CoderDojo が承認されているかを確認する方法 - CoderDojo Japan](/docs/how-to-check-dojo-status) -
1. 申請後もロゴ画像や説明文を更新できますので、まずは気軽にお申し込みください 📮✨ diff --git a/spec/requests/dojos_spec.rb b/spec/requests/dojos_spec.rb index 809abd498..457279c47 100644 --- a/spec/requests/dojos_spec.rb +++ b/spec/requests/dojos_spec.rb @@ -318,4 +318,63 @@ end end end + + describe "GET /dojos/activity" do + before do + # アクティブな道場を作成 + @active_dojo = create(:dojo, + name: "Active Dojo", + created_at: 1.week.ago, + inactivated_at: nil + ) + + # 非アクティブな道場を作成 + @inactive_dojo = create(:dojo, + name: "Inactive Dojo", + created_at: 2.years.ago, + inactivated_at: 1.year.ago + ) + end + + it "returns http success" do + get activity_dojos_path + expect(response).to have_http_status(:success) + end + + it "displays the activity status page" do + get activity_dojos_path + expect(response.body).to include("道場別の活動状況まとめ") + end + + it "includes only active dojos" do + get activity_dojos_path + expect(response.body).to include(@active_dojo.name) + expect(response.body).not_to include(@inactive_dojo.name) + end + + it "redirects from old URL /events/latest" do + get "/events/latest" + expect(response).to redirect_to(activity_dojos_path) + end + + it "displays proper column headers" do + get activity_dojos_path + expect(response.body).to include("掲載日") + expect(response.body).to include("開催日") + expect(response.body).to include("ノート") + end + + it "displays created_at date for active dojos" do + get activity_dojos_path + # 掲載日は YYYY-MM-DD 形式で表示される + expect(response.body).to match(@active_dojo.created_at.strftime("%Y-%m-%d")) + end + + it "displays dojo ID same as /dojos page" do + get activity_dojos_path + # /dojos ページと同じように ID が表示される + expect(response.body).to include("(ID: #{@active_dojo.id})") + expect(response.body).to include("道場名 (ID 番号)") + end + end end \ No newline at end of file