mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2025-06-13 17:40:40 +00:00
Rework corpora package
This commit is contained in:
@ -14,7 +14,7 @@
|
||||
<li class="tab"><a{%if request.path == url_for('corpora.create_corpus') %} class="active"{% endif %} href="{{ url_for('corpora.create_corpus') }}" target="_self">Create corpus</a></li>
|
||||
<li class="tab disabled"><i class="material-icons">navigate_next</i></li>
|
||||
{% if corpus %}
|
||||
<li class="tab"><a{%if request.path == url_for('corpora.create_corpus_file', corpus_id=corpus.id) %} class="active"{% endif %} href="{{ url_for('corpora.create_corpus_file', corpus_id=corpus.id) }}" target="_self">Create corpus file(s)</a></li>
|
||||
<li class="tab"><a{%if request.path == url_for('corpora.files.create_corpus_file', corpus_id=corpus.id) %} class="active"{% endif %} href="{{ url_for('corpora.files.create_corpus_file', corpus_id=corpus.id) }}" target="_self">Create corpus file(s)</a></li>
|
||||
{% else %}
|
||||
<li class="tab disabled tooltipped" data-tooltip="Select a corpus first" target="_self"><a>Create corpus file(s)</a></li>
|
||||
{% endif %}
|
||||
|
@ -49,4 +49,8 @@
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
{% include "_scripts.html.j2" %}
|
||||
{% set page_script = self._TemplateReference__context.name|replace('.html.j2', '.js.j2') %}
|
||||
<script>
|
||||
{% include page_script ignore missing %}
|
||||
</script>
|
||||
{% endblock scripts %}
|
||||
|
@ -79,37 +79,3 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock page_content %}
|
||||
|
||||
{% block modals %}
|
||||
{{ super() }}
|
||||
<div id="models-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>Tesseract OCR Pipeline models</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Description</th>
|
||||
<th>Biblio</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for m in tesseract_ocr_pipeline_models %}
|
||||
<tr id="tesseract-ocr-pipeline-model-{{ m.hashid }}">
|
||||
<td>{{ m.title }}</td>
|
||||
{% if m.description == '' %}
|
||||
<td>Description is not available.</td>
|
||||
{% else %}
|
||||
<td>{{ m.description }}</td>
|
||||
{% endif %}
|
||||
<td><a href="{{ m.publisher_url }}">{{ m.publisher }}</a> ({{ m.publishing_year }}), {{ m.title }} {{ m.version}}, <a href="{{ m.publishing_url }}">{{ m.publishing_url }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#!" class="modal-close waves-effect waves-light btn">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock modals %}
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% set breadcrumbs %}
|
||||
{# {% set breadcrumbs %}
|
||||
<li class="tab disabled"><i class="material-icons">navigate_next</i></li>
|
||||
<li class="tab"><a href="{{ url_for('main.dashboard', _anchor='jobs') }}" target="_self">My corpora</a></li>
|
||||
<li class="tab disabled"><i class="material-icons">navigate_next</i></li>
|
||||
@ -25,4 +25,4 @@
|
||||
<li class="tab disabled"><i class="material-icons">navigate_next</i></li>
|
||||
<li class="tab"><a class="active" href="{{ url_for('.corpus_file', corpus_file_id=corpus_file.id, corpus_id=corpus.id) }}" target="_self">{{ corpus_file.author }}: {{ corpus_file.title }} ({{ corpus_file.publishing_year }})</a></li>
|
||||
{% endif %}
|
||||
{% endset %}
|
||||
{% endset %} #}
|
||||
|
@ -91,7 +91,7 @@
|
||||
<div class="corpus-file-list" data-user-id="{{ corpus.user.hashid }}" data-corpus-id="{{ corpus.hashid }}"></div>
|
||||
</div>
|
||||
<div class="card-action right-align">
|
||||
<a href="{{ url_for('corpora.create_corpus_file', corpus_id=corpus.id) }}" class="btn waves-effect waves-light"><i class="material-icons left">add</i>Add corpus file</a>
|
||||
<a href="{{ url_for('corpora.files.create_corpus_file', corpus_id=corpus.id) }}" class="btn waves-effect waves-light"><i class="material-icons left">add</i>Add corpus file</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -215,132 +215,3 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock modals %}
|
||||
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
<script>
|
||||
let corpusId = {{ corpus.hashid|tojson }};
|
||||
let corpusDisplay = new CorpusDisplay(document.querySelector('#corpus-display'));
|
||||
|
||||
// #region publishing_modal_js
|
||||
let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
|
||||
publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
|
||||
let newIsPublic = publishingModalIsPublicSwitchElement.checked;
|
||||
Requests.corpora.entity.isPublic.update(corpusId, newIsPublic)
|
||||
.catch((response) => {
|
||||
publishingModalIsPublicSwitchElement.checked = !newIsPublic;
|
||||
});
|
||||
});
|
||||
// #endregion publishing_modal_js
|
||||
|
||||
// #region delete_modal_js
|
||||
let deleteModalDeleteButtonElement = document.querySelector('#delete-modal-delete-button');
|
||||
deleteModalDeleteButtonElement.addEventListener('click', (event) => {
|
||||
Requests.corpora.entity.delete(corpusId)
|
||||
.then((response) => {window.location.href = '/dashboard';});
|
||||
});
|
||||
// #endregion delete_modal_js
|
||||
|
||||
// #region invite_user_modal_js
|
||||
let inviteUserModalElement = document.querySelector('#invite-user-modal');
|
||||
let inviteUserModalSearchElement = document.querySelector('#invite-user-modal-search');
|
||||
let inviteUserModalInviteButtonElement = document.querySelector('#invite-user-modal-invite-button');
|
||||
|
||||
let inviteUserModalSearch = M.Chips.init(
|
||||
inviteUserModalSearchElement,
|
||||
{
|
||||
autocompleteOptions: {
|
||||
data: {
|
||||
'nopaque': '/users/3V8Aqpg74JvxOd9o/avatar',
|
||||
'pjentsch': '/users/3V8Aqpg74JvxOd9o/avatar',
|
||||
'pjentsch2': '/users/3V8Aqpg74JvxOd9o/avatar'
|
||||
}
|
||||
},
|
||||
limit: 3,
|
||||
onChipAdd: (a, chipElement) => {
|
||||
if (!(chipElement.firstChild.data in inviteUserModalSearch.autocomplete.options.data)) {
|
||||
chipElement.firstElementChild.click();
|
||||
}
|
||||
},
|
||||
placeholder: 'Enter a username',
|
||||
secondaryPlaceholder: 'Add more users'
|
||||
}
|
||||
);
|
||||
|
||||
M.Modal.init(
|
||||
inviteUserModalElement,
|
||||
{
|
||||
onOpenStart: (modalElement, modalTriggerElement) => {
|
||||
while (inviteUserModalSearch.chipsData.length > 0) {
|
||||
inviteUserModalSearch.deleteChip(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
inviteUserModalInviteButtonElement.addEventListener('click', (event) => {
|
||||
let usernames = inviteUserModalSearch.chipsData.map((chipData) => chipData.tag);
|
||||
Requests.corpora.entity.followers.add(corpusId, usernames);
|
||||
});
|
||||
// #endregion invite_user_modal_js
|
||||
|
||||
// #region share_link_modal_js
|
||||
let shareLinkModalElement = document.querySelector('#share-link-modal');
|
||||
let shareLinkModalCorpusFollowerRoleSelectElement = document.querySelector('#share-link-modal-corpus-follower-role-select');
|
||||
let shareLinkModalExpirationDateDatepickerElement = document.querySelector('#share-link-modal-expiration-date-datepicker');
|
||||
let shareLinkModalCreateButtonElement = document.querySelector('#share-link-modal-create-button');
|
||||
let shareLinkModalOutputContainerElement = document.querySelector('#share-link-modal-output-container');
|
||||
let shareLinkModalOutputFieldElement = document.querySelector('#share-link-modal-output-field');
|
||||
let shareLinkModalOutputCopyButtonElement = document.querySelector('#share-link-modal-output-copy-button');
|
||||
|
||||
let today = new Date();
|
||||
let tomorrow = new Date();
|
||||
tomorrow.setDate(today.getDate() + 1);
|
||||
let oneWeekLater = new Date();
|
||||
oneWeekLater.setDate(today.getDate() + 7);
|
||||
let fourWeeksLater = new Date();
|
||||
fourWeeksLater.setDate(today.getDate() + 28);
|
||||
|
||||
M.Datepicker.init(
|
||||
shareLinkModalExpirationDateDatepickerElement,
|
||||
{
|
||||
container: document.querySelector('main'),
|
||||
defaultDate: oneWeekLater,
|
||||
setDefaultDate: true,
|
||||
minDate: tomorrow,
|
||||
maxDate: fourWeeksLater
|
||||
}
|
||||
);
|
||||
|
||||
M.Modal.init(
|
||||
shareLinkModalElement,
|
||||
{
|
||||
onOpenStart: (modalElement, modalTriggerElement) => {
|
||||
shareLinkModalOutputFieldElement.value = '';
|
||||
shareLinkModalOutputContainerElement.classList.add('hide');
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
shareLinkModalCreateButtonElement.addEventListener('click', (event) => {
|
||||
Requests.corpora.entity.generateShareLink(corpusId, shareLinkModalCorpusFollowerRoleSelectElement.value, shareLinkModalExpirationDateDatepickerElement.value)
|
||||
.then((response) => {
|
||||
response.json()
|
||||
.then((json) => {
|
||||
shareLinkModalOutputContainerElement.classList.remove('hide');
|
||||
shareLinkModalOutputFieldElement.value = json.corpusShareLink;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
shareLinkModalOutputCopyButtonElement.addEventListener('click', (event) => {
|
||||
navigator.clipboard.writeText(shareLinkModalOutputFieldElement.value)
|
||||
.then(
|
||||
() => {app.flash('Copied!');},
|
||||
() => {app.flash('Could not copy to clipboard. Please copy manually.', 'error');}
|
||||
);
|
||||
|
||||
});
|
||||
// #endregion share_link_modal_js
|
||||
</script>
|
||||
{% endblock scripts %}
|
||||
|
127
app/templates/corpora/corpus.js.j2
Normal file
127
app/templates/corpora/corpus.js.j2
Normal file
@ -0,0 +1,127 @@
|
||||
let corpusId = {{ corpus.hashid|tojson }};
|
||||
let corpusDisplay = new CorpusDisplay(document.querySelector('#corpus-display'));
|
||||
|
||||
// #region Publishing
|
||||
let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
|
||||
publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
|
||||
let newIsPublic = publishingModalIsPublicSwitchElement.checked;
|
||||
Requests.corpora.entity.isPublic.update(corpusId, newIsPublic)
|
||||
.catch((response) => {
|
||||
publishingModalIsPublicSwitchElement.checked = !newIsPublic;
|
||||
});
|
||||
});
|
||||
// #endregion Publishing
|
||||
|
||||
// #region Delete
|
||||
let deleteModalDeleteButtonElement = document.querySelector('#delete-modal-delete-button');
|
||||
deleteModalDeleteButtonElement.addEventListener('click', (event) => {
|
||||
Requests.corpora.entity.delete(corpusId)
|
||||
.then((response) => {
|
||||
window.location.href = {{ url_for('main.dashboard')|tojson }};
|
||||
});
|
||||
});
|
||||
// #endregion Delete
|
||||
|
||||
// #region Invite users
|
||||
let inviteUserModalElement = document.querySelector('#invite-user-modal');
|
||||
let inviteUserModalSearchElement = document.querySelector('#invite-user-modal-search');
|
||||
let inviteUserModalInviteButtonElement = document.querySelector('#invite-user-modal-invite-button');
|
||||
|
||||
let inviteUserModalSearch = M.Chips.init(
|
||||
inviteUserModalSearchElement,
|
||||
{
|
||||
autocompleteOptions: {
|
||||
data: {
|
||||
'nopaque': '/users/3V8Aqpg74JvxOd9o/avatar',
|
||||
'pjentsch': '/users/3V8Aqpg74JvxOd9o/avatar',
|
||||
'pjentsch2': '/users/3V8Aqpg74JvxOd9o/avatar'
|
||||
}
|
||||
},
|
||||
limit: 3,
|
||||
onChipAdd: (a, chipElement) => {
|
||||
if (!(chipElement.firstChild.data in inviteUserModalSearch.autocomplete.options.data)) {
|
||||
chipElement.firstElementChild.click();
|
||||
}
|
||||
},
|
||||
placeholder: 'Enter a username',
|
||||
secondaryPlaceholder: 'Add more users'
|
||||
}
|
||||
);
|
||||
|
||||
M.Modal.init(
|
||||
inviteUserModalElement,
|
||||
{
|
||||
onOpenStart: (modalElement, modalTriggerElement) => {
|
||||
while (inviteUserModalSearch.chipsData.length > 0) {
|
||||
inviteUserModalSearch.deleteChip(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
inviteUserModalInviteButtonElement.addEventListener('click', (event) => {
|
||||
let usernames = inviteUserModalSearch.chipsData.map((chipData) => chipData.tag);
|
||||
Requests.corpora.entity.followers.add(corpusId, usernames);
|
||||
});
|
||||
// #endregion Invite users
|
||||
|
||||
// #region Share link
|
||||
let shareLinkModalElement = document.querySelector('#share-link-modal');
|
||||
let shareLinkModalCorpusFollowerRoleSelectElement = document.querySelector('#share-link-modal-corpus-follower-role-select');
|
||||
let shareLinkModalExpirationDateDatepickerElement = document.querySelector('#share-link-modal-expiration-date-datepicker');
|
||||
let shareLinkModalCreateButtonElement = document.querySelector('#share-link-modal-create-button');
|
||||
let shareLinkModalOutputContainerElement = document.querySelector('#share-link-modal-output-container');
|
||||
let shareLinkModalOutputFieldElement = document.querySelector('#share-link-modal-output-field');
|
||||
let shareLinkModalOutputCopyButtonElement = document.querySelector('#share-link-modal-output-copy-button');
|
||||
|
||||
let today = new Date();
|
||||
let tomorrow = new Date();
|
||||
tomorrow.setDate(today.getDate() + 1);
|
||||
let oneWeekLater = new Date();
|
||||
oneWeekLater.setDate(today.getDate() + 7);
|
||||
let fourWeeksLater = new Date();
|
||||
fourWeeksLater.setDate(today.getDate() + 28);
|
||||
|
||||
M.Datepicker.init(
|
||||
shareLinkModalExpirationDateDatepickerElement,
|
||||
{
|
||||
container: document.querySelector('main'),
|
||||
defaultDate: oneWeekLater,
|
||||
setDefaultDate: true,
|
||||
minDate: tomorrow,
|
||||
maxDate: fourWeeksLater
|
||||
}
|
||||
);
|
||||
|
||||
M.Modal.init(
|
||||
shareLinkModalElement,
|
||||
{
|
||||
onOpenStart: (modalElement, modalTriggerElement) => {
|
||||
shareLinkModalOutputFieldElement.value = '';
|
||||
shareLinkModalOutputContainerElement.classList.add('hide');
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
shareLinkModalCreateButtonElement.addEventListener('click', (event) => {
|
||||
let role = shareLinkModalCorpusFollowerRoleSelectElement.value;
|
||||
let expiration = shareLinkModalExpirationDateDatepickerElement.value
|
||||
Requests.corpora.entity.generateShareLink(corpusId, role, expiration)
|
||||
.then((response) => {
|
||||
response.json()
|
||||
.then((json) => {
|
||||
shareLinkModalOutputContainerElement.classList.remove('hide');
|
||||
shareLinkModalOutputFieldElement.value = json.corpusShareLink;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
shareLinkModalOutputCopyButtonElement.addEventListener('click', (event) => {
|
||||
navigator.clipboard.writeText(shareLinkModalOutputFieldElement.value)
|
||||
.then(
|
||||
() => {app.flash('Copied!');},
|
||||
() => {app.flash('Could not copy to clipboard. Please copy manually.', 'error');}
|
||||
);
|
||||
|
||||
});
|
||||
// #endregion Share link
|
@ -36,7 +36,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action right-align">
|
||||
<a class="waves-effect waves-light btn red" href="{{ url_for('.corpus', corpus_id=corpus.id) }}"><i class="material-icons left">close</i>Cancel</a>
|
||||
<a class="waves-effect waves-light btn red" href="{{ url_for('corpora.corpus', corpus_id=corpus.id) }}"><i class="material-icons left">close</i>Cancel</a>
|
||||
{{ wtf.render_field(form.submit, material_icon='send') }}
|
||||
</div>
|
||||
</div>
|
@ -1,72 +0,0 @@
|
||||
{% extends "base.html.j2" %}
|
||||
|
||||
{% block main_attribs %} class="service-scheme" data-service="corpus-analysis"{% endblock main_attribs %}
|
||||
|
||||
{% block page_content %}
|
||||
<div class="corpus-list no-autoinit" id="corpus-list">
|
||||
<div class="parallax-container">
|
||||
<div class="parallax"><img src="{{ url_for('static', filename='images/parallax_hq/canvas.png') }}"></div>
|
||||
<div style="position: absolute; bottom: 0; width: 100%;">
|
||||
<div class="container">
|
||||
<div class="white-text">
|
||||
<h1 id="title"><i class="nopaque-icons" style="font-size: inherit;">I</i>Corpora</h1>
|
||||
</div>
|
||||
<div class="white" style="padding: 1px 35px 0 10px; border-radius: 35px;">
|
||||
<div class="input-field">
|
||||
<i class="material-icons prefix">search</i>
|
||||
<input class="search" id="corpus-list-search" type="text">
|
||||
<label for="corpus-list-search">Search corpus</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col s12" id="corpora">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Title and Description</th>
|
||||
<th>Status</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list"></tbody>
|
||||
</table>
|
||||
<ul class="pagination"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock page_content %}
|
||||
|
||||
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
<script>
|
||||
let corpusListElement = document.querySelector('#corpus-list');
|
||||
let corpusListOptions = {
|
||||
initialHtmlGenerator: null,
|
||||
item: `
|
||||
<tr class="clickable hoverable">
|
||||
<td><a class="btn-floating disabled"><i class="material-icons service-color darken" data-service="corpus-analysis">book</i></a></td>
|
||||
<td><b class="title"></b><br><i class="description"></i></td>
|
||||
<td><span class="status badge new corpus-status-color corpus-status-text" data-badge-caption=""></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating service-color darken waves-effect waves-light" data-action="view" data-service="corpus-analysis"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trim(),
|
||||
};
|
||||
let corpusList = new CorpusList(corpusListElement, corpusListOptions);
|
||||
corpusList._init({{ corpora|tojson }});
|
||||
</script>
|
||||
{% endblock scripts %}
|
@ -101,30 +101,3 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock page_content %}
|
||||
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
<script>
|
||||
let corpusFileList = new PublicCorpusFileList(document.querySelector('.corpus-file-list'));
|
||||
corpusFileList.add({{ corpus_files|tojson }});
|
||||
|
||||
let unfollowRequestElement = document.querySelector('.action-button[data-action="unfollow-request"]');
|
||||
unfollowRequestElement.addEventListener('click', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch('{{ url_for("corpora.unfollow_corpus", corpus_id=corpus.id, follower_id=current_user.id) }}', {method: 'POST', headers: {Accept: 'application/json'}})
|
||||
.then(
|
||||
(response) => {
|
||||
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||
resolve(response);
|
||||
window.location.href = '{{ url_for("main.dashboard") }}';
|
||||
},
|
||||
(response) => {
|
||||
app.flash('Something went wrong', 'error');
|
||||
reject(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock scripts %}
|
||||
|
11
app/templates/corpora/public_corpus.js.j2
Normal file
11
app/templates/corpora/public_corpus.js.j2
Normal file
@ -0,0 +1,11 @@
|
||||
let corpusId = {{ corpus.hashid|tojson }};
|
||||
let corpusFileList = new PublicCorpusFileList(document.querySelector('.corpus-file-list'));
|
||||
corpusFileList.add({{ corpus_files|tojson }});
|
||||
|
||||
let unfollowRequestElement = document.querySelector('.action-button[data-action="unfollow-request"]');
|
||||
unfollowRequestElement.addEventListener('click', () => {
|
||||
Requests.corpora.entity.followers.entity.delete(corpusId, currentUserId)
|
||||
.then((response) => {
|
||||
window.location.href = {{ url_for('main.dashboard')|tojson }};
|
||||
});
|
||||
});
|
@ -77,7 +77,7 @@
|
||||
{{ form.model.label }}
|
||||
<span class="helper-text">
|
||||
<a class="modal-trigger tooltipped" href="#models-modal" data-position="bottom" data-tooltip="See more information about models"><i class="material-icons" style="color:#0064A3;">help_outline</i></a>
|
||||
<a class="tooltipped" href="{{ url_for('contributions.create_spacy_nlp_pipeline_model') }}" data-position="bottom" data-tooltip="Add your own spaCy NLP models"><i class="material-icons" style="color:#0064A3">new_label</i></a>
|
||||
<a class="tooltipped" href="{{ url_for('contributions.spacy_nlp_pipeline_models.create_spacy_nlp_pipeline_model') }}" data-position="bottom" data-tooltip="Add your own spaCy NLP models"><i class="material-icons" style="color:#0064A3">new_label</i></a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -59,7 +59,7 @@
|
||||
{{ form.model.label }}
|
||||
<span class="helper-text">
|
||||
<a class="modal-trigger tooltipped" href="#models-modal" data-position="bottom" data-tooltip="See more information about models"><i class="material-icons" style="color:#00A58B;">help_outline</i></a>
|
||||
<a class="tooltipped" href="{{ url_for('contributions.create_tesseract_ocr_pipeline_model') }}" data-position="bottom" data-tooltip="Add your own Tesseract OCR models"><i class="material-icons" style="color:#00A58B">new_label</i></a>
|
||||
<a class="tooltipped" href="{{ url_for('contributions.tesseract_ocr_pipeline_models.create_tesseract_ocr_pipeline_model') }}" data-position="bottom" data-tooltip="Add your own Tesseract OCR models"><i class="material-icons" style="color:#00A58B">new_label</i></a>
|
||||
</span>
|
||||
{% for error in form.model.errors %}
|
||||
<span class="helper-text error-color-text">{{ error }}</span>
|
||||
|
Reference in New Issue
Block a user