text:
<%= title @reason.reason_name %> (<%= @reason.weight %>)

  <%= @reason.description %>

  <% if user_signed_in? %>
     Edit description
  <% end %>

  <%= pie_chart reason_site_chart_path(@reason.id) %>

  <%= line_chart reason_accuracy_chart_path(@reason.id), colors: ["green", "red"], library: {"tooltip" => {'shared' => 'true'} } %>

  <li class="nav-tab nav-tab-all-results <%= 'active' if params[:filter].nil? or params[:filter] == 'all' %>">
    <%= link_to "All (#{@total})", reason_path(@reason, filter: nil) %>

  <li class="nav-tab nav-tab-tp <%= 'active' if params[:filter] == 'tp' %>">
    <%= link_to "True positives (#{@counts_by_feedback[:is_tp]})", reason_path(@reason, filter: 'tp') %>

  <li class="nav-tab nav-tab-fp <%= 'active' if params[:filter] == 'fp' %>">
    <%= link_to "False positives (#{@counts_by_feedback[:is_fp]})", reason_path(@reason, filter: 'fp') %>

  <li class="nav-tab nav-tab-naa <%= 'active' if params[:filter] == 'naa' %>">
    <%= link_to "NAA (#{@counts_by_feedback[:is_naa]})", reason_path(@reason, filter: 'naa') %>

    <%= render partial: 'posts/post', collection: @posts, cached: proc { |i| i.cachebreak } %>

  <%= will_paginate @posts, renderer: BootstrapPagination::Rails %>

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

Edit Description

        <%= form_tag update_reason_description_path, method: :post do %>
          <%= hidden_field_tag :id, @reason.id %>

            <%= label_tag :description do %>
               Description
            <% end %>

            <%= text_area_tag :description, @reason.description, class: 'form-control', rows: 3, cols: 100 %>

            <button type="submit" class="btn btn-success"> Update</button>

        <% end %>


text:
Site Settings

These control how the site works. Change rarely and with care.

      ID
      Name
      Value

    <% @settings.each do |s| %>

        <%= s.id %>
        <%= s.name %>

          <% case s.value_type %>
            <% when 'boolean' %>
              <input type="checkbox" id="setting-<%= s.id %>" class="setting-checkbox" data-name="<%= s.name %>"
                     <%= 'checked' if SiteSetting[s.name] %> />
            <% when 'number' %>
              <span class="editable-value" data-type='number' data-name="<%= s.name %>"><%= SiteSetting[s.name] %>
            <% when 'float' %>
              <span class="editable-value" data-type='number' data-step="0.01" data-name="<%= s.name %>"><%= SiteSetting[s.name] %>
            <% else %>
              <span class="editable-value" data-type='text' data-name="<%= s.name %>"><%= SiteSetting[s.name] %>
          <% end %>

        <%= link_to 'Delete', destroy_site_setting_path(s.id), method: :delete, data: { confirm: 'Are you sure?' }, class: 'text-danger' %>

    <% end %>

  <%= will_paginate @settings, renderer: BootstrapPagination::Rails %>

repo_name: Charcoal-SE/metasmoke

repo_language: Ruby

mime_type: text/plain


text: <%= line_chart query_times_graph_path(params.permit(:controller_name, :action_name)) %>


text:
<% title 'Graphs' %>

Reports last 3 months

<%= line_chart reports_graph_path, colors: ["#444", "#0a0", "#a00"], library: {"tooltip" => {'shared' => 'true'} } %>

Reports by site

        (<%= link_to "Last month", graphs_path, style: params[:timeframe].nil? ? "font-weight:bold" : "" %>
        |
        <%= link_to "All time", graphs_path(timeframe: "all"), style: params[:timeframe].present? ? "font-weight:bold" : ""%>)

<% h = HTMLEntities.new %>
<%= pie_chart url_for(controller: :graphs, action: :reports_by_site, timeframe: params[:timeframe]) %>

Reports by hour of day

        (<%= link_to "Last month", graphs_path, style: params[:timeframe].nil? ? "font-weight:bold" : "" %>
        |
        <%= link_to "All time", graphs_path(timeframe: "all"), style: params[:timeframe].present? ? "font-weight:bold" : ""%>)

<% t = Time.now %>
<%= line_chart url_for(controller: :graphs, action: :reports_by_hour_of_day, timeframe: params[:timeframe]), discrete: true,
               library: {"tooltip" => {'shared' => 'true'}, "xAxis": { "plotLines" => [{"width" => '2', value: "#{t.hour + t.min.to_f / 60.to_f}", color: 'blue', dashStyle: "dot" }]}},
               colors: ["#999", "green", "red"] %>

Time to deletion

tp posts only, same scale as above

<%= line_chart url_for(controller: :graphs, action: :time_to_deletion),
               library: { "xAxis": { "plotLines" => [{"width" => '2', value: "#{t.hour + t.min.to_f / 60.to_f}", color: 'blue', dashStyle: "dot" }]}} %>

Time to deletion

Last 3 months

<%= line_chart url_for(controller: :graphs, action: :monthly_ttd),
               library: { "xAxis": { "plotLines" => flag_settings_plot_lines(3.months.ago)} }%>


text:
Query Time Averages

      Path
      Average Runtime
      Hits
      DB Time
      View Time
      <% if current_user&.has_role?(:developer) %>

      <% end %>

    <% @query_times.each do |qt| %>
      <% if qt.counter(:total) > 0 %>

          <%= qt.path %>
          <td data-sort-value="<%= (qt.average(:total) * 100).to_i %>"><%= qt.average(:total).round(2) %>
          <td data-sort-value="<%= qt.counter(:total) %>"><%= qt.counter(:total) %>
          <td data-sort-value="<%= (qt.average(:db) * 100).to_i %>"><%= (qt.average(:db)).round(2) %>
          <td data-sort-value="<%= (qt.average(:view) * 100).to_i %>"><%= (qt.average(:view)).round(2) %>
          <% if current_user&.has_role?(:developer) %>
            <%= link_to 'Reset', reset_query_time_path(path: qt.raw_path), method: :post, class: 'text-danger' %>
          <% end %>

      <% end %>
    <% end %>


text:
Database Dumps

What follows is a list of sanitized metasmoke database dumps. Click a filename to download it.

    <% @dumps.each do |d| %>

        <%= link_to d, download_dump_path(filename: d) %>

    <% end %>


text:
<% tp ||= reason.tp_percentage * 100 %>
<% naa ||= reason.both_percentage * 100 %>
<% fp ||= reason.fp_percentage * 100 %>
<% empty = 100 - (tp + fp + naa) %>
<td width="30%" data-sort-value="<%= tp.round %>">
  <div class="progress" style="height:15px; margin-bottom:0px" title="TP: <%= tp.round(2) %>
NAA/Both: <%= naa.round(2) %>
FP: <%= fp.round(2) %>
None: <%= empty.round(2) %>">
    <div class="progress-bar progress-bar-success" style="width:<%= tp %>%; <%= "background-color:#b7b7b7" if reason.inactive %>">

    <div class="progress-bar progress-bar-info" style="width:<%= empty %>%; background-color: rgba(0,0,0,0)">

    <div class="progress-bar progress-bar-warning" style="width:<%= naa %>%; <%= "background-color:#efefef" if reason.inactive %>">

    <div class="progress-bar progress-bar-danger" style="width:<%= fp %>%; <%= "background-color:#d8d8d8" if reason.inactive %>">


text:
<%= link_to (image_tag @site.site_logo, size: "20"), @site.site_url %> <%= @site.site_name %>: Dashboard

  <%= form_tag :site_dash, method: :get, class: 'form-inline' do %>
    Data from site:
    <%= select_tag :site_id, options_from_collection_for_select(Site.mains.order(site_name: :asc), 'id', 'site_name', params[:site_id]), class: 'form-control' %>
    over the last
    <%= number_field_tag :months, @months, min: 1, class: 'form-control' %>
    months
    <%= hidden_field_tag :tab, @active_tab %>
    <%= submit_tag 'Apply', class: 'btn btn-primary', name: nil %>
  <% end %>

Stats (last <%= @months_string %>)

  There have been <%= number_with_delimiter @flags.count, delimiter: @delimiter %> attempts to cast flags automatically on <%= @site.site_name %> in the last <%= @months_string %>.

  We were able to cast automatic flags <%= number_with_delimiter @flags.successful.count, delimiter: @delimiter %> times (<%= ((@flags.successful.count.to_f / @flags.count) * 100).round(2) %>%) and we were unable to cast automatic flags <%= number_with_delimiter @flags.failed.count, delimiter: @delimiter %> times (<%= ((@flags.failed.count.to_f / @flags.count) * 100).round(2) %>%).

  The flags were <%= number_with_delimiter @flags.successful.tp.count, delimiter: @delimiter %> (<%= ((@flags.successful.tp.count.to_f / @flags.successful.count) * 100).round(2) %>%) true positives (TPs) and
  <%=  number_with_delimiter @flags.successful.fp.count, delimiter: @delimiter %> (<%= ((@flags.successful.fp.count.to_f / @flags.successful.count) * 100).round(2) %>%) false positives (FPs).

  The posts were <%= number_with_delimiter @posts_timescaled.autoflagged.tp.count, delimiter: @delimiter %> (<%= ((@posts_timescaled.autoflagged.tp.count.to_f / @posts_timescaled.autoflagged.count) * 100).round(2) %>%) TPs and
  <%= number_with_delimiter @posts_timescaled.autoflagged.fp.count, delimiter: @delimiter %> (<%= ((@posts_timescaled.autoflagged.fp.count.to_f / @posts_timescaled.autoflagged.count) * 100).round(2) %>%) FPs.

  <% height = '150px' %>

<%= link_to (image_tag @site.site_logo, size: "20"), @site.site_url %> Reports last <%= @months_string %>

    <%= pie_chart report_counts_graph_path(months: @months, site_id: @site.id), colors: ['#444', '#0a0', '#a00'], height: height %>

<%= link_to (image_tag @site.site_logo, size: "20"), @site.site_url %> Reports daily, last <%= @months_string %>

    <%= line_chart reports_graph_path(months: @months, site_id: @site.id), colors: ['#444', '#0a0', '#a00'], height: height, library: {'tooltip' => {'shared' => 'true'} }, legend: false %>

<%= link_to (image_tag @site.site_logo, size: "20"), @site.site_url %> Reasons post count, last <%= @months_string %>

    <%= pie_chart reason_counts_graph_path(months: @months, site_id: @site.id), height: height %>

<%= link_to (image_tag @site.site_logo, size: "20"), @site.site_url %> Time to deletion daily, last <%= @months_string %>

    <%= line_chart monthly_ttd_graph_path(months: @months, site_id: @site.id, round: 0), colors: ['#444'], height: height %>

Summary and Posts (All Time)

    Posts Caught:
    True Positives:
    False Positives:
    Non-answers:
    Autoflagged (total):
    Autoflagged False Positives:

    <%= number_with_delimiter @all_posts.count, delimiter: @delimiter %>
    <%= number_with_delimiter @all_posts.where(is_tp:true).count, delimiter: @delimiter %>
    <%= number_with_delimiter @all_posts.where(is_fp:true).count, delimiter: @delimiter %>
    <%= number_with_delimiter @all_posts.where(is_naa:true).count, delimiter: @delimiter %>
    <%= number_with_delimiter @all_posts.where(autoflagged:true).count, delimiter: @delimiter %>
    <%= number_with_delimiter @all_posts.where(autoflagged:true, is_fp: true).count, delimiter: @delimiter %>

  RSS

Use the below link as an RSS feed of all posts that were autoflagged then deleted. There's a few minutes of delay, but it's useful for watching what's happening on your site. It's safe to use this in your private mod chat room.

    <%= url_for(controller: 'rss', action: 'deleted', site: @site.id, format: :xml, only_path: false) %>

  <% @tabs.each do |tab, posts| %>
  <li class="nav-tab nav-tab-<%= tab.downcase %> <%= "active" if tab.downcase == @active_tab %>">
    <%= link_to "#{tab} (#{number_with_delimiter(posts.count, delimiter: @delimiter)})", site_dash_path(params.permit(:site_id, :months).to_h.merge(tab: tab.downcase)) %>

  <% end %>
  <li class="nav-tab nav-tab-spammers <%= "active" if @active_tab.downcase == "spammers" %>">
    <%= link_to "Spammers (#{number_with_delimiter(@spammers.length, delimiter: @delimiter)})", site_dash_path(params.permit(:site_id, :months).to_h.merge(tab: 'spammers')) %>

  <% if user_signed_in? && (current_user.moderator_sites.exists? || current_user.has_role?(:admin)) %>
    <li class="nav-tab nav-tab-autoflaggers <%= "active" if @active_tab.downcase == "autoflaggers" %>">
      <%= link_to "Autoflaggers (#{number_with_delimiter(@autoflaggers.length, delimiter: @delimiter)})", site_dash_path(params.permit(:site_id, :months).to_h.merge(tab: 'autoflaggers')) %>

  <% end %>

