codex 1.7.2__py3-none-any.whl → 1.7.3a0__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/choices.py +13 -5
- codex/librarian/bookmark/bookmarkd.py +4 -5
- codex/librarian/bookmark/tasks.py +1 -1
- codex/librarian/bookmark/update.py +15 -29
- codex/librarian/cron/crond.py +1 -1
- codex/librarian/importer/query_fks.py +2 -2
- codex/librarian/janitor/janitor.py +11 -1
- codex/librarian/janitor/log_compress.py +77 -0
- codex/librarian/janitor/status.py +1 -0
- codex/librarian/janitor/tasks.py +5 -0
- codex/librarian/librariand.py +18 -13
- codex/librarian/search/update.py +8 -4
- codex/migrations/0031_adminflag_banner.py +50 -0
- codex/models/admin.py +4 -3
- codex/serializers/admin/flags.py +1 -1
- codex/serializers/auth.py +1 -0
- codex/serializers/opds/v2/__init__.py +1 -0
- codex/serializers/opds/v2/facet.py +13 -0
- codex/serializers/opds/v2/feed.py +35 -0
- codex/serializers/opds/v2/links.py +73 -0
- codex/serializers/opds/v2/metadata.py +22 -0
- codex/serializers/opds/v2/progression.py +63 -0
- codex/serializers/opds/v2/publication.py +78 -0
- codex/serializers/opds/{v2_unused.py → v2/unused.py} +1 -1
- codex/settings/settings.py +1 -0
- codex/static_root/assets/VCheckbox-pHjSEgdV.176f3c1f4191.js +1 -0
- codex/static_root/assets/VCheckbox-pHjSEgdV.176f3c1f4191.js.br +0 -0
- codex/static_root/assets/VCheckbox-pHjSEgdV.176f3c1f4191.js.gz +0 -0
- codex/static_root/assets/VCheckbox-pHjSEgdV.js +1 -0
- codex/static_root/assets/VCheckbox-pHjSEgdV.js.br +0 -0
- codex/static_root/assets/VCheckbox-pHjSEgdV.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-DBKqrZGq.467e75859b62.js +1 -0
- codex/static_root/assets/VCheckboxBtn-DBKqrZGq.467e75859b62.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-DBKqrZGq.467e75859b62.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-DBKqrZGq.js +1 -0
- codex/static_root/assets/VCheckboxBtn-DBKqrZGq.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-DBKqrZGq.js.gz +0 -0
- codex/static_root/assets/VCombobox-Bg7uOTbF.2fc6073b789f.js +1 -0
- codex/static_root/assets/VCombobox-Bg7uOTbF.2fc6073b789f.js.br +0 -0
- codex/static_root/assets/VCombobox-Bg7uOTbF.2fc6073b789f.js.gz +0 -0
- codex/static_root/assets/VCombobox-Bg7uOTbF.js +1 -0
- codex/static_root/assets/VCombobox-Bg7uOTbF.js.br +0 -0
- codex/static_root/assets/VCombobox-Bg7uOTbF.js.gz +0 -0
- codex/static_root/assets/VDialog-Dyd05WHA.b07aca713774.css +1 -0
- codex/static_root/assets/VDialog-Dyd05WHA.b07aca713774.css.br +0 -0
- codex/static_root/assets/VDialog-Dyd05WHA.b07aca713774.css.gz +0 -0
- codex/static_root/assets/VDialog-Dyd05WHA.css +1 -0
- codex/static_root/assets/VDialog-Dyd05WHA.css.br +0 -0
- codex/static_root/assets/VDialog-Dyd05WHA.css.gz +0 -0
- codex/static_root/assets/VDialog-IrbBYFLM.91a058d572c4.js +1 -0
- codex/static_root/assets/VDialog-IrbBYFLM.91a058d572c4.js.br +0 -0
- codex/static_root/assets/VDialog-IrbBYFLM.91a058d572c4.js.gz +0 -0
- codex/static_root/assets/VDialog-IrbBYFLM.js +1 -0
- codex/static_root/assets/VDialog-IrbBYFLM.js.br +0 -0
- codex/static_root/assets/VDialog-IrbBYFLM.js.gz +0 -0
- codex/static_root/assets/VDivider-CuRohbVQ.3c12b040aed7.js +1 -0
- codex/static_root/assets/VDivider-CuRohbVQ.3c12b040aed7.js.br +0 -0
- codex/static_root/assets/VDivider-CuRohbVQ.3c12b040aed7.js.gz +0 -0
- codex/static_root/assets/VDivider-CuRohbVQ.js +1 -0
- codex/static_root/assets/VDivider-CuRohbVQ.js.br +0 -0
- codex/static_root/assets/VDivider-CuRohbVQ.js.gz +0 -0
- codex/static_root/assets/VDivider-DE8MJPGz.3d2e17799e5c.css +1 -0
- codex/static_root/assets/VDivider-DE8MJPGz.3d2e17799e5c.css.br +0 -0
- codex/static_root/assets/VDivider-DE8MJPGz.3d2e17799e5c.css.gz +0 -0
- codex/static_root/assets/VDivider-DE8MJPGz.css +1 -0
- codex/static_root/assets/VDivider-DE8MJPGz.css.br +0 -0
- codex/static_root/assets/VDivider-DE8MJPGz.css.gz +0 -0
- codex/static_root/assets/VExpansionPanels-b0xWLH75.bff6ea8b4055.js +1 -0
- codex/static_root/assets/VExpansionPanels-b0xWLH75.bff6ea8b4055.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-b0xWLH75.bff6ea8b4055.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-b0xWLH75.js +1 -0
- codex/static_root/assets/VExpansionPanels-b0xWLH75.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-b0xWLH75.js.gz +0 -0
- codex/static_root/assets/VForm-B4hkqnS8.afbd5cf0908a.js +1 -0
- codex/static_root/assets/VForm-B4hkqnS8.afbd5cf0908a.js.br +0 -0
- codex/static_root/assets/VForm-B4hkqnS8.afbd5cf0908a.js.gz +0 -0
- codex/static_root/assets/VForm-B4hkqnS8.js +1 -0
- codex/static_root/assets/VForm-B4hkqnS8.js.br +0 -0
- codex/static_root/assets/VForm-B4hkqnS8.js.gz +0 -0
- codex/static_root/assets/VForm-v1Gmu6E1.138c0b89b6fc.css +1 -0
- codex/static_root/assets/VForm-v1Gmu6E1.138c0b89b6fc.css.br +0 -0
- codex/static_root/assets/VForm-v1Gmu6E1.138c0b89b6fc.css.gz +0 -0
- codex/static_root/assets/VForm-v1Gmu6E1.css +1 -0
- codex/static_root/assets/VForm-v1Gmu6E1.css.br +0 -0
- codex/static_root/assets/VForm-v1Gmu6E1.css.gz +0 -0
- codex/static_root/assets/VRadioGroup-Cbayik6d.034f0f275265.js +1 -0
- codex/static_root/assets/VRadioGroup-Cbayik6d.034f0f275265.js.br +0 -0
- codex/static_root/assets/VRadioGroup-Cbayik6d.034f0f275265.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-Cbayik6d.js +1 -0
- codex/static_root/assets/VRadioGroup-Cbayik6d.js.br +0 -0
- codex/static_root/assets/VRadioGroup-Cbayik6d.js.gz +0 -0
- codex/static_root/assets/VSelect-8MFoaOUz.6309f7bf17bb.css +1 -0
- codex/static_root/assets/VSelect-8MFoaOUz.6309f7bf17bb.css.br +0 -0
- codex/static_root/assets/VSelect-8MFoaOUz.6309f7bf17bb.css.gz +0 -0
- codex/static_root/assets/VSelect-8MFoaOUz.css +1 -0
- codex/static_root/assets/VSelect-8MFoaOUz.css.br +0 -0
- codex/static_root/assets/VSelect-8MFoaOUz.css.gz +0 -0
- codex/static_root/assets/VSelect-BsuB-2P1.abe187c8b53f.js +1 -0
- codex/static_root/assets/VSelect-BsuB-2P1.abe187c8b53f.js.br +0 -0
- codex/static_root/assets/VSelect-BsuB-2P1.abe187c8b53f.js.gz +0 -0
- codex/static_root/assets/VSelect-BsuB-2P1.js +1 -0
- codex/static_root/assets/VSelect-BsuB-2P1.js.br +0 -0
- codex/static_root/assets/VSelect-BsuB-2P1.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-DLxcLoTI.cc18de4e83f6.css +1 -0
- codex/static_root/assets/VSelectionControl-DLxcLoTI.cc18de4e83f6.css.br +0 -0
- codex/static_root/assets/VSelectionControl-DLxcLoTI.cc18de4e83f6.css.gz +0 -0
- codex/static_root/assets/VSelectionControl-DLxcLoTI.css +1 -0
- codex/static_root/assets/VSelectionControl-DLxcLoTI.css.br +0 -0
- codex/static_root/assets/VSelectionControl-DLxcLoTI.css.gz +0 -0
- codex/static_root/assets/VSelectionControl-L41n5bnX.f4674bb62425.js +1 -0
- codex/static_root/assets/VSelectionControl-L41n5bnX.f4674bb62425.js.br +0 -0
- codex/static_root/assets/VSelectionControl-L41n5bnX.f4674bb62425.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-L41n5bnX.js +1 -0
- codex/static_root/assets/VSelectionControl-L41n5bnX.js.br +0 -0
- codex/static_root/assets/VSelectionControl-L41n5bnX.js.gz +0 -0
- codex/static_root/assets/VTable-CYv4gUUt.76e4658abeb3.js +1 -0
- codex/static_root/assets/VTable-CYv4gUUt.76e4658abeb3.js.br +0 -0
- codex/static_root/assets/VTable-CYv4gUUt.76e4658abeb3.js.gz +0 -0
- codex/static_root/assets/VTable-CYv4gUUt.js +1 -0
- codex/static_root/assets/VTable-CYv4gUUt.js.br +0 -0
- codex/static_root/assets/VTable-CYv4gUUt.js.gz +0 -0
- codex/static_root/assets/VWindowItem-f8UkxXa_.1d3e9e78fc9b.js +1 -0
- codex/static_root/assets/VWindowItem-f8UkxXa_.1d3e9e78fc9b.js.br +0 -0
- codex/static_root/assets/VWindowItem-f8UkxXa_.1d3e9e78fc9b.js.gz +0 -0
- codex/static_root/assets/VWindowItem-f8UkxXa_.js +1 -0
- codex/static_root/assets/VWindowItem-f8UkxXa_.js.br +0 -0
- codex/static_root/assets/VWindowItem-f8UkxXa_.js.gz +0 -0
- codex/static_root/assets/admin-BmuWJcAB.b0b253aefd88.js +1 -0
- codex/static_root/assets/admin-BmuWJcAB.b0b253aefd88.js.br +0 -0
- codex/static_root/assets/admin-BmuWJcAB.b0b253aefd88.js.gz +0 -0
- codex/static_root/assets/admin-BmuWJcAB.js +1 -0
- codex/static_root/assets/admin-BmuWJcAB.js.br +0 -0
- codex/static_root/assets/admin-BmuWJcAB.js.gz +0 -0
- codex/static_root/assets/admin-Izb24SXM.504ea9d9515c.js +1 -0
- codex/static_root/assets/admin-Izb24SXM.504ea9d9515c.js.br +0 -0
- codex/static_root/assets/admin-Izb24SXM.504ea9d9515c.js.gz +0 -0
- codex/static_root/assets/admin-Izb24SXM.js +1 -0
- codex/static_root/assets/admin-Izb24SXM.js.br +0 -0
- codex/static_root/assets/admin-Izb24SXM.js.gz +0 -0
- codex/static_root/assets/admin-dm3bSP7O.ae1234cc0beb.css +1 -0
- codex/static_root/assets/admin-dm3bSP7O.ae1234cc0beb.css.br +0 -0
- codex/static_root/assets/admin-dm3bSP7O.ae1234cc0beb.css.gz +0 -0
- codex/static_root/assets/admin-dm3bSP7O.css +1 -0
- codex/static_root/assets/admin-dm3bSP7O.css.br +0 -0
- codex/static_root/assets/admin-dm3bSP7O.css.gz +0 -0
- codex/static_root/assets/admin-menu-C712OV-9.ecd1f2af4cf4.js +1 -0
- codex/static_root/assets/admin-menu-C712OV-9.ecd1f2af4cf4.js.br +0 -0
- codex/static_root/assets/admin-menu-C712OV-9.ecd1f2af4cf4.js.gz +0 -0
- codex/static_root/assets/admin-menu-C712OV-9.js +1 -0
- codex/static_root/assets/admin-menu-C712OV-9.js.br +0 -0
- codex/static_root/assets/admin-menu-C712OV-9.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-Clv9yQ7G.2536580dece1.js +1 -0
- codex/static_root/assets/admin-settings-button-progress-Clv9yQ7G.2536580dece1.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-Clv9yQ7G.2536580dece1.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-Clv9yQ7G.js +1 -0
- codex/static_root/assets/admin-settings-button-progress-Clv9yQ7G.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-Clv9yQ7G.js.gz +0 -0
- codex/static_root/assets/browser-CReWGhn_.521193ab0710.css +1 -0
- codex/static_root/assets/browser-CReWGhn_.521193ab0710.css.br +0 -0
- codex/static_root/assets/browser-CReWGhn_.521193ab0710.css.gz +0 -0
- codex/static_root/assets/browser-CReWGhn_.css +1 -0
- codex/static_root/assets/browser-CReWGhn_.css.br +0 -0
- codex/static_root/assets/browser-CReWGhn_.css.gz +0 -0
- codex/static_root/assets/browser-DiAN9Ipo.a5b62a3cbe1d.js +1 -0
- codex/static_root/assets/browser-DiAN9Ipo.a5b62a3cbe1d.js.br +0 -0
- codex/static_root/assets/browser-DiAN9Ipo.a5b62a3cbe1d.js.gz +0 -0
- codex/static_root/assets/browser-DiAN9Ipo.js +1 -0
- codex/static_root/assets/browser-DiAN9Ipo.js.br +0 -0
- codex/static_root/assets/browser-DiAN9Ipo.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-BZPmAOML.73fdc23e13a4.js +1 -0
- codex/static_root/assets/change-password-dialog-BZPmAOML.73fdc23e13a4.js.br +0 -0
- codex/static_root/assets/change-password-dialog-BZPmAOML.73fdc23e13a4.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-BZPmAOML.js +1 -0
- codex/static_root/assets/change-password-dialog-BZPmAOML.js.br +0 -0
- codex/static_root/assets/change-password-dialog-BZPmAOML.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CBLQOik_.f53acd0c622a.js +1 -0
- codex/static_root/assets/confirm-dialog-CBLQOik_.f53acd0c622a.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CBLQOik_.f53acd0c622a.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CBLQOik_.js +1 -0
- codex/static_root/assets/confirm-dialog-CBLQOik_.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CBLQOik_.js.gz +0 -0
- codex/static_root/assets/datetime-column-CU19rCbi.9edc0d2da736.js +1 -0
- codex/static_root/assets/datetime-column-CU19rCbi.9edc0d2da736.js.br +1 -0
- codex/static_root/assets/datetime-column-CU19rCbi.9edc0d2da736.js.gz +0 -0
- codex/static_root/assets/datetime-column-CU19rCbi.js +1 -0
- codex/static_root/assets/datetime-column-CU19rCbi.js.br +1 -0
- codex/static_root/assets/datetime-column-CU19rCbi.js.gz +0 -0
- codex/static_root/assets/{filter-ud5mPZpn.0f0a537959aa.js → filter-CZ7kkBLq.171b4fcba146.js} +1 -1
- codex/static_root/assets/filter-CZ7kkBLq.171b4fcba146.js.br +0 -0
- codex/static_root/assets/filter-CZ7kkBLq.171b4fcba146.js.gz +0 -0
- codex/static_root/assets/{filter-ud5mPZpn.js → filter-CZ7kkBLq.js} +1 -1
- codex/static_root/assets/filter-CZ7kkBLq.js.br +0 -0
- codex/static_root/assets/filter-CZ7kkBLq.js.gz +0 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.2b7ef394b850.css +1 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.2b7ef394b850.css.br +0 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.2b7ef394b850.css.gz +0 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.css +1 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.css.br +0 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.css.gz +0 -0
- codex/static_root/assets/flag-tab-kcBN36xe.631c48ab75fd.js +1 -0
- codex/static_root/assets/flag-tab-kcBN36xe.631c48ab75fd.js.br +0 -0
- codex/static_root/assets/flag-tab-kcBN36xe.631c48ab75fd.js.gz +0 -0
- codex/static_root/assets/flag-tab-kcBN36xe.js +1 -0
- codex/static_root/assets/flag-tab-kcBN36xe.js.br +0 -0
- codex/static_root/assets/flag-tab-kcBN36xe.js.gz +0 -0
- codex/static_root/assets/forwardRefs-DNAemYUk.06a315272ed9.js +1 -0
- codex/static_root/assets/forwardRefs-DNAemYUk.06a315272ed9.js.br +0 -0
- codex/static_root/assets/forwardRefs-DNAemYUk.06a315272ed9.js.gz +0 -0
- codex/static_root/assets/forwardRefs-DNAemYUk.js +1 -0
- codex/static_root/assets/forwardRefs-DNAemYUk.js.br +0 -0
- codex/static_root/assets/forwardRefs-DNAemYUk.js.gz +0 -0
- codex/static_root/assets/forwardRefs-zKOZsbbr.9b56b4459240.css +1 -0
- codex/static_root/assets/forwardRefs-zKOZsbbr.9b56b4459240.css.br +0 -0
- codex/static_root/assets/forwardRefs-zKOZsbbr.9b56b4459240.css.gz +0 -0
- codex/static_root/assets/forwardRefs-zKOZsbbr.css +1 -0
- codex/static_root/assets/forwardRefs-zKOZsbbr.css.br +0 -0
- codex/static_root/assets/forwardRefs-zKOZsbbr.css.gz +0 -0
- codex/static_root/assets/group-tab-D9gwAdJc.60fb0ffa734c.js +1 -0
- codex/static_root/assets/group-tab-D9gwAdJc.60fb0ffa734c.js.br +0 -0
- codex/static_root/assets/group-tab-D9gwAdJc.60fb0ffa734c.js.gz +0 -0
- codex/static_root/assets/group-tab-D9gwAdJc.js +1 -0
- codex/static_root/assets/group-tab-D9gwAdJc.js.br +0 -0
- codex/static_root/assets/group-tab-D9gwAdJc.js.gz +0 -0
- codex/static_root/assets/http-error-DEJmFobt.8c13689ae574.css +1 -0
- codex/static_root/assets/http-error-DEJmFobt.8c13689ae574.css.br +0 -0
- codex/static_root/assets/http-error-DEJmFobt.8c13689ae574.css.gz +0 -0
- codex/static_root/assets/http-error-DEJmFobt.css +1 -0
- codex/static_root/assets/http-error-DEJmFobt.css.br +0 -0
- codex/static_root/assets/http-error-DEJmFobt.css.gz +0 -0
- codex/static_root/assets/http-error-DmFqD2Xz.593d626b5f1b.js +1 -0
- codex/static_root/assets/http-error-DmFqD2Xz.593d626b5f1b.js.br +0 -0
- codex/static_root/assets/http-error-DmFqD2Xz.593d626b5f1b.js.gz +0 -0
- codex/static_root/assets/http-error-DmFqD2Xz.js +1 -0
- codex/static_root/assets/http-error-DmFqD2Xz.js.br +0 -0
- codex/static_root/assets/http-error-DmFqD2Xz.js.gz +0 -0
- codex/static_root/assets/index-hvGLIBbY.30ce8cca0c6d.js +1 -0
- codex/static_root/assets/index-hvGLIBbY.30ce8cca0c6d.js.br +0 -0
- codex/static_root/assets/index-hvGLIBbY.30ce8cca0c6d.js.gz +0 -0
- codex/static_root/assets/index-hvGLIBbY.js +1 -0
- codex/static_root/assets/index-hvGLIBbY.js.br +0 -0
- codex/static_root/assets/index-hvGLIBbY.js.gz +0 -0
- codex/static_root/assets/library-tab-CF-RAEgP.a0ad816fb994.js +1 -0
- codex/static_root/assets/library-tab-CF-RAEgP.a0ad816fb994.js.br +0 -0
- codex/static_root/assets/library-tab-CF-RAEgP.a0ad816fb994.js.gz +0 -0
- codex/static_root/assets/library-tab-CF-RAEgP.js +1 -0
- codex/static_root/assets/library-tab-CF-RAEgP.js.br +0 -0
- codex/static_root/assets/library-tab-CF-RAEgP.js.gz +0 -0
- codex/static_root/assets/{library-tab-Cat0MAK5.5911f022188e.css → library-tab-Ce6qaeCV.75baedb7e976.css} +1 -1
- codex/static_root/assets/library-tab-Ce6qaeCV.75baedb7e976.css.br +0 -0
- codex/static_root/assets/library-tab-Ce6qaeCV.75baedb7e976.css.gz +0 -0
- codex/static_root/assets/{library-tab-Cat0MAK5.css → library-tab-Ce6qaeCV.css} +1 -1
- codex/static_root/assets/library-tab-Ce6qaeCV.css.br +0 -0
- codex/static_root/assets/library-tab-Ce6qaeCV.css.gz +0 -0
- codex/static_root/assets/main-Dv8e0bMI.bd74f1ba1627.js +35 -0
- codex/static_root/assets/main-Dv8e0bMI.bd74f1ba1627.js.br +0 -0
- codex/static_root/assets/main-Dv8e0bMI.bd74f1ba1627.js.gz +0 -0
- codex/static_root/assets/main-Dv8e0bMI.js +35 -0
- codex/static_root/assets/main-Dv8e0bMI.js.br +0 -0
- codex/static_root/assets/main-Dv8e0bMI.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.04a4f5c451b4.js +1 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.04a4f5c451b4.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.04a4f5c451b4.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.js +1 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-DSe0TkMm.css +1 -0
- codex/static_root/assets/pagination-toolbar-DSe0TkMm.css.br +0 -0
- codex/static_root/assets/pagination-toolbar-DSe0TkMm.css.gz +0 -0
- codex/static_root/assets/pagination-toolbar-DSe0TkMm.dcb0eba65827.css +1 -0
- codex/static_root/assets/pagination-toolbar-DSe0TkMm.dcb0eba65827.css.br +0 -0
- codex/static_root/assets/pagination-toolbar-DSe0TkMm.dcb0eba65827.css.gz +0 -0
- codex/static_root/assets/pagination-toolbar-D_whea1o.9bbd927058f1.js +1 -0
- codex/static_root/assets/pagination-toolbar-D_whea1o.9bbd927058f1.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-D_whea1o.9bbd927058f1.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-D_whea1o.js +1 -0
- codex/static_root/assets/pagination-toolbar-D_whea1o.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-D_whea1o.js.gz +0 -0
- codex/static_root/assets/pdf-doc-dnr5fHbU.fa1d7ed9255b.js +348 -0
- codex/static_root/assets/pdf-doc-dnr5fHbU.fa1d7ed9255b.js.br +0 -0
- codex/static_root/assets/pdf-doc-dnr5fHbU.fa1d7ed9255b.js.gz +0 -0
- codex/static_root/assets/pdf-doc-dnr5fHbU.js +348 -0
- codex/static_root/assets/pdf-doc-dnr5fHbU.js.br +0 -0
- codex/static_root/assets/pdf-doc-dnr5fHbU.js.gz +0 -0
- codex/static_root/assets/{reader-Dd2KmdCN.115d4bfe9280.css → reader-B3hgta6g.2ed32f08e906.css} +1 -1
- codex/static_root/assets/reader-B3hgta6g.2ed32f08e906.css.br +0 -0
- codex/static_root/assets/reader-B3hgta6g.2ed32f08e906.css.gz +0 -0
- codex/static_root/assets/{reader-Dd2KmdCN.css → reader-B3hgta6g.css} +1 -1
- codex/static_root/assets/reader-B3hgta6g.css.br +0 -0
- codex/static_root/assets/reader-B3hgta6g.css.gz +0 -0
- codex/static_root/assets/reader-Cn-ra_Dv.f38c0b419dec.js +2 -0
- codex/static_root/assets/reader-Cn-ra_Dv.f38c0b419dec.js.br +0 -0
- codex/static_root/assets/reader-Cn-ra_Dv.f38c0b419dec.js.gz +0 -0
- codex/static_root/assets/reader-Cn-ra_Dv.js +2 -0
- codex/static_root/assets/reader-Cn-ra_Dv.js.br +0 -0
- codex/static_root/assets/reader-Cn-ra_Dv.js.gz +0 -0
- codex/static_root/assets/relation-chips-fOPxWAMU.78e5fe70c014.js +1 -0
- codex/static_root/assets/relation-chips-fOPxWAMU.78e5fe70c014.js.br +0 -0
- codex/static_root/assets/relation-chips-fOPxWAMU.78e5fe70c014.js.gz +0 -0
- codex/static_root/assets/relation-chips-fOPxWAMU.js +1 -0
- codex/static_root/assets/relation-chips-fOPxWAMU.js.br +0 -0
- codex/static_root/assets/relation-chips-fOPxWAMU.js.gz +0 -0
- codex/static_root/assets/settings-drawer-1UEq8JY1.d95cee9aefb5.js +2 -0
- codex/static_root/assets/settings-drawer-1UEq8JY1.d95cee9aefb5.js.br +0 -0
- codex/static_root/assets/settings-drawer-1UEq8JY1.d95cee9aefb5.js.gz +0 -0
- codex/static_root/assets/settings-drawer-1UEq8JY1.js +2 -0
- codex/static_root/assets/settings-drawer-1UEq8JY1.js.br +0 -0
- codex/static_root/assets/settings-drawer-1UEq8JY1.js.gz +0 -0
- codex/static_root/assets/settings-drawer-CqJ4gXLq.75a6ea969e71.css +1 -0
- codex/static_root/assets/settings-drawer-CqJ4gXLq.75a6ea969e71.css.br +0 -0
- codex/static_root/assets/settings-drawer-CqJ4gXLq.75a6ea969e71.css.gz +0 -0
- codex/static_root/assets/settings-drawer-CqJ4gXLq.css +1 -0
- codex/static_root/assets/settings-drawer-CqJ4gXLq.css.br +0 -0
- codex/static_root/assets/settings-drawer-CqJ4gXLq.css.gz +0 -0
- codex/static_root/assets/stats-tab-0ptRCeKw.5514d3508e37.js +1 -0
- codex/static_root/assets/stats-tab-0ptRCeKw.5514d3508e37.js.br +0 -0
- codex/static_root/assets/stats-tab-0ptRCeKw.5514d3508e37.js.gz +0 -0
- codex/static_root/assets/stats-tab-0ptRCeKw.js +1 -0
- codex/static_root/assets/stats-tab-0ptRCeKw.js.br +0 -0
- codex/static_root/assets/stats-tab-0ptRCeKw.js.gz +0 -0
- codex/static_root/assets/task-tab-CG9_bi6Z.ad9f647f8e5f.js +1 -0
- codex/static_root/assets/task-tab-CG9_bi6Z.ad9f647f8e5f.js.br +0 -0
- codex/static_root/assets/task-tab-CG9_bi6Z.ad9f647f8e5f.js.gz +0 -0
- codex/static_root/assets/task-tab-CG9_bi6Z.js +1 -0
- codex/static_root/assets/task-tab-CG9_bi6Z.js.br +0 -0
- codex/static_root/assets/task-tab-CG9_bi6Z.js.gz +0 -0
- codex/static_root/assets/unauthorized-VnIXUO1w.c5536d9dae75.css +1 -0
- codex/static_root/assets/unauthorized-VnIXUO1w.c5536d9dae75.css.br +0 -0
- codex/static_root/assets/unauthorized-VnIXUO1w.c5536d9dae75.css.gz +0 -0
- codex/static_root/assets/unauthorized-VnIXUO1w.css +1 -0
- codex/static_root/assets/unauthorized-VnIXUO1w.css.br +0 -0
- codex/static_root/assets/unauthorized-VnIXUO1w.css.gz +0 -0
- codex/static_root/assets/unauthorized-vG1Lh0m_.0c4bae81ee09.js +1 -0
- codex/static_root/assets/unauthorized-vG1Lh0m_.0c4bae81ee09.js.br +0 -0
- codex/static_root/assets/unauthorized-vG1Lh0m_.0c4bae81ee09.js.gz +0 -0
- codex/static_root/assets/unauthorized-vG1Lh0m_.js +1 -0
- codex/static_root/assets/unauthorized-vG1Lh0m_.js.br +0 -0
- codex/static_root/assets/unauthorized-vG1Lh0m_.js.gz +0 -0
- codex/static_root/assets/user-tab-BOxWlpY7.1a94280a799b.js +1 -0
- codex/static_root/assets/user-tab-BOxWlpY7.1a94280a799b.js.br +0 -0
- codex/static_root/assets/user-tab-BOxWlpY7.1a94280a799b.js.gz +0 -0
- codex/static_root/assets/user-tab-BOxWlpY7.js +1 -0
- codex/static_root/assets/user-tab-BOxWlpY7.js.br +0 -0
- codex/static_root/assets/user-tab-BOxWlpY7.js.gz +0 -0
- codex/static_root/manifest.9b3479a6a4a6.json +735 -0
- codex/static_root/manifest.9b3479a6a4a6.json.br +0 -0
- codex/static_root/manifest.9b3479a6a4a6.json.gz +0 -0
- codex/static_root/manifest.json +365 -342
- codex/static_root/manifest.json.br +0 -0
- codex/static_root/manifest.json.gz +0 -0
- codex/static_root/staticfiles.json +1 -1
- codex/templates/index.html +1 -1
- codex/threads.py +8 -3
- codex/urls/api/admin.py +1 -0
- codex/urls/api/browser.py +1 -1
- codex/urls/opds/v2.py +6 -0
- codex/views/admin/flag.py +5 -1
- codex/views/admin/tasks.py +2 -0
- codex/views/bookmark.py +53 -41
- codex/views/browser/annotate/bookmark.py +6 -4
- codex/views/browser/annotate/card.py +1 -16
- codex/views/browser/annotate/order.py +45 -18
- codex/views/browser/bookmark.py +53 -0
- codex/views/browser/download.py +2 -0
- codex/views/browser/filters/bookmark.py +4 -32
- codex/views/browser/group_mtime.py +2 -2
- codex/views/browser/metadata/annotate.py +1 -1
- codex/views/browser/metadata/metadata.py +1 -1
- codex/views/browser/order_by.py +6 -1
- codex/views/frontend.py +19 -4
- codex/views/mixins.py +16 -28
- codex/views/opds/const.py +2 -0
- codex/views/opds/util.py +2 -2
- codex/views/opds/v1/entry/links.py +1 -2
- codex/views/opds/v2/feed.py +3 -2
- codex/views/opds/v2/href.py +60 -0
- codex/views/opds/v2/links.py +13 -47
- codex/views/opds/v2/progression.py +137 -0
- codex/views/opds/v2/publications.py +21 -1
- codex/views/opds/v2/top_links.py +2 -1
- codex/views/public.py +11 -4
- codex/views/reader/books.py +19 -8
- codex/views/reader/page.py +5 -5
- {codex-1.7.2.dist-info → codex-1.7.3a0.dist-info}/METADATA +21 -26
- {codex-1.7.2.dist-info → codex-1.7.3a0.dist-info}/RECORD +387 -370
- codex/serializers/opds/v2.py +0 -178
- codex/static_root/assets/VCheckbox-DLMzIII1.1ff8fc2d9a21.js +0 -1
- codex/static_root/assets/VCheckbox-DLMzIII1.1ff8fc2d9a21.js.br +0 -0
- codex/static_root/assets/VCheckbox-DLMzIII1.1ff8fc2d9a21.js.gz +0 -0
- codex/static_root/assets/VCheckbox-DLMzIII1.js +0 -1
- codex/static_root/assets/VCheckbox-DLMzIII1.js.br +0 -0
- codex/static_root/assets/VCheckbox-DLMzIII1.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.094679a3624b.js +0 -1
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.094679a3624b.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.094679a3624b.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.js +0 -1
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.js.gz +0 -0
- codex/static_root/assets/VCombobox-CBY8K5CP.fcf2221a9edd.js +0 -1
- codex/static_root/assets/VCombobox-CBY8K5CP.fcf2221a9edd.js.br +0 -0
- codex/static_root/assets/VCombobox-CBY8K5CP.fcf2221a9edd.js.gz +0 -0
- codex/static_root/assets/VCombobox-CBY8K5CP.js +0 -1
- codex/static_root/assets/VCombobox-CBY8K5CP.js.br +0 -0
- codex/static_root/assets/VCombobox-CBY8K5CP.js.gz +0 -0
- codex/static_root/assets/VDialog-DXQz0Ylp.7b23d86dbd0d.css +0 -1
- codex/static_root/assets/VDialog-DXQz0Ylp.7b23d86dbd0d.css.br +0 -0
- codex/static_root/assets/VDialog-DXQz0Ylp.7b23d86dbd0d.css.gz +0 -0
- codex/static_root/assets/VDialog-DXQz0Ylp.css +0 -1
- codex/static_root/assets/VDialog-DXQz0Ylp.css.br +0 -0
- codex/static_root/assets/VDialog-DXQz0Ylp.css.gz +0 -0
- codex/static_root/assets/VDialog-Db4tJYqR.e21a79a5030e.js +0 -1
- codex/static_root/assets/VDialog-Db4tJYqR.e21a79a5030e.js.br +0 -0
- codex/static_root/assets/VDialog-Db4tJYqR.e21a79a5030e.js.gz +0 -0
- codex/static_root/assets/VDialog-Db4tJYqR.js +0 -1
- codex/static_root/assets/VDialog-Db4tJYqR.js.br +0 -0
- codex/static_root/assets/VDialog-Db4tJYqR.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.163e59e38865.js +0 -1
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.163e59e38865.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.163e59e38865.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.js +0 -1
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-D2-PWEfs.ce7644863c25.js +0 -1
- codex/static_root/assets/VRadioGroup-D2-PWEfs.ce7644863c25.js.br +0 -0
- codex/static_root/assets/VRadioGroup-D2-PWEfs.ce7644863c25.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-D2-PWEfs.js +0 -1
- codex/static_root/assets/VRadioGroup-D2-PWEfs.js.br +0 -0
- codex/static_root/assets/VRadioGroup-D2-PWEfs.js.gz +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css +0 -1
- codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.br +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.gz +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.css +0 -1
- codex/static_root/assets/VSelect-DLu8bpcs.css.br +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.css.gz +0 -0
- codex/static_root/assets/VSelect-DqXJ23Pc.a1360cbed050.js +0 -1
- codex/static_root/assets/VSelect-DqXJ23Pc.a1360cbed050.js.br +0 -0
- codex/static_root/assets/VSelect-DqXJ23Pc.a1360cbed050.js.gz +0 -0
- codex/static_root/assets/VSelect-DqXJ23Pc.js +0 -1
- codex/static_root/assets/VSelect-DqXJ23Pc.js.br +0 -0
- codex/static_root/assets/VSelect-DqXJ23Pc.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css +0 -1
- codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css.br +0 -0
- codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css.gz +0 -0
- codex/static_root/assets/VSelectionControl-CiViEYoC.css +0 -1
- codex/static_root/assets/VSelectionControl-CiViEYoC.css.br +0 -0
- codex/static_root/assets/VSelectionControl-CiViEYoC.css.gz +0 -0
- codex/static_root/assets/VSelectionControl-CxhDNufT.dd7ca99567fc.js +0 -1
- codex/static_root/assets/VSelectionControl-CxhDNufT.dd7ca99567fc.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CxhDNufT.dd7ca99567fc.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-CxhDNufT.js +0 -1
- codex/static_root/assets/VSelectionControl-CxhDNufT.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CxhDNufT.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css +0 -1
- codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.br +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.gz +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.css +0 -1
- codex/static_root/assets/VSlideGroup-BtXPhMOT.css.br +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.css.gz +0 -0
- codex/static_root/assets/VSlideGroup-DRbthp6q.7365c5542d47.js +0 -1
- codex/static_root/assets/VSlideGroup-DRbthp6q.7365c5542d47.js.br +0 -0
- codex/static_root/assets/VSlideGroup-DRbthp6q.7365c5542d47.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-DRbthp6q.js +0 -1
- codex/static_root/assets/VSlideGroup-DRbthp6q.js.br +0 -0
- codex/static_root/assets/VSlideGroup-DRbthp6q.js.gz +0 -0
- codex/static_root/assets/VTable-Cbq-yJos.c884706cac21.js +0 -1
- codex/static_root/assets/VTable-Cbq-yJos.c884706cac21.js.br +0 -0
- codex/static_root/assets/VTable-Cbq-yJos.c884706cac21.js.gz +0 -0
- codex/static_root/assets/VTable-Cbq-yJos.js +0 -1
- codex/static_root/assets/VTable-Cbq-yJos.js.br +0 -0
- codex/static_root/assets/VTable-Cbq-yJos.js.gz +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css +0 -1
- codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css.br +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css.gz +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.css +0 -1
- codex/static_root/assets/VTextField-Crc3gdNh.css.br +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.css.gz +0 -0
- codex/static_root/assets/VTextField-X5yAw35c.155e276dd747.js +0 -1
- codex/static_root/assets/VTextField-X5yAw35c.155e276dd747.js.br +0 -0
- codex/static_root/assets/VTextField-X5yAw35c.155e276dd747.js.gz +0 -0
- codex/static_root/assets/VTextField-X5yAw35c.js +0 -1
- codex/static_root/assets/VTextField-X5yAw35c.js.br +0 -0
- codex/static_root/assets/VTextField-X5yAw35c.js.gz +0 -0
- codex/static_root/assets/VWindowItem-CRqhVh-9.cd73d01e0591.js +0 -1
- codex/static_root/assets/VWindowItem-CRqhVh-9.cd73d01e0591.js.br +0 -0
- codex/static_root/assets/VWindowItem-CRqhVh-9.cd73d01e0591.js.gz +0 -0
- codex/static_root/assets/VWindowItem-CRqhVh-9.js +0 -1
- codex/static_root/assets/VWindowItem-CRqhVh-9.js.br +0 -0
- codex/static_root/assets/VWindowItem-CRqhVh-9.js.gz +0 -0
- codex/static_root/assets/admin-BFvQwinN.6cfff21f780a.js +0 -1
- codex/static_root/assets/admin-BFvQwinN.6cfff21f780a.js.br +0 -0
- codex/static_root/assets/admin-BFvQwinN.6cfff21f780a.js.gz +0 -0
- codex/static_root/assets/admin-BFvQwinN.js +0 -1
- codex/static_root/assets/admin-BFvQwinN.js.br +0 -0
- codex/static_root/assets/admin-BFvQwinN.js.gz +0 -0
- codex/static_root/assets/admin-DJ7pIXDQ.css +0 -1
- codex/static_root/assets/admin-DJ7pIXDQ.css.br +0 -0
- codex/static_root/assets/admin-DJ7pIXDQ.css.gz +0 -0
- codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css +0 -1
- codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.br +0 -0
- codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.gz +0 -0
- codex/static_root/assets/admin-menu-Jfmp_Yd8.39fa7a18b3b4.js +0 -1
- codex/static_root/assets/admin-menu-Jfmp_Yd8.39fa7a18b3b4.js.br +0 -0
- codex/static_root/assets/admin-menu-Jfmp_Yd8.39fa7a18b3b4.js.gz +0 -0
- codex/static_root/assets/admin-menu-Jfmp_Yd8.js +0 -1
- codex/static_root/assets/admin-menu-Jfmp_Yd8.js.br +0 -0
- codex/static_root/assets/admin-menu-Jfmp_Yd8.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.cbf73c71330d.js +0 -1
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.cbf73c71330d.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.cbf73c71330d.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.js +0 -1
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.js.gz +0 -0
- codex/static_root/assets/browser-CctlSJji.css +0 -1
- codex/static_root/assets/browser-CctlSJji.css.br +0 -0
- codex/static_root/assets/browser-CctlSJji.css.gz +0 -0
- codex/static_root/assets/browser-CctlSJji.d42d796476d2.css +0 -1
- codex/static_root/assets/browser-CctlSJji.d42d796476d2.css.br +0 -0
- codex/static_root/assets/browser-CctlSJji.d42d796476d2.css.gz +0 -0
- codex/static_root/assets/browser-DJnEeVHz.a78c47516b08.js +0 -1
- codex/static_root/assets/browser-DJnEeVHz.a78c47516b08.js.br +0 -0
- codex/static_root/assets/browser-DJnEeVHz.a78c47516b08.js.gz +0 -0
- codex/static_root/assets/browser-DJnEeVHz.js +0 -1
- codex/static_root/assets/browser-DJnEeVHz.js.br +0 -0
- codex/static_root/assets/browser-DJnEeVHz.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-DJtOQw7K.be7fa5ec653d.js +0 -1
- codex/static_root/assets/change-password-dialog-DJtOQw7K.be7fa5ec653d.js.br +0 -0
- codex/static_root/assets/change-password-dialog-DJtOQw7K.be7fa5ec653d.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-DJtOQw7K.js +0 -1
- codex/static_root/assets/change-password-dialog-DJtOQw7K.js.br +0 -0
- codex/static_root/assets/change-password-dialog-DJtOQw7K.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CME4gKSZ.1606233e784c.js +0 -1
- codex/static_root/assets/confirm-dialog-CME4gKSZ.1606233e784c.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CME4gKSZ.1606233e784c.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CME4gKSZ.js +0 -1
- codex/static_root/assets/confirm-dialog-CME4gKSZ.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CME4gKSZ.js.gz +0 -0
- codex/static_root/assets/datetime-column-D_F30OLW.09cdce0ef96e.js +0 -1
- codex/static_root/assets/datetime-column-D_F30OLW.09cdce0ef96e.js.br +0 -2
- codex/static_root/assets/datetime-column-D_F30OLW.09cdce0ef96e.js.gz +0 -0
- codex/static_root/assets/datetime-column-D_F30OLW.js +0 -1
- codex/static_root/assets/datetime-column-D_F30OLW.js.br +0 -2
- codex/static_root/assets/datetime-column-D_F30OLW.js.gz +0 -0
- codex/static_root/assets/filter-ud5mPZpn.0f0a537959aa.js.br +0 -0
- codex/static_root/assets/filter-ud5mPZpn.0f0a537959aa.js.gz +0 -0
- codex/static_root/assets/filter-ud5mPZpn.js.br +0 -0
- codex/static_root/assets/filter-ud5mPZpn.js.gz +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css +0 -1
- codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.br +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.gz +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.css +0 -1
- codex/static_root/assets/flag-tab-CqWovuBu.css.br +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.css.gz +0 -0
- codex/static_root/assets/flag-tab-k2g6u_vi.3e1da9318af9.js +0 -1
- codex/static_root/assets/flag-tab-k2g6u_vi.3e1da9318af9.js.br +0 -0
- codex/static_root/assets/flag-tab-k2g6u_vi.3e1da9318af9.js.gz +0 -0
- codex/static_root/assets/flag-tab-k2g6u_vi.js +0 -1
- codex/static_root/assets/flag-tab-k2g6u_vi.js.br +0 -0
- codex/static_root/assets/flag-tab-k2g6u_vi.js.gz +0 -0
- codex/static_root/assets/group-tab-C6Ykf03Z.ff0cc204013a.js +0 -1
- codex/static_root/assets/group-tab-C6Ykf03Z.ff0cc204013a.js.br +0 -0
- codex/static_root/assets/group-tab-C6Ykf03Z.ff0cc204013a.js.gz +0 -0
- codex/static_root/assets/group-tab-C6Ykf03Z.js +0 -1
- codex/static_root/assets/group-tab-C6Ykf03Z.js.br +0 -0
- codex/static_root/assets/group-tab-C6Ykf03Z.js.gz +0 -0
- codex/static_root/assets/http-error-Ctcws1xe.cfd378a792d2.css +0 -1
- codex/static_root/assets/http-error-Ctcws1xe.cfd378a792d2.css.br +0 -0
- codex/static_root/assets/http-error-Ctcws1xe.cfd378a792d2.css.gz +0 -0
- codex/static_root/assets/http-error-Ctcws1xe.css +0 -1
- codex/static_root/assets/http-error-Ctcws1xe.css.br +0 -0
- codex/static_root/assets/http-error-Ctcws1xe.css.gz +0 -0
- codex/static_root/assets/http-error-DQBHK8v5.aea50b1327fd.js +0 -1
- codex/static_root/assets/http-error-DQBHK8v5.aea50b1327fd.js.br +0 -0
- codex/static_root/assets/http-error-DQBHK8v5.aea50b1327fd.js.gz +0 -0
- codex/static_root/assets/http-error-DQBHK8v5.js +0 -1
- codex/static_root/assets/http-error-DQBHK8v5.js.br +0 -0
- codex/static_root/assets/http-error-DQBHK8v5.js.gz +0 -0
- codex/static_root/assets/index-ClGiHwWc.0717bacf5135.js +0 -1
- codex/static_root/assets/index-ClGiHwWc.0717bacf5135.js.br +0 -0
- codex/static_root/assets/index-ClGiHwWc.0717bacf5135.js.gz +0 -0
- codex/static_root/assets/index-ClGiHwWc.js +0 -1
- codex/static_root/assets/index-ClGiHwWc.js.br +0 -0
- codex/static_root/assets/index-ClGiHwWc.js.gz +0 -0
- codex/static_root/assets/library-tab-BpinbqAu.53fa2625e727.js +0 -1
- codex/static_root/assets/library-tab-BpinbqAu.53fa2625e727.js.br +0 -0
- codex/static_root/assets/library-tab-BpinbqAu.53fa2625e727.js.gz +0 -0
- codex/static_root/assets/library-tab-BpinbqAu.js +0 -1
- codex/static_root/assets/library-tab-BpinbqAu.js.br +0 -0
- codex/static_root/assets/library-tab-BpinbqAu.js.gz +0 -0
- codex/static_root/assets/library-tab-Cat0MAK5.5911f022188e.css.br +0 -0
- codex/static_root/assets/library-tab-Cat0MAK5.5911f022188e.css.gz +0 -0
- codex/static_root/assets/library-tab-Cat0MAK5.css.br +0 -0
- codex/static_root/assets/library-tab-Cat0MAK5.css.gz +0 -0
- codex/static_root/assets/main-BVKrDunc.1c6f8cdc3afb.js +0 -35
- codex/static_root/assets/main-BVKrDunc.1c6f8cdc3afb.js.br +0 -0
- codex/static_root/assets/main-BVKrDunc.1c6f8cdc3afb.js.gz +0 -0
- codex/static_root/assets/main-BVKrDunc.js +0 -35
- codex/static_root/assets/main-BVKrDunc.js.br +0 -0
- codex/static_root/assets/main-BVKrDunc.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.f2e95b19621c.js +0 -1
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.f2e95b19621c.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.f2e95b19621c.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.js +0 -1
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.546121fa7a0d.css +0 -1
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.546121fa7a0d.css.br +0 -0
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.546121fa7a0d.css.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.css +0 -1
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.css.br +0 -0
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.css.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Diad0EdD.140911bf86af.js +0 -1
- codex/static_root/assets/pagination-toolbar-Diad0EdD.140911bf86af.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-Diad0EdD.140911bf86af.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Diad0EdD.js +0 -1
- codex/static_root/assets/pagination-toolbar-Diad0EdD.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-Diad0EdD.js.gz +0 -0
- codex/static_root/assets/pdf-doc-b-GyNR6z.c9d18f0d36ed.js +0 -305
- codex/static_root/assets/pdf-doc-b-GyNR6z.c9d18f0d36ed.js.br +0 -0
- codex/static_root/assets/pdf-doc-b-GyNR6z.c9d18f0d36ed.js.gz +0 -0
- codex/static_root/assets/pdf-doc-b-GyNR6z.js +0 -305
- codex/static_root/assets/pdf-doc-b-GyNR6z.js.br +0 -0
- codex/static_root/assets/pdf-doc-b-GyNR6z.js.gz +0 -0
- codex/static_root/assets/reader-2up6WEuE.c56ad81d14c6.js +0 -2
- codex/static_root/assets/reader-2up6WEuE.c56ad81d14c6.js.br +0 -0
- codex/static_root/assets/reader-2up6WEuE.c56ad81d14c6.js.gz +0 -0
- codex/static_root/assets/reader-2up6WEuE.js +0 -2
- codex/static_root/assets/reader-2up6WEuE.js.br +0 -0
- codex/static_root/assets/reader-2up6WEuE.js.gz +0 -0
- codex/static_root/assets/reader-Dd2KmdCN.115d4bfe9280.css.br +0 -0
- codex/static_root/assets/reader-Dd2KmdCN.115d4bfe9280.css.gz +0 -0
- codex/static_root/assets/reader-Dd2KmdCN.css.br +0 -0
- codex/static_root/assets/reader-Dd2KmdCN.css.gz +0 -0
- codex/static_root/assets/relation-chips-piYv1IcD.f8a2ae79de89.js +0 -1
- codex/static_root/assets/relation-chips-piYv1IcD.f8a2ae79de89.js.br +0 -0
- codex/static_root/assets/relation-chips-piYv1IcD.f8a2ae79de89.js.gz +0 -0
- codex/static_root/assets/relation-chips-piYv1IcD.js +0 -1
- codex/static_root/assets/relation-chips-piYv1IcD.js.br +0 -0
- codex/static_root/assets/relation-chips-piYv1IcD.js.gz +0 -0
- codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css +0 -1
- codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css.br +0 -0
- codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css.gz +0 -0
- codex/static_root/assets/settings-drawer-DKncO_vX.css +0 -1
- codex/static_root/assets/settings-drawer-DKncO_vX.css.br +0 -0
- codex/static_root/assets/settings-drawer-DKncO_vX.css.gz +0 -0
- codex/static_root/assets/settings-drawer-yVoY-WCS.1240cc47a246.js +0 -2
- codex/static_root/assets/settings-drawer-yVoY-WCS.1240cc47a246.js.br +0 -0
- codex/static_root/assets/settings-drawer-yVoY-WCS.1240cc47a246.js.gz +0 -0
- codex/static_root/assets/settings-drawer-yVoY-WCS.js +0 -2
- codex/static_root/assets/settings-drawer-yVoY-WCS.js.br +0 -0
- codex/static_root/assets/settings-drawer-yVoY-WCS.js.gz +0 -0
- codex/static_root/assets/stats-tab-bqSPLvTp.05106cb03ef0.js +0 -1
- codex/static_root/assets/stats-tab-bqSPLvTp.05106cb03ef0.js.br +0 -0
- codex/static_root/assets/stats-tab-bqSPLvTp.05106cb03ef0.js.gz +0 -0
- codex/static_root/assets/stats-tab-bqSPLvTp.js +0 -1
- codex/static_root/assets/stats-tab-bqSPLvTp.js.br +0 -0
- codex/static_root/assets/stats-tab-bqSPLvTp.js.gz +0 -0
- codex/static_root/assets/task-tab-DWPKaGPT.da4df28dde5c.js +0 -1
- codex/static_root/assets/task-tab-DWPKaGPT.da4df28dde5c.js.br +0 -0
- codex/static_root/assets/task-tab-DWPKaGPT.da4df28dde5c.js.gz +0 -0
- codex/static_root/assets/task-tab-DWPKaGPT.js +0 -1
- codex/static_root/assets/task-tab-DWPKaGPT.js.br +0 -0
- codex/static_root/assets/task-tab-DWPKaGPT.js.gz +0 -0
- codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css +0 -1
- codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.br +0 -4
- codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.gz +0 -0
- codex/static_root/assets/transition-5LRFTPo5.css +0 -1
- codex/static_root/assets/transition-5LRFTPo5.css.br +0 -4
- codex/static_root/assets/transition-5LRFTPo5.css.gz +0 -0
- codex/static_root/assets/transition-DWVQ2EZ3.0bdfaa37b937.js +0 -1
- codex/static_root/assets/transition-DWVQ2EZ3.0bdfaa37b937.js.br +0 -0
- codex/static_root/assets/transition-DWVQ2EZ3.0bdfaa37b937.js.gz +0 -0
- codex/static_root/assets/transition-DWVQ2EZ3.js +0 -1
- codex/static_root/assets/transition-DWVQ2EZ3.js.br +0 -0
- codex/static_root/assets/transition-DWVQ2EZ3.js.gz +0 -0
- codex/static_root/assets/unauthorized-CEGD20tR.064b0993a944.js +0 -1
- codex/static_root/assets/unauthorized-CEGD20tR.064b0993a944.js.br +0 -0
- codex/static_root/assets/unauthorized-CEGD20tR.064b0993a944.js.gz +0 -0
- codex/static_root/assets/unauthorized-CEGD20tR.js +0 -1
- codex/static_root/assets/unauthorized-CEGD20tR.js.br +0 -0
- codex/static_root/assets/unauthorized-CEGD20tR.js.gz +0 -0
- codex/static_root/assets/unauthorized-DyojW2ic.css +0 -1
- codex/static_root/assets/unauthorized-DyojW2ic.css.br +0 -0
- codex/static_root/assets/unauthorized-DyojW2ic.css.gz +0 -0
- codex/static_root/assets/unauthorized-DyojW2ic.feefa7628a23.css +0 -1
- codex/static_root/assets/unauthorized-DyojW2ic.feefa7628a23.css.br +0 -0
- codex/static_root/assets/unauthorized-DyojW2ic.feefa7628a23.css.gz +0 -0
- codex/static_root/assets/user-tab-EsokzMCB.b0acc46b56a3.js +0 -1
- codex/static_root/assets/user-tab-EsokzMCB.b0acc46b56a3.js.br +0 -0
- codex/static_root/assets/user-tab-EsokzMCB.b0acc46b56a3.js.gz +0 -0
- codex/static_root/assets/user-tab-EsokzMCB.js +0 -1
- codex/static_root/assets/user-tab-EsokzMCB.js.br +0 -0
- codex/static_root/assets/user-tab-EsokzMCB.js.gz +0 -0
- codex/static_root/manifest.4a38de3db1c5.json +0 -712
- codex/static_root/manifest.4a38de3db1c5.json.br +0 -0
- codex/static_root/manifest.4a38de3db1c5.json.gz +0 -0
- {codex-1.7.2.dist-info → codex-1.7.3a0.dist-info}/LICENSE +0 -0
- {codex-1.7.2.dist-info → codex-1.7.3a0.dist-info}/WHEEL +0 -0
- {codex-1.7.2.dist-info → codex-1.7.3a0.dist-info}/entry_points.txt +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"paths": {"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/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/fonts/glyphicons-halflings-regular.svg": "rest_framework/fonts/glyphicons-halflings-regular.08eda92397ae.svg", "rest_framework/fonts/glyphicons-halflings-regular.woff": "rest_framework/fonts/glyphicons-halflings-regular.fa2772327f55.woff", "rest_framework/fonts/fontawesome-webfont.ttf": "rest_framework/fonts/fontawesome-webfont.dcb26c7239d8.ttf", "rest_framework/fonts/glyphicons-halflings-regular.eot": "rest_framework/fonts/glyphicons-halflings-regular.f4769f9bdb74.eot", "rest_framework/fonts/fontawesome-webfont.svg": "rest_framework/fonts/fontawesome-webfont.83e37a11f9d7.svg", "rest_framework/fonts/glyphicons-halflings-regular.ttf": "rest_framework/fonts/glyphicons-halflings-regular.e18bbf611f2a.ttf", "rest_framework/fonts/fontawesome-webfont.eot": "rest_framework/fonts/fontawesome-webfont.8b27bc96115c.eot", "rest_framework/fonts/fontawesome-webfont.woff": "rest_framework/fonts/fontawesome-webfont.3293616ec0c6.woff", "rest_framework/fonts/glyphicons-halflings-regular.woff2": "rest_framework/fonts/glyphicons-halflings-regular.448c34a56d69.woff2", "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/img/grid.png": "rest_framework/img/grid.a4b938cf382b.png", "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/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/default.css": "rest_framework/css/default.789dfb5732d7.css", "rest_framework/css/bootstrap-theme.min.css.map": "rest_framework/css/bootstrap-theme.min.css.51806092cc05.map", "rest_framework/css/bootstrap.min.css.map": "rest_framework/css/bootstrap.min.css.cafbda9c0e9e.map", "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/default.js": "rest_framework/js/default.5b08897dbdc3.js", "rest_framework/js/load-ajax-form.js": "rest_framework/js/load-ajax-form.8cdb3a9f3466.js", "rest_framework/js/coreapi-0.1.1.js": "rest_framework/js/coreapi-0.1.1.8851fb9336c9.js", "rest_framework/js/csrf.js": "rest_framework/js/csrf.455080a7b2ce.js", "rest_framework/js/jquery-3.7.1.min.js": "rest_framework/js/jquery-3.7.1.min.2c872dbe60f4.js", "rest_framework/js/bootstrap.min.js": "rest_framework/js/bootstrap.min.2f34b630ffe3.js", "img/story-arc.svg": "img/story-arc.ca10014355ef.svg", "img/logo-maskable.svg": "img/logo-maskable.8f7de7f1c6a8.svg", "img/folder.svg": "img/folder.f28936a3701d.svg", "img/missing-cover-165.webp": "img/missing-cover-165.0743171f2148.webp", "img/missing-cover.svg": "img/missing-cover.ddb038cc2c56.svg", "img/publisher.svg": "img/publisher.82d378fcd601.svg", "img/logo-32.webp": "img/logo-32.5688944495bf.webp", "img/imprint.svg": "img/imprint.7c2adebb76d6.svg", "img/logo.svg": "img/logo.0f5344a028ca.svg", "img/volume.svg": "img/volume.814e4c79461a.svg", "img/logo-maskable-180.webp": "img/logo-maskable-180.c58d966aa64e.webp", "img/series.svg": "img/series.ec8a889b8f95.svg", "pwa/offline.html": "pwa/offline.7bfaf9f94bf9.html", "assets/transition-DWVQ2EZ3.js": "assets/transition-DWVQ2EZ3.0bdfaa37b937.js", "assets/change-password-dialog-C_EOKOn9.css": "assets/change-password-dialog-C_EOKOn9.a30e68c6e303.css", "assets/VCheckbox-DLMzIII1.js": "assets/VCheckbox-DLMzIII1.1ff8fc2d9a21.js", "assets/admin-settings-button-progress-BAk-B1sR.js": "assets/admin-settings-button-progress-BAk-B1sR.cbf73c71330d.js", "assets/reader-2up6WEuE.js": "assets/reader-2up6WEuE.c56ad81d14c6.js", "assets/main-BZ73p_WW.css": "assets/main-BZ73p_WW.d529e8b3f52a.css", "assets/VTextField-X5yAw35c.js": "assets/VTextField-X5yAw35c.155e276dd747.js", "assets/VSelect-DLu8bpcs.css": "assets/VSelect-DLu8bpcs.98bdcf35411c.css", "assets/transition-5LRFTPo5.css": "assets/transition-5LRFTPo5.3d726f9bbcb0.css", "assets/VCheckboxBtn-BzoQl8XC.js": "assets/VCheckboxBtn-BzoQl8XC.094679a3624b.js", "assets/stats-tab-BlXGStge.css": "assets/stats-tab-BlXGStge.9fdb0106124d.css", "assets/datetime-column-DeCthByU.css": "assets/datetime-column-DeCthByU.1f3bf499e063.css", "assets/browser-CctlSJji.css": "assets/browser-CctlSJji.d42d796476d2.css", "assets/VCombobox-CBY8K5CP.js": "assets/VCombobox-CBY8K5CP.fcf2221a9edd.js", "assets/flag-tab-k2g6u_vi.js": "assets/flag-tab-k2g6u_vi.3e1da9318af9.js", "assets/settings-drawer-DKncO_vX.css": "assets/settings-drawer-DKncO_vX.0a2cd24cd904.css", "assets/VSelect-DqXJ23Pc.js": "assets/VSelect-DqXJ23Pc.a1360cbed050.js", "assets/admin-settings-button-progress-DUUQfVsZ.css": "assets/admin-settings-button-progress-DUUQfVsZ.2548c49a853e.css", "assets/admin-menu-B9bzD6hV.css": "assets/admin-menu-B9bzD6hV.c13b7df2ff57.css", "assets/flag-tab-CqWovuBu.css": "assets/flag-tab-CqWovuBu.4dfc6b251e85.css", "assets/stats-tab-bqSPLvTp.js": "assets/stats-tab-bqSPLvTp.05106cb03ef0.js", "assets/admin-BFvQwinN.js": "assets/admin-BFvQwinN.6cfff21f780a.js", "assets/index-CL_6g4tJ.css": "assets/index-CL_6g4tJ.523d7b3d350f.css", "assets/relation-chips-ByfWwuQc.css": "assets/relation-chips-ByfWwuQc.01269a188e01.css", "assets/pager-full-pdf-C1ZSyXfG.js": "assets/pager-full-pdf-C1ZSyXfG.f2e95b19621c.js", "assets/materialdesignicons-webfont-PXm3-2wK.woff": "assets/materialdesignicons-webfont-PXm3-2wK.026b7ac9c43c.woff", "assets/VDialog-DXQz0Ylp.css": "assets/VDialog-DXQz0Ylp.7b23d86dbd0d.css", "assets/user-tab-EsokzMCB.js": "assets/user-tab-EsokzMCB.b0acc46b56a3.js", "assets/VTable-Cbq-yJos.js": "assets/VTable-Cbq-yJos.c884706cac21.js", "assets/group-tab-DkIN1Heu.css": "assets/group-tab-DkIN1Heu.948e907b1e6b.css", "assets/VSelectionControl-CxhDNufT.js": "assets/VSelectionControl-CxhDNufT.dd7ca99567fc.js", "assets/library-tab-BpinbqAu.js": "assets/library-tab-BpinbqAu.53fa2625e727.js", "assets/materialdesignicons-webfont-B7mPwVP_.ttf": "assets/materialdesignicons-webfont-B7mPwVP_.6e435534bd35.ttf", "assets/group-tab-C6Ykf03Z.js": "assets/group-tab-C6Ykf03Z.ff0cc204013a.js", "assets/VCombobox-bwEYrXCg.css": "assets/VCombobox-bwEYrXCg.9f25a34994e2.css", "assets/unauthorized-CEGD20tR.js": "assets/unauthorized-CEGD20tR.064b0993a944.js", "assets/VSlideGroup-BtXPhMOT.css": "assets/VSlideGroup-BtXPhMOT.830f136ffd41.css", "assets/filter-ud5mPZpn.js": "assets/filter-ud5mPZpn.0f0a537959aa.js", "assets/datetime-column-D_F30OLW.js": "assets/datetime-column-D_F30OLW.09cdce0ef96e.js", "assets/VTextField-Crc3gdNh.css": "assets/VTextField-Crc3gdNh.39995ccf4d52.css", "assets/confirm-dialog-54rblwf7.css": "assets/confirm-dialog-54rblwf7.9b5915b112c0.css", "assets/VTable-Y5Sc3hJd.css": "assets/VTable-Y5Sc3hJd.c36f0a6a30cf.css", "assets/VExpansionPanels-6G1AUajL.css": "assets/VExpansionPanels-6G1AUajL.5b17872981df.css", "assets/VSlideGroup-DRbthp6q.js": "assets/VSlideGroup-DRbthp6q.7365c5542d47.js", "assets/task-tab-EGlhcKTH.css": "assets/task-tab-EGlhcKTH.478e74041f80.css", "assets/materialdesignicons-webfont-CSr8KVlo.eot": "assets/materialdesignicons-webfont-CSr8KVlo.8ced95a05e3c.eot", "assets/VSelectionControl-CiViEYoC.css": "assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css", "assets/copy-to-clipboard-DoUvDJVx.js": "assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js", "assets/VWindowItem-CRqhVh-9.js": "assets/VWindowItem-CRqhVh-9.cd73d01e0591.js", "assets/VRadioGroup-i2qP9Wu9.css": "assets/VRadioGroup-i2qP9Wu9.8e3741381961.css", "assets/VDialog-Db4tJYqR.js": "assets/VDialog-Db4tJYqR.e21a79a5030e.js", "assets/reader-Dd2KmdCN.css": "assets/reader-Dd2KmdCN.115d4bfe9280.css", "assets/change-password-dialog-DJtOQw7K.js": "assets/change-password-dialog-DJtOQw7K.be7fa5ec653d.js", "assets/library-tab-Cat0MAK5.css": "assets/library-tab-Cat0MAK5.5911f022188e.css", "assets/VWindowItem-ByIod57Y.css": "assets/VWindowItem-ByIod57Y.f7fb19752bf3.css", "assets/settings-drawer-yVoY-WCS.js": "assets/settings-drawer-yVoY-WCS.1240cc47a246.js", "assets/browser-DJnEeVHz.js": "assets/browser-DJnEeVHz.a78c47516b08.js", "assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "assets/materialdesignicons-webfont-Dp5v-WZN.1d7bcee1b302.woff2", "assets/VExpansionPanels-DN4yGbOt.js": "assets/VExpansionPanels-DN4yGbOt.163e59e38865.js", "assets/index-ClGiHwWc.js": "assets/index-ClGiHwWc.0717bacf5135.js", "assets/VCheckbox-CMKdyl0R.css": "assets/VCheckbox-CMKdyl0R.016ed8d222c4.css", "assets/http-error-Ctcws1xe.css": "assets/http-error-Ctcws1xe.cfd378a792d2.css", "assets/admin-menu-Jfmp_Yd8.js": "assets/admin-menu-Jfmp_Yd8.39fa7a18b3b4.js", "assets/confirm-dialog-CME4gKSZ.js": "assets/confirm-dialog-CME4gKSZ.1606233e784c.js", "assets/pdf-doc-b-GyNR6z.js": "assets/pdf-doc-b-GyNR6z.c9d18f0d36ed.js", "assets/unauthorized-DyojW2ic.css": "assets/unauthorized-DyojW2ic.feefa7628a23.css", "assets/http-error-DQBHK8v5.js": "assets/http-error-DQBHK8v5.aea50b1327fd.js", "assets/admin-DJ7pIXDQ.css": "assets/admin-DJ7pIXDQ.e2a77af73ef2.css", "assets/pagination-toolbar-Cx_9nh6D.css": "assets/pagination-toolbar-Cx_9nh6D.546121fa7a0d.css", "assets/VRadioGroup-D2-PWEfs.js": "assets/VRadioGroup-D2-PWEfs.ce7644863c25.js", "assets/pagination-toolbar-Diad0EdD.js": "assets/pagination-toolbar-Diad0EdD.140911bf86af.js", "assets/relation-chips-piYv1IcD.js": "assets/relation-chips-piYv1IcD.f8a2ae79de89.js", "assets/main-BVKrDunc.js": "assets/main-BVKrDunc.1c6f8cdc3afb.js", "assets/task-tab-DWPKaGPT.js": "assets/task-tab-DWPKaGPT.da4df28dde5c.js", "assets/pdf-doc-CG5-AZ2M.css": "assets/pdf-doc-CG5-AZ2M.b94aac7e3313.css", "robots.txt": "robots.b6216d61c03e.txt", "manifest.json": "manifest.4a38de3db1c5.json"}, "version": "1.1", "hash": "3d42fa5855cb"}
|
|
1
|
+
{"paths": {"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/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/fonts/glyphicons-halflings-regular.svg": "rest_framework/fonts/glyphicons-halflings-regular.08eda92397ae.svg", "rest_framework/fonts/glyphicons-halflings-regular.woff": "rest_framework/fonts/glyphicons-halflings-regular.fa2772327f55.woff", "rest_framework/fonts/fontawesome-webfont.ttf": "rest_framework/fonts/fontawesome-webfont.dcb26c7239d8.ttf", "rest_framework/fonts/glyphicons-halflings-regular.eot": "rest_framework/fonts/glyphicons-halflings-regular.f4769f9bdb74.eot", "rest_framework/fonts/fontawesome-webfont.svg": "rest_framework/fonts/fontawesome-webfont.83e37a11f9d7.svg", "rest_framework/fonts/glyphicons-halflings-regular.ttf": "rest_framework/fonts/glyphicons-halflings-regular.e18bbf611f2a.ttf", "rest_framework/fonts/fontawesome-webfont.eot": "rest_framework/fonts/fontawesome-webfont.8b27bc96115c.eot", "rest_framework/fonts/fontawesome-webfont.woff": "rest_framework/fonts/fontawesome-webfont.3293616ec0c6.woff", "rest_framework/fonts/glyphicons-halflings-regular.woff2": "rest_framework/fonts/glyphicons-halflings-regular.448c34a56d69.woff2", "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/img/grid.png": "rest_framework/img/grid.a4b938cf382b.png", "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/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/default.css": "rest_framework/css/default.789dfb5732d7.css", "rest_framework/css/bootstrap-theme.min.css.map": "rest_framework/css/bootstrap-theme.min.css.51806092cc05.map", "rest_framework/css/bootstrap.min.css.map": "rest_framework/css/bootstrap.min.css.cafbda9c0e9e.map", "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/default.js": "rest_framework/js/default.5b08897dbdc3.js", "rest_framework/js/load-ajax-form.js": "rest_framework/js/load-ajax-form.8cdb3a9f3466.js", "rest_framework/js/coreapi-0.1.1.js": "rest_framework/js/coreapi-0.1.1.8851fb9336c9.js", "rest_framework/js/csrf.js": "rest_framework/js/csrf.455080a7b2ce.js", "rest_framework/js/jquery-3.7.1.min.js": "rest_framework/js/jquery-3.7.1.min.2c872dbe60f4.js", "rest_framework/js/bootstrap.min.js": "rest_framework/js/bootstrap.min.2f34b630ffe3.js", "img/story-arc.svg": "img/story-arc.ca10014355ef.svg", "img/logo-maskable.svg": "img/logo-maskable.8f7de7f1c6a8.svg", "img/folder.svg": "img/folder.f28936a3701d.svg", "img/missing-cover-165.webp": "img/missing-cover-165.0743171f2148.webp", "img/missing-cover.svg": "img/missing-cover.ddb038cc2c56.svg", "img/publisher.svg": "img/publisher.82d378fcd601.svg", "img/logo-32.webp": "img/logo-32.5688944495bf.webp", "img/imprint.svg": "img/imprint.7c2adebb76d6.svg", "img/logo.svg": "img/logo.0f5344a028ca.svg", "img/volume.svg": "img/volume.814e4c79461a.svg", "img/logo-maskable-180.webp": "img/logo-maskable-180.c58d966aa64e.webp", "img/series.svg": "img/series.ec8a889b8f95.svg", "pwa/offline.html": "pwa/offline.7bfaf9f94bf9.html", "assets/change-password-dialog-C_EOKOn9.css": "assets/change-password-dialog-C_EOKOn9.a30e68c6e303.css", "assets/pager-full-pdf-BXd9Y5oQ.js": "assets/pager-full-pdf-BXd9Y5oQ.04a4f5c451b4.js", "assets/task-tab-CG9_bi6Z.js": "assets/task-tab-CG9_bi6Z.ad9f647f8e5f.js", "assets/main-BZ73p_WW.css": "assets/main-BZ73p_WW.d529e8b3f52a.css", "assets/VExpansionPanels-b0xWLH75.js": "assets/VExpansionPanels-b0xWLH75.bff6ea8b4055.js", "assets/datetime-column-CU19rCbi.js": "assets/datetime-column-CU19rCbi.9edc0d2da736.js", "assets/pagination-toolbar-DSe0TkMm.css": "assets/pagination-toolbar-DSe0TkMm.dcb0eba65827.css", "assets/stats-tab-BlXGStge.css": "assets/stats-tab-BlXGStge.9fdb0106124d.css", "assets/browser-DiAN9Ipo.js": "assets/browser-DiAN9Ipo.a5b62a3cbe1d.js", "assets/datetime-column-DeCthByU.css": "assets/datetime-column-DeCthByU.1f3bf499e063.css", "assets/VDialog-Dyd05WHA.css": "assets/VDialog-Dyd05WHA.b07aca713774.css", "assets/VDivider-CuRohbVQ.js": "assets/VDivider-CuRohbVQ.3c12b040aed7.js", "assets/forwardRefs-zKOZsbbr.css": "assets/forwardRefs-zKOZsbbr.9b56b4459240.css", "assets/reader-B3hgta6g.css": "assets/reader-B3hgta6g.2ed32f08e906.css", "assets/admin-settings-button-progress-DUUQfVsZ.css": "assets/admin-settings-button-progress-DUUQfVsZ.2548c49a853e.css", "assets/admin-menu-B9bzD6hV.css": "assets/admin-menu-B9bzD6hV.c13b7df2ff57.css", "assets/index-CL_6g4tJ.css": "assets/index-CL_6g4tJ.523d7b3d350f.css", "assets/relation-chips-ByfWwuQc.css": "assets/relation-chips-ByfWwuQc.01269a188e01.css", "assets/VDialog-IrbBYFLM.js": "assets/VDialog-IrbBYFLM.91a058d572c4.js", "assets/materialdesignicons-webfont-PXm3-2wK.woff": "assets/materialdesignicons-webfont-PXm3-2wK.026b7ac9c43c.woff", "assets/stats-tab-0ptRCeKw.js": "assets/stats-tab-0ptRCeKw.5514d3508e37.js", "assets/VCheckboxBtn-DBKqrZGq.js": "assets/VCheckboxBtn-DBKqrZGq.467e75859b62.js", "assets/user-tab-BOxWlpY7.js": "assets/user-tab-BOxWlpY7.1a94280a799b.js", "assets/http-error-DmFqD2Xz.js": "assets/http-error-DmFqD2Xz.593d626b5f1b.js", "assets/http-error-DEJmFobt.css": "assets/http-error-DEJmFobt.8c13689ae574.css", "assets/group-tab-DkIN1Heu.css": "assets/group-tab-DkIN1Heu.948e907b1e6b.css", "assets/admin-BmuWJcAB.js": "assets/admin-BmuWJcAB.b0b253aefd88.js", "assets/flag-tab-DHGfv0Q3.css": "assets/flag-tab-DHGfv0Q3.2b7ef394b850.css", "assets/materialdesignicons-webfont-B7mPwVP_.ttf": "assets/materialdesignicons-webfont-B7mPwVP_.6e435534bd35.ttf", "assets/VCombobox-bwEYrXCg.css": "assets/VCombobox-bwEYrXCg.9f25a34994e2.css", "assets/unauthorized-VnIXUO1w.css": "assets/unauthorized-VnIXUO1w.c5536d9dae75.css", "assets/confirm-dialog-54rblwf7.css": "assets/confirm-dialog-54rblwf7.9b5915b112c0.css", "assets/pagination-toolbar-D_whea1o.js": "assets/pagination-toolbar-D_whea1o.9bbd927058f1.js", "assets/VTable-Y5Sc3hJd.css": "assets/VTable-Y5Sc3hJd.c36f0a6a30cf.css", "assets/admin-Izb24SXM.js": "assets/admin-Izb24SXM.504ea9d9515c.js", "assets/VExpansionPanels-6G1AUajL.css": "assets/VExpansionPanels-6G1AUajL.5b17872981df.css", "assets/VSelect-BsuB-2P1.js": "assets/VSelect-BsuB-2P1.abe187c8b53f.js", "assets/browser-CReWGhn_.css": "assets/browser-CReWGhn_.521193ab0710.css", "assets/filter-CZ7kkBLq.js": "assets/filter-CZ7kkBLq.171b4fcba146.js", "assets/task-tab-EGlhcKTH.css": "assets/task-tab-EGlhcKTH.478e74041f80.css", "assets/VForm-B4hkqnS8.js": "assets/VForm-B4hkqnS8.afbd5cf0908a.js", "assets/materialdesignicons-webfont-CSr8KVlo.eot": "assets/materialdesignicons-webfont-CSr8KVlo.8ced95a05e3c.eot", "assets/VRadioGroup-Cbayik6d.js": "assets/VRadioGroup-Cbayik6d.034f0f275265.js", "assets/pdf-doc-dnr5fHbU.js": "assets/pdf-doc-dnr5fHbU.fa1d7ed9255b.js", "assets/library-tab-Ce6qaeCV.css": "assets/library-tab-Ce6qaeCV.75baedb7e976.css", "assets/VSelectionControl-L41n5bnX.js": "assets/VSelectionControl-L41n5bnX.f4674bb62425.js", "assets/admin-dm3bSP7O.css": "assets/admin-dm3bSP7O.ae1234cc0beb.css", "assets/forwardRefs-DNAemYUk.js": "assets/forwardRefs-DNAemYUk.06a315272ed9.js", "assets/VCheckbox-pHjSEgdV.js": "assets/VCheckbox-pHjSEgdV.176f3c1f4191.js", "assets/copy-to-clipboard-DoUvDJVx.js": "assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js", "assets/index-hvGLIBbY.js": "assets/index-hvGLIBbY.30ce8cca0c6d.js", "assets/VCombobox-Bg7uOTbF.js": "assets/VCombobox-Bg7uOTbF.2fc6073b789f.js", "assets/VRadioGroup-i2qP9Wu9.css": "assets/VRadioGroup-i2qP9Wu9.8e3741381961.css", "assets/confirm-dialog-CBLQOik_.js": "assets/confirm-dialog-CBLQOik_.f53acd0c622a.js", "assets/settings-drawer-CqJ4gXLq.css": "assets/settings-drawer-CqJ4gXLq.75a6ea969e71.css", "assets/VWindowItem-ByIod57Y.css": "assets/VWindowItem-ByIod57Y.f7fb19752bf3.css", "assets/reader-Cn-ra_Dv.js": "assets/reader-Cn-ra_Dv.f38c0b419dec.js", "assets/settings-drawer-1UEq8JY1.js": "assets/settings-drawer-1UEq8JY1.d95cee9aefb5.js", "assets/VTable-CYv4gUUt.js": "assets/VTable-CYv4gUUt.76e4658abeb3.js", "assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "assets/materialdesignicons-webfont-Dp5v-WZN.1d7bcee1b302.woff2", "assets/VSelectionControl-DLxcLoTI.css": "assets/VSelectionControl-DLxcLoTI.cc18de4e83f6.css", "assets/library-tab-CF-RAEgP.js": "assets/library-tab-CF-RAEgP.a0ad816fb994.js", "assets/admin-menu-C712OV-9.js": "assets/admin-menu-C712OV-9.ecd1f2af4cf4.js", "assets/VCheckbox-CMKdyl0R.css": "assets/VCheckbox-CMKdyl0R.016ed8d222c4.css", "assets/VForm-v1Gmu6E1.css": "assets/VForm-v1Gmu6E1.138c0b89b6fc.css", "assets/main-Dv8e0bMI.js": "assets/main-Dv8e0bMI.bd74f1ba1627.js", "assets/unauthorized-vG1Lh0m_.js": "assets/unauthorized-vG1Lh0m_.0c4bae81ee09.js", "assets/VWindowItem-f8UkxXa_.js": "assets/VWindowItem-f8UkxXa_.1d3e9e78fc9b.js", "assets/VSelect-8MFoaOUz.css": "assets/VSelect-8MFoaOUz.6309f7bf17bb.css", "assets/relation-chips-fOPxWAMU.js": "assets/relation-chips-fOPxWAMU.78e5fe70c014.js", "assets/group-tab-D9gwAdJc.js": "assets/group-tab-D9gwAdJc.60fb0ffa734c.js", "assets/admin-settings-button-progress-Clv9yQ7G.js": "assets/admin-settings-button-progress-Clv9yQ7G.2536580dece1.js", "assets/change-password-dialog-BZPmAOML.js": "assets/change-password-dialog-BZPmAOML.73fdc23e13a4.js", "assets/pdf-doc-CG5-AZ2M.css": "assets/pdf-doc-CG5-AZ2M.b94aac7e3313.css", "assets/VDivider-DE8MJPGz.css": "assets/VDivider-DE8MJPGz.3d2e17799e5c.css", "assets/flag-tab-kcBN36xe.js": "assets/flag-tab-kcBN36xe.631c48ab75fd.js", "robots.txt": "robots.b6216d61c03e.txt", "manifest.json": "manifest.9b3479a6a4a6.json"}, "version": "1.1", "hash": "7391eba5a4e2"}
|
codex/templates/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta charset="utf-8" />
|
|
6
6
|
<meta name="viewport"
|
|
7
7
|
content="width=device-width,initial-scale=1.0,viewport-fit=cover" />
|
|
8
|
-
<title>
|
|
8
|
+
<title>{{ title }}</title>
|
|
9
9
|
{% include "headers-icons.html" %}
|
|
10
10
|
{% include "pwa/headers.html" %}
|
|
11
11
|
{% include "headers-script-globals.html" %}
|
codex/threads.py
CHANGED
|
@@ -5,6 +5,7 @@ from abc import ABC, abstractmethod
|
|
|
5
5
|
from queue import Empty, SimpleQueue
|
|
6
6
|
from threading import Thread
|
|
7
7
|
|
|
8
|
+
from codex.settings.settings import SET_PROC_TITLE
|
|
8
9
|
from codex.worker_base import WorkerBaseMixin
|
|
9
10
|
|
|
10
11
|
|
|
@@ -20,11 +21,15 @@ class NamedThread(Thread, WorkerBaseMixin, ABC):
|
|
|
20
21
|
librarian_queue = kwargs.pop("librarian_queue")
|
|
21
22
|
log_queue = kwargs.pop("log_queue")
|
|
22
23
|
self.init_worker(log_queue, librarian_queue)
|
|
23
|
-
super().__init__(*args, **kwargs)
|
|
24
|
+
super().__init__(*args, name=self.__class__.__name__, **kwargs)
|
|
24
25
|
|
|
25
26
|
def run_start(self):
|
|
26
27
|
"""First thing to do when running a new thread."""
|
|
27
|
-
|
|
28
|
+
if SET_PROC_TITLE:
|
|
29
|
+
from setproctitle import setthreadtitle
|
|
30
|
+
|
|
31
|
+
setthreadtitle("Codex" + self.name)
|
|
32
|
+
self.log.debug(f"Started {self.name}")
|
|
28
33
|
|
|
29
34
|
|
|
30
35
|
class QueuedThread(NamedThread, ABC):
|
|
@@ -36,7 +41,7 @@ class QueuedThread(NamedThread, ABC):
|
|
|
36
41
|
def __init__(self, *args, **kwargs):
|
|
37
42
|
"""Initialize with overridden name and as a daemon thread."""
|
|
38
43
|
self.queue = kwargs.pop("queue", SimpleQueue())
|
|
39
|
-
super().__init__(*args,
|
|
44
|
+
super().__init__(*args, daemon=True, **kwargs)
|
|
40
45
|
|
|
41
46
|
@abstractmethod
|
|
42
47
|
def process_item(self, item):
|
codex/urls/api/admin.py
CHANGED
|
@@ -19,6 +19,7 @@ from codex.views.admin.tasks import (
|
|
|
19
19
|
from codex.views.admin.user import AdminUserChangePasswordView, AdminUserViewSet
|
|
20
20
|
|
|
21
21
|
READ = {"get": "list"}
|
|
22
|
+
RETRIEVE = {"get": "retrieve"}
|
|
22
23
|
CREATE = {"post": "create"}
|
|
23
24
|
UPDATE = {"put": "partial_update"}
|
|
24
25
|
DELETE = {"delete": "destroy"}
|
codex/urls/api/browser.py
CHANGED
|
@@ -4,7 +4,7 @@ from django.urls import path
|
|
|
4
4
|
from django.views.decorators.cache import cache_control, cache_page, never_cache
|
|
5
5
|
|
|
6
6
|
from codex.urls.const import BROWSER_TIMEOUT, COVER_MAX_AGE, PAGE_MAX_AGE
|
|
7
|
-
from codex.views.bookmark import BookmarkView
|
|
7
|
+
from codex.views.browser.bookmark import BookmarkView
|
|
8
8
|
from codex.views.browser.browser import BrowserView
|
|
9
9
|
from codex.views.browser.choices import BrowserChoicesAvailableView, BrowserChoicesView
|
|
10
10
|
from codex.views.browser.cover import CoverView
|
codex/urls/opds/v2.py
CHANGED
|
@@ -6,6 +6,7 @@ from django.views.decorators.cache import cache_page
|
|
|
6
6
|
from codex.urls.const import BROWSER_TIMEOUT
|
|
7
7
|
from codex.views.opds.util import full_redirect_view
|
|
8
8
|
from codex.views.opds.v2.feed import OPDS2FeedView
|
|
9
|
+
from codex.views.opds.v2.progression import OPDS2ProgressionView
|
|
9
10
|
|
|
10
11
|
app_name = "v2"
|
|
11
12
|
|
|
@@ -22,6 +23,11 @@ urlpatterns = [
|
|
|
22
23
|
cache_page(BROWSER_TIMEOUT)(OPDS2FeedView.as_view()),
|
|
23
24
|
name="acq",
|
|
24
25
|
),
|
|
26
|
+
path(
|
|
27
|
+
"<group:group>/<int:pk>/position",
|
|
28
|
+
cache_page(BROWSER_TIMEOUT)(OPDS2ProgressionView.as_view()),
|
|
29
|
+
name="position",
|
|
30
|
+
),
|
|
25
31
|
#
|
|
26
32
|
# Catch All
|
|
27
33
|
path("", full_redirect_view("opds:v2:feed"), name="start"),
|
codex/views/admin/flag.py
CHANGED
|
@@ -13,7 +13,11 @@ LOG = get_logger(__name__)
|
|
|
13
13
|
|
|
14
14
|
_REFRESH_LIBRARY_FLAGS = frozenset(
|
|
15
15
|
flag.value
|
|
16
|
-
for flag in (
|
|
16
|
+
for flag in (
|
|
17
|
+
AdminFlag.FlagChoices.FOLDER_VIEW,
|
|
18
|
+
AdminFlag.FlagChoices.NON_USERS,
|
|
19
|
+
AdminFlag.FlagChoices.BANNER_TEXT,
|
|
20
|
+
)
|
|
17
21
|
)
|
|
18
22
|
|
|
19
23
|
|
codex/views/admin/tasks.py
CHANGED
|
@@ -23,6 +23,7 @@ from codex.librarian.janitor.tasks import (
|
|
|
23
23
|
JanitorCleanupBookmarksTask,
|
|
24
24
|
JanitorCleanupSessionsTask,
|
|
25
25
|
JanitorClearStatusTask,
|
|
26
|
+
JanitorCompressOldLogs,
|
|
26
27
|
JanitorForeignKeyCheck,
|
|
27
28
|
JanitorFTSIntegrityCheck,
|
|
28
29
|
JanitorFTSRebuildTask,
|
|
@@ -95,6 +96,7 @@ _TASK_MAP = MappingProxyType(
|
|
|
95
96
|
"janitor_nightly": JanitorNightlyTask(),
|
|
96
97
|
"force_update_groups": UpdateGroupsTask(start_time=EPOCH_START),
|
|
97
98
|
"adopt_folders": AdoptOrphanFoldersTask(),
|
|
99
|
+
"compress_logs": JanitorCompressOldLogs(),
|
|
98
100
|
}
|
|
99
101
|
)
|
|
100
102
|
|
codex/views/bookmark.py
CHANGED
|
@@ -1,24 +1,52 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Views for reading comic books."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from abc import ABC
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from django.db.models import Q
|
|
4
7
|
from rest_framework.response import Response
|
|
8
|
+
from rest_framework.views import APIView
|
|
5
9
|
|
|
6
|
-
from codex.librarian.bookmark.
|
|
10
|
+
from codex.librarian.bookmark.tasks import BookmarkUpdateTask
|
|
11
|
+
from codex.librarian.mp_queue import LIBRARIAN_QUEUE
|
|
7
12
|
from codex.logger.logging import get_logger
|
|
8
|
-
from codex.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
from codex.views.auth import (
|
|
13
|
-
AuthFilterAPIView,
|
|
14
|
-
AuthFilterGenericAPIView,
|
|
15
|
-
)
|
|
16
|
-
from codex.views.const import FILTER_ONLY_GROUP_RELATION
|
|
13
|
+
from codex.views.auth import AuthAPIView
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from codex.models import BrowserGroupModel
|
|
17
17
|
|
|
18
18
|
LOG = get_logger(__name__)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
class
|
|
21
|
+
class BookmarkFilterMixin(APIView, ABC):
|
|
22
|
+
"""Bookmark filter methods."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, *args, **kwargs):
|
|
25
|
+
"""Initialize the bm_annotation_data."""
|
|
26
|
+
super().__init__(*args, **kwargs)
|
|
27
|
+
self._bm_rels: dict[BrowserGroupModel, str] = {}
|
|
28
|
+
self._bm_filters: dict[BrowserGroupModel, Q] = {}
|
|
29
|
+
|
|
30
|
+
def get_bm_rel(self, model):
|
|
31
|
+
"""Create bookmark relation."""
|
|
32
|
+
if model not in self._bm_rels:
|
|
33
|
+
rel_prefix = self.get_rel_prefix(model) # type: ignore
|
|
34
|
+
self._bm_rels[model] = rel_prefix + "bookmark"
|
|
35
|
+
return self._bm_rels[model]
|
|
36
|
+
|
|
37
|
+
def get_my_bookmark_filter(self, bm_rel):
|
|
38
|
+
"""Get a filter for my session or user defined bookmarks."""
|
|
39
|
+
if self.request.user and self.request.user.is_authenticated:
|
|
40
|
+
key = f"{bm_rel}__user"
|
|
41
|
+
value = self.request.user
|
|
42
|
+
else:
|
|
43
|
+
key = f"{bm_rel}__session__session_key"
|
|
44
|
+
value = self.request.session.session_key
|
|
45
|
+
my_bookmarks_kwargs = {key: value}
|
|
46
|
+
return Q(**my_bookmarks_kwargs)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class BookmarkAuthMixin(APIView):
|
|
22
50
|
"""Base class for Bookmark Views."""
|
|
23
51
|
|
|
24
52
|
def get_bookmark_auth_filter(self):
|
|
@@ -35,36 +63,20 @@ class BookmarkBaseView(AuthFilterAPIView):
|
|
|
35
63
|
return {key: value}
|
|
36
64
|
|
|
37
65
|
|
|
38
|
-
class
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
serializer_class = BookmarkSerializer
|
|
42
|
-
|
|
43
|
-
def _parse_params(self):
|
|
44
|
-
"""Validate and translate the submitted data."""
|
|
45
|
-
group = self.kwargs.get("group")
|
|
46
|
-
# If the target is recursive, strip everything but finished state data.
|
|
47
|
-
serializer_class = None if group == "c" else BookmarkFinishedSerializer
|
|
48
|
-
|
|
49
|
-
data = self.request.data # type: ignore
|
|
50
|
-
if serializer_class:
|
|
51
|
-
serializer = serializer_class(data=data, partial=True)
|
|
52
|
-
else:
|
|
53
|
-
serializer = self.get_serializer(data=data, partial=True)
|
|
54
|
-
serializer.is_valid(raise_exception=True)
|
|
55
|
-
return serializer.validated_data
|
|
56
|
-
|
|
57
|
-
@extend_schema(request=serializer_class, responses=None)
|
|
58
|
-
def patch(self, *_args, **_kwargs):
|
|
59
|
-
"""Update bookmarks recursively."""
|
|
60
|
-
updates = self._parse_params()
|
|
66
|
+
class BookmarkPageView(BookmarkAuthMixin, AuthAPIView):
|
|
67
|
+
"""Display a comic page from the archive itself."""
|
|
61
68
|
|
|
69
|
+
def _update_bookmark(self):
|
|
70
|
+
"""Update the bookmark if the bookmark param was passed."""
|
|
62
71
|
auth_filter = self.get_bookmark_auth_filter()
|
|
72
|
+
comic_pks = (self.kwargs.get("pk"),)
|
|
73
|
+
page = self.kwargs.get("page")
|
|
74
|
+
updates = {"page": page}
|
|
63
75
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
pks = self.kwargs.get("pks")
|
|
67
|
-
comic_filter = {rel: pks}
|
|
76
|
+
task = BookmarkUpdateTask(auth_filter, comic_pks, updates)
|
|
77
|
+
LIBRARIAN_QUEUE.put(task)
|
|
68
78
|
|
|
69
|
-
|
|
79
|
+
def put(self, *_args, **_kwargs):
|
|
80
|
+
"""Get the comic page from the archive."""
|
|
81
|
+
self._update_bookmark()
|
|
70
82
|
return Response()
|
|
@@ -9,7 +9,7 @@ from django.db.models import (
|
|
|
9
9
|
)
|
|
10
10
|
from django.db.models.fields import BooleanField, PositiveSmallIntegerField
|
|
11
11
|
from django.db.models.functions import Least
|
|
12
|
-
from django.db.models.functions.comparison import Coalesce
|
|
12
|
+
from django.db.models.functions.comparison import Coalesce, Greatest
|
|
13
13
|
|
|
14
14
|
from codex.logger.logging import get_logger
|
|
15
15
|
from codex.models import (
|
|
@@ -69,8 +69,8 @@ class BrowserAnnotateBookmarkView(BrowserAnnotateOrderView):
|
|
|
69
69
|
|
|
70
70
|
def annotate_bookmarks(self, qs):
|
|
71
71
|
"""Hoist up bookmark annotations."""
|
|
72
|
-
bm_rel = self.
|
|
73
|
-
bm_filter = self.
|
|
72
|
+
bm_rel = self.get_bm_rel(qs.model)
|
|
73
|
+
bm_filter = self.get_my_bookmark_filter(bm_rel)
|
|
74
74
|
page_rel = f"{bm_rel}__page"
|
|
75
75
|
finished_rel = f"{bm_rel}__finished"
|
|
76
76
|
|
|
@@ -108,5 +108,7 @@ class BrowserAnnotateBookmarkView(BrowserAnnotateOrderView):
|
|
|
108
108
|
# Page counts can be null with metadata turned off.
|
|
109
109
|
# Least guard is for rare instances when bookmarks are set to
|
|
110
110
|
# invalid high values
|
|
111
|
-
progress = Least(
|
|
111
|
+
progress = Least(
|
|
112
|
+
Coalesce(F("page"), 0) * 100.0 / Greatest("page_count", 1), Value(100.0)
|
|
113
|
+
)
|
|
112
114
|
return qs.annotate(progress=progress)
|
|
@@ -6,7 +6,6 @@ from django.db.models import (
|
|
|
6
6
|
F,
|
|
7
7
|
Value,
|
|
8
8
|
)
|
|
9
|
-
from django.db.models.aggregates import Count
|
|
10
9
|
from django.db.models.fields import CharField
|
|
11
10
|
|
|
12
11
|
from codex.logger.logging import get_logger
|
|
@@ -30,20 +29,6 @@ class BrowserAnnotateCardView(BrowserAnnotateBookmarkView):
|
|
|
30
29
|
qs = qs.group_by(group_by)
|
|
31
30
|
return qs
|
|
32
31
|
|
|
33
|
-
def _annotate_child_count(self, qs):
|
|
34
|
-
"""Annotate child chount for card."""
|
|
35
|
-
if qs.model is Comic:
|
|
36
|
-
return qs
|
|
37
|
-
rel = self.rel_prefix + "pk"
|
|
38
|
-
count_func = Count(rel, distinct=True)
|
|
39
|
-
ann = {"child_count": count_func}
|
|
40
|
-
if self.TARGET == "opds2":
|
|
41
|
-
if qs.model is not Comic:
|
|
42
|
-
qs = qs.alias(**ann)
|
|
43
|
-
else:
|
|
44
|
-
qs = qs.annotate(**ann)
|
|
45
|
-
return qs
|
|
46
|
-
|
|
47
32
|
def _annotate_group(self, qs):
|
|
48
33
|
"""Annotate Group."""
|
|
49
34
|
value = "c" if qs.model is Comic else self.model_group # type: ignore
|
|
@@ -67,7 +52,7 @@ class BrowserAnnotateCardView(BrowserAnnotateBookmarkView):
|
|
|
67
52
|
qs = self._annotate_group(qs)
|
|
68
53
|
qs = self.annotate_group_names(qs)
|
|
69
54
|
qs = self._annotate_file_name(qs)
|
|
70
|
-
qs = self.
|
|
55
|
+
qs = self.annotate_child_count(qs)
|
|
71
56
|
qs = self.annotate_bookmarks(qs)
|
|
72
57
|
qs = self.annotate_progress(qs)
|
|
73
58
|
return qs.annotate(updated_ats=JsonGroupArray("updated_at", distinct=True))
|
|
@@ -9,7 +9,7 @@ from django.db.models import (
|
|
|
9
9
|
Q,
|
|
10
10
|
Value,
|
|
11
11
|
)
|
|
12
|
-
from django.db.models.aggregates import Avg, Max, Min, Sum
|
|
12
|
+
from django.db.models.aggregates import Avg, Count, Max, Min, Sum
|
|
13
13
|
from django.db.models.fields import CharField
|
|
14
14
|
from django.db.models.functions import Reverse, Right, StrIndex
|
|
15
15
|
|
|
@@ -33,6 +33,7 @@ _ORDER_AGGREGATE_FUNCS = MappingProxyType(
|
|
|
33
33
|
# These are annotated to order_value because they're simple relations
|
|
34
34
|
{
|
|
35
35
|
"age_rating": Avg,
|
|
36
|
+
"child_count": Min,
|
|
36
37
|
"community_rating": Avg,
|
|
37
38
|
"created_at": Min,
|
|
38
39
|
"critical_rating": Avg,
|
|
@@ -45,10 +46,11 @@ _ORDER_AGGREGATE_FUNCS = MappingProxyType(
|
|
|
45
46
|
_ANNOTATED_ORDER_FIELDS = frozenset(
|
|
46
47
|
# These are annotated with their own functions
|
|
47
48
|
{
|
|
49
|
+
"bookmark_updated_at",
|
|
50
|
+
"child_count",
|
|
48
51
|
"filename",
|
|
49
|
-
"sort_name",
|
|
50
52
|
"search_score",
|
|
51
|
-
"
|
|
53
|
+
"sort_name",
|
|
52
54
|
"story_arc_number",
|
|
53
55
|
}
|
|
54
56
|
)
|
|
@@ -71,6 +73,7 @@ class BrowserAnnotateOrderView(BrowserOrderByView, SharedAnnotationsMixin):
|
|
|
71
73
|
self._is_opds_acquisition: bool | None = None
|
|
72
74
|
self._opds_acquisition_groups: frozenset[str] | None = None
|
|
73
75
|
self.bmua_is_max = False
|
|
76
|
+
self._child_count_annotated = False
|
|
74
77
|
|
|
75
78
|
@property
|
|
76
79
|
def opds_acquisition_groups(self):
|
|
@@ -109,13 +112,14 @@ class BrowserAnnotateOrderView(BrowserOrderByView, SharedAnnotationsMixin):
|
|
|
109
112
|
qs.model is StoryArc and self.order_key == "story_arc_number"
|
|
110
113
|
):
|
|
111
114
|
return qs
|
|
115
|
+
group = self.kwargs.get("group")
|
|
112
116
|
pks = self.kwargs.get("pks")
|
|
113
|
-
show = MappingProxyType(self.params["show"])
|
|
117
|
+
show = MappingProxyType(self.params["show"])
|
|
114
118
|
# TODO too many annotations for order?
|
|
115
119
|
# Move other annotations to card.
|
|
116
120
|
# eager publisher for imprint of course
|
|
117
121
|
sort_name_annotations = self.get_sort_name_annotations(
|
|
118
|
-
qs.model,
|
|
122
|
+
qs.model, group, pks, show
|
|
119
123
|
)
|
|
120
124
|
if sort_name_annotations:
|
|
121
125
|
qs = qs.alias(**sort_name_annotations)
|
|
@@ -202,6 +206,35 @@ class BrowserAnnotateOrderView(BrowserOrderByView, SharedAnnotationsMixin):
|
|
|
202
206
|
# This is used by the serializer to compute mtime
|
|
203
207
|
return qs.annotate(bmua_is_max=Value(self.bmua_is_max))
|
|
204
208
|
|
|
209
|
+
def _annotate_search_scores(self, qs):
|
|
210
|
+
"""Annotate Search Scores."""
|
|
211
|
+
if (
|
|
212
|
+
self.TARGET not in self._COVER_AND_CARD_TARGETS
|
|
213
|
+
or self.order_key != "search_score"
|
|
214
|
+
):
|
|
215
|
+
return qs
|
|
216
|
+
|
|
217
|
+
# Rank is always the max of the relations, cannot aggregate?
|
|
218
|
+
# group by here fixes duplicates with story_arc, probably because it's a long relation
|
|
219
|
+
return qs.annotate(search_score=ComicFTSRank()).group_by("id")
|
|
220
|
+
|
|
221
|
+
def annotate_child_count(self, qs):
|
|
222
|
+
"""Annotate child count."""
|
|
223
|
+
if qs.model is Comic or self._child_count_annotated:
|
|
224
|
+
return qs
|
|
225
|
+
rel = self.rel_prefix + "pk"
|
|
226
|
+
count_func = Count(rel, distinct=True)
|
|
227
|
+
ann = {"child_count": count_func}
|
|
228
|
+
qs = qs.alias(**ann) if self.TARGET == "opds2" else qs.annotate(**ann)
|
|
229
|
+
self._child_count_annotated = True
|
|
230
|
+
return qs
|
|
231
|
+
|
|
232
|
+
def _annotate_order_child_count(self, qs):
|
|
233
|
+
"""Annotate child count for order."""
|
|
234
|
+
if self.order_key != "child_count":
|
|
235
|
+
return qs
|
|
236
|
+
return self.annotate_child_count(qs)
|
|
237
|
+
|
|
205
238
|
def annotate_order_value(self, qs):
|
|
206
239
|
"""Annotate a main key for sorting and browser card display."""
|
|
207
240
|
# Determine order func
|
|
@@ -209,7 +242,12 @@ class BrowserAnnotateOrderView(BrowserOrderByView, SharedAnnotationsMixin):
|
|
|
209
242
|
return qs
|
|
210
243
|
if qs.model is Folder and self.order_key == "filename":
|
|
211
244
|
order_value = F("name")
|
|
212
|
-
elif qs.model is Comic
|
|
245
|
+
elif qs.model is Comic:
|
|
246
|
+
order_key = (
|
|
247
|
+
"sort_name" if self.order_key == "child_count" else self.order_key
|
|
248
|
+
)
|
|
249
|
+
order_value = F(order_key)
|
|
250
|
+
elif self.order_key in _ANNOTATED_ORDER_FIELDS:
|
|
213
251
|
# These are annotated in browser_annotaions
|
|
214
252
|
order_value = F(self.order_key)
|
|
215
253
|
else:
|
|
@@ -224,18 +262,6 @@ class BrowserAnnotateOrderView(BrowserOrderByView, SharedAnnotationsMixin):
|
|
|
224
262
|
qs = qs.alias(order_value=order_value)
|
|
225
263
|
return qs
|
|
226
264
|
|
|
227
|
-
def _annotate_search_scores(self, qs):
|
|
228
|
-
"""Annotate Search Scores."""
|
|
229
|
-
if (
|
|
230
|
-
self.TARGET not in self._COVER_AND_CARD_TARGETS
|
|
231
|
-
or self.order_key != "search_score"
|
|
232
|
-
):
|
|
233
|
-
return qs
|
|
234
|
-
|
|
235
|
-
# Rank is always the max of the relations, cannot aggregate?
|
|
236
|
-
# group by here fixes duplicates with story_arc, probably because it's a long relation
|
|
237
|
-
return qs.annotate(search_score=ComicFTSRank()).group_by("id")
|
|
238
|
-
|
|
239
265
|
def annotate_order_aggregates(self, qs):
|
|
240
266
|
"""Annotate common aggregates between browser and metadata."""
|
|
241
267
|
qs = qs.annotate(ids=JsonGroupArray("id", distinct=True))
|
|
@@ -245,6 +271,7 @@ class BrowserAnnotateOrderView(BrowserOrderByView, SharedAnnotationsMixin):
|
|
|
245
271
|
qs = self._alias_story_arc_number(qs)
|
|
246
272
|
qs = self._annotate_page_count(qs)
|
|
247
273
|
qs = self._annotate_bookmark_updated_at(qs)
|
|
274
|
+
qs = self._annotate_order_child_count(qs)
|
|
248
275
|
if qs.model is not Comic:
|
|
249
276
|
# comic orders on indexed fields when it can
|
|
250
277
|
qs = self.annotate_order_value(qs)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Bookmark view."""
|
|
2
|
+
|
|
3
|
+
from drf_spectacular.utils import extend_schema
|
|
4
|
+
from rest_framework.response import Response
|
|
5
|
+
|
|
6
|
+
from codex.librarian.bookmark.update import BookmarkUpdate
|
|
7
|
+
from codex.logger.logging import get_logger
|
|
8
|
+
from codex.models.comic import Comic
|
|
9
|
+
from codex.serializers.models.bookmark import (
|
|
10
|
+
BookmarkFinishedSerializer,
|
|
11
|
+
BookmarkSerializer,
|
|
12
|
+
)
|
|
13
|
+
from codex.views.bookmark import BookmarkAuthMixin
|
|
14
|
+
from codex.views.browser.filters.filter import BrowserFilterView
|
|
15
|
+
|
|
16
|
+
LOG = get_logger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BookmarkView(BookmarkUpdate, BookmarkAuthMixin, BrowserFilterView):
|
|
20
|
+
"""User Bookmark View."""
|
|
21
|
+
|
|
22
|
+
serializer_class = BookmarkSerializer
|
|
23
|
+
|
|
24
|
+
def _parse_params(self):
|
|
25
|
+
"""Validate and translate the submitted data."""
|
|
26
|
+
group = self.kwargs.get("group")
|
|
27
|
+
# If the target is recursive, strip everything but finished state data.
|
|
28
|
+
serializer_class = None if group == "c" else BookmarkFinishedSerializer
|
|
29
|
+
|
|
30
|
+
data = self.request.data # type: ignore
|
|
31
|
+
if serializer_class:
|
|
32
|
+
serializer = serializer_class(data=data, partial=True)
|
|
33
|
+
else:
|
|
34
|
+
serializer = self.get_serializer(data=data, partial=True)
|
|
35
|
+
serializer.is_valid(raise_exception=True)
|
|
36
|
+
return serializer.validated_data
|
|
37
|
+
|
|
38
|
+
def _get_comic_query(self):
|
|
39
|
+
"""Get comic pks for group."""
|
|
40
|
+
group = self.kwargs.get("group")
|
|
41
|
+
pks = self.kwargs.get("pks")
|
|
42
|
+
return self.get_filtered_queryset(Comic, group=group, pks=pks).only("pk")
|
|
43
|
+
|
|
44
|
+
@extend_schema(request=serializer_class, responses=None)
|
|
45
|
+
def patch(self, *_args, **_kwargs):
|
|
46
|
+
"""Update bookmarks recursively."""
|
|
47
|
+
updates = self._parse_params()
|
|
48
|
+
|
|
49
|
+
auth_filter = self.get_bookmark_auth_filter()
|
|
50
|
+
comic_qs = self._get_comic_query()
|
|
51
|
+
|
|
52
|
+
self.update_bookmarks(auth_filter, comic_qs, updates, LOG)
|
|
53
|
+
return Response()
|
codex/views/browser/download.py
CHANGED
|
@@ -56,9 +56,11 @@ class GroupDownloadView(BrowserFilterView):
|
|
|
56
56
|
pks = self.kwargs.get("pks")
|
|
57
57
|
filename = f"{self.model.__name__} {pks} Comics.zip" # type: ignore
|
|
58
58
|
|
|
59
|
+
headers = {"Content-Length": len(zs), "Last-Modified": zs.last_modified}
|
|
59
60
|
return FileResponse(
|
|
60
61
|
download_file,
|
|
61
62
|
as_attachment=self.AS_ATTACHMENT,
|
|
62
63
|
content_type=self.content_type,
|
|
63
64
|
filename=filename,
|
|
65
|
+
headers=headers,
|
|
64
66
|
)
|
|
@@ -1,48 +1,20 @@
|
|
|
1
1
|
"""Bookmark filter view methods."""
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
|
|
5
3
|
from django.db.models import Q
|
|
6
4
|
|
|
5
|
+
from codex.views.bookmark import BookmarkFilterMixin
|
|
7
6
|
from codex.views.browser.validate import BrowserValidateView
|
|
8
7
|
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from codex.models import BrowserGroupModel
|
|
11
|
-
|
|
12
8
|
|
|
13
|
-
class BrowserFilterBookmarkView(BrowserValidateView):
|
|
9
|
+
class BrowserFilterBookmarkView(BookmarkFilterMixin, BrowserValidateView):
|
|
14
10
|
"""BookmarkFilter view methods."""
|
|
15
11
|
|
|
16
|
-
def __init__(self, *args, **kwargs):
|
|
17
|
-
"""Initialize the bm_annotation_data."""
|
|
18
|
-
super().__init__(*args, **kwargs)
|
|
19
|
-
self._bm_rels: dict[BrowserGroupModel, str] = {}
|
|
20
|
-
self._bm_filters: dict[BrowserGroupModel, Q] = {}
|
|
21
|
-
|
|
22
|
-
def _get_bm_rel(self, model):
|
|
23
|
-
"""Create bookmark relation."""
|
|
24
|
-
if model not in self._bm_rels:
|
|
25
|
-
rel_prefix = self.get_rel_prefix(model) # type: ignore
|
|
26
|
-
self._bm_rels[model] = rel_prefix + "bookmark"
|
|
27
|
-
return self._bm_rels[model]
|
|
28
|
-
|
|
29
|
-
def _get_my_bookmark_filter(self, bm_rel):
|
|
30
|
-
"""Get a filter for my session or user defined bookmarks."""
|
|
31
|
-
if self.request.user and self.request.user.is_authenticated:
|
|
32
|
-
key = f"{bm_rel}__user"
|
|
33
|
-
value = self.request.user
|
|
34
|
-
else:
|
|
35
|
-
key = f"{bm_rel}__session__session_key"
|
|
36
|
-
value = self.request.session.session_key
|
|
37
|
-
my_bookmarks_kwargs = {key: value}
|
|
38
|
-
return Q(**my_bookmarks_kwargs)
|
|
39
|
-
|
|
40
12
|
def get_bookmark_filter(self, model):
|
|
41
13
|
"""Build bookmark query."""
|
|
42
14
|
choice: str = self.params.get("filters", {}).get("bookmark", "") # type: ignore
|
|
43
15
|
if choice:
|
|
44
|
-
bm_rel = self.
|
|
45
|
-
my_bookmark_filter = self.
|
|
16
|
+
bm_rel = self.get_bm_rel(model)
|
|
17
|
+
my_bookmark_filter = self.get_my_bookmark_filter(bm_rel)
|
|
46
18
|
if choice == "READ":
|
|
47
19
|
bookmark_filter = my_bookmark_filter & Q(
|
|
48
20
|
**{f"{bm_rel}__finished": True}
|
|
@@ -46,8 +46,8 @@ class BrowserGroupMtimeView(BrowserFilterView):
|
|
|
46
46
|
self, model, agg_func: type[Aggregate] = Max, default=NONE_DATETIMEFIELD
|
|
47
47
|
):
|
|
48
48
|
"""Get filtered maximum bookmark updated_at relation."""
|
|
49
|
-
bm_rel = self.
|
|
50
|
-
bm_filter = self.
|
|
49
|
+
bm_rel = self.get_bm_rel(model)
|
|
50
|
+
bm_filter = self.get_my_bookmark_filter(bm_rel)
|
|
51
51
|
bmua_rel = f"{bm_rel}__updated_at"
|
|
52
52
|
args = {"default": default, "filter": bm_filter}
|
|
53
53
|
if agg_func is JsonGroupArray:
|
|
@@ -86,7 +86,7 @@ class MetadataAnnotateView(BrowserAnnotateCardView):
|
|
|
86
86
|
|
|
87
87
|
return filtered_qs, qs
|
|
88
88
|
|
|
89
|
-
def
|
|
89
|
+
def annotate_values_and_fks(self, qs, filtered_qs):
|
|
90
90
|
"""Annotate comic values and comic foreign key values."""
|
|
91
91
|
# Simple Values
|
|
92
92
|
querysets = (filtered_qs, qs)
|
|
@@ -54,7 +54,7 @@ class MetadataView(MetadataCopyIntersectionsView):
|
|
|
54
54
|
# Annotate
|
|
55
55
|
qs = self.annotate_order_aggregates(qs)
|
|
56
56
|
qs = self.annotate_card_aggregates(qs)
|
|
57
|
-
qs = self.
|
|
57
|
+
qs = self.annotate_values_and_fks(qs, filtered_qs)
|
|
58
58
|
qs = self.add_group_by(qs)
|
|
59
59
|
qs = self.force_inner_joins(qs)
|
|
60
60
|
|