Contributions update revised

This commit is contained in:
Patrick Jentsch
2022-11-15 15:11:16 +01:00
parent df5ae19e68
commit cd72614c0f
18 changed files with 481 additions and 444 deletions

View File

@ -10,6 +10,8 @@ class RessourceList {
JobList.autoInit();
JobInputList.autoInit();
JobResultList.autoInit();
SpacyNLPPipelineModelList.autoInit();
TesseractOCRPipelineModelList.autoInit();
QueryResultList.autoInit();
UserList.autoInit();
}

View File

@ -1,76 +0,0 @@
class SpacyNLPModelList {
constructor () {
this.elements = {
spacyNLPModelList: document.querySelector('#spacy-nlp-model-list'),
deleteButtons: document.querySelectorAll('.delete-spacy-model-button'),
editButtons: document.querySelectorAll('.edit-spacy-model-button'),
}
}
init () {
let userId = this.elements.spacyNLPModelList.dataset.userId;
for (let deleteButton of this.elements.deleteButtons) {
deleteButton.addEventListener('click', () => {this.deleteModel(deleteButton, userId);});
}
for (let editButton of this.elements.editButtons) {
editButton.addEventListener('click', () => {this.editModel(editButton);});
}
}
deleteModel(deleteButton, userId) {
return new Promise((resolve, reject) => {
let modelId = deleteButton.dataset.modelId;
let model = app.data.users[userId].spacy_nlp_pipeline_models[modelId];
let modalElement = Utils.elementFromString(
`
<div class="modal">
<div class="modal-content">
<h4>Confirm job deletion</h4>
<p>Do you really want to delete <b>${model.title}</b>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
<a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
</div>
</div>
`
);
document.querySelector('#modals').appendChild(modalElement);
let modal = M.Modal.init(
modalElement,
{
dismissible: false,
onCloseEnd: () => {
modal.destroy();
modalElement.remove();
}
}
);
let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
confirmElement.addEventListener('click', (event) => {
let modelTitle = model.title;
fetch(`/contributions/edit-spacy-model/${modelId}`, {method: 'DELETE'})
.then(
(response) => {
app.flash(`Model "${modelTitle}" marked for deletion`, 'corpus');
resolve(response);
},
(response) => {
if (response.status === 403) {app.flash('Forbidden', 'error');}
if (response.status === 404) {app.flash('Not Found', 'error');}
reject(response);
}
);
});
modal.open();
});
}
editModel(editButton) {
window.location.href = `/contributions/edit-spacy-model/${editButton.dataset.modelId}`;
}
}

View File

@ -0,0 +1,99 @@
class SpacyNLPPipelineModelList extends RessourceList {
static autoInit() {
for (let spaCyNLPPipelineModelListElement of document.querySelectorAll('.spacy-nlp-pipeline-model-list:not(.no-autoinit)')) {
new SpacyNLPPipelineModelList(spaCyNLPPipelineModelListElement);
}
}
static options = {
initialHtmlGenerator: (id) => {
return `
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="${id}-search" class="search" type="search"></input>
<label for="${id}-search">Search SpaCy NLP Pipeline Model</label>
</div>
<table>
<thead>
<tr>
<th>Title</th>
<th>Description</th>
<th>Biblio</th>
<th></th>
</tr>
</thead>
<tbody class="list"></tbody>
</table>
<ul class="pagination"></ul>
`.trim();
},
item: `
<tr class="clickable hoverable">
<td><span class="title"></span></td>
<td><span class="description"></span></td>
<td><a class="publisher-url"><span class="publisher"></span></a> (<span class="publishing-year"></span>), <span class="title-2"></span> <span class="version"></span>, <a class="publishing-url"><span class="publishing-url-2"></span></a></td>
<td class="right-align">
<a class="action-button btn-floating red waves-effect waves-light" data-action="delete-request"><i class="material-icons">delete</i></a>
<a class="action-button btn-floating service-color darken waves-effect waves-light service-2" data-action="view"><i class="material-icons">send</i></a>
</td>
</tr>
`.trim(),
ressourceMapper: (spaCyNLPPipelineModel) => {
return {
'id': spaCyNLPPipelineModel.id,
'creation-date': spaCyNLPPipelineModel.creation_date,
'description': spaCyNLPPipelineModel.description,
'publisher': spaCyNLPPipelineModel.publisher,
'publisher-url': spaCyNLPPipelineModel.publisher_url,
'publishing-url': spaCyNLPPipelineModel.publishing_url,
'publishing-url-2': spaCyNLPPipelineModel.publishing_url,
'publishing-year': spaCyNLPPipelineModel.publishing_year,
'title': spaCyNLPPipelineModel.title,
'title-2': spaCyNLPPipelineModel.title,
'version': spaCyNLPPipelineModel.version
};
},
sortArgs: ['creation-date', {order: 'desc'}],
valueNames: [
{data: ['id']},
{data: ['creation-date']},
{name: 'publisher-url', attr: 'href'},
{name: 'publishing-url', attr: 'href'},
'description',
'publisher',
'publishing-url-2',
'publishing-year',
'title',
'title-2',
'version'
]
};
constructor(listElement, options = {}) {
super(listElement, {...SpacyNLPPipelineModelList.options, ...options});
}
init (user) {
this._init(user.spacy_nlp_pipeline_models);
}
onClick(event) {
let actionButtonElement = event.target.closest('.action-button');
let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
let spaCyNLPPipelineModelElement = event.target.closest('tr');
let spaCyNLPPipelineModelId = spaCyNLPPipelineModelElement.dataset.id;
switch (action) {
case 'delete-request': {
Utils.deleteSpaCyNLPPipelineModelRequest(this.userId, spaCyNLPPipelineModelId);
break;
}
case 'view': {
window.location.href = `/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModelId}`;
break;
}
default: {
break;
}
}
}
}

