Skip to content
Snippets Groups Projects
Commit a413b41d authored by Patrick Jentsch's avatar Patrick Jentsch
Browse files

Update News page

parent 69152f5e
No related branches found
No related tags found
No related merge requests found
......@@ -30,11 +30,11 @@ class RessourceList {
...{pagination: {item: `<li><a class="page" href="#${listElement.id}"></a></li>`}},
...options
}
if ('ressourceMapper' in options) {
if ('ressourceMapper' in options && typeof options.ressourceMapper === 'function') {
this.ressourceMapper = options.ressourceMapper;
delete options.ressourceMapper;
}
if ('initialHtmlGenerator' in options) {
if ('initialHtmlGenerator' in options && typeof options.initialHtmlGenerator === 'function') {
this.initialHtmlGenerator = options.initialHtmlGenerator;
listElement.innerHTML = this.initialHtmlGenerator(listElement.id);
delete options.initialHtmlGenerator;
......
/**
* 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/SpacyNLPPipelineModelList.js',
'js/RessourceLists/TesseractOCRPipelineModelList.js',
'js/RessourceLists/UserList.js'
'js/RessourceLists/UserList.js',
'js/XMLtoObject.js'
%}
<script src="{{ ASSET_URL }}"></script>
{%- endassets %}
......@@ -52,7 +53,7 @@
// Initialize components
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(
document.querySelectorAll('#nav-more-dropdown-trigger'),
{alignment: 'right', constrainWidth: false, coverTrigger: false}
......
{% extends "base.html.j2" %}
{% block main_attribs %} class="service-scheme" data-service="corpus-analysis"{% endblock main_attribs %}
{% block page_content %}
<div class="parallax-container">
<div class="parallax"><img src="{{ url_for('static', filename='images/parallax_hq/canvas.png') }}"></div>
<div style="position: absolute; bottom: 0; width: 100%;">
<div class="container">
<div class="white-text">
<h1 id="title"><i class="nopaque-icons" style="font-size: inherit;">I</i>Corpora</h1>
</div>
<div class="white" style="padding: 0 15px; border-radius: 20px;">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input id="public-corpora-search" placeholder="Find public corpora" type="text">
<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 style="position: absolute; bottom: 0; width: 100%;">
<div class="container">
<div class="white-text">
<h1 id="title"><i class="nopaque-icons" style="font-size: inherit;">I</i>Corpora</h1>
</div>
<div class="white" style="padding: 1px 35px 0 10px; border-radius: 35px;">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input class="search" id="corpus-list-search" type="text">
<label for="corpus-list-search">Search corpus</label>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col s12" id="corpora">
<div class="card">
<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>
......@@ -36,9 +52,21 @@
{% block scripts %}
{{ super() }}
<script>
let publicCorporaSearchElement = document.querySelector('#public-corpora-search');
let corpusList = CorpusList.getInstance(document.querySelector('#corpora .corpus-list .list'));
publicCorporaSearchElement.addEventListener('keyup', function() {corpusList.listjs.search(this.value);});
let corpusListElement = document.querySelector('#corpus-list');
let corpusListOptions = {
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 }});
</script>
{% endblock scripts %}
......@@ -9,7 +9,7 @@
</div>
<div class="col s12">
<div id="mastodon"></div>
<div id="aggregated-news"></div>
<div class="card" id="april-2022-update">
<div class="card-content">
......@@ -132,29 +132,116 @@
{% block scripts %}
{{ super() }}
<script>
let mastodonElement = document.querySelector('#mastodon');
fetch(`https://fedihum.org/api/v1/accounts/109386364241901080/statuses`, {method: 'GET', headers: {Accept: 'application/json'}})
.then((response) => {return response.json();})
.then((statuses) => {
for (let status of statuses) {
console.log(status);
let contentHtml = `<div>${status.content}</div>`
let tagsHtml = '<p>';
for (let tag of status.tags) {
tagsHtml += `<a href="${tag.url}" class="chip">${tag.name}</a>`;
}
tagsHtml += '</p>';
let statusHtml = `
<div id="${status.id}" class="card">
function getMastodonStatuses() {
return new Promise((resolve, reject) => {
fetch(`https://fedihum.org/api/v1/accounts/109386364241901080/statuses`, {method: 'GET', headers: {Accept: 'application/json'}})
.then((response) => {
if (!response.ok) {reject(response);}
return response.json();
})
.then((statuses) => {resolve(statuses);})
});
}
function getBisBlogsEntries() {
return new Promise((resolve, reject) => {
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">
<span class="card-title">New Actitvity on Mastodon</span>
${status.content}
</div>
</div>
`.trim();
}
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">Mastodon News</span>
${contentHtml}
${tagsHtml}
<span class="card-title">${entry.title['#text']}</span>
${entry.content['#text']}
</div>
</div>
`;
mastodonElement.insertAdjacentHTML('beforeend', statusHtml);
</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>
{% endblock scripts %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment