houston-roadmaps 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/Gemfile +24 -0
  4. data/Gemfile.lock +358 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +31 -0
  7. data/Rakefile +25 -0
  8. data/app/assets/images/houston/roadmaps/.gitkeep +0 -0
  9. data/app/assets/javascripts/houston/roadmaps/app.coffee +2 -0
  10. data/app/assets/javascripts/houston/roadmaps/application.js +14 -0
  11. data/app/assets/javascripts/houston/roadmaps/handlebars_helpers.coffee +22 -0
  12. data/app/assets/javascripts/houston/roadmaps/jquery_extensions.coffee +4 -0
  13. data/app/assets/javascripts/houston/roadmaps/models/goal.coffee +11 -0
  14. data/app/assets/javascripts/houston/roadmaps/models/milestone.coffee +124 -0
  15. data/app/assets/javascripts/houston/roadmaps/models/roadmap.coffee +16 -0
  16. data/app/assets/javascripts/houston/roadmaps/models/viewport.coffee +3 -0
  17. data/app/assets/javascripts/houston/roadmaps/resize_listener.js +67 -0
  18. data/app/assets/javascripts/houston/roadmaps/views/_gantt_chart.coffee +224 -0
  19. data/app/assets/javascripts/houston/roadmaps/views/_show_milestone_view.coffee +204 -0
  20. data/app/assets/javascripts/houston/roadmaps/views/edit_gantt_chart.coffee +405 -0
  21. data/app/assets/javascripts/houston/roadmaps/views/edit_milestone_view.coffee +97 -0
  22. data/app/assets/javascripts/houston/roadmaps/views/edit_roadmap_view.coffee +80 -0
  23. data/app/assets/javascripts/houston/roadmaps/views/gantt_thumbnail_view.coffee +173 -0
  24. data/app/assets/javascripts/houston/roadmaps/views/goal_view.coffee +18 -0
  25. data/app/assets/javascripts/houston/roadmaps/views/project_goals_view.coffee +30 -0
  26. data/app/assets/javascripts/houston/roadmaps/views/roadmap_history_view.coffee +67 -0
  27. data/app/assets/javascripts/houston/roadmaps/views/roadmap_view.coffee +12 -0
  28. data/app/assets/javascripts/houston/roadmaps/views/roadmaps_view.coffee +29 -0
  29. data/app/assets/stylesheets/houston/roadmaps/application.css +13 -0
  30. data/app/assets/stylesheets/houston/roadmaps/colors.scss.erb +41 -0
  31. data/app/assets/stylesheets/houston/roadmaps/goals.scss +20 -0
  32. data/app/assets/stylesheets/houston/roadmaps/milestone.scss +58 -0
  33. data/app/assets/stylesheets/houston/roadmaps/roadmap.scss +276 -0
  34. data/app/assets/stylesheets/houston/roadmaps/roadmap_history.scss +42 -0
  35. data/app/assets/stylesheets/houston/roadmaps/roadmaps.scss +89 -0
  36. data/app/assets/templates/houston/roadmaps/goals/edit.hbs +6 -0
  37. data/app/assets/templates/houston/roadmaps/goals/index.hbs +9 -0
  38. data/app/assets/templates/houston/roadmaps/goals/new.hbs +27 -0
  39. data/app/assets/templates/houston/roadmaps/goals/show.hbs +6 -0
  40. data/app/assets/templates/houston/roadmaps/milestone/edit.hbs +67 -0
  41. data/app/assets/templates/houston/roadmaps/milestone/show.hbs +53 -0
  42. data/app/assets/templates/houston/roadmaps/milestone/ticket.hbs +28 -0
  43. data/app/assets/templates/houston/roadmaps/roadmap/goal.hbs +6 -0
  44. data/app/assets/templates/houston/roadmaps/roadmap/history.hbs +22 -0
  45. data/app/assets/templates/houston/roadmaps/roadmap/show.hbs +12 -0
  46. data/app/assets/templates/houston/roadmaps/roadmaps/index.hbs +2 -0
  47. data/app/assets/templates/houston/roadmaps/roadmaps/show.hbs +11 -0
  48. data/app/controllers/houston/roadmaps/api/v1/roadmap_controller.rb +20 -0
  49. data/app/controllers/houston/roadmaps/dashboard_controller.rb +34 -0
  50. data/app/controllers/houston/roadmaps/milestones_controller.rb +118 -0
  51. data/app/controllers/houston/roadmaps/project_goals_controller.rb +24 -0
  52. data/app/controllers/houston/roadmaps/roadmap_milestones_controller.rb +36 -0
  53. data/app/controllers/houston/roadmaps/roadmaps_controller.rb +77 -0
  54. data/app/helpers/houston/roadmaps/application_helper.rb +4 -0
  55. data/app/models/roadmap.rb +9 -0
  56. data/app/models/roadmap_commit.rb +35 -0
  57. data/app/models/roadmap_milestone.rb +29 -0
  58. data/app/models/roadmap_milestone_version.rb +8 -0
  59. data/app/presenters/houston/roadmaps/milestone_api_presenter.rb +27 -0
  60. data/app/presenters/houston/roadmaps/milestone_presenter.rb +74 -0
  61. data/app/presenters/houston/roadmaps/roadmap_milestone_presenter.rb +70 -0
  62. data/app/presenters/houston/roadmaps/roadmap_presenter.rb +37 -0
  63. data/app/presenters/houston/roadmaps/ticket_presenter.rb +20 -0
  64. data/app/views/houston/roadmaps/dashboard/show.html.erb +42 -0
  65. data/app/views/houston/roadmaps/milestones/show.html.erb +40 -0
  66. data/app/views/houston/roadmaps/project_goals/index.html.erb +42 -0
  67. data/app/views/houston/roadmaps/roadmaps/_form.html.erb +29 -0
  68. data/app/views/houston/roadmaps/roadmaps/edit.html.erb +8 -0
  69. data/app/views/houston/roadmaps/roadmaps/history.html.erb +41 -0
  70. data/app/views/houston/roadmaps/roadmaps/index.html.erb +24 -0
  71. data/app/views/houston/roadmaps/roadmaps/new.html.erb +7 -0
  72. data/app/views/houston/roadmaps/roadmaps/show.html.erb +27 -0
  73. data/app/views/houston/roadmaps/roadmaps/show_editable.html.erb +35 -0
  74. data/app/views/layouts/houston/roadmaps/application.html.erb +10 -0
  75. data/app/views/layouts/houston/roadmaps/dashboard.html.erb +9 -0
  76. data/bin/rails +8 -0
  77. data/config/database.yml +13 -0
  78. data/config/initializers/add_navigation_renderer.rb +13 -0
  79. data/config/routes.rb +37 -0
  80. data/db/.keep +0 -0
  81. data/db/migrate/20140831210254_add_band_to_milestones.rb +5 -0
  82. data/db/migrate/20140907212311_add_end_date_to_milestones.rb +19 -0
  83. data/db/migrate/20140916230539_add_locked_to_milestone.rb +5 -0
  84. data/db/migrate/20140927154728_add_closed_ticket_count_to_milestones.rb +11 -0
  85. data/db/migrate/20140929024130_create_roadmap_commits.rb +29 -0
  86. data/db/migrate/20141012023628_add_user_id_to_milestone_versions.rb +11 -0
  87. data/db/migrate/20150102192805_add_lanes_to_milestones.rb +5 -0
  88. data/db/migrate/20150119155145_add_goal_and_feedback_query_to_milestones.rb +6 -0
  89. data/db/migrate/20150524203903_add_project_id_to_roadmap_commits.rb +17 -0
  90. data/db/migrate/20150603203744_add_timestamps_to_roadmap_commits.rb +20 -0
  91. data/db/migrate/20160206214746_rename_roadmap_feature_to_milestones.rb +25 -0
  92. data/db/migrate/20160207154530_create_roadmaps.rb +125 -0
  93. data/db/structure.sql +2557 -0
  94. data/houston-roadmaps.gemspec +29 -0
  95. data/lib/houston-roadmaps.rb +1 -0
  96. data/lib/houston/roadmaps.rb +15 -0
  97. data/lib/houston/roadmaps/configuration.rb +14 -0
  98. data/lib/houston/roadmaps/engine.rb +27 -0
  99. data/lib/houston/roadmaps/milestone_ext.rb +14 -0
  100. data/lib/houston/roadmaps/project_ext.rb +20 -0
  101. data/lib/houston/roadmaps/railtie.rb +17 -0
  102. data/lib/houston/roadmaps/version.rb +5 -0
  103. data/lib/tasks/roadmap_tasks.rake +4 -0
  104. data/test/acceptance/houston_dummy_test.rb +17 -0
  105. data/test/dummy/houston.rb +23 -0
  106. data/test/fixtures/projects.yml +3 -0
  107. data/test/fixtures/users.yml +10 -0
  108. data/test/test_helper.rb +43 -0
  109. data/test/unit/fixtures_test.rb +11 -0
  110. metadata +227 -0