View File

@ -1,76 +0,0 @@
class TesseractOCRModelList {
constructor () {
this.elements = {
tesseractOCRModelList: document.querySelector('#tesseract-ocr-model-list'),
deleteButtons: document.querySelectorAll('.delete-button'),
editButtons: document.querySelectorAll('.edit-button'),
}
}
init () {
let userId = this.elements.tesseractOCRModelList.dataset.userId;
for (let deleteButton of this.elements.deleteButtons) {
deleteButton.addEventListener('click', () => {this.deleteModel(deleteButton, userId);});
}
for (let editButton of this.elements.editButtons) {
editButton.addEventListener('click', () => {this.editModel(editButton);});
}
}
deleteModel(deleteButton, userId) {
return new Promise((resolve, reject) => {
let modelId = deleteButton.dataset.modelId;
let model = app.data.users[userId].tesseract_ocr_pipeline_models[modelId];
let modalElement = Utils.elementFromString(
`
<div class="modal">
<div class="modal-content">
<h4>Confirm job deletion</h4>
<p>Do you really want to delete? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
<a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
</div>
</div>
`
);
document.querySelector('#modals').appendChild(modalElement);
let modal = M.Modal.init(
modalElement,
{
dismissible: false,
onCloseEnd: () => {
modal.destroy();
modalElement.remove();
}
}
);
let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
confirmElement.addEventListener('click', (event) => {
let modelTitle = model.title;
fetch(`/contributions/edit-tesseract-model/${modelId}`, {method: 'DELETE'})
.then(
(response) => {
app.flash(`Model "${modelTitle}" marked for deletion`, 'corpus');
resolve(response);
},
(response) => {
if (response.status === 403) {app.flash('Forbidden', 'error');}
if (response.status === 404) {app.flash('Not Found', 'error');}
reject(response);
}
);
});
modal.open();
});
}
editModel(editButton) {
window.location.href = `/contributions/edit-tesseract-model/${editButton.dataset.modelId}`;
}
}

View File

@ -0,0 +1,99 @@
class TesseractOCRPipelineModelList extends RessourceList {
static autoInit() {
for (let tesseractOCRPipelineModelListElement of document.querySelectorAll('.tesseract-ocr-pipeline-model-list:not(.no-autoinit)')) {
new TesseractOCRPipelineModelList(tesseractOCRPipelineModelListElement);
}
}
static options = {
initialHtmlGenerator: (id) => {
return `
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="${id}-search" class="search" type="search"></input>
<label for="${id}-search">Search Tesseract OCR Pipeline Model</label>
</div>
<table>
<thead>
<tr>
<th>Title</th>
<th>Description</th>
<th>Biblio</th>
<th></th>
</tr>
</thead>
<tbody class="list"></tbody>
</table>
<ul class="pagination"></ul>
`.trim();
},
item: `
<tr class="clickable hoverable">
<td><span class="title"></span></td>
<td><span class="description"></span></td>
<td><a class="publisher-url"><span class="publisher"></span></a> (<span class="publishing-year"></span>), <span class="title-2"></span> <span class="version"></span>, <a class="publishing-url"><span class="publishing-url-2"></span></a></td>
<td class="right-align">
<a class="action-button btn-floating red waves-effect waves-light" data-action="delete-request"><i class="material-icons">delete</i></a>
<a class="action-button btn-floating service-color darken waves-effect waves-light service-2" data-action="view"><i class="material-icons">send</i></a>
</td>
</tr>
`.trim(),
ressourceMapper: (tesseractOCRPipelineModel) => {
return {
'id': tesseractOCRPipelineModel.id,
'creation-date': tesseractOCRPipelineModel.creation_date,
'description': tesseractOCRPipelineModel.description,
'publisher': tesseractOCRPipelineModel.publisher,
'publisher-url': tesseractOCRPipelineModel.publisher_url,
'publishing-url': tesseractOCRPipelineModel.publishing_url,
'publishing-url-2': tesseractOCRPipelineModel.publishing_url,
'publishing-year': tesseractOCRPipelineModel.publishing_year,
'title': tesseractOCRPipelineModel.title,
'title-2': tesseractOCRPipelineModel.title,
'version': tesseractOCRPipelineModel.version
};
},
sortArgs: ['creation-date', {order: 'desc'}],
valueNames: [
{data: ['id']},
{data: ['creation-date']},
{name: 'publisher-url', attr: 'href'},
{name: 'publishing-url', attr: 'href'},
'description',
'publisher',
'publishing-url-2',
'publishing-year',
'title',
'title-2',
'version'
]
};
constructor(listElement, options = {}) {
super(listElement, {...TesseractOCRPipelineModelList.options, ...options});
}
init (user) {
this._init(user.tesseract_ocr_pipeline_models);
}
onClick(event) {
let actionButtonElement = event.target.closest('.action-button');
let action = actionButtonElement === null ? 'view' : actionButtonElement.dataset.action;
let tesseractOCRPipelineModelElement = event.target.closest('tr');
let tesseractOCRPipelineModelId = tesseractOCRPipelineModelElement.dataset.id;
switch (action) {
case 'delete-request': {
Utils.deleteTesseractOCRPipelineModelRequest(this.userId, tesseractOCRPipelineModelId);
break;
}
case 'view': {
window.location.href = `/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModelId}`;
break;
}
default: {
break;
}
}
}
}

