MediaWiki:Gadget-CheckShex.js: verschil tussen versies
Uit Knowledge Graph Kunstenpunt
Geen bewerkingssamenvatting Label: Ongedaan gemaakt |
Geen bewerkingssamenvatting Label: Ongedaan gemaakt |
||
Regel 1: | Regel 1: | ||
/** | /** | ||
* | * EntityShape.js adds an input box to a wikidata page wherein you can enter an entityschema | ||
* (such as E10). When you | * (such as E10). When you click "Check", checks whether each statement and property conforms | ||
* the schema | * to the schema. It then displays a summary at the top of the item for each property indicating | ||
* whether they conform or not. It also adds a badge to each statement and each property on the | |||
* page indicating whether they conform or not. | |||
**/ | **/ | ||
(function() { | |||
mw.util.addCSS(entityschema_getStylesheet()); | |||
let entityschema_list = []; | |||
let value = window.localStorage.getItem("entityschema-auto"); | |||
let schema = window.localStorage.getItem("entityschema"); | |||
let property_list = []; | |||
let item_list = []; | |||
let entityID = mw.config.get( 'wbEntityId' ); | |||
$(document).ready(function(){ | |||
if (document.location.pathname.includes( | let entityschema_conditions = ["/wiki/Q", "/wiki/P", "/wiki/L"]; | ||
if (entityschema_conditions.some(el => document.location.pathname.includes(el))) { | |||
let entityschema_entity_html = `<div><span id="entityschema-simpleSearch"> | |||
<span> | |||
<input type="text" id="entityschema-entityToCheck" | |||
placeholder="Enter schema to check against e.g. E234" | |||
title="Enter 1 or more schemas to check against separated by commas e.g. E10, E236 or press Check to auto-determine schemas to check"> | |||
<input type="submit" id="entityschema-schemaSearchButton" | |||
} | class="searchButton" name="check" value="Check"> | ||
<div class="entityshape-spinner" style="display:none"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div> | |||
</span> | |||
</span><input type="checkbox" id="entityschema-checkbox"> | |||
<label for="entityschema-checkbox"><small>Automatically check schema</small></label> | |||
<span id="entityschemaResponse"></span></div>`; | |||
$(entityschema_entity_html).insertAfter("#siteSub"); | |||
if (value == "true") { | |||
$("#entityschema-checkbox").prop('checked', true); | |||
} else { | |||
$("#entityschema-checkbox").prop('checked', false); | |||
} | |||
$("#entityschema-schemaSearchButton").click(function(){ entityschema_update(); }); | |||
$("#entityschema-checkbox").click(function() { entityschema_checkbox(); }); | |||
} | |||
}); | |||
mw.hook( 'wikibase.entityPage.entityLoaded' ).add( function ( data ) { | |||
let claims = data["claims"]; | |||
for (let claim in claims) { | |||
property_list.push(claim); | |||
let statements = claims[claim]; | |||
for (let statement in statements) { | |||
let mainsnak = statements[statement]["mainsnak"]; | |||
if (mainsnak["datavalue"] && mainsnak["datatype"] == "wikibase-item") { | |||
if (!item_list.includes(mainsnak["datavalue"]["value"]["id"])) { | |||
item_list.push(mainsnak["datavalue"]["value"]["id"]); | |||
} | |||
} | } | ||
} | |||
} | |||
check_entity_for_schemas(item_list); | |||
check_entity_for_schemas(property_list); | |||
}); | |||
mw.hook( 'wikibase.statement.saved' ).add( function ( data ) { | |||
if (value == "true") { | |||
entityschema_update(); | |||
} | |||
}); | |||
mw.hook( 'wikibase.statement.removed' ).add( function ( data ) { | |||
if (value == "true") { | |||
entityschema_update(); | |||
} | |||
}); | |||
function | function check_entity_for_schemas(entity_list) { | ||
for (let item in entity_list) { | |||
let url = "https://kg.kunsten.be/w/api.php?action=wbgetclaims&property=P12861&format=json&entity=" + entity_list[item]; | |||
$.ajax({ | $.ajax({ | ||
type: "GET", | type: "GET", | ||
dataType: "json", | dataType: "json", | ||
url: | url: url, | ||
success: function(data){ | success: function(data) { | ||
if (data["claims"].hasOwnProperty("P12861")) { | |||
for (let claim in data["claims"]["P12861"]) { | |||
entityschema_list.push(data["claims"]["P12861"][claim]["mainsnak"]["datavalue"]["value"]["id"]); | |||
} | } | ||
} | } | ||
} | }, | ||
}); | }); | ||
} | } | ||
} | |||
$(document).ajaxStop(function () { | |||
if (value == "true" && mw.config.get( 'wbEntityId' )) { | |||
entityschema_update(); | |||
} | |||
$("#entityschema-entityToCheck:text").val(schema); | |||
$(this).unbind('ajaxStop'); | |||
}); | |||
$("#entityschema-entityToCheck").on("keyup", function(event){ | |||
if (event.key === "Enter") { | |||
event.preventDefault(); | |||
$("#entityschema-schemaSearchButton").click(); | |||
return false; | |||
} | |||
}); | }); | ||
function entityschema_update() { | |||
let entityschema_entitySchema = $("#entityschema-entityToCheck")[0].value.toUpperCase(); | |||
if (entityschema_entitySchema.length == 0) { | |||
entityschema_entitySchema = entityschema_list.join(", "); | |||
window.localStorage.setItem("entityschema", ""); | |||
} else { | |||
window.localStorage.setItem("entityschema", entityschema_entitySchema); | |||
} | |||
if (entityschema_entitySchema.length == 0) { | |||
} | $("#entityschemaResponse").append( '<br/><span>No schemas entered and could not automatically determine schemas to check</span>' ); | ||
/ | } else { | ||
let entityschema_entityName = document.location.pathname.substring(6); | |||
let lang = mw.config.get( 'wgUserLanguage' ); | |||
/ | entityschema_checkEntity(entityschema_entityName, entityschema_entitySchema, lang); | ||
} | |||
} | |||
function entityschema_checkbox() { | |||
if ( | if ($('#entityschema-checkbox').is(":checked")) { | ||
window.localStorage.setItem("entityschema-auto", true); | |||
if ( | } else { | ||
window.localStorage.setItem("entityschema-auto", false); | |||
} | |||
} | |||
function entityschema_checkEntity(entity, entitySchema, language) { | |||
$("#entityschemaResponse").contents().remove(); | |||
$(".entityschema-property").remove(); | |||
$(".entityschema-span").remove(); | |||
let url = "https://entityshape.toolforge.org/api/v2?entityschema=" + entitySchema + "&entity=" + entity + "&language=" + language; | |||
// let url = "http://127.0.0.1:5000/api/v2 ?entityschema=" + entitySchema + "&entity=" + entity + "&language=" + language; | |||
$.ajax({ | |||
type: "GET", | |||
dataType: "json", | |||
url: url, | |||
beforeSend: function() { | |||
$(".entityshape-spinner").show(); | |||
}, | |||
success: function(data){ | |||
let html = ""; | |||
for (let i = 0; i < data.schema.length; i++ ) { | |||
if (data.properties[i]) { | |||
entityschema_add_to_properties(data.properties[i], data.schema[i], data.name[i]); | |||
} | |||
if (data.statements[i]) { | |||
entityschema_add_to_statements(data.statements[i], data.schema[i], data.name[i]); | |||
} | |||
if (data.general[i]) { | |||
entityschema_add_general(data.general[i]); | |||
} | |||
} | |||
const combined_properties = entityschema_combine_properties(data.properties, data.schema); | |||
html += "<br/>Checking against <b>"; | |||
for (let schema in data.schema) { | |||
html += `<a href='https://kg.kunsten.be/wiki/EntitySchema:${data.schema[schema]}'>${data.schema[schema]}: ${data.name[schema]}</a> `; | |||
} | |||
html += `</b>: | |||
<div style="overflow-y: scroll; max-height:200px;"> | |||
<table style="width:100%;"> | |||
<th class="entityschema_table" title="Properties in this item which must be present">Required properties</th> | |||
<th class="entityschema_table" title="Properties in this item which can be present but do not have to be">Optional properties</th> | |||
<th class="entityschema_table" title="Properties in this item which are not allowed to be present or not mentioned in the entityschema">Other properties</th> | |||
<tr>`; | |||
html += entityschema_process_combined_properties(combined_properties); | |||
$("#entityschemaResponse" ).append( html ); | |||
$(".entityshape-spinner").hide(); | |||
}, | |||
error: function(data) { | |||
$("#entityschemaResponse").append( '<br/><span>Unable to validate schema</span>' ); | |||
} | |||
}); | |||
} | |||
function entityschema_process_combined_properties(properties) { | |||
let required_html = '<td class="entityschema_table required"><ul style="list-style-type:none";>'; | |||
let optional_html = '<td class="entityschema_table optional"><ul style="list-style-type:none";>'; | |||
let absent_html = '<td class="entityschema_table absent"><ul style="list-style-type:none";>'; | |||
let other_array = []; | |||
let other_array_names = []; | |||
for (let key in properties) { | |||
let shape_html = ""; | |||
let response1 = properties[key].response.combined; | |||
let response_class = ""; | |||
switch (response1) { | |||
case "present": | |||
response_class = "present"; | |||
break; | |||
case "allowed": | |||
response_class = "present"; | |||
break; | |||
case "correct": | |||
response_class = "correct"; | |||
break; | |||
case "missing": | |||
response_class = "missing"; | |||
break; | |||
default: | |||
response_class = "wrong"; | |||
break; | |||
} | |||
if (properties[key].necessity.combined == "absent") { | |||
if (response1 == "too many statements") { | |||
response1 = "not allowed"; | |||
} | |||
} | |||
if (!response1) { | |||
response1 = "Not in schema"; | |||
response_class = "notinschema"; | |||
} | |||
if (response1 == null) { | |||
response1 = ""; | |||
shape_html += `<a href="https://kg.kunsten.be/wiki/Property:${key}">${key} - <small>${properties[key].name}</small></a><br/>`; | |||
} else if (response1 == "Not in schema") { | |||
other_array.push(key); | |||
other_array_names.push(properties[key].name); | |||
} else { | |||
shape_html += `<li class="is_entityschema-${response_class}"> | |||
<span class="entityschema-span entityschema-${response_class}">${response1}</span> | |||
<a href="https://kg.kunsten.be/wiki/Property:${key}" | |||
class="is_entityschema-${response_class}"> | |||
${key} - <small>${properties[key].name}</small></a></li>` | |||
} | |||
switch (properties[key].necessity.combined) { | |||
case "required": | |||
required_html += shape_html; | |||
break; | |||
case "optional": | |||
optional_html += shape_html; | |||
break; | |||
default: | |||
absent_html += shape_html; | |||
break; | |||
} | |||
} | |||
let other_html = `<details><summary>${other_array.length} properties not in any schema checked</summary> | |||
<ul style='list-style-type:none';>`; | |||
for (let item in other_array) { | |||
other_html += `<li><span class="entityschema-span entityschema-notinschema">Not in schema</span> | |||
<a href="https://kg.kunsten.be/wiki/Property:${other_array[item]}" | |||
class="is_entityschema-notinschema">${other_array[item]} - <small>${other_array_names[item]}</small></a></li>`; | |||
} | |||
other_html += "</ul></details>"; | |||
absent_html += "</ul>" + other_html; | |||
required_html += "</ul></td>"; | |||
optional_html += "</ul></td>"; | |||
absent_html += "</td>"; | |||
html = required_html + optional_html + absent_html + '</tr></table></div>'; | |||
return html; | |||
} | |||
function entityschema_add_to_properties(properties, schema, name) { | |||
for (let key in properties) { | |||
let response = properties[key].response; | |||
let response_class = ""; | |||
switch (response) { | |||
case "present": | |||
response_class = "present"; | |||
break; | |||
case "correct": | |||
response_class = "correct"; | |||
break; | |||
case "missing": | |||
response_class = "missing"; | |||
break; | |||
default: | |||
response_class = "wrong"; | |||
break; | |||
} | |||
if (properties[key].necessity == "absent") { | |||
if (response == "too many statements") { | |||
response = "not allowed"; | |||
} | |||
} | |||
if (!response) { | |||
response = "Not in schema"; | |||
response_class = "notinschema"; | |||
} | |||
if (response == null) { | |||
response = "Not in schema"; | |||
response_class = "notinschema"; | |||
} | |||
if (response != "Not in schema" && $("#" + key)[0]) { | |||
let html =`<br class='entityschema-property'/> | |||
<div style='display:inline-block;' | |||
class='entityschema-span entityschema-property entityschema-${response_class}' | |||
title='${schema}: ${name}'>${schema}: ${response} | |||
</div>`; | |||
$(`#${key} .wikibase-statementgroupview-property-label`).append(html); | |||
} | } | ||
} | } | ||
} | } | ||
function | |||
function entityschema_add_to_statements(statements, schema, name) { | |||
for (let statement in statements) { | |||
let response = statements[statement].response; | |||
if (response != "not in schema") { | |||
let html = `<br class='entityschema-property'/> | |||
<span class='entityschema-span entityschema-property entityschema-${response}' | |||
title='${schema}: ${name}'>${schema}: ${response} | |||
</span>`; | |||
$(`div[id='${statement}'] .wikibase-toolbar-button-edit`).append(html); | |||
} | |||
} | |||
} | |||
function entityschema_add_general(general) { | |||
if (general.language) { | |||
entityschema_add_general_item("language", general.language); | |||
} | |||
if (general.lexicalCategory) { | |||
entityschema_add_general_item("lexical_category", general.lexicalCategory); | |||
} | |||
} | |||
function entityschema_add_general_item(general_type, response) { | |||
if (response != "not in schema") { | |||
html = `<span class='entityschema-property'/> | |||
<span class='entityschema-span entityschema-property entityschema-${response}'>${response} | |||
</span>`; | |||
$(`span[class='language-lexical-category-${general_type}']`).append(html); | |||
} | } | ||
} | } | ||
function | |||
function entityschema_combine_properties(property, schema) { | |||
let combined_properties = {}; | |||
for (let i = 0; i < schema.length; i++ ) { | |||
for ( | for (let key in property[i]) { | ||
if ( | if(!combined_properties.hasOwnProperty(key)){ combined_properties[key] = {}; } | ||
combined_properties[key]["name"] = property[i][key]["name"]; | |||
if(!combined_properties[key].hasOwnProperty("response")) { combined_properties[key]["response"] = {}; } | |||
combined_properties[key]["response"][schema[i]] = property[i][key]["response"]; | |||
if(!combined_properties[key].hasOwnProperty("necessity")) { combined_properties[key]["necessity"] = {}; } | |||
combined_properties[key]["necessity"][schema[i]] = property[i][key]["necessity"]; | |||
} | } | ||
} | } | ||
for (let key in combined_properties) { | |||
let necessity = "absent"; | |||
let response = ""; | |||
let response_key = combined_properties[key]["response"]; | |||
let necessity_key = combined_properties[key]["necessity"]; | |||
if (Object.values(necessity_key).includes("required")) { | |||
necessity = "required"; | |||
} else if (Object.values(necessity_key).includes("optional")) { | |||
necessity = "optional"; | |||
} | |||
if (Object.values(response_key).includes("incorrect")) { | |||
response = "incorrect"; | |||
} else if (Object.values(response_key).includes("missing")) { | |||
response = "missing"; | |||
} else if (Object.values(response_key).includes("too many statements")) { | |||
response = "too many statements"; | |||
} else if (Object.values(response_key).includes("not enough statements")) { | |||
response = "not enough statements"; | |||
} else if (Object.values(response_key).includes("correct")) { | |||
response = "correct"; | |||
} else if (Object.values(response_key).includes("present")) { | |||
response = "present"; | |||
} else if (Object.values(response_key).includes("allowed")) { | |||
response = "present"; | |||
} | |||
combined_properties[key]["response"]["combined"] = response; | |||
combined_properties[key]["necessity"]["combined"] = necessity; | |||
} | |||
return combined_properties; | |||
} | |||
function entityschema_getStylesheet() { | |||
let stylesheet = "#entityschema-schemaSearchButton { background-position: center center; background-repeat: no-repeat; position: relative !important; top: 0; right: 0; overflow: hidden; height: 100%; background-color: #1E90FF !important; color: #FFFFFF !important; padding: 0.5em; text-indent: 0px !important; margin-left: 5px; width: 50px; margin-right: 5px;}"; | |||
stylesheet += "#entityschema-entityToCheck { padding: 0.5em; margin: 0; width: 33%;}"; | |||
stylesheet += ".response { padding: 2px;}"; | |||
stylesheet += "a.is_entityschema-present { color: #008800; }"; | |||
stylesheet += "a.is_entityschema-allowed { color: #008800; }"; | |||
stylesheet += "a.is_entityschema-correct { color: #00CC00; }"; | |||
stylesheet += "a.is_entityschema-missing { color: #FF5500; }"; | |||
stylesheet += "a.is_entityschema-notinschema { color: #FF5500; }"; | |||
stylesheet += "a.is_entityschema-wrong { color: #CC0000; }"; | |||
stylesheet += "a.is_entityschema-wrong_amount { color: #CC0000; }"; | |||
stylesheet += "a.is_entityschema-incorrect { color: #CC0000; }"; | |||
stylesheet += ".entityschema_table {vertical-align: top; width: 33%;} "; | |||
stylesheet += ".entityschema-missing { background-color: #FF8C00; }"; | |||
stylesheet += ".entityschema-notinschema { background-color: #FF8C00; }"; | |||
stylesheet += ".entityschema-wrong { background-color: #CC0000; }"; | |||
stylesheet += ".entityschema-incorrect { background-color: #CC0000; }"; | |||
stylesheet += ".entityschema-wrong_amount { background-color: #CC0000; }"; | |||
stylesheet += ".entityschema-excess { background-color: #CC0000; }"; | |||
stylesheet += ".entityschema-deficit { background-color: #CC0000; }"; | |||
stylesheet += ".entityschema-present { background-color: #008800; }"; | |||
stylesheet += ".entityschema-allowed { background-color: #008800; }"; | |||
stylesheet += ".entityschema-correct { background-color: #00CC00; }"; | |||
stylesheet += ".required .entityschema-missing { background-color: #FF0000;}"; | |||
stylesheet += ".required a.is_entityschema-missing { color: #FF0000;}"; | |||
stylesheet += ".absent .entityschema-missing { display: none;}"; | |||
stylesheet += ".absent a.is_entityschema-missing { display: none;}"; | |||
stylesheet += ".entityschema-span { color: #ffffff; padding:2px; margin: 2px; font-size:75%; border-radius:2px; }"; | |||
stylesheet += ".entityshape-spinner,.entityshape-spinner div,.entityshape-spinner div:after {box-sizing: border-box;}"; | |||
stylesheet += ".entityshape-spinner { padding-top:5px; padding-bottom:5px; color: currentColor; display: inline-block; position: relative; width: 20px; height: 20px;}"; | |||
stylesheet += ".entityshape-spinner div { transform-origin: 10px 10px; animation: entityshape-spinner 1.2s linear infinite;}"; | |||
stylesheet += '.entityshape-spinner div:after { content: " "; display: block; position: absolute; top: 0.8px; left: 9.2px; width: 1.6px; height: 4.4px; border-radius: 20%; background: currentColor;}'; | |||
stylesheet += ".entityshape-spinner div:nth-child(1) { transform: rotate(0deg); animation-delay: -1.1s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(2) { transform: rotate(30deg); animation-delay: -1s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(3) { transform: rotate(60deg); animation-delay: -0.9s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(4) { transform: rotate(90deg); animation-delay: -0.8s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(5) { transform: rotate(120deg); animation-delay: -0.7s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(6) { transform: rotate(150deg); animation-delay: -0.6s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(7) { transform: rotate(180deg); animation-delay: -0.5s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(8) { transform: rotate(210deg); animation-delay: -0.4s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(9) { transform: rotate(240deg); animation-delay: -0.3s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(10) { transform: rotate(270deg); animation-delay: -0.2s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(11) { transform: rotate(300deg); animation-delay: -0.1s;}"; | |||
stylesheet += ".entityshape-spinner div:nth-child(12) { transform: rotate(330deg); animation-delay: 0s;}"; | |||
stylesheet += "@keyframes entityshape-spinner { 0% { opacity: 1; } 100% { opacity: 0; }}"; | |||
return stylesheet; | |||
} | } | ||
}()); | |||
Versie van 7 okt 2024 22:45
/** * EntityShape.js adds an input box to a wikidata page wherein you can enter an entityschema * (such as E10). When you click "Check", checks whether each statement and property conforms * to the schema. It then displays a summary at the top of the item for each property indicating * whether they conform or not. It also adds a badge to each statement and each property on the * page indicating whether they conform or not. **/ (function() { mw.util.addCSS(entityschema_getStylesheet()); let entityschema_list = []; let value = window.localStorage.getItem("entityschema-auto"); let schema = window.localStorage.getItem("entityschema"); let property_list = []; let item_list = []; let entityID = mw.config.get( 'wbEntityId' ); $(document).ready(function(){ let entityschema_conditions = ["/wiki/Q", "/wiki/P", "/wiki/L"]; if (entityschema_conditions.some(el => document.location.pathname.includes(el))) { let entityschema_entity_html = `<div><span id="entityschema-simpleSearch"> <span> <input type="text" id="entityschema-entityToCheck" placeholder="Enter schema to check against e.g. E234" title="Enter 1 or more schemas to check against separated by commas e.g. E10, E236 or press Check to auto-determine schemas to check"> <input type="submit" id="entityschema-schemaSearchButton" class="searchButton" name="check" value="Check"> <div class="entityshape-spinner" style="display:none"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div> </span> </span><input type="checkbox" id="entityschema-checkbox"> <label for="entityschema-checkbox"><small>Automatically check schema</small></label> <span id="entityschemaResponse"></span></div>`; $(entityschema_entity_html).insertAfter("#siteSub"); if (value == "true") { $("#entityschema-checkbox").prop('checked', true); } else { $("#entityschema-checkbox").prop('checked', false); } $("#entityschema-schemaSearchButton").click(function(){ entityschema_update(); }); $("#entityschema-checkbox").click(function() { entityschema_checkbox(); }); } }); mw.hook( 'wikibase.entityPage.entityLoaded' ).add( function ( data ) { let claims = data["claims"]; for (let claim in claims) { property_list.push(claim); let statements = claims[claim]; for (let statement in statements) { let mainsnak = statements[statement]["mainsnak"]; if (mainsnak["datavalue"] && mainsnak["datatype"] == "wikibase-item") { if (!item_list.includes(mainsnak["datavalue"]["value"]["id"])) { item_list.push(mainsnak["datavalue"]["value"]["id"]); } } } } check_entity_for_schemas(item_list); check_entity_for_schemas(property_list); }); mw.hook( 'wikibase.statement.saved' ).add( function ( data ) { if (value == "true") { entityschema_update(); } }); mw.hook( 'wikibase.statement.removed' ).add( function ( data ) { if (value == "true") { entityschema_update(); } }); function check_entity_for_schemas(entity_list) { for (let item in entity_list) { let url = "https://kg.kunsten.be/w/api.php?action=wbgetclaims&property=P12861&format=json&entity=" + entity_list[item]; $.ajax({ type: "GET", dataType: "json", url: url, success: function(data) { if (data["claims"].hasOwnProperty("P12861")) { for (let claim in data["claims"]["P12861"]) { entityschema_list.push(data["claims"]["P12861"][claim]["mainsnak"]["datavalue"]["value"]["id"]); } } }, }); } } $(document).ajaxStop(function () { if (value == "true" && mw.config.get( 'wbEntityId' )) { entityschema_update(); } $("#entityschema-entityToCheck:text").val(schema); $(this).unbind('ajaxStop'); }); $("#entityschema-entityToCheck").on("keyup", function(event){ if (event.key === "Enter") { event.preventDefault(); $("#entityschema-schemaSearchButton").click(); return false; } }); function entityschema_update() { let entityschema_entitySchema = $("#entityschema-entityToCheck")[0].value.toUpperCase(); if (entityschema_entitySchema.length == 0) { entityschema_entitySchema = entityschema_list.join(", "); window.localStorage.setItem("entityschema", ""); } else { window.localStorage.setItem("entityschema", entityschema_entitySchema); } if (entityschema_entitySchema.length == 0) { $("#entityschemaResponse").append( '<br/><span>No schemas entered and could not automatically determine schemas to check</span>' ); } else { let entityschema_entityName = document.location.pathname.substring(6); let lang = mw.config.get( 'wgUserLanguage' ); entityschema_checkEntity(entityschema_entityName, entityschema_entitySchema, lang); } } function entityschema_checkbox() { if ($('#entityschema-checkbox').is(":checked")) { window.localStorage.setItem("entityschema-auto", true); } else { window.localStorage.setItem("entityschema-auto", false); } } function entityschema_checkEntity(entity, entitySchema, language) { $("#entityschemaResponse").contents().remove(); $(".entityschema-property").remove(); $(".entityschema-span").remove(); let url = "https://entityshape.toolforge.org/api/v2?entityschema=" + entitySchema + "&entity=" + entity + "&language=" + language; // let url = "http://127.0.0.1:5000/api/v2 ?entityschema=" + entitySchema + "&entity=" + entity + "&language=" + language; $.ajax({ type: "GET", dataType: "json", url: url, beforeSend: function() { $(".entityshape-spinner").show(); }, success: function(data){ let html = ""; for (let i = 0; i < data.schema.length; i++ ) { if (data.properties[i]) { entityschema_add_to_properties(data.properties[i], data.schema[i], data.name[i]); } if (data.statements[i]) { entityschema_add_to_statements(data.statements[i], data.schema[i], data.name[i]); } if (data.general[i]) { entityschema_add_general(data.general[i]); } } const combined_properties = entityschema_combine_properties(data.properties, data.schema); html += "<br/>Checking against <b>"; for (let schema in data.schema) { html += `<a href='https://kg.kunsten.be/wiki/EntitySchema:${data.schema[schema]}'>${data.schema[schema]}: ${data.name[schema]}</a> `; } html += `</b>: <div style="overflow-y: scroll; max-height:200px;"> <table style="width:100%;"> <th class="entityschema_table" title="Properties in this item which must be present">Required properties</th> <th class="entityschema_table" title="Properties in this item which can be present but do not have to be">Optional properties</th> <th class="entityschema_table" title="Properties in this item which are not allowed to be present or not mentioned in the entityschema">Other properties</th> <tr>`; html += entityschema_process_combined_properties(combined_properties); $("#entityschemaResponse" ).append( html ); $(".entityshape-spinner").hide(); }, error: function(data) { $("#entityschemaResponse").append( '<br/><span>Unable to validate schema</span>' ); } }); } function entityschema_process_combined_properties(properties) { let required_html = '<td class="entityschema_table required"><ul style="list-style-type:none";>'; let optional_html = '<td class="entityschema_table optional"><ul style="list-style-type:none";>'; let absent_html = '<td class="entityschema_table absent"><ul style="list-style-type:none";>'; let other_array = []; let other_array_names = []; for (let key in properties) { let shape_html = ""; let response1 = properties[key].response.combined; let response_class = ""; switch (response1) { case "present": response_class = "present"; break; case "allowed": response_class = "present"; break; case "correct": response_class = "correct"; break; case "missing": response_class = "missing"; break; default: response_class = "wrong"; break; } if (properties[key].necessity.combined == "absent") { if (response1 == "too many statements") { response1 = "not allowed"; } } if (!response1) { response1 = "Not in schema"; response_class = "notinschema"; } if (response1 == null) { response1 = ""; shape_html += `<a href="https://kg.kunsten.be/wiki/Property:${key}">${key} - <small>${properties[key].name}</small></a><br/>`; } else if (response1 == "Not in schema") { other_array.push(key); other_array_names.push(properties[key].name); } else { shape_html += `<li class="is_entityschema-${response_class}"> <span class="entityschema-span entityschema-${response_class}">${response1}</span> <a href="https://kg.kunsten.be/wiki/Property:${key}" class="is_entityschema-${response_class}"> ${key} - <small>${properties[key].name}</small></a></li>` } switch (properties[key].necessity.combined) { case "required": required_html += shape_html; break; case "optional": optional_html += shape_html; break; default: absent_html += shape_html; break; } } let other_html = `<details><summary>${other_array.length} properties not in any schema checked</summary> <ul style='list-style-type:none';>`; for (let item in other_array) { other_html += `<li><span class="entityschema-span entityschema-notinschema">Not in schema</span> <a href="https://kg.kunsten.be/wiki/Property:${other_array[item]}" class="is_entityschema-notinschema">${other_array[item]} - <small>${other_array_names[item]}</small></a></li>`; } other_html += "</ul></details>"; absent_html += "</ul>" + other_html; required_html += "</ul></td>"; optional_html += "</ul></td>"; absent_html += "</td>"; html = required_html + optional_html + absent_html + '</tr></table></div>'; return html; } function entityschema_add_to_properties(properties, schema, name) { for (let key in properties) { let response = properties[key].response; let response_class = ""; switch (response) { case "present": response_class = "present"; break; case "correct": response_class = "correct"; break; case "missing": response_class = "missing"; break; default: response_class = "wrong"; break; } if (properties[key].necessity == "absent") { if (response == "too many statements") { response = "not allowed"; } } if (!response) { response = "Not in schema"; response_class = "notinschema"; } if (response == null) { response = "Not in schema"; response_class = "notinschema"; } if (response != "Not in schema" && $("#" + key)[0]) { let html =`<br class='entityschema-property'/> <div style='display:inline-block;' class='entityschema-span entityschema-property entityschema-${response_class}' title='${schema}: ${name}'>${schema}: ${response} </div>`; $(`#${key} .wikibase-statementgroupview-property-label`).append(html); } } } function entityschema_add_to_statements(statements, schema, name) { for (let statement in statements) { let response = statements[statement].response; if (response != "not in schema") { let html = `<br class='entityschema-property'/> <span class='entityschema-span entityschema-property entityschema-${response}' title='${schema}: ${name}'>${schema}: ${response} </span>`; $(`div[id='${statement}'] .wikibase-toolbar-button-edit`).append(html); } } } function entityschema_add_general(general) { if (general.language) { entityschema_add_general_item("language", general.language); } if (general.lexicalCategory) { entityschema_add_general_item("lexical_category", general.lexicalCategory); } } function entityschema_add_general_item(general_type, response) { if (response != "not in schema") { html = `<span class='entityschema-property'/> <span class='entityschema-span entityschema-property entityschema-${response}'>${response} </span>`; $(`span[class='language-lexical-category-${general_type}']`).append(html); } } function entityschema_combine_properties(property, schema) { let combined_properties = {}; for (let i = 0; i < schema.length; i++ ) { for (let key in property[i]) { if(!combined_properties.hasOwnProperty(key)){ combined_properties[key] = {}; } combined_properties[key]["name"] = property[i][key]["name"]; if(!combined_properties[key].hasOwnProperty("response")) { combined_properties[key]["response"] = {}; } combined_properties[key]["response"][schema[i]] = property[i][key]["response"]; if(!combined_properties[key].hasOwnProperty("necessity")) { combined_properties[key]["necessity"] = {}; } combined_properties[key]["necessity"][schema[i]] = property[i][key]["necessity"]; } } for (let key in combined_properties) { let necessity = "absent"; let response = ""; let response_key = combined_properties[key]["response"]; let necessity_key = combined_properties[key]["necessity"]; if (Object.values(necessity_key).includes("required")) { necessity = "required"; } else if (Object.values(necessity_key).includes("optional")) { necessity = "optional"; } if (Object.values(response_key).includes("incorrect")) { response = "incorrect"; } else if (Object.values(response_key).includes("missing")) { response = "missing"; } else if (Object.values(response_key).includes("too many statements")) { response = "too many statements"; } else if (Object.values(response_key).includes("not enough statements")) { response = "not enough statements"; } else if (Object.values(response_key).includes("correct")) { response = "correct"; } else if (Object.values(response_key).includes("present")) { response = "present"; } else if (Object.values(response_key).includes("allowed")) { response = "present"; } combined_properties[key]["response"]["combined"] = response; combined_properties[key]["necessity"]["combined"] = necessity; } return combined_properties; } function entityschema_getStylesheet() { let stylesheet = "#entityschema-schemaSearchButton { background-position: center center; background-repeat: no-repeat; position: relative !important; top: 0; right: 0; overflow: hidden; height: 100%; background-color: #1E90FF !important; color: #FFFFFF !important; padding: 0.5em; text-indent: 0px !important; margin-left: 5px; width: 50px; margin-right: 5px;}"; stylesheet += "#entityschema-entityToCheck { padding: 0.5em; margin: 0; width: 33%;}"; stylesheet += ".response { padding: 2px;}"; stylesheet += "a.is_entityschema-present { color: #008800; }"; stylesheet += "a.is_entityschema-allowed { color: #008800; }"; stylesheet += "a.is_entityschema-correct { color: #00CC00; }"; stylesheet += "a.is_entityschema-missing { color: #FF5500; }"; stylesheet += "a.is_entityschema-notinschema { color: #FF5500; }"; stylesheet += "a.is_entityschema-wrong { color: #CC0000; }"; stylesheet += "a.is_entityschema-wrong_amount { color: #CC0000; }"; stylesheet += "a.is_entityschema-incorrect { color: #CC0000; }"; stylesheet += ".entityschema_table {vertical-align: top; width: 33%;} "; stylesheet += ".entityschema-missing { background-color: #FF8C00; }"; stylesheet += ".entityschema-notinschema { background-color: #FF8C00; }"; stylesheet += ".entityschema-wrong { background-color: #CC0000; }"; stylesheet += ".entityschema-incorrect { background-color: #CC0000; }"; stylesheet += ".entityschema-wrong_amount { background-color: #CC0000; }"; stylesheet += ".entityschema-excess { background-color: #CC0000; }"; stylesheet += ".entityschema-deficit { background-color: #CC0000; }"; stylesheet += ".entityschema-present { background-color: #008800; }"; stylesheet += ".entityschema-allowed { background-color: #008800; }"; stylesheet += ".entityschema-correct { background-color: #00CC00; }"; stylesheet += ".required .entityschema-missing { background-color: #FF0000;}"; stylesheet += ".required a.is_entityschema-missing { color: #FF0000;}"; stylesheet += ".absent .entityschema-missing { display: none;}"; stylesheet += ".absent a.is_entityschema-missing { display: none;}"; stylesheet += ".entityschema-span { color: #ffffff; padding:2px; margin: 2px; font-size:75%; border-radius:2px; }"; stylesheet += ".entityshape-spinner,.entityshape-spinner div,.entityshape-spinner div:after {box-sizing: border-box;}"; stylesheet += ".entityshape-spinner { padding-top:5px; padding-bottom:5px; color: currentColor; display: inline-block; position: relative; width: 20px; height: 20px;}"; stylesheet += ".entityshape-spinner div { transform-origin: 10px 10px; animation: entityshape-spinner 1.2s linear infinite;}"; stylesheet += '.entityshape-spinner div:after { content: " "; display: block; position: absolute; top: 0.8px; left: 9.2px; width: 1.6px; height: 4.4px; border-radius: 20%; background: currentColor;}'; stylesheet += ".entityshape-spinner div:nth-child(1) { transform: rotate(0deg); animation-delay: -1.1s;}"; stylesheet += ".entityshape-spinner div:nth-child(2) { transform: rotate(30deg); animation-delay: -1s;}"; stylesheet += ".entityshape-spinner div:nth-child(3) { transform: rotate(60deg); animation-delay: -0.9s;}"; stylesheet += ".entityshape-spinner div:nth-child(4) { transform: rotate(90deg); animation-delay: -0.8s;}"; stylesheet += ".entityshape-spinner div:nth-child(5) { transform: rotate(120deg); animation-delay: -0.7s;}"; stylesheet += ".entityshape-spinner div:nth-child(6) { transform: rotate(150deg); animation-delay: -0.6s;}"; stylesheet += ".entityshape-spinner div:nth-child(7) { transform: rotate(180deg); animation-delay: -0.5s;}"; stylesheet += ".entityshape-spinner div:nth-child(8) { transform: rotate(210deg); animation-delay: -0.4s;}"; stylesheet += ".entityshape-spinner div:nth-child(9) { transform: rotate(240deg); animation-delay: -0.3s;}"; stylesheet += ".entityshape-spinner div:nth-child(10) { transform: rotate(270deg); animation-delay: -0.2s;}"; stylesheet += ".entityshape-spinner div:nth-child(11) { transform: rotate(300deg); animation-delay: -0.1s;}"; stylesheet += ".entityshape-spinner div:nth-child(12) { transform: rotate(330deg); animation-delay: 0s;}"; stylesheet += "@keyframes entityshape-spinner { 0% { opacity: 1; } 100% { opacity: 0; }}"; return stylesheet; } }());