0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-06 13:08:40 +08:00
discourse/app/controllers/admin/emoji_controller.rb
Martin Brennan 9e9de80295
UX: Better admin emoji page sorting & filtering and service refactors (#41892)
This commit uses `DFilterControls` for emoji list filtering, and sorts
the
emoji by group then by name, with default always at the top:

<img width="1101" height="803" alt="image"
src="https://github.com/user-attachments/assets/77e384c1-33b1-4741-bd55-ca86cd5f2a03"
/>

I've also refactored the create + delete endpoints into services.
2026-07-24 12:01:21 +10:00

133 lines
4.9 KiB
Ruby
Vendored

# frozen_string_literal: true
class Admin::EmojiController < Admin::AdminController
skip_before_action :check_xhr, only: [:export]
def index
render_serialized(
Emoji.custom.sort_by do |emoji|
[emoji.group == "default" ? 0 : 1, emoji.group.downcase, emoji.name.downcase]
end,
EmojiSerializer,
root: false,
)
end
# NOTE: This kind of custom logic also needs to be implemented to
# be run in the ExternalUploadManager when a direct S3 upload is completed,
# related to preventDirectS3Uploads in the UppyUploadMixin.
#
# Until then, preventDirectS3Uploads is set to true in the UppyUploadMixin.
def create
hijack do
CustomEmoji::Create.call(service_params) do |result|
on_success do |custom_emoji:|
render json: {
name: custom_emoji.name,
url: custom_emoji.upload.url,
group: custom_emoji.group,
}
end
on_failed_contract do |contract|
render json: failed_json.merge(errors: contract.errors.full_messages),
status: :unprocessable_entity
end
on_model_errors(:upload) do |_, upload:|
render json: failed_json.merge(errors: upload.errors.full_messages),
status: :unprocessable_entity
end
on_model_errors(:custom_emoji) do |custom_emoji|
render json: failed_json.merge(errors: custom_emoji.errors.full_messages),
status: :unprocessable_entity
end
end
end
end
def export
CustomEmoji::Export.call(service_params) do |result|
on_success do |archive:|
send_data archive,
type: "application/zip",
disposition: "attachment",
filename: "emojis.zip"
end
on_failed_contract do
render json: failed_json.merge(errors: [I18n.t("emoji.export.no_selection")]),
status: :unprocessable_entity
end
on_model_not_found(:emojis) { render json: failed_json, status: :not_found }
end
end
def import_preview
hijack do
CustomEmoji::PreviewImport.call(service_params) do |result|
on_success do |token:, rows:|
render json: {
token:,
rows:
ActiveModel::ArraySerializer.new(
rows,
each_serializer: CustomEmoji::ImportRowSerializer,
).as_json,
}
end
on_failed_contract do
render json: failed_json.merge(errors: [I18n.t("emoji.import.missing_file")]),
status: :unprocessable_entity
end
on_failed_policy(:manifest_not_empty) do
render json: failed_json.merge(errors: [I18n.t("emoji.import.empty_manifest")]),
status: :unprocessable_entity
end
on_exceptions(CSV::MalformedCSVError) do
render json: failed_json.merge(errors: [I18n.t("emoji.import.invalid_csv")]),
status: :unprocessable_entity
end
on_exceptions(Compression::SafeZipReader::MissingEntryError) do
render json: failed_json.merge(errors: [I18n.t("emoji.import.missing_csv")]),
status: :unprocessable_entity
end
on_exceptions(Compression::SafeZipReader::TooManyEntriesError) do
render json: failed_json.merge(errors: [I18n.t("emoji.import.too_many_entries")]),
status: :unprocessable_entity
end
on_exceptions(Compression::SafeZipReader::EntryTooLargeError) do
render json: failed_json.merge(errors: [I18n.t("emoji.import.file_too_large")]),
status: :unprocessable_entity
end
on_exceptions(Compression::SafeZipReader::SuspiciousEntryError) do
render json: failed_json.merge(errors: [I18n.t("emoji.import.suspicious_entry")]),
status: :unprocessable_entity
end
end
end
end
def import_confirm
CustomEmoji::ConfirmImport.call(service_params) do |result|
on_success { |report:| render json: report }
on_failed_contract do |contract|
render json: failed_json.merge(errors: contract.errors.full_messages),
status: :unprocessable_entity
end
on_model_not_found(:rows) do
render json: failed_json.merge(errors: [I18n.t("emoji.import.session_expired")]),
status: :unprocessable_entity
end
on_exceptions(ActiveRecord::RecordInvalid) do |exception|
render json: failed_json.merge(errors: [exception.message]), status: :unprocessable_entity
end
end
end
def destroy
CustomEmoji::Destroy.call(
service_params.deep_merge(params: { name: params.require(:id) }),
) do |result|
on_success { render json: success_json }
on_failed_contract { raise Discourse::InvalidParameters.new(:name) }
end
end
end