discourse/app/assets/javascripts/admin/addon/templates/user-index.hbs
David Taylor c1f74cd92a
DEV: Update default tagName and connectorTagName for plugin outlets (#13685)
This commit should be a no-op for all existing core outlets. Outlets which are introduced by themes/plugins may see a change in behavior, and should follow the steps below if they want to maintain their previous behavior.

`tagName="" connectorTagName=""` is almost always the correct choice for plugin outlets. 40eba8cd introduced a `noTags=true` shortcut which achieved this, and left a comment saying it should be the future default. This commit does exactly that. To avoid any breaking changes for plugins, all existing plugin outlets have been reviewed and adjusted by following this logic:

1) If `noTags=true`, remove the `noTags` parameter, and do not complete any further steps
2) If `tagName` is not specified, set `tagName="span"` (the previous default)
3) If `connectorTagName` is not specified, set `selectorTagName="div"` (the previous default)
4) If `tagName=""`, remove it
5) If `connectorTagName=""`, remove it

The updates were accomplished with the help of a ruby script:

```ruby
def removeAttr(tag, attribute)
  tag = tag.sub /\s#{attribute}="?\w*"? /, " "
  tag = tag.sub /\s#{attribute}="?\w*"?}}/, "}}"
  tag = tag.sub /^\s*#{attribute}="?\w*"?\n/, ""
  tag
end

files = Dir.glob("app/assets/javascripts/**/*.hbs")

puts "Checking #{files.count} files..."
files.each do |f|
  content = File.read(f)

  count = 0
  edits = 0
  content.gsub!(/{{\s*plugin-outlet.*?}}/m) do |match|
    count += 1

    result = match

    noTags = result.include?("noTags=true")
    tagName = result[/tagName="(\w*)"/, 1]
    connectorTagName = result[/connectorTagName="(\w*)"/, 1]

    if noTags
      result = removeAttr(result, "noTags")
    else
      if connectorTagName == ""
        result = removeAttr(result, "connectorTagName")
      elsif connectorTagName.nil?
        result = result.sub(/name="[\w-]+"/) { |m| "#{m} connectorTagName=\"div\"" }
      end

      if tagName == ""
        result = removeAttr(result, "tagName")
      elsif tagName.nil?
        result = result.sub(/name="[\w-]+"/) { |m| "#{m} tagName=\"span\"" }
      end
    end

    edits += 1 if match != result

    result
  end

  puts "#{count} outlets, #{edits} edited -> #{f}"

  File.write(f, content)
end
```
2022-01-06 20:38:17 +00:00

775 lines
25 KiB
Handlebars

