codex 1.6.0a9__py3-none-any.whl → 1.6.0a11__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 (560) hide show
  1. codex/librarian/importer/cache.py +46 -133
  2. codex/librarian/importer/create_fks.py +3 -1
  3. codex/librarian/importer/importer.py +1 -1
  4. codex/librarian/importer/importerd.py +5 -5
  5. codex/librarian/importer/tasks.py +2 -2
  6. codex/librarian/janitor/janitor.py +0 -3
  7. codex/librarian/librariand.py +0 -2
  8. codex/librarian/notifier/notifierd.py +1 -1
  9. codex/librarian/notifier/tasks.py +4 -4
  10. codex/middleware.py +1 -2
  11. codex/migrations/0027_import_order_and_covers.py +1 -66
  12. codex/models/comic.py +0 -1
  13. codex/models/groups.py +0 -3
  14. codex/serializers/admin.py +41 -40
  15. codex/serializers/browser/choices.py +38 -10
  16. codex/serializers/browser/filters.py +2 -2
  17. codex/serializers/browser/metadata.py +45 -1
  18. codex/serializers/browser/mixins.py +35 -2
  19. codex/serializers/browser/page.py +2 -4
  20. codex/serializers/browser/settings.py +41 -14
  21. codex/serializers/choices.py +4 -0
  22. codex/serializers/fields.py +61 -1
  23. codex/serializers/models/pycountry.py +11 -51
  24. codex/serializers/reader.py +12 -1
  25. codex/serializers/route.py +1 -1
  26. codex/serializers/settings.py +12 -0
  27. codex/settings/settings.py +10 -1
  28. codex/static_root/assets/VCheckbox-BwDyxhU7.831b00df198a.js +1 -0
  29. codex/static_root/assets/VCheckbox-BwDyxhU7.831b00df198a.js.br +0 -0
  30. codex/static_root/assets/VCheckbox-BwDyxhU7.831b00df198a.js.gz +0 -0
  31. codex/static_root/assets/VCheckbox-BwDyxhU7.js +1 -0
  32. codex/static_root/assets/VCheckbox-BwDyxhU7.js.br +0 -0
  33. codex/static_root/assets/VCheckbox-BwDyxhU7.js.gz +0 -0
  34. codex/static_root/assets/{VCheckboxBtn-DLzF_WHB.9a47873b8548.js → VCheckboxBtn-DVq5lDK4.5e6464c8d80a.js} +1 -1
  35. codex/static_root/assets/VCheckboxBtn-DVq5lDK4.5e6464c8d80a.js.br +0 -0
  36. codex/static_root/assets/VCheckboxBtn-DVq5lDK4.5e6464c8d80a.js.gz +0 -0
  37. codex/static_root/assets/{VCheckboxBtn-DLzF_WHB.js → VCheckboxBtn-DVq5lDK4.js} +1 -1
  38. codex/static_root/assets/VCheckboxBtn-DVq5lDK4.js.br +0 -0
  39. codex/static_root/assets/VCheckboxBtn-DVq5lDK4.js.gz +0 -0
  40. codex/static_root/assets/VCombobox-BASCOy0n.7801caa5e192.js +1 -0
  41. codex/static_root/assets/VCombobox-BASCOy0n.7801caa5e192.js.br +0 -0
  42. codex/static_root/assets/VCombobox-BASCOy0n.7801caa5e192.js.gz +0 -0
  43. codex/static_root/assets/VCombobox-BASCOy0n.js +1 -0
  44. codex/static_root/assets/VCombobox-BASCOy0n.js.br +0 -0
  45. codex/static_root/assets/VCombobox-BASCOy0n.js.gz +0 -0
  46. codex/static_root/assets/VDialog-DnbL_v_u.0bd289bda8e6.js +1 -0
  47. codex/static_root/assets/VDialog-DnbL_v_u.0bd289bda8e6.js.br +0 -0
  48. codex/static_root/assets/VDialog-DnbL_v_u.0bd289bda8e6.js.gz +0 -0
  49. codex/static_root/assets/VDialog-DnbL_v_u.js +1 -0
  50. codex/static_root/assets/VDialog-DnbL_v_u.js.br +0 -0
  51. codex/static_root/assets/VDialog-DnbL_v_u.js.gz +0 -0
  52. codex/static_root/assets/{VDialog-C5Nxd_zP.css → VDialog-lQ13FnRR.1c801ad756b2.css} +1 -1
  53. codex/static_root/assets/VDialog-lQ13FnRR.1c801ad756b2.css.br +0 -0
  54. codex/static_root/assets/VDialog-lQ13FnRR.1c801ad756b2.css.gz +0 -0
  55. codex/static_root/assets/{VDialog-C5Nxd_zP.d327f505ef0e.css → VDialog-lQ13FnRR.css} +1 -1
  56. codex/static_root/assets/VDialog-lQ13FnRR.css.br +0 -0
  57. codex/static_root/assets/VDialog-lQ13FnRR.css.gz +0 -0
  58. codex/static_root/assets/VExpansionPanels-B8nz8lN5.56e5adec4f62.js +1 -0
  59. codex/static_root/assets/VExpansionPanels-B8nz8lN5.56e5adec4f62.js.br +0 -0
  60. codex/static_root/assets/VExpansionPanels-B8nz8lN5.56e5adec4f62.js.gz +0 -0
  61. codex/static_root/assets/VExpansionPanels-B8nz8lN5.js +1 -0
  62. codex/static_root/assets/VExpansionPanels-B8nz8lN5.js.br +0 -0
  63. codex/static_root/assets/VExpansionPanels-B8nz8lN5.js.gz +0 -0
  64. codex/static_root/assets/{VRadioGroup-B--7K_v5.4a4e9c2d6c42.js → VRadioGroup-BgwJ_b94.55f84f3429b9.js} +1 -1
  65. codex/static_root/assets/VRadioGroup-BgwJ_b94.55f84f3429b9.js.br +0 -0
  66. codex/static_root/assets/VRadioGroup-BgwJ_b94.55f84f3429b9.js.gz +0 -0
  67. codex/static_root/assets/{VRadioGroup-B--7K_v5.js → VRadioGroup-BgwJ_b94.js} +1 -1
  68. codex/static_root/assets/VRadioGroup-BgwJ_b94.js.br +0 -0
  69. codex/static_root/assets/VRadioGroup-BgwJ_b94.js.gz +0 -0
  70. codex/static_root/assets/VSelect-BoKpXxwe.a88f065dfe3b.js +1 -0
  71. codex/static_root/assets/VSelect-BoKpXxwe.a88f065dfe3b.js.br +0 -0
  72. codex/static_root/assets/VSelect-BoKpXxwe.a88f065dfe3b.js.gz +0 -0
  73. codex/static_root/assets/VSelect-BoKpXxwe.js +1 -0
  74. codex/static_root/assets/VSelect-BoKpXxwe.js.br +0 -0
  75. codex/static_root/assets/VSelect-BoKpXxwe.js.gz +0 -0
  76. codex/static_root/assets/{VSelectionControl-CVQ9wkE2.c02186cceba6.js → VSelectionControl-BXJGg8No.0cb36d941d2a.js} +1 -1
  77. codex/static_root/assets/VSelectionControl-BXJGg8No.0cb36d941d2a.js.br +0 -0
  78. codex/static_root/assets/VSelectionControl-BXJGg8No.0cb36d941d2a.js.gz +0 -0
  79. codex/static_root/assets/{VSelectionControl-CVQ9wkE2.js → VSelectionControl-BXJGg8No.js} +1 -1
  80. codex/static_root/assets/VSelectionControl-BXJGg8No.js.br +0 -0
  81. codex/static_root/assets/VSelectionControl-BXJGg8No.js.gz +0 -0
  82. codex/static_root/assets/VSlideGroup-C2TL5E34.775adeb5a973.js +1 -0
  83. codex/static_root/assets/VSlideGroup-C2TL5E34.775adeb5a973.js.br +0 -0
  84. codex/static_root/assets/VSlideGroup-C2TL5E34.775adeb5a973.js.gz +0 -0
  85. codex/static_root/assets/VSlideGroup-C2TL5E34.js +1 -0
  86. codex/static_root/assets/VSlideGroup-C2TL5E34.js.br +0 -0
  87. codex/static_root/assets/VSlideGroup-C2TL5E34.js.gz +0 -0
  88. codex/static_root/assets/{VTable-CrWkhkiP.6d530eea0c09.js → VTable-C0FptljX.e4840b635c6e.js} +1 -1
  89. codex/static_root/assets/VTable-C0FptljX.e4840b635c6e.js.br +0 -0
  90. codex/static_root/assets/VTable-C0FptljX.e4840b635c6e.js.gz +0 -0
  91. codex/static_root/assets/{VTable-CrWkhkiP.js → VTable-C0FptljX.js} +1 -1
  92. codex/static_root/assets/VTable-C0FptljX.js.br +0 -0
  93. codex/static_root/assets/VTable-C0FptljX.js.gz +0 -0
  94. codex/static_root/assets/VTextField-Aw8nKhY6.428732ac22d7.js +1 -0
  95. codex/static_root/assets/VTextField-Aw8nKhY6.428732ac22d7.js.br +0 -0
  96. codex/static_root/assets/VTextField-Aw8nKhY6.428732ac22d7.js.gz +0 -0
  97. codex/static_root/assets/VTextField-Aw8nKhY6.js +1 -0
  98. codex/static_root/assets/VTextField-Aw8nKhY6.js.br +0 -0
  99. codex/static_root/assets/VTextField-Aw8nKhY6.js.gz +0 -0
  100. codex/static_root/assets/VWindowItem-D9j_u9MX.828acf3dee55.js +1 -0
  101. codex/static_root/assets/VWindowItem-D9j_u9MX.828acf3dee55.js.br +0 -0
  102. codex/static_root/assets/VWindowItem-D9j_u9MX.828acf3dee55.js.gz +0 -0
  103. codex/static_root/assets/VWindowItem-D9j_u9MX.js +1 -0
  104. codex/static_root/assets/VWindowItem-D9j_u9MX.js.br +0 -0
  105. codex/static_root/assets/VWindowItem-D9j_u9MX.js.gz +0 -0
  106. codex/static_root/assets/admin-drawer-panel-Dmn4wEY3.af7e8490f0e3.js +30 -0
  107. codex/static_root/assets/admin-drawer-panel-Dmn4wEY3.af7e8490f0e3.js.br +0 -0
  108. codex/static_root/assets/admin-drawer-panel-Dmn4wEY3.af7e8490f0e3.js.gz +0 -0
  109. codex/static_root/assets/admin-drawer-panel-Dmn4wEY3.js +30 -0
  110. codex/static_root/assets/admin-drawer-panel-Dmn4wEY3.js.br +0 -0
  111. codex/static_root/assets/admin-drawer-panel-Dmn4wEY3.js.gz +0 -0
  112. codex/static_root/assets/{admin-drawer-panel-o87BwD38.ce39427c8201.css → admin-drawer-panel-mne3FIj6.561b3f75fe65.css} +1 -1
  113. codex/static_root/assets/admin-drawer-panel-mne3FIj6.561b3f75fe65.css.br +0 -0
  114. codex/static_root/assets/admin-drawer-panel-mne3FIj6.561b3f75fe65.css.gz +0 -0
  115. codex/static_root/assets/{admin-drawer-panel-o87BwD38.css → admin-drawer-panel-mne3FIj6.css} +1 -1
  116. codex/static_root/assets/admin-drawer-panel-mne3FIj6.css.br +0 -0
  117. codex/static_root/assets/admin-drawer-panel-mne3FIj6.css.gz +0 -0
  118. codex/static_root/assets/admin-jf7zR2p_.4741813376d2.js +1 -0
  119. codex/static_root/assets/admin-jf7zR2p_.4741813376d2.js.br +0 -0
  120. codex/static_root/assets/admin-jf7zR2p_.4741813376d2.js.gz +0 -0
  121. codex/static_root/assets/admin-jf7zR2p_.js +1 -0
  122. codex/static_root/assets/admin-jf7zR2p_.js.br +0 -0
  123. codex/static_root/assets/admin-jf7zR2p_.js.gz +0 -0
  124. codex/static_root/assets/browser-BKZuypzF.86e5333bd7d6.js +1 -0
  125. codex/static_root/assets/browser-BKZuypzF.86e5333bd7d6.js.br +0 -0
  126. codex/static_root/assets/browser-BKZuypzF.86e5333bd7d6.js.gz +0 -0
  127. codex/static_root/assets/browser-BKZuypzF.js +1 -0
  128. codex/static_root/assets/browser-BKZuypzF.js.br +0 -0
  129. codex/static_root/assets/browser-BKZuypzF.js.gz +0 -0
  130. codex/static_root/assets/browser-D7xci5SY.css +1 -0
  131. codex/static_root/assets/browser-D7xci5SY.css.br +0 -0
  132. codex/static_root/assets/browser-D7xci5SY.css.gz +0 -0
  133. codex/static_root/assets/browser-D7xci5SY.fa305e14005c.css +1 -0
  134. codex/static_root/assets/browser-D7xci5SY.fa305e14005c.css.br +0 -0
  135. codex/static_root/assets/browser-D7xci5SY.fa305e14005c.css.gz +0 -0
  136. codex/static_root/assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css +1 -0
  137. codex/static_root/assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css.br +0 -0
  138. codex/static_root/assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css.gz +0 -0
  139. codex/static_root/assets/change-password-dialog-0u6IJA87.css +1 -0
  140. codex/static_root/assets/change-password-dialog-0u6IJA87.css.br +0 -0
  141. codex/static_root/assets/change-password-dialog-0u6IJA87.css.gz +0 -0
  142. codex/static_root/assets/change-password-dialog-Cc1e755p.b29d200537bf.js +1 -0
  143. codex/static_root/assets/change-password-dialog-Cc1e755p.b29d200537bf.js.br +0 -0
  144. codex/static_root/assets/change-password-dialog-Cc1e755p.b29d200537bf.js.gz +0 -0
  145. codex/static_root/assets/change-password-dialog-Cc1e755p.js +1 -0
  146. codex/static_root/assets/change-password-dialog-Cc1e755p.js.br +0 -0
  147. codex/static_root/assets/change-password-dialog-Cc1e755p.js.gz +0 -0
  148. codex/static_root/assets/{confirm-dialog-jwL7B98r.1cfd579cbcfe.js → confirm-dialog-Cyr7HAAz.8ab1d8b6241a.js} +1 -1
  149. codex/static_root/assets/confirm-dialog-Cyr7HAAz.8ab1d8b6241a.js.br +0 -0
  150. codex/static_root/assets/confirm-dialog-Cyr7HAAz.8ab1d8b6241a.js.gz +0 -0
  151. codex/static_root/assets/{confirm-dialog-jwL7B98r.js → confirm-dialog-Cyr7HAAz.js} +1 -1
  152. codex/static_root/assets/confirm-dialog-Cyr7HAAz.js.br +0 -0
  153. codex/static_root/assets/confirm-dialog-Cyr7HAAz.js.gz +0 -0
  154. codex/static_root/assets/datetime-column-Cqi99Ze-.49d0ce340183.js +1 -0
  155. codex/static_root/assets/datetime-column-Cqi99Ze-.49d0ce340183.js.br +0 -0
  156. codex/static_root/assets/datetime-column-Cqi99Ze-.49d0ce340183.js.gz +0 -0
  157. codex/static_root/assets/datetime-column-Cqi99Ze-.js +1 -0
  158. codex/static_root/assets/datetime-column-Cqi99Ze-.js.br +0 -0
  159. codex/static_root/assets/datetime-column-Cqi99Ze-.js.gz +0 -0
  160. codex/static_root/assets/filter-CuocBoS2.885d1b8d44cc.js +1 -0
  161. codex/static_root/assets/filter-CuocBoS2.885d1b8d44cc.js.br +0 -0
  162. codex/static_root/assets/filter-CuocBoS2.885d1b8d44cc.js.gz +0 -0
  163. codex/static_root/assets/filter-CuocBoS2.js +1 -0
  164. codex/static_root/assets/filter-CuocBoS2.js.br +0 -0
  165. codex/static_root/assets/filter-CuocBoS2.js.gz +0 -0
  166. codex/static_root/assets/{flag-tab-Da2DBNyz.ffbe5ca37e1c.js → flag-tab-B5dRCBAt.e858f7ec9f55.js} +1 -1
  167. codex/static_root/assets/flag-tab-B5dRCBAt.e858f7ec9f55.js.br +0 -0
  168. codex/static_root/assets/flag-tab-B5dRCBAt.e858f7ec9f55.js.gz +0 -0
  169. codex/static_root/assets/{flag-tab-Da2DBNyz.js → flag-tab-B5dRCBAt.js} +1 -1
  170. codex/static_root/assets/flag-tab-B5dRCBAt.js.br +0 -0
  171. codex/static_root/assets/flag-tab-B5dRCBAt.js.gz +0 -0
  172. codex/static_root/assets/{group-tab-BONYWOc1.6ddf321a4a56.js → group-tab-_nT2o04v.c06032b254dc.js} +1 -1
  173. codex/static_root/assets/group-tab-_nT2o04v.c06032b254dc.js.br +0 -0
  174. codex/static_root/assets/group-tab-_nT2o04v.c06032b254dc.js.gz +0 -0
  175. codex/static_root/assets/{group-tab-BONYWOc1.js → group-tab-_nT2o04v.js} +1 -1
  176. codex/static_root/assets/group-tab-_nT2o04v.js.br +0 -0
  177. codex/static_root/assets/group-tab-_nT2o04v.js.gz +0 -0
  178. codex/static_root/assets/{http-error-D2Jnc20C.32846bc3a43d.js → http-error-CXo9qLiW.d5a337f399c9.js} +1 -1
  179. codex/static_root/assets/http-error-CXo9qLiW.d5a337f399c9.js.br +0 -0
  180. codex/static_root/assets/http-error-CXo9qLiW.d5a337f399c9.js.gz +0 -0
  181. codex/static_root/assets/{http-error-D2Jnc20C.js → http-error-CXo9qLiW.js} +1 -1
  182. codex/static_root/assets/http-error-CXo9qLiW.js.br +0 -0
  183. codex/static_root/assets/http-error-CXo9qLiW.js.gz +0 -0
  184. codex/static_root/assets/{library-tab-B419agXA.js → library-tab-lz5QMD4i.2f04b226ebe8.js} +1 -1
  185. codex/static_root/assets/library-tab-lz5QMD4i.2f04b226ebe8.js.br +0 -0
  186. codex/static_root/assets/library-tab-lz5QMD4i.2f04b226ebe8.js.gz +0 -0
  187. codex/static_root/assets/{library-tab-B419agXA.d4b778172aaa.js → library-tab-lz5QMD4i.js} +1 -1
  188. codex/static_root/assets/library-tab-lz5QMD4i.js.br +0 -0
  189. codex/static_root/assets/library-tab-lz5QMD4i.js.gz +0 -0
  190. codex/static_root/assets/main-17i0EBCp.7093c3f755f1.js +32 -0
  191. codex/static_root/assets/main-17i0EBCp.7093c3f755f1.js.br +0 -0
  192. codex/static_root/assets/main-17i0EBCp.7093c3f755f1.js.gz +0 -0
  193. codex/static_root/assets/main-17i0EBCp.js +32 -0
  194. codex/static_root/assets/main-17i0EBCp.js.br +0 -0
  195. codex/static_root/assets/main-17i0EBCp.js.gz +0 -0
  196. codex/static_root/assets/pagination-toolbar-BBvsIXTd.ad891da6617a.js +1 -0
  197. codex/static_root/assets/pagination-toolbar-BBvsIXTd.ad891da6617a.js.br +0 -0
  198. codex/static_root/assets/pagination-toolbar-BBvsIXTd.ad891da6617a.js.gz +0 -0
  199. codex/static_root/assets/pagination-toolbar-BBvsIXTd.js +1 -0
  200. codex/static_root/assets/pagination-toolbar-BBvsIXTd.js.br +0 -0
  201. codex/static_root/assets/pagination-toolbar-BBvsIXTd.js.gz +0 -0
  202. codex/static_root/assets/pagination-toolbar-B_zL7BQQ.css +1 -0
  203. codex/static_root/assets/pagination-toolbar-B_zL7BQQ.css.br +0 -0
  204. codex/static_root/assets/pagination-toolbar-B_zL7BQQ.css.gz +0 -0
  205. codex/static_root/assets/pagination-toolbar-B_zL7BQQ.d1311bd41edc.css +1 -0
  206. codex/static_root/assets/pagination-toolbar-B_zL7BQQ.d1311bd41edc.css.br +0 -0
  207. codex/static_root/assets/pagination-toolbar-B_zL7BQQ.d1311bd41edc.css.gz +0 -0
  208. codex/static_root/assets/{pdf-doc-8RVZqILx.2e7166dd26fb.js → pdf-doc-BpZdmj2g.93e86d9c7927.js} +1 -1
  209. codex/static_root/assets/pdf-doc-BpZdmj2g.93e86d9c7927.js.br +0 -0
  210. codex/static_root/assets/pdf-doc-BpZdmj2g.93e86d9c7927.js.gz +0 -0
  211. codex/static_root/assets/{pdf-doc-8RVZqILx.js → pdf-doc-BpZdmj2g.js} +1 -1
  212. codex/static_root/assets/pdf-doc-BpZdmj2g.js.br +0 -0
  213. codex/static_root/assets/pdf-doc-BpZdmj2g.js.gz +0 -0
  214. codex/static_root/assets/reader-CRJUR2qj.55d626f0f9fa.js +2 -0
  215. codex/static_root/assets/reader-CRJUR2qj.55d626f0f9fa.js.br +0 -0
  216. codex/static_root/assets/reader-CRJUR2qj.55d626f0f9fa.js.gz +0 -0
  217. codex/static_root/assets/reader-CRJUR2qj.js +2 -0
  218. codex/static_root/assets/reader-CRJUR2qj.js.br +0 -0
  219. codex/static_root/assets/reader-CRJUR2qj.js.gz +0 -0
  220. codex/static_root/assets/{reader-CCCfpM3x.1553e45bd775.css → reader-CqXFa_gE.78267e9de0c2.css} +1 -1
  221. codex/static_root/assets/reader-CqXFa_gE.78267e9de0c2.css.br +0 -0
  222. codex/static_root/assets/reader-CqXFa_gE.78267e9de0c2.css.gz +0 -0
  223. codex/static_root/assets/{reader-CCCfpM3x.css → reader-CqXFa_gE.css} +1 -1
  224. codex/static_root/assets/reader-CqXFa_gE.css.br +0 -0
  225. codex/static_root/assets/reader-CqXFa_gE.css.gz +0 -0
  226. codex/static_root/assets/relation-chips-NgDnInw_.3b5ba16f68f0.js +1 -0
  227. codex/static_root/assets/relation-chips-NgDnInw_.3b5ba16f68f0.js.br +0 -0
  228. codex/static_root/assets/relation-chips-NgDnInw_.3b5ba16f68f0.js.gz +0 -0
  229. codex/static_root/assets/relation-chips-NgDnInw_.js +1 -0
  230. codex/static_root/assets/relation-chips-NgDnInw_.js.br +0 -0
  231. codex/static_root/assets/relation-chips-NgDnInw_.js.gz +0 -0
  232. codex/static_root/assets/settings-drawer-BaQT27kc.e43fc1527b66.js +2 -0
  233. codex/static_root/assets/settings-drawer-BaQT27kc.e43fc1527b66.js.br +0 -0
  234. codex/static_root/assets/settings-drawer-BaQT27kc.e43fc1527b66.js.gz +0 -0
  235. codex/static_root/assets/settings-drawer-BaQT27kc.js +2 -0
  236. codex/static_root/assets/settings-drawer-BaQT27kc.js.br +0 -0
  237. codex/static_root/assets/settings-drawer-BaQT27kc.js.gz +0 -0
  238. codex/static_root/assets/stats-tab-B4yKuY0c.a5728396494b.css +1 -0
  239. codex/static_root/assets/stats-tab-B4yKuY0c.a5728396494b.css.br +0 -0
  240. codex/static_root/assets/stats-tab-B4yKuY0c.a5728396494b.css.gz +0 -0
  241. codex/static_root/assets/stats-tab-B4yKuY0c.css +1 -0
  242. codex/static_root/assets/stats-tab-B4yKuY0c.css.br +0 -0
  243. codex/static_root/assets/stats-tab-B4yKuY0c.css.gz +0 -0
  244. codex/static_root/assets/stats-tab-DoHb54IU.30d7deea7b9f.js +1 -0
  245. codex/static_root/assets/stats-tab-DoHb54IU.30d7deea7b9f.js.br +0 -0
  246. codex/static_root/assets/stats-tab-DoHb54IU.30d7deea7b9f.js.gz +0 -0
  247. codex/static_root/assets/stats-tab-DoHb54IU.js +1 -0
  248. codex/static_root/assets/stats-tab-DoHb54IU.js.br +0 -0
  249. codex/static_root/assets/stats-tab-DoHb54IU.js.gz +0 -0
  250. codex/static_root/assets/task-tab-B88ucu1U.4f240e3d82c4.js +1 -0
  251. codex/static_root/assets/task-tab-B88ucu1U.4f240e3d82c4.js.br +0 -0
  252. codex/static_root/assets/task-tab-B88ucu1U.4f240e3d82c4.js.gz +0 -0
  253. codex/static_root/assets/task-tab-B88ucu1U.js +1 -0
  254. codex/static_root/assets/task-tab-B88ucu1U.js.br +0 -0
  255. codex/static_root/assets/task-tab-B88ucu1U.js.gz +0 -0
  256. codex/static_root/assets/to-case-B7MjLIw-.08fc8412de69.js +1 -0
  257. codex/static_root/assets/to-case-B7MjLIw-.08fc8412de69.js.br +0 -0
  258. codex/static_root/assets/to-case-B7MjLIw-.js +1 -0
  259. codex/static_root/assets/to-case-B7MjLIw-.js.br +0 -0
  260. codex/static_root/assets/unauthorized-AnKtlgGy.62ee74d4373c.js +1 -0
  261. codex/static_root/assets/unauthorized-AnKtlgGy.62ee74d4373c.js.br +0 -0
  262. codex/static_root/assets/unauthorized-AnKtlgGy.62ee74d4373c.js.gz +0 -0
  263. codex/static_root/assets/unauthorized-AnKtlgGy.js +1 -0
  264. codex/static_root/assets/unauthorized-AnKtlgGy.js.br +0 -0
  265. codex/static_root/assets/unauthorized-AnKtlgGy.js.gz +0 -0
  266. codex/static_root/assets/{unauthorized-DHV6Q1n-.b7847b2872a1.css → unauthorized-CibJYD8o.4c2de98c2b53.css} +1 -1
  267. codex/static_root/assets/unauthorized-CibJYD8o.4c2de98c2b53.css.br +0 -0
  268. codex/static_root/assets/unauthorized-CibJYD8o.4c2de98c2b53.css.gz +0 -0
  269. codex/static_root/assets/{unauthorized-DHV6Q1n-.css → unauthorized-CibJYD8o.css} +1 -1
  270. codex/static_root/assets/unauthorized-CibJYD8o.css.br +0 -0
  271. codex/static_root/assets/unauthorized-CibJYD8o.css.gz +0 -0
  272. codex/static_root/assets/user-tab-BxtZ2u7W.161cc8f0dcce.js +1 -0
  273. codex/static_root/assets/user-tab-BxtZ2u7W.161cc8f0dcce.js.br +0 -0
  274. codex/static_root/assets/user-tab-BxtZ2u7W.161cc8f0dcce.js.gz +0 -0
  275. codex/static_root/assets/user-tab-BxtZ2u7W.js +1 -0
  276. codex/static_root/assets/user-tab-BxtZ2u7W.js.br +0 -0
  277. codex/static_root/assets/user-tab-BxtZ2u7W.js.gz +0 -0
  278. codex/static_root/js/choices-admin.3521e2a863df.json +1 -0
  279. codex/static_root/js/choices-admin.3521e2a863df.json.br +0 -0
  280. codex/static_root/js/choices-admin.3521e2a863df.json.gz +0 -0
  281. codex/static_root/js/choices-admin.json +1 -1
  282. codex/static_root/js/choices-admin.json.br +0 -0
  283. codex/static_root/js/choices-admin.json.gz +0 -0
  284. codex/static_root/js/{choices.a0aaaa6c7ef7.json → choices.2f6b0359e1ef.json} +1 -1
  285. codex/static_root/js/choices.2f6b0359e1ef.json.br +0 -0
  286. codex/static_root/js/choices.2f6b0359e1ef.json.gz +0 -0
  287. codex/static_root/js/choices.json +1 -1
  288. codex/static_root/js/choices.json.br +0 -0
  289. codex/static_root/js/choices.json.gz +0 -0
  290. codex/static_root/manifest.3851c028b0cb.json +622 -0
  291. codex/static_root/manifest.3851c028b0cb.json.br +0 -0
  292. codex/static_root/manifest.3851c028b0cb.json.gz +0 -0
  293. codex/static_root/manifest.json +245 -252
  294. codex/static_root/manifest.json.br +0 -0
  295. codex/static_root/manifest.json.gz +0 -0
  296. codex/static_root/staticfiles.json +1 -1
  297. codex/util.py +8 -6
  298. codex/views/admin/api_key.py +5 -2
  299. codex/views/admin/stats.py +13 -20
  300. codex/views/admin/tasks.py +2 -3
  301. codex/views/auth.py +1 -1
  302. codex/views/bookmark.py +49 -29
  303. codex/views/browser/annotations.py +11 -45
  304. codex/views/browser/base.py +22 -6
  305. codex/views/browser/breadcrumbs.py +5 -5
  306. codex/views/browser/browser.py +39 -27
  307. codex/views/browser/choices.py +22 -37
  308. codex/views/browser/cover.py +55 -65
  309. codex/views/browser/filters/annotations.py +33 -10
  310. codex/views/browser/filters/group.py +24 -15
  311. codex/views/browser/filters/search.py +3 -4
  312. codex/views/browser/metadata.py +98 -49
  313. codex/views/browser/mtime.py +3 -14
  314. codex/views/browser/order_by.py +1 -6
  315. codex/views/browser/settings.py +53 -0
  316. codex/views/browser/validate.py +3 -0
  317. codex/views/const.py +25 -2
  318. codex/views/opds/v1/feed.py +3 -5
  319. codex/views/opds/v2/feed.py +3 -3
  320. codex/views/reader/arcs.py +42 -51
  321. codex/views/reader/books.py +47 -63
  322. codex/views/reader/init.py +125 -0
  323. codex/views/reader/reader.py +9 -70
  324. codex/views/session.py +18 -12
  325. codex/views/settings.py +23 -10
  326. codex/views/util.py +2 -1
  327. codex/websockets/consumers.py +14 -10
  328. {codex-1.6.0a9.dist-info → codex-1.6.0a11.dist-info}/METADATA +1 -1
  329. {codex-1.6.0a9.dist-info → codex-1.6.0a11.dist-info}/RECORD +332 -328
  330. codex/static_root/assets/VCheckbox-eNspVUje.da8282a08876.js +0 -1
  331. codex/static_root/assets/VCheckbox-eNspVUje.da8282a08876.js.br +0 -0
  332. codex/static_root/assets/VCheckbox-eNspVUje.da8282a08876.js.gz +0 -0
  333. codex/static_root/assets/VCheckbox-eNspVUje.js +0 -1
  334. codex/static_root/assets/VCheckbox-eNspVUje.js.br +0 -0
  335. codex/static_root/assets/VCheckbox-eNspVUje.js.gz +0 -0
  336. codex/static_root/assets/VCheckboxBtn-DLzF_WHB.9a47873b8548.js.br +0 -0
  337. codex/static_root/assets/VCheckboxBtn-DLzF_WHB.9a47873b8548.js.gz +0 -0
  338. codex/static_root/assets/VCheckboxBtn-DLzF_WHB.js.br +0 -0
  339. codex/static_root/assets/VCheckboxBtn-DLzF_WHB.js.gz +0 -0
  340. codex/static_root/assets/VCombobox-BIO7lU_B.d607ada71b06.js +0 -1
  341. codex/static_root/assets/VCombobox-BIO7lU_B.d607ada71b06.js.br +0 -0
  342. codex/static_root/assets/VCombobox-BIO7lU_B.d607ada71b06.js.gz +0 -0
  343. codex/static_root/assets/VCombobox-BIO7lU_B.js +0 -1
  344. codex/static_root/assets/VCombobox-BIO7lU_B.js.br +0 -0
  345. codex/static_root/assets/VCombobox-BIO7lU_B.js.gz +0 -0
  346. codex/static_root/assets/VDialog-87AymJC5.4a46716358c0.js +0 -1
  347. codex/static_root/assets/VDialog-87AymJC5.4a46716358c0.js.br +0 -0
  348. codex/static_root/assets/VDialog-87AymJC5.4a46716358c0.js.gz +0 -0
  349. codex/static_root/assets/VDialog-87AymJC5.js +0 -1
  350. codex/static_root/assets/VDialog-87AymJC5.js.br +0 -0
  351. codex/static_root/assets/VDialog-87AymJC5.js.gz +0 -0
  352. codex/static_root/assets/VDialog-C5Nxd_zP.css.br +0 -0
  353. codex/static_root/assets/VDialog-C5Nxd_zP.css.gz +0 -0
  354. codex/static_root/assets/VDialog-C5Nxd_zP.d327f505ef0e.css.br +0 -0
  355. codex/static_root/assets/VDialog-C5Nxd_zP.d327f505ef0e.css.gz +0 -0
  356. codex/static_root/assets/VExpansionPanels-CgA3shsd.9e524c73726a.js +0 -1
  357. codex/static_root/assets/VExpansionPanels-CgA3shsd.9e524c73726a.js.br +0 -0
  358. codex/static_root/assets/VExpansionPanels-CgA3shsd.9e524c73726a.js.gz +0 -0
  359. codex/static_root/assets/VExpansionPanels-CgA3shsd.js +0 -1
  360. codex/static_root/assets/VExpansionPanels-CgA3shsd.js.br +0 -0
  361. codex/static_root/assets/VExpansionPanels-CgA3shsd.js.gz +0 -0
  362. codex/static_root/assets/VRadioGroup-B--7K_v5.4a4e9c2d6c42.js.br +0 -0
  363. codex/static_root/assets/VRadioGroup-B--7K_v5.4a4e9c2d6c42.js.gz +0 -0
  364. codex/static_root/assets/VRadioGroup-B--7K_v5.js.br +0 -0
  365. codex/static_root/assets/VRadioGroup-B--7K_v5.js.gz +0 -0
  366. codex/static_root/assets/VSelect-BoJq222l.fc714657e214.js +0 -1
  367. codex/static_root/assets/VSelect-BoJq222l.fc714657e214.js.br +0 -0
  368. codex/static_root/assets/VSelect-BoJq222l.fc714657e214.js.gz +0 -0
  369. codex/static_root/assets/VSelect-BoJq222l.js +0 -1
  370. codex/static_root/assets/VSelect-BoJq222l.js.br +0 -0
  371. codex/static_root/assets/VSelect-BoJq222l.js.gz +0 -0
  372. codex/static_root/assets/VSelectionControl-CVQ9wkE2.c02186cceba6.js.br +0 -0
  373. codex/static_root/assets/VSelectionControl-CVQ9wkE2.c02186cceba6.js.gz +0 -0
  374. codex/static_root/assets/VSelectionControl-CVQ9wkE2.js.br +0 -0
  375. codex/static_root/assets/VSelectionControl-CVQ9wkE2.js.gz +0 -0
  376. codex/static_root/assets/VSlideGroup-Ce0j2BKK.85e64443a928.js +0 -1
  377. codex/static_root/assets/VSlideGroup-Ce0j2BKK.85e64443a928.js.br +0 -0
  378. codex/static_root/assets/VSlideGroup-Ce0j2BKK.85e64443a928.js.gz +0 -0
  379. codex/static_root/assets/VSlideGroup-Ce0j2BKK.js +0 -1
  380. codex/static_root/assets/VSlideGroup-Ce0j2BKK.js.br +0 -0
  381. codex/static_root/assets/VSlideGroup-Ce0j2BKK.js.gz +0 -0
  382. codex/static_root/assets/VTable-CrWkhkiP.6d530eea0c09.js.br +0 -0
  383. codex/static_root/assets/VTable-CrWkhkiP.6d530eea0c09.js.gz +0 -0
  384. codex/static_root/assets/VTable-CrWkhkiP.js.br +0 -0
  385. codex/static_root/assets/VTable-CrWkhkiP.js.gz +0 -0
  386. codex/static_root/assets/VTextField-CkWbil3K.2cac13161dfe.js +0 -1
  387. codex/static_root/assets/VTextField-CkWbil3K.2cac13161dfe.js.br +0 -0
  388. codex/static_root/assets/VTextField-CkWbil3K.2cac13161dfe.js.gz +0 -0
  389. codex/static_root/assets/VTextField-CkWbil3K.js +0 -1
  390. codex/static_root/assets/VTextField-CkWbil3K.js.br +0 -0
  391. codex/static_root/assets/VTextField-CkWbil3K.js.gz +0 -0
  392. codex/static_root/assets/VWindowItem-7z55Y4lK.98eb7487e039.js +0 -1
  393. codex/static_root/assets/VWindowItem-7z55Y4lK.98eb7487e039.js.br +0 -0
  394. codex/static_root/assets/VWindowItem-7z55Y4lK.98eb7487e039.js.gz +0 -0
  395. codex/static_root/assets/VWindowItem-7z55Y4lK.js +0 -1
  396. codex/static_root/assets/VWindowItem-7z55Y4lK.js.br +0 -0
  397. codex/static_root/assets/VWindowItem-7z55Y4lK.js.gz +0 -0
  398. codex/static_root/assets/admin-D3OK784R.f69891726ec5.js +0 -1
  399. codex/static_root/assets/admin-D3OK784R.f69891726ec5.js.br +0 -0
  400. codex/static_root/assets/admin-D3OK784R.f69891726ec5.js.gz +0 -0
  401. codex/static_root/assets/admin-D3OK784R.js +0 -1
  402. codex/static_root/assets/admin-D3OK784R.js.br +0 -0
  403. codex/static_root/assets/admin-D3OK784R.js.gz +0 -0
  404. codex/static_root/assets/admin-drawer-panel-1pnfvY8O.5438f252970e.js +0 -30
  405. codex/static_root/assets/admin-drawer-panel-1pnfvY8O.5438f252970e.js.br +0 -0
  406. codex/static_root/assets/admin-drawer-panel-1pnfvY8O.5438f252970e.js.gz +0 -0
  407. codex/static_root/assets/admin-drawer-panel-1pnfvY8O.js +0 -30
  408. codex/static_root/assets/admin-drawer-panel-1pnfvY8O.js.br +0 -0
  409. codex/static_root/assets/admin-drawer-panel-1pnfvY8O.js.gz +0 -0
  410. codex/static_root/assets/admin-drawer-panel-o87BwD38.ce39427c8201.css.br +0 -0
  411. codex/static_root/assets/admin-drawer-panel-o87BwD38.ce39427c8201.css.gz +0 -0
  412. codex/static_root/assets/admin-drawer-panel-o87BwD38.css.br +0 -0
  413. codex/static_root/assets/admin-drawer-panel-o87BwD38.css.gz +0 -0
  414. codex/static_root/assets/browser-BuU2x9y7.css +0 -1
  415. codex/static_root/assets/browser-BuU2x9y7.css.br +0 -0
  416. codex/static_root/assets/browser-BuU2x9y7.css.gz +0 -0
  417. codex/static_root/assets/browser-BuU2x9y7.f67595d24664.css +0 -1
  418. codex/static_root/assets/browser-BuU2x9y7.f67595d24664.css.br +0 -0
  419. codex/static_root/assets/browser-BuU2x9y7.f67595d24664.css.gz +0 -0
  420. codex/static_root/assets/browser-CO9EYHIr.be49367c6a75.js +0 -1
  421. codex/static_root/assets/browser-CO9EYHIr.be49367c6a75.js.br +0 -0
  422. codex/static_root/assets/browser-CO9EYHIr.be49367c6a75.js.gz +0 -0
  423. codex/static_root/assets/browser-CO9EYHIr.js +0 -1
  424. codex/static_root/assets/browser-CO9EYHIr.js.br +0 -0
  425. codex/static_root/assets/browser-CO9EYHIr.js.gz +0 -0
  426. codex/static_root/assets/change-password-dialog-CjZdzaIk.188c765431ab.js +0 -1
  427. codex/static_root/assets/change-password-dialog-CjZdzaIk.188c765431ab.js.br +0 -0
  428. codex/static_root/assets/change-password-dialog-CjZdzaIk.188c765431ab.js.gz +0 -0
  429. codex/static_root/assets/change-password-dialog-CjZdzaIk.js +0 -1
  430. codex/static_root/assets/change-password-dialog-CjZdzaIk.js.br +0 -0
  431. codex/static_root/assets/change-password-dialog-CjZdzaIk.js.gz +0 -0
  432. codex/static_root/assets/change-password-dialog-HvIvmmIE.73be0c8a8278.css +0 -1
  433. codex/static_root/assets/change-password-dialog-HvIvmmIE.73be0c8a8278.css.br +0 -0
  434. codex/static_root/assets/change-password-dialog-HvIvmmIE.73be0c8a8278.css.gz +0 -0
  435. codex/static_root/assets/change-password-dialog-HvIvmmIE.css +0 -1
  436. codex/static_root/assets/change-password-dialog-HvIvmmIE.css.br +0 -0
  437. codex/static_root/assets/change-password-dialog-HvIvmmIE.css.gz +0 -0
  438. codex/static_root/assets/confirm-dialog-jwL7B98r.1cfd579cbcfe.js.br +0 -0
  439. codex/static_root/assets/confirm-dialog-jwL7B98r.1cfd579cbcfe.js.gz +0 -0
  440. codex/static_root/assets/confirm-dialog-jwL7B98r.js.br +0 -0
  441. codex/static_root/assets/confirm-dialog-jwL7B98r.js.gz +0 -0
  442. codex/static_root/assets/datetime-column-9w3GcKvo.f9172256f091.js +0 -1
  443. codex/static_root/assets/datetime-column-9w3GcKvo.f9172256f091.js.br +0 -0
  444. codex/static_root/assets/datetime-column-9w3GcKvo.f9172256f091.js.gz +0 -0
  445. codex/static_root/assets/datetime-column-9w3GcKvo.js +0 -1
  446. codex/static_root/assets/datetime-column-9w3GcKvo.js.br +0 -0
  447. codex/static_root/assets/datetime-column-9w3GcKvo.js.gz +0 -0
  448. codex/static_root/assets/filter-C-pghOri.eeb7c2ecf398.js +0 -1
  449. codex/static_root/assets/filter-C-pghOri.eeb7c2ecf398.js.br +0 -0
  450. codex/static_root/assets/filter-C-pghOri.eeb7c2ecf398.js.gz +0 -0
  451. codex/static_root/assets/filter-C-pghOri.js +0 -1
  452. codex/static_root/assets/filter-C-pghOri.js.br +0 -0
  453. codex/static_root/assets/filter-C-pghOri.js.gz +0 -0
  454. codex/static_root/assets/flag-tab-Da2DBNyz.ffbe5ca37e1c.js.br +0 -0
  455. codex/static_root/assets/flag-tab-Da2DBNyz.ffbe5ca37e1c.js.gz +0 -0
  456. codex/static_root/assets/flag-tab-Da2DBNyz.js.br +0 -0
  457. codex/static_root/assets/flag-tab-Da2DBNyz.js.gz +0 -0
  458. codex/static_root/assets/group-tab-BONYWOc1.6ddf321a4a56.js.br +0 -0
  459. codex/static_root/assets/group-tab-BONYWOc1.6ddf321a4a56.js.gz +0 -0
  460. codex/static_root/assets/group-tab-BONYWOc1.js.br +0 -0
  461. codex/static_root/assets/group-tab-BONYWOc1.js.gz +0 -0
  462. codex/static_root/assets/http-error-D2Jnc20C.32846bc3a43d.js.br +0 -0
  463. codex/static_root/assets/http-error-D2Jnc20C.32846bc3a43d.js.gz +0 -0
  464. codex/static_root/assets/http-error-D2Jnc20C.js.br +0 -0
  465. codex/static_root/assets/http-error-D2Jnc20C.js.gz +0 -0
  466. codex/static_root/assets/library-tab-B419agXA.d4b778172aaa.js.br +0 -0
  467. codex/static_root/assets/library-tab-B419agXA.d4b778172aaa.js.gz +0 -0
  468. codex/static_root/assets/library-tab-B419agXA.js.br +0 -0
  469. codex/static_root/assets/library-tab-B419agXA.js.gz +0 -0
  470. codex/static_root/assets/main-CMQwJ9aG.9836fe81c80a.js +0 -32
  471. codex/static_root/assets/main-CMQwJ9aG.9836fe81c80a.js.br +0 -0
  472. codex/static_root/assets/main-CMQwJ9aG.9836fe81c80a.js.gz +0 -0
  473. codex/static_root/assets/main-CMQwJ9aG.js +0 -32
  474. codex/static_root/assets/main-CMQwJ9aG.js.br +0 -0
  475. codex/static_root/assets/main-CMQwJ9aG.js.gz +0 -0
  476. codex/static_root/assets/pagination-toolbar-DWdp_kmz.css +0 -1
  477. codex/static_root/assets/pagination-toolbar-DWdp_kmz.css.br +0 -0
  478. codex/static_root/assets/pagination-toolbar-DWdp_kmz.css.gz +0 -0
  479. codex/static_root/assets/pagination-toolbar-DWdp_kmz.f98f47e87612.css +0 -1
  480. codex/static_root/assets/pagination-toolbar-DWdp_kmz.f98f47e87612.css.br +0 -0
  481. codex/static_root/assets/pagination-toolbar-DWdp_kmz.f98f47e87612.css.gz +0 -0
  482. codex/static_root/assets/pagination-toolbar-LTuj5U-G.a295defbcd2f.js +0 -1
  483. codex/static_root/assets/pagination-toolbar-LTuj5U-G.a295defbcd2f.js.br +0 -0
  484. codex/static_root/assets/pagination-toolbar-LTuj5U-G.a295defbcd2f.js.gz +0 -0
  485. codex/static_root/assets/pagination-toolbar-LTuj5U-G.js +0 -1
  486. codex/static_root/assets/pagination-toolbar-LTuj5U-G.js.br +0 -0
  487. codex/static_root/assets/pagination-toolbar-LTuj5U-G.js.gz +0 -0
  488. codex/static_root/assets/pdf-doc-8RVZqILx.2e7166dd26fb.js.br +0 -0
  489. codex/static_root/assets/pdf-doc-8RVZqILx.2e7166dd26fb.js.gz +0 -0
  490. codex/static_root/assets/pdf-doc-8RVZqILx.js.br +0 -0
  491. codex/static_root/assets/pdf-doc-8RVZqILx.js.gz +0 -0
  492. codex/static_root/assets/reader-CCCfpM3x.1553e45bd775.css.br +0 -0
  493. codex/static_root/assets/reader-CCCfpM3x.1553e45bd775.css.gz +0 -0
  494. codex/static_root/assets/reader-CCCfpM3x.css.br +0 -0
  495. codex/static_root/assets/reader-CCCfpM3x.css.gz +0 -0
  496. codex/static_root/assets/reader-DNnK_Chr.114d0e321547.js +0 -2
  497. codex/static_root/assets/reader-DNnK_Chr.114d0e321547.js.br +0 -0
  498. codex/static_root/assets/reader-DNnK_Chr.114d0e321547.js.gz +0 -0
  499. codex/static_root/assets/reader-DNnK_Chr.js +0 -2
  500. codex/static_root/assets/reader-DNnK_Chr.js.br +0 -0
  501. codex/static_root/assets/reader-DNnK_Chr.js.gz +0 -0
  502. codex/static_root/assets/relation-chips-PYua7aXv.428ba0b5861e.js +0 -1
  503. codex/static_root/assets/relation-chips-PYua7aXv.428ba0b5861e.js.br +0 -0
  504. codex/static_root/assets/relation-chips-PYua7aXv.428ba0b5861e.js.gz +0 -0
  505. codex/static_root/assets/relation-chips-PYua7aXv.js +0 -1
  506. codex/static_root/assets/relation-chips-PYua7aXv.js.br +0 -0
  507. codex/static_root/assets/relation-chips-PYua7aXv.js.gz +0 -0
  508. codex/static_root/assets/settings-drawer-DbN6ISRH.d14f525d8eee.js +0 -2
  509. codex/static_root/assets/settings-drawer-DbN6ISRH.d14f525d8eee.js.br +0 -0
  510. codex/static_root/assets/settings-drawer-DbN6ISRH.d14f525d8eee.js.gz +0 -0
  511. codex/static_root/assets/settings-drawer-DbN6ISRH.js +0 -2
  512. codex/static_root/assets/settings-drawer-DbN6ISRH.js.br +0 -0
  513. codex/static_root/assets/settings-drawer-DbN6ISRH.js.gz +0 -0
  514. codex/static_root/assets/stats-tab-DImNhH8O.d5026283841a.js +0 -1
  515. codex/static_root/assets/stats-tab-DImNhH8O.d5026283841a.js.br +0 -0
  516. codex/static_root/assets/stats-tab-DImNhH8O.d5026283841a.js.gz +0 -0
  517. codex/static_root/assets/stats-tab-DImNhH8O.js +0 -1
  518. codex/static_root/assets/stats-tab-DImNhH8O.js.br +0 -0
  519. codex/static_root/assets/stats-tab-DImNhH8O.js.gz +0 -0
  520. codex/static_root/assets/stats-tab-TsyG3wH_.b93c080356fc.css +0 -1
  521. codex/static_root/assets/stats-tab-TsyG3wH_.b93c080356fc.css.br +0 -2
  522. codex/static_root/assets/stats-tab-TsyG3wH_.b93c080356fc.css.gz +0 -0
  523. codex/static_root/assets/stats-tab-TsyG3wH_.css +0 -1
  524. codex/static_root/assets/stats-tab-TsyG3wH_.css.br +0 -2
  525. codex/static_root/assets/stats-tab-TsyG3wH_.css.gz +0 -0
  526. codex/static_root/assets/task-tab-DPD53kjv.e56a35ff1691.js +0 -1
  527. codex/static_root/assets/task-tab-DPD53kjv.e56a35ff1691.js.br +0 -0
  528. codex/static_root/assets/task-tab-DPD53kjv.e56a35ff1691.js.gz +0 -0
  529. codex/static_root/assets/task-tab-DPD53kjv.js +0 -1
  530. codex/static_root/assets/task-tab-DPD53kjv.js.br +0 -0
  531. codex/static_root/assets/task-tab-DPD53kjv.js.gz +0 -0
  532. codex/static_root/assets/to-case-ehC9Ccyj.a7b8e25b391f.js +0 -1
  533. codex/static_root/assets/to-case-ehC9Ccyj.js +0 -1
  534. codex/static_root/assets/unauthorized-BOIx7Y18.ee3961abfccb.js +0 -1
  535. codex/static_root/assets/unauthorized-BOIx7Y18.ee3961abfccb.js.br +0 -0
  536. codex/static_root/assets/unauthorized-BOIx7Y18.ee3961abfccb.js.gz +0 -0
  537. codex/static_root/assets/unauthorized-BOIx7Y18.js +0 -1
  538. codex/static_root/assets/unauthorized-BOIx7Y18.js.br +0 -0
  539. codex/static_root/assets/unauthorized-BOIx7Y18.js.gz +0 -0
  540. codex/static_root/assets/unauthorized-DHV6Q1n-.b7847b2872a1.css.br +0 -0
  541. codex/static_root/assets/unauthorized-DHV6Q1n-.b7847b2872a1.css.gz +0 -0
  542. codex/static_root/assets/unauthorized-DHV6Q1n-.css.br +0 -0
  543. codex/static_root/assets/unauthorized-DHV6Q1n-.css.gz +0 -0
  544. codex/static_root/assets/user-tab-BABwfxLO.37dd0440fbdd.js +0 -1
  545. codex/static_root/assets/user-tab-BABwfxLO.37dd0440fbdd.js.br +0 -0
  546. codex/static_root/assets/user-tab-BABwfxLO.37dd0440fbdd.js.gz +0 -0
  547. codex/static_root/assets/user-tab-BABwfxLO.js +0 -1
  548. codex/static_root/assets/user-tab-BABwfxLO.js.br +0 -0
  549. codex/static_root/assets/user-tab-BABwfxLO.js.gz +0 -0
  550. codex/static_root/js/choices-admin.d790df01c20a.json +0 -1
  551. codex/static_root/js/choices-admin.d790df01c20a.json.br +0 -0
  552. codex/static_root/js/choices-admin.d790df01c20a.json.gz +0 -0
  553. codex/static_root/js/choices.a0aaaa6c7ef7.json.br +0 -0
  554. codex/static_root/js/choices.a0aaaa6c7ef7.json.gz +0 -0
  555. codex/static_root/manifest.cbea5663003a.json +0 -629
  556. codex/static_root/manifest.cbea5663003a.json.br +0 -0
  557. codex/static_root/manifest.cbea5663003a.json.gz +0 -0
  558. {codex-1.6.0a9.dist-info → codex-1.6.0a11.dist-info}/LICENSE +0 -0
  559. {codex-1.6.0a9.dist-info → codex-1.6.0a11.dist-info}/WHEEL +0 -0
  560. {codex-1.6.0a9.dist-info → codex-1.6.0a11.dist-info}/entry_points.txt +0 -0