@@ -0,0 +1,42 @@
1
+ .roadmap-commit-reverted {
2
+ color: #ccc;
3
+ }
4
+
5
+ #roadmap_commits {
6
+ position: fixed;
7
+ left: 0;
8
+ right: 0;
9
+ bottom: 0;
10
+ overflow-y: scroll;
11
+ border-top: 2px solid;
12
+ margin: 0;
13
+
14
+ ul {
15
+ margin: 20px 0;
16
+ }
17
+
18
+ input[type="radio"] {
19
+ margin: 0;
20
+ }
21
+ }
22
+
23
+ .roadmap-commit {
24
+ display: block;
25
+
26
+ label {
27
+ margin-bottom: 0;
28
+ padding: 2px 24px;
29
+ }
30
+
31
+ &:hover {
32
+ background: rgba(128, 212, 255, 0.1);
33
+ }
34
+ }
35
+
36
+ .roadmap-commit-message {
37
+ display: inline;
38
+ p {
39
+ display: inline;
40
+ margin: 0;
41
+ }
42
+ }
@@ -0,0 +1,89 @@
1
+ ol#roadmaps {
2
+ margin: 0;
3
+ }
4
+
5
+ li.roadmap {
6
+ display: block;
7
+
8
+ > a {
9
+ display: block;
10
+ padding: 6px 12px;
11
+ border-radius: 4px;
12
+
13
+ &:hover {
14
+ background-color: #EDF9FF;
15
+ text-decoration: none;
16
+
17
+ .roadmap-empty {
18
+ color: #b6c2c7;
19
+ }
20
+ }
21
+ }
22
+
23
+ .roadmap-summary {
24
+ padding: 6px 0 0 4px;
25
+ vertical-align: top;
26
+ display: inline-block;
27
+ line-height: 0.92em;
28
+ width: 20%;
29
+
30
+ .bubble {
31
+ width: 8px;
32
+ height: 8px;
33
+ margin: 0;
34
+ }
35
+ }
36
+
37
+ .roadmap-name {
38
+ color: #555;
39
+ font-size: 1.25em;
40
+ font-weight: 500;
41
+ }
42
+
43
+ .roadmap-empty {
44
+ display: block;
45
+ padding: 5px 0px 0 0;
46
+ color: #d0d0d0;
47
+ font-style: italic;
48
+ }
49
+
50
+ .roadmap-preview {
51
+ position: relative;
52
+ overflow: hidden;
53
+ -moz-user-select: none;
54
+ -webkit-user-select: none;
55
+ -ms-user-select: none;
56
+ user-select: none;
57
+
58
+ display: inline-block;
59
+ width: 75%;
60
+
61
+ .roadmap-bands {
62
+ padding-top: 4px;
63
+ }
64
+
65
+ .roadmap-axis {
66
+ position: absolute;
67
+ bottom: 0;
68
+ width: 100%;
69
+
70
+ text {
71
+ font-size: 10px;
72
+ }
73
+ }
74
+
75
+ .roadmap-milestone {
76
+ border: none;
77
+
78
+ &::before {
79
+ width: auto;
80
+ top: 0;
81
+ left: 0;
82
+ right: 0;
83
+ bottom: 0;
84
+ border-radius: 1px;
85
+ }
86
+ .roadmap-milestone-name { display: none; }
87
+ }
88
+ }
89
+ }
@@ -0,0 +1,6 @@
1
+ <td class="goal-name"><input type="text" name="name" value="{{name}}" autofocus /></td>
2
+ <td class="goal-roadmapped">
3
+ {{#if roadmaps.length}}
4
+ <i class="fa fa-map"></i>
5
+ {{/if}}
6
+ </td>
@@ -0,0 +1,9 @@
1
+ <form>
2
+ <table class="table table-sortable table-roadmap-goals">
3
+ <thead>
4
+ <th class="goal-name">Name</th>
5
+ <td class="goal-roadmapped"></td>
6
+ </thead>
7
+ <tbody id="goals"></tbody>
8
+ </table>
9
+ </form>
@@ -0,0 +1,27 @@
1
+ <div id="new_goal_modal" class="modal hide">
2
+ <div class="modal-header">
3
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
4
+ <h3>New Goal</h3>
5
+ </div>
6
+ <div class="modal-body" style="overflow-y: visible;">
7
+ <form>
8
+ <label for="new_feedback_customer">Customer</label>
9
+ <input type="text" id="new_feedback_customer" name="attributedTo" />
10
+
11
+ <label for="new_feedback_text">Text</label>
12
+ <div class="uploader">
13
+ <textarea id="new_feedback_text" name="text"></textarea>
14
+ </div>
15
+
16
+ <label for="new_feedback_tags">Tags</label>
17
+ <div class="feedback-tags">
18
+ <div class="feedback-tag-list"></div>
19
+ <input type="text" id="new_feedback_tags" class="feedback-new-tag" placeholder="New Tag" />
20
+ </div>
21
+ </form>
22
+ </div>
23
+ <div class="modal-footer">
24
+ <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
25
+ <button type="button" id="create_button" class="btn btn-primary">Submit</button>
26
+ </div>
27
+ </div>
@@ -0,0 +1,6 @@
1
+ <td class="goal-name"><a href="/roadmap/milestones/{{id}}">{{name}}</a></td>
2
+ <td class="goal-roadmapped">
3
+ {{#if roadmaps.length}}
4
+ <i class="fa fa-map"></i>
5
+ {{/if}}
6
+ </td>
@@ -0,0 +1,67 @@
1
+ <div id="graph" class="burndown-chart callout callout-banner"></div>
2
+
3
+
4
+ <h2 class="light">Goal</h2>
5
+ <div class="milestone-goal inline-editable">
6
+ <div class="inline-editable-link markdown">
7
+ {{#if milestone/goal}}{{{markdown milestone/goal}}}{{else}}<span class="blank">Write a goal</span>{{/if}}
8
+ </div>
9
+ <textarea id="goal" name="goal">{{milestone/goal}}</textarea>
10
+ <button class="btn btn-default btn-cancel">Cancel</button>
11
+ <button id="save_goal" class="btn btn-primary btn-save">Save</button>
12
+ </div>
13
+
14
+ {{#if usesFeedback}}
15
+ <h2 class="light">Feedback</h2>
16
+ <div class="milestone-feedback inline-editable">
17
+ <div class="inline-editable-link milestone-feedback-query">
18
+ {{#if milestone/feedbackQuery}}{{milestone/feedbackQuery}}{{else}}<span class="blank">Write a feedback query</span>{{/if}}
19
+ </div>
20
+ {{#if milestone/feedbackQuery}}
21
+ {{{linkToFeedbackQuery projectSlug milestone/feedbackQuery}}}
22
+ {{/if}}
23
+ <input type="text" id="feedback_query" name="feedback_query" value="{{milestone/feedbackQuery}}" />
24
+ <button class="btn btn-default btn-cancel">Cancel</button>
25
+ <button id="save_feedback_query" class="btn btn-primary btn-save">Save</button>
26
+ </div>
27
+ {{/if}}
28
+
29
+
30
+ <div>
31
+ <h2 class="light">Tickets</h2>
32
+
33
+ <a class="btn" id="show_completed_tickets" data-toggle="button">Show Completed Tickets</a>
34
+
35
+ <div class="score score-medium milestone-progress">
36
+ <p class="positive">
37
+ <span class="score-count" id="milestone_progress"></span>
38
+ <span class="score-label">Complete</span>
39
+ </p>
40
+ </div>
41
+ </div>
42
+
43
+
44
+ <div id="find_or_create_ticket_view"></div>
45
+
46
+ <hr />
47
+
48
+ {{#if tickets}}
49
+ <table class="table table-milestone-tickets">
50
+ <thead>
51
+ <tr>
52
+ <td></td>
53
+ <th class="ticket-number">#</th>
54
+ <th class="ticket-summary">Summary</th>
55
+ <th class="ticket-effort">Effort</th>
56
+ <th class="ticket-progress">Progress</th>
57
+ <th class="ticket-status">Status</th>
58
+ <td></td>
59
+ </tr>
60
+ </thead>
61
+ <tbody id="tickets">
62
+ {{#tickets}}{{> milestoneTicket}}{{/tickets}}
63
+ </tbody>
64
+ </table>
65
+ {{else}}
66
+ <div class="alert alert-info">There are no tickets in this milestone.</div>
67
+ {{/if}}
@@ -0,0 +1,53 @@
1
+ <div id="graph" class="burndown-chart callout callout-banner"></div>
2
+
3
+ {{#if milestone/goal}}
4
+ <h2 class="light">Goal</h2>
5
+ <div class="milestone-goal markdown">{{{markdown milestone/goal}}}</div>
6
+ {{/if}}
7
+
8
+ {{#if milestone/feedbackQuery}}
9
+ <h2 class="light">Feedback</h2>
10
+ <div class="milestone-feedback">
11
+ {{#if milestone/feedbackQuery}}
12
+ {{{linkToFeedbackQuery projectSlug milestone/feedbackQuery}}}
13
+ {{/if}}
14
+ </div>
15
+ {{/if}}
16
+
17
+ <div>
18
+ <h2 class="light">Tickets</h2>
19
+
20
+ <a class="btn" id="show_completed_tickets" data-toggle="button">Show Completed Tickets</a>
21
+
22
+ <div class="score score-medium milestone-progress">
23
+ <p class="positive">
24
+ <span class="score-count" id="milestone_progress"></span>
25
+ <span class="score-label">Complete</span>
26
+ </p>
27
+ </div>
28
+ </div>
29
+
30
+ <div id="find_or_create_ticket_view"></div>
31
+
32
+ <hr />
33
+
34
+ {{#if tickets}}
35
+ <table class="table table-milestone-tickets">
36
+ <thead>
37
+ <tr>
38
+ <td></td>
39
+ <th class="ticket-number">#</th>
40
+ <th class="ticket-summary">Summary</th>
41
+ <th class="ticket-effort">Effort</th>
42
+ <th class="ticket-progress">Progress</th>
43
+ <th class="ticket-status">Status</th>
44
+ <td></td>
45
+ </tr>
46
+ </thead>
47
+ <tbody id="tickets">
48
+ {{#tickets}}{{> milestoneTicket}}{{/tickets}}
49
+ </tbody>
50
+ </table>
51
+ {{else}}
52
+ <div class="alert alert-info">There are no tickets in this milestone.</div>
53
+ {{/if}}
@@ -0,0 +1,28 @@
1
+ <tr id="ticket_{{id}}" class="ticket {{#firstReleaseAt}}ticket-released{{/firstReleaseAt}} {{#resolved}}ticket-resolved{{/resolved}} {{#closedAt}}ticket-closed{{/closedAt}}" rel="ticket" data-number="{{number}}" data-id="{{id}}">
2
+ <td class="ticket-handle"></td>
3
+ <td class="ticket-number">#{{number}}</td>
4
+ <td class="ticket-summary">
5
+ {{summary}}
6
+ {{#tags}}
7
+ <span class="ticket-tag" style="background-color: #{{color}}">{{name}}</span>
8
+ {{/tags}}
9
+ </td>
10
+ <td class="ticket-effort">
11
+ {{estimatedEffort}}
12
+ </td>
13
+ <td class="ticket-progress">
14
+ {{{ticketPercentComplete this}}}
15
+ </td>
16
+ <td class="ticket-status">
17
+ {{#if closedAt}}
18
+ <i class="fa fa-ban"></i> Closed
19
+ {{else}}{{#if firstReleaseAt}}
20
+ <i class="fa fa-paper-plane"></i> Released
21
+ {{else}}
22
+ <i class="fa fa-circle-o"></i> Open
23
+ {{/if}}{{/if}}
24
+ </td>
25
+ <td class="ticket-remove">
26
+ <a class="remove-ticket-button remove-button"></a>
27
+ </td>
28
+ </tr>
@@ -0,0 +1,6 @@
1
+ <tr class="goal" data-id="{{id}}">
2
+ <td class="goal-project">
3
+ <span class="label {{projectColor}}">{{projectName}}</span>
4
+ </td>
5
+ <td class="goal-name">{{name}}</td>
6
+ </tr>
@@ -0,0 +1,22 @@
1
+ <div id="roadmap" class="roadmap callout callout-banner"></div>
2
+
3
+ <form id="roadmap_commits">
4
+ <ul>
5
+ <li class="roadmap-commit">
6
+ <label for="commit_id_0">
7
+ <input id="commit_id_0" name="commit_id" type="radio" value="0" />
8
+ Now
9
+ </label>
10
+ </li>
11
+ {{#commits}}
12
+ <li class="roadmap-commit">
13
+ <label for="commit_id_{{id}}">
14
+ <input id="commit_id_{{id}}" name="commit_id" type="radio" value="{{id}}" />
15
+ {{formatDateWithYear2 createdAt}}
16
+ {{{avatar user.email 24 user.name}}}
17
+ <div class="roadmap-commit-message">{{{markdown message}}}</div>
18
+ </label>
19
+ </li>
20
+ {{/commits}}
21
+ </ul>
22
+ </form>
@@ -0,0 +1,12 @@
1
+ <div id="roadmap" class="roadmap callout callout-banner"></div>
2
+
3
+ <div id="goals_view">
4
+ <table class="table table-roadmap-goals">
5
+ <thead>
6
+ <th class="goal-project">Project</th>
7
+ <th class="goal-name">Name</th>
8
+ </thead>
9
+ <tbody id="goals">
10
+ </tbody>
11
+ </table>
12
+ </div>
@@ -0,0 +1,2 @@
1
+ <ol id="roadmaps">
2
+ </ol>
@@ -0,0 +1,11 @@
1
+ <li class="roadmap" id="roadmap_{{id}}">
2
+ <a href="/roadmaps/{{id}}">
3
+ <div class="roadmap-summary">
4
+ <div class="roadmap-name">{{name}}</div>
5
+ {{#projects}}
6
+ <b class="bubble {{color}}"></b>
7
+ {{/projects}}
8
+ </div>
9
+ <div class="roadmap-preview"></div>
10
+ </a>
11
+ </li>
@@ -0,0 +1,20 @@
1
+ module Houston
2
+ module Roadmaps
3
+ module Api
4
+ module V1
5
+ class RoadmapController < ApplicationController
6
+ before_filter :api_authenticate!
7
+ skip_before_filter :verify_authenticity_token
8
+
9
+
10
+ def current
11
+ milestones = Milestone.current.includes(:tickets)
12
+ render json: Houston::Roadmaps::MilestoneApiPresenter.new(milestones)
13
+ end
14
+
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ module Houston
2
+ module Roadmaps
3
+ class DashboardController < ApplicationController
4
+ layout "houston/roadmaps/dashboard"
5
+
6
+
7
+ def show
8
+ if params.key?(:range)
9
+ start_date, end_date = params[:range]
10
+ .split(/\.{2,}/)
11
+ .map { |date| Date.strptime(date, "%Y-%m-%d") }
12
+ @range = start_date..end_date
13
+ else
14
+ today = Date.today
15
+ @range = 6.months.before(today)..6.months.after(today)
16
+ end
17
+
18
+ @milestones = RoadmapMilestone.during(@range).preload(:milestone => :project)
19
+
20
+ @show_today = params[:today] != "false"
21
+
22
+ @title = "Roadmap"
23
+ respond_to do |format|
24
+ format.html { render }
25
+ format.json { render json: {
26
+ range: {start: @range.begin, end: @range.end},
27
+ milestones: Houston::Roadmaps::RoadmapMilestonePresenter.new(@milestones) } }
28
+ end
29
+ end
30
+
31
+
32
+ end
33
+ end
34
+ end