DEV: Introduce syntax_tree for ruby formatting (#70)

This commit is contained in:
David Taylor 2022-12-29 12:35:49 +00:00 committed by GitHub
parent e9ad98f65f
commit 2a524624df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 122 additions and 105 deletions

View File

@ -55,3 +55,12 @@ jobs:
- name: Rubocop - name: Rubocop
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
run: bundle exec rubocop . run: bundle exec rubocop .
- name: Syntax Tree
if: ${{ !cancelled() }}
run: |
if test -f .streerc; then
bundle exec stree check Gemfile $(git ls-files '*.rb') $(git ls-files '*.rake')
else
echo "Stree config not detected for this repository. Skipping."
fi

View File

@ -80,7 +80,7 @@ jobs:
- name: Get yarn cache directory - name: Get yarn cache directory
id: yarn-cache-dir id: yarn-cache-dir
run: echo "::set-output name=dir::$(yarn cache dir)" run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
- name: Yarn cache - name: Yarn cache
uses: actions/cache@v3 uses: actions/cache@v3
@ -130,7 +130,7 @@ jobs:
shell: bash shell: bash
run: | run: |
if [ 0 -lt $(find plugins/${{ github.event.repository.name }}/spec -type f -name "*.rb" 2> /dev/null | wc -l) ]; then if [ 0 -lt $(find plugins/${{ github.event.repository.name }}/spec -type f -name "*.rb" 2> /dev/null | wc -l) ]; then
echo "::set-output name=files_exist::true" echo "files_exist=true" >> $GITHUB_OUTPUT
fi fi
- name: Plugin RSpec - name: Plugin RSpec
@ -142,7 +142,7 @@ jobs:
shell: bash shell: bash
run: | run: |
if [ 0 -lt $(find plugins/${{ github.event.repository.name }}/test/javascripts -type f \( -name "*.js" -or -name "*.es6" \) 2> /dev/null | wc -l) ]; then if [ 0 -lt $(find plugins/${{ github.event.repository.name }}/test/javascripts -type f \( -name "*.js" -or -name "*.es6" \) 2> /dev/null | wc -l) ]; then
echo "::set-output name=files_exist::true" echo "files_exist=true" >> $GITHUB_OUTPUT
fi fi
- name: Plugin QUnit - name: Plugin QUnit

View File

@ -1,2 +1,2 @@
inherit_gem: inherit_gem:
rubocop-discourse: default.yml rubocop-discourse: stree-compat.yml

2
.streerc Normal file
View File

@ -0,0 +1,2 @@
--print-width=100
--plugins=plugin/trailing_comma

View File

@ -1,7 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
source 'https://rubygems.org' source "https://rubygems.org"
group :development do group :development do
gem 'rubocop-discourse' gem "rubocop-discourse"
gem "syntax_tree"
end end

View File

@ -6,6 +6,7 @@ GEM
parallel (1.22.1) parallel (1.22.1)
parser (3.1.2.1) parser (3.1.2.1)
ast (~> 2.4.1) ast (~> 2.4.1)
prettier_print (1.2.0)
rainbow (3.1.1) rainbow (3.1.1)
regexp_parser (2.6.0) regexp_parser (2.6.0)
rexml (3.2.5) rexml (3.2.5)
@ -27,6 +28,8 @@ GEM
rubocop-rspec (2.13.2) rubocop-rspec (2.13.2)
rubocop (~> 1.33) rubocop (~> 1.33)
ruby-progressbar (1.11.0) ruby-progressbar (1.11.0)
syntax_tree (5.1.0)
prettier_print (>= 1.2.0)
unicode-display_width (2.3.0) unicode-display_width (2.3.0)
PLATFORMS PLATFORMS
@ -39,6 +42,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
rubocop-discourse rubocop-discourse
syntax_tree
BUNDLED WITH BUNDLED WITH
2.3.10 2.3.10

View File

@ -13,10 +13,10 @@ class AddUserNotesCountIndex < ActiveRecord::Migration[5.2]
SQL SQL
add_index :user_custom_fields, add_index :user_custom_fields,
[:name, :user_id], %i[name user_id],
unique: true, unique: true,
name: :idx_user_custom_fields_user_notes_count, name: :idx_user_custom_fields_user_notes_count,
where: "name = 'user_notes_count'" where: "name = 'user_notes_count'"
end end
def down def down

View File

@ -23,7 +23,6 @@ class CorrectUserNotesCount < ActiveRecord::Migration[5.2]
ON CONFLICT (name, user_id) WHERE name::text = 'user_notes_count'::text ON CONFLICT (name, user_id) WHERE name::text = 'user_notes_count'::text
DO NOTHING DO NOTHING
SQL SQL
end end
def down def down

144
plugin.rb
View File

@ -9,15 +9,14 @@
enabled_site_setting :user_notes_enabled enabled_site_setting :user_notes_enabled
register_asset 'stylesheets/user_notes.scss' register_asset "stylesheets/user_notes.scss"
register_svg_icon "sticky-note" if respond_to?(:register_svg_icon) register_svg_icon "sticky-note" if respond_to?(:register_svg_icon)
COUNT_FIELD = "user_notes_count" COUNT_FIELD = "user_notes_count"
after_initialize do after_initialize do
require_dependency "user"
require_dependency 'user'
module ::DiscourseUserNotes module ::DiscourseUserNotes
class Engine < ::Rails::Engine class Engine < ::Rails::Engine
@ -30,7 +29,7 @@ after_initialize do
end end
def self.notes_for(user_id) def self.notes_for(user_id)
PluginStore.get('user_notes', key_for(user_id)) || [] PluginStore.get("user_notes", key_for(user_id)) || []
end end
def self.add_note(user, raw, created_by, opts = nil) def self.add_note(user, raw, created_by, opts = nil)
@ -42,7 +41,7 @@ after_initialize do
user_id: user.id, user_id: user.id,
raw: raw, raw: raw,
created_by: created_by, created_by: created_by,
created_at: Time.now created_at: Time.now,
}.merge(opts) }.merge(opts)
notes << record notes << record
@ -66,10 +65,9 @@ after_initialize do
user.custom_fields[COUNT_FIELD] = notes.size user.custom_fields[COUNT_FIELD] = notes.size
user.save_custom_fields user.save_custom_fields
end end
end end
require_dependency 'application_serializer' require_dependency "application_serializer"
class ::UserNoteSerializer < ApplicationSerializer class ::UserNoteSerializer < ApplicationSerializer
attributes( attributes(
:id, :id,
@ -80,7 +78,7 @@ after_initialize do
:can_delete, :can_delete,
:post_id, :post_id,
:post_url, :post_url,
:post_title :post_title,
) )
def id def id
@ -115,9 +113,7 @@ after_initialize do
url = object[:post].try(:url) url = object[:post].try(:url)
# In case the topic is deleted # In case the topic is deleted
if url == "/404" url = "/t/#{object[:post].topic_id}/#{object[:post].post_number}" if url == "/404"
url = "/t/#{object[:post].topic_id}/#{object[:post].post_number}"
end
"#{Discourse.base_path}#{url}" "#{Discourse.base_path}#{url}"
end end
@ -131,7 +127,7 @@ after_initialize do
end end
end end
require_dependency 'application_controller' require_dependency "application_controller"
class DiscourseUserNotes::UserNotesController < ::ApplicationController class DiscourseUserNotes::UserNotesController < ::ApplicationController
before_action :ensure_logged_in before_action :ensure_logged_in
before_action :ensure_staff before_action :ensure_staff
@ -141,10 +137,7 @@ after_initialize do
raise Discourse::NotFound if user.blank? raise Discourse::NotFound if user.blank?
notes = ::DiscourseUserNotes.notes_for(params[:user_id]) notes = ::DiscourseUserNotes.notes_for(params[:user_id])
render json: { render json: { extras: { username: user.username }, user_notes: create_json(notes.reverse) }
extras: { username: user.username },
user_notes: create_json(notes.reverse)
}
end end
def create def create
@ -155,12 +148,8 @@ after_initialize do
extras[:post_id] = post_id extras[:post_id] = post_id
end end
user_note = ::DiscourseUserNotes.add_note( user_note =
user, ::DiscourseUserNotes.add_note(user, params[:user_note][:raw], current_user.id, extras)
params[:user_note][:raw],
current_user.id,
extras
)
render json: create_json(user_note) render json: create_json(user_note)
end end
@ -182,12 +171,8 @@ after_initialize do
if obj.is_a?(Array) if obj.is_a?(Array)
users_by_id = {} users_by_id = {}
posts_by_id = {} posts_by_id = {}
User.where(id: obj.map { |o| o[:created_by] }).each do |u| User.where(id: obj.map { |o| o[:created_by] }).each { |u| users_by_id[u.id] = u }
users_by_id[u.id] = u Post.with_deleted.where(id: obj.map { |o| o[:post_id] }).each { |p| posts_by_id[p.id] = p }
end
Post.with_deleted.where(id: obj.map { |o| o[:post_id] }).each do |p|
posts_by_id[p.id] = p
end
obj.each do |o| obj.each do |o|
o[:created_by] = users_by_id[o[:created_by].to_i] o[:created_by] = users_by_id[o[:created_by].to_i]
o[:post] = posts_by_id[o[:post_id].to_i] o[:post] = posts_by_id[o[:post_id].to_i]
@ -213,31 +198,34 @@ after_initialize do
end end
add_to_serializer(:admin_detailed_user, :user_notes_count, false) do add_to_serializer(:admin_detailed_user, :user_notes_count, false) do
object.custom_fields && object.custom_fields['user_notes_count'].to_i object.custom_fields && object.custom_fields["user_notes_count"].to_i
end end
DiscourseUserNotes::Engine.routes.draw do DiscourseUserNotes::Engine.routes.draw do
get '/' => 'user_notes#index' get "/" => "user_notes#index"
post '/' => 'user_notes#create' post "/" => "user_notes#create"
delete '/:id' => 'user_notes#destroy' delete "/:id" => "user_notes#destroy"
end end
Discourse::Application.routes.append do Discourse::Application.routes.append { mount ::DiscourseUserNotes::Engine, at: "/user_notes" }
mount ::DiscourseUserNotes::Engine, at: "/user_notes"
end
add_model_callback(UserWarning, :after_commit, on: :create) do add_model_callback(UserWarning, :after_commit, on: :create) do
user = User.find_by_id(self.user_id) user = User.find_by_id(self.user_id)
created_by_user = User.find_by_id(self.created_by_id) created_by_user = User.find_by_id(self.created_by_id)
warning_topic = Topic.find_by_id(self.topic_id) warning_topic = Topic.find_by_id(self.topic_id)
raw_note = I18n.with_locale(SiteSetting.default_locale) do raw_note =
I18n.t("user_notes.official_warning", username: created_by_user.username, warning_link: "[#{warning_topic.title}](#{warning_topic.url})") I18n.with_locale(SiteSetting.default_locale) do
end I18n.t(
"user_notes.official_warning",
username: created_by_user.username,
warning_link: "[#{warning_topic.title}](#{warning_topic.url})",
)
end
::DiscourseUserNotes.add_note( ::DiscourseUserNotes.add_note(
user, user,
raw_note, raw_note,
Discourse::SYSTEM_USER_ID, Discourse::SYSTEM_USER_ID,
topic_id: self.topic_id topic_id: self.topic_id,
) )
end end
@ -245,46 +233,44 @@ after_initialize do
return unless self.action == UserHistory.actions[:suspend_user] return unless self.action == UserHistory.actions[:suspend_user]
target_user = User.find_by_id(self.target_user_id) target_user = User.find_by_id(self.target_user_id)
created_by_user = User.find_by_id(self.acting_user_id) created_by_user = User.find_by_id(self.acting_user_id)
raw_note = I18n.with_locale(SiteSetting.default_locale) do raw_note =
I18n.t("user_notes.user_suspended", I18n.with_locale(SiteSetting.default_locale) do
username: created_by_user.username, I18n.t(
suspended_till: I18n.l(target_user.suspended_till, format: :date_only), "user_notes.user_suspended",
reason: self.details username: created_by_user.username,
) suspended_till: I18n.l(target_user.suspended_till, format: :date_only),
end reason: self.details,
)
end
::DiscourseUserNotes.add_note( ::DiscourseUserNotes.add_note(
target_user, target_user,
raw_note, raw_note,
Discourse::SYSTEM_USER_ID, Discourse::SYSTEM_USER_ID,
post_id: self.post_id, post_id: self.post_id,
topic_id: self.topic_id topic_id: self.topic_id,
) )
end end
on(:user_silenced) do |details| on(:user_silenced) do |details|
raw_note = I18n.with_locale(SiteSetting.default_locale) do raw_note =
I18n.t( I18n.with_locale(SiteSetting.default_locale) do
"user_notes.user_silenced", I18n.t(
username: details[:silenced_by]&.username || '', "user_notes.user_silenced",
silenced_till: I18n.l(details[:silenced_till], format: :date_only), username: details[:silenced_by]&.username || "",
reason: details[:reason] silenced_till: I18n.l(details[:silenced_till], format: :date_only),
) reason: details[:reason],
end )
end
note_args = {} note_args = {}
if post = Post.with_deleted.where(id: details[:post_id]).first if post = Post.with_deleted.where(id: details[:post_id]).first
note_args = { post_id: post.id, topic_id: post.topic_id } note_args = { post_id: post.id, topic_id: post.topic_id }
end end
::DiscourseUserNotes.add_note( ::DiscourseUserNotes.add_note(details[:user], raw_note, Discourse::SYSTEM_USER_ID, note_args)
details[:user],
raw_note,
Discourse::SYSTEM_USER_ID,
note_args
)
end end
if respond_to? :add_report if respond_to? :add_report
add_report('user_notes') do |report| add_report("user_notes") do |report|
report.modes = [:table] report.modes = [:table]
report.data = [] report.data = []
@ -297,7 +283,7 @@ after_initialize do
id: :user_id, id: :user_id,
avatar: :user_avatar_template, avatar: :user_avatar_template,
}, },
title: I18n.t("reports.user_notes.labels.user") title: I18n.t("reports.user_notes.labels.user"),
}, },
{ {
type: :user, type: :user,
@ -306,34 +292,42 @@ after_initialize do
id: :moderator_id, id: :moderator_id,
avatar: :moderator_avatar_template, avatar: :moderator_avatar_template,
}, },
title: I18n.t("reports.user_notes.labels.moderator") title: I18n.t("reports.user_notes.labels.moderator"),
}, },
{ type: :text, property: :note, title: I18n.t("reports.user_notes.labels.note") } { type: :text, property: :note, title: I18n.t("reports.user_notes.labels.note") },
] ]
values = [] values = []
values = PluginStoreRow.where(plugin_name: 'user_notes') values =
.where("value::json->0->>'created_at'>=?", report.start_date) PluginStoreRow
.where("value::json->0->>'created_at'<=?", report.end_date) .where(plugin_name: "user_notes")
.pluck(:value) .where("value::json->0->>'created_at'>=?", report.start_date)
.where("value::json->0->>'created_at'<=?", report.end_date)
.pluck(:value)
values.each do |value| values.each do |value|
notes = JSON.parse(value) notes = JSON.parse(value)
notes.each do |note| notes.each do |note|
data = {} data = {}
created_at = Time.parse(note['created_at']) created_at = Time.parse(note["created_at"])
user = User.find_by(id: note['user_id']) user = User.find_by(id: note["user_id"])
moderator = User.find_by(id: note['created_by']) moderator = User.find_by(id: note["created_by"])
if user && moderator if user && moderator
data[:created_at] = created_at data[:created_at] = created_at
data[:user_id] = user.id data[:user_id] = user.id
data[:username] = user.username_lower data[:username] = user.username_lower
data[:user_avatar_template] = User.avatar_template(user.username_lower, user.uploaded_avatar_id) data[:user_avatar_template] = User.avatar_template(
user.username_lower,
user.uploaded_avatar_id,
)
data[:moderator_id] = moderator.id data[:moderator_id] = moderator.id
data[:moderator_username] = moderator.username_lower data[:moderator_username] = moderator.username_lower
data[:moderator_avatar_template] = User.avatar_template(moderator.username_lower, moderator.uploaded_avatar_id) data[:moderator_avatar_template] = User.avatar_template(
data[:note] = note['raw'] moderator.username_lower,
moderator.uploaded_avatar_id,
)
data[:note] = note["raw"]
report.data << data report.data << data
end end

