Merge branch 'watchlist' into develop
This commit is contained in:
		@@ -78,6 +78,158 @@ class IDF_Views_Issue
 | 
			
		||||
                                               $params, $request);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * View the issues watch list of a given user.
 | 
			
		||||
     * Limited to a specified project
 | 
			
		||||
     */
 | 
			
		||||
    public $watchList_precond = array('IDF_Precondition::accessIssues',
 | 
			
		||||
                                      'Pluf_Precondition::loginRequired');
 | 
			
		||||
    public function watchList($request, $match)
 | 
			
		||||
    {
 | 
			
		||||
        $prj = $request->project;
 | 
			
		||||
        $otags = $prj->getTagIdsByStatus('open');
 | 
			
		||||
        $ctags = $prj->getTagIdsByStatus('closed');
 | 
			
		||||
        if (count($otags) == 0) $otags[] = 0;
 | 
			
		||||
        if (count($ctags) == 0) $ctags[] = 0;
 | 
			
		||||
        
 | 
			
		||||
        // Get the id list of issue in the user watch list (for all projects !)
 | 
			
		||||
        $db =& Pluf::db();
 | 
			
		||||
        $issues_id = $db->select('SELECT GROUP_CONCAT(idf_issue_id) as id FROM '.Pluf::f('db_table_prefix', '').'idf_issue_pluf_user_assoc WHERE pluf_user_id='.$request->user->id.' GROUP BY pluf_user_id');
 | 
			
		||||
        if (empty ($issues_id)) $issues_id = "";
 | 
			
		||||
        else                    $issues_id = $issues_id[0]['id'];
 | 
			
		||||
        
 | 
			
		||||
        // Count open and close issues
 | 
			
		||||
        $sql = new Pluf_SQL('project=%s AND id IN ('.$issues_id.') AND status IN ('.implode(', ', $otags).')', array($prj->id));
 | 
			
		||||
        $nb_open = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen()));
 | 
			
		||||
        $sql = new Pluf_SQL('project=%s AND id IN ('.$issues_id.') AND status IN ('.implode(', ', $ctags).')', array($prj->id));
 | 
			
		||||
        $nb_closed = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen()));
 | 
			
		||||
        
 | 
			
		||||
        // Generate a filter for the paginator
 | 
			
		||||
        switch ($match[2]) {
 | 
			
		||||
        case 'closed':
 | 
			
		||||
            $title = sprintf(__('Watch List: Closed Issues for %s'), (string) $prj);
 | 
			
		||||
            $summary = __('This table shows the closed issues in your watch list for %s project.', (string) $prj);
 | 
			
		||||
            $f_sql = new Pluf_SQL('project=%s AND id IN ('.$issues_id.') AND status IN ('.implode(', ', $ctags).')', array($prj->id));   
 | 
			
		||||
            break; 
 | 
			
		||||
        case 'open':
 | 
			
		||||
        default:
 | 
			
		||||
            $title = sprintf(__('Watch List: Open Issues for %s'), (string) $prj);
 | 
			
		||||
            $summary = __('This table shows the open issues in your watch list for %s project.', (string) $prj);
 | 
			
		||||
            $f_sql = new Pluf_SQL('project=%s AND id IN ('.$issues_id.') AND status IN ('.implode(', ', $otags).')', array($prj->id));
 | 
			
		||||
            break;  
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Paginator to paginate the issues
 | 
			
		||||
        $pag = new Pluf_Paginator(new IDF_Issue());
 | 
			
		||||
        $pag->class = 'recent-issues';
 | 
			
		||||
        $pag->item_extra_props = array('project_m' => $prj,
 | 
			
		||||
                                       'shortname' => $prj->shortname,
 | 
			
		||||
                                       'current_user' => $request->user);
 | 
			
		||||
        $pag->summary = $summary;
 | 
			
		||||
        $pag->forced_where = $f_sql;
 | 
			
		||||
        $pag->action = array('IDF_Views_Issue::watchList', array($prj->shortname, $match[1]));
 | 
			
		||||
        $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted
 | 
			
		||||
        $pag->sort_reverse_order = array('modif_dtime');
 | 
			
		||||
        $pag->sort_link_title = true;
 | 
			
		||||
        $pag->extra_classes = array('a-c', '', 'a-c', '');
 | 
			
		||||
        $list_display = array(
 | 
			
		||||
             'id' => __('Id'),
 | 
			
		||||
             array('summary', 'IDF_Views_Issue_SummaryAndLabels', __('Summary')),
 | 
			
		||||
             array('status', 'IDF_Views_Issue_ShowStatus', __('Status')),
 | 
			
		||||
             array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')),
 | 
			
		||||
                              );
 | 
			
		||||
        $pag->configure($list_display, array(), array('id', 'status', 'modif_dtime'));
 | 
			
		||||
        $pag->items_per_page = 10;
 | 
			
		||||
        $pag->no_results_text = __('No issues were found.');
 | 
			
		||||
        $pag->setFromRequest($request);
 | 
			
		||||
        return Pluf_Shortcuts_RenderToResponse('idf/issues/project-watchlist.html',
 | 
			
		||||
                                               array('project' => $prj,
 | 
			
		||||
                                                     'page_title' => $title,
 | 
			
		||||
                                                     'open' => $nb_open,
 | 
			
		||||
                                                     'closed' => $nb_closed,
 | 
			
		||||
                                                     'issues' => $pag,
 | 
			
		||||
                                                     ),
 | 
			
		||||
                                               $request);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * View the issues watch list of a given user.
 | 
			
		||||
     * For all projects
 | 
			
		||||
     */
 | 
			
		||||
    public $forgeWatchList_precond = array('Pluf_Precondition::loginRequired');
 | 
			
		||||
    public function forgeWatchList($request, $match)
 | 
			
		||||
    {
 | 
			
		||||
        $otags = array();
 | 
			
		||||
        $ctags = array();
 | 
			
		||||
        // Note that this approach does not scale, we will need to add
 | 
			
		||||
        // a table to cache the meaning of the tags for large forges.
 | 
			
		||||
        foreach (IDF_Views::getProjects($request->user) as $project) {
 | 
			
		||||
            $otags = array_merge($otags, $project->getTagIdsByStatus('open'));
 | 
			
		||||
        }
 | 
			
		||||
        foreach (IDF_Views::getProjects($request->user) as $project) {
 | 
			
		||||
            $ctags = array_merge($ctags, $project->getTagIdsByStatus('closed'));
 | 
			
		||||
        }       
 | 
			
		||||
        if (count($otags) == 0) $otags[] = 0;
 | 
			
		||||
        if (count($ctags) == 0) $ctags[] = 0;
 | 
			
		||||
    
 | 
			
		||||
         // Get the id list of issue in the user watch list (for all projects !)
 | 
			
		||||
        $db =& Pluf::db();
 | 
			
		||||
        $issues_id = $db->select('SELECT GROUP_CONCAT(idf_issue_id) as id FROM '.Pluf::f('db_table_prefix', '').'idf_issue_pluf_user_assoc WHERE pluf_user_id='.$request->user->id.' GROUP BY pluf_user_id');
 | 
			
		||||
        if (empty ($issues_id)) $issues_id = "";
 | 
			
		||||
        else                    $issues_id = $issues_id[0]['id'];   
 | 
			
		||||
 | 
			
		||||
        // Count open and close issues
 | 
			
		||||
        $sql = new Pluf_SQL('id IN ('.$issues_id.') AND status IN ('.implode(', ', $otags).')', array());
 | 
			
		||||
        $nb_open = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen()));
 | 
			
		||||
        $sql = new Pluf_SQL('id IN ('.$issues_id.') AND status IN ('.implode(', ', $ctags).')', array());
 | 
			
		||||
        $nb_closed = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen()));
 | 
			
		||||
 | 
			
		||||
        // Generate a filter for the paginator
 | 
			
		||||
        switch ($match[1]) {
 | 
			
		||||
        case 'closed':
 | 
			
		||||
            $title = sprintf(__('Watch List: Closed Issues'));
 | 
			
		||||
            $summary = __('This table shows the closed issues in your watch list.');
 | 
			
		||||
            $f_sql = new Pluf_SQL('id IN ('.$issues_id.') AND status IN ('.implode(', ', $ctags).')', array());   
 | 
			
		||||
            break; 
 | 
			
		||||
        case 'open':
 | 
			
		||||
        default:
 | 
			
		||||
            $title = sprintf(__('Watch List: Open Issues'));
 | 
			
		||||
            $summary = __('This table shows the open issues in your watch list.');
 | 
			
		||||
            $f_sql = new Pluf_SQL('id IN ('.$issues_id.') AND status IN ('.implode(', ', $otags).')', array());
 | 
			
		||||
            break;  
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Paginator to paginate the issues
 | 
			
		||||
        $pag = new Pluf_Paginator(new IDF_Issue());
 | 
			
		||||
        $pag->class = 'recent-issues';
 | 
			
		||||
        $pag->item_extra_props = array('current_user' => $request->user);
 | 
			
		||||
        $pag->summary = $summary;
 | 
			
		||||
        $pag->forced_where = $f_sql;
 | 
			
		||||
        $pag->action = array('IDF_Views_Issue::forgeWatchList', array($match[1]));
 | 
			
		||||
        $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted
 | 
			
		||||
        $pag->sort_reverse_order = array('modif_dtime');
 | 
			
		||||
        $pag->sort_link_title = true;
 | 
			
		||||
        $pag->extra_classes = array('a-c', '', 'a-c', '');
 | 
			
		||||
        $list_display = array(
 | 
			
		||||
             'id' => __('Id'),
 | 
			
		||||
             array('summary', 'IDF_Views_Issue_SummaryAndLabelsUnknownProject', __('Summary')),
 | 
			
		||||
             array('project', 'Pluf_Paginator_FkToString', __('Project')),
 | 
			
		||||
             array('status', 'IDF_Views_Issue_ShowStatus', __('Status')),
 | 
			
		||||
             array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')),
 | 
			
		||||
                              );
 | 
			
		||||
        $pag->configure($list_display, array(), array('id', 'project', 'status', 'modif_dtime'));
 | 
			
		||||
        $pag->items_per_page = 10;
 | 
			
		||||
        $pag->no_results_text = __('No issues were found.');
 | 
			
		||||
        $pag->setFromRequest($request);
 | 
			
		||||
        return Pluf_Shortcuts_RenderToResponse('idf/issues/forge-watchlist.html',
 | 
			
		||||
                                               array('page_title' => $title,
 | 
			
		||||
                                                     'open' => $nb_open,
 | 
			
		||||
                                                     'closed' => $nb_closed,
 | 
			
		||||
                                                     'issues' => $pag,
 | 
			
		||||
                                                     ),
 | 
			
		||||
                                               $request);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * View the issues of a given user.
 | 
			
		||||
     *
 | 
			
		||||
@@ -540,6 +692,17 @@ class IDF_Views_Issue
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * When you access to your forge watch list, issue don't known
 | 
			
		||||
 * the project shortname.
 | 
			
		||||
 */
 | 
			
		||||
function IDF_Views_Issue_SummaryAndLabelsUnknownProject($field, $issue, $extra='')
 | 
			
		||||
{
 | 
			
		||||
    $shortname = $issue->get_project()->shortname;
 | 
			
		||||
    $issue->__set('shortname', $shortname);
 | 
			
		||||
    return IDF_Views_Issue_SummaryAndLabels ($field, $issue, $extra);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Display the summary of an issue, then on a new line, display the
 | 
			
		||||
 * list of labels with a link to a view "by label only".
 | 
			
		||||
@@ -576,3 +739,5 @@ function IDF_Views_Issue_ShowStatus($field, $issue, $extra='')
 | 
			
		||||
{
 | 
			
		||||
    return Pluf_esc($issue->get_status()->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -141,6 +141,16 @@ $ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/view/attachment/(\d+)/(.*)$#',
 | 
			
		||||
               'model' => 'IDF_Views_Issue',
 | 
			
		||||
               'method' => 'viewAttachment');
 | 
			
		||||
 | 
			
		||||
$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/watchlist/(\w+)$#',
 | 
			
		||||
               'base' => $base,
 | 
			
		||||
               'model' => 'IDF_Views_Issue',
 | 
			
		||||
               'method' => 'watchList');
 | 
			
		||||
               
 | 
			
		||||
$ctl[] = array('regex' => '#^/watchlist/(\w+)$#',
 | 
			
		||||
               'base' => $base,
 | 
			
		||||
               'model' => 'IDF_Views_Issue',
 | 
			
		||||
               'method' => 'forgeWatchList');
 | 
			
		||||
         
 | 
			
		||||
// ---------- SCM ----------------------------------------
 | 
			
		||||
 | 
			
		||||
$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/help/$#',
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,8 @@
 | 
			
		||||
{block subtabs}
 | 
			
		||||
<div id="sub-tabs">
 | 
			
		||||
<a {if $inOpenIssues}class="active" {/if}href="{url 'IDF_Views_Issue::index', array($project.shortname)}">{trans 'Open Issues'}</a>
 | 
			
		||||
{if !$user.isAnonymous()} | <a {if $inCreate}class="active" {/if}href="{url 'IDF_Views_Issue::create', array($project.shortname)}">{trans 'New Issue'}</a> | <a {if $inMyIssues}class="active" {/if}href="{url 'IDF_Views_Issue::myIssues', array($project.shortname, 'submit')}">{trans 'My Issues'}</a>{/if} |
 | 
			
		||||
{if !$user.isAnonymous()} | <a {if $inCreate}class="active" {/if}href="{url 'IDF_Views_Issue::create', array($project.shortname)}">{trans 'New Issue'}</a> | <a {if $inMyIssues}class="active" {/if}href="{url 'IDF_Views_Issue::myIssues', array($project.shortname, 'submit')}">{trans 'My Issues'}</a>
 | 
			
		||||
| <a {if $inWatchList}class="active" {/if}href="{url 'IDF_Views_Issue::watchList', array($project.shortname, 'open')}">{trans 'My watch list'}</a>{/if} |
 | 
			
		||||
<form class="star" action="{url 'IDF_Views_Issue::search', array($project.shortname)}" method="get">
 | 
			
		||||
<input accesskey="4" type="text" value="{$q}" name="q" size="20" />
 | 
			
		||||
<input type="submit" name="s" value="{trans 'Search'}" />
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								src/IDF/templates/idf/issues/forge-watchlist.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/IDF/templates/idf/issues/forge-watchlist.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
{extends "idf/base-simple.html"}
 | 
			
		||||
 | 
			
		||||
{block body}
 | 
			
		||||
{$issues.render}
 | 
			
		||||
{/block}
 | 
			
		||||
 | 
			
		||||
{block context}
 | 
			
		||||
{aurl 'open_url', 'IDF_Views_Issue::forgeWatchList', array('open')}
 | 
			
		||||
{aurl 'closed_url', 'IDF_Views_Issue::forgeWatchList', array('closed')}
 | 
			
		||||
{blocktrans}<p><strong>Open issues:</strong> <a href="{$open_url}">{$open}</a></p>
 | 
			
		||||
<p><strong>Closed issues:</strong> <a href="{$closed_url}">{$closed}</a></p>{/blocktrans}
 | 
			
		||||
{/block}
 | 
			
		||||
							
								
								
									
										17
									
								
								src/IDF/templates/idf/issues/project-watchlist.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/IDF/templates/idf/issues/project-watchlist.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
{extends "idf/issues/base.html"}
 | 
			
		||||
 | 
			
		||||
{block docclass}yui-t2{assign $inWatchList = true}{/block}
 | 
			
		||||
 | 
			
		||||
{block body}
 | 
			
		||||
{$issues.render}
 | 
			
		||||
{if !$user.isAnonymous()}
 | 
			
		||||
{aurl 'url', 'IDF_Views_Issue::create', array($project.shortname)}
 | 
			
		||||
<p><a href="{$url}"><img style="vertical-align: text-bottom;" src="{media '/idf/img/add.png'}" alt="+" align="bottom" /></a> <a href="{$url}">{trans 'New Issue'}</a></p>{/if}
 | 
			
		||||
{/block}
 | 
			
		||||
 | 
			
		||||
{block context}
 | 
			
		||||
{aurl 'open_url', 'IDF_Views_Issue::watchList', array($project.shortname, 'open')}
 | 
			
		||||
{aurl 'closed_url', 'IDF_Views_Issue::watchList', array($project.shortname, 'closed')}
 | 
			
		||||
{blocktrans}<p><strong>Open issues:</strong> <a href="{$open_url}">{$open}</a></p>
 | 
			
		||||
<p><strong>Closed issues:</strong> <a href="{$closed_url}">{$closed}</a></p>{/blocktrans}
 | 
			
		||||
{/block}
 | 
			
		||||
@@ -11,5 +11,7 @@
 | 
			
		||||
<p>{blocktrans}<a href="{$url}">Update your account</a>.{/blocktrans}</p>
 | 
			
		||||
{aurl 'url', 'IDF_Views_User::view', array($user.login)}
 | 
			
		||||
<p>{blocktrans}<a href="{$url}">See your public profile</a>.{/blocktrans}</p>
 | 
			
		||||
{aurl 'url', 'IDF_Views_Issue::forgeWatchList', array('open')}
 | 
			
		||||
<p>{blocktrans}<a href="{$url}">See your forge issue watch list</a>.{/blocktrans}</p>
 | 
			
		||||
{/block}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user