plan_my_stuff 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/CONFIGURATION.md +53 -1
  4. data/README.md +2 -30
  5. data/app/controllers/plan_my_stuff/comments_controller.rb +21 -10
  6. data/app/controllers/plan_my_stuff/issues/approvals_controller.rb +13 -4
  7. data/app/controllers/plan_my_stuff/issues/closures_controller.rb +12 -6
  8. data/app/controllers/plan_my_stuff/issues/links_controller.rb +14 -8
  9. data/app/controllers/plan_my_stuff/issues/takes_controller.rb +19 -17
  10. data/app/controllers/plan_my_stuff/issues/viewers_controller.rb +15 -9
  11. data/app/controllers/plan_my_stuff/issues/waitings_controller.rb +14 -8
  12. data/app/controllers/plan_my_stuff/issues_controller.rb +19 -5
  13. data/app/controllers/plan_my_stuff/labels_controller.rb +14 -8
  14. data/app/controllers/plan_my_stuff/project_items/assignments_controller.rb +6 -0
  15. data/app/controllers/plan_my_stuff/project_items/statuses_controller.rb +3 -0
  16. data/app/controllers/plan_my_stuff/project_items_controller.rb +11 -4
  17. data/app/controllers/plan_my_stuff/projects_controller.rb +14 -0
  18. data/app/controllers/plan_my_stuff/testing_project_items/results_controller.rb +3 -0
  19. data/app/controllers/plan_my_stuff/testing_project_items_controller.rb +5 -0
  20. data/app/controllers/plan_my_stuff/testing_projects_controller.rb +12 -0
  21. data/app/views/plan_my_stuff/issues/index.html.erb +1 -1
  22. data/app/views/plan_my_stuff/issues/partials/_approvals.html.erb +5 -5
  23. data/app/views/plan_my_stuff/issues/partials/_form.html.erb +1 -1
  24. data/app/views/plan_my_stuff/issues/partials/_links.html.erb +3 -3
  25. data/app/views/plan_my_stuff/issues/partials/_viewers.html.erb +2 -2
  26. data/app/views/plan_my_stuff/issues/show.html.erb +8 -8
  27. data/app/views/plan_my_stuff/projects/show.html.erb +3 -1
  28. data/app/views/plan_my_stuff/testing_projects/partials/_item.html.erb +1 -1
  29. data/lib/generators/plan_my_stuff/install/templates/initializer.rb +6 -0
  30. data/lib/plan_my_stuff/configuration.rb +61 -5
  31. data/lib/plan_my_stuff/issue.rb +91 -15
  32. data/lib/plan_my_stuff/repo.rb +28 -0
  33. data/lib/plan_my_stuff/version.rb +1 -1
  34. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe4f92dc92eca010b6fc7f53f4ce7701c6852420c9a537fdf0902e591c3309ad
4
- data.tar.gz: b167fd42a3b5a37fc897bebf8f3696ed2cd863ac7049359445a329d9a7861988
3
+ metadata.gz: 15988155f3d1798b5b0f43cbb1597f7e8b7ed881feb3db2504da7ecd74ab9c59
4
+ data.tar.gz: 35f298dce675a86ca15153a354411c23806e8420374fe5eb4fd7d2c392e0ed9d
5
5
  SHA512:
