Skip to content

Commit

Permalink
Adding label check en uitzonderingen
Browse files Browse the repository at this point in the history
  • Loading branch information
uittenbroekrobbert committed Feb 19, 2025
1 parent ffa853e commit fe06b62
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 37 deletions.
8 changes: 4 additions & 4 deletions docs/html/ai-verordening-popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ <h2>Bepaal je AI-verordening profiel</h2>
<div class="form__row">
<label class="form__label" id="rol-label">Rol</label>
<div class="input-checkbox">
<input type="checkbox" id="role-aanbieder" name="role" value="aanbieder" class="checkbox__input">
<input type="checkbox" id="role-aanbieder" name="role" value="rol-ai-act-aanbieder" class="checkbox__input">
<label class="checkbox__label" for="role-aanbieder">Aanbieder</label>
</div>
<div class="input-checkbox">
<input type="checkbox" id="role-gebruiksverantwoordelijke" name="role" value="gebruiksverantwoordelijke"
<input type="checkbox" id="role-gebruiksverantwoordelijke" name="role" value="rol-ai-act-gebruiksverantwoordelijke"
class="checkbox__input">
<label class="checkbox__label" for="role-gebruiksverantwoordelijke">Gebruiksverantwoordelijke</label>
</div>
<div class="input-checkbox">
<input type="checkbox" id="role-importeur" name="role" value="importeur" class="checkbox__input">
<input type="checkbox" id="role-importeur" name="role" value="rol-ai-act-importeur" class="checkbox__input">
<label class="checkbox__label" for="role-importeur">Importeur</label>
</div>
<div class="input-checkbox">
<input type="checkbox" id="role-distributeur" name="role" value="distributeur" class="checkbox__input">
<input type="checkbox" id="role-distributeur" name="role" value="rol-ai-act-distributeur" class="checkbox__input">
<label class="checkbox__label" for="role-distributeur">Distributeur</label>
</div>
</div>
Expand Down
37 changes: 33 additions & 4 deletions docs/javascripts/filtering.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ function filterTable() {
var selectedRoles = Array.from(select.options)
.filter(option => option.selected)
.map(option => option.value.toUpperCase());
selectedRoles = [] // DIT IS STUK

var levenscyclusSelect = document.getElementById("filterLevenscyclusSelect"); // Levenscyclus filter
var selectedLevenscyclus = Array.from(levenscyclusSelect.options)
Expand All @@ -144,6 +143,18 @@ function filterTable() {

var labelsInput = document.getElementById("labelsInput").value.split(",").map(item => item.trim()).filter(item => item !== "");

var labelsToFilterOn = []
if (labelsInput.length > 0) {
labelsToFilterOn.push(...labelsInput);
// prefill all labels that are missing, the rule is:
for (const [_, labels] of labelMapper.groups) {
let foundLabelInGroup = labelsInput.some(label => labels.has(label));
if (!foundLabelInGroup) {
labelsToFilterOn.push(...labels);
}
}
}

for (let i = 1; i < tr.length; i++) { // Skip header row
var dataLabels = ""
if (tr[i].hasAttribute("data-labels")) {
Expand All @@ -165,23 +176,38 @@ function filterTable() {
var txtValue3 = lc.textContent || lc.innerText; // Levenscyclus value
var txtValue4 = onderwerpen.textContent || onderwerpen.innerText; // Onderwerpen value

if (tr[i].getElementsByTagName("td")[2].querySelectorAll(".debug").length === 0) {
tr[i].getElementsByTagName("td")[2].innerHTML += "<div class='debug'></div>";
}
let debugDiv = tr[i].getElementsByTagName("td")[2].querySelectorAll(".debug")[0];

// console.log(`Row ${i} values: `, { txtValue, txtValue2, txtValue3, txtValue4 });

// Check if all selected filters are present
var roleMatch = selectedRoles.every(role => txtValue2.toUpperCase().indexOf(role) > -1);
var lcMatch = selectedLevenscyclus.every(lc => txtValue3.toUpperCase().indexOf(lc) > -1);
var onderwerpMatch = selectedOnderwerpen.every(onderwerp => txtValue4.toUpperCase().indexOf(onderwerp) > -1);
var labelMatch = dataLabels === "" || labelsInput.length === 0 || evaluateLabelExpression(dataLabels, labelsInput);
var uitzonderingMatch = labelsInput.length > 0 && anyExpressionMatches(uitzonderingExpressions, labelsInput);
var labelMatch = dataLabels === "" || labelsToFilterOn.length === 0 || evaluateLabelExpression(dataLabels, labelsToFilterOn);
var uitzonderingMatch = anyExpressionMatches(uitzonderingExpressions, labelsInput);

debugDiv.innerHTML = "";
debugDiv.innerHTML += "Match condition: " + dataLabels + "</br></br>";
debugDiv.innerHTML += "Current labels: " + labelsToFilterOn + "</br>";

if (uitzonderingMatch && labelMatch) {
tr[i].style.backgroundColor = "rgba(249, 105, 14, 0.15)";
labelMatch = false
} else if (labelMatch && dataLabels !== "") {
tr[i].style.backgroundColor = "rgba(0, 255, 0, 0.15)";
} else {
tr[i].style.backgroundColor = "rgba(0, 0, 255, 0.15)";
}

if (txtValue.toUpperCase().indexOf(filter) > -1 && roleMatch && lcMatch && onderwerpMatch && labelMatch) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
tr[i].style.backgroundColor = "red";
// tr[i].style.display = "none";
}
}
}
Expand All @@ -195,6 +221,9 @@ Given an expression like: ("ai-systeem-voor-algemene-doeleinden" || "ai-systeem"
and an array of labels, evaluates the expression and returns true or false.
*/
function evaluateLabelExpression(expression, labels) {
if (expression === "" || labels.length === 0) {
return false;
}
// replace the string with function calls to hasLabel so we get true / false values
const transformedExpression = expression.replace(/["']?([a-zA-Z0-9-_]+)["']?/g, "hasLabel('$1')");

Expand Down
65 changes: 44 additions & 21 deletions docs/javascripts/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function updateLabels(labels) {
const convertedLabels = convertLabels(labels);
document.getElementById("ai-act-info-with-labels").classList.remove("display-none");
document.getElementById("ai-act-info-no-labels").classList.add("display-none");
appendQueryParams({"labels": convertedLabels.map(obj=> obj.label).join(",")});
// appendQueryParams({"labels": convertedLabels.map(obj=> obj.label).join(",")});
document.getElementById('labelsInput').value = convertedLabels.map(obj=> obj.label).join(",");

let labelsHTML = "";
Expand All @@ -87,6 +87,7 @@ function getLabelsFromForm(el) {
}, {});
const labels = Object.values(jsonObject).flatMap(v => Array.isArray(v) ? v : [v]).filter(v => v !== "");
if (labels.length > 0) {
console.log(labels);
updateLabels(labels);
} else {
document.getElementById("ai-act-info-with-labels").classList.add("display-none");
Expand Down Expand Up @@ -139,43 +140,64 @@ function appendQueryParams(params) {
class ValueMapper {
constructor() {
this.map = new Map();
this.groups = new Map();
}

addEntry(label, display_value, synonyms = []) {
const standardFormat = { label, display_value };
this.map.set(label.toLowerCase(), standardFormat);
this.map.set(display_value.toLowerCase(), standardFormat);
addEntry(label, display_value, group, synonyms = []) {
const standardFormat = { label, group, display_value };
this.map.set(group + "-" + label.toLowerCase(), standardFormat);
synonyms.forEach(synonym => {
this.map.set(synonym.toLowerCase(), standardFormat);
this.map.set(group + "-" + synonym.toLowerCase(), standardFormat);
});

if (!this.groups.has(group)) {
this.groups.set(group, new Set());
}

this.groups.get(group).add(group + "-" + label.toLowerCase());
}


find(value) {
if (this.map.has(value.toLowerCase())) {
return this.map.get(value.toLowerCase());
}
return {"label": value, "display_value": value + " [onbekend]", "missing": true};
}

}


// Usage example:
const labelMapper = new ValueMapper();

labelMapper.addEntry('hoog-risico-ai-systeem', 'Hoog risico AI Systeem', ['hoog-risico AI']);
labelMapper.addEntry('gebruiksverantwoordelijke', 'Gebruiksverantwoordelijke', [])
labelMapper.addEntry('aanbieder', 'Aanbieder', []);
labelMapper.addEntry('importeur', 'Importeur', []);
labelMapper.addEntry('distributeur', 'Distributeur', []);
labelMapper.addEntry('ai-systeem', 'AI Systeem', ['AI-Systeem','ai-systeem']);
labelMapper.addEntry('ai-model-voor-algemene-doeleinden', 'AI model voor algemen doeleinden', ['AI-model voor algemene doeleinden']);
labelMapper.addEntry('verboden-ai', 'Verboden AI', ['Verboden AI']);
labelMapper.addEntry('impactvol-algoritme', 'Impactvol algoritme', []);
labelMapper.addEntry('transparantieverplichting', 'Transparantieverplichting', []);
labelMapper.addEntry('ai-systeem-voor-algemene-doeleinden', 'AI Systeem voor algemene doeleinden', ['AI-Systeem voor algemene doeleinden']);
labelMapper.addEntry('systeemrisico', 'Systeemrisico', []);
labelMapper.addEntry('geen-hoog-risico-ai-systeem', 'Geen hoog-risico AI Systeem', ['geen hoog-risico AI']);
labelMapper.addEntry('open-source', 'Open source', []);
labelMapper.addEntry('in-gebruik', 'In gebruik', []);
labelMapper.addEntry('hoog-risico-ai-systeem', 'Hoog risico AI Systeem', 'risicogroep', ['hoog-risico AI']);
labelMapper.addEntry('geen-hoog-risico-ai-systeem', 'Geen hoog-risico AI Systeem', 'risicogroep', ['geen hoog-risico AI']);
labelMapper.addEntry('verboden-ai', 'Verboden AI', 'risicogroep', ['Verboden AI']);
labelMapper.addEntry('uitzondering-van-toepassing', 'Uitzondering van toepassing', 'risicogroep', []);

labelMapper.addEntry('aanbieder', 'Aanbieder', 'rol-ai-act', []);
labelMapper.addEntry('gebruiksverantwoordelijke', 'Gebruiksverantwoordelijke', 'rol-ai-act', [])
labelMapper.addEntry('importeur', 'Importeur', 'rol-ai-act', []);
labelMapper.addEntry('distributeur', 'Distributeur','rol-ai-act', []);

labelMapper.addEntry('ai-systeem', 'AI Systeem', 'soort-toepassing', ['AI-Systeem','ai-systeem']);
labelMapper.addEntry('ai-systeem-voor-algemene-doeleinden', 'AI Systeem voor algemene doeleinden', 'soort-toepassing', ['AI-Systeem voor algemene doeleinden']);
labelMapper.addEntry('ai-model-voor-algemene-doeleinden', 'AI model voor algemen doeleinden', 'soort-toepassing',['AI-model voor algemene doeleinden']);
labelMapper.addEntry('impactvol-algoritme', 'Impactvol algoritme', 'soort-toepassing', []);
labelMapper.addEntry('niet-impactvol-algoritme', 'Niet-impactvol algoritme','soort-toepassing', []);

labelMapper.addEntry('transparantieverplichting', 'Transparantieverplichting', 'transparantieverplichting', []);
labelMapper.addEntry('geen-transparantieverplichting', 'Geen transparantieverplichting', 'transparantieverplichting', []);

labelMapper.addEntry('systeemrisico', 'Systeemrisico', 'systeemrisico', []);
labelMapper.addEntry('geen-systeemrisico', 'Geen systeemrisico', 'systeemrisico', []);

labelMapper.addEntry('open-source', 'Open source', 'open-source', []);
labelMapper.addEntry('geen-open-source', 'Geen open source', 'open-source', []);

labelMapper.addEntry('in-gebruik', 'In gebruik', 'in-gebruik', []);
labelMapper.addEntry('beoordeling-door-derde-partij', 'Beoordeling door derde partij', 'beoordeling-door-derde-partij', []);


window.addEventListener('message', (event) => {
Expand All @@ -185,6 +207,7 @@ window.addEventListener('message', (event) => {
const jsonObject = JSON.parse(sessionStorage.getItem("labels"))
const labels = convertLabels(Object.values(jsonObject).flatMap(v => Array.isArray(v) ? v : [v]).filter(v => v !== "")).map(obj => obj.label)
updateLabels(labels);
filterTable();
closeModal();
}
});
18 changes: 10 additions & 8 deletions src/overrides/hooks/lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,19 @@ def _create_table_row_2(file: File, filter_options: Dict[str, bool], current_fil
vereiste = file.page.meta.get('vereiste', [])
vereiste_id = file.page.meta.get('id', "")[14:] # remove the first part of the urn
# AI act label fields
soort_toepassing = file.page.meta.get('soort-toepassing', [])
risicogroep = file.page.meta.get('risicogroep', [])
rol_ai_act = file.page.meta.get('rol-ai-act', [])
transparantieverplichting = file.page.meta.get('transparantieverplichting', [])
systeemrisico = file.page.meta.get('systeemrisico', [])
ai_act_labels = {
"soort-toepassing": file.page.meta.get('soort-toepassing', []),
"risicogroep": file.page.meta.get('risicogroep', []),
"rol-ai-act": file.page.meta.get('rol-ai-act', []),
"transparantieverplichting": file.page.meta.get('transparantieverplichting', []),
"systeemrisico": file.page.meta.get('systeemrisico', []),
"open-source": file.page.meta.get('open-source', []),
}

# create match expression for labels
label_match_expression = []
for arr in [soort_toepassing, risicogroep, rol_ai_act, transparantieverplichting, systeemrisico]:
if arr:
label_match_expression.append("(" + " || ".join(arr) + ")")
label_match_expression.append(" || ".join(f"{key}-{value}" for key, values in ai_act_labels.items() for value in values if values))
# label_match_expression.append("(" + " || ".join(labels) + ")")
label_match_expression_str = " && ".join(label_match_expression) if label_match_expression else ""

data_html_attribute = "data-labels=\"" + label_match_expression_str + "\""
Expand Down

0 comments on commit fe06b62

Please sign in to comment.