<% if @active_tab == 'spammers' %>
  <%= render 'stack_exchange_users/table', users: @spammers_page %>
<% elsif @active_tab == 'autoflaggers' && user_signed_in? && (current_user.moderator_sites.exists? || current_user.has_role?(:admin)) %>
  <%= render 'users/table', users: @autoflaggers_page %>
<% else %>
  <% if @posts.count == 0 %>

No spam here! Try another filter.

  <% else %>

      <% @posts.each do |p| %>
        <%= render 'posts/post', post: p, deletion_date: true, show_autoflaggers: (user_signed_in? && current_user.moderator_sites.exists?), show_autoflagged: (user_signed_in? && current_user.moderator_sites.exists? && !%w[autoflagged].include?(@active_tab)) %>
      <% end %>

  <% end %>

    <%= will_paginate @posts, renderer: BootstrapPagination::Rails %>

<% end %>


text:
Privacy Statement

      EU citizens: This document is an outlining of your rights and required information, as they relate to the General Data Protection Regulation.
      It is important that you read it. Also contained in this document are contact details for the relevant parties should you have any privacy-related
      requests or concerns.

      The ordering in this document is a direct reference to points of Article 13 of the General Data Protection Regulation. Points that are irrelevant
      to our use-cases are omitted and this document may therefore skip points.

1a. Data Controller

      Charcoal

      smokey@charcoal-se.org

1c. Purpose of Collection

      Details of what data are collected from you as a user, including the reasons for their collection and the duration for which they will be retained,
      are available <%= link_to 'here', data_processing_path %>.

1e. Recipients

      The following people have access to some or all of the information collected by metasmoke:

<%= link_to 'Undo', 'https://chat.stackexchange.com/users/73046' %>

<%= link_to 'ArtOfCode', 'https://chat.stackexchange.com/users/121520' %>

<%= link_to 'thesecretmaster', 'https://chat.stackexchange.com/users/162795' %>

<%= link_to 'Thomas Ward', 'https://chat.stackexchange.com/users/10145' %>

2. Your Rights

      b. You have the right to request access to your data (that is, to view a complete record of the personal data we have stored about
      you). Further to this, you have the right to request that this data be deleted or corrected. Additionally, you have the right to request a copy of
      your personal data in a format that is convenient for its further reuse elsewhere.

      c. You may withdraw your consent to our processing of your personal data at any time. Such withdrawal of consent will not affect
      the lawfulness of any processing of your personal data completed prior to your withdrawal of consent.

      d. If you believe we are not meeting our obligations with regard to your rights contained herein, you have the right to lodge a
      complaint with the relevant supervisory authority.

      e. Our collection of your personal data for the purposes outlined in 1c. above is neither a legal nor a
      contractual requirement. You are not obligated to provide us with the requested data; however, failure (whether by choice or inability) to provide
      the requested data will render you ineligible to register an account on metasmoke.


text:
Data Processing

      This document outlines what data are collected from users as part of normal operation on metasmoke. It contains the rationale for the collection
      of each type of data and the period for which it is retained.

          Data
          Source
          Rationale
          Retention Period
          Who has access?

          Usernames
          Stack Exchange users; metasmoke users
          Used to publicly identify your account without revealing more identifying information to a wider audience.
          Lifetime of your account (metasmoke users); unlimited (Stack Exchange users)
          Public

          Email addresses
          metasmoke users registered without OAuth
          Used as a primary unique identifier for your account, necessary for logging in.
          Lifetime of your account
          Server host (Undo, or future additions)

          IP addresses
          metasmoke users
          Certain actions create a permanent record of the action for auditing purposes, including the source IP address.
          Unlimited
          Developers (Undo, ArtOfCode, thesecretmaster, or future additions)

          Stack Exchange post content
          Stack Exchange users
          Recorded for use in analysis of spam. These do not usually contain PII unless included by the user.
          Unlimited
          Public

          SmokeDetector feedback
          SmokeDetector privileged users
          SmokeDetector feedback is associated with a metasmoke user and used for analysing spam.
          Unlimited
          Public

          Stack Exchange API tokens
          metasmoke autoflagging users
          API tokens must be collected to be able to cast flags on behalf of users for autoflagging; these can be used to identify an account.
          Lifetime of your account or until revoked
          Server host (Undo, or future additions)


text:
Spam by Site

  <%= form_tag :spam_by_site, method: :get do %>

      <%= label_tag :site %>
      <%= select_tag :site, options_from_collection_for_select(Site.mains.order(site_name: :asc), 'id', 'site_name', params[:site]) %>

      <%= check_box_tag :undeleted, 'yes', checked: ('checked' if params[:undeleted].present?) %>
      <%= label_tag :undeleted, 'Undeleted posts only?' %>

      <%= submit_tag 'Apply', class: 'btn btn-xs btn-primary' %>

  <% end %>

<% if @posts.count == 0 %>

No spam here! Try another filter.

<% else %>

    <% @posts.each do |p| %>
      <%= render 'posts/post', post: p %>
    <% end %>

<% end %>


text:
<form role="search">

    <input type="text" id="search" class="form-control" placeholder="Search reasons">

</form>

  <%= @reasons.count %>
  <%= "filter".pluralize(@reasons.count) %> have caught
  <%= number_with_delimiter(@posts.count) %>
  <%= "post".pluralize(@posts.count) %>

      Reason
      Number caught
      Last caught
      Weight
      Accuracy

    <% @active_reasons[:results].each do |reason| %>

        <%= link_to reason.reason_name, reason_path(reason) %>
        <td data-sort-value="<%= reason.post_count %>"><%= reason.post_count %>
        <bdi><%= truncate((reason.last_post_title.nil? ? reason.posts.last.title : reason.last_post_title), length: 40, seperator: ' ') %></bdi>
        <td data-sort-value="<%= reason.weight %>"><%= reason.weight %>
        <% counts = @active_reasons[:counts][reason.id] %>
        <%= render 'reason_accuracy', reason: reason, tp: 100 * counts[:tp].to_f / counts[:total], fp: 100 * counts[:fp].to_f / counts[:total],
                                      naa: 100 * counts[:naa].to_f / counts[:total] %>

    <% end %>

      Inactive Reason
      Number caught
      Last caught
      Accuracy

    <% @inactive_reasons[:results].each do |reason| %>

        <%= link_to reason.reason_name, reason_path(reason) %>
        <td data-sort-value="<%= reason.post_count %>"><%= reason.post_count %>
        <bdi><%= truncate((reason.last_post_title.nil? ? reason.posts.last.title : reason.last_post_title), length: 40, seperator: ' ') %></bdi>
        <% counts = @inactive_reasons[:counts][reason.id] %>
        <%= render 'reason_accuracy', reason: reason, tp: 100 * counts[:tp].to_f / counts[:total], fp: 100 * counts[:fp].to_f / counts[:total],
                                      naa: 100 * counts[:naa].to_f / counts[:total] %>

    <% end %>


text:
<% title 'Dashboard' %>

    <% smokey_count = SmokeDetector.active.count %>
    <% system_status = smokey_count > 0 ? (smokey_count > 1 ? 'module-green' : 'module-amber') : 'module-red' %>
    <div class="module <%= system_status %>">

          <%= link_to status_path do %>
             system status
          <% end %>

<%= pluralize(smokey_count, 'instance') %> active

    <% is_enabled = FlagSetting['flagging_enabled'] == '1' %>
    <% is_dry_run = FlagSetting['dry_run'] == '1' %>
    <% status = is_enabled ? (is_dry_run ? 'Dry-running' : 'Enabled') : 'Disabled' %>
    <% flagging_status = is_enabled ? (is_dry_run ? 'module-amber' : 'module-green') : 'module-red' %>
    <div class="module <%= flagging_status %>">

          <%= link_to flagging_path do %>
             flagging
          <% end %>

          <%= status %>, <%= pluralize(FlagLog.successful.auto.today.count, 'flag') %> today
          <% if user_signed_in? && current_user.flags_enabled %>
            (<%= FlagLog.successful.auto.today.where(user: current_user).count %> yours)
          <% end %>

          <%= link_to posts_path do %>
             posts today
          <% end %>

<%= pluralize(Post.today.count, 'post') %> reported

 feedback

          <%= pluralize(Feedback.today.count, 'feedback') %> today
          <% if user_signed_in? %>
            (<%= link_to "#{Feedback.today.where(user: current_user).count} yours", admin_user_feedback_path(user_id: current_user.id) %>)
          <% end %>

Reports hourly, last week

<%= line_chart reports_by_hour_graph_path(cache: true), colors: ['#444', '#0a0', '#a00'] %>

Time to deletion daily, last month

  <%= line_chart monthly_ttd_graph_path(cache: true, months: 1), colors: ['#444'] %>

Flagging results daily, last month

  <%= line_chart flagging_timeline_graph_path(cache: true), colors: ['#a00', '#fa0', '#0a0'] %>

Stats

  <%= Post.count %> total reports from <%= Reason.count %> reasons:

<%= Post.tp.count %> (<%= ((Post.tp.count.to_f / Post.count) * 100).round(2) %>%) TP

<%= Post.fp.count %> (<%= ((Post.fp.count.to_f / Post.count) * 100).round(2) %>%) FP

<%= Post.naa.count %> (<%= ((Post.naa.count.to_f / Post.count) * 100).round(2) %>%) NAA

  <%= Post.autoflagged.count %> posts have been autoflagged,
  totalling <%= FlagLog.successful.auto.count %> flags:

<%= Post.autoflagged.tp.count %> (<%= ((Post.autoflagged.tp.count.to_f / Post.autoflagged.count) * 100).round(2) %>%) TP

<%= Post.autoflagged.fp.count %> (<%= ((Post.autoflagged.fp.count.to_f / Post.autoflagged.count) * 100).round(2) %>%) FP


text:
User Feedback for <%= @user.username %>

  <span title='<%= @feedback_count_today %> feedbacks today'>
  	<%= @feedback_count %>
  	feedbacks,

  <%= @invalid_count %>
  invalidated
  (<%= ((@invalid_count.to_f / @feedback_count.to_f) * 100).round(2) %>% invalid)

This data includes feedback from <%= @sources.to_sentence %>

      Post
      Feedback Type
      Invalidated
      Created

    <% @feedback.each do |f| %>
      <tr class="<%= "danger" if f.invalidated_at %>">
        <a href="/post/<%= f.post_id %>"><%= f.title %>
        <td class="<%= element_class_for_feedback f %>"><%= f.feedback_type %>
        <%= f.invalidated_at ? "Yes" : "No" %>
        <%= time_ago_in_words(f.created_at) + " ago" if f.created_at.present? %>

    <% end %>

  <%= will_paginate @feedback, renderer: BootstrapPagination::Rails %>


text:
Users

  A list of all user accounts on the site, with useful links about them and their content.

<%= form_tag users_path, class: 'form-inline', method: :get do %>
  <%= label_tag :filter, 'Username filter:' %>
  <%= text_field_tag :filter, params[:filter], class: 'form-control input-sm' %>
  <%= submit_tag 'Filter', class: 'btn btn-primary btn-sm' %>
<% end %>

      ID
      Username
      <% if current_user&.has_role?(:admin) %>
        <% @roles.map {|r| r.to_s.humanize.titlecase }.each do |role_name| %>
          <%= role_name %>
        <% end %>
      <% else %>
        Roles
      <% end %>

      <% if current_user&.has_role?(:developer) %>

      <% end %>

    <% @users.each do |user| %>

        <%= user.id %>
        <%= link_to_if user.stack_exchange_account_id.present?, sanitize(user.username), "//stackexchange.com/users/#{user.stack_exchange_account_id}" %>
        <% if current_user&.has_role?(:admin) %>
          <%= render partial: 'roles_admin', locals: {roles: @roles, user: user} %>
        <% else %>
          <%= user.roles.map(&:name).map{|n| n.humanize.downcase}.to_sentence.capitalize %>
        <% end %>
        <%= link_to 'Feedback', admin_user_feedback_path(user_id: user.id) %>
        <% if current_user&.has_role?(:admin) %>
          <%= link_to 'Flagging', user_overview_path(user: user.id) %>

            <%= link_to 'User Info', dev_user_path(user) %>
            <% if current_user&.has_role?(:developer) %>
              (<%= link_to 'Logs', redis_log_by_user_path(user) %>)
            <% end %>

          <% if current_user&.has_role?(:developer) %>
            <%= link_to 'Impersonate', impersonate_path(user), method: :post, class: 'text-warning' %>
            <%= link_to 'Nuke', 'javascript:void(0);', class: 'text-danger nuke-user-link', data: { user_id: user.id, username: user.username } %>
          <% end %>
        <% end %>

    <% end %>

  <%= will_paginate @users, renderer: BootstrapPagination::Rails %>


