Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/solver-it-sro/govbox-pro in…
Browse files Browse the repository at this point in the history
…to GO-200/admin_others_target_UX
  • Loading branch information
stage-rl committed Sep 22, 2023
2 parents b7318b5 + 4ef50ee commit 452edc4
Show file tree
Hide file tree
Showing 63 changed files with 2,318 additions and 144 deletions.
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ gem 'rails', '~> 7.0'
gem 'rails-i18n'

gem 'pg', '~> 1.0'
gem 'with_advisory_lock'

gem 'puma', '~> 5.0'

Expand Down Expand Up @@ -39,6 +40,9 @@ gem 'jsbundling-rails'
# Monitoring
gem 'rollbar'

# search
gem 'pg_search'

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.4', require: false

Expand Down
7 changes: 7 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ GEM
parser (3.2.2.1)
ast (~> 2.4.1)
pg (1.5.3)
pg_search (2.3.6)
activerecord (>= 5.2)
activesupport (>= 5.2)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
Expand Down Expand Up @@ -368,6 +371,8 @@ GEM
websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
with_advisory_lock (4.6.0)
activerecord (>= 4.2)
xpath (3.2.0)
nokogiri (~> 1.8)
yard (0.9.34)
Expand All @@ -394,6 +399,7 @@ DEPENDENCIES
omniauth-google-oauth2
omniauth-rails_csrf_protection
pg (~> 1.0)
pg_search
pry-byebug
pry-rails
puma (~> 5.0)
Expand All @@ -414,6 +420,7 @@ DEPENDENCIES
web-console
webdrivers
webmock
with_advisory_lock