6
- metadata.gz: 746332e19a507f81dc0ee902a87664dcb0a55e3170d688d878b14faf508bfb67cc5dd3236a4961c6b15768fd47e7489b6b0cdbe5bdd5d328bcf9836f805d561d
7
- data.tar.gz: 26a20b3318c99f34360bba90eee5698242f4043043991bf53d59e55b2507516452a5094c14366b19f6f53a140ff0b8a41f326a7048c13c4077f447eb2a083513
6
+ metadata.gz: 838ebf5cb77a3467fb291d76acd9b2ded4cc40d88e65673ca41374324736c6cdc11e5bbc0ed7e04eaf0c0bb5ac4f799c3052379cdc87edcd7343dc30be370059
7
+ data.tar.gz: b30d829c2255b61485c72d639992f1095f9726b7e6d8952114eef2e44c91f1016c0f05bd3abd238faf0be83a37c8b75ef492208351d33cbbe1f2f689270e7614
data/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.19.0
4
+
5
+ ### Added
6
+
7
+ - Every controller action now yields its primary object to a block when subclassed, so consumers can do
8
+ `super do |obj| ... end` to wedge in audit-log / instrumentation without rewriting the action. Webhook
9
+ controllers yield `(payload, result)`. See [CONFIGURATION.md](CONFIGURATION.md).
10
+
11
+ ## 0.18.0
12
+
13
+ ### Breaking
14
+
15
+ - `PMS::Issue#to_param` now returns `"Nickname-number"` (e.g. `"Rawr-1234"`) instead of the default ActiveModel id.
16
+ Single-issue URLs change from `/issues/1234?repo=rawr` to `/issues/Rawr-1234`. Consuming apps using
17
+ `youtrack_issue_path(@issue)` work natively; any hand-rolled URLs that passed `@issue.number` plus a `repo:`
18
+ query param must switch to `@issue` (or `@issue.to_param`). The mounted engine's controllers and views have
19
+ been updated to the new shape, as has the markdown link embedded in the GitHub issue body via
20
+ `Issue#user_link`.
21
+
22
+ ### Added
23
+
24
+ - `config.repo_nicknames` (default `{}`) -- Symbol-keyed map from repo key to the human-readable label used as
25
+ the `Issue#to_param` prefix. Missing keys fall back to `key.to_s.titleize`, so `:rawr` -> `"Rawr"` is free;
26
+ only divergent ones (e.g. `safety: 'Compliance'`) need an entry.
27
+ - `Configuration#repo_nickname_for(key)` accessor, `Repo#nickname`, and `Repo.from_nickname!` for the inverse
28
+ lookup used by `Issue.from_param`.
29
+ - `Issue#to_param` and `Issue.from_param` -- the latter parses `"Nickname-1234"` back into `[Repo, Integer]`.
30
+ - `Issue.find` first arg now accepts a nickname-id String (e.g. `"Rawr-1234"`) in addition to Integer / digit-
31
+ String + `repo:` kwarg. The nickname form ignores `repo:`.
32
+
3
33
  ## 0.17.0
4
34
 
5
35
  ### Added
data/CONFIGURATION.md CHANGED
@@ -37,13 +37,17 @@ config.organization = 'YourOrg'
37
37
  |---|---|---|---|
38
38
  | `repos` | `Hash{Symbol => String}` | `{}` | Named repo configs mapping a key to an `Org/Repo` string. |
39
39
  | `default_repo` | `Symbol, nil` | `nil` | Repo key used when callers omit the `repo:` param. |
40
+ | `repo_nicknames` | `Hash{Symbol => String}` | `{}` | `Issue#to_param` prefix override (default `key.titleize`). |
40
41
 
41
42
  ```ruby
42
43
  config.repos = { element: 'YourOrg/Element', underwriter: 'YourOrg/Underwriter' }
43
44
  config.default_repo = :element
45
+ config.repo_nicknames = { safety: 'Compliance' } # :element -> "Element", :underwriter -> "Underwriter" come free
44
46
  ```
45
47
 
46
- `repos` can be mutated via `config.repos[:key] = '...'` or set via `config.repos = { key: 'MyOrg/MyRepo' }`
48
+ `repos` can be mutated via `config.repos[:key] = '...'` or set via `config.repos = { key: 'MyOrg/MyRepo' }`.
49
+ `Issue#to_param` then returns `"Element-1234"` / `"Compliance-567"`, encoding both repo and number in a single
50
+ URL segment so `youtrack_issue_path(@issue)` works without a `repo:` query param.
47
51
 
48
52
  ## Projects
49
53
 
@@ -370,6 +374,54 @@ Controllable keys (with gem defaults):
370
374
  | `:'webhooks/github'` | `plan_my_stuff/webhooks/github` |
371
375
  | `:'webhooks/aws'` | `plan_my_stuff/webhooks/aws` |
372
376
 
