houston-core 0.6.3 → 0.7.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (232) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile.lock +53 -63
  4. data/app/adapters/houston/adapters/error_tracker/errbit_adapter.rb +2 -2
  5. data/app/adapters/houston/adapters/ticket_tracker/github_adapter.rb +1 -1
  6. data/app/adapters/houston/adapters/ticket_tracker/unfuddle_adapter.rb +5 -5
  7. data/app/adapters/houston/adapters/version_control/git_adapter.rb +4 -4
  8. data/app/assets/javascripts/{app → houston/app}/boot.coffee +0 -0
  9. data/app/assets/javascripts/{app → houston/app}/emoji.coffee.erb +0 -0
  10. data/app/assets/javascripts/{app → houston/app}/infinite_scroll.coffee +0 -0
  11. data/app/assets/javascripts/{app → houston/app}/models/commit.coffee +0 -0
  12. data/app/assets/javascripts/{app → houston/app}/models/release.coffee +0 -0
  13. data/app/assets/javascripts/{app → houston/app}/models/task.coffee +0 -0
  14. data/app/assets/javascripts/{app → houston/app}/models/tester.coffee +0 -0
  15. data/app/assets/javascripts/{app → houston/app}/models/testing_note.coffee +0 -0
  16. data/app/assets/javascripts/{app → houston/app}/models/ticket.coffee +0 -0
  17. data/app/assets/javascripts/{app → houston/app}/models/user.coffee +0 -0
  18. data/app/assets/javascripts/{app → houston/app}/mousetrap-bind-scoped.js +0 -0
  19. data/app/assets/javascripts/{app → houston/app}/releases.coffee +0 -0
  20. data/app/assets/javascripts/{app → houston/app}/table_row_expander.coffee +0 -0
  21. data/app/assets/javascripts/{app → houston/app}/ticket_tracker_refresh.coffee +0 -0
  22. data/app/assets/javascripts/{app → houston/app}/views/_show_sprint_view.coffee +0 -0
  23. data/app/assets/javascripts/{app → houston/app}/views/_tickets_view.coffee +0 -0
  24. data/app/assets/javascripts/{app → houston/app}/views/all_tickets_view.coffee +0 -0
  25. data/app/assets/javascripts/{app → houston/app}/views/commit_view.coffee +0 -0
  26. data/app/assets/javascripts/{app → houston/app}/views/edit_sprint_view.coffee +0 -0
  27. data/app/assets/javascripts/{app → houston/app}/views/edit_ticket_view.coffee +0 -0
  28. data/app/assets/javascripts/{app → houston/app}/views/find_or_create_ticket_view.coffee +0 -0
  29. data/app/assets/javascripts/{app → houston/app}/views/keyboard_shortcuts_modal.coffee +0 -0
  30. data/app/assets/javascripts/{app → houston/app}/views/new_ticket_modal.coffee +0 -0
  31. data/app/assets/javascripts/{app → houston/app}/views/new_ticket_view.coffee +0 -0
  32. data/app/assets/javascripts/{app → houston/app}/views/problems_view.coffee +0 -0
  33. data/app/assets/javascripts/{app → houston/app}/views/testing_note_view.coffee +0 -0
  34. data/app/assets/javascripts/{app → houston/app}/views/testing_report_view.coffee +0 -0
  35. data/app/assets/javascripts/{app → houston/app}/views/testing_ticket_view.coffee +0 -0
  36. data/app/assets/javascripts/{app → houston/app}/views/ticket_modal_view.coffee +0 -0
  37. data/app/assets/javascripts/{application.js → houston/application.js} +1 -1
  38. data/app/assets/javascripts/{core → houston/core}/app.coffee +0 -0
  39. data/app/assets/javascripts/{core → houston/core}/burndown_chart.coffee +0 -0
  40. data/app/assets/javascripts/{core → houston/core}/core_ext/array.coffee +0 -0
  41. data/app/assets/javascripts/{core → houston/core}/core_ext/date.coffee +0 -0
  42. data/app/assets/javascripts/{core → houston/core}/core_ext/number.coffee +0 -0
  43. data/app/assets/javascripts/{core → houston/core}/errors.coffee +1 -1
  44. data/app/assets/javascripts/{core → houston/core}/handlebars_helpers.coffee +0 -0
  45. data/app/assets/javascripts/{core → houston/core}/helpers.coffee +0 -0
  46. data/app/assets/javascripts/{core → houston/core}/jquery_extensions.coffee +5 -3
  47. data/app/assets/javascripts/{core → houston/core}/stacked_area_graph.coffee +0 -0
  48. data/app/assets/javascripts/{core → houston/core}/stacked_bar_graph.coffee +0 -0
  49. data/app/assets/javascripts/{dashboard.js → houston/dashboard.js} +1 -1
  50. data/app/assets/javascripts/{dashboard → houston/dashboard}/refresher.coffee +0 -0
  51. data/app/assets/javascripts/{vendor.js → houston/vendor.js} +0 -0
  52. data/app/assets/stylesheets/{application.css → houston/application.css} +0 -0
  53. data/app/assets/stylesheets/{application → houston/application}/ansi.scss +0 -0
  54. data/app/assets/stylesheets/{application → houston/application}/commit.scss +0 -0
  55. data/app/assets/stylesheets/{application → houston/application}/emoji.scss +0 -0
  56. data/app/assets/stylesheets/{application → houston/application}/exceptions.scss +1 -1
  57. data/app/assets/stylesheets/{application → houston/application}/find_or_create_ticket.scss +0 -0
  58. data/app/assets/stylesheets/{application → houston/application}/follow_up.scss +0 -0
  59. data/app/assets/stylesheets/{application → houston/application}/forms.scss +0 -0
  60. data/app/assets/stylesheets/{application → houston/application}/freight_train.css.scss +0 -0
  61. data/app/assets/stylesheets/{application → houston/application}/full_screen.scss +0 -0
  62. data/app/assets/stylesheets/{application → houston/application}/github_repos.scss +0 -0
  63. data/app/assets/stylesheets/{application → houston/application}/infinite_scroll.scss +0 -0
  64. data/app/assets/stylesheets/houston/application/jobs.scss +5 -0
  65. data/app/assets/stylesheets/{application → houston/application}/keyboard_shortcuts.scss +0 -0
  66. data/app/assets/stylesheets/{application → houston/application}/markdown.scss +0 -0
  67. data/app/assets/stylesheets/{application → houston/application}/mobile.scss +0 -0
  68. data/app/assets/stylesheets/{application → houston/application}/modals.scss +0 -0
  69. data/app/assets/stylesheets/{application → houston/application}/navigation.scss +0 -0
  70. data/app/assets/stylesheets/{application → houston/application}/new_ticket_view.scss +0 -0
  71. data/app/assets/stylesheets/{application → houston/application}/omnibar.scss +0 -0
  72. data/app/assets/stylesheets/{application → houston/application}/project_banner_buttons.scss +0 -0
  73. data/app/assets/stylesheets/{application → houston/application}/project_tiles.scss +0 -0
  74. data/app/assets/stylesheets/{application → houston/application}/projects.css.scss +0 -0
  75. data/app/assets/stylesheets/{application → houston/application}/pull_requests.scss +0 -0
  76. data/app/assets/stylesheets/{application → houston/application}/queue.scss +0 -0
  77. data/app/assets/stylesheets/{application → houston/application}/release_form.scss +0 -0
  78. data/app/assets/stylesheets/{application → houston/application}/releases.scss +1 -1
  79. data/app/assets/stylesheets/{application → houston/application}/sortable_table.scss +0 -0
  80. data/app/assets/stylesheets/{application → houston/application}/sprint.scss +0 -0
  81. data/app/assets/stylesheets/{application → houston/application}/tables.scss +0 -0
  82. data/app/assets/stylesheets/{application → houston/application}/test.scss +0 -0
  83. data/app/assets/stylesheets/{application → houston/application}/test_run.scss +0 -0
  84. data/app/assets/stylesheets/{application → houston/application}/testing_report.scss +0 -0
  85. data/app/assets/stylesheets/{application → houston/application}/ticket.scss +0 -0
  86. data/app/assets/stylesheets/{application → houston/application}/ticket_modal.scss +0 -0
  87. data/app/assets/stylesheets/{application → houston/application}/tickets.scss +0 -0
  88. data/app/assets/stylesheets/{application → houston/application}/timeline.scss +0 -0
  89. data/app/assets/stylesheets/{application → houston/application}/tips.scss +0 -0
  90. data/app/assets/stylesheets/{application → houston/application}/typeahead.scss +0 -0
  91. data/app/assets/stylesheets/{application → houston/application}/uploading.scss +0 -0
  92. data/app/assets/stylesheets/{application → houston/application}/user_wall.scss +0 -0
  93. data/app/assets/stylesheets/{application → houston/application}/users.scss +0 -0
  94. data/app/assets/stylesheets/{application → houston/application}/welcome.scss +0 -0
  95. data/app/assets/stylesheets/{core → houston/core}/alerts.scss +0 -0
  96. data/app/assets/stylesheets/{core → houston/core}/avatars.scss +0 -0
  97. data/app/assets/stylesheets/{core → houston/core}/burndown_chart.scss +0 -0
  98. data/app/assets/stylesheets/{core → houston/core}/colors.scss.erb +0 -0
  99. data/app/assets/stylesheets/{core → houston/core}/misc.scss +3 -0
  100. data/app/assets/stylesheets/{core → houston/core}/octicons-icons.scss +0 -0
  101. data/app/assets/stylesheets/{core → houston/core}/octicons.scss.erb +0 -0
  102. data/app/assets/stylesheets/{core → houston/core}/overrides.scss +0 -0
  103. data/app/assets/stylesheets/{core → houston/core}/roboto.scss.erb +0 -0
  104. data/app/assets/stylesheets/{core → houston/core}/scores.scss +0 -0
  105. data/app/assets/stylesheets/{dashboard.css → houston/dashboard.css} +0 -0
  106. data/app/assets/stylesheets/{dashboard → houston/dashboard}/dashboard.scss +0 -0
  107. data/app/assets/stylesheets/{print.css.scss → houston/print.css.scss} +0 -0
  108. data/app/assets/stylesheets/{variables.scss → houston/variables.scss} +0 -0
  109. data/app/assets/stylesheets/{vendor.css → houston/vendor.css} +0 -0
  110. data/app/concerns/houston/props.rb +96 -0
  111. data/app/concerns/project_adapter.rb +1 -1
  112. data/app/controllers/api/v1/measurements_controller.rb +32 -0
  113. data/app/controllers/application_controller.rb +1 -1
  114. data/app/controllers/authorizations_controller.rb +61 -0
  115. data/app/controllers/github/pulls_controller.rb +1 -1
  116. data/app/controllers/jobs_controller.rb +30 -1
  117. data/app/controllers/oauth/providers_controller.rb +45 -0
  118. data/app/controllers/project_options_controller.rb +2 -2
  119. data/app/controllers/projects_controller.rb +3 -3
  120. data/app/controllers/releases_controller.rb +3 -3
  121. data/app/controllers/user_options_controller.rb +2 -2
  122. data/app/controllers/users_controller.rb +1 -2
  123. data/app/helpers/application_helper.rb +49 -3
  124. data/app/helpers/email_helper.rb +19 -1
  125. data/app/helpers/release_helper.rb +1 -1
  126. data/app/helpers/ticket_helper.rb +0 -32
  127. data/app/interactors/cache_key_dependencies.rb +3 -8
  128. data/app/mailers/view_mailer.rb +8 -8
  129. data/app/models/authorization.rb +54 -0
  130. data/app/models/commit.rb +1 -1
  131. data/app/models/error.rb +14 -0
  132. data/app/models/github/comment_event.rb +4 -4
  133. data/app/models/github/pull_request.rb +39 -17
  134. data/app/models/github/pull_request_event.rb +1 -7
  135. data/app/models/job.rb +81 -0
  136. data/app/models/measurement.rb +2 -1
  137. data/app/models/oauth/provider.rb +35 -0
  138. data/app/models/project.rb +12 -3
  139. data/app/models/slackdown.rb +1 -1
  140. data/app/models/user.rb +28 -35
  141. data/app/presenters/measurements_presenter.rb +26 -0
  142. data/app/presenters/project_presenter.rb +1 -1
  143. data/app/views/authorizations/_form.html.erb +33 -0
  144. data/app/views/authorizations/edit.html.erb +7 -0
  145. data/app/views/authorizations/granted.html.erb +7 -0
  146. data/app/views/authorizations/index.html.erb +47 -0
  147. data/app/views/authorizations/new.html.erb +7 -0
  148. data/app/views/configuration_error/_no_ticket_tracker.html.erb +1 -1
  149. data/app/views/github/pulls/index.html.erb +5 -1
  150. data/app/views/jobs/index.html.erb +72 -0
  151. data/app/views/jobs/show.html.erb +25 -32
  152. data/app/views/layouts/_navigation.html.erb +1 -1
  153. data/app/views/layouts/application.html.erb +14 -15
  154. data/app/views/layouts/dashboard.html.erb +9 -10
  155. data/app/views/layouts/minimal.html.erb +14 -15
  156. data/app/views/layouts/naked.html.erb +52 -0
  157. data/app/views/layouts/naked_dashboard.html.erb +9 -10
  158. data/app/views/oauth/providers/_form.html.erb +54 -0
  159. data/app/views/oauth/providers/edit.html.erb +7 -0
  160. data/app/views/oauth/providers/index.html.erb +41 -0
  161. data/app/views/oauth/providers/new.html.erb +7 -0
  162. data/app/views/projects/_form.html.erb +8 -9
  163. data/app/views/projects/index.html.erb +1 -1
  164. data/app/views/users/_form.html.erb +20 -19
  165. data/bin/rails +1 -1
  166. data/config/application.rb +11 -10
  167. data/config/boot.rb +1 -2
  168. data/config/environments/development.rb +8 -6
  169. data/config/environments/production.rb +11 -16
  170. data/config/environments/test.rb +5 -5
  171. data/config/initializers/assets.rb +17 -7
  172. data/config/initializers/cookies_serializer.rb +1 -1
  173. data/config/initializers/houston_async.rb +22 -4
  174. data/config/initializers/houston_report_exception.rb +16 -11
  175. data/config/initializers/houston_scheduler.rb +1 -1
  176. data/config/initializers/houston_try.rb +12 -0
  177. data/config/routes.rb +29 -19
  178. data/db/fixtures/projects.yml +2 -2
  179. data/db/migrate/20160317140151_remove_limit_from_users_invitation_token.rb +9 -0
  180. data/db/migrate/20160419230411_create_oauth_providers.rb +14 -0
  181. data/db/migrate/20160420000616_create_authorizations.rb +16 -0
  182. data/db/migrate/20160507135209_create_jobs.rb +14 -0
  183. data/db/migrate/20160507135846_create_errors_2.rb +12 -0
  184. data/db/migrate/20160510233329_add_closed_at_and_merged_at_to_pull_requests.rb +7 -0
  185. data/db/migrate/20160625203412_convert_user_view_options_to_props.rb +21 -0
  186. data/db/migrate/20160625221840_convert_project_extended_attributes_to_props.rb +32 -0
  187. data/db/migrate/20160625230420_move_users_unfuddle_id_to_props.rb +14 -0
  188. data/db/structure.sql +247 -4
  189. data/{houston.gemspec → houston-core.gemspec} +8 -9
  190. data/lib/configuration.rb +15 -43
  191. data/lib/houston/version.rb +1 -1
  192. data/lib/houston_observer.rb +2 -7
  193. data/lib/parallel_enumerable.rb +2 -8
  194. data/templates/new-instance/app/assets/javascripts/.keep +0 -0
  195. data/templates/new-instance/app/assets/javascripts/application.js +13 -0
  196. data/templates/new-instance/app/assets/stylesheets/.keep +0 -0
  197. data/templates/new-instance/app/assets/stylesheets/application.css +13 -0
  198. data/templates/new-instance/app/controllers/.keep +0 -0
  199. data/templates/new-instance/app/models/.keep +0 -0
  200. data/templates/new-instance/app/views/.keep +0 -0
  201. data/templates/new-instance/config/alerts/errs.rb +1 -1
  202. data/templates/new-instance/config/jobs/purge_jobs.rb +3 -0
  203. data/templates/new-instance/config/main.rb +1 -0
  204. data/templates/new-instance/config/routes.rb +5 -0
  205. data/templates/new-instance/config/triggers/github/publish_comments_on_slack.rb +3 -3
  206. data/templates/new-instance/lib/houston/engine.rb +25 -0
  207. data/test/acceptance/creating_a_release_test.rb +1 -1
  208. data/test/integration/ci_integration_test.rb +2 -2
  209. data/test/integration/commits_api_test.rb +1 -1
  210. data/test/unit/controllers/hooks_controller_test.rb +1 -6
  211. data/test/unit/controllers/project_options_controller_test.rb +11 -11
  212. data/test/unit/controllers/user_options_controller_test.rb +13 -13
  213. data/test/unit/models/code_climate_coverage_report_test.rb +1 -1
  214. data/test/unit/models/commit_test.rb +4 -2
  215. data/test/unit/models/project_test.rb +5 -5
  216. data/test/unit/models/props_test.rb +57 -0
  217. data/test/unit/models/pull_request_test.rb +2 -2
  218. data/test/unit/models/test_run_test.rb +1 -1
  219. metadata +166 -151
  220. data/app/assets/javascripts/app/views/reports_view.coffee +0 -51
  221. data/app/controllers/oauth_consumers_controller.rb +0 -68
  222. data/app/controllers/reports_controller.rb +0 -215
  223. data/app/models/consumer_token.rb +0 -13
  224. data/app/models/github_token.rb +0 -8
  225. data/app/views/oauth_consumers/error.html.erb +0 -5
  226. data/app/views/oauth_consumers/index.html.erb +0 -29
  227. data/app/views/oauth_consumers/show.html.erb +0 -7
  228. data/app/views/reports/index.html.erb +0 -9
  229. data/app/views/reports/sprint.html.erb +0 -21
  230. data/app/views/reports/velocity.html.erb +0 -104
  231. data/config/initializers/oauth_consumers.rb +0 -18
  232. data/lib/patches/sprockets_output_path_for_assets.rb +0 -29
