Redesign: clear active nav state, Shipping labels + Receipts get free-text/raw print, shared label repository
deploy / deploy (push) Successful in 10s

- Home page is now just the print server overview, no more unrelated
  network links (3D printers, Cockpit) left over from when this was a
  general landing page.
- Navbar shows which section is active; Brother's per-printer buttons
  now live under a dedicated Brother nav item instead of always-visible.
- Shipping labels: paste raw ZPL directly (no need to save to a file
  first), with a Labelary preview link alongside it.
- Receipts: paste already-formatted ESC/POS text directly, printed as-is.
- Both can save what they just printed into a shared label repository
  (lib/label_repository.rb, one JSON file per label under data/labels/)
  for reprinting later -- saving happens independently of whether the
  print itself succeeds, so a failed/offline printer doesn't lose the
  content.
This commit is contained in:
randy committed 2026-09-13 11:11:12 +02:00
1 parent afae57aff4
commit 66e2e7a5c0
8 files changed
+226 -53

No files matched your search

+74
View File
@@ -4,6 +4,7 @@ require "sinatra/reloader"
require 'tmpdir'
require 'net/http'
require_relative 'lib/receipt_builder'
require_relative 'lib/label_repository'
set :protection, :except => :frame_options
set :environment, :production
@@ -24,6 +25,8 @@ TEST_LABEL_PDF = File.join(File.dirname(__FILE__), 'test-label.pdf')
PRINTER_DEVICE_EPSON = '/dev/usb/lp_epson' # see /etc/udev/rules.d/99-epson.rules
LABEL_REPO = LabelRepository.new(File.join(File.dirname(__FILE__), 'data', 'labels'))
BROTHER_PRINTERS = {
'ql560' => { port: 8560, label: 'Brother QL-560' },
'ql700' => { port: 8700, label: 'Brother QL-700' },
@@ -104,6 +107,16 @@ helpers do
receipt.print!(PRINTER_DEVICE_EPSON)
end
# Prints already-formatted ESC/POS text as-is (just the reset + code page
# prefix and a trailing cut) -- for content prepared elsewhere or reprinted
# from the label repository, unlike print_receipt's title/body template.
def print_raw_escpos(content)
receipt = ReceiptBuilder.new
receipt.align(:left).text(content)
receipt.feed(3).cut
receipt.print!(PRINTER_DEVICE_EPSON)
end
# Transparently reverse-proxies the current request to one of the
# brother_ql_web instances, so all three printers (web UI and API alike)
# are reachable through this single sinatra port instead of their own
@@ -153,9 +166,26 @@ get '/' do
end
get '/upload' do
@labels = LABEL_REPO.all(type: 'zpl')
erb :upload
end
post '/shipping/zpl' do
zpl = params[:zpl].to_s
if zpl.strip.empty?
flash 'ZPL text is empty', 'warning'
else
LABEL_REPO.save(name: params[:save_as], type: 'zpl', content: zpl) unless params[:save_as].to_s.empty?
begin
print_to_datamax(zpl)
flash 'ZPL sent to printer', 'success'
rescue => e
flash "ZPL print failed (#{e.message})", 'danger'
end
end
redirect '/upload'
end
post '/upload' do
if params[:file]
@@ -204,6 +234,7 @@ post '/test-print' do
end
get '/epson' do
@labels = LABEL_REPO.all(type: 'escpos')
erb :epson
end
@@ -217,6 +248,49 @@ post '/epson/print' do
redirect '/epson'
end
post '/epson/raw' do
content = params[:content].to_s
if content.strip.empty?
flash 'Receipt text is empty', 'warning'
else
LABEL_REPO.save(name: params[:save_as], type: 'escpos', content: content) unless params[:save_as].to_s.empty?
begin
print_raw_escpos(content)
flash 'Sent to Epson printer', 'success'
rescue => e
flash "Epson print failed (#{e.message})", 'danger'
end
end
redirect '/epson'
end
post '/labels/:id/print' do
label = LABEL_REPO.find(params[:id])
halt 404, 'unknown label' unless label
begin
case label['type']
when 'zpl'
print_to_datamax(label['content'])
when 'escpos'
print_raw_escpos(label['content'])
end
flash "Printed '#{label['name']}'", 'success'
rescue => e
flash "Print failed (#{e.message})", 'danger'
end
redirect_target = label['type'] == 'zpl' ? '/upload' : '/epson'
redirect redirect_target
end
post '/labels/:id/delete' do
label = LABEL_REPO.find(params[:id])
redirect_target = label && label['type'] == 'zpl' ? '/upload' : '/epson'
LABEL_REPO.delete(params[:id])
flash 'Label deleted', 'success'
redirect redirect_target
end
get '/brother' do
@printers = BROTHER_PRINTERS
erb :brother_picker