Skip to content

Commit f76c7a0

Browse files
authored
Merge pull request #1746 from coderdojo-japan/feature/move-events-latest-to-dojos-activity
feat: Move `/events/latest` → `/dojos/activity` to be more RESTful
2 parents 79d82d4 + d0a39af commit f76c7a0

File tree

11 files changed

+265
-172
lines changed

11 files changed

+265
-172
lines changed

app/assets/stylesheets/custom.scss

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,7 +1075,34 @@ section {
10751075

10761076
/* Stats and Dojos table styling */
10771077
.stats-table {
1078-
td.inactive-item {
1079-
background-color: gainsboro;
1078+
table-layout: auto;
1079+
1080+
th {
1081+
padding: 10px;
1082+
text-align: center;
1083+
}
1084+
1085+
td {
1086+
padding: 1px 10px 1px 10px;
1087+
text-align: right;
1088+
font-size: smaller;
1089+
1090+
&.url-cell {
1091+
white-space: normal; /* 改行を許可 */
1092+
word-wrap: break-word; /* 古めのブラウザ向け */
1093+
overflow-wrap: break-word; /* 新しめのブラウザ向け */
1094+
word-break: break-all; /* 英数字が続く場合の保険 (必要に応じて) */
1095+
text-align: left;
1096+
}
1097+
1098+
&.inactive-item {
1099+
background-color: gainsboro;
1100+
}
1101+
}
1102+
1103+
// Activity page specific style for expired events
1104+
span.expired a {
1105+
color: red;
1106+
background-color: #ffe5e5; /* 薄い赤背景 */
10801107
}
10811108
}

app/controllers/docs_controller.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ def show
2525
@doc.content.gsub! "{{ NUM_OF_TOTAL_EVENTS }}", Dojo::NUM_OF_TOTAL_EVENTS
2626
@doc.content.gsub! "{{ NUM_OF_TOTAL_NINJAS }}", Dojo::NUM_OF_TOTAL_NINJAS
2727
end
28+
29+
# INACTIVE_THRESHOLD を日本語の期間表記に変換
30+
if @doc.content.include? "INACTIVE_THRESHOLD"
31+
# 1.year → "1年間", 6.months → "6ヶ月間" のように変換
32+
threshold_in_months = Dojo::INACTIVE_THRESHOLD.to_i / 1.month.to_i
33+
threshold_text = if threshold_in_months >= 12
34+
years = threshold_in_months / 12
35+
"#{years.to_s.tr('0-9', '0-9')}年間"
36+
else
37+
"#{threshold_in_months.to_s.tr('0-9', '0-9')}ヶ月間"
38+
end
39+
@doc.content.gsub! "{{ INACTIVE_THRESHOLD }}", threshold_text
40+
end
2841

2942
@content = Kramdown::Document.new(@doc.content, input: 'GFM').to_html
3043
@url = request.url

app/controllers/dojos_controller.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,41 @@ def show
105105
format.csv { send_data render_to_string, type: :csv }
106106
end
107107
end
108+
109+
# GET /dojos/activity
110+
# 道場の活動状況を表示(旧 /events/latest から移行)
111+
def activity
112+
# ビューで使用するための閾値をインスタンス変数に設定(モデルから取得)
113+
@inactive_threshold = Dojo::INACTIVE_THRESHOLD
114+
115+
@latest_event_by_dojos = []
116+
Dojo.active.each do |dojo|
117+
link_in_note = dojo.note.match(URI.regexp)
118+
date_in_note = dojo.note.match(/(\d{4}-\d{1,2}-\d{1,2})/) # YYYY-MM-DD
119+
120+
latest_event = dojo.event_histories.newest.first
121+
122+
@latest_event_by_dojos << {
123+
id: dojo.id,
124+
name: dojo.name,
125+
note: dojo.note,
126+
url: dojo.url,
127+
created_at: dojo.created_at, # 掲載日(/dojos と同じ)
128+
129+
# 直近の開催日(イベント履歴がある場合のみ)
130+
latest_event_at: latest_event.nil? ? nil : latest_event.evented_at,
131+
latest_event_url: latest_event.nil? ? nil : latest_event.event_url,
132+
133+
# note内の日付とリンク(fallback用)
134+
note_date: date_in_note.nil? ? nil : Time.zone.parse(date_in_note.to_s),
135+
note_link: link_in_note.nil? ? nil : link_in_note.to_s
136+
}
137+
end
138+
139+
# Sort by latest event date (or created_at if no events) && Dojo's order if same date
140+
@latest_event_by_dojos.sort_by! do |dojo|
141+
sort_date = dojo[:latest_event_at] || dojo[:note_date] || dojo[:created_at]
142+
[sort_date, dojo[:order]]
143+
end
144+
end
108145
end

app/controllers/events_controller.rb

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,42 +13,4 @@ def index
1313
}
1414
end
1515
end
16-
17-
def latest
18-
# 現在はノートで細かな確認ができるため不要? (念のため残しています)
19-
# @active_dojos_verified = [
20-
# '和歌山', '市川真間', '泉', '石垣', '南紀田辺', '三好', '市川', 'ひばりヶ丘', '伊勢',
21-
# '徳島', '柏', '富山', 'ももち', '木曽', '熊本'
22-
# ]
23-
@latest_event_by_dojos = []
24-
Dojo.active.each do |dojo|
25-
link_in_note = dojo.note.match(URI.regexp)
26-
date_in_note = dojo.note.match(/(\d{4}-\d{1,2}-\d{1,2})/) # YYYY-MM-DD
27-
last_session_link = link_in_note.nil? ? dojo_path(dojo.id) : link_in_note.to_s
28-
last_session_date = date_in_note.nil? ? dojo.created_at : Time.zone.parse(date_in_note.to_s)
29-
30-
latest_event = dojo.event_histories.newest.first
31-
latest_event_at = latest_event.nil? ? Time.zone.parse('2000-01-23') : latest_event.evented_at
32-
@latest_event_by_dojos << {
33-
id: dojo.id,
34-
name: dojo.name,
35-
note: dojo.note,
36-
url: dojo.url,
37-
has_event_histories: latest_event.nil?,
38-
39-
# 過去のイベント開催日と note 内の日付を比較し、新しい方の日付を表示
40-
event_at: (latest_event_at < last_session_date) ?
41-
last_session_date.strftime("%Y-%m-%d") :
42-
latest_event.evented_at.strftime("%Y-%m-%d"),
43-
44-
# 過去のイベント開催日と note 内の日付を比較し、新しい方のリンクを表示
45-
event_url: (latest_event_at < last_session_date) ?
46-
last_session_link :
47-
latest_event.event_url
48-
}
49-
end
50-
51-
# Sort by older events first && older Dojo ID first if same event date.
52-
@latest_event_by_dojos.sort_by!{ |dojo| [dojo[:event_at], dojo[:id]] }
53-
end
5416
end

app/models/dojo.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ class Dojo < ApplicationRecord
55
NUM_OF_TOTAL_EVENTS = "10,000"
66
NUM_OF_TOTAL_NINJAS = "62,000"
77
DOJO_INFO_YAML_PATH = Rails.root.join('db', 'dojos.yml')
8+
9+
# 1年以上イベント開催していない道場を判定する閾値
10+
INACTIVE_THRESHOLD = 1.year
811

912
belongs_to :prefecture
1013
has_many :dojo_event_services, dependent: :destroy

app/views/dojos/activity.html.erb

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<% provide(:title, '道場情報 - 活動状況まとめ') %>
2+
<% provide(:desc, '道場別の掲載日と直近開催日をまとめたページです。') %>
3+
<% provide(:url, activity_dojos_url) %>
4+
<% provide(:meta_image, '/img/ogp-events.jpeg') %>
5+
6+
<section class="cover">
7+
<%= lazy_image_tag('/events_cover.jpg', alt: 'Cover Photo on Upcoming Events', min: true) %>
8+
</section>
9+
10+
<section id="events" class="text-center" style="margin-bottom: 100px;">
11+
<br />
12+
<h1>☯️ 道場別の活動状況まとめ</h1>
13+
<br />
14+
<p style="margin: 0 0px 40px 10px; line-height: 1.5em;">
15+
主にデータ分析や
16+
<a href="/signup#terms-of-use">Active/Inactive</a>
17+
の判断などの用途で使われています。
18+
<br>
19+
<div class='form__terms list'>
20+
<ul style='list-style-type: "\2713\0020"; font-size: smaller;'>
21+
<li>「掲載日」は<%= link_to '統計情報 (道場別) ', dojos_path %> と同じロジックで表示しています。</li>
22+
<li>「開催日」は<%= link_to '統計情報 (開催数)', stats_path %> から直近の開催日を表示しています。</li>
23+
<li>「開催日」のデータは <a href='https://doorkeeper.jp/'>Doorkeeper</a><a href='http://connpass.com/'>connpass</a> にのみ対応しています。</li>
24+
</ul>
25+
</div>
26+
</p>
27+
28+
<div style="margin-top: 20px;" align="center">
29+
<table border="1" class="stats-table">
30+
<tr>
31+
<th>
32+
<small>
33+
☯️
34+
<br class='ignore-pc'>
35+
道場名 (ID 番号)
36+
</small>
37+
</th>
38+
<th>
39+
<small>
40+
🗓
41+
<br class='ignore-pc'>
42+
<a href='/signup'>掲載日</a>
43+
</small>
44+
</th>
45+
<th>
46+
<small>
47+
👥
48+
<br class='ignore-pc'>
49+
開催日
50+
</small>
51+
</th>
52+
<th>
53+
<small>
54+
📝
55+
<br class='ignore-pc'>
56+
ノート
57+
</small>
58+
</th>
59+
</tr>
60+
<% @latest_event_by_dojos.each do |dojo| %>
61+
<tr>
62+
<td>
63+
<small>
64+
<%= link_to dojo_path(dojo[:id]) do %>
65+
<%= dojo[:name] %><br>
66+
<small>(ID: <%= dojo[:id] %>)</small>
67+
<% end %>
68+
</small>
69+
</td>
70+
<td>
71+
<small><%= dojo[:created_at].strftime("%Y-%m-%d") %></small>
72+
</td>
73+
<td>
74+
<small>
75+
<% if dojo[:latest_event_at] %>
76+
<!-- イベント履歴がある場合 -->
77+
<% expired = dojo[:latest_event_at] <= Time.current - @inactive_threshold && !dojo[:note].include?('Active') %>
78+
<span class="<%= 'expired' if expired %>">
79+
<%= link_to dojo[:latest_event_at].strftime("%Y-%m-%d"), dojo[:latest_event_url] %>
80+
</span>
81+
<% elsif dojo[:note_date] %>
82+
<!-- note内に日付がある場合 -->
83+
<% expired = dojo[:note_date] <= Time.current - @inactive_threshold && !dojo[:note].include?('Active') %>
84+
<span class="<%= 'expired' if expired %>">
85+
<% if dojo[:note_link] %>
86+
<%= link_to dojo[:note_date].strftime("%Y-%m-%d"), dojo[:note_link] %>
87+
<% else %>
88+
<%= dojo[:note_date].strftime("%Y-%m-%d") %>
89+
<% end %>
90+
</span>
91+
<% else %>
92+
<!-- 開催日情報なし -->
93+
<span style="color: #999;">-</span>
94+
<% end %>
95+
</small>
96+
</td>
97+
<td class="url-cell">
98+
<small>
99+
<span title="<%= dojo[:note] %>">
100+
<% truncated_note = truncate(dojo[:note], length: 60) %>
101+
<%= raw Addressable::URI.unescape(Rinku.auto_link(truncated_note)) %>
102+
</span>
103+
</small>
104+
</td>
105+
</tr>
106+
<% end %>
107+
</table>
108+
</div>
109+
110+
<p>
111+
<pre style='white-space: pre-wrap; margin-top: 60px; color: #505050;'>本ページにある開催日は <br class='ignore-pc'><a href='https://doorkeeper.jp/'>Doorkeeper</a><a href='http://connpass.com/'>connpass</a> にのみ対応しています。</pre>
112+
</p>
113+
<div style='margin-top: 30px;'><a href='#top'>&uarr; 上に戻る</a></div>
114+
</section>

app/views/dojos/index.html.erb

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,27 +62,6 @@
6262
</p>
6363
</div>
6464

65-
<style type="text/css">
66-
/* URL 用のセルにクラスを付けておく想定 */
67-
table { table-layout: auto; }
68-
td {
69-
padding: 1px 10px 1px 10px;
70-
text-align: right;
71-
font-size: smaller;
72-
}
73-
td.url-cell {
74-
white-space: normal; /* 改行を許可 */
75-
word-wrap: break-word; /* 古めのブラウザ向け */
76-
overflow-wrap: break-word; /* 新しめのブラウザ向け */
77-
word-break: break-all; /* 英数字が続く場合の保険 (必要に応じて) */
78-
text-align: left;
79-
}
80-
th {
81-
padding: 10px;
82-
text-align: center;
83-
}
84-
</style>
85-
8665
<div style="margin-top: 20px;" align="center">
8766
<table border="1" class="stats-table">
8867
<tr>

0 commit comments

Comments
 (0)