Skip to content

Commit 4dfac73

Browse files
authored
Merge pull request #461 from cidgoh/show-semantic-id
Show semantic id for each slot, and add report of all enumerations at bottom of reference guide.
2 parents e15e90f + 9728408 commit 4dfac73

File tree

5 files changed

+133
-12
lines changed

5 files changed

+133
-12
lines changed

lib/DataHarmonizer.js

+92-9
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ class DataHarmonizer {
125125
);
126126
this.columnHelpEntries = options.columnHelpEntries || [
127127
'column',
128+
'slot_uri',
128129
'description',
129130
'guidance',
130131
'examples',
@@ -176,7 +177,7 @@ class DataHarmonizer {
176177
(field) => field.title === field_reference
177178
);
178179
$('#field-description-text').html(
179-
urlToClickableAnchor(this.getComment(field))
180+
this.getComment(field)
180181
);
181182
$('#field-description-modal').modal('show');
182183
});
@@ -1037,6 +1038,30 @@ class DataHarmonizer {
10371038
hotInstance.render(); // Render the table to apply changes
10381039
}
10391040

1041+
renderSemanticID(curieOrURI, as_markup = false) {
1042+
if (curieOrURI) {
1043+
if (curieOrURI.toLowerCase().startsWith('http')) {
1044+
if (as_markup)
1045+
return `[${curieOrURI}](${curieOrURI})`;
1046+
1047+
return `<a href="${curieOrURI}" target="_blank">${curieOrURI}</a>`;
1048+
}
1049+
else if (curieOrURI.includes(':')) {
1050+
const [prefix, reference] = curieOrURI.split(':',2);
1051+
if (prefix && reference && (prefix in this.schema.prefixes)) {
1052+
// Lookup curie
1053+
let url = this.schema.prefixes[prefix]['prefix_reference'] + reference;
1054+
if (as_markup)
1055+
return `[${curieOrURI}](${url})`;
1056+
return `<a href="${url}" target="_blank">${curieOrURI}</a>`;
1057+
}
1058+
else
1059+
return `${curieOrURI}`;
1060+
}
1061+
}
1062+
return '';
1063+
}
1064+
10401065
/**
10411066
* Presents reference guide in a popup.
10421067
* @param {String} mystyle simple css stylesheet commands to override default.
@@ -1088,9 +1113,11 @@ class DataHarmonizer {
10881113
for (const slot of section.children) {
10891114
const slot_dict = this.getCommentDict(slot);
10901115

1116+
const slot_uri = this.renderSemanticID(slot_dict.slot_uri);
1117+
10911118
row_html += '<tr>';
10921119
if (this.columnHelpEntries.includes('column')) {
1093-
row_html += `<td class="label">${slot_dict.title}</td>`;
1120+
row_html += `<td class="label">${slot_dict.title}<br/>${slot_uri}</td>`;
10941121
}
10951122
if (this.columnHelpEntries.includes('description')) {
10961123
row_html += `<td>${slot_dict.description}</td>`;
@@ -1102,12 +1129,35 @@ class DataHarmonizer {
11021129
row_html += `<td>${slot_dict.examples}</td>`;
11031130
}
11041131
if (this.columnHelpEntries.includes('menus')) {
1105-
row_html += ` <td>${slot_dict.sources || ''}</td>`;
1132+
row_html += ` <td>${slot_dict.menus || ''}</td>`;
11061133
}
11071134
row_html += '</tr>';
11081135
}
11091136
}
11101137

1138+
// Note this may include more enumerations than exist in a given template.
1139+
let enum_html = ``;
1140+
for (const key of Object.keys(this.schema.enums).sort()) {
1141+
const enumeration = this.schema.enums[key];
1142+
let title = enumeration.title != enumeration.name ? enumeration.title : '';
1143+
enum_html += `<tr class="section">
1144+
<td colspan="2" id="${enumeration.name}">${enumeration.name}</td>
1145+
<td colspan="2">(${title})<br/>${this.renderSemanticID(enumeration.enum_uri)}</td>
1146+
</tr>`;
1147+
1148+
for (const item_key in enumeration.permissible_values) {
1149+
const item = enumeration.permissible_values[item_key];
1150+
let text = item.text != item_key ? item.text : '';
1151+
enum_html += `<tr>
1152+
<td>${this.renderSemanticID(item.meaning)}</td>
1153+
<td>${item_key}</td>
1154+
<td>${text}</td>
1155+
<td></td>
1156+
</tr>`;
1157+
}
1158+
}
1159+
1160+
11111161
var win = window.open(
11121162
'',
11131163
'Reference',
@@ -1168,7 +1218,19 @@ class DataHarmonizer {
11681218
</tbody>
11691219
</table>
11701220
</div>
1171-
</body>
1221+
1222+
<div>
1223+
<table>
1224+
<thead>
1225+
<tr class="section">
1226+
<td colspan="4"><h3>${i18next.t('help-picklists')}</h3>
1227+
</td>
1228+
</tr>
1229+
</thead>
1230+
<tbody>${enum_html}</tbody>
1231+
</table>
1232+
</div>
1233+
</body>
11721234
</html>
11731235
`;
11741236
return false;
@@ -1868,6 +1930,14 @@ class DataHarmonizer {
18681930
)}</strong>: ${field.title || field.name}</p>`;
18691931
}
18701932

1933+
// Requires markup treatment of URLS.
1934+
const slot_uri = this.renderSemanticID(field.slot_uri);
1935+
if (field.slot_uri && this.columnHelpEntries.includes('slot_uri')) {
1936+
ret += `<p><strong data-i18n="help-sidebar__column">${i18next.t(
1937+
'help-sidebar__slot_uri'
1938+
)}</strong>: ${slot_uri}</p>`;
1939+
}
1940+
18711941
if (field.description && this.columnHelpEntries.includes('description')) {
18721942
ret += `<p><strong data-i18n="help-sidebar__description">${i18next.t(
18731943
'help-sidebar__description'
@@ -1907,10 +1977,12 @@ class DataHarmonizer {
19071977
let guide = {
19081978
title: field.title,
19091979
name: field.name,
1910-
description: field.description || '',
1980+
slot_uri: field.slot_uri,
1981+
description: urlToClickableAnchor(field.description) || '',
19111982
guidance: '',
19121983
examples: '',
19131984
sources: '',
1985+
menus: ''
19141986
};
19151987

19161988
let guidance = [];
@@ -1955,7 +2027,13 @@ class DataHarmonizer {
19552027
guidance.push(i18next.t('reference_guide_msg_unique_record'));
19562028
}
19572029
if (field.sources && field.sources.length) {
1958-
let sources = [];
2030+
let menus = [];
2031+
for (const item of field.sources) {
2032+
menus.push('<a href="#'+ item + '" target="_self">' + item +'</a>');
2033+
}
2034+
guide.menus = '<ul><li>' + menus.join('</li><li>') + '</li></ul>';
2035+
/*
2036+
// List null value menu items directly
19592037
for (const [, item] of Object.entries(field.sources)) {
19602038
// List null value menu items directly
19612039
if (item === 'NullValueMenu') {
@@ -1967,7 +2045,8 @@ class DataHarmonizer {
19672045
sources.push(item);
19682046
}
19692047
}
1970-
guide.sources = '<ul><li>' + sources.join('</li>\n<li>') + '</li></ul>';
2048+
*/
2049+
guide.sources = '<ul><li>' + field.sources.join('</li><li>') + '</li></ul>';
19712050
}
19722051
if (field.multivalued) {
19732052
guidance.push(i18next.t('reference_guide_msg_more_than_one_selection'));
@@ -1979,6 +2058,10 @@ class DataHarmonizer {
19792058
})
19802059
.join('\n');
19812060

