libreqda 1.2.0__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.
- CHANGELOG.md +481 -0
- libreqda-1.2.0.dist-info/LICENSE.txt +28 -0
- libreqda-1.2.0.dist-info/METADATA +131 -0
- libreqda-1.2.0.dist-info/RECORD +255 -0
- libreqda-1.2.0.dist-info/WHEEL +4 -0
- libreqda-1.2.0.dist-info/entry_points.txt +4 -0
- scripts/babelrc +8 -0
- scripts/dist/LICENSE.txt +33 -0
- scripts/dist/RELEASE.txt +23 -0
- scripts/dist/macos/libreqda.icns +0 -0
- scripts/dist/macos/macos.spec +43 -0
- scripts/dist/macos/plist.patch +10 -0
- scripts/dist/macos/taguette.icns +0 -0
- scripts/dist/macos/taguette_console_wrapper +4 -0
- scripts/dist/macos.sh +32 -0
- scripts/dist/pyinstaller_entrypoint.py +19 -0
- scripts/dist/windows/windows-installer.iss +51 -0
- scripts/dist/windows/windows.spec +39 -0
- scripts/edugain/worker_update_edugain_idps.py +89 -0
- scripts/edugain/worker_update_edugain_idps.sh +9 -0
- scripts/make_password_reset_link.py +56 -0
- scripts/make_theme.py +99 -0
- scripts/new_db_revision.sh +8 -0
- scripts/register_user.py +76 -0
- scripts/update_pot.sh +33 -0
- scripts/update_translations.sh +17 -0
- scripts/validate.py +140 -0
- scripts/wipe_and_disable_user.py +90 -0
- taguette/__init__.py +13 -0
- taguette/access_control.py +145 -0
- taguette/convert.py +623 -0
- taguette/database/__init__.py +177 -0
- taguette/database/base.py +9 -0
- taguette/database/copy.py +433 -0
- taguette/database/models.py +920 -0
- taguette/demodata.py +688 -0
- taguette/export.py +500 -0
- taguette/extract.py +287 -0
- taguette/import_codebook.py +110 -0
- taguette/l10n/de_DE/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/de_DE/LC_MESSAGES/taguette_main.mo +0 -0
- taguette/l10n/el_EL/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/el_GR/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/el_GR/LC_MESSAGES/taguette_main.mo +0 -0
- taguette/l10n/en_US/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/en_US/LC_MESSAGES/taguette_main.mo +0 -0
- taguette/l10n/es_ES/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/es_ES/LC_MESSAGES/taguette_main.mo +0 -0
- taguette/l10n/fr_FR/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/fr_FR/LC_MESSAGES/taguette_main.mo +0 -0
- taguette/l10n/id_ID/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/id_ID/LC_MESSAGES/taguette_main.mo +0 -0
- taguette/l10n/it_IT/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/it_IT/LC_MESSAGES/taguette_main.mo +0 -0
- taguette/l10n/nl_NL/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/nl_NL/LC_MESSAGES/taguette_main.mo +0 -0
- taguette/l10n/pt_PT/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/pt_PT/LC_MESSAGES/taguette_main.mo +0 -0
- taguette/l10n/sv_SE/LC_MESSAGES/taguette_javascript.mo +0 -0
- taguette/l10n/sv_SE/LC_MESSAGES/taguette_main.mo +0 -0
- taguette/loki_handler.py +107 -0
- taguette/main.py +649 -0
- taguette/migrations/env.py +72 -0
- taguette/migrations/script.py.mako +24 -0
- taguette/migrations/versions/09c662cd9483_make_documents_filename_not_null.py +39 -0
- taguette/migrations/versions/1b29e68900c1_add_user_roles.py +55 -0
- taguette/migrations/versions/1b96a606551d_update_user_to_have_a_display_name.py +34 -0
- taguette/migrations/versions/2467bab602b7_add_color_column_to_tags_table.py +33 -0
- taguette/migrations/versions/382db36f20f4_add_user_disabled.py +66 -0
- taguette/migrations/versions/43d6c240309d_remove_document_groups.py +81 -0
- taguette/migrations/versions/447d636f72c5_cascades.py +40 -0
- taguette/migrations/versions/491de2dc7cd7_add_indexes.py +51 -0
- taguette/migrations/versions/4c55b3b3ff30_user_login_length.py +58 -0
- taguette/migrations/versions/61a4abcc8769_user_with_parent_for_permissions.py +40 -0
- taguette/migrations/versions/6489b5f9cfb5_increase_password_hash_size.py +34 -0
- taguette/migrations/versions/679f625e6e6a_fix_unique_tags.py +59 -0
- taguette/migrations/versions/77c4543a5b9b_add_parent_id_column_to_collection_table.py +41 -0
- taguette/migrations/versions/7c94b7a31e69_add_is_archived_column_to_projets.py +39 -0
- taguette/migrations/versions/7f56de97e3c8_change_edugain_displayname_length.py +42 -0
- taguette/migrations/versions/807c0cc0ecf6_remove_invalid_hltags.py +43 -0
- taguette/migrations/versions/80b1cc9d4c22_add_user_email.py +35 -0
- taguette/migrations/versions/91ade71ccf4d_add_user_language.py +28 -0
- taguette/migrations/versions/955db2e523d1_add_collections_tables_and_associations_.py +60 -0
- taguette/migrations/versions/a1b2c3d4e5f6_add_user_hide_code_counts.py +28 -0
- taguette/migrations/versions/b23f3b7a638e_add_user_password_change_date.py +36 -0
- taguette/migrations/versions/b7c1e2d3f4a5_add_project_compact_layout.py +28 -0
- taguette/migrations/versions/bc8e0e0677e9_rename_command_fields.py +126 -0
- taguette/migrations/versions/bce44849c2f2_lowercase_logins.py +96 -0
- taguette/migrations/versions/ca076140922f_update_user_for_external_logins.py +32 -0
- taguette/migrations/versions/d86c45d7aa8a_add_document_direction.py +127 -0
- taguette/migrations/versions/db5e31a0233d_remove_blank_highlights.py +88 -0
- taguette/migrations/versions/dd37d9027a24_unique_tags.py +68 -0
- taguette/migrations/versions/de678cef2a94_add_project_id_to_collections_and_.py +41 -0
- taguette/migrations/versions/e459991d960e_add_table_edugainidps.py +39 -0
- taguette/migrations/versions/e4cf92942271_add_index.py +29 -0
- taguette/migrations/versions/e4e090a5b511_remove_commands_document_id_fk.py +38 -0
- taguette/migrations/versions/e9a9f1c77971_add_favorite_column_to_document.py +32 -0
- taguette/migrations/versions/ecb4065de575_don_t_use_server_default_now_timezone_.py +44 -0
- taguette/migrations/versions/fbdc29566f62_edugain_fix_field_type.py +42 -0
- taguette/migrations/versions/fdc6eb54b034_add_parent_id_column_to_tags_table.py +31 -0
- taguette/static/README.md +34 -0
- taguette/static/alt_templates/.gitkeep +0 -0
- taguette/static/assets/test/logos/monsters-university-logo.png +0 -0
- taguette/static/css/custom.css +1696 -0
- taguette/static/css/fa-all.min.css +5 -0
- taguette/static/css/themed.css +3 -0
- taguette/static/css/themed.css.map +25 -0
- taguette/static/css/vendor/bootstrap-treeview.min.css +1 -0
- taguette/static/css/vendor/bootstrap.min.css +6 -0
- taguette/static/css/vendor/font/context-menu-icons.eot +0 -0
- taguette/static/css/vendor/font/context-menu-icons.ttf +0 -0
- taguette/static/css/vendor/font/context-menu-icons.woff +0 -0
- taguette/static/css/vendor/font/context-menu-icons.woff2 +0 -0
- taguette/static/css/vendor/hierarchy-select.min.css +1 -0
- taguette/static/css/vendor/introjs.min.css +2 -0
- taguette/static/css/vendor/jquery.contextMenu.min.css +16 -0
- taguette/static/favicon.ico +0 -0
- taguette/static/js/codebook-viz.js +428 -0
- taguette/static/js/collection/context-menu.js +180 -0
- taguette/static/js/collection/hierarchy-select.js +71 -0
- taguette/static/js/collection/manager.js +217 -0
- taguette/static/js/document/context-menu.js +92 -0
- taguette/static/js/document/custom-select.js +82 -0
- taguette/static/js/document/manager.js +943 -0
- taguette/static/js/document/treeview.js +593 -0
- taguette/static/js/highlight/README.md +18 -0
- taguette/static/js/highlight/crud.js +119 -0
- taguette/static/js/highlight/extracts.js +497 -0
- taguette/static/js/highlight/loader.js +109 -0
- taguette/static/js/highlight/renderer.js +405 -0
- taguette/static/js/login.js +15 -0
- taguette/static/js/permissions.js +153 -0
- taguette/static/js/polling-event.js +145 -0
- taguette/static/js/project/intro.js +524 -0
- taguette/static/js/project/manager.js +0 -0
- taguette/static/js/project/search.js +124 -0
- taguette/static/js/tag/context-menu.js +133 -0
- taguette/static/js/tag/explore-codes.js +400 -0
- taguette/static/js/tag/hierarchy-select.js +69 -0
- taguette/static/js/tag/manager.js +545 -0
- taguette/static/js/tag/treeview.js +613 -0
- taguette/static/js/taguette.js +1790 -0
- taguette/static/js/utilities.js +714 -0
- taguette/static/js/vendor/bootstrap-treeview-custum.js +421 -0
- taguette/static/js/vendor/bootstrap-treeview-custum.min.js +1 -0
- taguette/static/js/vendor/bootstrap-treeview-default.min.js +1 -0
- taguette/static/js/vendor/bootstrap.bundle.min.js +7 -0
- taguette/static/js/vendor/bootstrap.bundle.min.js.map +1 -0
- taguette/static/js/vendor/hierarchy-select.min.js +1 -0
- taguette/static/js/vendor/introjs.min.js +17 -0
- taguette/static/js/vendor/jquery-3.7.1.js +2 -0
- taguette/static/js/vendor/jquery.contextMenu.min.js +2 -0
- taguette/static/libreqda.ico +0 -0
- taguette/static/logo-h.png +0 -0
- taguette/static/logo.png +0 -0
- taguette/static/logo_blanc.png +0 -0
- taguette/static/missing.png +0 -0
- taguette/static/robots.txt +2 -0
- taguette/static/scss/components/_badge.scss +42 -0
- taguette/static/scss/components/_button.scss +169 -0
- taguette/static/scss/components/_checkbox.scss +40 -0
- taguette/static/scss/components/_context_menu.scss +28 -0
- taguette/static/scss/components/_custom_select.scss +150 -0
- taguette/static/scss/components/_dropdown.scss +43 -0
- taguette/static/scss/components/_form.scss +54 -0
- taguette/static/scss/components/_modal.scss +57 -0
- taguette/static/scss/components/_project_card.scss +163 -0
- taguette/static/scss/components/_tag.scss +308 -0
- taguette/static/scss/components/_treeview.scss +76 -0
- taguette/static/scss/custom.scss +809 -0
- taguette/static/scss/layout/_credits.scss +62 -0
- taguette/static/scss/layout/_footer.scss +6 -0
- taguette/static/scss/layout/_navigation.scss +165 -0
- taguette/static/scss/layout/_sidebar.scss +37 -0
- taguette/static/scss/themes/default/_variables.scss +103 -0
- taguette/static/scss/themes/default/theme.css +3 -0
- taguette/static/scss/themes/default/theme.css.map +26 -0
- taguette/static/scss/themes/default/theme.scss +4 -0
- taguette/static/webfonts/BadScript-OFL.txt +94 -0
- taguette/static/webfonts/BadScript.ttf +0 -0
- taguette/static/webfonts/Montserrat-Light.ttf +0 -0
- taguette/static/webfonts/Montserrat-OFL.txt +93 -0
- taguette/static/webfonts/fa-brands-400.eot +0 -0
- taguette/static/webfonts/fa-brands-400.svg +1184 -0
- taguette/static/webfonts/fa-brands-400.ttf +0 -0
- taguette/static/webfonts/fa-brands-400.woff +0 -0
- taguette/static/webfonts/fa-brands-400.woff2 +0 -0
- taguette/static/webfonts/fa-regular-400.eot +0 -0
- taguette/static/webfonts/fa-regular-400.svg +467 -0
- taguette/static/webfonts/fa-regular-400.ttf +0 -0
- taguette/static/webfonts/fa-regular-400.woff +0 -0
- taguette/static/webfonts/fa-regular-400.woff2 +0 -0
- taguette/static/webfonts/fa-solid-900.eot +0 -0
- taguette/static/webfonts/fa-solid-900.svg +2618 -0
- taguette/static/webfonts/fa-solid-900.ttf +0 -0
- taguette/static/webfonts/fa-solid-900.woff +0 -0
- taguette/static/webfonts/fa-solid-900.woff2 +0 -0
- taguette/templates/alt_templates/.gitkeep +0 -0
- taguette/templates/archived_projects.html +50 -0
- taguette/templates/auth/account.html +74 -0
- taguette/templates/auth/cilogon.login.html +89 -0
- taguette/templates/auth/email_reset_password.html +5 -0
- taguette/templates/auth/external_account.html +60 -0
- taguette/templates/auth/login.html +144 -0
- taguette/templates/auth/reset_password.html +27 -0
- taguette/templates/auth/token_needed.html +7 -0
- taguette/templates/base.html +209 -0
- taguette/templates/bug_report.html +158 -0
- taguette/templates/cookies_prompt.html +15 -0
- taguette/templates/downloads.html +127 -0
- taguette/templates/email_bug_report.txt +9 -0
- taguette/templates/email_reset_password.txt +5 -0
- taguette/templates/error.html +8 -0
- taguette/templates/export_codebook.html +20 -0
- taguette/templates/export_document.html +20 -0
- taguette/templates/export_highlights.html +47 -0
- taguette/templates/index.html +347 -0
- taguette/templates/maintenance.html +8 -0
- taguette/templates/messages.js +74 -0
- taguette/templates/modal/change_document.html +68 -0
- taguette/templates/modal/create_collection.html +100 -0
- taguette/templates/modal/create_document.html +84 -0
- taguette/templates/modal/create_highlight.html +38 -0
- taguette/templates/modal/create_tag.html +73 -0
- taguette/templates/modal/explore_codes.html +58 -0
- taguette/templates/modal/manage_collaborators.html +44 -0
- taguette/templates/modal/merge_tag.html +49 -0
- taguette/templates/new_password.html +32 -0
- taguette/templates/partials/alert.html +16 -0
- taguette/templates/partials/codebook_viz_modal.html +34 -0
- taguette/templates/partials/confirm.html +17 -0
- taguette/templates/partials/document_toolbar.html +37 -0
- taguette/templates/partials/hlinfo.html +13 -0
- taguette/templates/partials/project_card.html +44 -0
- taguette/templates/partials/project_card_archived.html +41 -0
- taguette/templates/partials/project_sidebar.html +99 -0
- taguette/templates/partials/spinner.html +11 -0
- taguette/templates/permissions.html +54 -0
- taguette/templates/project.html +288 -0
- taguette/templates/project_delete.html +17 -0
- taguette/templates/project_import.html +122 -0
- taguette/templates/project_import_codebook.html +34 -0
- taguette/templates/project_import_codebook_confirm.html +49 -0
- taguette/templates/project_new.html +31 -0
- taguette/templates/tos.html +8 -0
- taguette/templates/trans.js +7 -0
- taguette/templates/welcome.html +15 -0
- taguette/utils.py +177 -0
- taguette/validate.py +141 -0
- taguette/version_check.py +102 -0
- taguette/web/__init__.py +252 -0
- taguette/web/api.py +1835 -0
- taguette/web/base.py +864 -0
- taguette/web/export.py +338 -0
- taguette/web/views.py +1618 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block morejs %}
|
|
4
|
+
<script type="text/javascript" src="{{ static_url('js/utilities.js') }}"></script>
|
|
5
|
+
{% endblock %}
|
|
6
|
+
|
|
7
|
+
{% block contents %}
|
|
8
|
+
<div class="container py-4">
|
|
9
|
+
<h1>{% trans %}Archived projects{% endtrans %}</h1>
|
|
10
|
+
|
|
11
|
+
<div class="d-flex flex-column flex-sm-row justify-content-start mb-4 mt-4">
|
|
12
|
+
<a href="{{ reverse_url('index') }}" class="btn btn-secondary me-sm-3 mb-2">
|
|
13
|
+
<i class="fas fa-arrow-left"></i> {% trans %}Back to projects{% endtrans %}
|
|
14
|
+
</a>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<div class="main">
|
|
18
|
+
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-2 row-cols-lg-4 g-4">
|
|
19
|
+
{% if projects %}
|
|
20
|
+
{% for project in projects %}
|
|
21
|
+
{% include 'partials/project_card_archived.html' %}
|
|
22
|
+
{% endfor %}
|
|
23
|
+
{% else %}
|
|
24
|
+
<div class="col">
|
|
25
|
+
<p class="text-muted">{% trans %}No archived projects.{% endtrans %}</p>
|
|
26
|
+
</div>
|
|
27
|
+
{% endif %}
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<script>
|
|
33
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
34
|
+
document.querySelectorAll('.action-unarchive').forEach(function(link) {
|
|
35
|
+
link.addEventListener('click', function(e) {
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
const projectId = this.dataset.projectId;
|
|
38
|
+
const xsrf = getCookie('_xsrf');
|
|
39
|
+
fetch('/project/' + projectId + '/unarchive?_xsrf=' + encodeURIComponent(xsrf), {
|
|
40
|
+
method: 'POST'
|
|
41
|
+
}).then(function(response) {
|
|
42
|
+
if (response.ok) {
|
|
43
|
+
window.location.reload();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
</script>
|
|
50
|
+
{% endblock %}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
{% set active_page = "account" %}
|
|
3
|
+
|
|
4
|
+
{% block title %}{% trans "page title" %}Account settings{% endtrans %} | LibreQDA{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block contents %}
|
|
7
|
+
<h1>{% trans "title" %}Account settings{% endtrans %}</h1>
|
|
8
|
+
{% if error %}
|
|
9
|
+
<div class="alert alert-danger">{{ error }}</div>
|
|
10
|
+
{% endif %}
|
|
11
|
+
<form action="{{ reverse_url('account') }}" method="post">
|
|
12
|
+
{{ xsrf_form_html() }}
|
|
13
|
+
<div class="form-group row">
|
|
14
|
+
<label for="login" class="col-sm-2 col-form-label pt-0">{% trans "form label for user name" %}Login{% endtrans %}</label>
|
|
15
|
+
<div class="col-sm-10">
|
|
16
|
+
<input type="text" id="login" class="form-control" value="{{ user.login }}" disabled />
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="form-group row">
|
|
20
|
+
<label for="displayname" class="col-sm-2 col-form-label pt-0">{% trans "form label for displayname" %}Display name{% endtrans %}</label>
|
|
21
|
+
<div class="col-sm-10">
|
|
22
|
+
<input type="text" id="displayname" name="displayname" class="form-control" value="{{ user.displayname or '' }}" />
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="form-group row">
|
|
26
|
+
<label for="email" class="col-sm-2 col-form-label pt-0">{% trans "form label for email address" %}Email{% endtrans %}</label>
|
|
27
|
+
<div class="col-sm-10">
|
|
28
|
+
<input type="text" name="email" id="email" class="form-control" value="{{ user.email or '' }}" />
|
|
29
|
+
<small>{% trans %}Optional. <em>We will not share your email with anyone. This is only used in case you forget your password.</em>{% endtrans %}</small>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="form-group row">
|
|
33
|
+
<label for="language" class="col-sm-2 col-form-label pt-0">{% trans "form label for language selection" %}Language{% endtrans %}</label>
|
|
34
|
+
<div class="col-sm-10">
|
|
35
|
+
<select id="language" name="language" class="form-control">
|
|
36
|
+
<option value="auto"{% if current_language == None %} selected{% endif %}>{% trans "language selection option" %}Auto-detect{% endtrans %}</option>
|
|
37
|
+
{% for lang_code, lang_name in languages %}
|
|
38
|
+
<option value="{{ lang_code }}"{% if lang_code == current_language %} selected{% endif %}>{{ lang_name }}</option>
|
|
39
|
+
{% endfor %}
|
|
40
|
+
</select>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="form-group row">
|
|
44
|
+
<label for="password1" class="col-sm-2 col-form-label pt-0">{% trans %}New password{% endtrans %}</label>
|
|
45
|
+
<div class="col-sm-10">
|
|
46
|
+
<input type="password" name="password1" id="password1" class="form-control" />
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="form-group row">
|
|
50
|
+
<label for="password2" class="col-sm-2 col-form-label pt-0">{% trans %}Repeat new password{% endtrans %}</label>
|
|
51
|
+
<div class="col-sm-10">
|
|
52
|
+
<input type="password" name="password2" id="password2" class="form-control" />
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<hr class="my-4" />
|
|
57
|
+
<h2 class="h1">{% trans "section title" %}Display preferences{% endtrans %}</h2>
|
|
58
|
+
<div class="form-group row">
|
|
59
|
+
<label class="col-sm-2 col-form-label pt-0">{% trans "form label for hiding code counts" %}Hide code count badges{% endtrans %}</label>
|
|
60
|
+
<div class="col-sm-10">
|
|
61
|
+
<div class="form-check">
|
|
62
|
+
<input type="checkbox" name="hide_code_counts" id="hide_code_counts" class="form-check-input"{% if user.hide_code_counts %} checked{% endif %} />
|
|
63
|
+
<label for="hide_code_counts" class="form-check-label small fst-italic">{% trans "form label for hiding code counts" %}Hides the document/highlight count badges in the codebook and disables sorting codes by frequency.{% endtrans %}</label>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<div class="row position-sticky bottom-0 bg-body border-top py-3 mt-4">
|
|
69
|
+
<div class="col-12 text-center">
|
|
70
|
+
<button type="submit" class="btn btn-primary">{% trans "form submit button" %}Update{% endtrans %}</button>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</form>
|
|
74
|
+
{% endblock %}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
{% set active_page = "login" %}
|
|
3
|
+
|
|
4
|
+
{% block title %}{% trans "page title" %}Log in{% endtrans %} | LibreQDA{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block contents %}
|
|
7
|
+
<div class="row">
|
|
8
|
+
<div class="col">
|
|
9
|
+
<h1>{% trans "tab" %}Log in{% endtrans %}</h1>
|
|
10
|
+
<p class="mb-4">{% trans %}LibreQDA uses <a target="_blank" href="https://www.cilogon.org/home">CILogon</a> to authenticate users by redirecting them to their chosen identity provider.{% endtrans %}</p>
|
|
11
|
+
<div class="alert alert-secondary mt-3 small" role="alert">
|
|
12
|
+
{% trans %}
|
|
13
|
+
If your institution is not listed or authentication fails, please contact your institution's IT department.
|
|
14
|
+
You can refer them to <a href="https://www.cilogon.org/service/addidp" target="_blank">this page</a>.
|
|
15
|
+
<br>
|
|
16
|
+
Do not contact CILogon directly.
|
|
17
|
+
{% endtrans %}
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="row mt-4 g-3">
|
|
21
|
+
<div class="col-12 col-sm">
|
|
22
|
+
<div class="dropdown hierarchy-select w-100" id="entity_id-select">
|
|
23
|
+
<button class="btn btn-outline-secondary dropdown-toggle w-100 py-2 px-3" type="button"
|
|
24
|
+
id="entity_idButtonTag" data-bs-toggle="dropdown"
|
|
25
|
+
aria-expanded="false"></button>
|
|
26
|
+
<ul class="dropdown-menu" aria-labelledby="entity_idButtonTag">
|
|
27
|
+
<div class="hs-searchbox">
|
|
28
|
+
<input type="text" class="form-control" autocomplete="off">
|
|
29
|
+
</div>
|
|
30
|
+
<div class="hs-menu-inner">
|
|
31
|
+
<a class="dropdown-item" data-value="" data-level="1" href="#">
|
|
32
|
+
{% trans %}Select your institution{% endtrans %}
|
|
33
|
+
</a>
|
|
34
|
+
{% for idp in idps %}
|
|
35
|
+
<a class="dropdown-item" data-value="{{ idp['entityid'] }}" data-level="1" href="#"
|
|
36
|
+
{% if idp['entityid'] == entity_id %}selected=""{% endif %}>
|
|
37
|
+
{{ idp['name'] }}
|
|
38
|
+
</a>
|
|
39
|
+
{% endfor %}
|
|
40
|
+
</div>
|
|
41
|
+
</ul>
|
|
42
|
+
<input class="d-none" id="entity_id" name="entity_id" readonly="readonly" aria-hidden="true"
|
|
43
|
+
type="text" {% if entity_id %}value="{{ entity_id }}"{% endif %}/>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<div class="col-12 col-sm-auto">
|
|
48
|
+
<a class="btn btn-primary w-100 py-2 px-4" id="cilogon" href="/cilogon">
|
|
49
|
+
{% trans %}Continue to authentication with{% endtrans %} CILogon
|
|
50
|
+
</a>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
<!-- Alert modal -->
|
|
58
|
+
{% include 'partials/alert.html' %}
|
|
59
|
+
|
|
60
|
+
{% if error %}
|
|
61
|
+
<script type="text/javascript">
|
|
62
|
+
let error_msg = `{{ error_msg }}`;
|
|
63
|
+
window.addEventListener('load', function() {
|
|
64
|
+
showAlert(error_msg, 'error');
|
|
65
|
+
});
|
|
66
|
+
</script>
|
|
67
|
+
{% endif %}
|
|
68
|
+
{% endblock %}
|
|
69
|
+
|
|
70
|
+
{% block morejs %}
|
|
71
|
+
<script type="text/javascript">
|
|
72
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
73
|
+
const loginBtn = document.getElementById('cilogon');
|
|
74
|
+
const entityInput = document.getElementById('entity_id');
|
|
75
|
+
|
|
76
|
+
loginBtn.addEventListener('click', function (e) {
|
|
77
|
+
if (!entityInput.value) {
|
|
78
|
+
e.preventDefault();
|
|
79
|
+
showAlert("{% trans %}Please select your institution from the list before continuing{% endtrans %}.", "error");
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<!-- Utilities -->
|
|
86
|
+
<script type="text/javascript" src="{{ static_url('js/utilities.js') }}"></script>
|
|
87
|
+
<script type="text/javascript" src="{{ static_url('js/vendor/hierarchy-select.min.js') }}"></script>
|
|
88
|
+
<script type="text/javascript" src="{{ static_url('js/login.js') }}"></script>
|
|
89
|
+
{% endblock %}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<p>{% trans %}Someone has requested to reset the password on the Taguette account associated with this email. If this was you, please follow this link: <a href="{{ link }}">{{ link }}</a>{% endtrans %}</p>
|
|
2
|
+
|
|
3
|
+
<p>{% trans %}Your user name is: <strong>{{ login }}</strong>{% endtrans %}</p>
|
|
4
|
+
|
|
5
|
+
<p>{% trans %}This link will expire in 1 day.{% endtrans %}</p>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
{% set active_page = "account" %}
|
|
3
|
+
|
|
4
|
+
{% block title %}{% trans "page title" %}Account settings{% endtrans %} | LibreQDA{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block contents %}
|
|
7
|
+
<h1>{% trans "title" %}Account settings{% endtrans %}</h1>
|
|
8
|
+
{% if error %}
|
|
9
|
+
<div class="alert alert-danger">{{ error }}</div>
|
|
10
|
+
{% endif %}
|
|
11
|
+
<form action="{{ reverse_url('account') }}" method="post">
|
|
12
|
+
{{ xsrf_form_html() }}
|
|
13
|
+
<div class="form-group row">
|
|
14
|
+
<label for="login" class="col-sm-2 col-form-label pt-0">{% trans "form label for user name" %}Login{% endtrans %}</label>
|
|
15
|
+
<div class="col-sm-10">
|
|
16
|
+
<input type="text" id="login" class="form-control" value="{{ user.login }}" disabled />
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="form-group row">
|
|
20
|
+
<label for="displayname" class="col-sm-2 col-form-label pt-0">{% trans "form label for displayname" %}Display name{% endtrans %}</label>
|
|
21
|
+
<div class="col-sm-10">
|
|
22
|
+
<input type="text" id="displayname" name="displayname" class="form-control" value="{{ user.displayname or '' }}" />
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="form-group row">
|
|
26
|
+
<label for="email" class="col-sm-2 col-form-label pt-0">{% trans "form label for email address" %}Email{% endtrans %}</label>
|
|
27
|
+
<div class="col-sm-10">
|
|
28
|
+
<input type="text" name="email" id="email" class="form-control" value="{{ user.email }}" />
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="form-group row">
|
|
32
|
+
<label for="language" class="col-sm-2 col-form-label pt-0">{% trans "form label for language selection" %}Language{% endtrans %}</label>
|
|
33
|
+
<div class="col-sm-10">
|
|
34
|
+
<select id="language" name="language" class="form-control">
|
|
35
|
+
<option value="auto"{% if current_language == None %} selected{% endif %}>{% trans "language selection option" %}Auto-detect{% endtrans %}</option>
|
|
36
|
+
{% for lang_code, lang_name in languages %}
|
|
37
|
+
<option value="{{ lang_code }}"{% if lang_code == current_language %} selected{% endif %}>{{ lang_name }}</option>
|
|
38
|
+
{% endfor %}
|
|
39
|
+
</select>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
<hr class="my-4" />
|
|
43
|
+
<h2 class="h1">{% trans "section title" %}Display preferences{% endtrans %}</h2>
|
|
44
|
+
<div class="form-group row">
|
|
45
|
+
<label class="col-sm-2 col-form-label pt-0">{% trans "form label for hiding code counts" %}Hide code count badges{% endtrans %}</label>
|
|
46
|
+
<div class="col-sm-10">
|
|
47
|
+
<div class="form-check">
|
|
48
|
+
<input type="checkbox" name="hide_code_counts" id="hide_code_counts" class="form-check-input"{% if user.hide_code_counts %} checked{% endif %} />
|
|
49
|
+
<label for="hide_code_counts" class="form-check-label small fst-italic">{% trans "form label for hiding code counts" %}Hides the document/highlight count badges in the codebook and disables sorting codes by frequency.{% endtrans %}</label>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div class="row position-sticky bottom-0 bg-body border-top py-3 mt-4">
|
|
55
|
+
<div class="col-12 text-center">
|
|
56
|
+
<button type="submit" class="btn btn-primary">{% trans "form submit button" %}Update{% endtrans %}</button>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</form>
|
|
60
|
+
{% endblock %}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
{% set active_page = "login" %}
|
|
3
|
+
|
|
4
|
+
{% block title %}{% trans "page title" %}Log in{% endtrans %} | LibreQDA{% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block contents %}
|
|
7
|
+
<!-- Tab selector -->
|
|
8
|
+
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
|
9
|
+
<li class="nav-item">
|
|
10
|
+
<a class="nav-link{% if not register %} show active{% endif %}" id="log-in-tab" data-bs-toggle="tab" href="#log-in" role="tab" aria-controls="log-in" aria-selected="{% if not register %}true{% else %}false{% endif %}">{% trans "tab" %}Log in{% endtrans %}</a>
|
|
11
|
+
</li>
|
|
12
|
+
<li class="nav-item">
|
|
13
|
+
<a class="nav-link{% if not register_enabled %} disabled{% endif %}{% if register %} show active{% endif %}" id="register-tab" data-bs-toggle="tab" href="#register" role="tab" aria-controls="register-tab" aria-selected="{% if register %}true{% else %}false{% endif %}">{% trans "tab" %}Register{% endtrans %}</a>
|
|
14
|
+
</li>
|
|
15
|
+
</ul>
|
|
16
|
+
|
|
17
|
+
<div class="tab-content" id="myTabContent">
|
|
18
|
+
|
|
19
|
+
<div class="tab-pane fade{% if not register %} show active{% endif %}" id="log-in" role="tabpanel" aria-labelledby="log-in-tab">
|
|
20
|
+
<form action="{{ reverse_url('login') }}" method="post">
|
|
21
|
+
{{ xsrf_form_html() }}
|
|
22
|
+
{% if login_error %}
|
|
23
|
+
<div class="alert alert-danger" role="alert">
|
|
24
|
+
{{ login_error }}
|
|
25
|
+
</div>
|
|
26
|
+
{% endif %}
|
|
27
|
+
<input type="hidden" name="next" value="{{ next }}" />
|
|
28
|
+
<div class="form-group row">
|
|
29
|
+
<label for="log-in-login" class="col-sm-2 col-form-label">{% trans "form label for user name" %}Login{% endtrans %}</label>
|
|
30
|
+
<div class="col-sm-10">
|
|
31
|
+
<input type="text" class="form-control" id="log-in-login" name="login" required autocomplete="username" />
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
<div class="form-group row">
|
|
35
|
+
<label for="log-in-password" class="col-sm-2 col-form-label">{% trans "form label" %}Password{% endtrans %}</label>
|
|
36
|
+
<div class="col-sm-10">
|
|
37
|
+
<input type="password" class="form-control" id="log-in-password" name="password" required autocomplete="current-password" />
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
<div class="form-group row">
|
|
41
|
+
<div class="col-sm-10 offset-sm-2">
|
|
42
|
+
<button type="submit" name="log-in" class="btn btn-primary" data-test-id="log-in-button">{% trans "form submit button" %}Log in{% endtrans %}</button>
|
|
43
|
+
<a href="{{ reverse_url('reset_password') }}" class="btn btn-outline-secondary">{% trans "form link" %}Forgot password{% endtrans %}</a>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</form>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
{% if register_enabled %}
|
|
50
|
+
<div class="tab-pane fade{% if register %} show active{% endif %}" id="register" role="tabpanel" aria-labelledby="register-tab">
|
|
51
|
+
<form action="{{ reverse_url('register') }}" method="post" class="needs-validation">
|
|
52
|
+
{{ xsrf_form_html() }}
|
|
53
|
+
{% if register_error %}
|
|
54
|
+
<div class="alert alert-danger" role="alert">
|
|
55
|
+
{{ register_error }}
|
|
56
|
+
</div>
|
|
57
|
+
{% endif %}
|
|
58
|
+
<input type="hidden" name="next" value="{{ next }}" />
|
|
59
|
+
<div class="form-group row">
|
|
60
|
+
<label for="register-login" class="col-sm-2 col-form-label">{% trans "form label for user name" %}Login{% endtrans %}</label>
|
|
61
|
+
<div class="col-sm-10">
|
|
62
|
+
<input type="text" class="form-control" id="register-login" name="login" required maxlength="20" pattern="[A-Za-z0-9._\-]{1,20}" title="letters, numbers, dot, underscore, and dashes" autocomplete="username" />
|
|
63
|
+
<small>{% trans %}Please use only letters, numbers, dot, underscore, and dashes (._-){% endtrans %}</small>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="form-group row">
|
|
67
|
+
<label for="register-password1" class="col-sm-2 col-form-label">{% trans "form label" %}Password{% endtrans %}</label>
|
|
68
|
+
<div class="col-sm-10">
|
|
69
|
+
<input type="password" class="form-control" id="register-password1" name="password1" required autocomplete="new-password" minlength="5" maxlength="5120" />
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
<div class="form-group row">
|
|
73
|
+
<label for="register-password2" class="col-sm-2 col-form-label">{% trans "form label" %}Confirm password{% endtrans %}</label>
|
|
74
|
+
<div class="col-sm-10">
|
|
75
|
+
<input type="password" class="form-control" id="register-password2" name="password2" required autocomplete="new-password" minlength="5" maxlength="5120" />
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="form-group row">
|
|
79
|
+
<label for="register-email" class="col-sm-2 col-form-label">{% trans "form label for email address" %}Email{% endtrans %}</label>
|
|
80
|
+
<div class="col-sm-10">
|
|
81
|
+
<input type="email" class="form-control" id="register-email" name="email" autocomplete="email" />
|
|
82
|
+
<small>{% trans %}Optional. <em>We will not share your email with anyone. This is only used in case you forget your password.</em>{% endtrans %}</small>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
{% if tos %}
|
|
86
|
+
<div class="form-group row">
|
|
87
|
+
<label for="register-tos" class="col-sm-2 col-form-label">{% trans "link from registration form" %}Terms of service{% endtrans %}</label>
|
|
88
|
+
<div class="col-sm-10">
|
|
89
|
+
<div class="form-check form-check-inline">
|
|
90
|
+
<input class="form-check-input" type="checkbox" id="register-tos" name="tos" value="accepted" required>
|
|
91
|
+
<label class="form-check-label" for="register-tos">{% trans url=reverse_url('tos') %}I accept the <a href="{{ url }}">terms of service</a>{% endtrans %}</label>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
{% endif %}
|
|
96
|
+
<div class="form-group row">
|
|
97
|
+
<div class="col-sm-10 offset-sm-2">
|
|
98
|
+
<button type="submit" name="register" class="btn btn-primary" data-test-id="register-button">{% trans "form submit button" %}Register{% endtrans %}</button>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</form>
|
|
102
|
+
</div>
|
|
103
|
+
{% endif %}
|
|
104
|
+
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<script type="text/javascript">
|
|
108
|
+
// Adapted from https://stackoverflow.com/a/10787789
|
|
109
|
+
window.addEventListener('load', function() {
|
|
110
|
+
// Change URI for tabs
|
|
111
|
+
$('#log-in-tab').on('shown.bs.tab', function(e) {
|
|
112
|
+
window.history.pushState({'tab': 'log-in'}, "Log in", base_path + '/login');
|
|
113
|
+
});
|
|
114
|
+
$('#register-tab').on('shown.bs.tab', function(e) {
|
|
115
|
+
window.history.pushState({'tab': 'register'}, "Register", base_path + '/register');
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
window.onpopstate = function(e) {
|
|
119
|
+
if(e.state) {
|
|
120
|
+
if(e.state.tab !== undefined) {
|
|
121
|
+
$('.nav-tabs a[href="#' + e.state.tab + '"]').tab('show');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
</script>
|
|
127
|
+
<script>
|
|
128
|
+
// From bootstrap docs
|
|
129
|
+
window.addEventListener('load', function() {
|
|
130
|
+
// Fetch all the forms we want to apply custom Bootstrap validation styles to
|
|
131
|
+
var forms = document.getElementsByClassName('needs-validation');
|
|
132
|
+
// Loop over them and prevent submission
|
|
133
|
+
var validation = Array.prototype.filter.call(forms, function(form) {
|
|
134
|
+
form.addEventListener('submit', function(event) {
|
|
135
|
+
if(form.checkValidity() === false) {
|
|
136
|
+
event.preventDefault();
|
|
137
|
+
event.stopPropagation();
|
|
138
|
+
}
|
|
139
|
+
form.classList.add('was-validated');
|
|
140
|
+
}, false);
|
|
141
|
+
});
|
|
142
|
+
}, false);
|
|
143
|
+
</script>
|
|
144
|
+
{% endblock %}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}{% trans "page title" %}Reset password{% endtrans %} | LibreQDA{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block contents %}
|
|
6
|
+
{% if message %}
|
|
7
|
+
<div class="alert alert-secondary">{{ message }}</div>
|
|
8
|
+
{% endif %}
|
|
9
|
+
{% if error %}
|
|
10
|
+
<div class="alert alert-danger">{{ error }}</div>
|
|
11
|
+
{% endif %}
|
|
12
|
+
|
|
13
|
+
<p>{% trans %}If you had set an email address in your profile, you can enter it below and a link to reset your password will be sent to you.{% endtrans %}</p>
|
|
14
|
+
<form action="{{ reverse_url('reset_password') }}" method="post">
|
|
15
|
+
{{ xsrf_form_html() }}
|
|
16
|
+
<div class="form-group row">
|
|
17
|
+
<label for="email" class="col-sm-2 col-form-label">{% trans "form label for email address" %}Email{% endtrans %}</label>
|
|
18
|
+
<div class="col-sm-8">
|
|
19
|
+
<input type="text" class="form-control" id="email" name="email" required />
|
|
20
|
+
</div>
|
|
21
|
+
<div class="col-sm-2">
|
|
22
|
+
<button type="submit" class="btn btn-primary">{% trans "password reset form submit button" %}Send{% endtrans %}</button>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</form>
|
|
26
|
+
<p>{% trans %}If you didn't set an email address, you can try contacting your server administrator.{% endtrans %}</p>
|
|
27
|
+
{% endblock %}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}{% trans "page title" %}Error{% endtrans %} | LibreQDA{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block contents %}
|
|
6
|
+
<p>{% trans %}Your browser did not supply a secret token to authenticate with the application. Please check the console for the correct URL to log in, or simply restart Taguette.{% endtrans %}</p>
|
|
7
|
+
{% endblock %}
|