View File

@ -84,8 +84,8 @@ class Utils {
`
<div class="modal">
<div class="modal-content">
<h4>Confirm job deletion</h4>
<p>Do you really want to delete the job <b>${corpusFile.title}</b>? All files will be permanently deleted!</p>
<h4>Confirm Corpus File deletion</h4>
<p>Do you really want to delete the Corpus File <b>${corpusFile.title}</b>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
@ -126,6 +126,102 @@ class Utils {
});
}
static deleteSpaCyNLPPipelineModelRequest(userId, spaCyNLPPipelineModelId) {
return new Promise((resolve, reject) => {
let spaCyNLPPipelineModel = app.data.users[userId].spacy_nlp_pipeline_models[spaCyNLPPipelineModelId];
let modalElement = Utils.elementFromString(
`
<div class="modal">
<div class="modal-content">
<h4>Confirm SpaCy NLP Pipeline Model deletion</h4>
<p>Do you really want to delete the SpaCy NLP Pipeline Model <b>${spaCyNLPPipelineModel.title}</b>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
<a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
</div>
</div>
`
);
document.querySelector('#modals').appendChild(modalElement);
let modal = M.Modal.init(
modalElement,
{
dismissible: false,
onCloseEnd: () => {
modal.destroy();
modalElement.remove();
}
}
);
let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
confirmElement.addEventListener('click', (event) => {
let spaCyNLPPipelineModelTitle = spaCyNLPPipelineModel.title;
fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModelId}`, {method: 'DELETE'})
.then(
(response) => {
app.flash(`SpaCy NLP Pipeline Model "${spaCyNLPPipelineModelTitle}" marked for deletion`);
resolve(response);
},
(response) => {
if (response.status === 403) {app.flash('Forbidden', 'error');}
if (response.status === 404) {app.flash('Not Found', 'error');}
reject(response);
}
);
});
modal.open();
});
}
static deleteTesseractOCRPipelineModelRequest(userId, tesseractOCRPipelineModelId) {
return new Promise((resolve, reject) => {
let tesseractOCRPipelineModel = app.data.users[userId].tesseract_ocr_pipeline_models[tesseractOCRPipelineModelId];
let modalElement = Utils.elementFromString(
`
<div class="modal">
<div class="modal-content">
<h4>Confirm Tesseract OCR Pipeline Model deletion</h4>
<p>Do you really want to delete the Tesseract OCR Pipeline Model <b>${tesseractOCRPipelineModel.title}</b>? All files will be permanently deleted!</p>
</div>
<div class="modal-footer">
<a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
<a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
</div>
</div>
`
);
document.querySelector('#modals').appendChild(modalElement);
let modal = M.Modal.init(
modalElement,
{
dismissible: false,
onCloseEnd: () => {
modal.destroy();
modalElement.remove();
}
}
);
let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
confirmElement.addEventListener('click', (event) => {
let tesseractOCRPipelineModelTitle = tesseractOCRPipelineModel.title;
fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModelId}`, {method: 'DELETE'})
.then(
(response) => {
app.flash(`Tesseract OCR Pipeline Model "${tesseractOCRPipelineModelTitle}" marked for deletion`);
resolve(response);
},
(response) => {
if (response.status === 403) {app.flash('Forbidden', 'error');}
if (response.status === 404) {app.flash('Not Found', 'error');}
reject(response);
}
);
});
modal.open();
});
}
static deleteJobRequest(userId, jobId) {
return new Promise((resolve, reject) => {
let job = app.data.users[userId].jobs[jobId];