2061+
// Makes full URIs that aren't in markup into <a href>
2062+
if (guide.guidance)
2063+
guide.guidance = urlToClickableAnchor(guide.guidance);
2064+
19822065
if (field.examples && field.examples.length) {
19832066
let examples = [];
19842067
let first_item = true;
@@ -1994,9 +2077,9 @@ class DataHarmonizer {
19942077

19952078
if (first_item === true) {
19962079
first_item = false;
1997-
examples += '<ul><li>' + i18next.t(item.value) + '</li>\n';
2080+
examples += '<ul><li>' + i18next.t(item.value) + '</li>';
19982081
} else {
1999-
examples += '<li>' + i18next.t(item.value) + '</li>\n';
2082+
examples += '<li>' + i18next.t(item.value) + '</li>';
20002083
}
20012084
}
20022085
guide.examples = examples + '</ul>';

lib/Toolbar.js

+4
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,10 @@ class Toolbar {
818818
for (const dh in this.context.dhs) {
819819
this.context.dhs[dh].renderReference();
820820
}
821+
// Prevents another popup on repeated click if user focuses away from
822+
// previous popup.
823+
return false;
824+
821825
}
822826

823827
showError(prefix, message) {

lib/utils/content.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export const urlToClickableAnchor = (string) => {
5353
'g'
5454
);
5555
// Replace the URL with an anchor tag in the string
56-
string = string.replace(regex, `<a href="${escapedURL}">${escapedURL}</a>`);
56+
string = string.replace(regex, `<a href="${escapedURL}" target="_blank">${escapedURL}</a>`);
5757
});
5858