<section class="details {{unless model.active "not-activated"}}">
<div class="user-controls">
{{#if model.canViewProfile}}
{{#link-to "user" model class="btn btn-default"}}
{{d-icon "user"}}
{{i18n "admin.user.show_public_profile"}}
{{/link-to}}
{{/if}}
{{#if model.can_view_action_logs}}
{{d-button
action=(action "viewActionLogs")
class="btn-default"
actionParam=model.username
icon="far-list-alt"
label="admin.user.action_logs"}}
{{/if}}
{{#if model.active}}
{{#if currentUser.admin}}
{{d-button
class="btn-default"
action=(action "logOut")
icon="power-off"
label="admin.user.log_out"}}
{{/if}}
{{/if}}
{{plugin-outlet
name="admin-user-controls-after"
args=(hash model=model)
}}
</div>
<div class="display-row username">
{{admin-editable-field name="user.username.title"
value=model.username
action=(action "saveUsername")
editing=editingUsername}}
</div>
<div class="display-row name">
{{admin-editable-field name="user.name.title"
value=model.name
action=(action "saveName")
editing=editingName}}
</div>
{{plugin-outlet
name="admin-user-below-names"
args=(hash user=model)
}}
{{#if canCheckEmails}}
<div class="display-row email">
<div class="field">{{i18n "user.email.primary"}}</div>
<div class="value">
{{#unless model.active}}
<div class="controls">{{i18n "admin.users.not_verified"}}</div>
{{/unless}}
{{#if model.email}}
<a href="mailto:{{model.email}}">{{model.email}}</a>
{{else}}
{{d-button
class="btn-default"
action=(route-action "checkEmail")
actionParam=model icon="far-envelope"
label="admin.users.check_email.text"
title="admin.users.check_email.title"}}
{{/if}}
</div>
<div class="controls">
{{#if siteSettings.auth_overrides_email}}
{{i18n "user.email.auth_override_instructions"}}
{{else if model.email}}
{{html-safe (i18n "admin.user.visit_profile" url=preferencesPath)}}
{{/if}}
</div>
</div>
<div class="display-row secondary-emails">
<div class="field">{{i18n "user.email.secondary"}}</div>
<div class="value">
{{#if model.email}}
{{#if model.secondary_emails}}
<ul>
{{#each model.secondary_emails as |email| }}
<li><a href="mailto:{{email}}">{{email}}</a></li>
{{/each}}
</ul>
{{else}}
{{i18n "user.email.no_secondary"}}
{{/if}}
{{else}}
{{d-button action=(route-action "checkEmail")
class="btn-default"
actionParam=model
icon="far-envelope"
label="admin.users.check_email.text"
title="admin.users.check_email.title"}}
{{/if}}
</div>
<div class="controls">
{{#if model.email}}
{{#if model.secondary_emails}}
{{#if siteSettings.auth_overrides_email}}
{{i18n "user.email.auth_override_instructions"}}
{{else}}
{{html-safe (i18n "admin.user.visit_profile" url=preferencesPath)}}
{{/if}}
{{/if}}
{{/if}}
</div>
</div>
<div class="display-row bounce-score">
<div class="field"><a href={{model.bounceLink}}>{{i18n "admin.user.bounce_score"}}</a></div>
<div class="value">{{model.bounceScore}}</div>
<div class="controls">
{{#if model.canResetBounceScore}}
{{d-button
class="btn-default"
action=(action "resetBounceScore")
label="admin.user.reset_bounce_score.label"
title="admin.user.reset_bounce_score.title"}}
{{/if}}
{{model.bounceScoreExplanation}}
</div>
</div>
<div class="display-row associations">
<div class="field">{{i18n "user.associated_accounts.title"}}</div>
<div class="value">
{{#if associatedAccountsLoaded}}
{{associatedAccounts}}
{{else}}
{{d-button
class="btn-default"
action=(route-action "checkEmail")
actionParam=model icon="far-envelope"
label="admin.users.check_email.text"
title="admin.users.check_email.title"}}
{{/if}}
</div>
</div>
{{/if}}
<div class="display-row">
<div class="field">{{i18n "user.avatar.title"}}</div>
<div class="value">{{avatar model imageSize="large"}}</div>
<div class="controls">
{{html-safe (i18n "admin.user.visit_profile" url=preferencesPath)}}
</div>
</div>
<div class="display-row">
{{admin-editable-field name="user.title.title"
value=model.title
action=(action "saveTitle")
editing=editingTitle}}
</div>
<div class="display-row last-ip">
<div class="field">{{i18n "user.ip_address.title"}}</div>
<div class="value">{{model.ip_address}}</div>
<div class="controls">
{{#if currentUser.staff}}
{{ip-lookup ip=model.ip_address userId=model.id}}
{{/if}}
</div>
</div>
<div class="display-row registration-ip">
<div class="field">{{i18n "user.registration_ip_address.title"}}</div>
<div class="value">{{model.registration_ip_address}}</div>
<div class="controls">
{{#if currentUser.staff}}
{{ip-lookup ip=model.registration_ip_address userId=model.id}}
{{/if}}
</div>
</div>
{{#if showBadges}}
<div class="display-row">
<div class="field">{{i18n "admin.badges.title"}}</div>
<div class="value">
{{i18n "badges.badge_count" count=model.badge_count}}
</div>
<div class="controls">
{{#link-to "adminUser.badges" model class="btn btn-default"}}
{{d-icon "certificate"}}
{{i18n "admin.badges.edit_badges"}}
{{/link-to}}
</div>
</div>
{{/if}}
<div class="display-row">
<div class="field">{{i18n "user.second_factor.title"}}</div>
<div class="value">
{{#if model.second_factor_enabled}}
{{i18n "yes_value"}}
{{else}}
{{i18n "no_value"}}
{{/if}}
</div>
<div class="controls">
{{#if canDisableSecondFactor}}
{{d-button
class="btn-default"
action=(action "disableSecondFactor")
icon="unlock-alt"
label="user.second_factor.disable"}}
{{/if}}
</div>
</div>
</section>
{{#if userFields}}
<section class="details">
{{#each userFields as |uf|}}
<div class="display-row">
<div class="field">{{uf.name}}</div>
<div class="value">
{{#if uf.value}}
{{uf.value}}
{{else}}
&mdash;
{{/if}}
</div>
</div>
{{/each}}
</section>
{{/if}}
{{plugin-outlet name="admin-user-details" tagName="span" connectorTagName="div" args=(hash model=model)}}
<section class="details">
<h1>{{i18n "admin.user.permissions"}}</h1>
{{#if siteSettings.must_approve_users}}
<div class="display-row">
<div class="field">{{i18n "admin.users.approved"}}</div>
<div class="value">
{{#if model.approved}}
{{i18n "admin.user.approved_by"}}
{{#link-to "adminUser" model.approvedBy}}
{{avatar model.approvedBy imageSize="small"}}
{{/link-to}}
{{#link-to "adminUser" model.approvedBy}}
{{model.approvedBy.username}}
{{/link-to}}
{{else}}
{{i18n "no_value"}}
{{/if}}
</div>
<div class="controls">
{{#if model.approved}}
{{i18n "admin.user.approve_success"}}
{{else}}
{{#if model.can_approve}}
{{d-button
class="btn-default"
action=(action "approve")
icon="check"
label="admin.user.approve"}}
{{/if}}
{{/if}}
</div>
</div>
{{/if}}
<div class="display-row">
<div class="field">{{i18n "admin.users.active"}}</div>
<div class="value">{{i18n-yes-no model.active}}</div>
<div class="controls">
{{#if model.active}}
{{#if model.can_deactivate}}
{{d-button
class="btn-default"
action=(action "deactivate")
label="admin.user.deactivate_account"}}
{{i18n "admin.user.deactivate_explanation"}}
{{/if}}
{{else}}
{{#if model.can_send_activation_email}}
{{d-button
class="btn-default"
action=(action "sendActivationEmail")
icon="envelope"
label="admin.user.send_activation_email"}}
{{/if}}
{{#if model.can_activate}}
{{d-button
class="btn-default"
action=(action "activate")
icon="check"
label="admin.user.activate"}}
{{/if}}
{{/if}}
</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.staged"}}</div>
<div class="value">{{i18n-yes-no model.staged}}</div>
<div class="controls">{{i18n "admin.user.staged_explanation"}}</div>
</div>
{{#if currentUser.admin}}
<div class="display-row">
<div class="field">{{i18n "admin.api.active_keys"}}</div>
<div class="value">
{{model.api_key_count}}
</div>
<div class="controls">
{{d-button class="btn-default" href="/admin/api/keys" label="admin.api.manage_keys"}}
</div>
</div>
{{/if}}
<div class="display-row">
<div class="field">{{i18n "admin.user.admin"}}</div>
<div class="value">{{i18n-yes-no model.admin}}</div>
<div class="controls">
{{#if model.can_revoke_admin}}
{{d-button
class="btn-default"
action=(action "revokeAdmin")
icon="shield-alt"
label="admin.user.revoke_admin"}}
{{/if}}
{{#if model.can_grant_admin}}
{{d-button
class="btn-default grant-admin"
action=(action "grantAdmin")
icon="shield-alt"
label="admin.user.grant_admin"}}
{{/if}}
</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.moderator"}}</div>
<div class="value">{{i18n-yes-no model.moderator}}</div>
<div class="controls">
{{#if model.can_revoke_moderation}}
{{d-button
class="btn-default"
action=(action "revokeModeration")
icon="shield-alt"
label="admin.user.revoke_moderation"}}
{{/if}}
{{#if model.can_grant_moderation}}
{{d-button
class="btn-default"
action=(action "grantModeration")
icon="shield-alt"
label="admin.user.grant_moderation"}}
{{/if}}
</div>
</div>
<div class="display-row">
<div class="field">{{i18n "trust_level"}}</div>
<div class="value">
{{combo-box
content=site.trustLevels
nameProperty="detailedName"
value=model.trustLevel.id
onChange=(action (mut model.trust_level))
}}
{{#if model.dirty}}
<div>
{{d-button class="ok no-text" action=(action "saveTrustLevel") icon="check"}}
{{d-button class="cancel no-text" action=(action "restoreTrustLevel") icon="times"}}
</div>
{{/if}}
</div>
<div class="controls">
{{#if model.canLockTrustLevel}}
{{#if hasLockedTrustLevel}}
{{d-icon "lock" title="admin.user.trust_level_locked_tip"}}
{{d-button
class="btn-default"
action=(action "lockTrustLevel")
actionParam=false
label="admin.user.unlock_trust_level"}}
{{else}}
{{d-icon "unlock" title="admin.user.trust_level_unlocked_tip"}}
{{d-button
class="btn-default"
action=(action "lockTrustLevel")
actionParam=true
label="admin.user.lock_trust_level"}}
{{/if}}
{{/if}}
{{#if model.tl3Requirements}}
{{#link-to "adminUser.tl3Requirements" model class="btn btn-default"}}
{{i18n "admin.user.trust_level_3_requirements"}}
{{/link-to}}
{{/if}}
</div>
</div>
<div class="user-suspended display-row {{if model.suspended "highlight-danger"}}">
<div class="field">{{i18n "admin.user.suspended"}}</div>
<div class="value">
{{i18n-yes-no model.suspended}}
{{#if model.suspended}}
{{#unless model.suspendedForever}}
{{i18n "admin.user.suspended_until" until=model.suspendedTillDate}}
{{/unless}}
{{/if}}
</div>
<div class="controls">
{{#if model.suspended}}
{{d-button
class="btn-danger unsuspend-user"
action=(action "unsuspend")
icon="ban"
label="admin.user.unsuspend"}}
{{i18n "admin.user.suspended_explanation"}}
{{else}}
{{#if model.canSuspend}}
{{d-button
class="btn-danger suspend-user"
action=(action "showSuspendModal")
icon="ban"
label="admin.user.suspend"}}
{{i18n "admin.user.suspended_explanation"}}
{{/if}}
{{/if}}
</div>
</div>
{{#if model.suspended}}
<div class="display-row highlight-danger suspension-info">
<div class="field">{{i18n "admin.user.suspended_by"}}</div>
<div class="value">
{{#link-to "adminUser" model.suspendedBy}}
{{avatar model.suspendedBy imageSize="tiny"}}
{{/link-to}}
{{#link-to "adminUser" model.suspendedBy}}
{{model.suspendedBy.username}}
{{/link-to}}
</div>
<div class="controls">
<b>{{i18n "admin.user.suspend_reason"}}</b>:
<div class="full-reason">{{model.full_suspend_reason}}</div>
</div>
</div>
{{/if}}
<div class="display-row {{if model.silenced "highlight-danger"}}">
<div class="field">{{i18n "admin.user.silenced"}}</div>
<div class="value">
{{i18n-yes-no model.silenced}}
{{#if model.silenced}}
{{#unless model.silencedForever}}
{{i18n "admin.user.suspended_until" until=model.silencedTillDate}}
{{/unless}}
{{/if}}
</div>
<div class="controls">
{{#conditional-loading-spinner size="small" condition=model.silencingUser}}
{{#if model.silenced}}
{{d-button
class="btn-danger unsilence-user"
action=(action "unsilence")
icon="microphone-slash"
label="admin.user.unsilence"}}
{{i18n "admin.user.silence_explanation"}}
{{else}}
{{d-button
class="btn-danger silence-user"
action=(action "showSilenceModal")
icon="microphone-slash"
label="admin.user.silence"}}
{{i18n "admin.user.silence_explanation"}}
{{/if}}
{{/conditional-loading-spinner}}
</div>
</div>
{{#if model.silenced}}
<div class="display-row highlight-danger silence-info">
<div class="field">{{i18n "admin.user.silenced_by"}}</div>
<div class="value">
{{#link-to "adminUser" model.silencedBy}}
{{avatar model.silencedBy imageSize="tiny"}}
{{/link-to}}
{{#link-to "adminUser" model.silencedBy}}
{{model.silencedBy.username}}
{{/link-to}}
</div>
<div class="controls">
<b>{{i18n "admin.user.silence_reason"}}</b>:
<div class="full-reason">{{model.silence_reason}}</div>
</div>
</div>
{{/if}}
{{#if model.tl3_requirements.penalty_counts.total}}
<div class="display-row clear-penalty-history">
<div class="field">{{i18n "admin.user.penalty_count"}}</div>
<div class="value">{{model.tl3_requirements.penalty_counts.total}}</div>
{{#if currentUser.admin}}
<div class="controls">
{{d-button label="admin.user.clear_penalty_history.title"
class="btn-default"
icon="times"
action=(action "clearPenaltyHistory")}}
{{i18n "admin.user.clear_penalty_history.description"}}
</div>
{{/if}}
</div>
{{/if}}
</section>
{{#if currentUser.admin}}
<section class="details">
<h1>{{i18n "admin.groups.title"}}</h1>
<div class="display-row">
<div class="field">{{i18n "admin.groups.automatic"}}</div>
<div class="value">{{html-safe automaticGroups}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.groups.custom"}}</div>
<div class="value">
{{group-chooser
content=availableGroups
value=customGroupIdsBuffer
labelProperty="name"
onChange=(action (mut customGroupIdsBuffer))
}}
</div>
{{#if customGroupsDirty}}
<div class="controls">
{{d-button icon="check" class="ok" action=(action "saveCustomGroups")}}
{{d-button icon="times" class="cancel" action=(action "resetCustomGroups")}}
</div>
{{/if}}
</div>
{{#if model.customGroups}}
<div class="display-row">
<div class="field">{{i18n "admin.groups.primary"}}</div>
<div class="value">
{{combo-box
content=model.customGroups
value=model.primary_group_id
none="admin.groups.no_primary"
onChange=(action (mut model.primary_group_id))
}}
</div>
{{#if primaryGroupDirty}}
<div class="controls">
{{d-button icon="check" class="ok" action=(action "savePrimaryGroup")}}
{{d-button icon="times" class="cancel" action=(action "resetPrimaryGroup")}}
</div>
{{/if}}
</div>
{{/if}}
</section>
{{/if}}
<section class="details">
<h1>{{i18n "admin.user.activity"}}</h1>
<div class="display-row">
<div class="field">{{i18n "created"}}</div>
<div class="value">{{format-date model.created_at leaveAgo="true"}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.users.last_emailed"}}</div>
<div class="value">{{format-date model.last_emailed_at}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "last_seen"}}</div>
<div class="value">{{format-date model.last_seen_at leaveAgo="true"}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.like_count"}}</div>
<div class="value">{{model.like_given_count}} / {{model.like_count}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.topics_entered"}}</div>
<div class="value">{{model.topics_entered}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.post_count"}}</div>
<div class="value">{{model.post_count}}</div>
<div class="controls">
{{#if model.can_delete_all_posts}}
{{#if model.post_count}}
{{d-button
class="btn-danger"
action=(action "showDeletePostsConfirmation")
icon="far-trash-alt"
label="admin.user.delete_posts.button"}}
{{/if}}
{{else}}
{{deleteAllPostsExplanation}}
{{/if}}
</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.posts_read_count"}}</div>
<div class="value">{{model.posts_read_count}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.warnings_received_count"}}</div>
<div class="value">{{model.warnings_received_count}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.flags_given_received_count"}}</div>
<div class="value">
{{model.flags_given_count}} / {{model.flags_received_count}}
</div>
<div class="controls">
{{#if model.flags_received_count}}
{{#link-to "review" (query-params username=model.username type="ReviewableFlaggedPost" status="all") class="btn"}}
{{i18n "admin.user.show_flags_received"}}
{{/link-to}}
{{/if}}
</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.private_topics_count"}}</div>
<div class="value">{{model.private_topics_count}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.time_read"}}</div>
<div class="value">{{format-duration model.time_read}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "user.invited.days_visited"}}</div>
<div class="value">{{html-safe model.days_visited}}</div>
</div>
<div class="display-row post-edits-count">
<div class="field">{{i18n "admin.user.post_edits_count" }}</div>
<div class="value">
{{if (gt model.post_edits_count 0) model.post_edits_count "0"}}
</div>
<div class="controls">
{{#if (gt model.post_edits_count 0) }}
{{#link-to "adminReports.show" "post_edits" (query-params filters=postEditsByEditorFilter) class="btn btn-icon"}}
{{d-icon "far-eye"}}
{{i18n "admin.user.view_edits"}}
{{/link-to}}
{{/if}}
</div>
</div>
</section>
{{#if model.single_sign_on_record}}
<section class="details">
<h1>{{i18n "admin.user.discourse_connect.title"}}</h1>
{{#with model.single_sign_on_record as |sso|}}
<div class="display-row">
<div class="field">{{i18n "admin.user.discourse_connect.external_id"}}</div>
<div class="value">{{sso.external_id}}</div>
{{#if model.can_delete_sso_record}}
<div class="controls">
{{d-button
class="btn-danger"
action=(action "deleteSSORecord")
icon="far-trash-alt"
label="admin.user.discourse_connect.delete_sso_record"
}}
</div>
{{/if}}
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.discourse_connect.external_username"}}</div>
<div class="value">{{sso.external_username}}</div>
</div>
<div class="display-row">
<div class="field">{{i18n "admin.user.discourse_connect.external_name"}}</div>
<div class="value">{{sso.external_name}}</div>
</div>
{{#if canAdminCheckEmails}}
<div class="display-row">
<div class="field">{{i18n "admin.user.discourse_connect.external_email"}}</div>
{{#if ssoExternalEmail}}
<div class="value">{{ssoExternalEmail}}</div>
{{else}}
{{d-button
class="btn-default"
action=(action "checkSsoEmail")
actionParam=model icon="far-envelope"
label="admin.users.check_email.text"
title="admin.users.check_email.title"}}
{{/if}}
</div>
{{/if}}
<div class="display-row">
<div class="field">{{i18n "admin.user.discourse_connect.external_avatar_url"}}</div>
<div class="value">{{sso.external_avatar_url}}</div>
</div>
{{#if canAdminCheckEmails}}
<div class="display-row">
<div class="field">{{i18n "admin.user.discourse_connect.last_payload"}}</div>
{{#if ssoLastPayload}}
<div class="value">
{{#each ssoPayload as |line|}}
{{line}}<br>
{{/each}}
</div>
{{else}}
{{d-button
class="btn-default"
action=(action "checkSsoPayload")
actionParam=model icon="far-list-alt"
label="admin.users.check_sso.text"
title="admin.users.check_sso.title"}}
{{/if}}
</div>
{{/if}}
{{/with}}
</section>
{{/if}}
{{plugin-outlet name="after-user-details" tagName="span" connectorTagName="div" args=(hash model=model)}}
<section>
<hr>
<div class="pull-right">
{{#if model.active}}
{{#if model.can_impersonate}}
{{d-button
class="btn-danger"
action=(action "impersonate")
icon="crosshairs"
label="admin.impersonate.title"
title="admin.impersonate.help"}}
{{/if}}
{{/if}}
{{#if model.can_be_anonymized}}
{{d-button label="admin.user.anonymize"
icon="exclamation-triangle"
class="btn-danger"
action=(action "anonymize")}}
{{/if}}
{{#if model.canBeDeleted}}
{{d-button label="admin.user.delete"
icon="trash-alt"
class="btn-danger"
action=(action "destroy")}}
{{/if}}
{{#if model.can_be_merged}}
{{d-button label="admin.user.merge.button"
icon="arrows-alt-h"
class="btn-danger"
action=(action "promptTargetUser")}}
{{/if}}
</div>
{{#if deleteExplanation}}
<div class="clearfix"></div>
<br>
<div class="pull-right">
{{d-icon "exclamation-triangle"}} {{deleteExplanation}}
</div>
{{/if}}
</section>
<div class="clearfix"></div>