From afcc474d3c12e842cc735477917c56aa923a003c Mon Sep 17 00:00:00 2001 From: Quincy Morgan Date: Sat, 1 Dec 2018 17:39:16 -0800 Subject: [PATCH] Wikidata entity labels and descriptions are now fetched and displayed in the field, if present --- css/80_app.css | 7 +-- data/core.yaml | 4 ++ dist/locales/en.json | 8 +++- modules/services/wikidata.js | 27 ++++++++++++ modules/ui/fields/wikidata.js | 80 +++++++++++++++++++++++++++++++---- 5 files changed, 112 insertions(+), 14 deletions(-) diff --git a/css/80_app.css b/css/80_app.css index 11bfa43cb..ada187611 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -1303,6 +1303,7 @@ img.tag-reference-wiki-image { background-color: #f1f1f1; } .form-field-button .icon { + fill: #333; opacity: .5; } @@ -1336,12 +1337,12 @@ img.tag-reference-wiki-image { width: 100%; } .form-field ul.labeled-inputs li { - border-bottom: 1px solid #ccc; + border-top: 1px solid #ccc; display: flex; flex-flow: row nowrap; } -.form-field ul.labeled-inputs li:last-child { - border-bottom: 0; +.form-field ul.labeled-inputs li:first-child { + border-top: 0; } .form-field ul.labeled-inputs li > span, .form-field ul.labeled-inputs li > div { diff --git a/data/core.yaml b/data/core.yaml index 154539f0d..50e7a3031 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -5,6 +5,8 @@ en: remove: remove undo: undo zoom_to: zoom to + copy: copy + open_wikidata: open on wikidata.org modes: add_area: title: Area @@ -1245,3 +1247,5 @@ en: coordinate_pair: "{latitude}, {longitude}" wikidata: identifier: "Identifier" + label: "Label" + description: "Description" diff --git a/dist/locales/en.json b/dist/locales/en.json index bf0506afe..c7ffc067d 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -5,7 +5,9 @@ "information": "info", "remove": "remove", "undo": "undo", - "zoom_to": "zoom to" + "zoom_to": "zoom to", + "copy": "copy", + "open_wikidata": "open on wikidata.org" }, "modes": { "add_area": { @@ -1438,7 +1440,9 @@ "coordinate_pair": "{latitude}, {longitude}" }, "wikidata": { - "identifier": "Identifier" + "identifier": "Identifier", + "label": "Label", + "description": "Description" }, "presets": { "categories": { diff --git a/modules/services/wikidata.js b/modules/services/wikidata.js index 1e80e32a1..83301fc65 100644 --- a/modules/services/wikidata.js +++ b/modules/services/wikidata.js @@ -2,6 +2,7 @@ import { json as d3_json } from 'd3-request'; import { utilQsString } from '../util'; +import { currentLocale } from '../util/locale'; var endpoint = 'https://www.wikidata.org/w/api.php?'; @@ -34,6 +35,32 @@ export default { callback(title, data.entities || {}); } }); + }, + + entityByQID: function(qid, callback) { + if (!qid) { + callback('', {}); + return; + } + + var lang = currentLocale.replace(/-/g, '_'); + + d3_json(endpoint + utilQsString({ + action: 'wbgetentities', + format: 'json', + ids: qid, + props: /*sitelinks|*/'labels|descriptions', + //sitefilter: lang + 'wiki', + languages: lang, + languagefallback: 1, + origin: '*' + }), function(err, data) { + if (err || !data || data.error) { + callback('', {}); + } else { + callback(qid, data.entities[qid] || {}); + } + }); } }; diff --git a/modules/ui/fields/wikidata.js b/modules/ui/fields/wikidata.js index 497aebe6d..bfb1ac7dc 100644 --- a/modules/ui/fields/wikidata.js +++ b/modules/ui/fields/wikidata.js @@ -5,6 +5,8 @@ import { event as d3_event } from 'd3-selection'; +import { services } from '../../services/index'; + import { svgIcon } from '../../svg/index'; import { utilGetSetValue, @@ -16,6 +18,7 @@ import { t } from '../../util/locale'; export function uiFieldWikidata(field) { + var wikidata = services.wikidata; var dispatch = d3_dispatch('change'), link = d3_select(null), title = d3_select(null), @@ -42,29 +45,32 @@ export function uiFieldWikidata(field) { .attr('class', 'labeled-inputs') .merge(list); + var wikidataProperties = ['identifier', 'label', 'description']; var items = list.selectAll('li') - .data(field.keys); + .data(wikidataProperties); // Enter var enter = items.enter() .append('li') - .attr('class', function(d) { return 'preset-access-' + d; }); + .attr('class', function(d) { return 'preset-wikidata-' + d; }); enter .append('span') - .attr('class', 'label preset-label-access') + .attr('class', 'label') .attr('for', function(d) { return 'preset-input-wikidata-' + d; }) - .text(t('wikidata.identifier')); + .text(function(d) { return t('wikidata.'+d); }); var inputWrap = enter .append('div') - .attr('class', 'preset-input-wikidata-wrap'); + .attr('class', 'input-wrap'); - title = inputWrap.append('input') + inputWrap.append('input') .attr('type', 'text') .attr('class', 'preset-input-wikidata') - .attr('id', function(d) { return 'preset-input-wikidata-' + d; }) + .attr('id', function(d) { return 'preset-input-wikidata-' + d; }); + + title = wrap.select('.preset-wikidata-identifier input') .call(utilNoAuto) .merge(title); @@ -72,9 +78,14 @@ export function uiFieldWikidata(field) { .on('blur', blur) .on('change', change); - link = enter - .append('button') + var idItem = wrap.select('.preset-wikidata-identifier'); + + idItem.select('button') + .remove(); + + link = idItem.append('button') .attr('class', 'form-field-button wiki-link') + .attr('title', t('icons.open_wikidata')) .attr('tabindex', -1) .call(svgIcon('#iD-icon-out-link')) .merge(link); @@ -84,6 +95,29 @@ export function uiFieldWikidata(field) { d3_event.preventDefault(); if (wikiURL) window.open(wikiURL, '_blank'); }); + + var readOnlyItems = wrap.selectAll('li:not(.preset-wikidata-identifier)'); + + readOnlyItems.select('input') + .classed('disabled', 'true') + .attr('readonly', 'true'); + + readOnlyItems.select('button') + .remove(); + + readOnlyItems.append('button') + .attr('class', 'form-field-button wiki-link') + .attr('title', t('icons.copy')) + .attr('tabindex', -1) + .call(svgIcon('#iD-operation-copy')) + .on('click', function() { + d3_event.preventDefault(); + d3_select(this.parentNode) + .select('input') + .node() + .select(); + document.execCommand("copy"); + }); } @@ -109,8 +143,36 @@ export function uiFieldWikidata(field) { // value in correct format if (matches) { wikiURL = 'https://wikidata.org/wiki/' + value; + wikidata.entityByQID(value, function(qid, entity) { + var label = '', description = ''; + + if (entity.labels && Object.keys(entity.labels).length > 0) { + var lang = Object.keys(entity.labels)[0]; + label = entity.labels[lang].value; + } + if (entity.descriptions && Object.keys(entity.descriptions).length > 0) { + var lang = Object.keys(entity.descriptions)[0]; + description = entity.descriptions[lang].value; + } + + d3_select('.preset-wikidata-label') + .style('display', function(){ + return label.length > 0 ? 'flex' : 'none'; + }) + .select('input') + .attr('value', label); + + d3_select('.preset-wikidata-description') + .style('display', function(){ + return description.length > 0 ? 'flex' : 'none'; + }) + .select('input') + .attr('value', description); + }); // unrecognized value format } else { + d3_select('.preset-wikidata-label').style('display', 'none'); + d3_select('.preset-wikidata-description').style('display', 'none'); if (value && value !== '') { wikiURL = 'https://wikidata.org/wiki/Special:Search?search=' + value; } else {