Skip to content

Commit 57d4a0f

Browse files
Merge pull request #4 from knowledgepixels/feat/nanopubs-news
Use nanopubs for displaying news on the main page (latest news) and on the news page
2 parents c66665d + 14b8f16 commit 57d4a0f

3 files changed

Lines changed: 179 additions & 23 deletions

File tree

index.html

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,25 +84,11 @@ <h2>Our services, ready for you</h2>
8484

8585
<column>
8686
<h2>Our News</h2>
87-
<ul>
88-
89-
<li>
90-
<span><span>We are happy to announce that we are part of three papers that have been accepted for presentation at the <a href="https://fairdo.org/fdo-conference-2026/" rel="nofollow">3rd FAIR Digital Objects Conference</a>. So we are looking forward to presenting our work in Vienna in March!</span></span>
91-
</li>
92-
93-
<li>
94-
<span><span>Interested in nanopublications and how they could be useful to you? If so, come join the
95-
<a href="https://w3id.org/spaces/fenac" rel="nofollow">Fearless Early Nanopub Adopter Club</a>!</span></span>
96-
</li>
97-
98-
<li>
99-
<span><span>We are happy to announce that the final report for the FDO Connect project (a.k.a. FAIR Data Publisher) is now <a href="https://mission-ki.de/en/final-report-on-the-fair-data-publisher-a-foundation-for-interoperable-data-spaces-in-europe" rel="nofollow">available</a>.</span></span>
100-
</li>
87+
<ul id="latest-news"></ul>
10188

10289
<buttons>
103-
<a href="news.html" class="button">See all</a>
90+
<a href="news.html" class="button">See all</a>
10491
</buttons>
105-
</ul>
10692

10793
</column>
10894

@@ -246,6 +232,10 @@ <h2>Contact</h2>
246232

247233
</container>
248234
</section>
235+
<script type="module">
236+
import { showLatestNews } from "./scripts/news.js";
237+
showLatestNews();
238+
</script>
249239

250240
</body>
251241
</html>

news.html

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,10 @@ <h2>Our News</h2>
3232

3333
</section>
3434

35-
<section>
35+
<section data-year="2025">
3636
<h3>2025</h3>
3737

38-
<ul>
39-
38+
<ul id="news-items">
4039
<li>
4140
<span><span>We are happy to announce that we are part of three papers that have been accepted for presentation at the <a href="https://fairdo.org/fdo-conference-2026/" rel="nofollow">3rd FAIR Digital Objects Conference</a>. So we are looking forward to presenting our work in Vienna in March!</span></span>
4241
</li>
@@ -88,7 +87,7 @@ <h3>2025</h3>
8887
</ul>
8988
</section>
9089

91-
<section>
90+
<section data-year="2024">
9291
<h3>2024</h3>
9392

9493
<ul>
@@ -100,7 +99,7 @@ <h3>2024</h3>
10099
</ul>
101100
</section>
102101

103-
<section>
102+
<section data-year="2023">
104103
<h3>2023</h3>
105104

106105
<ul>
@@ -111,14 +110,17 @@ <h3>2023</h3>
111110
</ul>
112111
</section>
113112

114-
<section>
113+
<section data-year="2022">
115114
<h3>2022</h3>
116115

117116
<ul>
118117
<li><a target="_blank" href="https://gist.github.com/tkuhn/1a99ce119d248f53689d52239512ec1f" target="_blank">Welcome to the New Era of Scientific Publishing</a></li>
119118
</ul>
120119
</section>
121120

122-
121+
<script type="module">
122+
import { showNewsItems } from "./scripts/news.js";
123+
showNewsItems();
124+
</script>
123125
</body>
124126
</html>

scripts/news.js

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import { NanopubClient } from "https://esm.sh/@nanopub/nanopub-js@0.1.0";
2+
import DOMPurify from "https://esm.sh/dompurify@3.3.1";
3+
4+
export async function showNewsItems() {
5+
const client = new NanopubClient({
6+
endpoints: ["https://query.knowledgepixels.com/"],
7+
});
8+
9+
const container =
10+
document.querySelector("section[data-year] ul") ||
11+
document.getElementById("news-container");
12+
13+
const stopLoading = showLoadingMessage(container);
14+
15+
try {
16+
for await (const row of client.runQueryTemplate(
17+
"RAOGCU2nQzZ0aE2iXwJ20jJtnZsjVR0pfFg0qlSxYtBIA/get-news-content",
18+
{ resource: "https://w3id.org/spaces/knowledgepixels" }
19+
)) {
20+
stopLoading();
21+
22+
const year = row.datePublished
23+
? new Date(row.datePublished).getFullYear()
24+
: new Date().getFullYear();
25+
26+
const ul = getYearList(year);
27+
const li = buildNewsItem(row);
28+
29+
insertChronologically(ul, li);
30+
}
31+
} catch (err) {
32+
stopLoading();
33+
console.error(err);
34+
}
35+
}
36+
37+
export function buildNewsItem({ text, link, np, datePublished }) {
38+
const li = document.createElement("li");
39+
const span = document.createElement("span");
40+
41+
if (text) {
42+
const clean = DOMPurify.sanitize(text);
43+
const doc = new DOMParser().parseFromString(clean, "text/html");
44+
span.append(...doc.body.childNodes);
45+
}
46+
47+
if (link) {
48+
const a = document.createElement("a");
49+
a.href = link;
50+
a.rel = "nofollow";
51+
a.textContent = link;
52+
const inner = span.querySelector("span");
53+
if (inner) {
54+
inner.appendChild(a);
55+
} else {
56+
span.appendChild(a);
57+
}
58+
}
59+
60+
li.appendChild(span);
61+
62+
if (datePublished) li.dataset.date = datePublished;
63+
if (np) li.dataset.nanopub = np;
64+
65+
return li;
66+
}
67+
68+
function getYearList(year) {
69+
let section = document.querySelector(`section[data-year="${year}"]`);
70+
71+
if (!section) {
72+
section = document.createElement("section");
73+
section.dataset.year = year;
74+
75+
const h3 = document.createElement("h3");
76+
h3.textContent = year;
77+
78+
const ul = document.createElement("ul");
79+
80+
section.appendChild(h3);
81+
section.appendChild(ul);
82+
83+
const all = [...document.querySelectorAll("section[data-year]")];
84+
const before = all.find((s) => Number(s.dataset.year) < year);
85+
86+
document.body.insertBefore(section, before || null);
87+
}
88+
89+
return section.querySelector("ul");
90+
}
91+
92+
function insertChronologically(ul, li) {
93+
const date = li.dataset.date;
94+
95+
if (!date) {
96+
ul.prepend(li);
97+
return;
98+
}
99+
100+
const time = new Date(date).getTime();
101+
102+
const existing = [...ul.children];
103+
const before = existing.find((el) => {
104+
const d = el.dataset.date;
105+
return d && new Date(d).getTime() < time;
106+
});
107+
108+
ul.insertBefore(li, before || null);
109+
}
110+
111+
export async function showLatestNews(limit = 3) {
112+
const ul = document.getElementById("latest-news");
113+
const stopLoading = showLoadingMessage(ul);
114+
115+
const client = new NanopubClient({
116+
endpoints: ["https://query.knowledgepixels.com/"],
117+
});
118+
119+
const rows = [];
120+
121+
try {
122+
for await (const row of client.runQueryTemplate(
123+
"RAOGCU2nQzZ0aE2iXwJ20jJtnZsjVR0pfFg0qlSxYtBIA/get-news-content",
124+
{ resource: "https://w3id.org/spaces/knowledgepixels" }
125+
)) {
126+
rows.push(row);
127+
}
128+
129+
stopLoading();
130+
131+
rows
132+
.sort((a, b) => {
133+
if (!a.datePublished) return 1;
134+
if (!b.datePublished) return -1;
135+
return new Date(b.datePublished) - new Date(a.datePublished);
136+
})
137+
.slice(0, limit)
138+
.forEach((row) => {
139+
ul.appendChild(buildNewsItem(row));
140+
});
141+
} catch (err) {
142+
stopLoading();
143+
console.error(err);
144+
}
145+
}
146+
147+
function showLoadingMessage(container, text = "Fetching news") {
148+
const li = document.createElement("li");
149+
li.className = "news-loading";
150+
li.textContent = text;
151+
152+
let dots = 0;
153+
const interval = setInterval(() => {
154+
dots = (dots + 1) % 4;
155+
li.textContent = text + ".".repeat(dots);
156+
}, 400);
157+
158+
container.appendChild(li);
159+
160+
return () => {
161+
clearInterval(interval);
162+
li.remove();
163+
};
164+
}

0 commit comments

Comments
 (0)