From b068e18adad0d0086436b840e10085403d16a152 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 19 Feb 2019 14:37:11 +0000 Subject: [PATCH 01/17] Make suggest items clickable with the middle button. Clicking on an item with the middle button leads the user to the page for this item. This lets users inspect items without selecting them. Closes #1934. --- .../modules/core/externals/suggest/suggest-4_3.js | 14 ++++++++++++++ .../core/scripts/views/data-table/cell-ui.js | 3 +++ .../scripts/views/data-table/menu-reconcile.js | 3 +++ 3 files changed, 20 insertions(+) diff --git a/main/webapp/modules/core/externals/suggest/suggest-4_3.js b/main/webapp/modules/core/externals/suggest/suggest-4_3.js index bb10c3689..a630affc8 100644 --- a/main/webapp/modules/core/externals/suggest/suggest-4_3.js +++ b/main/webapp/modules/core/externals/suggest/suggest-4_3.js @@ -1299,6 +1299,20 @@ name.append($("").text(data.description)); } + // If we know of a view URL for this suggest service, + // clicking with the middle button sends the user to + // the view page. + if('view_url' in this.options && data.id) { + var view_url = this.options.view_url.replace('{{id}}', data.id); + li.on('mousedown', function(e) { + if (e.which == 2) { + var win = window.open(view_url, '_blank'); + win.focus(); + e.preventDefault(); + } + }); + } + //console.log("create_item", li); return li; }, diff --git a/main/webapp/modules/core/scripts/views/data-table/cell-ui.js b/main/webapp/modules/core/scripts/views/data-table/cell-ui.js index be5a9d29f..e399737e5 100644 --- a/main/webapp/modules/core/scripts/views/data-table/cell-ui.js +++ b/main/webapp/modules/core/scripts/views/data-table/cell-ui.js @@ -200,6 +200,9 @@ DataTableCellUI.prototype._render = function() { var addSuggest = false; if ((service) && (service.suggest) && (service.suggest.entity)) { suggestOptions = service.suggest.entity; + if ('view' in service && 'url' in service.view && !('view_url' in suggestOptions)) { + suggestOptions.view_url = service.view.url; + } addSuggest = true; } diff --git a/main/webapp/modules/core/scripts/views/data-table/menu-reconcile.js b/main/webapp/modules/core/scripts/views/data-table/menu-reconcile.js index 7845334fd..ffd021c3f 100644 --- a/main/webapp/modules/core/scripts/views/data-table/menu-reconcile.js +++ b/main/webapp/modules/core/scripts/views/data-table/menu-reconcile.js @@ -85,6 +85,9 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) { if (service && service.suggest && service.suggest.entity) { suggestOptions = $.extend({}, service.suggest.entity); suggestOptions.query_param_name = "prefix"; + if ('view' in service && 'url' in service.view && !('view_url' in suggestOptions)) { + suggestOptions.formatter_url = service.view.url; + } } var frame = DialogSystem.createDialog(); From 2f298b4093d75845452cd16a9febaf6bc085df5f Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 19 Feb 2019 14:42:04 +0000 Subject: [PATCH 02/17] Also make suggestions clickable in Wikidata extension --- .../module/scripts/dialogs/schema-alignment-dialog.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js b/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js index f9a1ebc8b..f6060957f 100644 --- a/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js +++ b/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js @@ -802,6 +802,10 @@ SchemaAlignmentDialog._initField = function(inputContainer, mode, initialValue, var suggestConfig = $.extend({}, endpoint); suggestConfig.key = null; suggestConfig.query_param_name = "prefix"; + if ('view' in this._reconService && 'url' in this._reconService.view && !('view_url' in endpoint)) { + suggestOptions.view_url = this._reconService.view.url; + } + input.suggestP(suggestConfig).bind("fb-select", function(evt, data) { inputContainer.data("jsonValue", { @@ -820,6 +824,9 @@ SchemaAlignmentDialog._initField = function(inputContainer, mode, initialValue, var suggestConfig = $.extend({}, endpoint); suggestConfig.key = null; suggestConfig.query_param_name = "prefix"; + if ('view' in this._reconService && 'url' in this._reconService.view && !('view_url' in endpoint)) { + suggestOptions.view_url = this._reconService.view.url; + } input.suggestP(suggestConfig).bind("fb-select", function(evt, data) { inputContainer.data("jsonValue", { From f9ef60e83955b853cc7cfbe264d826b0072bc4cf Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 19 Feb 2019 14:47:24 +0000 Subject: [PATCH 03/17] Also allow ${id} syntax for consistency with flyout --- main/webapp/modules/core/externals/suggest/suggest-4_3.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/webapp/modules/core/externals/suggest/suggest-4_3.js b/main/webapp/modules/core/externals/suggest/suggest-4_3.js index a630affc8..605ad1ea6 100644 --- a/main/webapp/modules/core/externals/suggest/suggest-4_3.js +++ b/main/webapp/modules/core/externals/suggest/suggest-4_3.js @@ -1303,7 +1303,7 @@ // clicking with the middle button sends the user to // the view page. if('view_url' in this.options && data.id) { - var view_url = this.options.view_url.replace('{{id}}', data.id); + var view_url = this.options.view_url.replace('{{id}}', data.id).replace('${id}', data.id); li.on('mousedown', function(e) { if (e.which == 2) { var win = window.open(view_url, '_blank'); From c509dd3847ad042328d79fc73f73e37bcadc0dad Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 19 Feb 2019 16:46:24 +0000 Subject: [PATCH 04/17] Show reconciliation previews on hover of reconciliation candidates and matches. Closes #1943. --- .../core/scripts/views/data-table/cell-ui.js | 89 ++++++++++--------- .../core/styles/views/data-table-view.less | 9 +- 2 files changed, 55 insertions(+), 43 deletions(-) diff --git a/main/webapp/modules/core/scripts/views/data-table/cell-ui.js b/main/webapp/modules/core/scripts/views/data-table/cell-ui.js index be5a9d29f..0f46677f9 100644 --- a/main/webapp/modules/core/scripts/views/data-table/cell-ui.js +++ b/main/webapp/modules/core/scripts/views/data-table/cell-ui.js @@ -108,6 +108,8 @@ DataTableCellUI.prototype._render = function() { a.attr("href", encodeURI(service.view.url.replace("{{id}}", match.id))); } + self._previewOnHover(service, match, a); + $(' ').appendTo(divContent); $('') .text($.i18n('core-views/choose-match')) @@ -125,18 +127,19 @@ DataTableCellUI.prototype._render = function() { var candidates = r.c; var renderCandidate = function(candidate, index) { var li = $('
').addClass("data-table-recon-candidate").appendTo(ul); + var liSpan = $('').appendTo(li); $(' ') .addClass("data-table-recon-match-similar") .attr("title", $.i18n('core-views/match-all-cells')) - .appendTo(li).click(function(evt) { + .appendTo(liSpan).click(function(evt) { self._doMatchTopicToSimilarCells(candidate); }); $(' ') .addClass("data-table-recon-match") .attr("title", $.i18n('core-views/match-this-cell') ) - .appendTo(li).click(function(evt) { + .appendTo(liSpan).click(function(evt) { self._doMatchTopicToOneCell(candidate); }); @@ -144,26 +147,13 @@ DataTableCellUI.prototype._render = function() { .addClass("data-table-recon-topic") .attr("target", "_blank") .text(_.unescape(candidate.name)) // TODO: only use of _.unescape - consolidate - .appendTo(li); + .appendTo(liSpan); if ((service) && (service.view) && (service.view.url)) { a.attr("href", encodeURI(service.view.url.replace("{{id}}", candidate.id))); } - var preview = null; - if ((service) && (service.preview)) { - preview = service.preview; - } - - if (preview) { - a.click(function(evt) { - if (!evt.metaKey && !evt.ctrlKey) { - self._previewCandidateTopic(candidate, this, preview); - evt.preventDefault(); - return false; - } - }); - } + self._previewOnHover(service, candidate, liSpan); var score; if (candidate.score < 1) { @@ -171,7 +161,7 @@ DataTableCellUI.prototype._render = function() { } else { score = Math.round(candidate.score); } - $('').addClass("data-table-recon-score").text("(" + score + ")").appendTo(li); + $('').addClass("data-table-recon-score").text("(" + score + ")").appendTo(liSpan); }; for (var i = 0; i < candidates.length; i++) { @@ -428,20 +418,11 @@ DataTableCellUI.prototype._postProcessSeveralCells = function(command, params, b ); }; -// TODO delete this -DataTableCellUI.internalPreview = { - srchurl: 'https://www.googleapis.com/freebase/v1/search?filter=(all mid:${id})' - + '&output=(notable:/client/summary (description citation provenance) type)' - + '&key='+CustomSuggest.FREEBASE_API_KEY+'&callback=?', - imgurl : 'https://www.googleapis.com/freebase/v1/image${id}?maxwidth=75&errorid=/freebase/no_image_png&key='+CustomSuggest.FREEBASE_API_KEY, - width: 430, - height: 300 -}; - DataTableCellUI.prototype._previewCandidateTopic = function(candidate, elmt, preview) { var self = this; var id = candidate.id; - var fakeMenu = MenuSystem.createMenu(); + var fakeMenu = $('
') + .addClass("menu-container"); fakeMenu .width(preview.width?preview.width:414) .addClass('data-table-topic-popup') @@ -454,19 +435,17 @@ DataTableCellUI.prototype._previewCandidateTopic = function(candidate, elmt, pre .height(preview.height) .attr("src", url) .appendTo(fakeMenu); - } else { // Otherwise use our internal preview - var url = encodeURI(DataTableCellUI.internalPreview.srchurl.replace("\${id}", id)); - $.ajax(url,{dataType:"jsonp"}).done(function(searchResponse) { - var data = searchResponse.result[0]; - var html = $.suggest.suggest.create_flyout(data, preview.imgurl); - var container = $('
').css({fontSize:16}); // Suggest assumes this as a base font size - container.append(html); - fakeMenu.append(container); - }); + } else { + return; // no preview service available } - MenuSystem.showMenu(fakeMenu, function(){}); MenuSystem.positionMenuLeftRight(fakeMenu, $(elmt)); + fakeMenu.appendTo(elmt); + + var dismissMenu = function() { + fakeMenu.remove(); + fakeMenu.unbind(); + }; var elmts = DOM.bind(fakeMenu); @@ -476,15 +455,41 @@ DataTableCellUI.prototype._previewCandidateTopic = function(candidate, elmt, pre elmts.matchButton.click(function() { self._doMatchTopicToOneCell(candidate); - MenuSystem.dismissAll(); + dismissMenu(); }); elmts.matchSimilarButton.click(function() { self._doMatchTopicToSimilarCells(candidate); - MenuSystem.dismissAll(); + dismissMenu(); }); elmts.cancelButton.click(function() { - MenuSystem.dismissAll(); + dismissMenu(); }); + return dismissMenu; +}; + +/** + * Sets up a preview widget to appear when hovering the given DOM element. + */ +DataTableCellUI.prototype._previewOnHover = function(service, candidate, element) { + var self = this; + var preview = null; + if ((service) && (service.preview)) { + preview = service.preview; + } + + if (preview) { + var dismissCallback = null; + element.hover(function(evt) { + if (!evt.metaKey && !evt.ctrlKey) { + dismissCallback = self._previewCandidateTopic(candidate, this, preview); + evt.preventDefault(); + } + }, function(evt) { + if(dismissCallback !== null) { + dismissCallback(); + } + }); + } }; DataTableCellUI.prototype._startEdit = function(elmt) { diff --git a/main/webapp/modules/core/styles/views/data-table-view.less b/main/webapp/modules/core/styles/views/data-table-view.less index da127748b..0469891dd 100644 --- a/main/webapp/modules/core/styles/views/data-table-view.less +++ b/main/webapp/modules/core/styles/views/data-table-view.less @@ -298,6 +298,13 @@ a.data-table-flag-off { padding: @padding_tight; .rounded_corners(); } + +.data-table-topic-popup { + z-index: 1010; + position: fixed; + line-height: 1; + white-space: initial; + } .data-table-topic-popup-header { padding: 0 0 5px; @@ -353,4 +360,4 @@ ul.sorting-dialog-blank-error-positions > li { margin: 2px; cursor: move; .rounded_corners(3px); - } \ No newline at end of file + } From 4344b2474c40db3c9a5881a39bf0efa6e2b7a744 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 19 Feb 2019 16:56:07 +0000 Subject: [PATCH 05/17] Remove buttons when previewing a matched cell --- .../core/scripts/views/data-table/cell-ui.js | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/main/webapp/modules/core/scripts/views/data-table/cell-ui.js b/main/webapp/modules/core/scripts/views/data-table/cell-ui.js index 0f46677f9..026a55a72 100644 --- a/main/webapp/modules/core/scripts/views/data-table/cell-ui.js +++ b/main/webapp/modules/core/scripts/views/data-table/cell-ui.js @@ -108,7 +108,7 @@ DataTableCellUI.prototype._render = function() { a.attr("href", encodeURI(service.view.url.replace("{{id}}", match.id))); } - self._previewOnHover(service, match, a); + self._previewOnHover(service, match, a, false); $(' ').appendTo(divContent); $('') @@ -153,7 +153,7 @@ DataTableCellUI.prototype._render = function() { a.attr("href", encodeURI(service.view.url.replace("{{id}}", candidate.id))); } - self._previewOnHover(service, candidate, liSpan); + self._previewOnHover(service, candidate, liSpan, true); var score; if (candidate.score < 1) { @@ -418,15 +418,18 @@ DataTableCellUI.prototype._postProcessSeveralCells = function(command, params, b ); }; -DataTableCellUI.prototype._previewCandidateTopic = function(candidate, elmt, preview) { +DataTableCellUI.prototype._previewCandidateTopic = function(candidate, elmt, preview, showActions) { var self = this; var id = candidate.id; var fakeMenu = $('
') .addClass("menu-container"); fakeMenu .width(preview.width?preview.width:414) - .addClass('data-table-topic-popup') - .html(DOM.loadHTML("core", "scripts/views/data-table/cell-recon-preview-popup-header.html")); + .addClass('data-table-topic-popup'); + if (showActions) { + fakeMenu + .html(DOM.loadHTML("core", "scripts/views/data-table/cell-recon-preview-popup-header.html")); + } if (preview && preview.url) { // Service has a preview URL associated with it var url = encodeURI(preview.url.replace("{{id}}", id)); @@ -447,30 +450,32 @@ DataTableCellUI.prototype._previewCandidateTopic = function(candidate, elmt, pre fakeMenu.unbind(); }; - var elmts = DOM.bind(fakeMenu); - - elmts.matchButton.html($.i18n('core-views/match-cell')); - elmts.matchSimilarButton.html($.i18n('core-views/match-identical')); - elmts.cancelButton.html($.i18n('core-buttons/cancel')); - - elmts.matchButton.click(function() { - self._doMatchTopicToOneCell(candidate); - dismissMenu(); - }); - elmts.matchSimilarButton.click(function() { - self._doMatchTopicToSimilarCells(candidate); - dismissMenu(); - }); - elmts.cancelButton.click(function() { - dismissMenu(); - }); + if (showActions) { + var elmts = DOM.bind(fakeMenu); + + elmts.matchButton.html($.i18n('core-views/match-cell')); + elmts.matchSimilarButton.html($.i18n('core-views/match-identical')); + elmts.cancelButton.html($.i18n('core-buttons/cancel')); + + elmts.matchButton.click(function() { + self._doMatchTopicToOneCell(candidate); + dismissMenu(); + }); + elmts.matchSimilarButton.click(function() { + self._doMatchTopicToSimilarCells(candidate); + dismissMenu(); + }); + elmts.cancelButton.click(function() { + dismissMenu(); + }); + } return dismissMenu; }; /** * Sets up a preview widget to appear when hovering the given DOM element. */ -DataTableCellUI.prototype._previewOnHover = function(service, candidate, element) { +DataTableCellUI.prototype._previewOnHover = function(service, candidate, element, showActions) { var self = this; var preview = null; if ((service) && (service.preview)) { @@ -481,7 +486,7 @@ DataTableCellUI.prototype._previewOnHover = function(service, candidate, element var dismissCallback = null; element.hover(function(evt) { if (!evt.metaKey && !evt.ctrlKey) { - dismissCallback = self._previewCandidateTopic(candidate, this, preview); + dismissCallback = self._previewCandidateTopic(candidate, this, preview, showActions); evt.preventDefault(); } }, function(evt) { From a7482ff0d29ed039f7f55811786ae5e66aa43390 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 19 Feb 2019 21:51:55 +0000 Subject: [PATCH 06/17] Add ability to copy references. Closes #1912. --- .../wikidata/module/langs/translation-en.json | 5 +- .../wikidata/module/langs/translation-fr.json | 5 +- .../dialogs/schema-alignment-dialog.js | 176 +++++++++++++++--- .../dialogs/schema-alignment-dialog.css | 48 ++++- 4 files changed, 202 insertions(+), 32 deletions(-) diff --git a/extensions/wikidata/module/langs/translation-en.json b/extensions/wikidata/module/langs/translation-en.json index a2c6b8191..50be8999a 100644 --- a/extensions/wikidata/module/langs/translation-en.json +++ b/extensions/wikidata/module/langs/translation-en.json @@ -23,6 +23,9 @@ "wikidata-schema/add-statement": "add statement", "wikidata-schema/add-value": "add value", "wikidata-schema/add-qualifier": "add qualifier", + "wikidata-schema/copy-reference": "copy", + "wikidata-schema/paste-reference": "paste reference", + "wikidata-schema/reference-copied": "copied", "wikidata-schema/add-reference": "add reference", "wikidata-schema/add-reference-snak": "add", "wikidata-schema/property-placeholder": "property", @@ -146,4 +149,4 @@ "warnings-messages/no-unit-provided/body": "Values such as {example_value} on {example_item_entity} are expected to have units.", "warnings-messages/invalid-entity-type/title": "{property_entity} used on items", "warnings-messages/invalid-entity-type/body": "Uses of {property_entity} on items such as {example_entity} are invalid." -} \ No newline at end of file +} diff --git a/extensions/wikidata/module/langs/translation-fr.json b/extensions/wikidata/module/langs/translation-fr.json index 0280f78fe..2924caee2 100644 --- a/extensions/wikidata/module/langs/translation-fr.json +++ b/extensions/wikidata/module/langs/translation-fr.json @@ -20,6 +20,9 @@ "wikidata-schema/add-statement": "ajouter une déclaration", "wikidata-schema/add-value": "ajouter une valeur", "wikidata-schema/add-qualifier": "ajouter un qualificatif", + "wikidata-schema/copy-reference": "copier", + "wikidata-schema/paste-reference": "coller une référence", + "wikidata-schema/reference-copied": "copiée", "wikidata-schema/add-reference": "ajouter une référence", "wikidata-schema/add-reference-snak": "ajouter", "wikidata-schema/property-placeholder": "propriété", @@ -139,4 +142,4 @@ "warnings-messages/no-unit-provided/body": "Des valeurs telles que {example_value} sur {example_item_entity} devraient avoir des unités.", "warnings-messages/invalid-entity-type/title": "{property_entity} utilisée sur des éléments", "warnings-messages/invalid-entity-type/body": "Les utilisations de {property_entity} sur des éléments tels que {example_entity} sont invalides." -} \ No newline at end of file +} diff --git a/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js b/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js index f9a1ebc8b..cc3770773 100644 --- a/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js +++ b/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js @@ -244,12 +244,18 @@ SchemaAlignmentDialog._reset = function(schema) { if (!this._schema.itemDocuments.length) { // this._addItem(); } + + this._copiedReference = null; }; SchemaAlignmentDialog._save = function(onDone) { var self = this; var schema = this.getJSON(); + if (schema === null) { + alert($.i18n('wikidata-schema/incomplete-schema-could-not-be-saved')); + } + Refine.postProcess( "wikidata", "save-wikibase-schema", @@ -394,17 +400,32 @@ SchemaAlignmentDialog._addItem = function(json) { SchemaAlignmentDialog._itemToJSON = function (item) { var statementGroupLst = new Array(); - item.find('.wbs-statement-group').each(function () { - statementGroupLst.push(SchemaAlignmentDialog._statementGroupToJSON($(this))); + var statementsDom = item.find('.wbs-statement-group'); + statementsDom.each(function () { + var statementGroupJSON = SchemaAlignmentDialog._statementGroupToJSON($(this)); + if (statementGroupJSON !== null) { + statementGroupLst.push(statementGroupJSON); + } }); var nameDescLst = new Array(); - item.find('.wbs-namedesc').each(function () { - nameDescLst.push(SchemaAlignmentDialog._nameDescToJSON($(this))); + var nameDescsDom = item.find('.wbs-namedesc'); + nameDescsDom.each(function () { + var nameDescJSON = SchemaAlignmentDialog._nameDescToJSON($(this)); + if (nameDescJSON !== null) { + nameDescLst.push(nameDescJSON); + } }); var inputContainer = item.find(".wbs-item-input").first(); - return {subject: SchemaAlignmentDialog._inputContainerToJSON(inputContainer), + var subjectJSON = SchemaAlignmentDialog._inputContainerToJSON(inputContainer); + if (subjectJSON !== null && + statementGroupLst.length === statementsDom.length && + nameDescLst.length === nameDescsDom.length) { + return {subject: subjectJSON, statementGroups: statementGroupLst, nameDescs: nameDescLst}; + } else { + return null; + } }; /************************** @@ -513,12 +534,21 @@ SchemaAlignmentDialog._addStatementGroup = function(item, json) { SchemaAlignmentDialog._statementGroupToJSON = function (statementGroup) { var lst = new Array(); - statementGroup.find('.wbs-statement-container').first().children('.wbs-statement').each(function () { - lst.push(SchemaAlignmentDialog._statementToJSON($(this))); + var domStatements = statementGroup.find('.wbs-statement-container').first().children('.wbs-statement'); + domStatements.each(function () { + var statementJSON = SchemaAlignmentDialog._statementToJSON($(this)); + if (statementJSON !== null) { + lst.push(statementJSON); + } }); var inputContainer = statementGroup.find(".wbs-prop-input").first(); - return {property: SchemaAlignmentDialog._inputContainerToJSON(inputContainer), - statements: lst}; + var propertyJSON = SchemaAlignmentDialog._inputContainerToJSON(inputContainer); + if (propertyJSON !== null && domStatements.length === lst.length && lst.length > 0) { + return {property: propertyJSON, + statements: lst}; + } else { + return null; + } }; /************** @@ -593,6 +623,28 @@ SchemaAlignmentDialog._addStatement = function(container, datatype, json) { e.preventDefault(); }).appendTo(toolbar3); SchemaAlignmentDialog._plusButton($.i18n('wikidata-schema/add-reference'), addReferenceButton); + + var pasteToolbar = $('
').addClass('wbs-toolbar').appendTo(referencesToggleContainer); + var referencePaste = $('') + .addClass('wbs-paste-reference') + .appendTo(pasteToolbar) + .hide(); + var pasteIcon = $('').addClass('wbs-icon').appendTo(referencePaste); + var referencePasteButton = $('') + .addClass('wbs-paste-reference-button') + .text($.i18n('wikidata-schema/paste-reference')) + .appendTo(referencePaste) + .click(function(e) { + if (SchemaAlignmentDialog._copiedReference !== null) { + SchemaAlignmentDialog._addReference(referenceContainer, SchemaAlignmentDialog._copiedReference); + SchemaAlignmentDialog._updateReferencesNumber(referenceContainer); + referencePaste.hide(); + SchemaAlignmentDialog._hasChanged(); + } + e.preventDefault(); + e.stopPropagation(); + }); + if (references) { for (var i = 0; i != references.length; i++) { SchemaAlignmentDialog._addReference(referenceContainer, references[i]); @@ -607,17 +659,32 @@ SchemaAlignmentDialog._statementToJSON = function (statement) { var inputContainer = statement.find(".wbs-target-input").first(); var qualifiersList = new Array(); var referencesList = new Array(); - statement.find('.wbs-qualifier-container').first().children().each(function () { - qualifiersList.push(SchemaAlignmentDialog._qualifierToJSON($(this))); + var qualifiersDom = statement.find('.wbs-qualifier-container').first().children(); + qualifiersDom.each(function () { + var qualifierJSON = SchemaAlignmentDialog._qualifierToJSON($(this)); + if (qualifierJSON !== null) { + qualifiersList.push(qualifierJSON); + } }); - statement.find('.wbs-reference-container').first().children().each(function () { - referencesList.push(SchemaAlignmentDialog._referenceToJSON($(this))); + var referencesDom = statement.find('.wbs-reference-container').first().children(); + referencesDom.each(function () { + var referenceJSON = SchemaAlignmentDialog._referenceToJSON($(this)); + if (referenceJSON !== null) { + referencesList.push(referenceJSON); + } }); - return { - value:SchemaAlignmentDialog._inputContainerToJSON(inputContainer), + var valueJSON = SchemaAlignmentDialog._inputContainerToJSON(inputContainer); + if (referencesList.length === referencesDom.length && + qualifiersList.length === qualifiersDom.length && + valueJSON !== null) { + return { + value: valueJSON, qualifiers: qualifiersList, references: referencesList, - }; + }; + } else { + return null; + } }; /************** @@ -655,10 +722,16 @@ SchemaAlignmentDialog._addQualifier = function(container, json) { SchemaAlignmentDialog._qualifierToJSON = function(elem) { var prop = elem.find(".wbs-prop-input").first(); var target = elem.find(".wbs-target-input").first(); - return { - prop: SchemaAlignmentDialog._inputContainerToJSON(prop), - value: SchemaAlignmentDialog._inputContainerToJSON(target), - }; + var propJSON = SchemaAlignmentDialog._inputContainerToJSON(prop); + var valueJSON = SchemaAlignmentDialog._inputContainerToJSON(target); + if (propJSON !== null && valueJSON !== null) { + return { + prop: propJSON, + value: valueJSON, + }; + } else { + return null; + } } /************** @@ -673,6 +746,20 @@ SchemaAlignmentDialog._addReference = function(container, json) { var reference = $('
').addClass('wbs-reference').appendTo(container); var referenceHeader = $('
').addClass('wbs-reference-header').appendTo(reference); + var referenceCopy = $('').addClass('wbs-copy-reference').appendTo(referenceHeader); + var referenceCopyIcon = $('').addClass('wbs-icon').appendTo(referenceCopy); + var copyButton = $('') + .addClass('wbs-copy-reference-button') + .text($.i18n('wikidata-schema/copy-reference')) + .appendTo(referenceCopy) + .click(function(e) { + if (SchemaAlignmentDialog._copyReference(reference)) { + $(this).text($.i18n('wikidata-schema/reference-copied')) + .parent().addClass('wbs-copied-reference'); + container.parent().parent().find('.wbs-paste-reference').hide(); + } + e.preventDefault(); + }); var toolbarRef = $('
').addClass('wbs-toolbar').appendTo(referenceHeader); SchemaAlignmentDialog._makeDeleteButton().click(function(e) { reference.remove(); @@ -703,9 +790,16 @@ SchemaAlignmentDialog._referenceToJSON = function(reference) { var snaks = reference.find('.wbs-qualifier-container').first().children(); var snaksList = new Array(); snaks.each(function () { - snaksList.push(SchemaAlignmentDialog._qualifierToJSON($(this))); + var qualifier = SchemaAlignmentDialog._qualifierToJSON($(this)); + if (qualifier !== null) { + snaksList.push(qualifier); + } }); - return {snaks:snaksList}; + if (snaksList.length === snaks.length) { + return {snaks:snaksList}; + } else { + return null; + } } SchemaAlignmentDialog._updateReferencesNumber = function(container) { @@ -715,6 +809,22 @@ SchemaAlignmentDialog._updateReferencesNumber = function(container) { a.html(childrenCount+$.i18n('wikidata-schema/nb-references')); } +SchemaAlignmentDialog._copyReference = function(reference) { + // mark any other copied reference as not copied + $('.wbs-copy-reference-button') + .text($.i18n('wikidata-schema/copy-reference')); + $('.wbs-copy-reference') + .removeClass('wbs-copied-reference'); + var copiedReference = SchemaAlignmentDialog._referenceToJSON(reference); + if (copiedReference !== null) { + SchemaAlignmentDialog._copiedReference = copiedReference; + $('.wbs-paste-reference').show(); + return true; + } else { + return false; + } +} + /************************ * FIELD INITIALIZATION * ************************/ @@ -1076,7 +1186,7 @@ SchemaAlignmentDialog.setupStringInputValidation = function(input, regex) { SchemaAlignmentDialog._inputContainerToJSON = function (inputContainer) { var data = inputContainer.data(); - if (data) { + if (data && 'jsonValue' in data) { return data.jsonValue; } else { return null; @@ -1095,13 +1205,21 @@ SchemaAlignmentDialog._removeStatement = function(statement) { SchemaAlignmentDialog.getJSON = function() { var list = new Array(); - $('#schema-alignment-statements-container .wbs-item').each(function () { - list.push(SchemaAlignmentDialog._itemToJSON($(this))); + var itemsDom = $('#schema-alignment-statements-container .wbs-item'); + itemsDom.each(function () { + var itemJSON = SchemaAlignmentDialog._itemToJSON($(this)); + if (itemJSON !== null) { + list.push(itemJSON); + } }); - return { + if (list.length === itemsDom.length) { + return { 'itemDocuments': list, 'wikibasePrefix': this._wikibasePrefix, - }; + }; + } else { + return null; + } }; SchemaAlignmentDialog._hasChanged = function() { @@ -1130,6 +1248,10 @@ SchemaAlignmentDialog.preview = function() { this.issueSpinner.show(); this.previewSpinner.show(); var schema = this.getJSON(); + if (schema === null) { + $('.invalid-schema-warning').show(); + return; + } $.post( "command/wikidata/preview-wikibase-schema?" + $.param({ project: theProject.id }), { schema: JSON.stringify(schema), engine: JSON.stringify(ui.browsingEngine.getJSON()) }, diff --git a/extensions/wikidata/module/styles/dialogs/schema-alignment-dialog.css b/extensions/wikidata/module/styles/dialogs/schema-alignment-dialog.css index 03561fede..2ae8fa79d 100644 --- a/extensions/wikidata/module/styles/dialogs/schema-alignment-dialog.css +++ b/extensions/wikidata/module/styles/dialogs/schema-alignment-dialog.css @@ -143,6 +143,7 @@ opacity: 0.7; } + .wbs-remove .wbs-icon { background-image:linear-gradient(transparent,transparent),url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%2224%22%20height=%2224%22%20viewBox=%220%200%2024%2024%22%3E%20%3Cg%20id=%22remove%22%3E%20%3Cpath%20id=%22trash-can%22%20d=%22M12%2010h-1v6h1v-6zm-2%200H9v6h1v-6zm4%200h-1v6h1v-6zm0-4V5H9v1H6v3h1v7.966l1%201.03v-.073V18h6.984l.016-.018v.015l1-1.03V9h1V6h-3zm1%2011H8V9h7v8zm1-9H7V7h9v1z%22/%3E%20%3C/g%3E%20%3C/svg%3E"); } @@ -211,7 +212,8 @@ .wbs-remove, .wbs-add-item, .wbs-add-statement-group, .wbs-add-statement, -.wbs-add-qualifier, .wbs-add-reference, .wbs-add-namedesc { +.wbs-add-qualifier, .wbs-add-reference, .wbs-add-namedesc, +.wbs-copy-reference-button, .wbs-paste-reference-button { color: #0645ad !important; font-size: 0.9em; cursor: pointer; @@ -250,6 +252,10 @@ color: gray; } +.schema-alignment-dialog-preview .wbs-prop-input { + float: left; +} + .schema-alignment-dialog-preview .wbs-qualifier .wbs-statement-container { display: table-cell; vertical-align: bottom; @@ -303,7 +309,7 @@ .wbs-qualifier, .wbs-reference { position: relative; - overflow-x: hidden; + overflow: hidden; } .wbs-qualifier .wbs-right { @@ -318,14 +324,50 @@ } .wbs-references-toggle { - width: 12em; margin: 5px; + margin-right: 0px; } .wbs-references-toggle a { color: #0645ad !important; } +.wbs-copy-reference { + float: left; + padding: 2px; +} + +.wbs-copied-reference { + opacity: 0.6; +} + +.wbs-copied-reference .wbs-copy-reference-button { + color: black !important; + cursor: default; +} + +.wbs-copied-reference span:hover { + text-decoration: none; +} + +.wbs-paste-reference .wbs-icon, +.wbs-copy-reference .wbs-icon { + height: 13px; + width: 13px; + background-size: 13px 13px; + opacity: 0.6; + margin-right: 2px; +} + +/* source: Font Awesome by Dave Gandy. https://commons.wikimedia.org/wiki/File:Paste_font_awesome.svg */ +.wbs-paste-reference .wbs-icon { + background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg version='1.1' viewBox='0 -256 1900 1900' xmlns='http://www.w3.org/2000/svg' xmlns:cc='http://creativecommons.org/ns%23' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns%23'%3E%3Cmetadata%3E%3Crdf:RDF%3E%3Ccc:Work rdf:about=''%3E%3Cdc:format%3Eimage/svg+xml%3C/dc:format%3E%3Cdc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/%3E%3C/cc:Work%3E%3C/rdf:RDF%3E%3C/metadata%3E%3Cg transform='matrix(1 0 0 -1 53.153 1325.1)'%3E%3Cpath d='m768-128h896v640h-416q-40 0-68 28t-28 68v416h-384v-1152zm256 1440v64q0 13-9.5 22.5t-22.5 9.5h-704q-13 0-22.5-9.5t-9.5-22.5v-64q0-13 9.5-22.5t22.5-9.5h704q13 0 22.5 9.5t9.5 22.5zm256-672h299l-299 299v-299zm512-128v-672q0-40-28-68t-68-28h-960q-40 0-68 28t-28 68v160h-544q-40 0-68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68-28t28-68v-328q21-13 36-28l408-408q28-28 48-76t20-88z' fill='currentColor'/%3E%3C/g%3E%3C/svg%3E%0A"); +} + +/* source: Font Awesome by Dave Gandy. https://commons.wikimedia.org/wiki/File:Copy_font_awesome.svg */ +.wbs-copy-reference .wbs-icon { + background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg version='1.1' viewBox='0 -256 1850 1850' xmlns='http://www.w3.org/2000/svg' xmlns:cc='http://creativecommons.org/ns%23' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns%23'%3E%3Cmetadata%3E%3Crdf:RDF%3E%3Ccc:Work rdf:about=''%3E%3Cdc:format%3Eimage/svg+xml%3C/dc:format%3E%3Cdc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/%3E%3C/cc:Work%3E%3C/rdf:RDF%3E%3C/metadata%3E%3Cg transform='matrix(1 0 0 -1 37.966 1305.5)'%3E%3Cpath d='m1696 1152q40 0 68-28t28-68v-1216q0-40-28-68t-68-28h-960q-40 0-68 28t-28 68v288h-544q-40 0-68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68-28t28-68v-328q68 40 128 40h416zm-544-213-299-299h299v299zm-640 384-299-299h299v299zm196-647 316 316v416h-384v-416q0-40-28-68t-68-28h-416v-640h512v256q0 40 20 88t48 76zm956-804v1152h-384v-416q0-40-28-68t-68-28h-416v-640h896z' fill='currentColor'/%3E%3C/g%3E%3C/svg%3E"); +} .wbs-references-toggle .triangle-icon { background: transparent url(data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20standalone%3D%22no%22%3F%3E%0A%3Csvg%0A%20%20%20xmlns%3Adc%3D%22http%3A//purl.org/dc/elements/1.1/%22%0A%20%20%20xmlns%3Acc%3D%22http%3A//creativecommons.org/ns%23%22%0A%20%20%20xmlns%3Ardf%3D%22http%3A//www.w3.org/1999/02/22-rdf-syntax-ns%23%22%0A%20%20%20xmlns%3Asvg%3D%22http%3A//www.w3.org/2000/svg%22%0A%20%20%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%0A%20%20%20id%3D%22svg8%22%0A%20%20%20version%3D%221.1%22%0A%20%20%20viewBox%3D%220%200%202.6458332%202.6458332%22%0A%20%20%20height%3D%2210%22%0A%20%20%20width%3D%2210%22%3E%0A%20%20%3Cdefs%0A%20%20%20%20%20id%3D%22defs2%22%20/%3E%0A%20%20%3Cmetadata%0A%20%20%20%20%20id%3D%22metadata5%22%3E%0A%20%20%20%20%3Crdf%3ARDF%3E%0A%20%20%20%20%20%20%3Ccc%3AWork%0A%20%20%20%20%20%20%20%20%20rdf%3Aabout%3D%22%22%3E%0A%20%20%20%20%20%20%20%20%3Cdc%3Aformat%3Eimage/svg+xml%3C/dc%3Aformat%3E%0A%20%20%20%20%20%20%20%20%3Cdc%3Atype%0A%20%20%20%20%20%20%20%20%20%20%20rdf%3Aresource%3D%22http%3A//purl.org/dc/dcmitype/StillImage%22%20/%3E%0A%20%20%20%20%20%20%20%20%3Cdc%3Atitle%3E%3C/dc%3Atitle%3E%0A%20%20%20%20%20%20%3C/cc%3AWork%3E%0A%20%20%20%20%3C/rdf%3ARDF%3E%0A%20%20%3C/metadata%3E%0A%20%20%3Cg%0A%20%20%20%20%20transform%3D%22translate%280%2C-294.35416%29%22%0A%20%20%20%20%20id%3D%22layer1%22%3E%0A%20%20%20%20%3Cpath%0A%20%20%20%20%20%20%20id%3D%22path12%22%0A%20%20%20%20%20%20%20d%3D%22m%200.21601809%2C294.5035%202.28763941%2C1.14744%20-2.29850705%2C1.20871%20z%22%0A%20%20%20%20%20%20%20style%3D%22fill%3A%23645eea%3Bfill-opacity%3A1%3Bfill-rule%3Aevenodd%3Bstroke%3A%23645eea%3Bstroke-width%3A0.06161711px%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-opacity%3A1%22%20/%3E%0A%20%20%3C/g%3E%0A%3C/svg%3E%0A) no-repeat center center; From a072328637a215abfb6c47348b078d57ec284791 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 19 Feb 2019 22:06:35 +0000 Subject: [PATCH 07/17] Accept URIs in 'Use values as ids' operation. Closes #1953. --- .../recon/ReconUseValuesAsIdentifiersOperation.java | 3 +++ .../recon/ReconUseValuesAsIdsOperationTests.java | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java b/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java index 6e1e6b32b..56dc50d73 100644 --- a/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java +++ b/main/src/com/google/refine/operations/recon/ReconUseValuesAsIdentifiersOperation.java @@ -116,6 +116,9 @@ public class ReconUseValuesAsIdentifiersOperation extends EngineDependentMassCel Cell cell = row.getCell(cellIndex); if (cell != null && ExpressionUtils.isNonBlankData(cell.value)) { String id = cell.value.toString(); + if(id.startsWith(identifierSpace)) { + id = id.substring(identifierSpace.length()); + } ReconCandidate match = new ReconCandidate(id, id, new String[0], 100); Recon newRecon = reconConfig.createNewRecon(historyEntryID); diff --git a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java index 0cebe10d6..757d734a6 100644 --- a/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java +++ b/main/tests/server/src/com/google/refine/tests/operations/recon/ReconUseValuesAsIdsOperationTests.java @@ -50,8 +50,8 @@ public class ReconUseValuesAsIdsOperationTests extends RefineTest { + "\"columnName\":\"ids\"," + "\"engineConfig\":{\"mode\":\"row-based\",\"facets\":[]}," + "\"service\":\"http://localhost:8080/api\"," - + "\"identifierSpace\":\"http://test.org/entities\"," - + "\"schemaSpace\":\"http://test.org/schema\"" + + "\"identifierSpace\":\"http://test.org/entities/\"," + + "\"schemaSpace\":\"http://test.org/schema/\"" + "}"; @BeforeSuite @@ -69,15 +69,15 @@ public class ReconUseValuesAsIdsOperationTests extends RefineTest { Project project = createCSVProject("ids,v\n" + "Q343,hello\n" + ",world\n" - + "Q31,test"); + + "http://test.org/entities/Q31,test"); ReconUseValuesAsIdentifiersOperation op = ParsingUtilities.mapper.readValue(json, ReconUseValuesAsIdentifiersOperation.class); op.createProcess(project, new Properties()).performImmediate(); assertEquals("Q343", project.rows.get(0).cells.get(0).recon.match.id); - assertEquals("http://test.org/entities", project.rows.get(0).cells.get(0).recon.identifierSpace); + assertEquals("http://test.org/entities/", project.rows.get(0).cells.get(0).recon.identifierSpace); assertNull(project.rows.get(1).cells.get(0)); assertEquals("Q31", project.rows.get(2).cells.get(0).recon.match.id); assertEquals(2, project.columnModel.columns.get(0).getReconStats().matchedTopics); - assertEquals("http://test.org/schema", ((StandardReconConfig)project.columnModel.columns.get(0).getReconConfig()).schemaSpace); + assertEquals("http://test.org/schema/", ((StandardReconConfig)project.columnModel.columns.get(0).getReconConfig()).schemaSpace); } } From 3c2cec161d94d08f9fc81da02630c3a02dbed147 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Tue, 19 Feb 2019 22:26:03 +0000 Subject: [PATCH 08/17] Update Jackson to 2.9.8 per CVE-2018-19360 --- extensions/database/pom.xml | 4 ++-- main/pom.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/database/pom.xml b/extensions/database/pom.xml index bc4ed6d22..22e447fae 100644 --- a/extensions/database/pom.xml +++ b/extensions/database/pom.xml @@ -153,13 +153,13 @@ com.fasterxml.jackson.core jackson-core - 2.9.7 + 2.9.8 provided com.fasterxml.jackson.core jackson-annotations - 2.9.7 + 2.9.8 org.apache.commons diff --git a/main/pom.xml b/main/pom.xml index c9593cf56..99c673bf3 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -278,12 +278,12 @@ com.fasterxml.jackson.core jackson-databind - 2.9.7 + 2.9.8 com.fasterxml.jackson.core jackson-annotations - 2.9.7 + 2.9.8 org.slf4j From deb73358487656e4723e5b21a7e15cd2fb64a722 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 22 Feb 2019 09:15:42 +0000 Subject: [PATCH 09/17] Fix Recon features computation for empty recons --- .../refine/model/recon/StandardReconConfig.java | 6 +++--- .../tests/model/recon/StandardReconConfigTests.java | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/main/src/com/google/refine/model/recon/StandardReconConfig.java b/main/src/com/google/refine/model/recon/StandardReconConfig.java index bb31aa6e0..b2d709a86 100644 --- a/main/src/com/google/refine/model/recon/StandardReconConfig.java +++ b/main/src/com/google/refine/model/recon/StandardReconConfig.java @@ -566,8 +566,8 @@ public class StandardReconConfig extends ReconConfig { * @param text * the cell value to compare the reconciliation data to */ - public void computeFeatures(Recon recon, String text) { - if (!recon.candidates.isEmpty()) { + public void computeFeatures(Recon recon, String text) { + if (recon.candidates != null && !recon.candidates.isEmpty()) { ReconCandidate candidate = recon.candidates.get(0); recon.setFeature(Recon.Feature_nameMatch, text.equalsIgnoreCase(candidate.name)); @@ -587,7 +587,7 @@ public class StandardReconConfig extends ReconConfig { } else { recon.features = new Object[Recon.Feature_max]; } - } + } static protected double wordDistance(String s1, String s2) { Set words1 = breakWords(s1); diff --git a/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java b/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java index dfe2a1f59..c9098b5f8 100644 --- a/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java @@ -27,6 +27,7 @@ package com.google.refine.tests.model.recon; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; @@ -333,4 +334,15 @@ public class StandardReconConfigTests extends RefineTest { assertEquals(recon.candidates.get(0).score, 0.3); assertEquals(recon.candidates.get(0).id, "18951129"); } + + /** + * computing the features on an empty recon should not fail + */ + @Test + public void testComputeFeatures() { + StandardReconConfigStub stub = new StandardReconConfigStub(); + Recon recon = stub.createNewRecon(2384738L); + stub.computeFeatures(recon, "my string"); + assertNotNull(recon.features); + } } From caebfe88486d61e4f6782bbf3fa20ce21dc76773 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 22 Feb 2019 16:44:25 +0000 Subject: [PATCH 10/17] Increment editgroups hash size for 3.2, fix comma issue in summaries Fixes https://github.com/Wikidata/editgroups/issues/4. --- .../operations/PerformWikibaseEditsOperation.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java index 1075b11a4..833c701b8 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java @@ -169,8 +169,13 @@ public class PerformWikibaseEditsOperation extends EngineDependentOperation { // Generate batch token long token = (new Random()).nextLong(); - String summary = _summary + String.format(" ([[:toollabs:editgroups/b/OR/%s|details]])", - (Long.toHexString(token).substring(0, 8))); + // The following replacement is a fix for: https://github.com/Wikidata/editgroups/issues/4 + // Because commas and colons are used by Wikibase to separate the auto-generated summaries + // from the user-supplied ones, we replace these separators by similar unicode characters to + // make sure they can be told apart. + String summaryWithoutCommas = _summary.replace(",","ꓹ").replace(":","։"); + String summary = summaryWithoutCommas + String.format(" ([[:toollabs:editgroups/b/OR/%s|details]])", + (Long.toHexString(token).substring(0, 9))); // Evaluate the schema List itemDocuments = _schema.evaluate(_project, _engine); From 50b5ce75614055f504c731a9d6c857668be6de50 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 22 Feb 2019 18:04:03 +0000 Subject: [PATCH 11/17] More robust replacement condition in Wikidata summaries --- .../wikidata/operations/PerformWikibaseEditsOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java index 833c701b8..eb880c7b5 100644 --- a/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java +++ b/extensions/wikidata/src/org/openrefine/wikidata/operations/PerformWikibaseEditsOperation.java @@ -173,7 +173,7 @@ public class PerformWikibaseEditsOperation extends EngineDependentOperation { // Because commas and colons are used by Wikibase to separate the auto-generated summaries // from the user-supplied ones, we replace these separators by similar unicode characters to // make sure they can be told apart. - String summaryWithoutCommas = _summary.replace(",","ꓹ").replace(":","։"); + String summaryWithoutCommas = _summary.replaceAll(", ","ꓹ ").replaceAll(": ","։ "); String summary = summaryWithoutCommas + String.format(" ([[:toollabs:editgroups/b/OR/%s|details]])", (Long.toHexString(token).substring(0, 9))); From d0a27543f5ab0823b86bf3154c31f23c2e0e69c7 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 22 Feb 2019 18:24:55 +0000 Subject: [PATCH 12/17] Add paste button on new statements, fix invalidation of 'copied' state --- .../module/scripts/dialogs/schema-alignment-dialog.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js b/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js index cc3770773..4d5405952 100644 --- a/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js +++ b/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js @@ -627,8 +627,10 @@ SchemaAlignmentDialog._addStatement = function(container, datatype, json) { var pasteToolbar = $('
').addClass('wbs-toolbar').appendTo(referencesToggleContainer); var referencePaste = $('') .addClass('wbs-paste-reference') - .appendTo(pasteToolbar) - .hide(); + .appendTo(pasteToolbar); + if (SchemaAlignmentDialog._copiedReference === null) { + referencePaste.hide(); + } var pasteIcon = $('').addClass('wbs-icon').appendTo(referencePaste); var referencePasteButton = $('') .addClass('wbs-paste-reference-button') @@ -1232,6 +1234,10 @@ SchemaAlignmentDialog._hasChanged = function() { SchemaAlignmentDialog._schemaElmts.discardButton .prop('disabled', false) .removeClass('disabled'); + $('.wbs-copy-reference-button') + .text($.i18n('wikidata-schema/copy-reference')); + $('.wbs-copy-reference') + .removeClass('wbs-copied-reference'); } SchemaAlignmentDialog.updateNbEdits = function(nb_edits) { From 7205da734a075a49719aa3263148671f49d26dda Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 22 Feb 2019 18:28:40 +0000 Subject: [PATCH 13/17] Revert "Fix Reconcile facets affected by change to list facet boolean handling" --- .../modules/core/scripts/views/data-table/menu-reconcile.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/webapp/modules/core/scripts/views/data-table/menu-reconcile.js b/main/webapp/modules/core/scripts/views/data-table/menu-reconcile.js index 7845334fd..48df8ef85 100644 --- a/main/webapp/modules/core/scripts/views/data-table/menu-reconcile.js +++ b/main/webapp/modules/core/scripts/views/data-table/menu-reconcile.js @@ -294,7 +294,7 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) { { "name" : column.name + " "+$.i18n('core-views/hist-entries'), "columnName" : column.name, - "expression" : "cell.recon.judgmentHistoryEntry.toString()" + "expression" : "cell.recon.judgmentHistoryEntry" } ); } @@ -326,7 +326,7 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) { { "name" : column.name + ": "+$.i18n('core-views/best-cand-type-match'), "columnName" : column.name, - "expression" : 'forNonBlank(cell.recon.features.typeMatch, v, v, if(isNonBlank(value), if(cell.recon != null, "(no type)", "(unreconciled)"), "(blank)")).toString()' + "expression" : 'forNonBlank(cell.recon.features.typeMatch, v, v, if(isNonBlank(value), if(cell.recon != null, "(no type)", "(unreconciled)"), "(blank)"))' }, { "scroll" : false @@ -343,7 +343,7 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) { { "name" : column.name + ": "+ $.i18n('core-views/best-cand-name'), "columnName" : column.name, - "expression" : 'forNonBlank(cell.recon.features.nameMatch, v, v, if(isNonBlank(value), if(cell.recon.new,"(new)","(unreconciled)"), "(blank)")).toString()' + "expression" : 'forNonBlank(cell.recon.features.nameMatch, v, v, if(isNonBlank(value), "(unreconciled)", "(blank)"))' }, { "scroll" : false From 2bfc268e6967f681f4b609bd431ed757efd6a49c Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 22 Feb 2019 18:38:45 +0000 Subject: [PATCH 14/17] Revert "Merge pull request #1666 from ostephens/list-facet-changes" This reverts commit 29a818f7b432c495e0b47d7c0707c649d0f99bd3, reversing changes made to 1189cdb4f98351e98a5bdd5d683a399ef0cb45e6. --- .../refine/browsing/facets/ListFacet.java | 17 +- .../filters/ExpressionEqualRowFilter.java | 17 +- .../util/ExpressionNominalValueGrouper.java | 62 +-- .../google/refine/expr/ExpressionUtils.java | 16 +- .../tests/browsing/facets/ListFacetTests.java | 5 +- .../browsing/facets/TextListFacetTests.java | 435 ------------------ .../ExpressionNominalValueGrouperTests.java | 37 +- .../google/refine/tests/model/CacheTests.java | 2 +- .../modules/core/scripts/facets/list-facet.js | 90 +--- .../views/data-table/data-table-view.js | 4 +- .../scripts/views/data-table/menu-facets.js | 12 +- 11 files changed, 46 insertions(+), 651 deletions(-) delete mode 100644 main/tests/server/src/com/google/refine/tests/browsing/facets/TextListFacetTests.java diff --git a/main/src/com/google/refine/browsing/facets/ListFacet.java b/main/src/com/google/refine/browsing/facets/ListFacet.java index 7e240d2fd..244b6c238 100644 --- a/main/src/com/google/refine/browsing/facets/ListFacet.java +++ b/main/src/com/google/refine/browsing/facets/ListFacet.java @@ -95,12 +95,6 @@ public class ListFacet implements Facet { @JsonIgnore public List selection = new LinkedList<>(); - @JsonProperty("selectNumber") - public boolean selectNumber; - @JsonProperty("selectDateTime") - public boolean selectDateTime; - @JsonProperty("selectBoolean") - public boolean selectBoolean; @JsonProperty("selectBlank") public boolean selectBlank; @JsonProperty("selectError") @@ -162,9 +156,6 @@ public class ListFacet implements Facet { * Computed results */ protected List _choices = new LinkedList(); - protected int _numberCount; - protected int _datetimeCount; - protected int _booleanCount; protected int _blankCount; protected int _errorCount; @@ -278,16 +269,13 @@ public class ListFacet implements Facet { return _eval == null || _errorMessage != null || - (_config.selection.size() == 0 && !_config.selectBlank && !_config.selectError && !_config.selectNumber && !_config.selectDateTime && !_config.selectBoolean) ? + (_config.selection.size() == 0 && !_config.selectBlank && !_config.selectError) ? null : new ExpressionEqualRowFilter( _eval, _config.columnName, _cellIndex, createMatches(), - _config.selectNumber, - _config.selectDateTime, - _config.selectBoolean, _config.selectBlank, _config.selectError, _config.invert); @@ -353,9 +341,6 @@ public class ListFacet implements Facet { } } - _numberCount = grouper.numberCount; - _datetimeCount = grouper.datetimeCount; - _booleanCount = grouper.booleanCount; _blankCount = grouper.blankCount; _errorCount = grouper.errorCount; } diff --git a/main/src/com/google/refine/browsing/filters/ExpressionEqualRowFilter.java b/main/src/com/google/refine/browsing/filters/ExpressionEqualRowFilter.java index a2701e105..b04ff28f5 100644 --- a/main/src/com/google/refine/browsing/filters/ExpressionEqualRowFilter.java +++ b/main/src/com/google/refine/browsing/filters/ExpressionEqualRowFilter.java @@ -33,7 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.browsing.filters; -import java.time.OffsetDateTime; import java.util.Collection; import java.util.Properties; @@ -58,10 +57,8 @@ public class ExpressionEqualRowFilter implements RowFilter { final protected int _cellIndex; // the expression is based on this column; // -1 if based on no column in particular, // for expression such as "row.starred". + final protected Object[] _matches; - final protected boolean _selectNumber; - final protected boolean _selectDateTime; - final protected boolean _selectBoolean; final protected boolean _selectBlank; final protected boolean _selectError; final protected boolean _invert; @@ -71,9 +68,6 @@ public class ExpressionEqualRowFilter implements RowFilter { String columnName, int cellIndex, Object[] matches, - boolean selectNumber, - boolean selectDateTime, - boolean selectBoolean, boolean selectBlank, boolean selectError, boolean invert @@ -82,9 +76,6 @@ public class ExpressionEqualRowFilter implements RowFilter { _columnName = columnName; _cellIndex = cellIndex; _matches = matches; - _selectNumber = selectNumber; - _selectDateTime = selectDateTime; - _selectBoolean = selectBoolean; _selectBlank = selectBlank; _selectError = selectError; _invert = invert; @@ -178,12 +169,6 @@ public class ExpressionEqualRowFilter implements RowFilter { protected boolean testValue(Object v) { if (ExpressionUtils.isError(v)) { return _selectError; - } else if (v instanceof Number) { - return _selectNumber; - } else if (v instanceof OffsetDateTime) { - return _selectDateTime; - } else if (v instanceof Boolean) { - return _selectBoolean; } else if (ExpressionUtils.isNonBlankData(v)) { for (Object match : _matches) { if (testValue(v, match)) { diff --git a/main/src/com/google/refine/browsing/util/ExpressionNominalValueGrouper.java b/main/src/com/google/refine/browsing/util/ExpressionNominalValueGrouper.java index 7e399fa03..a0039d7ce 100644 --- a/main/src/com/google/refine/browsing/util/ExpressionNominalValueGrouper.java +++ b/main/src/com/google/refine/browsing/util/ExpressionNominalValueGrouper.java @@ -57,6 +57,15 @@ import com.google.refine.util.StringUtils; * from a given expression. */ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor { + static public class IndexedNominalFacetChoice extends NominalFacetChoice { + int _latestIndex; + + public IndexedNominalFacetChoice(DecoratedValue decoratedValue, int latestIndex) { + super(decoratedValue); + _latestIndex = latestIndex; + } + } + /* * Configuration */ @@ -68,29 +77,14 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor * Computed results */ final public Map choices = new HashMap(); - public int numberCount = 0; - public int datetimeCount = 0; - public int booleanCount = 0; public int blankCount = 0; public int errorCount = 0; /* * Scratch pad variables */ - protected boolean hasNumber; - protected boolean hasDateTime; - protected boolean hasBoolean; protected boolean hasBlank; protected boolean hasError; - - static public class IndexedNominalFacetChoice extends NominalFacetChoice { - int _latestIndex; - - public IndexedNominalFacetChoice(DecoratedValue decoratedValue, int latestIndex) { - super(decoratedValue); - _latestIndex = latestIndex; - } - } public ExpressionNominalValueGrouper(Evaluable evaluable, String columnName, int cellIndex) { _evaluable = evaluable; @@ -110,25 +104,13 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor @Override public boolean visit(Project project, int rowIndex, Row row) { - hasNumber = false; - hasDateTime = false; - hasBoolean = false; hasError = false; hasBlank = false; Properties bindings = ExpressionUtils.createBindings(project); visitRow(project, rowIndex, row, bindings, rowIndex); - - if (hasNumber) { - numberCount++; - } - if (hasDateTime) { - datetimeCount++; - } - if (hasBoolean) { - booleanCount++; - } + if (hasError) { errorCount++; } @@ -141,9 +123,6 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor @Override public boolean visit(Project project, Record record) { - hasNumber = false; - hasDateTime = false; - hasBoolean = false; hasError = false; hasBlank = false; @@ -154,15 +133,6 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor visitRow(project, r, row, bindings, record.recordIndex); } - if (hasNumber) { - numberCount++; - } - if (hasDateTime) { - datetimeCount++; - } - if (hasBoolean) { - booleanCount++; - } if (hasError) { errorCount++; } @@ -204,12 +174,6 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor protected void processValue(Object value, int index) { if (ExpressionUtils.isError(value)) { hasError = true; - } else if (ExpressionUtils.isNumber(value)) { - hasNumber = true; - } else if (ExpressionUtils.isDateTime(value)) { - hasDateTime = true; - } else if (ExpressionUtils.isBoolean(value)) { - hasBoolean = true; } else if (ExpressionUtils.isNonBlankData(value)) { String valueString = StringUtils.toString(value); IndexedNominalFacetChoice facetChoice = choices.get(valueString); @@ -272,12 +236,6 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor public Integer getChoiceValueCount(Object choiceValue) { if (ExpressionUtils.isError(choiceValue)) { return errorCount; - } else if (ExpressionUtils.isNumber(choiceValue)) { - return numberCount; - } else if (ExpressionUtils.isDateTime(choiceValue)) { - return datetimeCount; - } else if (ExpressionUtils.isBoolean(choiceValue)) { - return booleanCount; } else if (ExpressionUtils.isNonBlankData(choiceValue)) { IndexedNominalFacetChoice choice = choices.get(StringUtils.toString(choiceValue)); return choice != null ? choice.count : 0; diff --git a/main/src/com/google/refine/expr/ExpressionUtils.java b/main/src/com/google/refine/expr/ExpressionUtils.java index 95179dcfe..955db6cd6 100644 --- a/main/src/com/google/refine/expr/ExpressionUtils.java +++ b/main/src/com/google/refine/expr/ExpressionUtils.java @@ -102,19 +102,11 @@ public class ExpressionUtils { static public boolean isError(Object o) { return o instanceof EvalError; } - - static public boolean isNumber(Object v) { - return v != null && (v instanceof Number); + /* + static public boolean isBlank(Object o) { + return o == null || (o instanceof String && ((String) o).length() == 0); } - - static public boolean isBoolean(Object v) { - return v != null && v instanceof Boolean; - } - - static public boolean isDateTime(Object v) { - return v != null && v instanceof OffsetDateTime; - } - + */ static public boolean isNonBlankData(Object o) { return o != null && diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java index 906e637f7..fac4465e7 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/ListFacetTests.java @@ -45,14 +45,11 @@ public class ListFacetTests extends RefineTest { private static String jsonConfig = "{" + "\"type\":\"list\"," + "\"name\":\"facet A\"," - + "\"expression\":\"value+\\\"bar\\\"\"," + "\"columnName\":\"Column A\"," + + "\"expression\":\"value+\\\"bar\\\"\"," + "\"omitBlank\":false," + "\"omitError\":false," + "\"selection\":[{\"v\":{\"v\":\"foobar\",\"l\":\"true\"}}]," - + "\"selectNumber\":false," - + "\"selectDateTime\":false," - + "\"selectBoolean\":false," + "\"selectBlank\":false," + "\"selectError\":false," + "\"invert\":false" diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/TextListFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/TextListFacetTests.java deleted file mode 100644 index 14f82d06b..000000000 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/TextListFacetTests.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - -Copyright 2018, Owen Stephens -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of the copyright holder nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -package com.google.refine.tests.browsing.facets; - -import com.google.refine.model.Cell; -import com.google.refine.model.Row; - -import java.io.IOException; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; - -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; - -import com.google.refine.model.ModelException; -import com.google.refine.model.Project; -import com.google.refine.browsing.RowFilter; -import com.google.refine.browsing.facets.Facet; -import com.google.refine.browsing.facets.ListFacet.ListFacetConfig; -import com.google.refine.tests.RefineTest; -import com.google.refine.util.ParsingUtilities; - - -public class TextListFacetTests extends RefineTest { - // dependencies - private Project project; - private RowFilter rowfilter; - - // Variables - private static OffsetDateTime dateTimeValue = OffsetDateTime.parse("2017-05-12T05:45:00+00:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME); - private static int integerValue = 1; - private static String stringValue = "a"; - private static String emptyStringValue = ""; - private static Boolean booleanValue = true; - - private static final String projectName = "TextListFacet"; - private static final String columnName = "Col1"; - private static final int numberOfRows = 5; - - @Override - @BeforeTest - public void init() { - logger = LoggerFactory.getLogger(this.getClass()); - } - - @BeforeMethod - public void setUp() throws IOException, ModelException { - project = createProjectWithColumns(projectName, columnName); - for (int i = 0; i < numberOfRows; i++) { - Row row = new Row(1); - row.setCell(0, new Cell(stringValue, null)); - project.rows.add(row); - } - for (int i = 0; i < numberOfRows; i++) { - Row row = new Row(1); - row.setCell(0, new Cell(dateTimeValue, null)); - project.rows.add(row); - } - for (int i = 0; i < numberOfRows; i++) { - Row row = new Row(1); - row.setCell(0, new Cell(integerValue, null)); - project.rows.add(row); - } - for (int i = 0; i < numberOfRows; i++) { - Row row = new Row(1); - row.setCell(0, new Cell(booleanValue, null)); - project.rows.add(row); - } - for (int i = 0; i < numberOfRows; i++) { - Row row = new Row(1); - row.setCell(0, new Cell(null, null)); - project.rows.add(row); - } - for (int i = 0; i < numberOfRows; i++) { - Row row = new Row(1); - row.setCell(0, new Cell(emptyStringValue, null)); - project.rows.add(row); - } - } - - @Test - public void testTextSelection() throws Exception { - //Need to work out the correct facet config for these tests to work - //Also need all rows in all tests so can check that rows aren't being selected when they shouldn't be - String jsonConfig = "{" - + "\"type\": \"list\"," - + "\"name\": \"Value\"," - + "\"columnName\": \"" + columnName + "\"," - + "\"expression\": \"value\"," - + "\"omitBlank\": false," - + "\"omitError\": false," - + "\"selection\": [" - + " {" - + "\"v\": {" - + "\"v\": \"a\"," - + "\"l\": \"a\"" - + "}" - + "}" - + "]," - + "\"selectNumber\": false," - + "\"selectDateTime\": false," - + "\"selectBoolean\": false," - + "\"selectBlank\": false," - + "\"selectError\": false," - + "\"invert\": false" - + "}"; - - //Add the facet to the project and create a row filter - ListFacetConfig facetConfig = ParsingUtilities.mapper.readValue(jsonConfig, ListFacetConfig.class); - Facet facet = facetConfig.apply(project); - rowfilter = facet.getRowFilter(project); - - //Check each row in the project against the filter - //Rows 1-5 are strings - Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),true); - Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),true); - Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),true); - Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),true); - Assert.assertEquals(rowfilter.filterRow(project, 4, project.rows.get(4)),true); - //Rows 6-10 are DateTimes - Assert.assertEquals(rowfilter.filterRow(project, 5, project.rows.get(5)),false); - Assert.assertEquals(rowfilter.filterRow(project, 6, project.rows.get(6)),false); - Assert.assertEquals(rowfilter.filterRow(project, 7, project.rows.get(7)),false); - Assert.assertEquals(rowfilter.filterRow(project, 8, project.rows.get(8)),false); - Assert.assertEquals(rowfilter.filterRow(project, 9, project.rows.get(9)),false); - //Rows 11-15 are integers - Assert.assertEquals(rowfilter.filterRow(project, 10, project.rows.get(10)),false); - Assert.assertEquals(rowfilter.filterRow(project, 11, project.rows.get(11)),false); - Assert.assertEquals(rowfilter.filterRow(project, 12, project.rows.get(12)),false); - Assert.assertEquals(rowfilter.filterRow(project, 13, project.rows.get(13)),false); - Assert.assertEquals(rowfilter.filterRow(project, 14, project.rows.get(14)),false); - //Rows 16-20 are booleans - Assert.assertEquals(rowfilter.filterRow(project, 15, project.rows.get(15)),false); - Assert.assertEquals(rowfilter.filterRow(project, 16, project.rows.get(16)),false); - Assert.assertEquals(rowfilter.filterRow(project, 17, project.rows.get(17)),false); - Assert.assertEquals(rowfilter.filterRow(project, 18, project.rows.get(18)),false); - Assert.assertEquals(rowfilter.filterRow(project, 19, project.rows.get(19)),false); - //Rows 21-25 are nulls - Assert.assertEquals(rowfilter.filterRow(project, 20, project.rows.get(20)),false); - Assert.assertEquals(rowfilter.filterRow(project, 21, project.rows.get(21)),false); - Assert.assertEquals(rowfilter.filterRow(project, 22, project.rows.get(22)),false); - Assert.assertEquals(rowfilter.filterRow(project, 23, project.rows.get(23)),false); - Assert.assertEquals(rowfilter.filterRow(project, 24, project.rows.get(24)),false); - //Rows 26-30 are empty strings - Assert.assertEquals(rowfilter.filterRow(project, 25, project.rows.get(25)),false); - Assert.assertEquals(rowfilter.filterRow(project, 26, project.rows.get(26)),false); - Assert.assertEquals(rowfilter.filterRow(project, 27, project.rows.get(27)),false); - Assert.assertEquals(rowfilter.filterRow(project, 28, project.rows.get(28)),false); - Assert.assertEquals(rowfilter.filterRow(project, 29, project.rows.get(29)),false); - } - - @Test - public void testDateSelection() throws Exception { - String jsonConfig = "{" - + "\"type\": \"list\"," - + "\"name\": \"Value\"," - + "\"columnName\": \"" + columnName + "\"," - + "\"expression\": \"value\"," - + "\"omitBlank\": false," - + "\"omitError\": false," - + "\"selection\": []," - + "\"selectNumber\": false," - + "\"selectDateTime\": true," - + "\"selectBoolean\": false," - + "\"selectBlank\": false," - + "\"selectError\": false," - + "\"invert\": false" - + "}"; - - //Add the facet to the project and create a row filter - ListFacetConfig facetConfig = ParsingUtilities.mapper.readValue(jsonConfig, ListFacetConfig.class); - Facet facet = facetConfig.apply(project); - rowfilter = facet.getRowFilter(project); - - //Check each row in the project against the filter - //Rows 1-5 are strings - Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),false); - Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),false); - Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),false); - Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),false); - Assert.assertEquals(rowfilter.filterRow(project, 4, project.rows.get(4)),false); - //Rows 6-10 are DateTimes - Assert.assertEquals(rowfilter.filterRow(project, 5, project.rows.get(5)),true); - Assert.assertEquals(rowfilter.filterRow(project, 6, project.rows.get(6)),true); - Assert.assertEquals(rowfilter.filterRow(project, 7, project.rows.get(7)),true); - Assert.assertEquals(rowfilter.filterRow(project, 8, project.rows.get(8)),true); - Assert.assertEquals(rowfilter.filterRow(project, 9, project.rows.get(9)),true); - //Rows 11-15 are integers - Assert.assertEquals(rowfilter.filterRow(project, 10, project.rows.get(10)),false); - Assert.assertEquals(rowfilter.filterRow(project, 11, project.rows.get(11)),false); - Assert.assertEquals(rowfilter.filterRow(project, 12, project.rows.get(12)),false); - Assert.assertEquals(rowfilter.filterRow(project, 13, project.rows.get(13)),false); - Assert.assertEquals(rowfilter.filterRow(project, 14, project.rows.get(14)),false); - //Rows 16-20 are booleans - Assert.assertEquals(rowfilter.filterRow(project, 15, project.rows.get(15)),false); - Assert.assertEquals(rowfilter.filterRow(project, 16, project.rows.get(16)),false); - Assert.assertEquals(rowfilter.filterRow(project, 17, project.rows.get(17)),false); - Assert.assertEquals(rowfilter.filterRow(project, 18, project.rows.get(18)),false); - Assert.assertEquals(rowfilter.filterRow(project, 19, project.rows.get(19)),false); - //Rows 21-25 are nulls - Assert.assertEquals(rowfilter.filterRow(project, 20, project.rows.get(20)),false); - Assert.assertEquals(rowfilter.filterRow(project, 21, project.rows.get(21)),false); - Assert.assertEquals(rowfilter.filterRow(project, 22, project.rows.get(22)),false); - Assert.assertEquals(rowfilter.filterRow(project, 23, project.rows.get(23)),false); - Assert.assertEquals(rowfilter.filterRow(project, 24, project.rows.get(24)),false); - //Rows 26-30 are empty strings - Assert.assertEquals(rowfilter.filterRow(project, 25, project.rows.get(25)),false); - Assert.assertEquals(rowfilter.filterRow(project, 26, project.rows.get(26)),false); - Assert.assertEquals(rowfilter.filterRow(project, 27, project.rows.get(27)),false); - Assert.assertEquals(rowfilter.filterRow(project, 28, project.rows.get(28)),false); - Assert.assertEquals(rowfilter.filterRow(project, 29, project.rows.get(29)),false); - } - - @Test - public void testIntegerSelection() throws Exception { - String jsonConfig = "{" - + "\"type\": \"list\"," - + "\"name\": \"Value\"," - + "\"columnName\": \"" + columnName + "\"," - + "\"expression\": \"value\"," - + "\"omitBlank\": false," - + "\"omitError\": false," - + "\"selection\": []," - + "\"selectNumber\": true," - + "\"selectDateTime\": false," - + "\"selectBoolean\": false," - + "\"selectBlank\": false," - + "\"selectError\": false," - + "\"invert\": false" - + "}"; - - //Add the facet to the project and create a row filter - ListFacetConfig facetConfig = ParsingUtilities.mapper.readValue(jsonConfig, ListFacetConfig.class); - Facet facet = facetConfig.apply(project); - rowfilter = facet.getRowFilter(project); - - //Check each row in the project against the filter - //Rows 1-5 are strings - Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),false); - Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),false); - Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),false); - Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),false); - Assert.assertEquals(rowfilter.filterRow(project, 4, project.rows.get(4)),false); - //Rows 6-10 are DateTimes - Assert.assertEquals(rowfilter.filterRow(project, 5, project.rows.get(5)),false); - Assert.assertEquals(rowfilter.filterRow(project, 6, project.rows.get(6)),false); - Assert.assertEquals(rowfilter.filterRow(project, 7, project.rows.get(7)),false); - Assert.assertEquals(rowfilter.filterRow(project, 8, project.rows.get(8)),false); - Assert.assertEquals(rowfilter.filterRow(project, 9, project.rows.get(9)),false); - //Rows 11-15 are integers - Assert.assertEquals(rowfilter.filterRow(project, 10, project.rows.get(10)),true); - Assert.assertEquals(rowfilter.filterRow(project, 11, project.rows.get(11)),true); - Assert.assertEquals(rowfilter.filterRow(project, 12, project.rows.get(12)),true); - Assert.assertEquals(rowfilter.filterRow(project, 13, project.rows.get(13)),true); - Assert.assertEquals(rowfilter.filterRow(project, 14, project.rows.get(14)),true); - //Rows 16-20 are booleans - Assert.assertEquals(rowfilter.filterRow(project, 15, project.rows.get(15)),false); - Assert.assertEquals(rowfilter.filterRow(project, 16, project.rows.get(16)),false); - Assert.assertEquals(rowfilter.filterRow(project, 17, project.rows.get(17)),false); - Assert.assertEquals(rowfilter.filterRow(project, 18, project.rows.get(18)),false); - Assert.assertEquals(rowfilter.filterRow(project, 19, project.rows.get(19)),false); - //Rows 21-25 are nulls - Assert.assertEquals(rowfilter.filterRow(project, 20, project.rows.get(20)),false); - Assert.assertEquals(rowfilter.filterRow(project, 21, project.rows.get(21)),false); - Assert.assertEquals(rowfilter.filterRow(project, 22, project.rows.get(22)),false); - Assert.assertEquals(rowfilter.filterRow(project, 23, project.rows.get(23)),false); - Assert.assertEquals(rowfilter.filterRow(project, 24, project.rows.get(24)),false); - //Rows 26-30 are empty strings - Assert.assertEquals(rowfilter.filterRow(project, 25, project.rows.get(25)),false); - Assert.assertEquals(rowfilter.filterRow(project, 26, project.rows.get(26)),false); - Assert.assertEquals(rowfilter.filterRow(project, 27, project.rows.get(27)),false); - Assert.assertEquals(rowfilter.filterRow(project, 28, project.rows.get(28)),false); - Assert.assertEquals(rowfilter.filterRow(project, 29, project.rows.get(29)),false); - } - - @Test - public void testBooleanSelection() throws Exception { - String jsonConfig = "{" - + "\"type\": \"list\"," - + "\"name\": \"Value\"," - + "\"columnName\": \"" + columnName + "\"," - + "\"expression\": \"value\"," - + "\"omitBlank\": false," - + "\"omitError\": false," - + "\"selection\": []," - + "\"selectNumber\": false," - + "\"selectDateTime\": false," - + "\"selectBoolean\": true," - + "\"selectBlank\": false," - + "\"selectError\": false," - + "\"invert\": false" - + "}"; - - //Add the facet to the project and create a row filter - ListFacetConfig facetConfig = ParsingUtilities.mapper.readValue(jsonConfig, ListFacetConfig.class); - Facet facet = facetConfig.apply(project); - rowfilter = facet.getRowFilter(project); - - //Check each row in the project against the filter - //Rows 1-5 are strings - Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),false); - Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),false); - Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),false); - Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),false); - Assert.assertEquals(rowfilter.filterRow(project, 4, project.rows.get(4)),false); - //Rows 6-10 are DateTimes - Assert.assertEquals(rowfilter.filterRow(project, 5, project.rows.get(5)),false); - Assert.assertEquals(rowfilter.filterRow(project, 6, project.rows.get(6)),false); - Assert.assertEquals(rowfilter.filterRow(project, 7, project.rows.get(7)),false); - Assert.assertEquals(rowfilter.filterRow(project, 8, project.rows.get(8)),false); - Assert.assertEquals(rowfilter.filterRow(project, 9, project.rows.get(9)),false); - //Rows 11-15 are integers - Assert.assertEquals(rowfilter.filterRow(project, 10, project.rows.get(10)),false); - Assert.assertEquals(rowfilter.filterRow(project, 11, project.rows.get(11)),false); - Assert.assertEquals(rowfilter.filterRow(project, 12, project.rows.get(12)),false); - Assert.assertEquals(rowfilter.filterRow(project, 13, project.rows.get(13)),false); - Assert.assertEquals(rowfilter.filterRow(project, 14, project.rows.get(14)),false); - //Rows 16-20 are booleans - Assert.assertEquals(rowfilter.filterRow(project, 15, project.rows.get(15)),true); - Assert.assertEquals(rowfilter.filterRow(project, 16, project.rows.get(16)),true); - Assert.assertEquals(rowfilter.filterRow(project, 17, project.rows.get(17)),true); - Assert.assertEquals(rowfilter.filterRow(project, 18, project.rows.get(18)),true); - Assert.assertEquals(rowfilter.filterRow(project, 19, project.rows.get(19)),true); - //Rows 21-25 are nulls - Assert.assertEquals(rowfilter.filterRow(project, 20, project.rows.get(20)),false); - Assert.assertEquals(rowfilter.filterRow(project, 21, project.rows.get(21)),false); - Assert.assertEquals(rowfilter.filterRow(project, 22, project.rows.get(22)),false); - Assert.assertEquals(rowfilter.filterRow(project, 23, project.rows.get(23)),false); - Assert.assertEquals(rowfilter.filterRow(project, 24, project.rows.get(24)),false); - //Rows 26-30 are empty strings - Assert.assertEquals(rowfilter.filterRow(project, 25, project.rows.get(25)),false); - Assert.assertEquals(rowfilter.filterRow(project, 26, project.rows.get(26)),false); - Assert.assertEquals(rowfilter.filterRow(project, 27, project.rows.get(27)),false); - Assert.assertEquals(rowfilter.filterRow(project, 28, project.rows.get(28)),false); - Assert.assertEquals(rowfilter.filterRow(project, 29, project.rows.get(29)),false); - } - - @Test - public void testBlankSelection() throws Exception { - String jsonConfig = "{" - + "\"type\": \"list\"," - + "\"name\": \"Value\"," - + "\"columnName\": \"" + columnName + "\"," - + "\"expression\": \"value\"," - + "\"omitBlank\": false," - + "\"omitError\": false," - + "\"selection\": []," - + "\"selectNumber\": false," - + "\"selectDateTime\": false," - + "\"selectBoolean\": false," - + "\"selectBlank\": true," - + "\"selectError\": false," - + "\"invert\": false" - + "}"; - - //Add the facet to the project and create a row filter - ListFacetConfig facetConfig = ParsingUtilities.mapper.readValue(jsonConfig, ListFacetConfig.class); - Facet facet = facetConfig.apply(project); - rowfilter = facet.getRowFilter(project); - - //Check each row in the project against the filter - //Rows 1-5 are strings - Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),false); - Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),false); - Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),false); - Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),false); - Assert.assertEquals(rowfilter.filterRow(project, 4, project.rows.get(4)),false); - //Rows 6-10 are DateTimes - Assert.assertEquals(rowfilter.filterRow(project, 5, project.rows.get(5)),false); - Assert.assertEquals(rowfilter.filterRow(project, 6, project.rows.get(6)),false); - Assert.assertEquals(rowfilter.filterRow(project, 7, project.rows.get(7)),false); - Assert.assertEquals(rowfilter.filterRow(project, 8, project.rows.get(8)),false); - Assert.assertEquals(rowfilter.filterRow(project, 9, project.rows.get(9)),false); - //Rows 11-15 are integers - Assert.assertEquals(rowfilter.filterRow(project, 10, project.rows.get(10)),false); - Assert.assertEquals(rowfilter.filterRow(project, 11, project.rows.get(11)),false); - Assert.assertEquals(rowfilter.filterRow(project, 12, project.rows.get(12)),false); - Assert.assertEquals(rowfilter.filterRow(project, 13, project.rows.get(13)),false); - Assert.assertEquals(rowfilter.filterRow(project, 14, project.rows.get(14)),false); - //Rows 16-20 are booleans - Assert.assertEquals(rowfilter.filterRow(project, 15, project.rows.get(15)),false); - Assert.assertEquals(rowfilter.filterRow(project, 16, project.rows.get(16)),false); - Assert.assertEquals(rowfilter.filterRow(project, 17, project.rows.get(17)),false); - Assert.assertEquals(rowfilter.filterRow(project, 18, project.rows.get(18)),false); - Assert.assertEquals(rowfilter.filterRow(project, 19, project.rows.get(19)),false); - //Rows 21-25 are nulls - Assert.assertEquals(rowfilter.filterRow(project, 20, project.rows.get(20)),true); - Assert.assertEquals(rowfilter.filterRow(project, 21, project.rows.get(21)),true); - Assert.assertEquals(rowfilter.filterRow(project, 22, project.rows.get(22)),true); - Assert.assertEquals(rowfilter.filterRow(project, 23, project.rows.get(23)),true); - Assert.assertEquals(rowfilter.filterRow(project, 24, project.rows.get(24)),true); - //Rows 26-30 are empty strings - Assert.assertEquals(rowfilter.filterRow(project, 25, project.rows.get(25)),true); - Assert.assertEquals(rowfilter.filterRow(project, 26, project.rows.get(26)),true); - Assert.assertEquals(rowfilter.filterRow(project, 27, project.rows.get(27)),true); - Assert.assertEquals(rowfilter.filterRow(project, 28, project.rows.get(28)),true); - Assert.assertEquals(rowfilter.filterRow(project, 29, project.rows.get(29)),true); - } - - // should add tests for errors as well -} diff --git a/main/tests/server/src/com/google/refine/tests/browsing/util/ExpressionNominalValueGrouperTests.java b/main/tests/server/src/com/google/refine/tests/browsing/util/ExpressionNominalValueGrouperTests.java index c4649fb03..2fd380f19 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/util/ExpressionNominalValueGrouperTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/util/ExpressionNominalValueGrouperTests.java @@ -59,9 +59,10 @@ public class ExpressionNominalValueGrouperTests extends RefineTest { private static Properties bindings; private static OffsetDateTime dateTimeValue = OffsetDateTime.parse("2017-05-12T05:45:00+00:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME); + private static String dateTimeStringValue = "2017-05-12T05:45:00Z"; private static int integerValue = 1; + private static String integerStringValue = "1"; private static String stringStringValue = "a"; - private static Boolean booleanValue = true; private static ExpressionNominalValueGrouper grouper; private static Evaluable eval; @@ -139,7 +140,11 @@ public class ExpressionNominalValueGrouperTests extends RefineTest { grouper.end(project); } - Assert.assertEquals(grouper.choices.size(),0); + Assert.assertEquals(grouper.choices.size(),1); + + Assert.assertTrue(grouper.choices.containsKey(integerStringValue)); + Assert.assertEquals(grouper.choices.get(integerStringValue).decoratedValue.label,integerStringValue); + Assert.assertEquals(grouper.choices.get(integerStringValue).decoratedValue.value.toString(),integerStringValue); } @Test @@ -163,30 +168,10 @@ public class ExpressionNominalValueGrouperTests extends RefineTest { grouper.end(project); } - Assert.assertEquals(grouper.choices.size(),0); - } - - @Test - public void expressionNominalValueGrouperBooleans() throws Exception { - //populate project - for (int i = 0; i < numberOfRows; i++) { - Row row = new Row(1); - row.setCell(0, new Cell(booleanValue, null)); - project.rows.add(row); - } - //create grouper - eval = MetaParser.parse("value"); - grouper = new ExpressionNominalValueGrouper(eval, columnName, cellIndex); - try { - grouper.start(project); - for (int rowIndex = 0; rowIndex < numberOfRows; rowIndex++) { - Row row = project.rows.get(rowIndex); - grouper.visit(project, rowIndex, row); - } - } finally { - grouper.end(project); - } + Assert.assertEquals(grouper.choices.size(),1); - Assert.assertEquals(grouper.choices.size(),0); + Assert.assertTrue(grouper.choices.containsKey(dateTimeStringValue)); + Assert.assertEquals(grouper.choices.get(dateTimeStringValue).decoratedValue.label,dateTimeStringValue); + Assert.assertEquals(grouper.choices.get(dateTimeStringValue).decoratedValue.value.toString(),dateTimeStringValue); } } diff --git a/main/tests/server/src/com/google/refine/tests/model/CacheTests.java b/main/tests/server/src/com/google/refine/tests/model/CacheTests.java index 7675acc79..b4d5b3cb7 100644 --- a/main/tests/server/src/com/google/refine/tests/model/CacheTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/CacheTests.java @@ -59,7 +59,7 @@ import com.google.refine.tests.RefineTest; public class CacheTests extends RefineTest { // Equivalent to duplicate facet on Column A with true selected - static private final String ENGINE_JSON_DUPLICATES = "{\"facets\":[{\"type\":\"list\",\"name\":\"facet A\",\"columnName\":\"Column A\",\"expression\":\"(facetCount(value, 'value', 'Column A') > 1).toString()\",\"omitBlank\":false,\"omitError\":false,\"selection\":[{\"v\":{\"v\":\"true\",\"l\":\"true\"}}],\"selectBlank\":false,\"selectError\":false,\"invert\":false}],\"mode\":\"row-based\"}}"; + static final String ENGINE_JSON_DUPLICATES = "{\"facets\":[{\"type\":\"list\",\"name\":\"facet A\",\"columnName\":\"Column A\",\"expression\":\"facetCount(value, 'value', 'Column A') > 1\",\"omitBlank\":false,\"omitError\":false,\"selection\":[{\"v\":{\"v\":true,\"l\":\"true\"}}],\"selectBlank\":false,\"selectError\":false,\"invert\":false}],\"mode\":\"row-based\"}}"; @Override @BeforeTest diff --git a/main/webapp/modules/core/scripts/facets/list-facet.js b/main/webapp/modules/core/scripts/facets/list-facet.js index 77a81cc41..33b1b3094 100644 --- a/main/webapp/modules/core/scripts/facets/list-facet.js +++ b/main/webapp/modules/core/scripts/facets/list-facet.js @@ -44,9 +44,6 @@ function ListFacet(div, config, options, selection) { } this._selection = selection || []; - this._numberChoice = (config.selectNumber) ? { s : true, c : 0 } : null; - this._datetimeChoice = (config.selectDateTime) ? { s : true, c : 0 } : null; - this._booleanChoice = (config.selecBoolean) ? { s : true, c : 0 } : null; this._blankChoice = (config.selectBlank) ? { s : true, c : 0 } : null; this._errorChoice = (config.selectError) ? { s : true, c : 0 } : null; @@ -65,9 +62,6 @@ ListFacet.prototype.dispose = function() { ListFacet.prototype.reset = function() { this._selection = []; - this._numberChoice = null; - this._datetimeChoice = null; - this._booleanChoice = null; this._blankChoice = null; this._errorChoice = null; }; @@ -91,14 +85,11 @@ ListFacet.prototype.getJSON = function() { columnName: this._config.columnName, expression: this._config.expression, omitBlank: "omitBlank" in this._config ? this._config.omitBlank : false, - omitError: "omitError" in this._config ? this._config.omitError : false, - selection: [], - selectNumber: this._numberChoice !== null && this._numberChoice.s, - selectDateTime: this._datetimeChoice !== null && this._datetimeChoice.s, - selectBoolean: this._booleanChoice !== null && this._booleanChoice.s, - selectBlank: this._blankChoice !== null && this._blankChoice.s, - selectError: this._errorChoice !== null && this._errorChoice.s, - invert: this._config.invert + omitError: "omitError" in this._config ? this._config.omitError : false, + selection: [], + selectBlank: this._blankChoice !== null && this._blankChoice.s, + selectError: this._errorChoice !== null && this._errorChoice.s, + invert: this._config.invert }; for (var i = 0; i < this._selection.length; i++) { var choice = { @@ -111,11 +102,8 @@ ListFacet.prototype.getJSON = function() { ListFacet.prototype.hasSelection = function() { return this._selection.length > 0 || - ( this._numberChoice !== null && this._numberChoice.s ) || - ( this._datetimeChoice !== null && this._datetimeChoice.s ) || - ( this._booleanChoice !== null && this._booleanChoice.s ) || - ( this._blankChoice !== null && this._blankChoice.s ) || - ( this._errorChoice !== null && this._errorChoice.s ); + (this._blankChoice !== null && this._blankChoice.s) || + (this._errorChoice !== null && this._errorChoice.s); }; ListFacet.prototype.updateState = function(data) { @@ -133,9 +121,6 @@ ListFacet.prototype.updateState = function(data) { this._selection = selection; this._reSortChoices(); - this._numberChoice = data.numberChoice || null; - this._datetimeChoice = data.datetimeChoice || null; - this._booleanChoice = data.booleanChoice || null; this._blankChoice = data.blankChoice || null; this._errorChoice = data.errorChoice || null; } @@ -254,15 +239,6 @@ ListFacet.prototype._copyChoices = function() { var choice = this._data.choices[i]; lines.push(choice.v.l + "\t" + choice.c); } - if (this._numberChoice) { - lines.push("(number)\t" + this._numberChoice.c); - } - if (this._datetimeChoice) { - lines.push("(date)\t" + this._datetimeChoice.c); - } - if (this._booleanChoice) { - lines.push("(boolean)\t" + this._booleanChoice.c); - } if (this._blankChoice) { lines.push("(blank)\t" + this._blankChoice.c); } @@ -359,9 +335,6 @@ ListFacet.prototype._update = function(resetScroll) { var choices = this._data.choices; var selectionCount = this._selection.length + - (this._numberChoice !== null && this._numberChoice.s ? 1 : 0) + - (this._datetimeChoice !== null && this._datetimeChoice.s ? 1 : 0) + - (this._booleanChoice !== null && this._booleanChoice.s ? 1 : 0) + (this._blankChoice !== null && this._blankChoice.s ? 1 : 0) + (this._errorChoice !== null && this._errorChoice.s ? 1 : 0); @@ -416,24 +389,10 @@ ListFacet.prototype._update = function(resetScroll) { for (var i = 0; i < choices.length; i++) { renderChoice(i, choices[i]); } - if (this._numberChoice !== null) { - renderEdit = false; - renderChoice(-5, this._numberChoice, "(number)"); - } - if (this._datetimeChoice !== null) { - renderEdit = false; - renderChoice(-4, this._datetimeChoice, "(date)"); - } - if (this._booleanChoice !== null) { - renderEdit = false; - renderChoice(-3, this._booleanChoice, "(boolean)"); - } if (this._blankChoice !== null) { - renderEdit = false; renderChoice(-1, this._blankChoice, "(blank)"); } if (this._errorChoice !== null) { - renderEdit = false; renderChoice(-2, this._errorChoice, "(error)"); } @@ -447,12 +406,6 @@ ListFacet.prototype._update = function(resetScroll) { return self._blankChoice; } else if (index === -2) { return self._errorChoice; - } else if (index === -3) { - return self._booleanChoice; - } else if (index === -4) { - return self._datetimeChoice; - } else if (index === -5) { - return self._numberChoice; } else { return choices[index]; } @@ -589,12 +542,6 @@ ListFacet.prototype._editChoice = function(choice, choiceDiv) { originalContent = "(blank)"; } else if (choice === this._errorChoice) { originalContent = "(error)"; - } else if (choice === this._booleanChoice) { - originalContent = "(boolean)"; - } else if (choice === this._datetimeChoice) { - originalContent = "(date)"; - } else if (choice === this._numberChoice) { - originalContent = "(number)"; } else { originalContent = choice.v.v; } @@ -670,15 +617,6 @@ ListFacet.prototype._editChoice = function(choice, choiceDiv) { ListFacet.prototype._select = function(choice, only) { if (only) { this._selection = []; - if (this._numberChoice !== null) { - this._numberChoice.s = false; - } - if (this._datetimeChoice !== null) { - this._datetimeChoice.s = false; - } - if (this._booleanChoice !== null) { - this._booleanChoice.s = false; - } if (this._blankChoice !== null) { this._blankChoice.s = false; } @@ -688,11 +626,7 @@ ListFacet.prototype._select = function(choice, only) { } choice.s = true; - if (choice !== this._errorChoice && - choice !== this._blankChoice && - choice !== this._numberChoice && - choice !== this._datetimeChoice && - choice !== this._booleanChoice ) { + if (choice !== this._errorChoice && choice !== this._blankChoice) { this._selection.push(choice); } @@ -700,7 +634,7 @@ ListFacet.prototype._select = function(choice, only) { }; ListFacet.prototype._deselect = function(choice) { - if (choice === this._errorChoice || choice === this._blankChoice || choice === this._numberChoice || choice === this._datetimeChoice || choice === this._booleanChoice) { + if (choice === this._errorChoice || choice === this._blankChoice) { choice.s = false; } else { for (var i = this._selection.length - 1; i >= 0; i--) { @@ -715,9 +649,6 @@ ListFacet.prototype._deselect = function(choice) { ListFacet.prototype._reset = function() { this._selection = []; - this._numberChoice = null; - this._datetimeChoice = null; - this._booleanChoice = null; this._blankChoice = null; this._errorChoice = null; this._config.invert = false; @@ -738,9 +669,6 @@ ListFacet.prototype._remove = function() { this._config = null; this._selection = null; - this._numberChoice = null; - this._datetimeChoice = null; - this._booleanChoice = null; this._blankChoice = null; this._errorChoice = null; this._data = null; diff --git a/main/webapp/modules/core/scripts/views/data-table/data-table-view.js b/main/webapp/modules/core/scripts/views/data-table/data-table-view.js index 182cb087b..27bbed432 100644 --- a/main/webapp/modules/core/scripts/views/data-table/data-table-view.js +++ b/main/webapp/modules/core/scripts/views/data-table/data-table-view.js @@ -626,7 +626,7 @@ DataTableView.prototype._createMenuForAllColumns = function(elmt) { { "name" : $.i18n('core-views/starred-rows'), "columnName" : "", - "expression" : "row.starred.toString()" + "expression" : "row.starred" }, { "scroll" : false @@ -643,7 +643,7 @@ DataTableView.prototype._createMenuForAllColumns = function(elmt) { { "name" : $.i18n('core-views/flagged-rows'), "columnName" : "", - "expression" : "row.flagged.toString()" + "expression" : "row.flagged" }, { "scroll" : false diff --git a/main/webapp/modules/core/scripts/views/data-table/menu-facets.js b/main/webapp/modules/core/scripts/views/data-table/menu-facets.js index ce3124db2..53d1ecc16 100644 --- a/main/webapp/modules/core/scripts/views/data-table/menu-facets.js +++ b/main/webapp/modules/core/scripts/views/data-table/menu-facets.js @@ -147,8 +147,8 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) { { "name": column.name, "columnName": column.name, - "expression": "(facetCount(value, 'value', '" + - column.name + "') > 1).toString()" + "expression": "facetCount(value, 'value', '" + + column.name + "') > 1" } ); } @@ -240,7 +240,7 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) { { "name": column.name, "columnName": column.name, - "expression": "isError(value).toString()" + "expression": "isError(value)" } ); } @@ -254,7 +254,7 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) { { "name": column.name, "columnName": column.name, - "expression": "isNull(value).toString()" + "expression": "isNull(value)" } ); } @@ -268,7 +268,7 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) { { "name": column.name, "columnName": column.name, - "expression": "isEmptyString(value).toString()" + "expression": "isEmptyString(value)" } ); } @@ -282,7 +282,7 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) { { "name": column.name, "columnName": column.name, - "expression": "isBlank(value).toString()" + "expression": "isBlank(value)" } ); } From 9cc481dcdc054c9fe9c6c1432a21ae12450de6c6 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sat, 23 Feb 2019 09:18:18 +0000 Subject: [PATCH 15/17] Make hover more stable on reconciliation candidates --- .../modules/core/scripts/views/data-table/cell-ui.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/main/webapp/modules/core/scripts/views/data-table/cell-ui.js b/main/webapp/modules/core/scripts/views/data-table/cell-ui.js index 026a55a72..91e4fd056 100644 --- a/main/webapp/modules/core/scripts/views/data-table/cell-ui.js +++ b/main/webapp/modules/core/scripts/views/data-table/cell-ui.js @@ -108,7 +108,7 @@ DataTableCellUI.prototype._render = function() { a.attr("href", encodeURI(service.view.url.replace("{{id}}", match.id))); } - self._previewOnHover(service, match, a, false); + self._previewOnHover(service, match, a, a, false); $(' ').appendTo(divContent); $('') @@ -153,7 +153,7 @@ DataTableCellUI.prototype._render = function() { a.attr("href", encodeURI(service.view.url.replace("{{id}}", candidate.id))); } - self._previewOnHover(service, candidate, liSpan, true); + self._previewOnHover(service, candidate, liSpan.parent(), liSpan, true); var score; if (candidate.score < 1) { @@ -475,7 +475,7 @@ DataTableCellUI.prototype._previewCandidateTopic = function(candidate, elmt, pre /** * Sets up a preview widget to appear when hovering the given DOM element. */ -DataTableCellUI.prototype._previewOnHover = function(service, candidate, element, showActions) { +DataTableCellUI.prototype._previewOnHover = function(service, candidate, hoverElement, coreElement, showActions) { var self = this; var preview = null; if ((service) && (service.preview)) { @@ -484,9 +484,9 @@ DataTableCellUI.prototype._previewOnHover = function(service, candidate, element if (preview) { var dismissCallback = null; - element.hover(function(evt) { + hoverElement.hover(function(evt) { if (!evt.metaKey && !evt.ctrlKey) { - dismissCallback = self._previewCandidateTopic(candidate, this, preview, showActions); + dismissCallback = self._previewCandidateTopic(candidate, coreElement, preview, showActions); evt.preventDefault(); } }, function(evt) { From ac07457306f772253ed7809229480be755aad5b4 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 25 Feb 2019 10:15:29 +0000 Subject: [PATCH 16/17] Fix suggest middle click in Wikidata schema --- .../module/scripts/dialogs/schema-alignment-dialog.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js b/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js index f6060957f..e5e730d67 100644 --- a/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js +++ b/extensions/wikidata/module/scripts/dialogs/schema-alignment-dialog.js @@ -803,11 +803,11 @@ SchemaAlignmentDialog._initField = function(inputContainer, mode, initialValue, suggestConfig.key = null; suggestConfig.query_param_name = "prefix"; if ('view' in this._reconService && 'url' in this._reconService.view && !('view_url' in endpoint)) { - suggestOptions.view_url = this._reconService.view.url; + suggestConfig.view_url = this._reconService.view.url; } - input.suggestP(suggestConfig).bind("fb-select", function(evt, data) { + input.suggest(suggestConfig).bind("fb-select", function(evt, data) { inputContainer.data("jsonValue", { type : "wbitemconstant", qid : data.id, @@ -824,9 +824,6 @@ SchemaAlignmentDialog._initField = function(inputContainer, mode, initialValue, var suggestConfig = $.extend({}, endpoint); suggestConfig.key = null; suggestConfig.query_param_name = "prefix"; - if ('view' in this._reconService && 'url' in this._reconService.view && !('view_url' in endpoint)) { - suggestOptions.view_url = this._reconService.view.url; - } input.suggestP(suggestConfig).bind("fb-select", function(evt, data) { inputContainer.data("jsonValue", { From 5dcd4a2f386eec256b7494f60c7878c7b755f241 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Wed, 27 Feb 2019 10:32:57 +0000 Subject: [PATCH 17/17] Add cell-ui.previewMatchCells=false preference to disable hover --- .../core/scripts/views/data-table/cell-ui.js | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/main/webapp/modules/core/scripts/views/data-table/cell-ui.js b/main/webapp/modules/core/scripts/views/data-table/cell-ui.js index 91e4fd056..33a96ae0f 100644 --- a/main/webapp/modules/core/scripts/views/data-table/cell-ui.js +++ b/main/webapp/modules/core/scripts/views/data-table/cell-ui.js @@ -41,6 +41,23 @@ function DataTableCellUI(dataTableView, cell, rowIndex, cellIndex, td) { this._render(); } +DataTableCellUI.previewMatchedCells = true; + +(function() { + + $.ajax({ + url: "command/core/get-preference?" + $.param({ + name: "cell-ui.previewMatchedCells" + }), + success: function(data) { + if (data.value && data.value == "false") { + DataTableCellUI.previewMatchedCells = false; + } + }, + dataType: "json", + }); +})(); + DataTableCellUI.prototype._render = function() { var self = this; var cell = this._cell; @@ -108,7 +125,9 @@ DataTableCellUI.prototype._render = function() { a.attr("href", encodeURI(service.view.url.replace("{{id}}", match.id))); } - self._previewOnHover(service, match, a, a, false); + if (DataTableCellUI.previewMatchedCells) { + self._previewOnHover(service, match, a, a, false); + } $(' ').appendTo(divContent); $('')