forked from e621ng/e621ng
[Staff Notes] Add staff notes
This commit is contained in:
parent
2c9e2511f7
commit
b3eb88405d
35
app/controllers/admin/staff_notes_controller.rb
Normal file
35
app/controllers/admin/staff_notes_controller.rb
Normal file
@ -0,0 +1,35 @@
|
||||
module Admin
|
||||
class StaffNotesController < ApplicationController
|
||||
before_action :moderator_only
|
||||
respond_to :html
|
||||
|
||||
def index
|
||||
@user = User.where('id = ?', params[:user_id]).first
|
||||
@notes = StaffNote.search(search_params).paginate(params[:page])
|
||||
respond_with(@notes)
|
||||
end
|
||||
|
||||
def new
|
||||
@user = User.find(params[:user_id])
|
||||
@staff_note = StaffNote.new(note_params)
|
||||
respond_with(@note)
|
||||
end
|
||||
|
||||
def create
|
||||
@user = User.find(params[:user_id])
|
||||
@staff_note = StaffNote.create(note_params.merge({creator: CurrentUser.user, user_id: @user.id}))
|
||||
flash[:notice] = @staff_note.valid? ? "Staff Note added" : @staff_note.errors.full_messages.join("; ")
|
||||
respond_with(@staff_note) do |format|
|
||||
format.html do
|
||||
redirect_back fallback_location: admin_staff_notes_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def note_params
|
||||
params.fetch(:staff_note, {}).permit([:body])
|
||||
end
|
||||
end
|
||||
end
|
7
app/models/staff_audit_log.rb
Normal file
7
app/models/staff_audit_log.rb
Normal file
@ -0,0 +1,7 @@
|
||||
class StaffAuditLog < ApplicationRecord
|
||||
belongs_to :user, :class_name => "User"
|
||||
|
||||
def self.log(category, user, details)
|
||||
create(user: user, action: category.to_s, values: details)
|
||||
end
|
||||
end
|
62
app/models/staff_note.rb
Normal file
62
app/models/staff_note.rb
Normal file
@ -0,0 +1,62 @@
|
||||
class StaffNote < ApplicationRecord
|
||||
belongs_to :creator, :class_name => "User"
|
||||
belongs_to :user
|
||||
|
||||
after_create :add_audit_entry
|
||||
|
||||
module SearchMethods
|
||||
def for_creator(user_id)
|
||||
user_id.present? ? where("creator_id = ?", user_id) : none
|
||||
end
|
||||
|
||||
def for_creator_name(user_name)
|
||||
for_creator(User.name_to_id(user_name))
|
||||
end
|
||||
|
||||
def for_user(user_id)
|
||||
user_id.present? ? where('creator_id = ?', user_id) : none
|
||||
end
|
||||
|
||||
def for_user_name(user_name)
|
||||
for_user(User.name_to_id(user_name))
|
||||
end
|
||||
|
||||
def search(params)
|
||||
q = super
|
||||
|
||||
if params[:resolved]
|
||||
q = q.attribute_matches(:resolved, params[:resolved])
|
||||
end
|
||||
|
||||
if params[:user_name].present?
|
||||
q = q.for_user_name(params[:user_name])
|
||||
end
|
||||
|
||||
if params[:creator_name].present?
|
||||
q = q.for_creator_name(params[:creator_name])
|
||||
end
|
||||
q.apply_default_order(params)
|
||||
end
|
||||
|
||||
def default_order
|
||||
order("resolved asc, id desc")
|
||||
end
|
||||
end
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
|
||||
def add_audit_entry
|
||||
StaffAuditLog.log(:staff_note_add, creator, {user_id: user_id})
|
||||
end
|
||||
|
||||
def resolve!
|
||||
self.resolved = true
|
||||
save
|
||||
end
|
||||
|
||||
def unresolve!
|
||||
self.resolved = false
|
||||
save
|
||||
end
|
||||
end
|
@ -183,4 +183,16 @@ class UserPresenter
|
||||
return false if user.enable_privacy_mode? && !CurrentUser.is_admin?
|
||||
true
|
||||
end
|
||||
|
||||
def show_staff_notes?
|
||||
CurrentUser.is_moderator?
|
||||
end
|
||||
|
||||
def staff_notes
|
||||
StaffNote.where(user_id: user.id).order(id: :desc).limit(15)
|
||||
end
|
||||
|
||||
def new_staff_note
|
||||
StaffNote.new(user_id: user.id)
|
||||
end
|
||||
end
|
||||
|
13
app/views/admin/staff_notes/_search.html.erb
Normal file
13
app/views/admin/staff_notes/_search.html.erb
Normal file
@ -0,0 +1,13 @@
|
||||
<div id='searchform_hide'>
|
||||
<%= search_show_link %>
|
||||
</div>
|
||||
<div class='section' id='searchform' style='width:400px;<% unless params[:show] %>display:none;
|
||||
<% end %>'>
|
||||
<%= simple_form_for(:search, :method => :get, url: admin_staff_notes_path, defaults: {required: false}, html: {class: "inline-form"}) do |f| %>
|
||||
<%= f.input :creator_name, label: "Creator Name", input_html: {data: {autocomplete: "user"}} %>
|
||||
<%= f.input :user_name, label: "User Name", input_html: {data: {autocomplete: "user"}} %>
|
||||
<%= f.input :body_matches, label: "Body" %>
|
||||
<%= f.submit "Search" %>
|
||||
<% end %>
|
||||
<%= search_hide_link %>
|
||||
</div>
|
15
app/views/admin/staff_notes/index.html.erb
Normal file
15
app/views/admin/staff_notes/index.html.erb
Normal file
@ -0,0 +1,15 @@
|
||||
<div id="c-staff-notes">
|
||||
<div id="a-index">
|
||||
<h1><%= @user ? "Staff Notes for #{@user.name}" : "Staff Notes" %></h1>
|
||||
<%= render "search" %>
|
||||
|
||||
<%= render "admin/staff_notes/partials/list_of_notes", staff_notes: @notes %>
|
||||
<%= numbered_paginator(@notes) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "users/secondary_links" %>
|
||||
|
||||
<% content_for(:page_title) do %>
|
||||
<%= @user ? "#{@user.name} - Staff Notes" : "Staff Notes" %>
|
||||
<% end %>
|
13
app/views/admin/staff_notes/new.html.erb
Normal file
13
app/views/admin/staff_notes/new.html.erb
Normal file
@ -0,0 +1,13 @@
|
||||
<div id="c-staff-notes">
|
||||
<div id="a-new">
|
||||
<h1>New Staff Note for <%= link_to_user(@user) %></h1>
|
||||
|
||||
<%= render "admin/staff_notes/partials/new", staff_note: @staff_note, user: @user %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "users/secondary_links" %>
|
||||
|
||||
<% content_for(:page_title) do %>
|
||||
New Staff Note
|
||||
<% end %>
|
@ -0,0 +1,3 @@
|
||||
<div id="p-staff-notes-list" class="staff-note-list">
|
||||
<%= render :partial => "admin/staff_notes/partials/staff_note", :collection => staff_notes %>
|
||||
</div>
|
7
app/views/admin/staff_notes/partials/_new.html.erb
Normal file
7
app/views/admin/staff_notes/partials/_new.html.erb
Normal file
@ -0,0 +1,7 @@
|
||||
<%= error_messages_for :staff_note %>
|
||||
|
||||
<%= simple_form_for(staff_note, url: user_staff_notes_path(user_id: user.id), method: :post) do |f| %>
|
||||
<%= dtext_field "staff_note", "body", name: "", :value => staff_note.body, :input_id => "staff_note_body_for_#{staff_note.id}", :preview_id => "dtext-preview-for-#{staff_note.id}" %>
|
||||
<%= f.button :submit, "Submit" %>
|
||||
<%= dtext_preview_button "staff_note", "body", :input_id => "staff_note_body_for_#{staff_note.id}", :preview_id => "dtext-preview-for-#{staff_note.id}" %>
|
||||
<% end %>
|
19
app/views/admin/staff_notes/partials/_staff_note.html.erb
Normal file
19
app/views/admin/staff_notes/partials/_staff_note.html.erb
Normal file
@ -0,0 +1,19 @@
|
||||
<article class="staff-note comment-post-grid" id="staff-note-<%= staff_note.id %>">
|
||||
<div class="author-info">
|
||||
<div class="name-rank">
|
||||
<h4 class="author-name"><%= link_to_user staff_note.creator %></h4>
|
||||
<%= staff_note.creator.level_string %>
|
||||
</div>
|
||||
<div class="avatar">
|
||||
<%= user_avatar(staff_note.creator) %>
|
||||
</div>
|
||||
<div class="post-time">
|
||||
<%= link_to time_ago_in_words_tagged(staff_note.created_at), user_staff_notes_path(user_id: staff_note.user_id, anchor: "staff-note-#{staff_note.id}") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="body styled-dtext">
|
||||
<%= format_text(staff_note.body, allow_color: true) %>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
@ -3,14 +3,31 @@
|
||||
<div class="profile-container">
|
||||
<%= render "statistics", :presenter => @presenter, :user => @user %>
|
||||
|
||||
<% if @presenter.show_staff_notes? %>
|
||||
<div class="styled-dtext">
|
||||
<div class="expandable">
|
||||
<div class="expandable-header">
|
||||
<span class="section-arrow"></span>
|
||||
<span>Staff Notes (<%= @presenter.staff_notes.count %>)</span>
|
||||
</div>
|
||||
<div class="expandable-content">
|
||||
<h4><%= link_to "Staff Notes", user_staff_notes_path(user_id: @user.id) %></h4>
|
||||
<%= render "admin/staff_notes/partials/list_of_notes", staff_notes: @presenter.staff_notes %>
|
||||
<h4>New Staff Note</h4>
|
||||
<%= render "admin/staff_notes/partials/new", staff_note: @presenter.new_staff_note, user: @user %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="bottom-section">
|
||||
<div class="posts-section">
|
||||
<% if @presenter.can_view_favorites? %>
|
||||
<div class="blacklist">
|
||||
<%= render "posts/partials/common/inline_blacklist" %>
|
||||
<%= render "posts/partials/common/inline_blacklist" %>
|
||||
</div>
|
||||
<div class="posts">
|
||||
<%= render "post_summary", :presenter => @presenter, :user => @user %>
|
||||
<%= render "post_summary", :presenter => @presenter, :user => @user %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
@ -21,6 +21,7 @@ Rails.application.routes.draw do
|
||||
resource :dashboard, :only => [:show]
|
||||
resources :exceptions, only: [:index, :show]
|
||||
resource :reowner, controller: 'reowner', only: [:new, :create]
|
||||
resources :staff_notes, only: [:index]
|
||||
end
|
||||
resources :edit_histories
|
||||
namespace :moderator do
|
||||
@ -336,6 +337,7 @@ Rails.application.routes.draw do
|
||||
resource :api_key, :only => [:show, :view, :update, :destroy], :controller => "maintenance/user/api_keys" do
|
||||
post :view
|
||||
end
|
||||
resources :staff_notes, only: [:index, :new, :create], controller: "admin/staff_notes"
|
||||
|
||||
collection do
|
||||
get :home
|
||||
|
11
db/migrate/20210426025625_add_staff_notes_table.rb
Normal file
11
db/migrate/20210426025625_add_staff_notes_table.rb
Normal file
@ -0,0 +1,11 @@
|
||||
class AddStaffNotesTable < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
create_table :staff_notes do |t|
|
||||
t.timestamps
|
||||
t.references :user, null: false, foreign_key: true, index: true
|
||||
t.integer :creator_id, null: false, index: true
|
||||
t.string :body
|
||||
t.boolean :resolved, null: false, default: false
|
||||
end
|
||||
end
|
||||
end
|
10
db/migrate/20210506235640_add_staff_audit_logs_table.rb
Normal file
10
db/migrate/20210506235640_add_staff_audit_logs_table.rb
Normal file
@ -0,0 +1,10 @@
|
||||
class AddStaffAuditLogsTable < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
create_table :staff_audit_logs do |t|
|
||||
t.timestamps
|
||||
t.references :user, null: false, foreign_key: true, index: true
|
||||
t.string :action, null: false, default: 'unknown_action'
|
||||
t.json :values
|
||||
end
|
||||
end
|
||||
end
|
138
db/structure.sql
138
db/structure.sql
@ -2022,6 +2022,73 @@ CREATE TABLE public.schema_migrations (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_audit_logs; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.staff_audit_logs (
|
||||
id bigint NOT NULL,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
action character varying DEFAULT 'unknown_action'::character varying NOT NULL,
|
||||
"values" json
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_audit_logs_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.staff_audit_logs_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_audit_logs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.staff_audit_logs_id_seq OWNED BY public.staff_audit_logs.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_notes; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.staff_notes (
|
||||
id bigint NOT NULL,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
creator_id integer NOT NULL,
|
||||
body character varying,
|
||||
resolved boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_notes_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.staff_notes_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_notes_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.staff_notes_id_seq OWNED BY public.staff_notes.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: tag_aliases; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@ -3025,6 +3092,20 @@ ALTER TABLE ONLY public.posts ALTER COLUMN change_seq SET DEFAULT nextval('publi
|
||||
ALTER TABLE ONLY public.saved_searches ALTER COLUMN id SET DEFAULT nextval('public.saved_searches_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_audit_logs id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.staff_audit_logs ALTER COLUMN id SET DEFAULT nextval('public.staff_audit_logs_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_notes id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.staff_notes ALTER COLUMN id SET DEFAULT nextval('public.staff_notes_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: tag_aliases id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@ -3547,6 +3628,22 @@ ALTER TABLE ONLY public.schema_migrations
|
||||
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_audit_logs staff_audit_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.staff_audit_logs
|
||||
ADD CONSTRAINT staff_audit_logs_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_notes staff_notes_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.staff_notes
|
||||
ADD CONSTRAINT staff_notes_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: tag_aliases tag_aliases_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@ -4522,6 +4619,27 @@ CREATE INDEX index_saved_searches_on_query ON public.saved_searches USING btree
|
||||
CREATE INDEX index_saved_searches_on_user_id ON public.saved_searches USING btree (user_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_staff_audit_logs_on_user_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_staff_audit_logs_on_user_id ON public.staff_audit_logs USING btree (user_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_staff_notes_on_creator_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_staff_notes_on_creator_id ON public.staff_notes USING btree (creator_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_staff_notes_on_user_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_staff_notes_on_user_id ON public.staff_notes USING btree (user_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_tag_aliases_on_antecedent_name; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@ -4865,6 +4983,14 @@ CREATE TRIGGER trigger_posts_on_tag_index_update BEFORE INSERT OR UPDATE ON publ
|
||||
CREATE TRIGGER trigger_wiki_pages_on_update BEFORE INSERT OR UPDATE ON public.wiki_pages FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('body_index', 'public.danbooru', 'body', 'title');
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_audit_logs fk_rails_02329e5ef9; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.staff_audit_logs
|
||||
ADD CONSTRAINT fk_rails_02329e5ef9 FOREIGN KEY (user_id) REFERENCES public.users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: post_image_hashes fk_rails_2b7afcc2f0; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@ -4881,6 +5007,14 @@ ALTER TABLE ONLY public.favorites
|
||||
ADD CONSTRAINT fk_rails_a7668ef613 FOREIGN KEY (user_id) REFERENCES public.users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: staff_notes fk_rails_bab7e2d92a; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.staff_notes
|
||||
ADD CONSTRAINT fk_rails_bab7e2d92a FOREIGN KEY (user_id) REFERENCES public.users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: favorites fk_rails_d20e53bb68; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@ -5128,6 +5262,8 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20210117173030'),
|
||||
('20210405040522'),
|
||||
('20210425020131'),
|
||||
('20210430201028');
|
||||
('20210426025625'),
|
||||
('20210430201028'),
|
||||
('20210506235640');
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user