diff --git a/NEWS.mdtext b/NEWS.mdtext index 5f52c3c..3b2b1c4 100644 --- a/NEWS.mdtext +++ b/NEWS.mdtext @@ -7,12 +7,19 @@ or newer to properly run this version of Indefero! - Indefero's issue tracker can now bi-directionally link issues with variable, configurable terms, such as "is related to", "is blocked by" or "is duplicated by" (issue 638) +- When you search for issues, the results can further be refined by issue state (open or closed) + and label (partially implements issue 548) - Mercurial source views now show parent revisions (if any) and detailed change information - Subversion source views now show detailed change information (issue 622) - File download URLs now contain the file name rather than the upload id; old links still work though (issues 559 and 686) - Display monotone file and directory attributes in the tree and file view (needs a monotone with an interface version of 13.1 or newer) - The context area is now kept in view when a page scrolls down several pages +- Add a summary section to the issue tracker with statistics about open/close issues, + tags of open issue, and count of open tickets for each owner. +- Improved home page with an customizable icon for each project. +- The download section provide MD5 for each files. +- Wiki page have now a css for printer output (issue 713) ## Bugfixes @@ -41,6 +48,8 @@ or newer to properly run this version of Indefero! - Indefero no longer displays an empty parents paragraph in the commit view for root revisions of a git repository - Indefero now only shows the tags of the closed and not the open issues in the closed issues list +- Avatar URL generation use correctly the configuration (issue 732) +- Git cron job doesn't erase anymore manually added keys (issue 247) ## Documentation diff --git a/src/IDF/Project.php b/src/IDF/Project.php index 66a070e..f23b34b 100644 --- a/src/IDF/Project.php +++ b/src/IDF/Project.php @@ -132,7 +132,7 @@ class IDF_Project extends Pluf_Model } return $projects[0]; } - + /** * Returns the number of open/closed issues. * @@ -167,7 +167,7 @@ GROUP BY uid"; $key = ($v['id'] === '-1') ? null : $v['id']; $ownerStatistics[$key] = (int)$v['nb']; } - + arsort($ownerStatistics); return $ownerStatistics; @@ -178,9 +178,10 @@ GROUP BY uid"; * * @param string Status ('open'), 'closed' * @param IDF_Tag Subfilter with a label (null) + * @param array Restrict further to a list of ids * @return int Count */ - public function getIssueCountByStatus($status='open', $label=null) + public function getIssueCountByStatus($status='open', $label=null, $ids=array()) { switch ($status) { case 'open': @@ -203,12 +204,48 @@ GROUP BY uid"; $sql2 = new Pluf_SQL('idf_tag_id=%s', array($label->id)); $sql->SAnd($sql2); } + if (count($ids) > 0) { + $sql2 = new Pluf_SQL(sprintf('id IN (%s)', implode(', ', $ids))); + $sql->SAnd($sql2); + } $params = array('filter' => $sql->gen()); if (!is_null($label)) { $params['view'] = 'join_tags'; } $gissue = new IDF_Issue(); return $gissue->getCount($params); } + /** + * Get the tags for a specific list of issues. + * + * @param string Status ('open') or 'closed' + * @param array A list of issue ids + * @return array An array of tag objects + */ + public function getTagsByIssues($issue_ids=array()) + { + // make the below query always a valid one + if (count($issue_ids) == 0) $issue_ids[] = 0; + + $assocTable = $this->_con->pfx.'idf_issue_idf_tag_assoc'; + $query = sprintf( + 'SELECT DISTINCT idf_tag_id FROM %s '. + 'WHERE idf_issue_id IN (%s) '. + 'GROUP BY idf_tag_id', + $assocTable, implode(',', $issue_ids) + ); + + $db = Pluf::db(); + $dbData = $db->select($query); + $ids = array(0); + foreach ($dbData as $data) { + $ids[] = $data['idf_tag_id']; + } + + $sql = new Pluf_SQL(sprintf('id IN (%s)', implode(', ', $ids))); + $model = new IDF_Tag(); + return $model->getList(array('filter' => $sql->gen())); + } + /** * Get the open/closed tag ids as they are often used when doing * listings. @@ -415,7 +452,11 @@ GROUP BY uid"; foreach ($this->_con->select($sql) as $idc) { $tag = new IDF_Tag($idc['id']); $tag->nb_use = $idc['nb_use']; - $tags[] = $tag; + // group by class + if (!array_key_exists($tag->class, $tags)) { + $tags[$tag->class] = array(); + } + $tags[$tag->class][] = $tag; } return new Pluf_Template_ContextVars($tags); } diff --git a/src/IDF/Views/Download.php b/src/IDF/Views/Download.php index 97e0ad4..5fb49e8 100644 --- a/src/IDF/Views/Download.php +++ b/src/IDF/Views/Download.php @@ -319,13 +319,11 @@ class IDF_Views_Download $pag->no_results_text = __('No downloads were found.'); $pag->sort_order = array('creation_dtime', 'DESC'); $pag->setFromRequest($request); - $tags = $prj->getTagCloud('downloads'); return Pluf_Shortcuts_RenderToResponse('idf/downloads/index.html', array( 'page_title' => $title, 'label' => $tag, 'downloads' => $pag, - 'tags' => $tags, 'dlabel' => $dtag, ), $request); diff --git a/src/IDF/Views/Issue.php b/src/IDF/Views/Issue.php index 953557c..083bd62 100644 --- a/src/IDF/Views/Issue.php +++ b/src/IDF/Views/Issue.php @@ -111,17 +111,21 @@ class IDF_Views_Issue foreach ($owners as $user => $nb) { if ($user === '') { $key = __('Not assigned'); + $login = null; } else { $obj = Pluf::factory('Pluf_User')->getOne(array('filter'=>'id='.$user)); $key = $obj->first_name . ' ' . $obj->last_name; + $login = $obj->login; } - $ownerStatistics[$key] = array($nb, (int)(100 * $nb / $opened)); + $ownerStatistics[$key] = array($nb, (int)(100 * $nb / $opened), $login); } // Issue class tag statistics - $tags = $prj->getTagCloud(); - foreach ($tags as $t) { - $tagStatistics[$t->class][$t->name] = array($t->nb_use, $t->id); + $grouped_tags = $prj->getTagCloud(); + foreach ($grouped_tags as $class => $tags) { + foreach ($tags as $tag) { + $tagStatistics[$class][$tag->name] = array($tag->nb_use, $tag->id); + } } foreach($tagStatistics as $k => $v) { $nbIssueInClass = 0; @@ -315,42 +319,55 @@ class IDF_Views_Issue * * Only open issues are shown. */ - public $myIssues_precond = array('IDF_Precondition::accessIssues', - 'Pluf_Precondition::loginRequired'); - public function myIssues($request, $match) + public $userIssues_precond = array('IDF_Precondition::accessIssues'); + public function userIssues($request, $match) { $prj = $request->project; + + $sql = new Pluf_SQL('login=%s', array($match[2])); + $user = Pluf::factory('Pluf_User')->getOne(array('filter' => $sql->gen())); + if ($user === null) { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::index', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + $otags = $prj->getTagIdsByStatus('open'); $ctags = $prj->getTagIdsByStatus('closed'); if (count($otags) == 0) $otags[] = 0; if (count($ctags) == 0) $ctags[] = 0; - switch ($match[2]) { + switch ($match[3]) { case 'submit': - $title = sprintf(__('My Submitted %s Issues'), (string) $prj); - $f_sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $request->user->id)); + $titleFormat = __('%s %s Submitted %s Issues'); + $f_sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $user->id)); break; case 'submitclosed': - $title = sprintf(__('My Closed Submitted %s Issues'), (string) $prj); - $f_sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $request->user->id)); + $titleFormat = __('%s %s Closed Submitted %s Issues'); + $f_sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $user->id)); break; case 'ownerclosed': - $title = sprintf(__('My Closed Working %s Issues'), (string) $prj); - $f_sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $request->user->id)); + $titleFormat = __('%s %s Closed Working %s Issues'); + $f_sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $user->id)); break; default: - $title = sprintf(__('My Working %s Issues'), (string) $prj); - $f_sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $request->user->id)); + $titleFormat = __('%s %s Working %s Issues'); + $f_sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $user->id)); break; } + $title = sprintf($titleFormat, + $user->first_name, + $user->last_name, + (string) $prj); + // Get stats about the issues - $sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $request->user->id)); + $sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $user->id)); $nb_submit = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); - $sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $request->user->id)); + $sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $user->id)); $nb_owner = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); // Closed issues - $sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $request->user->id)); + $sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $user->id)); $nb_submit_closed = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); - $sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $request->user->id)); + $sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $user->id)); $nb_owner_closed = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); // Paginator to paginate the issues @@ -361,7 +378,7 @@ class IDF_Views_Issue 'current_user' => $request->user); $pag->summary = __('This table shows the open issues.'); $pag->forced_where = $f_sql; - $pag->action = array('IDF_Views_Issue::myIssues', array($prj->shortname, $match[2])); + $pag->action = array('IDF_Views_Issue::userIssues', array($prj->shortname, $match[2])); $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted $pag->sort_reverse_order = array('modif_dtime'); $pag->sort_link_title = true; @@ -376,9 +393,10 @@ class IDF_Views_Issue $pag->items_per_page = 10; $pag->no_results_text = __('No issues were found.'); $pag->setFromRequest($request); - return Pluf_Shortcuts_RenderToResponse('idf/issues/my-issues.html', + return Pluf_Shortcuts_RenderToResponse('idf/issues/userIssues.html', array('project' => $prj, 'page_title' => $title, + 'login' => $user->login, 'nb_submit' => $nb_submit, 'nb_owner' => $nb_owner, 'nb_submit_closed' => $nb_submit_closed, @@ -431,45 +449,142 @@ class IDF_Views_Issue public $search_precond = array('IDF_Precondition::accessIssues'); public function search($request, $match) + { + $query = !isset($request->REQUEST['q']) ? '' : $request->REQUEST['q']; + return $this->doSearch($request, $query, 'open'); + } + + public $searchStatus_precond = array('IDF_Precondition::accessIssues'); + public function searchStatus($request, $match) + { + $query = !isset($request->REQUEST['q']) ? '' : $request->REQUEST['q']; + $status = in_array($match[2], array('open', 'closed')) ? $match[2] : 'open'; + return $this->doSearch($request, $query, $status); + } + + public $searchLabel_precond = array('IDF_Precondition::accessIssues'); + public function searchLabel($request, $match) + { + $query = !isset($request->REQUEST['q']) ? '' : $request->REQUEST['q']; + $tag_id = intval($match[2]); + $status = in_array($match[3], array('open', 'closed')) ? $match[3] : 'open'; + return $this->doSearch($request, $query, $status, $tag_id); + } + + private function doSearch($request, $query, $status, $tag_id=null) { $prj = $request->project; - if (!isset($request->REQUEST['q']) or trim($request->REQUEST['q']) == '') { - $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::index', - array($prj->shortname)); + if (trim($query) == '') { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::index', array($prj->shortname)); return new Pluf_HTTP_Response_Redirect($url); } - $q = $request->REQUEST['q']; - $title = sprintf(__('Search Issues - %s'), $q); - $issues = new Pluf_Search_ResultSet(IDF_Search::mySearch($q, $prj, 'IDF_Issue')); - if (count($issues) > 100) { - // no more than 100 results as we do not care - $issues->results = array_slice($issues->results, 0, 100); + + $tag = null; + if ($tag_id !== null) { + $tag = Pluf_Shortcuts_GetObjectOr404('IDF_Tag', $tag_id); } + + $title = sprintf(__('Search issues - %s'), $query); + if ($status === 'closed') { + $title = sprintf(__('Search closed issues - %s'), $query); + } + + // using Plufs ResultSet implementation here is inefficient, because + // it makes a SELECT for each item and does not allow for further + // filtering neither, so we just return the ids and filter by them + // and other things in the next round + $results = IDF_Search::mySearch($query, $prj, 'IDF_Issue'); + + $issue_ids = array(0); + foreach ($results as $result) { + $issue_ids[] = $result['model_id']; + } + + $otags = $prj->getTagIdsByStatus($status); + if (count($otags) == 0) $otags[] = 0; + $sql = new Pluf_SQL( + 'id IN ('.implode(',', $issue_ids).') '. + 'AND status IN ('.implode(', ', $otags).') '. + ($tag_id !== null ? 'AND idf_tag_id='.$tag_id.' ' : '') + ); + $model = new IDF_Issue(); + $issues = $model->getList(array('filter' => $sql->gen(), 'view' => 'join_tags')); + + // we unfortunately loose the original sort order, + // so we manually have to apply it here again + $sorted_issues = new ArrayObject(); + $filtered_issue_ids = array(0); + foreach ($issue_ids as $issue_id) { + foreach ($issues as $issue) { + if ($issue->id != $issue_id) + continue; + if (array_key_exists($issue_id, $sorted_issues)) + continue; + $sorted_issues[$issue_id] = $issue; + $filtered_issue_ids[] = $issue_id; + } + } + $pag = new Pluf_Paginator(); - $pag->items = $issues; $pag->class = 'recent-issues'; - $pag->item_extra_props = array('project_m' => $prj, - 'shortname' => $prj->shortname, - 'current_user' => $request->user); + $pag->items = $sorted_issues; + $pag->item_extra_props = array( + 'project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user + ); $pag->summary = __('This table shows the found issues.'); - $pag->action = array('IDF_Views_Issue::search', array($prj->shortname), array('q'=> $q)); $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); - $pag->items_per_page = 100; + $pag->configure(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')), + )); + // disable paginating + $pag->items_per_page = PHP_INT_MAX; $pag->no_results_text = __('No issues were found.'); $pag->setFromRequest($request); - $params = array('page_title' => $title, - 'issues' => $pag, - 'q' => $q, - ); - return Pluf_Shortcuts_RenderToResponse('idf/issues/search.html', $params, $request); + if ($tag_id === null) { + $pag->action = array('IDF_Views_Issue::searchStatus', + array($prj->shortname, $status), + array('q'=> $query), + ); + } else { + $pag->action = array('IDF_Views_Issue::searchLabel', + array($prj->shortname, $tag_id, $status), + array('q'=> $query), + ); + } + + // get stats about the issues + $open = $prj->getIssueCountByStatus('open', $tag, $issue_ids); + $closed = $prj->getIssueCountByStatus('closed', $tag, $issue_ids); + + // query the available tags for this search result + $all_tags = $prj->getTagsByIssues($filtered_issue_ids); + $grouped_tags = array(); + foreach ($all_tags as $atag) { + // group by class + if (!array_key_exists($atag->class, $grouped_tags)) { + $grouped_tags[$atag->class] = array(); + } + $grouped_tags[$atag->class][] = $atag; + } + + $params = array( + 'page_title' => $title, + 'issues' => $pag, + 'query' => $query, + 'status' => $status, + 'open' => $open, + 'closed' => $closed, + 'tag' => $tag, + 'all_tags' => $grouped_tags, + ); + + return Pluf_Shortcuts_RenderToResponse('idf/issues/search.html', $params, $request); } public $view_precond = array('IDF_Precondition::accessIssues'); @@ -617,6 +732,13 @@ class IDF_Views_Issue { $prj = $request->project; $status = $match[2]; + + if (mb_strtolower($status) == 'open') { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::index', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + $title = sprintf(__('%s Closed Issues'), (string) $prj); // Get stats about the issues $open = $prj->getIssueCountByStatus('open'); diff --git a/src/IDF/Views/Wiki.php b/src/IDF/Views/Wiki.php index 1104b51..6880f4c 100644 --- a/src/IDF/Views/Wiki.php +++ b/src/IDF/Views/Wiki.php @@ -152,13 +152,11 @@ class IDF_Views_Wiki $pag->items_per_page = 25; $pag->no_results_text = __('No documentation pages were found.'); $pag->setFromRequest($request); - $tags = $prj->getTagCloud('wiki'); return Pluf_Shortcuts_RenderToResponse('idf/wiki/index.html', array( 'page_title' => $title, 'label' => $tag, 'pages' => $pag, - 'tags' => $tags, 'dlabel' => $dtag, ), $request); diff --git a/src/IDF/conf/urls.php b/src/IDF/conf/urls.php index 03779c0..74bacf9 100644 --- a/src/IDF/conf/urls.php +++ b/src/IDF/conf/urls.php @@ -117,7 +117,7 @@ $ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/$#', 'base' => $base, 'model' => 'IDF_Views_Issue', 'method' => 'index'); - + $ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/summary/$#', 'base' => $base, 'model' => 'IDF_Views_Issue', @@ -128,6 +128,16 @@ $ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/search/$#', 'model' => 'IDF_Views_Issue', 'method' => 'search'); +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/search/status/(\w+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'searchStatus'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/search/label/(\d+)/(\w+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'searchLabel'); + $ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/(\d+)/$#', 'base' => $base, 'model' => 'IDF_Views_Issue', @@ -153,10 +163,10 @@ $ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/create/$#', 'model' => 'IDF_Views_Issue', 'method' => 'create'); -$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/my/(\w+)/$#', +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/(.*)/(\w+)/$#', 'base' => $base, 'model' => 'IDF_Views_Issue', - 'method' => 'myIssues'); + 'method' => 'userIssues'); $ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/attachment/(\d+)/(.*)$#', 'base' => $base, diff --git a/src/IDF/templates/idf/issues/base.html b/src/IDF/templates/idf/issues/base.html index 636d5da..5de2749 100644 --- a/src/IDF/templates/idf/issues/base.html +++ b/src/IDF/templates/idf/issues/base.html @@ -4,10 +4,10 @@
{trans 'Summary'} | {trans 'Open Issues'} -{if !$user.isAnonymous()} | {trans 'New Issue'} | {trans 'My Issues'} +{if !$user.isAnonymous()} | {trans 'New Issue'} | {trans 'My Issues'} | {trans 'My watch list'}{/if} |
- +
{if $inIssue} | diff --git a/src/IDF/templates/idf/issues/by-label.html b/src/IDF/templates/idf/issues/by-label.html index 3d57a3b..fdac576 100644 --- a/src/IDF/templates/idf/issues/by-label.html +++ b/src/IDF/templates/idf/issues/by-label.html @@ -8,16 +8,15 @@ {/block} {block context} -