text:
Recently Invalidated Feedback

<% if current_user&.has_role?(:developer) %>

    <%= link_to 'Resolve feedback conflicts', developer_fcrs_path, method: :post, class: 'text-danger' %>

    <%= link_to 'Reindex feedback', developer_reindex_path, method: :post, class: 'text-danger' %>

<% end %>

      Post
      Feedback Type
      Feedback Creator
      Invalidated At
      Invalidated By

    <% @feedbacks.each do |f| %>

        <a href="/post/<%= f.post_id %>"><%= f.title %>
        <%= f.feedback_type %>

          <% if f.user_id && User.exists?(f.user_id) %>
            <a href="/admin/user_feedback?user_id=<%= f.user_id %>"><%= f.user.username %>
          <% elsif f.user.try(:email) %>
            (From Review)
          <% elsif f.chat_user_id %>
            (Chat: <%= f.chat_host %>/<%= f.chat_user_id %>)
          <% elsif f.user_name %>
            <%= f.user_name %>
          <% end %>

        <%= time_ago_in_words(f.invalidated_at) + " ago" if f.invalidated_at %>
        <%= f.invalidated_by&.username %>

    <% end %>

  <%= will_paginate @feedbacks, renderer: BootstrapPagination::Rails %>


text:
Feedback via API

      Owner
      Type
      Post
      Application
      Created

    <% @feedback.each do |f| %>

          <% if f.user.present? %>
            <%= f.user.username %>
          <% else %>
            Nobody. Um.
          <% end %>

        <td class="<%= element_class_for_feedback f %>"><%= f.feedback_type %>
        <bdi><%= link_to truncate(f.post.title, length: 50, separator: ' '), "/post/" + f.post_id.to_s %></bdi>
        <%= f.api_key.app_name %>
        <%= time_ago_in_words(f.created_at) %> ago

    <% end %>

  <%= will_paginate @feedback, renderer: BootstrapPagination::Rails %>


text:
<%= title "Tools" %>

Someone thought these were useful, at some point. We take no responsibility for whether they actually are or not.

Invalidated Feedback

Feedback via API

User Data

    <% if current_user.try(:has_role?, :admin) %>

Posts with Admin Reports

API Keys

<%= link_to "User Permissions", admin_permissions_path %>

    <% end %>
    <% if current_user&.has_role?(:developer) %>

<%= link_to "Production log", url_for(controller: :developer, action: :production_log), class: "text-danger" %>

    <% end %>


text:
<% roles.each do |role| %>
  <td>
    <label class="permissions-checkbox-label">
      <%= check_box_tag "#{user.id}[#{role.to_s}]", 'foo', user.has_cached_role?(role),
                        disabled: (role == :developer and not user.has_cached_role?(role)),
                        class: "permissions-checkbox", data: {user_id: user.id, role: role.to_s } %>
    </label>
  </td>
<% end %>


text:
<%= form_for(flag_setting) do |f| %>
  <% if flag_setting.errors.any? %>

<%= pluralize(flag_setting.errors.count, "error") %> prohibited this flag setting from being saved:

      <% flag_setting.errors.full_messages.each do |message| %>

<%= message %>

      <% end %>

  <% end %>

    <%= f.label :name %>

    <%= f.text_field :name, class: "form-control" %>

    <%= f.label :value %>

    <%= f.text_field :value, class: "form-control" %>

    <%= f.submit "Save", class: "btn btn-success" %>

<% end %>


text:
<%= title "Flag Settings Audit" %>

    User
    Action
    Setting
    Change
    At

  <% @audits.each do |audit| %>

      <%= audit.user.try(:username) %>
      <%= audit.action %>
      <%= audit.auditable.name %>
      <% value_change = audit.audited_changes["value"] %>
      <%= value_change.try(:first) %><% if value_change.try(:second).present? %>
        → <%= value_change.try(:second) %>
      <% end %>
      <span data-livestamp="<%= audit.created_at.to_i %>" title="<%= audit.created_at %>">

  <% end %>


text:
<%= title "New Flag Setting" %>

<%= render 'form', flag_setting: @flag_setting %>


text:
<%= title "Edit Flag Setting" %>

<%= render 'form', flag_setting: @flag_setting %>


text:
<%= title "Flag Settings" %>

<%= link_to "Change Log", flag_settings_audits_path %>

      Name
      Value
      <% if user_signed_in? and current_user.has_role? :admin %>

      <% end %>

    <% @flag_settings.each do |flag_setting| %>

        <%= flag_setting.name.humanize %> (<%= flag_setting.name %>)
        <%= flag_setting.value %>
        <% if user_signed_in? and current_user.has_role? :admin %>
          <%= link_to 'Edit', edit_flag_setting_path(flag_setting) %>
        <% end %>

    <% end %>

<% if user_signed_in? and current_user.has_role? :admin %>
  <%= link_to 'New Flag Setting', new_flag_setting_path %>
<% end %>


text:
Site Settings

Contains settings that can be configured per SE site.

<input type="text" class="form-control input-sm site-search" placeholder="Filter (press Enter to apply)" />

      Site
      Flags enabled
      Max flags per post
      Auto-modflags enabled

    <% @sites.each do |s| %>
      <tr data-sid="<%= s.id %>">
        <%= HTMLEntities.new.decode s.site_name %>
        <input type="checkbox" name="flags_enabled" <%= 'checked' if s.flags_enabled %> />
        <input type="number" class="form-control input-sm" min="0" max="6" value="<%= s.max_flags_per_post %>" />
        <input type="checkbox" name="auto_disputed_flags_enabled" <%= 'checked' if s.auto_disputed_flags_enabled %> />

    <% end %>

      You have unsaved changes. Click the Save button to persist them to the database.

      Save


text:
  Autoflagging by Site
  <% if @site.present? %>
    - <%= @site.site_name %>
  <% end %>

<%= form_tag :flagging_by_site, method: :get do %>
  <%= label_tag :site, 'Select a site:' %>
  <%= select_tag :site, options_from_collection_for_select(@sites, 'id', 'site_name') %>
  <%= submit_tag 'Apply', class: 'btn btn-xs btn-primary' %>
<% end %>

<% if @site.present? %>

    There have been <%= @flags.count %> attempts to cast flags automatically on <%= @site.site_name %>.

    <%= @flags.successful.count %> successful and <%= @flags.failed.count %> failed;
    <%= @flags.successful.tp.count %> (<%= ((@flags.successful.tp.count.to_f / @flags.successful.count) * 100).round(2) %>%) TP and
    <%= @flags.successful.fp.count %> (<%= ((@flags.successful.fp.count.to_f / @flags.successful.count) * 100).round(2) %>%) FP.

Flagged Posts

    <% @posts.each do |p| %>
      <%= render 'posts/post', post: p %>
    <% end %>

<% end %>


text:
<% title "Flagging" %>

    <% if FlagSetting['flagging_enabled'] == '0' %>

 system status

Flagging is disabled.

    <% else %>
      <% if FlagSetting['dry_run'] == '1' %>

 system status

Enabled, but dry-running.

      <% else %>

 system status

Enabled & flagging.

      <% end %>
    <% end %>

    <% if FlagSetting['registration_enabled'] == '0' %>

 registration

Registration is closed.

    <% else %>

 registration

Registration is open.

    <% end %>

 last 24 hours

          <%= link_to flag_logs_path do %>
            <%= pluralize @recent_count, 'flag' %> cast
          <% end %>

 flagging & you

        <% if user_signed_in? %>
          <% if current_user.flags_enabled %>
            <%= link_to flag_logs_by_user_path(current_user) do %>

<%= pluralize current_user.flag_logs.where(is_auto: true, success: true).where('created_at > ?', Date.today).count, 'flag' %> used today

            <% end %>
          <% else %>

Not registered for flagging.

          <% end %>
        <% else %>

Not signed in.

        <% end %>

Links

<%= link_to "Unflagged logs", unflagged_logs_path %>

<%= link_to "System settings", url_for(controller: :flag_settings, action: :index) %>

<%= link_to "Your preferences", url_for(controller: :user_site_settings, action: :index) %>

<%= link_to "Your conditions", url_for(controller: :flag_conditions, action: :index) %>

<% if user_signed_in? && current_user.has_role?(:admin) %>

Admin

<%= link_to "All conditions", url_for(controller: :flag_conditions, action: :full_list) %>

<%= link_to "Per-site flag limits", url_for(controller: :flag_settings, action: :site_settings) %>

<%= link_to "Invalidate API tokens", url_for(controller: :authentication, action: :invalidate_tokens), class: "text-danger" %>

User views

  <%= form_tag url_for(controller: :flag_conditions, action: :user_overview), method: 'GET', class: 'form-inline' do %>

      <%= select_tag 'user', options_for_select(User.all.map{|u| [u.try(:username), u.id]}),
                     { class: 'form-control selectpicker', 'data-live-search' => true, 'data-actions-box' => true, 'data-dropup-auto' => false} %>

    <%= submit_tag 'View', class: 'btn btn-primary' %>
  <% end %>
<% end %>

Stats

<%= pluralize(User.where(flags_enabled: true).count, "active participant") %>

<%= pluralize(FlagLog.auto.where(success: true, is_dry_run: false).count, "spam flag") %> total cast in
<%= time_ago_in_words(FlagLog.auto.where(success: true, is_dry_run: false).first.try(:created_at)) rescue nil %>

<%= pie_chart url_for(controller: :graphs, action: :flagging_results), colors: ['red', 'orange', 'green'] %>
<%= line_chart url_for(controller: :graphs, action: :flagging_timeline), colors: ['red', 'orange', 'green'],
library: { "xAxis": { "plotLines" => flag_settings_plot_lines(1.month.ago)}} %>


text:
  <% linked_domain = link.left == domain ? link.right : link.left %>
  <%= linked_domain.blank? ? "null domain" : link_to(linked_domain.domain, spam_domain_path(linked_domain)) %>
  <% linked_domain.domain_tags.standard.each do |t| %>
    <%= render 'domain_tags/tag', tag: t, domain: linked_domain %>
  <% end %>
  <%= link.link_type %>
  <% if link.comments.present? %>
    <a href="#" data-toggle="modal" data-target="#link-modal-<%= link.id %>" class="text-warning">

    <div class="modal fade" id="link-modal-<%= link.id %>">

            <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

Domain Link Details

This domain (<%= domain.domain %>) is linked to <%= linked_domain.blank? ? "null domain" : link_to(linked_domain.domain, spam_domain_path(linked_domain)) %>
              (<%= link.link_type %>).

Linked by <%= link.creator.username %> <%= time_ago_in_words(link.created_at) %> ago, with these comments:

<%= link.comments %>

  <% end %>

    <%= link_to 'Delete', destroy_domain_link_path(link), method: :delete, data: { confirm: 'Are you sure?' }, class: 'text-danger' %>


text:
<%= form_for @preference do |f| %>

    <%= f.label :max_flags, "Maximum autoflags per day (per site)" %>

    <%= f.number_field :max_flags, class: "form-control" %>

    <%= f.label :sites, "Sites" %>

    <%= f.select :sites, options_for_select(Site.mains.order(:site_name).map{ |s| [s.site_name, s.id] }, @preference.site_ids), {}, { multiple: true, class: "form-control selectpicker", "data-live-search" => true, "data-actions-box" => true, "data-dropup-auto" => false, title: "Choose the sites this preference should apply to" } %>

  <% if (@preference.user || current_user).moderator_sites.any? %>

      We won't cast flags on any sites where you're a moderator, regardless of your settings here. That'd be these sites:

        <% (@preference.user || current_user).moderator_sites.each do |ms| %>

<%= ms.site.site_name %>

        <% end %>

  <% end %>

    <%= f.submit "Save", class: "btn btn-success" %>

<% end %>


text:
<%= title "New flagging preference" %>

<%= render 'form' %>


text:
<%= title "Edit flagging preferences" %>

<%= render 'form' %>


text:
<%= title "Autoflagging Preferences (#{@user.try(:username)})" %>

      ID
      Site Count
      Flags Used Today

    <% @preferences.each do |pref| %>

        <%= pref.id %>
        <%= pref.sites.count %>
        <%= pref.flags_used %>
        <%= link_to "Edit", url_for(controller: :user_site_settings, action: :edit, id: pref.id) %>
        <%= link_to "Delete", url_for(controller: :user_site_settings, action: :destroy, id: pref.id),
                        method: :delete, data: { confirm: "Are you sure?" }, class: "text-danger" %>

    <% end %>


