First RessourceList update

This commit is contained in:
Patrick Jentsch 2020-07-30 14:17:51 +02:00
parent 889c568ceb
commit 715c37813c
12 changed files with 432 additions and 477 deletions

View File

@ -6,20 +6,24 @@ def init_logger():
'''
Functions initiates a logger instance.
'''
if not os.path.isfile('logs/nopaqued.log'):
file_path = os.path.join(os.getcwd(), 'logs/nopaqued.log')
log = open(file_path, 'w+')
log.close()
logging.basicConfig(datefmt='%Y-%m-%d %H:%M:%S',
filemode='w', filename='logs/nopaqued.log',
format='%(asctime)s - %(levelname)s - %(name)s - '
'%(filename)s - %(lineno)d - %(message)s')
logger = logging.getLogger(__name__)
if os.environ.get('FLASK_CONFIG') == 'development':
logger.setLevel(logging.DEBUG)
if os.environ.get('FLASK_CONFIG') == 'production':
logger.setLevel(logging.WARNING)
return logger
os.makedirs('logs', exist_ok=True)
logging.basicConfig(filename='logs/nopaqued.log',
format='[%(asctime)s] %(levelname)s in '
'%(pathname)s:%(lineno)d - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S', filemode='w')
NOPAQUE_LOG_LEVEL = os.environ.get('NOPAQUE_LOG_LEVEL')
if NOPAQUE_LOG_LEVEL is None:
FLASK_CONFIG = os.environ.get('FLASK_CONFIG')
if FLASK_CONFIG == 'development':
logging.basicConfig(level='DEBUG')
elif FLASK_CONFIG == 'testing':
# TODO: Set an appropriate log level
pass
elif FLASK_CONFIG == 'production':
logging.basicConfig(level='ERROR')
else:
logging.basicConfig(level=NOPAQUE_LOG_LEVEL)
return logging.getLogger(__name__)
if __name__ == '__main__':

View File

@ -40,6 +40,6 @@ services:
volumes:
- "/srv/nopaque/db:/var/lib/postgresql/data"
redis:
image: redis:5
image: redis:6
volumes:
- "redis-trash1:/data"

View File

