--- /dev/null
+[% WRAPPER base.tt2 %]
+[% ctx.page_title = l('Org Unit Custom Tree') %]
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/conify/global/actor/org_unit_custom_tree.js'> </script>
+<link rel='stylesheet' type='text/css' href='[% ctx.media_prefix %]/js/dojo/dojo/resources/dnd.css'/>
+<link rel='stylesheet' type='text/css' href='[% ctx.media_prefix %]/js/dojo/dojo/resources/dndDefault.css'/>
+
+<style>
+ #wrapper {width : 100%; height: 100%}
+ .block {max-width : 45%; height: 100%; float : left; vertical-align : top; overflow: auto;}
+ #left-block {border-right: 2px solid #333; margin-right: 20px; padding-right: 40px;}
+ .tree-actions {width : 95%; border-bottom: 1px solid #333; padding: 5px; margin: 5px;}
+</style>
+
+<h2>[% l('Org Unit Custom Tree') %]</h2>
+
+<!-- 'opac' is currently the only purpose -->
+<select jsId='treePurposeSelector' dojoType='dijit.form.FilteringSelect' disabled='disabled' onChange='drawMagicTree()'>
+ <option value='opac'>[% l('OPAC') %]</option>
+</select>
+
+<hr/>
+
+<div id='wrapper'>
+ <div id='left-block' class='block'>
+ <div class='tree-actions'>
+ <button dojoType='dijit.form.Button' onClick='realTree.expandAll()'>[% l('Expand All') %]</button>
+ <button dojoType='dijit.form.Button' onClick='realTree.collapseAll()'>[% l('Collapse All') %]</button>
+ </div>
+ <div id='real-tree'></div>
+ </div>
+ <div id='right-block' class='block'>
+ <div class='tree-actions'>
+ <button dojoType='dijit.form.Button' onClick='magicTree.expandAll()'>[% l('Expand All') %]</button>
+ <button dojoType='dijit.form.Button' onClick='magicTree.collapseAll()'>[% l('Collapse All') %]</button>
+ <button dojoType='dijit.form.Button' onClick='applyChanges()'>[% l('Apply Changes') %]</button>
+ </div>
+ <div id='magic-tree'></div>
+ </div>
+</div>
+
+[% END %]
+
+
--- /dev/null
+dojo.require('dijit.form.Button');
+dojo.require('dijit.form.FilteringSelect');
+dojo.require('dojo.data.ItemFileReadStore');
+dojo.require('dojo.data.ItemFileWriteStore');
+dojo.require('dijit.Tree');
+dojo.require('dijit.tree.TreeStoreModel');
+dojo.require("dijit._tree.dndSource");
+dojo.require('fieldmapper.Fieldmapper');
+dojo.require('fieldmapper.OrgUtils');
+dojo.require('openils.User');
+dojo.require('openils.Util');
+dojo.require('openils.PermaCrud');
+
+var realTree;
+var magicTree;
+var pcrud;
+var virtId = -1;
+
+dojo.declare(
+ 'openils.actor.OrgUnitCustomTreeSource', dijit._tree.dndSource, {
+ itemCreator : function(nodes, etc) {
+ var items = this.inherited(arguments);
+ dojo.forEach(items, function(item) {item.shortname = item.name});
+ return items;
+ }
+});
+
+dojo.declare(
+ 'openils.actor.OrgUnitCustomTreeStoreModel', dijit.tree.TreeStoreModel, {
+ mayHaveChildren : function(item) { return true },
+});
+
+function drawPage() {
+ pcrud = new openils.PermaCrud({authtoken : openils.User.authtoken});
+
+ // real org unit list
+ var orgList = openils.Util.objectValues(
+ fieldmapper.aou.OrgCache).map(function(obj) { return obj.org });
+
+ var store = new dojo.data.ItemFileReadStore(
+ {data : fieldmapper.aou.toStoreData(orgList)});
+
+ var model = new dijit.tree.TreeStoreModel({
+ store: store,
+ query: {_top : 'true'}
+ });
+
+ realTree = new dijit.Tree(
+ { model: model,
+ expandAll: function() {treeDoAll(this)},
+ collapseAll: function() {treeDoAll(this, true)},
+ dndController : dijit._tree.dndSource,
+ persist : false,
+ },
+ 'real-tree'
+ );
+
+ realTree.expandAll();
+ drawMagicTree();
+}
+
+
+/**
+ * The magicTree is composed of aouctn items and uses the
+ * linked org unit shortname as the tree item label
+ */
+function drawMagicTree() {
+
+ var orgList = [];
+ var query = {};
+
+ var mTree = pcrud.search('aouct',
+ {active : 't', purpose : treePurposeSelector.attr('value')});
+
+ if (mTree.length) {
+ nodes = pcrud.search('aouctn', {tree : mTree[0].id()});
+
+ // create an org tree from the custom tree nodes
+ dojo.forEach(nodes,
+ function(node) {
+ var org = JSON2js(js2JSON( // deep clone
+ fieldmapper.aou.findOrgUnit(node.org_unit())
+ ));
+ org.parent_ou(null);
+ org.children([]);
+ if (node.parent_node()) {
+ org.parent_ou(
+ nodes.filter(
+ function(n) {return n.id() == node.parent_node()}
+ )[0].org_unit()
+ );
+ }
+ orgList.push(org);
+ }
+ );
+ var root = nodes.filter(function(n) {return n.parent_node() == null})[0];
+ query = {id : root.org_unit()+''}
+ }
+
+ var store = new dojo.data.ItemFileWriteStore(
+ {data : fieldmapper.aou.toStoreData(orgList)});
+
+ var model = new openils.actor.OrgUnitCustomTreeStoreModel({
+ store : store,
+ query : query
+ });
+
+ magicTree = new dijit.Tree(
+ { model: model,
+ expandAll: function() {treeDoAll(this)},
+ collapseAll: function() {treeDoAll(this, true)},
+ dndController : openils.actor.OrgUnitCustomTreeSource,
+ dragThreshold : 8,
+ betweenThreshold : 5,
+ persist : false,
+ },
+ 'magic-tree'
+ );
+
+ magicTree.expandAll();
+}
+
+function applyChanges() {
+ var list = [];
+ function traverse(pnode, node) {
+ var item = node.item;
+ list.push({
+ name : item.name,
+ org_id : item.id,
+ parent_node : pnode ? pnode.item.id : null
+ });
+ dojo.forEach(node.getChildren(), function(child) {traverse(node, child)});
+ }
+ traverse(null, magicTree.rootNode);
+ console.log(js2JSON(list));
+}
+
+
+// modified from
+// http://stackoverflow.com/questions/2161032/expanding-all-nodes-in-dijit-tree
+function treeDoAll(tree, collapse) {
+ function expand(node) {
+ if (collapse) tree._collapseNode(node);
+ else tree._expandNode(node);
+ var childBranches = dojo.filter(node.getChildren() || [],
+ function(node) { return node.isExpandable });
+ var def = new dojo.Deferred();
+ defs = dojo.map(childBranches, expand);
+ }
+ return expand(tree.rootNode);
+}
+
+openils.Util.addOnLoad(drawPage);