Indefero

Indefero Commit Details


Date:2011-12-23 18:07:25 (12 years 11 months ago)
Author:Thomas Keller
Branch:develop, release-1.3
Commit:608e7a40e4477296b72135752e7be83c5dc60b8c
Parents: 6875e62942dbe582611890071e110536f34b60dd
Message:Save a link to the latest activity value in the project model and render a simple green bar as activity measure in the project list view.

Changes:

File differences

src/IDF/Migrations/24CurrentProjectActivity.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
function IDF_Migrations_24CurrentProjectActivity_up($params=null)
{
$engine = Pluf::f('db_engine');
$db = Pluf::db();
if ($engine === 'PostgreSQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_projects ADD COLUMN current_activity INTEGER');
} else if ($engine === 'MySQL') {
$db->execute('ALTER TABLE '.$db->pfx.'idf_projects ADD COLUMN current_activity MEDIUMINT');
}
}
function IDF_Migrations_24CurrentProjectActivity_down($params=null)
{
$db = Pluf::db();
$db->execute('ALTER TABLE '.$db->pfx.'idf_projects DROP COLUMN current_activity');
}
src/IDF/Project.php
100100
101101
102102
103
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
104124
105125
106126
'verbose' => __('private'),
'default' => 0,
),
);
'current_activity' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'IDF_ProjectActivity',
'blank' => true,
'verbose' => __('current project activity'),
),
);
$table = $this->_con->pfx.'idf_projectactivities';
$this->_a['views'] = array(
'join_activities' =>
array(
'join' => 'LEFT JOIN '.$table
.' ON current_activity='.$table.'.id',
'select' => $this->getSelect().', date, value',
'props' => array(
'date' => 'current_activity_date',
'value' => 'current_activity_value'
),
),
);
}
src/IDF/ProjectActivity.php
6464
6565
6666
67
68
69
70
71
72
73
74
75
76
77
6778
),
);
}
function postSave($create=false)
{
$prj = $this->get_project();
$sql = new Pluf_SQL('project=%s', array($prj->id));
$latest = Pluf::factory('IDF_ProjectActivity')->getOne(array('filter' => $sql->gen(), 'order' => 'date desc'));
if ($prj->current_activity != $latest->id) {
$prj->current_activity = $latest;
$prj->update();
}
}
}
src/IDF/Views.php
3232
3333
3434
35
36
37
38
39
40
41
42
43
44
3545
3646
3747
3848
3949
40
50
4151
4252
4353
4454
4555
46
56
4757
4858
4959
......
334344
335345
336346
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
347
354348
355
356
357
358
359
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
360372
361
373
362374
363
364
375
376
377
378
379
380
365381
366382
367383
class IDF_Views
{
/**
* The index view.
*/
public function index($request, $match)
{
// TODO: add a switch here later on to determine whether the project list
// or a custom start page should be displayed
return $this->listProjects($request, $match);
}
/**
* List all the projects managed by InDefero.
*
* Only the public projects are listed or the private with correct
* rights.
*/
public function index($request, $match, $api=false)
public function listProjects($request, $match, $api=false)
{
$projects = self::getProjects($request->user);
$stats = self::getProjectsStatistics($projects);
if ($api == true) return $projects;
return Pluf_Shortcuts_RenderToResponse('idf/index.html',
return Pluf_Shortcuts_RenderToResponse('idf/listProjects.html',
array('page_title' => __('Projects'),
'projects' => $projects,
'stats' => new Pluf_Template_ContextVars($stats)),
{
$db =& Pluf::db();
$false = Pluf_DB_BooleanToDb(false, $db);
if ($user->isAnonymous()) {
$sql = sprintf('%s=%s', $db->qn('private'), $false);
return Pluf::factory('IDF_Project')->getList(array('filter'=> $sql,
'order' => 'name ASC'));
}
if ($user->administrator) {
return Pluf::factory('IDF_Project')->getList(array('order' => 'name ASC'));
}
// grab the list of projects where the user is admin, member
// or authorized
$perms = array(
Pluf_Permission::getFromString('IDF.project-member'),
Pluf_Permission::getFromString('IDF.project-owner'),
Pluf_Permission::getFromString('IDF.project-authorized-user')
);
$sql = new Pluf_SQL("model_class='IDF_Project' AND owner_class='Pluf_User' AND owner_id=%s AND negative=".$false, $user->id);
$rows = Pluf::factory('Pluf_RowPermission')->getList(array('filter' => $sql->gen()));
$sql = new Pluf_SQL(1);
$sql = sprintf('%s=%s', $db->qn('private'), $false);
if ($rows->count() > 0) {
$ids = array();
foreach ($rows as $row) {
$ids[] = $row->model_id;
if ($user->isAnonymous())
{
$authSql = new Pluf_SQL('private=%s', $false);
$sql->SAnd($authSql);
} else
if (!$user->administrator) {
// grab the list of projects where the user is admin,
// member or authorized
$perms = array(
Pluf_Permission::getFromString('IDF.project-member'),
Pluf_Permission::getFromString('IDF.project-owner'),
Pluf_Permission::getFromString('IDF.project-authorized-user')
);
$permSql = new Pluf_SQL("model_class='IDF_Project' AND owner_class='Pluf_User' AND owner_id=%s AND negative=".$false, $user->id);
$rows = Pluf::factory('Pluf_RowPermission')->getList(array('filter' => $permSql->gen()));
$authSql = new Pluf_SQL('private=%s', $false);
if ($rows->count() > 0) {
$ids = array();
foreach ($rows as $row) {
$ids[] = $row->model_id;
}
$authSql->SOr(new Pluf_SQL(sprintf('id IN (%s)', implode(', ', $ids))));
}
$sql .= sprintf(' OR id IN (%s)', implode(', ', $ids));
$sql->SAnd($authSql);
}
return Pluf::factory('IDF_Project')->getList(array('filter' => $sql,
'order' => 'name ASC'));
return Pluf::factory('IDF_Project')->getList(array(
'filter'=> $sql->gen(),
'view' => 'join_activities',
'order' => 'name ASC'
));
}
/**
src/IDF/Views/Api.php
2929
3030
3131
32
32
3333
3434
3535
......
9090
9191
9292
93
93
9494
9595
96
97
98
96
97
9998
10099
101100
102101
103
102
104103
105104
106105
* JSON instead of HTML.
*
* A special precondition is used to set the $request->user from the
* _login, _hash and _salt parameters.
* _login, _hash and _salt parameters.
*/
class IDF_Views_Api
{
* List all the projects
*/
public $projectIndex_precond = array('IDF_Precondition::apiSetUser');
public function projectIndex($request, $match)
{
$view = new IDF_Views();
$projects = $view->index($request, $match, true);
$projects = IDF_Views::getProjects($request->user);
$data = array();
foreach ($projects as $p) {
$data[] = array("shortname" => $p->shortname, "name" => $p->name, "shortdesc" => $p->shortdesc, "private" => $p->private);
}
$out = array();
$out['message'] = 'success';
$out['projects'] = $data;
src/IDF/conf/urls.php
2929
3030
3131
32
33
34
35
36
3237
3338
3439
'model' => 'IDF_Views',
'method' => 'index');
$ctl[] = array('regex' => '#^/label/(\d+)/$#',
'base' => $base,
'model' => 'IDF_Views',
'method' => 'listProjects');
$ctl[] = array('regex' => '#^/login/$#',
'base' => $base,
'model' => 'IDF_Views',
src/IDF/templates/idf/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{extends "idf/base-simple.html"}
{block docclass}yui-t2{/block}
{block tabhome} class="active"{/block}
{block subtabs}<a href="{url 'IDF_Views::index'}" class="active">{trans 'Projects'}</a>{/block}
{block body}
{if $projects.count() == 0}
<p>{trans 'No projects managed with InDefero were found.'}</p>
{if $isAdmin}
{aurl 'url', 'IDF_Views_Admin::projectCreate'}
<p><a href="{$url}"><img style="vertical-align: text-bottom;" src="{media '/idf/img/add.png'}" alt="+" align="bottom" /></a> <a href="{$url}">{trans 'Create Project'}</a></p>{/if}
{else}
{foreach $projects as $p}
<div class="p-list-img">
<a href="{url 'IDF_Views_Project::home', array($p.shortname)}">
<img src="{url 'IDF_Views_Project::logo', array($p.shortname)}" alt="{trans 'Project logo'}" />
</a>
{if $p.private}
<div class="p-list-private">
<a href="{url 'IDF_Views_Project::home', array($p.shortname)}">
<img style="float:right" src="{media '/idf/img/lock.png'}" alt="{trans 'Private project'}" />
</a>
</div>
{/if}
</div>
<div class="p-list-prj">
<p>
<a href="{url 'IDF_Views_Project::home', array($p.shortname)}"><strong>{$p}</strong></a>
{assign $url = $p.external_project_url}
{if $url != ''}
<a href="{$url}" target="_blank" class="external-link" title="{trans 'External link to project'}" />&nbsp;</a>
{/if}
{if $p.private} - {trans 'Private project'}{/if}
</p>
<p>{$p.shortdesc}</p>
</div>
<div style="clear: both"></div>
{/foreach}
{/if}
{/block}
{block context}
<div id="stats" class="issue-submit-info">
<h3 class="a-c">{trans 'Forge statistics'}</h3>
<table>
<tr><td class="right">{trans 'Projects:'}</td><td>{$stats.projects}</td></tr>
<tr><td class="right">{trans 'Members:'}</td><td>{$stats.members}</td></tr>
<tr><td class="right">{trans 'Issues:'}</td><td>{$stats.issues}</td></tr>
<tr><td class="right">{trans 'Commits:'}</td><td>{$stats.commits}</td></tr>
<tr><td class="right">{trans 'Documentations:'}</td><td>{$stats.docpages}</td></tr>
<tr><td class="right">{trans 'Downloads:'}</td><td>{$stats.downloads}</td></tr>
<tr><td class="right">{trans 'Code reviews:'}</td><td>{$stats.reviews}</td></tr>
</table>
</div>
{/block}
{block foot}<div id="branding">Powered by <a href="http://www.indefero.net" title="InDefero, bug tracking and more">InDefero</a>,<br />a <a href="http://www.ceondo.com">Céondo Ltd</a> initiative.</div>{/block}
src/IDF/templates/idf/listProjects.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{extends "idf/base-simple.html"}
{block docclass}yui-t2{/block}
{block tabhome} class="active"{/block}
{block subtabs}<a href="{url 'IDF_Views::index'}" class="active">{trans 'Projects'}</a>{/block}
{block body}
{if $projects.count() == 0}
<p>{trans 'No projects managed with InDefero were found.'}</p>
{if $isAdmin}
{aurl 'url', 'IDF_Views_Admin::projectCreate'}
<p><a href="{$url}"><img style="vertical-align: text-bottom;" src="{media '/idf/img/add.png'}" alt="+" align="bottom" /></a> <a href="{$url}">{trans 'Create Project'}</a></p>{/if}
{else}
{foreach $projects as $p}
<div class="p-list-prj">
<div class="logo">
<a href="{url 'IDF_Views_Project::home', array($p.shortname)}">
<img src="{url 'IDF_Views_Project::logo', array($p.shortname)}" alt="{trans 'Project logo'}" />
</a>
{if $p.private}
<div class="private">
<a href="{url 'IDF_Views_Project::home', array($p.shortname)}">
<img style="float:right" src="{media '/idf/img/lock.png'}" alt="{trans 'Private project'}" />
</a>
</div>
{/if}
{if $p.current_activity_value}
<div class="activity" title="{trans 'Project activity'}"><div class="bar" style="width: {$p.current_activity_value * 100}%"></div></div>
{/if}
</div>
<p>
<a href="{url 'IDF_Views_Project::home', array($p.shortname)}"><strong>{$p}</strong></a>
{assign $url = $p.external_project_url}
{if $url != ''}
<a href="{$url}" target="_blank" class="external-link" title="{trans 'External link to project'}" />&nbsp;</a>
{/if}
{if $p.private} - <span class="smaller">{trans 'Private project'}</span>{/if}
</p>
<p class="smaller">{$p.shortdesc}</p>
<p class="smaller">{trans 'Labels:'}
{assign $tags = $p.get_tags_list()}
{if count($tags) == 0}{trans 'n/a'}{else}
{foreach $p.get_tags_list() as $idx => $tag}
{if $idx != 0}, {/if}
<a class="label" href="{url 'IDF_Views::listProjects', array($tag->id)}">{$tag}</a>
{/foreach}
{/if}
</p>
</div>
{/foreach}
{/if}
{/block}
{block context}
<div id="stats" class="issue-submit-info">
<h3 class="a-c">{trans 'Forge statistics'}</h3>
<table>
<tr><td class="right">{trans 'Projects:'}</td><td>{$stats.projects}</td></tr>
<tr><td class="right">{trans 'Members:'}</td><td>{$stats.members}</td></tr>
<tr><td class="right">{trans 'Issues:'}</td><td>{$stats.issues}</td></tr>
<tr><td class="right">{trans 'Commits:'}</td><td>{$stats.commits}</td></tr>
<tr><td class="right">{trans 'Documentations:'}</td><td>{$stats.docpages}</td></tr>
<tr><td class="right">{trans 'Downloads:'}</td><td>{$stats.downloads}</td></tr>
<tr><td class="right">{trans 'Code reviews:'}</td><td>{$stats.reviews}</td></tr>
</table>
</div>
{/block}
{block foot}<div id="branding">Powered by <a href="http://www.indefero.net" title="InDefero, bug tracking and more">InDefero</a>,<br />a <a href="http://www.ceondo.com">Céondo Ltd</a> initiative.</div>{/block}
www/media/idf/css/style.css
12141214
12151215
12161216
1217
1217
12181218
1219
1219
1220
1221
12201222
1221
1222
1223
12231224
12241225
1225
1226
12261227
1227
1228
1229
1230
12281231
12291232
1230
1231
1233
1234
1235
12321236
12331237
1234
1235
1238
1239
12361240
1237
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
12381269
12391270
12401271
}
/*
* Project list on index
* Project list
*/
div.p-list-img {
div.p-list-prj {
width: 24em;
min-height: 5em;
float: left;
height: 32px;
margin-top: .5em;
margin: 0 1em 0.5em 0;
}
div.p-list-prj {
div.p-list-prj div.logo {
float: left;
margin: .5em 0 .5em .8em;
width: 32px;
height: 32px;
position: relative;
}
div.p-list-prj p {
margin: 0px;
div.p-list-prj div.logo img {
max-width: 32px;
max-height: 32px;
}
div.p-list-private {
bottom: 16px;
div.p-list-prj div.logo .private {
top: 18px;
right: -3px;
position: relative;
position: absolute;
}
div.p-list-prj div.logo .activity {
height: 4px;
width: 32px;
margin-top: 5px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
background: #E6E6E6;
}
div.p-list-prj div.logo .activity .bar {
background: #A5E26A;
height: 100%;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
div.p-list-prj p {
margin: 0;
margin-left: 42px;
}
div.p-list-prj .smaller {
font-size: 85%;
}
a.external-link {

Archive Download the corresponding diff file

Page rendered in 0.11238s using 13 queries.