views/admin/users i18n (#18582)
This commit is contained in:
parent
5dd33c1fe6
commit
5519fe563c
46 changed files with 1048 additions and 301 deletions
|
|
@ -16,45 +16,46 @@ module Admin
|
|||
return if timestamp.blank?
|
||||
|
||||
if timestamp.today?
|
||||
"Today, #{timestamp.strftime('%d %b')}"
|
||||
I18n.t("helpers.admin.user_helper.today", date: I18n.l(timestamp, format: :members))
|
||||
elsif timestamp.yesterday?
|
||||
"Yesterday, #{timestamp.strftime('%d %b')}"
|
||||
I18n.t("helpers.admin.user_helper.yesterday", date: I18n.l(timestamp, format: :members))
|
||||
else
|
||||
timestamp.strftime("%d %b, %Y")
|
||||
I18n.l(timestamp, format: :members_with_year)
|
||||
end
|
||||
end
|
||||
|
||||
def cascading_high_level_roles(user)
|
||||
if user.super_admin?
|
||||
"Super Admin"
|
||||
I18n.t("views.admin.users.roles.Super Admin")
|
||||
elsif user.admin?
|
||||
"Admin"
|
||||
I18n.t("views.admin.users.roles.Admin")
|
||||
elsif user.single_resource_admin_for?(:any)
|
||||
"Resource Admin"
|
||||
I18n.t("views.admin.users.roles.Resource Admin")
|
||||
end
|
||||
end
|
||||
|
||||
def format_role_tooltip(user)
|
||||
if user.super_admin?
|
||||
"Super Admin"
|
||||
I18n.t("views.admin.users.roles.Super Admin")
|
||||
elsif user.admin?
|
||||
"Admin"
|
||||
I18n.t("views.admin.users.roles.Admin")
|
||||
elsif user.single_resource_admin_for?(:any)
|
||||
"Resource Admin: #{user.roles.pluck(:resource_type).compact.join(', ')}"
|
||||
role = "Resource Admin: #{user.roles.pluck(:resource_type).compact.join(', ')}"
|
||||
I18n.t("views.admin.users.roles.#{role}", default: role)
|
||||
end
|
||||
end
|
||||
|
||||
def user_status(user)
|
||||
if user.suspended?
|
||||
"Suspended"
|
||||
I18n.t("views.admin.users.statuses.Suspended")
|
||||
elsif user.warned?
|
||||
"Warned"
|
||||
I18n.t("views.admin.users.statuses.Warned")
|
||||
elsif user.comment_suspended?
|
||||
"Comment Suspended"
|
||||
I18n.t("views.admin.users.statuses.Comment Suspended")
|
||||
elsif user.trusted?
|
||||
"Trusted"
|
||||
I18n.t("views.admin.users.statuses.Trusted")
|
||||
else
|
||||
"Good Standing"
|
||||
I18n.t("views.admin.users.statuses.Good Standing")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -83,16 +84,12 @@ module Admin
|
|||
# @param [Integer] The limit of organizations that we show
|
||||
# @return [String]
|
||||
def organization_tooltip(organization_names, count, imposed_limit: 0)
|
||||
str = organization_names.first(imposed_limit).join(", ").to_s
|
||||
str = organization_names.first(imposed_limit).join(I18n.t("helpers.admin.user_helper.org_join")).to_s
|
||||
|
||||
return str unless count > imposed_limit
|
||||
|
||||
overflow = overflow_count(count, imposed_limit: imposed_limit)
|
||||
if overflow == 1
|
||||
str + " & #{overflow_count(count, imposed_limit: imposed_limit)} other"
|
||||
else
|
||||
str + " & #{overflow_count(count, imposed_limit: imposed_limit)} others"
|
||||
end
|
||||
I18n.t("helpers.admin.user_helper.org_overflow", count: overflow_count(count, imposed_limit: imposed_limit),
|
||||
orgs: str)
|
||||
end
|
||||
|
||||
# Returns a string hex code representing the indicator color for the given status (also known as BASE_ROLE)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<button type="button" id="expand-search-btn" class="relative c-btn c-btn--icon-alone indicator-btn" aria-label="Expand search" aria-expanded="false" aria-controls="search-users">
|
||||
<%= crayons_icon_tag("search", aria_hidden: true) %>
|
||||
<button type="button" id="expand-search-btn" class="relative c-btn c-btn--icon-alone indicator-btn" aria-label="<%= t("views.admin.users.search.aria_expand") %>" aria-expanded="false" aria-controls="search-users">
|
||||
<%= crayons_icon_tag(t("views.admin.users.search.icon"), aria_hidden: true) %>
|
||||
<span data-testid="search-indicator" class="search-indicator absolute top-1 right-1 c-indicator c-indicator--info <%= params[:search].blank? ? "hidden" : "" %>"></span>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
<button type="button" class="js-export-csv-modal-trigger c-btn" data-modal-title="Download member data" aria-label="Download member data" data-modal-size="small" data-modal-content-selector="#export-csv-modal">
|
||||
<button type="button" class="js-export-csv-modal-trigger c-btn" data-modal-title="<%= t("views.admin.users.download.heading") %>" aria-label="<%= t("views.admin.users.download.aria_label") %>" data-modal-size="small" data-modal-content-selector="#export-csv-modal">
|
||||
<%= crayons_icon_tag(:export, class: "c-btn__icon", aria_hidden: true) %>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<div class="relative">
|
||||
<%= f.text_field :search, id: "search-#{context}", value: params[:search], class: "crayons-textfield mt-0", placeholder: placeholder, aria: { label: aria_label } %>
|
||||
<button type="submit" aria-label="Search" class="crayons-btn crayons-btn--ghost crayons-btn--s crayons-btn--icon-rounded absolute right-2 bottom-0 top-0 m-1">
|
||||
<button type="submit" aria-label="<%= t("views.admin.users.search.aria_label") %>" class="crayons-btn crayons-btn--ghost crayons-btn--s crayons-btn--icon-rounded absolute right-2 bottom-0 top-0 m-1">
|
||||
<%= crayons_icon_tag(:search, aria_hidden: true) %>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<%- headers = ["Name", "Username", "Email address", "Status", "Joining date", "Last activity", "Organizations"] -%>
|
||||
<%- headers = [t("views.admin.users.download.name"), t("views.admin.users.download.username"), t("views.admin.users.download.email"), t("views.admin.users.download.status"), t("views.admin.users.download.join"), t("views.admin.users.download.last_activity"), t("views.admin.users.download.orgs")] -%>
|
||||
<%= CSV.generate_line headers -%>
|
||||
<%- @users.each do |user| -%>
|
||||
<%- row = [user.name, user.username, user.email, user_status(user), user.registered_at&.strftime("%d %b, %Y"), user.last_activity&.strftime("%d %b, %Y"), user.organizations.pluck(:name)] -%>
|
||||
<%- row = [user.name, user.username, user.email, user_status(user), user.registered_at ? l(user.registered_at, format: :members_with_year) : '', user.last_activity ? l(user.last_activity, format: :members_with_year) : '', user.organizations.pluck(:name)] -%>
|
||||
<%= CSV.generate_line(row).html_safe -%>
|
||||
<%- end -%>
|
||||
|
|
@ -2,14 +2,14 @@
|
|||
<div id="member-index-content" class="crayons-card overflow-admin-main-layout-padding p-4 xl:p-0">
|
||||
<header class="xl:p-7 pb-4 mx-2">
|
||||
<div class="flex flex-col l:flex-row justify-content-between l:items-center">
|
||||
<h1 class="crayons-title">Members</h1>
|
||||
<h1 class="crayons-title"><%= t("views.admin.users.heading") %></h1>
|
||||
</div>
|
||||
<%= render "admin/users/index/controls" %>
|
||||
</header>
|
||||
<%= render "admin/users/index/applied_filters" %>
|
||||
<!-- Responsive screen (breakpoints below XL) data view start -->
|
||||
<div class="block xl:hidden fs-s">
|
||||
<h2 class="member-data-heading fs-s py-2 -mx-4 px-6 color-base-60">Members</h2>
|
||||
<h2 class="member-data-heading fs-s py-2 -mx-4 px-6 color-base-60"><%= t("views.admin.users.table.compact_subtitle") %></h2>
|
||||
<ul class="list-none mx-2">
|
||||
<% @users.each do |user| %>
|
||||
<li class="py-4">
|
||||
|
|
@ -42,12 +42,12 @@
|
|||
<div class="flex justify-between items-end">
|
||||
<dl class="flex gap-4">
|
||||
<div>
|
||||
<dt class="color-base-60 fw-normal">Last activity</dt>
|
||||
<dt class="color-base-60 fw-normal"><%= t("views.admin.users.table.last_activity") %></dt>
|
||||
<dd><%= format_last_activity_timestamp(user.last_activity) %></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="color-base-60 fw-normal">Joined on</dt>
|
||||
<dd><%= user.registered_at&.strftime("%d %b, %Y") %></dd>
|
||||
<dt class="color-base-60 fw-normal"><%= t("views.admin.users.table.joined_on") %></dt>
|
||||
<dd><%= l(user.registered_at, format: :members_with_year) if user.registered_at %></dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div>
|
||||
|
|
@ -65,11 +65,11 @@
|
|||
<table class="crayons-table crayons-table--minimal w-100 hidden xl:table">
|
||||
<thead class="member-data-heading">
|
||||
<tr>
|
||||
<th scope="col" class="pl-7">Member</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Last activity & Joined on</th>
|
||||
<th scope="col">Organizations</th>
|
||||
<th scope="col" class="screen-reader-only">Actions</th>
|
||||
<th scope="col" class="pl-7"><%= t("views.admin.users.table.heading.member") %></th>
|
||||
<th scope="col"><%= t("views.admin.users.table.heading.status") %></th>
|
||||
<th scope="col"><%= t("views.admin.users.table.heading.last_joined") %></th>
|
||||
<th scope="col"><%= t("views.admin.users.table.heading.orgs") %></th>
|
||||
<th scope="col" class="screen-reader-only"><%= t("views.admin.users.table.heading.actions") %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -87,7 +87,7 @@
|
|||
<td>
|
||||
<%= format_last_activity_timestamp(user.last_activity) %>
|
||||
<p class="fs-xs color-base-60">
|
||||
<%= user.registered_at&.strftime("%d %b, %Y") %>
|
||||
<%= l(user.registered_at, format: :members_with_year) if user.registered_at %>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
|
|
@ -103,28 +103,28 @@
|
|||
|
||||
<% if @users.empty? %>
|
||||
<div class="align-center flex flex-col my-auto py-7" id="empty-state-message-id">
|
||||
<p class="fs-xl fw-normal mb-2">No members found under these filters.</p>
|
||||
<p class="color-secondary">Try broadening or removing the filters.</p>
|
||||
<p class="fs-xl fw-normal mb-2"><%= t("views.admin.users.empty.text1") %></p>
|
||||
<p class="color-secondary"><%= t("views.admin.users.empty.text2") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
<!-- XL screen data view end -->
|
||||
|
||||
<div class="flex justify-end xl:p-7">
|
||||
<%= paginate @users, theme: "admin", scope: @users, label: "Paginate users", context: "bottom" %>
|
||||
<%= paginate @users, theme: "admin", scope: @users, label: t("views.admin.users.aria_paginate"), context: "bottom" %>
|
||||
</div>
|
||||
|
||||
<div id="export-csv-modal" class="hidden">
|
||||
<div class="flex flex-col gap-4">
|
||||
<p>
|
||||
Your data will be downloaded as a Comma Separated Values (.csv) file.
|
||||
<%= t("views.admin.users.download.desc1") %>
|
||||
</p>
|
||||
<p>
|
||||
Values listed are Name, Username, Email address, Status, Joining date, Last activity, and Organizations.
|
||||
<%= t("views.admin.users.download.desc2") %>
|
||||
</p>
|
||||
<div class="flex gap-2">
|
||||
<%= link_to "Download", "#{export_admin_users_path}.csv", class: "c-cta c-cta--branded self-end" %>
|
||||
<%= link_to t("views.admin.users.download.submit"), "#{export_admin_users_path}.csv", class: "c-cta c-cta--branded self-end" %>
|
||||
<button class="js-export-csv-modal-cancel crayons-btn crayons-btn--ghost">
|
||||
Cancel
|
||||
<%= t("views.admin.users.download.cancel") %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<div role="group" aria-labelledby="applied-filters" class="js-applied-filters hidden m:flex flex-wrap items-center gap-2 mb-4 px-2 xl:px-7">
|
||||
<h2 id="applied-filters" class="screen-reader-only">Applied filters</h2>
|
||||
<h2 id="applied-filters" class="screen-reader-only"><%= t("views.admin.users.filters.applied") %></h2>
|
||||
<% params[:roles]&.each do |role| %>
|
||||
<button
|
||||
data-filter-key="roles[]"
|
||||
data-filter-value="<%= role %>"
|
||||
aria-label="Remove filter: <%= role %>"
|
||||
aria-label="<%= t("views.admin.users.filters.aria_remove", value: t("views.admin.users.roles.#{role}")) %>"
|
||||
class="c-pill c-pill--action-icon c-pill--action-icon--destructive"
|
||||
type="button">
|
||||
<%= role %>
|
||||
<%= t("views.admin.users.roles.#{role}") %>
|
||||
<%= crayons_icon_tag("x.svg", class: "c-pill__action-icon", aria_hidden: true) %>
|
||||
</button>
|
||||
<% end %>
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
<button
|
||||
data-filter-key="statuses[]"
|
||||
data-filter-value="<%= status %>"
|
||||
aria-label="Remove filter: <%= status %>"
|
||||
aria-label="<%= t("views.admin.users.filters.aria_remove", value: t("views.admin.users.statuses.#{status}")) %>"
|
||||
class="c-pill c-pill--action-icon c-pill--action-icon--destructive"
|
||||
type="button">
|
||||
<%= render "admin/users/index/status_indicator", status: status %>
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
<button
|
||||
data-filter-key="organizations[]"
|
||||
data-filter-value="<%= org_id %>"
|
||||
aria-label="Remove filter: <%= org.name %>"
|
||||
aria-label="<%= t("views.admin.users.filters.aria_remove", value: org.name) %>"
|
||||
class="c-pill c-pill--action-icon c-pill--action-icon--destructive"
|
||||
type="button">
|
||||
<%= org.name %>
|
||||
|
|
@ -37,16 +37,16 @@
|
|||
<% if params[:joining_start].present? || params[:joining_end].present? %>
|
||||
<button
|
||||
data-filter-key="joining_date"
|
||||
aria-label="Remove filter: Joining date"
|
||||
aria-label="<%= t("views.admin.users.filters.aria_remove", value: t("views.admin.users.filters.join")) %>"
|
||||
class="c-pill c-pill--action-icon c-pill--action-icon--destructive"
|
||||
type="button">
|
||||
<% start_date = params[:joining_start].presence || "Community creation" %>
|
||||
<% end_date = params[:joining_end].presence || "Today" %>
|
||||
<% start_date = params[:joining_start].presence || t("views.admin.users.filters.creation") %>
|
||||
<% end_date = params[:joining_end].presence || t("views.admin.users.filters.today") %>
|
||||
<%= start_date %> - <%= end_date %>
|
||||
<%= crayons_icon_tag("x.svg", class: "c-pill__action-icon", aria_hidden: true) %>
|
||||
</button>
|
||||
<% end %>
|
||||
<% if params[:roles] || params[:organizations] || params[:joining_start].present? || params[:joining_end].present? || params[:statuses] %>
|
||||
<button class="js-clear-filters-btn c-btn" aria-label="Clear all filters">Clear all</button>
|
||||
<button class="js-clear-filters-btn c-btn" aria-label="<%= t("views.admin.users.filters.aria_clear") %>"><%= t("views.admin.users.filters.clear") %></button>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,17 +3,17 @@
|
|||
<%= form_with url: admin_users_path, method: :get, local: true do |f| %>
|
||||
<div class="flex m:flex-col xl:flex-row justify-between m:items-end xl:justify-end xl:items-center mb-4">
|
||||
<div>
|
||||
<%= paginate @users, theme: "admin", scope: @users, label: "Paginate users", context: "small" %>
|
||||
<%= paginate @users, theme: "admin", scope: @users, label: t("views.admin.users.aria_paginate"), context: "small" %>
|
||||
</div>
|
||||
<div class="flex justify-between xl:justify-end m:w-100 xl:w-max">
|
||||
<div class="hidden m:block m:w-50 xl:w-max">
|
||||
<%= render "admin/users/controls/search_field", f: f, context: "large", placeholder: "Search member...", aria_label: "Search member by name, username or email" %>
|
||||
<%= render "admin/users/controls/search_field", f: f, context: "large", placeholder: t("views.admin.users.search.placeholder"), aria_label: t("views.admin.users.search.aria_field") %>
|
||||
</div>
|
||||
<div class="flex xl:ml-2">
|
||||
<div class="m:hidden">
|
||||
<%= render "admin/users/controls/expand_search_button" %>
|
||||
</div>
|
||||
<button type="button" aria-label="Filter" class="js-open-filter-modal-btn c-btn c-btn--icon-alone"><%= crayons_icon_tag("filter", aria_hidden: true) %></button>
|
||||
<button type="button" aria-label="<%= t("views.admin.users.filters.aria_label") %>" class="js-open-filter-modal-btn c-btn c-btn--icon-alone"><%= crayons_icon_tag("filter", aria_hidden: true) %></button>
|
||||
<%= render "admin/users/controls/export" %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
<%= form_with url: admin_users_path, method: :get, local: true do |f| %>
|
||||
<div class="m:hidden">
|
||||
<div id="search-users" class="hidden">
|
||||
<%= render "admin/users/controls/search_field", f: f, context: "small", placeholder: "Search member...", aria_label: "Search member by name, username or email" %>
|
||||
<%= render "admin/users/controls/search_field", f: f, context: "small", placeholder: t("views.admin.users.search.placeholder"), aria_label: t("views.admin.users.search.aria_field") %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<div class="js-filters-modal hidden">
|
||||
<%= form_with url: admin_users_path, method: :get, local: true, class: "flex flex-col h-100" do |f| %>
|
||||
<div class="flex justify-between items-center border-0 border-b-1 border-base-10 border-solid -mx-7 px-7 pb-2">
|
||||
<h2 class="crayons-subtitle-2">Filters</h2>
|
||||
<button type="button" class="js-clear-all-filters-btn c-btn">Clear filters</button>
|
||||
<h2 class="crayons-subtitle-2"><%= t("views.admin.users.filters.heading") %></h2>
|
||||
<button type="button" class="js-clear-all-filters-btn c-btn"><%= t("views.admin.users.filters.clear_filters") %></button>
|
||||
</div>
|
||||
<p id="filters-description" class="mt-4 crayons-field__description">Members who match any of the selected filters will be displayed</p>
|
||||
<p id="filters-description" class="mt-4 crayons-field__description"><%= t("views.admin.users.filters.desc") %></p>
|
||||
<div class="py-4">
|
||||
<details data-section="roles" class="admin-details">
|
||||
<summary class="py-4 flex justify-between text-uppercase color-base-60 fs-s">
|
||||
<span class="flex">
|
||||
Member roles
|
||||
<%= t("views.admin.users.filters.summary.roles") %>
|
||||
<span class="js-filtered-indicator-roles relative ml-2 <%= params[:roles].blank? ? "hidden" : "" %>">
|
||||
<span class="block absolute c-indicator c-indicator--info"></span>
|
||||
</span>
|
||||
|
|
@ -17,31 +17,34 @@
|
|||
<%= crayons_icon_tag("chevron-down", aria_hidden: true, class: "summary-icon") %>
|
||||
</summary>
|
||||
<fieldset class="js-roles-fieldset pb-4 flex flex-col items-start">
|
||||
<legend class="screen-reader-only">Member roles</legend>
|
||||
<legend class="screen-reader-only"><%= t("views.admin.users.filters.legend.roles") %></legend>
|
||||
<% initially_visible_roles = Constants::Role::SPECIAL_ROLES[0..5] %>
|
||||
<% initially_hidden_roles = Constants::Role::SPECIAL_ROLES[6..] %>
|
||||
<% initially_visible_roles.each_with_index do |role, index| %>
|
||||
<div class="crayons-field crayons-field--checkbox">
|
||||
<%= f.check_box :roles, { multiple: true, class: "crayons-checkbox", id: "filter-role-#{index}", checked: params[:roles]&.include?(role) }, role, false %>
|
||||
<%= f.label :roles, for: "filter-role-#{index}", class: "crayons-field__label" do %><%= role %><% end %>
|
||||
<%= f.label :roles, for: "filter-role-#{index}", class: "crayons-field__label" do %><%= t("views.admin.users.roles.#{role}") %><% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="hidden js-initially-hidden-roles">
|
||||
<% initially_hidden_roles.each_with_index do |role, index| %>
|
||||
<div class="crayons-field crayons-field--checkbox">
|
||||
<%= f.check_box :roles, { multiple: true, class: "crayons-checkbox", id: "filter-role-#{6 + index}", checked: params[:roles]&.include?(role) }, role, false %>
|
||||
<%= f.label :roles, for: "filter-role-#{6 + index}", class: "crayons-field__label" do %><%= role %><% end %>
|
||||
<%= f.label :roles, for: "filter-role-#{6 + index}", class: "crayons-field__label" do %><%= t("views.admin.users.roles.#{role}") %><% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<button type="button" class="js-expand-roles-btn c-btn mt-2" aria-label="See more roles" aria-pressed="false">See more roles</button>
|
||||
<button type="button" class="js-clear-filter-btn c-btn <%= params[:roles].blank? ? "hidden" : "" %>" data-checkbox-fieldset-selector=".js-roles-fieldset" data-filter-indicator-selector=".js-filtered-indicator-roles" aria-label="Clear member roles filter">Clear filter</button>
|
||||
<button type="button" class="js-expand-roles-btn c-btn mt-2" aria-label="<%= t("views.admin.users.filters.aria_more_roles") %>" aria-pressed="false"><%= t("views.admin.users.filters.more_roles") %></button>
|
||||
<button type="button" class="js-clear-filter-btn c-btn <%= params[:roles].blank? ? "hidden" : "" %>" data-checkbox-fieldset-selector=".js-roles-fieldset" data-filter-indicator-selector=".js-filtered-indicator-roles"
|
||||
aria-label="<%= t("views.admin.users.filters.clear_filter.aria_roles") %>">
|
||||
<%= t("views.admin.users.filters.clear_filter.text") %>
|
||||
</button>
|
||||
</fieldset>
|
||||
</details>
|
||||
<details data-section="status" class="admin-details">
|
||||
<summary class="py-4 flex justify-between text-uppercase color-base-60 fs-s">
|
||||
<span class="flex">
|
||||
Status
|
||||
<%= t("views.admin.users.filters.summary.status") %>
|
||||
<span class="js-filtered-indicator-statuses relative ml-2 <%= params[:statuses].blank? ? "hidden" : "" %>">
|
||||
<span class="block absolute c-indicator c-indicator--info"></span>
|
||||
</span>
|
||||
|
|
@ -49,20 +52,23 @@
|
|||
<%= crayons_icon_tag("chevron-down", aria_hidden: true, class: "summary-icon") %>
|
||||
</summary>
|
||||
<fieldset class="js-statuses-fieldset pb-4 flex flex-col items-start">
|
||||
<legend class="screen-reader-only">Status</legend>
|
||||
<legend class="screen-reader-only"><%= t("views.admin.users.filters.legend.status") %></legend>
|
||||
<% filterable_statuses.each_with_index do |status, index| %>
|
||||
<div class="crayons-field crayons-field--checkbox">
|
||||
<%= f.check_box :statuses, { multiple: true, class: "crayons-checkbox", id: "filter-status-#{index}", checked: params[:statuses]&.include?(status) }, status, false %>
|
||||
<%= f.label :statuses, for: "filter-status-#{index}", class: "crayons-field__label" do %><%= render "admin/users/index/status_indicator", status: status %><% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<button type="button" class="js-clear-filter-btn c-btn <%= params[:statuses].blank? ? "hidden" : "" %>" data-checkbox-fieldset-selector=".js-statuses-fieldset" data-filter-indicator-selector=".js-filtered-indicator-statuses" aria-label="Clear statuses filter">Clear filter</button>
|
||||
<button type="button" class="js-clear-filter-btn c-btn <%= params[:statuses].blank? ? "hidden" : "" %>" data-checkbox-fieldset-selector=".js-statuses-fieldset" data-filter-indicator-selector=".js-filtered-indicator-statuses"
|
||||
aria-label="<%= t("views.admin.users.filters.clear_filter.aria_status") %>">
|
||||
<%= t("views.admin.users.filters.clear_filter.text") %>
|
||||
</button>
|
||||
</fieldset>
|
||||
</details>
|
||||
<details data-section="joining-date" class="admin-details">
|
||||
<summary class="py-4 flex justify-between text-uppercase color-base-60 fs-s">
|
||||
<span class="flex">
|
||||
Joining date
|
||||
<%= t("views.admin.users.filters.summary.join") %>
|
||||
<span class="js-filtered-indicator-joining-date relative ml-2 <%= params[:joining_start].blank? && params[:joining_end].blank? ? "hidden" : "" %>">
|
||||
<span class="block absolute c-indicator c-indicator--info"></span>
|
||||
</span>
|
||||
|
|
@ -76,7 +82,7 @@
|
|||
<details data-section="organizations" class="admin-details">
|
||||
<summary class="py-4 flex justify-between text-uppercase color-base-60 fs-s">
|
||||
<span class="flex">
|
||||
Organizations
|
||||
<%= t("views.admin.users.filters.summary.orgs") %>
|
||||
<span class="js-filtered-indicator-organizations relative ml-2 <%= params[:organizations].blank? ? "hidden" : "" %>">
|
||||
<span class="block absolute c-indicator c-indicator--info"></span>
|
||||
</span>
|
||||
|
|
@ -84,7 +90,7 @@
|
|||
<%= crayons_icon_tag("chevron-down", aria_hidden: true, class: "summary-icon") %>
|
||||
</summary>
|
||||
<fieldset class="js-organizations-fieldset pb-4 flex flex-col items-start">
|
||||
<legend class="screen-reader-only">Organizations</legend>
|
||||
<legend class="screen-reader-only"><%= t("views.admin.users.filters.legend.orgs") %></legend>
|
||||
<% @organizations.each_with_index do |org, index| %>
|
||||
<div class="crayons-field crayons-field--checkbox">
|
||||
<%= f.check_box :organizations, { multiple: true, class: "crayons-checkbox", id: "filter-org-#{index}", checked: params[:organizations]&.include?(org.id.to_s) }, org.id, false %>
|
||||
|
|
@ -92,13 +98,16 @@
|
|||
</div>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
<button type="button" class="js-clear-filter-btn c-btn <%= params[:organizations].blank? ? "hidden" : "" %>" data-checkbox-fieldset-selector=".js-organizations-fieldset" data-filter-indicator-selector=".js-filtered-indicator-organizations" aria-label="Clear organizations filter">Clear filter</button>
|
||||
<button type="button" class="js-clear-filter-btn c-btn <%= params[:organizations].blank? ? "hidden" : "" %>" data-checkbox-fieldset-selector=".js-organizations-fieldset" data-filter-indicator-selector=".js-filtered-indicator-organizations"
|
||||
aria-label="<%= t("views.admin.users.filters.clear_filter.aria_orgs") %>">
|
||||
<%= t("views.admin.users.filters.clear_filter.text") %>
|
||||
</button>
|
||||
|
||||
</details>
|
||||
</div>
|
||||
<div class="flex gap-2 mt-auto">
|
||||
<button class="c-btn c-btn--primary grow-1" aria-describedby="filters-description">Apply filters</button>
|
||||
<button type="button" class="js-filter-modal-cancel-btn c-btn grow-1">Cancel</button>
|
||||
<button class="c-btn c-btn--primary grow-1" aria-describedby="filters-description"><%= t("views.admin.users.filters.submit") %></button>
|
||||
<button type="button" class="js-filter-modal-cancel-btn c-btn grow-1"><%= t("views.admin.users.filters.cancel") %></button>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<div class="relative flex">
|
||||
<button type="button" id="<%= user.id %>-action-dropdown-btn-<%= context %>" data-toggle-dropdown="<%= user.id %>-action-dropdown-<%= context %>" aria-controls="<%= user.id %>-action-dropdown-<%= context %>" aria-haspopup="true" aria-expanded="false"
|
||||
class="c-btn c-btn--icon-alone ml-auto" aria-label="Invitation actions: <%= user.email %>">
|
||||
class="c-btn c-btn--icon-alone ml-auto" aria-label="<%= t("views.admin.users.invite.aria_email", email: user.email) %>">
|
||||
<%= crayons_icon_tag("overflow-vertical", aria_hidden: true) %>
|
||||
</button>
|
||||
<div id="<%= user.id %>-action-dropdown-<%= context %>" class="crayons-dropdown right-0">
|
||||
<%= button_to resend_admin_invitation_path(user.id), class: "c-btn c-btn--icon-left w-100 align-left" do %>
|
||||
<%= crayons_icon_tag("send", aria_hidden: true) %> Resend invite
|
||||
<%= crayons_icon_tag("send", aria_hidden: true) %> <%= t("views.admin.users.invite.resend") %>
|
||||
<% end %>
|
||||
<%= button_to admin_invitation_path(user.id), method: :delete, class: "c-btn c-btn--icon-left w-100 align-left" do %>
|
||||
<%= crayons_icon_tag("x", aria_hidden: true) %> Cancel invite
|
||||
<%= crayons_icon_tag("x", aria_hidden: true) %> <%= t("views.admin.users.invite.cancel") %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<img src="<%= organization.profile_image_url_for(length: 64) %>" width="32" height="32" alt="<%= organization.name %>" class="crayons-logo crayons-logo--l border border-2 border-base-0 <%= index.positive? ? "-ml-4" : "" %>">
|
||||
<% end %>
|
||||
<% if org_count > @organization_limit %>
|
||||
<span class="fs-s pr-1">+ <%= overflow_count(org_count, imposed_limit: @organization_limit) %></span>
|
||||
<span class="fs-s pr-1"><%= t("views.admin.users.more_orgs", count: overflow_count(org_count, imposed_limit: @organization_limit)) %></span>
|
||||
<% end %>
|
||||
</figure>
|
||||
<% else %>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
<span class="c-indicator mr-2 inline-block" style="--bg: <%= status_to_indicator_color(status) %>"></span><%= status %>
|
||||
<span class="c-indicator mr-2 inline-block" style="--bg: <%= status_to_indicator_color(status) %>"></span><%= t("views.admin.users.statuses.#{status}") %>
|
||||
|
|
|
|||
|
|
@ -7,41 +7,41 @@
|
|||
<ul class="list-none">
|
||||
<li>
|
||||
<button class="c-btn align-left w-100 c-btn--icon-left"
|
||||
data-modal-title="Add role"
|
||||
data-modal-title="<%= t("views.admin.users.actions.assign_role.heading") %>"
|
||||
data-modal-size="small"
|
||||
data-modal-content-selector="#add-role-modal"
|
||||
data-form-action="<%= user_status_admin_user_path(user) %>">
|
||||
<%= crayons_icon_tag("badge", aria_hidden: true, class: "c-btn__icon") %>
|
||||
Assign role
|
||||
<%= t("views.admin.users.actions.assign_role.text") %>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="c-btn align-left w-100 c-btn--icon-left"
|
||||
data-modal-title="Add organization"
|
||||
data-modal-title="<%= t("views.admin.users.actions.add_org.heading") %>"
|
||||
data-modal-size="small"
|
||||
data-modal-content-selector="#add-organization"
|
||||
data-user-name="<%= user.name %>"
|
||||
data-user-id="<%= user.id %>"
|
||||
data-form-action="<%= user_status_admin_user_path(user) %>">
|
||||
<%= crayons_icon_tag("team", aria_hidden: true, class: "c-btn__icon") %>
|
||||
Add organization
|
||||
<%= t("views.admin.users.actions.add_org.text") %>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="c-btn align-left w-100 c-btn--icon-left"
|
||||
data-modal-title="Adjust balance"
|
||||
data-modal-title="<%= t("views.admin.users.actions.adjust_credit.heading") %>"
|
||||
data-modal-size="small"
|
||||
data-modal-content-selector="#adjust-balance"
|
||||
data-user-name="<%= user.name %>"
|
||||
data-unspent-credits-count="<%= user.unspent_credits_count %>"
|
||||
data-form-action="<%= user_status_admin_user_path(user) %>">
|
||||
<%= crayons_icon_tag("wallet", aria_hidden: true, class: "c-btn__icon") %>
|
||||
Adjust credit balance
|
||||
<%= t("views.admin.users.actions.adjust_credit.text") %>
|
||||
</button>
|
||||
<hr />
|
||||
</li>
|
||||
|
||||
<li><button data-copy-email="<%= user.email %>" type="button" class="c-btn w-100 align-left c-btn--icon-left"> <%= crayons_icon_tag("copy", aria_hidden: true, class: "c-btn__icon") %>Copy email address</button></li>
|
||||
<li><button data-copy-email="<%= user.email %>" type="button" class="c-btn w-100 align-left c-btn--icon-left"> <%= crayons_icon_tag("copy", aria_hidden: true, class: "c-btn__icon") %><%= t("views.admin.users.actions.copy_email") %></button></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@
|
|||
<%= form_with model: [:admin, OrganizationMembership.new], local: true, html: { class: "flex flex-col gap-4" } do |f| %>
|
||||
<%= f.hidden_field :user_id %>
|
||||
<div class="crayons-field">
|
||||
<%= f.label :organization_id, "Organization ID", class: "crayons-field__label" %>
|
||||
<%= f.label :organization_id, t("views.admin.users.actions.add_org.id"), class: "crayons-field__label" %>
|
||||
<%= f.text_field :organization_id, class: "crayons-textfield", size: 8, required: true, inputmode: "numeric", type: "number", placeholder: "1234" %>
|
||||
</div>
|
||||
<div class="crayons-field">
|
||||
<%= f.label :type_of_user, "Role", class: "crayons-field__label" %>
|
||||
<p id="add-org-permission-description" class="crayons-field__description">You can assign <span class="js-user-name"></span> to be an Admin or a regular member.</p>
|
||||
<%= f.select(:type_of_user, options_for_select(%w[member admin]), {}, class: "crayons-select", aria: { describedby: "add-org-permission-description" }) %>
|
||||
<%= f.label :type_of_user, t("views.admin.users.actions.add_org.role"), class: "crayons-field__label" %>
|
||||
<p id="add-org-permission-description" class="crayons-field__description"><%= t("views.admin.users.actions.add_org.role_desc_html", user: tag.span(class: "js-user-name")) %></p>
|
||||
<%= f.select(:type_of_user, options_for_select({ t("views.admin.users.actions.add_org.member") => "member", t("views.admin.users.actions.add_org.admin") => "admin" }), {}, class: "crayons-select", aria: { describedby: "add-org-permission-description" }) %>
|
||||
</div>
|
||||
<div>
|
||||
<%= f.submit "Add organization", class: "c-btn c-btn--primary" %>
|
||||
<%= f.submit t("views.admin.users.actions.add_org.submit"), class: "c-btn c-btn--primary" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<div id="add-role-modal" class="hidden">
|
||||
<%= form_for(:user, method: "patch", html: { class: "js-add-role-form flex flex-col gap-4", id: nil }) do |f| %>
|
||||
<div class="crayons-field">
|
||||
<%= f.label :user_status, "Role", class: "crayons-field__label" %>
|
||||
<%= f.select(:user_status, grouped_options_for_select(role_options(current_user)), { include_blank: "Select role" }, class: "crayons-select") %>
|
||||
<%= f.label :user_status, t("views.admin.users.actions.assign_role.role"), class: "crayons-field__label" %>
|
||||
<%= f.select(:user_status, grouped_options_for_select(role_options(current_user)), { include_blank: t("views.admin.users.actions.assign_role.select") }, class: "crayons-select") %>
|
||||
</div>
|
||||
<div class="crayons-field">
|
||||
<%= f.label :note_for_current_role, "Add a note to this action:", class: "crayons-field__label" %>
|
||||
<%= f.label :note_for_current_role, t("views.admin.users.actions.assign_role.note"), class: "crayons-field__label" %>
|
||||
<%= f.text_area :note_for_current_role, required: true, class: "crayons-textfield", placeholder: "" %>
|
||||
</div>
|
||||
<div>
|
||||
<%= f.button "Add", class: "c-btn c-btn--primary" %>
|
||||
<%= f.button t("views.admin.users.actions.assign_role.submit"), class: "c-btn c-btn--primary" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,30 +3,31 @@
|
|||
<div class="flex items-center gap-2 color-secondary">
|
||||
<%= crayons_icon_tag(:wallet) %>
|
||||
<p>
|
||||
<span class="js-user-name"></span> currently has <span class="color-primary"><span class="js-unspent-credits-count"></span> credits</span>.
|
||||
<%= t("views.admin.users.actions.adjust_credit.desc_html", user: tag.span(class: "js-user-name"), credits: tag.span(t("views.admin.users.actions.adjust_credit.credits_html", amount: tag.span(class: "js-unspent-credits-count")), class: "color-primary")) %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="crayons-field">
|
||||
<%= f.label :credit_action, "Adjust balance", class: "crayons-field__label" %>
|
||||
<%= f.label :credit_action, t("views.admin.users.actions.adjust_credit.adjust"), class: "crayons-field__label" %>
|
||||
<div class="flex gap-2 items-center">
|
||||
<%= f.select :credit_action, options_for_select(%w[Add]), {}, class: "js-credit-action crayons-select w-auto" %>
|
||||
<%= f.text_field :credit_amount,
|
||||
type: "number",
|
||||
required: true,
|
||||
class: "js-credit-amount crayons-textfield w-auto",
|
||||
value: 1,
|
||||
size: 5,
|
||||
min: 1,
|
||||
max: 9999 %>
|
||||
<%= f.label :credit_amount, "credits", class: "color-secondary flex-1", "aria-label": "Amount of credits to add or remove" %>
|
||||
<%= t("views.admin.users.actions.adjust_credit.selector_html",
|
||||
action: f.select(:credit_action, options_for_select({ t("views.admin.users.actions.adjust_credit.add") => "Add" }), {}, class: "js-credit-action crayons-select w-auto"),
|
||||
amount: f.text_field(:credit_amount,
|
||||
type: "number",
|
||||
required: true,
|
||||
class: "js-credit-amount crayons-textfield w-auto",
|
||||
value: 1,
|
||||
size: 5,
|
||||
min: 1,
|
||||
max: 9999),
|
||||
credits: f.label(:credit_amount, t("views.admin.users.actions.adjust_credit.unit"), class: "color-secondary flex-1", "aria-label": t("views.admin.users.actions.adjust_credit.aria_credits"))) %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="crayons-field">
|
||||
<label for="balance-note" class="crayons-field__label">Add a note to this action:</label>
|
||||
<label for="balance-note" class="crayons-field__label"><%= t("views.admin.users.actions.adjust_credit.note") %></label>
|
||||
<%= f.text_area :new_note, id: "balance-note", size: 50, required: true, class: "crayons-textfield" %>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="c-btn c-btn--primary">Adjust balance</button>
|
||||
<button type="submit" class="c-btn c-btn--primary"><%= t("views.admin.users.actions.adjust_credit.submit") %></button>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<div id="banish-for-spam">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="js-banishable-user hidden">
|
||||
<p>This action is irreversible.</p>
|
||||
<p>Once banished, we will delete all content created by <span class="js-user-name"></span> and change their username to @spam_###.</p>
|
||||
<p>Be careful with this action.</p>
|
||||
<p><%= t("views.admin.users.danger.desc1") %></p>
|
||||
<p><%= t("views.admin.users.banish.desc2_html", user: tag.span(class: "js-user-name")) %></p>
|
||||
<p><%= t("views.admin.users.danger.desc3") %></p>
|
||||
<%= form_for(:user, html: { method: :post, id: nil, class: "js-banish-form" }) do %>
|
||||
<button class="c-btn c-btn--primary c-btn--destructive">Banish <span class="js-user-name"></span></button>
|
||||
<button class="c-btn c-btn--primary c-btn--destructive"><%= t("views.admin.users.banish.submit_html", user: tag.span(class: "js-user-name")) %></button>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="js-not-banishable-user">
|
||||
<div class="crayons-notice crayons-notice--danger">This is not a new user. Only Super Admins or Support Admins are allowed to banish <span class="js-user-name"></span>.</div>
|
||||
<div class="crayons-notice crayons-notice--danger"><%= t("views.admin.users.banish.notice_html", user: tag.span(class: "js-user-name")) %></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<div id="unpublish-all-posts">
|
||||
<%= form_tag("/admin/member_manager/users/#{@user.id}/unpublish_all_articles", html: { class: "js-unpublish-form flex flex-col gap-4",
|
||||
method: :post,
|
||||
onsubmit: "return confirm('Are you sure? All posts will be unavailable to the community.')",
|
||||
onsubmit: "return confirm('#{j t('views.admin.users.unpublish.onsubmit')}')",
|
||||
id: nil }) do %>
|
||||
<p>Once unpublished, all posts by <span class="js-user-name"></span> will become hidden and only accessible to themselves.</p>
|
||||
<p class="mt-2">If <span class="js-user-name"></span> is not suspended, they can still re-publish their posts from their dashboard.</p>
|
||||
<p class="mt-2"><%= label_tag "note[content]", "Note:" %><%= text_area_tag "note[content]", "", class: "crayons-textfield", placeholder: "Note text" %></p>
|
||||
<p><%= t("views.admin.users.unpublish.text1_html", username: tag.span(class: "js-user-name")) %></p>
|
||||
<p class="mt-2"><%= t("views.admin.users.unpublish.text2_html", username: tag.span(class: "js-user-name")) %></p>
|
||||
<p class="mt-2"><%= label_tag "note[content]", t("views.admin.users.unpublish.note") %><%= text_area_tag "note[content]", "", class: "crayons-textfield", placeholder: t("views.admin.users.unpublish.note_placeholder") %></p>
|
||||
<div>
|
||||
<button class="c-btn c-btn--destructive c-btn--primary">Unpublish all posts</button>
|
||||
<button class="c-btn c-btn--destructive c-btn--primary"><%= t("views.admin.users.unpublish.submit") %></button>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<% if @user.access_locked? %>
|
||||
<div class="crayons-notice crayons-notice--danger py-2 pr-2 mb-3 flex justify-between items-center">
|
||||
<p class="flex-1 flex">
|
||||
<%= crayons_icon_tag(:lock, title: "Access locked", class: "mr-2") %>
|
||||
This user has locked access.
|
||||
<%= crayons_icon_tag(:lock, title: t("views.admin.users.profile.locked.icon"), class: "mr-2") %>
|
||||
<%= t("views.admin.users.profile.locked.text") %>
|
||||
</p>
|
||||
<%= link_to "Unlock access", unlock_access_admin_user_path(@user), method: :patch, class: "c-link c-link--block c-link--branded" %>
|
||||
<%= link_to t("views.admin.users.profile.locked.unlock"), unlock_access_admin_user_path(@user), method: :patch, class: "c-link c-link--block c-link--branded" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
|
|
@ -23,28 +23,25 @@
|
|||
<%= render "admin/users/show/profile/actions" %>
|
||||
</div>
|
||||
<div class="fs-s mb-1 color-secondary">
|
||||
@<%= @user.username %> <span class="opacity-50">•</span> ID <%= @user.id %> <span class="opacity-50">•</span>
|
||||
@<%= @user.username %> <span class="opacity-50">•</span> <%= t("views.admin.users.profile.id", userid: @user.id) %> <span class="opacity-50">•</span>
|
||||
<% if @user.registered? %>
|
||||
Member since
|
||||
<time datetime="<%= @user.created_at.strftime("%Y-%m-%dT%H:%M:%S%z") %>" title="<%= @user.created_at.strftime("%Y-%m-%d, %H:%M") %>">
|
||||
<%= @user.created_at.strftime("%b %e '%y") %>
|
||||
</time>
|
||||
<%= t("views.admin.users.profile.since_html", time: tag.time(l(@user.created_at, format: :short_with_yy), datetime: @user.created_at.strftime("%Y-%m-%dT%H:%M:%S%z"), title: l(@user.created_at, format: :admin_user))) %>
|
||||
<% else %>
|
||||
<span class="color-accent-danger fw-medium">User has not accepted their invitation yet.</span>
|
||||
<span class="color-accent-danger fw-medium"><%= t("views.admin.users.profile.not_member") %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="flex flex-col s:flex-row gap-3 s:gap-6 flex-wrap">
|
||||
<li>
|
||||
<a href="mailto:<%= @user.email %>" class="c-link c-link--icon-left inline-block" target="_blank">
|
||||
<%= crayons_icon_tag(:email, title: "Email", class: "c-link__icon") %>
|
||||
<%= crayons_icon_tag(:email, title: t("views.admin.users.profile.email"), class: "c-link__icon") %>
|
||||
<%= @user.email %>
|
||||
</a>
|
||||
</li>
|
||||
<% if @user.github_username %>
|
||||
<li>
|
||||
<a href="https://github.com/<%= @user.github_username %>" class="c-link c-link--icon-left inline-block" target="_blank">
|
||||
<%= crayons_icon_tag(:github, title: "GitHub") %>
|
||||
<%= crayons_icon_tag(:github, title: t("views.admin.users.profile.github")) %>
|
||||
<%= @user.github_username %>
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -52,7 +49,7 @@
|
|||
<% if @user.twitter_username %>
|
||||
<li>
|
||||
<a href="https://twitter.com/<%= @user.twitter_username %>" class="c-link c-link--icon-left inline-block" target="_blank">
|
||||
<%= crayons_icon_tag(:twitter, title: "Twitter") %>
|
||||
<%= crayons_icon_tag(:twitter, title: t("views.admin.users.profile.twitter")) %>
|
||||
<%= @user.twitter_username %>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
<nav class="mb-2" aria-label="Member details">
|
||||
<ul class="crayons-navigation crayons-navigation--horizontal">
|
||||
<li><%= link_to "Overview", admin_user_path(@user.id), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'overview'}", aria: @current_tab == "overview" ? { current: "page" } : {} %></li>
|
||||
<li><%= link_to "Notes", admin_user_path(@user.id, tab: :notes), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'notes'}", aria: @current_tab == "notes" ? { current: "page" } : {} %></li>
|
||||
<li><%= link_to "Emails", admin_user_path(@user.id, tab: :emails), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'emails'}", aria: @current_tab == "emails" ? { current: "page" } : {} %></li></li>
|
||||
<li><%= link_to "Reports", admin_user_path(@user.id, tab: :reports), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'reports'}", aria: @current_tab == "reports" ? { current: "page" } : {} %></li></li>
|
||||
<li><%= link_to "Flags", admin_user_path(@user.id, tab: :flags), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'flags'}", aria: @current_tab == "flags" ? { current: "page" } : {} %></li></li>
|
||||
<li><%= link_to t("views.admin.users.tabs.overview"), admin_user_path(@user.id), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'overview'}", aria: @current_tab == "overview" ? { current: "page" } : {} %></li>
|
||||
<li><%= link_to t("views.admin.users.tabs.notes"), admin_user_path(@user.id, tab: :notes), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'notes'}", aria: @current_tab == "notes" ? { current: "page" } : {} %></li>
|
||||
<li><%= link_to t("views.admin.users.tabs.emails"), admin_user_path(@user.id, tab: :emails), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'emails'}", aria: @current_tab == "emails" ? { current: "page" } : {} %></li></li>
|
||||
<li><%= link_to t("views.admin.users.tabs.reports"), admin_user_path(@user.id, tab: :reports), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'reports'}", aria: @current_tab == "reports" ? { current: "page" } : {} %></li></li>
|
||||
<li><%= link_to t("views.admin.users.tabs.flags"), admin_user_path(@user.id, tab: :flags), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'flags'}", aria: @current_tab == "flags" ? { current: "page" } : {} %></li></li>
|
||||
<% if @unpublish_all_data.exists? %>
|
||||
<li><%= link_to "Unpublish All History", admin_user_path(@user.id, tab: :unpublish_logs), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'unpublish_logs'}", aria: @current_tab == "flags" ? { current: "page" } : {} %></li>
|
||||
<li><%= link_to t("views.admin.users.tabs.unpublish_logs"),
|
||||
admin_user_path(@user.id, tab: :unpublish_logs),
|
||||
class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if @current_tab == 'unpublish_logs'}",
|
||||
aria: @current_tab == "flags" ? { current: "page" } : {} %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
<h2 class="crayons-subtitle-1">Send an email</h2>
|
||||
<p class="fs-m fw-normal mb-2">To: <%= @user.name %> (<%= @user.email %>)</p>
|
||||
<h2 class="crayons-subtitle-1"><%= t("views.admin.users.emails.send") %></h2>
|
||||
<p class="fs-m fw-normal mb-2"><%= t("views.admin.users.emails.to", user: @user.name, email: @user.email) %></p>
|
||||
<%= form_with url: send_email_admin_user_path(@user), local: true, class: "grid gap-4 pt-3" do |f| %>
|
||||
<%= f.hidden_field(:user_id, value: @user.id) %>
|
||||
|
||||
<div class="crayons-field">
|
||||
<%= f.label :email_subject, "Subject", class: "crayons-field__label" %>
|
||||
<%= f.text_field :email_subject, class: "crayons-textfield", placeholder: "What do you want to say in the subject line?", required: true %>
|
||||
<%= f.label :email_subject, t("views.admin.users.emails.subject"), class: "crayons-field__label" %>
|
||||
<%= f.text_field :email_subject, class: "crayons-textfield", placeholder: t("views.admin.users.emails.subject_placeholder"), required: true %>
|
||||
</div>
|
||||
|
||||
<div class="crayons-field">
|
||||
<%= f.label :email_body, "Body", class: "crayons-field__label" %>
|
||||
<%= f.text_area :email_body, class: "crayons-textfield", rows: "7", placeholder: "What do you want to say?", required: true %>
|
||||
<%= f.label :email_body, t("views.admin.users.emails.body"), class: "crayons-field__label" %>
|
||||
<%= f.text_area :email_body, class: "crayons-textfield", rows: "7", placeholder: t("views.admin.users.emails.body_placeholder"), required: true %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= f.button "Send email", class: "c-btn c-btn--primary", type: "submit" %>
|
||||
<%= f.button t("views.admin.users.emails.send_submit"), class: "c-btn c-btn--primary", type: "submit" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<div class="flex flex-col h-100">
|
||||
<h2 class="crayons-subtitle-1">Previous emails (<%= @user.email_messages.count %>)</h2>
|
||||
<h2 class="crayons-subtitle-1"><%= t("views.admin.users.emails.previous", num: @user.email_messages.count) %></h2>
|
||||
<% if @user.email_messages.empty? %>
|
||||
<div class="align-center flex flex-col justify-center my-auto py-7">
|
||||
<h3 class="fs-xl fw-normal mb-2">No previous emails found for <%= @user.name %>.</h3>
|
||||
<p class="color-secondary">Any emails sent to <%= @user.email %> will be found here.</p>
|
||||
<h3 class="fs-xl fw-normal mb-2"><%= t("views.admin.users.emails.empty1", user: @user.name) %></h3>
|
||||
<p class="color-secondary"><%= t("views.admin.users.emails.empty2", email: @user.email) %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="pt-3">
|
||||
|
|
@ -14,8 +14,8 @@
|
|||
<%= email.subject %>
|
||||
</a>
|
||||
</h3>
|
||||
<time datetime="<%= email.sent_at&.strftime("%Y-%m-%dT%H:%M:%S%z") %>" class="color-secondary fs-s shrink-0" title="<%= email.sent_at&.strftime("%Y-%m-%d, %H:%M") %>">
|
||||
<%= email.sent_at&.strftime("%b %e '%y") %>
|
||||
<time datetime="<%= email.sent_at&.strftime("%Y-%m-%dT%H:%M:%S%z") %>" class="color-secondary fs-s shrink-0" title="<%= l(email.sent_at, format: :admin_user) if email.sent_at %>">
|
||||
<%= l(email.sent_at, format: :short_with_yy) if email.sent_at %>
|
||||
</time>
|
||||
</article>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
<%= form_with url: verify_email_ownership_admin_user_path(@user), local: true, class: "crayons-card mb-4 p-3 m:p-4 s:pl-4 m:pl-7 pr-4 flex flex-col s:flex-row justify-between gap-4 s:items-center" do |f| %>
|
||||
<% unless @last_email_verification_date %>
|
||||
<div>
|
||||
<h2 class="crayons-subtitle-2">Email not verified</h2>
|
||||
<p class="color-secondary"><%= @user.name %>'s email hasn't been verified yet.</p>
|
||||
<h2 class="crayons-subtitle-2"><%= t("views.admin.users.emails.not_verified.subtitle") %></h2>
|
||||
<p class="color-secondary"><%= t("views.admin.users.emails.not_verified.desc", user: @user.name) %></p>
|
||||
</div>
|
||||
<%= f.button "Verify email address", class: "c-btn c-btn--secondary whitespace-nowrap" %>
|
||||
<%= f.button t("views.admin.users.emails.verify"), class: "c-btn c-btn--secondary whitespace-nowrap" %>
|
||||
<% else %>
|
||||
<p>
|
||||
Last verified on
|
||||
<time datetime="<%= @last_email_verification_date.strftime("%Y-%m-%dT%H:%M:%S%z") %>" class="fw-medium whitespace-nowrap">
|
||||
<%= @last_email_verification_date.strftime("%b %e '%y, %H:%M") %>
|
||||
</time>
|
||||
<%= t("views.admin.users.emails.verified_html", time: tag.time(l(@last_email_verification_date, format: :email_verified), datetime: @last_email_verification_date.strftime("%Y-%m-%dT%H:%M:%S%z"), class: "fw-medium whitespace-nowrap")) %>
|
||||
</p>
|
||||
<%= f.button "Reverify", class: "c-btn c-btn--secondary whitespace-nowrap" %>
|
||||
<%= f.button t("views.admin.users.emails.reverify"), class: "c-btn c-btn--secondary whitespace-nowrap" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -17,28 +17,27 @@
|
|||
<h3 class="crayons-subtitle-3 mb-1">
|
||||
<%= link_to flag.reactable.path, class: "c-link" do %>
|
||||
<% if flag.reactable_type == "Article" %>
|
||||
Post "<%= flag.reactable.title %>"
|
||||
<%= t("views.admin.users.flags.type.article", title: flag.reactable.title) %>
|
||||
<% elsif flag.reactable_type == "User" %>
|
||||
User's profile
|
||||
<%= t("views.admin.users.flags.type.profile") %>
|
||||
<% elsif flag.reactable_type == "Comment" %>
|
||||
Comment on "<%= flag.reactable.title %>"
|
||||
<%= t("views.admin.users.flags.type.comment", title: flag.reactable.title) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</h3>
|
||||
<p class="fs-s color-secondary">
|
||||
Flagged by
|
||||
<%= link_to flag.user.username, admin_user_path(flag.user_id), class: "c-link c-link--branded" %>
|
||||
<%= t("views.admin.users.flags.origin_html", user: link_to(flag.user.username, admin_user_path(flag.user_id), class: "c-link c-link--branded")) %>
|
||||
</p>
|
||||
</div>
|
||||
<time datetime="<%= flag.created_at&.strftime("%Y-%m-%dT%H:%M:%S%z") %>" class="color-secondary fs-s shrink-0" title="<%= flag.created_at&.strftime("%Y-%m-%d, %H:%M") %>">
|
||||
<%= flag.created_at&.strftime("%b %e '%y") %>
|
||||
<time datetime="<%= flag.created_at&.strftime("%Y-%m-%dT%H:%M:%S%z") %>" class="color-secondary fs-s shrink-0" title="<%= l(flag.created_at, format: :admin_user) if flag.created_at %>">
|
||||
<%= l(flag.created_at, format: :short_with_yy) %>
|
||||
</time>
|
||||
</article>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="align-center flex flex-col justify-center my-auto py-8">
|
||||
<h3 class="fs-xl fw-normal mb-2">No flags received against <%= @user.name %> yet.</h3>
|
||||
<p class="color-secondary">Any flags received against <%= @user.name %> will be found here.</p>
|
||||
<h3 class="fs-xl fw-normal mb-2"><%= t("views.admin.users.flags.empty1", user: @user.name) %></h3>
|
||||
<p class="color-secondary"><%= t("views.admin.users.flags.empty2", user: @user.name) %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
<header>
|
||||
<h2 class="crayons-subtitle-1 mb-1">Write a user note</h2>
|
||||
<h2 class="crayons-subtitle-1 mb-1"><%= t("views.admin.users.notes.write") %></h2>
|
||||
</header>
|
||||
<%= form_with model: @user, url: admin_user_path(@user), method: :patch, html: { class: "grid gap-4 pt-3 m:sticky top-8" }, local: true do |f| %>
|
||||
<div class="crayons-field">
|
||||
<%= f.label :new_note, "Note", class: "crayons-field__label" %>
|
||||
<%= f.text_area :new_note, class: "crayons-textfield", rows: 5, placeholder: "Add a note...", aria: { describedby: "note-description" }, required: true %>
|
||||
<%= f.label :new_note, t("views.admin.users.notes.note"), class: "crayons-field__label" %>
|
||||
<%= f.text_area :new_note, class: "crayons-textfield", rows: 5, placeholder: t("views.admin.users.notes.note_placeholder"), aria: { describedby: "note-description" }, required: true %>
|
||||
</div>
|
||||
<div>
|
||||
<%= f.button "Submit", class: "c-btn c-btn--primary", type: "submit" %>
|
||||
<%= f.button t("views.admin.users.notes.submit"), class: "c-btn c-btn--primary", type: "submit" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,27 +1,24 @@
|
|||
<div class="flex flex-col h-100">
|
||||
<h2 class="crayons-subtitle-1">Previous notes (<%= @notes.count %>)</h2>
|
||||
<h2 class="crayons-subtitle-1"><%= t("views.admin.users.notes.previous", num: @notes.count) %></h2>
|
||||
<% if @notes.load.empty? %>
|
||||
<div class="align-center flex flex-col justify-center my-auto py-7">
|
||||
<h3 class="fs-xl fw-normal mb-2">No previous notes found for <%= @user.name %>.</h3>
|
||||
<p class="color-secondary">Any notes added for <%= @user.name %> will be found here. </p>
|
||||
<h3 class="fs-xl fw-normal mb-2"><%= t("views.admin.users.notes.empty1", user: @user.name) %></h3>
|
||||
<p class="color-secondary"><%= t("views.admin.users.notes.empty2", user: @user.name) %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="pt-3">
|
||||
<% @notes.each do |note| %>
|
||||
<% author = User.find(note.author_id).username %>
|
||||
<article class="c-list-item flex justify-between gap-4">
|
||||
<h3 class="screen-reader-only">Note by <%= author %> on <%= note.created_at.strftime("%b %e '%y") %></h3>
|
||||
<h3 class="screen-reader-only"><%= t("views.admin.users.notes.note_by", author: author, time: l(note.created_at, format: :short_with_yy)) %></h3>
|
||||
<div>
|
||||
<p><%= note.content %></p>
|
||||
<p class="fs-s color-secondary">
|
||||
<%= note.reason.presence %>
|
||||
<% if note.author_id.present? %>
|
||||
by <span class="fw-medium"><%= author %></span>
|
||||
<% end %>
|
||||
<%= t("views.admin.users.notes.reason_by_html", reason: note.reason.presence, by: note.author_id.present? ? t("views.admin.users.notes.by_html", author: tag.span(author, class: "fw-medium")) : "") %>
|
||||
</p>
|
||||
</div>
|
||||
<time datetime="<%= note.created_at.strftime("%Y-%m-%dT%H:%M:%S%z") %>" class="color-secondary fs-s shrink-0" title="<%= note.created_at.strftime("%Y-%m-%d, %H:%M") %>">
|
||||
<%= note.created_at.strftime("%b %e '%y") %>
|
||||
<time datetime="<%= note.created_at.strftime("%Y-%m-%dT%H:%M:%S%z") %>" class="color-secondary fs-s shrink-0" title="<%= l(note.created_at, format: :admin_user) %>">
|
||||
<%= l(note.created_at, format: :short_with_yy) %>
|
||||
</time>
|
||||
</article>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
<header class="mb-4">
|
||||
<h2 class="crayons-subtitle-2 mb-1 flex items-center">
|
||||
<%= crayons_icon_tag(:wallet, title: "Wallet", aria_hidden: true, class: "mr-2") %>
|
||||
Credits
|
||||
<%= crayons_icon_tag(:wallet, title: t("views.admin.users.overview.credits.icon"), aria_hidden: true, class: "mr-2") %>
|
||||
<%= t("views.admin.users.overview.credits.subtitle") %>
|
||||
</h2>
|
||||
<p class="color-secondary">Grant/remove credits to purchase classified listings. <a href="https://admin.forem.com/docs/advanced-customization/config/credits" rel="noopener noreferer" target="_blank" class="c-link c-link--branded" aria-label="Learn more about credits">Learn more</a></p>
|
||||
<p class="color-secondary">
|
||||
<%= t("views.admin.users.overview.credits.desc") %>
|
||||
<a href="https://admin.forem.com/docs/advanced-customization/config/credits" rel="noopener noreferer" target="_blank" class="c-link c-link--branded" aria-label="<%= t("views.admin.users.overview.credits.aria_learn") %>"><%= t("views.admin.users.overview.learn") %></a>
|
||||
</p>
|
||||
</header>
|
||||
<div class="flex justify-between items-center">
|
||||
<p data-testid="user-credits" class="fs-2xl fw-heavy"><%= @user.unspent_credits_count %></p>
|
||||
<button class="c-btn c-btn--secondary whitespace-nowrap" type="button"
|
||||
data-modal-title="Adjust balance"
|
||||
data-modal-title="<%= t("views.admin.users.actions.adjust_credit.heading") %>"
|
||||
data-modal-size="small"
|
||||
data-modal-content-selector="#adjust-balance"
|
||||
data-user-name="<%= @user.name %>"
|
||||
data-unspent-credits-count="<%= @user.unspent_credits_count %>"
|
||||
data-form-action="<%= admin_user_path(@user) %>">Adjust balance</button>
|
||||
data-form-action="<%= admin_user_path(@user) %>"><%= t("views.admin.users.overview.credits.button") %></button>
|
||||
</div>
|
||||
<%= render "admin/users/modals/adjust_credits_modal" %>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,23 @@
|
|||
<header class="mb-4">
|
||||
<h2 class="crayons-subtitle-2 mb-1 flex items-center">
|
||||
<%= crayons_icon_tag(:team, title: "Organizations", aria_hidden: true, class: "mr-2") %>
|
||||
Organizations
|
||||
<%= crayons_icon_tag(:team, title: t("views.admin.users.overview.orgs.icon"), aria_hidden: true, class: "mr-2") %>
|
||||
<%= t("views.admin.users.overview.orgs.subtitle") %>
|
||||
</h2>
|
||||
<p class="color-secondary">Add this member to organizations in your community. <a href="https://admin.forem.com/docs/managing-your-community/organization-pages#organization-roles" rel="noopener noreferer" target="_blank" class="c-link c-link--branded" aria-label="Learn more about organizations">Learn more</a></p>
|
||||
<p class="color-secondary">
|
||||
<%= t("views.admin.users.overview.orgs.desc") %>
|
||||
<a href="https://admin.forem.com/docs/managing-your-community/organization-pages#organization-roles" rel="noopener noreferer" target="_blank" class="c-link c-link--branded" aria-label="<%= t("views.admin.users.overview.orgs.aria_learn") %>"><%= t("views.admin.users.overview.learn") %></a>
|
||||
</p>
|
||||
</header>
|
||||
<% if @organization_memberships.load.empty? %>
|
||||
<div class="flex justify-between items-center gap-4">
|
||||
<p>Not part of any organization yet.</p>
|
||||
<button class="c-btn c-btn--secondary whitespace-nowrap" type="button" data-modal-title="Add organization" data-modal-size="small" data-modal-content-selector="#add-organization" data-user-name="<%= @user.name %>" data-user-id="<%= @user.id %>">Add organization</button>
|
||||
<p><%= t("views.admin.users.overview.orgs.empty") %></p>
|
||||
<button class="c-btn c-btn--secondary whitespace-nowrap" type="button" data-modal-title="<%= t("views.admin.users.actions.add_org.heading") %>" data-modal-size="small" data-modal-content-selector="#add-organization" data-user-name="<%= @user.name %>" data-user-id="<%= @user.id %>">
|
||||
<%= t("views.admin.users.overview.orgs.button") %>
|
||||
</button>
|
||||
</div>
|
||||
<% else %>
|
||||
<%# Used for aria-describedby on input fields, placed here to avoid duplicate IDs when mapping over orgs %>
|
||||
<span class="screen-reader-only" id="edit-org-permission-description">You can assign <%= @user.name %> to be an Admin or a regular member.</span>
|
||||
<span class="screen-reader-only" id="edit-org-permission-description"><%= t("views.admin.users.actions.add_org.role_desc_html", user: @user.name) %></span>
|
||||
<% @organization_memberships.each do |org_membership| %>
|
||||
<div class="c-card c-card--interactive flex p-2 relative items-center mb-2 pl-3">
|
||||
<div class="flex items-center gap-2 flex-1">
|
||||
|
|
@ -23,17 +28,17 @@
|
|||
<a href="<%= org_membership.organization.path %>" target="_blank" rel="noopener" class="c-link">
|
||||
<%= org_membership.organization.name %>
|
||||
</a>
|
||||
<span class="opacity-50">•</span> <%= org_membership.type_of_user.capitalize %></span>
|
||||
<span class="opacity-50">•</span> <%= t("views.admin.users.overview.orgs.type.#{org_membership.type_of_user}") %></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="c-card__revealable shrink-0">
|
||||
<button type="button" class="c-btn c-btn--icon-alone" aria-label="Edit <%= org_membership.organization.name %> organization membership"
|
||||
data-modal-title="Edit <%= @user.name %>'s role at an organization" data-modal-size="small" data-modal-content-selector="#edit-organization-<%= org_membership.organization.id %>">
|
||||
<button type="button" class="c-btn c-btn--icon-alone" aria-label="<%= t("views.admin.users.overview.orgs.aria_edit", org: org_membership.organization.name) %>"
|
||||
data-modal-title="<%= t("views.admin.users.actions.add_org.edit", user: @user.name) %>" data-modal-size="small" data-modal-content-selector="#edit-organization-<%= org_membership.organization.id %>">
|
||||
<%= crayons_icon_tag(:edit, class: "c-btn__icon", aria_hidden: true) %>
|
||||
</button>
|
||||
<%= form_with model: [:admin, org_membership], method: :delete, local: true, html: { class: "inline" } do |f| %>
|
||||
<%= f.button crayons_icon_tag(:x, class: "c-btn__icon", aria_hidden: true), aria: { label: "Revoke #{org_membership.organization.name} organization membership" }, class: "c-btn c-btn--destructive c-btn--icon-alone",
|
||||
data: { confirm: "Are you sure you want to remove #{org_membership.user.name} from #{org_membership.organization.name}?" } %>
|
||||
<%= f.button crayons_icon_tag(:x, class: "c-btn__icon", aria_hidden: true), aria: { label: t("views.admin.users.overview.orgs.aria_revoke", org: org_membership.organization.name) }, class: "c-btn c-btn--destructive c-btn--icon-alone",
|
||||
data: { confirm: t("views.admin.users.overview.orgs.revoke_confirm", user: org_membership.user.name, org: org_membership.organization.name) } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -41,22 +46,30 @@
|
|||
<div id="edit-organization-<%= org_membership.organization.id %>" class="hidden">
|
||||
<%= form_with model: [:admin, org_membership], method: :patch, local: true do |f| %>
|
||||
<div class="crayons-field mb-4">
|
||||
<%= f.label "Role", class: "crayons-field__label", for: "edit_#{org_membership.organization.id}_type_of_user" %>
|
||||
<p class="crayons-field__description">You can assign <%= @user.name %> to be an Admin or a regular member.</p>
|
||||
<%= f.select :type_of_user, options_for_select(%w[member admin], selected: org_membership.type_of_user), {}, id: "edit_#{org_membership.organization.id}_type_of_user", class: "crayons-select", aria: { describedby: "edit-org-permission-description" } %>
|
||||
<%= f.label t("views.admin.users.actions.add_org.role"), class: "crayons-field__label", for: "edit_#{org_membership.organization.id}_type_of_user" %>
|
||||
<p class="crayons-field__description"><%= t("views.admin.users.actions.add_org.role_desc_html", user: @user.name) %></p>
|
||||
<%= f.select(:type_of_user,
|
||||
options_for_select(
|
||||
{ t("views.admin.users.actions.add_org.member") => "member", t("views.admin.users.actions.add_org.admin") => "admin" },
|
||||
selected: org_membership.type_of_user,
|
||||
),
|
||||
{},
|
||||
id: "edit_#{org_membership.organization.id}_type_of_user",
|
||||
class: "crayons-select",
|
||||
aria: { describedby: "edit-org-permission-description" }) %>
|
||||
</div>
|
||||
<%= f.button "Submit", class: "c-btn c-btn--primary", type: "submit" %>
|
||||
<%= f.button t("views.admin.users.overview.orgs.submit"), class: "c-btn c-btn--primary", type: "submit" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<button
|
||||
class="c-btn c-btn--secondary whitespace-nowrap w-100"
|
||||
type="button"
|
||||
data-modal-title="Add <%= @user.name %> to an organization"
|
||||
data-modal-title="<%= t("views.admin.users.actions.add_org.add", user: @user.name) %>"
|
||||
data-modal-size="small"
|
||||
data-modal-content-selector="#add-organization"
|
||||
data-user-name="<%= @user.name %>"
|
||||
data-user-id="<%= @user.id %>">Add organization</button>
|
||||
data-user-id="<%= @user.id %>"><%= t("views.admin.users.overview.orgs.button") %></button>
|
||||
<% end %>
|
||||
|
||||
<%= render "admin/users/modals/add_organization_modal" %>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
<header class="mb-4">
|
||||
<h2 class="crayons-subtitle-2 mb-1 flex items-center">
|
||||
<%= crayons_icon_tag(:badge, title: "Roles", aria_hidden: true, class: "mr-2") %>
|
||||
Roles
|
||||
<%= crayons_icon_tag(:badge, title: t("views.admin.users.overview.roles.icon"), aria_hidden: true, class: "mr-2") %>
|
||||
<%= t("views.admin.users.overview.roles.subtitle") %>
|
||||
</h2>
|
||||
<p class="color-secondary">Grant this member permissions by assigning a role. <a href="https://admin.forem.com/docs/forem-basics/user-roles" rel="noopener noreferer" target="_blank" class="c-link c-link--branded" aria-label="Learn more about roles">Learn more</a></p>
|
||||
<p class="color-secondary">
|
||||
<%= t("views.admin.users.overview.roles.desc") %>
|
||||
<a href="https://admin.forem.com/docs/forem-basics/user-roles" rel="noopener noreferer" target="_blank" class="c-link c-link--branded" aria-label="<%= t("views.admin.users.overview.roles.aria_learn") %>"><%= t("views.admin.users.overview.learn") %></a>
|
||||
</p>
|
||||
</header>
|
||||
<% unless @user.roles.any? %>
|
||||
<div class="flex justify-between items-center">
|
||||
<p>No roles assigned yet.</p>
|
||||
<button class="c-btn c-btn--secondary whitespace-nowrap" type="button" data-modal-title="Add role" data-modal-size="m" data-modal-content-selector="#add-role-modal" data-form-action="<%= user_status_admin_user_path(@user) %>">Assign role</button>
|
||||
<p><%= t("views.admin.users.overview.roles.empty") %></p>
|
||||
<button class="c-btn c-btn--secondary whitespace-nowrap" type="button" data-modal-title="<%= t("views.admin.users.actions.assign_role.heading") %>" data-modal-size="m" data-modal-content-selector="#add-role-modal" data-form-action="<%= user_status_admin_user_path(@user) %>">
|
||||
<%= t("views.admin.users.overview.roles.button") %>
|
||||
</button>
|
||||
</div>
|
||||
<% else %>
|
||||
<ul class="flex flex-wrap gap-2">
|
||||
|
|
@ -20,27 +25,23 @@
|
|||
type="button"
|
||||
aria-disabled="true">
|
||||
<%= crayons_icon_tag(:lock, class: "c-pill__description-icon", aria_hidden: true, width: 18, height: 18) %>
|
||||
<% if role.resource_name %>
|
||||
<%= role.resource_name.to_s %>
|
||||
<% else %>
|
||||
<%= role_display_name(role) %>
|
||||
<% end %>
|
||||
<span data-testid="tooltip" class="crayons-tooltip__content">You can't remove this role.</span>
|
||||
<%= t("views.admin.users.overview.roles.name.#{role.name}", default: role.resource_name ? role.resource_name.to_s : role_display_name(role)) %>
|
||||
<span data-testid="tooltip" class="crayons-tooltip__content"><%= t("views.admin.users.overview.roles.locked") %></span>
|
||||
</button>
|
||||
<% else %>
|
||||
<%= button_to url_for(action: :destroy, user_id: @user.id, role: role.name.to_sym, resource_type: role.resource_type), method: :delete, data: { confirm: "Are you sure?" }, class: "c-pill c-pill--action-icon" do %>
|
||||
<span class="screen-reader-only">Remove role:</span>
|
||||
<% if role.resource_name %>
|
||||
<%= role.resource_name.to_s %>
|
||||
<% else %>
|
||||
<%= role_display_name(role) %>
|
||||
<% end %>
|
||||
<%= button_to url_for(action: :destroy, user_id: @user.id, role: role.name.to_sym, resource_type: role.resource_type), method: :delete, data: { confirm: t("views.admin.users.overview.roles.remove_confirm") }, class: "c-pill c-pill--action-icon" do %>
|
||||
<span class="screen-reader-only"><%= t("views.admin.users.overview.roles.remove") %></span>
|
||||
<%= t("views.admin.users.overview.roles.name.#{role.name}", default: role.resource_name ? role.resource_name.to_s : role_display_name(role)) %>
|
||||
<%= crayons_icon_tag(:x, class: "c-pill__action-icon", aria_hidden: true, width: 18, height: 18) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<li><button class="c-btn c-btn--secondary whitespace-nowrap" type="button" data-modal-title="Add role" data-modal-size="small" data-modal-content-selector="#add-role-modal" data-form-action="<%= user_status_admin_user_path(@user) %>">Assign role</button></li>
|
||||
<li>
|
||||
<button class="c-btn c-btn--secondary whitespace-nowrap" type="button" data-modal-title="<%= t("views.admin.users.actions.assign_role.heading") %>" data-modal-size="small" data-modal-content-selector="#add-role-modal" data-form-action="<%= user_status_admin_user_path(@user) %>">
|
||||
<%= t("views.admin.users.overview.roles.button") %>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,30 +2,30 @@
|
|||
<dl class="grid grid-flow-col grid-cols-3 grid-rows-2 l:grid-cols-6 l:grid-rows-1">
|
||||
<div class="flex flex-col items-center">
|
||||
<dd><strong class="fs-xl l:fs-2xl fw-heavy lh-tight"><%= @user.comments_count %></strong></dd>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal">Comments</dt>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal"><%= t("views.admin.users.overview.comments") %></dt>
|
||||
</div>
|
||||
<div class="flex flex-col items-center">
|
||||
<dd><strong class="fs-xl l:fs-2xl fw-heavy lh-tight"><%= @user.articles_count %></strong></dd>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal">Posts</dt>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal"><%= t("views.admin.users.overview.posts") %></dt>
|
||||
</div>
|
||||
<div class="flex flex-col items-center">
|
||||
<dd><strong class="fs-xl l:fs-2xl fw-heavy lh-tight"><%= @user.reactions_count %></strong></dd>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal">Reactions</dt>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal"><%= t("views.admin.users.overview.reactions") %></dt>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center">
|
||||
<dd><strong class="fs-xl l:fs-2xl fw-heavy lh-tight"><%= @user.followers_count %></strong></dd>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal">Followers</dt>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal"><%= t("views.admin.users.overview.followers") %></dt>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center">
|
||||
<dd><strong class="fs-xl l:fs-2xl fw-heavy lh-tight"><%= @user.following_users_count %></strong></dd>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal">Following</dt>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal"><%= t("views.admin.users.overview.following") %></dt>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center">
|
||||
<dd><strong class="fs-xl l:fs-2xl fw-heavy lh-tight"><%= @user.badge_achievements_count %></strong></dd>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal">Badges</dt>
|
||||
<dt class="fs-s l:fs-base color-secondary fw-normal"><%= t("views.admin.users.overview.badges") %></dt>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
<header class="mb-4">
|
||||
<h2 class="crayons-subtitle-2 mb-1 flex items-center">
|
||||
<%= crayons_icon_tag("mod-filled", title: "Mod", aria_hidden: true, class: "mr-2") %>
|
||||
Tags
|
||||
<%= crayons_icon_tag("mod-filled", title: t("views.admin.users.overview.tag_mod.icon"), aria_hidden: true, class: "mr-2") %>
|
||||
<%= t("views.admin.users.overview.tag_mod.subtitle") %>
|
||||
</h2>
|
||||
<p class="color-secondary">Add a tag that this member can moderate. <a href="https://admin.forem.com/docs/managing-your-community/tag-moderator-features" rel="noopener noreferer" target="_blank" class="c-link c-link--branded" aria-label="Learn more about tag moderation">Learn more</a></p>
|
||||
<p class="color-secondary">
|
||||
<%= t("views.admin.users.overview.tag_mod.desc") %>
|
||||
<a href="https://admin.forem.com/docs/managing-your-community/tag-moderator-features" rel="noopener noreferer" target="_blank" class="c-link c-link--branded" aria-label="<%= t("views.admin.users.overview.tag_mod.aria_learn") %>"><%= t("views.admin.users.overview.learn") %></a>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<% moderated_tags = @user.roles.select { |role| role.name == "tag_moderator" } %>
|
||||
|
|
@ -14,7 +17,7 @@
|
|||
<li>
|
||||
<%# You can't currently remove a tag from this view %>
|
||||
<button class="c-pill cursor-default" aria-disabled="true" aria-describedby="tag-moderation-description" style="--icon-right-color: var(--color-secondary); --icon-right-color-hover: var(--accent-danger);" type="button">
|
||||
<span class="screen-reader-only">Remove tag:</span>
|
||||
<span class="screen-reader-only"><%= t("views.admin.users.overview.tag_mod.remove") %></span>
|
||||
#<%= role.resource_name.to_s %>
|
||||
</button>
|
||||
</li>
|
||||
|
|
@ -23,5 +26,5 @@
|
|||
<% end %>
|
||||
|
||||
<div id="tag-moderation-description" class="crayons-notice crayons-notice--warning">
|
||||
Adding tags for moderation is currently only possible through a particular <a href="<%= admin_tags_path %>" class="c-link c-link--branded">tag's page</a>, by providing the user's ID (<strong><%= @user.id %></strong>).
|
||||
<%= t("views.admin.users.overview.tag_mod.notice_html", tag_page: link_to(t("views.admin.users.overview.tag_mod.tag_page"), admin_tags_path, class: "c-link c-link--branded"), user_id: tag.strong(@user.id)) %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,42 +1,42 @@
|
|||
<%= javascript_packs_with_chunks_tag "admin/editUser", defer: true %>
|
||||
<div class="flex relative justify-between s:justify-end gap-2 my-2 s:my-0">
|
||||
<%= link_to "Visit profile", @user.path, class: "c-cta", target: "_blank", rel: "noopener" %>
|
||||
<%= link_to t("views.admin.users.profile.visit"), @user.path, class: "c-cta", target: "_blank", rel: "noopener" %>
|
||||
<div class="dropdown-trigger-container">
|
||||
<button type="button" class="c-btn c-btn--icon-alone dropdown-trigger" id="options-dropdown-trigger" aria-haspopup="true" aria-expanded="false" aria-controls="options-dropdown">
|
||||
<%= crayons_icon_tag("overflow-vertical", title: "Options") %>
|
||||
<%= crayons_icon_tag("overflow-vertical", title: t("views.admin.users.profile.options.icon")) %>
|
||||
</button>
|
||||
<div class="crayons-dropdown right-0 left-0 s:left-auto" id="options-dropdown">
|
||||
<ul class="p-0">
|
||||
<% if @user.access_locked? %>
|
||||
<li><%= link_to "Unlock access", unlock_access_admin_user_path(@user), method: :patch, class: "c-link c-link--block" %></li>
|
||||
<li><%= link_to t("views.admin.users.profile.locked.unlock"), unlock_access_admin_user_path(@user), method: :patch, class: "c-link c-link--block" %></li>
|
||||
<% end %>
|
||||
<li><button type="button" class="c-btn w-100 align-left" data-modal-title="Export <%= @user.name %>'s data" data-modal-size="small" data-modal-content-selector="#export-data">Export data</button></li>
|
||||
<li><button type="button" class="c-btn w-100 align-left" data-modal-title="Merge users" data-modal-size="small" data-modal-content-selector="#merge-accounts">Merge users</button></li>
|
||||
<li><button type="button" class="c-btn w-100 align-left" data-modal-title="<%= t("views.admin.users.export.heading", user: @user.name) %>" data-modal-size="small" data-modal-content-selector="#export-data"><%= t("views.admin.users.profile.options.export") %></button></li>
|
||||
<li><button type="button" class="c-btn w-100 align-left" data-modal-title="<%= t("views.admin.users.merge.heading") %>" data-modal-size="small" data-modal-content-selector="#merge-accounts"><%= t("views.admin.users.profile.options.merge") %></button></li>
|
||||
<% if @user.articles_count > 0 %>
|
||||
<li>
|
||||
<button type="button"
|
||||
class="c-btn w-100 align-left"
|
||||
data-modal-title="Unpublish all posts"
|
||||
data-modal-title="<%= t("views.admin.users.unpublish.heading") %>"
|
||||
data-modal-size="small"
|
||||
data-modal-content-selector="#unpublish-all-posts"
|
||||
data-form-action="<%= unpublish_all_articles_admin_user_path(@user) %>"
|
||||
data-user-name="<%= @user.name %>">Unpublish all posts</button>
|
||||
data-user-name="<%= @user.name %>"><%= t("views.admin.users.profile.options.unpublish") %></button>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if @user.identities.any? %>
|
||||
<li><button type="button" class="c-btn w-100 align-left" data-modal-title="Remove social accounts" data-modal-size="medium" data-modal-content-selector="#remove-social-accounts">Remove social accounts</button></li>
|
||||
<li><button type="button" class="c-btn w-100 align-left" data-modal-title="<%= t("views.admin.users.social.heading") %>" data-modal-size="medium" data-modal-content-selector="#remove-social-accounts"><%= t("views.admin.users.profile.options.remove_social") %></button></li>
|
||||
<% end %>
|
||||
<li>
|
||||
<button type="button"
|
||||
class="c-btn c-btn--destructive w-100 align-left"
|
||||
data-modal-title="Banish <%= @user.name %>"
|
||||
data-modal-title="<%= t("views.admin.users.banish.heading", user: @user.name) %>"
|
||||
data-modal-size="small"
|
||||
data-modal-content-selector="#banish-for-spam"
|
||||
data-form-action="<%= banish_admin_user_path(@user) %>"
|
||||
data-user-name="<%= @user.name %>"
|
||||
data-banishable-user="<%= @banishable_user %>">Banish user</button>
|
||||
data-banishable-user="<%= @banishable_user %>"><%= t("views.admin.users.profile.options.banish") %></button>
|
||||
</li>
|
||||
<li><button type="button" class="c-btn c-btn--destructive w-100 align-left" data-modal-title="Delete <%= @user.name %>'s account" data-modal-size="small" data-modal-content-selector="#delete-user">Delete user</button></li>
|
||||
<li><button type="button" class="c-btn c-btn--destructive w-100 align-left" data-modal-title="<%= t("views.admin.users.delete.heading", user: @user.name) %>" data-modal-size="small" data-modal-content-selector="#delete-user"><%= t("views.admin.users.profile.options.delete") %></button></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<span class="ml-3 whitespace-nowrap" title="Current status">
|
||||
<span class="screen-reader-only">Current status:</span>
|
||||
<span class="ml-3 whitespace-nowrap" title="<%= t("views.admin.users.status_title") %>">
|
||||
<span class="screen-reader-only"><%= t("views.admin.users.status_reader") %></span>
|
||||
<% if @user.suspended? %>
|
||||
<span data-testid="user-status" class="c-indicator c-indicator--danger c-indicator--relaxed">Suspended</span>
|
||||
<span data-testid="user-status" class="c-indicator c-indicator--danger c-indicator--relaxed"><%= t("views.admin.users.statuses.Suspended") %></span>
|
||||
<% elsif @user.warned? %>
|
||||
<span data-testid="user-status" class="c-indicator c-indicator--warning c-indicator--relaxed">Warned</span>
|
||||
<span data-testid="user-status" class="c-indicator c-indicator--warning c-indicator--relaxed"><%= t("views.admin.users.statuses.Warned") %></span>
|
||||
<% elsif @user.comment_suspended? %>
|
||||
<span data-testid="user-status" class="c-indicator c-indicator--warning c-indicator--relaxed">Comment suspended</span>
|
||||
<span data-testid="user-status" class="c-indicator c-indicator--warning c-indicator--relaxed"><%= t("views.admin.users.statuses.Comment suspended") %></span>
|
||||
<% elsif @user.trusted? %>
|
||||
<span data-testid="user-status" class="c-indicator c-indicator--success c-indicator--relaxed">Trusted</span>
|
||||
<span data-testid="user-status" class="c-indicator c-indicator--success c-indicator--relaxed"><%= t("views.admin.users.statuses.Trusted") %></span>
|
||||
<% else %>
|
||||
<span data-testid="user-status" class="c-indicator c-indicator--relaxed">Good standing</span>
|
||||
<span data-testid="user-status" class="c-indicator c-indicator--relaxed"><%= t("views.admin.users.statuses.Good standing") %></span>
|
||||
<% end %>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<div id="delete-user">
|
||||
<% if current_user.super_admin? %>
|
||||
<%= form_for(@user, url: full_delete_admin_user_path(@user), html: { class: "flex flex-col gap-4", method: :post, onsubmit: "return confirm('Are you sure? This action is irreversible.')", id: nil }) do |f| %>
|
||||
<p>This action is irreversible.</p>
|
||||
<p>Once deleted, all data relating to <%= @user.name %> will be removed from our database.</p>
|
||||
<p>Be careful with this action.</p>
|
||||
<%= form_for(@user, url: full_delete_admin_user_path(@user), html: { class: "flex flex-col gap-4", method: :post, onsubmit: "return confirm('#{j t('views.admin.users.delete.onsubmit')}')", id: nil }) do |f| %>
|
||||
<p><%= t("views.admin.users.danger.desc1") %></p>
|
||||
<p><%= t("views.admin.users.delete.desc2", user: @user.name) %></p>
|
||||
<p><%= t("views.admin.users.danger.desc3") %></p>
|
||||
<div>
|
||||
<button class="c-btn c-btn--primary c-btn--destructive">Delete now</button>
|
||||
<button class="c-btn c-btn--primary c-btn--destructive"><%= t("views.admin.users.delete.submit") %></button>
|
||||
</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="crayons-notice crayons-notice--danger">Only Super Admins are allowed to delete users.</div>
|
||||
<div class="crayons-notice crayons-notice--danger"><%= t("views.admin.users.delete.notice") %></div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
<div id="export-data">
|
||||
<div class="flex flex-col gap-4">
|
||||
<p>
|
||||
Choose between sending the exported data to either your Admin contact email, <%= ForemInstance.email %>,
|
||||
or to <%= @user.name %>'s <a href="mailto:<%= @user.email %>">user email</a> directly.
|
||||
<%= t("views.admin.users.export.desc1_html", contact: ForemInstance.email, user: @user.name, user_email: mail_to(@user.email, t("views.admin.users.export.user_email"))) %>
|
||||
</p>
|
||||
<p>
|
||||
Exported data includes a user's posts and comments.
|
||||
<%= t("views.admin.users.export.desc2") %>
|
||||
</p>
|
||||
<div class="flex gap-2">
|
||||
<%= button_to "Export to Admin", export_data_admin_user_path(@user.id), data: { confirm: "Are you sure you want to export this user's content to #{ForemInstance.email}?" }, class: "c-btn c-btn--secondary", params: { send_to_admin: true } %>
|
||||
<%= button_to "Export to User", export_data_admin_user_path(@user.id), data: { confirm: "Are you sure you want to export this user's content to #{@user.email}?" }, class: "c-btn c-btn--secondary", params: { send_to_admin: false } %>
|
||||
<%= button_to t("views.admin.users.export.to_admin"), export_data_admin_user_path(@user.id), data: { confirm: t("views.admin.users.export.confirm", email: ForemInstance.email) }, class: "c-btn c-btn--secondary", params: { send_to_admin: true } %>
|
||||
<%= button_to t("views.admin.users.export.to_user"), export_data_admin_user_path(@user.id), data: { confirm: t("views.admin.users.export.confirm", email: @user.email) }, class: "c-btn c-btn--secondary", params: { send_to_admin: false } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<div id="merge-accounts">
|
||||
<%= form_for(@user, url: merge_admin_user_path(@user),
|
||||
html: { class: "flex flex-col gap-4", method: :post, onsubmit: "return confirm('Are you sure? This is extremely destructive and irreversible. Merging will delete all the other users content and combine it with this user')", id: nil }) do |f| %>
|
||||
<p>This action is irreversible.</p>
|
||||
<p>Make sure you are currently on the page of the user you want to <strong>keep</strong>. Once merged, the account entered below will be merged and deleted.</p>
|
||||
html: { class: "flex flex-col gap-4", method: :post, onsubmit: "return confirm('#{j t('views.admin.users.merge.onsubmit')}')", id: nil }) do |f| %>
|
||||
<p><%= t("views.admin.users.danger.desc1") %></p>
|
||||
<p><%= t("views.admin.users.merge.desc2_html") %></p>
|
||||
<div class="crayons-field mb-4">
|
||||
<%= f.label :merge_user_id, "User ID", class: "crayons-field__label" %>
|
||||
<%= f.label :merge_user_id, t("views.admin.users.merge.id"), class: "crayons-field__label" %>
|
||||
<%= f.text_field :merge_user_id, placeholder: "1234", class: "crayons-textfield", type: "number", inputmode: "numeric", aria: { describedby: "merge-user-description" } %>
|
||||
</div>
|
||||
<div>
|
||||
<%= f.button "Merge and delete", class: "c-btn c-btn--destructive c-btn--primary", type: "submit" %>
|
||||
<%= f.button t("views.admin.users.merge.submit"), class: "c-btn c-btn--destructive c-btn--primary", type: "submit" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,37 +1,39 @@
|
|||
<div id="remove-social-accounts">
|
||||
<div class="flex flex-col gap-4">
|
||||
<p>Sometimes users encounter sign-in issues when they....</p>
|
||||
<ol>
|
||||
<li>create an account on <%= community_name %> with a social account, and</li>
|
||||
<li>remove the original social account, and</li>
|
||||
<li>attempt to sign in again using the same, removed social account.</li>
|
||||
</ol>
|
||||
<p>If this is the case, removing the social accounts below can help restore their social accounts. To verify if this is the case, follow steps 1 and 2 below. If verified, follow through all steps to restore their social accounts.</p>
|
||||
<%= t("views.admin.users.social.desc_html", community: community_name) %>
|
||||
|
||||
<h3 class="crayons-subtitle-2">
|
||||
How to restore a social account
|
||||
<%= t("views.admin.users.social.howto.subtitle") %>
|
||||
</h3>
|
||||
<ol>
|
||||
<li>Check their social account's UID via these third party tools: <a href="https://tweeterid.com/?username=<%= @user.twitter_username %>" target="_blank" rel="noopener nofollow">Twitter UID</a> and <a href="https://caius.github.io/github_id/#<%= @user.github_username %>" target="_blank" rel="noopener nofollow">GitHub UID</a></li>
|
||||
<li>Check whether or not it matches the corresponding UID below.</li>
|
||||
<li>Remove the respective account if it doesn't match.</li>
|
||||
<li>Ask the user to reauthorize their social account via <%= app_url(user_settings_path(:account)) %></li>
|
||||
<li><%= t("views.admin.users.social.howto.first_html",
|
||||
twitter_uid: link_to(t("views.admin.users.social.howto.twitter_uid"), "https://tweeterid.com/?username=#{@user.twitter_username}", target: "_blank", rel: "noopener nofollow"),
|
||||
github_uid: link_to(t("views.admin.users.social.howto.github_uid"), "https://caius.github.io/github_id/##{@user.twitter_username}", target: "_blank", rel: "noopener nofollow")) %></li>
|
||||
<li><%= t("views.admin.users.social.howto.second") %></li>
|
||||
<li><%= t("views.admin.users.social.howto.third") %></li>
|
||||
<li><%= t("views.admin.users.social.howto.fourth", app: app_url(user_settings_path(:account))) %></li>
|
||||
</ol>
|
||||
|
||||
<% @user.identities.each do |identity| %>
|
||||
<%= form_for(@user, url: remove_identity_admin_user_path(@user),
|
||||
html: { class: "fs-base p-4 py-3 c-card c-card--interactive flex gap-2 justify-between items-center", method: :delete, onsubmit: "return confirm('Are you sure? This should only be done as a solution for the listed example(s).)", id: nil }) do |f| %>
|
||||
html: { class: "fs-base p-4 py-3 c-card c-card--interactive flex gap-2 justify-between items-center", method: :delete, onsubmit: "return confirm('#{j t('views.admin.users.social.onsubmit')}')", id: nil }) do |f| %>
|
||||
<%= f.hidden_field :identity_id, value: identity.id %>
|
||||
<div class="flex-1 flex items-center gap-2">
|
||||
<%= crayons_icon_tag(identity.provider, class: "shrink-0", width: 32, height: 32) %>
|
||||
<div class="lh-tight">
|
||||
<h4 class="crayons-subtitle-3"><%= identity.provider.capitalize %></h4>
|
||||
<p class="fs-base color-secondary"><strong>UID:</strong> <%= identity.uid %> • <strong>Username:</strong> <%= identity.auth_data_dump.present? ? identity.auth_data_dump["info"]["nickname"] : "No data available..." %></p>
|
||||
<h4 class="crayons-subtitle-3"><%= t("views.admin.users.identities.#{identity.provider}", default: identity.provider.capitalize) %></h4>
|
||||
<p class="fs-base color-secondary">
|
||||
<strong>
|
||||
<%= t("views.admin.users.social.uid") %>
|
||||
</strong> <%= identity.uid %> • <strong>
|
||||
<%= t("views.admin.users.social.username") %>
|
||||
</strong> <%= identity.auth_data_dump.present? ? identity.auth_data_dump["info"]["nickname"] : t("views.admin.users.social.no_data") %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<%= f.button class: "c-btn c-btn--icon-left c-btn--destructive", type: "submit" do %>
|
||||
<%= crayons_icon_tag(:bin, class: "c-btn__icon") %>
|
||||
Remove
|
||||
<%= t("views.admin.users.social.submit") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<h2 class="crayons-subtitle-1">Reports submitted by <%= @user.name %> (<%= @related_reports.count %>)</h2>
|
||||
<h2 class="crayons-subtitle-1"><%= t("views.admin.users.reports.subtitle", user: @user.name, num: @related_reports.count) %></h2>
|
||||
|
||||
<% unless @related_reports.empty? %>
|
||||
<div class="pt-3">
|
||||
|
|
@ -9,26 +9,26 @@
|
|||
<h3 class="crayons-subtitle-3 w-100 flex items-center justify-between">
|
||||
<span class="flex gap-3">
|
||||
<a href="<%= admin_report_path(report.id) %>" class="c-link">
|
||||
<%= report.category.capitalize %>
|
||||
<%= t("views.admin.users.reports.category.#{report.category}", default: report.category.capitalize) %>
|
||||
</a>
|
||||
<span class="c-indicator c-indicator--relaxed <%= "c-indicator--danger" if report.status.casecmp("open").zero? %> <%= "c-indicator--success" if report.status.casecmp("resolved").zero? %>">
|
||||
<%= report.status %>
|
||||
<%= t("views.admin.users.reports.status.#{report.status}", default: report.status) %>
|
||||
</span>
|
||||
</span>
|
||||
<time datetime="<%= report.created_at&.strftime("%Y-%m-%dT%H:%M:%S%z") %>" class="color-secondary fs-s shrink-0 fw-normal" title="<%= report.created_at&.strftime("%Y-%m-%d, %H:%M") %>">
|
||||
<%= report.created_at&.strftime("%b %e '%y") %>
|
||||
<time datetime="<%= report.created_at&.strftime("%Y-%m-%dT%H:%M:%S%z") %>" class="color-secondary fs-s shrink-0 fw-normal" title="<%= l(report.created_at, format: :admin_user) if report.created_at %>">
|
||||
<%= l(report.created_at, format: :short_with_yy) if report.created_at %>
|
||||
</time>
|
||||
</h3>
|
||||
</header>
|
||||
<p class="mb-1"><%= report.message %></p>
|
||||
<p class="fs-s color-secondary">For <a href="<%= report.reported_url %>" class="c-link" target="_blank" rel="noopener"><%= report.reported_url %></a></p>
|
||||
<p class="fs-s color-secondary"><%= t("views.admin.users.reports.for_html", url: link_to(report.reported_url, report.reported_url, class: "c-link", target: "_blank", rel: "noopener")) %></p>
|
||||
</div>
|
||||
</article>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="align-center flex flex-col justify-center my-auto py-8">
|
||||
<h3 class="fs-xl fw-normal mb-2">No comment or post has been reported yet.</h3>
|
||||
<p class="color-secondary">Any comment or post reported by <%= @user.name %> will be found here.</p>
|
||||
<h3 class="fs-xl fw-normal mb-2"><%= t("views.admin.users.reports.empty1") %></h3>
|
||||
<p class="color-secondary"><%= t("views.admin.users.reports.empty2", user: @user.name) %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,27 +1,27 @@
|
|||
<% if @unpublish_all_data.exists? %>
|
||||
<h2 class="fs-xl fw-normal mb-5">Unpublished by <%= link_to @unpublish_all_data.audit_log.user.username, @unpublish_all_data.audit_log.user.path %> on <%= @unpublish_all_data.audit_log.created_at.strftime("%Y-%m-%d, %H:%M") %></h3>
|
||||
<h2 class="fs-xl fw-normal mb-5"><%= t("views.admin.users.unpublish_logs.subtitle_html", user: link_to(@unpublish_all_data.audit_log.user.username, @unpublish_all_data.audit_log.user.path), time: l(@unpublish_all_data.audit_log.created_at, format: :admin_user)) %></h3>
|
||||
<div class="crayons-card p-6 mb-5">
|
||||
<h4 class="mb-2">Posts:</h4>
|
||||
<h4 class="mb-2"><%= t("views.admin.users.unpublish_logs.posts") %></h4>
|
||||
<% @unpublish_all_data.target_articles.each do |article| %>
|
||||
<div class="mb-1">
|
||||
<%= link_to article.title, article.current_state_path %>
|
||||
<a href="<%= article.path %>/edit" target="_blank" rel="noopener" class="c-link">Edit</a>
|
||||
<a href="<%= article.path %>/edit" target="_blank" rel="noopener" class="c-link"><%= t("views.admin.users.unpublish_logs.edit") %></a>
|
||||
<% if article.published %>
|
||||
<span class="color-base-60">(was republished)</span>
|
||||
<span class="color-base-60"><%= t("views.admin.users.unpublish_logs.republished") %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="crayons-card p-6">
|
||||
<h4 class="mb-2">Comments:</h4>
|
||||
<h4 class="mb-2"><%= t("views.admin.users.unpublish_logs.comments") %></h4>
|
||||
<% @unpublish_all_data.target_comments.each do |comment| %>
|
||||
<div class="crayons-card p-3 mb-3">
|
||||
<div class="color-base-80">
|
||||
<%= truncate(strip_tags(comment.processed_html), length: 250).html_safe %>
|
||||
</div>
|
||||
<%= link_to "commentable", comment.commentable.current_state_path %>
|
||||
<%= link_to t("views.admin.users.unpublish_logs.commentable"), comment.commentable.current_state_path %>
|
||||
<p class="fs-s">
|
||||
Created at: <%= comment.created_at.strftime("%Y-%m-%d, %H:%M") %>
|
||||
<%= t("views.admin.users.unpublish_logs.created", time: l(comment.created_at, format: :admin_user)) %>
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -173,10 +173,14 @@ en:
|
|||
other: is the wrong length (should be %{count} characters)
|
||||
time:
|
||||
formats:
|
||||
admin_user: "%Y-%m-%d, %H:%M"
|
||||
comment: "%B %d, %Y"
|
||||
email_verified: "%b %e '%y, %H:%M"
|
||||
github: "%b %d, %Y"
|
||||
json: "%b %e, %Y"
|
||||
medium: "%b %-d, %Y"
|
||||
members: "%d %b"
|
||||
members_with_year: "%d %b, %Y"
|
||||
reddit: "%b %e '%y"
|
||||
short: "%b %-e"
|
||||
short_with_yy: "%b %-d '%y"
|
||||
|
|
|
|||
|
|
@ -196,10 +196,14 @@ fr:
|
|||
other: est la mauvaise longueur (devrait être %{count} caractères)
|
||||
time:
|
||||
formats:
|
||||
admin_user: "%Y-%m-%d, %H:%M"
|
||||
comment: "%B %d, %Y"
|
||||
email_verified: "%b %e '%y, %H:%M"
|
||||
github: "%b %d, %Y"
|
||||
json: "%b %e, %Y"
|
||||
medium: "%b %-d, %Y"
|
||||
members: "%d %b"
|
||||
members_with_year: "%d %b, %Y"
|
||||
reddit: "%b %e '%y"
|
||||
short: "%-e %b"
|
||||
short_with_yy: "%-e %b '%y"
|
||||
|
|
|
|||
|
|
@ -230,3 +230,11 @@ en:
|
|||
novice: Novice
|
||||
social_link_helper:
|
||||
n_a: N/A
|
||||
admin:
|
||||
user_helper:
|
||||
today: Today, %{date}
|
||||
yesterday: Yesterday, %{date}
|
||||
org_join: ", "
|
||||
org_overflow:
|
||||
one: "%{orgs} & %{count} other"
|
||||
other: "%{orgs} & %{count} others"
|
||||
|
|
|
|||
|
|
@ -230,3 +230,11 @@ fr:
|
|||
novice: Novice
|
||||
social_link_helper:
|
||||
n_a: N/A
|
||||
admin:
|
||||
user_helper:
|
||||
today: Today, %{date}
|
||||
yesterday: Yesterday, %{date}
|
||||
org_join: ", "
|
||||
org_overflow:
|
||||
one: "%{orgs} & %{count} other"
|
||||
other: "%{orgs} & %{count} others"
|
||||
|
|
|
|||
351
config/locales/views/admin/users/en.yml
Normal file
351
config/locales/views/admin/users/en.yml
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
---
|
||||
en:
|
||||
views:
|
||||
admin:
|
||||
users:
|
||||
heading: Members
|
||||
aria_paginate: Paginate users
|
||||
table:
|
||||
compact_subtitle: Members
|
||||
joined_on: Joined on
|
||||
last_activity: Last activity
|
||||
heading:
|
||||
member: Member
|
||||
status: Status
|
||||
last_joined: Last activity & Joined on
|
||||
orgs: Organizations
|
||||
actions: Actions
|
||||
empty:
|
||||
text1: No members found under these filters.
|
||||
text2: Try broadening or removing the filters.
|
||||
download:
|
||||
aria_label: Download member data
|
||||
heading: Download member data
|
||||
desc1: Your data will be downloaded as a Comma Separated Values (.csv) file.
|
||||
desc2: Values listed are Name, Username, Email address, Status, Joining date, Last activity, and Organizations.
|
||||
submit: Download
|
||||
cancel: Cancel
|
||||
name: Name
|
||||
username: Username
|
||||
email: Email address
|
||||
status: Status
|
||||
join: Joining date
|
||||
last_activity: Last activity
|
||||
orgs: Organizations
|
||||
search:
|
||||
aria_expand: Expand search
|
||||
aria_field: Search member by name, username or email
|
||||
aria_label: Search
|
||||
icon: search
|
||||
placeholder: Search member...
|
||||
filters:
|
||||
aria_clear: Clear all filters
|
||||
aria_label: Filter
|
||||
aria_remove: "Remove filter: %{value}"
|
||||
aria_more_roles: See more roles
|
||||
heading: Filters
|
||||
applied: Applied filters
|
||||
join: Joining date
|
||||
creation: Community creation
|
||||
today: Today
|
||||
clear: Clear all
|
||||
clear_filter:
|
||||
aria_roles: Clear member roles filter
|
||||
aria_status: Clear statuses filter
|
||||
aria_orgs: Clear organizations filter
|
||||
text: Clear filter
|
||||
clear_filters: Clear filters
|
||||
desc: Members who match any of the selected filters will be displayed
|
||||
summary:
|
||||
roles: Member roles
|
||||
status: Status
|
||||
join: Joining date
|
||||
orgs: Organizations
|
||||
legend:
|
||||
roles: Member roles
|
||||
status: Status
|
||||
orgs: Organizations
|
||||
more_roles: See more roles
|
||||
submit: Apply filters
|
||||
cancel: Cancel
|
||||
invite:
|
||||
aria_email: "Invitation actions: %{email}"
|
||||
resend: Resend invite
|
||||
cancel: Cancel invite
|
||||
actions:
|
||||
assign_role:
|
||||
text: Assign role
|
||||
heading: Add role
|
||||
role: Role
|
||||
select: Select role
|
||||
note: "Add a note to this action:"
|
||||
submit: Add
|
||||
add_org:
|
||||
text: Add organization
|
||||
heading: Add organization
|
||||
add: Add %{user} to an organization
|
||||
edit: Edit %{user}'s role at an organization
|
||||
id: Organization ID
|
||||
role: Role
|
||||
role_desc_html: You can assign %{user} to be an Admin or a regular member.
|
||||
admin: admin
|
||||
member: member
|
||||
submit: Add organization
|
||||
adjust_credit:
|
||||
text: Adjust credit balance
|
||||
heading: Adjust balance
|
||||
desc_html: "%{user} currently has %{credits}."
|
||||
credits_html: "%{amount} credits"
|
||||
adjust: Adjust balance
|
||||
selector_html: "%{action}%{amount}%{credits}"
|
||||
add: Add
|
||||
unit: credits
|
||||
aria_credits: Amount of credits to add or remove
|
||||
note: "Add a note to this action:"
|
||||
submit: Adjust balance
|
||||
copy_email: Copy email address
|
||||
danger:
|
||||
desc1: This action is irreversible.
|
||||
desc3: Be careful with this action.
|
||||
banish:
|
||||
heading: Banish %{user}
|
||||
desc2_html: Once banished, we will delete all content created by %{user} and change their username to @spam_###.
|
||||
notice_html: This is not a new user. Only Super Admins or Support Admins are allowed to banish %{user}.
|
||||
submit_html: Banish %{user}
|
||||
delete:
|
||||
heading: Delete %{user}'s account
|
||||
onsubmit: Are you sure? This actions is irreversible.
|
||||
desc2: Once deleted, all data relating to %{user} will be removed from our database.
|
||||
notice: Only Super Admins are allowed to delete users.
|
||||
submit: Delete now
|
||||
export:
|
||||
heading: Export %{user}'s data
|
||||
desc1_html: Choose between sending the exported data to either your Admin contact email, %{contact}, or to %{user}'s %{user_email} directly.
|
||||
desc2: Exported data includes a user's posts and comments.
|
||||
user_email: user email
|
||||
to_admin: Export to Admin
|
||||
to_user: Export to User
|
||||
confirm: Are you sure you want to export this user's content to %{email}?
|
||||
merge:
|
||||
heading: Merge users
|
||||
onsubmit: Are you sure? This is extremely destructive and irreversible. Merging will delete all the other users content and combine it with this user
|
||||
desc2_html: Make sure you are currently on the page of the user you want to <strong>keep</strong>. Once merged, the account entered below will be merged and deleted.
|
||||
id: User ID
|
||||
submit: Merge and delete
|
||||
social:
|
||||
heading: Remove social accounts
|
||||
desc_html: |
|
||||
<p>Sometimes users encounter sign-in issues when they....</p>
|
||||
<ol>
|
||||
<li>create an account on %{community} with a social account, and</li>
|
||||
<li>remove the original social account, and</li>
|
||||
<li>attempt to sign in again using the same, removed social account.</li>
|
||||
</ol>
|
||||
<p>If this is the case, removing the social accounts below can help restore their social accounts. To verify if this is the case, follow steps 1 and 2 below. If verified, follow through all steps to restore their social accounts.</p>
|
||||
howto:
|
||||
subtitle: How to restore a social account
|
||||
first_html: "Check their social account's UID via these third party tools: %{twitter_uid} and %{github_uid}"
|
||||
twitter_uid: Twitter UID
|
||||
github_uid: GitHub UID
|
||||
second: Check whether or not it matches the corresponding UID below.
|
||||
third: Remove the respective account if it doesn't match.
|
||||
fourth: Ask the user to reauthorize their social account via %{app}
|
||||
onsubmit: Are you sure? This should only be done as a solution for the listed example(s).
|
||||
uid: "UID:"
|
||||
username: "Username:"
|
||||
no_data: No data available...
|
||||
submit: Remove
|
||||
unpublish:
|
||||
heading: Unpublish all posts
|
||||
onsubmit: Are you sure? All posts will be unavailable to the community.
|
||||
text1_html: Once unpublished, all posts by %{username} will become hidden and only accessible to themselves.
|
||||
text2_html: If %{username} is not suspended, they can still re-publish their posts from their dashboard.
|
||||
note: "Note:"
|
||||
note_placeholder: "Note text"
|
||||
submit: Unpublish all posts
|
||||
emails:
|
||||
empty1: No previous emails found for %{user}.
|
||||
empty2: Any emails sent to %{email} will be found here.
|
||||
previous: Previous emails (%{num})
|
||||
send: Send an email
|
||||
to: "To: %{user} (%{email})"
|
||||
subject: Subject
|
||||
subject_placeholder: What do you want to say in the subject line?
|
||||
body: Body
|
||||
body_placeholder: What do you want to say?
|
||||
send_submit: Send email
|
||||
not_verified:
|
||||
subtitle: Email not verified
|
||||
desc: "%{user}'s email hasn't been verified yet."
|
||||
verify: Verify email address
|
||||
verified_html: Last verified on %{time}
|
||||
reverify: Reverify
|
||||
flags:
|
||||
empty1: No flags received against %{user} yet.
|
||||
empty2: Any flags received against %{user} will be found here.
|
||||
type:
|
||||
article: Post "%{title}"
|
||||
comment: Comment on "%{title}"
|
||||
profile: User's profile
|
||||
origin_html: Flagged by %{user}
|
||||
notes:
|
||||
empty1: No previous notes found for %{user}.
|
||||
empty2: Any notes added for %{user} will be found here.
|
||||
previous: Previous notes (%{num})
|
||||
note_by: Note by %{author} on %{time}
|
||||
reason_by_html: "%{reason} %{by}"
|
||||
by_html: by %{author}
|
||||
write: Write a user note
|
||||
note: Note
|
||||
note_placeholder: Add a note...
|
||||
submit: Submit
|
||||
overview:
|
||||
comments: Comments
|
||||
posts: Posts
|
||||
reactions: Reactions
|
||||
followers: Followers
|
||||
following: Following
|
||||
badges: Badges
|
||||
learn: Learn more
|
||||
credits:
|
||||
subtitle: Credits
|
||||
aria_learn: Learn more about credits
|
||||
icon: Wallet
|
||||
desc: "Grant/remove credits to purchase classified listings. "
|
||||
button: Adjust balance
|
||||
orgs:
|
||||
subtitle: Organizations
|
||||
aria_edit: Edit %{org} organization membership
|
||||
aria_learn: Learn more about organizations
|
||||
aria_revoke: Revoke %{org} organization membership
|
||||
icon: Organizations
|
||||
desc: "Add this member to organizations in your community. "
|
||||
empty: Not part of any organization yet.
|
||||
button: Add organization
|
||||
type:
|
||||
admin: Admin
|
||||
member: Member
|
||||
guest: Guest
|
||||
revoke_confirm: Are your sure you want to remove %{user} from %{org}?
|
||||
submit: Submit
|
||||
roles:
|
||||
subtitle: Roles
|
||||
aria_learn: Learn more about roles
|
||||
icon: Roles
|
||||
desc: "Grant this member permissions by assigning a role. "
|
||||
empty: No roles assigned yet.
|
||||
button: Assign role
|
||||
locked: You can't remove this role.
|
||||
remove: "Remove role:"
|
||||
remove_confirm: Are you sure?
|
||||
name:
|
||||
admin: Admin
|
||||
codeland_admin: Codeland Admin
|
||||
comment_suspended: Comment Suspended
|
||||
creator: Creator
|
||||
mod_relations_admin: Mod Relations Admin
|
||||
super_moderator: Super Moderator
|
||||
podcast_admin: Podcast Admin
|
||||
restricted_liquid_tag: Restricted Liquid Tag
|
||||
single_resource_admin: Single Resource Admin
|
||||
super_admin: Super Admin
|
||||
support_admin: Support Admin
|
||||
suspended: Suspended
|
||||
tag_moderator: Tag Moderator
|
||||
tech_admin: Tech Admin
|
||||
trusted: Trusted
|
||||
warned: Warned
|
||||
workshop_pass: Workshop Pass
|
||||
tag_mod:
|
||||
subtitle: Tags
|
||||
aria_learn: Learn more about tag moderation
|
||||
icon: Mod
|
||||
desc: "Add a tag that this member can moderate. "
|
||||
remove: "Remove tag:"
|
||||
notice_html: Adding tags for moderation is currently only possible through a particular %{tag_page}, by providing the user's ID (%{user_id}).
|
||||
tag_page: tag's page
|
||||
profile:
|
||||
locked:
|
||||
icon: Access locked
|
||||
text: This user has locked access.
|
||||
unlock: Unlock access
|
||||
id: ID %{userid}
|
||||
since_html: Member since %{time}
|
||||
not_member: User has not accepted their invitation yet.
|
||||
email: Email
|
||||
github: GitHub
|
||||
twitter: Twitter
|
||||
visit: Visit profile
|
||||
options:
|
||||
icon: Options
|
||||
export: Export data
|
||||
merge: Merge users
|
||||
unpublish: Unpublished all posts
|
||||
remove_social: Remove social accounts
|
||||
banish: Banish user
|
||||
delete: Delete user
|
||||
reports:
|
||||
subtitle: Reports submitted by %{user} (%{num})
|
||||
for_html: For %{url}
|
||||
empty1: No comment or post has been reported yet.
|
||||
empty2: Any comment or post reported by %{user} will be found here.
|
||||
category:
|
||||
rude or vulgar: Rude or vulgar
|
||||
harrassment: Harrassment
|
||||
spam: Spam
|
||||
listings: Listings
|
||||
other: Other
|
||||
status:
|
||||
Open: Open
|
||||
Resolved: Resolved
|
||||
Invalid: Invalid
|
||||
unpublish_logs:
|
||||
subtitle_html: Unpublished by %{user} on %{time}
|
||||
posts: "Posts:"
|
||||
edit: Edit
|
||||
republished: (was republished)
|
||||
comments: "Comments:"
|
||||
commentable: commentable
|
||||
created: "Created at: %{time}"
|
||||
tabs:
|
||||
overview: Overview
|
||||
notes: Notes
|
||||
emails: Emails
|
||||
reports: Reports
|
||||
flags: Flags
|
||||
unpublish_logs: Unpublish All History
|
||||
status_title: Current status
|
||||
status_reader: "Current status:"
|
||||
more_orgs:
|
||||
one: + %{count}
|
||||
other: + %{count}
|
||||
roles:
|
||||
Admin: Admin
|
||||
Tech Admin: Tech Admin
|
||||
Super Admin: Super Admin
|
||||
Resource Admin: Resource Admin
|
||||
"Resource Admin: Article": "Resource Admin: Article"
|
||||
"Resource Admin: Badge": "Resource Admin: Badge"
|
||||
"Resource Admin: BadgeAchievement": "Resource Admin: BadgeAchievement"
|
||||
"Resource Admin: Broadcast": "Resource Admin: Broadcast"
|
||||
"Resource Admin: Comment": "Resource Admin: Comment"
|
||||
"Resource Admin: Config": "Resource Admin: Config"
|
||||
"Resource Admin: DisplayAd": "Resource Admin: DisplayAd"
|
||||
"Resource Admin: DataUpdateScript": "Resource Admin: DataUpdateScript"
|
||||
"Resource Admin: FeedbackMessage": "Resource Admin: FeedbackMessage"
|
||||
"Resource Admin: HtmlVariant": "Resource Admin: HtmlVariant"
|
||||
"Resource Admin: ListingCategory": "Resource Admin: ListingCategory"
|
||||
"Resource Admin: Page": "Resource Admin: Page"
|
||||
"Resource Admin: Tag": "Resource Admin: Tag"
|
||||
Super Moderator: Super Moderator
|
||||
statuses:
|
||||
Warned: Warned
|
||||
Comment Suspended: Comment Suspended
|
||||
Suspended: Suspended
|
||||
Good Standing: Good Standing
|
||||
Good standing: Good standing
|
||||
Trusted: Trusted
|
||||
identities:
|
||||
facebook: Facebook
|
||||
github: GitHub
|
||||
twitter: Twitter
|
||||
351
config/locales/views/admin/users/fr.yml
Normal file
351
config/locales/views/admin/users/fr.yml
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
---
|
||||
en:
|
||||
views:
|
||||
admin:
|
||||
users:
|
||||
heading: Members
|
||||
aria_paginate: Paginate users
|
||||
table:
|
||||
compact_subtitle: Members
|
||||
joined_on: Joined on
|
||||
last_activity: Last activity
|
||||
heading:
|
||||
member: Member
|
||||
status: Status
|
||||
last_joined: Last activity & Joined on
|
||||
orgs: Organizations
|
||||
actions: Actions
|
||||
empty:
|
||||
text1: No members found under these filters.
|
||||
text2: Try broadening or removing the filters.
|
||||
download:
|
||||
aria_label: Download member data
|
||||
heading: Download member data
|
||||
desc1: Your data will be downloaded as a Comma Separated Values (.csv) file.
|
||||
desc2: Values listed are Name, Username, Email address, Status, Joining date, Last activity, and Organizations.
|
||||
submit: Download
|
||||
cancel: Cancel
|
||||
name: Name
|
||||
username: Username
|
||||
email: Email address
|
||||
status: Status
|
||||
join: Joining date
|
||||
last_activity: Last activity
|
||||
orgs: Organizations
|
||||
search:
|
||||
aria_expand: Expand search
|
||||
aria_field: Search member by name, username or email
|
||||
aria_label: Search
|
||||
icon: search
|
||||
placeholder: Search member...
|
||||
filters:
|
||||
aria_clear: Clear all filters
|
||||
aria_label: Filter
|
||||
aria_remove: "Remove filter: %{value}"
|
||||
aria_more_roles: See more roles
|
||||
heading: Filters
|
||||
applied: Applied filters
|
||||
join: Joining date
|
||||
creation: Community creation
|
||||
today: Today
|
||||
clear: Clear all
|
||||
clear_filter:
|
||||
aria_roles: Clear member roles filter
|
||||
aria_status: Clear statuses filter
|
||||
aria_orgs: Clear organizations filter
|
||||
text: Clear filter
|
||||
clear_filters: Clear filters
|
||||
desc: Members who match any of the selected filters will be displayed
|
||||
summary:
|
||||
roles: Member roles
|
||||
status: Status
|
||||
join: Joining date
|
||||
orgs: Organizations
|
||||
legend:
|
||||
roles: Member roles
|
||||
status: Status
|
||||
orgs: Organizations
|
||||
more_roles: See more roles
|
||||
submit: Apply filters
|
||||
cancel: Cancel
|
||||
invite:
|
||||
aria_email: "Invitation actions: %{email}"
|
||||
resend: Resend invite
|
||||
cancel: Cancel invite
|
||||
actions:
|
||||
assign_role:
|
||||
text: Assign role
|
||||
heading: Add role
|
||||
role: Role
|
||||
select: Select role
|
||||
note: "Add a note to this action:"
|
||||
submit: Add
|
||||
add_org:
|
||||
text: Add organization
|
||||
heading: Add organization
|
||||
add: Add %{user} to an organization
|
||||
edit: Edit %{user}'s role at an organization
|
||||
id: Organization ID
|
||||
role: Role
|
||||
role_desc_html: You can assign %{user} to be an Admin or a regular member.
|
||||
admin: admin
|
||||
member: member
|
||||
submit: Add organization
|
||||
adjust_credit:
|
||||
text: Adjust credit balance
|
||||
heading: Adjust balance
|
||||
desc_html: "%{user} currently has %{credits}."
|
||||
credits_html: "%{amount} credits"
|
||||
adjust: Adjust balance
|
||||
selector_html: "%{action}%{amount}%{credits}"
|
||||
add: Add
|
||||
unit: credits
|
||||
aria_credits: Amount of credits to add or remove
|
||||
note: "Add a note to this action:"
|
||||
submit: Adjust balance
|
||||
copy_email: Copy email address
|
||||
danger:
|
||||
desc1: This action is irreversible.
|
||||
desc3: Be careful with this action.
|
||||
banish:
|
||||
heading: Banish %{user}
|
||||
desc2_html: Once banished, we will delete all content created by %{user} and change their username to @spam_###.
|
||||
notice_html: This is not a new user. Only Super Admins or Support Admins are allowed to banish %{user}.
|
||||
submit_html: Banish %{user}
|
||||
delete:
|
||||
heading: Delete %{user}'s account
|
||||
onsubmit: Are you sure? This actions is irreversible.
|
||||
desc2: Once deleted, all data relating to %{user} will be removed from our database.
|
||||
notice: Only Super Admins are allowed to delete users.
|
||||
submit: Delete now
|
||||
export:
|
||||
heading: Export %{user}'s data
|
||||
desc1_html: Choose between sending the exported data to either your Admin contact email, %{contact}, or to %{user}'s %{user_email} directly.
|
||||
desc2: Exported data includes a user's posts and comments.
|
||||
user_email: user email
|
||||
to_admin: Export to Admin
|
||||
to_user: Export to User
|
||||
confirm: Are you sure you want to export this user's content to %{email}?
|
||||
merge:
|
||||
heading: Merge users
|
||||
onsubmit: Are you sure? This is extremely destructive and irreversible. Merging will delete all the other users content and combine it with this user
|
||||
desc2_html: Make sure you are currently on the page of the user you want to <strong>keep</strong>. Once merged, the account entered below will be merged and deleted.
|
||||
id: User ID
|
||||
submit: Merge and delete
|
||||
social:
|
||||
heading: Remove social accounts
|
||||
desc_html: |
|
||||
<p>Sometimes users encounter sign-in issues when they....</p>
|
||||
<ol>
|
||||
<li>create an account on %{community} with a social account, and</li>
|
||||
<li>remove the original social account, and</li>
|
||||
<li>attempt to sign in again using the same, removed social account.</li>
|
||||
</ol>
|
||||
<p>If this is the case, removing the social accounts below can help restore their social accounts. To verify if this is the case, follow steps 1 and 2 below. If verified, follow through all steps to restore their social accounts.</p>
|
||||
howto:
|
||||
subtitle: How to restore a social account
|
||||
first_html: "Check their social account's UID via these third party tools: %{twitter_uid} and %{github_uid}"
|
||||
twitter_uid: Twitter UID
|
||||
github_uid: GitHub UID
|
||||
second: Check whether or not it matches the corresponding UID below.
|
||||
third: Remove the respective account if it doesn't match.
|
||||
fourth: Ask the user to reauthorize their social account via %{app}
|
||||
onsubmit: Are you sure? This should only be done as a solution for the listed example(s).
|
||||
uid: "UID:"
|
||||
username: "Username:"
|
||||
no_data: No data available...
|
||||
submit: Remove
|
||||
unpublish:
|
||||
heading: Unpublish all posts
|
||||
onsubmit: Are you sure? All posts will be unavailable to the community.
|
||||
text1_html: Once unpublished, all posts by %{username} will become hidden and only accessible to themselves.
|
||||
text2_html: If %{username} is not suspended, they can still re-publish their posts from their dashboard.
|
||||
note: "Note:"
|
||||
note_placeholder: "Note text"
|
||||
submit: Unpublish all posts
|
||||
emails:
|
||||
empty1: No previous emails found for %{user}.
|
||||
empty2: Any emails sent to %{email} will be found here.
|
||||
previous: Previous emails (%{num})
|
||||
send: Send an email
|
||||
to: "To: %{user} (%{email})"
|
||||
subject: Subject
|
||||
subject_placeholder: What do you want to say in the subject line?
|
||||
body: Body
|
||||
body_placeholder: What do you want to say?
|
||||
send_submit: Send email
|
||||
not_verified:
|
||||
subtitle: Email not verified
|
||||
desc: "%{user}'s email hasn't been verified yet."
|
||||
verify: Verify email address
|
||||
verified_html: Last verified on %{time}
|
||||
reverify: Reverify
|
||||
flags:
|
||||
empty1: No flags received against %{user} yet.
|
||||
empty2: Any flags received against %{user} will be found here.
|
||||
type:
|
||||
article: Post "%{title}"
|
||||
comment: Comment on "%{title}"
|
||||
profile: User's profile
|
||||
origin_html: Flagged by %{user}
|
||||
notes:
|
||||
empty1: No previous notes found for %{user}.
|
||||
empty2: Any notes added for %{user} will be found here.
|
||||
previous: Previous notes (%{num})
|
||||
note_by: Note by %{author} on %{time}
|
||||
reason_by_html: "%{reason} %{by}"
|
||||
by_html: by %{author}
|
||||
write: Write a user note
|
||||
note: Note
|
||||
note_placeholder: Add a note...
|
||||
submit: Submit
|
||||
overview:
|
||||
comments: Comments
|
||||
posts: Posts
|
||||
reactions: Reactions
|
||||
followers: Followers
|
||||
following: Following
|
||||
badges: Badges
|
||||
learn: Learn more
|
||||
credits:
|
||||
subtitle: Credits
|
||||
aria_learn: Learn more about credits
|
||||
icon: Wallet
|
||||
desc: "Grant/remove credits to purchase classified listings. "
|
||||
button: Adjust balance
|
||||
orgs:
|
||||
subtitle: Organizations
|
||||
aria_edit: Edit %{org} organization membership
|
||||
aria_learn: Learn more about organizations
|
||||
aria_revoke: Revoke %{org} organization membership
|
||||
icon: Organizations
|
||||
desc: "Add this member to organizations in your community. "
|
||||
empty: Not part of any organization yet.
|
||||
button: Add organization
|
||||
type:
|
||||
admin: Admin
|
||||
member: Member
|
||||
guest: Guest
|
||||
revoke_confirm: Are your sure you want to remove %{user} from %{org}?
|
||||
submit: Submit
|
||||
roles:
|
||||
subtitle: Roles
|
||||
aria_learn: Learn more about roles
|
||||
icon: Roles
|
||||
desc: "Grant this member permissions by assigning a role. "
|
||||
empty: No roles assigned yet.
|
||||
button: Assign role
|
||||
locked: You can't remove this role.
|
||||
remove: "Remove role:"
|
||||
remove_confirm: Are you sure?
|
||||
name:
|
||||
admin: Admin
|
||||
codeland_admin: Codeland Admin
|
||||
comment_suspended: Comment Suspended
|
||||
creator: Creator
|
||||
mod_relations_admin: Mod Relations Admin
|
||||
super_moderator: Super Moderator
|
||||
podcast_admin: Podcast Admin
|
||||
restricted_liquid_tag: Restricted Liquid Tag
|
||||
single_resource_admin: Single Resource Admin
|
||||
super_admin: Super Admin
|
||||
support_admin: Support Admin
|
||||
suspended: Suspended
|
||||
tag_moderator: Tag Moderator
|
||||
tech_admin: Tech Admin
|
||||
trusted: Trusted
|
||||
warned: Warned
|
||||
workshop_pass: Workshop Pass
|
||||
tag_mod:
|
||||
subtitle: Tags
|
||||
aria_learn: Learn more about tag moderation
|
||||
icon: Mod
|
||||
desc: "Add a tag that this member can moderate. "
|
||||
remove: "Remove tag:"
|
||||
notice_html: Adding tags for moderation is currently only possible through a particular %{tag_page}, by providing the user's ID (%{user_id}).
|
||||
tag_page: tag's page
|
||||
profile:
|
||||
locked:
|
||||
icon: Access locked
|
||||
text: This user has locked access.
|
||||
unlock: Unlock access
|
||||
id: ID %{userid}
|
||||
since_html: Member since %{time}
|
||||
not_member: User has not accepted their invitation yet.
|
||||
email: Email
|
||||
github: GitHub
|
||||
twitter: Twitter
|
||||
visit: Visit profile
|
||||
options:
|
||||
icon: Options
|
||||
export: Export data
|
||||
merge: Merge users
|
||||
unpublish: Unpublished all posts
|
||||
remove_social: Remove social accounts
|
||||
banish: Banish user
|
||||
delete: Delete user
|
||||
reports:
|
||||
subtitle: Reports submitted by %{user} (%{num})
|
||||
for_html: For %{url}
|
||||
empty1: No comment or post has been reported yet.
|
||||
empty2: Any comment or post reported by %{user} will be found here.
|
||||
category:
|
||||
rude or vulgar: Rude or vulgar
|
||||
harrassment: Harrassment
|
||||
spam: Spam
|
||||
listings: Listings
|
||||
other: Other
|
||||
status:
|
||||
Open: Open
|
||||
Resolved: Resolved
|
||||
Invalid: Invalid
|
||||
unpublish_logs:
|
||||
subtitle_html: Unpublished by %{user} on %{time}
|
||||
posts: "Posts:"
|
||||
edit: Edit
|
||||
republished: (was republished)
|
||||
comments: "Comments:"
|
||||
commentable: commentable
|
||||
created: "Created at: %{time}"
|
||||
tabs:
|
||||
overview: Overview
|
||||
notes: Notes
|
||||
emails: Emails
|
||||
reports: Reports
|
||||
flags: Flags
|
||||
unpublish_logs: Unpublish All History
|
||||
status_title: Current status
|
||||
status_reader: "Current status:"
|
||||
more_orgs:
|
||||
one: + %{count}
|
||||
other: + %{count}
|
||||
roles:
|
||||
Admin: Admin
|
||||
Tech Admin: Tech Admin
|
||||
Super Admin: Super Admin
|
||||
Resource Admin: Resource Admin
|
||||
"Resource Admin: Article": "Resource Admin: Article"
|
||||
"Resource Admin: Badge": "Resource Admin: Badge"
|
||||
"Resource Admin: BadgeAchievement": "Resource Admin: BadgeAchievement"
|
||||
"Resource Admin: Broadcast": "Resource Admin: Broadcast"
|
||||
"Resource Admin: Comment": "Resource Admin: Comment"
|
||||
"Resource Admin: Config": "Resource Admin: Config"
|
||||
"Resource Admin: DisplayAd": "Resource Admin: DisplayAd"
|
||||
"Resource Admin: DataUpdateScript": "Resource Admin: DataUpdateScript"
|
||||
"Resource Admin: FeedbackMessage": "Resource Admin: FeedbackMessage"
|
||||
"Resource Admin: HtmlVariant": "Resource Admin: HtmlVariant"
|
||||
"Resource Admin: ListingCategory": "Resource Admin: ListingCategory"
|
||||
"Resource Admin: Page": "Resource Admin: Page"
|
||||
"Resource Admin: Tag": "Resource Admin: Tag"
|
||||
Super Moderator: Super Moderator
|
||||
statuses:
|
||||
Warned: Warned
|
||||
Comment Suspended: Comment Suspended
|
||||
Suspended: Suspended
|
||||
Good Standing: Good Standing
|
||||
Good standing: Good standing
|
||||
Trusted: Trusted
|
||||
identities:
|
||||
facebook: Facebook
|
||||
github: GitHub
|
||||
twitter: Twitter
|
||||
|
|
@ -30,14 +30,14 @@ describe Admin::UsersHelper do
|
|||
|
||||
describe "#format_last_activity_timestamp" do
|
||||
it "renders the proper 'Last activity' date for a user that was active today" do
|
||||
timestamp = Time.zone.today
|
||||
timestamp = Time.zone.today.in_time_zone # Since actual user last_activity class is TimeWithZone
|
||||
date = timestamp.strftime("%d %b")
|
||||
formatted_date = helper.format_last_activity_timestamp(timestamp)
|
||||
expect(formatted_date).to eq "Today, #{date}"
|
||||
end
|
||||
|
||||
it "renders the proper 'Last activity' date for a user that was active yesterday" do
|
||||
timestamp = Date.yesterday
|
||||
timestamp = Date.yesterday.in_time_zone # Since actual user last_activity class is TimeWithZone
|
||||
date = timestamp.strftime("%d %b")
|
||||
formatted_date = helper.format_last_activity_timestamp(timestamp)
|
||||
expect(formatted_date).to eq "Yesterday, #{date}"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue