0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-14 13:58:53 +08:00
discourse/plugins/poll/app/serializers/poll_serializer.rb
Régis Hanol 72091d161c
FEATURE: Record who closed a poll (#40989)
Previously, there was no way to tell who closed (or reopened) a poll —
neither the staff action log nor the poll itself recorded it, as raised
in [meta](https://meta.discourse.org/t/who-closed-the-poll/405495).

This change logs `poll_closed`/`poll_opened` staff actions (auto-close
attributed to the system user) and stores `closed_by`/`closed_at` on the
poll, surfacing "Closed by @user" in the poll UI and making the closer
queryable.

---

Also includes a small fix: the poll buttons dropdown rendered a
`<dropdown.divider />` after every item, leaving a stray trailing border
below the last option; it now renders dividers only between items.

**Screenshot**

<img width="1400" height="1200" alt="image"
src="https://github.com/user-attachments/assets/fd04353a-eac6-448d-904e-47b8e5f8f14f"
/>
2026-06-29 12:22:43 +02:00

96 lines
1.9 KiB
Ruby
Vendored

# frozen_string_literal: true
class PollSerializer < ApplicationSerializer
attributes :id,
:name,
:type,
:status,
:public,
:dynamic,
:results,
:min,
:max,
:step,
:options,
:voters,
:close,
:preloaded_voters,
:chart_type,
:groups,
:title,
:ranked_choice_outcome,
:closed_at,
:closed_by
def closed_by
return if object.closed_by_id.blank? || object.closed_by_id == Discourse::SYSTEM_USER_ID
BasicUserSerializer.new(object.closed_by, root: false, scope:).as_json
end
def public
true
end
def include_public?
object.everyone?
end
def include_min?
object.min.present? && (object.number? || object.multiple?)
end
def include_max?
object.max.present? && (object.number? || object.multiple?)
end
def include_step?
object.step.present? && object.number?
end
def include_groups?
groups.present?
end
def options
can_see_results = object.can_see_results?(scope.user)
object.poll_options.map do |option|
PollOptionSerializer.new(
option,
root: false,
scope: {
can_see_results: can_see_results,
},
).as_json
end
end
def voters
object.voters_count + object.anonymous_voters.to_i
end
def close
object.close_at
end
def include_close?
object.close_at.present?
end
def preloaded_voters
DiscoursePoll::Poll.serialized_voters(object)
end
def include_preloaded_voters?
object.can_see_voters?(scope.user)
end
def include_ranked_choice_outcome?
object.ranked_choice? && object.can_see_results?(scope.user)
end
def ranked_choice_outcome
DiscoursePoll::RankedChoice.outcome(object.id)
end
end