377
+ ### Customizing per-action behavior
378
+
379
+ Every mounted route resolves its controller through `config.controller_for(key)`. Subclass a gem controller in your
380
+ own app and register it to wedge in `before_action`s, authentication, or response tweaks - no monkey patching:
381
+
382
+ ```ruby
383
+ # app/controllers/my_app/issues_controller.rb
384
+ class MyApp::IssuesController < PMS::IssuesController
385
+ before_action :authenticate_user!
386
+ before_action :authorize_ticket_access
387
+ end
388
+ ```
389
+
390
+ ```ruby
391
+ # config/initializers/plan_my_stuff.rb
392
+ PlanMyStuff.configure do |config|
393
+ config.controllers[:issues] = 'my_app/issues'
394
+ end
395
+ ```
396
+
397
+ For per-action side effects (audit log, metrics, notifications) without rewriting the action, yielding actions
398
+ pass their primary object to an optional block on the happy path. Call `super do |obj| ... end` from a subclass:
399
+
400
+ ```ruby
401
+ class MyApp::IssuesController < PMS::IssuesController
402
+ def create
403
+ super do |issue|
404
+ AuditLog.record(actor: current_user, action: :issue_created, target: issue)
405
+ end
406
+ end
407
+
408
+ def update
409
+ super do |issue|
410
+ AuditLog.record(actor: current_user, action: :issue_updated, target: issue)
411
+ end
412
+ end
413
+ end
414
+ ```
415
+
416
+ Contract:
417
+
418
+ - The yield fires on the happy path, after the model load / write succeeds and before the gem's default
419
+ `flash[:success]` + `redirect_to`. Error branches, `not_found`, and authorization redirects do not yield.
420
+ - Read actions (`index`, `show`, `new`, `edit`) yield before the implicit render; `index` yields the collection,
421
+ the rest yield the single object.
422
+ - If your block calls `render` or `redirect_to`, the gem's default response is skipped (the action checks
423
+ `performed?`), so you can fully replace the response from the block.
424
+
373
425
  ### Parent controller
374
426
 
375
427
  | Option | Type | Default | Description |
data/README.md CHANGED
@@ -787,34 +787,6 @@ All routes are under the engine's mount point. Each group can be disabled via `c
787
787
 
788
788
  ## Controller overrides
789
789
 
