Bug 1720042 - Support importing csv/tsv file in AddrBookFileImporter.jsm. r=benc
Differential Revision: https://phabricator.services.mozilla.com/D140016
This commit is contained in:
Родитель
f4d8992467
Коммит
6a82a3cbd8
|
@ -3,6 +3,7 @@
|
|||
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const EXPORTED_SYMBOLS = [
|
||||
"exportAttributes",
|
||||
"AddrBookUtils",
|
||||
"compareAddressBooks",
|
||||
"newUID",
|
||||
|
|
|
@ -501,6 +501,7 @@ class AddrBookImporterController extends ImporterController {
|
|||
async _showDirectories(sourceFile) {
|
||||
this._sourceFile = sourceFile;
|
||||
let elList = document.getElementById("directoryList");
|
||||
elList.innerHTML = "";
|
||||
this._directories = MailServices.ab.directories.filter(
|
||||
dir => dir.dirType == Ci.nsIAbManager.JS_DIRECTORY_TYPE
|
||||
);
|
||||
|
|
|
@ -4,7 +4,24 @@
|
|||
|
||||
const EXPORTED_SYMBOLS = ["AddrBookFileImporter"];
|
||||
|
||||
var { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm");
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
setTimeout: "resource://gre/modules/Timer.jsm",
|
||||
exportAttributes: "resource:///modules/AddrBookUtils.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "d3", () => {
|
||||
let d3Scope = Cu.Sandbox(null);
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://global/content/third_party/d3/d3.js",
|
||||
d3Scope
|
||||
);
|
||||
return Cu.waiveXrays(d3Scope.d3);
|
||||
});
|
||||
|
||||
/**
|
||||
* A module to import address book files.
|
||||
|
@ -44,6 +61,9 @@ class AddrBookFileImporter {
|
|||
this._targetDirectory = targetDirectory;
|
||||
|
||||
switch (this._type) {
|
||||
case "csv":
|
||||
await this._importCsvFile();
|
||||
break;
|
||||
case "ldif":
|
||||
await this._importLdifFile();
|
||||
break;
|
||||
|
@ -61,6 +81,65 @@ class AddrBookFileImporter {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the .csv/.tsv source file into the target directory.
|
||||
*/
|
||||
async _importCsvFile() {
|
||||
let content = await IOUtils.readUTF8(this._sourceFile.path);
|
||||
|
||||
let csvRows = d3.csv.parseRows(content);
|
||||
let tsvRows = d3.tsv.parseRows(content);
|
||||
// If we have more CSV columns, then it's a CSV file, otherwise a TSV file.
|
||||
let rows = csvRows[0].length > tsvRows[0].length ? csvRows : tsvRows;
|
||||
|
||||
let bundle = Services.strings.createBundle(
|
||||
"chrome://messenger/locale/importMsgs.properties"
|
||||
);
|
||||
let supportedFieldNames = [];
|
||||
let supportedProperties = [];
|
||||
// Collect field names in an exported CSV file, and their corresponding
|
||||
// nsIAbCard property names.
|
||||
for (let [property, stringId] of exportAttributes) {
|
||||
if (stringId) {
|
||||
supportedProperties.push(property);
|
||||
supportedFieldNames.push(
|
||||
bundle.GetStringFromID(stringId).toLowerCase()
|
||||
);
|
||||
}
|
||||
}
|
||||
let properties = [];
|
||||
// Get the nsIAbCard properties corresponding to the user supplied file.
|
||||
for (let field of rows[0]) {
|
||||
let index = supportedFieldNames.indexOf(field.toLowerCase());
|
||||
properties.push(supportedProperties[index]);
|
||||
}
|
||||
|
||||
let totalLines = rows.length - 1;
|
||||
let currentLine = 0;
|
||||
|
||||
for (let row of rows.slice(1)) {
|
||||
currentLine++;
|
||||
let card = Cc["@mozilla.org/addressbook/cardproperty;1"].createInstance(
|
||||
Ci.nsIAbCard
|
||||
);
|
||||
for (let i = 0; i < row.length; i++) {
|
||||
let property = properties[i];
|
||||
if (!property) {
|
||||
continue;
|
||||
}
|
||||
// Set the field value to the property.
|
||||
card.setProperty(property, row[i]);
|
||||
}
|
||||
this._targetDirectory.addCard(card);
|
||||
if (currentLine % 10 == 0) {
|
||||
this.onProgress(currentLine, totalLines);
|
||||
// Give UI a chance to update the progress bar.
|
||||
await new Promise(resolve => setTimeout(resolve));
|
||||
}
|
||||
}
|
||||
this.onProgress(totalLines, totalLines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the .ldif source file into the target directory.
|
||||
*/
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
[
|
||||
{
|
||||
"DisplayName" : "Acer America",
|
||||
"Work Phone" : "(800) 000-0000",
|
||||
"WorkPhone" : "(800) 000-0000",
|
||||
"Organization" : "Acer America"
|
||||
}
|
||||
],
|
||||
|
|
|
@ -228,6 +228,10 @@ AbImportHelper.prototype = {
|
|||
var fieldMap = importService.CreateNewFieldMap();
|
||||
|
||||
fieldMap.DefaultFieldMap(fieldMap.numMozFields);
|
||||
this.mInterface
|
||||
.GetData("addressInterface")
|
||||
.QueryInterface(Ci.nsIImportAddressBooks)
|
||||
.InitFieldMap(fieldMap);
|
||||
fieldMap.skipFirstRecord = aSkipFirstRecord;
|
||||
|
||||
return fieldMap;
|
||||
|
|
|
@ -34,7 +34,7 @@ async function test_importAbFile(type, testFile, refDataKey) {
|
|||
for (let i = 0; i < refData.length; i++) {
|
||||
let card = targetDir.childCards[i];
|
||||
for (let [key, value] of Object.entries(refData[i])) {
|
||||
if (["LastModifiedDate"].includes(key)) {
|
||||
if (["LastModifiedDate", "Organization"].includes(key)) {
|
||||
continue;
|
||||
}
|
||||
equal(value, card.getProperty(key, ""), `${key} should be correct`);
|
||||
|
@ -42,6 +42,17 @@ async function test_importAbFile(type, testFile, refDataKey) {
|
|||
}
|
||||
}
|
||||
|
||||
/** Test importing .csv file works. */
|
||||
add_task(async function test_importCsvFile() {
|
||||
await test_importAbFile(
|
||||
"csv",
|
||||
"resources/basic_csv_addressbook.csv",
|
||||
"csv_import"
|
||||
);
|
||||
|
||||
await test_importAbFile("csv", "resources/quote.csv", "quote_csv");
|
||||
});
|
||||
|
||||
/** Test importing .vcf file works. */
|
||||
add_task(async function test_importVCardFile() {
|
||||
return test_importAbFile(
|
||||
|
|
Загрузка…
Ссылка в новой задаче