Sort lists by ressources creation date. CSS and HTML cleanup

This commit is contained in:
Patrick Jentsch 2021-12-03 12:01:50 +01:00
parent 03a57fd7ee
commit 89f518fe38
14 changed files with 226 additions and 246 deletions

View File

@ -31,68 +31,10 @@
height: 30px !important;
}
/* flat-interaction addition to show background color */
.flat-interaction {
background-color: #DCDCDC;
width: 100%;
margin-bottom: 3px;
text-transform: capitalize;
}
.flat-interaction:hover {
background-color: #E6E6FA !important;
}
/* CSS for clickable th elements in tables. Needed for sortable table data with
list js. On click on th header elements will be sorted accordingly. Also a caret
indicator will show up how the column is sorted right now.; */
.sort {
cursor: pointer;
}
.sort:after {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid transparent;
content:"";
position: relative;
top:-10px;
right:-5px;
}
.sort.asc:after {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #000000;
content:"";
position: relative;
top:13px;
right:-5px;
}
.sort.desc:after {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid #000000;
content:"";
position: relative;
top:-10px;
right:-5px;
}
.show-if-only-child:not(:only-child) {
display: none !important;
}
/* class for expert view */
.expert-view {
cursor: pointer;
}
.btn-scale-x2 {
transform: scale(2);
}

View File

@ -13,7 +13,25 @@ class CorpusFileList extends RessourceList {
</td>
</tr>
`.trim(),
valueNames: [{data: ['id']}, 'author', 'filename', 'publishing_year', 'title']
ressourceMapper: corpusFile => {
return {
id: corpusFile.id,
author: corpusFile.author,
creationDate: corpusFile.creation_date,
filename: corpusFile.filename,
publishingYear: corpusFile.publishing_year,
title: corpusFile.title
};
},
sortValueName: 'creationDate',
valueNames: [
{data: ['id']},
{data: ['creationDate']},
'author',
'filename',
'publishingYear',
'title'
]
};
@ -115,15 +133,4 @@ class CorpusFileList extends RessourceList {
}
}
}
preprocessRessource(corpusFile) {
return {
id: corpusFile.id,
author: corpusFile.author,
creationDate: corpusFile.creation_date,
filename: corpusFile.filename,
publishing_year: corpusFile.publishing_year,
title: corpusFile.title
};
}
}

View File

@ -11,7 +11,23 @@ class CorpusList extends RessourceList {
</td>
</tr>
`.trim(),
valueNames: [{data: ['id']}, {name: 'status', attr: 'data-status'}, 'description', 'title']
ressourceMapper: corpus => {
return {
id: corpus.id,
creationDate: corpus.creation_date,
description: corpus.description,
status: corpus.status,
title: corpus.title
};
},
sortValueName: 'creationDate',
valueNames: [
{data: ['id']},
{data: ['creationDate']},
{name: 'status', attr: 'data-status'},
'description',
'title'
]
};
@ -107,14 +123,4 @@ class CorpusList extends RessourceList {
}
}
}
preprocessRessource(corpus) {
return {
id: corpus.id,
creationDate: corpus.creation_date,
description: corpus.description,
status: corpus.status,
title: corpus.title
};
}
}

View File