790
- Every mounted route resolves its controller through `config.controller_for(key)`, which looks up `config.controllers[key]` and falls back to the gem default. Subclass a gem controller in your own app and register it to wedge in before_actions, authentication, or response tweaks — no monkey patching.
791
-
792
- ```ruby
793
- # app/controllers/my_app/issues_controller.rb
794
- class MyApp::IssuesController < PMS::IssuesController
795
- before_action :authenticate_user!
796
- before_action :authorize_ticket_access
797
- end
798
- ```
799
-
800
- ```ruby
801
- # config/initializers/plan_my_stuff.rb
802
- PlanMyStuff.configure do |config|
803
- config.controllers['issues'] = 'my_app/issues'
804
- end
805
- ```
806
-
807
- Overridable keys (see `PMS::Configuration::DEFAULT_CONTROLLERS`):
808
-
809
- ```text
810
- issues issues/closures
811
- comments issues/viewers
812
- labels issues/takes
813
- projects issues/waitings
814
- project_items issues/links
815
- testing_projects issues/approvals
816
- testing_project_items project_items/statuses
817
- webhooks/github project_items/assignments
818
- webhooks/aws testing_project_items/results
819
- ```
790
+ See [CONFIGURATION.md](CONFIGURATION.md#controller-overrides) for the full walkthrough including subclassing,
791
+ per-route registration, and the per-action block hook.
820
792
 
@@ -4,9 +4,9 @@ module PlanMyStuff
4
4
  class CommentsController < PlanMyStuff::ApplicationController
5
5
  # POST /issues/:issue_id/comments
6
6
  def create
7
- @issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
7
+ @issue = PlanMyStuff::Issue.find(params[:issue_id])
8
8
 
9
- PlanMyStuff::Comment.create!(
9
+ comment = PlanMyStuff::Comment.create!(
10
10
  issue: @issue,
11
11
  body: comment_params[:body],
12
12
  user: pms_current_user,
@@ -14,12 +14,15 @@ module PlanMyStuff
14
14
  waiting_on_reply: comment_params[:waiting_on_reply] == '1',
15
15
  )
16
16
 
17
+ yield(comment) if block_given?
18
+ return if performed?
19
+
17
20
  flash[:success] = 'Comment was successfully created.'
18
- redirect_to(plan_my_stuff.issue_path(@issue.number, repo: @issue.repo.full_name))
21
+ redirect_to(plan_my_stuff.issue_path(@issue))
19
22
  rescue PlanMyStuff::LockedIssueError => e
20
23
  pms_handle_rescue(e)
21
24
  flash[:error] = 'This issue is locked; no new comments can be posted.'
22
- redirect_to(plan_my_stuff.issue_path(@issue.number, repo: @issue.repo.full_name))
25
+ redirect_to(plan_my_stuff.issue_path(@issue))
23
26
  end
24
27
 
25
28
  # GET /issues/:issue_id/comments/:id/edit
@@ -27,9 +30,14 @@ module PlanMyStuff
27
30
  load_comment
28
31
  return unless @comment
29
32
  return redirect_to_issue if issue_body_comment?
30
- return if can_edit?(@comment)
31
33
 
32
- redirect_to_unauthorized(plan_my_stuff.issue_path(@issue.number, repo: @issue.repo.full_name))
34
+ unless can_edit?(@comment)
35
+ redirect_to_unauthorized(plan_my_stuff.issue_path(@issue))
36
+
37
+ return
38
+ end
39
+
40
+ yield(@comment) if block_given?
33
41
  end
34
42
 
35
43
  # PATCH/PUT /issues/:issue_id/comments/:id
@@ -39,7 +47,7 @@ module PlanMyStuff
39
47
  return redirect_to_issue if issue_body_comment?
40
48
 
41
49
  unless can_edit?(@comment)
42
- redirect_to_unauthorized(plan_my_stuff.issue_path(@issue.number, repo: @issue.repo.full_name))
50
+ redirect_to_unauthorized(plan_my_stuff.issue_path(@issue))
43
51
 
44
52
  return
45
53
  end
@@ -49,8 +57,11 @@ module PlanMyStuff
49
57
 
50
58
  @comment.update!(**update_attrs, user: pms_current_user)
51
59
 
60
+ yield(@comment) if block_given?
61
+ return if performed?
62
+
52
63
  flash[:success] = 'Comment was successfully updated.'
53
- redirect_to(plan_my_stuff.issue_path(@issue.number, repo: @issue.repo.full_name))
64
+ redirect_to(plan_my_stuff.issue_path(@issue))
54
65
  rescue PlanMyStuff::StaleObjectError => e
55
66
  pms_handle_rescue(e)
56
67
  flash.now[:error] = 'Comment was modified by someone else. Please review the latest changes and try again.'
@@ -69,7 +80,7 @@ module PlanMyStuff
69
80
  # @return [void]
70
81
  #
71
82
  def load_comment
72
- @issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
83
+ @issue = PlanMyStuff::Issue.find(params[:issue_id])
73
84
  @comment = PlanMyStuff::Comment.find(params[:id].to_i, issue: @issue)
74
85
  end
75
86
 
@@ -96,7 +107,7 @@ module PlanMyStuff
96
107
 
97
108
  # @return [void]
98
109
  def redirect_to_issue
99
- redirect_to(plan_my_stuff.issue_path(@issue.number, repo: @issue.repo.full_name))
110
+ redirect_to(plan_my_stuff.issue_path(@issue))
100
111
  end
101
112
  end
102
113
  end
@@ -23,9 +23,12 @@ module PlanMyStuff
23
23
  return
24
24
  end
25
25
 
26
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
26
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
27
27
  issue.request_approvals!(user_ids: user_ids, user: pms_current_user)
28
28
 
29
+ yield(issue) if block_given?
30
+ return if performed?
31
+
29
32
  flash[:success] = 'Approvers were successfully added.'
30
33
  redirect_to(show_path)
31
34
  rescue PlanMyStuff::AuthorizationError, PlanMyStuff::ValidationError => e
@@ -44,7 +47,7 @@ module PlanMyStuff
44
47
  return
45
48
  end
46
49
 
47
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
50
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
48
51
  caller_id = pms_current_user.present? ? PlanMyStuff::UserResolver.user_id(pms_current_user) : nil
49
52
 
50
53
  case status
@@ -71,6 +74,9 @@ module PlanMyStuff
71
74
  flash[:success] = 'Response revoked.'
72
75
  end
73
76
 
77
+ yield(issue) if block_given?
78
+ return if performed?
79
+
74
80
  redirect_to(show_path)
75
81
  rescue PlanMyStuff::AuthorizationError, PlanMyStuff::ValidationError => e
76
82
  pms_handle_rescue(e)
@@ -85,9 +91,12 @@ module PlanMyStuff
85
91
  return
86
92
  end
87
93
 
88
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
94
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
89
95
  issue.remove_approvers!(user_ids: [params[:id].to_i], user: pms_current_user)
90
96
 
97
+ yield(issue) if block_given?
98
+ return if performed?
99
+
91
100
  flash[:success] = 'Approver was successfully removed.'
92
101
  redirect_to(show_path)
93
102
  rescue PlanMyStuff::AuthorizationError, PlanMyStuff::ValidationError => e
@@ -105,7 +114,7 @@ module PlanMyStuff
105
114
 
106
115
  # @return [String]
107
116
  def show_path
108
- plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo])
117
+ plan_my_stuff.issue_path(params[:issue_id])
109
118
  end
