Skip to content

Commit 32d14f4

Browse files
authored
feat: add publiccode.yml crawl status to software pages (italia#1003)
Add a status badge to every software page, displaying if the publiccode.yml was crawled correctly.
1 parent 040ce01 commit 32d14f4

File tree

5 files changed

+141
-0
lines changed

5 files changed

+141
-0
lines changed

_layouts/software-details.html

+7
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,13 @@ <h2>
426426
{{ page.publiccode.maintenance.type }}
427427
</p>
428428
</div>
429+
<div class="col-7 col-sm-7 col-md-3">
430+
<p>
431+
<span class="label">Stato publiccode.yml</span>
432+
<publiccode-badge id="{{ page.id }}"></publiccode-badge>
433+
<p>
434+
</div>
435+
429436
{% if page.publiccode.maintenance.type == "contract" %}
430437
{% if page.publiccode.maintenance.contractors[0].name != nil %}
431438
<div class="col-sm-12 col-md">

assets/js/App.js

+3
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import React, { useRef } from 'react';
22
import ReactDOM from 'react-dom';
33
import { SearchContainer } from './components/Search/SearchContainer.js';
44
import { CatalogueContainer } from './components/Catalogue/CatalogueContainer.js';
5+
import { PubliccodeBadge } from './components/PubliccodeBadge.js';
56
import { CatalogueItem } from './components/Catalogue/CatalogueItem.js';
67
import { MailingListSubscribe } from './components/MailingList/MailingListSubscribe.js';
78
import { MailingListConfirmation } from './components/MailingList/MailingListConfirmation.js';
89

910
export const App = () => {
1011
const search = useRef(Array.from(document.getElementsByTagName('custom-search')));
1112
const catalogue = useRef(Array.from(document.getElementsByTagName('custom-catalogue')));
13+
const publiccodeBadge = useRef(Array.from(document.getElementsByTagName('publiccode-badge')));
1214
const thumbnails = useRef(Array.from(document.getElementsByTagName('catalogue-item')));
1315
const mailingListSubscribe = useRef(Array.from(document.getElementsByTagName('mailing-list-subscribe')));
1416
const mailingListConfirmation = useRef(Array.from(document.getElementsByTagName('mailing-list-confirmation')));
@@ -32,6 +34,7 @@ export const App = () => {
3234
{thumbnails.current.map((t) => renderThumbnail(t))}
3335
{mailingListSubscribe.current.map((p) => renderCustomElement(p, MailingListSubscribe))}
3436
{mailingListConfirmation.current.map((p) => renderCustomElement(p, MailingListConfirmation))}
37+
{publiccodeBadge.current.map((p) => renderCustomElement(p, PubliccodeBadge))}
3538
</>
3639
);
3740
};
+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React, { useEffect, useState } from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import { Spinner } from './Spinner';
5+
6+
const stateClass = {
7+
loading: 'secondary',
8+
good: 'success',
9+
error: 'danger',
10+
};
11+
12+
export const PubliccodeBadge = React.memo(({ id }) => {
13+
const [publiccodeState, setPubliccodeState] = useState('loading');
14+
const logUrl = `https://api.developers.italia.it/v1/software/${id}/logs`;
15+
16+
useEffect(() => {
17+
async function fetchLogs() {
18+
const res = await fetch(logUrl);
19+
20+
if (res.status >= 200 || res.status <= 299) {
21+
const data = await res.json();
22+
const good = data.data[0]?.message.includes('GOOD publiccode.yml');
23+
24+
setPubliccodeState(good ? 'good' : 'error');
25+
} else {
26+
setPubliccodeState('error');
27+
}
28+
}
29+
30+
fetchLogs();
31+
}, [logUrl]);
32+
33+
return (
34+
<>
35+
<div className="lead">
36+
{publiccodeState === 'loading' && <Spinner />}
37+
<span className={`badge badge-${stateClass[publiccodeState]}`}>
38+
{publiccodeState !== 'loading' && publiccodeState}
39+
</span>
40+
</div>
41+
42+
<a
43+
className="x-small"
44+
href={logUrl}
45+
target="_blank"
46+
aria-label="Log results of the latest publiccode.yml crawling"
47+
rel="noreferrer"
48+
>
49+
(log)
50+
</a>
51+
</>
52+
);
53+
});
54+
55+
PubliccodeBadge.propTypes = {
56+
id: PropTypes.string.isRequired,
57+
};
58+
59+
PubliccodeBadge.displayName = 'PubliccodeBadge';

assets/js/components/Spinner.css

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
.lds-ellipsis {
2+
display: inline-block;
3+
position: relative;
4+
width: 80px;
5+
height: 80px;
6+
margin-bottom: 1rem;
7+
}
8+
.lds-ellipsis div {
9+
position: absolute;
10+
width: 6px;
11+
height: 6px;
12+
border-radius: 50%;
13+
background: gray;
14+
top: 0.5rem;
15+
animation-timing-function: cubic-bezier(0, 1, 1, 0);
16+
}
17+
.lds-ellipsis div:nth-child(1) {
18+
left: 8px;
19+
animation: lds-ellipsis1 0.6s infinite;
20+
}
21+
.lds-ellipsis div:nth-child(2) {
22+
left: 8px;
23+
animation: lds-ellipsis2 0.6s infinite;
24+
}
25+
.lds-ellipsis div:nth-child(3) {
26+
left: 32px;
27+
animation: lds-ellipsis2 0.6s infinite;
28+
}
29+
.lds-ellipsis div:nth-child(4) {
30+
left: 56px;
31+
animation: lds-ellipsis3 0.6s infinite;
32+
}
33+
@keyframes lds-ellipsis1 {
34+
0% {
35+
transform: scale(0);
36+
}
37+
100% {
38+
transform: scale(1);
39+
}
40+
}
41+
@keyframes lds-ellipsis3 {
42+
0% {
43+
transform: scale(1);
44+
}
45+
100% {
46+
transform: scale(0);
47+
}
48+
}
49+
@keyframes lds-ellipsis2 {
50+
0% {
51+
transform: translate(0, 0);
52+
}
53+
100% {
54+
transform: translate(24px, 0);
55+
}
56+
}

assets/js/components/Spinner.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
3+
import './Spinner.css';
4+
5+
export const Spinner = React.memo(() => (
6+
<>
7+
<div className="lds-ellipsis">
8+
<div></div>
9+
<div></div>
10+
<div></div>
11+
<div></div>
12+
</div>
13+
</>
14+
));
15+
16+
Spinner.displayName = 'Spinner';

0 commit comments

Comments
 (0)