text:
<%= title "Autoflagging Preferences" %>

Getting started

    If you're trying to get started with autoflags for the first time, you'll need to:

authorize metasmoke for write access to your Stack Exchange account (see "Clifford the Big Red Button" below)

verify that the "Allow metasmoke to raise flags for my account" checkbox is checked (see below)

set up your preferences (below), which govern how many of your flags metasmoke can use per-site. You must set at least one preference.

<%= link_to "set up your autoflagging conditions", url_for(controller: :flag_conditions, action: :index) %>, which govern how certain you want metasmoke to be a post is spam before using your account to flag it. You must set at least one flagging condition.

Authenticating metasmoke with your Stack Exchange account

Clifford the Big Red Button

      Warning: for all the joking about, this is serious. By authenticating metasmoke for write access to your Stack Exchange account, you
      are explicitly consenting to your Stack Exchange account being used to cast flags automatically based on data collected by SmokeDetector. While we believe this has a high
      rate of accuracy and have designed the system to reflect this, flags cast using your account are your responsibility, and having many invalid flags can, in some cases,
      result in your SE account being suspended, or being temporarily banned from flagging. Only authenticate metasmoke for write access if you accept this responsibility.

    <% if !current_user.write_authenticated %>

If you have not already done so, you need to first authenticate metasmoke for write access with Stack Exchange; <%= link_to "you can do that here", url_for(controller: :authentication, action: :status) %>.

    <% else %>
      <input id="red-button" name="red-button" type="checkbox" <%= "checked" if current_user.flags_enabled %> <%= "disabled" if (FlagSetting["registration_enabled"] == "0" || !current_user.has_role?(:flagger)) && !current_user.flags_enabled %> />
      Allow metasmoke to raise flags for my account

The above checkbox must be checked in order for either autoflagging or manual flagging through userscripts
      (e.g. FIRE) to work.
      For autoflagging to be active for your account, all of the following must happen:
      A) this checkbox must be checked;
      B) you must have at least one valid autoflagging preference (see "Preferences" below); and
      C) you must have at least one valid <%= link_to "autoflagging condition", url_for(controller: :flag_conditions, action: :index) %>.
      If the above checkbox is checked and you have either or both no valid autoflagging preferences or no valid and enabled  autoflagging conditions,
      then autoflagging for your account will be disabled and only manual flagging will be functional.

      <% if FlagSetting["registration_enabled"] == "0" && !current_user.flags_enabled %>

Registration is currently disabled.

      <% end %>

Write token status: metasmoke believes it has a valid SE API write token for your account. If you've
      removed that token from your application preferences on Stack Exchange, you will need to
      <%= link_to "re-authenticate", url_for(controller: :authentication, action: :status) %>
      in order for metasmoke to raise flags for your account, even though metasmoke doesn't think you need to do so.

    <% end %>

Preferences: maximum number of flags metasmoke will use

Each preference below sets the maximum number of your flags metasmoke will use on a site or group of sites. In order for metasmoke to use your account for autoflagging, you need to have at least one such preference set.

      ID
      Site Count
      Flags Used Today

    <% @preferences.each do |pref| %>

        <%= pref.id %>
        <%= pref.sites.count %>
        <%= current_user.flag_logs.where(is_auto: true, success: true).where('created_at > ?', 1.day.ago).count %>
        <%= link_to "Edit", url_for(controller: :user_site_settings, action: :edit, id: pref.id) %>
        <%= link_to "Delete", url_for(controller: :user_site_settings, action: :destroy, id: pref.id),
                        method: :delete, data: { confirm: "Are you sure?" }, class: "text-danger" %>

    <% end %>

<% if FlagSetting['registration_enabled'] == '1' %>
  <%= link_to "Add new maximum flags per site preference", url_for(controller: :user_site_settings, action: :new) %>

Don't want to set this up yourself? <%= link_to "There's a wizard for that.", url_for(controller: :flag_conditions, action: :one_click_setup) %>

<% else %>

Registration for autoflagging is currently closed.

<% end %>


text:
<%= title "Status" %>

    Name
    Scans Today
    Last Ping

  <% @statuses.each_with_index do |sd, index| %>
    <% if index == 0 or sd.last_ping > 1.hour.ago %>
      <tr class="status-row" data-id="<%= sd.id %>">
    <% else %>
      <tr class="status-row hidden-row" style="<%= 'display:none' %>" data-id="<%= sd.id %>">
    <% end %>

        <%= link_to smoke_detector_statistics_path(sd.id) do %>
          <%= sd.location %>
          <span class="label label-<%= sd.last_ping > 3.minutes.ago ? "primary" : "default" %> " style="display: <%= sd.is_standby ? 'inline' : 'none'%>">Standby
        <% end %>

        <%= @scans[sd.id] || '(unavailable)' %>

      <td class="status-<%= sd.status_color %> ping-cell" data-livestamp="<%= sd.last_ping.to_i %>" title="<%= sd.last_ping.to_s %>">
        <%= time_ago_in_words(sd.last_ping, include_seconds: true)%> ago

        <% if current_user&.has_role?(:admin) %>
          <%= link_to "De-authorize", url_for(controller: :smoke_detectors, action: :destroy, id: sd.id), class: "text-danger",
                data: {confirm: "This will be logged, and cannot be undone. Sure?"}, method: :delete %>
        <% end %>

      <% if current_user&.has_role?(:blacklist_manager) %>
        <% if sd.last_ping > 3.minutes.ago %>

            <% if sd.is_standby %>
              <%= link_to "Failover", smoke_detector_force_failover_path(sd.id), class: "text-danger", data: {confirm: "This will take effect at the next ping, within a minute. Sure?"}, method: :post %>
            <% end %>

            <%= link_to "Pull", smoke_detector_force_pull_path(sd.id), class: "text-danger", data: {confirm: "This will take effect at the next ping, within a minute. Sure?"}, method: :post %>

        <% else %>

        <% end %>
      <% end %>

  <% end %>

<% if @statuses.to_a.index { |s| s.last_ping < 1.hour.ago } %>
  Toggle hidden
<% end %>

<% if current_user.try(:has_role?, :smoke_detector_runner) %>
  <%= link_to "Manage my keys", smoke_detector_mine_path %>
<% end %>

<%= link_to "Audits", url_for(controller: :smoke_detectors, action: :audits) %>

<% if current_user&.has_role?(:admin) %>

Warning: clicking this button will send a message on the Smokey-MS websocket that causes
        all running SmokeDetector instances to die. This is useful in a select number of cases (rogue Smokeys, or unresponsive Smokeys),
        but make sure someone is around to restart an instance.

      <%= link_to 'Kill all instances', kill_smokey_path, method: :post, class: 'btn btn-danger', data: { confirm: 'Are you REALLY sure?' } %>

<% end %>


text: json.post_link deletion_log.post.link


text:
New Announcement

Use this form to create an announcement, which will be displayed prominently around metasmoke.

<%= form_tag url_for(controller: :announcements, action: :create) do %>

    <%= label_tag :text %>
    (Markdown allowed)

    <%= text_area_tag :text, nil, rows: 5, cols: 80, class: 'form-control' %>

    <%= label_tag :expiry_date, "Expiry (date & time)" %>

      Date
      <%= date_field_tag :expiry_date, nil, class: 'form-control' %>
      Time
      <%= time_field_tag :expiry_time, nil, class: 'form-control' %>

    <%= submit_tag "Create", class: 'btn btn-success' %>

<% end %>


text: <%= raw(sanitize(announcement.text, scrubber: Announcement.scrubber)) %>


text:
Announcements

<% @announcements.each do |announcement| %>

    <% if announcement.current? %>
      Active
    <% end %>
    Created <%= announcement.created_at %>, expires <%= announcement.expiry %>.
    <% if announcement.current? && current_user&.has_role?(:admin) %>
      <%= link_to "Expire now", announcements_expire_path(announcement), class: "text-danger", method: :post, data: { confirm: "Are you sure? This can't be undone" } %>
    <% end %>

  <%= render "announcements/announcement", announcement: announcement %>

<% end %>


text:
# frozen_string_literal: true

xml.instruct! :xml, version: '1.0'
xml.rss version: '2.0' do
  xml.channel do
    xml.title 'CharcoalHQ'
    xml.description 'Posts which have been caught by Charcoal HQ'
    xml.link root_url
    # category
    xml.copyright 'Copyright 2018 CharcoalHQ'
    # docs
    xml.language 'en-us'
    xml.lastBuildDate DateTime.now.strftime('%a, %-d %b %Y %T %z')
    xml.managingEditor 'smokey@charcoal-se.org'
    xml.pubDate DateTime.now.strftime('%a, %-d %b %Y %T %z')
    xml.webMaster 'smokey@charcoal-se.org'
    xml.generator 'Ruby on Rails XML generator'

    xml.image do
      xml.url 'https://charcoal-se.org/assets/images/charcoal.png'
      xml.title 'CharcoalHQ'
      xml.link root_url
      xml.description 'Posts which have been caught by Charcoal HQ'
      xml.width 516
      xml.height 516
    end

    @posts.each do |post|
      xml.item do
        tags = []
        tags.push 'deleted' unless post.deleted_at.nil?
        tags.push 'autoflagged' if post.autoflagged
        xml.title "[#{tags.join('] [')}] #{post.title}"
        params[:prefix_user] = 'true' if params[:fullbody] == 'false' && !params[:prefix_user].present?
        description = ''
        if params[:prefix_user] == 'true'
          description = "#{link_to post.stack_exchange_user.username, post.stack_exchange_user.stack_link} #{description}"
        end
        description = "#{description} #{post.body}" unless params[:fullbody] == 'false'
        xml.description description
        case params[:link_type].to_s.downcase
        when 'user'
          xml.link post.stack_exchange_user.stack_link
        when 'onsite'
          # We rely on Post.link being a protocol-relative link.
          # This is supported by current data; there are only four exceptions from back in early '17. Won't matter for RSS.
          xml.link 'https:' + post.link
        else
          xml.link url_for(controller: 'posts', action: 'show', id: post.id, only_path: false)
        end
        # category
        # comments
        xml.pubDate post.created_at.strftime('%a, %-d %b %Y %T %z')
      end
    end
  end
end


text:
Autoflagged Posts

<%= render 'posts/table', posts: @posts %>

  <%= will_paginate @posts, renderer: BootstrapPagination::Rails %>


text:
json.merge! post.as_json
json.merge!(count_tp: post.feedbacks.to_a.count { |f| f.feedback_type.include? 't' },
            count_fp: post.feedbacks.to_a.count { |f| f.feedback_type.include? 'f' },
            count_naa: post.feedbacks.to_a.count { |f| f.feedback_type.include? 'n' },
            autoflagged: {
              flagged: post.flagged?,
              names: post.flag_logs.select { |f| f.success && f.is_auto }.map { |f| f.user&.username },
              users: post.flaggers.map { |u| u.as_json.select { |k, _v| k == 'username' || k.include?('_chat_id') } }
            },
            manual_flags: {
              users: post.manual_flaggers.map { |u| u.as_json.select { |k, _v| k == 'username' || k.include?('_chat_id') } }
            },
            feedbacks: post.feedbacks.map { |f| { feedback_type: f.feedback_type, user_name: f.user_name || f.user&.username } },
            reason_weight: post.reasons.map(&:weight).reduce(:+),
            revision_count: post.get_revision_count)


text:
<% wrap_in_tr = true if wrap_in_tr.nil? %>
<% expand_post = false if expand_post.nil? %>
<% preload_post_body = expand_post || (false if preload_post_body.nil?) %>
<% hide_feedbacks = false if hide_feedbacks.nil? %>
<% deletion_date = false if deletion_date.nil? %>
<% show_autoflagged = false if show_autoflagged.nil? %>
<% show_autoflaggers = show_autoflagged if show_autoflaggers.nil? %>
<% @sites = [post.site] if @sites.nil? %>