110
119
  end
111
120
  end
@@ -11,28 +11,34 @@ module PlanMyStuff
11
11
  class ClosuresController < PlanMyStuff::ApplicationController
12
12
  # POST /issues/:issue_id/closure
13
13
  def create
14
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
14
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
15
15
  issue.update!(state: :closed)
16
16
 
17
+ yield(issue) if block_given?
18
+ return if performed?
19
+
17
20
  flash[:success] = 'Issue was successfully closed.'
18
- redirect_to(plan_my_stuff.issue_path(issue.number, repo: issue.repo.full_name))
21
+ redirect_to(plan_my_stuff.issue_path(issue))
19
22
  rescue PlanMyStuff::Error, ArgumentError => e
20
23
  pms_handle_rescue(e)
21
24
  flash[:error] = e.message
22
- redirect_to(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
25
+ redirect_to(plan_my_stuff.issue_path(params[:issue_id]))
23
26
  end
24
27
 
25
28
  # DELETE /issues/:issue_id/closure
26
29
  def destroy
27
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
30
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
28
31
  issue.update!(state: :open)
29
32
 
33
+ yield(issue) if block_given?
34
+ return if performed?
35
+
30
36
  flash[:success] = 'Issue was successfully reopened.'
31
- redirect_to(plan_my_stuff.issue_path(issue.number, repo: issue.repo.full_name))
37
+ redirect_to(plan_my_stuff.issue_path(issue))
32
38
  rescue PlanMyStuff::Error, ArgumentError => e
33
39
  pms_handle_rescue(e)
34
40
  flash[:error] = e.message
35
- redirect_to(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
41
+ redirect_to(plan_my_stuff.issue_path(params[:issue_id]))
36
42
  end
37
43
  end
38
44
  end
@@ -21,38 +21,44 @@ module PlanMyStuff
21
21
  def create
22
22
  type = link_params[:type].to_s
23
23
  unless dispatch_allowed?(type, :add)
24
- redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
24
+ redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id]))
25
25
  return
26
26
  end
27
27
 
28
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
28
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
29
29
  link = add_link(issue, type)
30
30
 
31
+ yield(issue) if block_given?
32
+ return if performed?
33
+
31
34
  flash[:success] = "Linked #{link}"
32
- redirect_to(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
35
+ redirect_to(plan_my_stuff.issue_path(issue))
33
36
  rescue PlanMyStuff::ValidationError, ActiveModel::ValidationError, ArgumentError => e
34
37
  pms_handle_rescue(e)
35
38
  flash[:error] = e.message
36
- redirect_to(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
39
+ redirect_to(plan_my_stuff.issue_path(params[:issue_id]))
37
40
  end
38
41
 
39
42
  # DELETE /issues/:issue_id/links/:id
40
43
  def destroy
41
44
  type, repo, number = parse_composite_id(params[:id])
42
45
  unless dispatch_allowed?(type, :remove)
43
- redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
46
+ redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id]))
44
47
  return
45
48
  end
46
49
 
