From 48770585552dc34cea6bdeef4147227e85b9225a Mon Sep 17 00:00:00 2001 From: "lpsolit%gmail.com" <> Date: Thu, 23 Feb 2006 06:02:07 +0000 Subject: Bug 251656: Redesign dependency tree, part 1: fix the tree itself - Patch by André Batosti r=myk r=LpSolit a=justdave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/expanding-tree.js | 157 ++++++++++++++++ showdependencytree.cgi | 4 +- skins/standard/dependency-tree.css | 90 +++++++++ template/en/default/bug/dependency-tree.html.tmpl | 216 +++++++++++----------- template/en/default/filterexceptions.pl | 4 +- 5 files changed, 359 insertions(+), 112 deletions(-) create mode 100644 js/expanding-tree.js create mode 100644 skins/standard/dependency-tree.css diff --git a/js/expanding-tree.js b/js/expanding-tree.js new file mode 100644 index 000000000..d210a629c --- /dev/null +++ b/js/expanding-tree.js @@ -0,0 +1,157 @@ +/* The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Bugzilla Bug Tracking System. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): Mike Shaver + * Christian Reis + * André Batosti + */ + +if (!Node) { + // MSIE doesn't define Node, so provide a compatibility object + var Node = { TEXT_NODE: 3 } +} + +if (!highlighted) { + var highlighted = 0; + var highlightedclass = ""; + var highlightedover = 0; +} + +function doToggle(node, event) { + var deep = event.altKey || event.ctrlKey; + + if (node.nodeType == Node.TEXT_NODE) + node = node.parentNode; + + var toggle = node.nextSibling; + while (toggle && toggle.tagName != "UL") + toggle = toggle.nextSibling; + + if (toggle) { + if (deep) { + var direction = toggleDisplay(toggle, node); + changeChildren(toggle, direction); + } else { + toggleDisplay(toggle, node); + } + } + /* avoid problems with default actions on links (mozilla's + * ctrl/shift-click defaults, for instance */ + event.preventBubble(); + event.preventDefault(); + return false; +} + +function changeChildren(node, direction) { + var item = node.firstChild; + while (item) { + /* find the LI inside the UL I got */ + while (item && item.tagName != "LI") + item = item.nextSibling; + if (!item) + return; + + /* got it, now find the first A */ + var child = item.firstChild; + while (child && child.tagName != "A") + child = child.nextSibling; + if (!child) { + return + } + var bullet = child; + + /* and check if it has its own sublist */ + var sublist = item.firstChild; + while (sublist && sublist.tagName != "UL") + sublist = sublist.nextSibling; + if (sublist) { + if (direction && isClosed(sublist)) { + openNode(sublist, bullet); + } else if (!direction && !isClosed(sublist)) { + closeNode(sublist, bullet); + } + changeChildren(sublist, direction) + } + item = item.nextSibling; + } +} + +function openNode(node, bullet) { + node.style.display = "block"; + bullet.className = "b b_open"; +} + +function closeNode(node, bullet) { + node.style.display = "none"; + bullet.className = "b b_closed"; +} + +function isClosed(node) { + /* XXX we should in fact check our *computed* style, not the display + * attribute of the current node, which may be inherited and not + * set. However, this really only matters when changing the default + * appearance of the tree through a parent style. */ + return node.style.display == "none"; +} + +function toggleDisplay(node, bullet) { + if (isClosed(node)) { + openNode(node, bullet); + return true; + } + + closeNode(node, bullet); + return false; +} + +function duplicated(element) { + var allsumm= document.getElementsByTagName("span"); + if (highlighted) { + for (i = 0;i < allsumm.length; i++) { + if (allsumm.item(i).id == highlighted) { + allsumm.item(i).className = highlightedclass; + } + } + if (highlighted == element) { + highlighted = 0; + return; + } + } + highlighted = element; + var elem = document.getElementById(element); + highlightedclass = elem.className; + for (var i = 0;i < allsumm.length; i++) { + if (allsumm.item(i).id == element) { + allsumm.item(i).className = "summ_h"; + } + } +} + +function duplicatedover(element) { + if (!highlighted) { + highlightedover = 1; + duplicated(element); + } +} + +function duplicatedout(element) { + if (highlighted == element && highlightedover) { + highlightedover = 0; + duplicated(element); + } +} + diff --git a/showdependencytree.cgi b/showdependencytree.cgi index 03abb2729..efc26a2b2 100755 --- a/showdependencytree.cgi +++ b/showdependencytree.cgi @@ -65,7 +65,7 @@ if ($maxdepth !~ /^\d+$/) { $maxdepth = 0 }; # have to embed a conditional statement into each query. my $milestone_column = Param('usetargetmilestone') ? "target_milestone" : "''"; -# The greatest depth to which either tree goes. +# Stores the greatest depth to which either tree goes. my $realdepth = 0; # Generate the tree of bugs that this bug depends on and a list of IDs @@ -148,12 +148,14 @@ sub GetBug { if (Bugzilla->user->can_see_bug($id)) { ($bug->{'exists'}, $bug->{'status'}, + $bug->{'resolution'}, $bug->{'summary'}, $bug->{'milestone'}, $bug->{'assignee_id'}, $bug->{'assignee_email'}) = $dbh->selectrow_array( "SELECT 1, bug_status, + resolution, short_desc, $milestone_column, assignee.userid, diff --git a/skins/standard/dependency-tree.css b/skins/standard/dependency-tree.css new file mode 100644 index 000000000..859ea199a --- /dev/null +++ b/skins/standard/dependency-tree.css @@ -0,0 +1,90 @@ +/* The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Bugzilla Bug Tracking System. + * + * The Initial Developer of the Original Code is Netscape + * Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): Christian Reis + * André Batosti + */ + +ul.tree { + padding-left: 0em; + margin-left: 1em; + display: block; +} + +ul.tree ul { + padding-top: 3px; + display: block; +} + +ul.tree li { + /* see http://www.kryogenix.org/code/browser/aqlists/ for idea */ + padding-top: 3px; + text-indent: -1.2em; + padding-left: 0.5em; + padding-bottom: 3px; + list-style-type: none; + background: url("dependency-tree/bug-item.png") no-repeat; +} + +ul.tree li a.b { + padding-left: 30px; + margin-right: -14px; + text-decoration: none; +} + +ul.tree li a.b_open { + background: url("dependency-tree/tree-open.png") center no-repeat; + cursor: pointer; +} + +ul.tree li a.b_closed { + background: url("dependency-tree/tree-closed.png") center no-repeat; + cursor: pointer; +} + +.summ_info { + /* change to inline if you would like to see the full bug details + * displayed in the list */ + display: none; + font-size: 75%; +} + +.hint { + font-size: 90%; + margin: 0.2em; + padding: 0.1em; +} + +.hint h3, .hint ul { + margin-top: 0.1em; + margin-bottom: 0.1em; +} + +.summ A, .summ_deep A { + text-decoration: none; + color: darkblue; +} + +.summ_deep { +} + +.summ_h A { + background-color: #ffffaa; + color: #333; + text-decoration: underline bold; +} diff --git a/template/en/default/bug/dependency-tree.html.tmpl b/template/en/default/bug/dependency-tree.html.tmpl index 8b5ecd59c..8fd0c18e6 100644 --- a/template/en/default/bug/dependency-tree.html.tmpl +++ b/template/en/default/bug/dependency-tree.html.tmpl @@ -19,6 +19,7 @@ # Contributor(s): Tobias Burnus # Ville Skyttä # Myk Melez + # André Batosti #%] [% PROCESS global/variables.none.tmpl %] @@ -26,136 +27,135 @@ [% filtered_desc = blocked_tree.$bugid.summary FILTER html %] [% PROCESS global/header.html.tmpl title = "Dependency tree for $terms.Bug $bugid" - h1 = "Dependency tree for $terms.Bug $bugid" + h1 = "Dependency tree for + $terms.Bug $bugid" + javascript_urls = ["js/expanding-tree.js"] + style_urls = ["skins/standard/dependency-tree.css"] h2 = filtered_desc %] [% PROCESS depthControlToolbar %] - -[%# Display the tree of bugs that this bug depends on. %] -

- [% IF hide_resolved %] - Open [% terms.bugs %] - [% ELSE %] - [% terms.Bugs %] - [% END %] - that [% terms.bug %] [%+ bugid %] - depends on

-[% IF dependson_ids.size > 0 %] - ( - [% IF maxdepth -%]Up to [% maxdepth %] level[% "s" IF maxdepth > 1 %] deep | [% END %] - view as [% terms.bug %] list - [% IF canedit && dependson_ids.size > 1 %] - | change several - [% END %]) - [% INCLUDE display_tree tree=dependson_tree bug_id=bugid %] -[% ELSE %] - -

None

-[% END %] - -[%# Display the tree of bugs that this bug blocks. %] -

- [% IF hide_resolved %] - Open [% terms.bugs %] - [% ELSE %] - [% terms.Bugs %] - [% END %] - that [% terms.bug %] [%+ bugid %] - blocks

-[% IF blocked_ids.size > 0 %] - ( - [% IF maxdepth -%]Up to [% maxdepth %] level[% "s" IF maxdepth > 1 %] deep | [% END %] - view as [% terms.bug %] list - [% IF canedit && blocked_ids.size > 1 %] - | change several - [% END %]) - [% INCLUDE display_tree tree=blocked_tree bug_id=bugid %] -[% ELSE %] - -

None

-[% END %] + +[% INCLUDE tree_section ids=dependson_ids type=1 %] + +[% INCLUDE tree_section ids=blocked_ids type=2 %] [% PROCESS depthControlToolbar %] +[% PROCESS global/footer.html.tmpl %] + [%###########################################################################%] -[%# Block to display a tree #%] +[%# Tree-drawing blocks #%] [%###########################################################################%] +[% BLOCK tree_section %] + [%# INTERFACE + # - ids: a list of bug IDs to be displayed as children + # - type: the type of tree. 1 = depends on, 2 = blockeds + # GLOBALS + # - seen: Maintains a global hash of bugs that have been displayed + #%] + [% global.seen = {} %] + [%# Display the tree of bugs that this bug depends on. %] +

+ [% ids.size %] + [% IF hide_resolved %] + Open [% terms.bugs %] + [% ELSE %] + [% terms.Bugs %] + [%- END %] + that [% terms.bug %] [%+ bugid %] + [% IF type == 1 %] + [% tree_name = "dependson_tree" %] + depends on + [% ELSIF type == 2 %] + [% tree_name = "blocked_tree" %] + blocks + [% END %] +

+ [% IF ids.size > 0 %] + ([% IF maxdepth -%]Up to [% maxdepth %] level[% "s" IF maxdepth > 1 %] deep | [% END -%] + view as [% terms.bug %] list + [% IF canedit && ids.size > 1 %] + | change several + [% END %]) +
    + [% INCLUDE display_tree tree=$tree_name %] +
+

+ [% ELSE %] +

None

+ [% END %] +[% END %] + + [% BLOCK display_tree %] -[% tree.$bug_id.seen = 1 %] -
    - [% FOREACH dep_id = tree.$bug_id.dependencies %] - [% dep = tree.$dep_id %] -
  • - [% "" - IF dep.dependencies.size > 0 && !dep.seen %] - [% isclosed = !dep.open %] - [% FILTER closed(isclosed) %] - [% dep_id %] - [[% IF dep.milestone %][% dep.milestone FILTER html %], [% END %] - [% dep.assignee_email FILTER html %]] - - [% IF dep.seen %] - This [% terms.bug %] appears elsewhere in this tree. - [% ELSE %] - [%+ dep.summary FILTER html %]. + [%# INTERFACE + # - bugid: the ID of the bug being displayed + # - tree: a hash of bug objects + #%] + [% bug = tree.$bugid %] +
  • + [%- INCLUDE bullet bugid=bugid bug=bug -%] + + [%- INCLUDE buglink bug=bug bugid=bugid %] + + [% IF global.seen.$bugid %] + (*) + [% ELSIF bug.dependencies.size %] +
      + [% FOREACH depid = bug.dependencies %] + [% INCLUDE display_tree bugid=depid %] [% END %] - [% END %] - [% INCLUDE display_tree bug_id=dep_id - IF dep.dependencies.size > 0 && !dep.seen %] - +
    + [% END %] +
  • + [% global.seen.$bugid = 1 %] +[% END %] + +[% BLOCK bullet %] + [% IF bug.dependencies.size > 0 && ! global.seen.$bugid %] + [% extra_class = " b_open" %] + [% extra_args = 'onclick="return doToggle(this, event)"' %] [% END %] -
+    [% END %] - +[% BLOCK buglink %] + [% isclosed = !bug.open %] + [% FILTER closed(isclosed) -%] + + [%- bugid %]: + [%+ bug.summary FILTER html %] + [[% INCLUDE buginfo %]] + + [% END %] +[% END %] -[% PROCESS global/footer.html.tmpl %] +[% BLOCK buginfo %] + [% bug.status FILTER html %] + [%+ bug.resolution FILTER html %]; assigned to [% bug.assignee_email FILTER html %]; + [% "Target: " _ bug.milestone IF bug.milestone %] +[% END %] [%###########################################################################%] [%# Block for depth control toolbar #%] [%###########################################################################%] [% BLOCK depthControlToolbar %] - - +
+ [%# Hide/show resolved button Swaps text depending on the state of hide_resolved %]
diff --git a/template/en/default/filterexceptions.pl b/template/en/default/filterexceptions.pl index 57a323e7f..dbc618ee6 100644 --- a/template/en/default/filterexceptions.pl +++ b/template/en/default/filterexceptions.pl @@ -313,10 +313,8 @@ 'bug/dependency-tree.html.tmpl' => [ 'bugid', 'maxdepth', - 'dependson_ids.join(",")', - 'blocked_ids.join(",")', - 'dep_id', 'hide_resolved', + 'ids.join(",")', 'maxdepth + 1', 'maxdepth > 0 && maxdepth <= realdepth ? maxdepth : ""', 'maxdepth == 1 ? 1 -- cgit v1.2.3-24-g4f1b