codex 1.6.0a4__py3-none-any.whl → 1.6.0a6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of codex might be problematic. Click here for more details.

Files changed (568) hide show
  1. codex/exceptions.py +17 -6
  2. codex/integrity.py +67 -3
  3. codex/librarian/covers/coverd.py +2 -2
  4. codex/librarian/covers/create.py +29 -13
  5. codex/librarian/covers/path.py +8 -6
  6. codex/librarian/covers/purge.py +28 -18
  7. codex/librarian/covers/tasks.py +3 -2
  8. codex/librarian/importer/aggregate_metadata.py +2 -2
  9. codex/librarian/importer/const.py +31 -3
  10. codex/librarian/importer/covers.py +47 -0
  11. codex/librarian/importer/create_fks.py +88 -28
  12. codex/librarian/importer/deleted.py +71 -9
  13. codex/librarian/importer/importerd.py +133 -28
  14. codex/librarian/importer/link_comics.py +55 -0
  15. codex/librarian/importer/moved.py +78 -3
  16. codex/librarian/importer/query_fks.py +65 -1
  17. codex/librarian/importer/status.py +6 -0
  18. codex/librarian/importer/tasks.py +11 -3
  19. codex/librarian/importer/update_comics.py +1 -5
  20. codex/librarian/janitor/cleanup.py +24 -0
  21. codex/librarian/janitor/failed_imports.py +1 -1
  22. codex/librarian/janitor/janitor.py +5 -0
  23. codex/librarian/janitor/janitord.py +1 -1
  24. codex/librarian/janitor/status.py +1 -0
  25. codex/librarian/janitor/tasks.py +5 -0
  26. codex/librarian/librariand.py +3 -3
  27. codex/librarian/search/update.py +1 -1
  28. codex/librarian/watchdog/db_snapshot.py +9 -6
  29. codex/librarian/watchdog/emitter.py +3 -0
  30. codex/librarian/watchdog/event_batcherd.py +19 -3
  31. codex/librarian/watchdog/events.py +176 -36
  32. codex/librarian/watchdog/observers.py +13 -3
  33. codex/migrations/0027_sort_name.py +2 -12
  34. codex/migrations/0028_custom_covers.py +166 -0
  35. codex/migrations/0029_choices_adminflag_and_timestamp.py +44 -0
  36. codex/models/admin.py +0 -2
  37. codex/models/base.py +3 -0
  38. codex/models/comic.py +15 -9
  39. codex/models/groups.py +30 -14
  40. codex/models/library.py +11 -3
  41. codex/models/paths.py +62 -14
  42. codex/models/{const.py → util.py} +15 -2
  43. codex/serializers/admin.py +11 -2
  44. codex/serializers/browser/mixins.py +1 -0
  45. codex/serializers/browser/page.py +0 -1
  46. codex/serializers/browser/settings.py +3 -0
  47. codex/settings/settings.py +11 -5
  48. codex/startup.py +77 -3
  49. codex/static_root/assets/{VCheckbox-CN6Sn_k7.9bf27129091c.js → VCheckbox-BS5fdM4M.a5d446e4aeb3.js} +1 -1
  50. codex/static_root/assets/VCheckbox-BS5fdM4M.a5d446e4aeb3.js.br +0 -0
  51. codex/static_root/assets/VCheckbox-BS5fdM4M.a5d446e4aeb3.js.gz +0 -0
  52. codex/static_root/assets/{VCheckbox-CN6Sn_k7.js → VCheckbox-BS5fdM4M.js} +1 -1
  53. codex/static_root/assets/VCheckbox-BS5fdM4M.js.br +0 -0
  54. codex/static_root/assets/VCheckbox-BS5fdM4M.js.gz +0 -0
  55. codex/static_root/assets/{VCheckboxBtn-CN1RPZPQ.b763c6a7abaf.js → VCheckboxBtn-m4IbdjEe.f0c4a814ded8.js} +1 -1
  56. codex/static_root/assets/VCheckboxBtn-m4IbdjEe.f0c4a814ded8.js.br +0 -0
  57. codex/static_root/assets/VCheckboxBtn-m4IbdjEe.f0c4a814ded8.js.gz +0 -0
  58. codex/static_root/assets/{VCheckboxBtn-CN1RPZPQ.js → VCheckboxBtn-m4IbdjEe.js} +1 -1
  59. codex/static_root/assets/VCheckboxBtn-m4IbdjEe.js.br +0 -0
  60. codex/static_root/assets/VCheckboxBtn-m4IbdjEe.js.gz +0 -0
  61. codex/static_root/assets/VCombobox-jg7SI5mn.af66f18b4c54.js +1 -0
  62. codex/static_root/assets/VCombobox-jg7SI5mn.af66f18b4c54.js.br +0 -0
  63. codex/static_root/assets/VCombobox-jg7SI5mn.af66f18b4c54.js.gz +0 -0
  64. codex/static_root/assets/VCombobox-jg7SI5mn.js +1 -0
  65. codex/static_root/assets/VCombobox-jg7SI5mn.js.br +0 -0
  66. codex/static_root/assets/VCombobox-jg7SI5mn.js.gz +0 -0
  67. codex/static_root/assets/{VDialog-DC3KGsMT.71e2a460e44b.js → VDialog-DiixpkQL.f84fd1fd1f84.js} +1 -1
  68. codex/static_root/assets/VDialog-DiixpkQL.f84fd1fd1f84.js.br +0 -0
  69. codex/static_root/assets/VDialog-DiixpkQL.f84fd1fd1f84.js.gz +0 -0
  70. codex/static_root/assets/{VDialog-DC3KGsMT.js → VDialog-DiixpkQL.js} +1 -1
  71. codex/static_root/assets/VDialog-DiixpkQL.js.br +0 -0
  72. codex/static_root/assets/VDialog-DiixpkQL.js.gz +0 -0
  73. codex/static_root/assets/{VExpansionPanels-DJQYXCn2.f0d471a1b80a.js → VExpansionPanels-Db5mPFue.56d0ad094a62.js} +1 -1
  74. codex/static_root/assets/VExpansionPanels-Db5mPFue.56d0ad094a62.js.br +0 -0
  75. codex/static_root/assets/VExpansionPanels-Db5mPFue.56d0ad094a62.js.gz +0 -0
  76. codex/static_root/assets/{VExpansionPanels-DJQYXCn2.js → VExpansionPanels-Db5mPFue.js} +1 -1
  77. codex/static_root/assets/VExpansionPanels-Db5mPFue.js.br +0 -0
  78. codex/static_root/assets/VExpansionPanels-Db5mPFue.js.gz +0 -0
  79. codex/static_root/assets/{VRadioGroup-CgodTThy.b20290d57146.js → VRadioGroup-DULWiMSI.4ae535e01d2b.js} +1 -1
  80. codex/static_root/assets/VRadioGroup-DULWiMSI.4ae535e01d2b.js.br +0 -0
  81. codex/static_root/assets/VRadioGroup-DULWiMSI.4ae535e01d2b.js.gz +0 -0
  82. codex/static_root/assets/{VRadioGroup-CgodTThy.js → VRadioGroup-DULWiMSI.js} +1 -1
  83. codex/static_root/assets/VRadioGroup-DULWiMSI.js.br +0 -0
  84. codex/static_root/assets/VRadioGroup-DULWiMSI.js.gz +0 -0
  85. codex/static_root/assets/VSelect-BnoCfCLY.4d50fd11c77c.js +1 -0
  86. codex/static_root/assets/VSelect-BnoCfCLY.4d50fd11c77c.js.br +0 -0
  87. codex/static_root/assets/VSelect-BnoCfCLY.4d50fd11c77c.js.gz +0 -0
  88. codex/static_root/assets/VSelect-BnoCfCLY.js +1 -0
  89. codex/static_root/assets/VSelect-BnoCfCLY.js.br +0 -0
  90. codex/static_root/assets/VSelect-BnoCfCLY.js.gz +0 -0
  91. codex/static_root/assets/VSelect-MGVSeLgr.7cabd30bc5e4.css +1 -0
  92. codex/static_root/assets/VSelect-MGVSeLgr.7cabd30bc5e4.css.br +0 -0
  93. codex/static_root/assets/VSelect-MGVSeLgr.7cabd30bc5e4.css.gz +0 -0
  94. codex/static_root/assets/VSelect-MGVSeLgr.css +1 -0
  95. codex/static_root/assets/VSelect-MGVSeLgr.css.br +0 -0
  96. codex/static_root/assets/VSelect-MGVSeLgr.css.gz +0 -0
  97. codex/static_root/assets/{VSelectionControl-zPp4DXWq.635b7f5aa882.js → VSelectionControl-BSL0qeL9.5b5835d286df.js} +1 -1
  98. codex/static_root/assets/VSelectionControl-BSL0qeL9.5b5835d286df.js.br +0 -0
  99. codex/static_root/assets/VSelectionControl-BSL0qeL9.5b5835d286df.js.gz +0 -0
  100. codex/static_root/assets/{VSelectionControl-zPp4DXWq.js → VSelectionControl-BSL0qeL9.js} +1 -1
  101. codex/static_root/assets/VSelectionControl-BSL0qeL9.js.br +0 -0
  102. codex/static_root/assets/VSelectionControl-BSL0qeL9.js.gz +0 -0
  103. codex/static_root/assets/{VSlideGroup-pK9Xompk.67014b86fc74.js → VSlideGroup-BQtz8h9p.ff97dbf209e1.js} +1 -1
  104. codex/static_root/assets/VSlideGroup-BQtz8h9p.ff97dbf209e1.js.br +0 -0
  105. codex/static_root/assets/VSlideGroup-BQtz8h9p.ff97dbf209e1.js.gz +0 -0
  106. codex/static_root/assets/{VSlideGroup-pK9Xompk.js → VSlideGroup-BQtz8h9p.js} +1 -1
  107. codex/static_root/assets/VSlideGroup-BQtz8h9p.js.br +0 -0
  108. codex/static_root/assets/VSlideGroup-BQtz8h9p.js.gz +0 -0
  109. codex/static_root/assets/{VTable-CMi6sDtP.8445f91d9023.js → VTable-C0gAriFq.fa6e4b60d4ef.js} +1 -1
  110. codex/static_root/assets/VTable-C0gAriFq.fa6e4b60d4ef.js.br +0 -0
  111. codex/static_root/assets/VTable-C0gAriFq.fa6e4b60d4ef.js.gz +0 -0
  112. codex/static_root/assets/{VTable-CMi6sDtP.js → VTable-C0gAriFq.js} +1 -1
  113. codex/static_root/assets/VTable-C0gAriFq.js.br +0 -0
  114. codex/static_root/assets/VTable-C0gAriFq.js.gz +0 -0
  115. codex/static_root/assets/VTextField-BssVoDhB.4cc388b4aa3c.css +1 -0
  116. codex/static_root/assets/VTextField-BssVoDhB.4cc388b4aa3c.css.br +0 -0
  117. codex/static_root/assets/VTextField-BssVoDhB.4cc388b4aa3c.css.gz +0 -0
  118. codex/static_root/assets/VTextField-BssVoDhB.css +1 -0
  119. codex/static_root/assets/VTextField-BssVoDhB.css.br +0 -0
  120. codex/static_root/assets/VTextField-BssVoDhB.css.gz +0 -0
  121. codex/static_root/assets/VTextField-Da_Hs7ls.c295f24c251e.js +1 -0
  122. codex/static_root/assets/VTextField-Da_Hs7ls.c295f24c251e.js.br +0 -0
  123. codex/static_root/assets/VTextField-Da_Hs7ls.c295f24c251e.js.gz +0 -0
  124. codex/static_root/assets/VTextField-Da_Hs7ls.js +1 -0
  125. codex/static_root/assets/VTextField-Da_Hs7ls.js.br +0 -0
  126. codex/static_root/assets/VTextField-Da_Hs7ls.js.gz +0 -0
  127. codex/static_root/assets/{VWindowItem-DNsRQx9l.c42f636c386e.js → VWindowItem-CFhKCj49.b2458002a937.js} +1 -1
  128. codex/static_root/assets/VWindowItem-CFhKCj49.b2458002a937.js.br +0 -0
  129. codex/static_root/assets/VWindowItem-CFhKCj49.b2458002a937.js.gz +0 -0
  130. codex/static_root/assets/{VWindowItem-DNsRQx9l.js → VWindowItem-CFhKCj49.js} +1 -1
  131. codex/static_root/assets/VWindowItem-CFhKCj49.js.br +0 -0
  132. codex/static_root/assets/VWindowItem-CFhKCj49.js.gz +0 -0
  133. codex/static_root/assets/{admin-BbrOU9Y9.29936748af9e.css → admin-B8Bp2Uih.82c98714bcf1.css} +1 -1
  134. codex/static_root/assets/admin-B8Bp2Uih.82c98714bcf1.css.br +0 -0
  135. codex/static_root/assets/admin-B8Bp2Uih.82c98714bcf1.css.gz +0 -0
  136. codex/static_root/assets/{admin-BbrOU9Y9.css → admin-B8Bp2Uih.css} +1 -1
  137. codex/static_root/assets/admin-B8Bp2Uih.css.br +0 -0
  138. codex/static_root/assets/admin-B8Bp2Uih.css.gz +0 -0
  139. codex/static_root/assets/admin-BpGFsvOH.d7193c78d0dd.js +1 -0
  140. codex/static_root/assets/admin-BpGFsvOH.d7193c78d0dd.js.br +0 -0
  141. codex/static_root/assets/admin-BpGFsvOH.d7193c78d0dd.js.gz +0 -0
  142. codex/static_root/assets/admin-BpGFsvOH.js +1 -0
  143. codex/static_root/assets/admin-BpGFsvOH.js.br +0 -0
  144. codex/static_root/assets/admin-BpGFsvOH.js.gz +0 -0
  145. codex/static_root/assets/admin-drawer-panel-BHdNPwzF.bd2c1d6148bb.css +1 -0
  146. codex/static_root/assets/admin-drawer-panel-BHdNPwzF.bd2c1d6148bb.css.br +0 -0
  147. codex/static_root/assets/admin-drawer-panel-BHdNPwzF.bd2c1d6148bb.css.gz +0 -0
  148. codex/static_root/assets/admin-drawer-panel-BHdNPwzF.css +1 -0
  149. codex/static_root/assets/admin-drawer-panel-BHdNPwzF.css.br +0 -0
  150. codex/static_root/assets/admin-drawer-panel-BHdNPwzF.css.gz +0 -0
  151. codex/static_root/assets/admin-drawer-panel-C34Ze3-5.113c50cdf2cc.js +30 -0
  152. codex/static_root/assets/admin-drawer-panel-C34Ze3-5.113c50cdf2cc.js.br +0 -0
  153. codex/static_root/assets/admin-drawer-panel-C34Ze3-5.113c50cdf2cc.js.gz +0 -0
  154. codex/static_root/assets/admin-drawer-panel-C34Ze3-5.js +30 -0
  155. codex/static_root/assets/admin-drawer-panel-C34Ze3-5.js.br +0 -0
  156. codex/static_root/assets/admin-drawer-panel-C34Ze3-5.js.gz +0 -0
  157. codex/static_root/assets/browser-CRPvEdqv.f355a71f4380.js +1 -0
  158. codex/static_root/assets/browser-CRPvEdqv.f355a71f4380.js.br +0 -0
  159. codex/static_root/assets/browser-CRPvEdqv.f355a71f4380.js.gz +0 -0
  160. codex/static_root/assets/browser-CRPvEdqv.js +1 -0
  161. codex/static_root/assets/browser-CRPvEdqv.js.br +0 -0
  162. codex/static_root/assets/browser-CRPvEdqv.js.gz +0 -0
  163. codex/static_root/assets/browser-Zqc9cR6T.b7d6ddeff130.css +1 -0
  164. codex/static_root/assets/browser-Zqc9cR6T.b7d6ddeff130.css.br +0 -0
  165. codex/static_root/assets/browser-Zqc9cR6T.b7d6ddeff130.css.gz +0 -0
  166. codex/static_root/assets/browser-Zqc9cR6T.css +1 -0
  167. codex/static_root/assets/browser-Zqc9cR6T.css.br +0 -0
  168. codex/static_root/assets/browser-Zqc9cR6T.css.gz +0 -0
  169. codex/static_root/assets/{change-password-dialog-BHTkpC6Z.2d5d5dd57ad3.js → change-password-dialog-JYM9aAR9.f71d378f4fa6.js} +1 -1
  170. codex/static_root/assets/change-password-dialog-JYM9aAR9.f71d378f4fa6.js.br +0 -0
  171. codex/static_root/assets/change-password-dialog-JYM9aAR9.f71d378f4fa6.js.gz +0 -0
  172. codex/static_root/assets/{change-password-dialog-BHTkpC6Z.js → change-password-dialog-JYM9aAR9.js} +1 -1
  173. codex/static_root/assets/change-password-dialog-JYM9aAR9.js.br +0 -0
  174. codex/static_root/assets/change-password-dialog-JYM9aAR9.js.gz +0 -0
  175. codex/static_root/assets/{confirm-dialog-DmXGDg4z.284812bd376d.js → confirm-dialog-ZAZ6P1Rc.515858dd21e8.js} +1 -1
  176. codex/static_root/assets/confirm-dialog-ZAZ6P1Rc.515858dd21e8.js.br +0 -0
  177. codex/static_root/assets/confirm-dialog-ZAZ6P1Rc.515858dd21e8.js.gz +0 -0
  178. codex/static_root/assets/{confirm-dialog-DmXGDg4z.js → confirm-dialog-ZAZ6P1Rc.js} +1 -1
  179. codex/static_root/assets/confirm-dialog-ZAZ6P1Rc.js.br +0 -0
  180. codex/static_root/assets/confirm-dialog-ZAZ6P1Rc.js.gz +0 -0
  181. codex/static_root/assets/{datetime-column-DKaH5S3z.5c6042016200.js → datetime-column-BT1MSP82.9617f6b94ebf.js} +1 -1
  182. codex/static_root/assets/datetime-column-BT1MSP82.9617f6b94ebf.js.br +0 -0
  183. codex/static_root/assets/datetime-column-BT1MSP82.9617f6b94ebf.js.gz +0 -0
  184. codex/static_root/assets/{datetime-column-DKaH5S3z.js → datetime-column-BT1MSP82.js} +1 -1
  185. codex/static_root/assets/datetime-column-BT1MSP82.js.br +0 -0
  186. codex/static_root/assets/datetime-column-BT1MSP82.js.gz +0 -0
  187. codex/static_root/assets/{filter-DUVATQW3.e1e7aa6d0b18.js → filter-frSNsexx.eab1570bd32d.js} +1 -1
  188. codex/static_root/assets/filter-frSNsexx.eab1570bd32d.js.br +0 -0
  189. codex/static_root/assets/filter-frSNsexx.eab1570bd32d.js.gz +0 -0
  190. codex/static_root/assets/{filter-DUVATQW3.js → filter-frSNsexx.js} +1 -1
  191. codex/static_root/assets/filter-frSNsexx.js.br +0 -0
  192. codex/static_root/assets/filter-frSNsexx.js.gz +0 -0
  193. codex/static_root/assets/flag-tab-BNwbLfrN.b755a99fff7e.css +1 -0
  194. codex/static_root/assets/flag-tab-BNwbLfrN.b755a99fff7e.css.br +0 -0
  195. codex/static_root/assets/flag-tab-BNwbLfrN.b755a99fff7e.css.gz +0 -0
  196. codex/static_root/assets/flag-tab-BNwbLfrN.css +1 -0
  197. codex/static_root/assets/flag-tab-BNwbLfrN.css.br +0 -0
  198. codex/static_root/assets/flag-tab-BNwbLfrN.css.gz +0 -0
  199. codex/static_root/assets/flag-tab-Ci_XcDT0.a5ea640a08d6.js +1 -0
  200. codex/static_root/assets/flag-tab-Ci_XcDT0.a5ea640a08d6.js.br +0 -0
  201. codex/static_root/assets/flag-tab-Ci_XcDT0.a5ea640a08d6.js.gz +0 -0
  202. codex/static_root/assets/flag-tab-Ci_XcDT0.js +1 -0
  203. codex/static_root/assets/flag-tab-Ci_XcDT0.js.br +0 -0
  204. codex/static_root/assets/flag-tab-Ci_XcDT0.js.gz +0 -0
  205. codex/static_root/assets/{group-tab-D3CyU-Il.fbf9ce5ef593.js → group-tab-DFma2R-E.879c37b15bbd.js} +1 -1
  206. codex/static_root/assets/group-tab-DFma2R-E.879c37b15bbd.js.br +0 -0
  207. codex/static_root/assets/group-tab-DFma2R-E.879c37b15bbd.js.gz +0 -0
  208. codex/static_root/assets/{group-tab-D3CyU-Il.js → group-tab-DFma2R-E.js} +1 -1
  209. codex/static_root/assets/group-tab-DFma2R-E.js.br +0 -0
  210. codex/static_root/assets/group-tab-DFma2R-E.js.gz +0 -0
  211. codex/static_root/assets/{http-error-0ef6-Ajc.e2879bcd242f.js → http-error-B3fQGxpt.9efc29496e30.js} +1 -1
  212. codex/static_root/assets/http-error-B3fQGxpt.9efc29496e30.js.br +0 -0
  213. codex/static_root/assets/http-error-B3fQGxpt.9efc29496e30.js.gz +0 -0
  214. codex/static_root/assets/{http-error-0ef6-Ajc.js → http-error-B3fQGxpt.js} +1 -1
  215. codex/static_root/assets/http-error-B3fQGxpt.js.br +0 -0
  216. codex/static_root/assets/http-error-B3fQGxpt.js.gz +0 -0
  217. codex/static_root/assets/library-tab-BN0SfPcH.913e236f625e.css +1 -0
  218. codex/static_root/assets/library-tab-BN0SfPcH.913e236f625e.css.br +0 -0
  219. codex/static_root/assets/library-tab-BN0SfPcH.913e236f625e.css.gz +0 -0
  220. codex/static_root/assets/library-tab-BN0SfPcH.css +1 -0
  221. codex/static_root/assets/library-tab-BN0SfPcH.css.br +0 -0
  222. codex/static_root/assets/library-tab-BN0SfPcH.css.gz +0 -0
  223. codex/static_root/assets/library-tab-V8DUGoHN.809c548ff347.js +1 -0
  224. codex/static_root/assets/library-tab-V8DUGoHN.809c548ff347.js.br +0 -0
  225. codex/static_root/assets/library-tab-V8DUGoHN.809c548ff347.js.gz +0 -0
  226. codex/static_root/assets/library-tab-V8DUGoHN.js +1 -0
  227. codex/static_root/assets/library-tab-V8DUGoHN.js.br +0 -0
  228. codex/static_root/assets/library-tab-V8DUGoHN.js.gz +0 -0
  229. codex/static_root/assets/{main-CuzJev9T.js → main-Cavvqkyp.a9c4df906406.js} +6 -6
  230. codex/static_root/assets/main-Cavvqkyp.a9c4df906406.js.br +0 -0
  231. codex/static_root/assets/main-Cavvqkyp.a9c4df906406.js.gz +0 -0
  232. codex/static_root/assets/{main-CuzJev9T.f58771cc37e2.js → main-Cavvqkyp.js} +6 -6
  233. codex/static_root/assets/main-Cavvqkyp.js.br +0 -0
  234. codex/static_root/assets/main-Cavvqkyp.js.gz +0 -0
  235. codex/static_root/assets/{pagination-toolbar-B3wS4_7p.7695fafdefce.css → pagination-toolbar-ClZui9Zf.697d7ae11c21.css} +1 -1
  236. codex/static_root/assets/pagination-toolbar-ClZui9Zf.697d7ae11c21.css.br +0 -0
  237. codex/static_root/assets/pagination-toolbar-ClZui9Zf.697d7ae11c21.css.gz +0 -0
  238. codex/static_root/assets/{pagination-toolbar-B3wS4_7p.css → pagination-toolbar-ClZui9Zf.css} +1 -1
  239. codex/static_root/assets/pagination-toolbar-ClZui9Zf.css.br +0 -0
  240. codex/static_root/assets/pagination-toolbar-ClZui9Zf.css.gz +0 -0
  241. codex/static_root/assets/pagination-toolbar-Dg9tH1Ju.b2eb1e0c6985.js +1 -0
  242. codex/static_root/assets/pagination-toolbar-Dg9tH1Ju.b2eb1e0c6985.js.br +0 -0
  243. codex/static_root/assets/pagination-toolbar-Dg9tH1Ju.b2eb1e0c6985.js.gz +0 -0
  244. codex/static_root/assets/pagination-toolbar-Dg9tH1Ju.js +1 -0
  245. codex/static_root/assets/pagination-toolbar-Dg9tH1Ju.js.br +0 -0
  246. codex/static_root/assets/pagination-toolbar-Dg9tH1Ju.js.gz +0 -0
  247. codex/static_root/assets/{pdf-doc-BlU5mm5n.0431bcdf48d1.js → pdf-doc-4PKLN-Z3.62d8de4d1fd8.js} +1 -1
  248. codex/static_root/assets/pdf-doc-4PKLN-Z3.62d8de4d1fd8.js.br +0 -0
  249. codex/static_root/assets/pdf-doc-4PKLN-Z3.62d8de4d1fd8.js.gz +0 -0
  250. codex/static_root/assets/{pdf-doc-BlU5mm5n.js → pdf-doc-4PKLN-Z3.js} +1 -1
  251. codex/static_root/assets/pdf-doc-4PKLN-Z3.js.br +0 -0
  252. codex/static_root/assets/pdf-doc-4PKLN-Z3.js.gz +0 -0
  253. codex/static_root/assets/{reader-s7jttB_F.f7b43b04961a.js → reader-C39uGGxn.67b0f324cd5e.js} +2 -2
  254. codex/static_root/assets/reader-C39uGGxn.67b0f324cd5e.js.br +0 -0
  255. codex/static_root/assets/reader-C39uGGxn.67b0f324cd5e.js.gz +0 -0
  256. codex/static_root/assets/{reader-s7jttB_F.js → reader-C39uGGxn.js} +2 -2
  257. codex/static_root/assets/reader-C39uGGxn.js.br +0 -0
  258. codex/static_root/assets/reader-C39uGGxn.js.gz +0 -0
  259. codex/static_root/assets/{reader-BiKxuxj7.css → reader-N2Ei_y2K.8c0cdc0d513f.css} +1 -1
  260. codex/static_root/assets/reader-N2Ei_y2K.8c0cdc0d513f.css.br +0 -0
  261. codex/static_root/assets/reader-N2Ei_y2K.8c0cdc0d513f.css.gz +0 -0
  262. codex/static_root/assets/{reader-BiKxuxj7.dabe592f46f1.css → reader-N2Ei_y2K.css} +1 -1
  263. codex/static_root/assets/reader-N2Ei_y2K.css.br +0 -0
  264. codex/static_root/assets/reader-N2Ei_y2K.css.gz +0 -0
  265. codex/static_root/assets/{relation-chips-D6T6FX7G.css → relation-chips-Bsc-gUxE.98e65384c3c9.css} +1 -1
  266. codex/static_root/assets/relation-chips-Bsc-gUxE.98e65384c3c9.css.br +0 -0
  267. codex/static_root/assets/relation-chips-Bsc-gUxE.98e65384c3c9.css.gz +0 -0
  268. codex/static_root/assets/{relation-chips-D6T6FX7G.db095b2497e4.css → relation-chips-Bsc-gUxE.css} +1 -1
  269. codex/static_root/assets/relation-chips-Bsc-gUxE.css.br +0 -0
  270. codex/static_root/assets/relation-chips-Bsc-gUxE.css.gz +0 -0
  271. codex/static_root/assets/relation-chips-CAC5ytqH.f205d920ffea.js +1 -0
  272. codex/static_root/assets/relation-chips-CAC5ytqH.f205d920ffea.js.br +0 -0
  273. codex/static_root/assets/relation-chips-CAC5ytqH.f205d920ffea.js.gz +0 -0
  274. codex/static_root/assets/relation-chips-CAC5ytqH.js +1 -0
  275. codex/static_root/assets/relation-chips-CAC5ytqH.js.br +0 -0
  276. codex/static_root/assets/relation-chips-CAC5ytqH.js.gz +0 -0
  277. codex/static_root/assets/{settings-drawer-DbJuixzh.352aaaab5925.js → settings-drawer-CT73ieiV.fac6f69e86ff.js} +2 -2
  278. codex/static_root/assets/settings-drawer-CT73ieiV.fac6f69e86ff.js.br +0 -0
  279. codex/static_root/assets/settings-drawer-CT73ieiV.fac6f69e86ff.js.gz +0 -0
  280. codex/static_root/assets/{settings-drawer-DbJuixzh.js → settings-drawer-CT73ieiV.js} +2 -2
  281. codex/static_root/assets/settings-drawer-CT73ieiV.js.br +0 -0
  282. codex/static_root/assets/settings-drawer-CT73ieiV.js.gz +0 -0
  283. codex/static_root/assets/{settings-drawer-BJOfMtqA.6471a50fc05b.css → settings-drawer-nZ9HvKSZ.01744e131806.css} +1 -1
  284. codex/static_root/assets/settings-drawer-nZ9HvKSZ.01744e131806.css.br +0 -0
  285. codex/static_root/assets/settings-drawer-nZ9HvKSZ.01744e131806.css.gz +0 -0
  286. codex/static_root/assets/{settings-drawer-BJOfMtqA.css → settings-drawer-nZ9HvKSZ.css} +1 -1
  287. codex/static_root/assets/settings-drawer-nZ9HvKSZ.css.br +0 -0
  288. codex/static_root/assets/settings-drawer-nZ9HvKSZ.css.gz +0 -0
  289. codex/static_root/assets/{stats-tab-BhRLh7XB.7be95b5021c3.js → stats-tab-C6qAnV6-.f08c46b5f141.js} +1 -1
  290. codex/static_root/assets/stats-tab-C6qAnV6-.f08c46b5f141.js.br +0 -0
  291. codex/static_root/assets/stats-tab-C6qAnV6-.f08c46b5f141.js.gz +0 -0
  292. codex/static_root/assets/{stats-tab-BhRLh7XB.js → stats-tab-C6qAnV6-.js} +1 -1
  293. codex/static_root/assets/stats-tab-C6qAnV6-.js.br +0 -0
  294. codex/static_root/assets/stats-tab-C6qAnV6-.js.gz +0 -0
  295. codex/static_root/assets/task-tab-JcG2vvgt.eed6e03db487.js +1 -0
  296. codex/static_root/assets/task-tab-JcG2vvgt.eed6e03db487.js.br +0 -0
  297. codex/static_root/assets/task-tab-JcG2vvgt.eed6e03db487.js.gz +0 -0
  298. codex/static_root/assets/task-tab-JcG2vvgt.js +1 -0
  299. codex/static_root/assets/task-tab-JcG2vvgt.js.br +0 -0
  300. codex/static_root/assets/task-tab-JcG2vvgt.js.gz +0 -0
  301. codex/static_root/assets/{unauthorized-BgXQnNpn.f63b36d526b5.js → unauthorized-28bmiwAU.c74825b5c16f.js} +1 -1
  302. codex/static_root/assets/unauthorized-28bmiwAU.c74825b5c16f.js.br +0 -0
  303. codex/static_root/assets/unauthorized-28bmiwAU.c74825b5c16f.js.gz +0 -0
  304. codex/static_root/assets/{unauthorized-BgXQnNpn.js → unauthorized-28bmiwAU.js} +1 -1
  305. codex/static_root/assets/unauthorized-28bmiwAU.js.br +0 -0
  306. codex/static_root/assets/unauthorized-28bmiwAU.js.gz +0 -0
  307. codex/static_root/assets/{user-tab-cZoJDlb-.2a497e8b2b24.js → user-tab-BOq4BMMc.b64ac15dd772.js} +1 -1
  308. codex/static_root/assets/user-tab-BOq4BMMc.b64ac15dd772.js.br +0 -0
  309. codex/static_root/assets/user-tab-BOq4BMMc.b64ac15dd772.js.gz +0 -0
  310. codex/static_root/assets/{user-tab-cZoJDlb-.js → user-tab-BOq4BMMc.js} +1 -1
  311. codex/static_root/assets/user-tab-BOq4BMMc.js.br +0 -0
  312. codex/static_root/assets/user-tab-BOq4BMMc.js.gz +0 -0
  313. codex/static_root/js/choices-admin.ef1ff3a8b9da.json +1 -0
  314. codex/static_root/js/choices-admin.ef1ff3a8b9da.json.br +0 -0
  315. codex/static_root/js/choices-admin.ef1ff3a8b9da.json.gz +0 -0
  316. codex/static_root/js/choices-admin.json +1 -1
  317. codex/static_root/js/choices-admin.json.br +0 -0
  318. codex/static_root/js/choices-admin.json.gz +0 -0
  319. codex/static_root/js/{choices.b60817ba0a93.json → choices.23fedac2b9ba.json} +1 -1
  320. codex/static_root/js/choices.23fedac2b9ba.json.br +0 -0
  321. codex/static_root/js/choices.23fedac2b9ba.json.gz +0 -0
  322. codex/static_root/js/choices.json +1 -1
  323. codex/static_root/js/choices.json.br +0 -0
  324. codex/static_root/js/choices.json.gz +0 -0
  325. codex/static_root/manifest.ad9da9714e46.json +642 -0
  326. codex/static_root/manifest.ad9da9714e46.json.br +0 -0
  327. codex/static_root/manifest.ad9da9714e46.json.gz +0 -0
  328. codex/static_root/manifest.json +256 -256
  329. codex/static_root/manifest.json.br +0 -0
  330. codex/static_root/manifest.json.gz +0 -0
  331. codex/static_root/staticfiles.json +1 -1
  332. codex/status_controller.py +11 -2
  333. codex/views/admin/library.py +47 -27
  334. codex/views/admin/stats.py +4 -1
  335. codex/views/admin/tasks.py +6 -1
  336. codex/views/browser/base.py +3 -3
  337. codex/views/browser/browser.py +1 -9
  338. codex/views/browser/browser_annotations.py +101 -20
  339. codex/views/browser/browser_breadcrumbs.py +2 -2
  340. codex/views/browser/browser_order_by.py +31 -20
  341. codex/views/browser/filters/field.py +3 -1
  342. codex/views/browser/filters/search.py +1 -1
  343. codex/views/browser/metadata.py +0 -1
  344. codex/views/cover.py +3 -2
  345. codex/views/session.py +1 -0
  346. {codex-1.6.0a4.dist-info → codex-1.6.0a6.dist-info}/METADATA +3 -2
  347. {codex-1.6.0a4.dist-info → codex-1.6.0a6.dist-info}/RECORD +350 -347
  348. codex/static_root/assets/VCheckbox-CN6Sn_k7.9bf27129091c.js.br +0 -0
  349. codex/static_root/assets/VCheckbox-CN6Sn_k7.9bf27129091c.js.gz +0 -0
  350. codex/static_root/assets/VCheckbox-CN6Sn_k7.js.br +0 -0
  351. codex/static_root/assets/VCheckbox-CN6Sn_k7.js.gz +0 -0
  352. codex/static_root/assets/VCheckboxBtn-CN1RPZPQ.b763c6a7abaf.js.br +0 -0
  353. codex/static_root/assets/VCheckboxBtn-CN1RPZPQ.b763c6a7abaf.js.gz +0 -0
  354. codex/static_root/assets/VCheckboxBtn-CN1RPZPQ.js.br +0 -0
  355. codex/static_root/assets/VCheckboxBtn-CN1RPZPQ.js.gz +0 -0
  356. codex/static_root/assets/VCombobox-CtLUGYtD.6e49097cea2c.js +0 -1
  357. codex/static_root/assets/VCombobox-CtLUGYtD.6e49097cea2c.js.br +0 -0
  358. codex/static_root/assets/VCombobox-CtLUGYtD.6e49097cea2c.js.gz +0 -0
  359. codex/static_root/assets/VCombobox-CtLUGYtD.js +0 -1
  360. codex/static_root/assets/VCombobox-CtLUGYtD.js.br +0 -0
  361. codex/static_root/assets/VCombobox-CtLUGYtD.js.gz +0 -0
  362. codex/static_root/assets/VDialog-DC3KGsMT.71e2a460e44b.js.br +0 -0
  363. codex/static_root/assets/VDialog-DC3KGsMT.71e2a460e44b.js.gz +0 -0
  364. codex/static_root/assets/VDialog-DC3KGsMT.js.br +0 -0
  365. codex/static_root/assets/VDialog-DC3KGsMT.js.gz +0 -0
  366. codex/static_root/assets/VExpansionPanels-DJQYXCn2.f0d471a1b80a.js.br +0 -0
  367. codex/static_root/assets/VExpansionPanels-DJQYXCn2.f0d471a1b80a.js.gz +0 -0
  368. codex/static_root/assets/VExpansionPanels-DJQYXCn2.js.br +0 -0
  369. codex/static_root/assets/VExpansionPanels-DJQYXCn2.js.gz +0 -0
  370. codex/static_root/assets/VRadioGroup-CgodTThy.b20290d57146.js.br +0 -0
  371. codex/static_root/assets/VRadioGroup-CgodTThy.b20290d57146.js.gz +0 -0
  372. codex/static_root/assets/VRadioGroup-CgodTThy.js.br +0 -0
  373. codex/static_root/assets/VRadioGroup-CgodTThy.js.gz +0 -0
  374. codex/static_root/assets/VSelect-ARDhJiQK.372c098fb475.css +0 -1
  375. codex/static_root/assets/VSelect-ARDhJiQK.372c098fb475.css.br +0 -0
  376. codex/static_root/assets/VSelect-ARDhJiQK.372c098fb475.css.gz +0 -0
  377. codex/static_root/assets/VSelect-ARDhJiQK.css +0 -1
  378. codex/static_root/assets/VSelect-ARDhJiQK.css.br +0 -0
  379. codex/static_root/assets/VSelect-ARDhJiQK.css.gz +0 -0
  380. codex/static_root/assets/VSelect-B6s-x36h.de1030c82785.js +0 -1
  381. codex/static_root/assets/VSelect-B6s-x36h.de1030c82785.js.br +0 -0
  382. codex/static_root/assets/VSelect-B6s-x36h.de1030c82785.js.gz +0 -0
  383. codex/static_root/assets/VSelect-B6s-x36h.js +0 -1
  384. codex/static_root/assets/VSelect-B6s-x36h.js.br +0 -0
  385. codex/static_root/assets/VSelect-B6s-x36h.js.gz +0 -0
  386. codex/static_root/assets/VSelectionControl-zPp4DXWq.635b7f5aa882.js.br +0 -0
  387. codex/static_root/assets/VSelectionControl-zPp4DXWq.635b7f5aa882.js.gz +0 -0
  388. codex/static_root/assets/VSelectionControl-zPp4DXWq.js.br +0 -0
  389. codex/static_root/assets/VSelectionControl-zPp4DXWq.js.gz +0 -0
  390. codex/static_root/assets/VSlideGroup-pK9Xompk.67014b86fc74.js.br +0 -0
  391. codex/static_root/assets/VSlideGroup-pK9Xompk.67014b86fc74.js.gz +0 -0
  392. codex/static_root/assets/VSlideGroup-pK9Xompk.js.br +0 -0
  393. codex/static_root/assets/VSlideGroup-pK9Xompk.js.gz +0 -0
  394. codex/static_root/assets/VTable-CMi6sDtP.8445f91d9023.js.br +0 -0
  395. codex/static_root/assets/VTable-CMi6sDtP.8445f91d9023.js.gz +0 -0
  396. codex/static_root/assets/VTable-CMi6sDtP.js.br +0 -0
  397. codex/static_root/assets/VTable-CMi6sDtP.js.gz +0 -0
  398. codex/static_root/assets/VTextField-DuIIp-VY.580110ad24dc.css +0 -1
  399. codex/static_root/assets/VTextField-DuIIp-VY.580110ad24dc.css.br +0 -0
  400. codex/static_root/assets/VTextField-DuIIp-VY.580110ad24dc.css.gz +0 -0
  401. codex/static_root/assets/VTextField-DuIIp-VY.css +0 -1
  402. codex/static_root/assets/VTextField-DuIIp-VY.css.br +0 -0
  403. codex/static_root/assets/VTextField-DuIIp-VY.css.gz +0 -0
  404. codex/static_root/assets/VTextField-dMTizQEN.e93eefec0fdf.js +0 -1
  405. codex/static_root/assets/VTextField-dMTizQEN.e93eefec0fdf.js.br +0 -0
  406. codex/static_root/assets/VTextField-dMTizQEN.e93eefec0fdf.js.gz +0 -0
  407. codex/static_root/assets/VTextField-dMTizQEN.js +0 -1
  408. codex/static_root/assets/VTextField-dMTizQEN.js.br +0 -0
  409. codex/static_root/assets/VTextField-dMTizQEN.js.gz +0 -0
  410. codex/static_root/assets/VWindowItem-DNsRQx9l.c42f636c386e.js.br +0 -0
  411. codex/static_root/assets/VWindowItem-DNsRQx9l.c42f636c386e.js.gz +0 -0
  412. codex/static_root/assets/VWindowItem-DNsRQx9l.js.br +0 -0
  413. codex/static_root/assets/VWindowItem-DNsRQx9l.js.gz +0 -0
  414. codex/static_root/assets/admin-BbrOU9Y9.29936748af9e.css.br +0 -0
  415. codex/static_root/assets/admin-BbrOU9Y9.29936748af9e.css.gz +0 -0
  416. codex/static_root/assets/admin-BbrOU9Y9.css.br +0 -0
  417. codex/static_root/assets/admin-BbrOU9Y9.css.gz +0 -0
  418. codex/static_root/assets/admin-CApphpty.5a41cbf0eefc.js +0 -1
  419. codex/static_root/assets/admin-CApphpty.5a41cbf0eefc.js.br +0 -0
  420. codex/static_root/assets/admin-CApphpty.5a41cbf0eefc.js.gz +0 -0
  421. codex/static_root/assets/admin-CApphpty.js +0 -1
  422. codex/static_root/assets/admin-CApphpty.js.br +0 -0
  423. codex/static_root/assets/admin-CApphpty.js.gz +0 -0
  424. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.1514926c78e8.css +0 -1
  425. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.1514926c78e8.css.br +0 -0
  426. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.1514926c78e8.css.gz +0 -0
  427. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.css +0 -1
  428. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.css.br +0 -0
  429. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.css.gz +0 -0
  430. codex/static_root/assets/admin-drawer-panel-Dp8KD9D7.a79eda3055a7.js +0 -30
  431. codex/static_root/assets/admin-drawer-panel-Dp8KD9D7.a79eda3055a7.js.br +0 -0
  432. codex/static_root/assets/admin-drawer-panel-Dp8KD9D7.a79eda3055a7.js.gz +0 -0
  433. codex/static_root/assets/admin-drawer-panel-Dp8KD9D7.js +0 -30
  434. codex/static_root/assets/admin-drawer-panel-Dp8KD9D7.js.br +0 -0
  435. codex/static_root/assets/admin-drawer-panel-Dp8KD9D7.js.gz +0 -0
  436. codex/static_root/assets/browser-C_PHQbyN.bb065e2ce21a.js +0 -1
  437. codex/static_root/assets/browser-C_PHQbyN.bb065e2ce21a.js.br +0 -0
  438. codex/static_root/assets/browser-C_PHQbyN.bb065e2ce21a.js.gz +0 -0
  439. codex/static_root/assets/browser-C_PHQbyN.js +0 -1
  440. codex/static_root/assets/browser-C_PHQbyN.js.br +0 -0
  441. codex/static_root/assets/browser-C_PHQbyN.js.gz +0 -0
  442. codex/static_root/assets/browser-DVI4LUNv.css +0 -1
  443. codex/static_root/assets/browser-DVI4LUNv.css.br +0 -0
  444. codex/static_root/assets/browser-DVI4LUNv.css.gz +0 -0
  445. codex/static_root/assets/browser-DVI4LUNv.fef2b997145a.css +0 -1
  446. codex/static_root/assets/browser-DVI4LUNv.fef2b997145a.css.br +0 -0
  447. codex/static_root/assets/browser-DVI4LUNv.fef2b997145a.css.gz +0 -0
  448. codex/static_root/assets/change-password-dialog-BHTkpC6Z.2d5d5dd57ad3.js.br +0 -0
  449. codex/static_root/assets/change-password-dialog-BHTkpC6Z.2d5d5dd57ad3.js.gz +0 -0
  450. codex/static_root/assets/change-password-dialog-BHTkpC6Z.js.br +0 -0
  451. codex/static_root/assets/change-password-dialog-BHTkpC6Z.js.gz +0 -0
  452. codex/static_root/assets/confirm-dialog-DmXGDg4z.284812bd376d.js.br +0 -0
  453. codex/static_root/assets/confirm-dialog-DmXGDg4z.284812bd376d.js.gz +0 -0
  454. codex/static_root/assets/confirm-dialog-DmXGDg4z.js.br +0 -0
  455. codex/static_root/assets/confirm-dialog-DmXGDg4z.js.gz +0 -0
  456. codex/static_root/assets/datetime-column-DKaH5S3z.5c6042016200.js.br +0 -0
  457. codex/static_root/assets/datetime-column-DKaH5S3z.5c6042016200.js.gz +0 -0
  458. codex/static_root/assets/datetime-column-DKaH5S3z.js.br +0 -0
  459. codex/static_root/assets/datetime-column-DKaH5S3z.js.gz +0 -0
  460. codex/static_root/assets/filter-DUVATQW3.e1e7aa6d0b18.js.br +0 -0
  461. codex/static_root/assets/filter-DUVATQW3.e1e7aa6d0b18.js.gz +0 -0
  462. codex/static_root/assets/filter-DUVATQW3.js.br +0 -0
  463. codex/static_root/assets/filter-DUVATQW3.js.gz +0 -0
  464. codex/static_root/assets/flag-tab-BacZLlVi.8deba6a5370d.css +0 -1
  465. codex/static_root/assets/flag-tab-BacZLlVi.8deba6a5370d.css.br +0 -0
  466. codex/static_root/assets/flag-tab-BacZLlVi.8deba6a5370d.css.gz +0 -0
  467. codex/static_root/assets/flag-tab-BacZLlVi.css +0 -1
  468. codex/static_root/assets/flag-tab-BacZLlVi.css.br +0 -0
  469. codex/static_root/assets/flag-tab-BacZLlVi.css.gz +0 -0
  470. codex/static_root/assets/flag-tab-CSKMJEn-.5d5c0604541b.js +0 -1
  471. codex/static_root/assets/flag-tab-CSKMJEn-.5d5c0604541b.js.br +0 -0
  472. codex/static_root/assets/flag-tab-CSKMJEn-.5d5c0604541b.js.gz +0 -0
  473. codex/static_root/assets/flag-tab-CSKMJEn-.js +0 -1
  474. codex/static_root/assets/flag-tab-CSKMJEn-.js.br +0 -0
  475. codex/static_root/assets/flag-tab-CSKMJEn-.js.gz +0 -0
  476. codex/static_root/assets/group-tab-D3CyU-Il.fbf9ce5ef593.js.br +0 -0
  477. codex/static_root/assets/group-tab-D3CyU-Il.fbf9ce5ef593.js.gz +0 -0
  478. codex/static_root/assets/group-tab-D3CyU-Il.js.br +0 -0
  479. codex/static_root/assets/group-tab-D3CyU-Il.js.gz +0 -0
  480. codex/static_root/assets/http-error-0ef6-Ajc.e2879bcd242f.js.br +0 -0
  481. codex/static_root/assets/http-error-0ef6-Ajc.e2879bcd242f.js.gz +0 -0
  482. codex/static_root/assets/http-error-0ef6-Ajc.js.br +0 -0
  483. codex/static_root/assets/http-error-0ef6-Ajc.js.gz +0 -0
  484. codex/static_root/assets/library-tab-CXbkxNZt.954f2850a439.css +0 -1
  485. codex/static_root/assets/library-tab-CXbkxNZt.954f2850a439.css.br +0 -2
  486. codex/static_root/assets/library-tab-CXbkxNZt.954f2850a439.css.gz +0 -0
  487. codex/static_root/assets/library-tab-CXbkxNZt.css +0 -1
  488. codex/static_root/assets/library-tab-CXbkxNZt.css.br +0 -2
  489. codex/static_root/assets/library-tab-CXbkxNZt.css.gz +0 -0
  490. codex/static_root/assets/library-tab-IdDfLn4k.70b55460b8e1.js +0 -1
  491. codex/static_root/assets/library-tab-IdDfLn4k.70b55460b8e1.js.br +0 -0
  492. codex/static_root/assets/library-tab-IdDfLn4k.70b55460b8e1.js.gz +0 -0
  493. codex/static_root/assets/library-tab-IdDfLn4k.js +0 -1
  494. codex/static_root/assets/library-tab-IdDfLn4k.js.br +0 -0
  495. codex/static_root/assets/library-tab-IdDfLn4k.js.gz +0 -0
  496. codex/static_root/assets/main-CuzJev9T.f58771cc37e2.js.br +0 -0
  497. codex/static_root/assets/main-CuzJev9T.f58771cc37e2.js.gz +0 -0
  498. codex/static_root/assets/main-CuzJev9T.js.br +0 -0
  499. codex/static_root/assets/main-CuzJev9T.js.gz +0 -0
  500. codex/static_root/assets/pagination-toolbar-B3wS4_7p.7695fafdefce.css.br +0 -0
  501. codex/static_root/assets/pagination-toolbar-B3wS4_7p.7695fafdefce.css.gz +0 -0
  502. codex/static_root/assets/pagination-toolbar-B3wS4_7p.css.br +0 -0
  503. codex/static_root/assets/pagination-toolbar-B3wS4_7p.css.gz +0 -0
  504. codex/static_root/assets/pagination-toolbar-CLr9RVHd.66d3b756d974.js +0 -1
  505. codex/static_root/assets/pagination-toolbar-CLr9RVHd.66d3b756d974.js.br +0 -0
  506. codex/static_root/assets/pagination-toolbar-CLr9RVHd.66d3b756d974.js.gz +0 -0
  507. codex/static_root/assets/pagination-toolbar-CLr9RVHd.js +0 -1
  508. codex/static_root/assets/pagination-toolbar-CLr9RVHd.js.br +0 -0
  509. codex/static_root/assets/pagination-toolbar-CLr9RVHd.js.gz +0 -0
  510. codex/static_root/assets/pdf-doc-BlU5mm5n.0431bcdf48d1.js.br +0 -0
  511. codex/static_root/assets/pdf-doc-BlU5mm5n.0431bcdf48d1.js.gz +0 -0
  512. codex/static_root/assets/pdf-doc-BlU5mm5n.js.br +0 -0
  513. codex/static_root/assets/pdf-doc-BlU5mm5n.js.gz +0 -0
  514. codex/static_root/assets/reader-BiKxuxj7.css.br +0 -0
  515. codex/static_root/assets/reader-BiKxuxj7.css.gz +0 -0
  516. codex/static_root/assets/reader-BiKxuxj7.dabe592f46f1.css.br +0 -0
  517. codex/static_root/assets/reader-BiKxuxj7.dabe592f46f1.css.gz +0 -0
  518. codex/static_root/assets/reader-s7jttB_F.f7b43b04961a.js.br +0 -0
  519. codex/static_root/assets/reader-s7jttB_F.f7b43b04961a.js.gz +0 -0
  520. codex/static_root/assets/reader-s7jttB_F.js.br +0 -0
  521. codex/static_root/assets/reader-s7jttB_F.js.gz +0 -0
  522. codex/static_root/assets/relation-chips-BiVsYCd9.27eca8616ba4.js +0 -1
  523. codex/static_root/assets/relation-chips-BiVsYCd9.27eca8616ba4.js.br +0 -0
  524. codex/static_root/assets/relation-chips-BiVsYCd9.27eca8616ba4.js.gz +0 -0
  525. codex/static_root/assets/relation-chips-BiVsYCd9.js +0 -1
  526. codex/static_root/assets/relation-chips-BiVsYCd9.js.br +0 -0
  527. codex/static_root/assets/relation-chips-BiVsYCd9.js.gz +0 -0
  528. codex/static_root/assets/relation-chips-D6T6FX7G.css.br +0 -0
  529. codex/static_root/assets/relation-chips-D6T6FX7G.css.gz +0 -0
  530. codex/static_root/assets/relation-chips-D6T6FX7G.db095b2497e4.css.br +0 -0
  531. codex/static_root/assets/relation-chips-D6T6FX7G.db095b2497e4.css.gz +0 -0
  532. codex/static_root/assets/settings-drawer-BJOfMtqA.6471a50fc05b.css.br +0 -0
  533. codex/static_root/assets/settings-drawer-BJOfMtqA.6471a50fc05b.css.gz +0 -0
  534. codex/static_root/assets/settings-drawer-BJOfMtqA.css.br +0 -0
  535. codex/static_root/assets/settings-drawer-BJOfMtqA.css.gz +0 -0
  536. codex/static_root/assets/settings-drawer-DbJuixzh.352aaaab5925.js.br +0 -0
  537. codex/static_root/assets/settings-drawer-DbJuixzh.352aaaab5925.js.gz +0 -0
  538. codex/static_root/assets/settings-drawer-DbJuixzh.js.br +0 -0
  539. codex/static_root/assets/settings-drawer-DbJuixzh.js.gz +0 -0
  540. codex/static_root/assets/stats-tab-BhRLh7XB.7be95b5021c3.js.br +0 -0
  541. codex/static_root/assets/stats-tab-BhRLh7XB.7be95b5021c3.js.gz +0 -0
  542. codex/static_root/assets/stats-tab-BhRLh7XB.js.br +0 -0
  543. codex/static_root/assets/stats-tab-BhRLh7XB.js.gz +0 -0
  544. codex/static_root/assets/task-tab-DLrd54z2.c574111658b9.js +0 -1
  545. codex/static_root/assets/task-tab-DLrd54z2.c574111658b9.js.br +0 -0
  546. codex/static_root/assets/task-tab-DLrd54z2.c574111658b9.js.gz +0 -0
  547. codex/static_root/assets/task-tab-DLrd54z2.js +0 -1
  548. codex/static_root/assets/task-tab-DLrd54z2.js.br +0 -0
  549. codex/static_root/assets/task-tab-DLrd54z2.js.gz +0 -0
  550. codex/static_root/assets/unauthorized-BgXQnNpn.f63b36d526b5.js.br +0 -0
  551. codex/static_root/assets/unauthorized-BgXQnNpn.f63b36d526b5.js.gz +0 -0
  552. codex/static_root/assets/unauthorized-BgXQnNpn.js.br +0 -0
  553. codex/static_root/assets/unauthorized-BgXQnNpn.js.gz +0 -0
  554. codex/static_root/assets/user-tab-cZoJDlb-.2a497e8b2b24.js.br +0 -0
  555. codex/static_root/assets/user-tab-cZoJDlb-.2a497e8b2b24.js.gz +0 -0
  556. codex/static_root/assets/user-tab-cZoJDlb-.js.br +0 -0
  557. codex/static_root/assets/user-tab-cZoJDlb-.js.gz +0 -0
  558. codex/static_root/js/choices-admin.248384ece3f6.json +0 -1
  559. codex/static_root/js/choices-admin.248384ece3f6.json.br +0 -0
  560. codex/static_root/js/choices-admin.248384ece3f6.json.gz +0 -0
  561. codex/static_root/js/choices.b60817ba0a93.json.br +0 -0
  562. codex/static_root/js/choices.b60817ba0a93.json.gz +0 -0
  563. codex/static_root/manifest.3c2f342d5f5a.json +0 -642
  564. codex/static_root/manifest.3c2f342d5f5a.json.br +0 -0
  565. codex/static_root/manifest.3c2f342d5f5a.json.gz +0 -0
  566. {codex-1.6.0a4.dist-info → codex-1.6.0a6.dist-info}/LICENSE +0 -0
  567. {codex-1.6.0a4.dist-info → codex-1.6.0a6.dist-info}/WHEEL +0 -0
  568. {codex-1.6.0a4.dist-info → codex-1.6.0a6.dist-info}/entry_points.txt +0 -0