@@ -1,7 +1,7 @@
1
1
  class Github::PullsController < ApplicationController
2
2
 
3
3
  def index
4
- @pulls = Github::PullRequest.order(created_at: :desc).preload(:project, :user)
4
+ @pulls = Github::PullRequest.open.order(created_at: :desc).preload(:project, :user)
5
5
  @labels = @pulls.flat_map(&:labels).uniq { |label| label["name"] }.sort_by { |label| label["name"] }
6
6
  @selected_labels = params.fetch(:only, "").split(/,\s*/)
7
7
  @selected_labels = @labels.map { |label| label["name"] } if @selected_labels.none?
@@ -1,12 +1,41 @@
1
1
  class JobsController < ApplicationController
2
2
 
3
+ def index
4
+ authorize! :show, :jobs
5
+ jobs_by_name = $scheduler.jobs.each_with_object({}) { |job, map|
6
+ map[job.tags.first] = {
7
+ name: job.tags.first,
8
+ schedule: job.original } }
9
+
10
+ jobs = Job.where(name: jobs_by_name.keys)
11
+
12
+ most_recent_jobs = jobs.joins(<<-SQL)
13
+ inner join (select name, max(started_at) "started_at" from jobs group by name) "most_recent"
14
+ on jobs.name=most_recent.name and jobs.started_at=most_recent.started_at
15
+ SQL
16
+ most_recent_jobs.each do |job|
17
+ jobs_by_name[job.name][:last] = job
18
+ end
19
+
20
+ jobs.group(:name).unscope(:order).pluck(:name, "COUNT(id)", "COUNT(CASE WHEN succeeded THEN 1 ELSE NULL END)", "AVG(EXTRACT(epoch from finished_at - started_at))").each do |name, runs, successful_runs, avg_duration|
21
+ jobs_by_name[name].merge!(
22
+ runs: runs,
23
+ successful_runs: successful_runs,
24
+ avg_duration: avg_duration )
25
+ end
26
+
27
+ @jobs = jobs_by_name.values
28
+ end
29
+
3
30
  def show