RUBY VERSION
ruby 3.2.2p53
Expand Down
4 changes: 2 additions & 2 deletions app/components/layout/tag_list_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
<p class=" text-sm text-center text-gray-400">Štítky</p>
</div>
<% @tags.each do |tag| %>
<%= link_to tag_message_threads_path(tag), class:"flex justify-start items-start px-4 py-2 gap-2 overflow-hidden" do %>
<%= link_to message_threads_path(q: "label:(#{tag.name})"), class:"flex justify-start items-start px-4 py-2 gap-2 overflow-hidden" do %>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class=" w-6 h-6 relative" preserveAspectRatio="xMidYMid meet">
<path d="M7 7H7.01M7 3H12C12.512 3 13.024 3.195 13.414 3.586L20.414 10.586C20.7889 10.9611 20.9996 11.4697 20.9996 12C20.9996 12.5303 20.7889 13.0389 20.414 13.414L13.414 20.414C13.0389 20.7889 12.5303 20.9996 12 20.9996C11.4697 20.9996 10.9611 20.7889 10.586 20.414L3.586 13.414C3.4 13.2285 3.25249 13.0081 3.15192 12.7655C3.05136 12.5228 2.99973 12.2627 3 12V7C3 5.93913 3.42143 4.92172 4.17157 4.17157C4.92172 3.42143 5.93913 3 7 3Z" stroke="#9CA3AF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<p class="truncate text-base font-medium text-left text-gray-900"><%= tag.name %></p>
<% end %>
<% end %>
<% if Current.user.admin? %>
<%= link_to message_threads_path(tags:"none"), class:"group relative " do %>
<%= link_to message_threads_path(no_visible_tags: "1"), class: "group relative" do %>
<div class="flex justify-start items-start px-4 py-2 gap-2">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class=" w-6 h-6 relative" preserveAspectRatio="xMidYMid meet">
<path d="M7 7H7.01M7 3H12C12.512 3 13.024 3.195 13.414 3.586L20.414 10.586C20.7889 10.9611 20.9996 11.4697 20.9996 12C20.9996 12.5303 20.7889 13.0389 20.414 13.414L13.414 20.414C13.0389 20.7889 12.5303 20.9996 12 20.9996C11.4697 20.9996 10.9611 20.7889 10.586 20.414L3.586 13.414C3.4 13.2285 3.25249 13.0081 3.15192 12.7655C3.05136 12.5228 2.99973 12.2627 3 12V7C3 5.93913 3.42143 4.92172 4.17157 4.17157C4.92172 3.42143 5.93913 3 7 3Z" stroke="#9CA3AF" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"></path>
Expand Down
2 changes: 1 addition & 1 deletion app/components/message_threads_table_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="flex flex-col justify-stretch items-stretch gap-4 p-4">
<div class="flex flex-col justify-stretch items-stretch rounded-md bg-white border border-gray-200">
<%= form_with(url:merge_message_threads_path, method: :get, local: true) do |form|%>
<%= form_with(url: merge_message_threads_path, local: true) do |form|%>
<div class="flex justify-stretch items-center gap-4 p-4 border-t-0 border-r-0 border-b border-l-0 border-gray-200">
<div class="todo flex justify-start items-start pr-[100px]">
<div class=" w-4 h-4 relative">
Expand Down
4 changes: 2 additions & 2 deletions app/components/message_threads_table_row_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="flex justify-stretch items-center gap-4 p-4 border-t-0 border-r-0 border-b border-l-0 border-gray-200">
<div class="flex justify-stretch items-center gap-4 pt-1 pb-[30px] rounded-full">
<%= check_box_tag('message_thread_ids[]', @message_thread.id) %>
<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512" class=<%= "invisible" if @message_thread.read? %>><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm0 48v40.805c-22.422 18.259-58.168 46.651-134.587 106.49-16.841 13.247-50.201 45.072-73.413 44.701-23.208.375-56.579-31.459-73.413-44.701C106.18 199.465 70.425 171.067 48 152.805V112h416zM48 400V214.398c22.914 18.251 55.409 43.862 104.938 82.646 21.857 17.205 60.134 55.186 103.062 54.955 42.717.231 80.509-37.199 103.053-54.947 49.528-38.783 82.032-64.401 104.947-82.653V400H48z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512" class=<%= "invisible" if @message_thread.all_read %>><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm0 48v40.805c-22.422 18.259-58.168 46.651-134.587 106.49-16.841 13.247-50.201 45.072-73.413 44.701-23.208.375-56.579-31.459-73.413-44.701C106.18 199.465 70.425 171.067 48 152.805V112h416zM48 400V214.398c22.914 18.251 55.409 43.862 104.938 82.646 21.857 17.205 60.134 55.186 103.062 54.955 42.717.231 80.509-37.199 103.053-54.947 49.528-38.783 82.032-64.401 104.947-82.653V400H48z"/></svg>
<div class="flex flex-col justify-start items-start pr-[7px]">
<div class="flex justify-center items-center gap-1.5 px-2 py-1 rounded-md bg-yellow-50 border border-yellow-300">
<p class="text-sm text-left text-yellow-700">GO</p>
Expand All @@ -10,7 +10,7 @@
</div>
<%= link_to @message_thread, class:"flex justify-stretch overflow-clip items-center grow gap-2" do %>
<div class="flex flex-col truncate justify-start items-stretch grow gap-1">
<p title="<%= @message_thread.title%>" class="truncate text-lg text-gray-900 <%="font-semibold" unless @message_thread.read? %>"><%= @message_thread.title %></p>
<p title="<%= @message_thread.title%>" class="truncate text-lg text-gray-900 <%="font-semibold" unless @message_thread.all_read %>"><%= @message_thread.title %></p>
<p class="text-base text-left text-gray-500"><%= @message_thread.with_whom %></p>
</div>
<div class="flex flex-wrap truncate justify-start items-start gap-1">
Expand Down
15 changes: 10 additions & 5 deletions app/components/t_w/top_navigation_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@
<svg width="1" height="64" viewBox="0 0 1 64" fill="none" xmlns="http://www.w3.org/2000/svg" class="todo " preserveAspectRatio="xMidYMid meet">
<line x1="0.5" y1="2.18557e-8" x2="0.499997" y2="64" stroke="#E5E7EB"></line>
</svg>
<div class="todo flex flex-col justify-center items-stretch grow gap-2">
<div class="flex flex-col justify-center items-stretch grow gap-2">
<div class="flex justify-start items-center relative gap-3 p-1.5 rounded-md bg-white">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" class=" w-5 h-5 relative" preserveAspectRatio="xMidYMid meet">
<path d="M17.5 17.5L12.5 12.5M14.1667 8.33333C14.1667 9.09938 14.0158 9.85792 13.7226 10.5657C13.4295 11.2734 12.9998 11.9164 12.4581 12.4581C11.9164 12.9998 11.2734 13.4295 10.5657 13.7226C9.85792 14.0158 9.09938 14.1667 8.33333 14.1667C7.56729 14.1667 6.80875 14.0158 6.10101 13.7226C5.39328 13.4295 4.75022 12.9998 4.20854 12.4581C3.66687 11.9164 3.23719 11.2734 2.94404 10.5657C2.65088 9.85792 2.5 9.09938 2.5 8.33333C2.5 6.78624 3.11458 5.30251 4.20854 4.20854C5.30251 3.11458 6.78624 2.5 8.33333 2.5C9.88043 2.5 11.3642 3.11458 12.4581 4.20854C13.5521 5.30251 14.1667 6.78624 14.1667 8.33333Z" stroke="#9CA3AF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<p class="grow text-base text-left text-gray-400">Vyhľadaj správu</p>
<%= form_with url: message_threads_path, method: :get, html: { style: 'width: 100%', class: 'relative' } do |f| %>
<%= f.label :q, class: 'flex' do %>
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" class="absolute top-2.5 left-3 w-5 h-5" preserveAspectRatio="xMidYMid meet">
<path d="M17.5 17.5L12.5 12.5M14.1667 8.33333C14.1667 9.09938 14.0158 9.85792 13.7226 10.5657C13.4295 11.2734 12.9998 11.9164 12.4581 12.4581C11.9164 12.9998 11.2734 13.4295 10.5657 13.7226C9.85792 14.0158 9.09938 14.1667 8.33333 14.1667C7.56729 14.1667 6.80875 14.0158 6.10101 13.7226C5.39328 13.4295 4.75022 12.9998 4.20854 12.4581C3.66687 11.9164 3.23719 11.2734 2.94404 10.5657C2.65088 9.85792 2.5 9.09938 2.5 8.33333C2.5 6.78624 3.11458 5.30251 4.20854 4.20854C5.30251 3.11458 6.78624 2.5 8.33333 2.5C9.88043 2.5 11.3642 3.11458 12.4581 4.20854C13.5521 5.30251 14.1667 6.78624 14.1667 8.33333Z" stroke="#9CA3AF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<% end %>
<%= f.search_field :q, value: params[:q], placeholder: 'Vyhľadaj správu', class: 'pl-10 text-base text-left text-gray-900 placeholder-gray-400', style: 'width: 100%' %>
<% end %>

