Merge pull request #1795 from OpenRefine/issue1776

Add import and export for Wikidata schema
This commit is contained in:
Antonin Delpeuch 2018-11-07 10:31:51 +00:00 committed by GitHub
commit 9b111952fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 200 additions and 11 deletions

View File

@ -36,8 +36,10 @@ function init() {
*/ */
var ExporterRegistry = Packages.com.google.refine.exporters.ExporterRegistry; var ExporterRegistry = Packages.com.google.refine.exporters.ExporterRegistry;
var QSExporter = Packages.org.openrefine.wikidata.exporters.QuickStatementsExporter; var QSExporter = Packages.org.openrefine.wikidata.exporters.QuickStatementsExporter;
var SchemaExporter = Packages.org.openrefine.wikidata.exporters.SchemaExporter;
ExporterRegistry.registerExporter("quickstatements", new QSExporter()); ExporterRegistry.registerExporter("quickstatements", new QSExporter());
ExporterRegistry.registerExporter("wikibase-schema", new SchemaExporter());
/* /*
* Commands * Commands
@ -62,6 +64,7 @@ function init() {
"scripts/dialogs/schema-alignment-dialog.js", "scripts/dialogs/schema-alignment-dialog.js",
"scripts/dialogs/manage-account-dialog.js", "scripts/dialogs/manage-account-dialog.js",
"scripts/dialogs/perform-edits-dialog.js", "scripts/dialogs/perform-edits-dialog.js",
"scripts/dialogs/import-schema-dialog.js",
"scripts/jquery.uls.data.js", "scripts/jquery.uls.data.js",
]); ]);
@ -71,6 +74,7 @@ function init() {
[ [
"styles/dialogs/schema-alignment-dialog.css", "styles/dialogs/schema-alignment-dialog.css",
"styles/dialogs/manage-account-dialog.less", "styles/dialogs/manage-account-dialog.less",
"styles/dialogs/import-schema-dialog.less",
"styles/dialogs/perform-edits.less", "styles/dialogs/perform-edits.less",
]); ]);

View File

@ -2,9 +2,11 @@
"wikidata-extension": { "wikidata-extension": {
"menu-label": "Wikidata", "menu-label": "Wikidata",
"edit-wikidata-schema": "Edit Wikidata schema", "edit-wikidata-schema": "Edit Wikidata schema",
"import-wikidata-schema": "Import schema",
"manage-wikidata-account": "Manage Wikidata account", "manage-wikidata-account": "Manage Wikidata account",
"perform-edits-on-wikidata": "Upload edits to Wikidata", "perform-edits-on-wikidata": "Upload edits to Wikidata",
"export-to-qs": "Export to QuickStatements", "export-to-qs": "Export to QuickStatements",
"export-schema": "Export schema",
"quickstatements-export-name": "QuickStatements" "quickstatements-export-name": "QuickStatements"
}, },
"wikidata-schema": { "wikidata-schema": {
@ -79,6 +81,13 @@
"cancel": "Cancel", "cancel": "Cancel",
"analyzing-edits": "Analyzing your edits..." "analyzing-edits": "Analyzing your edits..."
}, },
"import-wikibase-schema": {
"dialog-header": "Import Wikidata schema",
"file-label": "From JSON file: ",
"schema-label": "Or from JSON text:",
"invalid-schema": "Invalid Wikibase schema.",
"import": "Import"
},
"warnings-messages": { "warnings-messages": {
"new-item-created": { "new-item-created": {
"title": "This edit batch will create new Wikidata items.", "title": "This edit batch will create new Wikidata items.",

View File

@ -0,0 +1,13 @@
<div class="dialog-frame" style="width: 800px;">
<div class="dialog-header" bind="dialogHeader"></div>
<div class="dialog-body" bind="dialogBody">
<label for="schema-file" bind="fileLabel"></label><input type="file" name="schema-file" bind="fileInput" /><br />
<label for="schema" bind="schemaLabel"></label><br />
<textarea name="schema" class="wikibase-schema-textarea" bind="schemaTextarea"></textarea><br />
<div class="wikibase-invalid-schema" bind="invalidSchema"></div>
<div class="wikibase-login-buttons">
<button class="button cancel-button" bind="cancelButton"></button>
<button class="button button-primary" bind="importButton"></button>
</div>
</div>
</div>

View File

@ -0,0 +1,64 @@
var ImportSchemaDialog = {};
ImportSchemaDialog.launch = function() {
var self = this;
var frame = $(DOM.loadHTML("wikidata", "scripts/dialogs/import-schema-dialog.html"));
var elmts = this._elmts = DOM.bind(frame);
this._elmts.dialogHeader.text($.i18n._('import-wikibase-schema')["dialog-header"]);
this._elmts.fileLabel.html($.i18n._('import-wikibase-schema')["file-label"]);
this._elmts.schemaLabel.text($.i18n._('import-wikibase-schema')["schema-label"]);
this._elmts.cancelButton.text($.i18n._('core-project')["cancel"]);
this._elmts.importButton.text($.i18n._('import-wikibase-schema')["import"]);
this._level = DialogSystem.showDialog(frame);
var dismiss = function() {
DialogSystem.dismissUntil(self._level - 1);
};
frame.find('.cancel-button').click(function() {
dismiss();
});
elmts.fileInput.on("change", function(evt) {
var file = evt.target.files[0];
var freader = new FileReader();
freader.onload = function(evt) {
elmts.schemaTextarea.val(evt.target.result);
elmts.schemaTextarea.hide();
elmts.schemaLabel.hide();
}
freader.readAsText(file);
});
elmts.importButton.click(function() {
var schema = null;
try {
schema = JSON.parse(elmts.schemaTextarea.val());
} catch(e) {
elmts.invalidSchema.text($.i18n._('import-wikibase-schema')["invalid-schema"]);
return;
}
Refine.postProcess(
"wikidata",
"save-wikibase-schema",
{},
{ schema: JSON.stringify(schema) },
{},
{
onDone: function() {
theProject.overlayModels.wikibaseSchema = schema;
SchemaAlignmentDialog._discardChanges();
dismiss();
},
onError: function(e) {
elmts.invalidSchema.text($.i18n._('import-wikibase-schema')["invalid-schema"]);
},
}
);
});
};

View File

@ -19,19 +19,37 @@ $.i18n.setDictionary(dictionary);
ExporterManager.MenuItems.push({}); ExporterManager.MenuItems.push({});
ExporterManager.MenuItems.push( ExporterManager.MenuItems.push(
{ {
"id" : "exportQuickStatements", id:"performWikibaseEdits",
"label": $.i18n._('wikidata-extension')["quickstatements-export-name"], label: $.i18n._('wikidata-extension')["perform-edits-on-wikidata"],
"click": function() { WikibaseSchemaExporterMenuBar.checkSchemaAndExport(); } click: function() { PerformEditsDialog.checkAndLaunch(); }
});
ExporterManager.MenuItems.push(
{
id:"exportQuickStatements",
label: $.i18n._('wikidata-extension')["export-to-qs"],
click: function() { WikibaseExporterMenuBar.checkSchemaAndExport("quickstatements"); }
});
ExporterManager.MenuItems.push(
{
id:"exportWikibaseSchema",
label: $.i18n._('wikidata-extension')["export-schema"],
click: function() { WikibaseExporterMenuBar.checkSchemaAndExport("wikibase-schema"); }
} }
); );
WikibaseExporterMenuBar = {}; WikibaseExporterMenuBar = {};
WikibaseExporterMenuBar.exportTo = function(format) { WikibaseExporterMenuBar.exportTo = function(format) {
var targetUrl = null;
if (format ==="quickstatements") {
targetUrl = "statements.txt";
} else {
targetUrl = "schema.json";
}
var form = document.createElement("form"); var form = document.createElement("form");
$(form).css("display", "none") $(form).css("display", "none")
.attr("method", "post") .attr("method", "post")
.attr("action", "command/core/export-rows/statements.txt") .attr("action", "command/core/export-rows/"+targetUrl)
.attr("target", "gridworks-export"); .attr("target", "gridworks-export");
$('<input />') $('<input />')
.attr("name", "engine") .attr("name", "engine")
@ -54,9 +72,9 @@ WikibaseExporterMenuBar.exportTo = function(format) {
document.body.removeChild(form); document.body.removeChild(form);
}; };
WikibaseExporterMenuBar.checkSchemaAndExport = function() { WikibaseExporterMenuBar.checkSchemaAndExport = function(format) {
var onSaved = function(callback) { var onSaved = function(callback) {
WikibaseExporterMenuBar.exportTo("quickstatements"); WikibaseExporterMenuBar.exportTo(format);
}; };
if (!SchemaAlignmentDialog.isSetUp()) { if (!SchemaAlignmentDialog.isSetUp()) {
SchemaAlignmentDialog.launch(null); SchemaAlignmentDialog.launch(null);
@ -85,6 +103,18 @@ $(function(){
label: $.i18n._('wikidata-extension')["manage-wikidata-account"], label: $.i18n._('wikidata-extension')["manage-wikidata-account"],
click: function() { ManageAccountDialog.checkAndLaunch(); } click: function() { ManageAccountDialog.checkAndLaunch(); }
}, },
{},
{
id: "wikidata/import-schema",
label: $.i18n._('wikidata-extension')["import-wikidata-schema"],
click: function() { ImportSchemaDialog.launch(); }
},
{
id:"wikidata/export-schema",
label: $.i18n._('wikidata-extension')["export-schema"],
click: function() { WikibaseExporterMenuBar.checkSchemaAndExport("wikibase-schema"); }
},
{},
{ {
id:"wikidata/perform-edits", id:"wikidata/perform-edits",
label: $.i18n._('wikidata-extension')["perform-edits-on-wikidata"], label: $.i18n._('wikidata-extension')["perform-edits-on-wikidata"],
@ -93,7 +123,7 @@ $(function(){
{ {
id:"wikidata/export-qs", id:"wikidata/export-qs",
label: $.i18n._('wikidata-extension')["export-to-qs"], label: $.i18n._('wikidata-extension')["export-to-qs"],
click: function() { WikibaseExporterMenuBar.checkSchemaAndExport(); } click: function() { WikibaseExporterMenuBar.checkSchemaAndExport("quickstatements"); }
}, },
] ]

View File

@ -0,0 +1,10 @@
@import-less url("../theme.less");
.wikibase-invalid-schema {
color: red;
}
.wikibase-schema-textarea {
width: 100%;
height: 100px;

View File

@ -24,6 +24,8 @@
package org.openrefine.wikidata.commands; package org.openrefine.wikidata.commands;
import static org.openrefine.wikidata.commands.CommandUtilities.respondError;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.List; import java.util.List;
@ -36,7 +38,6 @@ import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter; import org.json.JSONWriter;
import org.openrefine.wikidata.qa.EditInspector; import org.openrefine.wikidata.qa.EditInspector;
import org.openrefine.wikidata.qa.QAWarning; import org.openrefine.wikidata.qa.QAWarning;
@ -45,10 +46,7 @@ import org.openrefine.wikidata.schema.WikibaseSchema;
import org.openrefine.wikidata.updates.ItemUpdate; import org.openrefine.wikidata.updates.ItemUpdate;
import org.openrefine.wikidata.updates.scheduler.WikibaseAPIUpdateScheduler; import org.openrefine.wikidata.updates.scheduler.WikibaseAPIUpdateScheduler;
import static org.openrefine.wikidata.commands.CommandUtilities.respondError;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
import com.google.refine.model.Project; import com.google.refine.model.Project;

View File

@ -0,0 +1,31 @@
package org.openrefine.wikidata.exporters;
import java.io.IOException;
import java.io.Writer;
import java.util.Properties;
import org.json.JSONWriter;
import org.openrefine.wikidata.schema.WikibaseSchema;
import com.google.refine.browsing.Engine;
import com.google.refine.exporters.WriterExporter;
import com.google.refine.model.Project;
public class SchemaExporter implements WriterExporter {
@Override
public String getContentType() {
return "application/octet-stream";
}
@Override
public void export(Project project, Properties options, Engine engine, Writer writer) throws IOException {
WikibaseSchema schema = (WikibaseSchema) project.overlayModels.get("wikibaseSchema");
if (schema == null) {
schema = new WikibaseSchema();
}
JSONWriter jsonWriter = new JSONWriter(writer);
schema.write(jsonWriter, new Properties());
}
}

View File

@ -0,0 +1,30 @@
package org.openrefine.wikidata.exporters;
import static org.openrefine.wikidata.testing.JacksonSerializationTest.assertJsonEquals;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Properties;
import org.testng.annotations.Test;
import com.google.refine.browsing.Engine;
import com.google.refine.model.Project;
import com.google.refine.tests.RefineTest;
public class SchemaExporterTest extends RefineTest {
private SchemaExporter exporter = new SchemaExporter();
@Test
public void testNoSchema()
throws IOException {
Project project = this.createCSVProject("a,b\nc,d");
Engine engine = new Engine(project);
StringWriter writer = new StringWriter();
Properties properties = new Properties();
exporter.export(project, properties, engine, writer);
assertJsonEquals("{\"itemDocuments\":[]}", writer.toString());
}
}