codex/models/groups.py CHANGED
@@ -1,17 +1,17 @@
1
1
  """Browser Group models."""
2
2
 
3
- from django.db.models import (
4
- CASCADE,
3
+ from django.db.models import CASCADE, SET_DEFAULT, ForeignKey
4
+ from django.db.models.fields import (
5
5
  CharField,
6
- ForeignKey,
7
6
  PositiveSmallIntegerField,
8
7
  SmallIntegerField,
9
8
  )
10
9
 
11
10
  from codex.models.base import MAX_NAME_LEN, BaseModel
12
- from codex.models.const import ARTICLES
11
+ from codex.models.paths import CustomCover, WatchedPath
12
+ from codex.models.util import get_sort_name
13
13
 
14
- __all__ = ("BrowserGroupModel", "Publisher", "Imprint", "Series", "Volume")
14
+ __all__ = ("BrowserGroupModel", "Publisher", "Imprint", "Series", "Volume", "Folder")
15
15
 
16
16
 
17
17
  class BrowserGroupModel(BaseModel):
@@ -22,18 +22,13 @@ class BrowserGroupModel(BaseModel):
22
22
 
23
23
  name = CharField(db_index=True, max_length=MAX_NAME_LEN, default=DEFAULT_NAME)
24
24
  sort_name = CharField(db_index=True, max_length=MAX_NAME_LEN, default=DEFAULT_NAME)
25
+ custom_cover = ForeignKey(
26
+ CustomCover, on_delete=SET_DEFAULT, null=True, default=None
27
+ )
25
28
 
26
29
  def set_sort_name(self):
27
30
  """Create sort_name for model."""
28
- lower_name = self.name.lower()
29
- sort_name = lower_name
30
- name_parts = lower_name.split()
31
- if len(name_parts) > 1:
32
- first_word = name_parts[0]
33
- if first_word in ARTICLES:
34
- sort_name = " ".join(name_parts[1:])
35
- sort_name += ", " + first_word
36
- self.sort_name = sort_name
31
+ self.sort_name = get_sort_name(self.name)
37
32
 
38
33
  def presave(self):
39
34
  """Set computed values."""
@@ -103,6 +98,7 @@ class Volume(BrowserGroupModel):
103
98
 
104
99
  # Harmful because name is numeric
105
100
  sort_name = None
101
+ custom_cover = None
106
102
 
107
103
  def set_sort_name(self):
108
104
  """Noop."""
@@ -125,3 +121,23 @@ class Volume(BrowserGroupModel):
125
121
  def __str__(self):
126
122
  """Represent volume as a string."""
127
123
  return self.to_str(self.name)
124
+
125
+
126
+ class WatchedPathBrowserGroup(BrowserGroupModel, WatchedPath):
127
+ """Watched Path Browser Group."""
128
+
129
+ def presave(self):
130
+ """Fix multiple inheritance presave."""
131
+ # TODO test presave calling bgm & stat
132
+ super().presave()
133
+ WatchedPath.presave(self)
134
+
135
+ class Meta(WatchedPath.Meta): # type: ignore
136
+ """Use Mixin Meta."""
137
+
138
+ # TODO see if this does unique properly.
139
+ abstract = True
140
+
141
+
142
+ class Folder(WatchedPathBrowserGroup):
143
+ """File system folder."""
codex/models/library.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from datetime import timedelta
4
4
  from pathlib import Path
5
+ from types import MappingProxyType
5
6
 
6
7
  from django.contrib.auth.models import Group
7
8
  from django.core.exceptions import ValidationError
@@ -32,7 +33,14 @@ class Library(BaseModel):
32
33
 
33
34
  DEFAULT_POLL_EVERY_SECONDS = 60 * 60
34
35
  DEFAULT_POLL_EVERY = timedelta(seconds=DEFAULT_POLL_EVERY_SECONDS)
35
-
36
+ CUSTOM_COVERS_DIR_DEFAULTS = MappingProxyType(
37
+ {
38
+ "covers_only": True,
39
+ "events": False,
40
+ "poll": False,
41
+ }
42
+ )
43
+ covers_only = BooleanField(db_index=True, default=False)
36
44
  path = CharField(
37
45
  unique=True,
38
46
  db_index=True,
@@ -46,9 +54,9 @@ class Library(BaseModel):
46
54
  update_in_progress = BooleanField(default=False)
47
55
  groups = ManyToManyField(Group, blank=True)
48
56
 
49
- def __str__(self):
57
+ def __str__(self) -> str:
50
58
  """Return the path."""
51
- return self.path
59
+ return str(self.path)
52
60
 
53
61
  class Meta(BaseModel.Meta):
54
62
  """Pluralize."""
codex/models/paths.py CHANGED
@@ -1,32 +1,35 @@
1
1
  """Watched Path models."""
2
2
 
3
3
  from pathlib import Path
4
+ from types import MappingProxyType
4
5
 
5
6
  from django.db.models import CASCADE, CharField, ForeignKey, JSONField
7
+ from django.db.models.enums import Choices
6
8
 
7
- from codex.models.base import MAX_NAME_LEN
8
- from codex.models.groups import BrowserGroupModel
9
+ from codex.models.base import MAX_NAME_LEN, BaseModel
9
10
  from codex.models.library import MAX_PATH_LEN, Library
11
+ from codex.models.util import get_sort_name
10
12
 
11
- __all__ = ("WatchedPath", "Folder", "FailedImport")
13
+ __all__ = ("CustomCover", "FailedImport")
12
14
 
13
15
 
14
- class WatchedPath(BrowserGroupModel):
16
+ class WatchedPath(BaseModel):
15
17
  """A filesystem path with data for Watchdog."""
16
18
 
17
19
  library = ForeignKey(Library, on_delete=CASCADE, db_index=True)
18
- path = CharField(max_length=MAX_PATH_LEN, db_index=True)
19
- stat = JSONField(null=True)
20
20
  parent_folder = ForeignKey(
21
21
  "Folder",
22
22
  on_delete=CASCADE,
23
23
  null=True,
24
24
  )
25
+ path = CharField(max_length=MAX_PATH_LEN, db_index=True)
26
+ stat = JSONField(null=True)
25
27
  ZERO_STAT = (0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0)
26
28
 
27
29
  def set_stat(self):
28
30
  """Set select stat params from the filesystem."""
29
- st_record = Path(self.path).stat()
31
+ path = Path(str(self.path))
32
+ st_record = path.stat()
30
33
  # Converting os.stat directly to a list or tuple saves
31
34
  # mtime as an int and causes problems.
32
35
  st = list(self.ZERO_STAT)
@@ -43,27 +46,29 @@ class WatchedPath(BrowserGroupModel):
43
46
 
44
47
  def presave(self):
45
48
  """Save stat."""
46
- super().presave()
47
49
  self.set_stat()
48
50
 
49
51
  def __str__(self):
50
52
  """Return the full path."""
51
- return self.path
53
+ return str(self.path)
52
54
 
53
- class Meta(BrowserGroupModel.Meta):
54
- """Constraints."""
55
+ class Meta(BaseModel.Meta):
56
+ """Use Mixin Meta."""
55
57
 
56
58
  unique_together = ("library", "path")
57
59
  abstract = True
58
60
 
59
-
60
- class Folder(WatchedPath):
61
- """File system folder."""
61
+ def search_path(self) -> str:
62
+ """Relative path for search index."""
63
+ return self.path.removeprefix(self.library.path)
62
64
 
63
65
 
64
66
  class FailedImport(WatchedPath):
65
67
  """Failed Comic Imports. Displayed in Admin Panel."""
66
68
 
69
+ # TODO rename reason
70
+ name = CharField(db_index=True, max_length=MAX_NAME_LEN, default="")
71
+
67
72
  def set_reason(self, exc):
68
73
  """Can't do this in save() because it breaks update_or_create."""
69
74
  reason = str(exc)
@@ -72,3 +77,46 @@ class FailedImport(WatchedPath):
72
77
  reason = reason.removesuffix(suffix)
73
78
  reason = reason[:MAX_NAME_LEN]
74
79
  self.name = reason.strip()
80
+
81
+
82
+ class CustomCover(WatchedPath):
83
+ """Custom Cover Image."""
84
+
85
+ class GroupChoice(Choices):
86
+ """Reading direction choices."""
87
+
88
+ P = "p"
89
+ I = "i" # noqa: E741
90
+ S = "s"
91
+ A = "a"
92
+ F = "f"
93
+
94
+ FOLDER_COVER_STEM = ".codex-cover"
95
+ DIR_GROUP_CHOICE_MAP = MappingProxyType(
96
+ {
97
+ "publishers": GroupChoice.P,
98
+ "imprints": GroupChoice.I,
99
+ "series": GroupChoice.S,
100
+ "story-arcs": GroupChoice.A,
101
+ }
102
+ )
103
+
104
+ parent_folder = None
105
+ group = CharField(max_length=1, db_index=True, choices=GroupChoice.choices)
106
+ sort_name = CharField(max_length=MAX_NAME_LEN, db_index=True, default="")
107
+
108
+ def _set_group_and_sort_name(self):
109
+ """Set group and sort_name from path."""
110
+ path = Path(self.path)
111
+ stem = path.stem
112
+ if stem == self.FOLDER_COVER_STEM:
113
+ self.group = self.GroupChoice.F.value
114
+ else:
115
+ choice = self.DIR_GROUP_CHOICE_MAP[path.parent.name]
116
+ self.group = choice.value
117
+ self.sort_name = get_sort_name(stem)
118
+
119
+ def presave(self):
120
+ """Presave group and sort_name."""
121
+ super().presave()
122
+ self._set_group_and_sort_name()
@@ -1,6 +1,6 @@
1
- """Constants for models."""
1
+ """Utilities for models."""
2
2
 
3
- ARTICLES = frozenset(
3
+ _ARTICLES = frozenset(
4
4
  ("a", "an", "the") # en # noqa RUF005
5
5
  + ("un", "unos", "unas", "el", "los", "la", "las") # es
6
6
  + ("un", "une", "le", "les", "la", "les", "l'") # fr
@@ -16,3 +16,16 @@ ARTICLES = frozenset(
16
16
  + ("en", "et") # da
17
17
  + ("el", "la", "els", "les", "un", "una", "uns", "unes", "na") # ct
18
18
  )
19
+
20
+
21
+ def get_sort_name(name: str) -> str:
22
+ """Create sort_name from name."""
23
+ lower_name = name.lower()
24
+ sort_name = lower_name
25
+ name_parts = lower_name.split()
26
+ if len(name_parts) > 1:
27
+ first_word = name_parts[0]
28
+ if first_word in _ARTICLES:
29
+ sort_name = " ".join(name_parts[1:])
30
+ sort_name += ", " + first_word
31
+ return sort_name
@@ -101,8 +101,17 @@ class LibrarySerializer(BaseModelSerializer):
101
101
  """Specify Model."""
102
102
 
103
103
  model = Library
104
- fields = ("pk", "events", "groups", "last_poll", "path", "poll", "poll_every")
105
- read_only_fields = ("last_poll", "pk")
104
+ fields = (
105
+ "pk",
106
+ "path",
107
+ "events",
108
+ "last_poll",
109
+ "poll",
110
+ "poll_every",
111
+ "groups",
112
+ "covers_only",
113
+ )
114
+ read_only_fields = ("last_poll", "pk", "covers_only")
106
115
 
107
116
  def validate_path(self, path):
108
117
  """Validate new library paths."""
@@ -22,6 +22,7 @@ class BrowserAggregateSerializerMixin(Serializer):
22
22
  child_count = IntegerField(read_only=True)
23
23
  cover_pk = IntegerField(read_only=True)
24
24
  cover_mtime = DateTimeField(format="%s", read_only=True)
25
+ cover_custom = BooleanField(read_only=True)
25
26
 
26
27
  # Bookmark annotations
27
28
  page = IntegerField(read_only=True)
@@ -57,7 +57,6 @@ class BrowserPageSerializer(Serializer):
57
57
  admin_flags = BrowserAdminFlagsSerializer(read_only=True)
58
58
  breadcrumbs = ListSerializer(child=RouteSerializer())
59
59
  title = BrowserTitleSerializer(read_only=True)
60
- covers_timestamp = IntegerField(read_only=True)
61
60
  zero_pad = IntegerField(read_only=True)
62
61
  libraries_exist = BooleanField(read_only=True)
63
62
  model_group = CharField(read_only=True)
@@ -36,6 +36,9 @@ class BrowserSettingsSerializer(Serializer):
36
36
  q = CharField(allow_blank=True, required=False)
37
37
  query = CharField(allow_blank=True, required=False) # OPDS 2.0
38
38
  show = BrowserSettingsShowGroupFlagsSerializer(required=False)
39
+ cover_style = ChoiceField(
40
+ choices=tuple(CHOICES["coverStyle"].keys()), required=False
41
+ )
39
42
  # search_results_limit = IntegerField(required=False)
40
43
  twenty_four_hour_time = BooleanField(required=False)
41
44
  top_group = ChoiceField(choices=tuple(CHOICES["topGroup"].keys()), required=False)
@@ -37,10 +37,11 @@ WRITER_MEMORY_PERCENT = float(environ.get("CODEX_WRITER_MEMORY_PERCENT", 0.6))
37
37
  CPU_MULTIPLIER = float(environ.get("CODEX_CPU_MULTIPLIER", 1.25))
38
38
  CHUNK_PER_GB = int(environ.get("CODEX_CHUNK_PER_GB", 250))
39
39
  MAX_CHUNK_SIZE = int(environ.get("CODEX_MAX_CHUNK_SIZE", 1000))
40
- # sqlite parser breaks with more than 1000 variables in a query and django only
41
- # fixes this in the bulk_create & bulk_update functions. So for complicated
42
- # queries I gotta batch them myself. Filter arg count is a proxy, but it works.
43
- FILTER_BATCH_SIZE = int(environ.get("CODEX_FILTER_BATCH_SIZE", 990))
40
+ # sqlite parser breaks with more than 1000 variables in a query and
41
+ # django only fixes this in the bulk_create & bulk_update functions.
42
+ # So for complicated queries I gotta batch them myself. Filter arg
43
+ # count is a proxy, but it works. 990 errors sometimes.
44
+ FILTER_BATCH_SIZE = int(environ.get("CODEX_FILTER_BATCH_SIZE", 900))
44
45
  VITE_HOST = environ.get("VITE_HOST")
45
46
 
46
47
  ####################################
@@ -62,7 +63,12 @@ THROTTLE_OPENSEARCH = int(environ.get("CODEX_THROTTLE_OPENSEARCH", 0))
62
63
  # Base paths
63
64
  BASE_DIR = Path(__file__).resolve().parent.parent.parent
64
65
  CODEX_PATH = BASE_DIR / "codex"
65
- CONFIG_PATH.mkdir(exist_ok=True, parents=True)
66
+ CUSTOM_COVERS_SUBDIR = "custom-covers"
67
+ CUSTOM_COVERS_DIR = CONFIG_PATH / CUSTOM_COVERS_SUBDIR
68
+ CUSTOM_COVERS_GROUP_DIRS = ("publishers", "imprints", "series", "volumes", "story-arcs")
69
+ for group_dir in CUSTOM_COVERS_GROUP_DIRS:
70
+ custom_cover_group_dir = CUSTOM_COVERS_DIR / group_dir
71
+ custom_cover_group_dir.mkdir(exist_ok=True, parents=True)
66
72
 
67
73
  # SECURITY WARNING: keep the secret key used in production secret!
68
74
  SECRET_KEY = get_secret_key(CONFIG_PATH)
codex/startup.py CHANGED
@@ -1,9 +1,11 @@
1
1
  """Initialize Codex Dataabse before running."""
2
2
 
3
+ from pathlib import Path
4
+
3
5
  from django.core.cache import cache
4
6
  from django.core.management import call_command
5
7
  from django.db import connection
6
- from django.db.models import Q
8
+ from django.db.models import F, Q
7
9
  from django.db.models.functions import Now
8
10
 
9
11
  from codex.integrity import has_unapplied_migrations, rebuild_db, repair_db
@@ -11,11 +13,13 @@ from codex.librarian.janitor.janitor import Janitor
11
13
  from codex.librarian.mp_queue import LIBRARIAN_QUEUE
12
14
  from codex.logger.logging import get_logger
13
15
  from codex.logger.mp_queue import LOG_QUEUE
14
- from codex.models import AdminFlag, LibrarianStatus, Library, Timestamp
16
+ from codex.models import AdminFlag, CustomCover, LibrarianStatus, Library, Timestamp
15
17
  from codex.registration import patch_registration_setting
16
18
  from codex.serializers.choices import CHOICES
17
19
  from codex.settings.settings import (
18
20
  BACKUP_DB_PATH,
21
+ CUSTOM_COVERS_DIR,
22
+ CUSTOM_COVERS_SUBDIR,
19
23
  HYPERCORN_CONFIG,
20
24
  HYPERCORN_CONFIG_TOML,
21
25
  RESET_ADMIN,
@@ -124,7 +128,75 @@ def clear_library_status():
124
128
  count = Library.objects.filter(update_in_progress=True).update(
125
129
  update_in_progress=False, updated_at=Now()
126
130
  )
127
- LOG.debug(f"Reset {count} Library's update_in_progress flag")
131
+ if count:
132
+ LOG.debug(f"Reset {count} Libraries' update_in_progress flag")
133
+
134
+
135
+ def init_custom_cover_dir():
136
+ """Initialize the Custom Cover Dir singleton row."""
137
+ defaults = dict(**Library.CUSTOM_COVERS_DIR_DEFAULTS, path=CUSTOM_COVERS_DIR)
138
+ covers_library, created = Library.objects.get_or_create(
139
+ defaults=defaults, covers_only=True
140
+ )
141
+ if created:
142
+ LOG.info("Created Custom Covers Dir settings in the db.")
143
+
144
+ old_path = covers_library.path
145
+ if Path(old_path) != CUSTOM_COVERS_DIR:
146
+ Library.objects.filter(covers_only=True).update(path=str(CUSTOM_COVERS_DIR))
147
+ LOG.info(
148
+ f"Updated Custom Group Covers Dir path from {old_path} to {CUSTOM_COVERS_DIR}."
149
+ )
150
+
151
+
152
+ def update_custom_covers_for_config_dir():
153
+ """Update custom covers if the config dir changes."""
154
+ # This is okay, but I wouldn't need to do it if paths were constructed from
155
+ # parent_folder and library.path
156
+ # Fast lookup without relations seems better though, paths shouldn't change too much.
157
+
158
+ # Determine which covers need re-pathing
159
+ update_covers = []
160
+ delete_cover_pks = []
161
+ update_fields = ("path", "updated_at")
162
+ group_covers = (
163
+ CustomCover.objects.filter(library__covers_only=True)
164
+ .exclude(path__startswith=F("library__path"))
165
+ .only(*update_fields)
166
+ )
167
+ LOG.debug(f"Checking that group custom covers are under {CUSTOM_COVERS_DIR}")
168
+ for cover in group_covers.iterator():
169
+ old_path = cover.path
170
+ parts = old_path.rsplit(f"/{CUSTOM_COVERS_SUBDIR}/")
171
+ if len(parts) < 2: # noqa: PLR2004
172
+ delete_cover_pks.append(cover.pk)
173
+ continue
174
+ new_path = CUSTOM_COVERS_DIR / parts[1]
175
+ if new_path.exists():
176
+ cover.path = str(new_path)
177
+ update_covers.append(cover)
178
+ else:
179
+ delete_cover_pks.append(cover.pk)
180
+ update_count = len(update_covers)
181
+ LOG.debug(
182
+ f"Found {update_count} custom covers to update, {len(delete_cover_pks)} to delete."
183
+ )
184
+
185
+ # Update covers
186
+ if update_count:
187
+ CustomCover.objects.bulk_update(update_covers, update_fields)
188
+ LOG.info(
189
+ f"Updated {update_count} CustomCovers sources to point to new config dir"
190
+ )
191
+
192
+ # Delete covers we can't reliably update.
193
+ if delete_cover_pks:
194
+ delete_qs = CustomCover.objects.filter(pk__in=delete_cover_pks)
195
+ delete_count = delete_qs.count()
196
+ delete_qs.delete()
197
+ LOG.warning(
198
+ f"Delete {delete_count} CustomCovers that could not be re-sourced after config dir change."
199
+ )
128
200
 
129
201
 
130
202
  def ensure_db_rows():
@@ -134,6 +206,8 @@ def ensure_db_rows():
134
206
  init_timestamps()
135
207
  init_librarian_statuses()
136
208
  clear_library_status()
209
+ init_custom_cover_dir()
210
+ update_custom_covers_for_config_dir()
137
211
 
138
212
 
139
213
  def codex_init():
@@ -1 +1 @@
1
- import{m as A,V as t}from"./VCheckboxBtn-CN1RPZPQ.js";import{a as F,u as I,V as l}from"./VSelectionControl-zPp4DXWq.js";import{x as B,al as U,G as R,as as D,y as G,h as K,K as L,cm as M,L as u,ap as r}from"./admin-drawer-panel-Dp8KD9D7.js";const N=B({...F(),...U(A(),["inline"])},"VCheckbox"),w=R()({name:"VCheckbox",inheritAttrs:!1,props:N(),emits:{"update:modelValue":e=>!0,"update:focused":e=>!0},setup(e,c){let{attrs:d,slots:a}=c;const s=D(e,"modelValue"),{isFocused:n,focus:i,blur:m}=I(e),V=G(),p=K(()=>e.id||`checkbox-${V}`);return L(()=>{const[b,f]=M(d),v=l.filterProps(e),k=t.filterProps(e);return u(l,r({class:["v-checkbox",e.class]},b,v,{modelValue:s.value,"onUpdate:modelValue":o=>s.value=o,id:p.value,focused:n.value,style:e.style}),{...a,default:o=>{let{id:x,messagesId:h,isDisabled:P,isReadonly:y,isValid:C}=o;return u(t,r(k,{id:x.value,"aria-describedby":h.value,disabled:P.value,readonly:y.value},f,{error:C.value===!1,modelValue:s.value,"onUpdate:modelValue":g=>s.value=g,onFocus:i,onBlur:m}),a)}})}),{}}});export{w as V};
1
+ import{m as A,V as t}from"./VCheckboxBtn-m4IbdjEe.js";import{a as F,u as I,V as l}from"./VSelectionControl-BSL0qeL9.js";import{x as B,al as U,G as R,as as D,y as G,h as K,K as L,cr as M,L as u,ap as r}from"./admin-drawer-panel-C34Ze3-5.js";const N=B({...F(),...U(A(),["inline"])},"VCheckbox"),w=R()({name:"VCheckbox",inheritAttrs:!1,props:N(),emits:{"update:modelValue":e=>!0,"update:focused":e=>!0},setup(e,c){let{attrs:d,slots:a}=c;const s=D(e,"modelValue"),{isFocused:n,focus:i,blur:m}=I(e),V=G(),p=K(()=>e.id||`checkbox-${V}`);return L(()=>{const[b,f]=M(d),v=l.filterProps(e),k=t.filterProps(e);return u(l,r({class:["v-checkbox",e.class]},b,v,{modelValue:s.value,"onUpdate:modelValue":o=>s.value=o,id:p.value,focused:n.value,style:e.style}),{...a,default:o=>{let{id:x,messagesId:h,isDisabled:P,isReadonly:y,isValid:C}=o;return u(t,r(k,{id:x.value,"aria-describedby":h.value,disabled:P.value,readonly:y.value},f,{error:C.value===!1,modelValue:s.value,"onUpdate:modelValue":g=>s.value=g,onFocus:i,onBlur:m}),a)}})}),{}}});export{w as V};
@@ -1 +1 @@
1
- import{m as A,V as t}from"./VCheckboxBtn-CN1RPZPQ.js";import{a as F,u as I,V as l}from"./VSelectionControl-zPp4DXWq.js";import{x as B,al as U,G as R,as as D,y as G,h as K,K as L,cm as M,L as u,ap as r}from"./admin-drawer-panel-Dp8KD9D7.js";const N=B({...F(),...U(A(),["inline"])},"VCheckbox"),w=R()({name:"VCheckbox",inheritAttrs:!1,props:N(),emits:{"update:modelValue":e=>!0,"update:focused":e=>!0},setup(e,c){let{attrs:d,slots:a}=c;const s=D(e,"modelValue"),{isFocused:n,focus:i,blur:m}=I(e),V=G(),p=K(()=>e.id||`checkbox-${V}`);return L(()=>{const[b,f]=M(d),v=l.filterProps(e),k=t.filterProps(e);return u(l,r({class:["v-checkbox",e.class]},b,v,{modelValue:s.value,"onUpdate:modelValue":o=>s.value=o,id:p.value,focused:n.value,style:e.style}),{...a,default:o=>{let{id:x,messagesId:h,isDisabled:P,isReadonly:y,isValid:C}=o;return u(t,r(k,{id:x.value,"aria-describedby":h.value,disabled:P.value,readonly:y.value},f,{error:C.value===!1,modelValue:s.value,"onUpdate:modelValue":g=>s.value=g,onFocus:i,onBlur:m}),a)}})}),{}}});export{w as V};
1
+ import{m as A,V as t}from"./VCheckboxBtn-m4IbdjEe.js";import{a as F,u as I,V as l}from"./VSelectionControl-BSL0qeL9.js";import{x as B,al as U,G as R,as as D,y as G,h as K,K as L,cr as M,L as u,ap as r}from"./admin-drawer-panel-C34Ze3-5.js";const N=B({...F(),...U(A(),["inline"])},"VCheckbox"),w=R()({name:"VCheckbox",inheritAttrs:!1,props:N(),emits:{"update:modelValue":e=>!0,"update:focused":e=>!0},setup(e,c){let{attrs:d,slots:a}=c;const s=D(e,"modelValue"),{isFocused:n,focus:i,blur:m}=I(e),V=G(),p=K(()=>e.id||`checkbox-${V}`);return L(()=>{const[b,f]=M(d),v=l.filterProps(e),k=t.filterProps(e);return u(l,r({class:["v-checkbox",e.class]},b,v,{modelValue:s.value,"onUpdate:modelValue":o=>s.value=o,id:p.value,focused:n.value,style:e.style}),{...a,default:o=>{let{id:x,messagesId:h,isDisabled:P,isReadonly:y,isValid:C}=o;return u(t,r(k,{id:x.value,"aria-describedby":h.value,disabled:P.value,readonly:y.value},f,{error:C.value===!1,modelValue:s.value,"onUpdate:modelValue":g=>s.value=g,onFocus:i,onBlur:m}),a)}})}),{}}});export{w as V};
@@ -1 +1 @@
1
- import{c as f,d as o}from"./VSelectionControl-zPp4DXWq.js";import{x as V,cq as v,G as x,as as c,h as l,K as I,al as h,L as k,ap as b}from"./admin-drawer-panel-Dp8KD9D7.js";const C=V({indeterminate:Boolean,indeterminateIcon:{type:v,default:"$checkboxIndeterminate"},...f({falseIcon:"$checkboxOff",trueIcon:"$checkboxOn"})},"VCheckboxBtn"),y=x()({name:"VCheckboxBtn",props:C(),emits:{"update:modelValue":e=>!0,"update:indeterminate":e=>!0},setup(e,r){let{slots:s}=r;const t=c(e,"indeterminate"),n=c(e,"modelValue");function u(a){t.value&&(t.value=!1)}const i=l(()=>t.value?e.indeterminateIcon:e.falseIcon),d=l(()=>t.value?e.indeterminateIcon:e.trueIcon);return I(()=>{const a=h(o.filterProps(e),["modelValue"]);return k(o,b(a,{modelValue:n.value,"onUpdate:modelValue":[m=>n.value=m,u],class:["v-checkbox-btn",e.class],style:e.style,type:"checkbox",falseIcon:i.value,trueIcon:d.value,"aria-checked":t.value?"mixed":void 0}),s)}),{}}});export{y as V,C as m};
1
+ import{c as f,d as o}from"./VSelectionControl-BSL0qeL9.js";import{x as V,ba as v,G as x,as as c,h as l,K as I,al as h,L as k,ap as b}from"./admin-drawer-panel-C34Ze3-5.js";const C=V({indeterminate:Boolean,indeterminateIcon:{type:v,default:"$checkboxIndeterminate"},...f({falseIcon:"$checkboxOff",trueIcon:"$checkboxOn"})},"VCheckboxBtn"),y=x()({name:"VCheckboxBtn",props:C(),emits:{"update:modelValue":e=>!0,"update:indeterminate":e=>!0},setup(e,r){let{slots:s}=r;const t=c(e,"indeterminate"),n=c(e,"modelValue");function u(a){t.value&&(t.value=!1)}const i=l(()=>t.value?e.indeterminateIcon:e.falseIcon),d=l(()=>t.value?e.indeterminateIcon:e.trueIcon);return I(()=>{const a=h(o.filterProps(e),["modelValue"]);return k(o,b(a,{modelValue:n.value,"onUpdate:modelValue":[m=>n.value=m,u],class:["v-checkbox-btn",e.class],style:e.style,type:"checkbox",falseIcon:i.value,trueIcon:d.value,"aria-checked":t.value?"mixed":void 0}),s)}),{}}});export{y as V,C as m};
@@ -1 +1 @@
1
- import{c as f,d as o}from"./VSelectionControl-zPp4DXWq.js";import{x as V,cq as v,G as x,as as c,h as l,K as I,al as h,L as k,ap as b}from"./admin-drawer-panel-Dp8KD9D7.js";const C=V({indeterminate:Boolean,indeterminateIcon:{type:v,default:"$checkboxIndeterminate"},...f({falseIcon:"$checkboxOff",trueIcon:"$checkboxOn"})},"VCheckboxBtn"),y=x()({name:"VCheckboxBtn",props:C(),emits:{"update:modelValue":e=>!0,"update:indeterminate":e=>!0},setup(e,r){let{slots:s}=r;const t=c(e,"indeterminate"),n=c(e,"modelValue");function u(a){t.value&&(t.value=!1)}const i=l(()=>t.value?e.indeterminateIcon:e.falseIcon),d=l(()=>t.value?e.indeterminateIcon:e.trueIcon);return I(()=>{const a=h(o.filterProps(e),["modelValue"]);return k(o,b(a,{modelValue:n.value,"onUpdate:modelValue":[m=>n.value=m,u],class:["v-checkbox-btn",e.class],style:e.style,type:"checkbox",falseIcon:i.value,trueIcon:d.value,"aria-checked":t.value?"mixed":void 0}),s)}),{}}});export{y as V,C as m};
1
+ import{c as f,d as o}from"./VSelectionControl-BSL0qeL9.js";import{x as V,ba as v,G as x,as as c,h as l,K as I,al as h,L as k,ap as b}from"./admin-drawer-panel-C34Ze3-5.js";const C=V({indeterminate:Boolean,indeterminateIcon:{type:v,default:"$checkboxIndeterminate"},...f({falseIcon:"$checkboxOff",trueIcon:"$checkboxOn"})},"VCheckboxBtn"),y=x()({name:"VCheckboxBtn",props:C(),emits:{"update:modelValue":e=>!0,"update:indeterminate":e=>!0},setup(e,r){let{slots:s}=r;const t=c(e,"indeterminate"),n=c(e,"modelValue");function u(a){t.value&&(t.value=!1)}const i=l(()=>t.value?e.indeterminateIcon:e.falseIcon),d=l(()=>t.value?e.indeterminateIcon:e.trueIcon);return I(()=>{const a=h(o.filterProps(e),["modelValue"]);return k(o,b(a,{modelValue:n.value,"onUpdate:modelValue":[m=>n.value=m,u],class:["v-checkbox-btn",e.class],style:e.style,type:"checkbox",falseIcon:i.value,trueIcon:d.value,"aria-checked":t.value?"mixed":void 0}),s)}),{}}});export{y as V,C as m};
@@ -0,0 +1 @@
1
+ import{m as pe,u as ke,a as Ce,b as we,c as Se}from"./VSelect-BnoCfCLY.js";import{m as Fe,V as Z}from"./VTextField-Da_Hs7ls.js";import{x as Ie,al as De,aZ as Pe,G as Ae,bS as Re,r as K,s as D,as as Q,h,cD as _e,an as Me,cE as P,a as A,n as Y,X as Ee,K as Te,L as s,M as O,ap as I,bq as Le,ak as ee,cF as Ne,ah as le,cG as Ke,bd as Oe,ad as Be,cH as Ue,cI as He,cJ as je}from"./admin-drawer-panel-C34Ze3-5.js";import{m as qe,u as ze}from"./filter-frSNsexx.js";import{g as Ge}from"./VSelectionControl-BSL0qeL9.js";import{f as $e}from"./VDialog-DiixpkQL.js";import{V as Je}from"./VCheckboxBtn-m4IbdjEe.js";function We(e,g,R){if(g==null)return e;if(Array.isArray(g))throw new Error("Multiple matches is not implemented");return typeof g=="number"&&~g?s(O,null,[s("span",{class:"v-combobox__unmask"},[e.substr(0,g)]),s("span",{class:"v-combobox__mask"},[e.substr(g,R)]),s("span",{class:"v-combobox__unmask"},[e.substr(g+R)])]):e}const Xe=Ie({autoSelectFirst:{type:[Boolean,String]},clearOnSelect:{type:Boolean,default:!0},delimiters:Array,...qe({filterKeys:["title"]}),...pe({hideNoData:!0,returnObject:!0}),...De(Fe({modelValue:null,role:"combobox"}),["validationValue","dirty","appendInnerIcon"]),...Pe({transition:!1})},"VCombobox"),ul=Ae()({name:"VCombobox",props:Xe(),emits:{"update:focused":e=>!0,"update:modelValue":e=>!0,"update:search":e=>!0,"update:menu":e=>!0},setup(e,g){var J;let{emit:R,slots:n}=g;const{t:B}=Re(),p=K(),x=D(!1),k=D(!0),_=D(!1),z=K(),G=K(),U=Q(e,"menu"),c=h({get:()=>U.value,set:l=>{var t;U.value&&!l&&((t=z.value)!=null&&t.ΨopenChildren)||(U.value=l)}}),r=D(-1);let H=!1;const ae=h(()=>{var l;return(l=p.value)==null?void 0:l.color}),$=h(()=>c.value?e.closeText:e.openText),{items:te,transformIn:ue,transformOut:ne}=_e(e),{textColorClasses:oe,textColorStyles:ie}=Me(ae),u=Q(e,"modelValue",[],l=>ue(je(l)),l=>{const t=ne(l);return e.multiple?t:t[0]??null}),F=Ge(),M=h(()=>!!(e.chips||n.chip)),y=h(()=>M.value||!!n.selection),C=D(!e.multiple&&!y.value?((J=u.value[0])==null?void 0:J.title)??"":""),v=h({get:()=>C.value,set:l=>{var t;if(C.value=l??"",!e.multiple&&!y.value&&(u.value=[P(e,l)]),l&&e.multiple&&((t=e.delimiters)!=null&&t.length)){const i=l.split(new RegExp(`(?:${e.delimiters.join("|")})+`));i.length>1&&(i.forEach(a=>{a=a.trim(),a&&m(P(e,a))}),C.value="")}l||(r.value=-1),k.value=!l}}),se=h(()=>typeof e.counterValue=="function"?e.counterValue(u.value):typeof e.counterValue=="number"?e.counterValue:e.multiple?u.value.length:v.value.length);A(C,l=>{H?Y(()=>H=!1):x.value&&!c.value&&(c.value=!0),R("update:search",l)}),A(u,l=>{var t;!e.multiple&&!y.value&&(C.value=((t=l[0])==null?void 0:t.title)??"")});const{filteredItems:E,getMatches:re}=ze(e,te,()=>k.value?"":v.value),V=h(()=>e.hideSelected?E.value.filter(l=>!u.value.some(t=>t.value===l.value)):E.value),ce=h(()=>u.value.map(l=>l.value)),T=h(()=>{var t;return(e.autoSelectFirst===!0||e.autoSelectFirst==="exact"&&v.value===((t=V.value[0])==null?void 0:t.title))&&V.value.length>0&&!k.value&&!_.value}),j=h(()=>e.hideNoData&&!V.value.length||e.readonly||(F==null?void 0:F.isReadonly.value)),q=K(),{onListScroll:ve,onListKeydown:de}=ke(q,p);function fe(l){H=!0,e.openOnClear&&(c.value=!0)}function me(){j.value||(c.value=!0)}function he(l){j.value||(x.value&&(l.preventDefault(),l.stopPropagation()),c.value=!c.value)}function be(l){var a;if(He(l)||e.readonly||F!=null&&F.isReadonly.value)return;const t=p.value.selectionStart,i=u.value.length;if((r.value>-1||["Enter","ArrowDown","ArrowUp"].includes(l.key))&&l.preventDefault(),["Enter","ArrowDown"].includes(l.key)&&(c.value=!0),["Escape"].includes(l.key)&&(c.value=!1),["Enter","Escape"].includes(l.key)&&(T.value&&l.key==="Enter"&&m(E.value[0]),k.value=!0),l.key==="ArrowDown"&&T.value&&((a=q.value)==null||a.focus("next")),l.key==="Enter"&&v.value&&(m(P(e,v.value)),y.value&&(C.value="")),["Backspace","Delete"].includes(l.key)){if(!e.multiple&&y.value&&u.value.length>0&&!v.value)return m(u.value[0],!1);if(~r.value){const o=r.value;m(u.value[r.value],!1),r.value=o>=i-1?i-2:o}else l.key==="Backspace"&&!v.value&&(r.value=i-1)}if(e.multiple){if(l.key==="ArrowLeft"){if(r.value<0&&t>0)return;const o=r.value>-1?r.value-1:i-1;u.value[o]?r.value=o:(r.value=-1,p.value.setSelectionRange(v.value.length,v.value.length))}if(l.key==="ArrowRight"){if(r.value<0)return;const o=r.value+1;u.value[o]?r.value=o:(r.value=-1,p.value.setSelectionRange(0,0))}}}function ge(){var l;x.value&&(k.value=!0,(l=p.value)==null||l.focus())}function m(l){let t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;if(!(!l||l.props.disabled))if(e.multiple){const i=u.value.findIndex(o=>e.valueComparator(o.value,l.value)),a=t??!~i;if(~i){const o=a?[...u.value,l]:[...u.value];o.splice(i,1),u.value=o}else a&&(u.value=[...u.value,l]);e.clearOnSelect&&(v.value="")}else{const i=t!==!1;u.value=i?[l]:[],C.value=i&&!y.value?l.title:"",Y(()=>{c.value=!1,k.value=!0})}}function xe(l){x.value=!0,setTimeout(()=>{_.value=!0})}function ye(l){_.value=!1}function Ve(l){(l==null||l===""&&!e.multiple&&!y.value)&&(u.value=[])}return A(x,(l,t)=>{if(!(l||l===t)){if(r.value=-1,c.value=!1,T.value&&!_.value&&!u.value.some(i=>{let{value:a}=i;return a===V.value[0].value})){m(V.value[0]);return}if(v.value){if(e.multiple){m(P(e,v.value));return}if(!y.value)return;u.value.some(i=>{let{title:a}=i;return a===v.value})?C.value="":m(P(e,v.value))}}}),A(c,()=>{if(!e.hideSelected&&c.value&&u.value.length){const l=V.value.findIndex(t=>u.value.some(i=>e.valueComparator(i.value,t.value)));Ee&&window.requestAnimationFrame(()=>{var t;l>=0&&((t=G.value)==null||t.scrollToIndex(l))})}}),A(()=>e.items,(l,t)=>{c.value||x.value&&!t.length&&l.length&&(c.value=!0)}),Te(()=>{const l=!!(!e.hideNoData||V.value.length||n["prepend-item"]||n["append-item"]||n["no-data"]),t=u.value.length>0,i=Z.filterProps(e);return s(Z,I({ref:p},i,{modelValue:v.value,"onUpdate:modelValue":[a=>v.value=a,Ve],focused:x.value,"onUpdate:focused":a=>x.value=a,validationValue:u.externalValue,counterValue:se.value,dirty:t,class:["v-combobox",{"v-combobox--active-menu":c.value,"v-combobox--chips":!!e.chips,"v-combobox--selection-slot":!!y.value,"v-combobox--selecting-index":r.value>-1,[`v-combobox--${e.multiple?"multiple":"single"}`]:!0},e.class],style:e.style,readonly:e.readonly,placeholder:t?void 0:e.placeholder,"onClick:clear":fe,"onMousedown:control":me,onKeydown:be}),{...n,default:()=>s(O,null,[s(Ce,I({ref:z,modelValue:c.value,"onUpdate:modelValue":a=>c.value=a,activator:"parent",contentClass:"v-combobox__content",disabled:j.value,eager:e.eager,maxHeight:310,openOnClick:!1,closeOnContentClick:!1,transition:e.transition,onAfterLeave:ge},e.menuProps),{default:()=>[l&&s(Le,I({ref:q,selected:ce.value,selectStrategy:e.multiple?"independent":"single-independent",onMousedown:a=>a.preventDefault(),onKeydown:de,onFocusin:xe,onFocusout:ye,onScrollPassive:ve,tabindex:"-1","aria-live":"polite",color:e.itemColor??e.color},e.listProps),{default:()=>{var a,o,b;return[(a=n["prepend-item"])==null?void 0:a.call(n),!V.value.length&&!e.hideNoData&&(((o=n["no-data"])==null?void 0:o.call(n))??s(ee,{title:B(e.noDataText)},null)),s(we,{ref:G,renderless:!0,items:V.value},{default:w=>{var X;let{item:d,index:S,itemRef:f}=w;const W=I(d.props,{ref:f,key:S,active:T.value&&S===0?!0:void 0,onClick:()=>m(d,null)});return((X=n.item)==null?void 0:X.call(n,{item:d,index:S,props:W}))??s(ee,I(W,{role:"option"}),{prepend:L=>{let{isSelected:N}=L;return s(O,null,[e.multiple&&!e.hideSelected?s(Je,{key:d.value,modelValue:N,ripple:!1,tabindex:"-1"},null):void 0,d.props.prependAvatar&&s(Ne,{image:d.props.prependAvatar},null),d.props.prependIcon&&s(le,{icon:d.props.prependIcon},null)])},title:()=>{var L,N;return k.value?d.title:We(d.title,(L=re(d))==null?void 0:L.title,((N=v.value)==null?void 0:N.length)??0)}})}}),(b=n["append-item"])==null?void 0:b.call(n)]}})]}),u.value.map((a,o)=>{function b(f){f.stopPropagation(),f.preventDefault(),m(a,!1)}const w={"onClick:close":b,onKeydown(f){f.key!=="Enter"&&f.key!==" "||(f.preventDefault(),f.stopPropagation(),b(f))},onMousedown(f){f.preventDefault(),f.stopPropagation()},modelValue:!0,"onUpdate:modelValue":void 0},d=M.value?!!n.chip:!!n.selection,S=d?Ke(M.value?n.chip({item:a,index:o,props:w}):n.selection({item:a,index:o})):void 0;if(!(d&&!S))return s("div",{key:a.value,class:["v-combobox__selection",o===r.value&&["v-combobox__selection--selected",oe.value]],style:o===r.value?ie.value:{}},[M.value?n.chip?s(Oe,{key:"chip-defaults",defaults:{VChip:{closable:e.closableChips,size:"small",text:a.title}}},{default:()=>[S]}):s(Se,I({key:"chip",closable:e.closableChips,size:"small",text:a.title,disabled:a.props.disabled},w),null):S??s("span",{class:"v-combobox__selection-text"},[a.title,e.multiple&&o<u.value.length-1&&s("span",{class:"v-combobox__selection-comma"},[Be(",")])])])})]),"append-inner":function(){var w;for(var a=arguments.length,o=new Array(a),b=0;b<a;b++)o[b]=arguments[b];return s(O,null,[(w=n["append-inner"])==null?void 0:w.call(n,...o),(!e.hideNoData||e.items.length)&&e.menuIcon?s(le,{class:"v-combobox__menu-icon",icon:e.menuIcon,onMousedown:he,onClick:Ue,"aria-label":B($.value),title:B($.value),tabindex:"-1"},null):void 0])}})}),$e({isFocused:x,isPristine:k,menu:c,search:v,selectionIndex:r,filteredItems:E,select:m},p)}});export{ul as V};
@@ -0,0 +1 @@
1
+ import{m as pe,u as ke,a as Ce,b as we,c as Se}from"./VSelect-BnoCfCLY.js";import{m as Fe,V as Z}from"./VTextField-Da_Hs7ls.js";import{x as Ie,al as De,aZ as Pe,G as Ae,bS as Re,r as K,s as D,as as Q,h,cD as _e,an as Me,cE as P,a as A,n as Y,X as Ee,K as Te,L as s,M as O,ap as I,bq as Le,ak as ee,cF as Ne,ah as le,cG as Ke,bd as Oe,ad as Be,cH as Ue,cI as He,cJ as je}from"./admin-drawer-panel-C34Ze3-5.js";import{m as qe,u as ze}from"./filter-frSNsexx.js";import{g as Ge}from"./VSelectionControl-BSL0qeL9.js";import{f as $e}from"./VDialog-DiixpkQL.js";import{V as Je}from"./VCheckboxBtn-m4IbdjEe.js";function We(e,g,R){if(g==null)return e;if(Array.isArray(g))throw new Error("Multiple matches is not implemented");return typeof g=="number"&&~g?s(O,null,[s("span",{class:"v-combobox__unmask"},[e.substr(0,g)]),s("span",{class:"v-combobox__mask"},[e.substr(g,R)]),s("span",{class:"v-combobox__unmask"},[e.substr(g+R)])]):e}const Xe=Ie({autoSelectFirst:{type:[Boolean,String]},clearOnSelect:{type:Boolean,default:!0},delimiters:Array,...qe({filterKeys:["title"]}),...pe({hideNoData:!0,returnObject:!0}),...De(Fe({modelValue:null,role:"combobox"}),["validationValue","dirty","appendInnerIcon"]),...Pe({transition:!1})},"VCombobox"),ul=Ae()({name:"VCombobox",props:Xe(),emits:{"update:focused":e=>!0,"update:modelValue":e=>!0,"update:search":e=>!0,"update:menu":e=>!0},setup(e,g){var J;let{emit:R,slots:n}=g;const{t:B}=Re(),p=K(),x=D(!1),k=D(!0),_=D(!1),z=K(),G=K(),U=Q(e,"menu"),c=h({get:()=>U.value,set:l=>{var t;U.value&&!l&&((t=z.value)!=null&&t.ΨopenChildren)||(U.value=l)}}),r=D(-1);let H=!1;const ae=h(()=>{var l;return(l=p.value)==null?void 0:l.color}),$=h(()=>c.value?e.closeText:e.openText),{items:te,transformIn:ue,transformOut:ne}=_e(e),{textColorClasses:oe,textColorStyles:ie}=Me(ae),u=Q(e,"modelValue",[],l=>ue(je(l)),l=>{const t=ne(l);return e.multiple?t:t[0]??null}),F=Ge(),M=h(()=>!!(e.chips||n.chip)),y=h(()=>M.value||!!n.selection),C=D(!e.multiple&&!y.value?((J=u.value[0])==null?void 0:J.title)??"":""),v=h({get:()=>C.value,set:l=>{var t;if(C.value=l??"",!e.multiple&&!y.value&&(u.value=[P(e,l)]),l&&e.multiple&&((t=e.delimiters)!=null&&t.length)){const i=l.split(new RegExp(`(?:${e.delimiters.join("|")})+`));i.length>1&&(i.forEach(a=>{a=a.trim(),a&&m(P(e,a))}),C.value="")}l||(r.value=-1),k.value=!l}}),se=h(()=>typeof e.counterValue=="function"?e.counterValue(u.value):typeof e.counterValue=="number"?e.counterValue:e.multiple?u.value.length:v.value.length);A(C,l=>{H?Y(()=>H=!1):x.value&&!c.value&&(c.value=!0),R("update:search",l)}),A(u,l=>{var t;!e.multiple&&!y.value&&(C.value=((t=l[0])==null?void 0:t.title)??"")});const{filteredItems:E,getMatches:re}=ze(e,te,()=>k.value?"":v.value),V=h(()=>e.hideSelected?E.value.filter(l=>!u.value.some(t=>t.value===l.value)):E.value),ce=h(()=>u.value.map(l=>l.value)),T=h(()=>{var t;return(e.autoSelectFirst===!0||e.autoSelectFirst==="exact"&&v.value===((t=V.value[0])==null?void 0:t.title))&&V.value.length>0&&!k.value&&!_.value}),j=h(()=>e.hideNoData&&!V.value.length||e.readonly||(F==null?void 0:F.isReadonly.value)),q=K(),{onListScroll:ve,onListKeydown:de}=ke(q,p);function fe(l){H=!0,e.openOnClear&&(c.value=!0)}function me(){j.value||(c.value=!0)}function he(l){j.value||(x.value&&(l.preventDefault(),l.stopPropagation()),c.value=!c.value)}function be(l){var a;if(He(l)||e.readonly||F!=null&&F.isReadonly.value)return;const t=p.value.selectionStart,i=u.value.length;if((r.value>-1||["Enter","ArrowDown","ArrowUp"].includes(l.key))&&l.preventDefault(),["Enter","ArrowDown"].includes(l.key)&&(c.value=!0),["Escape"].includes(l.key)&&(c.value=!1),["Enter","Escape"].includes(l.key)&&(T.value&&l.key==="Enter"&&m(E.value[0]),k.value=!0),l.key==="ArrowDown"&&T.value&&((a=q.value)==null||a.focus("next")),l.key==="Enter"&&v.value&&(m(P(e,v.value)),y.value&&(C.value="")),["Backspace","Delete"].includes(l.key)){if(!e.multiple&&y.value&&u.value.length>0&&!v.value)return m(u.value[0],!1);if(~r.value){const o=r.value;m(u.value[r.value],!1),r.value=o>=i-1?i-2:o}else l.key==="Backspace"&&!v.value&&(r.value=i-1)}if(e.multiple){if(l.key==="ArrowLeft"){if(r.value<0&&t>0)return;const o=r.value>-1?r.value-1:i-1;u.value[o]?r.value=o:(r.value=-1,p.value.setSelectionRange(v.value.length,v.value.length))}if(l.key==="ArrowRight"){if(r.value<0)return;const o=r.value+1;u.value[o]?r.value=o:(r.value=-1,p.value.setSelectionRange(0,0))}}}function ge(){var l;x.value&&(k.value=!0,(l=p.value)==null||l.focus())}function m(l){let t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;if(!(!l||l.props.disabled))if(e.multiple){const i=u.value.findIndex(o=>e.valueComparator(o.value,l.value)),a=t??!~i;if(~i){const o=a?[...u.value,l]:[...u.value];o.splice(i,1),u.value=o}else a&&(u.value=[...u.value,l]);e.clearOnSelect&&(v.value="")}else{const i=t!==!1;u.value=i?[l]:[],C.value=i&&!y.value?l.title:"",Y(()=>{c.value=!1,k.value=!0})}}function xe(l){x.value=!0,setTimeout(()=>{_.value=!0})}function ye(l){_.value=!1}function Ve(l){(l==null||l===""&&!e.multiple&&!y.value)&&(u.value=[])}return A(x,(l,t)=>{if(!(l||l===t)){if(r.value=-1,c.value=!1,T.value&&!_.value&&!u.value.some(i=>{let{value:a}=i;return a===V.value[0].value})){m(V.value[0]);return}if(v.value){if(e.multiple){m(P(e,v.value));return}if(!y.value)return;u.value.some(i=>{let{title:a}=i;return a===v.value})?C.value="":m(P(e,v.value))}}}),A(c,()=>{if(!e.hideSelected&&c.value&&u.value.length){const l=V.value.findIndex(t=>u.value.some(i=>e.valueComparator(i.value,t.value)));Ee&&window.requestAnimationFrame(()=>{var t;l>=0&&((t=G.value)==null||t.scrollToIndex(l))})}}),A(()=>e.items,(l,t)=>{c.value||x.value&&!t.length&&l.length&&(c.value=!0)}),Te(()=>{const l=!!(!e.hideNoData||V.value.length||n["prepend-item"]||n["append-item"]||n["no-data"]),t=u.value.length>0,i=Z.filterProps(e);return s(Z,I({ref:p},i,{modelValue:v.value,"onUpdate:modelValue":[a=>v.value=a,Ve],focused:x.value,"onUpdate:focused":a=>x.value=a,validationValue:u.externalValue,counterValue:se.value,dirty:t,class:["v-combobox",{"v-combobox--active-menu":c.value,"v-combobox--chips":!!e.chips,"v-combobox--selection-slot":!!y.value,"v-combobox--selecting-index":r.value>-1,[`v-combobox--${e.multiple?"multiple":"single"}`]:!0},e.class],style:e.style,readonly:e.readonly,placeholder:t?void 0:e.placeholder,"onClick:clear":fe,"onMousedown:control":me,onKeydown:be}),{...n,default:()=>s(O,null,[s(Ce,I({ref:z,modelValue:c.value,"onUpdate:modelValue":a=>c.value=a,activator:"parent",contentClass:"v-combobox__content",disabled:j.value,eager:e.eager,maxHeight:310,openOnClick:!1,closeOnContentClick:!1,transition:e.transition,onAfterLeave:ge},e.menuProps),{default:()=>[l&&s(Le,I({ref:q,selected:ce.value,selectStrategy:e.multiple?"independent":"single-independent",onMousedown:a=>a.preventDefault(),onKeydown:de,onFocusin:xe,onFocusout:ye,onScrollPassive:ve,tabindex:"-1","aria-live":"polite",color:e.itemColor??e.color},e.listProps),{default:()=>{var a,o,b;return[(a=n["prepend-item"])==null?void 0:a.call(n),!V.value.length&&!e.hideNoData&&(((o=n["no-data"])==null?void 0:o.call(n))??s(ee,{title:B(e.noDataText)},null)),s(we,{ref:G,renderless:!0,items:V.value},{default:w=>{var X;let{item:d,index:S,itemRef:f}=w;const W=I(d.props,{ref:f,key:S,active:T.value&&S===0?!0:void 0,onClick:()=>m(d,null)});return((X=n.item)==null?void 0:X.call(n,{item:d,index:S,props:W}))??s(ee,I(W,{role:"option"}),{prepend:L=>{let{isSelected:N}=L;return s(O,null,[e.multiple&&!e.hideSelected?s(Je,{key:d.value,modelValue:N,ripple:!1,tabindex:"-1"},null):void 0,d.props.prependAvatar&&s(Ne,{image:d.props.prependAvatar},null),d.props.prependIcon&&s(le,{icon:d.props.prependIcon},null)])},title:()=>{var L,N;return k.value?d.title:We(d.title,(L=re(d))==null?void 0:L.title,((N=v.value)==null?void 0:N.length)??0)}})}}),(b=n["append-item"])==null?void 0:b.call(n)]}})]}),u.value.map((a,o)=>{function b(f){f.stopPropagation(),f.preventDefault(),m(a,!1)}const w={"onClick:close":b,onKeydown(f){f.key!=="Enter"&&f.key!==" "||(f.preventDefault(),f.stopPropagation(),b(f))},onMousedown(f){f.preventDefault(),f.stopPropagation()},modelValue:!0,"onUpdate:modelValue":void 0},d=M.value?!!n.chip:!!n.selection,S=d?Ke(M.value?n.chip({item:a,index:o,props:w}):n.selection({item:a,index:o})):void 0;if(!(d&&!S))return s("div",{key:a.value,class:["v-combobox__selection",o===r.value&&["v-combobox__selection--selected",oe.value]],style:o===r.value?ie.value:{}},[M.value?n.chip?s(Oe,{key:"chip-defaults",defaults:{VChip:{closable:e.closableChips,size:"small",text:a.title}}},{default:()=>[S]}):s(Se,I({key:"chip",closable:e.closableChips,size:"small",text:a.title,disabled:a.props.disabled},w),null):S??s("span",{class:"v-combobox__selection-text"},[a.title,e.multiple&&o<u.value.length-1&&s("span",{class:"v-combobox__selection-comma"},[Be(",")])])])})]),"append-inner":function(){var w;for(var a=arguments.length,o=new Array(a),b=0;b<a;b++)o[b]=arguments[b];return s(O,null,[(w=n["append-inner"])==null?void 0:w.call(n,...o),(!e.hideNoData||e.items.length)&&e.menuIcon?s(le,{class:"v-combobox__menu-icon",icon:e.menuIcon,onMousedown:he,onClick:Ue,"aria-label":B($.value),title:B($.value),tabindex:"-1"},null):void 0])}})}),$e({isFocused:x,isPristine:k,menu:c,search:v,selectionIndex:r,filteredItems:E,select:m},p)}});export{ul as V};