</div>
</div>
<svg width="1" height="64" viewBox="0 0 1 64" fill="none" xmlns="http://www.w3.org/2000/svg" class=" " preserveAspectRatio="xMidYMid meet">
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/admin/tags_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def set_tag
end

def tag_params
params.require(:tag).permit(:name, :visible, :user_id)
params.require(:tag).permit(:name, :visible, :user_id, :tenant_id)
end

def tag_params_visibility
Expand Down
74 changes: 24 additions & 50 deletions app/controllers/message_threads_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,19 @@ def update

def index
authorize MessageThread
@cursor = params[:cursor] || {}
@cursor[DELIVERED_AT] = @cursor[DELIVERED_AT] ? millis_to_time(@cursor[DELIVERED_AT]) : Time.now

@message_threads, @next_cursor =
Pagination.paginate(
collection: message_threads_collection,
cursor: {
DELIVERED_AT => @cursor[DELIVERED_AT],
ID => @cursor[ID]
},
items_per_page: MESSAGE_THREADS_PER_PAGE,
direction: 'desc'
)
cursor = MessageThreadCollection.init_cursor(search_params[:cursor])

@next_cursor[DELIVERED_AT] = time_to_millis(@next_cursor[DELIVERED_AT]) if @next_cursor
# TODO: Toto reviewnime pls niekedy(to_unsage_h). Chcelo by elegantnejsie riesenie, ale domotal som sa v tom
@next_page_params = params.to_unsafe_h.merge(cursor: @next_cursor).merge(format: :turbo_stream)
@message_threads, @next_cursor = MessageThreadCollection.all(
scope: message_thread_policy_scope.includes(:tags),
search_permissions: search_permissions,
query: search_params[:q],
no_visible_tags: search_params[:no_visible_tags] == '1' && Current.user.admin?,
cursor: cursor
)

@next_cursor = MessageThreadCollection.serialize_cursor(@next_cursor)
@next_page_params = search_params.to_h.merge(cursor: @next_cursor).merge(format: :turbo_stream)

respond_to do |format|
format.html # GET
Expand All @@ -44,7 +40,7 @@ def index

