From e7104d06da3a03907e135db398ee23d89117d07e Mon Sep 17 00:00:00 2001 From: Egbert van der Wal Date: Thu, 29 May 2014 15:34:52 +0200 Subject: [PATCH] finalized functionality for 0.8.0-alpha release --- README.md | 13 +++-- assets/javascripts/planning.js | 92 ++++++++++++++++++++------------- assets/stylesheets/planning.css | 17 +++--- init.rb | 2 +- 4 files changed, 75 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 6a965a9..bf185ba 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,13 @@ Hit the 'Plan' button next to the 'Gantt' button in any project that has Issue m ### Navigation You can use the 'Back' and 'Forward' to move in the planning chart. You can also drag the canvas which will move it around. You can also use the scrolwheel to scroll horizontally and vertically. If you hold the Control-button down while scrolling, the chart will zoom in and out to give more overview. Additionally, since browsers sometimes force zooming when holding down Control while scrolling even though the JavaScript requests it not to, Alt+Scroll will also zoom the chart. +### List of issues +The left side of the screen will show a list of issues. Issues are indented to show their hierarchy. Issues are grouped by their parent task and sorted by their starting date. +You can double click on an issue in the list of issue on the left side. +This will center the issue in the screen. You can either scroll in the planning chart or in the list of issues, both views are synchronized. + +The list of issues can be resized by dragging the right edge of the list. Performance of this is currently quite poor in Firefox, Chrome seems to do it properly. Future updates hopefully may improve performance in Firefox. + ### Types of relations Redmine supports four types of relations: @@ -69,16 +76,16 @@ When you hit the left or right edge of the rectangles the cursor will indicate t ## Known issues * The tooltip showing issue information may something get in the way many issues are close together. **Planned fix**: better placement / close button / to be determined. * Critical path analysis is not completely valid when resizing issues. -* When an issue does not have a set due date, it will have an default initial size. However, resizing will not behave as expected. The workaroundis to do the resize in two steps: first just resize it to anything, release it to set the dates and then redo it to set the proper due date. +* When an issue does not have a set due date, it will have an default initial size. However, resizing will not behave as expected. The workaround is to do the resize in two steps: first just resize it to anything, release it to set the dates and then redo it to set the proper due date. +* Scrolling the chart and resizing the list of issues may be rather slow in Firefox. Chrome does a good job at this. Future updates hopefully will have to improve this situation. ## Planned features * Add new issues to the current project / subprojects * Add parent/child relations -* Show progress in Gantt style -* Optionally show a list of issues at the left side of the chart, Gantt style, to make it easier to find issues over a larger timespan * Export chart to SVG # Version log +* 0.8.0-alpha May 29, 2014. Add list of issues on the left side of the chart. * 0.7.3: May 27, 2014. Fix placement of tooltip in fullscreen and fix tooltip not showing when no description is set. * 0.7.2: May 27, 2014. Added support for progress visualization and manipulation * 0.7.1: May 26, 2014. Bug in relation to viewbox calculation fixed and date selection is back. diff --git a/assets/javascripts/planning.js b/assets/javascripts/planning.js index d73dfcf..723b5cf 100644 --- a/assets/javascripts/planning.js +++ b/assets/javascripts/planning.js @@ -453,6 +453,13 @@ PlanningChart.prototype.sortIssues = function (callback) { callback = function (a, b) { + if (a.start_date === null && b.start_date === null) + return 0; + else if (a.start_date === null) + return 1; + else if (b.start_date === null) + return -1; + return a.start_date.subtract(b.start_date).days(); }; } @@ -1047,20 +1054,20 @@ PlanningChart.prototype.setViewBox = function (x, y, w, h) continue; if ( - this.issues[k].due_date >= start_date && - this.issues[k].start_date < end_date && + this.issues[k].geometry.x + this.issues[k].geometry.width >= x && + this.issues[k].geometry.x <= x + w && this.issues[k].geometry.y >= this.viewbox.y + this.options.margin.y ) { if (!this.issues[k].element) { - this.issues[k].update(); + this.issues[k].draw(); this.issues[k].updateRelations(); } } else if (this.issues[k].element) { - this.issues[k].update(); + this.issues[k].draw(); } } }; @@ -1329,8 +1336,10 @@ PlanningChart.prototype.draw = function (redraw) this.relations[k].draw(); } - // Update the geometry limits to have space for 3 more issues + // Update the geometry limits to have space for 3 more issues and three more weeks on each side this.geometry_limits.y[1] += (this.options.issue_height + this.options.spacing.y) * 3; + this.geometry_limits.x[0] -= (this.dayWidth() * 21); + this.geometry_limits.x[1] += (this.dayWidth() * 21); // Draw the issue list this.drawList(); @@ -1348,7 +1357,7 @@ PlanningChart.prototype.drawList = function () var y; var indent = 2; - var level = 0; + var level = 1; var text; var caption; @@ -1416,8 +1425,8 @@ PlanningChart.prototype.drawList = function () height: dom_row_height }); - // Set indentation - if (!issue.leaf) + // Set bold for milestones and parent tasks + if (!issue.leaf || issue.milestone) issue.list_row.children('.issue_name').css('font-weight', 'bold'); row_container.append(issue.list_row); @@ -1620,8 +1629,14 @@ function PlanningIssue(data) { this.start_date = new Date(data.start_date); this.start_date.resetTime(); + if (this.start_date.getFullYear() == "1970") + this.start_date = null; + this.due_date = new Date(data.due_date); this.due_date.resetTime(); + if (this.due_date.getFullYear() == "1970") + this.due_date = null; + this.name = data.name; this.description = data.description; this.project = data.project_name; @@ -2769,41 +2784,44 @@ PlanningIssue.prototype.drawProgressBar = function () var pd_perPercent = (pd_maxWidth - pd_minWidth) / 100; var pd_w = Math.round(pd_minWidth + pd_perPercent * this.progress) - // Check if the task is on schedule, ahead or behind - var nDays = this.due_date.subtract(this.start_date).days(); - var ppd = 100.0 / nDays; - var nDaysSinceStart = rmp_getToday().subtract(this.start_date).days(); - var expectedProgress = rmp_clamp(ppd * nDaysSinceStart, 0, 100); - // Determine color based on schedule var behind_color = [200, 0, 0]; var schedule_color = [25, 50, 25]; var ahead_color = [0, 125, 0]; - - var remaining_days = rmp_clamp(nDays - nDaysSinceStart, 0, nDays); - var req_ppd = remaining_days > 0 ? (100 - this.progress) / remaining_days : 100.0 - this.progress; - var factor = req_ppd / ppd; - var color = [schedule_color[0], schedule_color[1], schedule_color[2]]; - if (factor > 1) - { - // Behind schedule, factor is now between 1 and infinity. Take the logarithm to get a decent value - factor = Math.log(factor); - color = [ - rmp_clamp(schedule_color[0] + (behind_color[0] - schedule_color[0]) * factor, 0, 255), - rmp_clamp(schedule_color[1] + (behind_color[1] - schedule_color[1]) * factor, 0, 255), - rmp_clamp(schedule_color[2] + (behind_color[2] - schedule_color[2]) * factor, 0, 255) - ]; - } - else + + // Check if the task is on schedule, ahead or behind + if (this.start_date && this.due_date) { - // Ahead of schedule, factor is now between 1 and infinity. Reverse to get a proper scale - factor = 1 - factor; - color = [ - rmp_clamp(schedule_color[0] + (ahead_color[0] - schedule_color[0]) * factor, 0, 255), - rmp_clamp(schedule_color[1] + (ahead_color[1] - schedule_color[1]) * factor, 0, 255), - rmp_clamp(schedule_color[2] + (ahead_color[2] - schedule_color[2]) * factor, 0, 255) - ]; + var nDays = this.due_date.subtract(this.start_date).days(); + var ppd = 100.0 / nDays; + var nDaysSinceStart = rmp_getToday().subtract(this.start_date).days(); + var expectedProgress = rmp_clamp(ppd * nDaysSinceStart, 0, 100); + + var remaining_days = rmp_clamp(nDays - nDaysSinceStart, 0, nDays); + var req_ppd = remaining_days > 0 ? (100 - this.progress) / remaining_days : 100.0 - this.progress; + var factor = req_ppd / ppd; + + if (factor > 1) + { + // Behind schedule, factor is now between 1 and infinity. Take the logarithm to get a decent value + factor = Math.log(factor); + color = [ + rmp_clamp(schedule_color[0] + (behind_color[0] - schedule_color[0]) * factor, 0, 255), + rmp_clamp(schedule_color[1] + (behind_color[1] - schedule_color[1]) * factor, 0, 255), + rmp_clamp(schedule_color[2] + (behind_color[2] - schedule_color[2]) * factor, 0, 255) + ]; + } + else + { + // Ahead of schedule, factor is now between 1 and infinity. Reverse to get a proper scale + factor = 1 - factor; + color = [ + rmp_clamp(schedule_color[0] + (ahead_color[0] - schedule_color[0]) * factor, 0, 255), + rmp_clamp(schedule_color[1] + (ahead_color[1] - schedule_color[1]) * factor, 0, 255), + rmp_clamp(schedule_color[2] + (ahead_color[2] - schedule_color[2]) * factor, 0, 255) + ]; + } } if (!this.progress_bar) diff --git a/assets/stylesheets/planning.css b/assets/stylesheets/planning.css index e21c57d..7325815 100644 --- a/assets/stylesheets/planning.css +++ b/assets/stylesheets/planning.css @@ -53,14 +53,15 @@ div #planning_list .planning_list_row_container div#planning_list .planning_issue { - position: absolute; - width: 500px; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; + position: absolute; + width: 500px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: context-menu; } div#planning_list .planning_issue_column diff --git a/init.rb b/init.rb index be7c478..7182c25 100644 --- a/init.rb +++ b/init.rb @@ -27,7 +27,7 @@ description 'Offers a UI tailored for planning projects by dragging, dropping ' + 'and resizing issues and by adding and editing relations and ' + 'providing critical path analysis' - version '0.7.3' + version '0.8.0-alpha' if respond_to?(:url) url 'https://github.com/MadEgg/redmine_planning'