mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-12-25 02:44:18 +00:00
Progress on list rework
This commit is contained in:
parent
1883a9bc63
commit
1003c4494d
@ -283,7 +283,7 @@ class JobInput(db.Model):
|
||||
|
||||
@property
|
||||
def download_url(self):
|
||||
return url_for('job.download_job_input', job_id=self.job_id,
|
||||
return url_for('jobs.download_job_input', job_id=self.job_id,
|
||||
job_input_id=self.id)
|
||||
|
||||
@property
|
||||
@ -323,7 +323,7 @@ class JobResult(db.Model):
|
||||
|
||||
@property
|
||||
def download_url(self):
|
||||
return url_for('job.download_job_result', job_id=self.job_id,
|
||||
return url_for('jobs.download_job_result', job_id=self.job_id,
|
||||
job_result_id=self.id)
|
||||
|
||||
@property
|
||||
@ -384,8 +384,8 @@ class Job(db.Model):
|
||||
return os.path.join(self.creator.path, 'jobs', str(self.id))
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return url_for('job.job', job_id=self.id)
|
||||
def url(self):
|
||||
return url_for('jobs.job', job_id=self.id)
|
||||
|
||||
def __repr__(self):
|
||||
'''
|
||||
@ -430,9 +430,9 @@ class Job(db.Model):
|
||||
'description': self.description,
|
||||
'end_date': (self.end_date.timestamp() if self.end_date else
|
||||
None),
|
||||
'service': {'args': self.service_args,
|
||||
'name': self.service,
|
||||
'version': self.service_version},
|
||||
'service': self.service,
|
||||
'service_args': self.service_args,
|
||||
'service_version': self.service_version,
|
||||
'status': self.status,
|
||||
'title': self.title,
|
||||
'inputs': {input.id: input.to_dict() for input in self.inputs},
|
||||
@ -529,6 +529,10 @@ class Corpus(db.Model):
|
||||
files = db.relationship('CorpusFile', backref='corpus', lazy='dynamic',
|
||||
cascade='save-update, merge, delete')
|
||||
|
||||
@property
|
||||
def analysis_url(self):
|
||||
return url_for('corpora.analyse_corpus', corpus_id=self.id)
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return os.path.join(self.creator.path, 'corpora', str(self.id))
|
||||
@ -538,7 +542,8 @@ class Corpus(db.Model):
|
||||
return url_for('corpora.corpus', corpus_id=self.id)
|
||||
|
||||
def to_dict(self):
|
||||
return {'url': self.url,
|
||||
return {'analysis_url': self.analysis_url,
|
||||
'url': self.url,
|
||||
'id': self.id,
|
||||
'user_id': self.user_id,
|
||||
'creation_date': self.creation_date.timestamp(),
|
||||
@ -628,8 +633,10 @@ class QueryResult(db.Model):
|
||||
'url': self.url,
|
||||
'id': self.id,
|
||||
'user_id': self.user_id,
|
||||
'corpus_title': self.query_metadata['corpus_name'],
|
||||
'description': self.description,
|
||||
'filename': self.filename,
|
||||
'query': self.query_metadata['query'],
|
||||
'query_metadata': self.query_metadata,
|
||||
'title': self.title}
|
||||
|
||||
|
@ -27,13 +27,13 @@ nopaque.socket = io({transports: ['websocket']});
|
||||
nopaque.socket.on("user_data_stream_init", function(msg) {
|
||||
nopaque.user = JSON.parse(msg);
|
||||
for (let subscriber of nopaque.corporaSubscribers) {
|
||||
subscriber._init(nopaque.user.corpora);
|
||||
subscriber.init(nopaque.user.corpora);
|
||||
}
|
||||
for (let subscriber of nopaque.jobsSubscribers) {
|
||||
subscriber._init(nopaque.user.jobs);
|
||||
subscriber.init(nopaque.user.jobs);
|
||||
}
|
||||
for (let subscriber of nopaque.queryResultsSubscribers) {
|
||||
subscriber._init(nopaque.user.query_results);
|
||||
subscriber.init(nopaque.user.query_results);
|
||||
}
|
||||
});
|
||||
|
||||
@ -46,13 +46,13 @@ nopaque.socket.on("user_data_stream_update", function(msg) {
|
||||
jobs_patch = patch.filter(operation => operation.path.startsWith("/jobs"));
|
||||
query_results_patch = patch.filter(operation => operation.path.startsWith("/query_results"));
|
||||
for (let subscriber of nopaque.corporaSubscribers) {
|
||||
subscriber._update(corpora_patch);
|
||||
subscriber.update(corpora_patch);
|
||||
}
|
||||
for (let subscriber of nopaque.jobsSubscribers) {
|
||||
subscriber._update(jobs_patch);
|
||||
subscriber.update(jobs_patch);
|
||||
}
|
||||
for (let subscriber of nopaque.queryResultsSubscribers) {
|
||||
subscriber._update(query_results_patch);
|
||||
subscriber.update(query_results_patch);
|
||||
}
|
||||
if (["all", "end"].includes(nopaque.user.settings.job_status_site_notifications)) {
|
||||
for (operation of jobs_patch) {
|
||||
@ -69,13 +69,13 @@ nopaque.socket.on("user_data_stream_update", function(msg) {
|
||||
nopaque.socket.on("foreign_user_data_stream_init", function(msg) {
|
||||
nopaque.foreignUser = JSON.parse(msg);
|
||||
for (let subscriber of nopaque.foreignCorporaSubscribers) {
|
||||
subscriber._init(nopaque.foreignUser.corpora);
|
||||
subscriber.init(nopaque.foreignUser.corpora);
|
||||
}
|
||||
for (let subscriber of nopaque.foreignJobsSubscribers) {
|
||||
subscriber._init(nopaque.foreignUser.jobs);
|
||||
subscriber.init(nopaque.foreignUser.jobs);
|
||||
}
|
||||
for (let subscriber of nopaque.foreignQueryResultsSubscribers) {
|
||||
subscriber._init(nopaque.foreignUser.query_results);
|
||||
subscriber.init(nopaque.foreignUser.query_results);
|
||||
}
|
||||
});
|
||||
|
||||
@ -87,9 +87,9 @@ nopaque.socket.on("foreign_user_data_stream_update", function(msg) {
|
||||
corpora_patch = patch.filter(operation => operation.path.startsWith("/corpora"));
|
||||
jobs_patch = patch.filter(operation => operation.path.startsWith("/jobs"));
|
||||
query_results_patch = patch.filter(operation => operation.path.startsWith("/query_results"));
|
||||
for (let subscriber of nopaque.foreignCorporaSubscribers) {subscriber._update(corpora_patch);}
|
||||
for (let subscriber of nopaque.foreignJobsSubscribers) {subscriber._update(jobs_patch);}
|
||||
for (let subscriber of nopaque.foreignQueryResultsSubscribers) {subscriber._update(query_results_patch);}
|
||||
for (let subscriber of nopaque.foreignCorporaSubscribers) {subscriber.update(corpora_patch);}
|
||||
for (let subscriber of nopaque.foreignJobsSubscribers) {subscriber.update(jobs_patch);}
|
||||
for (let subscriber of nopaque.foreignQueryResultsSubscribers) {subscriber.update(query_results_patch);}
|
||||
});
|
||||
|
||||
nopaque.Forms = {};
|
||||
|
@ -1,420 +1,140 @@
|
||||
class RessourceList extends List {
|
||||
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;
|
||||
class RessourceList {
|
||||
constructor(idOrElement, options = {}) {
|
||||
this.list = new List(idOrElement, {...RessourceList.options, ...options});
|
||||
}
|
||||
|
||||
init(ressources) {
|
||||
this.list.clear();
|
||||
this.add(Object.values(ressources));
|
||||
this.list.sort('id', {order: 'desc'});
|
||||
}
|
||||
|
||||
|
||||
_init(ressources) {
|
||||
this.clear();
|
||||
this._add(Object.values(ressources));
|
||||
this.sort("id", {order: "desc"});
|
||||
}
|
||||
|
||||
|
||||
_update(patch) {
|
||||
update(patch) {
|
||||
let item, pathArray;
|
||||
|
||||
for (let operation of patch) {
|
||||
/* "/{ressourceName}/{ressourceId}/..." -> ["{ressourceId}", "..."] */
|
||||
pathArray = operation.path.split("/").slice(2);
|
||||
/*
|
||||
* '/{ressourceName}/{ressourceId}/{valueName}' -> ['{ressourceId}', {valueName}]
|
||||
* Example: '/jobs/1/status' -> ['1', 'status']
|
||||
*/
|
||||
let [id, valueName] = operation.path.split("/").slice(2);
|
||||
switch(operation.op) {
|
||||
case "add":
|
||||
if (pathArray.includes("results")) {break;}
|
||||
this._add([operation.value]);
|
||||
case 'add':
|
||||
this.add(operation.value);
|
||||
break;
|
||||
case "remove":
|
||||
this.remove("id", pathArray[0]);
|
||||
case 'remove':
|
||||
this.remove(id);
|
||||
break;
|
||||
case 'replace':
|
||||
this.replace(id, valueName, operation.value);
|
||||
break;
|
||||
case "replace":
|
||||
item = this.get("id", pathArray[0])[0];
|
||||
switch(pathArray[1]) {
|
||||
case "status":
|
||||
item.values({status: operation.value,
|
||||
"analyse-link": ["analysing", "prepared", "start analysis"].includes(operation.value) ? `/corpora/${pathArray[0]}/analyse` : ""});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_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);
|
||||
add(values) {
|
||||
/* WORKAROUND: Set a callback function ('() => {return;}') to force List.js
|
||||
perform the add method asynchronous.
|
||||
* https://listjs.com/api/#add
|
||||
*/
|
||||
this.list.add(values, () => {return;});
|
||||
}
|
||||
|
||||
remove(id) {
|
||||
this.list.remove('id', id);
|
||||
}
|
||||
|
||||
replace(id, valueName, newValue) {
|
||||
if (!this.list.valuesNames.includes(valueName)) {return;}
|
||||
let item = this.list.get('id', id);
|
||||
item.values({[valueName]: newValue});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RessourceList.options = {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]};
|
||||
|
||||
|
||||
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.
|
||||
// Links are declared with double ticks(") around them. The key for links
|
||||
// have to correspond with the class of an <a> element in the
|
||||
// RessourceList.options item blueprint.
|
||||
class CorpusList extends RessourceList {
|
||||
constructor(listElementId, options = {}) {
|
||||
let listElement = document.querySelector(`#${listElementId}`);
|
||||
super(listElement, {...CorpusList.options, ...options});
|
||||
listElement.addEventListener('click', (event) => {
|
||||
let actionButtonElement = event.target.closest('.action-button');
|
||||
if (actionButtonElement === null) {return;}
|
||||
let corpusId = event.target.closest('tr').dataset.id;
|
||||
let action = actionButtonElement.dataset.action;
|
||||
switch (action) {
|
||||
case 'analyse':
|
||||
window.location.href = nopaque.user.corpora[corpusId].analysis_url;
|
||||
}
|
||||
});
|
||||
nopaque.corporaSubscribers.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
/* ### 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,
|
||||
id: corpus_file.id,
|
||||
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.name,
|
||||
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: `/corpora/result/${query_result.id}`,
|
||||
query: query_result.query_metadata.query,
|
||||
title: query_result.title,
|
||||
"delete-link": `/corpora/result/${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": `/corpora/result/${query_result.id}/inspect`,
|
||||
}),
|
||||
/* ### User mapper ### */
|
||||
User: user => ({
|
||||
confirmed: user.confirmed,
|
||||
email: user.email,
|
||||
id: user.id,
|
||||
link: `users/${user.id}`,
|
||||
role: user.role.name,
|
||||
username: user.username,
|
||||
username2: user.username,
|
||||
"delete-link": `/admin/users/${user.id}/delete`,
|
||||
"delete-modal": `delete-user-${user.id}-modal`,
|
||||
"delete-modal-trigger": `delete-user-${user.id}-modal`,
|
||||
}),
|
||||
|
||||
CorpusList.options = {
|
||||
item: `<tr>
|
||||
<td><a class="btn-floating disabled"><i class="material-icons">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="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="edit" data-position="top" data-tooltip="Edit"><i class="material-icons">edit</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="analyse" data-position="top" data-tooltip="Analyse"><i class="material-icons">search</i></a>
|
||||
</td>
|
||||
</tr>`,
|
||||
valueNames: [{data: ['id']}, {name: "status", attr: "data-status"}, 'description', 'title']
|
||||
};
|
||||
|
||||
|
||||
RessourceList.options = {
|
||||
// common list.js options for 5 rows per page etc.
|
||||
common: {page: 5, pagination: [{innerWindow: 4, 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,
|
||||
},
|
||||
],
|
||||
},
|
||||
/* 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>
|
||||
<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",
|
||||
{data: ["id"]},
|
||||
{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="id"></td>
|
||||
<td class="username"></td>
|
||||
<td class="email"></td>
|
||||
<td class="role"></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",
|
||||
{name: "link", attr: "href"},
|
||||
{name: "delete-link", attr: "href"},
|
||||
{name: "delete-modal-trigger", attr: "data-target"},
|
||||
{name: "delete-modal", attr: "id"},
|
||||
],
|
||||
},
|
||||
class JobList extends RessourceList {
|
||||
constructor(listElementId, options = {}) {
|
||||
let listElement = document.querySelector(`#${listElementId}`);
|
||||
super(listElement, {...JobList.options, ...options});
|
||||
nopaque.jobsSubscribers.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JobList.options = {
|
||||
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="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>`,
|
||||
valueNames: [{data: ['id']}, {name: 'service', attr: 'data-service'}, {name: "status", attr: "data-status"}, 'description', 'title']
|
||||
};
|
||||
|
||||
export { RessourceList, };
|
||||
|
||||
class QueryResultList extends RessourceList {
|
||||
constructor(listElementId, options = {}) {
|
||||
let listElement = document.querySelector(`#${listElementId}`);
|
||||
super(listElement, {...QueryResultList.options, ...options});
|
||||
nopaque.queryResultsSubscribers.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QueryResultList.options = {
|
||||
item: `<tr>
|
||||
<td><b class="title"></b><br><i class="description"></i><br></td>
|
||||
<td><span class="corpus_title"></span><br><span class="query"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
<a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="analyse" data-position="top" data-tooltip="Analyse"><i class="material-icons">search</i></a>
|
||||
</td>
|
||||
</tr>`,
|
||||
valueNames: [{data: ['id']}, 'corpus_title', 'description', 'query', 'title']
|
||||
};
|
||||
|
||||
export { CorpusList, JobList, QueryResultList };
|
||||
|
420
web/app/static/js/nopaque.lists.js.bak
Normal file
420
web/app/static/js/nopaque.lists.js.bak
Normal file
@ -0,0 +1,420 @@
|
||||
class RessourceList extends List {
|
||||
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._add(Object.values(ressources));
|
||||
this.sort("id", {order: "desc"});
|
||||
}
|
||||
|
||||
|
||||
_update(patch) {
|
||||
let item, pathArray;
|
||||
|
||||
for (let operation of patch) {
|
||||
/* "/{ressourceName}/{ressourceId}/..." -> ["{ressourceId}", "..."] */
|
||||
pathArray = operation.path.split("/").slice(2);
|
||||
switch(operation.op) {
|
||||
case "add":
|
||||
if (pathArray.includes("results")) {break;}
|
||||
this._add([operation.value]);
|
||||
break;
|
||||
case "remove":
|
||||
this.remove("id", pathArray[0]);
|
||||
break;
|
||||
case "replace":
|
||||
item = this.get("id", pathArray[0])[0];
|
||||
switch(pathArray[1]) {
|
||||
case "status":
|
||||
item.values({status: operation.value,
|
||||
"analyse-link": ["analysing", "prepared", "start analysis"].includes(operation.value) ? `/corpora/${pathArray[0]}/analyse` : ""});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_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.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.
|
||||
// Links are declared with double ticks(") around them. The key for links
|
||||
// have to correspond with the class of an <a> element in the
|
||||
// RessourceList.options item blueprint.
|
||||
|
||||
/* ### 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,
|
||||
id: corpus_file.id,
|
||||
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.name,
|
||||
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: `/corpora/result/${query_result.id}`,
|
||||
query: query_result.query_metadata.query,
|
||||
title: query_result.title,
|
||||
"delete-link": `/corpora/result/${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": `/corpora/result/${query_result.id}/inspect`,
|
||||
}),
|
||||
/* ### User mapper ### */
|
||||
User: user => ({
|
||||
confirmed: user.confirmed,
|
||||
email: user.email,
|
||||
id: user.id,
|
||||
link: `users/${user.id}`,
|
||||
role: user.role.name,
|
||||
username: user.username,
|
||||
username2: user.username,
|
||||
"delete-link": `/admin/users/${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 5 rows per page etc.
|
||||
common: {page: 5, pagination: [{innerWindow: 4, 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,
|
||||
},
|
||||
],
|
||||
},
|
||||
/* 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>
|
||||
<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",
|
||||
{data: ["id"]},
|
||||
{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="id"></td>
|
||||
<td class="username"></td>
|
||||
<td class="email"></td>
|
||||
<td class="role"></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",
|
||||
{name: "link", attr: "href"},
|
||||
{name: "delete-link", attr: "href"},
|
||||
{name: "delete-modal-trigger", attr: "data-target"},
|
||||
{name: "delete-modal", attr: "id"},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export { RessourceList, };
|
@ -1,33 +1,33 @@
|
||||
class RessourceList extends List {
|
||||
constructor(idOrElement, options) {
|
||||
super(idOrElement, {...RessourceList.options['default'], ...(options ? options : {})});
|
||||
class RessourceList {
|
||||
constructor(idOrElement, options = {}) {
|
||||
this.list = new List(idOrElement, {...RessourceList.options, ...options});
|
||||
}
|
||||
|
||||
_init(ressources) {
|
||||
this.clear();
|
||||
this._add(Object.values(ressources));
|
||||
this.sort("id", {order: "desc"});
|
||||
init(ressources) {
|
||||
this.list.clear();
|
||||
this.add(Object.values(ressources));
|
||||
this.list.sort('id', {order: 'desc'});
|
||||
}
|
||||
|
||||
|
||||
_update(patch) {
|
||||
update(patch) {
|
||||
let item, pathArray;
|
||||
|
||||
for (let operation of patch) {
|
||||
/*
|
||||
* '/{ressourceName}/{ressourceId}/...' -> ['{ressourceId}', ...]
|
||||
* '/{ressourceName}/{ressourceId}/{valueName}' -> ['{ressourceId}', {valueName}]
|
||||
* Example: '/jobs/1/status' -> ['1', 'status']
|
||||
*/
|
||||
pathArray = operation.path.split("/").slice(2);
|
||||
let [id, valueName] = operation.path.split("/").slice(2);
|
||||
switch(operation.op) {
|
||||
case "add":
|
||||
this.add_handler([operation.value]);
|
||||
case 'add':
|
||||
this.add(operation.value);
|
||||
break;
|
||||
case "remove":
|
||||
this.remove_handler(pathArray[0]);
|
||||
case 'remove':
|
||||
this.remove(id);
|
||||
break;
|
||||
case "replace":
|
||||
this.replace_handler(pathArray[0], pathArray[1], operation.value);
|
||||
case 'replace':
|
||||
this.replace(id, valueName, operation.value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -35,34 +35,93 @@ class RessourceList extends List {
|
||||
}
|
||||
}
|
||||
|
||||
add_handler(values, callback) {
|
||||
if (this.hasOwnProperty('add_')) {
|
||||
this.add_(values, callback);
|
||||
} else {
|
||||
this.add(values, callback);
|
||||
}
|
||||
add(values) {
|
||||
/* WORKAROUND: Set a callback function ('() => {return;}') to force List.js
|
||||
perform the add method asynchronous.
|
||||
* https://listjs.com/api/#add
|
||||
*/
|
||||
this.list.add(values, () => {return;});
|
||||
}
|
||||
|
||||
remove_handler(id) {
|
||||
if (this.hasOwnProperty('remove_')) {
|
||||
this.remove_(id);
|
||||
} else {
|
||||
this.remove(id);
|
||||
}
|
||||
remove(id) {
|
||||
this.list.remove('id', id);
|
||||
}
|
||||
|
||||
replace_handler(id, valueName, newValue) {
|
||||
let item = this.get('id', id);
|
||||
if (this.hasOwnProperty('add_'))
|
||||
item.values({valueName: operation.value});
|
||||
replace(id, valueName, newValue) {
|
||||
if (!this.list.valuesNames.includes(valueName)) {return;}
|
||||
let item = this.list.get('id', id);
|
||||
item.values({[valueName]: newValue});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RessourceList.options = {
|
||||
// default RessourceList options
|
||||
default: {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]},
|
||||
RessourceList.options = {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]};
|
||||
|
||||
|
||||
class CorpusList extends RessourceList {
|
||||
constructor(idOrElement, options = {}) {
|
||||
super(idOrElement, {...CorpusList.options, ...options});
|
||||
nopaque.corporaSubscribers.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CorpusList.options = {
|
||||
item: `<tr>
|
||||
<td><a class="btn-floating disabled"><i class="material-icons">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="right-align">
|
||||
<a class="btn-floating delete red tooltipped waves-effect waves-light" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="btn-floating edit tooltipped waves-effect waves-light" data-position="top" data-tooltip="Edit"><i class="material-icons">edit</i></a>
|
||||
<a class="analyse btn-floating tooltipped waves-effect waves-light" data-position="top" data-tooltip="Analyse"><i class="material-icons">search</i></a>
|
||||
</td>
|
||||
</tr>`,
|
||||
valueNames: [{data: ['id']}, 'description', 'status', 'title']
|
||||
};
|
||||
|
||||
|
||||
export { RessourceList, };
|
||||
class JobList extends RessourceList {
|
||||
constructor(idOrElement, options = {}) {
|
||||
super(idOrElement, {...JobList.options, ...options});
|
||||
nopaque.jobsSubscribers.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JobList.options = {
|
||||
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="right-align">
|
||||
<a class="btn-floating delete red tooltipped waves-effect waves-light" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="btn-floating tooltipped view waves-effect waves-light" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
</td>
|
||||
</tr>`,
|
||||
valueNames: [{data: ['id']}, {name: 'service', attr: 'data-service'}, 'description', 'status', 'title']
|
||||
};
|
||||
|
||||
|
||||
class QueryResultList extends RessourceList {
|
||||
constructor(idOrElement, options = {}) {
|
||||
super(idOrElement, {...QueryResultList.options, ...options});
|
||||
nopaque.queryResultsSubscribers.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QueryResultList.options = {
|
||||
item: `<tr>
|
||||
<td><b class="title"></b><br><i class="description"></i><br></td>
|
||||
<td><span class="corpus_title"></span><br><span class="query"></span></td>
|
||||
<td class="right-align">
|
||||
<a class="btn-floating delete red tooltipped waves-effect waves-light" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
|
||||
<a class="btn-floating tooltipped view waves-effect waves-light" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
|
||||
<a class="analyse btn-floating tooltipped waves-effect waves-light" data-position="top" data-tooltip="Analyse"><i class="material-icons">search</i></a>
|
||||
</td>
|
||||
</tr>`,
|
||||
valueNames: [{data: ['id']}, 'corpus_title', 'description', 'query', 'title']
|
||||
};
|
||||
|
||||
export { CorpusList, JobList, QueryResultList };
|
||||
|
@ -176,9 +176,9 @@
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
<script type="module">
|
||||
import {RessourceList} from '../../static/js/nopaque.lists.js';
|
||||
let corpusList = new RessourceList("corpora", nopaque.corporaSubscribers, "Corpus");
|
||||
let jobList = new RessourceList("jobs", nopaque.jobsSubscribers, "Job");
|
||||
let queryResultList = new RessourceList("query-results", nopaque.queryResultsSubscribers, "QueryResult");
|
||||
import {CorpusList, JobList, QueryResultList} from '../../static/js/nopaque.lists.js';
|
||||
let corpusList = new CorpusList("corpora");
|
||||
let jobList = new JobList("jobs");
|
||||
let queryResultList = new QueryResultList("query-results");
|
||||
</script>
|
||||
{% endblock scripts %}
|
||||
|
Loading…
Reference in New Issue
Block a user