tg-prepare 1.1.0__py3-none-any.whl → 2.1.0b2__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 tg-prepare might be problematic. Click here for more details.

Files changed (70) hide show
  1. {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/METADATA +3 -3
  2. tg_prepare-2.1.0b2.dist-info/RECORD +78 -0
  3. {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/WHEEL +1 -1
  4. tg_prepare-2.1.0b2.dist-info/projects/.secret_key +1 -0
  5. tgp_backend/__init__.py +3 -4
  6. tgp_backend/config.py +31 -0
  7. tgp_backend/directories.py +6 -8
  8. tgp_backend/nextcloud.py +40 -19
  9. tgp_backend/project.py +172 -45
  10. tgp_backend/session_manager.py +47 -0
  11. tgp_backend/util.py +73 -25
  12. tgp_ui/app.py +43 -335
  13. tgp_ui/routes/__init__.py +0 -0
  14. tgp_ui/routes/collection.py +272 -0
  15. tgp_ui/routes/data.py +228 -0
  16. tgp_ui/routes/project.py +102 -0
  17. tgp_ui/routes/publication.py +129 -0
  18. tgp_ui/routes/tabs.py +34 -0
  19. tgp_ui/routes/views.py +62 -0
  20. tgp_ui/static/css/bootstrap.min.css.map +1 -0
  21. tgp_ui/static/css/navbar.css +92 -0
  22. tgp_ui/static/img/favicon.ico +0 -0
  23. tgp_ui/static/img/textgrid-logo.svg +1 -0
  24. tgp_ui/static/js/collectionManager.js +60 -0
  25. tgp_ui/static/js/fileManager.js +186 -0
  26. tgp_ui/static/js/main.js +32 -485
  27. tgp_ui/static/js/modalManager.js +105 -0
  28. tgp_ui/static/js/navbarManager.js +151 -0
  29. tgp_ui/static/js/projectManager.js +60 -0
  30. tgp_ui/static/js/require.js +5 -0
  31. tgp_ui/static/js/sidebarManager.js +32 -0
  32. tgp_ui/static/js/tabManager.js +79 -0
  33. tgp_ui/templates/details/empty_container.html +16 -0
  34. tgp_ui/templates/details/manage_collection.html +205 -0
  35. tgp_ui/templates/includes/set_session_id_form.html +16 -0
  36. tgp_ui/templates/includes/upload_form.html +131 -0
  37. tgp_ui/templates/layout.html +9 -48
  38. tgp_ui/templates/macros.html +79 -72
  39. tgp_ui/templates/modal/delete_project.html +25 -0
  40. tgp_ui/templates/modal/empty_container.html +9 -0
  41. tgp_ui/templates/modal/file_explorer_content.html +34 -0
  42. tgp_ui/templates/modal/file_explorer_main.html +22 -0
  43. tgp_ui/templates/modal/file_explorer_nextcloud.html +27 -0
  44. tgp_ui/templates/modal/github_modal.html +29 -0
  45. tgp_ui/templates/modal/nextcloud_login.html +48 -0
  46. tgp_ui/templates/modal/tei_explorer.html +58 -0
  47. tgp_ui/templates/modal/xpath_parser.html +52 -0
  48. tgp_ui/templates/project_main.html +36 -0
  49. tgp_ui/templates/project_navbar.html +81 -0
  50. tgp_ui/templates/{projects.html → projects_main.html} +13 -28
  51. tgp_ui/templates/tab_final_upload.html +29 -0
  52. tgp_ui/templates/tabs/check_result.html +90 -0
  53. tgp_ui/templates/tabs/edit_project.html +113 -0
  54. tgp_ui/templates/tabs/empty_container.html +12 -0
  55. tgp_ui/templates/tabs/import_data.html +138 -0
  56. tgp_ui/templates/tabs/manage_collections.html +88 -0
  57. tgp_ui/templates/tabs/select_directories.html +41 -0
  58. tgp_ui/templates/tabs/upload.html +42 -0
  59. tgp_ui/templates/tabs/validate_metadata.html +227 -0
  60. tg_prepare-1.1.0.dist-info/RECORD +0 -39
  61. tgp_ui/templates/collection.html +0 -194
  62. tgp_ui/templates/file_upload.html +0 -24
  63. tgp_ui/templates/nxc_file_tree.html +0 -33
  64. tgp_ui/templates/project.html +0 -26
  65. tgp_ui/templates/storage.html +0 -49
  66. tgp_ui/templates/tei_explorer.html +0 -48
  67. tgp_ui/templates/xpath_parser_modal_content.html +0 -37
  68. {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/entry_points.txt +0 -0
  69. {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/licenses/LICENSE +0 -0
  70. {tg_prepare-1.1.0.dist-info → tg_prepare-2.1.0b2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,138 @@
1
+ <!DOCTYPE html>
2
+ {% macro file_upload_form(button_size='btn-sm') %}
3
+ <form action="{{ url_for('data.upload_files', projectname=project.name) }}" method="POST" enctype="multipart/form-data"
4
+ class="d-inline js-tab-submit" id="fileUploadLocal">
5
+ <input type="file" id="fileInput" name="files" multiple webkitdirectory class="d-none">
6
+ <button type="button" class="btn {{ button_size }} btn-outline-primary" id="triggerFileInput">
7
+ <i class="bi bi-folder-plus"></i> Local Files
8
+ </button>
9
+
10
+ </form>
11
+ {% endmacro %}
12
+
13
+ {% block content %}
14
+ {% set has_files = project.list_files_and_folders()|length > 0 %}
15
+ <div class="container py-4">
16
+ <div class="row">
17
+ <!-- Form Title -->
18
+ <div class="col-12 text-center mb-4">
19
+ <h1 class="fs-3 fw-bold">Upload Data</h1>
20
+ <p class="text-muted">Import directories containing your TEI files.</p>
21
+ {% if error_message %}
22
+ <div class="alert alert-danger" role="alert">
23
+ {{ error_message }}
24
+ </div>
25
+ {% endif %}
26
+ </div>
27
+ <div class="col-12">
28
+ {% if has_files %}
29
+ <!-- File display card when files exist -->
30
+ <div class="card">
31
+ <!-- Card header with title and upload buttons -->
32
+ <div class="card-header d-flex justify-content-between align-items-center">
33
+ <!-- Left side: Drop zone -->
34
+ <div data-url="{{ url_for('data.upload_files', projectname=project.name) }}"
35
+ class="border border-secondary rounded-3 js-file-upload btn btn-sm text-secondary">
36
+ <i class="bi bi-plus-lg"></i> Drop files here
37
+ </div>
38
+
39
+ <!-- Right side: Action buttons -->
40
+ <div class="btn-group">
41
+ <!-- Upload option buttons -->
42
+ {{ file_upload_form('btn-sm') }}
43
+ <button class="load-modal btn btn-sm btn-outline-dark"
44
+ data-url="{{ url_for('data.modal_github', projectname=project.name) }}">
45
+ <i class=" bi bi-github"></i> GitHub
46
+ </button>
47
+ <button class="load-modal btn btn-sm btn-outline-dark"
48
+ data-url="{{ url_for('data.modal_nextcloud', projectname=project.name) }}">
49
+ <i class="bi bi-cloud-plus"></i> Nextcloud
50
+ </button>
51
+ </div>
52
+ </div>
53
+ <!-- List of files and folders -->
54
+ <div class="list-group list-group-flush">
55
+ {% for item in project.list_files_and_folders() %}
56
+ <div class="list-group-item list-group-item-action d-flex align-items-center">
57
+ <!-- Different display for folders and files -->
58
+ {% if item.type == 'folder' %}
59
+ <button
60
+ class="btn btn-link text-decoration-none text-dark p-0 d-flex align-items-center flex-grow-1"
61
+ data-bs-toggle="modal" data-bs-target="#folderModal{{ loop.index }}">
62
+ <i class="bi bi-folder-fill text-warning me-2"></i>
63
+ <span>{{ item.name }}</span>
64
+ </button>
65
+ {% else %}
66
+ <i class="bi bi-file-text me-2"></i>
67
+ <span class="flex-grow-1">{{ item.name }}</span>
68
+ {% endif %}
69
+
70
+ <!-- Action buttons for each item -->
71
+ <div class="btn-group">
72
+ <button class="btn btn-sm btn-outline-danger delete-folder" data-item-path="{{ item.path }}"
73
+ data-item-name="{{ item.name }}" data-projectname="{{ project.name }}"
74
+ data-item-type="{{ item.type }}">
75
+ <i class="bi bi-trash"></i>
76
+ </button>
77
+ </div>
78
+ </div>
79
+ {% endfor %}
80
+ </div>
81
+
82
+ <!-- Folder modals - rendered at the end of file -->
83
+ {% for item in project.list_files_and_folders() %}
84
+ {% if item.type == 'folder' %}
85
+ {% with folder=item, index=loop.index %}
86
+ {% include 'modal/file_explorer_main.html' %}
87
+ {% endwith %}
88
+ {% endif %}
89
+ {% endfor %}
90
+
91
+ </div>
92
+ {% else %}
93
+ <!-- Welcome screen shown when no files exist -->
94
+ <div class="row min-vh-50 align-items-center justify-content-center">
95
+ <div class="col-12 text-center">
96
+ <div class="card border-0 bg-transparent">
97
+ <div class="card-body">
98
+ <div class="btn-group">
99
+ {{ file_upload_form('btn-lg') }}
100
+ <button class="load-modal btn btn-lg btn-outline-dark"
101
+ data-url="{{ url_for('data.modal_github', projectname=project.name) }}">
102
+ <i class="bi bi-github"></i> GitHub
103
+ </button>
104
+ <button class="load-modal btn btn-lg btn-outline-dark"
105
+ data-url="{{ url_for('data.modal_nextcloud', projectname=project.name) }}">
106
+ <i class="bi bi-cloud-plus"></i> Nextcloud
107
+ </button>
108
+ </div>
109
+ <p class="text-muted m-4">or</p>
110
+
111
+ <div class="row justify-content-center">
112
+ <div class="col-5 text-center">
113
+ <div data-url="{{ url_for('data.upload_files', projectname=project.name) }}" class="js-file-upload p-5 bg-white text-secondary border border-2 rounded-3 d-flex flex-column
114
+ align-items-center justify-content-center">
115
+ <i class="fs-1 bi bi-arrow-down-circle"></i>
116
+ <h4 class="mt-2 fw-bold">Drag and Drop files</h4>
117
+ </div>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ {% endif %}
125
+ </div>
126
+ <div class=" row mt-4">
127
+ <div class="col-12 text-end">
128
+ <button type="button" class="btn btn-primary btn-next" data-next-target="#tab-select-directories"
129
+ data-additional-button="#tab-group-collections">
130
+ <i class="bi bi-chevron-right"></i> Next
131
+ </button>
132
+ </div>
133
+ </div>
134
+ </div>
135
+
136
+ <!-- Modal definitions -->
137
+
138
+ {% endblock %}
@@ -0,0 +1,88 @@
1
+ <!-- Main container with padding -->
2
+ <div class="container py-4">
3
+ <div class="row">
4
+ <!-- Page Title -->
5
+ <div class="col-12 text-center mb-4">
6
+ <h1 class="fs-3 fw-bold">Manage Collections & Metadata</h1>
7
+ </div>
8
+
9
+ <!-- Main Content Area -->
10
+ <div class="row">
11
+ <!-- Left Column - Collections List -->
12
+ <div class="col-md-3">
13
+ <div class="card border-0 shadow-sm">
14
+ <div class="card-header bg-light">
15
+ <h5 class="card-title mb-0">Collections</h5>
16
+ </div>
17
+ <div class="card-body m-0">
18
+ <!-- Dynamic Collections List -->
19
+ <div class="row g-3">
20
+ <!-- Loop through available collections -->
21
+ {% if project.collections %}
22
+ {% for _collection in project.collections %}
23
+ {% set collection = project.collections[_collection] %}
24
+ <!-- Collection Row -->
25
+ <div class="col-12">
26
+ <div class="row">
27
+ <div class="col-12">
28
+ <button
29
+ class="btn btn-secondary btn-outline-secondary text-white w-100 text-start edit-collection-button text-truncate"
30
+ style="height: 50px;"
31
+ data-url="{{ url_for('collection.load_collection', projectname=project.path, collectionname=_collection) }}">
32
+ <span class="overflow-hidden">
33
+ {{ collection.config.title.short }}
34
+ </span>
35
+ </button>
36
+ </div>
37
+ <div class="col-12 mt-2">
38
+ <div class="row g-2">
39
+ <div class="col-auto">
40
+ <button class="btn btn-sm btn-outline-secondary load-modal"
41
+ title="Open XPath Parser"
42
+ data-url="{{ url_for('collection.modal_xpath_parser', projectname=project.path, collectionname=_collection) }}">
43
+ XPath Parser
44
+ </button>
45
+ </div>
46
+ <div class="col-auto">
47
+ <button class="btn btn-sm btn-outline-secondary load-modal"
48
+ title="Open TEI Explorer"
49
+ data-url="{{ url_for('collection.modal_tei_explorer', projectname=project.path, collectionname=_collection) }}">
50
+ TEI Explorer
51
+ </button>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ {% endfor %}
58
+ {% else %}
59
+ <!-- Message for no collections -->
60
+ <div class="col-12">
61
+ <p class="text-center text-muted">No collections available.</p>
62
+ </div>
63
+ {% endif %}
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </div>
68
+
69
+ <!-- Right Column - Collection Details -->
70
+ <div class="col-md-9">
71
+ <div class="card border-0 shadow-sm">
72
+ <div class="card-header bg-light">
73
+ <h5 class="card-title mb-0">Details</h5>
74
+ </div>
75
+ <!-- Details Content Area -->
76
+ {% include 'details/empty_container.html' %}
77
+ </div>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ <div class="row mt-4">
82
+ <div class="col-12 text-end">
83
+ <button type="button" class="btn btn-primary btn-next" data-next-target="#tab-check-metadata">
84
+ <i class="bi bi-chevron-right"></i> Next
85
+ </button>
86
+ </div>
87
+ </div>
88
+ </div>
@@ -0,0 +1,41 @@
1
+ <div class="container py-4">
2
+ <div class="row">
3
+ <!-- Form Title -->
4
+ <div class="col-12 text-center mb-4">
5
+ <h1 class="fs-3 fw-bold">Collection(s) - Select Data</h1>
6
+ <p class="text-muted">Choose folders containing TEI/XML documents.</p>
7
+ </div>
8
+
9
+ <form class="js-tab-submit" method="POST"
10
+ action="{{ url_for('collection.tab_select_directories', projectname=project.path) }}"
11
+ data-next-target="#tab-set-collections">
12
+ <div class="row">
13
+ {% for folder in project.get_selectable_folders() %}
14
+ <div class="col-md-4 mb-3">
15
+ <div class="card {{ 'border-primary' if folder.path
16
+ in selected_directories else 'border-secondary' }}">
17
+ <div class="card-body">
18
+ <h5 class="card-title">{{ folder.name }}</h5>
19
+ <p class="card-text text-muted">{{ folder.relative_path }}</p>
20
+ <div class="form-check">
21
+ <input class="form-check-input" type="checkbox" name="selected_folder"
22
+ value="{{ folder.path }}" id="folder-{{ loop.index }}" {{ 'checked' if folder.path
23
+ in selected_directories else '' }}>
24
+ <label class="form-check-label" for="folder-{{ loop.index }}">
25
+ Select this folder
26
+ </label>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ {% endfor %}
32
+ </div>
33
+ <div class="mt-4 text-end">
34
+ <button type="submit" class="btn btn-primary">
35
+ <i class="bi bi-chevron-right"></i>
36
+ <span>Next</span>
37
+ </button>
38
+ </div>
39
+ </form>
40
+ </div>
41
+ </div>
@@ -0,0 +1,42 @@
1
+ <!DOCTYPE html>
2
+ <div class="container py-4">
3
+ <div class="row">
4
+ <!-- Page Title -->
5
+ <div class="col-12 text-center mb-4">
6
+ <h1 class="fs-3 fw-bold">Upload Project</h1>
7
+ </div>
8
+ <!-- Instanzauswahl -->
9
+ <div class="col-12 mb-4">
10
+ <h4 class="text-center mb-3">Choose the instance:</h4>
11
+ <ul class="nav nav-tabs justify-content-center" id="instanceTabs" role="tablist">
12
+ <li class="nav-item" role="presentation">
13
+ <button class="nav-link active" id="test-tab" data-bs-toggle="tab" data-bs-target="#test-pane"
14
+ type="button" role="tab" aria-controls="test-pane" aria-selected="true">
15
+ Test
16
+ </button>
17
+ </li>
18
+ <li class="nav-item" role="presentation">
19
+ <button class="nav-link" id="prod-tab" data-bs-toggle="tab" data-bs-target="#prod-pane"
20
+ type="button" role="tab" aria-controls="prod-pane" aria-selected="false">
21
+ Live
22
+ </button>
23
+ </li>
24
+ </ul>
25
+ </div>
26
+
27
+ <!-- Tab-Inhalte -->
28
+ <div class="tab-content">
29
+ <!-- Testinstanz -->
30
+ <div class="tab-pane fade show active" id="test-pane" role="tabpanel" aria-labelledby="test-tab">
31
+ {% set instance='test' %}
32
+ {% include 'includes/upload_form.html' %}
33
+ </div>
34
+
35
+ <!-- Produktionsinstanz -->
36
+ <div class="tab-pane fade" id="prod-pane" role="tabpanel" aria-labelledby="prod-tab">
37
+ {% set instance='live' %}
38
+ {% include 'includes/upload_form.html' %}
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </div>
@@ -0,0 +1,227 @@
1
+ <!DOCTYPE html>
2
+ <div class="container py-4">
3
+ <!-- Form Title -->
4
+ <div class="col-12 text-center mb-4">
5
+ <h1 class="fs-3 fw-bold">Validation</h1>
6
+ <strong>Last validation run:</strong> {{ validation_results.last_run }}
7
+ </div>
8
+ <!-- Refresh Button -->
9
+ <div class="row mb-4">
10
+ <div class="col-12 text-center">
11
+ <form class="d-inline-block js-tab-submit"
12
+ action="{{ url_for('collection.tab_validate_metadata', projectname=projectname, refresh=True) }}"
13
+ method="GET">
14
+ <button type="submit" class="btn btn-lg btn-primary d-flex align-items-center justify-content-center">
15
+ <i class="bi bi-arrow-clockwise me-2"></i> Refresh Validation
16
+ </button>
17
+ </form>
18
+ </div>
19
+ </div>
20
+
21
+ {% set is_ready = validation_results.ready_for_publication %}
22
+
23
+ <!-- Validation Results -->
24
+ <div class="row">
25
+ <!-- General Validation Results -->
26
+ <div class="col-md-6 mb-4 mb-lg-0">
27
+ <div class="bg-light rounded px-2 h-100">
28
+ <h2 class="fs-4 mb-3">Project Validation</h2>
29
+ <ul class="list-group">
30
+ <!-- OK Results -->
31
+ {% for message in validation_results.project.ok %}
32
+ <li class="list-group-item d-flex align-items-center">
33
+ <i class="bi bi-check-circle-fill text-success me-2"></i>
34
+ {{ message }}
35
+ </li>
36
+ {% endfor %}
37
+
38
+ <!-- Warnings -->
39
+ {% for message in validation_results.project.warning %}
40
+ <li class="list-group-item d-flex align-items-center">
41
+ <i class="bi bi-exclamation-triangle-fill text-warning me-2"></i>
42
+ {{ message }}
43
+ </li>
44
+ {% endfor %}
45
+
46
+ <!-- Errors -->
47
+ {% for message in validation_results.project.error %}
48
+ <li class="list-group-item d-flex align-items-center">
49
+ <i class="bi bi-x-circle-fill text-danger me-2"></i>
50
+ {{ message }}
51
+ </li>
52
+ {% endfor %}
53
+ </ul>
54
+ <div class="d-flex justify-content-end mt-3">
55
+ <button type="button" class="btn btn-sm btn-primary btn-next" data-next-target="#tab-edit-project"
56
+ data-additional-button="#tab-group-project">
57
+ <i class="bi bi-chevron-right"></i> Go To Project Settings
58
+ </button>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ <div class="col-md-6 mb-4 mb-lg-0">
63
+ <div class="bg-light rounded px-2 h-100 d-flex flex-column align-items-center justify-content-center">
64
+ <h2 class="fs-4 mb-4">Overall Status</h2>
65
+
66
+ <div class="d-flex flex-column align-items-center">
67
+
68
+ {% if is_ready %}
69
+ <div class="text-center mb-4">
70
+ <img src="{{ url_for('static', filename='img/owl_super.png') }}" alt="Ready for publication"
71
+ height="120">
72
+ </div>
73
+ <button class="badge bg-success p-3 mb-3 border-0 btn-next" style="font-size: 1.25rem;"
74
+ data-next-target="#tab-prepare-upload" data-additional-button="#tab-group-upload">
75
+ <i class="bi bi-check-circle-fill me-2"></i>
76
+ Ready for Upload & Publication
77
+ </button>
78
+ <div class="alert alert-success mt-4">
79
+ <i class="bi bi-check-circle-fill me-2"></i>
80
+ <strong>All requirements fulfilled!</strong> Your project is ready for upload & publication.
81
+ </div>
82
+
83
+ {% if validation_results.project.warning %}
84
+ <div class="alert alert-warning">
85
+ <i class="bi bi-exclamation-triangle-fill me-2"></i>
86
+ Some <strong>Warnings</strong> still occur, but they do not prevent upload & publication.
87
+ </div>
88
+ {% endif %}
89
+
90
+ {% else %}
91
+ <div class="text-center mb-4">
92
+ <img src="{{ url_for('static', filename='img/owl_book.png') }}" alt="Not ready for publication"
93
+ height="120">
94
+ </div>
95
+ <div class="badge bg-danger p-3 mb-3" style="font-size: 1.25rem;">
96
+ <i class="bi bi-x-circle-fill me-2"></i>
97
+ Not Ready for Publication
98
+ </div>
99
+ <div class="alert alert-warning mt-4">
100
+ <i class="bi bi-exclamation-triangle-fill me-2"></i>
101
+ <strong>Required actions:</strong> Please fix the validation errors before proceeding to
102
+ publication.
103
+ </div>
104
+ {% endif %}
105
+ </div>
106
+ </div>
107
+ </div>
108
+
109
+ <!-- Subproject Validation Results -->
110
+ <div class="col-12">
111
+ <div class="bg-light rounded p-1 h-100">
112
+ <h2 class="fs-4 mb-2">Validation of Collection{{ 's' if len(subprojects) > 1 else '' }}</h2>
113
+
114
+ <!-- Accordion for Subproject Details -->
115
+ <div class="accordion" id="subprojectAccordion">
116
+ {% for subproject in validation_results.subprojects %}
117
+ <div class="card mb-3">
118
+ <!-- Card Header -->
119
+ <div class="card-header d-flex justify-content-between align-items-center"
120
+ id="heading-{{ loop.index }}">
121
+ <h5 class="mb-0">
122
+ <button class="btn btn-link text-decoration-none" type="button"
123
+ data-bs-toggle="collapse" data-bs-target="#collapse-{{ loop.index }}"
124
+ aria-expanded="true" aria-controls="collapse-{{ loop.index }}">
125
+ {{ subproject.title }}
126
+ </button>
127
+ </h5>
128
+ <div class="d-flex align-items-center">
129
+ <!-- CSV Export Button -->
130
+ <a href="{{ url_for('collection.export_tsv', projectname=projectname, collectionname=subproject.title) }}"
131
+ class="btn btn-sm btn-outline-secondary me-3"
132
+ title="Export validation results as CSV">
133
+ <i class="bi bi-filetype-csv me-1"></i> Export TSV
134
+ </a>
135
+
136
+ <!-- Statistics -->
137
+ {% set stats = subproject.stats %}
138
+ <div>
139
+ <span
140
+ class="badge bg-{{'success' if stats['success'] else 'secondary'}} me-2">Success:
141
+ {{ stats['success'] }}
142
+ </span>
143
+ <span class="badge bg-{{'danger' if stats['error'] else 'secondary'}}">Failed:
144
+ {{ stats['error'] }}
145
+ </span>
146
+ </div>
147
+ </div>
148
+ </div>
149
+
150
+ <!-- Card Body -->
151
+ <div id="collapse-{{ loop.index }}" class="collapse" aria-labelledby="heading-{{ loop.index }}"
152
+ data-bs-parent="#subprojectAccordion">
153
+ <div class="card-body">
154
+ <table class="table table-bordered table-hover">
155
+ <thead class="table-light">
156
+ <tr>
157
+ <th>File</th>
158
+ <th>Status</th>
159
+ <th>Details</th>
160
+ </tr>
161
+ </thead>
162
+ <tbody>
163
+ {% for file, errors in subproject.files.items() %}
164
+ <tr>
165
+ <!-- File Name -->
166
+ <td>{{ file }}</td>
167
+
168
+ <!-- Validation Status -->
169
+ <td>
170
+ {% if len(errors) == 0 %}
171
+ <span class="badge bg-success">Success</span>
172
+ {% else %}
173
+ <span class="badge bg-danger">Failed</span>
174
+ {% endif %}
175
+ </td>
176
+
177
+ <!-- Validation Details -->
178
+ <td>
179
+ {% if len(errors) > 0 %}
180
+ {% set file_stripped = file.split('.')[0] %}
181
+ <button class="btn btn-sm btn-outline-danger" type="button"
182
+ data-bs-toggle="collapse"
183
+ data-bs-target="#errors-{{ loop.index }}-{{ file_stripped }}"
184
+ aria-expanded="false"
185
+ aria-controls="errors-{{ loop.index }}-{{ file_stripped }}">
186
+ View Errors
187
+ </button>
188
+ <div class="collapse mt-2"
189
+ id="errors-{{ loop.index }}-{{ file_stripped }}">
190
+ <ul class="list-unstyled mb-0">
191
+ {% for error in errors %}
192
+ <li class="text-danger">
193
+ <i class="bi bi-x-circle-fill me-1"></i>{{ error }}
194
+ </li>
195
+ {% endfor %}
196
+ </ul>
197
+ </div>
198
+ {% else %}
199
+ <span class="text-muted">No errors</span>
200
+ {% endif %}
201
+ </td>
202
+ </tr>
203
+ {% endfor %}
204
+ </tbody>
205
+ </table>
206
+ </div>
207
+ </div>
208
+ </div>
209
+ {% endfor %}
210
+ </div>
211
+ </div>
212
+ </div>
213
+ </div>
214
+ <div class="row">
215
+ <div class="col-12 d-flex justify-content-between">
216
+ <button type="button" class="btn btn-primary btn-next" data-next-target="#tab-set-collections">
217
+ <i class="bi bi-chevron-left"></i> Back
218
+ </button>
219
+ {% if is_ready %}
220
+ <button type="button" class="btn btn-primary btn-next" data-next-target="#tab-prepare-upload"
221
+ data-additional-button="#tab-group-upload">
222
+ Next <i class="bi bi-chevron-right"></i>
223
+ </button>
224
+ {% endif %}
225
+ </div>
226
+ </div>
227
+ </div>
@@ -1,39 +0,0 @@
1
- tg_prepare-1.1.0.dist-info/licenses/LICENSE,sha256=deYu6g1OGKm0VUwhM4Octoh8qlzjsiHHxoI-KkCBVBE,11351
2
- tgp_backend/__init__.py,sha256=4Q_pjhWDF2eAyPa8bvgIcBIrV0qGKa3uYgvYqTCmKWs,419
3
- tgp_backend/auth.py,sha256=hUPd0rc01BTT003xpkdmhNc6o0JztbAdimyDb0B9oTQ,2293
4
- tgp_backend/cli.py,sha256=iw_gknn-_m_UFZZUKfkV9aJixG3sVcHIONybNtOG40I,551
5
- tgp_backend/directories.py,sha256=5w7FeEa0zcW4B_rkM0bLlaKdWUPrvtremlkgcU5W6dA,2385
6
- tgp_backend/interfaces.py,sha256=SO7mOdhkd1f7irUBrwFhp5aKx3UKkkUzU9QBYDl0Tvc,91
7
- tgp_backend/nextcloud.py,sha256=9p-YT-oN05seWo2zwnfHSbvVa4Am7qONczfR6Fx8pqM,4424
8
- tgp_backend/project.py,sha256=Lsxvy8DTalHqgTkyZmja7nb7icdUinp0KY9DuEVqEmo,8908
9
- tgp_backend/tgclient.py,sha256=QG2iFPrv2qLL4FRXoEfXzEMJriroiIaNL9rkreGtzuQ,2961
10
- tgp_backend/util.py,sha256=PsRO7CGhHZjGubkM39KDuTwJwyfq_Gs7HM-n0DFlIZc,2210
11
- tgp_ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- tgp_ui/app.py,sha256=cso4-T7a4uGgvVaMcFpqMT8to26c-7ASCOiVXVYIaGM,12252
13
- tgp_ui/static/css/bootstrap-icons.min.css,sha256=XxUvYRPQvG4RTCkukUmXwvf1N0YF9KQ_ocuWV6O1dk8,85797
14
- tgp_ui/static/css/bootstrap.min.css,sha256=djO3wMl9GeaC_u6K-ic4Uj_LKhRUSlUFcsruzS7v5ms,155845
15
- tgp_ui/static/css/main.css,sha256=EK8euwgxX8I3qsBiDmIvj8UBIxkSKQZz1mo_OX4Q1FQ,2641
16
- tgp_ui/static/css/simpleXML.css,sha256=dfY7UZCiC79BkNOT1hM0GQ6v_yLSxhKCnmV0RZIT9S8,961
17
- tgp_ui/static/js/bootstrap.bundle.min.js,sha256=fh8VA992XMpeCZiRuU4xii75UIG6KvHrbUF8yIS_2_4,78743
18
- tgp_ui/static/js/jquery.min.js,sha256=_xUj-3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej_m4,89501
19
- tgp_ui/static/js/main.js,sha256=mTrA94R8ZeBYaFPs4NtIdTZ1RKdRnFjwqaIKdB7UW8k,17169
20
- tgp_ui/static/js/simpleXML.js,sha256=jEkZe3TuiHuEt6V7If_1EmqYIgTywssJ3OwOQzOFYNg,8065
21
- tgp_ui/templates/collection.html,sha256=WnYAH_5kJ6CzvVIqGk8XU_TZmhIrcOXggBoImyuGVZE,11416
22
- tgp_ui/templates/file_tree.html,sha256=IKWp5MLUvnFF65cIUIxU4Jf5wi9Fg8koSXD96Mk328E,1640
23
- tgp_ui/templates/file_upload.html,sha256=fIelltVaTnqUqxBZoMy859IWbuwqNjrDZbVh9JlYl-g,1004
24
- tgp_ui/templates/layout.html,sha256=eB80fnfUw8q_PEO6wY8eefjnRUbqwZEbHCFAK8ccQaY,5026
25
- tgp_ui/templates/macros.html,sha256=zpbduAoTNj5OD2o_9z1IY6pPm_KX8kSOSWWN264kWB4,4253
26
- tgp_ui/templates/nxc_file_tree.html,sha256=i8nLf71c9vUyAP46eC6BdJJVXgAJcJd4xcIv7vW6Y9k,1275
27
- tgp_ui/templates/nxc_login.html,sha256=tDxqHYPZqsY2ZNnkn4a5bMOYiD8ybcNRpzSq7MvMWCo,1269
28
- tgp_ui/templates/nxc_tab.html,sha256=9HWCa7UZKxL0fZasT_g6uozI64L-497Y2LppPPTHF2M,517
29
- tgp_ui/templates/project.html,sha256=35oPO8yPMXqJSjtXZrXegrhIqmutECY_nk1ZYPFwAsc,1106
30
- tgp_ui/templates/projects.html,sha256=zUPCTPa129aTwfo-ZpMkhkmQvcO7HPY0TXwAi7MnIOE,3344
31
- tgp_ui/templates/publication.html,sha256=TXCHCE2198cHFmN4_l4JNmq0nQoy8GwnESePjRfjliU,9357
32
- tgp_ui/templates/storage.html,sha256=ZgLIawovCTkgQy7aX3QB0cMlQj4uiby68c8aJFQ_HNw,1985
33
- tgp_ui/templates/tei_explorer.html,sha256=YPLYZcgsqvA2AAL8NQ61Eo1ekwn3FEQf6pB58lLLL8U,2472
34
- tgp_ui/templates/xpath_parser_modal_content.html,sha256=Hm3VNtXbmEUIPFihGnE11AcSRdvMGro73IKjvDJAAqg,1573
35
- tg_prepare-1.1.0.dist-info/METADATA,sha256=tJr1V2ztaQCVSpNpwO4Y9HYN2btX9knxnl7uSnBMmhE,532
36
- tg_prepare-1.1.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
37
- tg_prepare-1.1.0.dist-info/entry_points.txt,sha256=mbsfiEA8_fQdrFUE_oabDi-Syw8jjli37Ms7tawDDhs,78
38
- tg_prepare-1.1.0.dist-info/top_level.txt,sha256=ueOyX_KdozreQJD_HRs6kAsvGNO4vfM9B_QqqhdyRPI,19
39
- tg_prepare-1.1.0.dist-info/RECORD,,