MultiClassification
Contents
Requirements
- unlimited number of classifications for one document (task)
- unlimited number of assigned aspect values in one aspect
Solution
Separate Classifications records are used for every classification which is set. No empty records used, a document has as many Classifications records as many classifications are set.
Issues
- How to handle auto-classification from the drawing code? E.g. do you create a new (additional) classification, or (all?) replace
- existing classifications?
Detail
No problems determined until now. A smarty loop goes through all Classifications records to display them line to line.
New/Update
For every aspects defined in table Aspects at least one line appears even if it is empty. At the right side of all line there is a new button to open additional line for entering classification in the same aspect, and a delete button to remove that classification. If there is no more classification in an aspect (after deleting the last one) an empty line appears.
aspect X |
code |
AX_L1_0 |
AX_L2_0 |
... |
from - to |
new/delete |
|
code |
AX_L1_1 |
AX_L2_1 |
... |
from - to |
new/delete |
Search
Searching is a performance issue. Because of all Classifications are different records a large joins could be used to perform searching, which can be very slow. The following optimization steps will be implemented:
determine first the number of Classifications records involved in one aspect value search
- perform a nested select with the smallest records set in the inner most level to limit the involved records to the minimum. The result should be saved into a temp table in the database. This temp table should be deleted at every new search or list.
read DrawingsRevisionsJoinSet with the id set got from the select above
E.g.: assumed that we are looking for documents with aspect codes 22, 345 and 42, the steps above:
1. select code, count(*) from Classifications where code in ( '22', '345', '42' ) order by 2; +------+----------+ | code | count(*) | +------+----------+ | 345 | 10 | | 42 | 234 | | 22 | 1410 | +------+----------+ 2. select objectId from Classifications where objectTypeId = ... and code = '22' and object Id in ( select objectId from Classifications where objectTypeId = ... and code = '42' and object Id in ( select objectId from Classifications where objectTypeId = ... and code = '345' ) )
List
Displaying of classifications in a document list is also a performance issue. To be able to display classification information quickly a static database table will be used to store some information about classified documents:
AspectCache Table
Object Id |
Object Type |
aspect 0 |
... |
aspect 9 |
||||||||||||
|
|
min code |
max code |
full code |
hoverText |
count |
from |
to |
... |
min code |
max code |
full code |
hoverText |
count |
from |
to |
There is one record for one object (Drawing, Task). The field full code is a comma separated list of all aspect values in the appropriate aspect assigned to the object. On a document list with classifications the min code, max code can appear according the sorting order. On a non-sorted list the full code can appear or it can be a site setting parameter.
Issue
The AspectCache table can be updated:
- database procedures on regularly basis (cron?)
- fired by triggers on the tables Drawings, Comments and Classifications
- by application transactions
Listing Multiple Classification Values
Three cases are possible:
- One classification, with a single from-to pair (E.g. one chainage range on a single alignment)
Display: Code x->y -- or code only, with no values?
Hover: Name x->y
- Multiple classifications on same classification, with different from-to pairs (e.g. multiple chainage ranges on a single alignment)
Display: Code min-x -> max-y...
Hover: Name min-x -> max-y (multiple)
- Multiple classifications on different classification, with different from-to pairs (e.g. multiple chainage ranges on multiple alignments)
Display: Code-mix, Code-max... -- Or can we display something more sensible?
Hover: Name-min, Nam-max...(multiple)
We don't need to make a decision now, as the display only changes the update that fills the aspect cache table.
Implementation Notes
Meta Generation
- Javascript core stored at: app/js/cascadingSelect.js, which is installed in pub/js (by app/install/setup.sh)
Implemented in lib/meta/aspect, which calls: app/model/AspectValuesSet->generateJavascript( $jsPath, $phpPath )
- Generates file: var/{site}/{instance}/config/AspectConfig.php - defines the max number of levels in each classification aspect.
- Generates files: pub/asp_cfg_{aspectId}.js - Calls to cascadingSelect.js with classification codes/names.
HTML Generation
Generation of the form HTML is performed by the custom Smarty tag: html_aspect_select, implemented in:
- lib/smarty/plugin/function.html_aspect_select.php
HTML input fields names (output by html_aspect_select):
code_{i} - Entry field for entering a code value, causes selects to change.
asp_sel_{i}_{j} - Select field(s), j=1..maxLevel. Visible/hidden depending on what is selected.
levelCode_{i} - Hidden field which contains the AspectValues.levelCode for the currently selected value. The first select is always visible.
aspectValueId_{i} - Hidden fields which contains the AspectValues.aspectValueId for the currently selected value.
Generates the following for a single level aspect (example for aspectId=3):
<input name="code_4" type="text" size="6" value="" onchange="asp_4.init();" tabindex=1/> <select name="asp_sel_4_0" size="1" onchange="asp_4.update(this);" tabindex=2></select> <input name="levelCode_4" style="display:none;"> <input name="aspectValueId_4" style="display:none;">
Generates the follow for a two-level select (for aspectId=2):
<input name="code_3" type="text" size="6" value="" onchange="asp_3.init();" tabindex=1/> <select name="asp_sel_3_0" size="1" onchange="asp_3.update(this);" tabindex=2></select> <select name="asp_sel_3_1" size="1" onchange="asp_3.update(this);" tabindex=2></select> <input name="levelCode_3" style="display:none;"> <input name="aspectValueId_3" style="display:none;">
Note that the numbering in the HTML is +1, compared to the aspectId value.
Data Values
- Display of data value fields is controlled by two fields:
AspectValues.dataTypeId - Controls is from/tofields are generated.
AspectValues.fromToFlag - Controls if a to HTML text entry field is generated.
AspectValues.dataTypeId is a foreign key to ClassificationDataTypeRef.dataTypeId
The following data type are available:
1 = Boolean - Not implemented yet
- 2 = Integer
- 3 = Float
- 4 = Date
5 = Text - Not implemented yet
6 = URI - Not implemented yet
7 = None - Not implemented yet
Cascading Select Java Script
Entry points
new selectSet( formName, aspectId, unselectedText, debugFlag )
- formName: HTML form name
- aspectId: aspectId from database
unselectText: Text for the unselected option, typically - Select -
- debugFlag: set to true to enable debug popups, and display of hidden fields.
- addItem(
cascadingSelect.js Classes
MenuItem - Implements a single menu item
Menu - Implements a set of MenuItems
Select - Implements an HTML select, includes a set of Menus (in the items variable)
SelectSet - Implements a set of Selects, e.g. a complete cascading select for a single aspect.
Functions are named using the convention {className}_{functionName}, e.g. SelectSet_init or Menu_addItem.