codex 1.7.1__py3-none-any.whl → 1.7.3__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 (916) hide show
  1. codex/asgi.py +2 -1
  2. codex/choices.py +10 -21
  3. codex/choices_to_json.py +8 -8
  4. codex/db.py +2 -2
  5. codex/exceptions.py +5 -6
  6. codex/librarian/bookmark/bookmarkd.py +9 -6
  7. codex/librarian/bookmark/tasks.py +1 -1
  8. codex/librarian/bookmark/update.py +17 -31
  9. codex/librarian/covers/create.py +10 -8
  10. codex/librarian/covers/path.py +6 -5
  11. codex/librarian/covers/purge.py +2 -2
  12. codex/librarian/cron/crond.py +1 -1
  13. codex/librarian/importer/aggregate.py +2 -2
  14. codex/librarian/importer/cache.py +1 -4
  15. codex/librarian/importer/create_comics.py +2 -2
  16. codex/librarian/importer/create_covers.py +1 -1
  17. codex/librarian/importer/create_fks.py +4 -3
  18. codex/librarian/importer/deleted.py +3 -3
  19. codex/librarian/importer/extract.py +2 -2
  20. codex/librarian/importer/failed_imports.py +1 -1
  21. codex/librarian/importer/importer.py +3 -1
  22. codex/librarian/importer/importerd.py +3 -3
  23. codex/librarian/importer/link_comics.py +2 -1
  24. codex/librarian/importer/moved.py +2 -7
  25. codex/librarian/importer/query_fks.py +3 -6
  26. codex/librarian/importer/tasks.py +1 -1
  27. codex/librarian/janitor/integrity.py +27 -20
  28. codex/librarian/janitor/janitor.py +5 -2
  29. codex/librarian/janitor/latest_version.py +1 -1
  30. codex/librarian/janitor/update.py +2 -2
  31. codex/librarian/janitor/vacuum.py +1 -1
  32. codex/librarian/librariand.py +16 -15
  33. codex/librarian/notifier/notifierd.py +2 -1
  34. codex/librarian/search/optimize.py +1 -1
  35. codex/librarian/search/remove.py +1 -1
  36. codex/librarian/search/update.py +11 -7
  37. codex/librarian/telemeter/stats.py +7 -6
  38. codex/librarian/telemeter/telemeter.py +0 -1
  39. codex/librarian/watchdog/db_snapshot.py +3 -3
  40. codex/librarian/watchdog/dir_snapshot_diff.py +3 -4
  41. codex/librarian/watchdog/emitter.py +4 -4
  42. codex/librarian/watchdog/event_batcherd.py +2 -1
  43. codex/librarian/watchdog/events.py +1 -2
  44. codex/librarian/watchdog/observers.py +15 -10
  45. codex/logger/loggerd.py +40 -17
  46. codex/logger/logging.py +1 -1
  47. codex/memory.py +3 -2
  48. codex/migrations/0001_init.py +1 -2
  49. codex/migrations/0014_pdf_issue_suffix_remove_cover_image_sort_name.py +1 -2
  50. codex/migrations/0018_rename_userbookmark_bookmark.py +1 -2
  51. codex/migrations/0028_telemeter.py +1 -5
  52. codex/migrations/0031_adminflag_banner.py +50 -0
  53. codex/models/admin.py +4 -3
  54. codex/models/base.py +3 -1
  55. codex/models/bookmark.py +4 -7
  56. codex/models/comic.py +2 -2
  57. codex/models/functions.py +12 -5
  58. codex/models/groups.py +1 -1
  59. codex/models/library.py +1 -1
  60. codex/models/paths.py +4 -4
  61. codex/models/query.py +8 -4
  62. codex/models/util.py +1 -1
  63. codex/permissions.py +1 -1
  64. codex/run.py +1 -1
  65. codex/serializers/admin/flags.py +1 -1
  66. codex/serializers/admin/libraries.py +1 -3
  67. codex/serializers/auth.py +1 -0
  68. codex/serializers/browser/choices.py +9 -11
  69. codex/serializers/browser/metadata.py +1 -1
  70. codex/serializers/browser/mixins.py +5 -1
  71. codex/serializers/browser/settings.py +2 -2
  72. codex/serializers/fields.py +7 -7
  73. codex/serializers/models/base.py +1 -1
  74. codex/serializers/models/comic.py +2 -2
  75. codex/serializers/models/groups.py +0 -2
  76. codex/serializers/opds/authentication.py +2 -1
  77. codex/serializers/opds/v2/__init__.py +1 -0
  78. codex/serializers/opds/v2/facet.py +13 -0
  79. codex/serializers/opds/v2/feed.py +36 -0
  80. codex/serializers/opds/v2/links.py +75 -0
  81. codex/serializers/opds/v2/metadata.py +23 -0
  82. codex/serializers/opds/v2/progression.py +65 -0
  83. codex/serializers/opds/v2/publication.py +81 -0
  84. codex/serializers/opds/{v2_unused.py → v2/unused.py} +16 -9
  85. codex/serializers/route.py +2 -2
  86. codex/settings/settings.py +4 -3
  87. codex/signals/django_signals.py +1 -1
  88. codex/static_root/assets/VCheckbox-Dv6fwaDb.56abbfb00c8a.js +1 -0
  89. codex/static_root/assets/VCheckbox-Dv6fwaDb.56abbfb00c8a.js.br +0 -0
  90. codex/static_root/assets/VCheckbox-Dv6fwaDb.56abbfb00c8a.js.gz +0 -0
  91. codex/static_root/assets/VCheckbox-Dv6fwaDb.js +1 -0
  92. codex/static_root/assets/VCheckbox-Dv6fwaDb.js.br +0 -0
  93. codex/static_root/assets/VCheckbox-Dv6fwaDb.js.gz +0 -0
  94. codex/static_root/assets/VCheckboxBtn-CNMFahfF.4ee9778a562e.js +1 -0
  95. codex/static_root/assets/VCheckboxBtn-CNMFahfF.4ee9778a562e.js.br +0 -0
  96. codex/static_root/assets/VCheckboxBtn-CNMFahfF.4ee9778a562e.js.gz +0 -0
  97. codex/static_root/assets/VCheckboxBtn-CNMFahfF.js +1 -0
  98. codex/static_root/assets/VCheckboxBtn-CNMFahfF.js.br +0 -0
  99. codex/static_root/assets/VCheckboxBtn-CNMFahfF.js.gz +0 -0
  100. codex/static_root/assets/VCombobox-DqBFki-9.2806f95c938d.js +1 -0
  101. codex/static_root/assets/VCombobox-DqBFki-9.2806f95c938d.js.br +0 -0
  102. codex/static_root/assets/VCombobox-DqBFki-9.2806f95c938d.js.gz +0 -0
  103. codex/static_root/assets/VCombobox-DqBFki-9.js +1 -0
  104. codex/static_root/assets/VCombobox-DqBFki-9.js.br +0 -0
  105. codex/static_root/assets/VCombobox-DqBFki-9.js.gz +0 -0
  106. codex/static_root/assets/VDialog-CQXjBvDZ.1a576c5e472f.js +1 -0
  107. codex/static_root/assets/VDialog-CQXjBvDZ.1a576c5e472f.js.br +0 -0
  108. codex/static_root/assets/VDialog-CQXjBvDZ.1a576c5e472f.js.gz +0 -0
  109. codex/static_root/assets/VDialog-CQXjBvDZ.js +1 -0
  110. codex/static_root/assets/VDialog-CQXjBvDZ.js.br +0 -0
  111. codex/static_root/assets/VDialog-CQXjBvDZ.js.gz +0 -0
  112. codex/static_root/assets/VDialog-DWos4S54.b07aca713774.css +1 -0
  113. codex/static_root/assets/VDialog-DWos4S54.b07aca713774.css.br +0 -0
  114. codex/static_root/assets/VDialog-DWos4S54.b07aca713774.css.gz +0 -0
  115. codex/static_root/assets/VDialog-DWos4S54.css +1 -0
  116. codex/static_root/assets/VDialog-DWos4S54.css.br +0 -0
  117. codex/static_root/assets/VDialog-DWos4S54.css.gz +0 -0
  118. codex/static_root/assets/VDivider-DU47sRrT.3d2e17799e5c.css +1 -0
  119. codex/static_root/assets/VDivider-DU47sRrT.3d2e17799e5c.css.br +0 -0
  120. codex/static_root/assets/VDivider-DU47sRrT.3d2e17799e5c.css.gz +0 -0
  121. codex/static_root/assets/VDivider-DU47sRrT.css +1 -0
  122. codex/static_root/assets/VDivider-DU47sRrT.css.br +0 -0
  123. codex/static_root/assets/VDivider-DU47sRrT.css.gz +0 -0
  124. codex/static_root/assets/VDivider-DUxQu-IZ.73d92ae2a07e.js +1 -0
  125. codex/static_root/assets/VDivider-DUxQu-IZ.73d92ae2a07e.js.br +0 -0
  126. codex/static_root/assets/VDivider-DUxQu-IZ.73d92ae2a07e.js.gz +0 -0
  127. codex/static_root/assets/VDivider-DUxQu-IZ.js +1 -0
  128. codex/static_root/assets/VDivider-DUxQu-IZ.js.br +0 -0
  129. codex/static_root/assets/VDivider-DUxQu-IZ.js.gz +0 -0
  130. codex/static_root/assets/VExpansionPanels-BaYzHUJp.5346826103eb.js +1 -0
  131. codex/static_root/assets/VExpansionPanels-BaYzHUJp.5346826103eb.js.br +0 -0
  132. codex/static_root/assets/VExpansionPanels-BaYzHUJp.5346826103eb.js.gz +0 -0
  133. codex/static_root/assets/VExpansionPanels-BaYzHUJp.js +1 -0
  134. codex/static_root/assets/VExpansionPanels-BaYzHUJp.js.br +0 -0
  135. codex/static_root/assets/VExpansionPanels-BaYzHUJp.js.gz +0 -0
  136. codex/static_root/assets/VForm-DxBt30-N.138c0b89b6fc.css +1 -0
  137. codex/static_root/assets/VForm-DxBt30-N.138c0b89b6fc.css.br +0 -0
  138. codex/static_root/assets/VForm-DxBt30-N.138c0b89b6fc.css.gz +0 -0
  139. codex/static_root/assets/VForm-DxBt30-N.css +1 -0
  140. codex/static_root/assets/VForm-DxBt30-N.css.br +0 -0
  141. codex/static_root/assets/VForm-DxBt30-N.css.gz +0 -0
  142. codex/static_root/assets/VForm-hB4C5jVd.a2b90ddcd8ee.js +1 -0
  143. codex/static_root/assets/VForm-hB4C5jVd.a2b90ddcd8ee.js.br +0 -0
  144. codex/static_root/assets/VForm-hB4C5jVd.a2b90ddcd8ee.js.gz +0 -0
  145. codex/static_root/assets/VForm-hB4C5jVd.js +1 -0
  146. codex/static_root/assets/VForm-hB4C5jVd.js.br +0 -0
  147. codex/static_root/assets/VForm-hB4C5jVd.js.gz +0 -0
  148. codex/static_root/assets/VRadioGroup-DOjw38qB.cbf2922d05af.js +1 -0
  149. codex/static_root/assets/VRadioGroup-DOjw38qB.cbf2922d05af.js.br +0 -0
  150. codex/static_root/assets/VRadioGroup-DOjw38qB.cbf2922d05af.js.gz +0 -0
  151. codex/static_root/assets/VRadioGroup-DOjw38qB.js +1 -0
  152. codex/static_root/assets/VRadioGroup-DOjw38qB.js.br +0 -0
  153. codex/static_root/assets/VRadioGroup-DOjw38qB.js.gz +0 -0
  154. codex/static_root/assets/VSelect-CP_CVb8s.6309f7bf17bb.css +1 -0
  155. codex/static_root/assets/VSelect-CP_CVb8s.6309f7bf17bb.css.br +0 -0
  156. codex/static_root/assets/VSelect-CP_CVb8s.6309f7bf17bb.css.gz +0 -0
  157. codex/static_root/assets/VSelect-CP_CVb8s.css +1 -0
  158. codex/static_root/assets/VSelect-CP_CVb8s.css.br +0 -0
  159. codex/static_root/assets/VSelect-CP_CVb8s.css.gz +0 -0
  160. codex/static_root/assets/VSelect-L4v_m3ag.db9fb8348617.js +1 -0
  161. codex/static_root/assets/VSelect-L4v_m3ag.db9fb8348617.js.br +0 -0
  162. codex/static_root/assets/VSelect-L4v_m3ag.db9fb8348617.js.gz +0 -0
  163. codex/static_root/assets/VSelect-L4v_m3ag.js +1 -0
  164. codex/static_root/assets/VSelect-L4v_m3ag.js.br +0 -0
  165. codex/static_root/assets/VSelect-L4v_m3ag.js.gz +0 -0
  166. codex/static_root/assets/VSelectionControl-BqB1JeKa.2fb68a673402.js +1 -0
  167. codex/static_root/assets/VSelectionControl-BqB1JeKa.2fb68a673402.js.br +0 -0
  168. codex/static_root/assets/VSelectionControl-BqB1JeKa.2fb68a673402.js.gz +0 -0
  169. codex/static_root/assets/VSelectionControl-BqB1JeKa.js +1 -0
  170. codex/static_root/assets/VSelectionControl-BqB1JeKa.js.br +0 -0
  171. codex/static_root/assets/VSelectionControl-BqB1JeKa.js.gz +0 -0
  172. codex/static_root/assets/VSelectionControl-DPpfgCW2.cc18de4e83f6.css +1 -0
  173. codex/static_root/assets/VSelectionControl-DPpfgCW2.cc18de4e83f6.css.br +0 -0
  174. codex/static_root/assets/VSelectionControl-DPpfgCW2.cc18de4e83f6.css.gz +0 -0
  175. codex/static_root/assets/VSelectionControl-DPpfgCW2.css +1 -0
  176. codex/static_root/assets/VSelectionControl-DPpfgCW2.css.br +0 -0
  177. codex/static_root/assets/VSelectionControl-DPpfgCW2.css.gz +0 -0
  178. codex/static_root/assets/VTable-CtorAbOx.bbda450cbd73.js +1 -0
  179. codex/static_root/assets/VTable-CtorAbOx.bbda450cbd73.js.br +0 -0
  180. codex/static_root/assets/VTable-CtorAbOx.bbda450cbd73.js.gz +0 -0
  181. codex/static_root/assets/VTable-CtorAbOx.js +1 -0
  182. codex/static_root/assets/VTable-CtorAbOx.js.br +0 -0
  183. codex/static_root/assets/VTable-CtorAbOx.js.gz +0 -0
  184. codex/static_root/assets/VWindowItem-Bl-fa3ss.334e6b813775.js +1 -0
  185. codex/static_root/assets/VWindowItem-Bl-fa3ss.334e6b813775.js.br +0 -0
  186. codex/static_root/assets/VWindowItem-Bl-fa3ss.334e6b813775.js.gz +0 -0
  187. codex/static_root/assets/VWindowItem-Bl-fa3ss.js +1 -0
  188. codex/static_root/assets/VWindowItem-Bl-fa3ss.js.br +0 -0
  189. codex/static_root/assets/VWindowItem-Bl-fa3ss.js.gz +0 -0
  190. codex/static_root/assets/admin-BAVKNREt.23c0966bd683.js +1 -0
  191. codex/static_root/assets/admin-BAVKNREt.23c0966bd683.js.br +0 -0
  192. codex/static_root/assets/admin-BAVKNREt.23c0966bd683.js.gz +0 -0
  193. codex/static_root/assets/admin-BAVKNREt.js +1 -0
  194. codex/static_root/assets/admin-BAVKNREt.js.br +0 -0
  195. codex/static_root/assets/admin-BAVKNREt.js.gz +0 -0
  196. codex/static_root/assets/admin-C3iCIUnm.06cb213f624d.css +1 -0
  197. codex/static_root/assets/admin-C3iCIUnm.06cb213f624d.css.br +0 -0
  198. codex/static_root/assets/admin-C3iCIUnm.06cb213f624d.css.gz +0 -0
  199. codex/static_root/assets/admin-C3iCIUnm.css +1 -0
  200. codex/static_root/assets/admin-C3iCIUnm.css.br +0 -0
  201. codex/static_root/assets/admin-C3iCIUnm.css.gz +0 -0
  202. codex/static_root/assets/admin-CHuFhx_t.a54700f97fc8.js +1 -0
  203. codex/static_root/assets/admin-CHuFhx_t.a54700f97fc8.js.br +0 -0
  204. codex/static_root/assets/admin-CHuFhx_t.a54700f97fc8.js.gz +0 -0
  205. codex/static_root/assets/admin-CHuFhx_t.js +1 -0
  206. codex/static_root/assets/admin-CHuFhx_t.js.br +0 -0
  207. codex/static_root/assets/admin-CHuFhx_t.js.gz +0 -0
  208. codex/static_root/assets/admin-menu-T8WJ_x0C.4f011540bb4c.js +1 -0
  209. codex/static_root/assets/admin-menu-T8WJ_x0C.4f011540bb4c.js.br +0 -0
  210. codex/static_root/assets/admin-menu-T8WJ_x0C.4f011540bb4c.js.gz +0 -0
  211. codex/static_root/assets/admin-menu-T8WJ_x0C.js +1 -0
  212. codex/static_root/assets/admin-menu-T8WJ_x0C.js.br +0 -0
  213. codex/static_root/assets/admin-menu-T8WJ_x0C.js.gz +0 -0
  214. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.7b36216f68b5.js +1 -0
  215. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.7b36216f68b5.js.br +0 -0
  216. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.7b36216f68b5.js.gz +0 -0
  217. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.js +1 -0
  218. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.js.br +0 -0
  219. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.js.gz +0 -0
  220. codex/static_root/assets/browser-DNzQvgkY.aea8b7d7ca40.css +1 -0
  221. codex/static_root/assets/browser-DNzQvgkY.aea8b7d7ca40.css.br +0 -0
  222. codex/static_root/assets/browser-DNzQvgkY.aea8b7d7ca40.css.gz +0 -0
  223. codex/static_root/assets/browser-DNzQvgkY.css +1 -0
  224. codex/static_root/assets/browser-DNzQvgkY.css.br +0 -0
  225. codex/static_root/assets/browser-DNzQvgkY.css.gz +0 -0
  226. codex/static_root/assets/browser-DdLCtUlr.380b79bea4a7.js +1 -0
  227. codex/static_root/assets/browser-DdLCtUlr.380b79bea4a7.js.br +0 -0
  228. codex/static_root/assets/browser-DdLCtUlr.380b79bea4a7.js.gz +0 -0
  229. codex/static_root/assets/browser-DdLCtUlr.js +1 -0
  230. codex/static_root/assets/browser-DdLCtUlr.js.br +0 -0
  231. codex/static_root/assets/browser-DdLCtUlr.js.gz +0 -0
  232. codex/static_root/assets/change-password-dialog-Cy1tU-tj.416ef5bdfd46.js +1 -0
  233. codex/static_root/assets/change-password-dialog-Cy1tU-tj.416ef5bdfd46.js.br +0 -0
  234. codex/static_root/assets/change-password-dialog-Cy1tU-tj.416ef5bdfd46.js.gz +0 -0
  235. codex/static_root/assets/change-password-dialog-Cy1tU-tj.js +1 -0
  236. codex/static_root/assets/change-password-dialog-Cy1tU-tj.js.br +0 -0
  237. codex/static_root/assets/change-password-dialog-Cy1tU-tj.js.gz +0 -0
  238. codex/static_root/assets/change-password-dialog-D0ymWcl_.a30e68c6e303.css +1 -0
  239. codex/static_root/assets/change-password-dialog-D0ymWcl_.a30e68c6e303.css.br +0 -0
  240. codex/static_root/assets/change-password-dialog-D0ymWcl_.a30e68c6e303.css.gz +0 -0
  241. codex/static_root/assets/change-password-dialog-D0ymWcl_.css +1 -0
  242. codex/static_root/assets/change-password-dialog-D0ymWcl_.css.br +0 -0
  243. codex/static_root/assets/change-password-dialog-D0ymWcl_.css.gz +0 -0
  244. codex/static_root/assets/confirm-dialog-B1ABbGMU.9b5915b112c0.css +1 -0
  245. codex/static_root/assets/confirm-dialog-B1ABbGMU.9b5915b112c0.css.br +0 -0
  246. codex/static_root/assets/confirm-dialog-B1ABbGMU.css +1 -0
  247. codex/static_root/assets/confirm-dialog-B1ABbGMU.css.br +0 -0
  248. codex/static_root/assets/confirm-dialog-B_Y3KKiL.1070d18f6b2d.js +1 -0
  249. codex/static_root/assets/confirm-dialog-B_Y3KKiL.1070d18f6b2d.js.br +0 -0
  250. codex/static_root/assets/confirm-dialog-B_Y3KKiL.1070d18f6b2d.js.gz +0 -0
  251. codex/static_root/assets/confirm-dialog-B_Y3KKiL.js +1 -0
  252. codex/static_root/assets/confirm-dialog-B_Y3KKiL.js.br +0 -0
  253. codex/static_root/assets/confirm-dialog-B_Y3KKiL.js.gz +0 -0
  254. codex/static_root/assets/datetime-column-DVC0YqHC.03bb52c198e9.js +1 -0
  255. codex/static_root/assets/datetime-column-DVC0YqHC.03bb52c198e9.js.br +0 -0
  256. codex/static_root/assets/datetime-column-DVC0YqHC.03bb52c198e9.js.gz +0 -0
  257. codex/static_root/assets/datetime-column-DVC0YqHC.js +1 -0
  258. codex/static_root/assets/datetime-column-DVC0YqHC.js.br +0 -0
  259. codex/static_root/assets/datetime-column-DVC0YqHC.js.gz +0 -0
  260. codex/static_root/assets/{filter-CnO_WiBE.4044b9091aae.js → filter-xcEcgcIx.be1bb4725c89.js} +1 -1
  261. codex/static_root/assets/filter-xcEcgcIx.be1bb4725c89.js.br +0 -0
  262. codex/static_root/assets/filter-xcEcgcIx.be1bb4725c89.js.gz +0 -0
  263. codex/static_root/assets/{filter-CnO_WiBE.js → filter-xcEcgcIx.js} +1 -1
  264. codex/static_root/assets/filter-xcEcgcIx.js.br +0 -0
  265. codex/static_root/assets/filter-xcEcgcIx.js.gz +0 -0
  266. codex/static_root/assets/flag-tab-BOyQb0kr.842fca93f19c.js +1 -0
  267. codex/static_root/assets/flag-tab-BOyQb0kr.842fca93f19c.js.br +0 -0
  268. codex/static_root/assets/flag-tab-BOyQb0kr.842fca93f19c.js.gz +0 -0
  269. codex/static_root/assets/flag-tab-BOyQb0kr.js +1 -0
  270. codex/static_root/assets/flag-tab-BOyQb0kr.js.br +0 -0
  271. codex/static_root/assets/flag-tab-BOyQb0kr.js.gz +0 -0
  272. codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css +1 -0
  273. codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css.br +0 -0
  274. codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css.gz +0 -0
  275. codex/static_root/assets/flag-tab-D2MYXCHk.css +1 -0
  276. codex/static_root/assets/flag-tab-D2MYXCHk.css.br +0 -0
  277. codex/static_root/assets/flag-tab-D2MYXCHk.css.gz +0 -0
  278. codex/static_root/assets/{VDialog-CSvrKKb2.css → forwardRefs-CFNX6kJ2.9b56b4459240.css} +1 -1
  279. codex/static_root/assets/forwardRefs-CFNX6kJ2.9b56b4459240.css.br +0 -0
  280. codex/static_root/assets/forwardRefs-CFNX6kJ2.9b56b4459240.css.gz +0 -0
  281. codex/static_root/assets/{VDialog-CSvrKKb2.fd4d50904b17.css → forwardRefs-CFNX6kJ2.css} +1 -1
  282. codex/static_root/assets/forwardRefs-CFNX6kJ2.css.br +0 -0
  283. codex/static_root/assets/forwardRefs-CFNX6kJ2.css.gz +0 -0
  284. codex/static_root/assets/forwardRefs-D1ZDjzWx.96fccf773093.js +1 -0
  285. codex/static_root/assets/forwardRefs-D1ZDjzWx.96fccf773093.js.br +0 -0
  286. codex/static_root/assets/forwardRefs-D1ZDjzWx.96fccf773093.js.gz +0 -0
  287. codex/static_root/assets/forwardRefs-D1ZDjzWx.js +1 -0
  288. codex/static_root/assets/forwardRefs-D1ZDjzWx.js.br +0 -0
  289. codex/static_root/assets/forwardRefs-D1ZDjzWx.js.gz +0 -0
  290. codex/static_root/assets/group-tab-DkAIGL8z.527cad03c21d.js +1 -0
  291. codex/static_root/assets/group-tab-DkAIGL8z.527cad03c21d.js.br +0 -0
  292. codex/static_root/assets/group-tab-DkAIGL8z.527cad03c21d.js.gz +0 -0
  293. codex/static_root/assets/group-tab-DkAIGL8z.js +1 -0
  294. codex/static_root/assets/group-tab-DkAIGL8z.js.br +0 -0
  295. codex/static_root/assets/group-tab-DkAIGL8z.js.gz +0 -0
  296. codex/static_root/assets/http-error-CODU7jcH.8c13689ae574.css +1 -0
  297. codex/static_root/assets/http-error-CODU7jcH.8c13689ae574.css.br +0 -0
  298. codex/static_root/assets/http-error-CODU7jcH.8c13689ae574.css.gz +0 -0
  299. codex/static_root/assets/http-error-CODU7jcH.css +1 -0
  300. codex/static_root/assets/http-error-CODU7jcH.css.br +0 -0
  301. codex/static_root/assets/http-error-CODU7jcH.css.gz +0 -0
  302. codex/static_root/assets/http-error-CjSb8orc.ad6fc5733ed8.js +1 -0
  303. codex/static_root/assets/http-error-CjSb8orc.ad6fc5733ed8.js.br +0 -0
  304. codex/static_root/assets/http-error-CjSb8orc.ad6fc5733ed8.js.gz +0 -0
  305. codex/static_root/assets/http-error-CjSb8orc.js +1 -0
  306. codex/static_root/assets/http-error-CjSb8orc.js.br +0 -0
  307. codex/static_root/assets/http-error-CjSb8orc.js.gz +0 -0
  308. codex/static_root/assets/index-CoFXW6I0.27f397e1425e.js +1 -0
  309. codex/static_root/assets/index-CoFXW6I0.27f397e1425e.js.br +0 -0
  310. codex/static_root/assets/index-CoFXW6I0.27f397e1425e.js.gz +0 -0
  311. codex/static_root/assets/index-CoFXW6I0.js +1 -0
  312. codex/static_root/assets/index-CoFXW6I0.js.br +0 -0
  313. codex/static_root/assets/index-CoFXW6I0.js.gz +0 -0
  314. codex/static_root/assets/library-tab-CgsXOX_r.75baedb7e976.css +1 -0
  315. codex/static_root/assets/library-tab-CgsXOX_r.75baedb7e976.css.br +0 -0
  316. codex/static_root/assets/library-tab-CgsXOX_r.75baedb7e976.css.gz +0 -0
  317. codex/static_root/assets/library-tab-CgsXOX_r.css +1 -0
  318. codex/static_root/assets/library-tab-CgsXOX_r.css.br +0 -0
  319. codex/static_root/assets/library-tab-CgsXOX_r.css.gz +0 -0
  320. codex/static_root/assets/library-tab-hkMMBz1x.02270491d822.js +1 -0
  321. codex/static_root/assets/library-tab-hkMMBz1x.02270491d822.js.br +0 -0
  322. codex/static_root/assets/library-tab-hkMMBz1x.02270491d822.js.gz +0 -0
  323. codex/static_root/assets/library-tab-hkMMBz1x.js +1 -0
  324. codex/static_root/assets/library-tab-hkMMBz1x.js.br +0 -0
  325. codex/static_root/assets/library-tab-hkMMBz1x.js.gz +0 -0
  326. codex/static_root/assets/main-DCaPxp2h.076707ddd123.js +35 -0
  327. codex/static_root/assets/main-DCaPxp2h.076707ddd123.js.br +0 -0
  328. codex/static_root/assets/main-DCaPxp2h.076707ddd123.js.gz +0 -0
  329. codex/static_root/assets/main-DCaPxp2h.js +35 -0
  330. codex/static_root/assets/main-DCaPxp2h.js.br +0 -0
  331. codex/static_root/assets/main-DCaPxp2h.js.gz +0 -0
  332. codex/static_root/assets/pager-full-pdf-CwmA9y3l.e7dfdd2a6937.js +1 -0
  333. codex/static_root/assets/pager-full-pdf-CwmA9y3l.e7dfdd2a6937.js.br +0 -0
  334. codex/static_root/assets/pager-full-pdf-CwmA9y3l.e7dfdd2a6937.js.gz +0 -0
  335. codex/static_root/assets/pager-full-pdf-CwmA9y3l.js +1 -0
  336. codex/static_root/assets/pager-full-pdf-CwmA9y3l.js.br +0 -0
  337. codex/static_root/assets/pager-full-pdf-CwmA9y3l.js.gz +0 -0
  338. codex/static_root/assets/pagination-toolbar-D5VQREy5.css +1 -0
  339. codex/static_root/assets/pagination-toolbar-D5VQREy5.css.br +0 -0
  340. codex/static_root/assets/pagination-toolbar-D5VQREy5.css.gz +0 -0
  341. codex/static_root/assets/pagination-toolbar-D5VQREy5.dcb0eba65827.css +1 -0
  342. codex/static_root/assets/pagination-toolbar-D5VQREy5.dcb0eba65827.css.br +0 -0
  343. codex/static_root/assets/pagination-toolbar-D5VQREy5.dcb0eba65827.css.gz +0 -0
  344. codex/static_root/assets/pagination-toolbar-DoqxSygU.f985bc705fe5.js +1 -0
  345. codex/static_root/assets/pagination-toolbar-DoqxSygU.f985bc705fe5.js.br +0 -0
  346. codex/static_root/assets/pagination-toolbar-DoqxSygU.f985bc705fe5.js.gz +0 -0
  347. codex/static_root/assets/pagination-toolbar-DoqxSygU.js +1 -0
  348. codex/static_root/assets/pagination-toolbar-DoqxSygU.js.br +0 -0
  349. codex/static_root/assets/pagination-toolbar-DoqxSygU.js.gz +0 -0
  350. codex/static_root/assets/pdf-doc-BwxvAx1z.96cbc39c321d.js +348 -0
  351. codex/static_root/assets/pdf-doc-BwxvAx1z.96cbc39c321d.js.br +0 -0
  352. codex/static_root/assets/pdf-doc-BwxvAx1z.96cbc39c321d.js.gz +0 -0
  353. codex/static_root/assets/pdf-doc-BwxvAx1z.js +348 -0
  354. codex/static_root/assets/pdf-doc-BwxvAx1z.js.br +0 -0
  355. codex/static_root/assets/pdf-doc-BwxvAx1z.js.gz +0 -0
  356. codex/static_root/assets/reader-D_3ruSqa.2ed32f08e906.css +1 -0
  357. codex/static_root/assets/reader-D_3ruSqa.2ed32f08e906.css.br +0 -0
  358. codex/static_root/assets/reader-D_3ruSqa.2ed32f08e906.css.gz +0 -0
  359. codex/static_root/assets/reader-D_3ruSqa.css +1 -0
  360. codex/static_root/assets/reader-D_3ruSqa.css.br +0 -0
  361. codex/static_root/assets/reader-D_3ruSqa.css.gz +0 -0
  362. codex/static_root/assets/reader-hHIonVbA.4c12219242a9.js +2 -0
  363. codex/static_root/assets/reader-hHIonVbA.4c12219242a9.js.br +0 -0
  364. codex/static_root/assets/reader-hHIonVbA.4c12219242a9.js.gz +0 -0
  365. codex/static_root/assets/reader-hHIonVbA.js +2 -0
  366. codex/static_root/assets/reader-hHIonVbA.js.br +0 -0
  367. codex/static_root/assets/reader-hHIonVbA.js.gz +0 -0
  368. codex/static_root/assets/relation-chips-D7-5kPem.4443b085aca2.js +1 -0
  369. codex/static_root/assets/relation-chips-D7-5kPem.4443b085aca2.js.br +0 -0
  370. codex/static_root/assets/relation-chips-D7-5kPem.4443b085aca2.js.gz +0 -0
  371. codex/static_root/assets/relation-chips-D7-5kPem.js +1 -0
  372. codex/static_root/assets/relation-chips-D7-5kPem.js.br +0 -0
  373. codex/static_root/assets/relation-chips-D7-5kPem.js.gz +0 -0
  374. codex/static_root/assets/settings-drawer-CdFmOhnd.f7dcd12b3ebc.js +2 -0
  375. codex/static_root/assets/settings-drawer-CdFmOhnd.f7dcd12b3ebc.js.br +0 -0
  376. codex/static_root/assets/settings-drawer-CdFmOhnd.f7dcd12b3ebc.js.gz +0 -0
  377. codex/static_root/assets/settings-drawer-CdFmOhnd.js +2 -0
  378. codex/static_root/assets/settings-drawer-CdFmOhnd.js.br +0 -0
  379. codex/static_root/assets/settings-drawer-CdFmOhnd.js.gz +0 -0
  380. codex/static_root/assets/settings-drawer-DMSsWF8c.75a6ea969e71.css +1 -0
  381. codex/static_root/assets/settings-drawer-DMSsWF8c.75a6ea969e71.css.br +0 -0
  382. codex/static_root/assets/settings-drawer-DMSsWF8c.75a6ea969e71.css.gz +0 -0
  383. codex/static_root/assets/settings-drawer-DMSsWF8c.css +1 -0
  384. codex/static_root/assets/settings-drawer-DMSsWF8c.css.br +0 -0
  385. codex/static_root/assets/settings-drawer-DMSsWF8c.css.gz +0 -0
  386. codex/static_root/assets/stats-tab-BzaipD0m.b6bf627ea860.js +1 -0
  387. codex/static_root/assets/stats-tab-BzaipD0m.b6bf627ea860.js.br +0 -0
  388. codex/static_root/assets/stats-tab-BzaipD0m.b6bf627ea860.js.gz +0 -0
  389. codex/static_root/assets/stats-tab-BzaipD0m.js +1 -0
  390. codex/static_root/assets/stats-tab-BzaipD0m.js.br +0 -0
  391. codex/static_root/assets/stats-tab-BzaipD0m.js.gz +0 -0
  392. codex/static_root/assets/{stats-tab-BAYTqQNg.5f715428c394.css → stats-tab-WvF2acoZ.9fdb0106124d.css} +1 -1
  393. codex/static_root/assets/stats-tab-WvF2acoZ.9fdb0106124d.css.br +0 -0
  394. codex/static_root/assets/stats-tab-WvF2acoZ.9fdb0106124d.css.gz +0 -0
  395. codex/static_root/assets/{stats-tab-BAYTqQNg.css → stats-tab-WvF2acoZ.css} +1 -1
  396. codex/static_root/assets/stats-tab-WvF2acoZ.css.br +0 -0
  397. codex/static_root/assets/stats-tab-WvF2acoZ.css.gz +0 -0
  398. codex/static_root/assets/task-tab-DCnS1sM9.44d8435b4989.js +1 -0
  399. codex/static_root/assets/task-tab-DCnS1sM9.44d8435b4989.js.br +0 -0
  400. codex/static_root/assets/task-tab-DCnS1sM9.44d8435b4989.js.gz +0 -0
  401. codex/static_root/assets/task-tab-DCnS1sM9.js +1 -0
  402. codex/static_root/assets/task-tab-DCnS1sM9.js.br +0 -0
  403. codex/static_root/assets/task-tab-DCnS1sM9.js.gz +0 -0
  404. codex/static_root/assets/task-tab-DfdUY9Rc.478e74041f80.css +1 -0
  405. codex/static_root/assets/{task-tab--cXi48kg.5dfd6890a1c2.css.br → task-tab-DfdUY9Rc.478e74041f80.css.br} +1 -1
  406. codex/static_root/assets/task-tab-DfdUY9Rc.478e74041f80.css.gz +0 -0
  407. codex/static_root/assets/task-tab-DfdUY9Rc.css +1 -0
  408. codex/static_root/assets/{task-tab--cXi48kg.css.br → task-tab-DfdUY9Rc.css.br} +1 -1
  409. codex/static_root/assets/task-tab-DfdUY9Rc.css.gz +0 -0
  410. codex/static_root/assets/unauthorized-CsSak07X.c5536d9dae75.css +1 -0
  411. codex/static_root/assets/unauthorized-CsSak07X.c5536d9dae75.css.br +0 -0
  412. codex/static_root/assets/unauthorized-CsSak07X.c5536d9dae75.css.gz +0 -0
  413. codex/static_root/assets/unauthorized-CsSak07X.css +1 -0
  414. codex/static_root/assets/unauthorized-CsSak07X.css.br +0 -0
  415. codex/static_root/assets/unauthorized-CsSak07X.css.gz +0 -0
  416. codex/static_root/assets/unauthorized-DJSr03Dw.7555cbcf1064.js +1 -0
  417. codex/static_root/assets/unauthorized-DJSr03Dw.7555cbcf1064.js.br +0 -0
  418. codex/static_root/assets/unauthorized-DJSr03Dw.7555cbcf1064.js.gz +0 -0
  419. codex/static_root/assets/unauthorized-DJSr03Dw.js +1 -0
  420. codex/static_root/assets/unauthorized-DJSr03Dw.js.br +0 -0
  421. codex/static_root/assets/unauthorized-DJSr03Dw.js.gz +0 -0
  422. codex/static_root/assets/user-tab-DAK_Deoh.1832877d449a.js +1 -0
  423. codex/static_root/assets/user-tab-DAK_Deoh.1832877d449a.js.br +0 -0
  424. codex/static_root/assets/user-tab-DAK_Deoh.1832877d449a.js.gz +0 -0
  425. codex/static_root/assets/user-tab-DAK_Deoh.js +1 -0
  426. codex/static_root/assets/user-tab-DAK_Deoh.js.br +0 -0
  427. codex/static_root/assets/user-tab-DAK_Deoh.js.gz +0 -0
  428. codex/static_root/manifest.cbc39bca88fc.json +735 -0
  429. codex/static_root/manifest.cbc39bca88fc.json.br +0 -0
  430. codex/static_root/manifest.cbc39bca88fc.json.gz +0 -0
  431. codex/static_root/manifest.json +389 -366
  432. codex/static_root/manifest.json.br +0 -0
  433. codex/static_root/manifest.json.gz +0 -0
  434. codex/static_root/staticfiles.json +1 -1
  435. codex/status_controller.py +9 -12
  436. codex/templates/index.html +1 -1
  437. codex/threads.py +3 -3
  438. codex/urls/api/admin.py +4 -3
  439. codex/urls/api/browser.py +10 -1
  440. codex/urls/api/reader.py +8 -4
  441. codex/urls/opds/v2.py +6 -0
  442. codex/urls/root.py +4 -3
  443. codex/util.py +11 -0
  444. codex/views/admin/api_key.py +1 -4
  445. codex/views/admin/flag.py +5 -1
  446. codex/views/admin/library.py +4 -4
  447. codex/views/admin/stats.py +10 -10
  448. codex/views/admin/tasks.py +9 -9
  449. codex/views/auth.py +3 -8
  450. codex/views/bookmark.py +53 -41
  451. codex/views/browser/annotate/bookmark.py +6 -4
  452. codex/views/browser/annotate/card.py +4 -21
  453. codex/views/browser/annotate/order.py +51 -25
  454. codex/views/browser/bookmark.py +53 -0
  455. codex/views/browser/breadcrumbs.py +6 -5
  456. codex/views/browser/browser.py +2 -2
  457. codex/views/browser/choices.py +6 -5
  458. codex/views/browser/cover.py +6 -3
  459. codex/views/browser/download.py +67 -0
  460. codex/views/browser/filters/bookmark.py +5 -33
  461. codex/views/browser/filters/field.py +1 -1
  462. codex/views/browser/filters/filter.py +6 -8
  463. codex/views/browser/filters/group.py +7 -4
  464. codex/views/browser/filters/search/field/expression.py +1 -2
  465. codex/views/browser/filters/search/field/optimize.py +1 -1
  466. codex/views/browser/filters/search/field/parse.py +2 -2
  467. codex/views/browser/filters/search/parse.py +4 -19
  468. codex/views/browser/group_mtime.py +3 -3
  469. codex/views/browser/metadata/annotate.py +1 -1
  470. codex/views/browser/metadata/copy_intersections.py +1 -1
  471. codex/views/browser/metadata/metadata.py +2 -2
  472. codex/views/browser/mtime.py +1 -1
  473. codex/views/browser/order_by.py +9 -6
  474. codex/views/browser/params.py +1 -1
  475. codex/views/browser/settings.py +1 -1
  476. codex/views/browser/validate.py +14 -7
  477. codex/views/const.py +0 -3
  478. codex/views/download.py +5 -5
  479. codex/views/frontend.py +20 -5
  480. codex/views/mixins.py +19 -30
  481. codex/views/opds/authentication_v1.py +1 -1
  482. codex/views/opds/const.py +6 -4
  483. codex/views/opds/util.py +5 -5
  484. codex/views/opds/v1/entry/entry.py +4 -2
  485. codex/views/opds/v1/entry/links.py +5 -7
  486. codex/views/opds/v1/facets.py +8 -4
  487. codex/views/opds/v1/feed.py +5 -5
  488. codex/views/opds/v1/links.py +11 -6
  489. codex/views/opds/v2/const.py +5 -2
  490. codex/views/opds/v2/feed.py +6 -5
  491. codex/views/opds/v2/href.py +60 -0
  492. codex/views/opds/v2/links.py +13 -47
  493. codex/views/opds/v2/progression.py +136 -0
  494. codex/views/opds/v2/publications.py +31 -21
  495. codex/views/opds/v2/top_links.py +2 -1
  496. codex/views/public.py +12 -5
  497. codex/views/reader/books.py +22 -10
  498. codex/views/reader/page.py +19 -14
  499. codex/views/reader/params.py +3 -3
  500. codex/views/reader/reader.py +6 -6
  501. codex/views/reader/settings.py +1 -1
  502. codex/views/session.py +10 -3
  503. codex/views/settings.py +2 -2
  504. codex/views/timezone.py +2 -2
  505. codex/views/util.py +10 -9
  506. codex/views/version.py +1 -1
  507. {codex-1.7.1.dist-info → codex-1.7.3.dist-info}/METADATA +23 -27
  508. codex-1.7.3.dist-info/RECORD +1031 -0
  509. {codex-1.7.1.dist-info → codex-1.7.3.dist-info}/WHEEL +1 -1
  510. codex/serializers/opds/v2.py +0 -178
  511. codex/static_root/assets/VCheckbox-Cf74Jfrq.2fbb5106ef5a.js +0 -1
  512. codex/static_root/assets/VCheckbox-Cf74Jfrq.2fbb5106ef5a.js.br +0 -0
  513. codex/static_root/assets/VCheckbox-Cf74Jfrq.2fbb5106ef5a.js.gz +0 -0
  514. codex/static_root/assets/VCheckbox-Cf74Jfrq.js +0 -1
  515. codex/static_root/assets/VCheckbox-Cf74Jfrq.js.br +0 -0
  516. codex/static_root/assets/VCheckbox-Cf74Jfrq.js.gz +0 -0
  517. codex/static_root/assets/VCheckboxBtn-D5jbIiqO.921713d268ba.js +0 -1
  518. codex/static_root/assets/VCheckboxBtn-D5jbIiqO.921713d268ba.js.br +0 -0
  519. codex/static_root/assets/VCheckboxBtn-D5jbIiqO.921713d268ba.js.gz +0 -0
  520. codex/static_root/assets/VCheckboxBtn-D5jbIiqO.js +0 -1
  521. codex/static_root/assets/VCheckboxBtn-D5jbIiqO.js.br +0 -0
  522. codex/static_root/assets/VCheckboxBtn-D5jbIiqO.js.gz +0 -0
  523. codex/static_root/assets/VCombobox-Dq3Y5j2w.8f4884677e5a.js +0 -1
  524. codex/static_root/assets/VCombobox-Dq3Y5j2w.8f4884677e5a.js.br +0 -0
  525. codex/static_root/assets/VCombobox-Dq3Y5j2w.8f4884677e5a.js.gz +0 -0
  526. codex/static_root/assets/VCombobox-Dq3Y5j2w.js +0 -1
  527. codex/static_root/assets/VCombobox-Dq3Y5j2w.js.br +0 -0
  528. codex/static_root/assets/VCombobox-Dq3Y5j2w.js.gz +0 -0
  529. codex/static_root/assets/VDialog-BVHV10WD.993b98f2be7f.js +0 -1
  530. codex/static_root/assets/VDialog-BVHV10WD.993b98f2be7f.js.br +0 -0
  531. codex/static_root/assets/VDialog-BVHV10WD.993b98f2be7f.js.gz +0 -0
  532. codex/static_root/assets/VDialog-BVHV10WD.js +0 -1
  533. codex/static_root/assets/VDialog-BVHV10WD.js.br +0 -0
  534. codex/static_root/assets/VDialog-BVHV10WD.js.gz +0 -0
  535. codex/static_root/assets/VDialog-CSvrKKb2.css.br +0 -0
  536. codex/static_root/assets/VDialog-CSvrKKb2.css.gz +0 -0
  537. codex/static_root/assets/VDialog-CSvrKKb2.fd4d50904b17.css.br +0 -0
  538. codex/static_root/assets/VDialog-CSvrKKb2.fd4d50904b17.css.gz +0 -0
  539. codex/static_root/assets/VExpansionPanels-BLAGU-dj.e244f3902cf9.js +0 -1
  540. codex/static_root/assets/VExpansionPanels-BLAGU-dj.e244f3902cf9.js.br +0 -0
  541. codex/static_root/assets/VExpansionPanels-BLAGU-dj.e244f3902cf9.js.gz +0 -0
  542. codex/static_root/assets/VExpansionPanels-BLAGU-dj.js +0 -1
  543. codex/static_root/assets/VExpansionPanels-BLAGU-dj.js.br +0 -0
  544. codex/static_root/assets/VExpansionPanels-BLAGU-dj.js.gz +0 -0
  545. codex/static_root/assets/VRadioGroup-Bnt5BbmK.826e1c2d9134.js +0 -1
  546. codex/static_root/assets/VRadioGroup-Bnt5BbmK.826e1c2d9134.js.br +0 -0
  547. codex/static_root/assets/VRadioGroup-Bnt5BbmK.826e1c2d9134.js.gz +0 -0
  548. codex/static_root/assets/VRadioGroup-Bnt5BbmK.js +0 -1
  549. codex/static_root/assets/VRadioGroup-Bnt5BbmK.js.br +0 -0
  550. codex/static_root/assets/VRadioGroup-Bnt5BbmK.js.gz +0 -0
  551. codex/static_root/assets/VSelect-BTo1ZM8U.ea4a7a7bbce9.js +0 -1
  552. codex/static_root/assets/VSelect-BTo1ZM8U.ea4a7a7bbce9.js.br +0 -0
  553. codex/static_root/assets/VSelect-BTo1ZM8U.ea4a7a7bbce9.js.gz +0 -0
  554. codex/static_root/assets/VSelect-BTo1ZM8U.js +0 -1
  555. codex/static_root/assets/VSelect-BTo1ZM8U.js.br +0 -0
  556. codex/static_root/assets/VSelect-BTo1ZM8U.js.gz +0 -0
  557. codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css +0 -1
  558. codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.br +0 -0
  559. codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.gz +0 -0
  560. codex/static_root/assets/VSelect-DLu8bpcs.css +0 -1
  561. codex/static_root/assets/VSelect-DLu8bpcs.css.br +0 -0
  562. codex/static_root/assets/VSelect-DLu8bpcs.css.gz +0 -0
  563. codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css +0 -1
  564. codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css.br +0 -0
  565. codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css.gz +0 -0
  566. codex/static_root/assets/VSelectionControl-CiViEYoC.css +0 -1
  567. codex/static_root/assets/VSelectionControl-CiViEYoC.css.br +0 -0
  568. codex/static_root/assets/VSelectionControl-CiViEYoC.css.gz +0 -0
  569. codex/static_root/assets/VSelectionControl-CrzLF2bD.965af5336c62.js +0 -1
  570. codex/static_root/assets/VSelectionControl-CrzLF2bD.965af5336c62.js.br +0 -0
  571. codex/static_root/assets/VSelectionControl-CrzLF2bD.965af5336c62.js.gz +0 -0
  572. codex/static_root/assets/VSelectionControl-CrzLF2bD.js +0 -1
  573. codex/static_root/assets/VSelectionControl-CrzLF2bD.js.br +0 -0
  574. codex/static_root/assets/VSelectionControl-CrzLF2bD.js.gz +0 -0
  575. codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css +0 -1
  576. codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.br +0 -0
  577. codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.gz +0 -0
  578. codex/static_root/assets/VSlideGroup-BtXPhMOT.css +0 -1
  579. codex/static_root/assets/VSlideGroup-BtXPhMOT.css.br +0 -0
  580. codex/static_root/assets/VSlideGroup-BtXPhMOT.css.gz +0 -0
  581. codex/static_root/assets/VSlideGroup-ZRALPG67.9807cdc6b330.js +0 -1
  582. codex/static_root/assets/VSlideGroup-ZRALPG67.9807cdc6b330.js.br +0 -0
  583. codex/static_root/assets/VSlideGroup-ZRALPG67.9807cdc6b330.js.gz +0 -0
  584. codex/static_root/assets/VSlideGroup-ZRALPG67.js +0 -1
  585. codex/static_root/assets/VSlideGroup-ZRALPG67.js.br +0 -0
  586. codex/static_root/assets/VSlideGroup-ZRALPG67.js.gz +0 -0
  587. codex/static_root/assets/VTable-Ci8_04Au.1382ab272e40.js +0 -1
  588. codex/static_root/assets/VTable-Ci8_04Au.1382ab272e40.js.br +0 -0
  589. codex/static_root/assets/VTable-Ci8_04Au.1382ab272e40.js.gz +0 -0
  590. codex/static_root/assets/VTable-Ci8_04Au.js +0 -1
  591. codex/static_root/assets/VTable-Ci8_04Au.js.br +0 -0
  592. codex/static_root/assets/VTable-Ci8_04Au.js.gz +0 -0
  593. codex/static_root/assets/VTextField-BnCEPZIq.b0c32b2c0b14.css +0 -1
  594. codex/static_root/assets/VTextField-BnCEPZIq.b0c32b2c0b14.css.br +0 -0
  595. codex/static_root/assets/VTextField-BnCEPZIq.b0c32b2c0b14.css.gz +0 -0
  596. codex/static_root/assets/VTextField-BnCEPZIq.css +0 -1
  597. codex/static_root/assets/VTextField-BnCEPZIq.css.br +0 -0
  598. codex/static_root/assets/VTextField-BnCEPZIq.css.gz +0 -0
  599. codex/static_root/assets/VTextField-D7pt5iJ3.c020691495b7.js +0 -1
  600. codex/static_root/assets/VTextField-D7pt5iJ3.c020691495b7.js.br +0 -0
  601. codex/static_root/assets/VTextField-D7pt5iJ3.c020691495b7.js.gz +0 -0
  602. codex/static_root/assets/VTextField-D7pt5iJ3.js +0 -1
  603. codex/static_root/assets/VTextField-D7pt5iJ3.js.br +0 -0
  604. codex/static_root/assets/VTextField-D7pt5iJ3.js.gz +0 -0
  605. codex/static_root/assets/VWindowItem-CGBsUHpV.7c57d79cf74a.js +0 -1
  606. codex/static_root/assets/VWindowItem-CGBsUHpV.7c57d79cf74a.js.br +0 -0
  607. codex/static_root/assets/VWindowItem-CGBsUHpV.7c57d79cf74a.js.gz +0 -0
  608. codex/static_root/assets/VWindowItem-CGBsUHpV.js +0 -1
  609. codex/static_root/assets/VWindowItem-CGBsUHpV.js.br +0 -0
  610. codex/static_root/assets/VWindowItem-CGBsUHpV.js.gz +0 -0
  611. codex/static_root/assets/admin-BTXUbxw5.23e0d3602f29.js +0 -1
  612. codex/static_root/assets/admin-BTXUbxw5.23e0d3602f29.js.br +0 -0
  613. codex/static_root/assets/admin-BTXUbxw5.23e0d3602f29.js.gz +0 -0
  614. codex/static_root/assets/admin-BTXUbxw5.js +0 -1
  615. codex/static_root/assets/admin-BTXUbxw5.js.br +0 -0
  616. codex/static_root/assets/admin-BTXUbxw5.js.gz +0 -0
  617. codex/static_root/assets/admin-DJ7pIXDQ.css +0 -1
  618. codex/static_root/assets/admin-DJ7pIXDQ.css.br +0 -0
  619. codex/static_root/assets/admin-DJ7pIXDQ.css.gz +0 -0
  620. codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css +0 -1
  621. codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.br +0 -0
  622. codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.gz +0 -0
  623. codex/static_root/assets/admin-menu-Dbt1Rajw.043fb778ba6c.js +0 -1
  624. codex/static_root/assets/admin-menu-Dbt1Rajw.043fb778ba6c.js.br +0 -0
  625. codex/static_root/assets/admin-menu-Dbt1Rajw.043fb778ba6c.js.gz +0 -0
  626. codex/static_root/assets/admin-menu-Dbt1Rajw.js +0 -1
  627. codex/static_root/assets/admin-menu-Dbt1Rajw.js.br +0 -0
  628. codex/static_root/assets/admin-menu-Dbt1Rajw.js.gz +0 -0
  629. codex/static_root/assets/admin-settings-button-progress-DSOZWzf1.fad596375b9b.js +0 -1
  630. codex/static_root/assets/admin-settings-button-progress-DSOZWzf1.fad596375b9b.js.br +0 -0
  631. codex/static_root/assets/admin-settings-button-progress-DSOZWzf1.fad596375b9b.js.gz +0 -0
  632. codex/static_root/assets/admin-settings-button-progress-DSOZWzf1.js +0 -1
  633. codex/static_root/assets/admin-settings-button-progress-DSOZWzf1.js.br +0 -0
  634. codex/static_root/assets/admin-settings-button-progress-DSOZWzf1.js.gz +0 -0
  635. codex/static_root/assets/browser-3Sm5qvA_.188da1350ec3.css +0 -1
  636. codex/static_root/assets/browser-3Sm5qvA_.188da1350ec3.css.br +0 -0
  637. codex/static_root/assets/browser-3Sm5qvA_.188da1350ec3.css.gz +0 -0
  638. codex/static_root/assets/browser-3Sm5qvA_.css +0 -1
  639. codex/static_root/assets/browser-3Sm5qvA_.css.br +0 -0
  640. codex/static_root/assets/browser-3Sm5qvA_.css.gz +0 -0
  641. codex/static_root/assets/browser-Dq-fQLJF.2e88354a9574.js +0 -1
  642. codex/static_root/assets/browser-Dq-fQLJF.2e88354a9574.js.br +0 -0
  643. codex/static_root/assets/browser-Dq-fQLJF.2e88354a9574.js.gz +0 -0
  644. codex/static_root/assets/browser-Dq-fQLJF.js +0 -1
  645. codex/static_root/assets/browser-Dq-fQLJF.js.br +0 -0
  646. codex/static_root/assets/browser-Dq-fQLJF.js.gz +0 -0
  647. codex/static_root/assets/change-password-dialog-BaGA_bnX.af8ea11b1579.js +0 -1
  648. codex/static_root/assets/change-password-dialog-BaGA_bnX.af8ea11b1579.js.br +0 -0
  649. codex/static_root/assets/change-password-dialog-BaGA_bnX.af8ea11b1579.js.gz +0 -0
  650. codex/static_root/assets/change-password-dialog-BaGA_bnX.js +0 -1
  651. codex/static_root/assets/change-password-dialog-BaGA_bnX.js.br +0 -0
  652. codex/static_root/assets/change-password-dialog-BaGA_bnX.js.gz +0 -0
  653. codex/static_root/assets/change-password-dialog-DrIXdKUC.217574b45b02.css +0 -1
  654. codex/static_root/assets/change-password-dialog-DrIXdKUC.217574b45b02.css.br +0 -0
  655. codex/static_root/assets/change-password-dialog-DrIXdKUC.217574b45b02.css.gz +0 -0
  656. codex/static_root/assets/change-password-dialog-DrIXdKUC.css +0 -1
  657. codex/static_root/assets/change-password-dialog-DrIXdKUC.css.br +0 -0
  658. codex/static_root/assets/change-password-dialog-DrIXdKUC.css.gz +0 -0
  659. codex/static_root/assets/confirm-dialog-B7w6z2rf.472011c06253.css +0 -1
  660. codex/static_root/assets/confirm-dialog-B7w6z2rf.css +0 -1
  661. codex/static_root/assets/confirm-dialog-X14gSw1w.21504f7c1db4.js +0 -1
  662. codex/static_root/assets/confirm-dialog-X14gSw1w.21504f7c1db4.js.br +0 -0
  663. codex/static_root/assets/confirm-dialog-X14gSw1w.21504f7c1db4.js.gz +0 -0
  664. codex/static_root/assets/confirm-dialog-X14gSw1w.js +0 -1
  665. codex/static_root/assets/confirm-dialog-X14gSw1w.js.br +0 -0
  666. codex/static_root/assets/confirm-dialog-X14gSw1w.js.gz +0 -0
  667. codex/static_root/assets/datetime-column-BN2Ulei5.a31061d3729c.js +0 -1
  668. codex/static_root/assets/datetime-column-BN2Ulei5.a31061d3729c.js.br +0 -0
  669. codex/static_root/assets/datetime-column-BN2Ulei5.a31061d3729c.js.gz +0 -0
  670. codex/static_root/assets/datetime-column-BN2Ulei5.js +0 -1
  671. codex/static_root/assets/datetime-column-BN2Ulei5.js.br +0 -0
  672. codex/static_root/assets/datetime-column-BN2Ulei5.js.gz +0 -0
  673. codex/static_root/assets/filter-CnO_WiBE.4044b9091aae.js.br +0 -0
  674. codex/static_root/assets/filter-CnO_WiBE.4044b9091aae.js.gz +0 -0
  675. codex/static_root/assets/filter-CnO_WiBE.js.br +0 -0
  676. codex/static_root/assets/filter-CnO_WiBE.js.gz +0 -0
  677. codex/static_root/assets/flag-tab-C5NP3j6O.1c692a00884d.js +0 -1
  678. codex/static_root/assets/flag-tab-C5NP3j6O.1c692a00884d.js.br +0 -0
  679. codex/static_root/assets/flag-tab-C5NP3j6O.1c692a00884d.js.gz +0 -0
  680. codex/static_root/assets/flag-tab-C5NP3j6O.js +0 -1
  681. codex/static_root/assets/flag-tab-C5NP3j6O.js.br +0 -0
  682. codex/static_root/assets/flag-tab-C5NP3j6O.js.gz +0 -0
  683. codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css +0 -1
  684. codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.br +0 -0
  685. codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.gz +0 -0
  686. codex/static_root/assets/flag-tab-CqWovuBu.css +0 -1
  687. codex/static_root/assets/flag-tab-CqWovuBu.css.br +0 -0
  688. codex/static_root/assets/flag-tab-CqWovuBu.css.gz +0 -0
  689. codex/static_root/assets/group-tab-Cq4QjmHS.a9d15dac0289.js +0 -1
  690. codex/static_root/assets/group-tab-Cq4QjmHS.a9d15dac0289.js.br +0 -0
  691. codex/static_root/assets/group-tab-Cq4QjmHS.a9d15dac0289.js.gz +0 -0
  692. codex/static_root/assets/group-tab-Cq4QjmHS.js +0 -1
  693. codex/static_root/assets/group-tab-Cq4QjmHS.js.br +0 -0
  694. codex/static_root/assets/group-tab-Cq4QjmHS.js.gz +0 -0
  695. codex/static_root/assets/http-error-DGFbgQC5.da17e7b6d980.js +0 -1
  696. codex/static_root/assets/http-error-DGFbgQC5.da17e7b6d980.js.br +0 -0
  697. codex/static_root/assets/http-error-DGFbgQC5.da17e7b6d980.js.gz +0 -0
  698. codex/static_root/assets/http-error-DGFbgQC5.js +0 -1
  699. codex/static_root/assets/http-error-DGFbgQC5.js.br +0 -0
  700. codex/static_root/assets/http-error-DGFbgQC5.js.gz +0 -0
  701. codex/static_root/assets/http-error-DKulXuTl.95e42988d5d5.css +0 -1
  702. codex/static_root/assets/http-error-DKulXuTl.95e42988d5d5.css.br +0 -0
  703. codex/static_root/assets/http-error-DKulXuTl.95e42988d5d5.css.gz +0 -0
  704. codex/static_root/assets/http-error-DKulXuTl.css +0 -1
  705. codex/static_root/assets/http-error-DKulXuTl.css.br +0 -0
  706. codex/static_root/assets/http-error-DKulXuTl.css.gz +0 -0
  707. codex/static_root/assets/index-BI-1EK3Q.51e5dd220639.js +0 -1
  708. codex/static_root/assets/index-BI-1EK3Q.51e5dd220639.js.br +0 -0
  709. codex/static_root/assets/index-BI-1EK3Q.51e5dd220639.js.gz +0 -0
  710. codex/static_root/assets/index-BI-1EK3Q.js +0 -1
  711. codex/static_root/assets/index-BI-1EK3Q.js.br +0 -0
  712. codex/static_root/assets/index-BI-1EK3Q.js.gz +0 -0
  713. codex/static_root/assets/library-tab-Wew8YOLv.0c1780a6b68e.css +0 -1
  714. codex/static_root/assets/library-tab-Wew8YOLv.0c1780a6b68e.css.br +0 -0
  715. codex/static_root/assets/library-tab-Wew8YOLv.0c1780a6b68e.css.gz +0 -0
  716. codex/static_root/assets/library-tab-Wew8YOLv.css +0 -1
  717. codex/static_root/assets/library-tab-Wew8YOLv.css.br +0 -0
  718. codex/static_root/assets/library-tab-Wew8YOLv.css.gz +0 -0
  719. codex/static_root/assets/library-tab-woA1HyfN.acfc4f327913.js +0 -1
  720. codex/static_root/assets/library-tab-woA1HyfN.acfc4f327913.js.br +0 -0
  721. codex/static_root/assets/library-tab-woA1HyfN.acfc4f327913.js.gz +0 -0
  722. codex/static_root/assets/library-tab-woA1HyfN.js +0 -1
  723. codex/static_root/assets/library-tab-woA1HyfN.js.br +0 -0
  724. codex/static_root/assets/library-tab-woA1HyfN.js.gz +0 -0
  725. codex/static_root/assets/main-Ed96tESk.7777498eb960.js +0 -35
  726. codex/static_root/assets/main-Ed96tESk.7777498eb960.js.br +0 -0
  727. codex/static_root/assets/main-Ed96tESk.7777498eb960.js.gz +0 -0
  728. codex/static_root/assets/main-Ed96tESk.js +0 -35
  729. codex/static_root/assets/main-Ed96tESk.js.br +0 -0
  730. codex/static_root/assets/main-Ed96tESk.js.gz +0 -0
  731. codex/static_root/assets/pager-full-pdf-DpxPZAZR.ec23b0e50b95.js +0 -1
  732. codex/static_root/assets/pager-full-pdf-DpxPZAZR.ec23b0e50b95.js.br +0 -0
  733. codex/static_root/assets/pager-full-pdf-DpxPZAZR.ec23b0e50b95.js.gz +0 -0
  734. codex/static_root/assets/pager-full-pdf-DpxPZAZR.js +0 -1
  735. codex/static_root/assets/pager-full-pdf-DpxPZAZR.js.br +0 -0
  736. codex/static_root/assets/pager-full-pdf-DpxPZAZR.js.gz +0 -0
  737. codex/static_root/assets/pagination-toolbar-Bz5nEUwa.d01b9cf3ab5e.js +0 -1
  738. codex/static_root/assets/pagination-toolbar-Bz5nEUwa.d01b9cf3ab5e.js.br +0 -0
  739. codex/static_root/assets/pagination-toolbar-Bz5nEUwa.d01b9cf3ab5e.js.gz +0 -0
  740. codex/static_root/assets/pagination-toolbar-Bz5nEUwa.js +0 -1
  741. codex/static_root/assets/pagination-toolbar-Bz5nEUwa.js.br +0 -0
  742. codex/static_root/assets/pagination-toolbar-Bz5nEUwa.js.gz +0 -0
  743. codex/static_root/assets/pagination-toolbar-DGrxp2OD.css +0 -1
  744. codex/static_root/assets/pagination-toolbar-DGrxp2OD.css.br +0 -0
  745. codex/static_root/assets/pagination-toolbar-DGrxp2OD.css.gz +0 -0
  746. codex/static_root/assets/pagination-toolbar-DGrxp2OD.f960a624f04f.css +0 -1
  747. codex/static_root/assets/pagination-toolbar-DGrxp2OD.f960a624f04f.css.br +0 -0
  748. codex/static_root/assets/pagination-toolbar-DGrxp2OD.f960a624f04f.css.gz +0 -0
  749. codex/static_root/assets/pdf-doc-6j4uJzw7.59963079f1ec.js +0 -305
  750. codex/static_root/assets/pdf-doc-6j4uJzw7.59963079f1ec.js.br +0 -0
  751. codex/static_root/assets/pdf-doc-6j4uJzw7.59963079f1ec.js.gz +0 -0
  752. codex/static_root/assets/pdf-doc-6j4uJzw7.js +0 -305
  753. codex/static_root/assets/pdf-doc-6j4uJzw7.js.br +0 -0
  754. codex/static_root/assets/pdf-doc-6j4uJzw7.js.gz +0 -0
  755. codex/static_root/assets/reader-DAyPkkSs.0f54806aed4b.js +0 -2
  756. codex/static_root/assets/reader-DAyPkkSs.0f54806aed4b.js.br +0 -0
  757. codex/static_root/assets/reader-DAyPkkSs.0f54806aed4b.js.gz +0 -0
  758. codex/static_root/assets/reader-DAyPkkSs.js +0 -2
  759. codex/static_root/assets/reader-DAyPkkSs.js.br +0 -0
  760. codex/static_root/assets/reader-DAyPkkSs.js.gz +0 -0
  761. codex/static_root/assets/reader-nD70BeEz.06e85e73c391.css +0 -1
  762. codex/static_root/assets/reader-nD70BeEz.06e85e73c391.css.br +0 -0
  763. codex/static_root/assets/reader-nD70BeEz.06e85e73c391.css.gz +0 -0
  764. codex/static_root/assets/reader-nD70BeEz.css +0 -1
  765. codex/static_root/assets/reader-nD70BeEz.css.br +0 -0
  766. codex/static_root/assets/reader-nD70BeEz.css.gz +0 -0
  767. codex/static_root/assets/relation-chips-DUOduJmS.8b39d35f8503.js +0 -1
  768. codex/static_root/assets/relation-chips-DUOduJmS.8b39d35f8503.js.br +0 -0
  769. codex/static_root/assets/relation-chips-DUOduJmS.8b39d35f8503.js.gz +0 -0
  770. codex/static_root/assets/relation-chips-DUOduJmS.js +0 -1
  771. codex/static_root/assets/relation-chips-DUOduJmS.js.br +0 -0
  772. codex/static_root/assets/relation-chips-DUOduJmS.js.gz +0 -0
  773. codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css +0 -1
  774. codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css.br +0 -0
  775. codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css.gz +0 -0
  776. codex/static_root/assets/settings-drawer-DKncO_vX.css +0 -1
  777. codex/static_root/assets/settings-drawer-DKncO_vX.css.br +0 -0
  778. codex/static_root/assets/settings-drawer-DKncO_vX.css.gz +0 -0
  779. codex/static_root/assets/settings-drawer-lRimDTyf.054f1f057cee.js +0 -2
  780. codex/static_root/assets/settings-drawer-lRimDTyf.054f1f057cee.js.br +0 -0
  781. codex/static_root/assets/settings-drawer-lRimDTyf.054f1f057cee.js.gz +0 -0
  782. codex/static_root/assets/settings-drawer-lRimDTyf.js +0 -2
  783. codex/static_root/assets/settings-drawer-lRimDTyf.js.br +0 -0
  784. codex/static_root/assets/settings-drawer-lRimDTyf.js.gz +0 -0
  785. codex/static_root/assets/stats-tab-BAYTqQNg.5f715428c394.css.br +0 -0
  786. codex/static_root/assets/stats-tab-BAYTqQNg.5f715428c394.css.gz +0 -0
  787. codex/static_root/assets/stats-tab-BAYTqQNg.css.br +0 -0
  788. codex/static_root/assets/stats-tab-BAYTqQNg.css.gz +0 -0
  789. codex/static_root/assets/stats-tab-Cyli0TxY.f9af7d3387d9.js +0 -1
  790. codex/static_root/assets/stats-tab-Cyli0TxY.f9af7d3387d9.js.br +0 -0
  791. codex/static_root/assets/stats-tab-Cyli0TxY.f9af7d3387d9.js.gz +0 -0
  792. codex/static_root/assets/stats-tab-Cyli0TxY.js +0 -1
  793. codex/static_root/assets/stats-tab-Cyli0TxY.js.br +0 -0
  794. codex/static_root/assets/stats-tab-Cyli0TxY.js.gz +0 -0
  795. codex/static_root/assets/task-tab--cXi48kg.5dfd6890a1c2.css +0 -1
  796. codex/static_root/assets/task-tab--cXi48kg.5dfd6890a1c2.css.gz +0 -0
  797. codex/static_root/assets/task-tab--cXi48kg.css +0 -1
  798. codex/static_root/assets/task-tab--cXi48kg.css.gz +0 -0
  799. codex/static_root/assets/task-tab-CrRRKMNo.52cc73a5889d.js +0 -1
  800. codex/static_root/assets/task-tab-CrRRKMNo.52cc73a5889d.js.br +0 -0
  801. codex/static_root/assets/task-tab-CrRRKMNo.52cc73a5889d.js.gz +0 -0
  802. codex/static_root/assets/task-tab-CrRRKMNo.js +0 -1
  803. codex/static_root/assets/task-tab-CrRRKMNo.js.br +0 -0
  804. codex/static_root/assets/task-tab-CrRRKMNo.js.gz +0 -0
  805. codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css +0 -1
  806. codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.br +0 -4
  807. codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.gz +0 -0
  808. codex/static_root/assets/transition-5LRFTPo5.css +0 -1
  809. codex/static_root/assets/transition-5LRFTPo5.css.br +0 -4
  810. codex/static_root/assets/transition-5LRFTPo5.css.gz +0 -0
  811. codex/static_root/assets/transition-CyIqQdeu.7496bae455dc.js +0 -1
  812. codex/static_root/assets/transition-CyIqQdeu.7496bae455dc.js.br +0 -0
  813. codex/static_root/assets/transition-CyIqQdeu.7496bae455dc.js.gz +0 -0
  814. codex/static_root/assets/transition-CyIqQdeu.js +0 -1
  815. codex/static_root/assets/transition-CyIqQdeu.js.br +0 -0
  816. codex/static_root/assets/transition-CyIqQdeu.js.gz +0 -0
  817. codex/static_root/assets/unauthorized-BjhIc97q.728511c92cd0.css +0 -1
  818. codex/static_root/assets/unauthorized-BjhIc97q.728511c92cd0.css.br +0 -0
  819. codex/static_root/assets/unauthorized-BjhIc97q.728511c92cd0.css.gz +0 -0
  820. codex/static_root/assets/unauthorized-BjhIc97q.css +0 -1
  821. codex/static_root/assets/unauthorized-BjhIc97q.css.br +0 -0
  822. codex/static_root/assets/unauthorized-BjhIc97q.css.gz +0 -0
  823. codex/static_root/assets/unauthorized-IWC3QdqX.1d5d2dafa046.js +0 -1
  824. codex/static_root/assets/unauthorized-IWC3QdqX.1d5d2dafa046.js.br +0 -0
  825. codex/static_root/assets/unauthorized-IWC3QdqX.1d5d2dafa046.js.gz +0 -0
  826. codex/static_root/assets/unauthorized-IWC3QdqX.js +0 -1
  827. codex/static_root/assets/unauthorized-IWC3QdqX.js.br +0 -0
  828. codex/static_root/assets/unauthorized-IWC3QdqX.js.gz +0 -0
  829. codex/static_root/assets/user-tab-Bt7BG8Ih.8f797a19b7ae.js +0 -1
  830. codex/static_root/assets/user-tab-Bt7BG8Ih.8f797a19b7ae.js.br +0 -0
  831. codex/static_root/assets/user-tab-Bt7BG8Ih.8f797a19b7ae.js.gz +0 -0
  832. codex/static_root/assets/user-tab-Bt7BG8Ih.js +0 -1
  833. codex/static_root/assets/user-tab-Bt7BG8Ih.js.br +0 -0
  834. codex/static_root/assets/user-tab-Bt7BG8Ih.js.gz +0 -0
  835. codex/static_root/manifest.dbf5ed7a4b40.json +0 -712
  836. codex/static_root/manifest.dbf5ed7a4b40.json.br +0 -0
  837. codex/static_root/manifest.dbf5ed7a4b40.json.gz +0 -0
  838. codex-1.7.1.dist-info/RECORD +0 -1012
  839. /codex/static_root/assets/{VCheckbox-CMKdyl0R.016ed8d222c4.css → VCheckbox-CvH8ekHL.016ed8d222c4.css} +0 -0
  840. /codex/static_root/assets/{VCheckbox-CMKdyl0R.016ed8d222c4.css.br → VCheckbox-CvH8ekHL.016ed8d222c4.css.br} +0 -0
  841. /codex/static_root/assets/{VCheckbox-CMKdyl0R.016ed8d222c4.css.gz → VCheckbox-CvH8ekHL.016ed8d222c4.css.gz} +0 -0
  842. /codex/static_root/assets/{VCheckbox-CMKdyl0R.css → VCheckbox-CvH8ekHL.css} +0 -0
  843. /codex/static_root/assets/{VCheckbox-CMKdyl0R.css.br → VCheckbox-CvH8ekHL.css.br} +0 -0
  844. /codex/static_root/assets/{VCheckbox-CMKdyl0R.css.gz → VCheckbox-CvH8ekHL.css.gz} +0 -0
  845. /codex/static_root/assets/{VCombobox-bwEYrXCg.9f25a34994e2.css → VCombobox-BQHELb_o.9f25a34994e2.css} +0 -0
  846. /codex/static_root/assets/{VCombobox-bwEYrXCg.9f25a34994e2.css.br → VCombobox-BQHELb_o.9f25a34994e2.css.br} +0 -0
  847. /codex/static_root/assets/{VCombobox-bwEYrXCg.9f25a34994e2.css.gz → VCombobox-BQHELb_o.9f25a34994e2.css.gz} +0 -0
  848. /codex/static_root/assets/{VCombobox-bwEYrXCg.css → VCombobox-BQHELb_o.css} +0 -0
  849. /codex/static_root/assets/{VCombobox-bwEYrXCg.css.br → VCombobox-BQHELb_o.css.br} +0 -0
  850. /codex/static_root/assets/{VCombobox-bwEYrXCg.css.gz → VCombobox-BQHELb_o.css.gz} +0 -0
  851. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.5b17872981df.css → VExpansionPanels-RsCANmDP.5b17872981df.css} +0 -0
  852. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.5b17872981df.css.br → VExpansionPanels-RsCANmDP.5b17872981df.css.br} +0 -0
  853. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.5b17872981df.css.gz → VExpansionPanels-RsCANmDP.5b17872981df.css.gz} +0 -0
  854. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.css → VExpansionPanels-RsCANmDP.css} +0 -0
  855. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.css.br → VExpansionPanels-RsCANmDP.css.br} +0 -0
  856. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.css.gz → VExpansionPanels-RsCANmDP.css.gz} +0 -0
  857. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.8e3741381961.css → VRadioGroup-Cp9mZ7cb.8e3741381961.css} +0 -0
  858. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.8e3741381961.css.br → VRadioGroup-Cp9mZ7cb.8e3741381961.css.br} +0 -0
  859. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.8e3741381961.css.gz → VRadioGroup-Cp9mZ7cb.8e3741381961.css.gz} +0 -0
  860. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.css → VRadioGroup-Cp9mZ7cb.css} +0 -0
  861. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.css.br → VRadioGroup-Cp9mZ7cb.css.br} +0 -0
  862. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.css.gz → VRadioGroup-Cp9mZ7cb.css.gz} +0 -0
  863. /codex/static_root/assets/{VTable-Y5Sc3hJd.c36f0a6a30cf.css → VTable-BnxSZ_W5.c36f0a6a30cf.css} +0 -0
  864. /codex/static_root/assets/{VTable-Y5Sc3hJd.c36f0a6a30cf.css.br → VTable-BnxSZ_W5.c36f0a6a30cf.css.br} +0 -0
  865. /codex/static_root/assets/{VTable-Y5Sc3hJd.c36f0a6a30cf.css.gz → VTable-BnxSZ_W5.c36f0a6a30cf.css.gz} +0 -0
  866. /codex/static_root/assets/{VTable-Y5Sc3hJd.css → VTable-BnxSZ_W5.css} +0 -0
  867. /codex/static_root/assets/{VTable-Y5Sc3hJd.css.br → VTable-BnxSZ_W5.css.br} +0 -0
  868. /codex/static_root/assets/{VTable-Y5Sc3hJd.css.gz → VTable-BnxSZ_W5.css.gz} +0 -0
  869. /codex/static_root/assets/{VWindowItem-ByIod57Y.css → VWindowItem-CWBhiE_Y.css} +0 -0
  870. /codex/static_root/assets/{VWindowItem-ByIod57Y.css.br → VWindowItem-CWBhiE_Y.css.br} +0 -0
  871. /codex/static_root/assets/{VWindowItem-ByIod57Y.css.gz → VWindowItem-CWBhiE_Y.css.gz} +0 -0
  872. /codex/static_root/assets/{VWindowItem-ByIod57Y.f7fb19752bf3.css → VWindowItem-CWBhiE_Y.f7fb19752bf3.css} +0 -0
  873. /codex/static_root/assets/{VWindowItem-ByIod57Y.f7fb19752bf3.css.br → VWindowItem-CWBhiE_Y.f7fb19752bf3.css.br} +0 -0
  874. /codex/static_root/assets/{VWindowItem-ByIod57Y.f7fb19752bf3.css.gz → VWindowItem-CWBhiE_Y.f7fb19752bf3.css.gz} +0 -0
  875. /codex/static_root/assets/{admin-menu-B9bzD6hV.c13b7df2ff57.css → admin-menu-B3iXsOyy.c13b7df2ff57.css} +0 -0
  876. /codex/static_root/assets/{admin-menu-B9bzD6hV.c13b7df2ff57.css.br → admin-menu-B3iXsOyy.c13b7df2ff57.css.br} +0 -0
  877. /codex/static_root/assets/{admin-menu-B9bzD6hV.c13b7df2ff57.css.gz → admin-menu-B3iXsOyy.c13b7df2ff57.css.gz} +0 -0
  878. /codex/static_root/assets/{admin-menu-B9bzD6hV.css → admin-menu-B3iXsOyy.css} +0 -0
  879. /codex/static_root/assets/{admin-menu-B9bzD6hV.css.br → admin-menu-B3iXsOyy.css.br} +0 -0
  880. /codex/static_root/assets/{admin-menu-B9bzD6hV.css.gz → admin-menu-B3iXsOyy.css.gz} +0 -0
  881. /codex/static_root/assets/{admin-settings-button-progress-DUUQfVsZ.2548c49a853e.css → admin-settings-button-progress-BGB22oTD.2548c49a853e.css} +0 -0
  882. /codex/static_root/assets/{admin-settings-button-progress-DUUQfVsZ.css → admin-settings-button-progress-BGB22oTD.css} +0 -0
  883. /codex/static_root/assets/{datetime-column-DeCthByU.1f3bf499e063.css → datetime-column-BavtvLnf.1f3bf499e063.css} +0 -0
  884. /codex/static_root/assets/{datetime-column-DeCthByU.css → datetime-column-BavtvLnf.css} +0 -0
  885. /codex/static_root/assets/{group-tab-DkIN1Heu.948e907b1e6b.css → group-tab-_vKWzoyd.948e907b1e6b.css} +0 -0
  886. /codex/static_root/assets/{group-tab-DkIN1Heu.948e907b1e6b.css.br → group-tab-_vKWzoyd.948e907b1e6b.css.br} +0 -0
  887. /codex/static_root/assets/{group-tab-DkIN1Heu.948e907b1e6b.css.gz → group-tab-_vKWzoyd.948e907b1e6b.css.gz} +0 -0
  888. /codex/static_root/assets/{group-tab-DkIN1Heu.css → group-tab-_vKWzoyd.css} +0 -0
  889. /codex/static_root/assets/{group-tab-DkIN1Heu.css.br → group-tab-_vKWzoyd.css.br} +0 -0
  890. /codex/static_root/assets/{group-tab-DkIN1Heu.css.gz → group-tab-_vKWzoyd.css.gz} +0 -0
  891. /codex/static_root/assets/{index-CL_6g4tJ.523d7b3d350f.css → index-BHXJTQ4V.523d7b3d350f.css} +0 -0
  892. /codex/static_root/assets/{index-CL_6g4tJ.523d7b3d350f.css.br → index-BHXJTQ4V.523d7b3d350f.css.br} +0 -0
  893. /codex/static_root/assets/{index-CL_6g4tJ.523d7b3d350f.css.gz → index-BHXJTQ4V.523d7b3d350f.css.gz} +0 -0
  894. /codex/static_root/assets/{index-CL_6g4tJ.css → index-BHXJTQ4V.css} +0 -0
  895. /codex/static_root/assets/{index-CL_6g4tJ.css.br → index-BHXJTQ4V.css.br} +0 -0
  896. /codex/static_root/assets/{index-CL_6g4tJ.css.gz → index-BHXJTQ4V.css.gz} +0 -0
  897. /codex/static_root/assets/{main-BZ73p_WW.css → main-K8cER0IH.css} +0 -0
  898. /codex/static_root/assets/{main-BZ73p_WW.css.br → main-K8cER0IH.css.br} +0 -0
  899. /codex/static_root/assets/{main-BZ73p_WW.css.gz → main-K8cER0IH.css.gz} +0 -0
  900. /codex/static_root/assets/{main-BZ73p_WW.d529e8b3f52a.css → main-K8cER0IH.d529e8b3f52a.css} +0 -0
  901. /codex/static_root/assets/{main-BZ73p_WW.d529e8b3f52a.css.br → main-K8cER0IH.d529e8b3f52a.css.br} +0 -0
  902. /codex/static_root/assets/{main-BZ73p_WW.d529e8b3f52a.css.gz → main-K8cER0IH.d529e8b3f52a.css.gz} +0 -0
  903. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.b94aac7e3313.css → pdf-doc-B4cGW_Hl.b94aac7e3313.css} +0 -0
  904. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.b94aac7e3313.css.br → pdf-doc-B4cGW_Hl.b94aac7e3313.css.br} +0 -0
  905. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.b94aac7e3313.css.gz → pdf-doc-B4cGW_Hl.b94aac7e3313.css.gz} +0 -0
  906. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.css → pdf-doc-B4cGW_Hl.css} +0 -0
  907. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.css.br → pdf-doc-B4cGW_Hl.css.br} +0 -0
  908. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.css.gz → pdf-doc-B4cGW_Hl.css.gz} +0 -0
  909. /codex/static_root/assets/{relation-chips-ByfWwuQc.01269a188e01.css → relation-chips-DpbzrZxT.01269a188e01.css} +0 -0
  910. /codex/static_root/assets/{relation-chips-ByfWwuQc.01269a188e01.css.br → relation-chips-DpbzrZxT.01269a188e01.css.br} +0 -0
  911. /codex/static_root/assets/{relation-chips-ByfWwuQc.01269a188e01.css.gz → relation-chips-DpbzrZxT.01269a188e01.css.gz} +0 -0
  912. /codex/static_root/assets/{relation-chips-ByfWwuQc.css → relation-chips-DpbzrZxT.css} +0 -0
  913. /codex/static_root/assets/{relation-chips-ByfWwuQc.css.br → relation-chips-DpbzrZxT.css.br} +0 -0
  914. /codex/static_root/assets/{relation-chips-ByfWwuQc.css.gz → relation-chips-DpbzrZxT.css.gz} +0 -0
  915. {codex-1.7.1.dist-info → codex-1.7.3.dist-info}/LICENSE +0 -0
  916. {codex-1.7.1.dist-info → codex-1.7.3.dist-info}/entry_points.txt +0 -0
