codex 1.6.2__py3-none-any.whl → 1.6.4__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/exceptions.py +42 -16
- codex/librarian/importer/importer.py +1 -1
- codex/librarian/janitor/cleanup.py +2 -4
- codex/librarian/janitor/update.py +10 -9
- codex/librarian/search/merge.py +37 -40
- codex/librarian/search/remove.py +30 -26
- codex/librarian/search/update.py +47 -38
- codex/librarian/stats.py +177 -0
- codex/librarian/watchdog/events.py +2 -2
- codex/serializers/admin/__init__.py +1 -0
- codex/serializers/admin/flags.py +15 -0
- codex/serializers/admin/groups.py +38 -0
- codex/serializers/admin/libraries.py +90 -0
- codex/serializers/admin/stats.py +126 -0
- codex/serializers/admin/tasks.py +16 -0
- codex/serializers/admin/users.py +40 -0
- codex/serializers/fields.py +30 -0
- codex/serializers/reader.py +8 -3
- codex/settings/settings.py +3 -3
- codex/static_root/assets/VCheckbox-DtXDauZz.54986ad416a1.js +1 -0
- codex/static_root/assets/VCheckbox-DtXDauZz.54986ad416a1.js.br +0 -0
- codex/static_root/assets/VCheckbox-DtXDauZz.54986ad416a1.js.gz +0 -0
- codex/static_root/assets/VCheckbox-DtXDauZz.js +1 -0
- codex/static_root/assets/VCheckbox-DtXDauZz.js.br +0 -0
- codex/static_root/assets/VCheckbox-DtXDauZz.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-B-iT1MnG.8505f6eed0fe.js +1 -0
- codex/static_root/assets/VCheckboxBtn-B-iT1MnG.8505f6eed0fe.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-B-iT1MnG.8505f6eed0fe.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-B-iT1MnG.js +1 -0
- codex/static_root/assets/VCheckboxBtn-B-iT1MnG.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-B-iT1MnG.js.gz +0 -0
- codex/static_root/assets/{VCombobox-CGyBgdqr.2f85598cc1a4.js → VCombobox-DZmum3X-.330883d59742.js} +1 -1
- codex/static_root/assets/VCombobox-DZmum3X-.330883d59742.js.br +0 -0
- codex/static_root/assets/VCombobox-DZmum3X-.330883d59742.js.gz +0 -0
- codex/static_root/assets/{VCombobox-CGyBgdqr.js → VCombobox-DZmum3X-.js} +1 -1
- codex/static_root/assets/VCombobox-DZmum3X-.js.br +0 -0
- codex/static_root/assets/VCombobox-DZmum3X-.js.gz +0 -0
- codex/static_root/assets/VDialog-DUdNpXLj.6088d518d3af.js +1 -0
- codex/static_root/assets/VDialog-DUdNpXLj.6088d518d3af.js.br +0 -0
- codex/static_root/assets/VDialog-DUdNpXLj.6088d518d3af.js.gz +0 -0
- codex/static_root/assets/VDialog-DUdNpXLj.js +1 -0
- codex/static_root/assets/VDialog-DUdNpXLj.js.br +0 -0
- codex/static_root/assets/VDialog-DUdNpXLj.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-CurqcyFg.860017abf25d.js +1 -0
- codex/static_root/assets/VExpansionPanels-CurqcyFg.860017abf25d.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-CurqcyFg.860017abf25d.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-CurqcyFg.js +1 -0
- codex/static_root/assets/VExpansionPanels-CurqcyFg.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-CurqcyFg.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-B7n5ReZ-.8acbc71ac411.js +1 -0
- codex/static_root/assets/VRadioGroup-B7n5ReZ-.8acbc71ac411.js.br +0 -0
- codex/static_root/assets/VRadioGroup-B7n5ReZ-.8acbc71ac411.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-B7n5ReZ-.js +1 -0
- codex/static_root/assets/VRadioGroup-B7n5ReZ-.js.br +0 -0
- codex/static_root/assets/VRadioGroup-B7n5ReZ-.js.gz +0 -0
- codex/static_root/assets/VSelect-FYWbH55D.83e91b93fdd1.js +1 -0
- codex/static_root/assets/VSelect-FYWbH55D.83e91b93fdd1.js.br +0 -0
- codex/static_root/assets/VSelect-FYWbH55D.83e91b93fdd1.js.gz +0 -0
- codex/static_root/assets/VSelect-FYWbH55D.js +1 -0
- codex/static_root/assets/VSelect-FYWbH55D.js.br +0 -0
- codex/static_root/assets/VSelect-FYWbH55D.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-DXxRmssH.js → VSelectionControl-CUlT3cc_.63f60240eb49.js} +1 -1
- codex/static_root/assets/VSelectionControl-CUlT3cc_.63f60240eb49.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CUlT3cc_.63f60240eb49.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-DXxRmssH.252890f79cc6.js → VSelectionControl-CUlT3cc_.js} +1 -1
- codex/static_root/assets/VSelectionControl-CUlT3cc_.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CUlT3cc_.js.gz +0 -0
- codex/static_root/assets/{VSlideGroup-DYJ3EYZI.a2542c5f90c4.js → VSlideGroup-CRJazQeR.cb89b2222518.js} +1 -1
- codex/static_root/assets/VSlideGroup-CRJazQeR.cb89b2222518.js.br +0 -0
- codex/static_root/assets/VSlideGroup-CRJazQeR.cb89b2222518.js.gz +0 -0
- codex/static_root/assets/{VSlideGroup-DYJ3EYZI.js → VSlideGroup-CRJazQeR.js} +1 -1
- codex/static_root/assets/VSlideGroup-CRJazQeR.js.br +0 -0
- codex/static_root/assets/VSlideGroup-CRJazQeR.js.gz +0 -0
- codex/static_root/assets/{VTable-BveGtxei.7f76f4ef812b.js → VTable-DtyBEZ5i.6848f15ea03f.js} +1 -1
- codex/static_root/assets/VTable-DtyBEZ5i.6848f15ea03f.js.br +0 -0
- codex/static_root/assets/VTable-DtyBEZ5i.6848f15ea03f.js.gz +0 -0
- codex/static_root/assets/{VTable-BveGtxei.js → VTable-DtyBEZ5i.js} +1 -1
- codex/static_root/assets/VTable-DtyBEZ5i.js.br +0 -0
- codex/static_root/assets/VTable-DtyBEZ5i.js.gz +0 -0
- codex/static_root/assets/VTextField-DEiVah7O.fbf3130f2dea.js +1 -0
- codex/static_root/assets/VTextField-DEiVah7O.fbf3130f2dea.js.br +0 -0
- codex/static_root/assets/VTextField-DEiVah7O.fbf3130f2dea.js.gz +0 -0
- codex/static_root/assets/VTextField-DEiVah7O.js +1 -0
- codex/static_root/assets/VTextField-DEiVah7O.js.br +0 -0
- codex/static_root/assets/VTextField-DEiVah7O.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-FBuIO_rT.8610c7e83905.js → VWindowItem-BVIaHO-S.419e4ecf523d.js} +1 -1
- codex/static_root/assets/VWindowItem-BVIaHO-S.419e4ecf523d.js.br +0 -0
- codex/static_root/assets/VWindowItem-BVIaHO-S.419e4ecf523d.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-FBuIO_rT.js → VWindowItem-BVIaHO-S.js} +1 -1
- codex/static_root/assets/VWindowItem-BVIaHO-S.js.br +0 -0
- codex/static_root/assets/VWindowItem-BVIaHO-S.js.gz +0 -0
- codex/static_root/assets/{admin-B8Bp2Uih.82c98714bcf1.css → admin-D4sw3N4T.b590f88a62cf.css} +1 -1
- codex/static_root/assets/admin-D4sw3N4T.b590f88a62cf.css.br +0 -0
- codex/static_root/assets/admin-D4sw3N4T.b590f88a62cf.css.gz +0 -0
- codex/static_root/assets/{admin-B8Bp2Uih.css → admin-D4sw3N4T.css} +1 -1
- codex/static_root/assets/admin-D4sw3N4T.css.br +0 -0
- codex/static_root/assets/admin-D4sw3N4T.css.gz +0 -0
- codex/static_root/assets/admin-S53JleJt.f629d90f73a1.js +1 -0
- codex/static_root/assets/admin-S53JleJt.f629d90f73a1.js.br +0 -0
- codex/static_root/assets/admin-S53JleJt.f629d90f73a1.js.gz +0 -0
- codex/static_root/assets/admin-S53JleJt.js +1 -0
- codex/static_root/assets/admin-S53JleJt.js.br +0 -0
- codex/static_root/assets/admin-S53JleJt.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-CnAnGx7w.1e4eb021cb21.js +56 -0
- codex/static_root/assets/admin-drawer-panel-CnAnGx7w.1e4eb021cb21.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-CnAnGx7w.1e4eb021cb21.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-CnAnGx7w.js +56 -0
- codex/static_root/assets/admin-drawer-panel-CnAnGx7w.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-CnAnGx7w.js.gz +0 -0
- codex/static_root/assets/browser-BHHgqDP7.7ada4400d63f.js +1 -0
- codex/static_root/assets/browser-BHHgqDP7.7ada4400d63f.js.br +0 -0
- codex/static_root/assets/browser-BHHgqDP7.7ada4400d63f.js.gz +0 -0
- codex/static_root/assets/browser-BHHgqDP7.js +1 -0
- codex/static_root/assets/browser-BHHgqDP7.js.br +0 -0
- codex/static_root/assets/browser-BHHgqDP7.js.gz +0 -0
- codex/static_root/assets/{browser-DP9eEJ0M.css → browser-Cy0OgQJC.css} +1 -1
- codex/static_root/assets/browser-Cy0OgQJC.css.br +0 -0
- codex/static_root/assets/browser-Cy0OgQJC.css.gz +0 -0
- codex/static_root/assets/{browser-DP9eEJ0M.276e8636f8fc.css → browser-Cy0OgQJC.fabbd1aaffcf.css} +1 -1
- codex/static_root/assets/browser-Cy0OgQJC.fabbd1aaffcf.css.br +0 -0
- codex/static_root/assets/browser-Cy0OgQJC.fabbd1aaffcf.css.gz +0 -0
- codex/static_root/assets/change-password-dialog-Du1bwEt1.a4c0205c9bc4.js +1 -0
- codex/static_root/assets/change-password-dialog-Du1bwEt1.a4c0205c9bc4.js.br +0 -0
- codex/static_root/assets/change-password-dialog-Du1bwEt1.a4c0205c9bc4.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-Du1bwEt1.js +1 -0
- codex/static_root/assets/change-password-dialog-Du1bwEt1.js.br +0 -0
- codex/static_root/assets/change-password-dialog-Du1bwEt1.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-eKN71B8a.af6187dc12bd.js +1 -0
- codex/static_root/assets/confirm-dialog-eKN71B8a.af6187dc12bd.js.br +0 -0
- codex/static_root/assets/confirm-dialog-eKN71B8a.af6187dc12bd.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-eKN71B8a.js +1 -0
- codex/static_root/assets/confirm-dialog-eKN71B8a.js.br +0 -0
- codex/static_root/assets/confirm-dialog-eKN71B8a.js.gz +0 -0
- codex/static_root/assets/{datetime-column-uaXWFgF_.29c6d50b483e.js → datetime-column-CWp600fz.e8a969126bf5.js} +1 -1
- codex/static_root/assets/datetime-column-CWp600fz.e8a969126bf5.js.br +0 -0
- codex/static_root/assets/datetime-column-CWp600fz.e8a969126bf5.js.gz +0 -0
- codex/static_root/assets/{datetime-column-uaXWFgF_.js → datetime-column-CWp600fz.js} +1 -1
- codex/static_root/assets/datetime-column-CWp600fz.js.br +0 -0
- codex/static_root/assets/datetime-column-CWp600fz.js.gz +0 -0
- codex/static_root/assets/{filter-DS84uTvk.4fbebd4832bc.js → filter-_XbKRiIR.2c7ac68a2d03.js} +1 -1
- codex/static_root/assets/filter-_XbKRiIR.2c7ac68a2d03.js.br +0 -0
- codex/static_root/assets/filter-_XbKRiIR.2c7ac68a2d03.js.gz +0 -0
- codex/static_root/assets/{filter-DS84uTvk.js → filter-_XbKRiIR.js} +1 -1
- codex/static_root/assets/filter-_XbKRiIR.js.br +0 -0
- codex/static_root/assets/filter-_XbKRiIR.js.gz +0 -0
- codex/static_root/assets/flag-tab-DBqpLKi7.css +1 -0
- codex/static_root/assets/flag-tab-DBqpLKi7.css.br +0 -0
- codex/static_root/assets/flag-tab-DBqpLKi7.css.gz +0 -0
- codex/static_root/assets/flag-tab-DBqpLKi7.dcfef39f541e.css +1 -0
- codex/static_root/assets/flag-tab-DBqpLKi7.dcfef39f541e.css.br +0 -0
- codex/static_root/assets/flag-tab-DBqpLKi7.dcfef39f541e.css.gz +0 -0
- codex/static_root/assets/flag-tab-DR_nY0Jg.7323e386c6ed.js +1 -0
- codex/static_root/assets/flag-tab-DR_nY0Jg.7323e386c6ed.js.br +0 -0
- codex/static_root/assets/flag-tab-DR_nY0Jg.7323e386c6ed.js.gz +0 -0
- codex/static_root/assets/flag-tab-DR_nY0Jg.js +1 -0
- codex/static_root/assets/flag-tab-DR_nY0Jg.js.br +0 -0
- codex/static_root/assets/flag-tab-DR_nY0Jg.js.gz +0 -0
- codex/static_root/assets/group-tab-JKsMHOmK.d2c2f3fceec1.js +1 -0
- codex/static_root/assets/group-tab-JKsMHOmK.d2c2f3fceec1.js.br +0 -0
- codex/static_root/assets/group-tab-JKsMHOmK.d2c2f3fceec1.js.gz +0 -0
- codex/static_root/assets/group-tab-JKsMHOmK.js +1 -0
- codex/static_root/assets/group-tab-JKsMHOmK.js.br +0 -0
- codex/static_root/assets/group-tab-JKsMHOmK.js.gz +0 -0
- codex/static_root/assets/http-error-Bw1wUv3U.c8313a2fb129.js +1 -0
- codex/static_root/assets/http-error-Bw1wUv3U.c8313a2fb129.js.br +0 -0
- codex/static_root/assets/http-error-Bw1wUv3U.c8313a2fb129.js.gz +0 -0
- codex/static_root/assets/http-error-Bw1wUv3U.js +1 -0
- codex/static_root/assets/http-error-Bw1wUv3U.js.br +0 -0
- codex/static_root/assets/http-error-Bw1wUv3U.js.gz +0 -0
- codex/static_root/assets/{library-tab-BN0SfPcH.913e236f625e.css → library-tab-BygwYPnO.94e92aa60bf2.css} +1 -1
- codex/static_root/assets/library-tab-BygwYPnO.94e92aa60bf2.css.br +0 -0
- codex/static_root/assets/library-tab-BygwYPnO.94e92aa60bf2.css.gz +0 -0
- codex/static_root/assets/{library-tab-BN0SfPcH.css → library-tab-BygwYPnO.css} +1 -1
- codex/static_root/assets/library-tab-BygwYPnO.css.br +0 -0
- codex/static_root/assets/library-tab-BygwYPnO.css.gz +0 -0
- codex/static_root/assets/library-tab-D9GTugZ6.8e3e6ebd38b7.js +1 -0
- codex/static_root/assets/library-tab-D9GTugZ6.8e3e6ebd38b7.js.br +0 -0
- codex/static_root/assets/library-tab-D9GTugZ6.8e3e6ebd38b7.js.gz +0 -0
- codex/static_root/assets/library-tab-D9GTugZ6.js +1 -0
- codex/static_root/assets/library-tab-D9GTugZ6.js.br +0 -0
- codex/static_root/assets/library-tab-D9GTugZ6.js.gz +0 -0
- codex/static_root/assets/main-BJiV8IG3.9d708627091f.js +6 -0
- codex/static_root/assets/main-BJiV8IG3.9d708627091f.js.br +0 -0
- codex/static_root/assets/main-BJiV8IG3.9d708627091f.js.gz +0 -0
- codex/static_root/assets/main-BJiV8IG3.js +6 -0
- codex/static_root/assets/main-BJiV8IG3.js.br +0 -0
- codex/static_root/assets/main-BJiV8IG3.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-i2VoXaGH.c3dbb703af2e.js +1 -0
- codex/static_root/assets/pagination-toolbar-i2VoXaGH.c3dbb703af2e.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-i2VoXaGH.c3dbb703af2e.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-i2VoXaGH.js +1 -0
- codex/static_root/assets/pagination-toolbar-i2VoXaGH.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-i2VoXaGH.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-C-4EM9-d.ce9cf66bd4c3.js → pdf-doc-BLxZLD38.4cf9622c535f.js} +1 -1
- codex/static_root/assets/pdf-doc-BLxZLD38.4cf9622c535f.js.br +0 -0
- codex/static_root/assets/pdf-doc-BLxZLD38.4cf9622c535f.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-C-4EM9-d.js → pdf-doc-BLxZLD38.js} +1 -1
- codex/static_root/assets/pdf-doc-BLxZLD38.js.br +0 -0
- codex/static_root/assets/pdf-doc-BLxZLD38.js.gz +0 -0
- codex/static_root/assets/reader-D2O_yHTW.70d616ddc2cc.js +2 -0
- codex/static_root/assets/reader-D2O_yHTW.70d616ddc2cc.js.br +0 -0
- codex/static_root/assets/reader-D2O_yHTW.70d616ddc2cc.js.gz +0 -0
- codex/static_root/assets/reader-D2O_yHTW.js +2 -0
- codex/static_root/assets/reader-D2O_yHTW.js.br +0 -0
- codex/static_root/assets/reader-D2O_yHTW.js.gz +0 -0
- codex/static_root/assets/{reader-DOQuhDYO.css → reader-YbzUiD0T.css} +1 -1
- codex/static_root/assets/reader-YbzUiD0T.css.br +0 -0
- codex/static_root/assets/reader-YbzUiD0T.css.gz +0 -0
- codex/static_root/assets/{reader-DOQuhDYO.df559ad29ab3.css → reader-YbzUiD0T.efb15835b39d.css} +1 -1
- codex/static_root/assets/reader-YbzUiD0T.efb15835b39d.css.br +0 -0
- codex/static_root/assets/reader-YbzUiD0T.efb15835b39d.css.gz +0 -0
- codex/static_root/assets/{relation-chips-Bsc-gUxE.98e65384c3c9.css → relation-chips-BGitp3yx.b3e7d178a615.css} +1 -1
- codex/static_root/assets/relation-chips-BGitp3yx.b3e7d178a615.css.br +0 -0
- codex/static_root/assets/relation-chips-BGitp3yx.b3e7d178a615.css.gz +0 -0
- codex/static_root/assets/{relation-chips-Bsc-gUxE.css → relation-chips-BGitp3yx.css} +1 -1
- codex/static_root/assets/relation-chips-BGitp3yx.css.br +0 -0
- codex/static_root/assets/relation-chips-BGitp3yx.css.gz +0 -0
- codex/static_root/assets/relation-chips-CmeSIsRq.f169f7c3f48d.js +1 -0
- codex/static_root/assets/relation-chips-CmeSIsRq.f169f7c3f48d.js.br +0 -0
- codex/static_root/assets/relation-chips-CmeSIsRq.f169f7c3f48d.js.gz +0 -0
- codex/static_root/assets/relation-chips-CmeSIsRq.js +1 -0
- codex/static_root/assets/relation-chips-CmeSIsRq.js.br +0 -0
- codex/static_root/assets/relation-chips-CmeSIsRq.js.gz +0 -0
- codex/static_root/assets/settings-drawer-XH4sNDNT.98ee4b24901c.js +2 -0
- codex/static_root/assets/settings-drawer-XH4sNDNT.98ee4b24901c.js.br +0 -0
- codex/static_root/assets/settings-drawer-XH4sNDNT.98ee4b24901c.js.gz +0 -0
- codex/static_root/assets/settings-drawer-XH4sNDNT.js +2 -0
- codex/static_root/assets/settings-drawer-XH4sNDNT.js.br +0 -0
- codex/static_root/assets/settings-drawer-XH4sNDNT.js.gz +0 -0
- codex/static_root/assets/stats-tab-BGxkeKnY.44cf18ca895d.js +1 -0
- codex/static_root/assets/stats-tab-BGxkeKnY.44cf18ca895d.js.br +0 -0
- codex/static_root/assets/stats-tab-BGxkeKnY.44cf18ca895d.js.gz +0 -0
- codex/static_root/assets/stats-tab-BGxkeKnY.js +1 -0
- codex/static_root/assets/stats-tab-BGxkeKnY.js.br +0 -0
- codex/static_root/assets/stats-tab-BGxkeKnY.js.gz +0 -0
- codex/static_root/assets/stats-tab-CI0u-X7Y.2d1b6a0d4139.css +1 -0
- codex/static_root/assets/stats-tab-CI0u-X7Y.2d1b6a0d4139.css.br +0 -0
- codex/static_root/assets/stats-tab-CI0u-X7Y.2d1b6a0d4139.css.gz +0 -0
- codex/static_root/assets/stats-tab-CI0u-X7Y.css +1 -0
- codex/static_root/assets/stats-tab-CI0u-X7Y.css.br +0 -0
- codex/static_root/assets/stats-tab-CI0u-X7Y.css.gz +0 -0
- codex/static_root/assets/task-tab-B74Kah_b.58627993d3c6.js +1 -0
- codex/static_root/assets/task-tab-B74Kah_b.58627993d3c6.js.br +0 -0
- codex/static_root/assets/task-tab-B74Kah_b.58627993d3c6.js.gz +0 -0
- codex/static_root/assets/task-tab-B74Kah_b.js +1 -0
- codex/static_root/assets/task-tab-B74Kah_b.js.br +0 -0
- codex/static_root/assets/task-tab-B74Kah_b.js.gz +0 -0
- codex/static_root/assets/unauthorized-BF45der6.d34f8022124b.js +1 -0
- codex/static_root/assets/unauthorized-BF45der6.d34f8022124b.js.br +0 -0
- codex/static_root/assets/unauthorized-BF45der6.d34f8022124b.js.gz +0 -0
- codex/static_root/assets/unauthorized-BF45der6.js +1 -0
- codex/static_root/assets/unauthorized-BF45der6.js.br +0 -0
- codex/static_root/assets/unauthorized-BF45der6.js.gz +0 -0
- codex/static_root/assets/user-tab-BP2TTPg5.e63a5661a1a5.js +1 -0
- codex/static_root/assets/user-tab-BP2TTPg5.e63a5661a1a5.js.br +0 -0
- codex/static_root/assets/user-tab-BP2TTPg5.e63a5661a1a5.js.gz +0 -0
- codex/static_root/assets/user-tab-BP2TTPg5.js +1 -0
- codex/static_root/assets/user-tab-BP2TTPg5.js.br +0 -0
- codex/static_root/assets/user-tab-BP2TTPg5.js.gz +0 -0
- codex/static_root/{manifest.80e911824648.json → manifest.7033f9a22987.json} +230 -242
- codex/static_root/manifest.7033f9a22987.json.br +0 -0
- codex/static_root/manifest.7033f9a22987.json.gz +0 -0
- codex/static_root/manifest.json +230 -242
- codex/static_root/manifest.json.br +0 -0
- codex/static_root/manifest.json.gz +0 -0
- codex/static_root/staticfiles.json +1 -1
- codex/urls/root.py +12 -2
- codex/views/admin/api_key.py +1 -1
- codex/views/admin/flag.py +1 -1
- codex/views/admin/group.py +1 -1
- codex/views/admin/library.py +1 -1
- codex/views/admin/stats.py +41 -155
- codex/views/admin/tasks.py +1 -1
- codex/views/admin/user.py +1 -1
- codex/views/browser/browser.py +4 -1
- codex/views/browser/filters/field.py +15 -6
- codex/views/browser/paginate.py +61 -11
- codex/views/browser/validate.py +7 -5
- codex/views/opds/binary.py +1 -3
- codex/views/opds/const.py +10 -0
- codex/views/opds/util.py +10 -0
- codex/views/opds/v1/entry/entry.py +14 -18
- codex/views/opds/v1/feed.py +10 -24
- codex/views/opds/v1/links.py +1 -0
- codex/views/reader/arcs.py +65 -53
- codex/views/reader/books.py +38 -38
- codex/views/reader/init.py +7 -5
- codex/views/reader/reader.py +0 -2
- {codex-1.6.2.dist-info → codex-1.6.4.dist-info}/METADATA +18 -7
- {codex-1.6.2.dist-info → codex-1.6.4.dist-info}/RECORD +293 -289
- codex/serializers/admin.py +0 -268
- codex/settings/logging.py +0 -20
- codex/static_root/assets/VCheckbox-DUxuAZcY.46ab94043464.js +0 -1
- codex/static_root/assets/VCheckbox-DUxuAZcY.46ab94043464.js.br +0 -0
- codex/static_root/assets/VCheckbox-DUxuAZcY.46ab94043464.js.gz +0 -0
- codex/static_root/assets/VCheckbox-DUxuAZcY.js +0 -1
- codex/static_root/assets/VCheckbox-DUxuAZcY.js.br +0 -0
- codex/static_root/assets/VCheckbox-DUxuAZcY.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-BTFFFGx3.0cbde4eb9a65.js +0 -1
- codex/static_root/assets/VCheckboxBtn-BTFFFGx3.0cbde4eb9a65.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-BTFFFGx3.0cbde4eb9a65.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-BTFFFGx3.js +0 -1
- codex/static_root/assets/VCheckboxBtn-BTFFFGx3.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-BTFFFGx3.js.gz +0 -0
- codex/static_root/assets/VCombobox-CGyBgdqr.2f85598cc1a4.js.br +0 -0
- codex/static_root/assets/VCombobox-CGyBgdqr.2f85598cc1a4.js.gz +0 -0
- codex/static_root/assets/VCombobox-CGyBgdqr.js.br +0 -0
- codex/static_root/assets/VCombobox-CGyBgdqr.js.gz +0 -0
- codex/static_root/assets/VDialog-DTWAoZBU.b8c4c276e9b2.js +0 -1
- codex/static_root/assets/VDialog-DTWAoZBU.b8c4c276e9b2.js.br +0 -0
- codex/static_root/assets/VDialog-DTWAoZBU.b8c4c276e9b2.js.gz +0 -0
- codex/static_root/assets/VDialog-DTWAoZBU.js +0 -1
- codex/static_root/assets/VDialog-DTWAoZBU.js.br +0 -0
- codex/static_root/assets/VDialog-DTWAoZBU.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-D4psrz4h.b55b901da65f.js +0 -1
- codex/static_root/assets/VExpansionPanels-D4psrz4h.b55b901da65f.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-D4psrz4h.b55b901da65f.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-D4psrz4h.js +0 -1
- codex/static_root/assets/VExpansionPanels-D4psrz4h.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-D4psrz4h.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-BY572TP-.6d47a94795de.js +0 -1
- codex/static_root/assets/VRadioGroup-BY572TP-.6d47a94795de.js.br +0 -2
- codex/static_root/assets/VRadioGroup-BY572TP-.6d47a94795de.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-BY572TP-.js +0 -1
- codex/static_root/assets/VRadioGroup-BY572TP-.js.br +0 -2
- codex/static_root/assets/VRadioGroup-BY572TP-.js.gz +0 -0
- codex/static_root/assets/VSelect-Bnhj5kBc.fdcd87c9e253.js +0 -1
- codex/static_root/assets/VSelect-Bnhj5kBc.fdcd87c9e253.js.br +0 -0
- codex/static_root/assets/VSelect-Bnhj5kBc.fdcd87c9e253.js.gz +0 -0
- codex/static_root/assets/VSelect-Bnhj5kBc.js +0 -1
- codex/static_root/assets/VSelect-Bnhj5kBc.js.br +0 -0
- codex/static_root/assets/VSelect-Bnhj5kBc.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-DXxRmssH.252890f79cc6.js.br +0 -0
- codex/static_root/assets/VSelectionControl-DXxRmssH.252890f79cc6.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-DXxRmssH.js.br +0 -0
- codex/static_root/assets/VSelectionControl-DXxRmssH.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-DYJ3EYZI.a2542c5f90c4.js.br +0 -0
- codex/static_root/assets/VSlideGroup-DYJ3EYZI.a2542c5f90c4.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-DYJ3EYZI.js.br +0 -0
- codex/static_root/assets/VSlideGroup-DYJ3EYZI.js.gz +0 -0
- codex/static_root/assets/VTable-BveGtxei.7f76f4ef812b.js.br +0 -0
- codex/static_root/assets/VTable-BveGtxei.7f76f4ef812b.js.gz +0 -0
- codex/static_root/assets/VTable-BveGtxei.js.br +0 -0
- codex/static_root/assets/VTable-BveGtxei.js.gz +0 -0
- codex/static_root/assets/VTextField-BayL7C1D.6e53c61b3760.js +0 -1
- codex/static_root/assets/VTextField-BayL7C1D.6e53c61b3760.js.br +0 -0
- codex/static_root/assets/VTextField-BayL7C1D.6e53c61b3760.js.gz +0 -0
- codex/static_root/assets/VTextField-BayL7C1D.js +0 -1
- codex/static_root/assets/VTextField-BayL7C1D.js.br +0 -0
- codex/static_root/assets/VTextField-BayL7C1D.js.gz +0 -0
- codex/static_root/assets/VWindowItem-FBuIO_rT.8610c7e83905.js.br +0 -0
- codex/static_root/assets/VWindowItem-FBuIO_rT.8610c7e83905.js.gz +0 -0
- codex/static_root/assets/VWindowItem-FBuIO_rT.js.br +0 -0
- codex/static_root/assets/VWindowItem-FBuIO_rT.js.gz +0 -0
- codex/static_root/assets/admin-B8Bp2Uih.82c98714bcf1.css.br +0 -0
- codex/static_root/assets/admin-B8Bp2Uih.82c98714bcf1.css.gz +0 -0
- codex/static_root/assets/admin-B8Bp2Uih.css.br +0 -0
- codex/static_root/assets/admin-B8Bp2Uih.css.gz +0 -0
- codex/static_root/assets/admin-BH6uiYBb.d51c720fa05c.js +0 -1
- codex/static_root/assets/admin-BH6uiYBb.d51c720fa05c.js.br +0 -0
- codex/static_root/assets/admin-BH6uiYBb.d51c720fa05c.js.gz +0 -0
- codex/static_root/assets/admin-BH6uiYBb.js +0 -1
- codex/static_root/assets/admin-BH6uiYBb.js.br +0 -0
- codex/static_root/assets/admin-BH6uiYBb.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-DsgLbfnD.7c409b430d79.js +0 -30
- codex/static_root/assets/admin-drawer-panel-DsgLbfnD.7c409b430d79.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-DsgLbfnD.7c409b430d79.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-DsgLbfnD.js +0 -30
- codex/static_root/assets/admin-drawer-panel-DsgLbfnD.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-DsgLbfnD.js.gz +0 -0
- codex/static_root/assets/browser-BVciW8XB.ab1d75272aa7.js +0 -1
- codex/static_root/assets/browser-BVciW8XB.ab1d75272aa7.js.br +0 -0
- codex/static_root/assets/browser-BVciW8XB.ab1d75272aa7.js.gz +0 -0
- codex/static_root/assets/browser-BVciW8XB.js +0 -1
- codex/static_root/assets/browser-BVciW8XB.js.br +0 -0
- codex/static_root/assets/browser-BVciW8XB.js.gz +0 -0
- codex/static_root/assets/browser-DP9eEJ0M.276e8636f8fc.css.br +0 -0
- codex/static_root/assets/browser-DP9eEJ0M.276e8636f8fc.css.gz +0 -0
- codex/static_root/assets/browser-DP9eEJ0M.css.br +0 -0
- codex/static_root/assets/browser-DP9eEJ0M.css.gz +0 -0
- codex/static_root/assets/change-password-dialog-B-Sd5U5p.adf0a0f02866.js +0 -1
- codex/static_root/assets/change-password-dialog-B-Sd5U5p.adf0a0f02866.js.br +0 -0
- codex/static_root/assets/change-password-dialog-B-Sd5U5p.adf0a0f02866.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-B-Sd5U5p.js +0 -1
- codex/static_root/assets/change-password-dialog-B-Sd5U5p.js.br +0 -0
- codex/static_root/assets/change-password-dialog-B-Sd5U5p.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CYEBgtj5.a5f142656c12.js +0 -1
- codex/static_root/assets/confirm-dialog-CYEBgtj5.a5f142656c12.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CYEBgtj5.a5f142656c12.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CYEBgtj5.js +0 -1
- codex/static_root/assets/confirm-dialog-CYEBgtj5.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CYEBgtj5.js.gz +0 -0
- codex/static_root/assets/datetime-column-uaXWFgF_.29c6d50b483e.js.br +0 -0
- codex/static_root/assets/datetime-column-uaXWFgF_.29c6d50b483e.js.gz +0 -0
- codex/static_root/assets/datetime-column-uaXWFgF_.js.br +0 -0
- codex/static_root/assets/datetime-column-uaXWFgF_.js.gz +0 -0
- codex/static_root/assets/filter-DS84uTvk.4fbebd4832bc.js.br +0 -0
- codex/static_root/assets/filter-DS84uTvk.4fbebd4832bc.js.gz +0 -0
- codex/static_root/assets/filter-DS84uTvk.js.br +0 -0
- codex/static_root/assets/filter-DS84uTvk.js.gz +0 -0
- codex/static_root/assets/flag-tab-BNwbLfrN.b755a99fff7e.css +0 -1
- codex/static_root/assets/flag-tab-BNwbLfrN.b755a99fff7e.css.br +0 -0
- codex/static_root/assets/flag-tab-BNwbLfrN.b755a99fff7e.css.gz +0 -0
- codex/static_root/assets/flag-tab-BNwbLfrN.css +0 -1
- codex/static_root/assets/flag-tab-BNwbLfrN.css.br +0 -0
- codex/static_root/assets/flag-tab-BNwbLfrN.css.gz +0 -0
- codex/static_root/assets/flag-tab-iJTJldQ1.213201f8e03b.js +0 -1
- codex/static_root/assets/flag-tab-iJTJldQ1.213201f8e03b.js.br +0 -0
- codex/static_root/assets/flag-tab-iJTJldQ1.213201f8e03b.js.gz +0 -0
- codex/static_root/assets/flag-tab-iJTJldQ1.js +0 -1
- codex/static_root/assets/flag-tab-iJTJldQ1.js.br +0 -0
- codex/static_root/assets/flag-tab-iJTJldQ1.js.gz +0 -0
- codex/static_root/assets/group-tab-DdmGE4gB.48ef83a4c7cd.js +0 -1
- codex/static_root/assets/group-tab-DdmGE4gB.48ef83a4c7cd.js.br +0 -0
- codex/static_root/assets/group-tab-DdmGE4gB.48ef83a4c7cd.js.gz +0 -0
- codex/static_root/assets/group-tab-DdmGE4gB.js +0 -1
- codex/static_root/assets/group-tab-DdmGE4gB.js.br +0 -0
- codex/static_root/assets/group-tab-DdmGE4gB.js.gz +0 -0
- codex/static_root/assets/http-error-HtOe8jPa.141ad665f81d.js +0 -1
- codex/static_root/assets/http-error-HtOe8jPa.141ad665f81d.js.br +0 -0
- codex/static_root/assets/http-error-HtOe8jPa.141ad665f81d.js.gz +0 -0
- codex/static_root/assets/http-error-HtOe8jPa.js +0 -1
- codex/static_root/assets/http-error-HtOe8jPa.js.br +0 -0
- codex/static_root/assets/http-error-HtOe8jPa.js.gz +0 -0
- codex/static_root/assets/library-tab-BN0SfPcH.913e236f625e.css.br +0 -0
- codex/static_root/assets/library-tab-BN0SfPcH.913e236f625e.css.gz +0 -0
- codex/static_root/assets/library-tab-BN0SfPcH.css.br +0 -0
- codex/static_root/assets/library-tab-BN0SfPcH.css.gz +0 -0
- codex/static_root/assets/library-tab-DLAJV6j2.dae6292bbf28.js +0 -1
- codex/static_root/assets/library-tab-DLAJV6j2.dae6292bbf28.js.br +0 -0
- codex/static_root/assets/library-tab-DLAJV6j2.dae6292bbf28.js.gz +0 -0
- codex/static_root/assets/library-tab-DLAJV6j2.js +0 -1
- codex/static_root/assets/library-tab-DLAJV6j2.js.br +0 -0
- codex/static_root/assets/library-tab-DLAJV6j2.js.gz +0 -0
- codex/static_root/assets/main-BjGE3kSi.22c1b19a9e19.js +0 -32
- codex/static_root/assets/main-BjGE3kSi.22c1b19a9e19.js.br +0 -0
- codex/static_root/assets/main-BjGE3kSi.22c1b19a9e19.js.gz +0 -0
- codex/static_root/assets/main-BjGE3kSi.js +0 -32
- codex/static_root/assets/main-BjGE3kSi.js.br +0 -0
- codex/static_root/assets/main-BjGE3kSi.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-C8CSryCU.9b61f95fd710.js +0 -1
- codex/static_root/assets/pagination-toolbar-C8CSryCU.9b61f95fd710.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-C8CSryCU.9b61f95fd710.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-C8CSryCU.js +0 -1
- codex/static_root/assets/pagination-toolbar-C8CSryCU.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-C8CSryCU.js.gz +0 -0
- codex/static_root/assets/pdf-doc-C-4EM9-d.ce9cf66bd4c3.js.br +0 -0
- codex/static_root/assets/pdf-doc-C-4EM9-d.ce9cf66bd4c3.js.gz +0 -0
- codex/static_root/assets/pdf-doc-C-4EM9-d.js.br +0 -0
- codex/static_root/assets/pdf-doc-C-4EM9-d.js.gz +0 -0
- codex/static_root/assets/reader-C5OTEQ7N.fae52c1fee51.js +0 -2
- codex/static_root/assets/reader-C5OTEQ7N.fae52c1fee51.js.br +0 -0
- codex/static_root/assets/reader-C5OTEQ7N.fae52c1fee51.js.gz +0 -0
- codex/static_root/assets/reader-C5OTEQ7N.js +0 -2
- codex/static_root/assets/reader-C5OTEQ7N.js.br +0 -0
- codex/static_root/assets/reader-C5OTEQ7N.js.gz +0 -0
- codex/static_root/assets/reader-DOQuhDYO.css.br +0 -0
- codex/static_root/assets/reader-DOQuhDYO.css.gz +0 -0
- codex/static_root/assets/reader-DOQuhDYO.df559ad29ab3.css.br +0 -0
- codex/static_root/assets/reader-DOQuhDYO.df559ad29ab3.css.gz +0 -0
- codex/static_root/assets/relation-chips-Bsc-gUxE.98e65384c3c9.css.br +0 -0
- codex/static_root/assets/relation-chips-Bsc-gUxE.98e65384c3c9.css.gz +0 -0
- codex/static_root/assets/relation-chips-Bsc-gUxE.css.br +0 -0
- codex/static_root/assets/relation-chips-Bsc-gUxE.css.gz +0 -0
- codex/static_root/assets/relation-chips-C4LQSHRc.3c85433df91c.js +0 -1
- codex/static_root/assets/relation-chips-C4LQSHRc.3c85433df91c.js.br +0 -0
- codex/static_root/assets/relation-chips-C4LQSHRc.3c85433df91c.js.gz +0 -0
- codex/static_root/assets/relation-chips-C4LQSHRc.js +0 -1
- codex/static_root/assets/relation-chips-C4LQSHRc.js.br +0 -0
- codex/static_root/assets/relation-chips-C4LQSHRc.js.gz +0 -0
- codex/static_root/assets/settings-drawer-aTAAoX2A.2f21008ade35.js +0 -2
- codex/static_root/assets/settings-drawer-aTAAoX2A.2f21008ade35.js.br +0 -0
- codex/static_root/assets/settings-drawer-aTAAoX2A.2f21008ade35.js.gz +0 -0
- codex/static_root/assets/settings-drawer-aTAAoX2A.js +0 -2
- codex/static_root/assets/settings-drawer-aTAAoX2A.js.br +0 -0
- codex/static_root/assets/settings-drawer-aTAAoX2A.js.gz +0 -0
- codex/static_root/assets/stats-tab-B4yKuY0c.a5728396494b.css +0 -1
- codex/static_root/assets/stats-tab-B4yKuY0c.a5728396494b.css.br +0 -0
- codex/static_root/assets/stats-tab-B4yKuY0c.a5728396494b.css.gz +0 -0
- codex/static_root/assets/stats-tab-B4yKuY0c.css +0 -1
- codex/static_root/assets/stats-tab-B4yKuY0c.css.br +0 -0
- codex/static_root/assets/stats-tab-B4yKuY0c.css.gz +0 -0
- codex/static_root/assets/stats-tab-DL4J3pvZ.b9056e70a70f.js +0 -1
- codex/static_root/assets/stats-tab-DL4J3pvZ.b9056e70a70f.js.br +0 -0
- codex/static_root/assets/stats-tab-DL4J3pvZ.b9056e70a70f.js.gz +0 -0
- codex/static_root/assets/stats-tab-DL4J3pvZ.js +0 -1
- codex/static_root/assets/stats-tab-DL4J3pvZ.js.br +0 -0
- codex/static_root/assets/stats-tab-DL4J3pvZ.js.gz +0 -0
- codex/static_root/assets/task-tab-0t7ZJlwL.1ff1cc14a6aa.js +0 -1
- codex/static_root/assets/task-tab-0t7ZJlwL.1ff1cc14a6aa.js.br +0 -0
- codex/static_root/assets/task-tab-0t7ZJlwL.1ff1cc14a6aa.js.gz +0 -0
- codex/static_root/assets/task-tab-0t7ZJlwL.js +0 -1
- codex/static_root/assets/task-tab-0t7ZJlwL.js.br +0 -0
- codex/static_root/assets/task-tab-0t7ZJlwL.js.gz +0 -0
- codex/static_root/assets/to-case-BCB751sX.4afb5ae1b77d.js +0 -1
- codex/static_root/assets/to-case-BCB751sX.js +0 -1
- codex/static_root/assets/unauthorized-Ovy_BO5R.598527e8e4fe.js +0 -1
- codex/static_root/assets/unauthorized-Ovy_BO5R.598527e8e4fe.js.br +0 -0
- codex/static_root/assets/unauthorized-Ovy_BO5R.598527e8e4fe.js.gz +0 -0
- codex/static_root/assets/unauthorized-Ovy_BO5R.js +0 -1
- codex/static_root/assets/unauthorized-Ovy_BO5R.js.br +0 -0
- codex/static_root/assets/unauthorized-Ovy_BO5R.js.gz +0 -0
- codex/static_root/assets/user-tab-Cdspo8ie.8e886a1a28e8.js +0 -1
- codex/static_root/assets/user-tab-Cdspo8ie.8e886a1a28e8.js.br +0 -0
- codex/static_root/assets/user-tab-Cdspo8ie.8e886a1a28e8.js.gz +0 -0
- codex/static_root/assets/user-tab-Cdspo8ie.js +0 -1
- codex/static_root/assets/user-tab-Cdspo8ie.js.br +0 -0
- codex/static_root/assets/user-tab-Cdspo8ie.js.gz +0 -0
- codex/static_root/manifest.80e911824648.json.br +0 -0
- codex/static_root/manifest.80e911824648.json.gz +0 -0
- {codex-1.6.2.dist-info → codex-1.6.4.dist-info}/LICENSE +0 -0
- {codex-1.6.2.dist-info → codex-1.6.4.dist-info}/WHEEL +0 -0
- {codex-1.6.2.dist-info → codex-1.6.4.dist-info}/entry_points.txt +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"paths": {"rest_framework/docs/js/api.js": "rest_framework/docs/js/api.18a5ba8a1bd8.js", "rest_framework/docs/js/jquery.json-view.min.js": "rest_framework/docs/js/jquery.json-view.min.b7c2d6981377.js", "rest_framework/docs/js/highlight.pack.js": "rest_framework/docs/js/highlight.pack.479b5f21dcba.js", "rest_framework/docs/img/favicon.ico": "rest_framework/docs/img/favicon.5195b4d0f3eb.ico", "rest_framework/docs/img/grid.png": "rest_framework/docs/img/grid.a4b938cf382b.png", "rest_framework/docs/css/jquery.json-view.min.css": "rest_framework/docs/css/jquery.json-view.min.a2e6beeb6710.css", "rest_framework/docs/css/highlight.css": "rest_framework/docs/css/highlight.e0e4d973c6d7.css", "rest_framework/docs/css/base.css": "rest_framework/docs/css/base.e630f8f4990e.css", "rest_framework/js/ajax-form.js": "rest_framework/js/ajax-form.4e1cdcb7acab.js", "rest_framework/js/csrf.js": "rest_framework/js/csrf.455080a7b2ce.js", "rest_framework/js/prettify-min.js": "rest_framework/js/prettify-min.709bfcc456c6.js", "rest_framework/js/jquery-3.7.1.min.js": "rest_framework/js/jquery-3.7.1.min.2c872dbe60f4.js", "rest_framework/js/default.js": "rest_framework/js/default.5b08897dbdc3.js", "rest_framework/js/bootstrap.min.js": "rest_framework/js/bootstrap.min.2f34b630ffe3.js", "rest_framework/js/coreapi-0.1.1.js": "rest_framework/js/coreapi-0.1.1.8851fb9336c9.js", "rest_framework/js/load-ajax-form.js": "rest_framework/js/load-ajax-form.8cdb3a9f3466.js", "rest_framework/fonts/fontawesome-webfont.woff": "rest_framework/fonts/fontawesome-webfont.3293616ec0c6.woff", "rest_framework/fonts/glyphicons-halflings-regular.eot": "rest_framework/fonts/glyphicons-halflings-regular.f4769f9bdb74.eot", "rest_framework/fonts/glyphicons-halflings-regular.ttf": "rest_framework/fonts/glyphicons-halflings-regular.e18bbf611f2a.ttf", "rest_framework/fonts/fontawesome-webfont.ttf": "rest_framework/fonts/fontawesome-webfont.dcb26c7239d8.ttf", "rest_framework/fonts/glyphicons-halflings-regular.woff2": "rest_framework/fonts/glyphicons-halflings-regular.448c34a56d69.woff2", "rest_framework/fonts/fontawesome-webfont.svg": "rest_framework/fonts/fontawesome-webfont.83e37a11f9d7.svg", "rest_framework/fonts/glyphicons-halflings-regular.woff": "rest_framework/fonts/glyphicons-halflings-regular.fa2772327f55.woff", "rest_framework/fonts/glyphicons-halflings-regular.svg": "rest_framework/fonts/glyphicons-halflings-regular.08eda92397ae.svg", "rest_framework/fonts/fontawesome-webfont.eot": "rest_framework/fonts/fontawesome-webfont.8b27bc96115c.eot", "rest_framework/img/glyphicons-halflings-white.png": "rest_framework/img/glyphicons-halflings-white.9bbc6e960299.png", "rest_framework/img/glyphicons-halflings.png": "rest_framework/img/glyphicons-halflings.90233c9067e9.png", "rest_framework/img/grid.png": "rest_framework/img/grid.a4b938cf382b.png", "rest_framework/css/bootstrap.min.css.map": "rest_framework/css/bootstrap.min.css.cafbda9c0e9e.map", "rest_framework/css/default.css": "rest_framework/css/default.789dfb5732d7.css", "rest_framework/css/bootstrap.min.css": "rest_framework/css/bootstrap.min.f17d4516b026.css", "rest_framework/css/prettify.css": "rest_framework/css/prettify.a987f72342ee.css", "rest_framework/css/bootstrap-theme.min.css": "rest_framework/css/bootstrap-theme.min.1d4b05b397c3.css", "rest_framework/css/bootstrap-tweaks.css": "rest_framework/css/bootstrap-tweaks.ee4ee6acf9eb.css", "rest_framework/css/font-awesome-4.0.3.css": "rest_framework/css/font-awesome-4.0.3.c1e1ea213abf.css", "rest_framework/css/bootstrap-theme.min.css.map": "rest_framework/css/bootstrap-theme.min.css.51806092cc05.map", "img/publisher.svg": "img/publisher.82d378fcd601.svg", "img/logo-32.webp": "img/logo-32.5688944495bf.webp", "img/logo.svg": "img/logo.0f5344a028ca.svg", "img/story-arc.svg": "img/story-arc.ca10014355ef.svg", "img/missing-cover-165.webp": "img/missing-cover-165.0743171f2148.webp", "img/series.svg": "img/series.ec8a889b8f95.svg", "img/logo-maskable-180.webp": "img/logo-maskable-180.c58d966aa64e.webp", "img/missing-cover.svg": "img/missing-cover.ddb038cc2c56.svg", "img/folder.svg": "img/folder.f28936a3701d.svg", "img/volume.svg": "img/volume.814e4c79461a.svg", "img/logo-maskable.svg": "img/logo-maskable.8f7de7f1c6a8.svg", "img/imprint.svg": "img/imprint.7c2adebb76d6.svg", "pwa/offline.html": "pwa/offline.7bfaf9f94bf9.html", "js/choices.json": "js/choices.2f6b0359e1ef.json", "js/choices-admin.json": "js/choices-admin.3521e2a863df.json", "assets/relation-chips-Bsc-gUxE.css": "assets/relation-chips-Bsc-gUxE.98e65384c3c9.css", "assets/group-tab-CBKuS3Iv.css": "assets/group-tab-CBKuS3Iv.7e4746634782.css", "assets/http-error-DKulXuTl.css": "assets/http-error-DKulXuTl.95e42988d5d5.css", "assets/VSelect-ARDhJiQK.css": "assets/VSelect-ARDhJiQK.372c098fb475.css", "assets/flag-tab-BNwbLfrN.css": "assets/flag-tab-BNwbLfrN.b755a99fff7e.css", "assets/admin-BH6uiYBb.js": "assets/admin-BH6uiYBb.d51c720fa05c.js", "assets/http-error-HtOe8jPa.js": "assets/http-error-HtOe8jPa.141ad665f81d.js", "assets/browser-DP9eEJ0M.css": "assets/browser-DP9eEJ0M.276e8636f8fc.css", "assets/group-tab-DdmGE4gB.js": "assets/group-tab-DdmGE4gB.48ef83a4c7cd.js", "assets/VSelectionControl-BFq--28I.css": "assets/VSelectionControl-BFq--28I.9687c77461fc.css", "assets/filter-DS84uTvk.js": "assets/filter-DS84uTvk.4fbebd4832bc.js", "assets/pdf-doc-CMzaSV_K.css": "assets/pdf-doc-CMzaSV_K.8cd4b3e65f9a.css", "assets/VWindowItem-FBuIO_rT.js": "assets/VWindowItem-FBuIO_rT.8610c7e83905.js", "assets/materialdesignicons-webfont-PXm3-2wK.woff": "assets/materialdesignicons-webfont-PXm3-2wK.026b7ac9c43c.woff", "assets/VSlideGroup-Dk_1upHt.css": "assets/VSlideGroup-Dk_1upHt.2c836070ec75.css", "assets/admin-drawer-panel-mne3FIj6.css": "assets/admin-drawer-panel-mne3FIj6.561b3f75fe65.css", "assets/VTable-DflzroDq.css": "assets/VTable-DflzroDq.160504d82195.css", "assets/settings-drawer-nZ9HvKSZ.css": "assets/settings-drawer-nZ9HvKSZ.01744e131806.css", "assets/VDialog-lQ13FnRR.css": "assets/VDialog-lQ13FnRR.1c801ad756b2.css", "assets/library-tab-DLAJV6j2.js": "assets/library-tab-DLAJV6j2.dae6292bbf28.js", "assets/flag-tab-iJTJldQ1.js": "assets/flag-tab-iJTJldQ1.213201f8e03b.js", "assets/main-Ztp855PW.css": "assets/main-Ztp855PW.d46d718fac45.css", "assets/VRadioGroup-i2qP9Wu9.css": "assets/VRadioGroup-i2qP9Wu9.8e3741381961.css", "assets/pagination-toolbar-C8CSryCU.js": "assets/pagination-toolbar-C8CSryCU.9b61f95fd710.js", "assets/VSelect-Bnhj5kBc.js": "assets/VSelect-Bnhj5kBc.fdcd87c9e253.js", "assets/to-case-BCB751sX.js": "assets/to-case-BCB751sX.4afb5ae1b77d.js", "assets/VCheckboxBtn-BTFFFGx3.js": "assets/VCheckboxBtn-BTFFFGx3.0cbde4eb9a65.js", "assets/change-password-dialog-0u6IJA87.css": "assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css", "assets/VTable-BveGtxei.js": "assets/VTable-BveGtxei.7f76f4ef812b.js", "assets/copy-to-clipboard-DoUvDJVx.js": "assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js", "assets/VDialog-DTWAoZBU.js": "assets/VDialog-DTWAoZBU.b8c4c276e9b2.js", "assets/browser-BVciW8XB.js": "assets/browser-BVciW8XB.ab1d75272aa7.js", "assets/VWindowItem-ByIod57Y.css": "assets/VWindowItem-ByIod57Y.f7fb19752bf3.css", "assets/main-BjGE3kSi.js": "assets/main-BjGE3kSi.22c1b19a9e19.js", "assets/datetime-column-uaXWFgF_.js": "assets/datetime-column-uaXWFgF_.29c6d50b483e.js", "assets/VCheckbox-DUxuAZcY.js": "assets/VCheckbox-DUxuAZcY.46ab94043464.js", "assets/pagination-toolbar-BA9ifTed.css": "assets/pagination-toolbar-BA9ifTed.b4865334ee08.css", "assets/user-tab-Cdspo8ie.js": "assets/user-tab-Cdspo8ie.8e886a1a28e8.js", "assets/relation-chips-C4LQSHRc.js": "assets/relation-chips-C4LQSHRc.3c85433df91c.js", "assets/reader-C5OTEQ7N.js": "assets/reader-C5OTEQ7N.fae52c1fee51.js", "assets/library-tab-BN0SfPcH.css": "assets/library-tab-BN0SfPcH.913e236f625e.css", "assets/confirm-dialog-BmhedLCx.css": "assets/confirm-dialog-BmhedLCx.7c2103d319d4.css", "assets/materialdesignicons-webfont-B7mPwVP_.ttf": "assets/materialdesignicons-webfont-B7mPwVP_.6e435534bd35.ttf", "assets/admin-drawer-panel-DsgLbfnD.js": "assets/admin-drawer-panel-DsgLbfnD.7c409b430d79.js", "assets/task-tab-0t7ZJlwL.js": "assets/task-tab-0t7ZJlwL.1ff1cc14a6aa.js", "assets/VRadioGroup-BY572TP-.js": "assets/VRadioGroup-BY572TP-.6d47a94795de.js", "assets/pdf-doc-C-4EM9-d.js": "assets/pdf-doc-C-4EM9-d.ce9cf66bd4c3.js", "assets/VCombobox-BksEr4D_.css": "assets/VCombobox-BksEr4D_.73429bb75f42.css", "assets/change-password-dialog-B-Sd5U5p.js": "assets/change-password-dialog-B-Sd5U5p.adf0a0f02866.js", "assets/VSlideGroup-DYJ3EYZI.js": "assets/VSlideGroup-DYJ3EYZI.a2542c5f90c4.js", "assets/unauthorized-Ovy_BO5R.js": "assets/unauthorized-Ovy_BO5R.598527e8e4fe.js", "assets/admin-B8Bp2Uih.css": "assets/admin-B8Bp2Uih.82c98714bcf1.css", "assets/VSelectionControl-DXxRmssH.js": "assets/VSelectionControl-DXxRmssH.252890f79cc6.js", "assets/settings-drawer-aTAAoX2A.js": "assets/settings-drawer-aTAAoX2A.2f21008ade35.js", "assets/task-tab-1XiWn9xP.css": "assets/task-tab-1XiWn9xP.06cb8e1b794d.css", "assets/VTextField-BayL7C1D.js": "assets/VTextField-BayL7C1D.6e53c61b3760.js", "assets/stats-tab-B4yKuY0c.css": "assets/stats-tab-B4yKuY0c.a5728396494b.css", "assets/datetime-column-DeCthByU.css": "assets/datetime-column-DeCthByU.1f3bf499e063.css", "assets/materialdesignicons-webfont-CSr8KVlo.eot": "assets/materialdesignicons-webfont-CSr8KVlo.8ced95a05e3c.eot", "assets/reader-DOQuhDYO.css": "assets/reader-DOQuhDYO.df559ad29ab3.css", "assets/unauthorized-DWDO1s6-.css": "assets/unauthorized-DWDO1s6-.d34daac27dcf.css", "assets/VExpansionPanels-DsEXVcCv.css": "assets/VExpansionPanels-DsEXVcCv.20b475255e66.css", "assets/VExpansionPanels-D4psrz4h.js": "assets/VExpansionPanels-D4psrz4h.b55b901da65f.js", "assets/VCheckbox-CMKdyl0R.css": "assets/VCheckbox-CMKdyl0R.016ed8d222c4.css", "assets/stats-tab-DL4J3pvZ.js": "assets/stats-tab-DL4J3pvZ.b9056e70a70f.js", "assets/VTextField-BssVoDhB.css": "assets/VTextField-BssVoDhB.4cc388b4aa3c.css", "assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "assets/materialdesignicons-webfont-Dp5v-WZN.1d7bcee1b302.woff2", "assets/VCombobox-CGyBgdqr.js": "assets/VCombobox-CGyBgdqr.2f85598cc1a4.js", "assets/confirm-dialog-CYEBgtj5.js": "assets/confirm-dialog-CYEBgtj5.a5f142656c12.js", "robots.txt": "robots.b6216d61c03e.txt", "manifest.json": "manifest.80e911824648.json"}, "version": "1.1", "hash": "5a4e0c1aba28"}
|
|
1
|
+
{"paths": {"rest_framework/docs/js/api.js": "rest_framework/docs/js/api.18a5ba8a1bd8.js", "rest_framework/docs/js/jquery.json-view.min.js": "rest_framework/docs/js/jquery.json-view.min.b7c2d6981377.js", "rest_framework/docs/js/highlight.pack.js": "rest_framework/docs/js/highlight.pack.479b5f21dcba.js", "rest_framework/docs/img/favicon.ico": "rest_framework/docs/img/favicon.5195b4d0f3eb.ico", "rest_framework/docs/img/grid.png": "rest_framework/docs/img/grid.a4b938cf382b.png", "rest_framework/docs/css/jquery.json-view.min.css": "rest_framework/docs/css/jquery.json-view.min.a2e6beeb6710.css", "rest_framework/docs/css/highlight.css": "rest_framework/docs/css/highlight.e0e4d973c6d7.css", "rest_framework/docs/css/base.css": "rest_framework/docs/css/base.e630f8f4990e.css", "rest_framework/js/ajax-form.js": "rest_framework/js/ajax-form.4e1cdcb7acab.js", "rest_framework/js/csrf.js": "rest_framework/js/csrf.455080a7b2ce.js", "rest_framework/js/prettify-min.js": "rest_framework/js/prettify-min.709bfcc456c6.js", "rest_framework/js/jquery-3.7.1.min.js": "rest_framework/js/jquery-3.7.1.min.2c872dbe60f4.js", "rest_framework/js/default.js": "rest_framework/js/default.5b08897dbdc3.js", "rest_framework/js/bootstrap.min.js": "rest_framework/js/bootstrap.min.2f34b630ffe3.js", "rest_framework/js/coreapi-0.1.1.js": "rest_framework/js/coreapi-0.1.1.8851fb9336c9.js", "rest_framework/js/load-ajax-form.js": "rest_framework/js/load-ajax-form.8cdb3a9f3466.js", "rest_framework/fonts/fontawesome-webfont.woff": "rest_framework/fonts/fontawesome-webfont.3293616ec0c6.woff", "rest_framework/fonts/glyphicons-halflings-regular.eot": "rest_framework/fonts/glyphicons-halflings-regular.f4769f9bdb74.eot", "rest_framework/fonts/glyphicons-halflings-regular.ttf": "rest_framework/fonts/glyphicons-halflings-regular.e18bbf611f2a.ttf", "rest_framework/fonts/fontawesome-webfont.ttf": "rest_framework/fonts/fontawesome-webfont.dcb26c7239d8.ttf", "rest_framework/fonts/glyphicons-halflings-regular.woff2": "rest_framework/fonts/glyphicons-halflings-regular.448c34a56d69.woff2", "rest_framework/fonts/fontawesome-webfont.svg": "rest_framework/fonts/fontawesome-webfont.83e37a11f9d7.svg", "rest_framework/fonts/glyphicons-halflings-regular.woff": "rest_framework/fonts/glyphicons-halflings-regular.fa2772327f55.woff", "rest_framework/fonts/glyphicons-halflings-regular.svg": "rest_framework/fonts/glyphicons-halflings-regular.08eda92397ae.svg", "rest_framework/fonts/fontawesome-webfont.eot": "rest_framework/fonts/fontawesome-webfont.8b27bc96115c.eot", "rest_framework/img/glyphicons-halflings-white.png": "rest_framework/img/glyphicons-halflings-white.9bbc6e960299.png", "rest_framework/img/glyphicons-halflings.png": "rest_framework/img/glyphicons-halflings.90233c9067e9.png", "rest_framework/img/grid.png": "rest_framework/img/grid.a4b938cf382b.png", "rest_framework/css/bootstrap.min.css.map": "rest_framework/css/bootstrap.min.css.cafbda9c0e9e.map", "rest_framework/css/default.css": "rest_framework/css/default.789dfb5732d7.css", "rest_framework/css/bootstrap.min.css": "rest_framework/css/bootstrap.min.f17d4516b026.css", "rest_framework/css/prettify.css": "rest_framework/css/prettify.a987f72342ee.css", "rest_framework/css/bootstrap-theme.min.css": "rest_framework/css/bootstrap-theme.min.1d4b05b397c3.css", "rest_framework/css/bootstrap-tweaks.css": "rest_framework/css/bootstrap-tweaks.ee4ee6acf9eb.css", "rest_framework/css/font-awesome-4.0.3.css": "rest_framework/css/font-awesome-4.0.3.c1e1ea213abf.css", "rest_framework/css/bootstrap-theme.min.css.map": "rest_framework/css/bootstrap-theme.min.css.51806092cc05.map", "img/publisher.svg": "img/publisher.82d378fcd601.svg", "img/logo-32.webp": "img/logo-32.5688944495bf.webp", "img/logo.svg": "img/logo.0f5344a028ca.svg", "img/story-arc.svg": "img/story-arc.ca10014355ef.svg", "img/missing-cover-165.webp": "img/missing-cover-165.0743171f2148.webp", "img/series.svg": "img/series.ec8a889b8f95.svg", "img/logo-maskable-180.webp": "img/logo-maskable-180.c58d966aa64e.webp", "img/missing-cover.svg": "img/missing-cover.ddb038cc2c56.svg", "img/folder.svg": "img/folder.f28936a3701d.svg", "img/volume.svg": "img/volume.814e4c79461a.svg", "img/logo-maskable.svg": "img/logo-maskable.8f7de7f1c6a8.svg", "img/imprint.svg": "img/imprint.7c2adebb76d6.svg", "pwa/offline.html": "pwa/offline.7bfaf9f94bf9.html", "js/choices.json": "js/choices.2f6b0359e1ef.json", "js/choices-admin.json": "js/choices-admin.3521e2a863df.json", "assets/group-tab-CBKuS3Iv.css": "assets/group-tab-CBKuS3Iv.7e4746634782.css", "assets/http-error-DKulXuTl.css": "assets/http-error-DKulXuTl.95e42988d5d5.css", "assets/VSelect-ARDhJiQK.css": "assets/VSelect-ARDhJiQK.372c098fb475.css", "assets/VSelectionControl-BFq--28I.css": "assets/VSelectionControl-BFq--28I.9687c77461fc.css", "assets/VTextField-DEiVah7O.js": "assets/VTextField-DEiVah7O.fbf3130f2dea.js", "assets/VSlideGroup-CRJazQeR.js": "assets/VSlideGroup-CRJazQeR.cb89b2222518.js", "assets/change-password-dialog-Du1bwEt1.js": "assets/change-password-dialog-Du1bwEt1.a4c0205c9bc4.js", "assets/pdf-doc-CMzaSV_K.css": "assets/pdf-doc-CMzaSV_K.8cd4b3e65f9a.css", "assets/VExpansionPanels-CurqcyFg.js": "assets/VExpansionPanels-CurqcyFg.860017abf25d.js", "assets/VRadioGroup-B7n5ReZ-.js": "assets/VRadioGroup-B7n5ReZ-.8acbc71ac411.js", "assets/materialdesignicons-webfont-PXm3-2wK.woff": "assets/materialdesignicons-webfont-PXm3-2wK.026b7ac9c43c.woff", "assets/VSlideGroup-Dk_1upHt.css": "assets/VSlideGroup-Dk_1upHt.2c836070ec75.css", "assets/admin-drawer-panel-mne3FIj6.css": "assets/admin-drawer-panel-mne3FIj6.561b3f75fe65.css", "assets/VTable-DflzroDq.css": "assets/VTable-DflzroDq.160504d82195.css", "assets/settings-drawer-nZ9HvKSZ.css": "assets/settings-drawer-nZ9HvKSZ.01744e131806.css", "assets/VDialog-lQ13FnRR.css": "assets/VDialog-lQ13FnRR.1c801ad756b2.css", "assets/VTable-DtyBEZ5i.js": "assets/VTable-DtyBEZ5i.6848f15ea03f.js", "assets/relation-chips-BGitp3yx.css": "assets/relation-chips-BGitp3yx.b3e7d178a615.css", "assets/main-Ztp855PW.css": "assets/main-Ztp855PW.d46d718fac45.css", "assets/flag-tab-DR_nY0Jg.js": "assets/flag-tab-DR_nY0Jg.7323e386c6ed.js", "assets/settings-drawer-XH4sNDNT.js": "assets/settings-drawer-XH4sNDNT.98ee4b24901c.js", "assets/VSelect-FYWbH55D.js": "assets/VSelect-FYWbH55D.83e91b93fdd1.js", "assets/pagination-toolbar-i2VoXaGH.js": "assets/pagination-toolbar-i2VoXaGH.c3dbb703af2e.js", "assets/VRadioGroup-i2qP9Wu9.css": "assets/VRadioGroup-i2qP9Wu9.8e3741381961.css", "assets/pdf-doc-BLxZLD38.js": "assets/pdf-doc-BLxZLD38.4cf9622c535f.js", "assets/VSelectionControl-CUlT3cc_.js": "assets/VSelectionControl-CUlT3cc_.63f60240eb49.js", "assets/admin-D4sw3N4T.css": "assets/admin-D4sw3N4T.b590f88a62cf.css", "assets/group-tab-JKsMHOmK.js": "assets/group-tab-JKsMHOmK.d2c2f3fceec1.js", "assets/relation-chips-CmeSIsRq.js": "assets/relation-chips-CmeSIsRq.f169f7c3f48d.js", "assets/reader-YbzUiD0T.css": "assets/reader-YbzUiD0T.efb15835b39d.css", "assets/change-password-dialog-0u6IJA87.css": "assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css", "assets/copy-to-clipboard-DoUvDJVx.js": "assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js", "assets/stats-tab-BGxkeKnY.js": "assets/stats-tab-BGxkeKnY.44cf18ca895d.js", "assets/library-tab-D9GTugZ6.js": "assets/library-tab-D9GTugZ6.8e3e6ebd38b7.js", "assets/task-tab-B74Kah_b.js": "assets/task-tab-B74Kah_b.58627993d3c6.js", "assets/VWindowItem-ByIod57Y.css": "assets/VWindowItem-ByIod57Y.f7fb19752bf3.css", "assets/VCheckbox-DtXDauZz.js": "assets/VCheckbox-DtXDauZz.54986ad416a1.js", "assets/pagination-toolbar-BA9ifTed.css": "assets/pagination-toolbar-BA9ifTed.b4865334ee08.css", "assets/library-tab-BygwYPnO.css": "assets/library-tab-BygwYPnO.94e92aa60bf2.css", "assets/confirm-dialog-eKN71B8a.js": "assets/confirm-dialog-eKN71B8a.af6187dc12bd.js", "assets/user-tab-BP2TTPg5.js": "assets/user-tab-BP2TTPg5.e63a5661a1a5.js", "assets/browser-Cy0OgQJC.css": "assets/browser-Cy0OgQJC.fabbd1aaffcf.css", "assets/confirm-dialog-BmhedLCx.css": "assets/confirm-dialog-BmhedLCx.7c2103d319d4.css", "assets/admin-S53JleJt.js": "assets/admin-S53JleJt.f629d90f73a1.js", "assets/materialdesignicons-webfont-B7mPwVP_.ttf": "assets/materialdesignicons-webfont-B7mPwVP_.6e435534bd35.ttf", "assets/VWindowItem-BVIaHO-S.js": "assets/VWindowItem-BVIaHO-S.419e4ecf523d.js", "assets/VCombobox-DZmum3X-.js": "assets/VCombobox-DZmum3X-.330883d59742.js", "assets/VCombobox-BksEr4D_.css": "assets/VCombobox-BksEr4D_.73429bb75f42.css", "assets/browser-BHHgqDP7.js": "assets/browser-BHHgqDP7.7ada4400d63f.js", "assets/main-BJiV8IG3.js": "assets/main-BJiV8IG3.9d708627091f.js", "assets/flag-tab-DBqpLKi7.css": "assets/flag-tab-DBqpLKi7.dcfef39f541e.css", "assets/task-tab-1XiWn9xP.css": "assets/task-tab-1XiWn9xP.06cb8e1b794d.css", "assets/VCheckboxBtn-B-iT1MnG.js": "assets/VCheckboxBtn-B-iT1MnG.8505f6eed0fe.js", "assets/filter-_XbKRiIR.js": "assets/filter-_XbKRiIR.2c7ac68a2d03.js", "assets/http-error-Bw1wUv3U.js": "assets/http-error-Bw1wUv3U.c8313a2fb129.js", "assets/reader-D2O_yHTW.js": "assets/reader-D2O_yHTW.70d616ddc2cc.js", "assets/datetime-column-DeCthByU.css": "assets/datetime-column-DeCthByU.1f3bf499e063.css", "assets/materialdesignicons-webfont-CSr8KVlo.eot": "assets/materialdesignicons-webfont-CSr8KVlo.8ced95a05e3c.eot", "assets/VDialog-DUdNpXLj.js": "assets/VDialog-DUdNpXLj.6088d518d3af.js", "assets/datetime-column-CWp600fz.js": "assets/datetime-column-CWp600fz.e8a969126bf5.js", "assets/unauthorized-DWDO1s6-.css": "assets/unauthorized-DWDO1s6-.d34daac27dcf.css", "assets/stats-tab-CI0u-X7Y.css": "assets/stats-tab-CI0u-X7Y.2d1b6a0d4139.css", "assets/admin-drawer-panel-CnAnGx7w.js": "assets/admin-drawer-panel-CnAnGx7w.1e4eb021cb21.js", "assets/unauthorized-BF45der6.js": "assets/unauthorized-BF45der6.d34f8022124b.js", "assets/VExpansionPanels-DsEXVcCv.css": "assets/VExpansionPanels-DsEXVcCv.20b475255e66.css", "assets/VCheckbox-CMKdyl0R.css": "assets/VCheckbox-CMKdyl0R.016ed8d222c4.css", "assets/VTextField-BssVoDhB.css": "assets/VTextField-BssVoDhB.4cc388b4aa3c.css", "assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "assets/materialdesignicons-webfont-Dp5v-WZN.1d7bcee1b302.woff2", "robots.txt": "robots.b6216d61c03e.txt", "manifest.json": "manifest.7033f9a22987.json"}, "version": "1.1", "hash": "792a07608140"}
|
codex/urls/root.py
CHANGED
|
@@ -7,7 +7,7 @@ from django.contrib.staticfiles.storage import staticfiles_storage
|
|
|
7
7
|
from django.urls import include, path, register_converter, set_script_prefix
|
|
8
8
|
from django.views.generic.base import RedirectView
|
|
9
9
|
|
|
10
|
-
from codex.settings.settings import ROOT_PATH
|
|
10
|
+
from codex.settings.settings import DEBUG, ROOT_PATH
|
|
11
11
|
from codex.urls.converters import GroupConverter, IntListConverter
|
|
12
12
|
|
|
13
13
|
register_converter(GroupConverter, "group")
|
|
@@ -17,7 +17,17 @@ if ROOT_PATH:
|
|
|
17
17
|
# Django 5 bug https://code.djangoproject.com/ticket/35169#comment:11
|
|
18
18
|
set_script_prefix(ROOT_PATH)
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
urlpatterns = []
|
|
22
|
+
if DEBUG:
|
|
23
|
+
# Pyright doesn't follow logic so will try to find these types.
|
|
24
|
+
from schema_graph.views import Schema # type: ignore
|
|
25
|
+
|
|
26
|
+
urlpatterns += [
|
|
27
|
+
path("schema/", Schema.as_view()), # type: ignore
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
urlpatterns += [
|
|
21
31
|
path(
|
|
22
32
|
"favicon.ico",
|
|
23
33
|
RedirectView.as_view(url=staticfiles_storage.url("img/logo-32.webp")),
|
codex/views/admin/api_key.py
CHANGED
|
@@ -4,7 +4,7 @@ from drf_spectacular.utils import extend_schema
|
|
|
4
4
|
from rest_framework.response import Response
|
|
5
5
|
|
|
6
6
|
from codex.models import Timestamp
|
|
7
|
-
from codex.serializers.admin import APIKeySerializer
|
|
7
|
+
from codex.serializers.admin.stats import APIKeySerializer
|
|
8
8
|
from codex.views.admin.auth import AdminGenericAPIView
|
|
9
9
|
|
|
10
10
|
|
codex/views/admin/flag.py
CHANGED
|
@@ -5,7 +5,7 @@ from codex.librarian.notifier.tasks import LIBRARY_CHANGED_TASK
|
|
|
5
5
|
from codex.logger.logging import get_logger
|
|
6
6
|
from codex.models import AdminFlag
|
|
7
7
|
from codex.registration import patch_registration_setting
|
|
8
|
-
from codex.serializers.admin import AdminFlagSerializer
|
|
8
|
+
from codex.serializers.admin.flags import AdminFlagSerializer
|
|
9
9
|
from codex.views.admin.auth import AdminModelViewSet
|
|
10
10
|
|
|
11
11
|
LOG = get_logger(__name__)
|
codex/views/admin/group.py
CHANGED
|
@@ -6,7 +6,7 @@ from django.core.cache import cache
|
|
|
6
6
|
from codex.librarian.mp_queue import LIBRARIAN_QUEUE
|
|
7
7
|
from codex.librarian.notifier.tasks import LIBRARY_CHANGED_TASK
|
|
8
8
|
from codex.logger.logging import get_logger
|
|
9
|
-
from codex.serializers.admin import GroupSerializer
|
|
9
|
+
from codex.serializers.admin.groups import GroupSerializer
|
|
10
10
|
from codex.views.admin.auth import AdminModelViewSet
|
|
11
11
|
|
|
12
12
|
LOG = get_logger(__name__)
|
codex/views/admin/library.py
CHANGED
|
@@ -18,7 +18,7 @@ from codex.librarian.watchdog.tasks import (
|
|
|
18
18
|
)
|
|
19
19
|
from codex.logger.logging import get_logger
|
|
20
20
|
from codex.models import FailedImport, Folder, Library
|
|
21
|
-
from codex.serializers.admin import (
|
|
21
|
+
from codex.serializers.admin.libraries import (
|
|
22
22
|
AdminFolderListSerializer,
|
|
23
23
|
AdminFolderSerializer,
|
|
24
24
|
FailedImportSerializer,
|
codex/views/admin/stats.py
CHANGED
|
@@ -1,184 +1,70 @@
|
|
|
1
|
-
"""Admin
|
|
1
|
+
"""Admin Stats View."""
|
|
2
2
|
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from platform import machine, python_version, release, system
|
|
5
|
-
from types import MappingProxyType
|
|
6
3
|
from typing import ClassVar
|
|
7
4
|
|
|
8
|
-
from caseconverter import snakecase
|
|
9
|
-
from django.contrib.sessions.models import Session
|
|
10
|
-
from django.db.models import Count
|
|
11
5
|
from drf_spectacular.utils import extend_schema
|
|
12
6
|
from rest_framework.response import Response
|
|
7
|
+
from rest_framework.serializers import empty
|
|
13
8
|
|
|
9
|
+
from codex.librarian.stats import CodexStats
|
|
14
10
|
from codex.logger.logging import get_logger
|
|
15
|
-
from codex.models import
|
|
16
|
-
Comic,
|
|
17
|
-
Library,
|
|
18
|
-
Timestamp,
|
|
19
|
-
)
|
|
11
|
+
from codex.models.admin import Timestamp
|
|
20
12
|
from codex.permissions import HasAPIKeyOrIsAdminUser
|
|
21
|
-
from codex.serializers.admin import
|
|
22
|
-
|
|
13
|
+
from codex.serializers.admin.stats import (
|
|
14
|
+
AdminStatsRequestSerializer,
|
|
15
|
+
StatsSerializer,
|
|
16
|
+
)
|
|
23
17
|
from codex.views.admin.auth import AdminGenericAPIView
|
|
24
|
-
from codex.views.const import CONFIG_MODELS, METADATA_MODELS, STATS_GROUP_MODELS
|
|
25
18
|
|
|
26
19
|
LOG = get_logger(__name__)
|
|
27
|
-
_KEY_MODELS_MAP = MappingProxyType(
|
|
28
|
-
{
|
|
29
|
-
"config": CONFIG_MODELS,
|
|
30
|
-
"groups": STATS_GROUP_MODELS,
|
|
31
|
-
"metadata": METADATA_MODELS,
|
|
32
|
-
}
|
|
33
|
-
)
|
|
34
|
-
_DOCKERENV_PATH = Path("/.dockerenv")
|
|
35
|
-
_CGROUP_PATH = Path("/proc/self/cgroup")
|
|
36
20
|
|
|
37
21
|
|
|
38
22
|
class AdminStatsView(AdminGenericAPIView):
|
|
39
23
|
"""Admin Flag Viewset."""
|
|
40
24
|
|
|
41
25
|
permission_classes: ClassVar[list] = [HasAPIKeyOrIsAdminUser] # type: ignore
|
|
42
|
-
serializer_class =
|
|
26
|
+
serializer_class = StatsSerializer
|
|
43
27
|
input_serializer_class = AdminStatsRequestSerializer
|
|
44
28
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
""
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
models.append(model)
|
|
72
|
-
else:
|
|
73
|
-
models = all_models
|
|
74
|
-
return models
|
|
75
|
-
|
|
76
|
-
def _get_model_counts(self, key):
|
|
77
|
-
"""Get database counts of each model group."""
|
|
78
|
-
models = self._get_models(key)
|
|
79
|
-
obj = {}
|
|
80
|
-
for model in models:
|
|
81
|
-
vnp = model._meta.verbose_name_plural
|
|
82
|
-
if vnp:
|
|
83
|
-
title = vnp.title()
|
|
84
|
-
else:
|
|
85
|
-
LOG.warning(f"No verbose plural name for {model.__name__}")
|
|
86
|
-
title = model.__name__
|
|
87
|
-
|
|
88
|
-
vnp_name = snakecase(title)
|
|
89
|
-
vnp_name += "_count"
|
|
90
|
-
qs = model.objects
|
|
91
|
-
if model == Library:
|
|
92
|
-
qs = qs.filter(covers_only=False)
|
|
93
|
-
obj[vnp_name] = qs.count()
|
|
94
|
-
return obj
|
|
95
|
-
|
|
96
|
-
@staticmethod
|
|
97
|
-
def _get_anon_sessions():
|
|
98
|
-
"""Return the number of anonymous sessions."""
|
|
99
|
-
sessions = Session.objects.all()
|
|
100
|
-
anon_sessions = 0
|
|
101
|
-
for encoded_session in sessions:
|
|
102
|
-
session = encoded_session.get_decoded()
|
|
103
|
-
if not session.get("_auth_user_id"):
|
|
104
|
-
anon_sessions += 1
|
|
105
|
-
|
|
106
|
-
return anon_sessions
|
|
107
|
-
|
|
108
|
-
def _get_platform(self, obj):
|
|
109
|
-
"""Add dict of platform information to object."""
|
|
110
|
-
platform = {
|
|
111
|
-
"docker": self._is_docker(),
|
|
112
|
-
"machine": machine(),
|
|
113
|
-
"system": system(),
|
|
114
|
-
"system_release": release(),
|
|
115
|
-
"python": python_version(),
|
|
116
|
-
"codex": VERSION,
|
|
117
|
-
}
|
|
118
|
-
obj["platform"] = platform
|
|
119
|
-
|
|
120
|
-
def _get_config(self, obj):
|
|
121
|
-
"""Add dict of config informaation to object."""
|
|
122
|
-
config = self._get_model_counts("config")
|
|
123
|
-
request_counts = self._get_request_counts("config")
|
|
124
|
-
if not request_counts or "sessionanon" in request_counts:
|
|
125
|
-
config["sessions_anon_count"] = self._get_anon_sessions()
|
|
126
|
-
if not request_counts or "apikey" in request_counts:
|
|
127
|
-
config["api_key"] = Timestamp.objects.get(
|
|
128
|
-
key=Timestamp.TimestampChoices.API_KEY.value
|
|
129
|
-
).version
|
|
130
|
-
obj["config"] = config
|
|
131
|
-
|
|
132
|
-
def _get_file_types(self):
|
|
133
|
-
"""Query for file types."""
|
|
134
|
-
file_types = {}
|
|
135
|
-
qs = (
|
|
136
|
-
Comic.objects.values("file_type")
|
|
137
|
-
.annotate(count=Count("file_type"))
|
|
138
|
-
.order_by()
|
|
139
|
-
)
|
|
140
|
-
for query_group in qs:
|
|
141
|
-
value = query_group["file_type"]
|
|
142
|
-
name = value.lower() if value else "unknown"
|
|
143
|
-
field = f"{name}_count"
|
|
144
|
-
file_types[field] = query_group["count"]
|
|
145
|
-
return file_types
|
|
146
|
-
|
|
147
|
-
def _get_groups(self, obj):
|
|
148
|
-
"""Add dict of groups information to object."""
|
|
149
|
-
if not self.params or "groups" in self.params:
|
|
150
|
-
groups = self._get_model_counts("groups")
|
|
151
|
-
obj["groups"] = groups
|
|
152
|
-
|
|
153
|
-
if not self.params or "fileTypes" in self.params:
|
|
154
|
-
file_types = self._get_file_types()
|
|
155
|
-
obj["file_types"] = file_types
|
|
156
|
-
|
|
157
|
-
def _get_metadata(self, obj):
|
|
158
|
-
"""Add dict of metadata counts to object."""
|
|
159
|
-
metadata = self._get_model_counts("metadata")
|
|
160
|
-
obj["metadata"] = metadata
|
|
29
|
+
def _parse_params(self):
|
|
30
|
+
"""Parse and input params."""
|
|
31
|
+
data = self.request.GET
|
|
32
|
+
|
|
33
|
+
input_serializer = self.input_serializer_class(data=data)
|
|
34
|
+
input_serializer.is_valid(raise_exception=True)
|
|
35
|
+
params = {}
|
|
36
|
+
if input_serializer.validated_data and not isinstance(
|
|
37
|
+
input_serializer.validated_data, empty
|
|
38
|
+
):
|
|
39
|
+
for key, value in input_serializer.validated_data.items():
|
|
40
|
+
if value:
|
|
41
|
+
params[key] = value
|
|
42
|
+
return params
|
|
43
|
+
|
|
44
|
+
def _add_api_key(self, obj):
|
|
45
|
+
"""Add the api key to the config object if specified."""
|
|
46
|
+
request_counts = self.params.get("config", {})
|
|
47
|
+
if request_counts and ("apikey" not in request_counts):
|
|
48
|
+
return
|
|
49
|
+
api_key = Timestamp.objects.get(
|
|
50
|
+
key=Timestamp.TimestampChoices.API_KEY.value
|
|
51
|
+
).version
|
|
52
|
+
if "config" not in obj:
|
|
53
|
+
obj["config"] = {}
|
|
54
|
+
obj["config"]["api_key"] = api_key
|
|
161
55
|
|
|
162
56
|
def get_object(self):
|
|
163
|
-
"""
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if not self.params or "config" in self.params:
|
|
168
|
-
self._get_config(obj)
|
|
169
|
-
if not self.params or "groups" in self.params:
|
|
170
|
-
self._get_groups(obj)
|
|
171
|
-
if not self.params or "metadata" in self.params:
|
|
172
|
-
self._get_metadata(obj)
|
|
57
|
+
"""Get the stats object with an api key."""
|
|
58
|
+
getter = CodexStats(self.params)
|
|
59
|
+
obj = getter.get()
|
|
60
|
+
self._add_api_key(obj)
|
|
173
61
|
return obj
|
|
174
62
|
|
|
175
63
|
@extend_schema(parameters=[input_serializer_class])
|
|
176
64
|
def get(self, *_args, **_kwargs):
|
|
177
65
|
"""Get the stats object and serialize it."""
|
|
178
|
-
|
|
179
|
-
input_serializer.is_valid()
|
|
180
|
-
self.params = frozenset(input_serializer.validated_data.get("params", {})) # type: ignore
|
|
181
|
-
|
|
66
|
+
self.params = self._parse_params()
|
|
182
67
|
obj = self.get_object()
|
|
68
|
+
|
|
183
69
|
serializer = self.get_serializer(obj)
|
|
184
70
|
return Response(serializer.data)
|
codex/views/admin/tasks.py
CHANGED
|
@@ -44,7 +44,7 @@ from codex.librarian.watchdog.tasks import (
|
|
|
44
44
|
)
|
|
45
45
|
from codex.logger.logging import get_logger
|
|
46
46
|
from codex.models import LibrarianStatus
|
|
47
|
-
from codex.serializers.admin import AdminLibrarianTaskSerializer
|
|
47
|
+
from codex.serializers.admin.tasks import AdminLibrarianTaskSerializer
|
|
48
48
|
from codex.serializers.mixins import OKSerializer
|
|
49
49
|
from codex.serializers.models.admin import LibrarianStatusSerializer
|
|
50
50
|
from codex.views.admin.auth import AdminAPIView, AdminReadOnlyModelViewSet
|
codex/views/admin/user.py
CHANGED
|
@@ -10,7 +10,7 @@ from rest_framework.status import HTTP_202_ACCEPTED, HTTP_400_BAD_REQUEST
|
|
|
10
10
|
from codex.librarian.mp_queue import LIBRARIAN_QUEUE
|
|
11
11
|
from codex.librarian.notifier.tasks import LIBRARY_CHANGED_TASK
|
|
12
12
|
from codex.logger.logging import get_logger
|
|
13
|
-
from codex.serializers.admin import UserChangePasswordSerializer, UserSerializer
|
|
13
|
+
from codex.serializers.admin.users import UserChangePasswordSerializer, UserSerializer
|
|
14
14
|
from codex.views.admin.auth import AdminGenericAPIView, AdminModelViewSet
|
|
15
15
|
|
|
16
16
|
LOG = get_logger(__name__)
|
codex/views/browser/browser.py
CHANGED
|
@@ -81,7 +81,10 @@ class BrowserView(BrowserTitleView):
|
|
|
81
81
|
self.group_query = self.group_class.objects.none()
|
|
82
82
|
else:
|
|
83
83
|
reason = f"{group}__in={pks} does not exist!"
|
|
84
|
-
|
|
84
|
+
settings_mask = {"breadcrumbs": []}
|
|
85
|
+
self.raise_redirect(
|
|
86
|
+
reason, route_mask={"group": group}, settings_mask=settings_mask
|
|
87
|
+
)
|
|
85
88
|
elif self.group_class:
|
|
86
89
|
self.group_query = self.group_class.objects.none()
|
|
87
90
|
else:
|
|
@@ -18,9 +18,9 @@ _FILTER_REL_MAP = MappingProxyType(
|
|
|
18
18
|
class ComicFieldFilterView(GroupFilterView):
|
|
19
19
|
"""Comic field filters."""
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
@staticmethod
|
|
22
|
+
def _filter_by_comic_field(field, rel_prefix, filter_list):
|
|
22
23
|
"""Filter by a comic any2many attribute."""
|
|
23
|
-
filter_list = self.params["filters"].get(field) # type: ignore
|
|
24
24
|
filter_query = Q()
|
|
25
25
|
if not filter_list:
|
|
26
26
|
return filter_query
|
|
@@ -36,10 +36,19 @@ class ComicFieldFilterView(GroupFilterView):
|
|
|
36
36
|
filter_query |= Q(**{f"{rel}__in": filter_list})
|
|
37
37
|
return filter_query
|
|
38
38
|
|
|
39
|
+
@classmethod
|
|
40
|
+
def get_all_comic_field_filters(cls, rel_prefix, filters):
|
|
41
|
+
"""Get all comicfiled filters for rel_prefix."""
|
|
42
|
+
comic_field_filter = Q()
|
|
43
|
+
for field in cls.FILTER_ATTRIBUTES:
|
|
44
|
+
filter_list = filters.get(field, [])
|
|
45
|
+
comic_field_filter &= cls._filter_by_comic_field(
|
|
46
|
+
field, rel_prefix, filter_list
|
|
47
|
+
)
|
|
48
|
+
return comic_field_filter
|
|
49
|
+
|
|
39
50
|
def get_comic_field_filter(self, model):
|
|
40
51
|
"""Filter the comics based on the form filters."""
|
|
41
|
-
comic_field_filter = Q()
|
|
42
52
|
rel_prefix = self.get_rel_prefix(model)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return comic_field_filter
|
|
53
|
+
filters = self.params["filters"] # type: ignore
|
|
54
|
+
return self.get_all_comic_field_filters(rel_prefix, filters)
|
codex/views/browser/paginate.py
CHANGED
|
@@ -13,6 +13,7 @@ from codex.views.browser.annotations import BrowserAnnotationsView
|
|
|
13
13
|
from codex.views.const import (
|
|
14
14
|
MAX_OBJ_PER_PAGE,
|
|
15
15
|
)
|
|
16
|
+
from codex.views.util import Route
|
|
16
17
|
|
|
17
18
|
LOG = get_logger(__name__)
|
|
18
19
|
|
|
@@ -20,30 +21,79 @@ LOG = get_logger(__name__)
|
|
|
20
21
|
class BrowserPaginateView(BrowserAnnotationsView):
|
|
21
22
|
"""Browser pagination."""
|
|
22
23
|
|
|
24
|
+
def _get_back_one_page_route(self, num_pages):
|
|
25
|
+
"""Get max page if oob or 1."""
|
|
26
|
+
LOG.debug("Redirect back one page.")
|
|
27
|
+
group = self.kwargs.get("group")
|
|
28
|
+
pks = self.kwargs.get("pks")
|
|
29
|
+
page = self.kwargs.get("page", 1)
|
|
30
|
+
new_page = num_pages if num_pages and page > num_pages else 1
|
|
31
|
+
pks = pks if pks else "0"
|
|
32
|
+
return {"group": group, "pks": pks, "page": new_page}
|
|
33
|
+
|
|
34
|
+
def _get_up_breadcrumbs(self):
|
|
35
|
+
"""Walk up the breadcrumbs to get the next level up."""
|
|
36
|
+
breadcrumbs = self.params.get("breadcrumbs", [])
|
|
37
|
+
new_breadcrumbs = []
|
|
38
|
+
level = False
|
|
39
|
+
group = self.kwargs.get("group")
|
|
40
|
+
pks = self.kwargs.get("pks")
|
|
41
|
+
page = self.kwargs.get("page", 1)
|
|
42
|
+
current_route = Route(group=group, pks=pks, page=page)
|
|
43
|
+
for crumb in reversed(breadcrumbs):
|
|
44
|
+
if not level:
|
|
45
|
+
crumb_route = Route(**crumb)
|
|
46
|
+
level = current_route & crumb_route
|
|
47
|
+
continue
|
|
48
|
+
new_breadcrumbs = [crumb, *new_breadcrumbs]
|
|
49
|
+
|
|
50
|
+
if not new_breadcrumbs:
|
|
51
|
+
if group not in ("f", "a"):
|
|
52
|
+
group = "r"
|
|
53
|
+
top_route = {"group": group, "pks": (), "page": 1}
|
|
54
|
+
new_breadcrumbs = [top_route]
|
|
55
|
+
return new_breadcrumbs
|
|
56
|
+
|
|
57
|
+
def _get_up_page_redirect(self):
|
|
58
|
+
"""Walk up the breadcrumbs."""
|
|
59
|
+
try:
|
|
60
|
+
up_breadcrumbs = self._get_up_breadcrumbs()
|
|
61
|
+
route_mask = up_breadcrumbs[-1]
|
|
62
|
+
settings_mask = {"breadcrumbs": up_breadcrumbs}
|
|
63
|
+
LOG.debug("Redirect up a level.")
|
|
64
|
+
except IndexError:
|
|
65
|
+
group = self.kwargs.get("group")
|
|
66
|
+
pks = "0"
|
|
67
|
+
new_page = 1
|
|
68
|
+
route_mask = {"group": group, "pks": pks, "page": new_page}
|
|
69
|
+
settings_mask = {"breadcrumbs": [route_mask]}
|
|
70
|
+
LOG.debug("Redirect to all at current group.")
|
|
71
|
+
return route_mask, settings_mask
|
|
72
|
+
|
|
23
73
|
def _check_page_in_bounds(self, total_count):
|
|
24
74
|
"""Redirect page out of bounds."""
|
|
25
75
|
pks = self.kwargs.get("pks")
|
|
26
76
|
page = self.kwargs.get("page", 1)
|
|
27
77
|
num_pages = ceil(total_count / MAX_OBJ_PER_PAGE)
|
|
28
|
-
if
|
|
78
|
+
if page == 1 or (page >= 1 and page <= num_pages):
|
|
29
79
|
# Don't redirect if on the root page for the group.
|
|
30
80
|
# Or page within valid range.
|
|
31
81
|
return num_pages
|
|
32
82
|
|
|
33
|
-
# Adjust route mask for redirect
|
|
34
83
|
group = self.kwargs.get("group")
|
|
84
|
+
reason = f"{group=} {pks=} {page=} does not exist."
|
|
85
|
+
|
|
86
|
+
# Adjust route mask for redirect
|
|
35
87
|
if num_pages and page > 1:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
pks = pks if pks else "0"
|
|
88
|
+
route_mask = self._get_back_one_page_route(num_pages)
|
|
89
|
+
settings_mask = None
|
|
39
90
|
else:
|
|
40
|
-
#
|
|
41
|
-
|
|
42
|
-
new_page = 1
|
|
91
|
+
# This now only occurs when page < 1
|
|
92
|
+
route_mask, settings_mask = self._get_up_page_redirect()
|
|
43
93
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
94
|
+
return self.raise_redirect(
|
|
95
|
+
reason, route_mask=route_mask, settings_mask=settings_mask
|
|
96
|
+
)
|
|
47
97
|
|
|
48
98
|
def _paginate_section(self, model, qs, page):
|
|
49
99
|
"""Paginate a group or Comic section."""
|
codex/views/browser/validate.py
CHANGED
|
@@ -15,7 +15,6 @@ from codex.views.const import (
|
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
LOG = get_logger(__name__)
|
|
18
|
-
_NO_TOP_GROUP_VALIDATE = frozenset({"metadata"})
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
class BrowserValidateView(BrowserBaseView):
|
|
@@ -56,8 +55,6 @@ class BrowserValidateView(BrowserBaseView):
|
|
|
56
55
|
return valid_top_groups
|
|
57
56
|
|
|
58
57
|
def _validate_top_group(self, valid_top_groups):
|
|
59
|
-
# if self.TARGET in _NO_TOP_GROUP_VALIDATE:
|
|
60
|
-
# return
|
|
61
58
|
nav_group = self.kwargs.get("group")
|
|
62
59
|
top_group = self.params.get("top_group")
|
|
63
60
|
if top_group not in valid_top_groups:
|
|
@@ -72,7 +69,8 @@ class BrowserValidateView(BrowserBaseView):
|
|
|
72
69
|
pks = self.kwargs.get("pks", ())
|
|
73
70
|
page = self.kwargs["page"]
|
|
74
71
|
route = {"group": nav_group, "pks": pks, "page": page}
|
|
75
|
-
|
|
72
|
+
breadcrumbs = []
|
|
73
|
+
settings_mask = {"top_group": valid_top_group, "breadcrumbs": breadcrumbs}
|
|
76
74
|
self.raise_redirect(reason, route, settings_mask)
|
|
77
75
|
|
|
78
76
|
def set_valid_browse_nav_groups(self, valid_top_groups):
|
|
@@ -109,7 +107,11 @@ class BrowserValidateView(BrowserBaseView):
|
|
|
109
107
|
if not self.admin_flags["folder_view"]:
|
|
110
108
|
reason = "folder view disabled"
|
|
111
109
|
valid_top_groups = self._get_valid_browse_top_groups()
|
|
112
|
-
|
|
110
|
+
breadcrumbs = []
|
|
111
|
+
settings_mask = {
|
|
112
|
+
"top_group": valid_top_groups[0],
|
|
113
|
+
"breadcrumbs": breadcrumbs,
|
|
114
|
+
}
|
|
113
115
|
self.raise_redirect(reason, settings_mask=settings_mask)
|
|
114
116
|
|
|
115
117
|
valid_top_groups = (FOLDER_GROUP,)
|
codex/views/opds/binary.py
CHANGED
|
@@ -6,11 +6,9 @@ from codex.views.opds.auth import OPDSAuthMixin
|
|
|
6
6
|
from codex.views.reader.page import ReaderPageView
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class OPDSCoverView(CoverView):
|
|
9
|
+
class OPDSCoverView(OPDSAuthMixin, CoverView):
|
|
10
10
|
"""Cover View with Basic Auth."""
|
|
11
11
|
|
|
12
|
-
# Panels sometimes doesn't send auth with cover requests.
|
|
13
|
-
|
|
14
12
|
|
|
15
13
|
class OPDSDownloadView(OPDSAuthMixin, DownloadView):
|
|
16
14
|
"""Download View with Basic Auth."""
|
codex/views/opds/const.py
CHANGED
|
@@ -84,3 +84,13 @@ class MimeType:
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
OPDS_M2M_MODELS = (Character, Genre, Location, SeriesGroup, StoryArc, Tag, Team)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class UserAgentNames:
|
|
90
|
+
"""Control whether to hack in facets with nav links."""
|
|
91
|
+
|
|
92
|
+
CLIENT_REORDERS = frozenset({"Chunky"})
|
|
93
|
+
FACET_SUPPORT = frozenset({"yar"}) # kybooks
|
|
94
|
+
SIMPLE_DOWNLOAD_MIME_TYPES = frozenset({"PocketBook Reader"})
|
|
95
|
+
# Other known valid names:
|
|
96
|
+
# "Chunky"
|
codex/views/opds/util.py
CHANGED
|
@@ -93,3 +93,13 @@ def full_redirect_view(url_name):
|
|
|
93
93
|
return response
|
|
94
94
|
|
|
95
95
|
return func
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def get_user_agent_name(request):
|
|
99
|
+
"""Get the first part of the user agent."""
|
|
100
|
+
user_agent_name = ""
|
|
101
|
+
if (user_agent := request.headers.get("User-Agent")) and (
|
|
102
|
+
user_agent_parts := user_agent.split("/", 1)
|
|
103
|
+
):
|
|
104
|
+
user_agent_name = user_agent_parts[0]
|
|
105
|
+
return user_agent_name
|