47
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
50
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
48
51
  remove_link(issue, type, repo: repo, number: number)
49
52
 
53
+ yield(issue) if block_given?
54
+ return if performed?
55
+
50
56
  flash[:success] = "Unlinked #{repo}##{number}"
51
- redirect_to(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
57
+ redirect_to(plan_my_stuff.issue_path(issue))
52
58
  rescue PlanMyStuff::ValidationError, ActiveModel::ValidationError, ArgumentError => e
53
59
  pms_handle_rescue(e)
54
60
  flash[:error] = e.message
55
- redirect_to(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
61
+ redirect_to(plan_my_stuff.issue_path(params[:issue_id]))
56
62
  end
57
63
 
58
64
  private
@@ -11,37 +11,35 @@ module PlanMyStuff
11
11
 
12
12
  # POST /issues/:issue_id/take
13
13
  def create
14
- issue_number = params[:issue_id].to_i
15
- repo = params[:repo]
16
-
17
- issue = PlanMyStuff::Issue.find(issue_number, repo: repo)
14
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
18
15
  guard_already_taken!(issue)
19
16
 
20
- project_item = PlanMyStuff::Pipeline::IssueLinker.find_project_item(issue_number)
17
+ project_item = PlanMyStuff::Pipeline::IssueLinker.find_project_item(issue.number)
21
18
  project_item ||= add_to_pipeline(issue)
22
19
 
23
20
  PlanMyStuff::Pipeline.take!(project_item)
24
21
  assign_current_user(project_item)
25
- flash[:success] ||= "Issue ##{issue_number} taken."
26
22
 
27
- redirect_to(plan_my_stuff.issue_path(issue_number, repo: repo))
23
+ yield(project_item) if block_given?
24
+ return if performed?
25
+
26
+ flash[:success] ||= "Issue ##{issue.number} taken."
27
+
28
+ redirect_to(plan_my_stuff.issue_path(issue))
28
29
  rescue ArgumentError, PlanMyStuff::Error => e
29
30
  pms_handle_rescue(e)
30
31
  flash[:error] = e.message
31
- redirect_to(plan_my_stuff.issue_path(issue_number, repo: repo))
32
+ redirect_to(plan_my_stuff.issue_path(params[:issue_id]))
32
33
  end
33
34
 
34
35
  # DELETE /issues/:issue_id/take
35
36
  def destroy
36
- issue_number = params[:issue_id].to_i
37
- repo = params[:repo]
38
-
39
- issue = PlanMyStuff::Issue.find(issue_number, repo: repo)
37
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
40
38
  login = current_user_login
41
39
  guard_release!(issue, login)
42
40
 
43
41
  remaining = issue.assignees - [login]
44
- project_item = PlanMyStuff::Pipeline::IssueLinker.find_project_item(issue_number)
42
+ project_item = PlanMyStuff::Pipeline::IssueLinker.find_project_item(issue.number)
45
43
 
46
44
  if project_item.present?
47
45
  if remaining.empty?
@@ -54,12 +52,16 @@ module PlanMyStuff
54
52
  issue.update!(assignees: remaining)
55
53
  end
56
54
 
57
- flash[:success] = "Issue ##{issue_number} released."
58
- redirect_to(plan_my_stuff.issue_path(issue_number, repo: repo))
55
+ yielded = project_item.presence || issue
56
+ yield(yielded) if block_given?
57
+ return if performed?
58
+
59
+ flash[:success] = "Issue ##{issue.number} released."
60
+ redirect_to(plan_my_stuff.issue_path(issue))
59
61
  rescue ArgumentError, PlanMyStuff::Error => e
60
62
  pms_handle_rescue(e)
61
63
  flash[:error] = e.message
62
- redirect_to(plan_my_stuff.issue_path(issue_number, repo: repo))
64
+ redirect_to(plan_my_stuff.issue_path(params[:issue_id]))
63
65
  end
64
66
 
65
67
  private
@@ -72,7 +74,7 @@ module PlanMyStuff
72
74
  return if support_user?
73
75
 
74
76
  redirect_to_unauthorized(
75
- plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]),
77
+ plan_my_stuff.issue_path(params[:issue_id]),
76
78
  )
77
79
  end