<% if wrap_in_tr %>
<tr class="post-cell post-cell-<%= post.id %> post-row">
<% end %>

    <% if post.try(:body).present? or post.try(:body_exists) == 1 %>
      <span class="text-muted show-post-body" data-postloaded="<%= preload_post_body.to_s %>" data-postid="<%= post.id %>"><%= (expand_post.present? and expand_post) ? "▼" : "►" %>
    <% end %>

    <bdi class="post-title-bdi"><%= link_to post.title, "/post/" + post.id.to_s, class: 'post-title-link'  %></bdi>

    <% if show_autoflagged && post.flagged? %>

    <% end %>

    <% unless post.feedbacks.empty? or hide_feedbacks %>

         <% post.feedbacks.each do |feedback| %>
           <span style="<%= "font-weight:normal" if feedback.is_naa? %>" data-feedbackid="<%= feedback.id %>" data-toggle="tooltip" data-placement="top" title="<%= (feedback.user.present? or feedback.api_key_id.present?) ? "#{feedback.user.try(:username)} (From #{feedback.api_key.try(:app_name) || ("Chat" if feedback.chat_user_id.present?) || "Review"})" : feedback.user_name %>: <%= feedback.feedback_type %>" class="<%= element_class_for_feedback feedback %> feedback-span"><%= element_symbol_for_feedback(feedback).html_safe %>
         <% end %>

    <% end %>

      (<%= post.reasons.map(&:weight).reduce(:+) %>)

    <% if deletion_date && post.deleted_at %>
      (deleted <%= distance_of_time_in_words(post.created_at, post.deleted_at, include_seconds: true) %> after creation)
    <% end %>

    <% if post.comments.any? && !hide_feedbacks %>
      <span class="comment-hint text-muted" title="<%= pluralize(post.comments.size, 'comment') %>">
         ×<%= post.comments.size %>

    <% end %>

      <% unless post.created_at.nil? %>
        <%= link_to "", post_path(id: post.id), title: post.created_at, "data-livestamp": post.created_at.to_i, class: "text-muted post-creation-date" %>
      <% end %>

      <% unless post.username.nil? || post.stack_exchange_user.nil? %>
        by <bdi class="post-owner-username-bdi"><%= link_to post.username, url_for(controller: :stack_exchange_users, action: :show, id: post.stack_exchange_user.id), class: 'post-username-link' %></bdi>
      <% end %>

      <% if post.site.present? %>
        <%= link_to (image_tag post.site.site_logo, size: "20"), post.link, class: 'post-site-link' %>
      <% end %>

    <div class="post-body" data-postid="<%= post.id %>" style="<%= "display: none;" unless expand_post.present? and expand_post %>">
      <% if preload_post_body %>

            <a href="#post-body-tab-<%= post.id %>" role="tab" data-toggle="tab" class="post-render-mode" data-render-mode="text">Text

          <% unless post.markdown.nil? %>

              <a href="#post-source-tab-<%= post.id %>" role="tab" data-toggle="tab" class="post-render-mode" data-render-mode="markdown">Markdown

          <% end %>

            <a href="#preview-tab-<%= post.id %>" role="tab" data-toggle="tab" class="post-render-mode" data-render-mode="rendered">Preview

          <div role="tabpanel" class="tab-pane active post-body-panel-text" id="post-body-tab-<%= post.id %>">
            <% if post.try(:body).present? or post.try(:body_exists) == 1 %>

<%= post.body %>

                    <%= post.reasons.map(&:reason_name).join(", ") %>

                <% if show_autoflaggers && post.flagged? %>

Autoflagged by:
                    <% post.flaggers.each do |flagger| %>
                      <%= link_to flagger.username, "https://stackexchange.com/users/#{flagger.stack_exchange_account_id}" %>
                    <% end %>

                <% end %>

            <% end %>

          <% unless post.markdown.nil? %>
            <div role="tabpanel" class="tab-pane post-body-panel-markdown" id="post-source-tab-<%= post.id %>">

<%= post.markdown %>

          <% end %>
          <div role="tabpanel" class="tab-pane post-body-panel-preview" id="preview-tab-<%= post.id %>">

      <% end %>

<% if wrap_in_tr %>

<% end %>


text:
  <% if @post.flag_logs.auto.successful.any? %>
    <%= link_to post_flag_logs_path(@post), style: "text-decoration:none"  do %>
      <%= @post.flag_logs.auto.successful.first.flag_icon %>
    <% end %>
  <% end %>
  <bdi class="post-title-bdi"><%= title @post.title %></bdi>
  <% unless @is_review_item %>

       <% @post.feedbacks.each do |feedback| %>
         <span style="<%= "font-weight:normal" if feedback.is_naa? %>" data-feedbackid="<%= feedback.id %>" data-toggle="tooltip" data-placement="top" title="<%= (feedback.user.present? || feedback.api_key_id.present?) ? "#{feedback.user.try(:username)} (From #{feedback.api_key.try(:app_name) || ("Chat" if feedback.chat_user_id.present?) || "Review"})" : feedback.user_name %>: <%= feedback.feedback_type %>" class="<%= element_class_for_feedback feedback %> feedback-span"><%= element_symbol_for_feedback(feedback).html_safe %>
       <% end %>

  <% end %>

    <%= link_to post_path(@post) do %>

    <% end %>

  <% unless @post.feedbacks.empty? || @is_review_item %>
    <% if current_user.present? && (current_user.has_role?(:admin) || @post.feedbacks.where(user_id: current_user.id).exists?) %>

        · <%= link_to "(clear)", clear_post_feedback_path(@post), class: 'clear-link' %>

    <% end %>
  <% end %>

<% if user_signed_in? %>

     Something not right?

<% end %>

<% if user_signed_in? && current_user.has_role?(:reviewer) && !@is_review_item %>

    Add feedback:
    <%= link_to raw('&#x2713'), post_feedback_path(post_id: @post.id, feedback_type: 'tp'),
                class: 'feedback-button on-post text-success', remote: true, method: :post, data: { post_id: @post.id } %>
    <%= link_to raw('&#x2717'), post_feedback_path(post_id: @post.id, feedback_type: 'fp'),
                class: 'feedback-button on-post text-danger', remote: true, method: :post, data: { post_id: @post.id } %>
    <% if @post.link.nil? or @post.link.include? '/a/' %>
        <%= link_to raw('&#x1f4a9'), post_feedback_path(post_id: @post.id, feedback_type: 'naa'), class: 'feedback-button on-post text-warning',
                    remote: true, method: :post, data: { post_id: @post.id } %>
    <% end %>

<% end %>

    <% if @post.post_tags.any? %>
      Tagged with:
      <% @post.post_tags.each do |t| %>
        <%= render 'domain_tags/post_tag', tag: t, post: @post %>
      <% end %>
    <% else %>
      No tags.
    <% end %>

  <% if current_user&.has_role?(:core) %>
    <%= form_tag add_post_tag_path, method: :post, class: 'form-inline pull-left add-post-tag' do %>
      <%= hidden_field_tag :post_id, @post.id %>
      <%= select_tag :tag_name, options_for_select(DomainTag.all.map { |dt| [dt.name, dt.name, { 'data-subtext' => dt.description&.truncate(100) }] }),
                     class: 'selectpicker', include_blank: true %>
      <%= submit_tag 'Add', class: 'btn btn-primary btn-sm' %>
    <% end %>
  <% end %>

<% unless @post.body.nil? %>

      Text

    <% unless @post.markdown.nil? %>

        Markdown

    <% end %>

      Preview

<%= @post.body %>

    <% unless @post.markdown.nil? %>

<%= @post.markdown %>

    <% end %>

<% end %>

<% unless @post.link.nil? %>
  <% unless @post.site&.site_logo.nil? %>
    <%= image_tag @post.site.site_logo, size: "20", class: "site-logo-image" %>
  <% end %>
  <%= link_to "View on site", @post.link, class: 'post-site-link' %>
  <% if @post.deleted_at %>

      (deleted
        <span title="<%= (@post.deleted_at - @post.created_at).round(0) %> seconds">
          <%= distance_of_time_in_words(@post.created_at, @post.deleted_at, include_seconds: true) %>

      after being reported)

  <% end %>
<% end %>

<% unless @post.created_at.nil? %>

    <span class="report-created-at-span" title="<%= @post.created_at %>">
      <%= "reported " + time_ago_in_words(@post.created_at).sub("about ", "") + " ago " %>

    <% if @post.revision_count.to_i >= 2 %>
      | edited <%= number_to_multiplicative_quantifier @post.revision_count - 1 %>
    <% end %>
    <% unless @post.user_link.nil? %>
      | posted by
      <% unless @post.site&.site_logo&.nil? %>
        <%= link_to @post.user_link, class: 'user-se-site-link' do %>
          <% unless @post.site&.site_logo.nil? %>
            <%= image_tag @post.site.site_logo, size: "20" %>
          <% end %>
        <% end %>
      <% end %>
      <% if @post.stack_exchange_user_id.present? %>
          <bdi class="post-owner-username-bdi"><%= link_to @post.username, stack_exchange_user_path(@post.stack_exchange_user_id), class: 'post-username-link' %></bdi>
      <% end %>
      <% unless @post.user_reputation.nil? %>
        (<%= @post.user_reputation %>)
      <% end %>

    <% end %>

<% end %>

Caught by:

  <% @post.reasons.each do |reason| %>

      <%= link_to reason.reason_name, reason_path(reason), title: reason.description, data: { toggle: 'tooltip' } %>
      (<%= reason.weight %>)

  <% end %>

<% if @post.respond_to?(:reason_weight) && @post.reason_weight&.present? %>

Reason weight: <%= @post.reason_weight %>

<% else %>

Reason weight: <%= @post.reasons.map(&:weight).reduce(:+) %>

<% end %>

<% if @post.why.present? %>

<%= render_links @post.why %>

<% end %>

<% if user_signed_in? && current_user.write_authenticated && current_user.flags_enabled && !@post.is_fp && !@post.deleted? && Time.now - (@post.created_at || 1.day.ago) <= 1.hour && current_user.has_role?(:reviewer) %>

    <% %w[spam abusive].each do |flag_type| %>
      <%= link_to url_for(controller: :posts, action: :cast_spam_flag, id: @post.id, flag_type: flag_type), method: :post, class: ("text-danger flagging-link flagging-link-" + flag_type) do %>
         <%= flag_type.capitalize %> flag
      <% end %>
    <% end %>

<% end %>

<% if current_user&.has_role?(:core) %>
  <%= render 'abuse_reports/list', item: @post %>
<% end %>

Contains domains:

<% if @post.spam_domains.any? %>

    <% @post.spam_domains.each do |d| %>

        <%= render 'spam_domains/domain', domain: d, occurances: true, post_id: @post.id %>
        <% if current_user&.has_role?(:core) && !(psd = PostSpamDomain.find_by(post: @post, spam_domain: d)).added_by.nil? %>
          <%= link_to "remove domain", remove_post_domain_path(id: @post.id, domain_id: d.id), class: 'btn-sm btn-danger remove-domain-link', method: :post %>
          <% if current_user&.has_role?(:admin) %>
            (added by <%= psd.added_by.username %>, user_id: <%= psd.added_by.id %>)
          <% end %>
        <% end %>

    <% end %>

<% else %>

No domains

<% end %>

<% if current_user&.has_role?(:core) %>
  <%= form_tag add_post_domain_path(@post), method: :post, class: "add-domain-form" do %>
    <%= hidden_field_tag :post_id, @post.id %>
    <%= text_field_tag :domain_name %>
    <%= submit_tag 'Add Domain', class: 'btn btn-primary btn-sm' %>
  <% end %>
<% end %>

  <% @post.comments.each do |c| %>
    <%= render 'post_comments/comment', comment: c, feedback: @post.feedbacks.to_a.select { |f| f.user_id == c.user_id }[0] %>
  <% end %>

<% if current_user&.has_role?(:reviewer) %>

 Add a comment

<% end %>

  <%= form_for PostComment.new, url: create_comment_path do |f| %>
    <%= f.hidden_field :post_id, value: @post.id %>

      <%= f.text_area :text, rows: 3, cols: 100, placeholder: 'Useful information about this post that others might need...', class: 'form-control' %>

      <%= f.submit 'Add Comment', class: 'btn btn-primary' %>

  <% end %>

<% if user_signed_in? && current_user.has_role?(:developer) %>

Developer tools

<%= link_to "Update feedback cache", url_for(controller: :posts, action: :reindex_feedback, id: @post.id), method: :post, class: 'post-developer-tools-update-feeback-cache-link' %>

<%= link_to "Delete post", dev_delete_post_path(@post.id), method: :post, data: { confirm: "Are you sure you want to delete this post? This can't be undone." }, class: 'post-developer-tools-delete-post-link' %>

<% end %>

<%= render 'flags/create', post: @post %>


text:
    <a href="#post-body-tab-<%= @post.id %>" role="tab" data-toggle="tab" class="post-render-mode" data-render-mode="text">Text

  <% unless @post.markdown.nil? %>

      <a href="#post-source-tab-<%= @post.id %>" role="tab" data-toggle="tab" class="post-render-mode" data-render-mode="markdown">Markdown

  <% end %>

    <a href="#preview-tab-<%= @post.id %>" role="tab" data-toggle="tab" class="post-render-mode" data-render-mode="rendered">Preview

  <div role="tabpanel" class="tab-pane active post-body-panel-text" id="post-body-tab-<%= @post.id %>">

