Unify more tables (Corpus: corpus files view)

This commit is contained in:
Stephan Porada 2020-07-08 15:24:18 +02:00
parent 43f79291aa
commit ea7bb82661
7 changed files with 134 additions and 51 deletions

View File

@ -9,6 +9,7 @@ from .forms import (AddCorpusFileForm, AddCorpusForm, EditCorpusFileForm,
from .. import db from .. import db
from ..models import Corpus, CorpusFile from ..models import Corpus, CorpusFile
import os import os
from .. import logger
@corpora.route('/add', methods=['GET', 'POST']) @corpora.route('/add', methods=['GET', 'POST'])
@ -44,7 +45,17 @@ def corpus(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id) corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.creator == current_user or current_user.is_administrator()): if not (corpus.creator == current_user or current_user.is_administrator()):
abort(403) abort(403)
return render_template('corpora/corpus.html.j2', corpus=corpus, corpus_files = [dict(filename=corpus_file.filename,
author=corpus_file.author,
title=corpus_file.title,
publishing_year=corpus_file.publishing_year,
corpus_id=corpus.id,
id=corpus_file.id
)
for corpus_file in corpus.files]
return render_template('corpora/corpus.html.j2',
corpus=corpus,
corpus_files=corpus_files,
title='Corpus') title='Corpus')
@ -216,7 +227,7 @@ def prepare_corpus(corpus_id):
abort(403) abort(403)
if corpus.files.all(): if corpus.files.all():
tasks.build_corpus(corpus_id) tasks.build_corpus(corpus_id)
flash('Corpus gets build now.', 'corpus') flash('Building Corpus...', 'corpus')
else: else:
flash('Can not build corpus, please add corpus file(s).', 'corpus') flash('Can not build corpus, please add corpus file(s).', 'corpus')
return redirect(url_for('corpora.corpus', corpus_id=corpus_id)) return redirect(url_for('corpora.corpus', corpus_id=corpus_id))

View File