4
31
  authorize! :show, :jobs
32
+ @job_name = params[:slug]
33
+ @jobs = Job.where(name: @job_name).preload(:error)
5
34
  end
6
35
 
7
36
  def run
8
37
  authorize! :run, :jobs
9
- Houston.jobs.run_async params[:slug]
38
+ Houston.jobs.run params[:slug]
10
39
  redirect_to "/jobs", notice: "#{params[:slug]} is running"
11
40
  end
12
41
 
@@ -0,0 +1,45 @@
1
+ module Oauth
2
+ class ProvidersController < ApplicationController
3
+
4
+ def index
5
+ @title = "Providers"
6
+ authorize! :read, Oauth::Provider
7
+ @providers = Oauth::Provider.all
8
+ end
9
+
10
+ def new
11
+ @title = "New Provider"
12
+ authorize! :create, Oauth::Provider
13
+ @provider = Oauth::Provider.new
14
+ end
15
+
16
+ def create
17
+ @provider = Oauth::Provider.new(params[:oauth_provider])
18
+ authorize! :create, @provider
19
+
20
+ if @provider.save
21
+ redirect_to oauth_providers_path
22
+ else
23
+ render action: :new
24
+ end
25
+ end
26
+
27
+ def edit
28
+ @title = "Edit Provider"
29
+ @provider = Oauth::Provider.find(params[:id])
30
+ authorize! :update, @provider
31
+ end
32
+
33
+ def update
34
+ @provider = Oauth::Provider.find(params[:id])
35
+ authorize! :update, @provider
36
+
37
+ if @provider.update_attributes(params[:oauth_provider])
38
+ redirect_to oauth_providers_path
39
+ else
40
+ render action: :edit
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -4,14 +4,14 @@ class ProjectOptionsController < ApplicationController
4
4
 
5
5
 
6
6
  def update
7
- project.view_options = project.view_options.merge(params[:options])
7
+ project.props.merge! params[:options]
8
8
  project.save!
9
9
  head :ok
10
10
  end
11
11
 
12
12
 
13
13
  def destroy
14
- project.view_options = project.view_options.except(params[:key])
14
+ project.props.delete! params[:key]
15
15
  project.save!
16
16
  head :ok
17
17
  end
@@ -31,13 +31,13 @@ class ProjectsController < ApplicationController
31
31
  def new_from_github
32
32
  authorize! :create, Project
33
33
 
34
- existing_projects = Project.unscoped.where("extended_attributes->'git_location' LIKE '%github.com%'")
34
+ existing_projects = Project.unscoped.where("props->>'git.location' LIKE '%github.com%'")
35
35
  github_repos = Houston.benchmark "Fetching repos" do
36
36
  Houston.github.repos
37
37
  end
38
38
  @repos = github_repos.map do |repo|
39
39
  project = existing_projects.detect { |project|
40
- [repo.git_url, repo.ssh_url, repo.clone_url].member?(project.extended_attributes["git_location"]) }
40
+ [repo.git_url, repo.ssh_url, repo.clone_url].member?(project.props["git.location"]) }
41
41
  { name: repo.name,
42
42
  owner: repo.owner.login,
43
43
  full_name: repo.full_name,
@@ -60,7 +60,7 @@ class ProjectsController < ApplicationController
60
60
  name: title,
61
61
  slug: name,
62
62
  version_control_name: "Git",
63
- extended_attributes: {"git_location" => "git@github.com:#{repo}.git"})
63
+ props: {"git.location" => "git@github.com:#{repo}.git"})
64
64
  end