def merge
authorize MessageThread
@selected_message_threads = policy_scope(MessageThread).where(id: params[:message_thread_ids]).order(:last_message_delivered_at)
@selected_message_threads = message_thread_policy_scope.where(id: params[:message_thread_ids]).order(:last_message_delivered_at)
if !@selected_message_threads || @selected_message_threads.size < 2
flash[:error] = 'Označte zaškrtávacími políčkami minimálne 2 vlákna, ktoré chcete spojiť'
redirect_back fallback_location: message_threads_path
Expand All @@ -57,47 +53,25 @@ def merge

private

MESSAGE_THREADS_PER_PAGE = 20
DELIVERED_AT = 'message_threads.last_message_delivered_at'
ID = 'message_threads.id'

def message_threads_collection
@message_threads_collection = policy_scope(MessageThread).includes(:tags).includes(:messages)
@message_threads_collection =
@message_threads_collection #.where(ts: { id: params[:tag_id] }) if params[:tag_id]
.where(message_threads: { id: MessageThread.joins(:tags).where(tags: { id: params[:tag_id] }) }) if params[:tag_id]
if params[:tags] && params[:tags] == 'none' && Current.user.admin?
@message_threads_collection =
@message_threads_collection.where.not(message_threads: { id: (MessageThread.joins(:tags).where('tags.name not like ?', 'slovensko.sk:%')) })
end
add_calculated_fields
end

def add_calculated_fields
@message_threads_collection.select(
'message_threads.*',
# TODO: - mame tu velmi hruby sposob ako zistit, s kym je dany thread komunikacie, vedeny, len pre ucely zobrazenia. Dohodnut aj s @Taja, co s tym
'(select count(messages.id) from messages where messages.message_thread_id = message_threads.id) as messages_count,
coalesce((select max(coalesce(recipient_name)) from messages where messages.message_thread_id = message_threads.id),
(select max(coalesce(sender_name)) from messages where messages.message_thread_id = message_threads.id)) as with_whom',
# last_message_id - potrebujeme kvoli spravnej linke na konkretny message, ktory chceme otvorit, a nech to netahame potom pre kazdy thread
'(select max(messages.id) from messages where messages.message_thread_id = message_threads.id and messages.delivered_at = message_threads.last_message_delivered_at) as last_message_id'
)
def set_message_thread
@message_thread = message_thread_policy_scope.find(params[:id])
end

def time_to_millis(time)
time.strftime('%s%L').to_f
def message_thread_policy_scope
policy_scope(MessageThread)
end

def millis_to_time(millis)
Time.at(millis.to_f / 1000)
def search_permissions
result = { tenant_id: Current.tenant }
result[:tag_ids] = policy_scope(Tag).pluck(:id) unless Current.user.admin?
result
end

def set_message_thread
@message_thread = policy_scope(MessageThread).find(params[:id])
def message_thread_params
params.require(:message_thread).permit(:title, :original_title, :merge_uuids, :tag_id, :tags)
end

def message_thread_params
params.require(:message_thread).permit(:title, :original_title, :merge_uuids, :tag_id, :tags, :format, cursor: [DELIVERED_AT, ID])
def search_params
params.permit(:q, :no_visible_tags, :format, cursor: MessageThreadCollection::CURSOR_PARAMS)
end
end
10 changes: 10 additions & 0 deletions app/jobs/govbox/destroy_box_data_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module Govbox
class DestroyBoxDataJob < ApplicationJob
queue_as :default

def perform(box_id)
Govbox::ApiConnection.find_by(box_id: box_id).destroy
Govbox::Folder.where(box_id: box_id).destroy_all
end
end
end
2 changes: 2 additions & 0 deletions app/jobs/govbox/process_message_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module Govbox
class ProcessMessageJob < ApplicationJob
queue_as :default

retry_on ::Govbox::Message::FailedToAcquireLockError, wait: :exponentially_longer, attempts: Float::INFINITY

def perform(govbox_message)
ActiveRecord::Base.transaction do
Govbox::Message.create_message_with_thread!(govbox_message)
Expand Down
41 changes: 22 additions & 19 deletions app/jobs/govbox/submit_message_draft_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,24 @@ def perform(message_draft, upvs_client: UpvsEnvironment.upvs_client)
}.compact

sktalk_api = upvs_client.api(message_draft.thread.folder.box).sktalk
success, response_status, response_body = sktalk_api.receive_and_save_to_outbox(message_draft_data)

begin
success, response_status = sktalk_api.receive_and_save_to_outbox(message_draft_data)
if success
message_draft.metadata["status"] = "submitted"
Govbox::SyncBoxJob.set(wait: 3.minutes).perform_later(message_draft.thread.folder.box)
else
handle_submit_fail(message_draft, response_status)
end

