Skip to content

Commit f49794b

Browse files
Ticket to claim WCA ID
1 parent bdd75a8 commit f49794b

File tree

24 files changed

+614
-38
lines changed

24 files changed

+614
-38
lines changed

app/assets/javascripts/users.js

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,6 @@ onPage('users#edit, users#update', function() {
66
$('.form-group.user_avatar').toggle(!toDelete);
77
}).trigger("change");
88

9-
var $approve_wca_id = $('#approve-wca-id');
10-
var $unconfirmed_wca_id = $("#user_unconfirmed_wca_id");
11-
var $unconfirmed_wca_id_profile_link = $("a#unconfirmed-wca-id-profile");
12-
$approve_wca_id.on("click", function(e) {
13-
$("#user_wca_id").val($unconfirmed_wca_id.val());
14-
$unconfirmed_wca_id.val('');
15-
$unconfirmed_wca_id.trigger('input');
16-
});
17-
$unconfirmed_wca_id.on("input", function(e) {
18-
var unconfirmed_wca_id = $unconfirmed_wca_id.val();
19-
$approve_wca_id.prop("disabled", !unconfirmed_wca_id);
20-
$unconfirmed_wca_id_profile_link.parent().toggle(!!unconfirmed_wca_id);
21-
$unconfirmed_wca_id_profile_link.attr('href', "/persons/" + unconfirmed_wca_id);
22-
});
23-
$unconfirmed_wca_id.trigger('input');
24-
259
// Change the 'section' parameter when a tab is switched.
2610
$('a[data-toggle="tab"]').on('show.bs.tab', function() {
2711
var section = $(this).attr('href').slice(1);

app/controllers/accounts/registrations_controller.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
# frozen_string_literal: true
22

33
class Accounts::RegistrationsController < Devise::RegistrationsController
4-
# We delegate the create method to the super class
5-
# rubocop:disable Rails/LexicallyScopedActionFilter
64
before_action :check_captcha, only: [:create]
7-
# rubocop:enable Rails/LexicallyScopedActionFilter
5+
86
protected def after_update_path_for(_resource)
97
edit_user_registration_path
108
end
119

10+
def create
11+
super do |resource|
12+
next unless resource.persisted?
13+
next if resource.delegate_to_handle_wca_id_claim.nil?
14+
15+
TicketsClaimWcaId.create_ticket!(resource)
16+
end
17+
end
18+
1219
private
1320

1421
def check_captcha

app/controllers/tickets_controller.rb

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ class TicketsController < ApplicationController
1010
before_action -> { check_ticket_errors(TicketLog.action_types[:metadata_action], TicketsEditPerson::ACTION_TYPE[:approve_edit_person_request]) }, only: [:approve_edit_person_request]
1111
before_action -> { check_ticket_errors(TicketLog.action_types[:metadata_action], TicketsEditPerson::ACTION_TYPE[:reject_edit_person_request]) }, only: [:reject_edit_person_request]
1212
before_action -> { check_ticket_errors(TicketLog.action_types[:metadata_action], TicketsEditPerson::ACTION_TYPE[:sync_edit_person_request]) }, only: [:sync_edit_person_request]
13+
before_action -> { check_ticket_errors(TicketLog.action_types[:metadata_action], TicketsClaimWcaId::ACTION_TYPE[:approve_claim]) }, only: [:approve_claim_wca_id]
14+
before_action -> { check_ticket_errors(TicketLog.action_types[:metadata_action], TicketsClaimWcaId::ACTION_TYPE[:reject_claim]) }, only: [:reject_claim_wca_id]
15+
before_action -> { check_ticket_errors(TicketLog.action_types[:metadata_action], TicketsClaimWcaId::ACTION_TYPE[:transfer_claim]) }, only: [:transfer_claim_wca_id]
1316
before_action -> { redirect_to_root_unless_user(:can_admin_results?) }, only: %i[delete_inbox_persons]
1417

1518
SORT_WEIGHT_LAMBDAS = {
@@ -36,6 +39,39 @@ class TicketsController < ApplicationController
3639
return if metadata_action.nil?
3740

3841
render status: :unauthorized, json: { error: "You are not allowed to perform this metadata action." } unless @acting_stakeholder.metadata_actions_allowed.include?(@metadata_action)
42+
43+
case @ticket.metadata_type
44+
when Ticket::TICKET_TYPES[:claim_wca_id]
45+
if @metadata_action == TicketsClaimWcaId::ACTION_TYPE[:approve_claim]
46+
@user = @ticket.metadata.user
47+
if @user.wca_id.present?
48+
render status: :unprocessable_content, json: {
49+
error: "This user already has a WCA ID assigned.",
50+
}
51+
end
52+
53+
if @user.unconfirmed_wca_id.nil?
54+
render status: :unprocessable_content, json: {
55+
error: "This user does not have an unconfirmed WCA ID to approve.",
56+
}
57+
end
58+
59+
unless @acting_stakeholder.assigned?
60+
render status: :unauthorized, json: {
61+
error: "Only the assigned delegate can approve/reject.",
62+
}
63+
end
64+
elsif @metadata_action == TicketsClaimWcaId::ACTION_TYPE[:transfer_claim]
65+
new_delegate_id = params.require(:new_delegate_id)
66+
@new_delegate = User.find(new_delegate_id)
67+
68+
unless @new_delegate.any_kind_of_delegate?
69+
render status: :unprocessable_content, json: {
70+
error: "The selected user is not a delegate.",
71+
}
72+
end
73+
end
74+
end
3975
end
4076

4177
def index
@@ -394,4 +430,83 @@ def join_as_bcc_stakeholder
394430

395431
render status: :ok, json: { success: true }
396432
end
433+
434+
def approve_claim_wca_id
435+
ticket_status = TicketsClaimWcaId.statuses[:closed]
436+
437+
ActiveRecord::Base.transaction do
438+
user.update!(wca_id: @user.unconfirmed_wca_id)
439+
@ticket.metadata.update!(status: ticket_status)
440+
ticket_log = @ticket.ticket_logs.create!(
441+
action_type: @action_type,
442+
acting_user_id: current_user.id,
443+
acting_stakeholder_id: @acting_stakeholder.id,
444+
metadata_action: @metadata_action,
445+
)
446+
ticket_log.ticket_log_changes.create!(
447+
field_name: TicketLogChange.field_names[:status],
448+
field_value: ticket_status,
449+
)
450+
end
451+
render status: :ok, json: { success: true }
452+
end
453+
454+
def reject_claim_wca_id
455+
ticket_status = TicketsClaimWcaId.statuses[:closed]
456+
457+
ActiveRecord::Base.transaction do
458+
@ticket.metadata.update!(status: ticket_status)
459+
ticket_log = @ticket.ticket_logs.create!(
460+
action_type: @action_type,
461+
acting_user_id: current_user.id,
462+
acting_stakeholder_id: @acting_stakeholder.id,
463+
metadata_action: @metadata_action,
464+
)
465+
ticket_log.ticket_log_changes.create!(
466+
field_name: TicketLogChange.field_names[:status],
467+
field_value: ticket_status,
468+
)
469+
end
470+
render status: :ok, json: { success: true }
471+
end
472+
473+
def transfer_claim_wca_id
474+
user = @ticket.metadata.user
475+
476+
ActiveRecord::Base.transaction do
477+
user.update!(delegate_to_handle_wca_id_claim: @new_delegate)
478+
479+
old_stakeholder = @ticket.ticket_stakeholders.find_by(
480+
stakeholder_type: "User",
481+
stakeholder_role: TicketStakeholder.stakeholder_roles[:actioner],
482+
connection: TicketStakeholder.connections[:assigned],
483+
)
484+
old_stakeholder.update!(connection: TicketStakeholder.connections[:cc])
485+
486+
existing_new = @ticket.ticket_stakeholders.find_by(
487+
stakeholder_type: "User",
488+
stakeholder_id: @new_delegate.id,
489+
)
490+
491+
if existing_new
492+
existing_new.update!(connection: TicketStakeholder.connections[:assigned])
493+
else
494+
@ticket.ticket_stakeholders.create!(
495+
stakeholder: @new_delegate,
496+
connection: TicketStakeholder.connections[:assigned],
497+
stakeholder_role: TicketStakeholder.stakeholder_roles[:actioner],
498+
is_active: true,
499+
)
500+
end
501+
502+
@ticket.ticket_logs.create!(
503+
action_type: @action_type,
504+
acting_user_id: current_user.id,
505+
acting_stakeholder_id: @acting_stakeholder.id,
506+
metadata_action: @metadata_action,
507+
)
508+
end
509+
510+
render status: :ok, json: @ticket
511+
end
397512
end

app/controllers/users_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,8 @@ def update
293293
wca_id: @user.unconfirmed_wca_id,
294294
user: @user.delegate_to_handle_wca_id_claim.name)
295295
WcaIdClaimMailer.notify_delegate_of_wca_id_claim(@user).deliver_later
296+
TicketsClaimWcaId.create_ticket!(@user)
297+
296298
redirect_to profile_claim_wca_id_path
297299
else
298300
redirect_to edit_user_url(@user, params.permit(:section))

app/models/ticket.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ class Ticket < ApplicationRecord
44
TICKET_TYPES = {
55
edit_person: "TicketsEditPerson",
66
competition_result: "TicketsCompetitionResult",
7+
claim_wca_id: "TicketsClaimWcaId",
78
}.freeze
89

910
has_many :ticket_comments

app/models/tickets_claim_wca_id.rb

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# frozen_string_literal: true
2+
3+
class TicketsClaimWcaId < ApplicationRecord
4+
self.table_name = "tickets_claim_wca_id"
5+
6+
enum :status, {
7+
open: "open",
8+
closed: "closed",
9+
}
10+
11+
has_one :ticket, as: :metadata
12+
belongs_to :user
13+
14+
ACTION_TYPE = {
15+
approve_claim: "approve_claim",
16+
reject_claim: "reject_claim",
17+
transfer_claim: "transfer_claim",
18+
}.freeze
19+
20+
def metadata_actions_allowed_for(ticket_stakeholder)
21+
if ticket_stakeholder.actioner?
22+
[
23+
ACTION_TYPE[:approve_claim],
24+
ACTION_TYPE[:reject_claim],
25+
ACTION_TYPE[:transfer_claim],
26+
]
27+
else
28+
[]
29+
end
30+
end
31+
32+
def eligible_roles_for_bcc(user)
33+
if user.admin?
34+
[
35+
TicketStakeholder.stakeholder_roles[:actioner],
36+
TicketStakeholder.stakeholder_roles[:requester],
37+
]
38+
elsif user.any_kind_of_delegate?
39+
[
40+
TicketStakeholder.stakeholder_roles[:actioner],
41+
]
42+
else
43+
[]
44+
end
45+
end
46+
47+
def self.create_ticket!(user)
48+
ActiveRecord::Base.transaction do
49+
ticket_metadata = TicketsClaimWcaId.create!(
50+
status: TicketsClaimWcaId.statuses[:open],
51+
user: user,
52+
)
53+
54+
ticket = Ticket.create!(metadata: ticket_metadata)
55+
56+
ticket.ticket_stakeholders.create!(
57+
stakeholder: user.delegate_to_handle_wca_id_claim,
58+
connection: TicketStakeholder.connections[:assigned],
59+
stakeholder_role: TicketStakeholder.stakeholder_roles[:actioner],
60+
is_active: true,
61+
)
62+
63+
ticket.ticket_stakeholders.create!(
64+
stakeholder: user,
65+
connection: TicketStakeholder.connections[:cc],
66+
stakeholder_role: TicketStakeholder.stakeholder_roles[:requester],
67+
is_active: true,
68+
)
69+
end
70+
end
71+
72+
DEFAULT_SERIALIZE_OPTIONS = {
73+
include: %w[user],
74+
}.freeze
75+
76+
def serializable_hash(options = nil)
77+
super(DEFAULT_SERIALIZE_OPTIONS.merge(options || {}))
78+
end
79+
end

app/models/user.rb

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,12 +1111,7 @@ def editable_fields_of_user(user)
11111111
fields += %i[name dob gender country_iso2] unless cannot_edit_data_reason_html(user)
11121112
fields += CLAIM_WCA_ID_PARAMS if user == self || can_edit_any_user?
11131113
fields << :name if user.wca_id.blank? && organizer_for?(user)
1114-
if can_edit_any_user?
1115-
fields += %i[
1116-
unconfirmed_wca_id
1117-
]
1118-
fields += %i[wca_id] unless user.special_account?
1119-
end
1114+
fields << :wca_id if can_edit_any_user? && !user.special_account?
11201115
fields
11211116
end
11221117

app/views/users/edit.html.erb

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,12 @@
7676
<%= t 'activerecord.attributes.user.unconfirmed_wca_id' %>
7777
</label>
7878
<div class="input-group">
79-
<%= f.input_field :unconfirmed_wca_id, as: :wca_id, disabled: !editable_fields.include?(:unconfirmed_wca_id), class: "form-control" %>
80-
<span class="input-group-addon">
81-
<a href="#" id="unconfirmed-wca-id-profile" target="_blank">
82-
<%= t '.profile' %>
83-
</a>
84-
</span>
79+
<%= f.input_field :unconfirmed_wca_id, as: :wca_id, disabled: true, class: "form-control" %>
8580
<div class="input-group-btn">
86-
<button type="button" class="btn btn-default" id="approve-wca-id">
87-
<%= t '.approve' %>
88-
</button>
81+
<% claim_ticket = TicketsClaimWcaId.open.find_by(user: @user)&.ticket %>
82+
<% if claim_ticket %>
83+
<%= link_to t('.go_to_claim_wca_id_ticket'), ticket_path(claim_ticket), class: "btn btn-primary", target: "_blank" %>
84+
<% end %>
8985
</div>
9086
</div>
9187
</div>

app/webpacker/components/Tickets/TicketHeader/index.jsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import { Card, Header } from 'semantic-ui-react';
33
import _ from 'lodash';
44
import { ticketTypes } from '../../../lib/wca-data.js.erb';
55
import I18n from '../../../lib/i18n';
6-
import { personUrl, competitionUrl } from '../../../lib/requests/routes.js.erb';
6+
import { personUrl, competitionUrl, editPersonUrl } from '../../../lib/requests/routes.js.erb';
77

88
// let i18n-tasks know the key is used
99
// i18n-tasks-use t('tickets.type.edit_person')
1010
// i18n-tasks-use t('tickets.type.competition_result')
11+
// i18n-tasks-use t('tickets.type.claim_wca_id')
1112

1213
export default function TicketHeader({ ticketDetails }) {
1314
const { ticket: { id, metadata_type: ticketType, metadata: { status } } } = ticketDetails;
@@ -61,6 +62,20 @@ function SubHeading({ ticketDetails }) {
6162
</a>
6263
</>
6364
);
65+
case ticketTypes.claim_wca_id:
66+
return (
67+
<>
68+
Claim WCA ID for
69+
{' '}
70+
<a
71+
href={editPersonUrl(metadata.user.id)}
72+
target="_blank"
73+
rel="noreferrer"
74+
>
75+
{metadata.user.name}
76+
</a>
77+
</>
78+
);
6479
default:
6580
return 'Unknown Ticket';
6681
}

app/webpacker/components/Tickets/TicketWorkbenches.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ticketTypes, ticketStakeholderRoles } from '../../lib/wca-data.js.erb';
2+
import ClaimWcaIdActionerView from './TicketWorkbenches/ClaimWcaIdActionerView';
23
import CompetitionResultActionerView from './TicketWorkbenches/CompetitionResultActionerView';
34
import CompetitionResultRequesterView from './TicketWorkbenches/CompetitionResultRequesterView';
45
import EditPersonActionerView from './TicketWorkbenches/EditPersonActionerView';
@@ -11,4 +12,7 @@ export default {
1112
[ticketStakeholderRoles.actioner]: CompetitionResultActionerView,
1213
[ticketStakeholderRoles.requester]: CompetitionResultRequesterView,
1314
},
15+
[ticketTypes.claim_wca_id]: {
16+
[ticketStakeholderRoles.actioner]: ClaimWcaIdActionerView,
17+
},
1418
};

0 commit comments

Comments
 (0)