65
65
  end
66
66
 
@@ -75,12 +75,12 @@ class ReleasesController < ApplicationController
75
75
  @title = "Release #{@release.release_date.strftime("%b %-d")} • #{@project.name}"
76
76
 
77
77
  if request.format.oembed?
78
- render json: {
78
+ render json: MultiJson.dump({
79
79
  version: "1.0",
80
80
  type: "link",
81
- author_name: "#{@project.slug} / #{@release.environment_name}",
81
+ provider_name: "#{@project.slug} / #{@release.environment_name}",
82
82
  title: format_release_subject(@release),
83
- html: format_release_description(@release) }
83
+ html: format_release_description(@release) })
84
84
  end
85
85
  end
86
86
 
@@ -3,14 +3,14 @@ class UserOptionsController < ApplicationController
3
3
 
4
4
 
5
5
  def update
6
- current_user.view_options = current_user.view_options.merge(params[:options])
6
+ current_user.props.merge! params[:options]
7
7
  current_user.save!
8
8
  head :ok
9
9
  end
10
10
 
11
11
 
12
12
  def destroy
13
- current_user.view_options = current_user.view_options.except(params[:key])
13
+ current_user.props.delete! params[:key]
14
14
  current_user.save!
15
15
  head :ok
16
16
  end
@@ -44,7 +44,6 @@ class UsersController < ApplicationController
44
44
  User.invite!(params[:user])
