1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2014-2015 Alexandre Terrasa <alexandre@moz-code.org>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Panels templates for `nitpg`.
20 import templates_events
22 # A panel can be displayed in a html page.
24 # This display a Bootstrap panel.
28 redef fun rendering
do
29 add
"""<div class="panel panel-default">
30 <div class="panel-heading">
31 <h3 class="panel-title">"""
35 <div class="panel-body">"""
41 # Render the panel title.
42 # Betweem `<h4>` tags.
43 fun render_title
do end
45 # Render the panel body.
46 fun render_body
do end
49 # A panel that contain only a table as body.
53 redef fun rendering
do
54 add
"""<div class="panel panel-default">
55 <div class="panel-heading">
56 <h3 class="panel-title">"""
66 # Display an error message within a panel.
70 redef fun rendering
do
72 <div class="panel panel-danger">
73 <div class="panel-heading">
74 <h3 class="panel-title">"""
79 <div class="panel-body">"""
87 # The error message to display as panel body.
90 redef fun render_title
do
91 add
"<span class=\"glyphicon glyphicon-warning-sign\
"></span> "
95 redef fun render_body
do
101 # A panel that display repo statistics.
102 class GameStatusPanel
108 redef fun render_title
do
109 add
"<span class=\"glyphicon glyphicon-home\
"></span> "
113 redef fun render_body
do
114 add
"<strong class=\"text-success\
">{game.load_players.length}</strong>"
115 add
" <a href=\"{game.url}/players\
">players</a><br>"
116 add
"<strong class=\"text-success\
">{game.stats["achievements"]}</strong>"
117 add
" <a href=\"{game.url}/achievements\
">achievements</a><br><br>"
118 add
"<strong class=\"text-success\
">{game.stats["pulls"]}</strong> pull requests"
119 add
" (<strong>{game.stats["pulls_open"]}</strong> open)<br>"
120 add
"<strong class=\"text-success\
">{game.stats["issues"]}</strong> issues"
121 add
" (<strong>{game.stats["issues_open"]}</strong> open)<br>"
122 add
"<strong class=\"text-success\
">{game.stats["commits"]}</strong> commits"
126 # Player status panel.
127 class PlayerStatusPanel
136 redef fun render_title
do
137 add
"<a href=\"{player.url}\
">"
138 add
" <img class=\"img-circle\
" style=\"width
: 30px\
""
139 add
" src=\"{player.user.avatar_url}\
" alt=\"{player.name}\
">"
140 add
"</a> {player.link}"
143 redef fun render_body
do
144 var ranking
= game
.player_ranking
146 add
"<p class=\"lead\
">ranked "
147 add
" <span class=\"text-success\
"># {ranking[player.name]}</span></p>"
148 add
"<strong class=\"text-success\
">{player.nitcoins}</strong> nitcoins<br><br>"
149 add
"<strong class=\"text-success\
">{player.stats["achievements"]}</strong> achievements<br><br>"
150 add
"<strong>{player.stats["pulls"]}</strong> pull requests<br>"
151 add
"<strong>{player.stats["issues"]}</strong> issues<br>"
152 add
"<strong>{player.stats["commits"]}</strong> commits"
156 # A panel that display a list of player in a repo.
157 class ShortListPlayersPanel
163 redef fun render_title
do
164 add
"<span class=\"glyphicon glyphicon-user\
"></span> "
165 add
"<a href=\"{game.url}/players\
">Players</a>"
168 redef fun render_body
do
169 var players
= game
.load_players
.values
.to_a
170 if players
.is_empty
then
171 add
"<em>No player yet...</em>"
174 (new PlayerCoinComparator).sort
(players
)
175 for player
in players
do
176 add
"{player.nitcoins} - {player.link}<br>"
181 # A panel that display a list of player in a repo.
182 class ListPlayersPanel
188 redef fun render_title
do
189 add
"<span class=\"glyphicon glyphicon-user\
"></span> "
190 add
"<a href=\"{game.url}/players\
">Players</a>"
193 redef fun render_body
do
194 var players
= game
.load_players
.values
.to_a
195 (new PlayerCoinComparator).sort
(players
)
196 if players
.is_empty
then
197 add
"<div class=\"panel-body\
">"
198 add
"<em>No player yet...</em>"
202 add
"""<table class="table table-striped table-hover">
209 for player
in players
do
211 add
" <td>{rank}</td>"
212 add
" <td>{player.link}</td>"
213 add
" <td>{player.nitcoins}</td>"
221 # A panel that display the podium.
228 redef fun render_title
do
229 add
"<span class=\"glyphicon glyphicon-stats\
"></span> Hall of fame"
232 redef fun render_body
do
233 var players
= game
.load_players
.values
.to_a
234 (new PlayerCoinComparator).sort
(players
)
235 if players
.is_empty
then
236 add
"<em>No players yet...</em>"
240 <div class="container-fluid">
241 <div id="podium" class="row row-sm-height">"""
242 var max
= players
.first
.nitcoins
243 var orders
= [3, 1, 0, 2, 4]
244 for order
in orders
do
245 if order
>= players
.length
then continue
246 var player
= players
[order
]
248 if max
> 0 then size
= player
.nitcoins
* 300 / max
250 <div class="col-xs-2 col-xs-height col-xs-offset-{{{order}}} col-bottom"
251 style="text-align: center;">
253 <a href="{{{player.url}}}">
254 <img class="img-circle" style="width: 80px"
255 src="{{{player.user.avatar_url}}}" alt="{{{player.name}}}">
258 <p>{{{player.link}}}</p>
259 <p>{{{player.nitcoins}}}</p>
260 <div class=" progress-bar-warning progress-bar-striped"
261 style="height: {{{size}}}px;"></div>
270 # A `Panel` that displays the list of PR to review for a `Player`.
271 class PlayerReviewsPanel
277 # Player to display customized list for.
280 redef fun render_title
do
281 add
"<span class=\"glyphicon glyphicon-check\
"></span> "
282 add
"Review pull requests to gain nitcoins!"
285 redef fun render_body
do
286 var q
= "is:open label:need_review sort:updated-asc " +
287 "-involves:{player.name}"
289 var issues
= game
.repo
.search_issues
(q
)
290 if issues
.is_empty
then
291 add
"<em>No pull request to review yet...</em>"
294 for issue
in issues
do
295 var user
= issue
.user
296 var uplay
= user
.player
(game
)
297 add
"""<div class="media">
298 <a class="media-left" href="{{{uplay.url}}}">
299 <img class=\"img-circle\" style="width:50px"
300 src="{{{user.avatar_url}}}" alt="{{{uplay.name}}}">
302 <div class="media-body">
303 <h4 class="media-heading">
304 {{{issue.link}}} {{{issue.title}}}
306 <span class="text-muted">opened by </span>
314 # A `Panel` that displays a pagined list of events stored in the `entity`.
316 # This way the panel can be used to view events stored under `Game`, `Player`...
320 # Entity to load the events from.
321 var entity
: GameEntity
323 # Number of events to display.
326 # From where to start?
329 redef fun render_title
do
330 add
"<span class=\"glyphicon glyphicon-flash\
"></span> "
334 redef fun render_body
do
335 var events
= entity
.load_events
336 if events
.is_empty
then
337 add
"<em>No event yet...</em>"
341 if limit
< 0 then limit
= 10
342 if from
< 0 then from
= 0
344 for i
in [from
.. from
+ limit
] do
345 if i
>= events
.length
then break
346 add events
[i
].tpl_event
.media_item
349 if limit
> events
.length
then return
351 add
"""<div class="btn-group" role="group">"""
353 add
"""<a class="btn btn-default" role="button"
354 href="?pfrom={{{from - limit}}}&plimit={{{limit}}}">
355 <span class=\"glyphicon glyphicon-chevron-left\"></span></a>"""
357 if from
+ limit
< events
.length
then
359 <a class="btn btn-default" role="button"
360 href="?pfrom={{{from + limit}}}&plimit={{{limit}}}">
361 <span class=\"glyphicon glyphicon-chevron-right\"></span></a>"""
367 # Achievement unlocked list panel.
368 class AchievementsListPanel
371 # Entity to load the events from.
372 var entity
: GameEntity
374 redef fun render_title
do
375 add
"<span class=\"glyphicon glyphicon-list\
"></span> "
376 add
"Achievements unlocked"
379 redef fun render_body
do
380 var achs
= entity
.load_achievements
.values
.to_a
381 if achs
.is_empty
then
382 add
"<em>No achievement yet...</em>"
385 for ach
in achs
do add ach
.list_item
389 # Achievement detail panel.
390 class AchievementPanel
393 # Achievement to display.
394 var achievement
: Achievement
396 redef fun render_title
do
397 add
"<span class=\"glyphicon glyphicon-check\
"></span> "
398 add
"Achievement details"
401 redef fun render_body
do
402 add
"""<p class=\"lead\">
403 <span class="badge progress-bar-success"
404 style="vertical-align: middle">+{{{achievement.reward}}}</span>
405 {{{achievement.name}}}
407 <p><strong>{{{achievement.desc}}}</strong></p>"""
409 var events
= achievement
.load_events
411 if events
.is_empty
then
412 add
"<em>Never unlocked...</em>"
416 var event
= events
.last
417 var tpl
= event
.tpl_event
418 var player
= tpl
.player
420 add
"""<div class="media">
421 <a class="media-left" href="{{{player.url}}}">
422 <span class="badge progress-bar-warning" style="position: absolute">#1</span>
423 <img class=\"img-circle\" style="width:50px"
424 src="{{{player.user.avatar_url}}}" alt="{{{player.name}}}">
426 <div class="media-body">
427 <h4 class="media-heading">Unlocked first by {{{player.link}}}</h4>
428 <span class="text-muted">at {{{event.time}}} </span>
432 if events
.length
> 1 then
433 add
"""<p><br>Also unlocked by <strong class="text-success">
434 {{{events.length}}} players</strong>.</p>"""