@ -169,10 +169,10 @@ def download_corpus_file(corpus_id, corpus_file_id):
filename=corpus_file.filename)
@corpora.route('/<int:corpus_id>/files/<int:corpus_file_id>/edit',
@corpora.route('/<int:corpus_id>/files/<int:corpus_file_id>',
methods=['GET', 'POST'])
@login_required
def edit_corpus_file(corpus_id, corpus_file_id):
def corpus_file(corpus_id, corpus_file_id):
corpus = Corpus.query.get_or_404(corpus_id)
corpus_file = CorpusFile.query.get_or_404(corpus_file_id)
if not corpus_file.corpus_id == corpus_id:
@ -212,7 +212,7 @@ def edit_corpus_file(corpus_id, corpus_file_id):
edit_corpus_file_form.publishing_year.data = corpus_file.publishing_year
edit_corpus_file_form.school.data = corpus_file.school
edit_corpus_file_form.title.data = corpus_file.title
return render_template('corpora/edit_corpus_file.html.j2',
return render_template('corpora/corpus_file.html.j2',
corpus_file=corpus_file, corpus=corpus,
edit_corpus_file_form=edit_corpus_file_form,
title='Edit corpus file')

View File

@ -43,7 +43,6 @@ nopaque.socket.init = function() {
for (let subscriber of nopaque.queryResultsSubscribers) {
subscriber._init(nopaque.user.query_results);
}
RessourceList.modifyTooltips(false)
});
nopaque.socket.on("user_data_stream_update", function(msg) {
@ -86,7 +85,6 @@ nopaque.socket.init = function() {
for (let subscriber of nopaque.foreignQueryResultsSubscribers) {
subscriber._init(nopaque.foreignUser.query_results);
}
RessourceList.modifyTooltips(false)
});
nopaque.socket.on("foreign_user_data_stream_update", function(msg) {

View File

@ -1,27 +1,19 @@
class RessourceList extends List {
constructor(idOrElement, subscriberList, type, options={}) {
if (!["Corpus", "CorpusFile", "Job", "JobInput", "QueryResult", "User"].includes(type)) {
console.error("Unknown Type!");
return;
}
if (subscriberList) {
super(idOrElement, {...RessourceList.options['common'],
...RessourceList.options[type],
...options});
this.type = type;
subscriberList.push(this);
} else {
super(idOrElement, {...RessourceList.options['extended'],
...RessourceList.options[type],
...options});
this.type = type;
constructor(idOrElement, subscriberList, type, options) {
if (!type || !["Corpus", "CorpusFile", "Job", "JobInput", "QueryResult", "User"].includes(type)) {
throw "Unknown Type!";
}
super(idOrElement, {...RessourceList.options['common'],
...RessourceList.options[type],
...(options ? options : {})});
if (subscriberList) {subscriberList.push(this);}
this.type = type;
}
_init(ressources) {
this.clear();
this.addRessources(Object.values(ressources));
this._add(Object.values(ressources));
this.sort("creation_date", {order: "desc"});
}
@ -35,7 +27,7 @@ class RessourceList extends List {
switch(operation.op) {
case "add":
if (pathArray.includes("results")) {break;}
this.addRessources([operation.value]);
this._add([operation.value]);
break;
case "remove":
this.remove("id", pathArray[0]);
@ -56,30 +48,17 @@ class RessourceList extends List {
}
}
addRessources(ressources) {
this.add(ressources.map(x => RessourceList.dataMapper[this.type](x)));
}
// Use this to modify tooltips to show after 750ms. If loaded is set to
// true (default) tooltips will only be initialized if DOMContentLoaded event
// triggered. If you do not want to wait for this event set pass false.
static modifyTooltips(waitForDOMContentLoaded=true) {
if (waitForDOMContentLoaded) {
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.tooltipped');
var instances = M.Tooltip.init(elems, {enterDelay: 750});
});
} else {
var elems = document.querySelectorAll('.tooltipped');
var instances = M.Tooltip.init(elems, {enterDelay: 750});
}
_add(values, callback) {
this.add(values.map(x => RessourceList.dataMappers[this.type](x)), callback);
// Initialize modal and tooltipped elements in list
M.AutoInit(this.listContainer);
}
}
RessourceList.dataMapper = {
RessourceList.dataMappers = {
// A data mapper describes entitys rendered per row. One key value pair holds
// the data to be rendered in the list.js table. Key has to correspond
// with the ValueNames defined below in RessourceList.options ValueNames.
@ -87,221 +66,361 @@ RessourceList.dataMapper = {
// have to correspond with the class of an <a> element in the
// RessourceList.options item blueprint.
// Mapping for Corpus entities shown in the dashboard table.
Corpus: corpus => ({creation_date: corpus.creation_date,
"delete-onclick": `prepareDeleteCorpusModal(${corpus.id})`,
description: corpus.description,
id: corpus.id,
"analyse-link": ["analysing", "prepared", "start analysis"].includes(corpus.status) ? `/corpora/${corpus.id}/analyse` : "",
"edit-link": `/corpora/${corpus.id}`,
status: corpus.status,
title: corpus.title}),
// Mapping for corpus file entities shown in the corpus overview
CorpusFile: corpus_file => ({filename: corpus_file.filename,
author: corpus_file.author,
title: corpus_file.title,
publishing_year: corpus_file.publishing_year,
"edit-link": `${corpus_file.corpus_id}/files/${corpus_file.id}/edit`,
"download-link": `${corpus_file.corpus_id}/files/${corpus_file.id}/download`,
"delete-modal": `delete-corpus-file-${corpus_file.id}-modal`}),
// Mapping for job entities shown in the dashboard table.
Job: job => ({creation_date: job.creation_date,
"delete-onclick": `prepareDeleteJobModal(${job.id})`,
description: job.description,
id: job.id,
link: `/jobs/${job.id}`,
service: job.service,
status: job.status,
title: job.title}),
// Mapping for job input files shown in table on every job page
JobInput: job_input => ({filename: job_input.filename,
id: job_input.job_id,
"download-link": `${job_input.job_id}/inputs/${job_input.id}/download`}),
// Mapping for imported result entities from corpus analysis.
// Shown in imported results table
QueryResult: query_result => ({corpus_name: query_result.query_metadata.corpus_name,
"delete-onclick": `prepareDeleteQueryResultModal(${query_result.id})`,
description: query_result.description,
id: query_result.id,
"inspect-link": `/query_results/${query_result.id}/inspect`,
link: `/query_results/${query_result.id}`,
query: query_result.query_metadata.query,
title: query_result.title}),
// Mapping for user entities shown in admin table
User: user => ({username: user.username,
email: user.email,
role_id: user.role_id,
confirmed: user.confirmed,
id: user.id,
"profile-link": `user/${user.id}`})
/* ### Corpus mapper ### */
Corpus: corpus => ({
creation_date: corpus.creation_date,
description: corpus.description,
id: corpus.id,
link: `/corpora/${corpus.id}`,
status: corpus.status,
title: corpus.title,
title1: corpus.title,
"analyse-link": ["analysing", "prepared", "start analysis"].includes(corpus.status) ? `/corpora/${corpus.id}/analyse` : "",
"delete-link": `/corpora/${corpus.id}/delete`,
"delete-modal": `delete-corpus-${corpus.id}-modal`,
"delete-modal-trigger": `delete-corpus-${corpus.id}-modal`,
}),
/* ### CorpusFile mapper ### TODO: replace delete-modal with delete-onclick */
CorpusFile: corpus_file => ({
author: corpus_file.author,
filename: corpus_file.filename,
link: `${corpus_file.corpus_id}/files/${corpus_file.id}`,
publishing_year: corpus_file.publishing_year,
title: corpus_file.title,
title1: corpus_file.title,
"delete-link": `/corpora/${corpus_file.corpus_id}/files/${corpus_file.id}/delete`,
"delete-modal": `delete-corpus-file-${corpus_file.id}-modal`,
"delete-modal-trigger": `delete-corpus-file-${corpus_file.id}-modal`,
"download-link": `${corpus_file.corpus_id}/files/${corpus_file.id}/download`,
}),
/* ### Job mapper ### */
Job: job => ({
creation_date: job.creation_date,
description: job.description,
id: job.id,
link: `/jobs/${job.id}`,
service: job.service,
status: job.status,
title: job.title,
title1: job.title,
"delete-link": `/jobs/${job.id}/delete`,
"delete-modal": `delete-job-${job.id}-modal`,
"delete-modal-trigger": `delete-job-${job.id}-modal`,
}),
/* ### JobInput mapper ### */
JobInput: job_input => ({
filename: job_input.filename,
id: job_input.job_id,
"download-link": `${job_input.job_id}/inputs/${job_input.id}/download`
}),
/* ### QueryResult mapper ### */
QueryResult: query_result => ({
corpus_name: query_result.query_metadata.corpus_name,
description: query_result.description,
id: query_result.id,
link: `/query_results/${query_result.id}`,
query: query_result.query_metadata.query,
title: query_result.title,
"delete-link": `/query_results/${query_result.id}/delete`,
"delete-modal": `delete-query-result-${query_result.id}-modal`,
"delete-modal-trigger": `delete-query-result-${query_result.id}-modal`,
"inspect-link": `/query_results/${query_result.id}/inspect`,
}),
/* ### User mapper ### */
User: user => ({
confirmed: user.confirmed,
email: user.email,
id: user.id,
link: `user/${user.id}`,
role_id: user.role_id,
username: user.username,
username2: user.username,
"delete-link": `/admin/user/${user.id}/delete`,
"delete-modal": `delete-user-${user.id}-modal`,
"delete-modal-trigger": `delete-user-${user.id}-modal`,
}),
};
RessourceList.options = {
// common list.js options for 4 rows per page etc.
common: {page: 4, pagination: {innerWindow: 8, outerWindow: 1}},
common: {
page: 4,
pagination: {
innerWindow: 8,
outerWindow: 1,
},
},
// extended list.js options for 10 rows per page etc.
extended: {page: 10,
pagination: [{name: "paginationTop",
paginationClass: "paginationTop",
innerWindow: 8,
outerWindow: 1},
{paginationClass: "paginationBottom",
innerWindow: 8,
outerWindow: 1}]},
extended: {
page: 10,
pagination: [
{
name: "paginationTop",
paginationClass: "paginationTop",
innerWindow: 8,
outerWindow: 1
},
{
paginationClass: "paginationBottom",
innerWindow: 8,
outerWindow: 1,
},
],
},
/* Type specific List.js options. Usually only "item" and "valueNames" gets
* defined here but it is possible to define other List.js options.
* item: https://listjs.com/api/#item
* valueNames: https://listjs.com/api/#valueNames
*/
Corpus: {item: `<tr>
<td>
<a class="btn-floating disabled">
<i class="material-icons service">book</i>
</a>
</td>
<td>
<b class="title"></b><br>
<i class="description"></i>
</td>
<td>
<span class="badge new status" data-badge-caption="">
</span>
</td>
<td class="actions right-align">
<a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-onclick" data-position="top" data-tooltip="Delete">
<i class="material-icons">delete</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light edit-link" data-position="top" data-tooltip="Edit">
<i class="material-icons">edit</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light analyse-link" data-position="top" data-tooltip="Analyse">
<i class="material-icons">search</i>
</a>
</td>
</tr>`,
valueNames: ["creation_date",
"description",
"title",
{data: ["id"]},
{name: "analyse-link", attr: "href"},
{name: "delete-onclick", attr: "onclick"},
{name: "edit-link", attr: "href"},
{name: "status", attr: "data-status"}]},
CorpusFile: {item: `<tr>
<td class="filename" style="word-break: break-word;"></td>
<td class="author" style="word-break: break-word;"></td>
<td class="title" style="word-break: break-word;"></td>
<td class="publishing_year" style="word-break: break-word;"></td>
<td class="actions right-align">
<a class="btn-floating tooltipped waves-effect waves-light edit-link" data-position="top" data-tooltip="Edit">
<i class="material-icons">edit</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light download-link" data-position="top" data-tooltip="Download">
<i class="material-icons">file_download</i>
</a>
<a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal" data-position="top" data-tooltip="Delete">
<i class="material-icons">delete</i>
</a>
</td>
</tr>`,
valueNames: ["filename",
"author",
"title",
"publishing_year",
{name: "edit-link", attr: "href"},
{name: "download-link", attr: "href"},
{name: "delete-modal", attr: "data-target"}]},
Job: {item: `<tr>
<td>
<a class="btn-floating disabled">
<i class="material-icons service"></i>
</a>
</td>
<td>
<b class="title"></b><br>
<i class="description"></i>
</td>
<td>
<span class="badge new status" data-badge-caption=""></span>
</td>
<td class="actions right-align">
<a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-onclick" data-position="top" data-tooltip="Delete">
<i class="material-icons">delete</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Go to Job">
<i class="material-icons">send</i>
</a>
</td>
</tr>`,
valueNames: ["creation_date",
"description",
"title",
{data: ["id"]},
{name: "delete-onclick", attr: "onclick"},
{name: "link", attr: "href"},
{name: "service", attr: "data-service"},
{name: "status", attr: "data-status"}]},
JobInput: {item : `<tr>
<td class="filename"></td>
<td class="actions right-align">
<a class="btn-floating tooltipped waves-effect waves-light download-link" data-position="top" data-tooltip="Download">
<i class="material-icons">file_download</i>
</a>
</td>
</tr>`,
valueNames: ["filename",
"id",
{name: "download-link", attr: "href"}]},
QueryResult: {item: `<tr>
<td>
<b class="title"></b><br>
<i class="description"></i><br>
</td>
<td>
<span class="corpus_name"></span><br>
<span class="query"></span>
</td>
<td class="actions right-align">
<a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-onclick" data-position="top" data-tooltip="Delete">
<i class="material-icons">delete</i>
</a>
<a class="btn-floating tooltipped link waves-effect waves-light" data-position="top" data-tooltip="Info">
<i class="material-icons">info</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light inspect-link" data-position="top" data-tooltip="Analyse">
<i class="material-icons">search</i>
</a>
</td>
</tr>`,
valueNames: ["corpus_name",
"description",
"query",
"title",
{data: ["id"]},
{name: "delete-onclick", attr: "onclick"},
{name: "inspect-link", attr: "href"},
{name: "link", attr: "href"}]},
// User entity blueprint setting html strucuture per entity per row
// Link classes have to correspond with Links defined in the Mapping process
User: {item: `<tr>
<td class="username"></td>
<td class="email"></td>
<td class="role_id"></td>
<td class="confirmed"></td>
<td class="id"></td>
<td class="actions right-align">
<a class="btn-floating tooltipped profile-link waves-effect waves-light" data-position="top" data-tooltip="Edit User">
<i class="material-icons">edit</i>
</a>
</td>
</tr>`,
valueNames: ["username",
"email",
"role_id",
"confirmed",
"id",
{name: "profile-link", attr: "href"}]}
Corpus: {
item: `<tr>
<td>
<a class="btn-floating disabled">
<i class="material-icons service">book</i>
</a>
</td>
<td>
<b class="title"></b><br>
<i class="description"></i>
</td>
<td>
<span class="badge new status" data-badge-caption=""></span>
</td>
<td>
<div class="right-align">
<a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
<i class="material-icons">delete</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Edit">
<i class="material-icons">edit</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light analyse-link" data-position="top" data-tooltip="Analyse">
<i class="material-icons">search</i>
</a>
</div>
<div class="modal delete-modal">
<div class="modal-content">
<h4>Confirm corpus deletion</h4>
<p>Do you really want to delete the corpus <b class="title1"></b>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
</td>
</tr>`,
valueNames: [
"creation_date",
"description",
"title",
"title1",
{data: ["id"]},
{name: "analyse-link", attr: "href"},
{name: "delete-link", attr: "href"},
{name: "delete-modal-trigger", attr: "data-target"},
{name: "delete-modal", attr: "id"},
{name: "link", attr: "href"},
{name: "status", attr: "data-status"},
]
},
CorpusFile: {
item: `<tr>
<td class="filename" style="word-break: break-word;"></td>
<td class="author" style="word-break: break-word;"></td>
<td class="title" style="word-break: break-word;"></td>
<td class="publishing_year" style="word-break: break-word;"></td>
<td>
<div class="right-align">
<a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
<i class="material-icons">delete</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light download-link" data-position="top" data-tooltip="Download">
<i class="material-icons">file_download</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Edit">
<i class="material-icons">edit</i>
</a>
</div>
<div class="modal delete-modal">
<div class="modal-content">
<h4>Confirm corpus file deletion</h4>
<p>Do you really want to delete the corpus file <b class="title1"></b>? It be permanently deleted!</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
</td>
</tr>`,
valueNames: [
"author",
"filename",
"publishing_year",
"title",
"title1",
{name: "delete-link", attr: "href"},
{name: "delete-modal-trigger", attr: "data-target"},
{name: "delete-modal", attr: "id"},
{name: "download-link", attr: "href"},
{name: "link", attr: "href"},
],
},
Job: {
item: `<tr>
<td>
<a class="btn-floating disabled">
<i class="material-icons service"></i>
</a>
</td>
<td>
<b class="title"></b><br>
<i class="description"></i>
</td>
<td>
<span class="badge new status" data-badge-caption=""></span>
</td>
<td>
<div class="right-align">
<a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
<i class="material-icons">delete</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Go to job">
<i class="material-icons">send</i>
</a>
</div>
<div class="modal delete-modal">
<div class="modal-content">
<h4>Confirm job deletion</h4>
<p>Do you really want to delete the job <b class="title1"></b>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
</td>
</tr>`,
valueNames: [
"creation_date",
"description",
"title",
"title1",
{data: ["id"]},
{name: "delete-link", attr: "href"},
{name: "delete-modal-trigger", attr: "data-target"},
{name: "delete-modal", attr: "id"},
{name: "link", attr: "href"},
{name: "service", attr: "data-service"},
{name: "status", attr: "data-status"},
],
},
JobInput: {
item : `<tr>
<td class="filename"></td>
<td class="right-align">
<a class="btn-floating tooltipped waves-effect waves-light download-link" data-position="top" data-tooltip="Download">
<i class="material-icons">file_download</i>
</a>
</td>
</tr>`,
valueNames: [
"filename",
"id",
{name: "download-link", attr: "href"},
],
},
QueryResult: {
item: `<tr>
<td>
<b class="title"></b><br>
<i class="description"></i><br>
</td>
<td>
<span class="corpus_name"></span><br>
<span class="query"></span>
</td>
<td>
<div class="right-align">
<a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
<i class="material-icons">delete</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Info">
<i class="material-icons">info</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light inspect-link" data-position="top" data-tooltip="Analyse">
<i class="material-icons">search</i>
</a>
</div>
<div class="modal delete-modal">
<div class="modal-content">
<h4>Confirm query result deletion</h4>
<p>Do you really want to delete the query result <b class="title1"></b>? It will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
</td>
</tr>`,
valueNames: [
"corpus_name",
"description",
"query",
"title",
"title2",
{data: ["id"]},
{name: "delete-link", attr: "href"},
{name: "delete-modal-trigger", attr: "data-target"},
{name: "delete-modal", attr: "id"},
{name: "inspect-link", attr: "href"},
{name: "link", attr: "href"},
],
},
User: {
item: `<tr>
<td class="username"></td>
<td class="email"></td>
<td class="role_id"></td>
<td class="confirmed"></td>
<td class="id"></td>
<td>
<div class="right-align">
<a class="btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data-position="top" data-tooltip="Delete">
<i class="material-icons">delete</i>
</a>
<a class="btn-floating tooltipped waves-effect waves-light link" data-position="top" data-tooltip="Go to user">
<i class="material-icons">send</i>
</a>
</div>
<div class="modal delete-modal">
<div class="modal-content">
<h4>Confirm corpus deletion</h4>
<p>Do you really want to delete the job <b class="title1"></b>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light delete-link"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
</td>
</tr>`,
valueNames: [
"username",
"username2",
"email",
"role_id",
"confirmed",
"id",
{name: "link", attr: "href"},
{name: "delete-link", attr: "href"},
{name: "delete-modal-trigger", attr: "data-target"},
{name: "delete-modal", attr: "id"},
],
},
};

View File

@ -33,9 +33,10 @@
</div>
<script>
var ressources = {{ users|tojson|safe }};
var users = {{ users|tojson|safe }};
var userList = new RessourceList('users', null, "User");
userList.addRessources(ressources);
RessourceList.modifyTooltips();
document.addEventListener("DOMContentLoaded", () => {
userList.addRessources(users);
});
</script>
{% endblock %}

View File

@ -122,12 +122,6 @@
<script>
// create corpus file table
var ressources = {{ corpus_files|tojson|safe }};
var corpusFilesList = new RessourceList("corpus-files", null, "CorpusFile");
corpusFilesList.addRessources(ressources);
RessourceList.modifyTooltips();
class InformationUpdater {
constructor(corpusId, foreignCorpusFlag) {
this.corpusId = corpusId;
@ -215,5 +209,9 @@
nopaque.socket.emit("foreign_user_data_stream_init", {{ corpus.user_id }});
});
{% endif %}
var corpusFilesList = new RessourceList("corpus-files", null, "CorpusFile");
document.addEventListener("DOMContentLoaded", () => {
corpusFilesList._add({{ corpus_files|tojson|safe }});
});
</script>
{% endblock %}

View File

@ -158,12 +158,6 @@
<script>
// job_input_table code
var ressources = {{ job_inputs|tojson|safe }};
var jobInputsList = new RessourceList("inputs", null, "JobInput");
jobInputsList.addRessources(ressources);
RessourceList.modifyTooltips();
class InformationUpdater {
constructor(jobId, foreignJobFlag) {
this.jobId = jobId;
@ -299,5 +293,9 @@
nopaque.socket.emit("foreign_user_data_stream_init", {{ job.user_id }});
});
{% endif %}
let jobInputsList = new RessourceList("inputs", null, "JobInput");
document.addEventListener("DOMContentLoaded", () => {
jobInputsList._add({{ job_inputs|tojson|safe }});
});
</script>
{% endblock %}

View File

@ -112,143 +112,49 @@
<p><a class="modal-trigger waves-effect waves-light btn" href="#" data-target="new-job-modal"><i class="material-icons left">add</i>New job</a></p>
</div>
</div>
</div>
<!-- Modals -->
<div id="delete-corpus-modal" class="modal">
<div class="modal-content">
<h4>Confirm corpus deletion</h4>
<p>Do you really want to delete the corpus <b id="selected-corpus-title"></b>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" id="selected-corpus-delete-link"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
<div id="delete-job-modal" class="modal">
<div class="modal-content">
<h4>Confirm job deletion</h4>
<p>Do you really want to delete the job <b id="selected-job-title"></b>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" id="selected-job-delete-link"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
<div id="delete-query-result-modal" class="modal no-autoinit">
<div class="modal-content">
<h4>Confirm query result deletion</h4>
<p>Do you really want to delete the query result <b id="selected-query-result-title"></b>? It will be permanently deleted.</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" id="selected-query-result-delete-link"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
<div id="new-job-modal" class="modal">
<div class="modal-content">
<h4>Select a service</h4>
<div class="row">
<div class="col s12 m4">
<a href="{{ url_for('services.service', service='file-setup') }}" style="color: rgba(0,0,0,0.87);">
<div class="card-panel center-align hoverable">
<i class="large material-icons" style="color: #ee6e73;">burst_mode</i>
<p>File setup</p>
<p class="light">Digital copies of text based research data (books, letters, etc.) often comprise various files and formats. nopaque converts and merges those files to facilitate further processing and the application of other services.</p>
</div>
</a>
</div>
<div class="col s12 m4">
<a href="{{ url_for('services.service', service='ocr') }}" style="color: rgba(0,0,0,0.87);">
<div class="card-panel center-align hoverable">
<i class="large material-icons" style="color: #ee6e73;">find_in_page</i>
<p>Optical Character Recognition</p>
<p class="light">nopaque converts your image data like photos or scans into text data through a process called OCR. This step enables you to proceed with further computational analysis of your documents.</p>
</div>
</a>
</div>
<div class="col s12 m4">
<a href="{{ url_for('services.service', service='nlp') }}" style="color: rgba(0,0,0,0.87);">
<div class="card-panel center-align hoverable">
<i class="large material-icons" style="color: #ee6e73;">format_textdirection_l_to_r</i>
<p>Natural Language Processing</p>
<p class="light">By means of computational linguistic data processing (tokenization, lemmatization, part-of-speech tagging and named-entity recognition) nopaque extracts additional information from your text.</p>
</div>
</a>
<div id="new-job-modal" class="modal">
<div class="modal-content">
<h4>Select a service</h4>
<div class="row">
<div class="col s12 m4">
<a href="{{ url_for('services.service', service='file-setup') }}" style="color: rgba(0,0,0,0.87);">
<div class="card-panel center-align hoverable">
<i class="large material-icons" style="color: #ee6e73;">burst_mode</i>
<p>File setup</p>
<p class="light">Digital copies of text based research data (books, letters, etc.) often comprise various files and formats. nopaque converts and merges those files to facilitate further processing and the application of other services.</p>
</div>
</a>
</div>
<div class="col s12 m4">
<a href="{{ url_for('services.service', service='ocr') }}" style="color: rgba(0,0,0,0.87);">
<div class="card-panel center-align hoverable">
<i class="large material-icons" style="color: #ee6e73;">find_in_page</i>
<p>Optical Character Recognition</p>
<p class="light">nopaque converts your image data like photos or scans into text data through a process called OCR. This step enables you to proceed with further computational analysis of your documents.</p>
</div>
</a>
</div>
<div class="col s12 m4">
<a href="{{ url_for('services.service', service='nlp') }}" style="color: rgba(0,0,0,0.87);">
<div class="card-panel center-align hoverable">
<i class="large material-icons" style="color: #ee6e73;">format_textdirection_l_to_r</i>
<p>Natural Language Processing</p>
<p class="light">By means of computational linguistic data processing (tokenization, lemmatization, part-of-speech tagging and named-entity recognition) nopaque extracts additional information from your text.</p>
</div>
</a>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-light btn-flat">Close</a>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-light btn-flat">Close</a>
</div>
</div>
</div>
<script>
var corpusList = new RessourceList("corpora", nopaque.corporaSubscribers,
"Corpus");
var corpusList = new RessourceList("corpora", nopaque.corporaSubscribers, "Corpus");
var jobList = new RessourceList("jobs", nopaque.jobsSubscribers, "Job");
var queryResultList = new RessourceList("query-results",
nopaque.queryResultsSubscribers,
"QueryResult", {page: 10});
var deleteCorpusModalElement = document.getElementById("delete-corpus-modal");
var deleteCorpusModal;
var deleteJobModalElement = document.getElementById("delete-job-modal");
var deleteJobModal;
var deleteQueryResultModalElement = document.getElementById("delete-query-result-modal");
var deleteQueryResultModal;
var selectedCorpusDeleteLinkElement = document.getElementById("selected-corpus-delete-link");
var selectedCorpusTitleElement = document.getElementById("selected-corpus-title");
var selectedJobDeleteLinkElement = document.getElementById("selected-job-delete-link");
var selectedJobTitleElement = document.getElementById("selected-job-title");
var selectedQueryResultDeleteLinkElement = document.getElementById("selected-query-result-delete-link");
var selectedQueryResultTitleElement = document.getElementById("selected-query-result-title");
function prepareDeleteCorpusModal(selectedCorpusId) {
var selectedCorpus;
if (selectedCorpusId in nopaque.user.corpora) {
selectedCorpus = nopaque.user.corpora[selectedCorpusId];
selectedCorpusDeleteLinkElement.href = `/corpora/${selectedCorpus.id}/delete`;
selectedCorpusTitleElement.innerText = selectedCorpus.title;
} else {
selectedQueryResult = undefined;
selectedCorpusDeleteLinkElement.href = "";
selectedCorpusTitleElement.innerText = "";
}
deleteCorpusModal.open();
}
function prepareDeleteJobModal(selectedJobId) {
var selectedJob;
if (selectedJobId in nopaque.user.jobs) {
selectedJob = nopaque.user.jobs[selectedJobId];
selectedJobDeleteLinkElement.href = `/jobs/${selectedJob.id}/delete`;
selectedJobTitleElement.innerText = selectedJob.title;
} else {
selectedJob = undefined;
selectedJobDeleteLinkElement.href = "";
selectedJobTitleElement.innerText = "";
}
deleteJobModal.open();
}
function prepareDeleteQueryResultModal(selectedQueryResultId) {
var selectedQueryResult;
if (selectedQueryResultId in nopaque.user.query_results) {
selectedQueryResult = nopaque.user.query_results[selectedQueryResultId];
selectedQueryResultDeleteLinkElement.href = `/query_results/${selectedQueryResult.id}/delete`;
selectedQueryResultTitleElement.innerText = selectedQueryResult.title;
} else {
selectedQueryResult = undefined;
selectedQueryResultDeleteLinkElement.href = "";
selectedQueryResultTitleElement.innerText = "";
}
deleteQueryResultModal.open();
}
document.addEventListener("DOMContentLoaded", () => {
deleteCorpusModal = M.Modal.init(deleteCorpusModalElement);
deleteJobModal = M.Modal.init(deleteJobModalElement);
deleteQueryResultModal = M.Modal.init(deleteQueryResultModalElement);
});
var queryResultList = new RessourceList("query-results", nopaque.queryResultsSubscribers, "QueryResult");
</script>
{% endblock %}

View File

@ -83,72 +83,8 @@
</div>
</div>
<!-- Modals -->
<div id="delete-corpus-modal" class="modal">
<div class="modal-content">
<h4>Confirm corpus deletion</h4>
<p>Do you really want to delete the corpus <b id="selected-corpus-title"></b>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" id="selected-corpus-delete-link"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
<div id="delete-query-result-modal" class="modal no-autoinit">
<div class="modal-content">
<h4>Confirm query result deletion</h4>
<p>Do you really want to delete the query result <b id="selected-query-result-title"></b>? It will be permanently deleted.</p>
</div>
<div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" id="selected-query-result-delete-link"><i class="material-icons left">delete</i>Delete</a>
</div>
</div>
<script>
var corpusList = new RessourceList("corpora", nopaque.corporaSubscribers,
"Corpus", {page: 10});
var queryResultList = new RessourceList("query-results",
nopaque.queryResultsSubscribers,
"QueryResult", {page: 10});
var deleteCorpusModalElement = document.getElementById("delete-corpus-modal");
var deleteCorpusModal;
var deleteQueryResultModalElement = document.getElementById("delete-query-result-modal");
var deleteQueryResultModal;
var selectedCorpusDeleteLinkElement = document.getElementById("selected-corpus-delete-link");
var selectedCorpusTitleElement = document.getElementById("selected-corpus-title");
var selectedQueryResultDeleteLinkElement = document.getElementById("selected-query-result-delete-link");
var selectedQueryResultTitleElement = document.getElementById("selected-query-result-title");
function prepareDeleteCorpusModal(selectedCorpusId) {
var selectedCorpus;
if (selectedCorpusId in nopaque.user.corpora) {
selectedCorpus = nopaque.user.corpora[selectedCorpusId];
selectedCorpusDeleteLinkElement.href = `/corpora/${selectedCorpus.id}/delete`;
selectedCorpusTitleElement.innerText = selectedCorpus.title;
} else {
selectedQueryResult = undefined;
selectedCorpusDeleteLinkElement.href = "";
selectedCorpusTitleElement.innerText = "";
}
deleteCorpusModal.open();
}
function prepareDeleteQueryResultModal(selectedQueryResultId) {
var selectedQueryResult;
if (selectedQueryResultId in nopaque.user.query_results) {
selectedQueryResult = nopaque.user.query_results[selectedQueryResultId];
selectedQueryResultDeleteLinkElement.href = `/query_results/${selectedQueryResult.id}/delete`;
selectedQueryResultTitleElement.innerText = selectedQueryResult.title;
} else {
selectedQueryResult = undefined;
selectedQueryResultDeleteLinkElement.href = "";
selectedQueryResultTitleElement.innerText = "";
}
deleteQueryResultModal.open();
}
document.addEventListener("DOMContentLoaded", () => {
deleteCorpusModal = M.Modal.init(deleteCorpusModalElement);
deleteQueryResultModal = M.Modal.init(deleteQueryResultModalElement);
});
var corpusList = new RessourceList("corpora", nopaque.corporaSubscribers, "Corpus");
var queryResultList = new RessourceList("query-results", nopaque.queryResultsSubscribers, "QueryResult");
</script>
{% endblock %}

View File

@ -47,12 +47,7 @@ class Config:
@staticmethod
def init_app(app):
proxy_fix_kwargs = {
'x_for': 1,
'x_host': 1,
'x_port': 1,
'x_proto': 1,
}
proxy_fix_kwargs = {'x_for': 1, 'x_host': 1, 'x_port': 1, 'x_proto': 1}
app.wsgi_app = ProxyFix(app.wsgi_app, **proxy_fix_kwargs)