45
45
  else
46
46
  @user.administrator = @administrator
47
- @user.skip_password = true
48
47
  @user.save!
49
48
  end
50
49
 
@@ -62,7 +61,7 @@ class UsersController < ApplicationController
62
61
 
63
62
  attributes = params[:user]
64
63
  attributes[:alias_emails] = attributes.fetch(:alias_emails, "").split.map(&:strip)
65
- attributes[:view_options] = @user.view_options.merge(attributes[:view_options] || {})
64
+ @user.props.merge! attributes.delete(:props) if attributes.key?(:props)
66
65
 
67
66
  if @user.update_attributes(attributes)
68
67
  redirect_to @user, notice: 'User was successfully updated.'
@@ -45,23 +45,69 @@ module ApplicationHelper
45
45
 
46
46
 
47
47
 
48
- def format_time(time)
48
+ def format_time(time, options={})
49
49
  if time.nil?
50
50
  date, time = ["", "Never"]
51
51
  elsif time.to_date == Date.today
52
- date, time = ["Today", time.strftime("%l:%M %p")]
52
+ date, time = [options[:today] ? "Today" : "", time.strftime("%l:%M %p")]
53
53
  elsif time.to_date == Date.today - 1
54
54
  date, time = ["Yesterday", time.strftime("%l:%M %p")]
55
55
  else
