diff --git a/app/assets/javascripts/sitewide/print_progress_modal.js b/app/assets/javascripts/sitewide/print_progress_modal.js new file mode 100644 index 000000000..217b35d41 --- /dev/null +++ b/app/assets/javascripts/sitewide/print_progress_modal.js @@ -0,0 +1,32 @@ +function updateProgressModal() { + var status; + var modal = $(document).find('.label-printing-progress-modal'); + + if (modal.length === 0) { + return; + } + + $.getJSON( + `/label_printers/${modal.data('labelPrinterId')}/update_progress_modal` + + `?starting_item_count=${modal.data('startingItemCount')}`, + function(data) { + modal.replaceWith(data.html); + + status = modal.data('label-printer-status'); + if (status !== 'done' && status !== 'error') { + setTimeout(updateProgressModal, 3000); + } + } + ); +} + +$(document).on('click', '.label-printing-progress-modal .close', function() { + $(this).closest('.label-printing-progress-modal').remove(); +}); + +$(document).on('turbolinks:load', function() { + var modal = $(document).find('.label-printing-progress-modal'); + if (modal.length > 0) { + updateProgressModal(); + } +}); diff --git a/app/assets/javascripts/sitewide/repository_row_info_modal.js b/app/assets/javascripts/sitewide/repository_row_info_modal.js index b80b1029f..2160e2c88 100644 --- a/app/assets/javascripts/sitewide/repository_row_info_modal.js +++ b/app/assets/javascripts/sitewide/repository_row_info_modal.js @@ -67,7 +67,7 @@ $(this).remove(); }); - dropdownSelector.init('#modal-print-repository-row-label #printers', { + dropdownSelector.init('#modal-print-repository-row-label #label_printer_id', { noEmptyOption: true, singleSelect: true, closeOnSelect: true, diff --git a/app/assets/stylesheets/repository/print_progress_modal.scss b/app/assets/stylesheets/repository/print_progress_modal.scss index 99670fde0..984ecb69d 100644 --- a/app/assets/stylesheets/repository/print_progress_modal.scss +++ b/app/assets/stylesheets/repository/print_progress_modal.scss @@ -34,6 +34,12 @@ border-color: $brand-warning; color: $color-white; } + + &[data-status="error"] { + background: $brand-danger; + border-color: $brand-danger; + color: $color-white; + } } } @@ -52,7 +58,7 @@ color: $brand-success; } - &[data-status="waiting_labels"] { + &[data-status="waiting_labels"], &[data-status="error"] { color: $brand-danger; } } diff --git a/app/controllers/label_printers_controller.rb b/app/controllers/label_printers_controller.rb index 2bfe78332..e78243b6f 100644 --- a/app/controllers/label_printers_controller.rb +++ b/app/controllers/label_printers_controller.rb @@ -3,7 +3,7 @@ class LabelPrintersController < ApplicationController include InputSanitizeHelper - before_action :check_manage_permissions, except: :index + before_action :check_manage_permissions, except: %i(index update_progress_modal) before_action :find_label_printer, only: %i(edit update destroy) def index @@ -59,8 +59,22 @@ class LabelPrintersController < ApplicationController render json: { job_id: print_job.job_id } end + def update_progress_modal + render( + json: { + html: + render_to_string( + partial: 'label_printers/print_progress_modal', + locals: { + starting_item_count: params[:starting_item_count].to_i, + label_printer: LabelPrinter.find(params[:id]) + } + ) + } + ) + end + def create_fluics - # Placeholder for FLUICS printer management begin printers = LabelPrinters::Fluics::ApiClient.new(label_printer_params[:fluics_api_key]).list @@ -74,7 +88,10 @@ class LabelPrintersController < ApplicationController language_type: :zpl ) - label_printer.update(name: fluics_printer['serviceName']) + label_printer.update( + name: fluics_printer['serviceName'], + description: fluics_printer['comment'] + ) end rescue LabelPrinters::Fluics::ApiClient::BadRequestError flash[:error] = t('users.settings.account.label_printer.api_key_error') diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 6857e006d..5ff2ca8a4 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -49,12 +49,8 @@ class RepositoriesController < ApplicationController @display_delete_button = can_delete_repository_rows?(@repository) @display_duplicate_button = can_create_repository_rows?(@repository) @snapshot_provisioning = @repository.repository_snapshots.provisioning.any? - @printing = { - printer_name: 'Fluics label printer', - printer_status: :out_of_labels, - items: RepositoryRow.all, - printing_status: :waiting_labels - } + + @busy_printer = LabelPrinter.where.not(current_print_job_ids: []).first end def table_toolbar diff --git a/app/controllers/repository_rows_controller.rb b/app/controllers/repository_rows_controller.rb index 3aed09887..879db239c 100644 --- a/app/controllers/repository_rows_controller.rb +++ b/app/controllers/repository_rows_controller.rb @@ -73,7 +73,7 @@ class RepositoryRowsController < ApplicationController def print_modal @repository_rows = @repository.repository_rows.where(id: params[:rows]) - @printers = [] + @printers = LabelPrinter.all respond_to do |format| format.json do render json: { @@ -85,6 +85,29 @@ class RepositoryRowsController < ApplicationController end end + def print + label_printer = LabelPrinter.find(params[:label_printer_id]) + + # reset potential error state + label_printer.update!(status: :ready, current_print_job_ids: []) + + job_ids = RepositoryRow.where(id: params[:repository_row_ids]).flat_map do |repository_row| + Array.new(params[:copies].to_i).map do + LabelPrinters::PrintJob.perform_later( + label_printer, + LabelTemplate.first.render( # Currently we will only use the default template + item_id: repository_row.code, + item_name: repository_row.name + ) + ).job_id + end + end + + label_printer.update!(current_print_job_ids: job_ids) + + redirect_to repository_path(@repository) + end + def update row_update = RepositoryRows::UpdateRepositoryRowService .call(repository_row: @repository_row, user: current_user, params: update_params) diff --git a/app/jobs/label_printers/print_job.rb b/app/jobs/label_printers/print_job.rb index 96b4d4f54..2f95e70ce 100644 --- a/app/jobs/label_printers/print_job.rb +++ b/app/jobs/label_printers/print_job.rb @@ -2,8 +2,15 @@ module LabelPrinters class PrintJob < ApplicationJob + MAX_STATUS_UPDATES = 10 + queue_as :high_priority + discard_on(StandardError) do |job, _error| + label_printer = job.arguments.first + label_printer.update!(status: :error) + end + def perform(label_printer, payload) case label_printer.type_of when 'fluics' @@ -14,7 +21,25 @@ module LabelPrinters api_client.print(label_printer.fluics_lid, payload) # wait for FLUICS printer to stop being busy - sleep(5) while api_clinet.status(label_printer.fluics_lid).dig('printerState', 'printerStatus') != '00' + MAX_STATUS_UPDATES.times do + status = + LabelPrinter::FLUICS_STATUS_MAP[ + api_client.status(label_printer.fluics_lid).dig('printerState', 'printerStatus') + ] + label_printer.update!(status: status) + + break if status == :ready + + sleep 5 + end + end + + # mark as unreachable if no final state is reached + label_printer.update!(status: :unreachable) unless label_printer.status.in? %w(ready out_of_labels) + + label_printer.with_lock do + label_printer.current_print_job_ids.delete(job_id) + label_printer.save! end end end diff --git a/app/models/label_printer.rb b/app/models/label_printer.rb index d05db4b26..0de3a17d9 100644 --- a/app/models/label_printer.rb +++ b/app/models/label_printer.rb @@ -1,14 +1,41 @@ # frozen_string_literal: true class LabelPrinter < ApplicationRecord + FLUICS_STATUS_MAP = Hash.new(:error).merge( + { + '00' => :ready, + '50' => :busy, + '60' => :busy, + '01' => :out_of_labels, + '02' => :out_of_labels + } + ).freeze + enum type_of: { fluics: 0 } enum language_type: { zpl: 0 } + enum status: { ready: 0, busy: 1, out_of_labels: 2, unreachable: 3, error: 4 } validates :name, presence: true validates :type_of, presence: true validates :language_type, presence: true - def ready? - true # TODO + def display_name + "#{name} • #{description}" + end + + def done? + current_print_job_ids.blank? && ready? + end + + def printing? + current_print_job_ids.any? && ready? + end + + def printing_status + return 'printing' if printing? + + return 'done' if done? + + status end end diff --git a/app/views/label_printers/_print_progress_modal.html.erb b/app/views/label_printers/_print_progress_modal.html.erb new file mode 100644 index 000000000..c5f1656f1 --- /dev/null +++ b/app/views/label_printers/_print_progress_modal.html.erb @@ -0,0 +1,27 @@ +
+ + +
diff --git a/app/views/label_printers/index.html.erb b/app/views/label_printers/index.html.erb index 80c265f3d..4ce103a74 100644 --- a/app/views/label_printers/index.html.erb +++ b/app/views/label_printers/index.html.erb @@ -88,7 +88,7 @@ <% if @label_printers.any? %> <% @label_printers.each do |printer| %>
  • - <%= printer.name %> + <%= printer.name %> • <%= printer.description %>
  • <% end %> <% else %> diff --git a/app/views/repositories/_print_label_modal.html.erb b/app/views/repositories/_print_label_modal.html.erb index e9421ce14..5c469e06f 100644 --- a/app/views/repositories/_print_label_modal.html.erb +++ b/app/views/repositories/_print_label_modal.html.erb @@ -1,34 +1,38 @@