mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-11-15 01:05:42 +00:00
Update News page
This commit is contained in:
parent
69152f5e6a
commit
a413b41dfd
@ -30,11 +30,11 @@ class RessourceList {
|
|||||||
...{pagination: {item: `<li><a class="page" href="#${listElement.id}"></a></li>`}},
|
...{pagination: {item: `<li><a class="page" href="#${listElement.id}"></a></li>`}},
|
||||||
...options
|
...options
|
||||||
}
|
}
|
||||||
if ('ressourceMapper' in options) {
|
if ('ressourceMapper' in options && typeof options.ressourceMapper === 'function') {
|
||||||
this.ressourceMapper = options.ressourceMapper;
|
this.ressourceMapper = options.ressourceMapper;
|
||||||
delete options.ressourceMapper;
|
delete options.ressourceMapper;
|
||||||
}
|
}
|
||||||
if ('initialHtmlGenerator' in options) {
|
if ('initialHtmlGenerator' in options && typeof options.initialHtmlGenerator === 'function') {
|
||||||
this.initialHtmlGenerator = options.initialHtmlGenerator;
|
this.initialHtmlGenerator = options.initialHtmlGenerator;
|
||||||
listElement.innerHTML = this.initialHtmlGenerator(listElement.id);
|
listElement.innerHTML = this.initialHtmlGenerator(listElement.id);
|
||||||
delete options.initialHtmlGenerator;
|
delete options.initialHtmlGenerator;
|
||||||
|
102
app/static/js/XMLtoObject.js
Normal file
102
app/static/js/XMLtoObject.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* XMLtoObject - Converts XML into a JavaScript value or object.
|
||||||
|
* GitHub: https://github.com/Pevtrick/XMLtoObject
|
||||||
|
* by Patrick Jentsch: https://github.com/Pevtrick
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The XMLDocument.toObject() method converts the XMLDocument into a JavaScript value or object.
|
||||||
|
* @param {String} [attributePrefix=] - A Prefix, which is added to all properties generated by XML attributes.
|
||||||
|
* @returns {Object} - The converted result.
|
||||||
|
*/
|
||||||
|
XMLDocument.prototype.toObject = function(attributePrefix='') {
|
||||||
|
let obj = {};
|
||||||
|
|
||||||
|
obj[this.documentElement.nodeName] = this.documentElement.toObject(attributePrefix);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Node.toObject() method converts the Node into a JavaScript value or object.
|
||||||
|
* @param {String} [attributePrefix=] - A Prefix, which is added to all properties generated by XML attributes.
|
||||||
|
* @returns {Object|String|null} - The converted result.
|
||||||
|
*/
|
||||||
|
Node.prototype.toObject = function(attributePrefix='') {
|
||||||
|
let obj = null;
|
||||||
|
|
||||||
|
switch (this.nodeType) {
|
||||||
|
case Node.ELEMENT_NODE:
|
||||||
|
let hasAttributes = this.attributes.length > 0;
|
||||||
|
let hasChildNodes = this.childNodes.length > 0;
|
||||||
|
|
||||||
|
/* Stop conversion if the Node doesn't contain any attributes or child nodes */
|
||||||
|
if (!(hasAttributes || hasChildNodes)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = {};
|
||||||
|
|
||||||
|
/* Convert attributes */
|
||||||
|
for (let attribute of this.attributes) {
|
||||||
|
obj[`attributePrefix${attribute.name}`] = attribute.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert child nodes */
|
||||||
|
for (let childNode of this.childNodes) {
|
||||||
|
switch (childNode.nodeType) {
|
||||||
|
case Node.ELEMENT_NODE:
|
||||||
|
break;
|
||||||
|
case Node.TEXT_NODE:
|
||||||
|
/* Check whether the child text node is the only child of the current node. */
|
||||||
|
if (!hasAttributes && this.childNodes.length === 1) {
|
||||||
|
obj = childNode.toObject(attributePrefix);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (childNode.data.trim() === '') {continue;}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* This recursion leads to a console message. */
|
||||||
|
childNode.toObject(attributePrefix);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* If the child node is the first of its type in this childset,
|
||||||
|
* process it and add it directly as a property to the return object.
|
||||||
|
* If not add it to an array which is set as a property of the return object.
|
||||||
|
*/
|
||||||
|
if (childNode.nodeName in obj) {
|
||||||
|
if (!Array.isArray(obj[childNode.nodeName])) {
|
||||||
|
obj[childNode.nodeName] = [obj[childNode.nodeName]];
|
||||||
|
}
|
||||||
|
obj[childNode.nodeName].push(childNode.toObject(attributePrefix));
|
||||||
|
} else {
|
||||||
|
obj[childNode.nodeName] = childNode.toObject(attributePrefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Node.TEXT_NODE:
|
||||||
|
if (this.data.trim() !== '') {obj = this.data;}
|
||||||
|
break;
|
||||||
|
case Node.COMMENT_NODE:
|
||||||
|
console.log('Skipping comment node:');
|
||||||
|
console.log(node);
|
||||||
|
break;
|
||||||
|
case Node.DOCUMENT_NODE:
|
||||||
|
obj = {};
|
||||||
|
obj[this.documentElement.nodeName] = this.documentElement.toObject(attributePrefix);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/**
|
||||||
|
* The following node types are not processed because they don't offer data, which has to be stored in the object:
|
||||||
|
* Node.PROCESSING_INSTRUCTION_NODE, Node.DOCUMENT_TYPE_NODE, Node.DOCUMENT_FRAGMENT_NODE
|
||||||
|
* The following node types are deprecated and therefore not supported by this function:
|
||||||
|
* Node.ATTRIBUTE_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, Node.ENTITY_NODE, Node.NOTATION_NODE
|
||||||
|
*/
|
||||||
|
console.log(`Node type: '${this.nodeType}' is not supported.`);
|
||||||
|
console.log(node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
@ -26,7 +26,8 @@
|
|||||||
'js/RessourceLists/JobResultList.js',
|
'js/RessourceLists/JobResultList.js',
|
||||||
'js/RessourceLists/SpacyNLPPipelineModelList.js',
|
'js/RessourceLists/SpacyNLPPipelineModelList.js',
|
||||||
'js/RessourceLists/TesseractOCRPipelineModelList.js',
|
'js/RessourceLists/TesseractOCRPipelineModelList.js',
|
||||||
'js/RessourceLists/UserList.js'
|
'js/RessourceLists/UserList.js',
|
||||||
|
'js/XMLtoObject.js'
|
||||||
%}
|
%}
|
||||||
<script src="{{ ASSET_URL }}"></script>
|
<script src="{{ ASSET_URL }}"></script>
|
||||||
{%- endassets %}
|
{%- endassets %}
|
||||||
@ -52,7 +53,7 @@
|
|||||||
|
|
||||||
// Initialize components
|
// Initialize components
|
||||||
M.AutoInit();
|
M.AutoInit();
|
||||||
M.CharacterCounter.init(document.querySelectorAll('input[data-length][type="text"], input[data-length][type="email"], input[data-length][type="search"], input[data-length][type="password"], input[data-length][type="tel"], input[data-length][type="url"], textarea[data-length]'));
|
M.CharacterCounter.init(document.querySelectorAll('input[data-length], textarea[data-length]'));
|
||||||
M.Dropdown.init(
|
M.Dropdown.init(
|
||||||
document.querySelectorAll('#nav-more-dropdown-trigger'),
|
document.querySelectorAll('#nav-more-dropdown-trigger'),
|
||||||
{alignment: 'right', constrainWidth: false, coverTrigger: false}
|
{alignment: 'right', constrainWidth: false, coverTrigger: false}
|
||||||
|
@ -1,30 +1,46 @@
|
|||||||
{% extends "base.html.j2" %}
|
{% extends "base.html.j2" %}
|
||||||
|
|
||||||
|
{% block main_attribs %} class="service-scheme" data-service="corpus-analysis"{% endblock main_attribs %}
|
||||||
|
|
||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
<div class="parallax-container">
|
<div class="corpus-list no-autoinit" id="corpus-list">
|
||||||
|
<div class="parallax-container">
|
||||||
<div class="parallax"><img src="{{ url_for('static', filename='images/parallax_hq/canvas.png') }}"></div>
|
<div class="parallax"><img src="{{ url_for('static', filename='images/parallax_hq/canvas.png') }}"></div>
|
||||||
<div style="position: absolute; bottom: 0; width: 100%;">
|
<div style="position: absolute; bottom: 0; width: 100%;">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="white-text">
|
<div class="white-text">
|
||||||
<h1 id="title"><i class="nopaque-icons" style="font-size: inherit;">I</i>Corpora</h1>
|
<h1 id="title"><i class="nopaque-icons" style="font-size: inherit;">I</i>Corpora</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="white" style="padding: 0 15px; border-radius: 20px;">
|
<div class="white" style="padding: 1px 35px 0 10px; border-radius: 35px;">
|
||||||
<div class="input-field">
|
<div class="input-field">
|
||||||
<i class="material-icons prefix">search</i>
|
<i class="material-icons prefix">search</i>
|
||||||
<input id="public-corpora-search" placeholder="Find public corpora" type="text">
|
<input class="search" id="corpus-list-search" type="text">
|
||||||
|
<label for="corpus-list-search">Search corpus</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12" id="corpora">
|
<div class="col s12" id="corpora">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="corpus-list"></div>
|
<div>
|
||||||
|
<table>
|
||||||
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -36,9 +52,21 @@
|
|||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script>
|
<script>
|
||||||
let publicCorporaSearchElement = document.querySelector('#public-corpora-search');
|
let corpusListElement = document.querySelector('#corpus-list');
|
||||||
let corpusList = CorpusList.getInstance(document.querySelector('#corpora .corpus-list .list'));
|
let corpusListOptions = {
|
||||||
publicCorporaSearchElement.addEventListener('keyup', function() {corpusList.listjs.search(this.value);});
|
initialHtmlGenerator: null,
|
||||||
|
item: `
|
||||||
|
<tr class="clickable hoverable">
|
||||||
|
<td><a class="btn-floating disabled"><i class="material-icons service-color darken" data-service="corpus-analysis">book</i></a></td>
|
||||||
|
<td><b class="title"></b><br><i class="description"></i></td>
|
||||||
|
<td><span class="status badge new corpus-status-color corpus-status-text" data-badge-caption=""></span></td>
|
||||||
|
<td class="right-align">
|
||||||
|
<a class="action-button btn-floating service-color darken waves-effect waves-light" data-action="view" data-service="corpus-analysis"><i class="material-icons">send</i></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`.trim(),
|
||||||
|
};
|
||||||
|
let corpusList = new CorpusList(corpusListElement, corpusListOptions);
|
||||||
corpusList._init({{ corpora|tojson }});
|
corpusList._init({{ corpora|tojson }});
|
||||||
</script>
|
</script>
|
||||||
{% endblock scripts %}
|
{% endblock scripts %}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
<div id="mastodon"></div>
|
<div id="aggregated-news"></div>
|
||||||
|
|
||||||
<div class="card" id="april-2022-update">
|
<div class="card" id="april-2022-update">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
@ -132,28 +132,115 @@
|
|||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script>
|
<script>
|
||||||
let mastodonElement = document.querySelector('#mastodon');
|
function getMastodonStatuses() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
fetch(`https://fedihum.org/api/v1/accounts/109386364241901080/statuses`, {method: 'GET', headers: {Accept: 'application/json'}})
|
fetch(`https://fedihum.org/api/v1/accounts/109386364241901080/statuses`, {method: 'GET', headers: {Accept: 'application/json'}})
|
||||||
.then((response) => {return response.json();})
|
.then((response) => {
|
||||||
.then((statuses) => {
|
if (!response.ok) {reject(response);}
|
||||||
for (let status of statuses) {
|
return response.json();
|
||||||
console.log(status);
|
})
|
||||||
let contentHtml = `<div>${status.content}</div>`
|
.then((statuses) => {resolve(statuses);})
|
||||||
let tagsHtml = '<p>';
|
});
|
||||||
for (let tag of status.tags) {
|
|
||||||
tagsHtml += `<a href="${tag.url}" class="chip">${tag.name}</a>`;
|
|
||||||
}
|
}
|
||||||
tagsHtml += '</p>';
|
function getBisBlogsEntries() {
|
||||||
let statusHtml = `
|
return new Promise((resolve, reject) => {
|
||||||
<div id="${status.id}" class="card">
|
fetch(`https://blogs.uni-bielefeld.de/blog/uniintern/feed/entries/atom?cat=%2FAllgemein`, {method: 'GET', headers: {Accept: 'application/xml'}})
|
||||||
|
.then((response) => {
|
||||||
|
if (!response.ok) {reject(response);}
|
||||||
|
return response.text();
|
||||||
|
})
|
||||||
|
.then((responseText) => {return new DOMParser().parseFromString(responseText, 'application/xml');})
|
||||||
|
.then((xmlDocument) => {return xmlDocument.toObject();})
|
||||||
|
.then((feed) => {resolve(feed);});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function sortAggregatedNews(a, b) {
|
||||||
|
let aDate;
|
||||||
|
let bDate;
|
||||||
|
|
||||||
|
switch (a.source) {
|
||||||
|
case 'mastodon':
|
||||||
|
aDate = new Date(a.created_at);
|
||||||
|
break;
|
||||||
|
case 'big-blogs':
|
||||||
|
aDate = new Date(a.published);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('Unknown source');
|
||||||
|
}
|
||||||
|
switch (b.source) {
|
||||||
|
case 'mastodon':
|
||||||
|
bDate = new Date(b.created_at);
|
||||||
|
break;
|
||||||
|
case 'big-blogs':
|
||||||
|
bDate = new Date(b.published);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('Unknown source');
|
||||||
|
}
|
||||||
|
return bDate - aDate;
|
||||||
|
}
|
||||||
|
function aggregateNews() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
Promise.all([getMastodonStatuses(), getBisBlogsEntries()])
|
||||||
|
.then(
|
||||||
|
(responses) => {
|
||||||
|
console.log(responses[1]);
|
||||||
|
let mastodonStatuses = responses[0].map((obj) => {return { ...obj, source: 'mastodon'}});
|
||||||
|
let bisBlogsEntries = responses[1].feed.entry.map((obj) => {return { ...obj, source: 'big-blogs'};});
|
||||||
|
let aggregatedNews = [...mastodonStatuses, ...bisBlogsEntries];
|
||||||
|
aggregatedNews.sort(sortAggregatedNews);
|
||||||
|
resolve(aggregatedNews);
|
||||||
|
},
|
||||||
|
(error) => {reject(error);}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function mastodonStatusToHtml(status) {
|
||||||
|
return htmlString = `
|
||||||
|
<div class="card white-text" style="background-color:#5D50E7;">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<span class="card-title">Mastodon News</span>
|
<span class="card-title">New Actitvity on Mastodon</span>
|
||||||
${contentHtml}
|
${status.content}
|
||||||
${tagsHtml}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`.trim();
|
||||||
mastodonElement.insertAdjacentHTML('beforeend', statusHtml);
|
}
|
||||||
|
function bisBlogsEntryToHtml(entry) {
|
||||||
|
return `
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s1">
|
||||||
|
<img src="https://blogs.uni-bielefeld.de/blog/uniintern/resource/themabilder/unilogo-square.svg" alt="Bielefeld University Blogs" class="responsive-img">
|
||||||
|
</div>
|
||||||
|
<div class="col s11">
|
||||||
|
<div class="card" style="background-color: #14f5b4;">
|
||||||
|
<div class="card-content">
|
||||||
|
<span class="card-title">${entry.title['#text']}</span>
|
||||||
|
${entry.content['#text']}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
let aggregatedNewsElement = document.querySelector('#aggregated-news');
|
||||||
|
aggregateNews().then((aggregatedNews) => {
|
||||||
|
for (let item of aggregatedNews) {
|
||||||
|
let itemHtmlString;
|
||||||
|
switch (item.source) {
|
||||||
|
case 'mastodon':
|
||||||
|
console.log(item);
|
||||||
|
itemHtmlString = mastodonStatusToHtml(item);
|
||||||
|
break;
|
||||||
|
case 'big-blogs':
|
||||||
|
itemHtmlString = bisBlogsEntryToHtml(item);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('Unknown source');
|
||||||
|
}
|
||||||
|
aggregatedNewsElement.insertAdjacentHTML('beforeend', itemHtmlString);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
Reference in New Issue
Block a user