From 85978a4d18c0d86a62022d28858ae361f7d33bd6 Mon Sep 17 00:00:00 2001 From: Thomas Keller Date: Mon, 3 Oct 2011 01:54:01 +0200 Subject: [PATCH 01/11] Implement basic filtering capabilities in the issue search view. Since IDF's text search component does not allow further restrictions on the result set, we make a second, filtered query to restrict to the item state ('open' or 'closed') and optionally a label. All in all this is all harder than it could be, especially the tag cloud is very monolithic and should be replaced by a data-driven component that is less dependent on a single data / query and link usage, but this would for now require too many changes. Similar questionable is the code duplication for the index, listStatus and listLabel view implementations that all do more or less the same. The search implementation now only uses one implementation for a very similar use case. It also removes the artificial restriction to 100 results we had previously there and does not query a record for each single result (as was done with Pluf_Search_ResultSet previously). On my way through this I tried to generalize a couple of i18n texts and removed smaller issues like the "trailing comma" in label lists. This partially fixes issue 548. --- src/IDF/Project.php | 49 ++++++- src/IDF/Views/Issue.php | 151 +++++++++++++++++---- src/IDF/conf/urls.php | 12 +- src/IDF/templates/idf/issues/base.html | 2 +- src/IDF/templates/idf/issues/by-label.html | 11 +- src/IDF/templates/idf/issues/search.html | 22 ++- src/IDF/templates/idf/tags-cloud.html | 12 +- 7 files changed, 212 insertions(+), 47 deletions(-) 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/Issue.php b/src/IDF/Views/Issue.php index 953557c..03850dd 100644 --- a/src/IDF/Views/Issue.php +++ b/src/IDF/Views/Issue.php @@ -431,45 +431,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(); + 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(); + 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'); diff --git a/src/IDF/conf/urls.php b/src/IDF/conf/urls.php index 03779c0..e5b8081 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', diff --git a/src/IDF/templates/idf/issues/base.html b/src/IDF/templates/idf/issues/base.html index 636d5da..60f9d85 100644 --- a/src/IDF/templates/idf/issues/base.html +++ b/src/IDF/templates/idf/issues/base.html @@ -7,7 +7,7 @@ {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/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}

