mirror of
https://github.com/zotero/zotero.git
synced 2026-08-28 05:25:31 +00:00
Make Original Date a date field
Update the global schema to 45, resolve a field's date type through its base-field mapping in ItemFields.isDate() (to cover priorityDate), and convert stored values of date-type fields to multipart dates on schema upgrade.
This commit is contained in:
parent
04796dff22
commit
73f4273e2d
6 changed files with 139 additions and 11 deletions
|
|
@ -1999,8 +1999,7 @@
|
|||
let tooltipText;
|
||||
if (fieldID && !this._extraItems.length) {
|
||||
// Display the SQL date as a tooltip for date fields
|
||||
// TEMP - filingDate
|
||||
if (Zotero.ItemFields.isFieldOfBase(fieldID, 'date') || fieldName == 'filingDate') {
|
||||
if (Zotero.ItemFields.isDate(fieldID)) {
|
||||
tooltipText = Zotero.Date.multipartToSQL(this.item.getField(fieldName, true));
|
||||
}
|
||||
}
|
||||
|
|
@ -2549,9 +2548,9 @@
|
|||
break;
|
||||
|
||||
default:
|
||||
// TODO: generalize to all date rows/fields
|
||||
if (Zotero.ItemFields.isFieldOfBase(fieldName, 'date')) {
|
||||
// Parse 'yesterday'/'today'/'tomorrow'
|
||||
// Parse 'yesterday'/'today'/'tomorrow' for date fields -- not applied to Original Date
|
||||
if (Zotero.ItemFields.isDate(fieldName)
|
||||
&& !Zotero.ItemFields.isFieldOfBase(fieldName, 'originalDate')) {
|
||||
value = Zotero.Date.parseDescriptiveString(value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,11 +190,16 @@ Zotero.ItemFields = new function () {
|
|||
this.isDate = function (field) {
|
||||
var fieldID = this.getID(field);
|
||||
var fieldName = this.getName(field);
|
||||
if (Zotero.ItemFields.isFieldOfBase(fieldID, 'date')) {
|
||||
return true;
|
||||
}
|
||||
if (Zotero.Schema.globalSchemaMeta.fields[fieldName]) {
|
||||
return Zotero.Schema.globalSchemaMeta.fields[fieldName].type == 'date'
|
||||
return Zotero.Schema.globalSchemaMeta.fields[fieldName].type == 'date';
|
||||
}
|
||||
// A type-specific field has the type of the base field it maps to
|
||||
for (let baseFieldID in _typeFieldIDsByBase) {
|
||||
if (_typeFieldIDsByBase[baseFieldID].includes(fieldID)) {
|
||||
let baseName = this.getName(parseInt(baseFieldID));
|
||||
let baseMeta = Zotero.Schema.globalSchemaMeta.fields[baseName];
|
||||
return !!baseMeta && baseMeta.type == 'date';
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -587,7 +587,40 @@ Zotero.Schema = new function () {
|
|||
+ baseFieldMappingsValueSets.join(", "));
|
||||
await Zotero.DB.queryAsync("INSERT INTO itemTypeCreatorTypes VALUES "
|
||||
+ itemTypeCreatorTypesValueSets.join(", "));
|
||||
|
||||
|
||||
// Convert stored values of date-type fields to multipart dates, for
|
||||
// values saved while a field was a text field
|
||||
var dateFieldIDs = new Set();
|
||||
for (let [fieldName, meta] of Object.entries(data.meta?.fields || {})) {
|
||||
if (meta.type != 'date') {
|
||||
continue;
|
||||
}
|
||||
let fieldID = postFieldIDsByName.get(fieldName);
|
||||
if (!fieldID) {
|
||||
continue;
|
||||
}
|
||||
dateFieldIDs.add(fieldID);
|
||||
// Type-specific fields mapped to a date-type base field
|
||||
let mappedIDs = await Zotero.DB.columnQueryAsync(
|
||||
"SELECT DISTINCT fieldID FROM baseFieldMappings WHERE baseFieldID=?",
|
||||
fieldID
|
||||
);
|
||||
for (let id of mappedIDs) {
|
||||
dateFieldIDs.add(id);
|
||||
}
|
||||
}
|
||||
if (dateFieldIDs.size) {
|
||||
// strToMultipart() needs the month strings, which aren't loaded
|
||||
// yet this early in startup
|
||||
Zotero.Date.init();
|
||||
await _updateItemDataValues(
|
||||
[...dateFieldIDs],
|
||||
value => (Zotero.Date.isMultipart(value)
|
||||
? false
|
||||
: Zotero.Date.strToMultipart(value))
|
||||
);
|
||||
}
|
||||
|
||||
// Store data in DB as compressed binary string. This lets us use a schema that matches the
|
||||
// DB tables even if the user downgrades to a version with an earlier bundled schema file.
|
||||
var pako = require('pako');
|
||||
|
|
@ -630,6 +663,51 @@ Zotero.Schema = new function () {
|
|||
await Zotero.DB.queryAsync("PRAGMA foreign_keys=ON");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rewrite stored itemData values through a transform, reusing or creating
|
||||
* rows in itemDataValues
|
||||
*
|
||||
* @param {Number[]} fieldIDs - Fields whose values to rewrite
|
||||
* @param {Function} transform - Given a value, returns the new value, or
|
||||
* false to leave the value as it is
|
||||
*/
|
||||
async function _updateItemDataValues(fieldIDs, transform) {
|
||||
if (!fieldIDs.length) {
|
||||
return;
|
||||
}
|
||||
var rows = await Zotero.DB.queryAsync(
|
||||
"SELECT itemID, fieldID, value FROM itemData "
|
||||
+ "JOIN itemDataValues USING (valueID) "
|
||||
+ "WHERE fieldID IN (" + fieldIDs.join(", ") + ")"
|
||||
);
|
||||
for (let row of rows) {
|
||||
let value = transform(row.value);
|
||||
if (value === false || value === row.value) {
|
||||
continue;
|
||||
}
|
||||
let valueID = await Zotero.DB.valueQueryAsync(
|
||||
"SELECT valueID FROM itemDataValues WHERE value=?", value
|
||||
);
|
||||
if (!valueID) {
|
||||
valueID = Zotero.ID.get('itemDataValues');
|
||||
await Zotero.DB.queryAsync(
|
||||
"INSERT INTO itemDataValues (valueID, value, valueNormalized) "
|
||||
+ "VALUES (?, ?, ?)",
|
||||
[
|
||||
valueID,
|
||||
value,
|
||||
Zotero.Utilities.Internal.normalizeForSearchStorage(value)
|
||||
]
|
||||
);
|
||||
}
|
||||
await Zotero.DB.queryAsync(
|
||||
"UPDATE itemData SET valueID=? WHERE itemID=? AND fieldID=?",
|
||||
[valueID, row.itemID, row.fieldID]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 70c3aa98627413d6a30dca955886eafbde085ce9
|
||||
Subproject commit b86c79b56479cadac3288e1f122cf34ef04e8809
|
||||
|
|
@ -45,6 +45,16 @@ describe("Zotero.ItemFields", function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe("#isDate()", function () {
|
||||
it("should treat base and mapped date-type fields as dates", function () {
|
||||
assert.isTrue(Zotero.ItemFields.isDate('date'));
|
||||
assert.isTrue(Zotero.ItemFields.isDate('dateDecided'));
|
||||
assert.isTrue(Zotero.ItemFields.isDate('originalDate'));
|
||||
assert.isTrue(Zotero.ItemFields.isDate('priorityDate'));
|
||||
assert.isFalse(Zotero.ItemFields.isDate('title'));
|
||||
});
|
||||
});
|
||||
|
||||
describe("#getDirection()", function () {
|
||||
it("should follow app locale for primary field", function () {
|
||||
assert.equal(Zotero.ItemFields.getDirection('book', 'dateAdded', ''), Zotero.dir)
|
||||
|
|
|
|||
|
|
@ -94,6 +94,42 @@ describe("Zotero.Schema", function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe("date-type field conversion", function () {
|
||||
it("should convert stored text values of date-type fields to multipart dates", async function () {
|
||||
var item = await createDataObject('item', { itemType: 'patent' });
|
||||
// A value stored while the field was a text field
|
||||
var fieldID = Zotero.ItemFields.getID('priorityDate');
|
||||
var valueID = Zotero.ID.get('itemDataValues');
|
||||
await Zotero.DB.queryAsync(
|
||||
"INSERT INTO itemDataValues (valueID, value, valueNormalized) VALUES (?, ?, ?)",
|
||||
[valueID, '1969-04-20', null]
|
||||
);
|
||||
await Zotero.DB.queryAsync(
|
||||
"INSERT INTO itemData VALUES (?, ?, ?)",
|
||||
[item.id, fieldID, valueID]
|
||||
);
|
||||
|
||||
schema.version++;
|
||||
await Zotero.Schema._updateGlobalSchemaForTest(schema);
|
||||
await item.reload(['itemData'], true);
|
||||
|
||||
var stored = await Zotero.DB.valueQueryAsync(
|
||||
"SELECT value FROM itemData JOIN itemDataValues USING (valueID) "
|
||||
+ "WHERE itemID=? AND fieldID=?",
|
||||
[item.id, fieldID]
|
||||
);
|
||||
assert.isTrue(Zotero.Date.isMultipart(stored));
|
||||
assert.equal(item.getField('priorityDate'), '1969-04-20');
|
||||
|
||||
// The converted value matches a date search on the base field
|
||||
var s = new Zotero.Search();
|
||||
s.libraryID = item.libraryID;
|
||||
s.addCondition('originalDate', 'isBefore', '1970');
|
||||
var matches = await s.search();
|
||||
assert.include(matches, item.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#migrateExtraFields()", function () {
|
||||
async function migrate(options) {
|
||||
schema.version++;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue