Skip to content

Commit

Permalink
feat : add pages eap2024 & emb2025
Browse files Browse the repository at this point in the history
  • Loading branch information
HugoBouttes authored Dec 20, 2024
1 parent cd62ac9 commit 7581bb2
Show file tree
Hide file tree
Showing 4 changed files with 703 additions and 0 deletions.
224 changes: 224 additions & 0 deletions pages/common/eap2024/display-item.htm
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<title>EAP - consultation</title>
<link href="../commun.css" rel="stylesheet" type="text/css"/>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK" crossorigin="anonymous"></script>
<script>
const endpointURL = "https://rdf.insee.fr/sparql";
const racine = "http://id.insee.fr/codes/";
const nomenclature = "eap2024";
const regex = new RegExp(racine + nomenclature + "/[A-Z0-9]+/", "g");
const replacement = 'display-item.htm?code=';
const itemTypes = ['Produit', 'produit'];
const parentLength = [0, 4];

document.addEventListener("DOMContentLoaded", function() {
const code = sanitizeInput(getURLParameter('code'));
if (code) {
document.getElementById('fil-ariane').innerHTML = '<ul>' + breadcrumbs(code, false) + '</ul>';
getLabel(code);
}
});

async function fetchData(query, type = "json") {
const headers = {
'Accept': type === 'n-triples' ? 'application/n-triples' : 'application/sparql-results+json'
};
try {
const response = await fetch(`${endpointURL}?query=${encodeURIComponent(query)}`, {
method: 'GET',
headers: headers,
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
const contentType = response.headers.get("content-type");
if (type === "json" && contentType.includes("application/sparql-results+json")) {
return await response.json();
} else if (type === "n-triples" && contentType.includes("application/n-triples")) {
const text = await response.text();
return parseNTriples(text);
} else {
throw new Error('Received content is not in the expected format');
}
} catch (error) {
console.error('Error fetching data:', error);
throw error;
}
}

function parseNTriples(text) {
const triples = text.trim().split('\n').map(line => {
const match = line.match(/<([^>]*)>\s*<([^>]*)>\s*<([^>]*)>|<([^>]*)>\s*<([^>]*)>\s*"([^"]*)"/);
if (match) {
return {
subject: match[1] || match[4],
predicate: match[2] || match[5],
object: match[3] || match[6]
};
} else {
console.error('Failed to parse n-triple line:', line);
return null;
}
});
return triples.filter(triple => triple !== null);
}

async function getLabel(code) {
const query = `
PREFIX skos:<http://www.w3.org/2004/02/skos/core#>
SELECT ?uri ?label WHERE {
GRAPH <http://rdf.insee.fr/graphes/codes/${nomenclature}> {
?uri skos:prefLabel ?label ; skos:notation '${encodeHTML(code)}'.
FILTER langMatches (lang(?label), 'fr')
}
}
`;
try {
const data = await fetchData(query);
const itemURI = data.results.bindings[0].uri.value;
document.getElementById('label').textContent = `${code} - ${data.results.bindings[0].label.value}`;
if (code.length > 6) {
getDescription(itemURI);
}
const childTypeIndex = (code.length == 6 ? 1 : 0);
getChildren(itemURI, itemTypes[childTypeIndex]);
} catch (error) {
console.error('Error in getLabel:', error);
}
}

async function getDescription(itemURI) {
const query = `
PREFIX skos:<http://www.w3.org/2004/02/skos/core#>
DESCRIBE <${encodeHTML(itemURI)}>
`;
try {
const data = await fetchData(query, "n-triples");
data.forEach(triple => {
const predicateValue = triple.predicate;
const objectValue = triple.object;
if (predicateValue === "http://www.w3.org/2004/02/skos/core#definition") getNote(objectValue, "note-generale");
else if (predicateValue === "http://www.w3.org/2004/02/skos/core#scopeNote") getNote(objectValue, "note-generale");
else if (predicateValue === "http://rdf-vocabulary.ddialliance.org/xkos#coreContentNote") getNote(objectValue, "contenu-central");
else if (predicateValue === "http://rdf-vocabulary.ddialliance.org/xkos#additionalContentNote") getNote(objectValue, "contenu-limite");
else if (predicateValue === "http://rdf-vocabulary.ddialliance.org/xkos#exclusionNote") getNote(objectValue, "exclusions");
else if (predicateValue === "http://www.w3.org/2004/02/skos/core#note") getNote(objectValue, "remarques");
});
} catch (error) {
console.error('Error in getDescription:', error);
}
}

async function getChildren(itemURI, childType) {
const query = `
PREFIX skos:<http://www.w3.org/2004/02/skos/core#>
SELECT ?code ?label WHERE {
<${encodeHTML(itemURI)}> skos:narrower ?child .
?child skos:notation ?code ; skos:prefLabel ?label .
FILTER langMatches (lang(?label), 'fr')
} ORDER BY ?code
`;
try {
const data = await fetchData(query);
if (data.results.bindings.length > 0) {
let innerHTML = '<p class="nom-enfants">Liste des produits détaillés</p><ul class="enfants">';
data.results.bindings.forEach(item => {
const childCode = encodeHTML(item.code.value);
const childLabel = encodeHTML(item.label.value);
innerHTML += `<li><p><a href="${replacement}${encodeURIComponent(childCode)}">${childCode} - ${childLabel}</a></p></li>`;
});
innerHTML += '</ul>';
const sousItemsElement = document.getElementById('sous-items');
sousItemsElement.innerHTML = innerHTML;
sousItemsElement.classList.add("sous-items");
}
} catch (error) {
console.error('Error in getChildren:', error);
}
}

async function getNote(uri, tag) {
const query = `
SELECT ?text WHERE {
<${encodeHTML(uri)}> <http://eurovoc.europa.eu/schema#noteLiteral> ?text
}
`;
try {
const data = await fetchData(query);
const noteText = encodeHTML(data.results.bindings[0].text.value.replace(regex, replacement));
const tagElement = document.getElementById(tag);
tagElement.innerHTML += noteText.replace(/\\\$/g, "<br />");
tagElement.classList.add(tag);
} catch (error) {
console.error('Error in getNote:', error);
}
}

function getURLParameter(name) {
const result = new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search);
return result ? decodeURIComponent(result[1].replace(/\+/g, '%20')) : null;
}

