libreqda 1.2.0.post1__tar.gz → 1.2.1__tar.gz

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.
Files changed (274) hide show
  1. {libreqda-1.2.0.post1 → libreqda-1.2.1}/CHANGELOG.md +11 -0
  2. {libreqda-1.2.0.post1 → libreqda-1.2.1}/PKG-INFO +27 -14
  3. {libreqda-1.2.0.post1 → libreqda-1.2.1}/README.md +26 -13
  4. {libreqda-1.2.0.post1 → libreqda-1.2.1}/pyproject.toml +1 -1
  5. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/__init__.py +1 -1
  6. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/database/copy.py +4 -1
  7. libreqda-1.2.1/taguette/l10n/de_DE/LC_MESSAGES/taguette_javascript.mo +0 -0
  8. libreqda-1.2.1/taguette/l10n/de_DE/LC_MESSAGES/taguette_main.mo +0 -0
  9. libreqda-1.2.1/taguette/l10n/el_GR/LC_MESSAGES/taguette_javascript.mo +0 -0
  10. libreqda-1.2.1/taguette/l10n/el_GR/LC_MESSAGES/taguette_main.mo +0 -0
  11. libreqda-1.2.1/taguette/l10n/en_US/LC_MESSAGES/taguette_javascript.mo +0 -0
  12. libreqda-1.2.1/taguette/l10n/en_US/LC_MESSAGES/taguette_main.mo +0 -0
  13. libreqda-1.2.1/taguette/l10n/es_ES/LC_MESSAGES/taguette_javascript.mo +0 -0
  14. libreqda-1.2.1/taguette/l10n/es_ES/LC_MESSAGES/taguette_main.mo +0 -0
  15. libreqda-1.2.1/taguette/l10n/fr_FR/LC_MESSAGES/taguette_javascript.mo +0 -0
  16. libreqda-1.2.1/taguette/l10n/fr_FR/LC_MESSAGES/taguette_main.mo +0 -0
  17. libreqda-1.2.1/taguette/l10n/id_ID/LC_MESSAGES/taguette_javascript.mo +0 -0
  18. libreqda-1.2.1/taguette/l10n/id_ID/LC_MESSAGES/taguette_main.mo +0 -0
  19. libreqda-1.2.1/taguette/l10n/it_IT/LC_MESSAGES/taguette_javascript.mo +0 -0
  20. libreqda-1.2.1/taguette/l10n/it_IT/LC_MESSAGES/taguette_main.mo +0 -0
  21. libreqda-1.2.1/taguette/l10n/nl_NL/LC_MESSAGES/taguette_javascript.mo +0 -0
  22. libreqda-1.2.1/taguette/l10n/nl_NL/LC_MESSAGES/taguette_main.mo +0 -0
  23. libreqda-1.2.1/taguette/l10n/pt_PT/LC_MESSAGES/taguette_javascript.mo +0 -0
  24. libreqda-1.2.1/taguette/l10n/pt_PT/LC_MESSAGES/taguette_main.mo +0 -0
  25. libreqda-1.2.1/taguette/l10n/sv_SE/LC_MESSAGES/taguette_javascript.mo +0 -0
  26. libreqda-1.2.1/taguette/l10n/sv_SE/LC_MESSAGES/taguette_main.mo +0 -0
  27. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/base.html +1 -1
  28. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/project_import.html +12 -0
  29. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/version_check.py +1 -4
  30. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/web/api.py +16 -3
  31. libreqda-1.2.0.post1/taguette/l10n/de_DE/LC_MESSAGES/taguette_javascript.mo +0 -0
  32. libreqda-1.2.0.post1/taguette/l10n/de_DE/LC_MESSAGES/taguette_main.mo +0 -0
  33. libreqda-1.2.0.post1/taguette/l10n/el_GR/LC_MESSAGES/taguette_javascript.mo +0 -0
  34. libreqda-1.2.0.post1/taguette/l10n/el_GR/LC_MESSAGES/taguette_main.mo +0 -0
  35. libreqda-1.2.0.post1/taguette/l10n/en_US/LC_MESSAGES/taguette_javascript.mo +0 -0
  36. libreqda-1.2.0.post1/taguette/l10n/en_US/LC_MESSAGES/taguette_main.mo +0 -0
  37. libreqda-1.2.0.post1/taguette/l10n/es_ES/LC_MESSAGES/taguette_javascript.mo +0 -0
  38. libreqda-1.2.0.post1/taguette/l10n/es_ES/LC_MESSAGES/taguette_main.mo +0 -0
  39. libreqda-1.2.0.post1/taguette/l10n/fr_FR/LC_MESSAGES/taguette_javascript.mo +0 -0
  40. libreqda-1.2.0.post1/taguette/l10n/fr_FR/LC_MESSAGES/taguette_main.mo +0 -0
  41. libreqda-1.2.0.post1/taguette/l10n/id_ID/LC_MESSAGES/taguette_javascript.mo +0 -0
  42. libreqda-1.2.0.post1/taguette/l10n/id_ID/LC_MESSAGES/taguette_main.mo +0 -0
  43. libreqda-1.2.0.post1/taguette/l10n/it_IT/LC_MESSAGES/taguette_javascript.mo +0 -0
  44. libreqda-1.2.0.post1/taguette/l10n/it_IT/LC_MESSAGES/taguette_main.mo +0 -0
  45. libreqda-1.2.0.post1/taguette/l10n/nl_NL/LC_MESSAGES/taguette_javascript.mo +0 -0
  46. libreqda-1.2.0.post1/taguette/l10n/nl_NL/LC_MESSAGES/taguette_main.mo +0 -0
  47. libreqda-1.2.0.post1/taguette/l10n/pt_PT/LC_MESSAGES/taguette_javascript.mo +0 -0
  48. libreqda-1.2.0.post1/taguette/l10n/pt_PT/LC_MESSAGES/taguette_main.mo +0 -0
  49. libreqda-1.2.0.post1/taguette/l10n/sv_SE/LC_MESSAGES/taguette_javascript.mo +0 -0
  50. libreqda-1.2.0.post1/taguette/l10n/sv_SE/LC_MESSAGES/taguette_main.mo +0 -0
  51. {libreqda-1.2.0.post1 → libreqda-1.2.1}/LICENSE.txt +0 -0
  52. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/babelrc +0 -0
  53. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/LICENSE.txt +0 -0
  54. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/RELEASE.txt +0 -0
  55. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/macos/libreqda.icns +0 -0
  56. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/macos/macos.spec +0 -0
  57. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/macos/plist.patch +0 -0
  58. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/macos/taguette.icns +0 -0
  59. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/macos/taguette_console_wrapper +0 -0
  60. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/macos.sh +0 -0
  61. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/pyinstaller_entrypoint.py +0 -0
  62. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/windows/windows-installer.iss +0 -0
  63. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/dist/windows/windows.spec +0 -0
  64. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/edugain/worker_update_edugain_idps.py +0 -0
  65. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/edugain/worker_update_edugain_idps.sh +0 -0
  66. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/make_password_reset_link.py +0 -0
  67. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/make_theme.py +0 -0
  68. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/new_db_revision.sh +0 -0
  69. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/register_user.py +0 -0
  70. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/update_pot.sh +0 -0
  71. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/update_translations.sh +0 -0
  72. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/validate.py +0 -0
  73. {libreqda-1.2.0.post1 → libreqda-1.2.1}/scripts/wipe_and_disable_user.py +0 -0
  74. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/access_control.py +0 -0
  75. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/convert.py +0 -0
  76. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/database/__init__.py +0 -0
  77. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/database/base.py +0 -0
  78. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/database/models.py +0 -0
  79. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/demodata.py +0 -0
  80. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/export.py +0 -0
  81. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/extract.py +0 -0
  82. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/import_codebook.py +0 -0
  83. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/l10n/el_EL/LC_MESSAGES/taguette_javascript.mo +0 -0
  84. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/loki_handler.py +0 -0
  85. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/main.py +0 -0
  86. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/env.py +0 -0
  87. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/script.py.mako +0 -0
  88. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/09c662cd9483_make_documents_filename_not_null.py +0 -0
  89. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/1b29e68900c1_add_user_roles.py +0 -0
  90. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/1b96a606551d_update_user_to_have_a_display_name.py +0 -0
  91. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/2467bab602b7_add_color_column_to_tags_table.py +0 -0
  92. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/382db36f20f4_add_user_disabled.py +0 -0
  93. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/43d6c240309d_remove_document_groups.py +0 -0
  94. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/447d636f72c5_cascades.py +0 -0
  95. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/491de2dc7cd7_add_indexes.py +0 -0
  96. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/4c55b3b3ff30_user_login_length.py +0 -0
  97. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/61a4abcc8769_user_with_parent_for_permissions.py +0 -0
  98. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/6489b5f9cfb5_increase_password_hash_size.py +0 -0
  99. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/679f625e6e6a_fix_unique_tags.py +0 -0
  100. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/77c4543a5b9b_add_parent_id_column_to_collection_table.py +0 -0
  101. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/7c94b7a31e69_add_is_archived_column_to_projets.py +0 -0
  102. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/7f56de97e3c8_change_edugain_displayname_length.py +0 -0
  103. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/807c0cc0ecf6_remove_invalid_hltags.py +0 -0
  104. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/80b1cc9d4c22_add_user_email.py +0 -0
  105. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/91ade71ccf4d_add_user_language.py +0 -0
  106. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/955db2e523d1_add_collections_tables_and_associations_.py +0 -0
  107. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/a1b2c3d4e5f6_add_user_hide_code_counts.py +0 -0
  108. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/b23f3b7a638e_add_user_password_change_date.py +0 -0
  109. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/b7c1e2d3f4a5_add_project_compact_layout.py +0 -0
  110. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/bc8e0e0677e9_rename_command_fields.py +0 -0
  111. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/bce44849c2f2_lowercase_logins.py +0 -0
  112. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/ca076140922f_update_user_for_external_logins.py +0 -0
  113. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/d86c45d7aa8a_add_document_direction.py +0 -0
  114. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/db5e31a0233d_remove_blank_highlights.py +0 -0
  115. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/dd37d9027a24_unique_tags.py +0 -0
  116. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/de678cef2a94_add_project_id_to_collections_and_.py +0 -0
  117. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/e459991d960e_add_table_edugainidps.py +0 -0
  118. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/e4cf92942271_add_index.py +0 -0
  119. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/e4e090a5b511_remove_commands_document_id_fk.py +0 -0
  120. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/e9a9f1c77971_add_favorite_column_to_document.py +0 -0
  121. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/ecb4065de575_don_t_use_server_default_now_timezone_.py +0 -0
  122. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/fbdc29566f62_edugain_fix_field_type.py +0 -0
  123. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/migrations/versions/fdc6eb54b034_add_parent_id_column_to_tags_table.py +0 -0
  124. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/README.md +0 -0
  125. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/alt_templates/.gitkeep +0 -0
  126. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/assets/test/logos/monsters-university-logo.png +0 -0
  127. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/custom.css +0 -0
  128. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/fa-all.min.css +0 -0
  129. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/themed.css +0 -0
  130. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/themed.css.map +0 -0
  131. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/vendor/bootstrap-treeview.min.css +0 -0
  132. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/vendor/bootstrap.min.css +0 -0
  133. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/vendor/font/context-menu-icons.eot +0 -0
  134. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/vendor/font/context-menu-icons.ttf +0 -0
  135. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/vendor/font/context-menu-icons.woff +0 -0
  136. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/vendor/font/context-menu-icons.woff2 +0 -0
  137. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/vendor/hierarchy-select.min.css +0 -0
  138. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/vendor/introjs.min.css +0 -0
  139. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/css/vendor/jquery.contextMenu.min.css +0 -0
  140. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/favicon.ico +0 -0
  141. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/codebook-viz.js +0 -0
  142. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/collection/context-menu.js +0 -0
  143. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/collection/hierarchy-select.js +0 -0
  144. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/collection/manager.js +0 -0
  145. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/document/context-menu.js +0 -0
  146. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/document/custom-select.js +0 -0
  147. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/document/manager.js +0 -0
  148. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/document/treeview.js +0 -0
  149. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/highlight/README.md +0 -0
  150. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/highlight/crud.js +0 -0
  151. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/highlight/extracts.js +0 -0
  152. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/highlight/loader.js +0 -0
  153. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/highlight/renderer.js +0 -0
  154. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/login.js +0 -0
  155. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/permissions.js +0 -0
  156. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/polling-event.js +0 -0
  157. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/project/intro.js +0 -0
  158. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/project/manager.js +0 -0
  159. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/project/search.js +0 -0
  160. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/tag/context-menu.js +0 -0
  161. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/tag/explore-codes.js +0 -0
  162. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/tag/hierarchy-select.js +0 -0
  163. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/tag/manager.js +0 -0
  164. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/tag/treeview.js +0 -0
  165. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/taguette.js +0 -0
  166. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/utilities.js +0 -0
  167. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/vendor/bootstrap-treeview-custum.js +0 -0
  168. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/vendor/bootstrap-treeview-custum.min.js +0 -0
  169. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/vendor/bootstrap-treeview-default.min.js +0 -0
  170. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/vendor/bootstrap.bundle.min.js +0 -0
  171. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/vendor/bootstrap.bundle.min.js.map +0 -0
  172. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/vendor/hierarchy-select.min.js +0 -0
  173. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/vendor/introjs.min.js +0 -0
  174. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/vendor/jquery-3.7.1.js +0 -0
  175. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/js/vendor/jquery.contextMenu.min.js +0 -0
  176. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/libreqda.ico +0 -0
  177. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/logo-h.png +0 -0
  178. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/logo.png +0 -0
  179. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/logo_blanc.png +0 -0
  180. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/missing.png +0 -0
  181. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/robots.txt +0 -0
  182. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_badge.scss +0 -0
  183. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_button.scss +0 -0
  184. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_checkbox.scss +0 -0
  185. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_context_menu.scss +0 -0
  186. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_custom_select.scss +0 -0
  187. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_dropdown.scss +0 -0
  188. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_form.scss +0 -0
  189. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_modal.scss +0 -0
  190. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_project_card.scss +0 -0
  191. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_tag.scss +0 -0
  192. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/components/_treeview.scss +0 -0
  193. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/custom.scss +0 -0
  194. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/layout/_credits.scss +0 -0
  195. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/layout/_footer.scss +0 -0
  196. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/layout/_navigation.scss +0 -0
  197. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/layout/_sidebar.scss +0 -0
  198. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/themes/default/_variables.scss +0 -0
  199. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/themes/default/theme.css +0 -0
  200. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/themes/default/theme.css.map +0 -0
  201. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/scss/themes/default/theme.scss +0 -0
  202. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/BadScript-OFL.txt +0 -0
  203. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/BadScript.ttf +0 -0
  204. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/Montserrat-Light.ttf +0 -0
  205. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/Montserrat-OFL.txt +0 -0
  206. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-brands-400.eot +0 -0
  207. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-brands-400.svg +0 -0
  208. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-brands-400.ttf +0 -0
  209. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-brands-400.woff +0 -0
  210. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-brands-400.woff2 +0 -0
  211. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-regular-400.eot +0 -0
  212. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-regular-400.svg +0 -0
  213. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-regular-400.ttf +0 -0
  214. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-regular-400.woff +0 -0
  215. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-regular-400.woff2 +0 -0
  216. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-solid-900.eot +0 -0
  217. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-solid-900.svg +0 -0
  218. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-solid-900.ttf +0 -0
  219. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-solid-900.woff +0 -0
  220. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/static/webfonts/fa-solid-900.woff2 +0 -0
  221. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/alt_templates/.gitkeep +0 -0
  222. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/archived_projects.html +0 -0
  223. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/auth/account.html +0 -0
  224. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/auth/cilogon.login.html +0 -0
  225. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/auth/email_reset_password.html +0 -0
  226. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/auth/external_account.html +0 -0
  227. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/auth/login.html +0 -0
  228. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/auth/reset_password.html +0 -0
  229. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/auth/token_needed.html +0 -0
  230. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/bug_report.html +0 -0
  231. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/cookies_prompt.html +0 -0
  232. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/downloads.html +0 -0
  233. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/email_bug_report.txt +0 -0
  234. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/email_reset_password.txt +0 -0
  235. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/error.html +0 -0
  236. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/export_codebook.html +0 -0
  237. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/export_document.html +0 -0
  238. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/export_highlights.html +0 -0
  239. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/index.html +0 -0
  240. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/maintenance.html +0 -0
  241. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/messages.js +0 -0
  242. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/modal/change_document.html +0 -0
  243. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/modal/create_collection.html +0 -0
  244. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/modal/create_document.html +0 -0
  245. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/modal/create_highlight.html +0 -0
  246. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/modal/create_tag.html +0 -0
  247. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/modal/explore_codes.html +0 -0
  248. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/modal/manage_collaborators.html +0 -0
  249. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/modal/merge_tag.html +0 -0
  250. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/new_password.html +0 -0
  251. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/partials/alert.html +0 -0
  252. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/partials/codebook_viz_modal.html +0 -0
  253. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/partials/confirm.html +0 -0
  254. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/partials/document_toolbar.html +0 -0
  255. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/partials/hlinfo.html +0 -0
  256. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/partials/project_card.html +0 -0
  257. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/partials/project_card_archived.html +0 -0
  258. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/partials/project_sidebar.html +0 -0
  259. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/partials/spinner.html +0 -0
  260. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/permissions.html +0 -0
  261. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/project.html +0 -0
  262. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/project_delete.html +0 -0
  263. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/project_import_codebook.html +0 -0
  264. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/project_import_codebook_confirm.html +0 -0
  265. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/project_new.html +0 -0
  266. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/tos.html +0 -0
  267. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/trans.js +0 -0
  268. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/templates/welcome.html +0 -0
  269. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/utils.py +0 -0
  270. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/validate.py +0 -0
  271. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/web/__init__.py +0 -0
  272. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/web/base.py +0 -0
  273. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/web/export.py +0 -0
  274. {libreqda-1.2.0.post1 → libreqda-1.2.1}/taguette/web/views.py +0 -0