56
56
  date, time = [time.strftime("%b %e"), time.strftime("%l:%M %p")]
57
57
  end
58
58
 
59
- <<-HTML.html_safe
59
+ <<-HTML.strip.html_safe
60
60
  <span class="time-date">#{date}</span>
61
61
  <span class="time-time">#{time.gsub(" AM", "a").gsub(" PM", "p")}</span>
62
62
  HTML
63
63
  end
64
64
 
65
+ def format_boolean(boolean)
66
+ if boolean
67
+ '<i class="fa fa-check success"></i>'.html_safe
68
+ else
69
+ '<i class="fa fa-times failure"></i>'.html_safe
70
+ end
71
+ end
72
+
73
+ def format_job_state(job)
74
+ if job.in_progress?
75
+ '<i class="fa fa-spinner fa-pulse"></i>'.html_safe
76
+ elsif job.succeeded?
77
+ '<i class="fa fa-check success"></i>'.html_safe
78
+ else
79
+ '<i class="fa fa-times failure"></i>'.html_safe
80
+ end
81
+ end
82
+
83
+ MINUTE = 60
84
+ HOUR = MINUTE * 60
85
+ DAY = HOUR * 24
86
+
87
+ def format_duration(seconds)
88
+ if seconds.nil?
89
+ return "&mdash;".html_safe
90
+ elsif seconds < 1
91
+ "#{(seconds * 1000).floor}ms"
92
+ elsif seconds < MINUTE
93
+ "%.2f seconds" % seconds
94
+ elsif seconds < HOUR
95
+ format_duration_with_units(seconds / MINUTE, 'minute')
96
+ elsif seconds < DAY
97
+ format_duration_with_units(seconds / HOUR, 'hour')
98
+ else
99
+ format_duration_with_units(seconds / DAY, 'day')
100
+ end
101
+ end
102
+
103
+ def format_duration_with_units(quantity, unit)
104
+ quantity = quantity.floor
105
+ unit << 's' unless quantity == 1
106
+ "#{quantity} #{unit}"
107
+ end
108
+
109
+
110
+
65
111
  def format_date_with_year(date)
66
112
  return "" if date.nil?
67
113
  "#{date.strftime("%b %d")}<span class=\"year\">#{date.strftime("%Y")}</span>".html_safe
@@ -1,7 +1,7 @@
1
1
  module EmailHelper
2
2
 
3
3
  def render_scss(relative_path)
4
- asset = Rails.application.assets.find_asset(relative_path)
4
+ asset = sprockets_env.find_asset(relative_path)
5
5
  raise "Asset not found #{relative_path.inspect}" unless asset
6
6
  asset.to_s.html_safe
7
7
  end
@@ -10,4 +10,22 @@ module EmailHelper
10
10
  @for_email == true
11
11
  end
12
12
 
13
+ def sprockets_env
14
+ # In environments where assets.compile = false, Sprockets will no longer
15
+ # instantiate the Sprockets environment at Rails.application.assets.
16
+ #
17
+ # See how different gems worked around this change:
18
+ # https://github.com/Compass/compass-rails/issues/257#issuecomment-174819398
19
+ # https://github.com/wwidea/font-awesome-rails/pull/2
20
+ # https://github.com/rails/sprockets-rails/issues/311#issuecomment-172395232
21
+ #
22
+ # The last seems to be the recommended solution; but not all assets show up
23
+ # in the manifest; and it will still give an error ("manifest requires
24
+ # environment for compilation"). Therefore, we'll create the compilation
25
+ # environment for the sake of the mailer.
26
+ return Rails.application.assets if Rails.application.assets
27
+ return @sprockets_env if defined?(@sprockets_env)
28
+ @sprockets_env = Sprockets::Railtie.build_environment(Rails.application)
29
+ end
30
+
13
31
  end
@@ -10,7 +10,7 @@ module ReleaseHelper
10
10
 
11
11
  def format_release_description(release)
12
12
  ordered_by_tag(release.release_changes)
13
- .map { |change| "#{change.tag.name.upcase}&nbsp;&nbsp;&nbsp;#{change.description}" }
13
+ .map { |change| "#{change.tag.name.upcase}\t#{change.description}" }
14
14
  .join("\r\n")
15
15
  .html_safe
16
16
  end
@@ -35,36 +35,4 @@ module TicketHelper
35
35
  link_to "##{number}", goldmine_case_number_url(number), target: "_blank"
36
36
  end
37
37
 