<%= @post.body %>

          <%= @post.reasons.map(&:reason_name).join(", ") %>

  <% unless @post.markdown.nil? %>
    <div role="tabpanel" class="tab-pane post-body-panel-markdown" id="post-source-tab-<%= @post.id %>">

<%= @post.markdown %>

  <% end %>
  <div role="tabpanel" class="tab-pane post-body-panel-preview" id="preview-tab-<%= @post.id %>">


text:
json.array!(@posts) do |post|
  json.extract! post, :id
  json.url post_url(post, format: :json)
end


text:
Disambiguation

    <% @posts.each do |post| %>
      <%= render partial: 'posts/post', locals: { post: post, wrap_in_tr: true } %>
    <% end %>


text: <%= render partial: 'posts/post', collection: posts, cached: proc { |i| i.cachebreak } %>


text:
<% per_user_unreviewed_count ||= nil %>

  <%= render 'review_queues/responses', queue: queue, item: item, exclude_responses: item.reviewable.question? ? [['NAA', 'naa']] : [] %>
  <% @post = item.reviewable %>
  <% @is_review_item = true %>
  <% unless per_user_unreviewed_count.nil? %>

<%= per_user_unreviewed_count %> posts that you haven't reviewed

  <% end %>
  <%= render file: 'posts/show.html.erb' %>


text:
<%= notice %>

<%= title 'Recent posts' %>

  <li class="<%= "active" if params[:filter].nil? %>">
    <%= link_to "All", posts_path %>

  <li class="<%= 'active' if params[:filter] == 'undeleted' %>">
    <%= link_to "Undeleted", posts_path(filter: :undeleted) %>

<%= render 'table', posts: @posts %>

  <%= will_paginate @posts, renderer: BootstrapPagination::Rails %>


text:
Flagger Overview

User

      ID
      Username
      SE A/C ID
      Flags enabled?

      <%= @user.id %>
      <%= @user.username %>
      <%= link_to @user.stack_exchange_account_id, "https://stackexchange.com/users/#{@user.stack_exchange_account_id}" %>
      <%= @user.flags_enabled ? "Yes" : "No" %>

Preferences

    ID
    Site Count
    Flags Used Today

  <% @preferences.each do |pref| %>

        <%= pref.id %>
        <%= pref.sites.count %>
        <%= pref.flags_used %>
        <%= link_to "Edit", url_for(controller: :user_site_settings, action: :edit, id: pref.id) %>
        <%= link_to "Delete", url_for(controller: :user_site_settings, action: :destroy, id: pref.id),
                        method: :delete, data: { confirm: "Are you sure?" }, class: "text-danger" %>

  <% end %>

Conditions

    ID
    Enabled
    Minimum Weight
    Maximum Poster Rep
    Minimum Reason Count
    Sites

    <% @conditions.each do |condition| %>

        <%= condition.id %>
        <td class="text-<%= condition.flags_enabled ? 'success' : 'danger' %>">
          <%= condition.flags_enabled ? 'Enabled' : 'Disabled' %>

        <%= condition.min_weight %>
        <%= condition.max_poster_rep %>
        <%= condition.min_reason_count %>
        <%= condition.sites.count %>
        <%= link_to "Edit", url_for(controller: :flag_conditions, action: :edit, id: condition.id) %>
        <%= link_to "Delete", url_for(controller: :flag_conditions, action: :destroy, id: condition.id),
                        method: :delete, data: { confirm: "Are you sure?" }, class: "text-danger" %>

    <% end %>

<%= link_to 'Validate all conditions', flag_conditions_validate_user_path(user: params[:user]), class: 'btn btn-warning', method: :post %>


text:
<% exclude_save = false if exclude_save.nil? %>

<%= form_for @condition do |f| %>

    <%= f.check_box :flags_enabled %> <%= f.label :flags_enabled %>

    <%= f.label :min_weight, "Minimum Weight" %>

    <%= f.number_field :min_weight, class: "form-control" %>

    <%= f.label :max_poster_rep, "Maximum Poster Reputation" %>

    <%= f.number_field :max_poster_rep, class: "form-control" %>

    <%= f.label :min_reason_count, "Minimum Reason Count" %>

    <%= f.number_field :min_reason_count, class: "form-control" %>

    <%= f.label :sites %>

    <%= f.select :sites, options_for_select(Site.mains.map{ |s| [s.site_name, s.id] }, @condition.site_ids), {}, { multiple: true, class: "form-control selectpicker", 'data-live-search' => true, 'data-actions-box' => true, 'data-dropup-auto' => false, title: "Choose the sites this condition should apply to" } %>

  <% if (@condition.user || current_user).moderator_sites.any? %>

      We won't cast flags on any sites where you're a moderator, regardless of your settings here. That'd be these sites:

        <% (@condition.user || current_user).moderator_sites.each do |ms| %>

<%= ms.site.site_name %>

        <% end %>

  <% end %>

    <%= f.submit "Preview", type: 'button', class: "btn btn-primary preview-flag-conditions-button", name: "preview" %>
    <% unless exclude_save %>
      <%= f.submit "Save", class: "btn btn-success" %>
    <% end %>

<% end %>

  <%= render "preview" %>


text:
Autoflagging: one-click setup

If you don't want to run through setting autoflagging up yourself, you can use this wizard to set it up for you.

When you click the button below, metasmoke will create settings for you with the default values where possible, or
  otherwise reasonable assumptions. That means:

You will have one flag condition set up to 280/1/1, the default setting, with an accuracy of 99.98%.

You will have one preference set up to use 7 of your flags maximum per-site.

Flagging in your name will be enabled.

You can still change these settings manually after they've been created.

Disclaimer

      Warning: standard disclaimers apply. By using this wizard, you are explicitly consenting to
      your Stack Exchange account being used to cast flags automatically based on data collected by SmokeDetector. While we believe this has a high
      rate of accuracy and have designed the system to reflect this, flags cast using your account are your responsibility, and many invalid flags
      can in some cases result in your SE account being suspended. Only use this wizard if you are happy with this responsibility.

<%= link_to "Set me up!", url_for(controller: :flag_conditions, action: :run_ocs), method: :post, class: "btn btn-danger" %>


text:
/* global previewHandler */

$(".flag-condition-preview").html("<%= escape_javascript(render partial: 'preview') %>");
$(".preview-flag-conditions-button").off('click').on('click', previewHandler);


text:
Condition Sandbox

This lets you play with different flag condition settings, to test out what gets flagged. This page is heavy on the
  database - please don't abuse it.

<%= render 'form', exclude_save: true %>

  <%= line_chart af_accuracy_path, library: { series: [{ name: 'All posts', linecap: 'butt' }, { name: 'TPs', linecap: 'butt' },
                                                       { yAxis: 1, name: 'Accuracy', linecap: 'butt' }],
                                              yAxis: [{ gridLineWidth: 1, minorGridLineWidth: 1, minRange: 100, title: { text: 'Post counts' } },
                                                      { ceiling: 100, floor: 90, gridLineWidth: 1, minorGridLineWidth: 1, minRange: 1,
                                                        plotLines: [{ color: '#888', width: 1, zIndex: 5,
                                                                      label: { text: "Min. accuracy (#{FlagSetting['min_accuracy']})",
                                                                               align: 'right', style: { color: '#888' } },
                                                                      value: FlagSetting['min_accuracy'].to_f }], opposite: true,
                                                        title: { text: 'Accuracy' }, min: 90, max: 100, index: 1 }],
                                              xAxis: { gridLineWidth: 1, minorGridLineWidth: 1, minRange: 10 },
                                              chart: { zoomType: 'xy', alignTicks: true }, tooltip: { shared: true }, curveType: 'none' },
                 height: '500px', colors: ['#71C143', '#51A8FA', '#FBE130'] %>


text:
New Flagging Condition

<% if @condition.errors.any? %>

The following <%= pluralize(@condition.errors.count, "error") %> prevented this condition from being saved:

      <% @condition.errors.full_messages.each do |message| %>

<%= message %>

      <% end %>

<% end %>

<%= render partial: "form" %>


text:
Edit Flagging Condition

<% if @condition.errors.any? %>

The following <%= pluralize(@condition.errors.count, "error") %> prevented this condition from being saved:

        <% @condition.errors.full_messages.each do |message| %>

<%= message %>

        <% end %>

<% end %>

<% if @validation_errors.present? %>

This condition doesn't match the current requirements, and is disabled. It may have been automatically disabled. Here's what's wrong:

        <% @validation_errors.full_messages.each do |message| %>

<%= message %>

        <% end %>

<% end %>

<%= render partial: "form" %>


text:
<% if params[:action] == "full_list" %>

All Flagging Conditions

<% else %>

Your Flagging Conditions

These conditions are used to determine whether or not we can use your account to cast an automatic flag. This gives
    you control over what you're comfortable flagging; if you want 99.9999% accuracy, you can ensure that here.

<% end %>

<% if @conditions.count > 0 %>

        ID
        <% if params[:action] == "full_list" %>
          User
        <% end %>
        Enabled
        Minimum Weight
        Maximum Poster Rep
        Minimum Reason Count
        Sites

      <% @conditions.each do |condition| %>

          <%= condition.id %>
          <% if params[:action] == "full_list" %>
            <%= condition.user&.username %>
          <% end %>
          <td class="text-<%= condition.flags_enabled ? 'success' : 'danger' %>">
            <%= condition.flags_enabled ? 'Enabled' : 'Disabled' %>
            <% if params[:action] == 'index' %>
              <%= link_to condition.flags_enabled ? '(disable)' : '(enable)', flag_conditions_enable_path(condition.id), method: :patch %>
            <% end %>

          <%= condition.min_weight %>
          <%= condition.max_poster_rep %>
          <%= condition.min_reason_count %>
          <%= condition.sites.count %>
          <%= link_to "Edit", url_for(controller: :flag_conditions, action: :edit, id: condition.id) %>
          <%= link_to "Delete", url_for(controller: :flag_conditions, action: :destroy, id: condition.id),
                          method: :delete, data: { confirm: "Are you sure?" }, class: "text-danger" %>

      <% end %>

<% else %>

You don't have any flagging conditions at the moment. To get started with autoflagging, create a new condition
    using the link below.

<% end %>

<% unless params[:action] == "full_list" %>
  <% if FlagSetting['registration_enabled'] == '1' %>
    <%= link_to "New condition", url_for(controller: :flag_conditions, action: :new) %>
  <% else %>

Registration for autoflagging is currently closed.

  <% end %>
<% end %>


text:
<% if @true_positive_count.present? and @false_positive_count.present? %>

<%= number_to_percentage(@true_positive_count.to_f * 100.0 / (@true_positive_count + @false_positive_count).to_f, precision: 2) %>

      True positives
      False positives

      <%= @true_positive_count %>
      <%= @false_positive_count %>

Last 100 posts included

        Post

      <% @posts.each do |post| %>
        <%= render "posts/post", post: post %>
      <% end %>

<% end %>


text:
json.repo @repo.to_h
json.compare @compare.to_h
json.compare_diff @compare_diff.encode('utf-8', invalid: :replace, undef: :replace, replace: '?')
json.commit @commit.to_h
json.commit_diff @commit_diff.encode('utf-8', invalid: :replace, undef: :replace, replace: '?')
json.commit_sha CurrentCommit


text:
<%= stylesheet_link_tag \
  "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/styles/github.min.css",
  "https://cdn.jsdelivr.net/gh/rtfpessoa/diff2html@01c0f152/dist/diff2html.min.css"
%>
<%= javascript_include_tag \
  "https://cdn.jsdelivr.net/gh/rtfpessoa/diff2html@01c0f152/dist/diff2html.min.js",
  "https://cdn.jsdelivr.net/gh/rtfpessoa/diff2html@01c0f152/dist/diff2html-ui.min.js",
  "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/highlight.min.js"
%>

Revision <%= CurrentCommit&.first(7) %>

      <%= link_to 'This commit', "https://github.com/Charcoal-SE/metasmoke/commit/#{CurrentCommit}" %>
      is
      … commits ahead, … commits behind
      the
      <%= link_to "...", "", class: "fill-branch" %>
      branch.
      <%= link_to " diff", "#", id: "toggle-compare-diff", class: "diff-toggle" %>
      |
      <%= link_to " commit diff", "#", id: "toggle-commit-diff", class: "diff-toggle" %>
      <% if current_user&.has_role?(:developer) %>
        |
        <%= link_to "Trigger deploy", developer_deploy_path, method: :post, data: { confirm: "Sure you want to deploy master?" }, class: "text-danger" %>
      <% end %>

      Loading commit info…

