codex 1.5.12__py3-none-any.whl → 1.5.13__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.
- codex/applications/websocket.py +1 -7
- codex/librarian/importer/importerd.py +2 -1
- codex/librarian/importer/query_fks.py +1 -1
- codex/middleware.py +50 -1
- codex/serializers/choices.py +11 -14
- codex/serializers/metadata.py +1 -1
- codex/settings/settings.py +11 -5
- codex/static_root/assets/{VCheckbox-CC74mhfV.a196e804e50a.js → VCheckbox-Wdu19ZuZ.50f2bf3b5ce5.js} +1 -1
- codex/static_root/assets/VCheckbox-Wdu19ZuZ.50f2bf3b5ce5.js.br +0 -0
- codex/static_root/assets/VCheckbox-Wdu19ZuZ.50f2bf3b5ce5.js.gz +0 -0
- codex/static_root/assets/{VCheckbox-CC74mhfV.js → VCheckbox-Wdu19ZuZ.js} +1 -1
- codex/static_root/assets/VCheckbox-Wdu19ZuZ.js.br +0 -0
- codex/static_root/assets/VCheckbox-Wdu19ZuZ.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-F27UKlAX.f74083aa5b9a.js → VCheckboxBtn-C7NngFC8.bd12ea5cdbb2.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-C7NngFC8.bd12ea5cdbb2.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-C7NngFC8.bd12ea5cdbb2.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-F27UKlAX.js → VCheckboxBtn-C7NngFC8.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-C7NngFC8.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-C7NngFC8.js.gz +0 -0
- codex/static_root/assets/VCombobox-DxNlm_ji.11d317a5dbb0.js +1 -0
- codex/static_root/assets/VCombobox-DxNlm_ji.11d317a5dbb0.js.br +0 -0
- codex/static_root/assets/VCombobox-DxNlm_ji.11d317a5dbb0.js.gz +0 -0
- codex/static_root/assets/VCombobox-DxNlm_ji.js +1 -0
- codex/static_root/assets/VCombobox-DxNlm_ji.js.br +0 -0
- codex/static_root/assets/VCombobox-DxNlm_ji.js.gz +0 -0
- codex/static_root/assets/{VDataTableVirtual-BgFOSn9_.969c17b4d50a.js → VDataTableVirtual-C4UTS-jp.4b2926f1461f.js} +1 -1
- codex/static_root/assets/VDataTableVirtual-C4UTS-jp.4b2926f1461f.js.br +0 -0
- codex/static_root/assets/VDataTableVirtual-C4UTS-jp.4b2926f1461f.js.gz +0 -0
- codex/static_root/assets/{VDataTableVirtual-BgFOSn9_.js → VDataTableVirtual-C4UTS-jp.js} +1 -1
- codex/static_root/assets/VDataTableVirtual-C4UTS-jp.js.br +0 -0
- codex/static_root/assets/VDataTableVirtual-C4UTS-jp.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanel-B06inlZY.a77a3ad1cc7c.js → VExpansionPanel-1dRZTsNe.6213946f43dd.js} +1 -1
- codex/static_root/assets/VExpansionPanel-1dRZTsNe.6213946f43dd.js.br +0 -0
- codex/static_root/assets/VExpansionPanel-1dRZTsNe.6213946f43dd.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanel-B06inlZY.js → VExpansionPanel-1dRZTsNe.js} +1 -1
- codex/static_root/assets/VExpansionPanel-1dRZTsNe.js.br +0 -0
- codex/static_root/assets/VExpansionPanel-1dRZTsNe.js.gz +0 -0
- codex/static_root/assets/{VMain-BR4DrMy3.977234e0db6a.js → VMain-BVEH6Gtw.51ef468a0780.js} +1 -1
- codex/static_root/assets/VMain-BVEH6Gtw.51ef468a0780.js.br +0 -0
- codex/static_root/assets/VMain-BVEH6Gtw.51ef468a0780.js.gz +0 -0
- codex/static_root/assets/{VMain-BR4DrMy3.js → VMain-BVEH6Gtw.js} +1 -1
- codex/static_root/assets/VMain-BVEH6Gtw.js.br +0 -0
- codex/static_root/assets/VMain-BVEH6Gtw.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DE0KmC8d.75bdb9d16a32.js → VRadioGroup-D1WV2cpK.83ba2e5689fd.js} +1 -1
- codex/static_root/assets/VRadioGroup-D1WV2cpK.83ba2e5689fd.js.br +0 -0
- codex/static_root/assets/VRadioGroup-D1WV2cpK.83ba2e5689fd.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DE0KmC8d.js → VRadioGroup-D1WV2cpK.js} +1 -1
- codex/static_root/assets/VRadioGroup-D1WV2cpK.js.br +0 -0
- codex/static_root/assets/VRadioGroup-D1WV2cpK.js.gz +0 -0
- codex/static_root/assets/VSelect-BVyqMxyX.4a54cd987085.js +1 -0
- codex/static_root/assets/VSelect-BVyqMxyX.4a54cd987085.js.br +0 -0
- codex/static_root/assets/VSelect-BVyqMxyX.4a54cd987085.js.gz +0 -0
- codex/static_root/assets/VSelect-BVyqMxyX.js +1 -0
- codex/static_root/assets/VSelect-BVyqMxyX.js.br +0 -0
- codex/static_root/assets/VSelect-BVyqMxyX.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-B1zPb_Yg.6112179d7a5d.js → VSelectionControl-CC9aC7ZT.2db18d99af8b.js} +1 -1
- codex/static_root/assets/VSelectionControl-CC9aC7ZT.2db18d99af8b.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CC9aC7ZT.2db18d99af8b.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-B1zPb_Yg.js → VSelectionControl-CC9aC7ZT.js} +1 -1
- codex/static_root/assets/VSelectionControl-CC9aC7ZT.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CC9aC7ZT.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-D4n-jSgi.686cc428f5fe.js +1 -0
- codex/static_root/assets/VSlideGroup-D4n-jSgi.686cc428f5fe.js.br +0 -0
- codex/static_root/assets/VSlideGroup-D4n-jSgi.686cc428f5fe.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-D4n-jSgi.js +1 -0
- codex/static_root/assets/VSlideGroup-D4n-jSgi.js.br +0 -0
- codex/static_root/assets/VSlideGroup-D4n-jSgi.js.gz +0 -0
- codex/static_root/assets/{VTable-Pq4fCfUx.e50f8ad539ed.js → VTable-DioYRJkC.c8638b2267ed.js} +1 -1
- codex/static_root/assets/VTable-DioYRJkC.c8638b2267ed.js.br +0 -0
- codex/static_root/assets/VTable-DioYRJkC.c8638b2267ed.js.gz +0 -0
- codex/static_root/assets/{VTable-Pq4fCfUx.js → VTable-DioYRJkC.js} +1 -1
- codex/static_root/assets/VTable-DioYRJkC.js.br +0 -0
- codex/static_root/assets/VTable-DioYRJkC.js.gz +0 -0
- codex/static_root/assets/{VToolbar-BFYiqJrS.js → VToolbar-DLtG5Ngs.e32539656f6d.js} +2 -2
- codex/static_root/assets/VToolbar-DLtG5Ngs.e32539656f6d.js.br +0 -0
- codex/static_root/assets/VToolbar-DLtG5Ngs.e32539656f6d.js.gz +0 -0
- codex/static_root/assets/{VToolbar-BFYiqJrS.71a0cbf7eb5f.js → VToolbar-DLtG5Ngs.js} +2 -2
- codex/static_root/assets/VToolbar-DLtG5Ngs.js.br +0 -0
- codex/static_root/assets/VToolbar-DLtG5Ngs.js.gz +0 -0
- codex/static_root/assets/{VToolbar-BfNszTMd.css → VToolbar-DqQLg1UA.614d6a4a8a09.css} +1 -1
- codex/static_root/assets/VToolbar-DqQLg1UA.614d6a4a8a09.css.br +0 -0
- codex/static_root/assets/{VToolbar-BfNszTMd.111f25cdd6d8.css.gz → VToolbar-DqQLg1UA.614d6a4a8a09.css.gz} +0 -0
- codex/static_root/assets/{VToolbar-BfNszTMd.111f25cdd6d8.css → VToolbar-DqQLg1UA.css} +1 -1
- codex/static_root/assets/VToolbar-DqQLg1UA.css.br +0 -0
- codex/static_root/assets/{VToolbar-BfNszTMd.css.gz → VToolbar-DqQLg1UA.css.gz} +0 -0
- codex/static_root/assets/{VWindowItem-g6ho7Hf4.b91f9a3277ff.js → VWindowItem-D-OB7e0u.ef9bcb84a01e.js} +1 -1
- codex/static_root/assets/VWindowItem-D-OB7e0u.ef9bcb84a01e.js.br +0 -0
- codex/static_root/assets/VWindowItem-D-OB7e0u.ef9bcb84a01e.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-g6ho7Hf4.js → VWindowItem-D-OB7e0u.js} +1 -1
- codex/static_root/assets/VWindowItem-D-OB7e0u.js.br +0 -0
- codex/static_root/assets/VWindowItem-D-OB7e0u.js.gz +0 -0
- codex/static_root/assets/{admin-BVkY78tW.affa20285127.js → admin-BwXMQOyX.8c44117c2b63.js} +1 -1
- codex/static_root/assets/admin-BwXMQOyX.8c44117c2b63.js.br +0 -0
- codex/static_root/assets/admin-BwXMQOyX.8c44117c2b63.js.gz +0 -0
- codex/static_root/assets/{admin-BVkY78tW.js → admin-BwXMQOyX.js} +1 -1
- codex/static_root/assets/admin-BwXMQOyX.js.br +0 -0
- codex/static_root/assets/admin-BwXMQOyX.js.gz +0 -0
- codex/static_root/assets/{admin-drawer-panel-s72VfDNy.css → admin-drawer-panel-Bk7z8uTR.1531b747003f.css} +1 -1
- codex/static_root/assets/admin-drawer-panel-Bk7z8uTR.1531b747003f.css.br +0 -0
- codex/static_root/assets/admin-drawer-panel-Bk7z8uTR.1531b747003f.css.gz +0 -0
- codex/static_root/assets/{admin-drawer-panel-s72VfDNy.ef6cb7221a44.css → admin-drawer-panel-Bk7z8uTR.css} +1 -1
- codex/static_root/assets/admin-drawer-panel-Bk7z8uTR.css.br +0 -0
- codex/static_root/assets/admin-drawer-panel-Bk7z8uTR.css.gz +0 -0
- codex/static_root/assets/{admin-drawer-panel-CEiEnUcn.9f94b93a422f.js → admin-drawer-panel-CGj6J0rX.cc680f2603da.js} +4 -4
- codex/static_root/assets/admin-drawer-panel-CGj6J0rX.cc680f2603da.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-CGj6J0rX.cc680f2603da.js.gz +0 -0
- codex/static_root/assets/{admin-drawer-panel-CEiEnUcn.js → admin-drawer-panel-CGj6J0rX.js} +4 -4
- codex/static_root/assets/admin-drawer-panel-CGj6J0rX.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-CGj6J0rX.js.gz +0 -0
- codex/static_root/assets/browser-BLCruguN.ca6300976f82.js +1 -0
- codex/static_root/assets/browser-BLCruguN.ca6300976f82.js.br +0 -0
- codex/static_root/assets/browser-BLCruguN.ca6300976f82.js.gz +0 -0
- codex/static_root/assets/browser-BLCruguN.js +1 -0
- codex/static_root/assets/browser-BLCruguN.js.br +0 -0
- codex/static_root/assets/browser-BLCruguN.js.gz +0 -0
- codex/static_root/assets/{browser-2i0QA4La.587673ac534c.css → browser-CTxEKlCx.211d729d9165.css} +1 -1
- codex/static_root/assets/browser-CTxEKlCx.211d729d9165.css.br +0 -0
- codex/static_root/assets/browser-CTxEKlCx.211d729d9165.css.gz +0 -0
- codex/static_root/assets/{browser-2i0QA4La.css → browser-CTxEKlCx.css} +1 -1
- codex/static_root/assets/browser-CTxEKlCx.css.br +0 -0
- codex/static_root/assets/browser-CTxEKlCx.css.gz +0 -0
- codex/static_root/assets/{change-password-dialog-Bh7raeqK.6d408dcd933e.js → change-password-dialog-DDvVSrWH.915709700c5f.js} +1 -1
- codex/static_root/assets/change-password-dialog-DDvVSrWH.915709700c5f.js.br +0 -0
- codex/static_root/assets/change-password-dialog-DDvVSrWH.915709700c5f.js.gz +0 -0
- codex/static_root/assets/{change-password-dialog-Bh7raeqK.js → change-password-dialog-DDvVSrWH.js} +1 -1
- codex/static_root/assets/change-password-dialog-DDvVSrWH.js.br +0 -0
- codex/static_root/assets/change-password-dialog-DDvVSrWH.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-CvURjaTY.cadecd4cefa8.js → confirm-dialog-Bf3Sde_o.b437109b579e.js} +1 -1
- codex/static_root/assets/confirm-dialog-Bf3Sde_o.b437109b579e.js.br +0 -0
- codex/static_root/assets/confirm-dialog-Bf3Sde_o.b437109b579e.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-CvURjaTY.js → confirm-dialog-Bf3Sde_o.js} +1 -1
- codex/static_root/assets/confirm-dialog-Bf3Sde_o.js.br +0 -0
- codex/static_root/assets/confirm-dialog-Bf3Sde_o.js.gz +0 -0
- codex/static_root/assets/{confirm-footer-C-VAfuKA.js → confirm-footer-CLwOC3F0.d25d9085b300.js} +1 -1
- codex/static_root/assets/confirm-footer-CLwOC3F0.d25d9085b300.js.br +0 -0
- codex/static_root/assets/confirm-footer-CLwOC3F0.d25d9085b300.js.gz +0 -0
- codex/static_root/assets/{confirm-footer-C-VAfuKA.c93e5c6d41ca.js → confirm-footer-CLwOC3F0.js} +1 -1
- codex/static_root/assets/confirm-footer-CLwOC3F0.js.br +0 -0
- codex/static_root/assets/confirm-footer-CLwOC3F0.js.gz +0 -0
- codex/static_root/assets/{datetime-column-CDcOr8sM.951343a94a28.js → datetime-column-DGfoC2Ap.ef9499c6bca8.js} +1 -1
- codex/static_root/assets/datetime-column-DGfoC2Ap.ef9499c6bca8.js.br +0 -0
- codex/static_root/assets/datetime-column-DGfoC2Ap.ef9499c6bca8.js.gz +0 -0
- codex/static_root/assets/{datetime-column-CDcOr8sM.js → datetime-column-DGfoC2Ap.js} +1 -1
- codex/static_root/assets/datetime-column-DGfoC2Ap.js.br +0 -0
- codex/static_root/assets/datetime-column-DGfoC2Ap.js.gz +0 -0
- codex/static_root/assets/{filter-DT8MlNGw.c70bb7a7c265.js → filter-DcOs3rVI.495426fbd29e.js} +1 -1
- codex/static_root/assets/filter-DcOs3rVI.495426fbd29e.js.br +0 -0
- codex/static_root/assets/filter-DcOs3rVI.495426fbd29e.js.gz +0 -0
- codex/static_root/assets/{filter-DT8MlNGw.js → filter-DcOs3rVI.js} +1 -1
- codex/static_root/assets/filter-DcOs3rVI.js.br +0 -0
- codex/static_root/assets/filter-DcOs3rVI.js.gz +0 -0
- codex/static_root/assets/{flag-tab-BVoz2gvN.591572581c12.js → flag-tab-D77e2Ors.068789b9d816.js} +1 -1
- codex/static_root/assets/flag-tab-D77e2Ors.068789b9d816.js.br +0 -0
- codex/static_root/assets/flag-tab-D77e2Ors.068789b9d816.js.gz +0 -0
- codex/static_root/assets/{flag-tab-BVoz2gvN.js → flag-tab-D77e2Ors.js} +1 -1
- codex/static_root/assets/flag-tab-D77e2Ors.js.br +0 -0
- codex/static_root/assets/flag-tab-D77e2Ors.js.gz +0 -0
- codex/static_root/assets/{group-tab-Bu1Hn4DR.8c9fb2cbc4d2.js → group-tab-SxqTtCGs.c23d57a22257.js} +1 -1
- codex/static_root/assets/group-tab-SxqTtCGs.c23d57a22257.js.br +0 -0
- codex/static_root/assets/group-tab-SxqTtCGs.c23d57a22257.js.gz +0 -0
- codex/static_root/assets/{group-tab-Bu1Hn4DR.js → group-tab-SxqTtCGs.js} +1 -1
- codex/static_root/assets/group-tab-SxqTtCGs.js.br +0 -0
- codex/static_root/assets/group-tab-SxqTtCGs.js.gz +0 -0
- codex/static_root/assets/{http-error-BKXUvS3w.93b39ceed2f7.js → http-error-CKL2ByeE.c0333de973b1.js} +1 -1
- codex/static_root/assets/http-error-CKL2ByeE.c0333de973b1.js.br +0 -0
- codex/static_root/assets/http-error-CKL2ByeE.c0333de973b1.js.gz +0 -0
- codex/static_root/assets/{http-error-BKXUvS3w.js → http-error-CKL2ByeE.js} +1 -1
- codex/static_root/assets/http-error-CKL2ByeE.js.br +0 -0
- codex/static_root/assets/http-error-CKL2ByeE.js.gz +0 -0
- codex/static_root/assets/{library-tab-AM2XWHOr.31f48701358e.js → library-tab-jesPyoqi.453abce07ca3.js} +1 -1
- codex/static_root/assets/library-tab-jesPyoqi.453abce07ca3.js.br +0 -0
- codex/static_root/assets/library-tab-jesPyoqi.453abce07ca3.js.gz +0 -0
- codex/static_root/assets/{library-tab-AM2XWHOr.js → library-tab-jesPyoqi.js} +1 -1
- codex/static_root/assets/library-tab-jesPyoqi.js.br +0 -0
- codex/static_root/assets/library-tab-jesPyoqi.js.gz +0 -0
- codex/static_root/assets/main-BXWucpmC.f8485541954a.js +37 -0
- codex/static_root/assets/main-BXWucpmC.f8485541954a.js.br +0 -0
- codex/static_root/assets/main-BXWucpmC.f8485541954a.js.gz +0 -0
- codex/static_root/assets/main-BXWucpmC.js +37 -0
- codex/static_root/assets/main-BXWucpmC.js.br +0 -0
- codex/static_root/assets/main-BXWucpmC.js.gz +0 -0
- codex/static_root/assets/main-CGRrI5lh.4f849ef1c5db.css.br +0 -0
- codex/static_root/assets/main-CGRrI5lh.css.br +0 -0
- codex/static_root/assets/materialdesignicons-webfont-B7mPwVP_.6e435534bd35.ttf.br +0 -0
- codex/static_root/assets/materialdesignicons-webfont-B7mPwVP_.ttf.br +0 -0
- codex/static_root/assets/materialdesignicons-webfont-CSr8KVlo.8ced95a05e3c.eot.br +0 -0
- codex/static_root/assets/materialdesignicons-webfont-CSr8KVlo.eot.br +0 -0
- codex/static_root/assets/{metadata-dialog-DFDQ4P3u.js → metadata-dialog-Dkadd19B.0c95b145042a.js} +1 -1
- codex/static_root/assets/metadata-dialog-Dkadd19B.0c95b145042a.js.br +0 -0
- codex/static_root/assets/metadata-dialog-Dkadd19B.0c95b145042a.js.gz +0 -0
- codex/static_root/assets/{metadata-dialog-DFDQ4P3u.b959bb5a03a2.js → metadata-dialog-Dkadd19B.js} +1 -1
- codex/static_root/assets/metadata-dialog-Dkadd19B.js.br +0 -0
- codex/static_root/assets/metadata-dialog-Dkadd19B.js.gz +0 -0
- codex/static_root/assets/{metadata-dialog-BGJasBRy.0553851658b5.css → metadata-dialog-QTkQOBoB.2e6935edafee.css} +1 -1
- codex/static_root/assets/metadata-dialog-QTkQOBoB.2e6935edafee.css.br +0 -0
- codex/static_root/assets/metadata-dialog-QTkQOBoB.2e6935edafee.css.gz +0 -0
- codex/static_root/assets/{metadata-dialog-BGJasBRy.css → metadata-dialog-QTkQOBoB.css} +1 -1
- codex/static_root/assets/metadata-dialog-QTkQOBoB.css.br +0 -0
- codex/static_root/assets/metadata-dialog-QTkQOBoB.css.gz +0 -0
- codex/static_root/assets/{pdf-doc-DSq1qfWx.50ab90d8b609.js → pdf-doc-DwPaMGER.d981a9066397.js} +1 -1
- codex/static_root/assets/pdf-doc-DwPaMGER.d981a9066397.js.br +0 -0
- codex/static_root/assets/pdf-doc-DwPaMGER.d981a9066397.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-DSq1qfWx.js → pdf-doc-DwPaMGER.js} +1 -1
- codex/static_root/assets/pdf-doc-DwPaMGER.js.br +0 -0
- codex/static_root/assets/pdf-doc-DwPaMGER.js.gz +0 -0
- codex/static_root/assets/{reader-Qan6W6n-.js → reader-7CNuDD9b.3593146c30b7.js} +2 -2
- codex/static_root/assets/reader-7CNuDD9b.3593146c30b7.js.br +0 -0
- codex/static_root/assets/reader-7CNuDD9b.3593146c30b7.js.gz +0 -0
- codex/static_root/assets/{reader-Qan6W6n-.fc91835a9075.js → reader-7CNuDD9b.js} +2 -2
- codex/static_root/assets/reader-7CNuDD9b.js.br +0 -0
- codex/static_root/assets/reader-7CNuDD9b.js.gz +0 -0
- codex/static_root/assets/{stats-tab-Bv3OL9xU.949c9b8d7135.js → stats-tab-CyQ4G2G_.10e279711e77.js} +1 -1
- codex/static_root/assets/stats-tab-CyQ4G2G_.10e279711e77.js.br +0 -0
- codex/static_root/assets/stats-tab-CyQ4G2G_.10e279711e77.js.gz +0 -0
- codex/static_root/assets/{stats-tab-Bv3OL9xU.js → stats-tab-CyQ4G2G_.js} +1 -1
- codex/static_root/assets/stats-tab-CyQ4G2G_.js.br +0 -0
- codex/static_root/assets/stats-tab-CyQ4G2G_.js.gz +0 -0
- codex/static_root/assets/{task-tab-CgR8JqMw.54569b8df927.js → task-tab-ncnnRysH.13fa947767f5.js} +1 -1
- codex/static_root/assets/task-tab-ncnnRysH.13fa947767f5.js.br +0 -0
- codex/static_root/assets/task-tab-ncnnRysH.13fa947767f5.js.gz +0 -0
- codex/static_root/assets/{task-tab-CgR8JqMw.js → task-tab-ncnnRysH.js} +1 -1
- codex/static_root/assets/task-tab-ncnnRysH.js.br +0 -0
- codex/static_root/assets/task-tab-ncnnRysH.js.gz +0 -0
- codex/static_root/assets/{user-tab-Xzi_07Yi.d165773d55aa.js → user-tab-BWjYndVM.503bf20bdbc0.js} +1 -1
- codex/static_root/assets/user-tab-BWjYndVM.503bf20bdbc0.js.br +0 -0
- codex/static_root/assets/user-tab-BWjYndVM.503bf20bdbc0.js.gz +0 -0
- codex/static_root/assets/{user-tab-Xzi_07Yi.js → user-tab-BWjYndVM.js} +1 -1
- codex/static_root/assets/user-tab-BWjYndVM.js.br +0 -0
- codex/static_root/assets/user-tab-BWjYndVM.js.gz +0 -0
- codex/static_root/{manifest.0d2e5eed5ce7.json → manifest.a5c8e7a036f3.json} +213 -213
- codex/static_root/manifest.a5c8e7a036f3.json.br +0 -0
- codex/static_root/manifest.a5c8e7a036f3.json.gz +0 -0
- codex/static_root/manifest.json +213 -213
- codex/static_root/manifest.json.br +0 -0
- codex/static_root/manifest.json.gz +0 -0
- codex/static_root/rest_framework/fonts/fontawesome-webfont.dcb26c7239d8.ttf.br +0 -0
- codex/static_root/rest_framework/fonts/fontawesome-webfont.ttf.br +0 -0
- codex/static_root/rest_framework/fonts/glyphicons-halflings-regular.e18bbf611f2a.ttf.br +0 -0
- codex/static_root/rest_framework/fonts/glyphicons-halflings-regular.ttf.br +0 -0
- codex/static_root/staticfiles.json +1 -1
- codex/views/bookmark.py +12 -9
- codex/views/browser/base.py +12 -1
- codex/views/browser/browser.py +72 -58
- codex/views/browser/const.py +3 -0
- codex/views/browser/filters/search.py +0 -4
- codex/views/error.py +6 -3
- codex/views/opds/v1/feed.py +2 -1
- codex/views/opds/v2/feed.py +4 -6
- codex/views/opds/v2/publications.py +6 -3
- {codex-1.5.12.dist-info → codex-1.5.13.dist-info}/METADATA +22 -12
- {codex-1.5.12.dist-info → codex-1.5.13.dist-info}/RECORD +258 -257
- codex/static_root/assets/VCheckbox-CC74mhfV.a196e804e50a.js.br +0 -0
- codex/static_root/assets/VCheckbox-CC74mhfV.a196e804e50a.js.gz +0 -0
- codex/static_root/assets/VCheckbox-CC74mhfV.js.br +0 -0
- codex/static_root/assets/VCheckbox-CC74mhfV.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-F27UKlAX.f74083aa5b9a.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-F27UKlAX.f74083aa5b9a.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-F27UKlAX.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-F27UKlAX.js.gz +0 -0
- codex/static_root/assets/VCombobox-Dw57vrly.b1184dfd61ec.js +0 -1
- codex/static_root/assets/VCombobox-Dw57vrly.b1184dfd61ec.js.br +0 -0
- codex/static_root/assets/VCombobox-Dw57vrly.b1184dfd61ec.js.gz +0 -0
- codex/static_root/assets/VCombobox-Dw57vrly.js +0 -1
- codex/static_root/assets/VCombobox-Dw57vrly.js.br +0 -0
- codex/static_root/assets/VCombobox-Dw57vrly.js.gz +0 -0
- codex/static_root/assets/VDataTableVirtual-BgFOSn9_.969c17b4d50a.js.br +0 -0
- codex/static_root/assets/VDataTableVirtual-BgFOSn9_.969c17b4d50a.js.gz +0 -0
- codex/static_root/assets/VDataTableVirtual-BgFOSn9_.js.br +0 -0
- codex/static_root/assets/VDataTableVirtual-BgFOSn9_.js.gz +0 -0
- codex/static_root/assets/VExpansionPanel-B06inlZY.a77a3ad1cc7c.js.br +0 -0
- codex/static_root/assets/VExpansionPanel-B06inlZY.a77a3ad1cc7c.js.gz +0 -0
- codex/static_root/assets/VExpansionPanel-B06inlZY.js.br +0 -0
- codex/static_root/assets/VExpansionPanel-B06inlZY.js.gz +0 -0
- codex/static_root/assets/VMain-BR4DrMy3.977234e0db6a.js.br +0 -0
- codex/static_root/assets/VMain-BR4DrMy3.977234e0db6a.js.gz +0 -0
- codex/static_root/assets/VMain-BR4DrMy3.js.br +0 -0
- codex/static_root/assets/VMain-BR4DrMy3.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-DE0KmC8d.75bdb9d16a32.js.br +0 -0
- codex/static_root/assets/VRadioGroup-DE0KmC8d.75bdb9d16a32.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-DE0KmC8d.js.br +0 -0
- codex/static_root/assets/VRadioGroup-DE0KmC8d.js.gz +0 -0
- codex/static_root/assets/VSelect-5wraBYHV.54a9a3184add.js +0 -1
- codex/static_root/assets/VSelect-5wraBYHV.54a9a3184add.js.br +0 -0
- codex/static_root/assets/VSelect-5wraBYHV.54a9a3184add.js.gz +0 -0
- codex/static_root/assets/VSelect-5wraBYHV.js +0 -1
- codex/static_root/assets/VSelect-5wraBYHV.js.br +0 -0
- codex/static_root/assets/VSelect-5wraBYHV.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-B1zPb_Yg.6112179d7a5d.js.br +0 -0
- codex/static_root/assets/VSelectionControl-B1zPb_Yg.6112179d7a5d.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-B1zPb_Yg.js.br +0 -0
- codex/static_root/assets/VSelectionControl-B1zPb_Yg.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-F7Hpcms9.dce335daf8f2.js +0 -1
- codex/static_root/assets/VSlideGroup-F7Hpcms9.dce335daf8f2.js.br +0 -0
- codex/static_root/assets/VSlideGroup-F7Hpcms9.dce335daf8f2.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-F7Hpcms9.js +0 -1
- codex/static_root/assets/VSlideGroup-F7Hpcms9.js.br +0 -0
- codex/static_root/assets/VSlideGroup-F7Hpcms9.js.gz +0 -0
- codex/static_root/assets/VTable-Pq4fCfUx.e50f8ad539ed.js.br +0 -0
- codex/static_root/assets/VTable-Pq4fCfUx.e50f8ad539ed.js.gz +0 -0
- codex/static_root/assets/VTable-Pq4fCfUx.js.br +0 -0
- codex/static_root/assets/VTable-Pq4fCfUx.js.gz +0 -0
- codex/static_root/assets/VToolbar-BFYiqJrS.71a0cbf7eb5f.js.br +0 -0
- codex/static_root/assets/VToolbar-BFYiqJrS.71a0cbf7eb5f.js.gz +0 -0
- codex/static_root/assets/VToolbar-BFYiqJrS.js.br +0 -0
- codex/static_root/assets/VToolbar-BFYiqJrS.js.gz +0 -0
- codex/static_root/assets/VToolbar-BfNszTMd.111f25cdd6d8.css.br +0 -0
- codex/static_root/assets/VToolbar-BfNszTMd.css.br +0 -0
- codex/static_root/assets/VWindowItem-g6ho7Hf4.b91f9a3277ff.js.br +0 -0
- codex/static_root/assets/VWindowItem-g6ho7Hf4.b91f9a3277ff.js.gz +0 -0
- codex/static_root/assets/VWindowItem-g6ho7Hf4.js.br +0 -0
- codex/static_root/assets/VWindowItem-g6ho7Hf4.js.gz +0 -0
- codex/static_root/assets/admin-BVkY78tW.affa20285127.js.br +0 -0
- codex/static_root/assets/admin-BVkY78tW.affa20285127.js.gz +0 -0
- codex/static_root/assets/admin-BVkY78tW.js.br +0 -0
- codex/static_root/assets/admin-BVkY78tW.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-CEiEnUcn.9f94b93a422f.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-CEiEnUcn.9f94b93a422f.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-CEiEnUcn.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-CEiEnUcn.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-s72VfDNy.css.br +0 -0
- codex/static_root/assets/admin-drawer-panel-s72VfDNy.css.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-s72VfDNy.ef6cb7221a44.css.br +0 -0
- codex/static_root/assets/admin-drawer-panel-s72VfDNy.ef6cb7221a44.css.gz +0 -0
- codex/static_root/assets/browser-2i0QA4La.587673ac534c.css.br +0 -0
- codex/static_root/assets/browser-2i0QA4La.587673ac534c.css.gz +0 -0
- codex/static_root/assets/browser-2i0QA4La.css.br +0 -0
- codex/static_root/assets/browser-2i0QA4La.css.gz +0 -0
- codex/static_root/assets/browser-BYquFWOA.3e5479490c40.js +0 -1
- codex/static_root/assets/browser-BYquFWOA.3e5479490c40.js.br +0 -0
- codex/static_root/assets/browser-BYquFWOA.3e5479490c40.js.gz +0 -0
- codex/static_root/assets/browser-BYquFWOA.js +0 -1
- codex/static_root/assets/browser-BYquFWOA.js.br +0 -0
- codex/static_root/assets/browser-BYquFWOA.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-Bh7raeqK.6d408dcd933e.js.br +0 -0
- codex/static_root/assets/change-password-dialog-Bh7raeqK.6d408dcd933e.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-Bh7raeqK.js.br +0 -0
- codex/static_root/assets/change-password-dialog-Bh7raeqK.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CvURjaTY.cadecd4cefa8.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CvURjaTY.cadecd4cefa8.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CvURjaTY.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CvURjaTY.js.gz +0 -0
- codex/static_root/assets/confirm-footer-C-VAfuKA.c93e5c6d41ca.js.br +0 -0
- codex/static_root/assets/confirm-footer-C-VAfuKA.c93e5c6d41ca.js.gz +0 -0
- codex/static_root/assets/confirm-footer-C-VAfuKA.js.br +0 -0
- codex/static_root/assets/confirm-footer-C-VAfuKA.js.gz +0 -0
- codex/static_root/assets/datetime-column-CDcOr8sM.951343a94a28.js.br +0 -0
- codex/static_root/assets/datetime-column-CDcOr8sM.951343a94a28.js.gz +0 -0
- codex/static_root/assets/datetime-column-CDcOr8sM.js.br +0 -0
- codex/static_root/assets/datetime-column-CDcOr8sM.js.gz +0 -0
- codex/static_root/assets/filter-DT8MlNGw.c70bb7a7c265.js.br +0 -0
- codex/static_root/assets/filter-DT8MlNGw.c70bb7a7c265.js.gz +0 -0
- codex/static_root/assets/filter-DT8MlNGw.js.br +0 -0
- codex/static_root/assets/filter-DT8MlNGw.js.gz +0 -0
- codex/static_root/assets/flag-tab-BVoz2gvN.591572581c12.js.br +0 -0
- codex/static_root/assets/flag-tab-BVoz2gvN.591572581c12.js.gz +0 -0
- codex/static_root/assets/flag-tab-BVoz2gvN.js.br +0 -0
- codex/static_root/assets/flag-tab-BVoz2gvN.js.gz +0 -0
- codex/static_root/assets/group-tab-Bu1Hn4DR.8c9fb2cbc4d2.js.br +0 -0
- codex/static_root/assets/group-tab-Bu1Hn4DR.8c9fb2cbc4d2.js.gz +0 -0
- codex/static_root/assets/group-tab-Bu1Hn4DR.js.br +0 -0
- codex/static_root/assets/group-tab-Bu1Hn4DR.js.gz +0 -0
- codex/static_root/assets/http-error-BKXUvS3w.93b39ceed2f7.js.br +0 -4
- codex/static_root/assets/http-error-BKXUvS3w.93b39ceed2f7.js.gz +0 -0
- codex/static_root/assets/http-error-BKXUvS3w.js.br +0 -4
- codex/static_root/assets/http-error-BKXUvS3w.js.gz +0 -0
- codex/static_root/assets/library-tab-AM2XWHOr.31f48701358e.js.br +0 -0
- codex/static_root/assets/library-tab-AM2XWHOr.31f48701358e.js.gz +0 -0
- codex/static_root/assets/library-tab-AM2XWHOr.js.br +0 -0
- codex/static_root/assets/library-tab-AM2XWHOr.js.gz +0 -0
- codex/static_root/assets/main-CacfwsKA.4f849ef1c5db.css.br +0 -0
- codex/static_root/assets/main-CacfwsKA.css.br +0 -0
- codex/static_root/assets/main-Dr7xEc75.ffae6222f1aa.js +0 -37
- codex/static_root/assets/main-Dr7xEc75.ffae6222f1aa.js.br +0 -0
- codex/static_root/assets/main-Dr7xEc75.ffae6222f1aa.js.gz +0 -0
- codex/static_root/assets/main-Dr7xEc75.js +0 -37
- codex/static_root/assets/main-Dr7xEc75.js.br +0 -0
- codex/static_root/assets/main-Dr7xEc75.js.gz +0 -0
- codex/static_root/assets/metadata-dialog-BGJasBRy.0553851658b5.css.br +0 -0
- codex/static_root/assets/metadata-dialog-BGJasBRy.0553851658b5.css.gz +0 -0
- codex/static_root/assets/metadata-dialog-BGJasBRy.css.br +0 -0
- codex/static_root/assets/metadata-dialog-BGJasBRy.css.gz +0 -0
- codex/static_root/assets/metadata-dialog-DFDQ4P3u.b959bb5a03a2.js.br +0 -0
- codex/static_root/assets/metadata-dialog-DFDQ4P3u.b959bb5a03a2.js.gz +0 -0
- codex/static_root/assets/metadata-dialog-DFDQ4P3u.js.br +0 -0
- codex/static_root/assets/metadata-dialog-DFDQ4P3u.js.gz +0 -0
- codex/static_root/assets/pdf-doc-DSq1qfWx.50ab90d8b609.js.br +0 -0
- codex/static_root/assets/pdf-doc-DSq1qfWx.50ab90d8b609.js.gz +0 -0
- codex/static_root/assets/pdf-doc-DSq1qfWx.js.br +0 -0
- codex/static_root/assets/pdf-doc-DSq1qfWx.js.gz +0 -0
- codex/static_root/assets/reader-Qan6W6n-.fc91835a9075.js.br +0 -0
- codex/static_root/assets/reader-Qan6W6n-.fc91835a9075.js.gz +0 -0
- codex/static_root/assets/reader-Qan6W6n-.js.br +0 -0
- codex/static_root/assets/reader-Qan6W6n-.js.gz +0 -0
- codex/static_root/assets/stats-tab-Bv3OL9xU.949c9b8d7135.js.br +0 -0
- codex/static_root/assets/stats-tab-Bv3OL9xU.949c9b8d7135.js.gz +0 -0
- codex/static_root/assets/stats-tab-Bv3OL9xU.js.br +0 -0
- codex/static_root/assets/stats-tab-Bv3OL9xU.js.gz +0 -0
- codex/static_root/assets/task-tab-CgR8JqMw.54569b8df927.js.br +0 -0
- codex/static_root/assets/task-tab-CgR8JqMw.54569b8df927.js.gz +0 -0
- codex/static_root/assets/task-tab-CgR8JqMw.js.br +0 -0
- codex/static_root/assets/task-tab-CgR8JqMw.js.gz +0 -0
- codex/static_root/assets/user-tab-Xzi_07Yi.d165773d55aa.js.br +0 -0
- codex/static_root/assets/user-tab-Xzi_07Yi.d165773d55aa.js.gz +0 -0
- codex/static_root/assets/user-tab-Xzi_07Yi.js.br +0 -0
- codex/static_root/assets/user-tab-Xzi_07Yi.js.gz +0 -0
- codex/static_root/manifest.0d2e5eed5ce7.json.br +0 -0
- codex/static_root/manifest.0d2e5eed5ce7.json.gz +0 -0
- /codex/static_root/assets/{main-CacfwsKA.4f849ef1c5db.css → main-CGRrI5lh.4f849ef1c5db.css} +0 -0
- /codex/static_root/assets/{main-CacfwsKA.4f849ef1c5db.css.gz → main-CGRrI5lh.4f849ef1c5db.css.gz} +0 -0
- /codex/static_root/assets/{main-CacfwsKA.css → main-CGRrI5lh.css} +0 -0
- /codex/static_root/assets/{main-CacfwsKA.css.gz → main-CGRrI5lh.css.gz} +0 -0
- {codex-1.5.12.dist-info → codex-1.5.13.dist-info}/LICENSE +0 -0
- {codex-1.5.12.dist-info → codex-1.5.13.dist-info}/WHEEL +0 -0
- {codex-1.5.12.dist-info → codex-1.5.13.dist-info}/entry_points.txt +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"paths": {"rest_framework/docs/
|
|
1
|
+
{"paths": {"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/docs/css/jquery.json-view.min.css": "rest_framework/docs/css/jquery.json-view.min.a2e6beeb6710.css", "rest_framework/docs/js/highlight.pack.js": "rest_framework/docs/js/highlight.pack.479b5f21dcba.js", "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/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/css/bootstrap.min.css": "rest_framework/css/bootstrap.min.f17d4516b026.css", "rest_framework/css/bootstrap.min.css.map": "rest_framework/css/bootstrap.min.css.cafbda9c0e9e.map", "rest_framework/css/bootstrap-theme.min.css.map": "rest_framework/css/bootstrap-theme.min.css.51806092cc05.map", "rest_framework/css/prettify.css": "rest_framework/css/prettify.a987f72342ee.css", "rest_framework/css/default.css": "rest_framework/css/default.789dfb5732d7.css", "rest_framework/css/font-awesome-4.0.3.css": "rest_framework/css/font-awesome-4.0.3.c1e1ea213abf.css", "rest_framework/css/bootstrap-tweaks.css": "rest_framework/css/bootstrap-tweaks.ee4ee6acf9eb.css", "rest_framework/css/bootstrap-theme.min.css": "rest_framework/css/bootstrap-theme.min.1d4b05b397c3.css", "rest_framework/js/load-ajax-form.js": "rest_framework/js/load-ajax-form.8cdb3a9f3466.js", "rest_framework/js/ajax-form.js": "rest_framework/js/ajax-form.4e1cdcb7acab.js", "rest_framework/js/prettify-min.js": "rest_framework/js/prettify-min.709bfcc456c6.js", "rest_framework/js/csrf.js": "rest_framework/js/csrf.455080a7b2ce.js", "rest_framework/js/bootstrap.min.js": "rest_framework/js/bootstrap.min.2f34b630ffe3.js", "rest_framework/js/default.js": "rest_framework/js/default.5b08897dbdc3.js", "rest_framework/js/coreapi-0.1.1.js": "rest_framework/js/coreapi-0.1.1.8851fb9336c9.js", "rest_framework/js/jquery-3.7.1.min.js": "rest_framework/js/jquery-3.7.1.min.2c872dbe60f4.js", "rest_framework/img/grid.png": "rest_framework/img/grid.a4b938cf382b.png", "rest_framework/img/glyphicons-halflings.png": "rest_framework/img/glyphicons-halflings.90233c9067e9.png", "rest_framework/img/glyphicons-halflings-white.png": "rest_framework/img/glyphicons-halflings-white.9bbc6e960299.png", "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.eot": "rest_framework/fonts/glyphicons-halflings-regular.f4769f9bdb74.eot", "rest_framework/fonts/glyphicons-halflings-regular.woff2": "rest_framework/fonts/glyphicons-halflings-regular.448c34a56d69.woff2", "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/fontawesome-webfont.woff": "rest_framework/fonts/fontawesome-webfont.3293616ec0c6.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", "img/logo-32.webp": "img/logo-32.dbb98f6dfde4.webp", "img/missing-page.svg": "img/missing-page.71bb10f7c72a.svg", "img/missing-cover.webp": "img/missing-cover.8c8c1d4f6782.webp", "img/logo-maskable.svg": "img/logo-maskable.d618c2d7943f.svg", "img/logo-maskable-180.webp": "img/logo-maskable-180.201cbde62d55.webp", "img/logo.svg": "img/logo.3fb129bfbd92.svg", "pwa/offline.html": "pwa/offline.7bfaf9f94bf9.html", "js/choices-admin.json": "js/choices-admin.bb730e4f26ac.json", "js/choices.json": "js/choices.fedcbd1ec085.json", "assets/VMain-BVEH6Gtw.js": "assets/VMain-BVEH6Gtw.51ef468a0780.js", "assets/VDataTableVirtual-C4UTS-jp.js": "assets/VDataTableVirtual-C4UTS-jp.4b2926f1461f.js", "assets/VSelect-BdGop3V2.css": "assets/VSelect-BdGop3V2.604c1785fbff.css", "assets/browser-CTxEKlCx.css": "assets/browser-CTxEKlCx.211d729d9165.css", "assets/VExpansionPanel-DsEXVcCv.css": "assets/VExpansionPanel-DsEXVcCv.20b475255e66.css", "assets/VRadioGroup-i2qP9Wu9.css": "assets/VRadioGroup-i2qP9Wu9.8e3741381961.css", "assets/admin-drawer-panel-CGj6J0rX.js": "assets/admin-drawer-panel-CGj6J0rX.cc680f2603da.js", "assets/admin-Df82-Qcj.css": "assets/admin-Df82-Qcj.4c3f0406ee54.css", "assets/main-BXWucpmC.js": "assets/main-BXWucpmC.f8485541954a.js", "assets/VCheckboxBtn-C7NngFC8.js": "assets/VCheckboxBtn-C7NngFC8.bd12ea5cdbb2.js", "assets/change-password-dialog-BRmvkNir.css": "assets/change-password-dialog-BRmvkNir.2fead58a78c7.css", "assets/task-tab-ncnnRysH.js": "assets/task-tab-ncnnRysH.13fa947767f5.js", "assets/VTable-DioYRJkC.js": "assets/VTable-DioYRJkC.c8638b2267ed.js", "assets/flag-tab-DUXtbpA2.css": "assets/flag-tab-DUXtbpA2.8d52c0d4f9e2.css", "assets/VSelectionControl-BFq--28I.css": "assets/VSelectionControl-BFq--28I.9687c77461fc.css", "assets/flag-tab-D77e2Ors.js": "assets/flag-tab-D77e2Ors.068789b9d816.js", "assets/http-error-C25WdjWC.css": "assets/http-error-C25WdjWC.1c7337ad6e1d.css", "assets/VCheckbox-Wdu19ZuZ.js": "assets/VCheckbox-Wdu19ZuZ.50f2bf3b5ce5.js", "assets/VRadioGroup-D1WV2cpK.js": "assets/VRadioGroup-D1WV2cpK.83ba2e5689fd.js", "assets/stats-tab-CyQ4G2G_.js": "assets/stats-tab-CyQ4G2G_.10e279711e77.js", "assets/datetime-column-DGfoC2Ap.js": "assets/datetime-column-DGfoC2Ap.ef9499c6bca8.js", "assets/pdf-doc-CMzaSV_K.css": "assets/pdf-doc-CMzaSV_K.8cd4b3e65f9a.css", "assets/materialdesignicons-webfont-CSr8KVlo.eot": "assets/materialdesignicons-webfont-CSr8KVlo.8ced95a05e3c.eot", "assets/confirm-footer-CLwOC3F0.js": "assets/confirm-footer-CLwOC3F0.d25d9085b300.js", "assets/stats-tab-BTZLMBCU.css": "assets/stats-tab-BTZLMBCU.7e0a9547c12e.css", "assets/VWindowItem-ByIod57Y.css": "assets/VWindowItem-ByIod57Y.f7fb19752bf3.css", "assets/task-tab-DoX9OA37.css": "assets/task-tab-DoX9OA37.9bb355f36dbf.css", "assets/to-case-kUm8NPpW.js": "assets/to-case-kUm8NPpW.5b3369f511b8.js", "assets/confirm-dialog-BmhedLCx.css": "assets/confirm-dialog-BmhedLCx.7c2103d319d4.css", "assets/VSlideGroup-D4n-jSgi.js": "assets/VSlideGroup-D4n-jSgi.686cc428f5fe.js", "assets/materialdesignicons-webfont-PXm3-2wK.woff": "assets/materialdesignicons-webfont-PXm3-2wK.026b7ac9c43c.woff", "assets/VSelect-BVyqMxyX.js": "assets/VSelect-BVyqMxyX.4a54cd987085.js", "assets/metadata-dialog-QTkQOBoB.css": "assets/metadata-dialog-QTkQOBoB.2e6935edafee.css", "assets/http-error-CKL2ByeE.js": "assets/http-error-CKL2ByeE.c0333de973b1.js", "assets/VCheckbox-CMKdyl0R.css": "assets/VCheckbox-CMKdyl0R.016ed8d222c4.css", "assets/change-password-dialog-DDvVSrWH.js": "assets/change-password-dialog-DDvVSrWH.915709700c5f.js", "assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "assets/materialdesignicons-webfont-Dp5v-WZN.1d7bcee1b302.woff2", "assets/group-tab-3DXxSetf.css": "assets/group-tab-3DXxSetf.5fc2cfa31669.css", "assets/VCombobox-DxNlm_ji.js": "assets/VCombobox-DxNlm_ji.11d317a5dbb0.js", "assets/admin-drawer-panel-Bk7z8uTR.css": "assets/admin-drawer-panel-Bk7z8uTR.1531b747003f.css", "assets/reader-7CNuDD9b.js": "assets/reader-7CNuDD9b.3593146c30b7.js", "assets/VToolbar-DqQLg1UA.css": "assets/VToolbar-DqQLg1UA.614d6a4a8a09.css", "assets/VMain-Byt37V4c.css": "assets/VMain-Byt37V4c.a00e206f3cfa.css", "assets/main-CGRrI5lh.css": "assets/main-CGRrI5lh.4f849ef1c5db.css", "assets/VDataTableVirtual-Cbj7IGxa.css": "assets/VDataTableVirtual-Cbj7IGxa.24039b2ebc61.css", "assets/browser-BLCruguN.js": "assets/browser-BLCruguN.ca6300976f82.js", "assets/confirm-dialog-Bf3Sde_o.js": "assets/confirm-dialog-Bf3Sde_o.b437109b579e.js", "assets/VSlideGroup-C3lY91uv.css": "assets/VSlideGroup-C3lY91uv.d268067bd078.css", "assets/index-DUjeNg4x.js": "assets/index-DUjeNg4x.36d50c91b2c1.js", "assets/VWindowItem-D-OB7e0u.js": "assets/VWindowItem-D-OB7e0u.ef9bcb84a01e.js", "assets/group-tab-SxqTtCGs.js": "assets/group-tab-SxqTtCGs.c23d57a22257.js", "assets/VExpansionPanel-1dRZTsNe.js": "assets/VExpansionPanel-1dRZTsNe.6213946f43dd.js", "assets/VTable-DflzroDq.css": "assets/VTable-DflzroDq.160504d82195.css", "assets/library-tab-jesPyoqi.js": "assets/library-tab-jesPyoqi.453abce07ca3.js", "assets/VSelectionControl-CC9aC7ZT.js": "assets/VSelectionControl-CC9aC7ZT.2db18d99af8b.js", "assets/reader-CG6zrLXl.css": "assets/reader-CG6zrLXl.ed017042cd53.css", "assets/admin-BwXMQOyX.js": "assets/admin-BwXMQOyX.8c44117c2b63.js", "assets/VToolbar-DLtG5Ngs.js": "assets/VToolbar-DLtG5Ngs.e32539656f6d.js", "assets/datetime-column-BWWfvyhn.css": "assets/datetime-column-BWWfvyhn.a4a94ba57c73.css", "assets/metadata-dialog-Dkadd19B.js": "assets/metadata-dialog-Dkadd19B.0c95b145042a.js", "assets/library-tab-DZKDtQ5v.css": "assets/library-tab-DZKDtQ5v.c8123e4bc5a4.css", "assets/VCombobox-BksEr4D_.css": "assets/VCombobox-BksEr4D_.73429bb75f42.css", "assets/confirm-footer-VFepxcJs.css": "assets/confirm-footer-VFepxcJs.4150131304bd.css", "assets/pdf-doc-DwPaMGER.js": "assets/pdf-doc-DwPaMGER.d981a9066397.js", "assets/user-tab-BWjYndVM.js": "assets/user-tab-BWjYndVM.503bf20bdbc0.js", "assets/filter-DcOs3rVI.js": "assets/filter-DcOs3rVI.495426fbd29e.js", "assets/materialdesignicons-webfont-B7mPwVP_.ttf": "assets/materialdesignicons-webfont-B7mPwVP_.6e435534bd35.ttf", "robots.txt": "robots.b6216d61c03e.txt", "manifest.json": "manifest.a5c8e7a036f3.json"}, "version": "1.1", "hash": "54ff58bbb924"}
|
codex/views/bookmark.py
CHANGED
|
@@ -92,18 +92,15 @@ class BookmarkBaseView(GenericAPIView, GroupACLMixin):
|
|
|
92
92
|
.only(*self._BOOKMARK_ONLY_FIELDS)
|
|
93
93
|
)
|
|
94
94
|
update_bookmarks = []
|
|
95
|
-
existing_comic_pks = set()
|
|
96
95
|
for bm in existing_bookmarks:
|
|
97
96
|
self._update_bookmarks_validate_page(bm, updates)
|
|
98
97
|
self._update_bookmarks_validate_two_pages(bm, updates)
|
|
99
98
|
for key, value in updates.items():
|
|
100
99
|
setattr(bm, key, value)
|
|
101
100
|
update_bookmarks.append(bm)
|
|
102
|
-
existing_comic_pks.add(bm.comic.pk)
|
|
103
101
|
if update_bookmarks:
|
|
104
102
|
update_fields = list(self._BOOKMARK_UPDATE_FIELDS | updates.keys())
|
|
105
103
|
Bookmark.objects.bulk_update(update_bookmarks, update_fields)
|
|
106
|
-
return existing_comic_pks
|
|
107
104
|
|
|
108
105
|
@staticmethod
|
|
109
106
|
def _create_bookmarks_validate_two_pages(updates):
|
|
@@ -114,19 +111,25 @@ class BookmarkBaseView(GenericAPIView, GroupACLMixin):
|
|
|
114
111
|
):
|
|
115
112
|
updates.pop("two_pages", None)
|
|
116
113
|
|
|
117
|
-
def _create_bookmarks(
|
|
118
|
-
self, existing_comic_pks, comic_filter, search_kwargs, updates
|
|
119
|
-
):
|
|
114
|
+
def _create_bookmarks(self, comic_filter, search_kwargs, updates):
|
|
120
115
|
"""Create new bookmarks for comics that don't exist yet."""
|
|
121
116
|
self._create_bookmarks_validate_two_pages(updates)
|
|
122
117
|
if not updates:
|
|
123
118
|
return
|
|
124
119
|
create_bookmarks = []
|
|
125
120
|
group_acl_filter = self.get_group_acl_filter(Comic)
|
|
121
|
+
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)
|
|
126
129
|
create_bookmark_comics = (
|
|
127
130
|
Comic.objects.filter(group_acl_filter)
|
|
128
131
|
.filter(**comic_filter)
|
|
129
|
-
.exclude(
|
|
132
|
+
.exclude(**exclude)
|
|
130
133
|
.only(*self._COMIC_ONLY_FIELDS)
|
|
131
134
|
)
|
|
132
135
|
for comic in create_bookmark_comics:
|
|
@@ -151,8 +154,8 @@ class BookmarkBaseView(GenericAPIView, GroupACLMixin):
|
|
|
151
154
|
def update_bookmarks(self, updates, comic_filter):
|
|
152
155
|
"""Update a user bookmark."""
|
|
153
156
|
search_kwargs = self.get_bookmark_search_kwargs(comic_filter)
|
|
154
|
-
|
|
155
|
-
self._create_bookmarks(
|
|
157
|
+
self._update_bookmarks(search_kwargs, updates)
|
|
158
|
+
self._create_bookmarks(comic_filter, search_kwargs, updates)
|
|
156
159
|
|
|
157
160
|
|
|
158
161
|
class BookmarkView(BookmarkBaseView):
|
codex/views/browser/base.py
CHANGED
|
@@ -89,10 +89,21 @@ class BrowserBaseView(
|
|
|
89
89
|
parsed_val = json.loads(unquoted_val)
|
|
90
90
|
if not parsed_val:
|
|
91
91
|
continue
|
|
92
|
+
parsed_key = key
|
|
93
|
+
elif key in ("q", "query"):
|
|
94
|
+
# parse and strip query param
|
|
95
|
+
# "query" is used by opds v2
|
|
96
|
+
if "q" in result:
|
|
97
|
+
continue
|
|
98
|
+
parsed_val = val.strip()
|
|
99
|
+
if not parsed_val:
|
|
100
|
+
continue
|
|
101
|
+
parsed_key = "q"
|
|
92
102
|
else:
|
|
103
|
+
parsed_key = key
|
|
93
104
|
parsed_val = val
|
|
94
105
|
|
|
95
|
-
result[
|
|
106
|
+
result[parsed_key] = parsed_val
|
|
96
107
|
return underscoreize(result, **api_settings.JSON_UNDERSCOREIZE)
|
|
97
108
|
|
|
98
109
|
def parse_params(self):
|
codex/views/browser/browser.py
CHANGED
|
@@ -29,11 +29,18 @@ from codex.models import (
|
|
|
29
29
|
Volume,
|
|
30
30
|
)
|
|
31
31
|
from codex.serializers.browser.page import BrowserPageSerializer
|
|
32
|
-
from codex.serializers.choices import
|
|
32
|
+
from codex.serializers.choices import DEFAULTS
|
|
33
33
|
from codex.views.auth import IsAuthenticatedOrEnabledNonUsers
|
|
34
34
|
from codex.views.browser.browser_annotations import BrowserAnnotationsView
|
|
35
|
+
from codex.views.browser.const import MAX_OBJ_PER_PAGE
|
|
35
36
|
|
|
36
37
|
LOG = get_logger(__name__)
|
|
38
|
+
_ADMIN_FLAG_VALUE_KEY_MAP = MappingProxyType(
|
|
39
|
+
{
|
|
40
|
+
AdminFlag.FlagChoices.FOLDER_VIEW.value: "folder_view",
|
|
41
|
+
AdminFlag.FlagChoices.IMPORT_METADATA.value: "import_metadata",
|
|
42
|
+
}
|
|
43
|
+
)
|
|
37
44
|
|
|
38
45
|
|
|
39
46
|
class BrowserView(BrowserAnnotationsView):
|
|
@@ -42,7 +49,6 @@ class BrowserView(BrowserAnnotationsView):
|
|
|
42
49
|
permission_classes: ClassVar[list] = [IsAuthenticatedOrEnabledNonUsers] # type: ignore
|
|
43
50
|
serializer_class = BrowserPageSerializer
|
|
44
51
|
|
|
45
|
-
MAX_OBJ_PER_PAGE = 100
|
|
46
52
|
_NAV_GROUPS = "rpisv"
|
|
47
53
|
|
|
48
54
|
_GROUP_INSTANCE_SELECT_RELATED = MappingProxyType(
|
|
@@ -132,29 +138,32 @@ class BrowserView(BrowserAnnotationsView):
|
|
|
132
138
|
self.model_group = self._get_model_group()
|
|
133
139
|
self.model = self.GROUP_MODEL_MAP[self.model_group]
|
|
134
140
|
|
|
141
|
+
def _get_common_queryset(self, model, search_scores):
|
|
142
|
+
"""Create queryset common to group & books."""
|
|
143
|
+
object_filter = self.get_query_filters(model, search_scores, False)
|
|
144
|
+
qs = model.objects.filter(object_filter)
|
|
145
|
+
qs = self._add_annotations(qs, model, search_scores)
|
|
146
|
+
qs = self.add_order_by(qs, model)
|
|
147
|
+
if limit := self.params.get("limit"):
|
|
148
|
+
# limit only is set by some opds views
|
|
149
|
+
qs = qs[:limit]
|
|
150
|
+
return qs
|
|
151
|
+
|
|
135
152
|
def _get_group_queryset(self, search_scores: dict | None):
|
|
136
153
|
"""Create group queryset."""
|
|
137
154
|
if not self.model:
|
|
138
|
-
reason = "Model not set
|
|
155
|
+
reason = "Model not set for browser queryset."
|
|
139
156
|
raise ValueError(reason)
|
|
140
|
-
if self.model
|
|
141
|
-
object_filter = self.get_query_filters(self.model, search_scores, False)
|
|
142
|
-
qs = self.model.objects.filter(object_filter)
|
|
143
|
-
qs = self._add_annotations(qs, self.model, search_scores)
|
|
144
|
-
qs = self.add_order_by(qs, self.model)
|
|
145
|
-
else:
|
|
157
|
+
if self.model == Comic or search_scores is None:
|
|
146
158
|
qs = self.model.objects.none()
|
|
159
|
+
else:
|
|
160
|
+
qs = self._get_common_queryset(self.model, search_scores)
|
|
147
161
|
return qs
|
|
148
162
|
|
|
149
163
|
def _get_book_queryset(self, search_scores: dict | None):
|
|
150
164
|
"""Create book queryset."""
|
|
151
165
|
if self.model in (Comic, Folder) and search_scores is not None:
|
|
152
|
-
|
|
153
|
-
qs = Comic.objects.filter(object_filter)
|
|
154
|
-
qs = self._add_annotations(qs, Comic, search_scores)
|
|
155
|
-
qs = self.add_order_by(qs, Comic)
|
|
156
|
-
if limit := self.params.get("limit"):
|
|
157
|
-
qs = qs[:limit]
|
|
166
|
+
qs = self._get_common_queryset(Comic, search_scores)
|
|
158
167
|
else:
|
|
159
168
|
qs = Comic.objects.none()
|
|
160
169
|
return qs
|
|
@@ -193,8 +202,12 @@ class BrowserView(BrowserAnnotationsView):
|
|
|
193
202
|
)
|
|
194
203
|
except self.group_class.DoesNotExist:
|
|
195
204
|
group = self.kwargs.get("group")
|
|
196
|
-
|
|
197
|
-
|
|
205
|
+
page = self.kwargs.get("page")
|
|
206
|
+
if group == "r" and pk == 0 and page == 1:
|
|
207
|
+
self.group_instance: BrowserGroupModel | None = None
|
|
208
|
+
else:
|
|
209
|
+
reason = f"{group}={pk} does not exist!"
|
|
210
|
+
self._raise_redirect({"group": group, "pk": 0, "page": 1}, reason)
|
|
198
211
|
else:
|
|
199
212
|
self.group_instance: BrowserGroupModel | None = None
|
|
200
213
|
|
|
@@ -276,11 +289,22 @@ class BrowserView(BrowserAnnotationsView):
|
|
|
276
289
|
"group_count": group_count,
|
|
277
290
|
}
|
|
278
291
|
|
|
279
|
-
def _page_out_of_bounds(self,
|
|
292
|
+
def _page_out_of_bounds(self, num_pages):
|
|
280
293
|
"""Redirect page out of bounds."""
|
|
281
294
|
group = self.kwargs.get("group")
|
|
282
|
-
pk = self.kwargs.get("pk",
|
|
283
|
-
|
|
295
|
+
pk = self.kwargs.get("pk", 0)
|
|
296
|
+
page = self.kwargs.get("page", 1)
|
|
297
|
+
if group == "r" and pk == 0 and page == 1:
|
|
298
|
+
# Don't redirect if on the root page.
|
|
299
|
+
return
|
|
300
|
+
|
|
301
|
+
if num_pages:
|
|
302
|
+
new_page = num_pages if page > num_pages else 1
|
|
303
|
+
else:
|
|
304
|
+
# Redirect to root.
|
|
305
|
+
group = "r"
|
|
306
|
+
pk = 0
|
|
307
|
+
new_page = 1
|
|
284
308
|
route_changes = {"group": group, "pk": pk, "page": new_page}
|
|
285
309
|
reason = f"{page=} does not exist!"
|
|
286
310
|
LOG.debug(f"{reason} redirect to page {new_page}.")
|
|
@@ -288,8 +312,8 @@ class BrowserView(BrowserAnnotationsView):
|
|
|
288
312
|
|
|
289
313
|
def _paginate_section(self, model, qs, page):
|
|
290
314
|
"""Paginate a group or Comic section."""
|
|
291
|
-
orphans =
|
|
292
|
-
paginator = Paginator(qs,
|
|
315
|
+
orphans = 0 if self.model_group == "f" or self.params.get("q") else 5
|
|
316
|
+
paginator = Paginator(qs, MAX_OBJ_PER_PAGE, orphans=orphans)
|
|
293
317
|
try:
|
|
294
318
|
qs = paginator.page(page).object_list
|
|
295
319
|
except EmptyPage:
|
|
@@ -311,27 +335,25 @@ class BrowserView(BrowserAnnotationsView):
|
|
|
311
335
|
|
|
312
336
|
def _paginate_books(self, book_qs, total_group_count, page_obj_count):
|
|
313
337
|
"""Paginate the book object list based on how many group/folders are showing."""
|
|
314
|
-
if page_obj_count >=
|
|
338
|
+
if page_obj_count >= MAX_OBJ_PER_PAGE:
|
|
315
339
|
# No books for this page
|
|
316
340
|
page_book_qs = Comic.objects.none()
|
|
317
341
|
else:
|
|
318
|
-
group_remainder = total_group_count %
|
|
342
|
+
group_remainder = total_group_count % MAX_OBJ_PER_PAGE
|
|
319
343
|
if page_obj_count:
|
|
320
344
|
# There are books after the groups on the same page
|
|
321
345
|
# Manually add books without the paginator
|
|
322
|
-
book_limit =
|
|
346
|
+
book_limit = MAX_OBJ_PER_PAGE - group_remainder
|
|
323
347
|
page_book_qs = book_qs[:book_limit]
|
|
324
348
|
else:
|
|
325
349
|
# There are books after the groups on a new page
|
|
326
350
|
if group_remainder:
|
|
327
|
-
book_offset =
|
|
351
|
+
book_offset = MAX_OBJ_PER_PAGE - group_remainder
|
|
328
352
|
page_book_qs = book_qs[book_offset:]
|
|
329
353
|
else:
|
|
330
354
|
page_book_qs = book_qs
|
|
331
355
|
|
|
332
|
-
num_group_and_mixed_pages = ceil(
|
|
333
|
-
total_group_count / self.MAX_OBJ_PER_PAGE
|
|
334
|
-
)
|
|
356
|
+
num_group_and_mixed_pages = ceil(total_group_count / MAX_OBJ_PER_PAGE)
|
|
335
357
|
book_only_page = self.kwargs.get("page", 1) - num_group_and_mixed_pages
|
|
336
358
|
page_book_qs = self._paginate_section(
|
|
337
359
|
Comic, page_book_qs, book_only_page
|
|
@@ -342,20 +364,20 @@ class BrowserView(BrowserAnnotationsView):
|
|
|
342
364
|
"""Paginate the queryset into a group and book object lists."""
|
|
343
365
|
page = self.kwargs.get("page", 1)
|
|
344
366
|
if page < 1:
|
|
345
|
-
self._page_out_of_bounds(
|
|
367
|
+
self._page_out_of_bounds(1)
|
|
346
368
|
|
|
347
369
|
page_obj_count = 0
|
|
348
370
|
|
|
349
|
-
|
|
350
|
-
|
|
371
|
+
group_count = group_qs.count()
|
|
372
|
+
book_count = book_qs.count()
|
|
351
373
|
|
|
352
|
-
num_pages = ceil((
|
|
374
|
+
num_pages = ceil((group_count + book_count) / MAX_OBJ_PER_PAGE)
|
|
353
375
|
if page > num_pages:
|
|
354
|
-
self._page_out_of_bounds(
|
|
376
|
+
self._page_out_of_bounds(num_pages)
|
|
355
377
|
|
|
356
|
-
page_group_qs = self._paginate_groups(group_qs,
|
|
378
|
+
page_group_qs = self._paginate_groups(group_qs, group_count)
|
|
357
379
|
page_obj_count += page_group_qs.count()
|
|
358
|
-
page_book_qs = self._paginate_books(book_qs,
|
|
380
|
+
page_book_qs = self._paginate_books(book_qs, group_count, page_obj_count)
|
|
359
381
|
page_obj_count += page_book_qs.count()
|
|
360
382
|
|
|
361
383
|
return page_group_qs, page_book_qs, num_pages, page_obj_count
|
|
@@ -389,19 +411,6 @@ class BrowserView(BrowserAnnotationsView):
|
|
|
389
411
|
else:
|
|
390
412
|
up_route = {}
|
|
391
413
|
|
|
392
|
-
admin_flag_objs = AdminFlag.objects.only("on").filter(
|
|
393
|
-
key__in=(
|
|
394
|
-
AdminFlag.FlagChoices.FOLDER_VIEW.value,
|
|
395
|
-
AdminFlag.FlagChoices.IMPORT_METADATA.value,
|
|
396
|
-
)
|
|
397
|
-
)
|
|
398
|
-
admin_flags = {}
|
|
399
|
-
for flag in admin_flag_objs:
|
|
400
|
-
if flag.key == AdminFlag.FlagChoices.FOLDER_VIEW.value:
|
|
401
|
-
admin_flags["folder_view"] = flag.on
|
|
402
|
-
if flag.key == AdminFlag.FlagChoices.IMPORT_METADATA.value:
|
|
403
|
-
admin_flags["import_metadata"] = flag.on
|
|
404
|
-
|
|
405
414
|
libraries_exist = Library.objects.exists()
|
|
406
415
|
|
|
407
416
|
# runs obj list query twice :/
|
|
@@ -426,7 +435,7 @@ class BrowserView(BrowserAnnotationsView):
|
|
|
426
435
|
"issue_number_max": issue_number_max,
|
|
427
436
|
"num_pages": num_pages,
|
|
428
437
|
"total_count": total_count,
|
|
429
|
-
"admin_flags": admin_flags,
|
|
438
|
+
"admin_flags": self.admin_flags,
|
|
430
439
|
"libraries_exist": libraries_exist,
|
|
431
440
|
"covers_timestamp": covers_timestamp,
|
|
432
441
|
}
|
|
@@ -549,18 +558,23 @@ class BrowserView(BrowserAnnotationsView):
|
|
|
549
558
|
page = self.kwargs.get("page", 1)
|
|
550
559
|
self.params["route"] = {"group": group, "pk": pk, "page": page}
|
|
551
560
|
|
|
561
|
+
def _set_admin_flags(self):
|
|
562
|
+
"""Set browser relevant admin flags."""
|
|
563
|
+
admin_pairs = AdminFlag.objects.filter(
|
|
564
|
+
key__in=_ADMIN_FLAG_VALUE_KEY_MAP.keys()
|
|
565
|
+
).values_list("key", "on")
|
|
566
|
+
admin_flags = {}
|
|
567
|
+
for key, on in admin_pairs:
|
|
568
|
+
export_key = _ADMIN_FLAG_VALUE_KEY_MAP[key]
|
|
569
|
+
admin_flags[export_key] = on
|
|
570
|
+
self.admin_flags = MappingProxyType(admin_flags)
|
|
571
|
+
|
|
552
572
|
def validate_settings(self):
|
|
553
573
|
"""Validate group and top group settings."""
|
|
554
574
|
group = self.kwargs.get("group")
|
|
555
575
|
self.set_order_key()
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
key = AdminFlag.FlagChoices.FOLDER_VIEW.value
|
|
559
|
-
try:
|
|
560
|
-
enable_folder_view = AdminFlag.objects.only("on").get(key=key).on
|
|
561
|
-
except Exception as err:
|
|
562
|
-
title = CHOICES["admin"]["adminFlags"].get(key)
|
|
563
|
-
LOG.warning(f"Getting {title} AdminFlag: {err}")
|
|
576
|
+
self._set_admin_flags()
|
|
577
|
+
enable_folder_view = self.admin_flags["folder_view"]
|
|
564
578
|
|
|
565
579
|
if group == self.FOLDER_GROUP:
|
|
566
580
|
self._validate_folder_settings(enable_folder_view)
|
|
@@ -16,10 +16,6 @@ class SearchFilterMixin:
|
|
|
16
16
|
"""Perform the search and return the scores as a dict."""
|
|
17
17
|
search_scores = {}
|
|
18
18
|
text = self.params.get("q", "") # type: ignore
|
|
19
|
-
if not text:
|
|
20
|
-
# for opds 2
|
|
21
|
-
text = self.params.get("query", "") # type: ignore
|
|
22
|
-
text = text.strip()
|
|
23
19
|
if not text:
|
|
24
20
|
return search_scores
|
|
25
21
|
|
codex/views/error.py
CHANGED
|
@@ -7,15 +7,18 @@ from rest_framework.views import exception_handler
|
|
|
7
7
|
|
|
8
8
|
from codex.exceptions import SeeOtherRedirectError
|
|
9
9
|
|
|
10
|
+
_OPDS_PREFIX = "opds/v"
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
def codex_exception_handler(exc, context):
|
|
12
14
|
"""Assume OPDS clients want redirects instead of errors."""
|
|
13
15
|
response = None
|
|
14
16
|
request = context.get("request")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
if _OPDS_PREFIX in request.path:
|
|
18
|
+
name = "opds:v2:feed" if _OPDS_PREFIX + "2" in request.path else "opds:v1:feed"
|
|
19
|
+
opds_start = reverse(name)
|
|
17
20
|
if isinstance(exc, SeeOtherRedirectError):
|
|
18
|
-
response = exc.get_response(
|
|
21
|
+
response = exc.get_response(opds_start)
|
|
19
22
|
elif hasattr(exc, "status_code") and exc.status_code in (
|
|
20
23
|
status.HTTP_400_BAD_REQUEST,
|
|
21
24
|
status.HTTP_404_NOT_FOUND,
|
codex/views/opds/v1/feed.py
CHANGED
|
@@ -12,6 +12,7 @@ from codex.serializers.opds.v1 import (
|
|
|
12
12
|
OPDS1TemplateSerializer,
|
|
13
13
|
)
|
|
14
14
|
from codex.views.browser.browser import BrowserView
|
|
15
|
+
from codex.views.browser.const import MAX_OBJ_PER_PAGE
|
|
15
16
|
from codex.views.const import FALSY
|
|
16
17
|
from codex.views.opds.const import BLANK_TITLE, MimeType
|
|
17
18
|
from codex.views.opds.v1.entry.data import OPDS1EntryData
|
|
@@ -107,7 +108,7 @@ class OPDS1FeedView(CodexXMLTemplateView, LinksMixin):
|
|
|
107
108
|
"""Return opensearch:itemsPerPage."""
|
|
108
109
|
try:
|
|
109
110
|
if self.params.get("q"):
|
|
110
|
-
return
|
|
111
|
+
return MAX_OBJ_PER_PAGE
|
|
111
112
|
except Exception:
|
|
112
113
|
LOG.exception("Getting OPDS v1 items per page")
|
|
113
114
|
|
codex/views/opds/v2/feed.py
CHANGED
|
@@ -11,6 +11,7 @@ from codex.logger.logging import get_logger
|
|
|
11
11
|
from codex.models import AdminFlag
|
|
12
12
|
from codex.serializers.opds.v2 import OPDS2FeedSerializer
|
|
13
13
|
from codex.views.browser.browser import BrowserView
|
|
14
|
+
from codex.views.browser.const import MAX_OBJ_PER_PAGE
|
|
14
15
|
from codex.views.const import FALSY
|
|
15
16
|
from codex.views.opds.const import BLANK_TITLE
|
|
16
17
|
from codex.views.opds.v2.const import (
|
|
@@ -175,14 +176,11 @@ class OPDS2FeedView(PublicationMixin, TopLinksMixin):
|
|
|
175
176
|
"""Get the browser page and serialize it for this subclass."""
|
|
176
177
|
group = self.kwargs.get("group")
|
|
177
178
|
if group in ("f", "a"):
|
|
178
|
-
self.acquisition_groups = frozenset()
|
|
179
|
-
else:
|
|
180
|
-
self.acquisition_groups = frozenset(self.valid_nav_groups[-2:])
|
|
181
|
-
if group == "a":
|
|
182
179
|
pk = self.kwargs["pk"]
|
|
183
180
|
self.is_opds_2_acquisition = bool(pk)
|
|
184
181
|
else:
|
|
185
|
-
|
|
182
|
+
acquisition_groups = frozenset(self.valid_nav_groups[-2:])
|
|
183
|
+
self.is_opds_2_acquisition = group in acquisition_groups
|
|
186
184
|
self.is_opds_metadata = (
|
|
187
185
|
self.request.query_params.get("opdsMetadata", "").lower() not in FALSY
|
|
188
186
|
)
|
|
@@ -202,7 +200,7 @@ class OPDS2FeedView(PublicationMixin, TopLinksMixin):
|
|
|
202
200
|
"metadata": {
|
|
203
201
|
"title": title,
|
|
204
202
|
"number_of_items": number_of_items,
|
|
205
|
-
"items_per_page":
|
|
203
|
+
"items_per_page": MAX_OBJ_PER_PAGE,
|
|
206
204
|
"current_page": self.kwargs.get("page"),
|
|
207
205
|
},
|
|
208
206
|
"links": self.get_links(browser_page["up_route"]),
|
|
@@ -144,8 +144,10 @@ class PublicationMixin(LinksMixin):
|
|
|
144
144
|
|
|
145
145
|
download_mime_type = MimeType.FILE_TYPE_MAP.get(obj.file_type, MimeType.OCTET)
|
|
146
146
|
self_kwargs = {"group": "c", "pk": obj.pk, "page": 1}
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
|
|
148
|
+
# This would be for comic streaming which is not supported by OPDS 2 yet?
|
|
149
|
+
# self_href_data = HrefData(self_kwargs, absolute_query_params=True)
|
|
150
|
+
# self_link_data = LinkData(Rel.SELF, self_href_data, mime_type=MimeType.OPDS_PUB)
|
|
149
151
|
|
|
150
152
|
alt_kwargs = self_kwargs
|
|
151
153
|
alt_href_data = HrefData(
|
|
@@ -168,7 +170,8 @@ class PublicationMixin(LinksMixin):
|
|
|
168
170
|
mime_type=download_mime_type,
|
|
169
171
|
)
|
|
170
172
|
links = [
|
|
171
|
-
|
|
173
|
+
# Comic streaming link (unsupported)
|
|
174
|
+
# self.link(self_link_data),
|
|
172
175
|
self.link(alt_link_data),
|
|
173
176
|
self.link(acq_link_data),
|
|
174
177
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: codex
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.13
|
|
4
4
|
Summary: A comic archive web server.
|
|
5
5
|
Home-page: https://github.com/ajslater/codex
|
|
6
6
|
License: GPL-3.0-only
|
|
@@ -267,15 +267,29 @@ remove users to groups.
|
|
|
267
267
|
Codex can make groups for libraries that exclude groups of users or exclude
|
|
268
268
|
everyone and include only certain groups of users.
|
|
269
269
|
|
|
270
|
-
###
|
|
270
|
+
### PDF Metadata
|
|
271
271
|
|
|
272
|
-
Codex
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
272
|
+
Codex reads PDF metadata from the filename, PDF metadata fields and also many
|
|
273
|
+
formats of common complex comic metadata if they are embedded in the PDF
|
|
274
|
+
`keywords` field.
|
|
275
|
+
|
|
276
|
+
If you decide to include PDFs in your comic library, I recommend taking time to
|
|
277
|
+
rename your files so Codex can find some metadata. Codex recognizes several file
|
|
278
|
+
naming schemes. This one has good results:
|
|
276
279
|
|
|
277
280
|
`{series} v{volume} #{issue} {title} ({year}) {ignored}.pdf`
|
|
278
281
|
|
|
282
|
+
Complex comic metadata, such as ComicInfo.xml, can be also be embedded in the
|
|
283
|
+
keywords field by using the [comicbox](https://github.com/ajslater/comicbox)
|
|
284
|
+
command line tool. Codex will read this data because it relies on comicbox
|
|
285
|
+
internally. Not many people use comicbox or embedded metadata in PDFs in this
|
|
286
|
+
fashion, so you likely won't find it unless you've added it yourself.
|
|
287
|
+
|
|
288
|
+
### 🗝️ API with Key Access
|
|
289
|
+
|
|
290
|
+
Codex has a limited number of API endpoints available with API Key Access. The
|
|
291
|
+
API Key is available on the admin/stats tab.
|
|
292
|
+
|
|
279
293
|
## <a name="configuration">🎛️ Configuration</a>
|
|
280
294
|
|
|
281
295
|
### Config Dir
|
|
@@ -384,7 +398,7 @@ If you must run Codex in an admin restricted memory environment you might want
|
|
|
384
398
|
to temporarily give Codex a lot of memory to run a very large import job and
|
|
385
399
|
then restrict it for normal operation.
|
|
386
400
|
|
|
387
|
-
## <a name="
|
|
401
|
+
## <a name="use">📖 Use</a>
|
|
388
402
|
|
|
389
403
|
### 👤 Sessions & Accounts
|
|
390
404
|
|
|
@@ -395,11 +409,6 @@ To preserve these settings across browsers and after sessions expire, you may
|
|
|
395
409
|
register an account with a username and password. You will have to contact your
|
|
396
410
|
administrator to reset your password if you forget it.
|
|
397
411
|
|
|
398
|
-
### 🗝️ API with Key Access
|
|
399
|
-
|
|
400
|
-
Codex has a limited number of API endpoints available with API Key Access. The
|
|
401
|
-
API Key is available on the admin/stats tab.
|
|
402
|
-
|
|
403
412
|
### ᯤ OPDS
|
|
404
413
|
|
|
405
414
|
Codex supports OPDS syndication and OPDS streaming. You may find the OPDS url in
|
|
@@ -438,6 +447,7 @@ authentication. In that case the OPDS url will look like:
|
|
|
438
447
|
- [OPDS-PSE 1.2](https://github.com/anansi-project/opds-pse/blob/master/v1.2.md)
|
|
439
448
|
- [OPDS Authentication 1.0](https://drafts.opds.io/authentication-for-opds-1.0.html)
|
|
440
449
|
- [OpenSearch 1.1](https://github.com/dewitt/opensearch)
|
|
450
|
+
- [OPDS 2.0 (draft)](https://drafts.opds.io/opds-2.0.html)
|
|
441
451
|
|
|
442
452
|
## <a name="troubleshooting">🩺 Troubleshooting</a>
|
|
443
453
|
|