78
80
 
@@ -12,44 +12,50 @@ module PlanMyStuff
12
12
  # POST /issues/:issue_id/viewers
13
13
  def create
14
14
  unless support_user?
15
- redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
15
+ redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id]))
16
16
  return
17
17
  end
18
18
 
19
19
  viewer_ids = parse_viewer_ids(params[:viewer_ids])
20
20
  if viewer_ids.blank?
21
21
  flash[:error] = 'No valid viewer IDs provided.'
22
- redirect_to(plan_my_stuff.edit_issue_path(params[:issue_id], repo: params[:repo]))
22
+ redirect_to(plan_my_stuff.edit_issue_path(params[:issue_id]))
23
23
  return
24
24
  end
25
25
 
26
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
26
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
27
27
  issue.add_viewers!(user_ids: viewer_ids, user: pms_current_user)
28
28
 
29
+ yield(issue) if block_given?
30
+ return if performed?
31
+
29
32
  flash[:success] = 'Viewers were successfully added.'
30
- redirect_to(plan_my_stuff.edit_issue_path(params[:issue_id], repo: params[:repo]))
33
+ redirect_to(plan_my_stuff.edit_issue_path(params[:issue_id]))
31
34
  rescue PlanMyStuff::Error, Octokit::Error => e
32
35
  pms_handle_rescue(e)
33
36
  flash[:error] = e.message
34
- redirect_to(plan_my_stuff.edit_issue_path(params[:issue_id], repo: params[:repo]))
37
+ redirect_to(plan_my_stuff.edit_issue_path(params[:issue_id]))
35
38
  end
36
39
 
37
40
  # DELETE /issues/:issue_id/viewers/:id
38
41
  def destroy
39
42
  unless support_user?
40
- redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
43
+ redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id]))
41
44
  return
42
45
  end
43
46
 
44
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
47
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
45
48
  issue.remove_viewers!(user_ids: [params[:id].to_i], user: pms_current_user)
46
49
 
50
+ yield(issue) if block_given?
51
+ return if performed?
52
+
47
53
  flash[:success] = 'Viewer was successfully removed.'
48
- redirect_to(plan_my_stuff.edit_issue_path(params[:issue_id], repo: params[:repo]))
54
+ redirect_to(plan_my_stuff.edit_issue_path(params[:issue_id]))
49
55
  rescue PlanMyStuff::Error, Octokit::Error => e
50
56
  pms_handle_rescue(e)
51
57
  flash[:error] = e.message
52
- redirect_to(plan_my_stuff.edit_issue_path(params[:issue_id], repo: params[:repo]))
58
+ redirect_to(plan_my_stuff.edit_issue_path(params[:issue_id]))
53
59
  end
54
60
  end
55
61
  end
@@ -12,37 +12,43 @@ module PlanMyStuff
12
12
  # POST /issues/:issue_id/waiting
13
13
  def create
14
14
  unless support_user?
15
- redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
15
+ redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id]))
16
16
  return
17
17
  end
18
18
 
19
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
19
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
20
20
  issue.enter_waiting_on_user!(user: pms_current_user)
21
21
 
22
+ yield(issue) if block_given?
23
+ return if performed?
24
+
22
25
  flash[:success] = 'Issue marked as waiting on user reply.'
23
- redirect_to(plan_my_stuff.issue_path(issue.number, repo: issue.repo.full_name))
26
+ redirect_to(plan_my_stuff.issue_path(issue))
24
27
  rescue PlanMyStuff::Error, ArgumentError => e
25
28
  pms_handle_rescue(e)
26
29
  flash[:error] = e.message