@@ -105,7 +105,7 @@ class RootTopLinks:
105
105
  class OPDS1LinksView(OPDS1FacetsView):
106
106
  """OPDS 1 Links methods."""
107
107
 
108
- # overwritten in get_object()
108
+ # overwritten in get_object method
109
109
  DEFAULT_ROUTE = MappingProxyType(
110
110
  {
111
111
  **OPDS1FacetsView.DEFAULT_ROUTE,
@@ -143,7 +143,7 @@ class OPDS1LinksView(OPDS1FacetsView):
143
143
  def _root_links(self):
144
144
  """Navigation Root Links."""
145
145
  links = []
146
- if up_route := self.get_last_route():
146
+ if up_route := self.get_last_route(name=True):
147
147
  links += [self._link(up_route, Rel.UP)]
148
148
  page = self.kwargs.get("page", 1)
149
149
  if page > 1:
@@ -179,7 +179,7 @@ class OPDS1LinksView(OPDS1FacetsView):
179
179
  for top_link in TopLinks.ALL + RootTopLinks.ALL:
180
180
  if not self.is_top_link_displayed(top_link):
181
181
  links += [self._top_link(top_link)]
182
- if facets := self.facets():
182
+ if facets := self.facets(entries=False, root=True):
183
183
  links += facets
184
184
  except Exception:
185
185
  LOG.exception("Getting OPDS v1 links")
@@ -194,11 +194,16 @@ class OPDS1LinksView(OPDS1FacetsView):
194
194
  name=name,
195
195
  summary=top_link.desc,
196
196
  )
197
- zero_pad: int = self.obj["zero_pad"] # type: ignore
197
+ zero_pad: int = self.obj["zero_pad"]
198
198
  data = OPDS1EntryData(
199
- self.opds_acquisition_groups, zero_pad, False, self.mime_type_map
199
+ self.opds_acquisition_groups,
200
+ zero_pad,
201
+ metadata=False,
202
+ mime_type_map=self.mime_type_map,
203
+ )
204
+ return OPDS1Entry(
205
+ entry_obj, top_link.query_params, data, title_filename_fallback=False
200
206
  )
201
- return OPDS1Entry(entry_obj, top_link.query_params, data)
202
207
 
203
208
  def add_top_links(self, top_links):
204
209
  """Add a list of top links as entries if they should be enabled."""
@@ -31,7 +31,10 @@ FACETS = (
31
31
  "Order Direction",
32
32
  "orderReverse",
33
33
  "⇕",
34
- (Facet(False, "Ascending"), Facet(True, "Descending")),
34
+ (
35
+ Facet(query_param_value=False, title="Ascending"),
36
+ Facet(query_param_value=True, title="Descending"),
37
+ ),
35
38
  ),
36
39
  FacetGroup(
37
40
  "Top Group",
@@ -114,5 +117,5 @@ class LinksSectionData:
114
117
 
115
118
 
116
119
  TOP_NAV_GROUP_SECTION_DATA = LinksSectionData(group_kwarg=True)
117
- GROUPS_SECTION_DATA = LinksSectionData("Groups", Rel.SUB, True)
120
+ GROUPS_SECTION_DATA = LinksSectionData("Groups", Rel.SUB, group_kwarg=True)
118
121
  FACETS_SECTION_DATA = LinksSectionData(rel=Rel.FACET, links_key="links")
@@ -8,7 +8,7 @@ from rest_framework.response import Response
8
8
  from codex.logger.logging import get_logger
9
9
  from codex.models import AdminFlag
10
10
  from codex.serializers.browser.settings import OPDSSettingsSerializer
11
- from codex.serializers.opds.v2 import OPDS2FeedSerializer
11
+ from codex.serializers.opds.v2.feed import OPDS2FeedSerializer
12
12
  from codex.views.const import MAX_OBJ_PER_PAGE
13
13
  from codex.views.opds.auth import OPDSAuthMixin
14
14
  from codex.views.opds.const import BLANK_TITLE
@@ -20,7 +20,8 @@ from codex.views.opds.v2.const import (
20
20
  TOP_NAV_GROUP_SECTION_DATA,
21
21
  NavigationGroup,
22
22
  )
23
- from codex.views.opds.v2.links import HrefData, LinkData
23
+ from codex.views.opds.v2.href import HrefData
24
+ from codex.views.opds.v2.links import LinkData
24
25
  from codex.views.opds.v2.publications import OPDS2PublicationView
25
26
 
26
27
  LOG = get_logger(__name__)
@@ -55,9 +56,9 @@ class OPDS2FeedView(OPDSAuthMixin, OPDS2PublicationView):
55
56
 
56
57
  # def _detect_user_agent(self):
57
58
  # """Hacks for individual clients."""
58
- # user_agent = self.request.headers.get("User-Agent")
59
+ # user_agent = self.request.headers.get("User-Agent") # noqa: ERA001
59
60
  # if not user_agent:
60
- # return
61
+ # return # noqa: ERA001
61
62
 
62
63
  @staticmethod
63
64
  def _is_allowed(link_spec):
@@ -184,7 +185,7 @@ class OPDS2FeedView(OPDSAuthMixin, OPDS2PublicationView):
184
185
  title = self._title(title)
185
186
  number_of_items = total_count
186
187
  current_page = self.kwargs.get("page")
187
- up_route = self.get_last_route()
188
+ up_route = self.get_last_route(name=True)
188
189
  links = self.get_links(up_route)
189
190
  facets = self._get_facets()
190
191
 
@@ -0,0 +1,60 @@
1
+ """Href methods for OPDS v2.0 Feed."""
2
+
3
+ from abc import ABC
4
+ from dataclasses import dataclass
5
+
6
+ from django.urls import reverse
7
+ from rest_framework.views import APIView
8
+
9
+ from codex.views.opds.util import update_href_query_params
10
+ from codex.views.util import pop_name
11
+
12
+
13
+ @dataclass
14
+ class HrefData:
15
+ """Data for creating hrefs."""
16
+
17
+ kwargs: dict | None = None
18
+ query_params: dict | None = None
19
+ absolute_query_params: bool = False
20
+ url_name: str | None = None
21
+ min_page: int | None = None
22
+ max_page: int | None = None
23
+
24
+
25
+ class OPDS2HrefMixin(APIView, ABC):
26
+ """Create links method."""
27
+
28
+ @property
29
+ def num_pages(self) -> int:
30
+ """Dummy."""
31
+ return 1
32
+
33
+ def _href_page_validate(self, kwargs, data):
34
+ """Validate the page bounds."""
35
+ min_page = 1 if data.min_page is None else data.min_page
36
+ max_page = self.num_pages if data.max_page is None else data.max_page
37
+ page = int(kwargs["page"])
38
+ return page >= min_page and page <= max_page
39
+
40
+ def _href_update_query_params(self, href, data):
41
+ """Update the query params."""
42
+ if data.absolute_query_params and data.query_params:
43
+ href = update_href_query_params(href, data.query_params)
44
+ elif hasattr(self, "request"):
45
+ # if request link and not init static links
46
+ href = update_href_query_params(
47
+ href, self.request.GET, new_query_params=data.query_params
48
+ )
49
+ return href
50
+
51
+ def href(self, data):
52
+ """Create an href."""
53
+ url_name = data.url_name if data.url_name else "opds:v2:feed"
54
+ kwargs = data.kwargs if data.kwargs is not None else self.kwargs
55
+ if "page" in kwargs and not self._href_page_validate(kwargs, data):
56
+ return None
57
+
58
+ kwargs = pop_name(kwargs)
59
+ href = reverse(url_name, kwargs=kwargs)
60
+ return self._href_update_query_params(href, data)
@@ -1,30 +1,17 @@
1
1
  """Links methods for OPDS v2.0 Feed."""
2
2
 
3
+ from collections.abc import Mapping
3
4
  from copy import deepcopy
4
5
  from dataclasses import dataclass
5
6
  from datetime import datetime
6
7
  from urllib.parse import parse_qsl, urlparse
7
8
 
8
9
  from django.db.models import QuerySet
9
- from django.urls import reverse
10
10
 
11
11
  from codex.settings.settings import FALSY
12
12
  from codex.views.browser.browser import BrowserView
13
13
  from codex.views.opds.const import MimeType, Rel
14
- from codex.views.opds.util import update_href_query_params
15
- from codex.views.util import pop_name
16
-
17
-
18
- @dataclass
19
- class HrefData:
20
- """Data for creating hrefs."""
21
-
22
- kwargs: dict | None = None
23
- query_params: dict | None = None
24
- absolute_query_params: bool = False
25
- url_name: str | None = None
26
- min_page: int | None = None
27
- max_page: int | None = None
14
+ from codex.views.opds.v2.href import HrefData, OPDS2HrefMixin
28
15
 
29
16
 
30
17
  @dataclass
@@ -40,9 +27,10 @@ class LinkData:
40
27
  width: int | None = None
41
28
  href: str | None = None
42
29
  num_items: int | None = None
30
+ authenticate: Mapping | None = None
43
31
 
44
32
 
45
- class OPDS2LinksView(BrowserView):
33
+ class OPDS2LinksView(OPDS2HrefMixin, BrowserView):
46
34
  """Links methods for OPDS 2.0 Feed."""
47
35
 
48
36
  def __init__(self, *args, **kwargs):
@@ -70,41 +58,12 @@ class OPDS2LinksView(BrowserView):
70
58
  self._num_pages = self.group_and_books[2]
71
59
  return self._num_pages
72
60
 
73
- def _href_page_validate(self, kwargs, data):
74
- """Validate the page bounds."""
75
- min_page = 1 if data.min_page is None else data.min_page
76
- max_page = self.num_pages if data.max_page is None else data.max_page
77
- page = int(kwargs["page"])
78
- return page >= min_page and page <= max_page
79
-
80
- def _href_update_query_params(self, href, data):
81
- """Update the query params."""
82
- if data.absolute_query_params and data.query_params:
83
- href = update_href_query_params(href, data.query_params)
84
- elif hasattr(self, "request"):
85
- # if request link and not init static links
86
- href = update_href_query_params(
87
- href, self.request.GET, new_query_params=data.query_params
88
- )
89
- return href
90
-
91
- def _href(self, data):
92
- """Create an href."""
93
- url_name = data.url_name if data.url_name else "opds:v2:feed"
94
- kwargs = data.kwargs if data.kwargs is not None else self.kwargs
95
- if "page" in kwargs and not self._href_page_validate(kwargs, data):
96
- return None
97
-
98
- kwargs = pop_name(kwargs)
99
- href = reverse(url_name, kwargs=kwargs)
100
- return self._href_update_query_params(href, data)
101
-
102
61
  def link(self, data):
103
62
  """Create a link element."""
104
63
  if data.href:
105
64
  href = data.href
106
65
  else:
107
- href = self._href(data.href_data)
66
+ href = self.href(data.href_data)
108
67
  if not href:
109
68
  return None
110
69
  mime_type = data.mime_type if data.mime_type else MimeType.OPDS_JSON
@@ -118,8 +77,15 @@ class OPDS2LinksView(BrowserView):
118
77
  link["height"] = data.height
119
78
  if data.width:
120
79
  link["width"] = data.width
80
+
81
+ # Properties
82
+ if data.num_items or data.authenticate:
83
+ link["properties"] = {}
121
84
  if data.num_items:
122
- link["properties"] = {"number_of_items": data.num_items}
85
+ link["properties"]["number_of_items"] = data.num_items
86
+ if data.authenticate:
87
+ link["properties"]["authenticate"] = data.authenticate
88
+
123
89
  return link
124
90
 
125
91
  @staticmethod
@@ -0,0 +1,136 @@
1
+ """OPDS 2 Progression view."""
2
+ # https://github.com/opds-community/drafts/discussions/67#discussioncomment-6414507
3
+
4
+ from types import MappingProxyType
5
+
6
+ from django.db.models.expressions import F, Value
7
+ from django.db.models.fields import FloatField
8
+ from django.db.models.functions.comparison import Cast, Coalesce, Greatest, Least
9
+ from django.db.models.query_utils import FilteredRelation
10
+ from rest_framework.exceptions import ValidationError
11
+ from rest_framework.response import Response
12
+
13
+ from codex.logger.logging import get_logger
14
+ from codex.serializers.opds.v2.progression import OPDS2ProgressionSerializer
15
+ from codex.util import max_none
16
+ from codex.views.auth import AuthFilterGenericAPIView
17
+ from codex.views.bookmark import BookmarkFilterMixin, BookmarkPageView
18
+ from codex.views.const import GROUP_MODEL_MAP
19
+ from codex.views.opds.v2.href import HrefData, OPDS2HrefMixin
20
+
21
+ _EMPTY_DEVICE = MappingProxyType(
22
+ {
23
+ "id": "",
24
+ "name": "",
25
+ }
26
+ )
27
+ LOG = get_logger(__name__)
28
+
29
+
30
+ # This is an independent api requiring a separate get.
31
+ class OPDS2ProgressionView(
32
+ BookmarkFilterMixin, OPDS2HrefMixin, BookmarkPageView, AuthFilterGenericAPIView
33
+ ):
34
+ """OPDS 2 Progression view."""
35
+
36
+ serializer_class = OPDS2ProgressionSerializer
37
+
38
+ @property
39
+ def modified(self):
40
+ """Get modified from bookmark."""
41
+ return self._obj.bookmark_updated_at # type: ignore[reportAttributeAccessIssue]
42
+
43
+ @property
44
+ def device(self):
45
+ """Dummy device."""
46
+ # Codex doesn't record this.
47
+ return _EMPTY_DEVICE
48
+
49
+ @property
50
+ def title(self):
51
+ """The locator title is the page number."""
52
+ return f"Page {self._obj.page}" # type: ignore[reportAttributeAccessIssue]
53
+
54
+ @property
55
+ def _progression_href(self):
56
+ """Build a Progression HRef."""
57
+ acq_kwargs = {
58
+ "pk": self._obj.pk,
59
+ "page": self._obj.page, # type: ignore[reportAttributeAccessIssue]
60
+ }
61
+ max_page = max_none(self._obj.page_count - 1, 0) # type: ignore[reportAttributeAccessIssue]
62
+ data = HrefData(
63
+ acq_kwargs,
64
+ url_name="opds:bin:page",
65
+ min_page=0,
66
+ max_page=max_page,
67
+ )
68
+ return self.href(data)
69
+
70
+ @property
71
+ def _locations(self):
72
+ """Build the Locations object."""
73
+ return {
74
+ "position": self._obj.page, # type: ignore[reportAttributeAccessIssue]
75
+ "progression": self._obj.progress, # type: ignore[reportAttributeAccessIssue]
76
+ "total_progression": self._obj.progress, # type: ignore[reportAttributeAccessIssue]
77
+ }
78
+
79
+ @property
80
+ def locator(self):
81
+ """Build the Locator object."""
82
+ return {
83
+ "title": self.title, # See publication.py:103
84
+ "href": self._progression_href,
85
+ "type": "image/jpeg",
86
+ "locations": self._locations,
87
+ }
88
+
89
+ def get_object(self):
90
+ """Build the progression data object."""
91
+ group = self.kwargs.get("group")
92
+ pk = self.kwargs.get("pk")
93
+
94
+ if not pk:
95
+ reason = f"Bad primary key for {group}:{pk}"
96
+ return ValidationError(reason, code="422")
97
+
98
+ model = GROUP_MODEL_MAP.get(group)
99
+ if not model:
100
+ reason = f"No model found for group {group}"
101
+ raise ValidationError(reason, code="422")
102
+
103
+ acl_filter = self.get_group_acl_filter(model, self.request.user)
104
+ qs = model.objects.filter(acl_filter).distinct()
105
+
106
+ bm_rel = self.get_bm_rel(model)
107
+ bm_filter = self.get_my_bookmark_filter(bm_rel)
108
+ progress = Least(
109
+ F("page") / Greatest(Cast(F("page_count"), FloatField()), 1.0), Value(1.0)
110
+ )
111
+
112
+ qs = qs.annotate(
113
+ my_bookmark=FilteredRelation("bookmark", condition=bm_filter),
114
+ bookmark_updated_at=F("my_bookmark__updated_at"),
115
+ page=Coalesce(F("my_bookmark__page"), 0),
116
+ progress=progress,
117
+ )
118
+ self._obj = qs.only("page_count").distinct().get(pk=pk)
119
+
120
+ return {
121
+ "modified": self.modified,
122
+ "device": self.device,
123
+ "locator": self.locator,
124
+ }
125
+
126
+ def get(self, *args, **kwargs):
127
+ """Get Response."""
128
+ try:
129
+ obj = self.get_object()
130
+ serializer = self.get_serializer(obj)
131
+ return Response(serializer.data)
132
+ except Exception:
133
+ LOG.exception("progression")
134
+ raise
135
+
136
+ # PUT handled by BookmarkPageView parent
@@ -10,15 +10,17 @@ from codex.models import Comic
10
10
  from codex.settings.settings import FALSY
11
11
  from codex.views.opds.const import AUTHOR_ROLES, MimeType, Rel
12
12
  from codex.views.opds.util import get_contributors, get_m2m_objects
13
- from codex.views.opds.v2.top_links import HrefData, LinkData, OPDS2TopLinksView
13
+ from codex.views.opds.v2.href import HrefData
14
+ from codex.views.opds.v2.links import LinkData
15
+ from codex.views.opds.v2.top_links import OPDS2TopLinksView
14
16
 
15
17
  _MD_CONTRIBUTOR_MAP = MappingProxyType(
16
18
  {
17
19
  "author": AUTHOR_ROLES,
18
- # "translator": {},
20
+ # "translator": {}, unused
19
21
  "editor": {"Editor"},
20
22
  "artist": {"CoverArtist"},
21
- # "illustrator": {},
23
+ # "illustrator": {}, unused, could use penciller
22
24
  "letterer": {"Letterer"},
23
25
  "penciller": {"Penciller"},
24
26
  "colorist": {"Colorist"},
@@ -40,7 +42,9 @@ class OPDS2PublicationView(OPDS2TopLinksView):
40
42
  "dynamicCovers": False,
41
43
  "ts": ts,
42
44
  }
43
- href_data = HrefData(kwargs, query_params, True, "opds:bin:cover")
45
+ href_data = HrefData(
46
+ kwargs, query_params, absolute_query_params=True, url_name="opds:bin:cover"
47
+ )
44
48
  link_data = LinkData(
45
49
  Rel.THUMBNAIL,
46
50
  href_data,
@@ -63,15 +67,13 @@ class OPDS2PublicationView(OPDS2TopLinksView):
63
67
  @staticmethod
64
68
  def _add_contributors(md, pks, key, roles):
65
69
  """Add contributors to metadata."""
66
- if contributors := get_contributors(pks, roles):
70
+ if contributors := get_contributors(pks, roles, exclude=False):
67
71
  md[key] = contributors
68
72
 
69
73
  def _publication_optional_metadata(self, md, obj):
70
74
  """Add optional Publication Metadtata."""
71
75
  if subtitle := obj.name:
72
76
  md["subtitle"] = subtitle
73
- # if identifier := obj.get("guid")
74
- # md["identifier"] = identifier
75
77
  if desc := obj.summary:
76
78
  md["description"] = desc
77
79
  if lang := obj.language:
@@ -87,25 +89,21 @@ class OPDS2PublicationView(OPDS2TopLinksView):
87
89
  """Publication m2m metadata only on the metadata alternate link."""
88
90
  for key, roles in _MD_CONTRIBUTOR_MAP.items():
89
91
  self._add_contributors(md, obj.ids, key, roles)
90
- if contributors := get_contributors(obj.ids, _CONTRIBUTOR_ROLES, True):
92
+ if contributors := get_contributors(obj.ids, _CONTRIBUTOR_ROLES, exclude=True):
91
93
  md["contributor"] = contributors
92
94
 
93
95
  if m2m_objs := get_m2m_objects(obj.ids):
94
- # XXX Subjects can also have links
96
+ # Subjects can also have links
95
97
  # https://readium.org/webpub-manifest/schema/subject-object.schema.json
96
- subjects = []
97
- for subjs in m2m_objs.values():
98
- for subj in subjs:
99
- subjects.append(subj.name)
100
- md["subject"] = subjects
98
+ md["subject"] = [subj.name for subjs in m2m_objs.values() for subj in subjs]
101
99
 
102
100
  def _publication_metadata(self, obj, zero_pad):
103
101
  title = Comic.get_title(
104
102
  obj,
105
103
  volume=False,
106
104
  name=False,
107
- zero_pad=zero_pad,
108
105
  filename_fallback=self.title_filename_fallback,
106
+ zero_pad=zero_pad,
109
107
  )
110
108
  md = {
111
109
  "type": MimeType.BOOK,
@@ -127,10 +125,6 @@ class OPDS2PublicationView(OPDS2TopLinksView):
127
125
  download_mime_type = MimeType.FILE_TYPE_MAP.get(obj.file_type, MimeType.OCTET)
128
126
  self_kwargs = {"pk": obj.pk, "page": 1}
129
127
 
130
- # This would be for comic streaming which is not supported by OPDS 2 yet?
131
- # self_href_data = HrefData(self_kwargs, absolute_query_params=True)
132
- # self_link_data = LinkData(Rel.SELF, self_href_data, mime_type=MimeType.OPDS_PUB)
133
-
134
128
  alt_kwargs = self_kwargs
135
129
  alt_href_data = HrefData(
136
130
  alt_kwargs,
@@ -154,11 +148,27 @@ class OPDS2PublicationView(OPDS2TopLinksView):
154
148
  acq_href_data,
155
149
  mime_type=download_mime_type,
156
150
  )
151
+ prog_kwargs = {"group": "c", "pk": obj.pk}
152
+ prog_href_data = HrefData(prog_kwargs, url_name="opds:v2:position")
153
+
154
+ auth_href_data = HrefData({}, url_name="opds:authentication:v1")
155
+ auth_link_data = LinkData(
156
+ Rel.AUTHENTICATION,
157
+ auth_href_data,
158
+ mime_type=MimeType.AUTHENTICATION,
159
+ )
160
+ auth_link = self.link(auth_link_data)
161
+
162
+ prog_link_data = LinkData(
163
+ Rel.PROGRESSION,
164
+ prog_href_data,
165
+ mime_type=MimeType.PROGRESSION,
166
+ authenticate=auth_link,
167
+ )
157
168
  links = [
158
- # Comic streaming link (unsupported)
159
- # self.link(self_link_data),
160
169
  self.link(alt_link_data),
161
170
  self.link(acq_link_data),
171
+ self.link(prog_link_data),
162
172
  ]
163
173
  pub["links"] = links
164
174
 
@@ -1,7 +1,8 @@
1
1
  """OPDS v2.0 top links section methods."""
2
2
 
3
3
  from codex.views.opds.const import MimeType, Rel
4
- from codex.views.opds.v2.links import HrefData, LinkData, OPDS2LinksView
4
+ from codex.views.opds.v2.href import HrefData
5
+ from codex.views.opds.v2.links import LinkData, OPDS2LinksView
5
6
 
6
7
 
7
8
  class OPDS2TopLinksView(OPDS2LinksView):
codex/views/public.py CHANGED
@@ -13,6 +13,7 @@ _ADMIN_FLAG_KEYS = frozenset(
13
13
  {
14
14
  AdminFlag.FlagChoices.NON_USERS.value,
15
15
  AdminFlag.FlagChoices.REGISTRATION.value,
16
+ AdminFlag.FlagChoices.BANNER_TEXT.value,
16
17
  }
17
18
  )
18
19
 
@@ -21,16 +22,22 @@ class AdminFlagsView(GenericAPIView, RetrieveModelMixin):
21
22
  """Get admin flags relevant to auth."""
22
23
 
23
24
  serializer_class = AuthAdminFlagsSerializer
24
- queryset = AdminFlag.objects.filter(key__in=_ADMIN_FLAG_KEYS).only("key", "on")
25
+ queryset = AdminFlag.objects.filter(key__in=_ADMIN_FLAG_KEYS).only(
26
+ "key", "on", "value"
27
+ )
25
28
 
26
29
  def get_object(self):
27
30
  """Get admin flags."""
28
31
  flags = {}
29
- for obj in self.get_queryset(): # type: ignore
32
+ for obj in self.get_queryset():
30
33
  name = ADMIN_FLAG_CHOICES[obj.key].lower().replace(" ", "_")
31
- flags[name] = obj.on
34
+ if obj.key == AdminFlag.FlagChoices.BANNER_TEXT.value:
35
+ val = obj.value
36
+ else:
37
+ val = obj.on
38
+ flags[name] = val
32
39
  return flags
33
40
 
34
- def get(self, request, *args, **kwargs):
41
+ def get(self, *args, **kwargs):
35
42
  """Get admin flags relevant to auth."""
36
- return self.retrieve(request, *args, **kwargs)
43
+ return self.retrieve(*args, **kwargs)
@@ -6,7 +6,7 @@ from django.db.models import F
6
6
  from django.db.models.query import Q
7
7
 
8
8
  from codex.models import Bookmark, Comic
9
- from codex.views.bookmark import BookmarkBaseView
9
+ from codex.views.bookmark import BookmarkAuthMixin
10
10
  from codex.views.browser.filters.field import ComicFieldFilterView
11
11
  from codex.views.const import (
12
12
  FOLDER_GROUP,
@@ -15,7 +15,7 @@ from codex.views.const import (
15
15
  NONE_INTEGERFIELD,
16
16
  STORY_ARC_GROUP,
17
17
  )
18
- from codex.views.mixins import BookmarkSearchMixin, SharedAnnotationsMixin
18
+ from codex.views.mixins import SharedAnnotationsMixin
19
19
  from codex.views.reader.params import ReaderParamsView
20
20
 
21
21
  if TYPE_CHECKING:
@@ -34,9 +34,7 @@ _COMIC_FIELDS = (
34
34
  )
35
35
 
36
36
 
37
- class ReaderBooksView(
38
- BookmarkBaseView, ReaderParamsView, SharedAnnotationsMixin, BookmarkSearchMixin
39
- ):
37
+ class ReaderBooksView(SharedAnnotationsMixin, BookmarkAuthMixin, ReaderParamsView):
40
38
  """Get Books methods."""
41
39
 
42
40
  def _get_reader_arc_pks(
@@ -81,10 +79,10 @@ class ReaderBooksView(
81
79
  """Get ordering for query."""
82
80
  sort_name_annotations = {}
83
81
  if arc_group in ("v", "s"):
82
+ parent_group = "i" if arc_group == "s" else "s"
84
83
  show = self.params["show"]
85
- model_group = "i" if arc_group == "s" else "s"
86
84
  sort_name_annotations = self.get_sort_name_annotations(
87
- model, model_group, arc_pks, show
85
+ model, parent_group, arc_pks, show
88
86
  )
89
87
  if sort_name_annotations and model is Comic:
90
88
  ordering += (*sort_name_annotations.keys(),)
@@ -97,7 +95,7 @@ class ReaderBooksView(
97
95
 
98
96
  def _get_comics_list(self):
99
97
  """Get the reader naviation group filter."""
100
- arc: Mapping = self.params.get("arc", {}) # type: ignore
98
+ arc: Mapping = self.params.get("arc", {})
101
99
 
102
100
  arc_group = arc.get("group", "")
103
101
  if not GROUP_MODEL_MAP.get(arc_group):
@@ -149,6 +147,19 @@ class ReaderBooksView(
149
147
  qs = qs.order_by(*ordering)
150
148
  return qs, arc_group
151
149
 
150
+ @staticmethod
151
+ def _get_bookmark_filter(auth_filter, comic_filter=None):
152
+ """Get the search kwargs for a user's authentication state."""
153
+ # search kwargs are relative to the bookmark object.
154
+ search_kwargs = {}
155
+ search_kwargs.update(auth_filter)
156
+
157
+ if comic_filter:
158
+ for key, value in comic_filter.items():
159
+ search_kwargs[f"comic__{key}"] = value
160
+
161
+ return search_kwargs
162
+
152
163
  def _append_with_settings(self, book, bookmark_filter):
153
164
  """Append bookmark to book list."""
154
165
  book.settings = (
@@ -159,7 +170,8 @@ class ReaderBooksView(
159
170
  return book
160
171
 
161
172
  def get_book_collection(self):
162
- """Get the -1, +1 window around the current issue.
173
+ """
174
+ Get the -1, +1 window around the current issue.
163
175
 
164
176
  Uses iteration in python. There are some complicated ways of
165
177
  doing this with __gt[0] & __lt[0] in the db, but I think they
@@ -169,7 +181,7 @@ class ReaderBooksView(
169
181
  """
170
182
  comics, arc_group = self._get_comics_list()
171
183
  auth_filter = self.get_bookmark_auth_filter()
172
- bookmark_filter = self.get_bookmark_search_kwargs(auth_filter)
184
+ bookmark_filter = self._get_bookmark_filter(auth_filter)
173
185
  books = {}
174
186
  prev_book = None
175
187
  pk = self.kwargs.get("pk")