Source: sdw/templates/containerGUI/searchResultTree.js

 
/**
 * Dieses Modul definiert die Klasse searchResultTree.
 * Eine Baumstruktur, die die Ergebnisse der Suche nach Objekten darstellt.
 * 
 * Dieses Modul ist von module:sdw/templates/widgets/treeController abgeleitet und überschreibt lediglich die Methoden onClickTreeNode
 * und onDoubleClickTreeNode alle anderen Eigenschaften und Methoden der Vaterklasse werden ohne Änderung verwendet.
 * 
 * @author sdw.systems
 * 
 * @module module:sdw/templates/containerGUI/searchResultTree
 * 
 * @extends module:sdw/templates/widgets/treeController
 * 
 * @see module:sdw/templates/application/searchPerspective
 * 
 */
 

define([
    "dojo/_base/declare", "dojo/_base/lang", 
    "sdw/const", "sdw/util",
    "sdw/templates/widgets/treeController"
    ], function(
    	declare, lang, 
    	SDWConst, Util,
    	Tree
){
	
var moduleName="module:sdw/templates/containerGUI/searchResultTree";

var Class=declare(moduleName, Tree, {
	/** @lends module:sdw/templates/containerGUI/searchResultTree# */

	/** @property {String} moduleName Name des Moduls aus lokaler Konstante */
	moduleName:moduleName,
	
	/** @property {String} klasseSearchResultItem Klasse der gefundenen Items, muss von den abgeleiteten Klassen überschrieben werden*/
	klasseSearchResultItem:null,

	/** @property {OPCODE} opcDropSearchResultItem Opcode zum Löschen, muss von den abgeleiteten Klassen überschrieben werden*/
	opcDropSearchResultItem:0,
	
	/** @property {Integer} itemCount Wird in onLoadTreeComplete auf die Anzahl Items im resultSet gesetzt. Das ist asynchron.*/
	itemCount:0,
	
	/** @property {UUID} resultId Wird in onLoadTreeComplete auf die UUID des Resultsets gesetzt. Das ist asynchron. Dient dazu, das ResultSet eindeutig zu identifizieren, insb. wenn es in einem containerView als Tabelle geöffnet werden soll*/
	resultId:null,

	/** @property {String} gridClass Muss von den abgeleiteten Klassen überschrieben werden falls die Ergebnisse in einem Grid geöffnet werden sollen*/
	gridClass:null,
	
	/** @property {Boolean}	 hasContextMenue Kontextmenü soll verwendet werden*/
	hasContextMenue:true,
	/** @property {Boolean}	 hasDefaultContextMenue Kontextmenü soll nur mit bestimmten MenüItems verwendet werden. Deshalb muss createContextMenue explizit aufgerufen werden, siehe Konstruktor */
	hasDefaultContextMenue:false,	
	/** @property {String[]} contextMenuActionArray Liste der Actions die im KOntextmenu als menuItems erscheinen sollen*/
	contextMenuActionArray:[SDWConst.menuActionOpen, SDWConst.menuActionClose,SDWConst.menuActionDelete,SDWConst.menuActionDuplicate],

	/**
	 * Setzt die Eigenschaften des Baumes für die initiale Query 
	 */
	setProperties:function() {
		if (this.debug)	console.debug(moduleName+" ->setProperties");
		//
		this.queryRootItemParams={"klasse":SDWConst.klasseQueryResult};
		this.childrenAttrs=["items"];
		//
		this.singular=true;
		//
		if (this.debug)	console.debug(moduleName+" <-setProperties");
	},
	
	/**
	 * Eventhandler für das Klicken auf einen Treenode. Überschreibt den Methodenstub der Vaterklasse.
	 * Lädt den Objektcontainer auch bei Einfach-Klick.
	 * Anforderung da manche mobile Geräte keine Doppelklick unterstützen  
	 */
	onClickTreeNode: function (treeItem, treeNode) {
		if (this.debug)	console.log(moduleName+" ->onClickTreeNode on treeItem: "+treeItem.oid);
		//
		//this.onDoubleClickTreeNode(treeItem, treeNode);
		//
		if (this.debug)	console.log(moduleName+" <-onClickTreeNode on treeItem: "+treeItem.oid);
	},
	
	
	/**
	 * Eventhandler für das Doppelklicken auf einen Treenode. Überschreibt den Methodenstub der Vaterklasse.
	 * Als Ergebnis wird der Event von der API geladen und in einem neuen Pane angezeigt, der in den Viewcontainer
	 * eingehängt wird.
	 * Die Methode ruft die Methode addOrSelectTab des ViewContainers auf falls es sich nicht um die Wurzel handelt
	 * denn die enthält nur Metadaten über den Suchvorgang.
	 *  
	 * Dazu zeigt delegate auf die Perspektive, die auf die Application und diese wiederum auf den
	 * ViewContainer zeigt. Der ViewContainer existiert schon, ist beim Initialisieren der Application bereits
	 * erzeugt worden. Die Perspektiven teilen sich den Viewcontainer, deshalb ist dieser bei der application 
	 * angesiedelt, nicht bei der einzelnen Perspektive wie z.B. beim ViewTabPane-Paradigma
	 * @param {Object} treeItem	Das TreeItem, auf das geklickt wurde
	 * @param {String} treeItem.klasse	Die fachliche Klasse des treeItems, hier immer de_stattbuchung_Event
	 * @param {OID} treeItem.oid		Die fachliche oid des treeItems
	 * @param {String} treeItem.name 	Der Name des fachlichen Objektes des treeItems
	 * @param {Object} treeNode 		Der zugehörige TreeNode. 
	 */
	onDoubleClickTreeNode: function (treeItem, treeNode) {
		if (this.debug)	console.log(moduleName+" ->onDoubleClickTreeNode on treeItem: "+treeItem.oid);
		//
		if (Util.getKlasseValueOfStoreItem(treeItem)==this.klasseSearchResultItem) {
			// Nur für die Items der klasseSearchResultItem aufrufen, es gibt ja auch noch die Wurzel des Baumes, da soll nichts passieren
			this.delegate.application.viewContainer.addOrSelectTab(	
					Util.getKlasseValueOfStoreItem(treeItem), 
					Util.getOIDValueOfStoreItem(treeItem), 
					Util.getLabelValueOfStoreItem(treeItem), 
					true, true
			);
		}
		//
		if (this.debug)	console.log(moduleName+" <-onDoubleClickTreeNode on treeItem: "+treeItem.oid);
	},
	
	/**
	 * Wird mit der Antwort des Servers auf den Drop-Request aufgerufen.
	 * Diese Implementierung sorgt dafür dass das gelöscht Objekt aus allen ResultTrees und ggf. auch als eigenständiger containerView
	 * verschwindet.
	 * Kann von den abgeleiteten Klassen überschrieben werden um zusätzliche Aufräumarbeiten zu machen, sollte aber auf jeden Fall 
	 * aufgerufen werden.
	 * @param {Object}	treeItem 	Das gelöschte treeItem. Dieses existiert noch im aktiven resultSetTree, wird erst durch this.inherited(arguments) aus dem aktiven und allen anderen ResultTrees gelöscht
	 * @param {Object}	response 	Die Antwort des Server auf den drop-Request
	 */
	callbackOnDropSearchResultItem:function(treeItem, response) {
		if (this.debug) console.log(moduleName+" ->callbackOnDropSearchResultItem");
		//
		if (response.exception) {alert(response.exception);}
		else {
			var perspective=this.delegate;
			if (perspective){
				//	Ggf. offenen Tab mit dem Objekt löschen
				perspective.application.viewContainer.closeTab(Util.getOIDValueOfStoreItem(treeItem));
				//	Objekt in allen Search-Trees der Perspektive löschen, diese Instanz eingeschlossen
				perspective.removeFromAllTrees(Util.getOIDValueOfStoreItem(treeItem), this.klasseSearchResultItem); 
			}
		}
		//
		if (this.debug) console.log(moduleName+" <-callbackOnDropSearchResultItem");
	},		
	
	/** 
	 * Öffnet das Kontextmenü des Baumes wenn ein Rechtsklick auf ein treeItem erfolgt und aktiviert das Menüitems für das Löschen.
	 * Falls die response vom Server die Eigenschaft resultSetCount hat und eine G
	 * @prarm{Object}  treeItem Zeiger auf das treeItem auf das geklickt worden ist
	 * @param{Object} treeNode Zeiger auf den DomNode des treeItems
	 */
	onOpenContextMenue: function(treeItem, treeNode) {
		if (this.debug)	console.log(moduleName+" ->onOpenContextMenue "+treeItem.klasse+ " "+treeItem.id[0]);
		//
		if (Util.getKlasseValueOfStoreItem(treeItem)==SDWConst.klasseQueryResult) {
			if (this.gridClass!=null && this.resultSetCount) {
				var label= this.resultSetCount + ((this.resultSetCount==1) ? " Ergebnis als Tabelle öffnen" : " Ergebnisse als Tabelle öffnen");
				this.setDefaultContextMenueItem(SDWConst.menuActionOpen, (this.delegate.application.viewContainer.hasTab(this.resultId)) ? "Zugehörigen Reiter einblenden" : label, true);
			} else {
				this.setDefaultContextMenueItem(SDWConst.menuActionOpen, null, false);
			}
			this.setDefaultContextMenueItem(SDWConst.menuActionClose, null, this.delegate.application.viewContainer.hasTab(this.resultId));
			this.setDefaultContextMenueItem(SDWConst.menuActionDelete, null, false);
		}
		else {
			this.setDefaultContextMenueItem(SDWConst.menuActionOpen, (this.delegate.application.viewContainer.hasTab(Util.getOIDValueOfStoreItem(treeItem))) ? "Zugehörigen Reiter einblenden" : null, true);
			this.setDefaultContextMenueItem(SDWConst.menuActionClose, null, this.delegate.application.viewContainer.hasTab(Util.getOIDValueOfStoreItem(treeItem)));
			this.setDefaultContextMenueItem(SDWConst.menuActionDelete, null, this.opcDropSearchResultItem>0);
		}
		
		this.setDefaultContextMenueItem(SDWConst.menuActionInsert, null);
		this.setDefaultContextMenueItem(SDWConst.menuActionUpdate, null);
		this.setDefaultContextMenueItem(SDWConst.menuActionDuplicate, null);

		//
		if (this.debug)	console.log(moduleName+" <-onOpenContextMenue "+treeItem.oid);
	},
	
	/**
	 * Überschreibt diese Methode der Vaterklasse und löscht das aktuelle treeItem-Objekt
	 * @prarm{String}  action Konstante die den typ des Button beschreibt der geklickt worden ist, z.B. SDWConst.domIdInsert
	 * @prarm{Object}  treeItem Zeiger auf das treeItem auf das geklickt worden ist
	 * @param{Object} treeNode Deprecated, ignorieren
	 */
	onClickTreeNodeContextmenue: function (action, treeItem, treeNode) {
		if (this.debug)	console.log(moduleName+" ->onClickTreeNodeContextmenue "+action + " "+treeItem.klasse+ " "+treeItem.id);
		//
		switch (action) {
		
		case SDWConst.menuActionClose:
			if (Util.getKlasseValueOfStoreItem(treeItem)==SDWConst.klasseQueryResult) {
				this.delegate.application.viewContainer.closeTab(this.resultId);
			}
			else {
				this.delegate.application.viewContainer.closeTab(Util.getOIDValueOfStoreItem(treeItem));
			}
			break;
			
		case SDWConst.menuActionDelete: 
			var param={};
			param[this.klasseSearchResultItem]=Util.getOIDValueOfStoreItem(treeItem);
			this.confirmAndDelete(treeItem, this.opcDropSearchResultItem, param, lang.hitch(this, lang.partial(this.callbackOnDropSearchResultItem, treeItem)));
			break;
		
		case SDWConst.menuActionOpen:
			if (Util.getKlasseValueOfStoreItem(treeItem)==SDWConst.klasseQueryResult) {
				var label=Util.getLabelValueOfStoreItem(treeItem);
				var muster=Util.getValue(this.delegate.domIdSuchmuster);
				if (muster!=SDWConst.emptyString) label+= " für Muster "+muster;
				var stichtag=Util.getValue(this.delegate.domIdStichtag);
				if (stichtag!=null && stichtag!=SDWConst.emptyString) {
					stichtag = Util.date2ISOString(Util.getValue(this.delegate.domIdStichtag));
					label+= " zum Stichtag "+Util.date2string(Util.getValue(this.delegate.domIdStichtag));
				} else stichtag=null;
				//
				var data={};
				data.muster=muster; data.stichtag=stichtag; data.itemCount=this.itemCount; data.resultSetCount=this.resultSetCount;
				this.delegate.application.viewContainer.addOrSelectTab(this.gridClass, this.resultId, label, true, true, data);
				//
			} else {
				this.onDoubleClickTreeNode(treeItem, treeNode);
			}
			break;
		}
		//
		if (this.debug)	console.log(moduleName+" <-onClickTreeNodeContextmenue "+action + " "+treeItem.klasse+ " "+treeItem.id);
	},
	
	/**
	 * Callback-Methode, die vom tree-Widget aufgerufen wird, nachdem das asynchrone Laden der Daten beendet ist
	 * Nach dem Laden des trees soll standardmäßig das Hauptobjekt angezeigt werden.
	 */
	onLoadTreeComplete: function () {
		if (this.debug)	console.log(moduleName+" ->onLoadTreeComplete");
		//
		var callback=lang.hitch(this, function(items) {
			if (this.debug)	console.log(moduleName+" ->callback onLoadTreeComplete");
			//	es gibt per definitionem im treeStore nur ein Objekt mit der Klasse rootKlasse, also direkt mit [0] drauf zugreifen.
			this.itemCount=Util.getValueOfStoreItem(items[0], SDWConst.jsonItemCount, false);
			this.resultSetCount=Util.getValueOfStoreItem(items[0], SDWConst.jsonResultSetCount, false);
			this.resultId=Util.getIDValueOfStoreItem(items[0]);
			this.treeItem=items[0];
			this.treeNode=this.getTreeNodeForTreeItem(this.treeItem);
			//
			if (this.debug)	console.log(moduleName+" <-callback onLoadTreeComplete for "+this.itemCount+ " items");
		});
		this.queryItemsByClass(SDWConst.klasseQueryResult, callback);
		//
		if (this.debug)	console.log(moduleName+" <-onLoadTreeComplete");
	},
	
	
	/**	
	 * Kann von den abgeleiteten Klassen überschrieben werden, diese Implementierung
	 * muss aber immer aufgerufen werden.
	 */
	dispose: function() {
		if (this.debug)	console.log(moduleName+" ->dispose");
		//
		this.inherited(arguments);
		//
		if (this.debug)	console.log(moduleName+" <-dispose");
	}

	
	});

	Class.moduleName=moduleName;
	return Class;

});