27
- redirect_to(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
30
+ redirect_to(plan_my_stuff.issue_path(params[:issue_id]))
28
31
  end
29
32
 
30
33
  # DELETE /issues/:issue_id/waiting
31
34
  def destroy
32
35
  unless support_user?
33
- redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
36
+ redirect_to_unauthorized(plan_my_stuff.issue_path(params[:issue_id]))
34
37
  return
35
38
  end
36
39
 
37
- issue = PlanMyStuff::Issue.find(params[:issue_id].to_i, repo: params[:repo])
40
+ issue = PlanMyStuff::Issue.find(params[:issue_id])
38
41
  issue.clear_waiting_on_user!
39
42
 
43
+ yield(issue) if block_given?
44
+ return if performed?
45
+
40
46
  flash[:success] = 'Waiting-on-user state cleared.'
41
- redirect_to(plan_my_stuff.issue_path(issue.number, repo: issue.repo.full_name))
47
+ redirect_to(plan_my_stuff.issue_path(issue))
42
48
  rescue PlanMyStuff::Error, ArgumentError => e
43
49
  pms_handle_rescue(e)
44
50
  flash[:error] = e.message
45
- redirect_to(plan_my_stuff.issue_path(params[:issue_id], repo: params[:repo]))
51
+ redirect_to(plan_my_stuff.issue_path(params[:issue_id]))
46
52
  end
47
53
  end
48
54
  end
@@ -17,11 +17,15 @@ module PlanMyStuff
17
17
  page: @page,
18
18
  per_page: @per_page,
19
19
  )
20
+
21
+ yield(@issues) if block_given?
20
22
  end
21
23
 
22
24
  # GET /issues/new
23
25
  def new
24
26
  @issue = PlanMyStuff::Issue.new
27
+
28
+ yield(@issue) if block_given?
25
29
  end
26
30
 
27
31
  # POST /issues
@@ -33,8 +37,11 @@ module PlanMyStuff
33
37
  user: pms_current_user,
34
38
  )
35
39
 
40
+ yield(@issue) if block_given?
41
+ return if performed?
42
+
36
43
  flash[:success] = 'Issue was successfully created.'
37
- redirect_to(plan_my_stuff.issue_path(@issue.number, repo: @issue.repo.full_name))
44
+ redirect_to(plan_my_stuff.issue_path(@issue))
38
45
  rescue PlanMyStuff::ValidationError => e
39
46
  pms_handle_rescue(e)
40
47
  @issue = PlanMyStuff::Issue.new(title: issue_params[:title], body: issue_params[:body])
@@ -44,22 +51,26 @@ module PlanMyStuff
44
51
 
45
52
  # GET /issues/:id
46
53
  def show
47
- @issue = PlanMyStuff::Issue.find(params[:id].to_i, repo: params[:repo])
54
+ @issue = PlanMyStuff::Issue.find(params[:id])
48
55
  @comments = filter_visible_comments(@issue.comments)
49
56
  @current_user_id = pms_current_user.present? ? PlanMyStuff::UserResolver.user_id(pms_current_user) : nil
50
57
  @current_user_login = PlanMyStuff.configuration.github_login_for[@current_user_id]
51
58
  @pipeline_enabled = PlanMyStuff.configuration.pipeline_enabled
52
59
  @pipeline_item = load_pipeline_item(@issue.number) if @pipeline_enabled
60
+
61
+ yield(@issue) if block_given?
53
62
  end
54
63
 
55
64
  # GET /issues/:id/edit
56
65
  def edit
57
- @issue = PlanMyStuff::Issue.find(params[:id].to_i, repo: params[:repo])
66
+ @issue = PlanMyStuff::Issue.find(params[:id])
67
+
68
+ yield(@issue) if block_given?
58
69
  end
59
70
 
60
71
  # PATCH/PUT /issues/:id
61
72
  def update
62
- @issue = PlanMyStuff::Issue.find(params[:id].to_i, repo: params[:repo])
73
+ @issue = PlanMyStuff::Issue.find(params[:id])
63
74
 
64
75
  @issue.update!(
65
76
  title: issue_params[:title],
@@ -67,8 +78,11 @@ module PlanMyStuff
67
78
  labels: parse_labels(issue_params[:labels]),
68
79
  )
69
80
 
81
+ yield(@issue) if block_given?
82
+ return if performed?
83
+
70
84
  flash[:success] = 'Issue was successfully updated.'
71
- redirect_to(plan_my_stuff.issue_path(@issue.number, repo: @issue.repo.full_name))
85
+ redirect_to(plan_my_stuff.issue_path(@issue))
72
86
  rescue PlanMyStuff::StaleObjectError => e
73
87
  pms_handle_rescue(e)
74
88
  flash.now[:error] = 'Issue was modified by someone else. Please review the latest changes and try again.'