Schema and Item Type Manager updates to handle item type templates
Note that there's no code for user types and fields yet -- just the schema (actually there's a tiny bit of code in the item type manager, since we'll probably use some of the same methods for managing user types, but not much) Templates for primary item types are currently only used by the item type manager to make creating new types easier and to prevent the removal of fields from an item type that are associated with its template item type -- the fields are all still recorded in itemTypeFields, since they might have different orders or default visibility settings from their templates
This commit is contained in:
parent
287e082805
commit
fe319f033b
|
@ -1,3 +1,7 @@
|
|||
listitem[isTemplateField=true] {
|
||||
color:brown;
|
||||
}
|
||||
|
||||
listitem[isHidden=true] {
|
||||
color:lightblue;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
var Scholar_ItemTypeManager = new function(){
|
||||
this.init = init;
|
||||
this.handleTypeSelect = handleTypeSelect;
|
||||
this.buildTypeContextMenu = buildTypeContextMenu;
|
||||
this.setTemplate = setTemplate;
|
||||
this.addFieldToType = addFieldToType;
|
||||
this.removeFieldFromType = removeFieldFromType;
|
||||
this.handleShowHide = handleShowHide;
|
||||
|
@ -13,12 +15,14 @@ var Scholar_ItemTypeManager = new function(){
|
|||
this.createSQLDump = createSQLDump;
|
||||
|
||||
var _typesList;
|
||||
var _typeTemplates;
|
||||
var _typeFieldsList;
|
||||
var _fieldsList;
|
||||
|
||||
|
||||
function init(){
|
||||
// Populate the listbox with item types
|
||||
_typesList = document.getElementById('item-type-list');
|
||||
_typeTemplates = document.getElementById('scholar-type-template-menu');
|
||||
_typeFieldsList = document.getElementById('item-type-fields-list');
|
||||
_fieldsList = document.getElementById('fields-list');
|
||||
|
||||
|
@ -44,6 +48,19 @@ var Scholar_ItemTypeManager = new function(){
|
|||
}
|
||||
}
|
||||
|
||||
// Update the context menu
|
||||
while (_typeTemplates.childNodes[2]){
|
||||
_typeTemplates.removeChild(_typeTemplates.childNodes[2]);
|
||||
}
|
||||
for (var i in types){
|
||||
var item = document.createElement('menuitem');
|
||||
item.setAttribute('label', types[i]['name']);
|
||||
item.setAttribute('value', types[i]['id']);
|
||||
item.setAttribute('type', 'checkbox');
|
||||
item.setAttribute('oncommand', "Scholar_ItemTypeManager.setTemplate(document.popupNode.value, this.value)");
|
||||
_typeTemplates.appendChild(item);
|
||||
}
|
||||
|
||||
if (_typesList.selectedIndex==-1){
|
||||
_typesList.selectedIndex=0;
|
||||
}
|
||||
|
@ -64,6 +81,87 @@ var Scholar_ItemTypeManager = new function(){
|
|||
_populateFieldsList(id);
|
||||
}
|
||||
|
||||
function buildTypeContextMenu(){
|
||||
var id = _typesList.selectedItem.value;
|
||||
var template = _getItemTypeTemplate(id);
|
||||
|
||||
if (!template){
|
||||
_typeTemplates.childNodes[0].setAttribute('checked', true);
|
||||
}
|
||||
else {
|
||||
_typeTemplates.childNodes[0].setAttribute('checked', false);
|
||||
}
|
||||
|
||||
for (var i=2, len=_typeTemplates.childNodes.length; i<len; i++){
|
||||
var item = _typeTemplates.childNodes[i];
|
||||
|
||||
if (item.getAttribute('value')==id){
|
||||
item.setAttribute('hidden', true);
|
||||
}
|
||||
else {
|
||||
item.setAttribute('hidden', false);
|
||||
}
|
||||
|
||||
if (item.getAttribute('value')==template){
|
||||
item.setAttribute('checked', true);
|
||||
}
|
||||
else {
|
||||
item.setAttribute('checked', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setTemplate(itemTypeID, templateItemTypeID){
|
||||
var currentTemplateItemTypeID = _getItemTypeTemplate(itemTypeID);
|
||||
|
||||
if (itemTypeID<1000){
|
||||
var typesTable = 'itemTypes';
|
||||
}
|
||||
else {
|
||||
var typesTable = 'userItemTypes';
|
||||
}
|
||||
|
||||
// If currently from a template, clear the template fields
|
||||
if (currentTemplateItemTypeID){
|
||||
var sql = "SELECT fieldID FROM itemTypeFields WHERE itemTypeID=?";
|
||||
var fields = Scholar.DB.columnQuery(sql, currentTemplateItemTypeID);
|
||||
|
||||
for (var i in fields){
|
||||
_DBUnmapField(itemTypeID, fields[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (templateItemTypeID){
|
||||
// Add the new template fields
|
||||
var sql = "SELECT fieldID FROM itemTypeFields WHERE itemTypeID=? "
|
||||
+ "ORDER BY orderIndex";
|
||||
var fields = Scholar.DB.columnQuery(sql, templateItemTypeID);
|
||||
Scholar.debug('--------');
|
||||
Scholar.debug(fields);
|
||||
Scholar.debug('--------');
|
||||
for (var i in fields){
|
||||
_DBMapField(itemTypeID, fields[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
templateItemTypeID = null;
|
||||
}
|
||||
|
||||
var sql = "UPDATE " + typesTable + " SET templateItemTypeID=? WHERE "
|
||||
+ "itemTypeID=?";
|
||||
|
||||
return Scholar.DB.query(sql, [templateItemTypeID, itemTypeID]);
|
||||
}
|
||||
|
||||
|
||||
function _getItemTypeTemplate(itemTypeID){
|
||||
var table = itemTypeID>=1000 ? 'userItemTypes' : 'itemTypes';
|
||||
var sql = "SELECT templateItemTypeID FROM " + table
|
||||
sql += " WHERE itemTypeID=?";
|
||||
return Scholar.DB.valueQuery(sql, itemTypeID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a field to an item type
|
||||
|
@ -74,17 +172,7 @@ var Scholar_ItemTypeManager = new function(){
|
|||
Scholar.debug('Adding field ' + item.value + ' to item type '
|
||||
+ _getCurrentTypeID());
|
||||
|
||||
Scholar.DB.beginTransaction();
|
||||
|
||||
// Get the next available position
|
||||
var sql = "SELECT IFNULL(MAX(orderIndex)+1,1) FROM itemTypeFields "
|
||||
+ "WHERE itemTypeID=?";
|
||||
var nextIndex = Scholar.DB.valueQuery(sql, [_getCurrentTypeID()]);
|
||||
|
||||
var sql = "INSERT INTO itemTypeFields VALUES (?,?,?,?)";
|
||||
Scholar.DB.query(sql, [_getCurrentTypeID(), item.value, null, nextIndex]);
|
||||
|
||||
Scholar.DB.commitTransaction();
|
||||
_DBMapField(_getCurrentTypeID(), item.value);
|
||||
|
||||
var pos = _fieldsList.getIndexOfItem(item);
|
||||
_fieldsList.removeItemAt(pos);
|
||||
|
@ -162,7 +250,6 @@ var Scholar_ItemTypeManager = new function(){
|
|||
return _handleAddEvent(box, event, 'field');
|
||||
}
|
||||
|
||||
|
||||
function _handleAddEvent(box, event, target){
|
||||
if (target=='type'){
|
||||
var existsFunc = _typeExists;
|
||||
|
@ -283,7 +370,10 @@ var Scholar_ItemTypeManager = new function(){
|
|||
|
||||
for (var i in types){
|
||||
sql += prefix + "INSERT INTO itemTypes VALUES ("
|
||||
+ types[i]['itemTypeID'] + ",'" + types[i]['typeName'] + "');\n"
|
||||
+ types[i]['itemTypeID'] + ", '" + types[i]['typeName'] + "', "
|
||||
+ (types[i]['templateItemTypeID']
|
||||
? types[i]['templateItemTypeID'] : 'NULL')
|
||||
+ ");\n"
|
||||
}
|
||||
|
||||
sql += "\n";
|
||||
|
@ -329,9 +419,14 @@ var Scholar_ItemTypeManager = new function(){
|
|||
* Populate the listbox of fields used by this item type
|
||||
**/
|
||||
function _populateTypeFieldsList(itemTypeID){
|
||||
var sql = 'SELECT fieldID, hide FROM itemTypeFields '
|
||||
+ 'WHERE itemTypeID=' + itemTypeID + ' ORDER BY orderIndex';
|
||||
var fields = Scholar.DB.query(sql);
|
||||
// TODO: show template fields for user types
|
||||
|
||||
var sql = "SELECT fieldID, hide, "
|
||||
+ "(fieldID IN (SELECT fieldID FROM itemTypeFields WHERE itemTypeID="
|
||||
+ "(SELECT templateItemTypeID FROM itemTypes WHERE itemTypeID=?1))) "
|
||||
+ "AS isTemplateField FROM itemTypeFields ITF WHERE itemTypeID=?1 "
|
||||
+ "ORDER BY orderIndex";
|
||||
var fields = Scholar.DB.query(sql, itemTypeID);
|
||||
|
||||
// Clear fields box
|
||||
while (_typeFieldsList.getRowCount()){
|
||||
|
@ -341,11 +436,21 @@ var Scholar_ItemTypeManager = new function(){
|
|||
for (var i in fields){
|
||||
var item = _typeFieldsList.appendItem(_getFieldName(fields[i]['fieldID']), fields[i]['fieldID']);
|
||||
|
||||
item.addEventListener('dblclick', new function(){
|
||||
return function(){
|
||||
Scholar_ItemTypeManager.removeFieldFromType(this);
|
||||
}
|
||||
}, true);
|
||||
if (fields[i]['isTemplateField']){
|
||||
item.setAttribute('isTemplateField', true);
|
||||
item.addEventListener('dblclick', new function(){
|
||||
return function(){
|
||||
alert('You cannot remove template fields.');
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
else {
|
||||
item.addEventListener('dblclick', new function(){
|
||||
return function(){
|
||||
Scholar_ItemTypeManager.removeFieldFromType(this);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
item.setAttribute('isHidden', !!fields[i]['hide']);
|
||||
}
|
||||
|
@ -391,6 +496,24 @@ var Scholar_ItemTypeManager = new function(){
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Map a field to an item type in the DB
|
||||
*/
|
||||
function _DBMapField(itemTypeID, fieldID){
|
||||
Scholar.DB.beginTransaction();
|
||||
|
||||
// Get the next available position
|
||||
var sql = "SELECT IFNULL(MAX(orderIndex)+1,1) FROM itemTypeFields "
|
||||
+ "WHERE itemTypeID=?";
|
||||
var nextIndex = Scholar.DB.valueQuery(sql, itemTypeID);
|
||||
|
||||
var sql = "INSERT INTO itemTypeFields VALUES (?,?,?,?)";
|
||||
Scholar.DB.query(sql, [itemTypeID, fieldID, null, nextIndex]);
|
||||
|
||||
Scholar.DB.commitTransaction();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unmap a field from an item type in the DB
|
||||
*/
|
||||
|
|
|
@ -15,18 +15,28 @@
|
|||
|
||||
|
||||
<popupset>
|
||||
<popup id="scholar-remove-type-menu">
|
||||
<menuitem label="Remove item type" oncommand="Scholar_ItemTypeManager.removeType(document.popupNode)"/>
|
||||
<popup id="scholar-type-menu"
|
||||
onpopupshowing="Scholar_ItemTypeManager.buildTypeContextMenu()"
|
||||
onpopuphidden="Scholar_ItemTypeManager.init()">
|
||||
<menuitem label="Remove item type" oncommand="Scholar_ItemTypeManager.removeType(document.popupNode)"/>
|
||||
<menuseparator/>
|
||||
<menu label="Template">
|
||||
<menupopup id="scholar-type-template-menu">
|
||||
<menuitem type="checkbox" label="None" oncommand="Scholar_ItemTypeManager.setTemplate(document.popupNode.value, this.value)"/>
|
||||
<menuseparator/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</popup>
|
||||
|
||||
<popup id="scholar-remove-field-menu">
|
||||
<menuitem label="Remove field" oncommand="Scholar_ItemTypeManager.removeField(document.popupNode)"/>
|
||||
<menuitem label="Remove field" oncommand="Scholar_ItemTypeManager.removeField(document.popupNode)"/>
|
||||
</popup>
|
||||
</popupset>
|
||||
|
||||
|
||||
<vbox>
|
||||
<hbox style="height:25em">
|
||||
<listbox id="item-type-list" seltype="single" context="scholar-remove-type-menu"
|
||||
<listbox id="item-type-list" seltype="single" context="scholar-type-menu"
|
||||
onselect="Scholar_ItemTypeManager.handleTypeSelect()">
|
||||
<listhead>
|
||||
<listheader label="Item Types"/>
|
||||
|
@ -66,11 +76,10 @@
|
|||
<label style="margin:.5em 0; color:red" id="status-line"></label>
|
||||
|
||||
<description style="font-size:small; margin:.4em 0 .3em">
|
||||
Double-click a field to add it to or remove it from the currently selected item type.
|
||||
Double-click a field to add it to or remove it from the currently selected item type. Hit Return on a mapped field to toggle its default visibility.
|
||||
</description>
|
||||
|
||||
<description style="font-size:small; margin:.3em 0 .8em">
|
||||
Hit Return on a mapped field to toggle its default visibility. (Light blue fields are hidden.)
|
||||
<description style="font-size:small; margin:.4em 0 .3em">
|
||||
Light blue fields are hidden. Brown fields are template fields and can only be removed by changing the template.
|
||||
</description>
|
||||
|
||||
<button label="Generate SQL" oncommand="document.getElementById('sql-dump').value=Scholar_ItemTypeManager.createSQLDump()"/>
|
||||
|
|
35
system.sql
35
system.sql
|
@ -1,4 +1,4 @@
|
|||
-- 1
|
||||
-- 2
|
||||
|
||||
-- This file creates system tables that can be safely wiped and reinitialized
|
||||
-- at any time, as long as existing ids are preserved.
|
||||
|
@ -8,7 +8,8 @@
|
|||
DROP TABLE IF EXISTS itemTypes;
|
||||
CREATE TABLE itemTypes (
|
||||
itemTypeID INTEGER PRIMARY KEY,
|
||||
typeName TEXT
|
||||
typeName TEXT,
|
||||
templateItemTypeID INT
|
||||
);
|
||||
|
||||
-- Describes various types of fields and their format restrictions,
|
||||
|
@ -38,7 +39,7 @@
|
|||
orderIndex INT,
|
||||
PRIMARY KEY (itemTypeID, fieldID),
|
||||
FOREIGN KEY (itemTypeID) REFERENCES itemTypes(itemTypeID),
|
||||
FOREIGN KEY (fieldID) REFERENCES itemTypes(itemTypeID)
|
||||
FOREIGN KEY (fieldID) REFERENCES fields(fieldID)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS charsets;
|
||||
|
@ -129,20 +130,20 @@
|
|||
INSERT INTO "fieldFormats" VALUES(2, '[0-9]*', 1);
|
||||
INSERT INTO "fieldFormats" VALUES(3, '[0-9]{4}', 1);
|
||||
|
||||
INSERT INTO itemTypes VALUES (1,'note');
|
||||
INSERT INTO itemTypes VALUES (2,'book');
|
||||
INSERT INTO itemTypes VALUES (3,'bookSection');
|
||||
INSERT INTO itemTypes VALUES (4,'journalArticle');
|
||||
INSERT INTO itemTypes VALUES (5,'magazineArticle');
|
||||
INSERT INTO itemTypes VALUES (6,'newspaperArticle');
|
||||
INSERT INTO itemTypes VALUES (7,'thesis');
|
||||
INSERT INTO itemTypes VALUES (8,'letter');
|
||||
INSERT INTO itemTypes VALUES (9,'manuscript');
|
||||
INSERT INTO itemTypes VALUES (10,'interview');
|
||||
INSERT INTO itemTypes VALUES (11,'film');
|
||||
INSERT INTO itemTypes VALUES (12,'artwork');
|
||||
INSERT INTO itemTypes VALUES (13,'website');
|
||||
INSERT INTO itemTypes VALUES (14,'attachment');
|
||||
INSERT INTO itemTypes VALUES (1,'note',NULL);
|
||||
INSERT INTO itemTypes VALUES (2,'book',NULL);
|
||||
INSERT INTO itemTypes VALUES (3,'bookSection',2);
|
||||
INSERT INTO itemTypes VALUES (4,'journalArticle',NULL);
|
||||
INSERT INTO itemTypes VALUES (5,'magazineArticle',NULL);
|
||||
INSERT INTO itemTypes VALUES (6,'newspaperArticle',NULL);
|
||||
INSERT INTO itemTypes VALUES (7,'thesis',NULL);
|
||||
INSERT INTO itemTypes VALUES (8,'letter',NULL);
|
||||
INSERT INTO itemTypes VALUES (9,'manuscript',NULL);
|
||||
INSERT INTO itemTypes VALUES (10,'interview',NULL);
|
||||
INSERT INTO itemTypes VALUES (11,'film',NULL);
|
||||
INSERT INTO itemTypes VALUES (12,'artwork',NULL);
|
||||
INSERT INTO itemTypes VALUES (13,'website',NULL);
|
||||
INSERT INTO itemTypes VALUES (14,'attachment',NULL);
|
||||
|
||||
INSERT INTO fields VALUES (1,'url',NULL);
|
||||
INSERT INTO fields VALUES (2,'rights',NULL);
|
||||
|
|
35
user.sql
35
user.sql
|
@ -1,4 +1,4 @@
|
|||
-- 1
|
||||
-- 2
|
||||
|
||||
-- This file creates tables containing user-specific data -- any changes
|
||||
-- to existing tables made here must be mirrored in transition steps in
|
||||
|
@ -13,6 +13,39 @@ CREATE TABLE IF NOT EXISTS version (
|
|||
);
|
||||
CREATE INDEX IF NOT EXISTS schema ON version(schema);
|
||||
|
||||
-- Show or hide pre-mapped fields for system item types
|
||||
CREATE TABLE IF NOT EXISTS userFieldMask (
|
||||
itemTypeID INT,
|
||||
fieldID INT,
|
||||
hide INT,
|
||||
PRIMARY KEY (itemTypeID, fieldID),
|
||||
FOREIGN KEY (itemTypeID, fieldID) REFERENCES itemTypeFields(itemTypeID, fieldID)
|
||||
);
|
||||
|
||||
-- User-defined item types -- itemTypeIDs must be >= 1000
|
||||
CREATE TABLE IF NOT EXISTS userItemTypes (
|
||||
itemTypeID INT,
|
||||
typeName TEXT,
|
||||
templateItemTypeID INT,
|
||||
PRIMARY KEY (itemTypeID)
|
||||
);
|
||||
|
||||
-- User-defined fields
|
||||
CREATE TABLE IF NOT EXISTS userFields (
|
||||
userFieldID INT,
|
||||
fieldName TEXT,
|
||||
PRIMARY KEY (userFieldID)
|
||||
);
|
||||
|
||||
-- Map custom fields to system and custom item types
|
||||
CREATE TABLE IF NOT EXISTS userItemTypeFields (
|
||||
itemTypeID INT,
|
||||
userFieldID INT,
|
||||
orderIndex INT,
|
||||
PRIMARY KEY (itemTypeID, userFieldID),
|
||||
FOREIGN KEY (userFieldID) REFERENCES userFields(userFieldID)
|
||||
);
|
||||
|
||||
-- The foundational table; every item collected has a unique record here
|
||||
CREATE TABLE IF NOT EXISTS items (
|
||||
itemID INTEGER PRIMARY KEY,
|
||||
|
|
Loading…
Reference in New Issue
Block a user