View File

@ -1,34 +1,44 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'rails_helper' require "rails_helper"
describe UserHistory do describe UserHistory do
let(:user) { Fabricate(:user, suspended_till: 7.days.from_now) } let(:user) { Fabricate(:user, suspended_till: 7.days.from_now) }
let(:admin) { Fabricate(:admin) } let(:admin) { Fabricate(:admin) }
describe 'when a user suspension log is created' do describe "when a user suspension log is created" do
context "when staff notes plugin is enabled" do context "when staff notes plugin is enabled" do
before do before { SiteSetting.user_notes_enabled = true }
SiteSetting.user_notes_enabled = true
end
it "should create staff note for suspension" do it "should create staff note for suspension" do
UserHistory.create!(action: UserHistory.actions[:suspend_user], target_user_id: user.id, acting_user_id: admin.id) UserHistory.create!(
action: UserHistory.actions[:suspend_user],
target_user_id: user.id,
acting_user_id: admin.id,
)
expect(PluginStore.get('user_notes', "notes:#{user.id}")).to be_present expect(PluginStore.get("user_notes", "notes:#{user.id}")).to be_present
end end
it "should use system language" do it "should use system language" do
freeze_time freeze_time
UserHistory.create!(action: UserHistory.actions[:suspend_user], target_user_id: user.id, acting_user_id: admin.id) UserHistory.create!(
action: UserHistory.actions[:suspend_user],
target_user_id: user.id,
acting_user_id: admin.id,
)
I18n.with_locale(:fr) do # Simulate request from french user I18n.with_locale(:fr) do # Simulate request from french user
UserHistory.create!(action: UserHistory.actions[:suspend_user], target_user_id: user.id, acting_user_id: admin.id) UserHistory.create!(
action: UserHistory.actions[:suspend_user],
target_user_id: user.id,
acting_user_id: admin.id,
)
end end
notes = PluginStore.get('user_notes', "notes:#{user.id}") notes = PluginStore.get("user_notes", "notes:#{user.id}")
expect(notes[0]['raw']).to eq(notes[1]['raw']) expect(notes[0]["raw"]).to eq(notes[1]["raw"])
end end
end end
end end