@ -10,6 +10,7 @@ from flask import (abort, render_template, current_app, request, redirect,
from flask_login import current_user, login_required from flask_login import current_user, login_required
import json import json
import os import os
from .. import logger
@results.route('/import_results', methods=['GET', 'POST']) @results.route('/import_results', methods=['GET', 'POST'])
@ -69,7 +70,7 @@ def results_overview():
''' '''
# get all results of current user # get all results of current user
results = User.query.get(current_user.id).results results = User.query.get(current_user.id).results
logger.warning(results)
def __p_time(time_str): def __p_time(time_str):
# helper to convert the datetime into a nice readable string # helper to convert the datetime into a nice readable string
return datetime.strptime(time_str, '%Y-%m-%dT%H:%M:%S.%f') return datetime.strptime(time_str, '%Y-%m-%dT%H:%M:%S.%f')

View File

@ -1,6 +1,7 @@
class RessourceList extends List { class RessourceList extends List {
constructor(idOrElement, subscriberList, type, options={}) { constructor(idOrElement, subscriberList, type, options={}) {
if (!["corpus", "job", "result", "user", "job_input"].includes(type)) { if (!["corpus", "job", "result", "user", "job_input",
"corpus_file"].includes(type)) {
console.error("Unknown Type!"); console.error("Unknown Type!");
return; return;
} }
@ -78,7 +79,17 @@ RessourceList.dataMapper = {
"analyse-link": ["analysing", "prepared", "start analysis"].includes(corpus.status) ? `/corpora/${corpus.id}/analyse` : "", "analyse-link": ["analysing", "prepared", "start analysis"].includes(corpus.status) ? `/corpora/${corpus.id}/analyse` : "",
"edit-link": `/corpora/${corpus.id}`, "edit-link": `/corpora/${corpus.id}`,
status: corpus.status, status: corpus.status,
title: corpus.title}), title: corpus.title
}),
// Mapping for corpus file entities shown in the corpus overview
corpus_file: 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. // Mapping for job entities shown in the dashboard table.
job: job => ({creation_date: job.creation_date, job: job => ({creation_date: job.creation_date,
description: job.description, description: job.description,
@ -86,11 +97,13 @@ RessourceList.dataMapper = {
link: `/jobs/${job.id}`, link: `/jobs/${job.id}`,
service: job.service, service: job.service,
status: job.status, status: job.status,
title: job.title}), title: job.title
}),
// Mapping for job input files shown in table on every job page // Mapping for job input files shown in table on every job page
job_input: job_input => ({filename: job_input.filename, job_input: job_input => ({filename: job_input.filename,
id: job_input.job_id, id: job_input.job_id,
"download-link": `${job_input.job_id}/inputs/${job_input.id}/download`}), "download-link": `${job_input.job_id}/inputs/${job_input.id}/download`
}),
// Mapping for imported result entities from corpus analysis. // Mapping for imported result entities from corpus analysis.
// Shown in imported results table // Shown in imported results table
result: result => ({ query: result.query, result: result => ({ query: result.query,
@ -101,14 +114,16 @@ RessourceList.dataMapper = {
corpus_type : result.corpus_type, corpus_type : result.corpus_type,
"details-link": `${result.id}/details`, "details-link": `${result.id}/details`,
"inspect-link": `${result.id}/inspect`, "inspect-link": `${result.id}/inspect`,
"delete-modal": `delete-result-${result.id}-modal`}), "delete-modal": `delete-result-${result.id}-modal`
}),
// Mapping for user entities shown in admin table // Mapping for user entities shown in admin table
user: user => ({username: user.username, user: user => ({username: user.username,
email: user.email, email: user.email,
role_id: user.role_id, role_id: user.role_id,
confirmed: user.confirmed, confirmed: user.confirmed,
id: user.id, id: user.id,
"profile-link": `user/${user.id}`}) "profile-link": `user/${user.id}`
})
}; };
@ -146,12 +161,12 @@ RessourceList.options = {
<span class="badge new status" data-badge-caption=""> <span class="badge new status" data-badge-caption="">
</span> </span>
</td> </td>
<td class="right-align"> <td class="actions center-align">
<a class="btn-floating edit-link waves-effect waves-light"> <a class="btn-floating edit-link waves-effect waves-light" data-tooltip="Edit">
<i class="material-icons">edit</i> <i class="material-icons">edit</i>
</a> </a>
<a class="btn-floating analyse-link waves-effect waves-light"> <a class="btn-floating analyse-link waves-effect waves-light">
<i class="material-icons right">search</i> <i class="material-icons">search</i>
</a> </a>
</td> </td>
</tr>`, </tr>`,
@ -165,6 +180,42 @@ RessourceList.options = {
{name: "edit-link", attr: "href"}, {name: "edit-link", attr: "href"},
{name: "status", attr: "data-status"}] {name: "status", attr: "data-status"}]
}, },
// Corpus file entity blueprint setting html strucuture per entity per row
// Link classes have to correspond with Links defined in the Mapping process
corpus_file: {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 center-align">
<a class="btn-floating tooltipped edit-link
waves-effect waves-light"
data-position="top"
data-tooltip="Edit">
<i class="material-icons">edit</i>
</a>
<a class="btn-floating tooltipped download-link
waves-effect waves-light"
data-position="top"
data-tooltip="Download">
<i class="material-icons">file_download</i>
</a>
<a class="btn-floating tooltipped modal-trigger red
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 entity blueprint setting html strucuture per entity per row // Job entity blueprint setting html strucuture per entity per row
// Link classes have to correspond with Links defined in the Mapping process // Link classes have to correspond with Links defined in the Mapping process
job: {item: `<tr> job: {item: `<tr>
@ -180,9 +231,9 @@ RessourceList.options = {
<td> <td>
<span class="badge new status" data-badge-caption=""></span> <span class="badge new status" data-badge-caption=""></span>
</td> </td>
<td class="right-align"> <td class="actions center-align">
<a class="btn-floating link waves-effect waves-light"> <a class="btn-floating link waves-effect waves-light">
<i class="material-icons right">send</i> <i class="material-icons">send</i>
</a> </a>
</td> </td>
</tr>`, </tr>`,
@ -198,8 +249,12 @@ RessourceList.options = {
}, },
job_input: {item : `<tr> job_input: {item : `<tr>
<td class="filename"></td> <td class="filename"></td>
<td class="actions"> <td class="actions center-align">
<a class="btn-floating download-link waves-effect waves-light"><i class="material-icons">file_download</i> <a class="btn-floating tooltipped download-link
waves-effect waves-light"
data-position="top"
data-tooltip="Download">
<i class="material-icons">file_download</i>
</a> </a>
</td> </td>
</tr>`, </tr>`,
@ -217,12 +272,24 @@ RessourceList.options = {
<td class="corpus_creation_date"></td> <td class="corpus_creation_date"></td>
<td class="corpus_analysis_date"></td> <td class="corpus_analysis_date"></td>
<td class="corpus_type"></td> <td class="corpus_type"></td>
<td class="actions right-align"> <td class="actions center-align">
<a class="btn-floating details-link waves-effect waves-light"><i class="material-icons">info_outline</i> <a class="btn-floating tooltipped details-link
waves-effect waves-light"
data-position="top"
data-tooltip="Metadata Info">
<i class="material-icons">info_outline</i>
</a> </a>
<a class="btn-floating inspect-link waves-effect waves-light"><i class="material-icons">search</i> <a class="btn-floating tooltipped inspect-link
waves-effect waves-light"
data-position="top"
data-tooltip="View Results">
<i class="material-icons">search</i>
</a> </a>
<a class="btn-floating red delete-modal waves-effect waves-light modal-trigger"><i class="material-icons">delete</i> <a class="btn-floating tooltipped red delete-modal
waves-effect waves-light modal-trigger"
data-position="top"
data-tooltip="Delete">
<i class="material-icons">delete</i>
</a> </a>
</td> </td>
</tr>`, </tr>`,
@ -246,8 +313,12 @@ RessourceList.options = {
<td class="role_id"></td> <td class="role_id"></td>
<td class="confirmed"></td> <td class="confirmed"></td>
<td class="id"></td> <td class="id"></td>
<td class="actions"> <td class="actions center-align">
<a class="btn-floating profile-link waves-effect waves-light"><i class="material-icons">edit</i> <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> </a>
</td> </td>
</tr>`, </tr>`,

View File

@ -59,41 +59,34 @@
<div class="col s12"> <div class="col s12">
<div class="card"> <div class="card">
<div class="card-content" style="overflow: hidden;"> <div class="card-content" id="corpus-files" style="overflow: hidden;">
<span class="card-title">Files</span> <span class="card-title">Files</span>
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="search-results" class="search" type="search"></input>
<label for="search-results">Search results</label>
</div>
<ul class="pagination paginationTop"></ul>
<table class="highlight responsive-table"> <table class="highlight responsive-table">
<thead> <thead>
<tr> <tr>
<th>Filename</th> <th class="sort" data-sort="filename">Filename</th>
<th>Author</th> <th class="sort" data-sort="author">Author</th>
<th>Title</th> <th class="sort" data-sort="title">Title</th>
<th>Publishing year</th> <th class="sort" data-sort="publishing_year">Publishing year</th>
<th></th> <th>{# Actions #}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody class="list">
<tr class="show-if-only-child"> <tr class="show-if-only-child">
<td colspan="5"> <td colspan="5">
<span class="card-title"><i class="material-icons left">book</i>Nothing here...</span> <span class="card-title"><i class="material-icons left">book</i>Nothing here...</span>
<p>Corpus is empty. Add texts using the option below.</p> <p>Corpus is empty. Add texts using the option below.</p>
</td> </td>
</tr> </tr>
{% for file in corpus.files %}
<tr>
<td style="word-break: break-word;">{{ file.filename }}</td>
<td style="word-break: break-word;">{{ file.author }}</td>
<td style="word-break: break-word;">{{ file.title }}</td>
<td>{{ file.publishing_year }}</td>
<td class="right-align">
<a class="btn-floating waves-effect waves-light" href="{{ url_for('corpora.edit_corpus_file', corpus_file_id=file.id, corpus_id=corpus.id) }}"><i class="material-icons">edit</i></a>
<a class="btn-floating waves-effect waves-light" href="{{ url_for('corpora.download_corpus_file', corpus_file_id=file.id, corpus_id=corpus.id) }}"><i class="material-icons">file_download</i></a>
<a data-target="delete-corpus-file-{{ file.id }}-modal" class="btn-floating modal-trigger red waves-effect waves-light"><i class="material-icons">delete</i></a>
</td>
</tr>
{% endfor %}
</tbody> </tbody>
</table> </table>
<ul class="pagination paginationBottom"></ul>
</div> </div>
<div class="card-action right-align"> <div class="card-action right-align">
<a href="{{ url_for('corpora.add_corpus_file', corpus_id=corpus.id) }}" class="btn waves-effect waves-light"><i class="material-icons left">add</i>Add corpus file</a> <a href="{{ url_for('corpora.add_corpus_file', corpus_id=corpus.id) }}" class="btn waves-effect waves-light"><i class="material-icons left">add</i>Add corpus file</a>
@ -129,6 +122,11 @@
<script> <script>
// create corpus file table
var ressources = {{ corpus_files|tojson|safe }};
var corpusFilesList = new RessourceList("corpus-files", null, "corpus_file");
corpusFilesList.addRessources(ressources);
class InformationUpdater { class InformationUpdater {
constructor(corpusId, foreignCorpusFlag) { constructor(corpusId, foreignCorpusFlag) {
this.corpusId = corpusId; this.corpusId = corpusId;

View File

@ -120,7 +120,7 @@
<tr> <tr>
<th>Result Type</th> <th>Result Type</th>
<th>Archive Name</th> <th>Archive Name</th>
<th>Download</th> <th>{# Actions #}</th>
</tr> </tr>
</thead> </thead>
<tbody class="results"> <tbody class="results">
@ -159,7 +159,6 @@
<script> <script>
// job_input_table code // job_input_table code
var ressources = {{ job_inputs|tojson|safe }}; var ressources = {{ job_inputs|tojson|safe }};
console.log(ressources);
var jobInputsList = new RessourceList("inputs", null, "job_input"); var jobInputsList = new RessourceList("inputs", null, "job_input");
jobInputsList.addRessources(ressources); jobInputsList.addRessources(ressources);
@ -244,9 +243,12 @@
<tr> <tr>
<td>${resultType}</td> <td>${resultType}</td>
<td>${result.filename}</td> <td>${result.filename}</td>
<td> <td class="center-align">
<a class="btn-floating waves-effect waves-light" download href="/jobs/${result.job_id}/results/${result.id}/download"> <a class="btn-floating tooltipped waves-effect waves-light"
<i class="material-icons left">file_download</i> download href="/jobs/${result.job_id}/results/${result.id}/download"
data-position="top"
data-tooltip="Download">
<i class="material-icons">file_download</i>
</a> </a>
</td> </td>
</tr> </tr>

View File

@ -85,7 +85,8 @@
</button> </button>
{% endmacro %} {% endmacro %}
{% macro delete_modal_file(file) %} {# maybe create a modal template later on for actions like delete etc #}
{# {% macro delete_modal_file(file) %}
<div id="delete-corpus-file-{{ file.id }}-modal" class="modal"> <div id="delete-corpus-file-{{ file.id }}-modal" class="modal">
<div class="modal-content"> <div class="modal-content">
<h4>Confirm corpus file deletion</h4> <h4>Confirm corpus file deletion</h4>
@ -96,4 +97,4 @@
<a class="btn modal-close red waves-effect waves-light" href="{{ url_for('corpora.delete_corpus_file', corpus_file_id=resource_id, corpus_id=corpus.id) }}"><i class="material-icons left">delete</i>Delete</a> <a class="btn modal-close red waves-effect waves-light" href="{{ url_for('corpora.delete_corpus_file', corpus_file_id=resource_id, corpus_id=corpus.id) }}"><i class="material-icons left">delete</i>Delete</a>
</div> </div>
</div> </div>
{% endmacro %} {% endmacro %} #}

View File

@ -8,7 +8,6 @@ Flask-Migrate
Flask-Paranoid Flask-Paranoid
Flask-SocketIO Flask-SocketIO
Flask-SQLAlchemy Flask-SQLAlchemy
Flask-Table
Flask-WTF Flask-WTF
jsonpatch jsonpatch
psycopg2 psycopg2