function breadcrumbs(code, finalLink) {
let niveau;
if (code && code.length > 6) {
niveau = 'Produit détaillé ';
} else {
niveau = 'Produit agrégé ';
}
const name = `${niveau}${encodeHTML(code)}`;
const fin = finalLink ?
`<li><a href="${replacement}${encodeURIComponent(code)}" title="${name}">${name}</a></li>` :
`<li>${name}</li>`;

if (code && code.length <= 6) {
return `<li><a href="eap.htm" title="Accueil">${nomenclature.toUpperCase()}</a></li>&nbsp;${fin}`;
} else if (code) {
return `${breadcrumbs(getParentCode(code), true)}&nbsp;${fin}`;
}
return '';
}

function getParentCode(code) {
if (code && code.length > 6) {
let codeParent = code.substr(0, parentLength[1]);
if (/[A-Z]/.test(code.slice(-1))) {
codeParent += code.slice(-1).toLowerCase();
}
return codeParent;
}
return null;
}

// Encode HTML entities to prevent XSS
function encodeHTML(str) {
return str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}

// Sanitize input to prevent XSS
function sanitizeInput(input) {
return input ? input.replace(/[^a-zA-Z0-9-_]/g, '') : '';
}
</script>
</head>
<body>
<div id="fil-ariane"></div>
<h1 id="label" class="item"></h1>
<br/>
<div id="notes">
<div id="note-generale"></div>
<div id="contenu-central"></div>
<div id="contenu-limite"></div>
<div id="exclusions"></div>
<div id="remarques"></div>
</div>
<div id="sous-items"></div>
</body>
</html>
103 changes: 103 additions & 0 deletions pages/common/eap2024/eap.htm
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<title>Consultation - EAP 2024</title>
<link href="../commun.css" rel="stylesheet" type="text/css"/>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.1.6/purify.min.js" integrity="sha384-+VfUPEb0PdtChMwmBcBmykRMDd+v6D/oFmB3rZM/puCMDYcIvF968OimRh4KQY9a" crossorigin="anonymous"></script>
</head>
<body>
<h1 class="titre-class">Nomenclatures de l'Enquête Annuelle de Production (EAP) 2024</h1>
<div class="note-generale">
<p>Liste des produits de l'Enquête Annuelle de Production 2024</p>
</div>
<div id="sous-items1" class="sous-items" style="width: 45%; float: left;"></div>
<div id="sous-items2" class="sous-items" style="width: 45%; float: left;"></div>