Versions <%= link_to "Show ", "#", id: "show-all-gem-versions" %>

      Name
      Version

      <%= link_to "Ruby", "https://www.ruby-lang.org/en/" %>
      <%= link_to RUBY_VERSION, "http://ruby-doc.org/core-#{RUBY_VERSION}/", title: "Ruby docs" %>

    <% @gem_versions.each do |g| %>
      <tr class="<% if !@important_gems.include? g.name %>minor hide<% end %>">
        <%= link_to g.name.titleize, "https://rubygems.org/gems/#{g.name}" %>
        <%= link_to g.version, "https://rubygems.org/gems/#{g.name}/versions/#{g.version}" %>

    <% end %>


text:
        <%= render 'abuse_report_statuses/status', status: report.status, nl: true %>
        <%= link_to abuse_report_path(report) do %>
          #<%= report.id %>
        <% end %>

        Reported to
        <%= report.contact.present? ? link_to(report.contact.name, abuse_contact_path(report.contact)) : 'No contact stored' %>
        by
        <%= report.user.present? ? report.user.username : 'User not stored' %>
        <%= time_ago_in_words report.created_at %> ago


text:
<% abuse_reports = item.abuse_reports %>

<% if abuse_reports.count > 0 %>

Abuse Reports:
    <%= raw(abuse_reports.map do |abuse_report| %>
      <% link_to abuse_report do %>
        #<%= abuse_report.id %>
      <% end %>
    <% end.join(', ')) %>
      |
    <%= link_to new_abuse_report_path(reportable_type: item.class.to_s, reportable_id: item.id), class: 'text-muted' do %>
       Create Abuse Report
    <% end %>

<% else %>

<%= link_to new_abuse_report_path(reportable_type: item.class.to_s, reportable_id: item.id) do %>
     Create Abuse Report
  <% end %>

<% end %>


text:
<%= form_for report, url: url do |f| %>

      <%= f.label :reportable_type do %>
         What are you reporting? *
      <% end %>

      <%= f.select :reportable_type,
                   options_for_select([['SpamDomain', 'SpamDomain'], ['Post', 'Post'], ['DomainTag', 'DomainTag']], report.reportable_type),
                   { include_blank: true }, { class: 'form-control' } %>

      <%= f.label :reportable_id, raw(' ') %>

        #
        <%= f.number_field :reportable_id, class: 'form-control' %>

    <%= f.label :abuse_contact_id do %>
       Who are you reporting it to? *
    <% end %>
    Not listed? Create it now.

    <%= f.select :abuse_contact_id, options_for_select(AbuseContact.all.map { |ac| [ac.name, ac.id] }, report.abuse_contact_id || flash[:abuse_contact_id]),
                 { include_blank: true }, { class: 'form-control selectpicker',
                                            data: { live_search: true, actions_box: true, dropup_auto: false } } %>

    <%= f.label :details do %>
       Any more details you want to add?
    <% end %>
    Optional; Markdown supported. If you're sending the report via email you may want to
    include its text here.

    <%= f.text_area :details, rows: 7, cols: 100, class: 'form-control' %>

    <%= f.submit 'Save Report', class: 'btn btn-success' %>

<% end %>

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

New Abuse Contact

        <%= render 'abuse_contacts/form', contact: AbuseContact.new, url: create_abuse_contact_path %>


text:
  <%= render 'abuse_report_statuses/status', status: @report.status, nl: true %>
  #<%= @report.id %>:
  <% if @report.reportable_type == 'SpamDomain' %>
    <%= @report.reportable.domain %>
  <% elsif @report.reportable_type == 'Post' %>
    <%= @report.reportable.title %>
  <% elsif @report.reportable_type == 'DomainTag' %>
    #<%= @report.reportable.name %>
  <% end %>

<% if current_user == @report.user || current_user&.has_role?(:admin) %>

    Edit
    <% if current_user&.has_role?(:admin) %>
      ·
      <%= link_to 'Delete', destroy_abuse_report_path(@report), class: 'text-danger', method: :delete, data: { confirm: 'Are you sure?' } %>
    <% end %>

       Get shareable link

  <%= form_tag update_abuse_report_status_path(@report), class: 'form-inline' do %>
    <%= label_tag :status_id, 'Update report status:' %>
    <%= select_tag :status_id, options_from_collection_for_select(AbuseReportStatus.all, 'id', 'name'), include_blank: true,
                   class: 'form-control input-sm' %>
    <%= submit_tag 'Update', class: 'btn btn-success btn-sm' %>
  <% end %>

<% end %>

  <%= link_to @reportable_path do %>
     Go to reported item
  <% end %>

    Reported to <%= @report.contact.present? ? link_to(@report.contact.name, abuse_contact_path(@report.contact)) : 'No contact stored' %>

    Opened by <%= @report.user.username %> <%= time_ago_in_words @report.created_at %> ago

    <%= safe_render_markdown(@report.details.present? ? @report.details : 'No report details stored', scrubber: Announcement.scrubber) %>

<% @report.comments.each do |c| %>
    <%= render 'abuse_comments/comment', comment: c %>
<% end %>

<% if current_user&.has_role?(:core) %>

 Add a comment

<% end %>

  <%= form_for AbuseComment.new, url: create_abuse_comment_path do |f| %>
    <%= f.hidden_field :abuse_report_id, value: @report.id %>

      <%= f.text_area :text, rows: 3, cols: 100, placeholder: 'Useful information about this report that others might need...',
                      class: 'form-control' %>

      <%= f.submit 'Add Comment', class: 'btn btn-primary' %>

  <% end %>

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

Edit Report

        <%= render 'form', report: @report, url: update_abuse_report_path(@report) %>

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

Public Shareable Link

         Link

        <input id="public-link" class="form-control" type="text" value="<%= shared_abuse_report_url(@report.uuid) %>" />

        <button type="button" class="btn btn-success" data-dismiss="modal">OK</button>


text:
New Abuse Report

<%= render 'form', report: AbuseReport.new(reportable_type: params[:reportable_type], reportable_id: params[:reportable_id]),
           url: create_abuse_report_path %>


text:
Abuse Reports

One giant list of all the abuse reports, ever.

  <li class="<%= 'active' if params[:filter] == 'open' || params[:filter].nil? %>"><%= link_to 'Open', abuse_reports_path(filter: 'open') %>

  <li class="<%= 'active' if params[:filter] == 'stale' %>"><%= link_to 'Stale', abuse_reports_path(filter: 'stale') %>

  <li class="<%= 'active' if params[:filter] == 'closed' %>"><%= link_to 'Closed', abuse_reports_path(filter: 'closed') %>

<% @reports.in_groups_of(3).map(&:compact).each do |g| %>

    <% g.each do |r| %>
      <%= render 'report', report: r %>
    <% end %>

<% end %>

<%= will_paginate @reports, renderer: BootstrapPagination::Rails %>


text:
<% wave ||= nil %>
<% submit_path ||= create_spam_wave_path %>
<% page_title ||= 'New Spam Wave' %>

<%= page_title %>

        <% if @errors.any? %>

            The following errors occurred while trying to create this wave:

              <% @errors.full_messages.each do |m| %>

<%= m %>

              <% end %>

        <% end %>

        <%= form_tag submit_path, method: :post do %>

Details

          <div class="field form-group <%= 'has-error' if error?(:name) %>">
            <%= label_tag :name %>

            <%= text_field_tag :name, default(:name, wave, nil), class: 'form-control', autocomplete: 'off' %>
            <%= help_or_error(:name, "Something to describe very briefly what the spam wave is.") %>

          <div class="field form-group <%= 'has-error' if error?(:max_flags) %>">
            <%= label_tag :max_flags %>

            <%= number_field_tag :max_flags, default(:max_flags, wave, FlagSetting['max_flags']), class: 'form-control' %>

              <%= help_or_error(:max_flags) do %>
                How many flags should be applied to matching posts?
                Overrides default autoflagging max_flags.
              <% end %>

          <div class="field form-group <%= 'has-error' if error?(:expiry) %>">
            <%= label_tag :expiry %>

            <%= datetime_field_tag :expiry, default(:expiry, wave, 24.hours.from_now)&.to_datetime&.iso8601[0..-2], class: 'form-control' %>

              <%= help_or_error(:expiry, "A point after which this wave will be deactivated. Maximum 48 hours from now. Default 24 hours from now.") %>

Sites

            <% h = HTMLEntities.new %>
            <%= label_tag :sites %>

            <%= select_tag :sites, options_for_select(Site.select(:site_name, :id).all.order(:site_name).map{ |s| [h.decode(s.site_name), s.id] }, selected: wave&.sites&.map(&:id)),
                           multiple: true, class: 'form-control selectpicker', 'data-live-search' => true, 'data-actions-box' => true,
                           'data-dropup-auto' => false %>
            Choose the sites this wave should apply to.

Conditions

            <%= label_tag 'conditions[title_regex]', 'Title regex' %>

            <%= text_field_tag 'conditions[title_regex]', default('conditions[title_regex]', wave, '.*'), class: 'form-control' %>
            Posts must have titles that match this regex to be flagged.

            <%= label_tag 'conditions[body_regex]', 'Body regex' %>

            <%= text_field_tag 'conditions[body_regex]', default('conditions[body_regex]', wave, '.*'), class: 'form-control' %>
            Posts must have bodies that match this regex to be flagged.

            <%= label_tag 'conditions[username_regex]', 'Username regex' %>

            <%= text_field_tag 'conditions[username_regex]', default('conditions[username_regex]', wave, '.*'), class: 'form-control' %>
            Post authors must have usernames that match this regex for the post to be flagged.

            <%= label_tag 'conditions[max_user_rep]', 'Max user rep' %>

            <%= number_field_tag 'conditions[max_user_rep]', default('conditions[max_user_rep]', wave, 1), class: 'form-control' %>
            Post authors must have less reputation than this value for the post to be flagged.

            <button type="button" class="btn btn-success wave-preview">Preview</button>
            <%= submit_tag 'Submit', class: 'btn btn-primary' %>

        <% end %>

Preview

Click Preview to view the posts caught by your current settings.


text:
<%= @wave.name %>

Currently <%= @wave.expiry.past? ? 'expired' : 'active' %>.

Created by <%= @wave.user.username %> <span title="<%= @wave.created_at %>"><%= time_ago_in_words(@wave.created_at) %> ago.

<% if @wave.expiry.past? %>

Expired <span title="<%= @wave.expiry %>"><%= distance_of_time_in_words(DateTime.now, @wave.expiry) %> ago.

<% else %>

Expires in <span title="<%= @wave.expiry %>"><%= distance_of_time_in_words(DateTime.now, @wave.expiry) %>.

<% end %>

<%= link_to 'Edit', edit_spam_wave_path(@wave), class: 'btn btn-primary' %>
<%= link_to 'Renew Wave', renew_spam_wave_path(@wave), class: 'btn btn-warning', method: :post %>
<% unless @wave.expiry.past? %>
  <%= link_to 'Cancel Wave', cancel_spam_wave_path(@wave), class: 'btn btn-danger', method: :post %>
<% end %>

Conditions

{
  "title_regex": "<%= escape_javascript(@wave.conditions['title_regex']) %>",
  "body_regex": "<%= escape_javascript(@wave.conditions['body_regex']) %>",
  "username_regex": "<%= escape_javascript(@wave.conditions['username_regex']) %>",
  "max_user_rep": <%= escape_javascript(@wave.conditions['max_user_rep']) %>
}


text:
<div class="spam-wave" data-id="<%= wave.id %>">

<%= link_to wave.name, spam_wave_path(wave) %>

Created by <%= wave.user.username %> <span title="<%= wave.created_at %>"><%= time_ago_in_words(wave.created_at) %> ago.

  <% if wave.expiry.past? %>
    <p title="<%= wave.expiry %>">Expired.

  <% else %>

Expires in <span title="<%= wave.expiry %>"><%= distance_of_time_in_words(DateTime.now, wave.expiry) %>.

  <% end %>

    <%= link_to 'Edit', edit_spam_wave_path(wave), class: 'btn btn-primary' %>
    <%= link_to 'Renew Wave', renew_spam_wave_path(wave), class: 'btn btn-warning', method: :post %>
    <% unless wave.expiry.past? %>
      <%= link_to 'Cancel Wave', cancel_spam_wave_path(wave), class: 'btn btn-danger', method: :post %>
    <% end %>


text:
Spam waves

Spam waves are a way to make it easy for us to respond to sudden influxes of a certain type of spam. By adding a wave here, everything matching
the conditions specified will be autoflagged for up to 48 hours (default 24 hours). Make sure you communicate what's being done to site mods or CM's.

  <%= link_to new_spam_wave_path, class: 'btn btn-primary btn-sm' do %>
     Create New
  <% end %>

