taskbar.rb 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Taskbar < ApplicationModel
  3. include ChecksClientNotification
  4. include ::Taskbar::HasAttachments
  5. include Taskbar::Assets
  6. include Taskbar::TriggersSubscriptions
  7. TASKBAR_APPS = %w[desktop mobile].freeze
  8. store :state
  9. store :params
  10. store :preferences
  11. belongs_to :user
  12. validates :app, inclusion: { in: TASKBAR_APPS }
  13. before_create :update_last_contact, :set_user, :update_preferences_infos
  14. before_update :update_last_contact, :set_user, :update_preferences_infos
  15. after_update :notify_clients
  16. after_destroy :update_preferences_infos, :notify_clients
  17. association_attributes_ignored :user
  18. client_notification_events_ignored :create, :update, :touch
  19. client_notification_send_to :user_id
  20. attr_accessor :local_update
  21. default_scope { order(:id) }
  22. scope :related_taskbars, lambda { |taskbar|
  23. where(key: taskbar.key)
  24. .where.not(id: taskbar.id)
  25. }
  26. def state_changed?
  27. return false if state.blank?
  28. state.each_value do |value|
  29. if value.is_a? Hash
  30. value.each do |key1, value1|
  31. next if value1.blank?
  32. next if key1 == 'form_id'
  33. return true
  34. end
  35. else
  36. next if value.blank?
  37. return true
  38. end
  39. end
  40. false
  41. end
  42. def attributes_with_association_names(empty_keys: false)
  43. add_attachments_to_attributes(super)
  44. end
  45. def attributes_with_association_ids
  46. add_attachments_to_attributes(super)
  47. end
  48. def as_json(options = {})
  49. add_attachments_to_attributes(super)
  50. end
  51. def preferences_task_info
  52. output = { user_id:, apps: { app.to_sym => { last_contact: last_contact, changed: state_changed? } } }
  53. output[:id] = id if persisted?
  54. output
  55. end
  56. def related_taskbars
  57. self.class.related_taskbars(self)
  58. end
  59. private
  60. def update_last_contact
  61. return true if local_update
  62. return true if changes.blank?
  63. if changes['notify']
  64. count = 0
  65. changes.each_key do |attribute|
  66. next if attribute == 'updated_at'
  67. next if attribute == 'created_at'
  68. count += 1
  69. end
  70. return true if count <= 1
  71. end
  72. self.last_contact = Time.zone.now
  73. end
  74. def set_user
  75. return true if local_update
  76. return true if !UserInfo.current_user_id
  77. self.user_id = UserInfo.current_user_id
  78. end
  79. def update_preferences_infos
  80. return if key == 'Search'
  81. return if local_update
  82. preferences = self.preferences || {}
  83. preferences[:tasks] = collect_related_tasks
  84. update_related_taskbars(preferences)
  85. # remember preferences for current taskbar
  86. self.preferences = preferences if !destroyed?
  87. end
  88. def collect_related_tasks
  89. related_taskbars.map(&:preferences_task_info)
  90. .tap { |arr| arr.push(preferences_task_info) if !destroyed? }
  91. .each_with_object({}) { |elem, memo| reduce_related_tasks(elem, memo) }
  92. .values
  93. .sort_by { |elem| elem[:id] || Float::MAX } # sort by IDs to pass old tests
  94. end
  95. def reduce_related_tasks(elem, memo)
  96. key = elem[:user_id]
  97. if memo[key]
  98. memo[key].deep_merge! elem
  99. return
  100. end
  101. memo[key] = elem
  102. end
  103. def update_related_taskbars(preferences)
  104. related_taskbars.each do |taskbar|
  105. taskbar.with_lock do
  106. taskbar.preferences = preferences
  107. taskbar.local_update = true
  108. taskbar.save!
  109. end
  110. end
  111. end
  112. def notify_clients
  113. return true if !saved_change_to_attribute?('preferences')
  114. data = {
  115. event: 'taskbar:preferences',
  116. data: {
  117. id: id,
  118. key: key,
  119. preferences: preferences,
  120. },
  121. }
  122. PushMessages.send_to(
  123. user_id,
  124. data,
  125. )
  126. end
  127. end