From 33882d4fa788e44462709718050238202a89a6ea Mon Sep 17 00:00:00 2001 From: William MARTIN Date: Mon, 3 Oct 2011 10:00:35 +0200 Subject: [PATCH 02/11] Update how the myIssue view works. It's allow to display this view for other members. In the issue summary, we can now follow make links for each user display in the part "Unresolved: By Assignee". --- src/IDF/Views/Issue.php | 46 ++++++++++++++------- src/IDF/conf/urls.php | 2 +- src/IDF/templates/idf/issues/base.html | 2 +- src/IDF/templates/idf/issues/my-issues.html | 10 ++--- src/IDF/templates/idf/issues/summary.html | 2 +- src/IDF/templates/idf/js-hotkeys.html | 4 +- src/IDF/templates/idf/review/base-full.html | 2 +- 7 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/IDF/Views/Issue.php b/src/IDF/Views/Issue.php index 9c749af..3ef8e96 100644 --- a/src/IDF/Views/Issue.php +++ b/src/IDF/Views/Issue.php @@ -113,7 +113,7 @@ class IDF_Views_Issue $obj = Pluf::factory('Pluf_User')->getOne(array('filter'=>'id='.$user)); $key = $obj->first_name . ' ' . $obj->last_name; } - $ownerStatistics[$key] = array($nb, (int)(100 * $nb / $opened)); + $ownerStatistics[$key] = array($nb, (int)(100 * $nb / $opened), $obj->login); } // Issue class tag statistics @@ -313,42 +313,55 @@ class IDF_Views_Issue * * Only open issues are shown. */ - public $myIssues_precond = array('IDF_Precondition::accessIssues', - 'Pluf_Precondition::loginRequired'); + public $myIssues_precond = array('IDF_Precondition::accessIssues'); public function myIssues($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 = + $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)); + $title = __('%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)); + $title = __('%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)); + $title = __('%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(__('%s %s Submitted %s Issues'), + $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 @@ -377,6 +390,7 @@ class IDF_Views_Issue return Pluf_Shortcuts_RenderToResponse('idf/issues/my-issues.html', array('project' => $prj, 'page_title' => $title, + 'login' => $user->login, 'nb_submit' => $nb_submit, 'nb_owner' => $nb_owner, 'nb_submit_closed' => $nb_submit_closed, diff --git a/src/IDF/conf/urls.php b/src/IDF/conf/urls.php index 03779c0..a011f37 100644 --- a/src/IDF/conf/urls.php +++ b/src/IDF/conf/urls.php @@ -153,7 +153,7 @@ $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'); diff --git a/src/IDF/templates/idf/issues/base.html b/src/IDF/templates/idf/issues/base.html index 636d5da..0856f8f 100644 --- a/src/IDF/templates/idf/issues/base.html +++ b/src/IDF/templates/idf/issues/base.html @@ -4,7 +4,7 @@
{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} |
diff --git a/src/IDF/templates/idf/issues/my-issues.html b/src/IDF/templates/idf/issues/my-issues.html index f3d1d27..9823cd2 100644 --- a/src/IDF/templates/idf/issues/my-issues.html +++ b/src/IDF/templates/idf/issues/my-issues.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::myIssues', array($project.shortname, $login, 'owner')} +{aurl 'submit_url', 'IDF_Views_Issue::myIssues', array($project.shortname, $login, 'submit')} +{aurl 'owner_closed_url', 'IDF_Views_Issue::myIssues', array($project.shortname, $login, 'ownerclosed')} +{aurl 'submit_closed_url', 'IDF_Views_Issue::myIssues', 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/issues/summary.html b/src/IDF/templates/idf/issues/summary.html index bfff813..61e117a 100644 --- a/src/IDF/templates/idf/issues/summary.html +++ b/src/IDF/templates/idf/issues/summary.html @@ -71,7 +71,7 @@ {foreach $ownerStatistics as $key => $value} - {$key} + {$key} {$value[0]} diff --git a/src/IDF/templates/idf/js-hotkeys.html b/src/IDF/templates/idf/js-hotkeys.html index 66793fb..78ecb37 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::myIssues', array($project.shortname, $user.login, 'submit')} +{hotkey 'Shift+w', 'IDF_Views_Issue::myIssues', 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..370e056 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} | From d860f299fdec7dfbcf7c602f8d7841c944ecb097 Mon Sep 17 00:00:00 2001 From: William MARTIN Date: Mon, 3 Oct 2011 10:17:10 +0200 Subject: [PATCH 03/11] The last part of the previous patch. --- src/IDF/Views/Issue.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/IDF/Views/Issue.php b/src/IDF/Views/Issue.php index 3ef8e96..aa37634 100644 --- a/src/IDF/Views/Issue.php +++ b/src/IDF/Views/Issue.php @@ -332,23 +332,23 @@ class IDF_Views_Issue if (count($ctags) == 0) $ctags[] = 0; switch ($match[3]) { case 'submit': - $titleFormat = + $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 = __('%s %s Closed Submitted %s Issues'); + $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 = __('%s %s Closed Working %s Issues'); + $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 = __('%s %s Working %s Issues'); + $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(__('%s %s Submitted %s Issues'), + $title = sprintf($titleFormat, $user->first_name, $user->last_name, (string) $prj); From 160d11b89be35086ae0e132c4a1f090ad3ceb767 Mon Sep 17 00:00:00 2001 From: Thomas Keller Date: Tue, 4 Oct 2011 00:37:28 +0200 Subject: [PATCH 04/11] Properly initialize arrays with 0 for IN conditions --- src/IDF/Views/Issue.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/IDF/Views/Issue.php b/src/IDF/Views/Issue.php index 03850dd..854b9b9 100644 --- a/src/IDF/Views/Issue.php +++ b/src/IDF/Views/Issue.php @@ -477,7 +477,7 @@ class IDF_Views_Issue // and other things in the next round $results = IDF_Search::mySearch($query, $prj, 'IDF_Issue'); - $issue_ids = array(); + $issue_ids = array(0); foreach ($results as $result) { $issue_ids[] = $result['model_id']; } @@ -495,7 +495,7 @@ class IDF_Views_Issue // we unfortunately loose the original sort order, // so we manually have to apply it here again $sorted_issues = new ArrayObject(); - $filtered_issue_ids = array(); + $filtered_issue_ids = array(0); foreach ($issue_ids as $issue_id) { foreach ($issues as $issue) { if ($issue->id != $issue_id) From 9e2ea7404b46d53b558c290613e6cf85fe9e0f40 Mon Sep 17 00:00:00 2001 From: Thomas Keller Date: Tue, 4 Oct 2011 00:46:48 +0200 Subject: [PATCH 05/11] Tags are now returned grouped by class, I seem to have missed this call when I changed the API... --- src/IDF/Views/Issue.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/IDF/Views/Issue.php b/src/IDF/Views/Issue.php index 854b9b9..a8e52fd 100644 --- a/src/IDF/Views/Issue.php +++ b/src/IDF/Views/Issue.php @@ -119,9 +119,11 @@ class IDF_Views_Issue } // 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; From 9a8bd464a33774741133eb1a36b6d11c8800dfc0 Mon Sep 17 00:00:00 2001 From: Thomas Keller Date: Tue, 4 Oct 2011 00:47:31 +0200 Subject: [PATCH 06/11] Remove a couple of unused calls to get a list of project tags; these calls are currently done from within the tags-cloud template most of the time, which is ugly, but the way it works as of now. --- src/IDF/Views/Download.php | 2 -- src/IDF/Views/Wiki.php | 2 -- src/IDF/templates/idf/review/index.html | 13 ------------- 3 files changed, 17 deletions(-) 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/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/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} From 813184f06cf4589e019b68e74dec2180853e87c0 Mon Sep 17 00:00:00 2001 From: William MARTIN Date: Tue, 4 Oct 2011 10:05:42 +0200 Subject: [PATCH 07/11] Fix an issue with "unasigned issues" Rename the view to userIssues --- src/IDF/Views/Issue.php | 12 +++++++----- src/IDF/conf/urls.php | 2 +- src/IDF/templates/idf/issues/base.html | 2 +- src/IDF/templates/idf/issues/summary.html | 7 ++++++- .../idf/issues/{my-issues.html => userIssues.html} | 8 ++++---- src/IDF/templates/idf/js-hotkeys.html | 4 ++-- src/IDF/templates/idf/review/base-full.html | 2 +- 7 files changed, 22 insertions(+), 15 deletions(-) rename src/IDF/templates/idf/issues/{my-issues.html => userIssues.html} (74%) diff --git a/src/IDF/Views/Issue.php b/src/IDF/Views/Issue.php index aa37634..2a234fb 100644 --- a/src/IDF/Views/Issue.php +++ b/src/IDF/Views/Issue.php @@ -109,11 +109,13 @@ 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), $obj->login); + $ownerStatistics[$key] = array($nb, (int)(100 * $nb / $opened), $login); } // Issue class tag statistics @@ -313,8 +315,8 @@ class IDF_Views_Issue * * Only open issues are shown. */ - public $myIssues_precond = array('IDF_Precondition::accessIssues'); - public function myIssues($request, $match) + public $userIssues_precond = array('IDF_Precondition::accessIssues'); + public function userIssues($request, $match) { $prj = $request->project; @@ -372,7 +374,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; @@ -387,7 +389,7 @@ 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, diff --git a/src/IDF/conf/urls.php b/src/IDF/conf/urls.php index a011f37..1aa395c 100644 --- a/src/IDF/conf/urls.php +++ b/src/IDF/conf/urls.php @@ -156,7 +156,7 @@ $ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/create/$#', $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 0856f8f..1d40c02 100644 --- a/src/IDF/templates/idf/issues/base.html +++ b/src/IDF/templates/idf/issues/base.html @@ -4,7 +4,7 @@
{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} | diff --git a/src/IDF/templates/idf/issues/summary.html b/src/IDF/templates/idf/issues/summary.html index 61e117a..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 74% rename from src/IDF/templates/idf/issues/my-issues.html rename to src/IDF/templates/idf/issues/userIssues.html index 9823cd2..018a642 100644 --- a/src/IDF/templates/idf/issues/my-issues.html +++ b/src/IDF/templates/idf/issues/userIssues.html @@ -8,10 +8,10 @@ {/block} {block context} -{aurl 'owner_url', 'IDF_Views_Issue::myIssues', array($project.shortname, $login, 'owner')} -{aurl 'submit_url', 'IDF_Views_Issue::myIssues', array($project.shortname, $login, 'submit')} -{aurl 'owner_closed_url', 'IDF_Views_Issue::myIssues', array($project.shortname, $login, 'ownerclosed')} -{aurl 'submit_closed_url', 'IDF_Views_Issue::myIssues', array($project.shortname, $login, '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 78ecb37..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, $user.login, 'submit')} -{hotkey 'Shift+w', 'IDF_Views_Issue::myIssues', array($project.shortname, $user.login, '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 370e056..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} | From a9d327d54fcff1404b09f3fef01441072ed8ffc7 Mon Sep 17 00:00:00 2001 From: Thomas Keller Date: Tue, 4 Oct 2011 12:50:51 +0200 Subject: [PATCH 08/11] Note that issues can now be filtered in the search view. --- NEWS.mdtext | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.mdtext b/NEWS.mdtext index 5f52c3c..c87d99f 100644 --- a/NEWS.mdtext +++ b/NEWS.mdtext @@ -7,6 +7,8 @@ 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) From ac7a4c4aa5357eb34a03ecc28c32190309cd1197 Mon Sep 17 00:00:00 2001 From: William MARTIN Date: Tue, 4 Oct 2011 21:29:11 +0200 Subject: [PATCH 09/11] Update NEWS --- NEWS.mdtext | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.mdtext b/NEWS.mdtext index c87d99f..f21fa02 100644 --- a/NEWS.mdtext +++ b/NEWS.mdtext @@ -15,6 +15,10 @@ or newer to properly run this version of Indefero! - 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. ## Bugfixes @@ -43,6 +47,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 From 708b90fccd4b49d8e9ab3a10033c29e6f0510753 Mon Sep 17 00:00:00 2001 From: William MARTIN Date: Tue, 4 Oct 2011 21:45:23 +0200 Subject: [PATCH 10/11] Fix url /p/aaa/issues/status/open/ --- src/IDF/Views/Issue.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/IDF/Views/Issue.php b/src/IDF/Views/Issue.php index 59f905c..083bd62 100644 --- a/src/IDF/Views/Issue.php +++ b/src/IDF/Views/Issue.php @@ -732,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'); From 15d4d1aa7d3c5772247109e594d94a5314d1713a Mon Sep 17 00:00:00 2001 From: William MARTIN Date: Tue, 4 Oct 2011 22:45:51 +0200 Subject: [PATCH 11/11] Fix issue 713 : Wiki page have now a css for printer output --- NEWS.mdtext | 1 + src/IDF/templates/idf/wiki/view.html | 7 +++++- www/media/idf/css/print-wiki.css | 32 ++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 www/media/idf/css/print-wiki.css diff --git a/NEWS.mdtext b/NEWS.mdtext index f21fa02..3b2b1c4 100644 --- a/NEWS.mdtext +++ b/NEWS.mdtext @@ -19,6 +19,7 @@ or newer to properly run this version of Indefero! 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 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; +}