Active waves

<% @active.each do |w| %>
  <%= render 'spam_wave', wave: w %>
<% end %>
<% if @active.count == 0 %>
  None right now.
<% end %>

  <%= will_paginate @active, renderer: BootstrapPagination::Rails %>

Expired waves

<% @expired.each do |w| %>
  <%= render 'spam_wave', wave: w %>
<% end %>
<% if @expired.count == 0 %>
  No waves expired yet.
<% end %>

  <%= will_paginate @expired, renderer: BootstrapPagination::Rails %>


text:
<%= @accuracy %>%

<% if @posts.count == 0 %>
  No posts caught.
<% else %>

    <% @posts.each do |p| %>
      <%= render 'posts/post', post: p, wrap_in_tr: true %>
    <% end %>

<% end %>


text:
Email Preference Search

  As an admin, you are able to control email preferences for other people.
  This is a significant responsibility, do not abuse it.
  You are able to select a user by their addressee name, or you are able to search for users by their email address.
  You are deliberately not able to view email addresses for all addressees.

Select by name

    <%= form_tag email_preferences_list_path, method: :get do %>
      <%= select_tag :addressee, options_from_collection_for_select(@addressees, :id, :name), class: 'form-control selectpicker', include_blank: true %>

      <%= submit_tag 'Show', class: 'btn btn-primary' %>
    <% end %>

or

Search by email address

    <%= form_tag email_preferences_list_path, method: :get do %>
      <%= text_field_tag :email, nil, class: 'form-control', placeholder: 'someone@example.com' %>

      <%= submit_tag 'Show', class: 'btn btn-primary' %>
    <% end %>


text:
Email Preferences

  You can control the emails you receive on this page, including turning on and off any type of email, and changing the frequency at which
  we send you emails.

<% @preferences.each do |type_id, preferences| %>
  <% type = @types.select { |et| et.id == type_id }[0] %>

<%= type.name %>

<%= type.description %>

  <% preferences.each do |ep| %>
    <%= render 'preference', preference: ep %>
  <% end %>
<% end %>


text:
  <%= preference.reference_type.underscore.humanize %>: <%= preference.reference.preference_ref_name %>

    OFF

      <input type="checkbox" class="js-preference-toggle" <%= preference.enabled? ? 'checked' : '' %> data-pref-id="<%= preference.id %>" />

    ON

  <a href="#" class="js-preference-delete" data-pref-id="<%= preference.id %>" title="Delete">

<form class="form-inline">
  Sent every
  <input type="number" value="<%= preference.frequency %>" class="form-control input-sm js-frequency" data-pref-id="<%= preference.id %>" />
  days.

  <button type="button" class="btn btn-sm btn-primary js-preference-frequency" data-pref-id="<%= preference.id %>">Save</button>
</form>


text:
Channels: Join link

Once you've entered your channel-verify email address into the Channel's join page, Stack Overflow
  will send it a verification email. That email will be picked up by metasmoke, and the link from it will show up here.

<% if @channels_user.link.present? %>

<%= link_to 'Join Channel', @channels_user.link %>

<% else %>

We haven't received the email yet. Check back in a few minutes.

<% end %>


text:
Channels: Email address

The following is your email address to use with Channels. Copy and paste it into the box at
  stackoverflowteams.com/c/charcoal/join.

<input type="text" class="form-control" value="<%= @secret %>@channel-verify.charcoal-se.org" />

<%= link_to 'Okay, done it', channels_link_path, class: 'btn btn-success' %>


text:
<%= form_for @group, url: url do |f| %>

    <%= f.label :name %>
    <%= f.text_field :name, class: 'form-control' %>

    <%= f.label :regex %>
    <%= f.text_field :regex, class: 'form-control' %>

  <%= f.submit 'Submit', class: 'btn btn-primary' %>
<% end %>


text:
<%= link_to domain_groups_path do %>
  « Back to domain groups
<% end %>

Domain Group: <%= @group.name %>

Defined by <%= @group.regex %>

  <%= link_to 'Edit', edit_domain_group_path(@group) %> ·
  <%= link_to 'Delete', destroy_domain_group_path(@group), class: 'text-danger', method: :delete, data: { confirm: 'Are you sure?' } %>

<% if current_user&.has_role?(:admin) %>
   Create email subscription
<% end %>

Matched Domains

<% @domains.each do |sd| %>

<%= render 'spam_domains/domain', domain: sd %>

<% end %>

<%= will_paginate @domains, renderer: BootstrapPagination::Rails %>

<% if current_user&.has_role?(:admin) %>

          <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

Manage emails

          <%= form_tag domain_group_emails_path(@group) do %>

              <%= label_tag :addressee_name %>
              <%= text_field_tag :addressee_name, params[:addressee_name], class: 'form-control', required: true %>

              <%= label_tag :addressee_email %>
              <%= email_field_tag :addressee_email, params[:addressee_email], class: 'form-control', required: true %>

              <%= label_tag :frequency %>
              <%= number_field_tag :frequency, params[:frequency], class: 'form-control', required: true %>
              How often should we send emails, in days?

              <%= label_tag :consent_comment %>
              <%= text_area_tag :consent_comment, params[:consent_comment], rows: 2, class: 'form-control', required: true %>
              How did you obtain this person's consent to be sent emails?

            <%= submit_tag 'Submit', class: 'btn btn-primary' %>
          <% end %>

<% end %>


text:
New Domain Group

You can define a new group here. Try to use start and end anchors in your regex where possible (^ and $).

<%= render 'form', url: create_domain_group_path %>


text:
Edit Domain Group

  You can change the details of a domain group here. Keep in mind that domains that are already associated with this group will remain so -
  changing the regex will not remove previously matched domains.

<%= render 'form', url: update_domain_group_path(@group) %>


text:
Domain Groups

  These are groups of related domains, as defined by a regex for each group. Use them to group things like domains on the same host
  (think things like *.000webhost.com).

<%= link_to 'Create new group', new_domain_group_path %>

      ID
      Group Name
      Regex
      Domain count

    <% @groups.each do |dg| %>

        <td class="text-muted" data-sort-value="<%= dg.id %>"><%= dg.id %>
        <%= link_to dg.name, domain_group_path(dg) %>
        <%= dg.regex %>
        <td data-sort-value="<%= dg.domain_count %>"><%= dg.domain_count %>
        <%= link_to 'Edit', edit_domain_group_path(dg) %>
        <%= link_to 'Delete', destroy_domain_group_path(dg), class: 'text-danger', method: :delete, data: { confirm: 'Are you sure?' } %>

    <% end %>

<%= will_paginate @groups, renderer: BootstrapPagination::Rails %>


text:
Invalid API Key

An API application attempted to process write authorization for your metasmoke account, but has provided an unrecognized
  request key. The authorization cannot be completed. Please contact the app's developer to tell them that their request key
  is incorrect.


text:
API Access Request

The app <%= @api_key.app_name %> is requesting permission to perform write operations on metasmoke on your behalf.

Granting this permission will enable the app to perform actions such as creating feedback in your name. It will not have to ask for your
  confirmation to do this.

Do you trust this app?

<%= link_to "Yes, grant permission", oauth_authorize_path(key: @api_key.key, redirect: params[:redirect]),
            method: :post, class: "btn btn-success" %>
<%= link_to "No, deny permission", oauth_reject_path(key: @api_key.key),
            class: "btn btn-danger" %>


text:
Rejected API Application

You have denied permission for the app <%= @api_key.app_name %> to perform write operations on
  metasmoke on your behalf.

If you did not intend to do this, go back a page and grant the permission.


text:
Authorized API Application

You have authorized the app <%= @token.api_key.app_name %> to perform write actions on metasmoke on your behalf.

If you did not intend to do this, contact a metasmoke admin.

The code you may need to provide to the app is <%= @token.code %>.


text:
<% post ||= nil %>
<div class="label label-info tag-label" data-toggle="tooltip" title="<%= tag.description %>">
  <%= link_to domain_tag_path(tag), class: 'domain-tag' do %>
    #<%= tag.name %>
  <% end %>
  <% unless post.nil? %>
    <%= form_tag remove_post_tag_path, method: :post do %>
      <%= hidden_field_tag :post_id, post.id %>
      <%= hidden_field_tag :tag_name, tag.name %>
      ×
    <% end %>
  <% end %>


text:
<% domain ||= nil %>
<div class="label label-<%= tag.special? ? 'warning' : 'info' %> tag-label" data-toggle="tooltip" title="<%= tag.description %>">
  <%= link_to domain_tag_path(tag), class: 'domain-tag' do %>
    #<%= tag.name %>
  <% end %>
  <% if domain.present? && !tag.special %>
    <%= form_tag remove_domain_tag_path, method: :post do %>
      <%= hidden_field_tag :domain_id, domain.id %>
      <%= hidden_field_tag :tag_name, tag.name %>
      ×
    <% end %>
  <% end %>


text:
Tag: <%= render 'tag', tag: @tag %>

<% if @counts_summary %>
  <%= @counts_summary[:all] %>
  (<%= @counts_summary[:tp] %>,
  <%= @counts_summary[:fp] %>,
  <%= @counts_summary[:naa] %>)
<% end %>
<% if @tag.description.present? %>

<%= @tag.description %>

<% else %>

No description.

<% end %>
<% if user_signed_in? && (current_user.has_role?(:core) || current_user.has_role?(:admin)) %>

    <% if current_user.has_role?(:core) %>
      <%= link_to 'Edit', edit_domain_tag_path(@tag) %>
    <% end %>
    <% if current_user.has_role?(:admin) %>
      · <%= link_to 'Delete', destroy_domain_tag_path(@tag), method: :delete,
                    data: { confirm: 'Are you sure?' }, class: 'text-danger' %>
    <% end %>

  <%= render 'abuse_reports/list', item: @tag %>
<% end %>

  <li class="<%= 'active' if params[:what] == 'domains' || params[:what].nil? %>"><%= link_to 'Domains', domain_tag_path(@tag, what: 'domains') %>

  <li class="<%= 'active' if params[:what] == 'posts' %>"><%= link_to 'Posts', domain_tag_path(@tag, what: 'posts') %>

<% if params[:what] == 'domains' || params[:what].nil? %>

      Domain
      Other Tags
      Occurrences

      <% @domains.each do |d| %>

          <%= d.domain %>

            <% (d.domain_tags - [@tag]).each do |t| %>
              <%= render 'tag', tag: t %>
            <% end %>

            <%= @counts[d.id] || 0 %>
            (<%= @counts_per_domain[:tp][d.id] || 0 %>,
            <%= @counts_per_domain[:fp][d.id] || 0 %>,
            <%= @counts_per_domain[:naa][d.id] || 0 %>)

          <%= link_to 'Details', spam_domain_path(d) %>
          <% if user_signed_in? && current_user.has_role?(:core) %>
            <%= link_to 'Edit', edit_spam_domain_path(d) %>
          <% end %>
          <% if user_signed_in? && current_user.has_role?(:admin) %>
            <%= link_to 'Delete', destroy_spam_domain_path(d), method: :delete, class: 'text-danger',
                            data: { confirm: 'Are you sure?' } %>
          <% end %>

      <% end %>

  <%= will_paginate @domains, renderer: BootstrapPagination::Rails %>
<% elsif params[:what] == 'posts' %>

      <% @posts.each do |p| %>
        <%= render 'posts/post', post: p, wrap_in_tr: true %>
      <% end %>

  <%= will_paginate @posts, renderer: BootstrapPagination::Rails %>
<% end %>

<% if current_user&.has_role?(:developer) %>

Developer tools

      <%= form_tag merge_tags_path, method: :post, class: 'form-inline' do %>
        <%= hidden_field_tag :source_id, @tag.id %>
        <%= label_tag :target_id, 'Merge this tag with:' %>
        <%= select_tag :target_id, options_for_select(DomainTag.all.map { |t| [t.name, t.id, { 'data-subtext' => t.id }] }),
                       class: 'form-control input-sm selectpicker', include_blank: true %>
        <%= submit_tag 'Merge', class: 'btn btn-sm btn-danger' %>
      <% end %>

<% end %>


text:
Editing Domain Tag: <%= render 'tag', tag: @tag %>

<%= form_for @tag, url: update_domain_tag_path do |f| %>

    <%= f.label :name %>

    <%= f.text_field :name, class: 'form-control' %>

    <%= f.label :description %>

    <%= f.text_area :description, rows: 5, cols: 70, class: 'form-control' %>

    <%= f.submit 'Save', class: 'btn btn-primary' %>

<% end %>