message_draft.save!
rescue Error => error
message_draft.metadata["status"] = "submit_failed_temporary"
if success
message_draft.metadata["status"] = "submitted"
message_draft.save!

raise error
Govbox::SyncBoxJob.set(wait: 3.minutes).perform_later(message_draft.thread.folder.box)
else
handle_submit_fail(message_draft, response_status, response_body.dig("message"))
end
end

class SubmissionError < StandardError
end

class TemporarySubmissionError < SubmissionError
end

private

def build_objects(message_draft)
Expand All @@ -52,14 +51,18 @@ def build_objects(message_draft)
objects
end

def handle_submit_fail(message_draft, response_status)
def handle_submit_fail(message_draft, response_status, response_message)
case response_status
when 408
# TODO
when 422
message_draft.metadata["status"] = "submit_failed_unprocessable"
when 408, 503
message_draft.metadata["status"] = "temporary_submit_fail"
message_draft.save

raise TemporarySubmissionError, "#{response_status}, #{response_message}"
else
message_draft.metadata["status"] = "submit_failed_temporary"
message_draft.metadata["status"] = "submit_fail"
message_draft.save

raise SubmissionError, "#{response_status}, #{response_message}"
end
end
end
3 changes: 1 addition & 2 deletions app/jobs/govbox/sync_box_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@ def find_or_create_folder_with_parent(folder_hash, folders, box)
parent_folder = find_or_create_folder_with_parent(folders[folder_hash['parent_id']], folders, box)
end

folder = Govbox::Folder.find_or_initialize_by(edesk_folder_id: folder_hash['id']).tap do |f|
folder = Govbox::Folder.find_or_initialize_by(edesk_folder_id: folder_hash['id'], box: box).tap do |f|
f.edesk_folder_id = folder_hash['id']
f.parent_folder = parent_folder
f.name = folder_hash['name']
f.system = folder_hash['system'] || false
f.box = box
f.save!
end

Expand Down
2 changes: 1 addition & 1 deletion app/jobs/govbox/sync_folder_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def perform(folder, upvs_client: UpvsEnvironment.upvs_client, batch_size: 1000)

raise "Unable to fetch folder messages" if response_status != 200

edesk_message_ids_to_folder_ids = Govbox::Message.where(edesk_message_id: raw_messages.pluck('id')).pluck(:edesk_message_id, :folder_id).to_h
edesk_message_ids_to_folder_ids = Govbox::Message.joins(:folder).where(folder: { box_id: folder.box.id }).where(edesk_message_id: raw_messages.pluck('id')).pluck(:edesk_message_id, :folder_id).to_h
moved_edesk_message_ids = []

raw_messages.each do |raw_message|
Expand Down
7 changes: 7 additions & 0 deletions app/jobs/searchable/reindex_message_thread_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Searchable::ReindexMessageThreadJob < ApplicationJob
queue_as :default

def perform(message_thread)
::Searchable::MessageThread.index_record(message_thread)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Searchable::ReindexMessageThreadsWithTagIdJob < ApplicationJob
queue_as :default

def perform(tag_id)
::Searchable::MessageThread.reindex_with_tag_id(tag_id)
end
end
7 changes: 7 additions & 0 deletions app/lib/event_bus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,10 @@ def self.reset!
# wiring
EventBus.subscribe_job :message_thread_created, Automation::MessageThreadCreatedJob
EventBus.subscribe_job :message_created, Automation::MessageCreatedJob
EventBus.subscribe :message_changed, ->(message) { Searchable::ReindexMessageThreadJob.perform_later(message.thread) }
EventBus.subscribe_job :message_thread_changed, Searchable::ReindexMessageThreadJob
EventBus.subscribe :message_thread_tag_changed,
->(message_thread_tag) { Searchable::ReindexMessageThreadJob.perform_later(message_thread_tag.message_thread) }
EventBus.subscribe :tag_renamed, ->(tag) { Searchable::ReindexMessageThreadsWithTagIdJob.perform_later(tag.id) }
EventBus.subscribe :tag_removed, ->(tag) { Searchable::ReindexMessageThreadsWithTagIdJob.perform_later(tag.id) }
EventBus.subscribe :box_destroyed, ->(box_id) { Govbox::DestroyBoxDataJob.perform_later(box_id) }
Loading

0 comments on commit 452edc4

Please sign in to comment.