@@ -1,6 +1,17 @@
1
1
  LibreQDA Changelog
2
2
  ==================
3
3
 
4
+ 1.2.1 (2026-09-24)
5
+ ------------------
6
+ - New features:
7
+ - Rename a project on SQLite3 import
8
+ - Outdated-version banner shown on every install method
9
+ - Bugfixes:
10
+ - Extracts no longer bloat to full document via orphan highlights
11
+ - `TagDelete` now also removes highlights whose only tag was the one deleted
12
+ - Docs:
13
+ - README: clearer Docker and dev setup instructions
14
+
4
15
  1.2.0 (2026-09-10)
5
16
  ------------------
6
17
  - New features:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: libreqda
3
- Version: 1.2.0.post1
3
+ Version: 1.2.1
4
4
  Summary: Free and open source qualitative research tool
5
5
  Home-page: https://www.libreqda.org/
6
6
  License: BSD-3-Clause
@@ -111,24 +111,37 @@ Docker
111
111
  ------
112
112
 
113
113
  docker pull phunudes/libreqda
114
- docker run -d -p 7465:7465 -v libreqda-data:/data phunudes/libreqda
114
+ docker run -d --name libreqda -p 7465:7465 -v libreqda-data:/data phunudes/libreqda
115
+ docker logs libreqda | grep -A1 "is now running"
115
116
 