<!-- Template for items -->
<script id="items-template" type="text/x-handlebars-template">
<p class="nom-enfants">{{title}}</p>
<ul class="enfants">
{{#each items}}
<li><p><a href="display-item.htm?code={{encodeURIComponent code}}">{{code}} - {{label}}</a></p></li>
{{/each}}
</ul>
</script>

<script>
const endpointURL = "https://rdf.insee.fr/sparql";
const racine = "http://id.insee.fr/codes/";
const nomenclature = "eap2024";
const niveau = "produits";
const niveau2 = "produitsAgreges";

document.addEventListener("DOMContentLoaded", function() {
const fetchData = (queryURL, elementId, title) => {
fetch(queryURL, {
headers: {
'Accept': 'application/sparql-results+json'
}
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
const templateSource = document.getElementById('items-template').innerHTML;
const template = Handlebars.compile(templateSource);

const context = {
title: DOMPurify.sanitize(title), // Sanitize the title
items: data.results.bindings.map(item => ({
code: DOMPurify.sanitize(item.code.value), // Sanitize each code
label: DOMPurify.sanitize(item.label.value) // Sanitize each label
}))
};

const sanitizedHTML = template(context);
const container = document.getElementById(elementId);
container.innerHTML = DOMPurify.sanitize(sanitizedHTML); // Sanitize the final HTML
})
.catch(error => console.error('Error fetching data:', error));
};

const query1 = `
PREFIX skos:<http://www.w3.org/2004/02/skos/core#>
SELECT ?code ?label WHERE {
GRAPH <http://rdf.insee.fr/graphes/codes/${nomenclature}> {
?uri skos:prefLabel ?label ;
skos:notation ?code .
<${racine}${nomenclature}/${niveau}> skos:member ?uri .
FILTER langMatches(lang(?label), "fr")
}
} ORDER BY ?code
`;
const queryURL1 = `${endpointURL}?query=${encodeURIComponent(query1)}`;
fetchData(queryURL1, 'sous-items2', 'Liste des produits détaillés');

const query2 = `
PREFIX skos:<http://www.w3.org/2004/02/skos/core#>
SELECT ?code ?label WHERE {
GRAPH <http://rdf.insee.fr/graphes/codes/${nomenclature}> {
?uri skos:prefLabel ?label ;
skos:notation ?code .
<${racine}${nomenclature}/${niveau2}> skos:member ?uri .
FILTER langMatches(lang(?label), "fr")
}
} ORDER BY ?code
`;
const queryURL2 = `${endpointURL}?query=${encodeURIComponent(query2)}`;
fetchData(queryURL2, 'sous-items1', 'Liste des produits agrégés');
});

// Helper to encode URL components
Handlebars.registerHelper('encodeURIComponent', function(context) {
return encodeURIComponent(context);
});
</script>
</body>
</html>
Loading

0 comments on commit 7581bb2

Please sign in to comment.