5959
return string;

web/templates/canada_covid19/schema_core.yaml

+28-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,34 @@ in_language:
88
imports:
99
- 'linkml:types'
1010
prefixes:
11-
linkml: 'https://w3id.org/linkml/'
12-
GENEPIO: 'http://purl.obolibrary.org/obo/GENEPIO_'
11+
linkml: https://w3id.org/linkml/
12+
BTO: http://purl.obolibrary.org/obo/BTO_
13+
CIDO: http://purl.obolibrary.org/obo/CIDO_
14+
CLO: http://purl.obolibrary.org/obo/CLO_
15+
DOID: http://purl.obolibrary.org/obo/DOID_
16+
ECTO: http://purl.obolibrary.org/obo/ECTO_
17+
EFO: http://purl.obolibrary.org/obo/EFO_
18+
ENVO: http://purl.obolibrary.org/obo/ENVO_
19+
FOODON: http://purl.obolibrary.org/obo/FOODON_
20+
GAZ: http://purl.obolibrary.org/obo/GAZ_
21+
GENEPIO: http://purl.obolibrary.org/obo/GENEPIO_
22+
GSSO: http://purl.obolibrary.org/obo/GSSO_
23+
HP: http://purl.obolibrary.org/obo/HP_
24+
IDO: http://purl.obolibrary.org/obo/IDO_
25+
MP: http://purl.obolibrary.org/obo/MP_
26+
MMO: http://purl.obolibrary.org/obo/MMO_
27+
MONDO: http://purl.obolibrary.org/obo/MONDO_
28+
MPATH: http://purl.obolibrary.org/obo/MPATH_
29+
NCIT: http://purl.obolibrary.org/obo/NCIT_
30+
NCBITaxon: http://purl.obolibrary.org/obo/NCBITaxon_
31+
NBO: http://purl.obolibrary.org/obo/NBO_
32+
OBI: http://purl.obolibrary.org/obo/OBI_
33+
OMRSE: http://purl.obolibrary.org/obo/OMRSE_
34+
PCO: http://purl.obolibrary.org/obo/PCO_
35+
TRANS: http://purl.obolibrary.org/obo/TRANS_
36+
UBERON: http://purl.obolibrary.org/obo/UBERON_
37+
UO: http://purl.obolibrary.org/obo/UO_
38+
VO: http://purl.obolibrary.org/obo/VO_
1339
classes:
1440
dh_interface:
1541
name: dh_interface

web/translations/translations.json

+8
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@
223223
"en": "Column",
224224
"fr": "Colonne"
225225
},
226+
"help-sidebar__slot_uri": {
227+
"en": "Semantic ID",
228+
"fr": "ID sémantique"
229+
},
226230
"help-sidebar__description": {
227231
"en": "Description",
228232
"fr": "Description"
@@ -239,6 +243,10 @@
239243
"en": "Menus",
240244
"fr": "Menus"
241245
},
246+
"help-picklists": {
247+
"en": "Controlled vocabulary picklists",
248+
"fr": "Des listes de choix de vocabulaire contrôlé"
249+
},
242250
"reference_guide_title": {
243251
"en": "Reference Guide for",
244252
"fr": "Guide de référence pour"

0 commit comments

Comments
 (0)