116
- Browse to [localhost:7465](http://localhost:7465/). Data persists in the `libreqda-data` volume.
117
+ The second command prints the token URL (single-user mode). Browse to it. Data persists in the `libreqda-data` volume.
118
+
119
+ Prefer to see the token URL live? Drop `-d` and let it run in the foreground — closing the terminal will stop the container, so you'd relaunch each session:
120
+
121
+ docker run --name libreqda -p 7465:7465 -v libreqda-data:/data phunudes/libreqda
117
122
 
118
123
  Development Setup from the Repository
119
124
  -------------------------------------
120
125
 
121
- You can install from a local clone of this repository, which will allow you to easily change the sources to suit your needs. Taguette provide the base infrastructure for LibreQDA, which is reflected in these instructions:
122
-
123
- 1. Clone this git repository from the terminal: `git clone https://gitlab.com/bin-cirst/libreqda/libre-qda/`
124
- 2. Navigate on the command line to the repository you've just cloned locally, using the `cd` command. To get help using `cd`, use [this tutorial](https://swcarpentry.github.io/shell-novice/02-filedir/index.html).
125
- 3. LibreQDA uses [Poetry](https://python-poetry.org/) for its packaging and dependency management. You will need to [install Poetry](https://python-poetry.org/docs/#installation).
126
- 4. Install LibreQDA and its dependencies by running `poetry install`. Poetry will create a virtual environment for you by default, activate it by running `poetry shell`.
127
- - To install dependencies for mysql or postgres, use the following command `poetry install -E postgres`.
128
- 5. Build translation files using `scripts/update_translations.sh`.
129
- 6. You can start LibreQDA in development mode using `libreqda --debug` (or `libreqda --debug server <config_file>`). This will start Tornado in debug mode, which means in particular that it will auto-restart every time you make changes.
130
- 1. A config file can be created by running `libreqda default-config > taguette.conf`
131
- 7. Navigate to [localhost:7465](http://localhost:7465/) to use LibreQDA!
126
+ Requires **Python 3.11** (3.12+ fails because `frozenlist 1.3.3` in the lock file has no wheels for it) and [Poetry](https://python-poetry.org/docs/#installation).
127
+
128
+ ```
129
+ git clone https://gitlab.com/bin-cirst/libreqda/libre-qda/
130
+ cd libre-qda
131
+ poetry env use python3.11
132
+ poetry install # add -E postgres or -E mysql for those drivers
133
+ poetry run bash scripts/update_translations.sh
134
+ poetry run libreqda --debug # single-user, local SQLite (~/.local/share/taguette/)
135
+ ```
136
+
137
+ Open [localhost:7465](http://localhost:7465/). Tornado auto-restarts on file changes.
138
+
139
+ For multi-user mode, generate a config first and pass it to the `server` subcommand:
140
+
141
+ ```
142
+ poetry run libreqda default-config > taguette.conf
143
+ poetry run libreqda --debug server taguette.conf
144
+ ```
132
145
 
133
146
  Create custom theme
134
147
  -------------------
@@ -54,24 +54,37 @@ Docker
54
54
  ------
55
55
 
56
56
  docker pull phunudes/libreqda
57
- docker run -d -p 7465:7465 -v libreqda-data:/data phunudes/libreqda
57
+ docker run -d --name libreqda -p 7465:7465 -v libreqda-data:/data phunudes/libreqda
58
+ docker logs libreqda | grep -A1 "is now running"
58
59
 
59
- Browse to [localhost:7465](http://localhost:7465/). Data persists in the `libreqda-data` volume.
60
+ The second command prints the token URL (single-user mode). Browse to it. Data persists in the `libreqda-data` volume.
61
+
62
+ Prefer to see the token URL live? Drop `-d` and let it run in the foreground — closing the terminal will stop the container, so you'd relaunch each session:
63
+
64
+ docker run --name libreqda -p 7465:7465 -v libreqda-data:/data phunudes/libreqda
60
65
 
61
66
  Development Setup from the Repository
62
67
  -------------------------------------
63
68
 
64
- You can install from a local clone of this repository, which will allow you to easily change the sources to suit your needs. Taguette provide the base infrastructure for LibreQDA, which is reflected in these instructions:
65
-
66
- 1. Clone this git repository from the terminal: `git clone https://gitlab.com/bin-cirst/libreqda/libre-qda/`
67
- 2. Navigate on the command line to the repository you've just cloned locally, using the `cd` command. To get help using `cd`, use [this tutorial](https://swcarpentry.github.io/shell-novice/02-filedir/index.html).
68
- 3. LibreQDA uses [Poetry](https://python-poetry.org/) for its packaging and dependency management. You will need to [install Poetry](https://python-poetry.org/docs/#installation).
69
- 4. Install LibreQDA and its dependencies by running `poetry install`. Poetry will create a virtual environment for you by default, activate it by running `poetry shell`.
70
- - To install dependencies for mysql or postgres, use the following command `poetry install -E postgres`.
71
- 5. Build translation files using `scripts/update_translations.sh`.
72
- 6. You can start LibreQDA in development mode using `libreqda --debug` (or `libreqda --debug server <config_file>`). This will start Tornado in debug mode, which means in particular that it will auto-restart every time you make changes.
73
- 1. A config file can be created by running `libreqda default-config > taguette.conf`
74
- 7. Navigate to [localhost:7465](http://localhost:7465/) to use LibreQDA!
69
+ Requires **Python 3.11** (3.12+ fails because `frozenlist 1.3.3` in the lock file has no wheels for it) and [Poetry](https://python-poetry.org/docs/#installation).
70
+
71
+ ```
72
+ git clone https://gitlab.com/bin-cirst/libreqda/libre-qda/
73
+ cd libre-qda
74
+ poetry env use python3.11
75
+ poetry install # add -E postgres or -E mysql for those drivers
76
+ poetry run bash scripts/update_translations.sh
77
+ poetry run libreqda --debug # single-user, local SQLite (~/.local/share/taguette/)
78
+ ```
79
+
80
+ Open [localhost:7465](http://localhost:7465/). Tornado auto-restarts on file changes.
81
+
82
+ For multi-user mode, generate a config first and pass it to the `server` subcommand:
83
+
84
+ ```
85
+ poetry run libreqda default-config > taguette.conf
86
+ poetry run libreqda --debug server taguette.conf
87
+ ```
75
88
 
76
89
  Create custom theme
77
90
  -------------------
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "libreqda"
3
- version = "1.2.0.post1"
3
+ version = "1.2.1"
4
4
  description = "Free and open source qualitative research tool"
5
5
  packages = [
6
6
  { include = "taguette" },
@@ -1,4 +1,4 @@
1
- __version__ = '1.1.3'
1
+ __version__ = '1.2.1'
2
2
 
3
3
 
4
4
  from gettext import NullTranslations
@@ -17,6 +17,7 @@ tracer = opentelemetry.trace.get_tracer(__name__)
17
17
  def copy_project(
18
18
  src_db, dest_db,
19
19
  project_id, user_login,
20
+ new_name=None,
20
21
  ):
21
22
  def copy(
22
23
  table, pkey, fkeys, size,
@@ -42,9 +43,11 @@ def copy_project(
42
43
  ).fetchone()
43
44
  if project is None:
44
45
  raise KeyError("project ID not found")
46
+ project = dict(project)
47
+ if new_name is not None:
48
+ project['name'] = new_name
45
49
  validate.project_name(project['name'])
46
50
  validate.description(project['description'])
47
- project = dict(project)
48
51
  project.pop('id')
49
52
  project['is_archived'] = False
50
53
  new_project_id, = insert(Project.__table__, project).inserted_primary_key
@@ -23,7 +23,7 @@
23
23
  {% if outdated_version %}
24
24
  <div id="version-outdated-banner" class="alert alert-warning alert-dismissible mb-0 rounded-0 border-0 text-center d-none" role="alert" style="position: fixed; top: 6.5em; left: 0; right: 0; z-index: 101;">
25
25
  {% set downloads_url = reverse_url('downloads') %}
26
- {% trans latest_version=outdated_version, current_version=version, url=downloads_url %}A newer version of LibreQDA ({{ latest_version }}) is available. You are running {{ current_version }}. <a href="{{ url }}">Download the latest installer</a>.{% endtrans %}
26
+ {% trans latest_version=outdated_version, current_version=version, url=downloads_url %}A newer version of LibreQDA ({{ latest_version }}) is available. You are running {{ current_version }}. <a href="{{ url }}">Update now</a>.{% endtrans %}
27
27
  <button type="button" class="btn-close" id="version-outdated-dismiss" aria-label="{% trans %}Close{% endtrans %}"></button>
28
28
  </div>
29
29
  <script>
@@ -21,6 +21,13 @@
21
21
  </select>
22
22
  </div>
23
23
  </div>
24
+ <div class="form-group row">
25
+ <label for="new-name" class="col-sm-2 col-form-label">{% trans "form label for new project name" %}New name:{% endtrans %}</label>
26
+ <div class="col-sm-10">
27
+ <input type="text" class="form-control" name="new-name" id="new-name" maxlength="200"
28
+ placeholder="{% trans %}Optional — leave blank to keep the original name{% endtrans %}" disabled>
29
+ </div>
30
+ </div>
24
31
  <p>
25
32
  <input type="submit" class="btn btn-primary" id="submit" value="{% trans "form submit button" %}Import project{% endtrans %}" disabled>
26
33
  </p>
@@ -57,6 +64,7 @@ projectFile.addEventListener('change', function() {
57
64
  elem.innerText = '' + project.id + ' - ' + project.name;
58
65
  projectList.appendChild(elem);
59
66
  }
67
+ document.getElementById('new-name').disabled = false;
60
68
  document.getElementById('submit').disabled = false;
61
69
  } else {
62
70
  console.error("Project upload failed:", xhr.status);
@@ -85,6 +93,10 @@ function importProject() {
85
93
  var file = projectFile.files[0];
86
94
  var form_data = new FormData();
87
95
  form_data.append('project_id', parseInt(document.getElementById('project').value, 10));
96
+ var newName = document.getElementById('new-name').value.trim();
97
+ if(newName) {
98
+ form_data.append('new_name', newName);
99
+ }
88
100
  form_data.append('file', file);
89
101
  var xsrf = document.cookie.match('\\b' + '_xsrf' + '=([^;]*)\\b');
90
102
  if(xsrf) {
@@ -72,7 +72,7 @@ async def _fetch_latest():
72
72
  _cache['in_flight'] = False
73
73
 
74
74
 
75
- def is_desktop_bundle():
75
+ def is_standalone_bundle():
76
76
  return getattr(sys, 'frozen', False)
77
77
 
78
78
 
@@ -81,9 +81,6 @@ def get_outdated_version():
81
81
  if forced:
82
82
  return forced
83
83
 
84
- if not is_desktop_bundle():
85
- return None
86
-
87
84
  now = time.time()
88
85
  if (
89
86
  not _cache['in_flight']
@@ -580,6 +580,11 @@ class TagUpdate(BaseHandler):
580
580
  tag = self.db.query(database.Tag).get(int(tag_id))
581
581
  if tag is None or tag.project_id != project.id:
582
582
  return self.send_error_json(404, self.gettext("No such tag"))
583
+ # Drop highlights that would become orphaned.
584
+ self.db.query(database.Highlight).filter(
585
+ database.Highlight.tags.any(database.Tag.id == tag.id),
586
+ ~database.Highlight.tags.any(database.Tag.id != tag.id),
587
+ ).delete(synchronize_session=False)
583
588
  self.db.delete(tag)
584
589
  cmd = database.Command.tag_delete(
585
590
  self.current_user,
@@ -1045,7 +1050,8 @@ class Highlights(BaseHandler):
1045
1050
  all_tag_ids = set(t.id for t in hl.tags if t.path not in excluded)
1046
1051
 
1047
1052
  # Find related highlights: any overlap
1048
- # (identical, contained, containing, or partial)
1053
+ # (identical, contained, containing, or partial).
1054
+ # Skip orphans (no tags) — they inflate the union range.
1049
1055
  related_highlights = (
1050
1056
  self.db.query(database.Highlight)
1051
1057
  .options(joinedload(database.Highlight.tags))
@@ -1054,6 +1060,7 @@ class Highlights(BaseHandler):
1054
1060
  database.Highlight.id != hl.id,
1055
1061
  database.Highlight.start_offset < hl.end_offset,
1056
1062
  database.Highlight.end_offset > hl.start_offset,
1063
+ database.Highlight.tags.any(),
1057
1064
  )
1058
1065
  .all()
1059
1066
  )
@@ -1369,7 +1376,12 @@ class ProjectImport(BaseHandler):
1369
1376
  return await self.send_json({
1370
1377
  'error': "Invalid project ID",
1371
1378
  })
1372
- return await self._import_project(filename, project_id)
1379
+ new_name = (
1380
+ self.get_body_argument('new_name', '').strip() or None
1381
+ )
1382
+ return await self._import_project(
1383
+ filename, project_id, new_name=new_name,
1384
+ )
1373
1385
 
1374
1386
  async def _list_projects(self, filename):
1375
1387
  # Connect to the database
@@ -1415,7 +1427,7 @@ class ProjectImport(BaseHandler):
1415
1427
  self.write('{"projects": [')
1416
1428
  return await self.finish(']}')
1417
1429
 
1418
- async def _import_project(self, filename, project_id):
1430
+ async def _import_project(self, filename, project_id, new_name=None):
1419
1431
  # Connect to the database
1420
1432
  try:
1421
1433
  src_db = database.connect(
@@ -1431,6 +1443,7 @@ class ProjectImport(BaseHandler):
1431
1443
  new_project_id = database.copy_project(
1432
1444
  src_db, self.db,
1433
1445
  project_id, self.current_user,
1446
+ new_name=new_name,
1434
1447
  )
1435
1448
  src_db.close()
1436
1449
 
File without changes
File without changes