@ -8,7 +8,15 @@ class JobInputList extends RessourceList {
</td>
</tr>
`.trim(),
valueNames: [{data: ['id']}, 'filename']
ressourceMapper: jobInput => {
return {
id: jobInput.id,
creationDate: jobInput.creation_date,
filename: jobInput.filename
};
},
sortValueName: 'creationDate',
valueNames: [{data: ['id']}, {data: ['creationDate']}, 'filename']
};
@ -43,12 +51,4 @@ class JobInputList extends RessourceList {
}
usersPatchHandler(patch) {return;}
preprocessRessource(jobInput) {
return {
id: jobInput.id,
creationDate: jobInput.creation_date,
filename: jobInput.filename
};
}
}

View File

@ -1,17 +1,39 @@
class JobList extends RessourceList {
static options = {
item: `
<tr>
<td><a class="btn-floating disabled"><i class="nopaque-icons service service-color darken service-icon"></i></a></td>
<tr class="service-color lighten">
<td><a class="btn-floating disabled"><i class="nopaque-icons service-color darken serviceDuplicate1 service-icon"></i></a></td>
<td><b class="title"></b><br><i class="description"></i></td>
<td><span class="badge new status status-color status-text" 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>
<a class="action-button btn-floating serviceDuplicate2 service-color darken tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
</td>
</tr>
`.trim(),
valueNames: [{data: ['id']}, {name: 'service', attr: 'data-service'}, {name: 'status', attr: 'data-status'}, 'description', 'title']
ressourceMapper: job => {
return {
id: job.id,
creationDate: job.creation_date,
description: job.description,
service: job.service,
serviceDuplicate1: job.service,
serviceDuplicate2: job.service,
status: job.status,
title: job.title
};
},
sortValueName: 'creationDate',
valueNames: [
{data: ['id']},
{data: ['creationDate']},
{data: ['service']},
{name: 'serviceDuplicate1', attr: 'data-service'},
{name: 'serviceDuplicate2', attr: 'data-service'},
{name: 'status', attr: 'data-status'},
'description',
'title'
]
};
@ -109,15 +131,4 @@ class JobList extends RessourceList {
}
}
}
preprocessRessource(job) {
return {
id: job.id,
creationDate: job.creation_date,
description: job.description,
service: job.service,
status: job.status,
title: job.title
};
}
}

View File

@ -9,7 +9,36 @@ class JobResultList extends RessourceList {
</td>
</tr>
`.trim(),
valueNames: [{data: ['id']}, 'description', 'filename']
ressourceMapper: jobResult => {
let description;
if (jobResult.filename.endsWith('.pdf.zip')) {
description = 'PDF files with text layer';
} else if (jobResult.filename.endsWith('.txt.zip')) {
description = 'Raw text files';
} else if (jobResult.filename.endsWith('.vrt.zip')) {
description = 'VRT compliant files including the NLP data';
} else if (jobResult.filename.endsWith('.xml.zip')) {
description = 'TEI compliant files';
} else if (jobResult.filename.endsWith('.poco.zip')) {
description = 'HOCR and image files for post correction (PoCo)';
} else {
description = 'All result files created during this job';
}
return {
id: jobResult.id,
creationDate: jobResult.creation_date,
description: description,
filename: jobResult.filename
};
},
sortValueName: 'creationDate',
valueNames: [
{data: ['id']},
{data: ['creationDate']},
'description',
'filename'
]
};
@ -63,28 +92,4 @@ class JobResultList extends RessourceList {
}
}
}
preprocessRessource(jobResult) {
let description;
if (jobResult.filename.endsWith('.pdf.zip')) {
description = 'PDF files with text layer';
} else if (jobResult.filename.endsWith('.txt.zip')) {
description = 'Raw text files';
} else if (jobResult.filename.endsWith('.vrt.zip')) {
description = 'VRT compliant files including the NLP data';
} else if (jobResult.filename.endsWith('.xml.zip')) {
description = 'TEI compliant files';
} else if (jobResult.filename.endsWith('.poco.zip')) {
description = 'HOCR and image files for post correction (PoCo)';
} else {
description = 'All result files created during this job';
}
return {
id: jobResult.id,
creationDate: jobResult.creation_date,
description: description,
filename: jobResult.filename
};
}
}

View File