View File

@ -1,22 +1,20 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'rails_helper' require "rails_helper"
describe UserWarning do describe UserWarning do
let(:user) { Fabricate(:user) } let(:user) { Fabricate(:user) }
let(:admin) { Fabricate(:admin) } let(:admin) { Fabricate(:admin) }
let(:topic) { Fabricate(:topic) } let(:topic) { Fabricate(:topic) }
describe 'when a user warning is created' do describe "when a user warning is created" do
context "when staff notes plugin is enabled" do context "when staff notes plugin is enabled" do
before do before { SiteSetting.user_notes_enabled = true }
SiteSetting.user_notes_enabled = true
end
it "should create staff note for warning" do it "should create staff note for warning" do
UserWarning.create(topic_id: topic.id, user_id: user.id, created_by_id: admin.id) UserWarning.create(topic_id: topic.id, user_id: user.id, created_by_id: admin.id)
expect(PluginStore.get('user_notes', "notes:#{user.id}")).to be_present expect(PluginStore.get("user_notes", "notes:#{user.id}")).to be_present
end end
it "should use system language" do it "should use system language" do
@ -29,8 +27,8 @@ describe UserWarning do
UserWarning.create(topic_id: topic.id, user_id: user.id, created_by_id: admin.id) UserWarning.create(topic_id: topic.id, user_id: user.id, created_by_id: admin.id)
end end
notes = PluginStore.get('user_notes', "notes:#{user.id}") notes = PluginStore.get("user_notes", "notes:#{user.id}")
expect(notes[0]['raw']).to eq(notes[1]['raw']) expect(notes[0]["raw"]).to eq(notes[1]["raw"])
end end
end end
end end