Binary file
Binary file
@@ -1 +1 @@
1
- {"paths": {"rest_framework/docs/js/api.js": "rest_framework/docs/js/api.18a5ba8a1bd8.js", "rest_framework/docs/js/jquery.json-view.min.js": "rest_framework/docs/js/jquery.json-view.min.b7c2d6981377.js", "rest_framework/docs/js/highlight.pack.js": "rest_framework/docs/js/highlight.pack.479b5f21dcba.js", "rest_framework/docs/img/favicon.ico": "rest_framework/docs/img/favicon.5195b4d0f3eb.ico", "rest_framework/docs/img/grid.png": "rest_framework/docs/img/grid.a4b938cf382b.png", "rest_framework/docs/css/jquery.json-view.min.css": "rest_framework/docs/css/jquery.json-view.min.a2e6beeb6710.css", "rest_framework/docs/css/highlight.css": "rest_framework/docs/css/highlight.e0e4d973c6d7.css", "rest_framework/docs/css/base.css": "rest_framework/docs/css/base.e630f8f4990e.css", "rest_framework/js/ajax-form.js": "rest_framework/js/ajax-form.4e1cdcb7acab.js", "rest_framework/js/csrf.js": "rest_framework/js/csrf.455080a7b2ce.js", "rest_framework/js/prettify-min.js": "rest_framework/js/prettify-min.709bfcc456c6.js", "rest_framework/js/jquery-3.7.1.min.js": "rest_framework/js/jquery-3.7.1.min.2c872dbe60f4.js", "rest_framework/js/default.js": "rest_framework/js/default.5b08897dbdc3.js", "rest_framework/js/bootstrap.min.js": "rest_framework/js/bootstrap.min.2f34b630ffe3.js", "rest_framework/js/coreapi-0.1.1.js": "rest_framework/js/coreapi-0.1.1.8851fb9336c9.js", "rest_framework/js/load-ajax-form.js": "rest_framework/js/load-ajax-form.8cdb3a9f3466.js", "rest_framework/fonts/fontawesome-webfont.woff": "rest_framework/fonts/fontawesome-webfont.3293616ec0c6.woff", "rest_framework/fonts/glyphicons-halflings-regular.eot": "rest_framework/fonts/glyphicons-halflings-regular.f4769f9bdb74.eot", "rest_framework/fonts/glyphicons-halflings-regular.ttf": "rest_framework/fonts/glyphicons-halflings-regular.e18bbf611f2a.ttf", "rest_framework/fonts/fontawesome-webfont.ttf": "rest_framework/fonts/fontawesome-webfont.dcb26c7239d8.ttf", "rest_framework/fonts/glyphicons-halflings-regular.woff2": "rest_framework/fonts/glyphicons-halflings-regular.448c34a56d69.woff2", "rest_framework/fonts/fontawesome-webfont.svg": "rest_framework/fonts/fontawesome-webfont.83e37a11f9d7.svg", "rest_framework/fonts/glyphicons-halflings-regular.woff": "rest_framework/fonts/glyphicons-halflings-regular.fa2772327f55.woff", "rest_framework/fonts/glyphicons-halflings-regular.svg": "rest_framework/fonts/glyphicons-halflings-regular.08eda92397ae.svg", "rest_framework/fonts/fontawesome-webfont.eot": "rest_framework/fonts/fontawesome-webfont.8b27bc96115c.eot", "rest_framework/img/glyphicons-halflings-white.png": "rest_framework/img/glyphicons-halflings-white.9bbc6e960299.png", "rest_framework/img/glyphicons-halflings.png": "rest_framework/img/glyphicons-halflings.90233c9067e9.png", "rest_framework/img/grid.png": "rest_framework/img/grid.a4b938cf382b.png", "rest_framework/css/bootstrap.min.css.map": "rest_framework/css/bootstrap.min.css.cafbda9c0e9e.map", "rest_framework/css/default.css": "rest_framework/css/default.789dfb5732d7.css", "rest_framework/css/bootstrap.min.css": "rest_framework/css/bootstrap.min.f17d4516b026.css", "rest_framework/css/prettify.css": "rest_framework/css/prettify.a987f72342ee.css", "rest_framework/css/bootstrap-theme.min.css": "rest_framework/css/bootstrap-theme.min.1d4b05b397c3.css", "rest_framework/css/bootstrap-tweaks.css": "rest_framework/css/bootstrap-tweaks.ee4ee6acf9eb.css", "rest_framework/css/font-awesome-4.0.3.css": "rest_framework/css/font-awesome-4.0.3.c1e1ea213abf.css", "rest_framework/css/bootstrap-theme.min.css.map": "rest_framework/css/bootstrap-theme.min.css.51806092cc05.map", "img/publisher.svg": "img/publisher.82d378fcd601.svg", "img/logo-32.webp": "img/logo-32.5688944495bf.webp", "img/logo.svg": "img/logo.0f5344a028ca.svg", "img/story-arc.svg": "img/story-arc.ca10014355ef.svg", "img/missing-cover-165.webp": "img/missing-cover-165.0743171f2148.webp", "img/series.svg": "img/series.ec8a889b8f95.svg", "img/logo-maskable-180.webp": "img/logo-maskable-180.c58d966aa64e.webp", "img/missing-cover.svg": "img/missing-cover.ddb038cc2c56.svg", "img/folder.svg": "img/folder.f28936a3701d.svg", "img/volume.svg": "img/volume.814e4c79461a.svg", "img/logo-maskable.svg": "img/logo-maskable.8f7de7f1c6a8.svg", "img/imprint.svg": "img/imprint.7c2adebb76d6.svg", "pwa/offline.html": "pwa/offline.7bfaf9f94bf9.html", "js/choices.json": "js/choices.a0aaaa6c7ef7.json", "js/choices-admin.json": "js/choices-admin.d790df01c20a.json", "assets/relation-chips-Bsc-gUxE.css": "assets/relation-chips-Bsc-gUxE.98e65384c3c9.css", "assets/group-tab-CBKuS3Iv.css": "assets/group-tab-CBKuS3Iv.7e4746634782.css", "assets/main-CMQwJ9aG.js": "assets/main-CMQwJ9aG.9836fe81c80a.js", "assets/http-error-DKulXuTl.css": "assets/http-error-DKulXuTl.95e42988d5d5.css", "assets/VSelect-ARDhJiQK.css": "assets/VSelect-ARDhJiQK.372c098fb475.css", "assets/flag-tab-BNwbLfrN.css": "assets/flag-tab-BNwbLfrN.b755a99fff7e.css", "assets/VCheckbox-eNspVUje.js": "assets/VCheckbox-eNspVUje.da8282a08876.js", "assets/pagination-toolbar-LTuj5U-G.js": "assets/pagination-toolbar-LTuj5U-G.a295defbcd2f.js", "assets/VTable-CrWkhkiP.js": "assets/VTable-CrWkhkiP.6d530eea0c09.js", "assets/VSelectionControl-BFq--28I.css": "assets/VSelectionControl-BFq--28I.9687c77461fc.css", "assets/pdf-doc-CMzaSV_K.css": "assets/pdf-doc-CMzaSV_K.8cd4b3e65f9a.css", "assets/unauthorized-DHV6Q1n-.css": "assets/unauthorized-DHV6Q1n-.b7847b2872a1.css", "assets/materialdesignicons-webfont-PXm3-2wK.woff": "assets/materialdesignicons-webfont-PXm3-2wK.026b7ac9c43c.woff", "assets/VSlideGroup-Dk_1upHt.css": "assets/VSlideGroup-Dk_1upHt.2c836070ec75.css", "assets/VTable-DflzroDq.css": "assets/VTable-DflzroDq.160504d82195.css", "assets/settings-drawer-nZ9HvKSZ.css": "assets/settings-drawer-nZ9HvKSZ.01744e131806.css", "assets/main-Ztp855PW.css": "assets/main-Ztp855PW.d46d718fac45.css", "assets/admin-drawer-panel-1pnfvY8O.js": "assets/admin-drawer-panel-1pnfvY8O.5438f252970e.js", "assets/task-tab-DPD53kjv.js": "assets/task-tab-DPD53kjv.e56a35ff1691.js", "assets/VRadioGroup-i2qP9Wu9.css": "assets/VRadioGroup-i2qP9Wu9.8e3741381961.css", "assets/change-password-dialog-HvIvmmIE.css": "assets/change-password-dialog-HvIvmmIE.73be0c8a8278.css", "assets/pdf-doc-8RVZqILx.js": "assets/pdf-doc-8RVZqILx.2e7166dd26fb.js", "assets/VTextField-CkWbil3K.js": "assets/VTextField-CkWbil3K.2cac13161dfe.js", "assets/settings-drawer-DbN6ISRH.js": "assets/settings-drawer-DbN6ISRH.d14f525d8eee.js", "assets/user-tab-BABwfxLO.js": "assets/user-tab-BABwfxLO.37dd0440fbdd.js", "assets/copy-to-clipboard-DoUvDJVx.js": "assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js", "assets/VSelectionControl-CVQ9wkE2.js": "assets/VSelectionControl-CVQ9wkE2.c02186cceba6.js", "assets/VWindowItem-ByIod57Y.css": "assets/VWindowItem-ByIod57Y.f7fb19752bf3.css", "assets/to-case-ehC9Ccyj.js": "assets/to-case-ehC9Ccyj.a7b8e25b391f.js", "assets/datetime-column-9w3GcKvo.js": "assets/datetime-column-9w3GcKvo.f9172256f091.js", "assets/stats-tab-DImNhH8O.js": "assets/stats-tab-DImNhH8O.d5026283841a.js", "assets/stats-tab-TsyG3wH_.css": "assets/stats-tab-TsyG3wH_.b93c080356fc.css", "assets/browser-BuU2x9y7.css": "assets/browser-BuU2x9y7.f67595d24664.css", "assets/reader-DNnK_Chr.js": "assets/reader-DNnK_Chr.114d0e321547.js", "assets/VWindowItem-7z55Y4lK.js": "assets/VWindowItem-7z55Y4lK.98eb7487e039.js", "assets/browser-CO9EYHIr.js": "assets/browser-CO9EYHIr.be49367c6a75.js", "assets/confirm-dialog-jwL7B98r.js": "assets/confirm-dialog-jwL7B98r.1cfd579cbcfe.js", "assets/library-tab-BN0SfPcH.css": "assets/library-tab-BN0SfPcH.913e236f625e.css", "assets/admin-D3OK784R.js": "assets/admin-D3OK784R.f69891726ec5.js", "assets/confirm-dialog-BmhedLCx.css": "assets/confirm-dialog-BmhedLCx.7c2103d319d4.css", "assets/group-tab-BONYWOc1.js": "assets/group-tab-BONYWOc1.6ddf321a4a56.js", "assets/materialdesignicons-webfont-B7mPwVP_.ttf": "assets/materialdesignicons-webfont-B7mPwVP_.6e435534bd35.ttf", "assets/reader-CCCfpM3x.css": "assets/reader-CCCfpM3x.1553e45bd775.css", "assets/change-password-dialog-CjZdzaIk.js": "assets/change-password-dialog-CjZdzaIk.188c765431ab.js", "assets/relation-chips-PYua7aXv.js": "assets/relation-chips-PYua7aXv.428ba0b5861e.js", "assets/VCheckboxBtn-DLzF_WHB.js": "assets/VCheckboxBtn-DLzF_WHB.9a47873b8548.js", "assets/VCombobox-BksEr4D_.css": "assets/VCombobox-BksEr4D_.73429bb75f42.css", "assets/filter-C-pghOri.js": "assets/filter-C-pghOri.eeb7c2ecf398.js", "assets/admin-drawer-panel-o87BwD38.css": "assets/admin-drawer-panel-o87BwD38.ce39427c8201.css", "assets/VSelect-BoJq222l.js": "assets/VSelect-BoJq222l.fc714657e214.js", "assets/pagination-toolbar-DWdp_kmz.css": "assets/pagination-toolbar-DWdp_kmz.f98f47e87612.css", "assets/flag-tab-Da2DBNyz.js": "assets/flag-tab-Da2DBNyz.ffbe5ca37e1c.js", "assets/admin-B8Bp2Uih.css": "assets/admin-B8Bp2Uih.82c98714bcf1.css", "assets/http-error-D2Jnc20C.js": "assets/http-error-D2Jnc20C.32846bc3a43d.js", "assets/task-tab-1XiWn9xP.css": "assets/task-tab-1XiWn9xP.06cb8e1b794d.css", "assets/VDialog-87AymJC5.js": "assets/VDialog-87AymJC5.4a46716358c0.js", "assets/datetime-column-DeCthByU.css": "assets/datetime-column-DeCthByU.1f3bf499e063.css", "assets/materialdesignicons-webfont-CSr8KVlo.eot": "assets/materialdesignicons-webfont-CSr8KVlo.8ced95a05e3c.eot", "assets/library-tab-B419agXA.js": "assets/library-tab-B419agXA.d4b778172aaa.js", "assets/VSlideGroup-Ce0j2BKK.js": "assets/VSlideGroup-Ce0j2BKK.85e64443a928.js", "assets/VCombobox-BIO7lU_B.js": "assets/VCombobox-BIO7lU_B.d607ada71b06.js", "assets/VExpansionPanels-CgA3shsd.js": "assets/VExpansionPanels-CgA3shsd.9e524c73726a.js", "assets/VExpansionPanels-DsEXVcCv.css": "assets/VExpansionPanels-DsEXVcCv.20b475255e66.css", "assets/VDialog-C5Nxd_zP.css": "assets/VDialog-C5Nxd_zP.d327f505ef0e.css", "assets/VCheckbox-CMKdyl0R.css": "assets/VCheckbox-CMKdyl0R.016ed8d222c4.css", "assets/VTextField-BssVoDhB.css": "assets/VTextField-BssVoDhB.4cc388b4aa3c.css", "assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "assets/materialdesignicons-webfont-Dp5v-WZN.1d7bcee1b302.woff2", "assets/VRadioGroup-B--7K_v5.js": "assets/VRadioGroup-B--7K_v5.4a4e9c2d6c42.js", "assets/unauthorized-BOIx7Y18.js": "assets/unauthorized-BOIx7Y18.ee3961abfccb.js", "robots.txt": "robots.b6216d61c03e.txt", "manifest.json": "manifest.cbea5663003a.json"}, "version": "1.1", "hash": "469437147ea5"}
1
+ {"paths": {"rest_framework/docs/js/api.js": "rest_framework/docs/js/api.18a5ba8a1bd8.js", "rest_framework/docs/js/jquery.json-view.min.js": "rest_framework/docs/js/jquery.json-view.min.b7c2d6981377.js", "rest_framework/docs/js/highlight.pack.js": "rest_framework/docs/js/highlight.pack.479b5f21dcba.js", "rest_framework/docs/img/favicon.ico": "rest_framework/docs/img/favicon.5195b4d0f3eb.ico", "rest_framework/docs/img/grid.png": "rest_framework/docs/img/grid.a4b938cf382b.png", "rest_framework/docs/css/jquery.json-view.min.css": "rest_framework/docs/css/jquery.json-view.min.a2e6beeb6710.css", "rest_framework/docs/css/highlight.css": "rest_framework/docs/css/highlight.e0e4d973c6d7.css", "rest_framework/docs/css/base.css": "rest_framework/docs/css/base.e630f8f4990e.css", "rest_framework/js/ajax-form.js": "rest_framework/js/ajax-form.4e1cdcb7acab.js", "rest_framework/js/csrf.js": "rest_framework/js/csrf.455080a7b2ce.js", "rest_framework/js/prettify-min.js": "rest_framework/js/prettify-min.709bfcc456c6.js", "rest_framework/js/jquery-3.7.1.min.js": "rest_framework/js/jquery-3.7.1.min.2c872dbe60f4.js", "rest_framework/js/default.js": "rest_framework/js/default.5b08897dbdc3.js", "rest_framework/js/bootstrap.min.js": "rest_framework/js/bootstrap.min.2f34b630ffe3.js", "rest_framework/js/coreapi-0.1.1.js": "rest_framework/js/coreapi-0.1.1.8851fb9336c9.js", "rest_framework/js/load-ajax-form.js": "rest_framework/js/load-ajax-form.8cdb3a9f3466.js", "rest_framework/fonts/fontawesome-webfont.woff": "rest_framework/fonts/fontawesome-webfont.3293616ec0c6.woff", "rest_framework/fonts/glyphicons-halflings-regular.eot": "rest_framework/fonts/glyphicons-halflings-regular.f4769f9bdb74.eot", "rest_framework/fonts/glyphicons-halflings-regular.ttf": "rest_framework/fonts/glyphicons-halflings-regular.e18bbf611f2a.ttf", "rest_framework/fonts/fontawesome-webfont.ttf": "rest_framework/fonts/fontawesome-webfont.dcb26c7239d8.ttf", "rest_framework/fonts/glyphicons-halflings-regular.woff2": "rest_framework/fonts/glyphicons-halflings-regular.448c34a56d69.woff2", "rest_framework/fonts/fontawesome-webfont.svg": "rest_framework/fonts/fontawesome-webfont.83e37a11f9d7.svg", "rest_framework/fonts/glyphicons-halflings-regular.woff": "rest_framework/fonts/glyphicons-halflings-regular.fa2772327f55.woff", "rest_framework/fonts/glyphicons-halflings-regular.svg": "rest_framework/fonts/glyphicons-halflings-regular.08eda92397ae.svg", "rest_framework/fonts/fontawesome-webfont.eot": "rest_framework/fonts/fontawesome-webfont.8b27bc96115c.eot", "rest_framework/img/glyphicons-halflings-white.png": "rest_framework/img/glyphicons-halflings-white.9bbc6e960299.png", "rest_framework/img/glyphicons-halflings.png": "rest_framework/img/glyphicons-halflings.90233c9067e9.png", "rest_framework/img/grid.png": "rest_framework/img/grid.a4b938cf382b.png", "rest_framework/css/bootstrap.min.css.map": "rest_framework/css/bootstrap.min.css.cafbda9c0e9e.map", "rest_framework/css/default.css": "rest_framework/css/default.789dfb5732d7.css", "rest_framework/css/bootstrap.min.css": "rest_framework/css/bootstrap.min.f17d4516b026.css", "rest_framework/css/prettify.css": "rest_framework/css/prettify.a987f72342ee.css", "rest_framework/css/bootstrap-theme.min.css": "rest_framework/css/bootstrap-theme.min.1d4b05b397c3.css", "rest_framework/css/bootstrap-tweaks.css": "rest_framework/css/bootstrap-tweaks.ee4ee6acf9eb.css", "rest_framework/css/font-awesome-4.0.3.css": "rest_framework/css/font-awesome-4.0.3.c1e1ea213abf.css", "rest_framework/css/bootstrap-theme.min.css.map": "rest_framework/css/bootstrap-theme.min.css.51806092cc05.map", "img/publisher.svg": "img/publisher.82d378fcd601.svg", "img/logo-32.webp": "img/logo-32.5688944495bf.webp", "img/logo.svg": "img/logo.0f5344a028ca.svg", "img/story-arc.svg": "img/story-arc.ca10014355ef.svg", "img/missing-cover-165.webp": "img/missing-cover-165.0743171f2148.webp", "img/series.svg": "img/series.ec8a889b8f95.svg", "img/logo-maskable-180.webp": "img/logo-maskable-180.c58d966aa64e.webp", "img/missing-cover.svg": "img/missing-cover.ddb038cc2c56.svg", "img/folder.svg": "img/folder.f28936a3701d.svg", "img/volume.svg": "img/volume.814e4c79461a.svg", "img/logo-maskable.svg": "img/logo-maskable.8f7de7f1c6a8.svg", "img/imprint.svg": "img/imprint.7c2adebb76d6.svg", "pwa/offline.html": "pwa/offline.7bfaf9f94bf9.html", "js/choices.json": "js/choices.2f6b0359e1ef.json", "js/choices-admin.json": "js/choices-admin.3521e2a863df.json", "assets/relation-chips-Bsc-gUxE.css": "assets/relation-chips-Bsc-gUxE.98e65384c3c9.css", "assets/pagination-toolbar-BBvsIXTd.js": "assets/pagination-toolbar-BBvsIXTd.ad891da6617a.js", "assets/group-tab-CBKuS3Iv.css": "assets/group-tab-CBKuS3Iv.7e4746634782.css", "assets/http-error-DKulXuTl.css": "assets/http-error-DKulXuTl.95e42988d5d5.css", "assets/group-tab-_nT2o04v.js": "assets/group-tab-_nT2o04v.c06032b254dc.js", "assets/VSelect-ARDhJiQK.css": "assets/VSelect-ARDhJiQK.372c098fb475.css", "assets/flag-tab-BNwbLfrN.css": "assets/flag-tab-BNwbLfrN.b755a99fff7e.css", "assets/library-tab-lz5QMD4i.js": "assets/library-tab-lz5QMD4i.2f04b226ebe8.js", "assets/VSelectionControl-BFq--28I.css": "assets/VSelectionControl-BFq--28I.9687c77461fc.css", "assets/datetime-column-Cqi99Ze-.js": "assets/datetime-column-Cqi99Ze-.49d0ce340183.js", "assets/VExpansionPanels-B8nz8lN5.js": "assets/VExpansionPanels-B8nz8lN5.56e5adec4f62.js", "assets/pdf-doc-CMzaSV_K.css": "assets/pdf-doc-CMzaSV_K.8cd4b3e65f9a.css", "assets/VSlideGroup-C2TL5E34.js": "assets/VSlideGroup-C2TL5E34.775adeb5a973.js", "assets/materialdesignicons-webfont-PXm3-2wK.woff": "assets/materialdesignicons-webfont-PXm3-2wK.026b7ac9c43c.woff", "assets/unauthorized-AnKtlgGy.js": "assets/unauthorized-AnKtlgGy.62ee74d4373c.js", "assets/VSlideGroup-Dk_1upHt.css": "assets/VSlideGroup-Dk_1upHt.2c836070ec75.css", "assets/admin-drawer-panel-mne3FIj6.css": "assets/admin-drawer-panel-mne3FIj6.561b3f75fe65.css", "assets/VTable-DflzroDq.css": "assets/VTable-DflzroDq.160504d82195.css", "assets/settings-drawer-nZ9HvKSZ.css": "assets/settings-drawer-nZ9HvKSZ.01744e131806.css", "assets/stats-tab-DoHb54IU.js": "assets/stats-tab-DoHb54IU.30d7deea7b9f.js", "assets/VCombobox-BASCOy0n.js": "assets/VCombobox-BASCOy0n.7801caa5e192.js", "assets/http-error-CXo9qLiW.js": "assets/http-error-CXo9qLiW.d5a337f399c9.js", "assets/VCheckboxBtn-DVq5lDK4.js": "assets/VCheckboxBtn-DVq5lDK4.5e6464c8d80a.js", "assets/VDialog-lQ13FnRR.css": "assets/VDialog-lQ13FnRR.1c801ad756b2.css", "assets/relation-chips-NgDnInw_.js": "assets/relation-chips-NgDnInw_.3b5ba16f68f0.js", "assets/main-Ztp855PW.css": "assets/main-Ztp855PW.d46d718fac45.css", "assets/VRadioGroup-i2qP9Wu9.css": "assets/VRadioGroup-i2qP9Wu9.8e3741381961.css", "assets/task-tab-B88ucu1U.js": "assets/task-tab-B88ucu1U.4f240e3d82c4.js", "assets/browser-BKZuypzF.js": "assets/browser-BKZuypzF.86e5333bd7d6.js", "assets/change-password-dialog-0u6IJA87.css": "assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css", "assets/copy-to-clipboard-DoUvDJVx.js": "assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js", "assets/VWindowItem-ByIod57Y.css": "assets/VWindowItem-ByIod57Y.f7fb19752bf3.css", "assets/VTextField-Aw8nKhY6.js": "assets/VTextField-Aw8nKhY6.428732ac22d7.js", "assets/VWindowItem-D9j_u9MX.js": "assets/VWindowItem-D9j_u9MX.828acf3dee55.js", "assets/VCheckbox-BwDyxhU7.js": "assets/VCheckbox-BwDyxhU7.831b00df198a.js", "assets/settings-drawer-BaQT27kc.js": "assets/settings-drawer-BaQT27kc.e43fc1527b66.js", "assets/library-tab-BN0SfPcH.css": "assets/library-tab-BN0SfPcH.913e236f625e.css", "assets/confirm-dialog-BmhedLCx.css": "assets/confirm-dialog-BmhedLCx.7c2103d319d4.css", "assets/materialdesignicons-webfont-B7mPwVP_.ttf": "assets/materialdesignicons-webfont-B7mPwVP_.6e435534bd35.ttf", "assets/user-tab-BxtZ2u7W.js": "assets/user-tab-BxtZ2u7W.161cc8f0dcce.js", "assets/admin-jf7zR2p_.js": "assets/admin-jf7zR2p_.4741813376d2.js", "assets/change-password-dialog-Cc1e755p.js": "assets/change-password-dialog-Cc1e755p.b29d200537bf.js", "assets/VSelect-BoKpXxwe.js": "assets/VSelect-BoKpXxwe.a88f065dfe3b.js", "assets/VCombobox-BksEr4D_.css": "assets/VCombobox-BksEr4D_.73429bb75f42.css", "assets/pdf-doc-BpZdmj2g.js": "assets/pdf-doc-BpZdmj2g.93e86d9c7927.js", "assets/VRadioGroup-BgwJ_b94.js": "assets/VRadioGroup-BgwJ_b94.55f84f3429b9.js", "assets/admin-drawer-panel-Dmn4wEY3.js": "assets/admin-drawer-panel-Dmn4wEY3.af7e8490f0e3.js", "assets/flag-tab-B5dRCBAt.js": "assets/flag-tab-B5dRCBAt.e858f7ec9f55.js", "assets/browser-D7xci5SY.css": "assets/browser-D7xci5SY.fa305e14005c.css", "assets/main-17i0EBCp.js": "assets/main-17i0EBCp.7093c3f755f1.js", "assets/admin-B8Bp2Uih.css": "assets/admin-B8Bp2Uih.82c98714bcf1.css", "assets/reader-CRJUR2qj.js": "assets/reader-CRJUR2qj.55d626f0f9fa.js", "assets/task-tab-1XiWn9xP.css": "assets/task-tab-1XiWn9xP.06cb8e1b794d.css", "assets/stats-tab-B4yKuY0c.css": "assets/stats-tab-B4yKuY0c.a5728396494b.css", "assets/reader-CqXFa_gE.css": "assets/reader-CqXFa_gE.78267e9de0c2.css", "assets/confirm-dialog-Cyr7HAAz.js": "assets/confirm-dialog-Cyr7HAAz.8ab1d8b6241a.js", "assets/to-case-B7MjLIw-.js": "assets/to-case-B7MjLIw-.08fc8412de69.js", "assets/datetime-column-DeCthByU.css": "assets/datetime-column-DeCthByU.1f3bf499e063.css", "assets/materialdesignicons-webfont-CSr8KVlo.eot": "assets/materialdesignicons-webfont-CSr8KVlo.8ced95a05e3c.eot", "assets/VExpansionPanels-DsEXVcCv.css": "assets/VExpansionPanels-DsEXVcCv.20b475255e66.css", "assets/unauthorized-CibJYD8o.css": "assets/unauthorized-CibJYD8o.4c2de98c2b53.css", "assets/VCheckbox-CMKdyl0R.css": "assets/VCheckbox-CMKdyl0R.016ed8d222c4.css", "assets/VTable-C0FptljX.js": "assets/VTable-C0FptljX.e4840b635c6e.js", "assets/VTextField-BssVoDhB.css": "assets/VTextField-BssVoDhB.4cc388b4aa3c.css", "assets/pagination-toolbar-B_zL7BQQ.css": "assets/pagination-toolbar-B_zL7BQQ.d1311bd41edc.css", "assets/VDialog-DnbL_v_u.js": "assets/VDialog-DnbL_v_u.0bd289bda8e6.js", "assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "assets/materialdesignicons-webfont-Dp5v-WZN.1d7bcee1b302.woff2", "assets/filter-CuocBoS2.js": "assets/filter-CuocBoS2.885d1b8d44cc.js", "assets/VSelectionControl-BXJGg8No.js": "assets/VSelectionControl-BXJGg8No.0cb36d941d2a.js", "robots.txt": "robots.b6216d61c03e.txt", "manifest.json": "manifest.3851c028b0cb.json"}, "version": "1.1", "hash": "5a212e3ae156"}
codex/util.py CHANGED
@@ -1,10 +1,12 @@
1
1
  """Utility functions."""
2
2
 
3
3
 
4
- def max_none(a, b):
4
+ def max_none(*args):
5
5
  """None aware math.max."""
6
- if a is not None and b is not None:
7
- return max(a, b)
8
- if a is None:
9
- return b
10
- return a
6
+ max_arg = None
7
+ for arg in args:
8
+ if max_arg is None:
9
+ max_arg = arg
10
+ elif arg is not None:
11
+ max_arg = max(max_arg, arg)
12
+ return max_arg
@@ -14,8 +14,11 @@ class AdminAPIKey(AdminGenericAPIView):
14
14
  serializer_class = APIKeySerializer
15
15
  input_serializer_class = None
16
16
 
17
- @extend_schema(request=input_serializer_class)
18
- def post(self, *_args, **_kwargs):
17
+ @extend_schema(
18
+ # parameters=[input_serializer_class],
19
+ request=input_serializer_class
20
+ )
21
+ def put(self, *_args, **_kwargs):
19
22
  """Regenerate the API Key."""
20
23
  ts = Timestamp.objects.get(key=Timestamp.TimestampChoices.API_KEY.value)
21
24
  ts.save_uuid_version()
@@ -21,9 +21,18 @@ from codex.permissions import HasAPIKeyOrIsAdminUser
21
21
  from codex.serializers.admin import AdminStatsRequestSerializer, AdminStatsSerializer
22
22
  from codex.version import VERSION
23
23
  from codex.views.admin.auth import AdminGenericAPIView
24
- from codex.views.const import CONFIG_MODELS, GROUP_MODELS, METADATA_MODELS
24
+ from codex.views.const import CONFIG_MODELS, METADATA_MODELS, STATS_GROUP_MODELS
25
25
 
26
26
  LOG = get_logger(__name__)
27
+ _KEY_MODELS_MAP = MappingProxyType(
28
+ {
29
+ "config": CONFIG_MODELS,
30
+ "groups": STATS_GROUP_MODELS,
31
+ "metadata": METADATA_MODELS,
32
+ }
33
+ )
34
+ _DOCKERENV_PATH = Path("/.dockerenv")
35
+ _CGROUP_PATH = Path("/proc/self/cgroup")
27
36
 
28
37
 
29
38
  class AdminStatsView(AdminGenericAPIView):
@@ -33,24 +42,11 @@ class AdminStatsView(AdminGenericAPIView):
33
42
  serializer_class = AdminStatsSerializer
34
43
  input_serializer_class = AdminStatsRequestSerializer
35
44
 
36
- _KEY_MODELS_MAP = MappingProxyType(
37
- {
38
- "config": CONFIG_MODELS,
39
- "groups": GROUP_MODELS,
40
- "metadata": METADATA_MODELS,
41
- }
42
- )
43
- _DOCKERENV_PATH = Path("/.dockerenv")
44
- _CGROUP_PATH = Path("/proc/self/cgroup")
45
-
46
45
  @classmethod
47
46
  def _is_docker(cls):
48
47
  """Test if we're in a docker container."""
49
48
  try:
50
- return (
51
- cls._DOCKERENV_PATH.is_file()
52
- or "docker" in cls._CGROUP_PATH.read_text()
53
- )
49
+ return _DOCKERENV_PATH.is_file() or "docker" in _CGROUP_PATH.read_text()
54
50
  except Exception:
55
51
  return False
56
52
 
@@ -66,7 +62,7 @@ class AdminStatsView(AdminGenericAPIView):
66
62
  def _get_models(self, key):
67
63
  """Get models from request params."""
68
64
  request_model_list = self.request.GET.get(key)
69
- all_models = self._KEY_MODELS_MAP[key]
65
+ all_models = _KEY_MODELS_MAP[key]
70
66
  if request_model_list:
71
67
  models = []
72
68
  for model_name in request_model_list.split(","):
@@ -176,10 +172,7 @@ class AdminStatsView(AdminGenericAPIView):
176
172
  self._get_metadata(obj)
177
173
  return obj
178
174
 
179
- @extend_schema(
180
- parameters=[input_serializer_class],
181
- request=input_serializer_class,
182
- )
175
+ @extend_schema(parameters=[input_serializer_class])
183
176
  def get(self, *_args, **_kwargs):
184
177
  """Get the stats object and serialize it."""
185
178
  input_serializer = self.input_serializer_class(data=self.request.GET)
@@ -13,7 +13,7 @@ from codex.librarian.covers.tasks import (
13
13
  )
14
14
  from codex.librarian.importer.tasks import (
15
15
  AdoptOrphanFoldersTask,
16
- UpdateGroupsFirstComic,
16
+ UpdateGroupsTask,
17
17
  )
18
18
  from codex.librarian.janitor.tasks import (
19
19
  ForceUpdateAllFailedImportsTask,
@@ -102,8 +102,7 @@ class AdminLibrarianTaskView(AdminAPIView):
102
102
  "poll": WatchdogPollLibrariesTask(frozenset(), False),
103
103
  "poll_force": WatchdogPollLibrariesTask(frozenset(), True),
104
104
  "janitor_nightly": JanitorNightlyTask(),
105
- "update_first_covers": UpdateGroupsFirstComic(),
106
- "force_update_first_covers": UpdateGroupsFirstComic(start_time=EPOCH_START),
105
+ "force_update_groups": UpdateGroupsTask(start_time=EPOCH_START),
107
106
  "adopt_folders": AdoptOrphanFoldersTask(),
108
107
  }
109
108
  )
codex/views/auth.py CHANGED
@@ -52,7 +52,7 @@ class TimezoneView(AuthGenericAPIView):
52
52
  serializer_class = OKSerializer
53
53
 
54
54
  @extend_schema(request=input_serializer_class)
55
- def post(self, request, *args, **kwargs):
55
+ def put(self, request, *args, **kwargs):
56
56
  """Get the user info for the current user."""
57
57
  data = self.request.data # type: ignore
58
58
  serializer = self.input_serializer_class(data=data)
codex/views/bookmark.py CHANGED
@@ -5,6 +5,8 @@ from django.db.models.functions import Now
5
5
  from drf_spectacular.utils import extend_schema
6
6
  from rest_framework.response import Response
7
7
 
8
+ from codex.librarian.mp_queue import LIBRARIAN_QUEUE
9
+ from codex.librarian.notifier.tasks import NotifierTask
8
10
  from codex.logger.logging import get_logger
9
11
  from codex.models import Bookmark, Comic
10
12
  from codex.serializers.models.bookmark import (
@@ -14,7 +16,7 @@ from codex.serializers.models.bookmark import (
14
16
  from codex.views.auth import (
15
17
  AuthFilterGenericAPIView,
16
18
  )
17
- from codex.views.const import GROUP_RELATION
19
+ from codex.views.const import FOLDER_GROUP, GROUP_RELATION
18
20
 
19
21
  LOG = get_logger(__name__)
20
22
  VERTICAL_READING_DIRECTIONS = frozenset({"ttb", "btt"})
@@ -47,7 +49,7 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
47
49
  if not self.request.session or not self.request.session.session_key:
48
50
  LOG.debug("no session, make one")
49
51
  self.request.session.save()
50
- search_kwargs["session__session_key"] = self.request.session.session_key
52
+ search_kwargs["session_id"] = self.request.session.session_key
51
53
  return search_kwargs
52
54
 
53
55
  @staticmethod
@@ -74,8 +76,22 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
74
76
  ):
75
77
  updates["two_pages"] = None
76
78
 
79
+ def notify_library_changed(self):
80
+ """Notify one user that their library changed."""
81
+ if user := self.request.user:
82
+ uid = user.id # type: ignore
83
+ else:
84
+ uid = self.request.session.session_key
85
+ group = f"user_{uid}"
86
+ task = NotifierTask("LIBRARY_CHANGED", group)
87
+ LIBRARIAN_QUEUE.put(task)
88
+
77
89
  def _update_bookmarks(self, search_kwargs, updates):
78
90
  """Update existing bookmarks."""
91
+ count = 0
92
+ finished = False
93
+ if not updates:
94
+ return count, finished
79
95
  group_acl_filter = self.get_group_acl_filter(Bookmark)
80
96
  update_fields = set(updates.keys()) & _BOOKMARK_UPDATE_FIELDS
81
97
  update_fields.add("updated_at")
@@ -87,20 +103,22 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
87
103
  existing_bookmarks = existing_bookmarks.annotate(
88
104
  page_count=F("comic__page_count")
89
105
  )
90
- # only_fields = (*only_fields, "page_count")
91
106
  existing_bookmarks = existing_bookmarks.only(*only_fields)
92
107
  update_bookmarks = []
93
108
  for bm in existing_bookmarks:
94
109
  self._update_bookmarks_validate_page(bm, updates)
95
110
  self._update_bookmarks_validate_two_pages(bm, updates)
111
+ old_finished = bm.finished
96
112
  for key, value in updates.items():
97
113
  setattr(bm, key, value)
98
114
  bm.updated_at = Now()
99
115
  update_bookmarks.append(bm)
116
+ finished = finished or old_finished != bm.finished
100
117
  count = len(update_bookmarks)
101
118
  if count:
102
119
  Bookmark.objects.bulk_update(update_bookmarks, tuple(update_fields))
103
- LOG.debug(f"Updated {count} bookmarks.")
120
+ return count, finished
121
+ # LOG.debug(f"Updated {count} bookmarks.")
104
122
 
105
123
  @staticmethod
106
124
  def _create_bookmarks_validate_two_pages(updates):
@@ -113,25 +131,23 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
113
131
 
114
132
  def _create_bookmarks(self, comic_filter, search_kwargs, updates):
115
133
  """Create new bookmarks for comics that don't exist yet."""
134
+ count = 0
135
+ finished = False
116
136
  self._create_bookmarks_validate_two_pages(updates)
117
137
  if not updates:
118
- return
138
+ return count, finished
119
139
  create_bookmarks = []
120
140
  group_acl_filter = self.get_group_acl_filter(Comic)
141
+ exclude = {}
121
142
  for key, value in search_kwargs.items():
122
- exclude = {"bookmark__" + key: value}
123
- break
124
- else:
125
- reason = (
126
- f"No user or session_id found for creating bookmarks: {search_kwargs}"
127
- )
128
- raise ValueError(reason)
143
+ exclude["bookmark__" + key] = value
129
144
  create_bookmark_comics = (
130
145
  Comic.objects.filter(group_acl_filter)
131
146
  .filter(**comic_filter)
132
147
  .exclude(**exclude)
133
148
  .only(*_COMIC_ONLY_FIELDS)
134
149
  )
150
+ finished = False
135
151
  for comic in create_bookmark_comics:
136
152
  defaults = {"comic": comic}
137
153
  defaults.update(updates)
@@ -140,10 +156,6 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
140
156
  defaults[key] = value
141
157
 
142
158
  bm = Bookmark(**defaults)
143
- if updates.get("page") == comic.max_page:
144
- # Auto finish on bookmark last page
145
- # This almost never happens. Possibly never.
146
- bm.finished = True
147
159
  create_bookmarks.append(bm)
148
160
  count = len(create_bookmarks)
149
161
  if count:
@@ -152,13 +164,21 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
152
164
  update_fields=tuple(_BOOKMARK_UPDATE_FIELDS),
153
165
  unique_fields=Bookmark._meta.unique_together[0], # type: ignore
154
166
  )
155
- LOG.debug(f"Create {count} bookmarks.")
167
+ finished = updates.get("finished", False)
168
+ # LOG.debug(f"Create {count} bookmarks.")
169
+ return count, finished
156
170
 
157
171
  def update_bookmarks(self, updates, comic_filter):
158
172
  """Update a user bookmark."""
159
173
  search_kwargs = self.get_bookmark_search_kwargs(comic_filter)
160
- self._update_bookmarks(search_kwargs, updates)
161
- self._create_bookmarks(comic_filter, search_kwargs, updates)
174
+ count, finished = self._update_bookmarks(search_kwargs, updates)
175
+ create_count, create_finished = self._create_bookmarks(
176
+ comic_filter, search_kwargs, updates
177
+ )
178
+ count += create_count
179
+ finished = finished or create_finished
180
+ if count and finished:
181
+ self.notify_library_changed()
162
182
 
163
183
 
164
184
  class BookmarkView(BookmarkBaseView):
@@ -166,8 +186,12 @@ class BookmarkView(BookmarkBaseView):
166
186
 
167
187
  serializer_class = BookmarkSerializer
168
188
 
169
- def _validate(self, serializer_class):
189
+ def _parse_params(self):
170
190
  """Validate and translate the submitted data."""
191
+ group = self.kwargs.get("group")
192
+ # If the target is recursive, strip everything but finished state data.
193
+ serializer_class = None if group == "c" else BookmarkFinishedSerializer
194
+
171
195
  data = self.request.data # type: ignore
172
196
  if serializer_class:
173
197
  serializer = serializer_class(data=data, partial=True)
@@ -179,16 +203,12 @@ class BookmarkView(BookmarkBaseView):
179
203
  @extend_schema(request=serializer_class, responses=None)
180
204
  def patch(self, *_args, **_kwargs):
181
205
  """Update bookmarks recursively."""
182
- group = self.kwargs.get("group")
183
- # If the target is recursive, strip everything but finished state data.
184
- serializer_class = None if group == "c" else BookmarkFinishedSerializer
185
-
186
- updates = self._validate(serializer_class)
206
+ updates = self._parse_params()
187
207
 
208
+ group = self.kwargs.get("group")
188
209
  pks = self.kwargs.get("pks")
210
+ rel = "folders__in" if group == FOLDER_GROUP else GROUP_RELATION[group] + "__in"
211
+ comic_filter = {rel: pks}
189
212
 
190
- relation = "folders__in" if group == "f" else GROUP_RELATION[group] + "__in"
191
- comic_filter = {relation: pks}
192
-
193
- self.update_bookmarks(updates, comic_filter=comic_filter)
213
+ self.update_bookmarks(updates, comic_filter)
194
214
  return Response()
@@ -9,17 +9,14 @@ from django.db.models import (
9
9
  Case,
10
10
  F,
11
11
  FilteredRelation,
12
- Max,
13
12
  Min,
14
13
  Q,
15
14
  Sum,
16
15
  Value,
17
16
  When,
18
17
  )
19
- from django.db.models.expressions import OuterRef
20
18
  from django.db.models.fields import CharField, PositiveSmallIntegerField
21
- from django.db.models.functions import Coalesce, Least, Reverse, Right, StrIndex
22
- from django.db.models.functions.comparison import Greatest
19
+ from django.db.models.functions import Least, Reverse, Right, StrIndex
23
20
 
24
21
  from codex.logger.logging import get_logger
25
22
  from codex.models import (
@@ -34,7 +31,6 @@ from codex.views.browser.order_by import (
34
31
  BrowserOrderByView,
35
32
  )
36
33
  from codex.views.const import (
37
- EPOCH_START,
38
34
  NONE_DATETIMEFIELD,
39
35
  NONE_INTEGERFIELD,
40
36
  STORY_ARC_GROUP,
@@ -161,32 +157,21 @@ class BrowserAnnotationsView(BrowserOrderByView, SharedAnnotationsMixin):
161
157
  qs = qs.annotate(page_count=page_count_sum)
162
158
  return qs
163
159
 
164
- def get_bookmark_updated_at_aggregate(self, model, always_max=False):
165
- """Get The aggregate function for relevant bookmark.updated_at."""
160
+ def _annotate_bookmark_updated_at(self, qs, model):
161
+ if not self.is_opds_1_acquisition and self.order_key != "bookmark_updated_at":
162
+ return qs
166
163
  bm_rel, bm_filter = self.get_bookmark_rel_and_filter(model)
167
-
168
164
  bm_updated_at_rel = f"{bm_rel}__updated_at"
169
- agg_func = Max if always_max else self.order_agg_func
170
- return agg_func(bm_updated_at_rel, default=NONE_DATETIMEFIELD, filter=bm_filter)
171
-
172
- def _annotate_bookmark_updated_at(self, qs, model):
173
- if (
174
- self.is_opds_1_acquisition
175
- or self.order_key == "bookmark_updated_at"
176
- or self.is_bookmark_filtered
177
- ):
178
- bookmark_updated_at_aggregate = self.get_bookmark_updated_at_aggregate(
179
- model
180
- )
181
- if self.TARGET == "opds1" or self.is_bookmark_filtered:
182
- qs = qs.annotate(bookmark_updated_at=bookmark_updated_at_aggregate)
183
- else:
184
- qs = qs.alias(bookmark_updated_at=bookmark_updated_at_aggregate)
185
- return qs
165
+ bmua_agg = self.order_agg_func(
166
+ bm_updated_at_rel, default=NONE_DATETIMEFIELD, filter=bm_filter
167
+ )
168
+ return qs.annotate(bookmark_updated_at=bmua_agg)
186
169
 
187
170
  def _annotate_order_value(self, qs, model):
188
171
  """Annotate a main key for sorting and browser card display."""
189
172
  # Determine order func
173
+ if self.TARGET == "metadata":
174
+ return qs
190
175
  if model == Folder and self.order_key == "filename":
191
176
  order_value = F("name")
192
177
  elif model == Comic or self.order_key in _ANNOTATED_ORDER_FIELDS:
@@ -206,7 +191,6 @@ class BrowserAnnotationsView(BrowserOrderByView, SharedAnnotationsMixin):
206
191
 
207
192
  def annotate_order_aggregates(self, qs, model):
208
193
  """Annotate common aggregates between browser and metadata."""
209
- # ids coming first or before cover_qs works.
210
194
  qs = qs.annotate(ids=JsonGroupArray("id", distinct=True))
211
195
  qs = self._alias_sort_names(qs, model)
212
196
  qs = self._alias_filename(qs, model)
@@ -297,24 +281,6 @@ class BrowserAnnotationsView(BrowserOrderByView, SharedAnnotationsMixin):
297
281
  progress = Case(When(page_count__gt=0, then=then), default=0.0)
298
282
  return qs.annotate(progress=progress)
299
283
 
300
- def _annotate_mtime(self, qs, model):
301
- """Annotations mtime."""
302
- if self.is_bookmark_filtered:
303
- sub_qs = self.get_filtered_queryset(model, bookmark_filter=False)
304
- bm_rel, bm_filter = self.get_bookmark_rel_and_filter(model)
305
- ua_rel = bm_rel + "__updated_at"
306
- qs = qs.annotate(
307
- bmu_max=Max(
308
- sub_qs.filter(pk=OuterRef("pk")).values_list(ua_rel, flat=True),
309
- default=NONE_DATETIMEFIELD,
310
- filter=bm_filter,
311
- )
312
- )
313
- mtime = Greatest(Coalesce("bmu_max", Value(EPOCH_START)), "updated_at")
314
- else:
315
- mtime = F("updated_at")
316
- return qs.annotate(mtime=mtime)
317
-
318
284
  def annotate_card_aggregates(self, qs, model):
319
285
  """Annotate aggregates that appear the browser card."""
320
286
  if model == Comic:
@@ -324,4 +290,4 @@ class BrowserAnnotationsView(BrowserOrderByView, SharedAnnotationsMixin):
324
290
  qs = self.annotate_group_names(qs, model)
325
291
  qs = self._annotate_bookmarks(qs, model)
326
292
  qs = self._annotate_progress(qs)
327
- return self._annotate_mtime(qs, model)
293
+ return qs.annotate(updated_ats=JsonGroupArray("updated_at", distinct=True))
@@ -14,7 +14,7 @@ from codex.models import (
14
14
  )
15
15
  from codex.serializers.browser.settings import BrowserSettingsSerializer
16
16
  from codex.views.browser.filters.search import SearchFilterView
17
- from codex.views.const import GROUP_MODEL_MAP, ROOT_GROUP
17
+ from codex.views.const import FOLDER_GROUP, GROUP_MODEL_MAP, ROOT_GROUP, STORY_ARC_GROUP
18
18
  from codex.views.util import reparse_json_query_params
19
19
 
20
20
  LOG = get_logger(__name__)
@@ -29,9 +29,7 @@ class BrowserBaseView(SearchFilterView):
29
29
  input_serializer_class = BrowserSettingsSerializer
30
30
 
31
31
  ADMIN_FLAG_VALUE_KEY_MAP = MappingProxyType({})
32
- REPARSE_JSON_FIELDS = frozenset({"filters", "show"})
33
-
34
- _GET_JSON_KEYS = frozenset({"filters", "show"})
32
+ REPARSE_JSON_FIELDS = frozenset({"breadcrumbs", "filters", "show"})
35
33
 
36
34
  def __init__(self, *args, **kwargs):
37
35
  """Set params for the type checker."""
@@ -87,9 +85,27 @@ class BrowserBaseView(SearchFilterView):
87
85
  data = self._parse_query_params()
88
86
  serializer = self.input_serializer_class(data=data)
89
87
  serializer.is_valid(raise_exception=True)
90
- self.load_params_from_session(serializer.validated_data)
88
+
89
+ params: dict[str, Any] = {}
90
+ defaults = self.SESSION_DEFAULTS[self.SESSION_KEY]
91
+ params.update(defaults)
92
+ group = self.kwargs.get("group")
93
+ if group:
94
+ # order_by has a dynamic group based default
95
+ order_defaults = {
96
+ "order_by": "filename"
97
+ if group == FOLDER_GROUP
98
+ else "story_arc_number"
99
+ if group == STORY_ARC_GROUP
100
+ else "sort_name"
101
+ }
102
+ params.update(order_defaults)
103
+ validated_data = serializer.validated_data
104
+
105
+ if validated_data:
106
+ params.update(validated_data) # type: ignore
107
+ self.params = MappingProxyType(params)
91
108
  self.is_bookmark_filtered = bool(self.params.get("filters", {}).get("bookmark"))
92
- return serializer.validated_data
93
109
 
94
110
  def set_order_key(self):
95
111
  """Unused until browser."""
@@ -18,10 +18,10 @@ class BrowserBreadcrumbsView(BrowserPaginateView):
18
18
  """Load breadcrumbs and determine if they should be searched for a graft."""
19
19
  breadcrumbs: list[Route] = list(self.params.get("breadcrumbs", []))
20
20
  old_breadcrumbs = [Route(**crumb) for crumb in breadcrumbs]
21
- changed = bool(old_breadcrumbs) and old_breadcrumbs[-1].group in valid_groups
22
- if changed:
21
+ invalid = not old_breadcrumbs or old_breadcrumbs[-1].group not in valid_groups
22
+ if invalid:
23
23
  old_breadcrumbs = []
24
- return old_breadcrumbs, changed
24
+ return old_breadcrumbs, invalid
25
25
 
26
26
  def _breadcrumbs_save(self, breadcrumbs):
27
27
  """Save the breadcrumbs to params."""
@@ -184,7 +184,7 @@ class BrowserBreadcrumbsView(BrowserPaginateView):
184
184
 
185
185
  return tuple(new_breadcrumbs), changed
186
186
 
187
- def get_parent_breadcrumbs(
187
+ def get_breadcrumbs(
188
188
  self,
189
189
  ) -> tuple[Route, ...]:
190
190
  """Graft or create breadcrumbs by browser mode."""
@@ -199,4 +199,4 @@ class BrowserBreadcrumbsView(BrowserPaginateView):
199
199
  if changed:
200
200
  self._breadcrumbs_save(breadcrumbs)
201
201
 
202
- return breadcrumbs[:-1] if breadcrumbs else ()
202
+ return breadcrumbs