@ -10,7 +10,25 @@ class QueryResultList extends RessourceList {
</td>
</tr>
`.trim(),
valueNames: [{data: ['id']}, 'corpus_title', 'description', 'query', 'title']
ressourceMapper: queryResult => {
return {
id: queryResult.id,
corpusTitle: queryResult.corpus_title,
creationDate: queryResult.creation_date,
description: queryResult.description,
query: queryResult.query,
title: queryResult.title
};
},
sortValueName: 'creationDate',
valueNames: [
{data: ['id']},
{data: ['creationDate']},
'corpusTitle',
'description',
'query',
'title'
]
};
@ -108,15 +126,4 @@ class QueryResultList extends RessourceList {
}
}
}
preprocessRessource(queryResult) {
return {
id: queryResult.id,
corpus_title: queryResult.corpus_title,
creationDate: queryResult.creation_date,
description: queryResult.description,
query: queryResult.query,
title: queryResult.title
};
}
}

View File

@ -35,7 +35,7 @@ class RessourceList {
}
}
}
static options = {page: 5, pagination: [{innerWindow: 4, outerWindow: 1}]};
static options = {page: 5, pagination: {innerWindow: 4, outerWindow: 1}};
constructor(listElement, options = {}) {
@ -48,6 +48,18 @@ class RessourceList {
break;
}
}
options = {
...{pagination: {item: `<li><a class="page" href="#${listElement.id}"></a></li>`}},
...options
}
if ('ressourceMapper' in options) {
this.ressourceMapper = options.ressourceMapper;
delete options.ressourceMapper;
}
if ('sortValueName' in options) {
this.sortValueName = options.sortValueName;
delete options.sortValueName;
}
this.listjs = new List(listElement, {...RessourceList.options, ...options});
this.listjs.list.innerHTML = `
<tr>
@ -107,11 +119,16 @@ class RessourceList {
preprocessRessource() {throw 'Not implemented'}
add(values) {
let ressources = Array.isArray(values) ? values : [values];
ressources = ressources.map(ressource => this.preprocessRessource(ressource));
this.listjs.add(ressources, () => {
this.listjs.sort('id', {order: 'desc'});
add(ressources) {
let values = Array.isArray(ressources) ? ressources : [ressources];
if ('ressourceMapper' in this) {
values = values.map(value => this.ressourceMapper(value));
}
this.listjs.add(values, () => {
if ('sortValueName' in this) {
this.listjs.sort(this.sortValueName, {order: 'desc'});
}
});
}

View File

@ -2,7 +2,7 @@ class UserList extends RessourceList {
static options = {
item: `
<tr>
<td><span class="id_"></span></td>
<td><span class="idDuplicate"></span></td>
<td><span class="username"></span></td>
<td><span class="email"></span></td>
<td><span class="last_seen"></span></td>
@ -14,7 +14,26 @@ class UserList extends RessourceList {
</td>
</tr>
`.trim(),
valueNames: [{data: ['id']}, 'id_', 'username', 'email', 'last_seen', 'role']
ressourceMapper: user => {
return {
id: user.id,
idDuplicate: user.id,
username: user.username,
email: user.email,
last_seen: new Date(user.last_seen).toLocaleString("en-US"),
role: user.role.name
};
},
sortValueName: 'memberSince',
valueNames: [
{data: ['id']},
{data: ['memberSince']},
'email',
'idDuplicate',
'last_seen',
'role',
'username'
]
};
@ -78,15 +97,4 @@ class UserList extends RessourceList {
break;
}
}
preprocessRessource(user) {
return {
id: user.id,
id_: user.id,
username: user.username,
email: user.email,
last_seen: new Date(user.last_seen).toLocaleString("en-US"),
role: user.role.name
};
}
}

View File

@ -37,58 +37,54 @@
</div>
</div>
<div class="col s12 l6 nopaque-ressource-list" data-ressource-type="Job" data-user-id="{{ user.hashid }}">
<h3>Corpora</h3>
<div class="card">
<div class="card-content">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="search-corpus" class="search" type="search"></input>
<label for="search-corpus">Search corpus</label>
<div class="col s12 l6 nopaque-ressource-list" data-ressource-type="Corpus" data-user-id="{{ user.hashid }}">
<h3>Corpora</h3>
<div class="card">
<div class="card-content">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="search-corpus" class="search" type="search"></input>
<label for="search-corpus">Search corpus</label>
</div>
<table class="highlight ressource-list">
<thead>
<tr>
<th></th>
<th>Title and Description</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody class="list"></tbody>
</table>
<ul class="pagination"></ul>
</div>
</div>
<table class="highlight ressource-list">
<thead>
<tr>
<th></th>
<th>
<span class="sort" data-sort="title">Title</span>
<span class="sort" data-sort="description">Description</span>
</th>
<th><span class="sort" data-sort="status">Status</span></th>
<th></th>
</tr>
</thead>
<tbody class="list"></tbody>
</table>
<ul class="pagination"></ul>
</div>
</div>
</div>
<div class="col s12 l6 nopaque-ressource-list" data-ressource-type="Job" data-user-id="{{ user.hashid }}">
<h3>Jobs</h3>
<div class="card">
<div class="card-content">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="search-job" class="search" type="search"></input>
<label for="search-job">Search job</label>
<div class="col s12 l6 nopaque-ressource-list" data-ressource-type="Job" data-user-id="{{ user.hashid }}">
<h3>Jobs</h3>
<div class="card">
<div class="card-content">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="search-job" class="search" type="search"></input>
<label for="search-job">Search job</label>
</div>
<table class="highlight">
<thead>
<tr>
<th>Service</th>
<th>Title and Description</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody class="list"></tbody>
</table>
<ul class="pagination"></ul>
</div>
</div>
<table class="highlight">
<thead>
<tr>
<th><span class="sort" data-sort="service">Service</span></th>
<th>
<span class="sort" data-sort="title">Title</span>
<span class="sort" data-sort="description">Description</span>
</th>
<th><span class="sort" data-sort="status">Status</span></th>
<th></th>
</tr>
</thead>
<tbody class="list"></tbody>
</table>
<ul class="pagination"></ul>
</div>
</div>
</div>

View File

@ -19,11 +19,11 @@
<table class="highlight">
<thead>
<tr>
<th class="sort" data-sort="id">Id</th>
<th class="sort" data-sort="username">Username</th>
<th class="sort" data-sort="email">Email</th>
<th class="sort" data-sort="last_seen">Last seen</th>
<th class="sort" data-sort="role">Role</th>
<th>Id</th>
<th>Username</th>
<th>Email</th>
<th>Last seen</th>
<th>Role</th>
<th></th>
</tr>
</thead>

View File

@ -84,10 +84,10 @@
<table class="highlight responsive-table">
<thead>
<tr>
<th class="sort" data-sort="filename">Filename</th>
<th class="sort" data-sort="author">Author</th>
<th class="sort" data-sort="title">Title</th>
<th class="sort" data-sort="publishing-year">Publishing year</th>
<th>Filename</th>
<th>Author</th>
<th>Title</th>
<th>Publishing year</th>
<th></th>
</tr>
</thead>

View File

@ -99,7 +99,7 @@
<table class="highlight responsive-table">
<thead>
<tr>
<th class="sort" data-sort="filename">Filename</th>
<th>Filename</th>
<th></th>
</tr>
</thead>

View File

@ -30,11 +30,8 @@
<thead>
<tr>
<th></th>
<th>
<span class="sort" data-sort="title">Title</span>
<span class="sort" data-sort="description">Description</span>
</th>
<th><span class="sort" data-sort="status">Status</span></th>
<th>Title and Description</th>
<th>Status</th>
<th></th>
</tr>
</thead>
@ -59,25 +56,12 @@
<table class="highlight">
<thead>
<tr>
<th>
<span class="sort" data-sort="title">Title</span> and<br>
<span class="sort" data-sort="description">Description</span>
</th>
<th>
<span class="sort" data-sort="corpus">Corpus</span> and<br>
<span class="sort" data-sort="query">Query</span>
</th>
<th>Title and Description</th>
<th>Corpus and Query</th>
<th></th>
</tr>
</thead>
<tbody class="list">
<tr class="show-if-only-child">
<td colspan="5">
<span class="card-title"><i class="material-icons left">folder</i>Nothing here...</span>
<p>No query results yet imported.</p>
</td>
</tr>
</tbody>
<tbody class="list"></tbody>
</table>
<ul class="pagination"></ul>
</div>
@ -102,12 +86,9 @@
<table class="highlight">
<thead>
<tr>
<th><span class="sort" data-sort="service">Service</span></th>
<th>
<span class="sort" data-sort="title">Title</span>
<span class="sort" data-sort="description">Description</span>
</th>
<th><span class="sort" data-sort="status">Status</span></th>
<th>Service</th>
<th>Title and Description</th>
<th>Status</th>
<th></th>
</tr>
</thead>