38
-
39
-
40
- MINUTE = 60
41
- HOUR = MINUTE * 60
42
- DAY = HOUR * 24
43
-
44
- def format_duration(seconds)
45
- if seconds < HOUR
46
- format_duration_with_units(seconds / MINUTE, 'minute')
47
- elsif seconds < DAY
48
- format_duration_with_units(seconds / HOUR, 'hour')
49
- else
50
- format_duration_with_units(seconds / DAY, 'day')
51
- end
52
- end
53
-
54
- def format_duration_with_units(quantity, unit)
55
- quantity = quantity.floor
56
- unit << 's' unless quantity == 1
57
- "#{quantity} #{unit}"
58
- end
59
-
60
- def class_for_age(seconds)
61
- if seconds < 6.hours; 'infant'
62
- elsif seconds < 2.days; 'child'
63
- elsif seconds < 7.days; 'adult'
64
- elsif seconds < 4.weeks; 'senior'
65
- elsif seconds < 26.weeks; 'old'
66
- else 'ancient'
67
- end
68
- end
69
-
70
38
  end
@@ -4,11 +4,7 @@ class CacheKeyDependencies
4
4
  def self.for(*projects)
5
5
  projects = projects[0] if projects.length == 1 && projects[0].respond_to?(:each)
6
6
  projects.each do |project|
7
- begin
8
- self.new(project).perform!
9
- rescue StandardError => e
10
- Houston.report_exception(e)
11
- end
7
+ self.new(project).perform!
12
8
  end
13
9
  end
14
10
 
@@ -19,10 +15,9 @@ class CacheKeyDependencies
19
15
  def perform!
20
16
  KeyDependency.all.each do |dependency|
21
17
  version = ProjectDependency.new(project, dependency).version
22
- project.extended_attributes = project.extended_attributes.merge(
23
- "key_dependency.#{dependency.slug}" => version)
18
+ project.props["keyDependency.#{dependency.slug}"] = version
24
19
  end
25
- project.update_column :extended_attributes, project.extended_attributes
20
+ project.update_column :props, project.props.to_h
26
21
  end
27
22
 
28
23
  end
@@ -16,14 +16,14 @@ class ViewMailer < ActionMailer::Base
16
16
 
17
17
  class_attribute :stylesheets
18
18
  self.stylesheets = %w{
19
- core/colors.scss.erb
20
- core/avatars.scss
21
- core/scores.scss
22
- application/emoji.scss
23
- application/markdown.scss
24
- application/test_run.scss
25
- application/releases.scss
26
- application/follow_up.scss
19
+ houston/core/colors.scss.erb
20
+ houston/core/avatars.scss
21
+ houston/core/scores.scss
22
+ houston/application/emoji.scss
23
+ houston/application/markdown.scss
24
+ houston/application/test_run.scss
25
+ houston/application/releases.scss
26
+ houston/application/follow_up.scss
27
27
  }
28
28
 
29
29
  helper_method :can?, :cannot?, :current_ability, :stylesheets
@@ -0,0 +1,54 @@
1
+ class Authorization < ActiveRecord::Base
2
+
3
+ belongs_to :provider, class_name: "Oauth::Provider"
4
+
5
+ validates :name, :provider_id, presence: true
6
+
7
+ def self.[](name)
8
+ find_by(name: name)
9
+ end
10
+
11
+ def self.set_access_token!(params)
12
+ Authorization.find(params.fetch(:state)).tap do |authorization|
13
+ authorization.get_access_token! params.fetch(:code)
14
+ end
15
+ end
16
+
17
+ def granted?
18
+ expires_in.present?
19
+ end
20
+
21
+ def authorize_url(params={})
22
+ provider.authorize_url params.merge(scope: scope, state: id)
23
+ end
24
+
25
+ def refresh!
26
+ merge! provider.refresh_access_token(self)
27
+ end
28
+
29
+ def get_access_token!(code)
30
+ merge! provider.redeem_access_token(code)
31
+ end
32
+
33
+ def access_token
34
+ refresh! if expired?
35
+ super
36
+ end
37
+
38
+ def expired?
39
+ return false unless granted?
40
+ Time.now >= expires_at
41
+ end
42
+
43
+ private
44
+
45
+ def merge!(new_token)
46
+ self.access_token = new_token.token
47
+ self.expires_in = new_token.expires_in
48
+ self.expires_at = expires_in.seconds.from_now
49
+ self.refresh_token = new_token.refresh_token if new_token.respond_to?(:refresh_token)
50
+ self.secret = new_token.secret if new_token.respond_to?(:secret)
51
+ save!
52
+ end
53
+
54
+ end