Skip to content

Commit

Permalink
feat: add publiccode.yml crawl status to software pages (#1003)
Browse files Browse the repository at this point in the history
Add a status badge to every software page, displaying if the publiccode.yml was crawled
correctly.
  • Loading branch information
bfabio authored Jul 30, 2024
1 parent 040ce01 commit 32d14f4
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 0 deletions.
7 changes: 7 additions & 0 deletions _layouts/software-details.html
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,13 @@ <h2>
{{ page.publiccode.maintenance.type }}
</p>
</div>
<div class="col-7 col-sm-7 col-md-3">
<p>
<span class="label">Stato publiccode.yml</span>
<publiccode-badge id="{{ page.id }}"></publiccode-badge>
<p>
</div>

{% if page.publiccode.maintenance.type == "contract" %}
{% if page.publiccode.maintenance.contractors[0].name != nil %}
<div class="col-sm-12 col-md">
Expand Down
3 changes: 3 additions & 0 deletions assets/js/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import { SearchContainer } from './components/Search/SearchContainer.js';
import { CatalogueContainer } from './components/Catalogue/CatalogueContainer.js';
import { PubliccodeBadge } from './components/PubliccodeBadge.js';
import { CatalogueItem } from './components/Catalogue/CatalogueItem.js';
import { MailingListSubscribe } from './components/MailingList/MailingListSubscribe.js';
import { MailingListConfirmation } from './components/MailingList/MailingListConfirmation.js';

export const App = () => {
const search = useRef(Array.from(document.getElementsByTagName('custom-search')));
const catalogue = useRef(Array.from(document.getElementsByTagName('custom-catalogue')));
const publiccodeBadge = useRef(Array.from(document.getElementsByTagName('publiccode-badge')));
const thumbnails = useRef(Array.from(document.getElementsByTagName('catalogue-item')));
const mailingListSubscribe = useRef(Array.from(document.getElementsByTagName('mailing-list-subscribe')));
const mailingListConfirmation = useRef(Array.from(document.getElementsByTagName('mailing-list-confirmation')));
Expand All @@ -32,6 +34,7 @@ export const App = () => {
{thumbnails.current.map((t) => renderThumbnail(t))}
{mailingListSubscribe.current.map((p) => renderCustomElement(p, MailingListSubscribe))}
{mailingListConfirmation.current.map((p) => renderCustomElement(p, MailingListConfirmation))}
{publiccodeBadge.current.map((p) => renderCustomElement(p, PubliccodeBadge))}
</>
);
};
59 changes: 59 additions & 0 deletions assets/js/components/PubliccodeBadge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';

import { Spinner } from './Spinner';

const stateClass = {
loading: 'secondary',
good: 'success',
error: 'danger',
};

export const PubliccodeBadge = React.memo(({ id }) => {
const [publiccodeState, setPubliccodeState] = useState('loading');
const logUrl = `https://api.developers.italia.it/v1/software/${id}/logs`;

useEffect(() => {
async function fetchLogs() {
const res = await fetch(logUrl);

if (res.status >= 200 || res.status <= 299) {
const data = await res.json();
const good = data.data[0]?.message.includes('GOOD publiccode.yml');

setPubliccodeState(good ? 'good' : 'error');
} else {
setPubliccodeState('error');
}
}

fetchLogs();
}, [logUrl]);

return (
<>
<div className="lead">
{publiccodeState === 'loading' && <Spinner />}
<span className={`badge badge-${stateClass[publiccodeState]}`}>
{publiccodeState !== 'loading' && publiccodeState}
</span>
</div>

<a
className="x-small"
href={logUrl}
target="_blank"
aria-label="Log results of the latest publiccode.yml crawling"
rel="noreferrer"
>
(log)
</a>
</>
);
});

PubliccodeBadge.propTypes = {
id: PropTypes.string.isRequired,
};

PubliccodeBadge.displayName = 'PubliccodeBadge';
56 changes: 56 additions & 0 deletions assets/js/components/Spinner.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
.lds-ellipsis {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
margin-bottom: 1rem;
}
.lds-ellipsis div {
position: absolute;
width: 6px;
height: 6px;
border-radius: 50%;
background: gray;
top: 0.5rem;
animation-timing-function: cubic-bezier(0, 1, 1, 0);
}
.lds-ellipsis div:nth-child(1) {
left: 8px;
animation: lds-ellipsis1 0.6s infinite;
}
.lds-ellipsis div:nth-child(2) {
left: 8px;
animation: lds-ellipsis2 0.6s infinite;
}
.lds-ellipsis div:nth-child(3) {
left: 32px;
animation: lds-ellipsis2 0.6s infinite;
}
.lds-ellipsis div:nth-child(4) {
left: 56px;
animation: lds-ellipsis3 0.6s infinite;
}
@keyframes lds-ellipsis1 {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
@keyframes lds-ellipsis3 {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
@keyframes lds-ellipsis2 {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(24px, 0);
}
}
16 changes: 16 additions & 0 deletions assets/js/components/Spinner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';

import './Spinner.css';

export const Spinner = React.memo(() => (
<>
<div className="lds-ellipsis">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</>
));

Spinner.displayName = 'Spinner';

0 comments on commit 32d14f4

Please sign in to comment.