Module: Labimotion::ShareNotifier

Defined in:
lib/labimotion/libs/share_notifier.rb

Overview

Courtesy notifications for share events (template-sharing.md §7), moved in from the host's Chemotion::TemplateShareAPI (chem-generic-ui#1040): the gem writes the share rows, so the gem announces them, and the two-call dance the Designer used to do (write to the gem, then call the host back to notify) collapses into the write.

These messages buy awareness outside the Designer only — the toast in the main ELN. klass_shares is the record and the Designer reads the rows; it never reads or acks a Message. Nothing here may therefore fail a share: every public method rescues to nil, and an undeliverable notification is a notification not sent, never an error. Callers fire after the successful write and ignore the return value.

The host models are reached by their bare names and only if they exist: a host without Message/Channel machinery (or one that has not run the channel migration) simply sends nothing. The channel is looked up by its literal subject — referencing Channel::TEMPLATE_SHARE_NOTIFICATION would raise on hosts whose Channel model predates the constant.

Constant Summary collapse

CHANNEL_SUBJECT =

Must match the subject the host ELN's channel migration seeds (add_template_share_notification_channel; channel_type 8, the targeted per-user delivery branch of generate_notifications).

'Template Share Notification'

Class Method Summary collapse

Class Method Details

.grant(klass:, actor:, user_ids:, level:) ⇒ Object

Fired for level changes too — the grant endpoint is an upsert and cannot tell a fresh share from a level change, so "granted you X access" stays honest for both.



31
32
33
34
35
36
37
38
39
40
# File 'lib/labimotion/libs/share_notifier.rb', line 31

def self.grant(klass:, actor:, user_ids:, level:)
  label = template_label(klass)
  ping(
    actor: actor, user_ids: user_ids,
    text: "#{actor.name} granted you #{level} access to the template '#{label}'."
  )
rescue StandardError => e
  Labimotion.log_exception(e, actor)
  nil
end

.request(klass:, actor:) ⇒ Object

The owner to ask: the klass_shares owner row, falling back to the immutable created_by for an owner-less template. A blank owner matches no user and channel_type-8 fan-out reaches Persons only, so an Admin owner gets no toast — they learn about the request when they next open the Designer, where the rows are the truth. The caller gates on created: the unique index dedupes rows, not messages, so only the ask that wrote the row earns a ping.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/labimotion/libs/share_notifier.rb', line 60

def self.request(klass:, actor:)
  owner_id = Labimotion::KlassShare.owner_row_for(klass)&.shared_with_id ||
             klass.created_by
  return if owner_id.nil?

  label = template_label(klass)
  ping(
    actor: actor, user_ids: [owner_id],
    text: "#{actor.name} asks for access to your template '#{label}'. " \
          'You can grant it from the Share dialog in the Designer.'
  )
rescue StandardError => e
  Labimotion.log_exception(e, actor)
  nil
end

.transfer(klass:, actor:, user_id:) ⇒ Object



42
43
44
45
46
47
48
49
50
51
# File 'lib/labimotion/libs/share_notifier.rb', line 42

def self.transfer(klass:, actor:, user_id:)
  label = template_label(klass)
  ping(
    actor: actor, user_ids: [user_id],
    text: "#{actor.name} transferred ownership of the template '#{label}' to you."
  )
rescue StandardError => e
  Labimotion.log_exception(e, actor)
  nil
end