{trans 'Label:'} -{aurl 'url', 'IDF_Views_Issue::listLabel', array($project.shortname, $label.id, 'open')} -{$label.class}:{$label.name}

{aurl 'open_url', 'IDF_Views_Issue::listLabel', array($project.shortname, $label.id, 'open')} {aurl 'closed_url', 'IDF_Views_Issue::listLabel', array($project.shortname, $label.id, 'closed')} {blocktrans}

Open issues: {$open}

Closed issues: {$closed}

-{/blocktrans}{if $completion} +{/blocktrans} +

{trans 'Label:'} +{aurl 'url', 'IDF_Views_Issue::listLabel', array($project.shortname, $label.id, 'open')} +{$label.class}:{$label.name}

+{if $completion}

{trans 'Completion:'} {$completion}

{/if} - - {/block} diff --git a/src/IDF/templates/idf/issues/search.html b/src/IDF/templates/idf/issues/search.html index 71388ed..4c0b720 100644 --- a/src/IDF/templates/idf/issues/search.html +++ b/src/IDF/templates/idf/issues/search.html @@ -8,5 +8,25 @@ {/block} {block context} -

{trans 'Found issues:'} {$issues.nb_items}

+{aurl 'open_url', 'IDF_Views_Issue::searchStatus', array($project.shortname, 'open'), array('q' => $query)} +{aurl 'closed_url', 'IDF_Views_Issue::searchStatus', array($project.shortname, 'closed'), array('q' => $query)} +{if $tag != null} +{aurl 'open_url', 'IDF_Views_Issue::searchLabel', array($project.shortname, $tag.id, 'open'), array('q' => $query)} +{aurl 'closed_url', 'IDF_Views_Issue::searchLabel', array($project.shortname, $tag.id, 'closed'), array('q' => $query)} +{/if} +{blocktrans} +

