Yu-Gi-Oh! Deck Building and Card Inventory Management web interface written in Common Lisp, utilizing HTMX.
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
6.1KB

  1. #|
  2. src/web/label-maker.lisp
  3. Label Maker Front-End
  4. https://www.uline.com/product/detail/s-20247/store-fixtures/price-tag-insert-cards-1-1-4-x-2
  5. Supports arbitrary number of labels.
  6. Currently tested with LABELS-LENGTH set to 32 (ULINE S-20247) or 30 (Avery 5160).
  7. We generate a LaTeX file then use PDFLaTeX to produce a pdf in
  8. GENERATE-LABELS-FOR-ATTACHMENT-ID.
  9. The barcodes are generated by ZXingWriter.
  10. TODO A lot of functionality that resides in the web interface needs to be moved to the model interface:
  11. - public-relative-pathname
  12. - generate-labels
  13. - generate-labels-for-attachment
  14. - generate-labels-for-attachment-id
  15. - *current-label-class*
  16. |#
  17. (in-package #:cl-user)
  18. (defpackage #:cl-deck-builder2.web.label-maker
  19. (:use #:cl
  20. #:cl-deck-builder2.models.label-maker)
  21. (:import-from #:caveman2
  22. #:<app>
  23. #:defroute
  24. #:redirect
  25. #:clear-routing-rules)
  26. (:import-from #:cl-deck-builder2.i18n
  27. #:_)
  28. (:import-from #:cl-deck-builder2.toolkit
  29. #:query-param
  30. #:random-pathname-name)
  31. (:import-from #:cl-deck-builder2.web
  32. #:flash-error
  33. #:flash-message
  34. #:render-with-env
  35. #:render-markdown-file)
  36. (:import-from #:cl-deck-builder2.web.query
  37. #:select-attachment-by-id)
  38. (:import-from #:cl-deck-builder2.models.attachment
  39. #:attachment-valid-p
  40. #:create-attachment)
  41. (:import-from #:cl-deck-builder2.config
  42. #:*public-directory*
  43. #:*static-directory*
  44. #:*template-directory*)
  45. (:local-nicknames (#:v #:org.shirakumo.verbose))
  46. (:export #:*web*))
  47. (in-package #:cl-deck-builder2.web.label-maker)
  48. (defclass <web> (<app>) ())
  49. (defvar *web* (make-instance '<web>))
  50. (clear-routing-rules *web*)
  51. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  52. (defparameter *base-pathspec* #P"/tmp/labels/")
  53. (defparameter *current-label-class* 'latex-label-uline-s-20247
  54. "The most recently used class for making labels.
  55. The idea was you could select the types of labels from a select box on the Label Maker page.")
  56. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  57. (defun public-relative-pathname (pathspec)
  58. "PROBE-FILE on PATHSPEC in *PUBLIC-DIRECTORY*.
  59. TODO I think this is duplicate code from TOOLKIT.PATHS."
  60. (probe-file
  61. (merge-pathnames
  62. pathspec
  63. cl-deck-builder2.config:*public-directory*)))
  64. ;; TODO All of this needs to be rewritten in some kind of pipeline form.
  65. (defun generate-labels (output &key (class 'latex-label-uline-s-20247) csv pdf tex)
  66. "Create output with RENDER-PAGE."
  67. (ensure-directories-exist *base-pathspec*)
  68. (let ((page (make-instance class :csv csv)))
  69. (with-open-file (s tex
  70. :if-exists :supersede
  71. :direction :output)
  72. (format s "~a" (render-page page))))
  73. (uiop:delete-file-if-exists (probe-file #P"~/public/labels.pdf"))
  74. (if (inferior-shell:run
  75. `(and
  76. (cd "/tmp/labels/")
  77. (pdflatex ,tex)
  78. (mv ,pdf ,output)))
  79. output))
  80. ;; TODO ENOUGH-PATHNAME
  81. ;; TODO rewrite this using defclass like we did for CARDINFO
  82. (defun generate-labels-for-attachment (path file-key)
  83. (generate-labels (make-pathname :name file-key
  84. :type "pdf"
  85. :directory (namestring *public-directory*))
  86. :class *current-label-class*
  87. :csv path
  88. :tex #P"/tmp/labels/labels.tex"
  89. :pdf #P"/tmp/labels/labels.pdf"))
  90. (defun generate-labels-for-attachment-id (id)
  91. (let ((found (select-attachment-by-id id)))
  92. (when found
  93. (generate-labels-for-attachment
  94. (public-relative-pathname
  95. (;; Trim leading "/"
  96. subseq
  97. (namestring (mito-attachment:file-url found)) 1))
  98. (pathname-name
  99. (mito-attachment:file-key found))))))
  100. (defun label-maker-process-files (files)
  101. "Process FILES with ATTACHMENT-VALID-P, CREATE-ATTACHMENT, then GENERATE-LABELS-FOR-ATTACHMENT-ID."
  102. (dolist (file files)
  103. (if (attachment-valid-p file)
  104. (destructuring-bind (content filename content-type)
  105. file
  106. (setf filename (random-pathname-name :type (pathname-type filename)))
  107. (let ((success (create-attachment content filename content-type)))
  108. (if success
  109. (progn
  110. ;; Create ATTACHMENT was successful
  111. (generate-labels-for-attachment-id (mito:object-id success))
  112. (flash-message (format nil (_ "Success! Download link: <a href=\"/public/~a.pdf\">labels.pdf</a>")
  113. (pathname-name
  114. (mito-attachment:file-key success)))))
  115. (flash-error (_ "Something went wrong. Try again?")))))
  116. (flash-error (_ "Invalid upload.")))))
  117. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  118. (defroute ("/" :method :GET) ()
  119. "Label Maker Main Route."
  120. (render-with-env #P"label-maker.html"
  121. `(:active "/label-maker")))
  122. (defroute ("/instructions" :method :GET) ()
  123. "Display Label Maker Instructions using RENDER-MARKDOWN-FILE."
  124. (render-markdown-file
  125. (asdf:system-relative-pathname :cl-deck-builder2 "doc/label-maker.md")))
  126. (defroute ("/" :method :POST) (&key _parsed)
  127. "Label Maker POST route.
  128. TODO Parameters: FILES A list of CSV files to process. CLASS the class of label you wish to generate. May be one of LATEX-LABEL-ULINE-S-20247 or LATEX-LABEL-AVERY-5160."
  129. (v:info :label-maker "POST /label-maker => ~a" _parsed)
  130. (let ((files (query-param "files" _parsed))
  131. (class (query-param "class" _parsed)))
  132. ;; Check the CLASS parameter
  133. (setf *current-label-class*
  134. (find-class
  135. (cond ((string= class "latex-label-uline-s-20247") 'latex-label-uline-s-20247)
  136. (t 'latex-label-avery-5160))))
  137. (if files
  138. (label-maker-process-files files)
  139. (flash-error (_ "No files.")))
  140. (redirect "/label-maker")))