tg-prepare 2.1.0b1__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.
- {tg_prepare-2.1.0b1.dist-info → tg_prepare-2.1.0b2.dist-info}/METADATA +1 -1
- {tg_prepare-2.1.0b1.dist-info → tg_prepare-2.1.0b2.dist-info}/RECORD +31 -7
- tgp_ui/static/css/bootstrap.min.css.map +1 -0
- tgp_ui/static/img/favicon.ico +0 -0
- tgp_ui/static/img/textgrid-logo.svg +1 -0
- tgp_ui/templates/details/empty_container.html +16 -0
- tgp_ui/templates/details/manage_collection.html +205 -0
- tgp_ui/templates/includes/set_session_id_form.html +16 -0
- tgp_ui/templates/includes/upload_form.html +131 -0
- tgp_ui/templates/modal/delete_project.html +25 -0
- tgp_ui/templates/modal/empty_container.html +9 -0
- tgp_ui/templates/modal/file_explorer_content.html +34 -0
- tgp_ui/templates/modal/file_explorer_main.html +22 -0
- tgp_ui/templates/modal/file_explorer_nextcloud.html +27 -0
- tgp_ui/templates/modal/github_modal.html +29 -0
- tgp_ui/templates/modal/nextcloud_login.html +48 -0
- tgp_ui/templates/modal/tei_explorer.html +58 -0
- tgp_ui/templates/modal/xpath_parser.html +52 -0
- tgp_ui/templates/tabs/check_result.html +90 -0
- tgp_ui/templates/tabs/edit_project.html +113 -0
- tgp_ui/templates/tabs/empty_container.html +12 -0
- tgp_ui/templates/tabs/import_data.html +138 -0
- tgp_ui/templates/tabs/manage_collections.html +88 -0
- tgp_ui/templates/tabs/select_directories.html +41 -0
- tgp_ui/templates/tabs/upload.html +42 -0
- tgp_ui/templates/tabs/validate_metadata.html +227 -0
- {tg_prepare-2.1.0b1.dist-info → tg_prepare-2.1.0b2.dist-info}/WHEEL +0 -0
- {tg_prepare-2.1.0b1.dist-info → tg_prepare-2.1.0b2.dist-info}/entry_points.txt +0 -0
- {tg_prepare-2.1.0b1.dist-info → tg_prepare-2.1.0b2.dist-info}/licenses/LICENSE +0 -0
- {tg_prepare-2.1.0b1.dist-info → tg_prepare-2.1.0b2.dist-info}/projects/.secret_key +0 -0
- {tg_prepare-2.1.0b1.dist-info → tg_prepare-2.1.0b2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<!-- Nextcloud Upload Modal -->
|
|
3
|
+
<div class="modal-dialog modal-sm">
|
|
4
|
+
<div class="modal-content">
|
|
5
|
+
<form class="js-modal-submit" action="{{ url_for('data.modal_nextcloud', projectname=projectname) }}"
|
|
6
|
+
method="POST" id="nextcloudUploadForm">
|
|
7
|
+
<div class="modal-header">
|
|
8
|
+
<h5 class="modal-title">Login to Nextcloud</h5>
|
|
9
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="modal-body">
|
|
12
|
+
<div class="mb-3">
|
|
13
|
+
<label for="nextcloudUrl" class="form-label">Endpoint/URL *</label>
|
|
14
|
+
<input type="url" class="form-control" id="nextcloudUrl" name="nextcloud_url"
|
|
15
|
+
placeholder="https://cloud.example.com" required>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="mb-3">
|
|
18
|
+
<label for="nextcloudUser" class="form-label">Username *</label>
|
|
19
|
+
<input type="text" class="form-control" id="nextcloudUser" name="nextcloud_user" required>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="mb-3">
|
|
22
|
+
<label for="nextcloudPassword" class="form-label">Password *</label>
|
|
23
|
+
<input type="password" class="form-control" id="nextcloudPassword" name="nextcloud_password"
|
|
24
|
+
required>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="mb-3">
|
|
27
|
+
<label for="nextcloudFolder" class="form-label">Folder</label>
|
|
28
|
+
<input type="text" class="form-control" id="nextcloudFolder" name="nextcloud_folder"
|
|
29
|
+
placeholder="/path/to/folder">
|
|
30
|
+
</div>
|
|
31
|
+
<div class="alert alert-info" role="alert">
|
|
32
|
+
<small>* Required fields</small>
|
|
33
|
+
</div>
|
|
34
|
+
{% if message %}
|
|
35
|
+
<div class="alert text-center alert-warning" role="alert">
|
|
36
|
+
{{ message }}
|
|
37
|
+
</div>
|
|
38
|
+
{% endif %}
|
|
39
|
+
</div>
|
|
40
|
+
<div class="modal-footer d-flex justify-content-center">
|
|
41
|
+
<button type="submit" class="btn btn-primary">
|
|
42
|
+
<span class="spinner-border spinner-border-sm me-2 d-none" role="status" aria-hidden="true"></span>
|
|
43
|
+
<span>Login</span>
|
|
44
|
+
</button>
|
|
45
|
+
</div>
|
|
46
|
+
</form>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<div class="modal-dialog modal-xl">
|
|
2
|
+
<div class="modal-content">
|
|
3
|
+
<div class="modal-header align-items-center">
|
|
4
|
+
<h5 id="teiExplorerModalLabel" class="mb-0">TEI Explorer</h5>
|
|
5
|
+
<button type="button" class="btn-close ms-auto" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
6
|
+
</div>
|
|
7
|
+
<div class="modal-body">
|
|
8
|
+
<!-- Tabs Navigation -->
|
|
9
|
+
<ul class="nav nav-tabs" id="teiExplorerTabs" role="tablist">
|
|
10
|
+
<li class="nav-item" role="presentation">
|
|
11
|
+
<button class="nav-link active" id="filesTab" data-bs-toggle="tab" data-bs-target="#files"
|
|
12
|
+
type="button" role="tab" aria-controls="files" aria-selected="true">
|
|
13
|
+
TEI Files
|
|
14
|
+
</button>
|
|
15
|
+
</li>
|
|
16
|
+
<li class="nav-item" role="presentation">
|
|
17
|
+
<button class="nav-link" id="contentTab" data-bs-toggle="tab" data-bs-target="#content"
|
|
18
|
+
type="button" role="tab" aria-controls="content" aria-selected="false">
|
|
19
|
+
TEI Content
|
|
20
|
+
</button>
|
|
21
|
+
</li>
|
|
22
|
+
</ul>
|
|
23
|
+
|
|
24
|
+
<!-- Tabs Content -->
|
|
25
|
+
<div class="tab-content" id="teiExplorerTabsContent" style="height: 70vh; overflow-y: auto;">
|
|
26
|
+
<!-- Tab: TEI Files -->
|
|
27
|
+
<div class="tab-pane fade show active" id="files" role="tabpanel" aria-labelledby="filesTab">
|
|
28
|
+
<ul class="list-group">
|
|
29
|
+
{% for file in file_list %}
|
|
30
|
+
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
31
|
+
<span class="text-truncate">{{ file.name_stripped }}</span>
|
|
32
|
+
<div class="btn-group">
|
|
33
|
+
<button class="btn btn-sm btn-outline-secondary load-tei-content"
|
|
34
|
+
data-url="{{ url_for('collection.load_tei_content') }}"
|
|
35
|
+
data-path="{{ file['fullpath'] }}" data-type="header" data-heading="TEI Header">
|
|
36
|
+
Header
|
|
37
|
+
</button>
|
|
38
|
+
<button class="btn btn-sm btn-outline-secondary load-tei-content"
|
|
39
|
+
data-url="{{ url_for('collection.load_tei_content') }}"
|
|
40
|
+
data-path="{{ file['fullpath'] }}" data-type="text" data-heading="TEI Text">
|
|
41
|
+
Text
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
44
|
+
</li>
|
|
45
|
+
{% endfor %}
|
|
46
|
+
</ul>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<!-- Tab: TEI Content -->
|
|
50
|
+
<div class="tab-pane fade" id="content" role="tabpanel" aria-labelledby="contentTab">
|
|
51
|
+
<div id="teiContentOutput" class="m-3">
|
|
52
|
+
<p class="text-muted">Select a file to view its content.</p>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<div class="modal-dialog modal-xl">
|
|
2
|
+
<div class="modal-content">
|
|
3
|
+
<div class="modal-header align-items-center">
|
|
4
|
+
<h5 id="xpathParserModalLabel" class="mb-0">Parse XPath:</h5>
|
|
5
|
+
<button type="button" class="btn-close ms-auto" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
6
|
+
</div>
|
|
7
|
+
<div class="modal-body">
|
|
8
|
+
<form class="js-modal-submit mb-4" id="parseXPath"
|
|
9
|
+
action="{{ url_for('collection.modal_xpath_parser', projectname=projectname, collectionname=collectionname) }}">
|
|
10
|
+
<div class="input-group">
|
|
11
|
+
<input type="text" class="form-control" placeholder="Enter XPath query" name="xpath"
|
|
12
|
+
value="{{ xpath }}">
|
|
13
|
+
<button type="submit" class="btn btn-secondary">Parse</button>
|
|
14
|
+
</div>
|
|
15
|
+
</form>
|
|
16
|
+
{% set elements = collection_parser.elements %}
|
|
17
|
+
<div class="row">
|
|
18
|
+
{% if elements %}
|
|
19
|
+
{% for element in elements %}
|
|
20
|
+
{% set result = element['tei_parser'].find(xpath) if xpath else None %}
|
|
21
|
+
<div class="col mb-3">
|
|
22
|
+
<div class="card shadow-sm">
|
|
23
|
+
<div class="card-header bg-light">
|
|
24
|
+
<h6 class="mb-0 text-truncate">
|
|
25
|
+
<i class="bi bi-file-earmark-text"></i> {{ element['file']['filename'] }}
|
|
26
|
+
</h6>
|
|
27
|
+
</div>
|
|
28
|
+
{% if xpath %}
|
|
29
|
+
<div class="card-body border border-2 {{'border-success' if result else 'border-danger'}}">
|
|
30
|
+
{% else %}
|
|
31
|
+
<div class="card-body">
|
|
32
|
+
{% endif %}
|
|
33
|
+
{% if xpath %}
|
|
34
|
+
<p class="mb-0 text-muted small">
|
|
35
|
+
<b>XPath Result:</b>
|
|
36
|
+
<br>
|
|
37
|
+
{{ result }}
|
|
38
|
+
</p>
|
|
39
|
+
{% endif %}
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
{% endfor %}
|
|
44
|
+
{% else %}
|
|
45
|
+
<div class="col-12">
|
|
46
|
+
<p class="text-center text-muted">No files available for parsing.</p>
|
|
47
|
+
</div>
|
|
48
|
+
{% endif %}
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
@@ -0,0 +1,90 @@
|
|
|
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">Check Upload Results</h1>
|
|
6
|
+
<p class="text-muted">Manually check for Issues</p>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<div class="row">
|
|
11
|
+
<div class="col-12 text-center mb-4">
|
|
12
|
+
<a href="https://test.textgridrep.org/projects" target="_blank" class="btn btn-lg btn-primary px-5 py-3">
|
|
13
|
+
<i class="bi bi-eye"></i> Open Preview Webview
|
|
14
|
+
</a>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="row">
|
|
19
|
+
<!-- Bootstrap Carousel -->
|
|
20
|
+
<div class="col-md-6 d-flex align-items-center">
|
|
21
|
+
<div id="carouselExampleIndicators" class="carousel slide w-100" data-bs-ride="carousel">
|
|
22
|
+
<div class="carousel-indicators">
|
|
23
|
+
<button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="0"
|
|
24
|
+
class="active" aria-current="true" aria-label="Slide 1"></button>
|
|
25
|
+
<button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="1"
|
|
26
|
+
aria-label="Slide 2"></button>
|
|
27
|
+
<button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="2"
|
|
28
|
+
aria-label="Slide 3"></button>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="carousel-inner">
|
|
31
|
+
<div class="carousel-item active">
|
|
32
|
+
<img src="https://placehold.co/600x400" class="d-block w-100 rounded" alt="Slide 1">
|
|
33
|
+
</div>
|
|
34
|
+
<div class="carousel-item">
|
|
35
|
+
<img src="https://placehold.co/600x400" class="d-block w-100 rounded" alt="Slide 2">
|
|
36
|
+
</div>
|
|
37
|
+
<div class="carousel-item">
|
|
38
|
+
<img src="https://placehold.co/600x400" class="d-block w-100 rounded" alt="Slide 3">
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleIndicators"
|
|
42
|
+
data-bs-slide="prev">
|
|
43
|
+
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
|
44
|
+
<span class="visually-hidden">Previous</span>
|
|
45
|
+
</button>
|
|
46
|
+
<button class="carousel-control-next" type="button" data-bs-target="#carouselExampleIndicators"
|
|
47
|
+
data-bs-slide="next">
|
|
48
|
+
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
|
49
|
+
<span class="visually-hidden">Next</span>
|
|
50
|
+
</button>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
<!-- Info-Bereich: Hinweise für die Prüfung -->
|
|
54
|
+
<div class="col-md-6 mb-4 mb-md-0">
|
|
55
|
+
<div class="bg-light rounded p-4 h-100">
|
|
56
|
+
<h2 class="fs-4 mb-3">What to check in the preview?</h2>
|
|
57
|
+
<ul class="list-group mb-3">
|
|
58
|
+
<li class="list-group-item">
|
|
59
|
+
<i class="bi bi-spellcheck text-primary me-2"></i>
|
|
60
|
+
Check for typos and spelling mistakes.
|
|
61
|
+
</li>
|
|
62
|
+
<li class="list-group-item">
|
|
63
|
+
<i class="bi bi-card-list text-secondary me-2"></i>
|
|
64
|
+
Ensure all required metadata fields are present and correct.
|
|
65
|
+
</li>
|
|
66
|
+
<li class="list-group-item">
|
|
67
|
+
<i class="bi bi-calendar-check text-success me-2"></i>
|
|
68
|
+
Verify date formats and values.
|
|
69
|
+
</li>
|
|
70
|
+
<li class="list-group-item">
|
|
71
|
+
<i class="bi bi-person-check text-info me-2"></i>
|
|
72
|
+
Confirm author and contributor information.
|
|
73
|
+
</li>
|
|
74
|
+
<li class="list-group-item">
|
|
75
|
+
<i class="bi bi-eye text-warning me-2"></i>
|
|
76
|
+
Review the overall layout and formatting.
|
|
77
|
+
</li>
|
|
78
|
+
<li class="list-group-item">
|
|
79
|
+
<i class="bi bi-exclamation-triangle text-danger me-2"></i>
|
|
80
|
+
Look for missing or inconsistent data.
|
|
81
|
+
</li>
|
|
82
|
+
</ul>
|
|
83
|
+
<div class="alert alert-info mt-3" role="alert">
|
|
84
|
+
<b>Tip:</b> You can repeat this process as often as needed!
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
{% from "macros.html" import multi_input with context %}
|
|
3
|
+
<div class="container py-4">
|
|
4
|
+
<div class="row">
|
|
5
|
+
<!-- Form Title -->
|
|
6
|
+
<div class="col-12 text-center mb-4">
|
|
7
|
+
<h1 class="fs-3 fw-bold">Project Settings</h1>
|
|
8
|
+
<p class="text-muted">Define some basic settings of your project.</p>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="row justify-content-center">
|
|
12
|
+
<div class="col-xl-8 col-lg-12">
|
|
13
|
+
<div class="bg-white border rounded-3 shadow-sm p-4">
|
|
14
|
+
<form method="POST" enctype="multipart/form-data"
|
|
15
|
+
action="{{ url_for('project.tab_edit_project', projectname=project.path) }}" id="editProjectForm"
|
|
16
|
+
class="js-tab-submit" data-next-target="#tab-import-data">
|
|
17
|
+
<div class="row">
|
|
18
|
+
<!-- Linke Seite: Name & Bild -->
|
|
19
|
+
<div class="col-md-5 d-flex flex-column align-items-center justify-content-start">
|
|
20
|
+
<div class="mb-3 w-100">
|
|
21
|
+
<label for="inlineFormInputName" class="form-label small">Name</label>
|
|
22
|
+
<input type="text" class="form-control" name="title" id="inlineFormInputName"
|
|
23
|
+
value="{{ project.title }}" placeholder="Name of the project">
|
|
24
|
+
</div>
|
|
25
|
+
<label for="inlineImage"
|
|
26
|
+
class="ratio ratio-1x1 d-block rounded overflow-hidden bg-light border mb-3"
|
|
27
|
+
style="cursor: pointer; height: 18rem; width: 100%;">
|
|
28
|
+
{% if project.avatar %}
|
|
29
|
+
<!-- Display existing project image -->
|
|
30
|
+
<div class="w-100 h-100" style="background-image: url({{ url_for('data.serve_image', filepath=project.avatar) }});
|
|
31
|
+
background-size: cover;
|
|
32
|
+
background-position: center;">
|
|
33
|
+
</div>
|
|
34
|
+
{% else %}
|
|
35
|
+
<div class="d-flex align-items-center justify-content-center bg-light h-100">
|
|
36
|
+
<div class="text-center">
|
|
37
|
+
<i class="bi bi-cloud-upload text-secondary d-block mb-2"
|
|
38
|
+
style="font-size: 2.5rem;"></i>
|
|
39
|
+
<span class="text-secondary">Upload image</span>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
{% endif %}
|
|
43
|
+
</label>
|
|
44
|
+
<input type="file" class="showPreviewOfAvatar d-none" id="inlineImage" name="avatar"
|
|
45
|
+
accept="image/*">
|
|
46
|
+
</div>
|
|
47
|
+
<!-- Rechte Seite: Rest -->
|
|
48
|
+
<div class="col-md-7 d-flex flex-column">
|
|
49
|
+
<div class="">
|
|
50
|
+
<label for="xsltFileUpload" class="form-label small">Upload XSLT File</label>
|
|
51
|
+
<div class="d-flex align-items-center">
|
|
52
|
+
<!-- Custom File Input -->
|
|
53
|
+
<input class="form-control me-2" type="file" id="xsltFileUpload" name="xslt"
|
|
54
|
+
accept=".xslt,.xsl" title="Upload XSLT">
|
|
55
|
+
|
|
56
|
+
<!-- Löschen-Button -->
|
|
57
|
+
<button {{ "disabled" if not project.xslt else "" }} type="button"
|
|
58
|
+
data-projectname="{{project.name}}" id="deleteXsltButton"
|
|
59
|
+
class="btn btn-outline-danger me-2" title="Delete XSLT">
|
|
60
|
+
<i class="bi bi-trash"></i>
|
|
61
|
+
</button>
|
|
62
|
+
|
|
63
|
+
<!-- Anzeigen-Button -->
|
|
64
|
+
{% set path = url_for('data.serve_file', filepath=project.xslt or "") %}
|
|
65
|
+
<button {{ "disabled" if not project.xslt else "" }} type="button"
|
|
66
|
+
id="viewXsltButton" class="btn btn-outline-primary" title="View XSLT"
|
|
67
|
+
onclick="window.open('{{ path }}', '_blank' )">
|
|
68
|
+
<i class="bi bi-eye"></i>
|
|
69
|
+
</button>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
<label for="formFile" class="form-label mb-2">
|
|
73
|
+
<div id="uploadStatus" class="mt-2 d-flex align-items-center gap-2">
|
|
74
|
+
{% if project.xslt %}
|
|
75
|
+
<span class="text-success d-flex align-items-center xslt-upload">
|
|
76
|
+
<i class="bi bi-check-circle me-2"></i>
|
|
77
|
+
{{ project.xslt.split('/')[-1] }}
|
|
78
|
+
</span>
|
|
79
|
+
{% else %}
|
|
80
|
+
<span class="text-danger d-flex align-items-center xslt-upload">
|
|
81
|
+
<i class="bi bi-exclamation-circle me-2"></i>
|
|
82
|
+
No file uploaded
|
|
83
|
+
</span>
|
|
84
|
+
{% endif %}
|
|
85
|
+
</div>
|
|
86
|
+
</label>
|
|
87
|
+
<div class="mb-3 flex-grow-1 d-flex flex-column">
|
|
88
|
+
<label for="inlineFormInputDescription" class="form-label small">Description</label>
|
|
89
|
+
<textarea class="form-control flex-grow-1" name="description"
|
|
90
|
+
id="inlineFormInputDescription">{{ project.description or '' }}</textarea>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="col-12">
|
|
94
|
+
<div class="mb-3">
|
|
95
|
+
<label for="inlineFormInputCollector" class="form-label small">Collector/s</label>
|
|
96
|
+
{{ multi_input(project.collectors, 'collector') }}
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="col-12">
|
|
100
|
+
<div class="text-center mt-1">
|
|
101
|
+
<button type="submit" class="btn btn-primary px-4 rounded-3">
|
|
102
|
+
<i class="bi bi-chevron-right"></i> Next
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</form>
|
|
108
|
+
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<div class="container py-5">
|
|
3
|
+
<div class="row justify-content-center">
|
|
4
|
+
<div class="col-md-6 text-center">
|
|
5
|
+
<div class="spinner-container my-5">
|
|
6
|
+
<div class="spinner-border text-secondary" style="width: 4rem; height: 4rem;" role="status">
|
|
7
|
+
<span class="visually-hidden">Loading...</span>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
@@ -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>
|