Found open issues: {$open}

+

Found closed issues: {$closed}

{/blocktrans} +{if $tag !== null} +{blocktrans}

Label: +{$tag.class}:{$tag.name}

{/blocktrans} +{else} +{* yes, this is duplicated from tags-cloud.html, but the code there cannot be easily overridden *} +
{foreach $all_tags as $class => $labels} +
{$class}
+{foreach $labels as $idx => $label} +{aurl 'url', 'IDF_Views_Issue::searchLabel', array($project.shortname, $label.id, $status), array('q'=> $query)} +
{$label.name}{if $idx != count($labels) - 1},{/if}
+{/foreach}{/foreach}

+{/if} {/block} diff --git a/src/IDF/templates/idf/issues/summary.html b/src/IDF/templates/idf/issues/summary.html index bfff813..7a7ccb0 100644 --- a/src/IDF/templates/idf/issues/summary.html +++ b/src/IDF/templates/idf/issues/summary.html @@ -71,7 +71,12 @@ {foreach $ownerStatistics as $key => $value} - {$key} + + {if !empty($value[2])} + {aurl 'url', 'IDF_Views_Issue::userIssues', array($project.shortname, $value[2], 'owner')} + {$key} + {else}{$key}{/if} + {$value[0]} diff --git a/src/IDF/templates/idf/issues/my-issues.html b/src/IDF/templates/idf/issues/userIssues.html similarity index 68% rename from src/IDF/templates/idf/issues/my-issues.html rename to src/IDF/templates/idf/issues/userIssues.html index f3d1d27..018a642 100644 --- a/src/IDF/templates/idf/issues/my-issues.html +++ b/src/IDF/templates/idf/issues/userIssues.html @@ -1,5 +1,5 @@ {extends "idf/issues/base.html"} -{block docclass}yui-t2{assign $inMyIssues = true}{/block} +{block docclass}yui-t2{if $user.login == $login}{assign $inMyIssues = true}{/if}{/block} {block body} {$issues.render} {if !$user.isAnonymous()} @@ -8,10 +8,10 @@ {/block} {block context} -{aurl 'owner_url', 'IDF_Views_Issue::myIssues', array($project.shortname, 'owner')} -{aurl 'submit_url', 'IDF_Views_Issue::myIssues', array($project.shortname, 'submit')} -{aurl 'owner_closed_url', 'IDF_Views_Issue::myIssues', array($project.shortname, 'ownerclosed')} -{aurl 'submit_closed_url', 'IDF_Views_Issue::myIssues', array($project.shortname, 'submitclosed')} +{aurl 'owner_url', 'IDF_Views_Issue::userIssues', array($project.shortname, $login, 'owner')} +{aurl 'submit_url', 'IDF_Views_Issue::userIssues', array($project.shortname, $login, 'submit')} +{aurl 'owner_closed_url', 'IDF_Views_Issue::userIssues', array($project.shortname, $login, 'ownerclosed')} +{aurl 'submit_closed_url', 'IDF_Views_Issue::userIssues', array($project.shortname, $login, 'submitclosed')}

{trans 'Submitted issues:'} {$nb_submit} {if $nb_submit_closed}
{blocktrans $nb_submit_closed}See the {$nb_submit_closed} closed.{plural}See the {$nb_submit_closed} closed.{/blocktrans}{/if}

{if $nb_owner > 0} diff --git a/src/IDF/templates/idf/js-hotkeys.html b/src/IDF/templates/idf/js-hotkeys.html index 66793fb..dc5e2c6 100644 --- a/src/IDF/templates/idf/js-hotkeys.html +++ b/src/IDF/templates/idf/js-hotkeys.html @@ -10,8 +10,8 @@ {if $hasWikiAccess}{hotkey 'Shift+o', 'IDF_Views_Wiki::index', array($project.shortname)}{/if} {if $hasSourceAccess}{hotkey 'Shift+s', 'IDF_Views_Source::treeBase', array($project.shortname, $project.getScmRoot())}{/if} {if $hasIssuesAccess and !$user.isAnonymous()} -{hotkey 'Shift+m', 'IDF_Views_Issue::myIssues', array($project.shortname, 'submit')} -{hotkey 'Shift+w', 'IDF_Views_Issue::myIssues', array($project.shortname, 'owner')} +{hotkey 'Shift+m', 'IDF_Views_Issue::userIssues', array($project.shortname, $user.login, 'submit')} +{hotkey 'Shift+w', 'IDF_Views_Issue::userIssues', array($project.shortname, $user.login, 'owner')} {/if}{/if} //--> diff --git a/src/IDF/templates/idf/review/base-full.html b/src/IDF/templates/idf/review/base-full.html index 4d2b360..e013932 100644 --- a/src/IDF/templates/idf/review/base-full.html +++ b/src/IDF/templates/idf/review/base-full.html @@ -4,7 +4,7 @@
{trans 'Open Reviews'} {* -{if !$user.isAnonymous()} | {trans 'New Issue'} | {trans 'My Issues'}{/if} | +{if !$user.isAnonymous()} | {trans 'New Issue'} | {trans 'My Issues'}{/if} |
diff --git a/src/IDF/templates/idf/review/index.html b/src/IDF/templates/idf/review/index.html index d73dbaa..876f606 100644 --- a/src/IDF/templates/idf/review/index.html +++ b/src/IDF/templates/idf/review/index.html @@ -5,17 +5,4 @@ {if !$user.isAnonymous()} {aurl 'url', 'IDF_Views_Review::create', array($project.shortname)}

+ {trans 'Start Code Review'}

{/if} - {/block} -{block context} -{* -{aurl 'open_url', 'IDF_Views_Issue::index', array($project.shortname)} -{aurl 'closed_url', 'IDF_Views_Issue::listStatus', array($project.shortname, 'closed')} -{blocktrans}

Open issues: {$open}

-

Closed issues: {$closed}

{/blocktrans} -{assign $class = ''}{assign $i = 0} -

{foreach $project.getTagCloud($cloud) as $label} -{aurl 'url', 'IDF_Views_Issue::listLabel', array($project.shortname, $label.id, 'open')} -{if $class != $label.class}{if $i != 0}
{/if}{$label.class}: {/if} -{$label.name},{assign $class = $label.class}{assign $i = $i + 1}{/foreach}

-*}{/block} diff --git a/src/IDF/templates/idf/tags-cloud.html b/src/IDF/templates/idf/tags-cloud.html index 353b9c5..e230268 100644 --- a/src/IDF/templates/idf/tags-cloud.html +++ b/src/IDF/templates/idf/tags-cloud.html @@ -1,8 +1,6 @@ -{assign $class = ''}{assign $i = 0} -
{foreach $project.getTagCloud($cloud) as $label} +
{foreach $project.getTagCloud($cloud) as $class => $labels} +
{$class}
+{foreach $labels as $idx => $label} {aurl 'url', $cloud_url, array($project.shortname, $label.id, 'open')} -{if $class != $label.class}
{$label.class}
{assign $i = 0}{/if} -
{$label.name},
-{assign $class = $label.class} -{assign $i = $i + 1} -{/foreach}

+
{$label.name}{if $idx != count($labels) - 1},{/if}
+{/foreach}{/foreach}

diff --git a/src/IDF/templates/idf/wiki/view.html b/src/IDF/templates/idf/wiki/view.html index 42fba21..bacb131 100644 --- a/src/IDF/templates/idf/wiki/view.html +++ b/src/IDF/templates/idf/wiki/view.html @@ -1,5 +1,10 @@ {extends "idf/wiki/base.html"} -{block extraheader}{if $oldrev}{/if}{/block} + +{block extraheader} +{if $oldrev}{/if} + +{/block} + {block docclass}yui-t3{assign $inView=true}{/block} {block body} diff --git a/www/media/idf/css/print-wiki.css b/www/media/idf/css/print-wiki.css new file mode 100644 index 0000000..ba1eb38 --- /dev/null +++ b/www/media/idf/css/print-wiki.css @@ -0,0 +1,32 @@ +/* +# ***** 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 ***** */ + +#hd, #ft, #context { + display: none; +} + +.yui-t3 #yui-main .yui-b { + margin: 0; +} + +#wiki-toc { + float: none; +}