Ext.define( 'Swnm.view.sheet.GridTabSheet', { extend: 'Swnm.view.sheet.CustomTabSheet', // config /// app: null, /// title: "", gridSelType : 'rbkcellmodel', /** * identisch mit this.user */ lehrer: null, /** * Referenz auf this.lehrer.schule */ schule: null, // muss von den abgeleiteten Komponenten gesetzt werden model: "", prefix: "", editFieldNote1: "", editFieldNote2: "", editFieldFsu: "", editFieldFsg: "", eingabeFertigFields: [], grid: null, store: null, cellEditing: null, toolbar: null, filterbar: null, detailsContainer: null, detailsGrid: null, detailsStore: null, activeInputWindow: null, activeMessageBox: null, internCellSelect: false, helpForm: null, istKoordinatorAnsicht: false, filterCriterias: [], filterCmpIds: [], // itemIds der Filter-Komponenten filterCmps: [], filterCmpsHash: {}, // itemId => FilterComponent filterLoaded: false, filterActive: false, filterLocked: 0, hasSpecFilter_Faecher: false, /** * * @property array recordsInMainFilter */ recordsInStandardFilter: undefined, eventsLocked: 0, actions: [], fixedCols: [], actionHandler: null, app: null, appSurface: null, user: null, // wird beim Resume gesetzt cachedState: undefined, notenKuerzel: 'E1 E2 E3 AT AM NB NT NE LM', inputColumns: [], inputColumnFieldNames : "", childWindowCloseTask: null, filterHash: null, filterItemsKlassen: null, filterItemsKurse: null, filterItemsFaecher: null, filterItemsKursArten: null, datenStatus: {}, visDatenStatus: {}, // Daten-Status der sichtbaren gefilterten Daten sortierungen: undefined, // enthält nach dem Laden der DAten die Sortierungen für Klassen, Fächer und Kurse hasCachedData: false, loadingData: false, dataLoaded: false, cbFilterKlasse: null, cbFilterFach: null, cbFilterKurs: null, cbLehrerStatus: null, lehrerStatus: '-', // '-', 'K', 'F' konferenzModus: false, // zur Verwaltung der Spalten bei denen Noten bzw. Punkte eingegeben werden können notenPunkteColumns: undefined, //[], notenPunkteColumnsMap: undefined, //{}, floskelEditor: null, /** * @private * @property {boolean} needMinimumFilterCriterias * Wenn TRUE, dann muss mindestens einer Klasse+Fach oder ein Kurs ausgewählt seon, * damit die DAtensätze angezeigt werden */ needMinimumFilterCriterias: false, needToolbar : true, needEditStatusCol: true, needDetails: false, /** * @property {Object} * Verweist je nach Datenart auf den entsprechenden FoemCache des Schul-Objekts.
*/ foemaCache: {}, startEditDelayedTask: null, // wird NUR für den IE benötigt initComponent: function() { var me = this, ext = Ext, items = [], i, len, bar, user = this.user, currentCfg = this.getUserCurrentCfg(), columns, col, colDefs, notenPunkteColumns = [], notenPunkteColumnsMap = {}; if (this.needDetails) this.layout = 'border'; me.app = App; me.user = user; me.schule = user.schule; me.cachedState = user.getCachedState( me.prefix ); me.konferenzModus = me.user.konferenzModus; // Handler für die User-Events installieren user.on( "hasmodifdata", this.onUserEventHasModifData, this ); user.on( "getmodifdata", this.onUserEventGetModifData, this ); user.on( "getcachedata", this.onUserEventGetCacheData, this ); user.on( "getcurrentconfig", this.onUserEventGetCurrentConfig, this ); user.on( "standardconfigchange", this.onUserEventStandardConfigChange, this ); me.fixedCols = []; me.childWindowCloseTask = new Ext.util.DelayedTask(); //----------------- // TOOLBAR //----------------- if (this.needToolbar) { this.extendToolBar( items ); me.toolbar = Ext.create( 'Ext.toolbar.Toolbar', { itemId: 'toolbar', dock: 'top', height: 30, padding: '0 0 0 8', ui: 'rbktb', defaultButtonUI: 'rbktb-toolbar', // style: { // "background-color": "rgb(173, 210, 237)" // }, items: items }); //----------------- // ACTIONS //----------------- me.actionHandler = Ext.create( 'Rbk.action.ActionHandler', { extendActionText: true }); // Action-objekte erstellen this.createActions(); // die vom Sheet benötigten Actions dem Toolbar hinzufügen me.actionHandler.addToToolbar( me.toolbar, this.getNeededActionIds(), {}, items.length === 0 ? -1 : 0 /*links einfügen*/ ); this.mnuSave = this.toolbar.down( '#mnuSave '); this.mnuUndo = this.toolbar.down( '#mnuUndo '); } //----------------- // FILTERBAR //----------------- me.filterbar = this.createFilterBar(); ext.apply( this, { dockedItems: [ me.toolbar, Ext.create( "Ext.container.Container", { // schmaler Balken dock: 'top', height: 1, style: { "background-color": "rgb(21, 127, 204)" } }), me.filterbar ] }); //----------------- // STORE //----------------- me.store = ext.create('Ext.data.Store', { autoDestroy: false, model:me.model, proxy: { type: 'memory' }, remoteSort: false, sortOnLoad: false, sortOnFilter: false }); // me.store.on('datachanged', me.onStoreDataChanged, me ); // me.store.on('update', me.onStoreUpdate, me ); //----------------- // GRID //----------------- this.initialGridWidth = this.needDetails ? (currentCfg.grid.width > 0 ? currentCfg.grid.width : 450) : 'auto'; me.grid = ext.create('Rbk.ext.grid.Panel', { selTYpe: this.gridSelType, region: this.needDetails ? 'west' : undefined, width: this.initialGridWidth, // this.needDetails ? (currentCfg.grid.width > 0 ? currentCfg.grid.width : 450) : 'auto', //split: this.needDetails ? true : false, store: me.store, columns: [], epmtyText: 'Kein Daten vorhanden' }); me.items = [me.grid]; // DETAILS-CONTAINER //----------------- var exCtConfig = {}; this.createDetailsContainer( exCtConfig ); if (this.detailsContainer) me.items.push( this.detailsContainer ); // // me.cellEditing = Ext.create('Swnm.lib.CellEditing', { // clicksToEdit: 1, // tabSheet: me, // pluginId: 'piCellEdit_' + this.prefix // }); // // colDefs = [{ // text:' ', // width:24, // resizeable: false, // sortable:false, // hideable: false, // dataIndex: 'editStatus', // draggable: false, // renderer: this.statusColRenderer, // scope: this, // sheet: this, // form: this // }]; // // if (this.prefix === 'TL') { // Ext.apply( colDefs[0], { // locked : true, // lockable : false // }); // } // colDefs = colDefs.concat( this.getColumnsDef() ); // // Ext.each( colDefs, function(colDef){ // if (!colDef.renderer && colDef.xtype !== 'rbkcheckcolumn') // colDef.renderer = me.standardColumnRenderer; // colDef.sheet = me; // }); // // //me.grid = Ext.create('Ext.grid.Panel', { // me.grid = Ext.create('Rbk.ext.grid.Panel', { // store: me.store, // selectOnFocus: true, // scroll: 'both', //// selModel: { //// selType: 'rbkcellmodel' //// //selType: 'cellmodel' //// }, // viewConfig: { // stripeRows: false, // loadMask:false // }, // plugins: [ // me.cellEditing, // { // ptype: 'bufferedrenderer', // trailingBufferZone: 20, // Keep 20 rows rendered in the table behind scroll // leadingBufferZone: 20 // Keep 50 rows rendered in the table ahead of scroll // } // ], // columnLines: true, // columns: colDefs, // listeners: { // beforeselect: me.onGridBeforeSelect, // selectionchange: me.onGridSelectionChange, // scope: me // } // }); // // // Beim Teilleistungssheet gibt "me.grid.getPlugin" 'undefined' zurück (Grid mit CategoryHeaders und LockedColumns). // // Stattdessen erstellt das Grid eine eigene CellEditing-Instanz (allerdings mit der korrekten Klasse). // // In diesem Fall wird die Referenz vom CellEditing-Objekt beim ersten Aufruf von CellEditing.StatrEdit gesetz //// me.cellEditing = me.grid.getPlugin( 'piCellEdit_' + this.prefix ); //// if (!me.cellEditing) //// me.cellEditing = this.grid.editingPlugin; // // me.items = [me.grid]; // // me.grid.on('focus', me.onFocus, me ); // me.grid.on('beforeedit', this.onGridBeforeEdit, me ); // me.grid.on('edit', me.onGridAfterEdit, me ); //// me.grid.on('beforeselect', me.onGridBeforeSelect, me ); //// me.grid.on('selectionchange', me.onGridSelectionChange, me ); //// //----------------- // INHERITED //----------------- me.callParent(arguments); // die verwendeten Filter-Komponenten sammeln var fc; this.filterCmpsHash = {}; for (i = 0, len = this.filterCmpIds.length; i < len; i++) { fc = this.filterbar.down( '#'+this.filterCmpIds[i] ); this.filterCmps.push( fc ); this.filterCmpsHash[this.filterCmpIds[i]] = fc; } // // die Spalten, in denen Noten/Punkte eingegeben werden können sammeln // // columns = this.grid.columns; // for (i = 0, len = columns.length; i < len; i++) { // col = columns[i]; // if (col.fuerNotenPunkte) { // notenPunkteColumns.push( col ); // notenPunkteColumnsMap[col.dataIndex] = col; // } // } // // if (notenPunkteColumns.length > 0) { // this.notenPunkteColumns = notenPunkteColumns; // this.notenPunkteColumnsMap = notenPunkteColumnsMap; // } // // //--------- // // me.calcFixedCols(); // // Wenn für die aktuelle Datenart 'cachedData' vorhanden sind, dann // werden die Store-Daten sofort geladen; // Andernfalls erste dann, wenn das Sheet das ertse mal angezeigt wird if (user.getCachedState( this.prefix)) { this.hasCachedData = true; this.appSurface.numSheetsWithCachedData++; this.loadStore(); } // Lehrer-Status me.cbLehrerStatus = me.filterbar.down('#cbLehrerstatus'); //this.grid.getSelectionModel().on('selectionchange', this.osc, this ); //this.grid.getSelectionModel().on('focuschange', this.ofc, this ); //----------------- // Hotkey-Actions sammeln /* function addAction( btn ) { var text, p; text = btn.text; p = text.indexOf( '' ); if (p == -1) return; text = text.substr( p + 3, 1 ).toUpperCase(); me.actions.push( { action: btn.itemId.substring( 3 ), // ohne den Prefix 'btn' hotkey : text, btn : btn } ); } me.actions = []; var btns = me.toolbar.items.items, btn; for (i = 0; i < btns.length; i++) { btn = btns[i]; if (btn.xtype !== 'button') continue; addAction( btn ); } addAction( me.filterbar.down( '#btnClearFilter' )); */ //----------------- // REFERENZEN der Komponenteninstanzen //----------- // für den IE if (ext.isIE) { this.startEditDelayedTask = new ext.util.DelayedTask(); } }, afterRender: function() { // if (!this.dataLoaded) { // this.loadStore(); // } // // this.cellEditing = this.grid.getPlugin( 'piCellEdit_' + this.prefix ); this.callParent(arguments); }, // abstrakte Methode; muss von der abgeleiteten Klasse �beschrieben werden getColumnsDef: function() { return []; }, // abstrakte Methode; muss von der abgeleiteten Klasse �beschrieben werden getFilterDef: function() { return []; }, // abstrakte Methode; muss von der abgeleiteten Klasse �beschrieben werden onFocus: function( editor, e ) { }, // Listener f�r grid.beforeselect onGridBeforeSelect: function( selModel, record, rowIndex, eOpts ) { var me = this; if (me.internCellSelect) { me.internCellSelect = false; return true; } var valid = me.commit(); // ggf. aktuelle Editor-Eingabe validieren return valid; }, // Listener f�r grid.selectionchanged // onGridSelectionChange: function( selModel, selected, eOpts ) // { // if (selected.length === 0) return true; // unselect // // this.enableActions(); // return true; // }, // abstrakte Methode; muss von der abgeleiteten Klasse �beschrieben werden onGridBeforeEdit: function( editor, e ) { var me = this, rec = e.record.data, fieldName = e.field; if (me.canEditCell( e.record, fieldName)) return true; else { e.cancel = true; return false; } }, // abstrakte Methode; muss von der abgeleiteten Klasse �beschrieben werden onGridAfterEdit: function( editor, e ) { this.enableActions(); }, // abstrakte Methode; muss von der abgeleiteten Klasse �beschrieben werden onValidateEdit: function( value ) { return true; }, onDataHandler_DataChanged: function( dataHandler, opts) { this.enableActions(); }, // ABSTRACT // wird von this.onStoreUpdae aufgerufen, wenn ein Feld editiert wurde onAfterStoreEdit: function( record, modifiedFieldNames ) { }, /** * Handler fuer this.dataHandler.dataUpdate */ onDataHandler_DataUpdate: function( dataHandler, record, operation, modifiedFieldNames, eOpts ) { if (operation === 'edit') this.enableActions(); //this.onAfterStoreEdit( record, modifiedFieldNames ); }, // @virtual // wird VOR dem Laden der Daten in den Store aufgerufen // kann von den abgeleiteten Klassen für Initialisierungen überschrieben werden onAfterStoreDataReceived: function( data ) { return data; }, // @virtual // Wird NACH dem Laden der Daten in den Store und NACH dem Initialisieren der Filter aufgerufen // kann von den abgeleiteten Klassen für Initialisierungen überschrieben werden onAfterStoreDataLoaded: function() { }, recreateGrid: function ( afterError ) { var me = this, colDefs = [], columns, col, notenPunkteColumns = [], notenPunkteColumnsMap = {}, grid, oldGrid = this.grid, // getEditGrid(), oldDataHandler = this.dataHandler, gridWidth = oldGrid.getWidth(); this.dataHandler = Ext.create( "Rbk.db.DataHandler", { baseCt: this, handler: { // beforeScroll: this.onGridBeforeScroll, afterScroll: this.onGridAfterScroll, checkEditInput: this.pruefeEingabe, dataChange : this.onDataHandler_DataChage, dataUpdate : this.onDataHandler_DataUpdate }, doLog: true }); if (this.gridSelType === 'rbkcellmodel') { // ROWMODEL ist immer OHNE Editieren me.cellEditing = Ext.create('Rbk.ext.grid.plugin.CellEditing', { dataHandler : this.dataHandler, clicksToEdit: 1, baseCt: me, pluginId: 'piCellEdit_' + this.prefix }); } colDefs = []; if (this.needEditStatusCol) colDefs.push({ text:' ', width:24, resizeable: false, sortable:false, hideable: false, dataIndex: 'editStatus', draggable: false, renderer: this.getMainGridEditStatusColRenderer(), scope: this, sheet: this, form: this }); if (this.prefix === 'TL') { Ext.apply( colDefs[0], { locked : true, lockable : false }); } colDefs = colDefs.concat( this.getColumnsDef() ); Ext.each( colDefs, function(colDef){ if (!colDef.renderer && colDef.xtype !== 'rbkcheckcolumn') colDef.renderer = me.standardColumnRenderer; colDef.sheet = me; }); var gridPlugins = [ { ptype: 'bufferedrenderer', trailingBufferZone: 20, // Keep 20 rows rendered in the table behind scroll leadingBufferZone: 20 // Keep 50 rows rendered in the table ahead of scroll } ]; if (me.cellEditing) gridPlugins.push( me.cellEditing ); grid = Ext.create('Rbk.ext.grid.Panel', { selType: this.gridSelType, region: this.needDetails ? 'west' : undefined, width: this.needDetails ? this.initialGridWidth : 'auto', split: this.needDetails ? true : false, dataHandler : this.dataHandler, baseCt : this, store: me.store, selectOnFocus: true, scroll: 'both', viewConfig: { stripeRows: false, loadMask:false, deferEmptyText: false }, plugins: gridPlugins, columnLines: true, columns: colDefs, emptyText: !afterError ? 'Kein Daten vorhanden' : 'Fehler beim Ermitteln der Daten', listeners: { // beforeselect: me.onGridBeforeSelect, // selectionchange: me.onGridSelectionChange, scope: me } }); Ext.suspendLayouts(); this.eventsLocked++; try { this.remove( oldGrid, true ); this.grid = grid; this.add( this.grid ); } finally { this.eventsLocked--; Ext.resumeLayouts(true); } me.grid.on('focus', me.onFocus, me ); me.grid.on('beforeedit', this.onGridBeforeEdit, me ); me.grid.on('edit', me.onGridAfterEdit, me ); // die Spalten, in denen Noten/Punkte eingegeben werden können sammeln columns = this.grid.columns; for (i = 0, len = columns.length; i < len; i++) { col = columns[i]; if (col.fuerNotenPunkte) { notenPunkteColumns.push( col ); notenPunkteColumnsMap[col.dataIndex] = col; } } if (notenPunkteColumns.length > 0) { this.notenPunkteColumns = notenPunkteColumns; this.notenPunkteColumnsMap = notenPunkteColumnsMap; } //--------- me.calcFixedCols(); }, getMainGridEditStatusColRenderer: function () { return this.statusColRenderer; }, /** * Success-Callback-Methode * @param {type} respData * @param {type} opts * @returns {undefined} */ loadStoreDataSuccess: function( respData, opts, afterError ) { // diverse Filter-Comboboxen mit den tats�chlich vorhanden Werten f�llen var me = this, lehrer = this.lehrer, data = respData.daten, cachedState = me.cachedState, i, len, kurs; this.loadingData = false; this.istKoordinatorAnsicht = opts.datenFuerKoordinator; this.sortierungen = lehrer.schule.sortierungen; this.datenStatus = respData.status; this.schuelerOhneKlasse = respData.schuelerOhneKlasse; this.visDatenStatus = Ext.merge( {}, this.datenStatus ); try { Ext.suspendLayouts(); // damit die abgeleiteten Klassen die Daten ggf. auf- und umarbeiten können data = me.onAfterStoreDataReceived( data ); // das Grid erstellen this.recreateGrid( afterError ); this.initLehrerStatusCombo( data ); me.store.loadData( data ); this.rawData = data; this.dataLoaded = true; // Filter-Combos füllen this.fillFilterCombos(); // damit ggf. die abgeleiteten Klassen die Storedaten auswerten können (z.B. Leistungsdaten: Map{Klassen=>[store-Records]} this.onAfterStoreDataLoaded(); // falls notwendig, die zuletzt gesetzten Filterkriterien wieder setzen // und die modifizierten, aber noch nicht abgespeicherten Werte zurückschreiben if (this.hasCachedData) { me.applyCachedState(); me.appSurface.afterSheetDataLoaded(); } else { // das Sheet wurde das erste mal aktiviert und hat darauf hin seine Strore-DAten geladen this.filterLoaded = true; if (this.needMinimumFilterCriterias) // alle Datensätze inital ausblenden this.applyFilter( false ); else this.doAfterApplyFilter(); this.filterLoaded = false; // this.afterSheetShow(); // this.filterLoaded = true; } } finally { if (this.hasCachedData) Ext.resumeLayouts( false ); else Ext.resumeLayouts( true ); //Ext.resumeLayouts( /*false*/ /*true*/ ); } // NACH Ext.resumeLayouts ausführen if (this.hasCachedData) { } else { this.afterSheetShow(); this.filterLoaded = true; } this.enableActions(); // aus den Daten die Schueler-Objekte aufbauen this.schule.schueler.initFromSheetRawData( this.prefix, data ); if (this.callbackAfterStoreDataLoaded) Ext.callback( this.callbackAfterStoreDataLoaded.fn, this.callbackAfterStoreDataLoaded.scope, [!afterError ? true : false] ); // } // finally { // Ext.resumeLayouts(true); // } if (this.schuelerOhneKlasse.length > 0) { var msg = "Folgende aktive oder externe Schüler sind in SchILD keiner Klasse zugeordnet:", schuelerOhneKlasse = this.schuelerOhneKlasse, schueler, i = 0, len = schuelerOhneKlasse.length; for (;i < len; i++) { schueler = schuelerOhneKlasse[i]; msg += "
- " + schueler.aname + ' (ID: ' + schueler.id + ")"; } RSU.infoBox( msg ); } }, /** * Failure-Callback-Methode
* Erzeugt eine leeres Response-Object und ruft damit loadStoreData() auf. */ loadStoreDataFailure: function() { var respData = this.getEmptyResponse(); this.loadStoreDataSuccess( respData, {}, true ); }, getEmptyResponse: function() { return { daten: "[]", status: {} }; }, initLehrerStatusCombo: function( data ) { var me = this, lehrer = this.lehrer, lkrz = lehrer.kuerzel, rec, status = this.datenStatus, filterbar = me.filterbar, alle = false, storeData = []; if (data.length === 0) return; if (status.mitFremdSchuelern) { if (lehrer.istSchulleiter) { storeData.push( ['-', 'Schulleiter'] ); alle = true; } if (status.mitKoordinatorSchuelern) storeData.push( ['koord', 'Koordinator'] ); } if (status.mitKlassenSchuelern) { if (status.mitKlassenSchuelernStv && !status.mitKlassenSchuelernPri) storeData.push( ['kl_stv', 'Klassenlehrer (Stv.)'] ); else { storeData.push( ['kl_alle', 'Klassenlehrer'] ); if (status.mitKlassenSchuelernStv && status.mitKlassenSchuelernPri) { storeData.push( ['kl_prim', 'Klassenlehrer (primär)'] ); storeData.push( ['kl_stv', 'Klassenlehrer (Stv.)'] ); } } } if (status.mitFachSchuelern) { if (status.mitFachSchuelernStv && !status.mitFachSchuelernPri) storeData.push( ['fl_stv', 'Fachlehrer (Stv.)'] ); else { storeData.push( ['fl_alle', 'Fachlehrer'] ); if (status.mitFachSchuelernStv && status.mitFachSchuelernPri) { storeData.push( ['fl_prim', 'Fachlehrer (primär)'] ); storeData.push( ['fl_stv', 'Fachlehrer (Stv.)'] ); } } } if (storeData.length <= 1) return; // die Lehrerstaus-Combo muss nicht angezeigt werden if (!alle) storeData.insert( 0, ['-', '-'] ); Ext.suspendLayouts(); try { this.cbLehrerStatus.loadData( storeData ); filterbar.down('#tbsLehrerstatus').setVisible( true ); filterbar.down('#lblLehrerstatus').setVisible( true ); this.cbLehrerStatus.setVisible( true ); } finally { Ext.resumeLayouts(true); } }, getActiveRecord: function() { var me = this, grid = this.getEditGrid(), sel = grid ? grid.getSelectionModel().getSelection() : null; return ((sel !== null) && sel.length > 0) ? sel[0] : null; }, fillFilterCombos: function( resetKriterienWert ) { var me = this, data = this.rawData, rec, ok, klassen = [], kurse = [], kursArten = [], faecher = [], hsKlassen = {}, hsKurse = {}, hsKursArten = {}, hsFaecher = {}, cbStatus = this.cbLehrerStatus, cbKlasse = me.filterbar.down( '#cbKlasse' ), cbKurs = me.filterbar.down( '#cbKurs' ), cbKursart = me.filterbar.down( '#cbKursart' ), cbFach = me.filterbar.down( '#cbFach' ), lehrerStatus = (cbStatus && cbStatus.isVisible() && cbStatus.hasValue()) ? cbStatus.getValue() : '-', istLehrerStatusKoord = lehrerStatus === 'koord', istLehrerStatusKl = lehrerStatus === 'kl_alle' || lehrerStatus === 'kl_prim' || lehrerStatus === 'kl_stv', istLehrerStatusFl = lehrerStatus === 'fl_alle' || lehrerStatus === 'fl_prim' || lehrerStatus === 'fl_stv', activeKlasse = resetKriterienWert !== 'klasse' && cbKlasse.hasValue() ? cbKlasse.getValue() : '-', //activeFach = resetKriterienWert !== 'fach' && cbFach && cbFach.getValue() !== null ? cbFach.getValue() : '-', activeFachId = resetKriterienWert !== 'fach' && cbFach && cbFach.hasValue() ? cbFach.getValue() : 0, activeKursId = resetKriterienWert !== 'kurs' && cbKurs && cbKurs.hasValue() ? cbKurs.getValue() : 0, activeKursart = resetKriterienWert !== 'kursart' && cbKursart && cbKursart.hasValue() ? cbKursart.getValue() : '-', isLD = me.prefix == 'LD', isBD = me.prefix == 'BD', isTL = me.prefix === 'TL', isKAZ = me.prefix === 'KAZ', isFoema = this.prefix == 'Foema', mitKuFa = isLD || isTL, // MIT Kursen/FÄchern mitSpecFachFilter = isKAZ, // die Fach-IDs sind nicht als Field in den records desmain-Store enthalten filterFaecher, keinKursFilter = !(isLD || isTL), cachedState = me.cachedState, i, len, kurs, j, len2, map, ext = Ext, isEmpty = ext.isEmpty; //------------------------------------- // Filter-Combos füllen //------------------------------------- function add( field, aArray, hash ) { if (aArray.length == 0) aArray.push( '-' ); if (!rec) return; var val = rec[field]; if (isEmpty(val)) return; if (hash[val]) return; aArray.push( val ); // Name hash[val] = '+'; } function addKurs() { if (kurse.length == 0) kurse.push( [0, '-', '']); if (!rec) return; var valId = rec['kursId'], valKrz = rec['kurs'], valJhrg = rec['jahrgang'] !== undefined ? rec['jahrgang'] : ''; if (isEmpty(valKrz)) return; if (hsKurse[valId]) return; // kurse.push([valId, valKrz, valJhrg]); // ID, Name, Jahrgang kurse.push([valId, valJhrg, valKrz]); // ID, Jahrgang, Name hsKurse[valId] = '+'; } function addFach( arec) { if (faecher.length == 0) faecher.push( [0, '-', '-']); if (!arec) return; var valId = arec['fachId'], valKrz = arec['fachKrz'], valName = arec['fach']; if (Ext.isEmpty(valKrz)) return; if (hsFaecher[valId]) return; faecher.push([valId, valName, valKrz]); // ID, Name, Kürzel hsFaecher[valId] = '+'; } function sortKurse( aArray ) { return aArray.sort( function(a1, a2) { // Bezeichnung vergleichen if (a1[2] < a2[2]) // [2] === Kursbezeichnung return -1; else if (a1[2] > a2[2]) return 1; // a1 und a2 haben identische Kursbezeichnung if (a1.length === 3) a1.push( '+' ); // '+' bedeutet: nachher noch Jahrgang an Kursbez anhängen if (a2.length === 3) a2.push( '+' ); // Jahrgänge vergleichen if (a1[1] < a2[1]) return -1; else if (a1[1] > a2[1]) return 1; else return 0; } ); // return aArray.sort( function(a1, a2) { // // Bezeichnung vergleichen // if (a1[1] < a2[1]) // return -1; // else if (a1[1] > a2[1]) // return 1; // // // a1 und a2 haben identische Kursbezeichnung // // if (a1.length === 3) // a1.push( '+' ); // '+' bedeutet: nachher noch Jahrgang an Kursbez anhängen // if (a2.length === 3) // a2.push( '+' ); // // // Jahrgänge vergleichen // if (a1[2] < a2[2]) // return -1; // else if (a1[2] > a2[2]) // return 1; // else // return 0; // } // ); } function sortFaecher( aArray ) { return aArray.sort( function(a1, a2) { // Kürzel vergleichen return a1[2].localeCompare( a2[2] ); } ); } function lehrerStatusOk() { var ok; ok = (lehrerStatus === '-') || (istLehrerStatusKl && rec.alsKlassenLehrer && ( (lehrerStatus === 'kl_alle') || ((lehrerStatus === 'kl_prim') && (!rec.alsKlassenLehrerStv)) || ((lehrerStatus === 'kl_stv') && (rec.alsKlassenLehrerStv)) ) ) || (istLehrerStatusFl && rec.alsFachLehrer && ( (lehrerStatus === 'fl_alle') || ((lehrerStatus === 'fl_prim') && (!rec.alsFachLehrerStv)) || ((lehrerStatus === 'fl_stv') && (rec.alsFachLehrerStv)) ) ) || (istLehrerStatusKoord && rec.alsKoordinator ); return ok; } // Daten-Arrays für die Stores aufbauen // zuerst den 1. "Leer-Eintrag" einfügen rec = undefined; add( 'klasse', klassen, hsKlassen ); if (mitSpecFachFilter) { addFach(); } else if (mitKuFa) { addFach(); //add( 'fach_anz', faecher, hsFaecher ); add( 'kursart', kursArten, hsKursArten ); addKurs(); } for (i = 0, len = data.length; i < len; i++) { rec = data[i]; // ok = (lehrerStatus === '-') // || (istLehrerStatusKl && rec.alsKlassenLehrer // && ( (lehrerStatus === 'kl_alle') // || ((lehrerStatus === 'kl_prim') && (!rec.alsKlassenLehrerStv)) // || ((lehrerStatus === 'kl_stv') && (rec.alsKlassenLehrerStv)) // ) // ) // || (istLehrerStatusFl && rec.alsFachLehrer // && ( (lehrerStatus === 'fl_alle') // || ((lehrerStatus === 'fl_prim') && (!rec.alsFachLehrerStv)) // || ((lehrerStatus === 'fl_stv') && (rec.alsFachLehrerStv)) // ) // ) // || (istLehrerStatusKoord && rec.alsKoordinator // ); ok = lehrerStatusOk(); if (!ok) continue; else if (!(mitKuFa || mitSpecFachFilter)) { add( 'klasse', klassen, hsKlassen ); continue; } add( 'klasse', klassen, hsKlassen ); if (activeKlasse !== '-' && rec.klasse !== activeKlasse) continue; if (!mitSpecFachFilter) addFach( rec ); else { // z. B. KAZ filterFaecher = this.getFachFilterItems( rec ); for (j = 0, len2 = filterFaecher.length; j < len2; j++) addFach( filterFaecher[j] ); } if (keinKursFilter /*z.B. KAZ*/ || (activeFachId !== 0 && rec.fachId !== activeFachId)) continue; // if (activeFach !== '-' && rec.fach_anz !== activeFach) // continue; add( 'kursart', kursArten, hsKursArten ); if (activeKursart !== '-' && rec.kursart !== activeKursart) continue; addKurs(); } // prüfen, ob alle aktuellen Werte <> '-' der Filterkriterien in den neuen Kriterienlisten vorkommen. // Wenn nicht, dann muss der betreffende Wert auf '-' gesetz und die KriterienListen neu ermittelt werden if (activeKlasse !== '-' && hsKlassen[activeKlasse] === undefined) { this.fillFilterCombos( 'klasse' ); return; } if (activeFachId !== 0 && hsFaecher[activeFachId] === undefined) { this.fillFilterCombos( 'fach' ); return; } // if (activeFach !== '-' && hsFaecher[activeFach] === undefined) { // this.fillFilterCombos( 'fach' ); // return; // } if (activeKursart !== '-' && hsKursArten[activeKursart] === undefined) { this.fillFilterCombos( 'kursart' ); return; } // faecher, kurse und Kursarten alphabetisch sortieren if (mitKuFa) { kurse = sortKurse( kurse ); //faecher = faecher.sort(); faecher = sortFaecher( faecher ); kursArten = kursArten.sort(); // bei der Kursliste prüfen, ob Einträge mit identischen Bez. vorliegen (kurse[n][3] === '+'); // wenn ja, wird für diese der Name um den Jahrgang erweitert for (i = 0, len = kurse.length; i < len; i++) { kurs = kurse[i]; // if (kurs[3] === '+') // kurs[1] += ' (Jg. ' + kurs[2] + ')'; } } try { this.filterLocked++; // Ausführen des Listener-Handler blockieren // Daten in die Stores laden cbKlasse.loadData( klassen ); if (mitSpecFachFilter) { cbFach.loadData( faecher ); } else if (mitKuFa) { cbFach.loadData( faecher ); cbKurs.loadData( kurse ); cbKursart.loadData( kursArten ); } // versuchen, die alten Werte zu setzen if (activeKlasse != '-') cbKlasse.setValueStrict( activeKlasse ); // if (activeFach !== '-') // cbFach.setValueStrict( activeFach ); if (activeFachId !== 0) cbFach.setValueStrict( activeFachId ); if (activeKursId !== 0) cbKurs.setValueStrict( activeKursId ); if (activeKursart !== '-') cbKursart.setValueStrict( activeKursart ); } finally { this.filterLocked--; } }, getActiveColumn: function() { var me = this, grid = this.getEditGrid(), selModel = grid.getSelectionModel(); return selModel.selection ? selModel.selection.columnHeader : null; var col = grid.getSelectionModel().selection.column, colIndex = grid.getSelectionModel().getCurrentPosition().column, gridView = grid.getView(), cols = gridView.getHeaderContainer ? grid.getColumns() : grid.columns; if (Ext.isNumber(colIndex)) return cols[colIndex]; else return null; for (var i= 0, len = cols.length; i < len; i++) { if (cols[i].getIndex() === colIndex) return cols[i]; } return null; }, statusColRenderer: function( value, meta, rec, rowix, colIx ) { var column = meta.column, dataIndex = column.dataIndex, me = column.form, tlArtId, recModif; if (me.prefix === 'TL' && !me.readOnly) { recModif = rec.modified; tlArtId = me.activeTLArtID; if (recModif && (recModif['tl_note_'+tlArtId] !== undefined || recModif['tl_bemerkung_'+tlArtId] !== undefined || recModif['tl_datum_'+tlArtId] !== undefined)) { meta.style = "padding: 0px"; return ''; } } else if (rec.dirty) { meta.style = "padding: 0px"; return ''; } else return ""; }, // sorgt für das richtige Icon in den Spalten, die mittels InputWindow bearbeitet werden actionColumnRenderer: function( value, meta, rec, rowix, colIx ) { var col = this, ef = 'ef_' + col.dataIndex, //dirty = rec.modified[ef] !== undefined || rec.modified[col.dataIndex] !== undefined, //tdCls = "", //style = "background-color: #c4f4b6;", column = meta.column, me = column.sheet, recData = rec.data, item = column.items[0], //disabled = rec.get('bearbeitungGesperrt'), disabled = !me.canEditCell(rec, column.dataIndex ), visible = rec.get('spalte' + col.dataIndex.toUpperCase() + 'Sichtbar'); if (visible) { item.iconCls = (disabled ? 'rbk-action-col-disabled ' : '') + 'edit-' + (Ext.isEmpty(value) ? 'yellow' : (rec.get( ef ) === '+' ? 'green' : 'red')); item.disabled = false; meta.tdCls = 'rbk-grid-cell-bk-' + (disabled ? 'disabled-' : '') + (rowix % 2 === 1 ? 'odd' : 'even'); } else { item.iconCls = ''; item.disabled = true; meta.tdCls = 'rbk-grid-cell-bk-unused-' + (rowix % 2 === 1 ? 'odd' : 'even'); } return ""; }, // sorgt für das richtige Icon in den Spalten, die mittels InputWindow bearbeitet werden foemaActionColumnRenderer: function( value, meta, rec, rowix ) { var column = meta.column, me = column.sheet, item = column.items[0], disabled = rec.data.foemaGesperrt; item.iconCls = (disabled ? 'rbk-action-col-disabled ' : '') + 'edit-' + (Ext.isEmpty(rec.data['foemaGuid']) ? 'yellow' : (rec.data['ef_foema'] === '+' ? 'green' : 'red')); meta.tdCls = 'rbk-grid-cell-bk-' + (disabled ? 'disabled-' : '') + (rowix % 2 === 1 ? 'odd' : 'even'); // // // meta.tdCls = 'edit-action-col-' // + (Ext.isEmpty(rec.data['foemaGuid']) // ? 'ohne-text' // : (rec.data['ef_foema'] === '+' // ? 'mit-text' // : 'text-in-arbeit')) // + ' ' // + (!rec.data.foemaGesperrt // ? 'rbk-grid-cell-bk-' // : 'rbk-grid-cell-bk-disabled-') // + (rowix % 2 === 1 ? 'odd' : 'even'); return ""; }, inputColumnRenderer: function( value, meta, rec, rowix, colIx ) { var recData = rec.data, column = meta.column, me = column.sheet, evenOdd = rowix % 2 === 1 ? 'odd' : 'even'; switch (me.getCellStatus(rec, column.dataIndex)) { case 'editable' : meta.tdCls = 'rbk-grid-cell-bk-' + evenOdd; break; case 'disabled' : meta.tdCls = 'rbk-grid-cell-bk-disabled-' + evenOdd; break; default : // 'unused' meta.tdCls = 'rbk-grid-cell-bk-unused-' + evenOdd; } // if (me.canEditCell(rec, column.dataIndex )) // meta.tdCls = 'rbk-grid-cell-bk-' + evenOdd; // else // meta.tdCls = 'rbk-grid-cell-bk-disabled-' + evenOdd; return value; }, standardColumnRenderer: function( value, meta, rec, rowix, colIx ) { var recData = rec.data, column = meta.column, me = column.sheet; if (rowix % 2 === 1) meta.tdCls = "rbk-grid-cell-bk-odd"; if (column.xtype === 'datecolumn') return column.defaultRenderer(value); else return value; }, checkboxColumnRenderer: function( value, meta, rec, rowix, colIx ) { var recData = rec.data, column = meta.column, me = column.sheet, cssPrefix = Ext.baseCSSPrefix, cls = [cssPrefix + 'grid-checkcolumn'], evenOdd = rowix % 2 === 1 ? '-odd' : '-even', disabled = column.disabled || !me.canEditCell(rec, column.dataIndex ); meta.tdCls = 'rbk-grid-cell-bk' + (disabled ? '-disabled' : '') + evenOdd; if (disabled) { cls.push( 'rbk-action-col-disabled' ); //meta.tdCls += ' ' + 'rbk-action-col-disabled'; //column.disabledCls; } if (value) { cls.push(cssPrefix + 'grid-checkcolumn-checked'); } return ''; }, // /** * Aktiviert/daktiviert die relevanten Schalter entsprechend dem aktuelled Daten- bzw Filter-Status * @returns {Boolean} */ enableActions: function() { var grid = this.getEditGrid(); if (!grid || !this.actionHandler) return false ; if (App.isShutdown()) // die Anwendung wird heruntergefahren return false; var me = this, fb = me.filterbar, dataToSave = this.getDataToSave(), // this.getModifiedRecords(), //me.store.getModifiedRecords(), dataModified = (dataToSave !== null) && (dataToSave.length > 0), rec = me.getActiveRecord(), recData = rec ? rec.data : null, recModified = rec && rec.dirty, filterActive = me.store.isFiltered(), ah = me.actionHandler, acFS; ah.enable( 'Save', dataModified ); ah.enable( 'SaveRecord', recModified ); ah.enable( 'Reset', dataModified ); ah.enable( 'ResetRecord', recModified ); ah.enable( 'Print', me.store.getCount() > 0 ); ah.enable( 'EinzelFehlstunden', recData && recData.fehlstundenModel === 'D' ); if (this.mnuSave) this.mnuSave.setDisabled( !dataModified ); if (this.mnuUndo) this.mnuUndo.setDisabled( !dataModified ); fb.down( '#btnClearFilter').setDisabled( !filterActive ); // ggf. Symbol auf dem Tab-Reiter einfügen this.setIconCls( dataModified ? 'data-changed' : '' ); this.dataModified = dataModified; // die entsprechende Routine in der MainView aufrufen (wg. dem globalen Save-Button) this.app.mainView.onDataStateChange(); return true; }, // Handler für die ActionColumns der Grids onActionColumnClick: function( gridView, rowIndex, colIndex, itemCfg, e ) { var me = this, grid = this.getEditGrid(), rec = grid.store.getAt(rowIndex), column = grid.columnByFieldName( itemCfg.dataIndex ), //column = Rbk.grid.Tools.columnByVisibleIndex( me.grid, colIndex ), //column = me.grid.columns[colIndex], field = column.dataIndex, text = rec.get(field), // nacharbeiten = (text !== '') && (rec.get( 'ef_' + field) === ''); // ef_XYZ signalisert 'feriggestellt' flag = rec.get( 'ef_' + field), nacharbeiten = flag !== '+' && (flag === '-' || text !== '') ? true : false; me.openInputWindow( rec, rowIndex, column, text, nacharbeiten, e.keyCode === 13 ); }, openInputWindow: function( rec, rowIndex, colIndexOrColumn, text, nacharbeiten, openByReturnKey ) { var me = this, grid = this.getEditGrid(), column = Ext.isNumber( colIndexOrColumn ) ? Rbk.grid.Tools.columnByVisibleIndex( grid, colIndexOrColumn ) : colIndexOrColumn, title = column.items[0].tooltip, field = column.dataIndex; if (!me.commit()) // evtl. aktive Eingabe in anderer Spalte validieren return; grid.getSelectionModel().setCurrentPosition({record: rec, columnHeader: column }); // Eingabefenster öffnen if (true) { this.floskelEditor = Ext.create( 'Swnm.view.FrmFloskelEditor', { title: title, sheet: me, field: field, nacharbeiten: nacharbeiten, bearbeitungGesperrt: !this.canEditCell( rec, field ), schuelerId: rec.get('schuelerId'), fachId: rec.get('fachId'), floskelHauptgruppe: column.floskelHauptgruppe, text: text, success: me.onInputSuccess, scope: me, opts: { rowIndex: rowIndex, colIndex: column.index , column: column, openByReturnKey : openByReturnKey } }); this.floskelEditor.show(); } else { Ext.create('Swnm.view.InputWindow', { title: title, sheet: me, field: field, nacharbeiten: nacharbeiten, bearbeitungGesperrt: !this.canEditCell( rec, field ), //bearbeitungGesperrt: rec.get('bearbeitungGesperrt'), info: { vname: rec.get('vname'), nname: rec.get('nname'), geschlecht: rec.get('geschlecht'), fach: (field == 'fble') ? rec.get('fach') : '' }, text: text, success: me.onInputSuccess, scope: me, opts: { rowIndex: rowIndex, colIndex: column.index , column: column, openByReturnKey : openByReturnKey } }).show(); } }, // callback f�r "me.onActionColumnClick -> InputWindow -> OK-Button onInputSuccess: function( text, nacharbeiten, opts ) { var me = this, grid = this.getEditGrid(), rec = grid.store.getAt(opts.rowIndex), //column = me.grid.columns[opts.colIndex], column = opts.column, // Rbk.grid.Tools.columnByVisibleIndex( me.grid, opts.colIndex ), field = column.dataIndex, fertig; rec.set( field, text ); fertig = nacharbeiten ? '-' : ( text !== "" ? '+' : '' ); rec.set( 'ef_' + field, fertig ); // EingabeFertig this.enableActions(); }, // obsolet /* showFilter: function() { var me = this, filterData = me.grid.filters.getFilterData(), data = null, txt = "", columns = me.grid.columns, hdr = "", i,j, field, col; if (filterData.length == 0) return; for (i = 0; i < filterData.length; i++) { data = filterData[i]; field = data.field; hdr = ""; for (j = 0; j < columns.length; j++) { col = columns[j]; if (col.dataIndex == field) { hdr = col.text; break; } } if (txt !== "") txt += '
'; txt += hdr; if (data.data.comparison) { switch(data.data.comparison) { case "eq" : txt += ' = '; break; case "gt" : txt += ' > '; break; case "lt" : txt += ' < '; break; } } else txt += ' = '; txt += data.data.value; } Rbk.SysUtils.infoBox( txt, null, {}, 'Aktuell aktive Filter' ); }, */ print: function() { var grid = this.getEditGrid(); Swnm.print.Printer.printAutomatically = false; Swnm.print.Printer.print( grid, this.prefix, this.title, this.getCurrentFilterAsinfoText() ); }, /** * Für den Ausdruck * @param {type} divider * @returns {String} */ getCurrentFilterAsinfoText: function( divider) { var fch = this.filterCmpsHash, cmp, n = 0, isEmpty = Ext.isEmpty, ret = ''; divider = divider || '
'; function getCritAsText( itemId, caption, isCheck ) { if (!fch[itemId]) return ''; cmp = fch[itemId]; if (!cmp.isVisible()) return ''; var value = cmp.getValue(); if (isCheck && value) value = 'Ja'; if (!value || isEmpty(value) || value === 0 || value === '-') return ''; if (Ext.isNumber(value)) { value = cmp.getRawValue(); } n++; return (n > 1 ? divider : '') + caption + ' : ' + value; }; ret = '' + getCritAsText( 'edName', 'Name' ) + getCritAsText( 'cbKlasse', 'Klasse' ) + getCritAsText( 'cbFach', 'Fach' ) + getCritAsText( 'cbKurs', 'Kurs' ) + getCritAsText( 'cbKursart', 'Kursart' ) + getCritAsText( 'ckMahnen', 'Mahnen', true ) ; return ret; }, einzelFehlstundenBearbeiten : function() { var rec = this.getActiveRecord(), recData = rec ? rec.data : null; if (!rec) return; Ext.create( "Swnm.view.FrmEinzelFehlstunden", { sheet: this, recData: recData, schuelerId: recData.schuelerId, schuelerName : recData.vname + ' ' + recData.nname, klasse: recData.klasse, fachId: recData.fachId, fachKrz: recData.fachKrz, fach: recData.fach } ).show(); }, showNotentabelle: function() { var me = this, rec = me.getActiveRecord(), recData = rec ? rec.data : null, col, colDataIndex, tlArtId = 0, note, canModify = false; if (!rec) return; if (this.prefix === 'LD') { note = rec.data.note; canModify = me.getCellStatus(rec, 'note' ) === 'editable'; } else if (this.prefix === 'TL') { note = null; col = this.getActiveColumn(); if (col) { tlArtId = this.artIdFromField( col.dataIndex); if (tlArtId > 0) { colDataIndex = 'tl_note_' + tlArtId; note = rec[colDataIndex]; canModify = me.getCellStatus(rec, colDataIndex ) === 'editable'; } } } else return; Ext.create( 'Swnm.view.FrmNotenkuerzel', { sheet : this, tlArtId : tlArtId, // NUR bei TL relevant note: note, noteOderPunkte : !rec.data.benoetigtPunkte || rec.data.noteStattPunkteEingegeben ? 'note' : 'punkte', canModify: canModify, // !rec.data.bearbeitungGesperrt, callback : canModify /*!rec.data.bearbeitungGesperrt*/ ? this.onNotenkuerzelSelected : null, callbackScope: me } ).show(); }, /** * Wird vom NotenListe-Fenster aufgerufen, nachdem eine Note (Punkte) ausgewählt wurde * @param {String} note * @returns {undefined} */ onNotenkuerzelSelected: function( note ) { var me = this, rec = this.getActiveRecord(), col, tlArtId; if (rec) { if (this.prefix === 'LD') rec.set( 'note', note ); else if (this.prefix === 'TL') { col = this.getActiveColumn(); if (!col) return; tlArtId = this.artIdFromField( col.dataIndex); if (tlArtId <= 0) return; rec.set( 'tl_note_' + tlArtId, note ); } else return; this.enableActions(); } }, showHelp: function() { var me = this; if (me.helpForm == null) { me.helpForm = Ext.create('Ext.window.Window', { title: 'Hilfe : ' + me.title, width: 400, height:500, //autoScroll:true, layout: 'fit', plain:true, closeAction: 'hide', constrainHeader: true, items: [ { xtype: 'panel', padding: '8 8 8 8', autoLoad: './res/hilfe-' + me.prefix.toLowerCase() + '.htm', autoScroll:true } ], buttons: [{ text: 'Schließen', sheet: me, handler: function(){ this.sheet.helpForm.hide(); // this == button } }] }); } me.helpForm.show(); }, loadStore: function( callback, scope, aLoadMaskCmp, loadMaskText ) { if (!this.dataLoaded && callback) { this.callbackAfterStoreDataLoaded = { fn : callback, scope : scope }; } if (this.dataLoaded) { if (callback) Ext.callback( callback, scope, [true] ); return; } if (this.loadingData) { return; } var me = this, datenFuerKoordinator = this.user.istKoordinator || this.user.istSchulleiter, activeSheet = this.appSurface.centerView ? this.appSurface.centerView.activeTab : this, loadMaskCmp = aLoadMaskCmp ? aLoadMaskCmp : (activeSheet && activeSheet.grid ? activeSheet.grid : this.appSurface.centerView ); this.loadingData = true; Rbk.Ajax.sendRequest( 'get' + me.prefix + "Data", { notenStattPunkte: this.getNotenStattPunkte(), datenFuerKoordinator : datenFuerKoordinator // alle Schüler/Facher/Kurse; nicht nur die als Klassen-/Kurs-Lehrer }, { loadMaskCmp: loadMaskCmp, // this.hasCachedData ? this.appSurface.centerView : this.grid, loadMaskText: loadMaskText ? loadMaskText : '#load', success: this.loadStoreDataSuccess, failure: this.loadStoreDataFailure, scope: me, datenFuerKoordinator : datenFuerKoordinator } ); }, /** * Speichert geänderte Daten in der DB * * @param {Object|Array} data * Die zu speichernden Daten. * @param {Array} modifStoreRecords * Die Records des Stores, deren geänderte Daten gespeichert werden.
* @param {Boolean} showMsg * Wenn TRUE, dann wird nach dem Speichern eine entsprechende Meldung angezeigt * @returns {Boolean} */ saveData: function (data, modifStoreRecords, showMsg, exCallbackOnSuccess, exCallbackScope, exLoadMaskCmp ) { var me = this; if (Ext.isEmpty(data) || data.length == 0) return true; Rbk.Ajax.sendRequest( 'save'+me.prefix+'Data', data, { success: this.onSaveDataSuccess, scope: this, loadMaskCmp: exLoadMaskCmp || exCallbackScope || this.getEditGrid(), loadMaskText: '#save', savedData: data, modifStoreRecords: modifStoreRecords, showMsg : showMsg, exCallbackOnSuccess: exCallbackOnSuccess, exCallbackScope : exCallbackScope } ); }, /** * Success-Handler für den Ajax-Request "saveData" * @param {Object} respData * @param {Object} opts * @returns {undefined} */ onSaveDataSuccess: function( respData, opts ) { var grid = this.getEditGrid(); this.commitChanges( opts.modifStoreRecords, respData.savedRecords ); // this.commitChanges( opts.modifStoreRecords ); this.enableActions(); if (opts.showMsg) { var m = respData.numSavedRecords !== 1 ? respData.numSavedRecords + ' Datensätzen' : ' einem Datensatz'; Rbk.SysUtils.infoBox( 'Die Änderungen an ' + m + ' wurden gespeichert', null, null, grid.getView() ); } if (opts.exCallbackOnSuccess) { Ext.callback( opts.exCallbackOnSuccess, opts.exCallbackScope ); } }, /* * * @param {function} callbackOnSuccess * Callback-Funktion die aufgerufen wird, wenn die DAten erfolgreich gespeichert wurden. * Wird von anderen Formularen gesetzt, die Shwwt.saveStor verwenden; z.B. Klassenübersicht * @param {object} callbackScope * @returns {undefined} */ saveStore: function( callbackOnSuccess, callbackScope, exLoadMaskCmp ) { var me = this, modifStoreRecords = [], dataToSave = this.getDataToSave( modifStoreRecords ); if (dataToSave.length == 0 ) return; this.saveData( dataToSave, modifStoreRecords, true, callbackOnSuccess, callbackScope, exLoadMaskCmp ); }, saveRecord: function() { var me = this, record = me.getActiveRecord(), data = this.getCurrentRecordModifData(); // (record && record.dirty) ? [record.data] : null; me.saveData( data, [record], false ); }, /** * Wird von der Mainview zum Speichern aller DB-Daten verwendet * @param {type} allModifData * @param {type} allModifRecords * @returns {undefined} */ getModifDataForSaveAll: function( allDataToSave, allModifRecords ) { var propName = this.prefix + 'Data', modifStoreRecords = [], dataToSave = this.getDataToSave( modifStoreRecords ); if (dataToSave.length == 0 ) return; allDataToSave[propName] = dataToSave; allModifRecords.push({ sheet : this, modifStoreRecords: modifStoreRecords, countModifData : dataToSave.length // muss nicht unbedingt identisch sein mit der Anzahl modifStoreRecords (z.B. bei Teilleistungen) }); }, resetStore: function() { var me = this; Rbk.SysUtils.confirmBox( 'Wollen Sie wirklich alle Änderungen verwerfen?', me.callbackResetStore, me ); }, callbackResetStore: function( btn ) { var me = this; if (btn == 'yes') { //me.store.rejectChanges(); me.rejectChanges(); me.enableActions(); } }, resetRecord: function() { var me = this, record = me.getActiveRecord(); if (!record) return; record.reject(); me.enableActions(); }, // Handler f�r dFilterRelationCombobox.change onCbRelChange: function( cb ) { if (!this.filterLoaded) return; var me = this, val = me.down('#' + cb.valueCmp).getValue(); // applyFilter nur dann aufrufen, wenn das zugeh�rige Eingabefeld nicht leer ist if (!Ext.isEmpty(val)) me.applyFilter( false, false); }, /** * Handler für den FilterCombo-Change-Event * @returns {Boolean} */ onFilterComboChange: function(cb, newValue, oldValue, eOpts) { if (!this.filterLoaded || this.filterLocked) return; if (cb === this.cbFilterKurs || cb === this.cbFilterFach) { if (!Ext.isNumber(newValue)) return true; } else if ((cb === this.cbFilterKlasse || cb === this.cbFilterKursart) && (!Ext.isString(newValue) || !cb.dataMap[newValue])) return true; this.applyFilter( cb !== this.cbFilterKurs ); // mit FilterCombo-Refresh }, // Callback für applyFilter filterFunc2: function( rec ) { return this.filterHash[rec.data.id] !== undefined ? true : false; }, prepareFilter: function() { if (this.filterCriterias === 'hideall') { this.filterHash = {}; return; } var me = this, ext = Ext, isEmpty = ext.isEmpty, filterHash = {}, recordsInStandardFilter = [], storeRecords = this.store.snapshot ? this.store.snapshot.items : this.store.data.items, lenRecords = storeRecords.length, crits = me.filterCriterias, lenCrits = crits.length, crit, rec, recData, val, nval, cval, valIsNumber, r, i, j, eff = me.eingabeFertigFields, lenEff = eff.length, ok = false, recOk, recInSpecFilterFunc = this.getIsRecordInSpecFilterFunc(), // Funktion die zusätzliche Kriterien prüft (z.B. bei Teilleistungen in EditModus) recInExFilterFunc = this.isRecordInExFilterFunc, recInStoreFilter, // Record wird im Grid dargestellt; es können Records unterdrückt werden, die zwar den Standard-Filterkriterien, aber nicht ed Ex-Filter-Kriterien genügen recInStandardFilter, // Record, die den Standard-Filterkriterien genügen;wird nur im Grid dargestellt, wenn er auch den Ex-Filter-Kriterien genügt fn, cbStatus = this.cbLehrerStatus, lehrerStatus = (cbStatus && cbStatus.isVisible() && cbStatus.hasValue()) ? cbStatus.getValue() : '-', istLehrerStatusKoord = lehrerStatus === 'koord', istLehrerStatusKl = lehrerStatus === 'kl_alle' || lehrerStatus === 'kl_prim' || lehrerStatus === 'kl_stv', istLehrerStatusFl = lehrerStatus === 'fl_alle' || lehrerStatus === 'fl_prim' || lehrerStatus === 'fl_stv'; for (r = 0; r < lenRecords; r++) { rec = storeRecords[r]; recData = rec.data; if (recInSpecFilterFunc) recInStoreFilter = recInSpecFilterFunc( this, recData ); else recInStoreFilter = true; recInStandardFilter = true; for (i = 0; i < lenCrits; i++) // �ber die involvierten Filterkriterien iterieren { crit = crits[i]; if (crit.swFilterFunc) { if (crit.swFilterFunc( this, crit, recData )) continue; else { recInStoreFilter = false; recInStandardFilter = false; break; } } else if (crit.isSpecFilter) { // z. B. Combo für TL-Arten continue; } // Sonderbehandlung f�r die Felder "EingabeFertig" if (crit.field == 'ef_*') { ok = false; for (j = 0; j < lenEff; j++) { fn = eff[j], val = recData[fn]; // bei den Förderempfehlungen wird nicht der Text überprüft (leer oder nicht leer), // sondern die foemaGuid; diese existiert nur, wenn auch Foemas vorliegen if (fn === 'foema') val = recData['foemaGuid']; if (!ext.isEmpty(val) && recData['ef_'+fn] == '-') {// Eingabe noch nicht fertig ok = true; // noch nacharbeiten break; } } if (ok) continue; // n�chstes Filterkriterium else { recInStoreFilter = false; recInStandardFilter = false; break; } } // ENDE: Sonderbehandlung f�r die Felder "EingabeFertig" // Sonderbehandlung "LehrerStatus if (crit.field == 'lehrerStatus') { ok = (lehrerStatus === '-') || (istLehrerStatusKl && recData.alsKlassenLehrer && ( (lehrerStatus === 'kl_alle') || ((lehrerStatus === 'kl_prim') && (!recData.alsKlassenLehrerStv)) || ((lehrerStatus === 'kl_stv') && (recData.alsKlassenLehrerStv)) ) ) || (istLehrerStatusFl && recData.alsFachLehrer && ( (lehrerStatus === 'fl_alle') || ((lehrerStatus === 'fl_prim') && (!recData.alsFachLehrerStv)) || ((lehrerStatus === 'fl_stv') && (recData.alsFachLehrerStv)) ) ) || (istLehrerStatusKoord && recData.alsKoordinator ); if (!ok) { recInStoreFilter = false; recInStandardFilter = false; break; // nächster Record } continue; // nächstes Kriterium } val = recData[crit.field]; if (isEmpty(val)) { recInStoreFilter = false; recInStandardFilter = false; break; // nächster Record } if (crit.type == 'boolean') { if (val !== crit.value) { recInStoreFilter = false; recInStandardFilter = false; break; // nächster Record } } else { valIsNumber = !isNaN( val ); //nval = parseInt(val, 10); // fürt bei Klassenkürzeln im 'Float-Format' (z.B. "5.1" ) zu Problemen if (crit.field == 'klasse') nval = val; else if (crit.type === 'fachnote') { // Tendenznote für Leistungsdaten oder Teilleistung if (recData.tendenznote || recData.noteStattPunkteEingegeben) { if (valIsNumber) { nval = parseInt(val, 10); } else { // Tendenznote mit "+" oder "-"; // bei einem "+" wird die Note um 0,1 vermindert // bei einem "-" wird die Note um 0,1 erhöht val = parseInt( val.charAt(0), 10 ) + (val.charAt(1) === "+" ? -0.1 : 0.1); nval = val; } } } else nval = parseInt(val, 10); // Number if (!isNaN(val)) { switch (crit.comparison) { case '=' : if (nval != crit.value) { // nächster Record recInStoreFilter = false; recInStandardFilter = false; } break; case '<' : if (nval >= crit.value) { // nächster Record recInStoreFilter = false; recInStandardFilter = false; } break; case '>' : if (nval <= crit.value) { // nächster Record recInStoreFilter = false; recInStandardFilter = false; } break; } if (!recInStandardFilter) break; } // STRING else { val = val.toUpperCase(); if (crit.field == 'nname') { // partiell suchen if (val.indexOf( crit.value ) == -1) { recInStoreFilter = false; recInStandardFilter = false; break; // nächster Record } } else { if (val !== crit.value) { recInStoreFilter = false; recInStandardFilter = false; break; // nächster Record } } } } } // OK if (recInStoreFilter) filterHash[recData.id] = true; if (recInSpecFilterFunc && recInStandardFilter) recordsInStandardFilter.push( rec ); } this.filterHash = filterHash; if (recInExFilterFunc) this.recordsInStandardFilter = recordsInStandardFilter; }, // Callback für applyFilter filterFunc: function( rec ) { var me = this, crits = me.filterCriterias, crit, recData = rec.data, val, nval, cval, i, j, isEmpty = Ext.isEmpty, istFa; for (i = 0; i < crits.length; i++) // �ber die involvierten Filterkriterien iterieren { crit = crits[i]; // Sonderbehandlung f�r die Felder "EingabeFertig" if (crit.field == 'ef_*') { var eff = me.eingabeFertigFields, ok = false, fn; for (j = 0; j < eff.length; j++) { fn = eff[j], val = recData[fn];; if (!isEmpty(val) && recData['ef_'+fn] == '-') {// Eingabe noch nicht fertig ok = true; // noch nacharbeiten break; } } if (ok) continue; // n�chstes Filterkriterium else return false; } // ENDE: Sonderbehandlung f�r die Felder "EingabeFertig" val = recData[crit.field]; if (isEmpty(val)) return false; if (crit.type == 'boolean') { if (val !== crit.value) return false; } else if (crit.type === 'fachnote') { } else { nval = parseInt(val, 10); // Number if (!isNaN(val)) { switch (crit.comparison) { case '=' : if (nval != crit.value) return false; break; case '<' : if (nval >= crit.value) return false; break; case '>' : if (nval <= crit.value) return false; break; } } // STRING else { val = val.toUpperCase(); if (crit.field == 'nname') { // partiell suchen if (val.indexOf( crit.value ) == -1) return false; } else { if (val !== crit.value) return false; } } } } return true; }, /** * Handler für die Filter-Komponenten * */ onApplyFilter: function() { this.applyFilter( false, false ); }, applyFilter: function( needFilterComboRefresh, setSelection ) { if (!this.filterLoaded || this.filterLocked) return; var me = this, cmpIds = me.filterCmpIds, filterCmps = me.filterCmps, cmp, cbRel, itemId, val, valIsNumber, crit, nval, ext = Ext, isString = ext.isString, isNumber = ext.isNumber, filterbar = me.filterbar, criterias = [], nInvalidCriterias = 0, canShowRecords = this.canShowRecords(), chr0, chr1; this.clearSelection(); if (needFilterComboRefresh) this.fillFilterCombos(); // Filterkriterien zusammenstellen if (canShowRecords) { for (var i = 0; i < cmpIds.length; i++) { //cmp = filterbar.down( '#' + cmpIds[i] ); cmp = filterCmps[i]; if (!cmp.isVisible()) continue; if (cmp.getIsValidFilterCmp && !cmp.getIsValidFilterCmp.call( this, cmp )) // z. B. FOEMA; CB-DatumBis-Typ und DTP-DatumBis sind nur 'brauchbar', // wenn in beiden Konponenten ein Wert steht continue; val = cmp.getValue(); if (Ext.isEmpty(val)) continue; crit = { cmpId: cmpIds[i], cmpXtype: cmp.xtype, type : 'string', field: cmp.field, value: undefined, rawValue: val, comparison: '=', swFilterFunc: cmp.swFilterFunc, isSpecFilter: cmp.isSpecFilter }; // if (crit.isSpecFilter) { // } // if (cmp.xtype == 'swcombo') { if (isString( val )) { val = val.trim().toUpperCase(); if (val == '-') continue; } else if (isNumber( val )) { if (val === 0) continue; } else continue; // if (val.is) // if (cmp.itemId !== 'cbKurs' && cmp.itemId !== 'cbFach') { // val = val.trim().toUpperCase(); // if (val == '-') // continue; // } // else { // bei Kursen/Fächern wird die ID als Kriterium verwendet // if (val === 0) // continue; // } } else if (cmp.xtype == 'checkbox' ) { if (val === false) continue; crit.type = 'boolean'; } else if (cmp.xtype == 'datefield' ) { crit.type = 'date'; } else // 'textfield' { val = val.trim(); if (cmp.itemId === 'edName') { // Schülername val = val.toUpperCase(); } else { // Noten oder Fehlstunden. crit.tendenznotenMoeglich = cmp.tendenznotenMoeglich; valIsNumber = !isNaN(val); if (val.length > 2 || (!valIsNumber && !cmp.tendenznotenMoeglich)) { val = null; nInvalidCriterias++; } else if (cmp.tendenznotenMoeglich) //------------------------------------------------ // Fach-Note (Leistungsdaten oder Teilleistungen) //------------------------------------------------ { crit.type = 'fachnote'; chr0 = val.charAt(0); chr1 = val.length === 2 ? val.charAt(1) : undefined; if (valIsNumber) { val = parseInt(val, 10); // Number } else // der Wert enthält nichtnumerische Zeichen { if (val.length === 2 && !isNaN( chr0 ) && (chr1 == '+' || chr1 === '-')) { // gültige Tendenznote crit.istTendenznote = true; val = parseInt(chr0, 10) + (chr1 === "+" ? -0.1 : 0.1); } else { val = null; nInvalidCriterias++; } } } //------------------------------------------------ // Andere Noten oder Fehlstunden //------------------------------------------------ else if (valIsNumber) // 'numerische' Note/Fehlstunde { val = parseInt(val, 10); // Number crit.type = 'number'; } else // KEIN numerischer Wert { val = null; nInvalidCriterias++; } //------------------------------------------------ // RelationCombobox // "=" oder "<" oder ">" //------------------------------------------------ if (val !== null) { cbRel = me.filterbar.down( '#' + cmp.relCmp ); if (cbRel) crit.comparison = cbRel.getValue(); } } } if (val !== null) { if (!crit.isSpecFilter) { crit.value = val; } criterias.push( crit ); } } if (criterias.length == 0) { // && !this.getIsRecordInSpecFilterFunc()) { // zusätzlich zu den Standard-Kriterien kann noch eien "erweiteret Filterfunktion" aktiv sein (z.B. wenn Teilleistungen im EditModus) // KEINE gültigen Filterkriterien vorhanden. // Wenn der Filter aktive ist, dann wird er zurückgesetz, // falls es keine un if (me.filterActive && nInvalidCriterias === 0) { this.clearFilter( false ); } return; } } else { if (this.filterCriterias === 'hideall') return; criterias = 'hideall'; } try { Ext.suspendLayouts(); me.filterActive = true; me.filterCriterias = criterias; // einer abgeleitetn Klasse vor dem Filtern die Möglichkeit geben, // die aktuellen Filterkriterien zu puffern. // z. B. die FM-spezifischen Kriterien, die zum Filtern der FM benötigt werden this.onFilterCriteriasChange(); this.prepareFilter(); me.store.filterBy( me.filterFunc2, me ); me.enableActions(); if (setSelection === undefined || setSelection) me.initSelection( true ); if (this.applyDetaislFilter) this.applyDetaislFilter(); this.doAfterApplyFilter( needFilterComboRefresh ); } finally { Ext.resumeLayouts(true); } }, /** * @virtual * @param {type} resetCmp * @returns {undefined} */ onFilterCriteriasChange: function() {}, clearFilter: function( resetCmp ) { var me = this, fltrCmps = me.filterCmpIds, fb = me.filterbar, cmp, canShowRecords = this.canShowRecords(), suppressEvent = !resetCmp; // ? undefined : true; function resetComponents() { if (!resetCmp) return; var cmp, i = 0, len = fltrCmps.length; me.filterLoaded = false; // unterbindet den Aufruf von applyFilter() for (; i < len; i++) { cmp = fb.down( '#' + fltrCmps[i] ); if (cmp.xtype == 'swcombo' ) cmp.setValue( '-' ); else // Editor cmp.setValue( '' ); } me.filterLoaded = true; }; if (this.needMinimumFilterCriterias) { resetComponents(); this.applyFilter(); return; } me.filterActive = false; // einer abgeleitetn Klasse vor dem Filtern die Möglichkeit geben, // die aktuellen Filterkriterien zu puffern. // z. B. die FM-spezifischen Kriterien, die zum Filtern der FM benötigt werden this.onFilterCriteriasChange(); this.clearSelection(); me.store.clearFilter(); resetComponents(); me.filterCriterias = []; me.recordsInStandardFilter = undefined; this.fillFilterCombos(); me.initSelection( true ); me.enableActions(); me.doAfterApplyFilter(); }, // overload getRequiredHotkeys: function ( hotkeys ) { var me = this; if (me.actionHandler) me.actionHandler.getRequiredHotkeys( hotkeys ); }, // overload // Handler f�r die [ALT]-Keys processKey: function( keyCode, e ) { var me = this, ix, btn, chr = String.fromCharCode( keyCode ), actions = me.actions, ac; return me.actionHandler.processKey( keyCode, e ); /* for (var i = 0; i < actions.length; i++ ) { ac = actions[i]; if (ac.hotkey !== chr) continue; btn = ac.btn; if (!btn.isDisabled()) { btn.handler.call( btn.scope, me, e); } e.stopEvent(); return true; // keyCode wurde verarbeitet } */ return false; }, // overload // Prueft, ob ein Editor aktiv ist; // wenn ja wird gepr�ft, ob die aktuelle Eingabe gueltig ist ////commit: function() validateCurrentInput: function() { var me = this, ce = me.dataHandler.cellEditing, activeEdit = this.dataHandler.activeEdit; // ist Editor aktiv? if (!ce || !ce.editing) return true; ce.completeEdit(); if (activeEdit && activeEdit.editor !== null) return activeEdit.valid === true; else return true; // JA, aktuelle Eingabe pr�fen //result = me.pruefeEingabe( ) }, onGridAfterScroll: function( dataHandler, newRecord ) { this.enableActions(); }, // override // wird aufgerufen, bevor das TabSheet aktiviert wird beforeSheetShow: function() { var me = this; if (me.grid) // grid bereits erstellt return true; me.enableActions(); }, // override // wird aufgerufen, nachdem das TabSheet das erste mal aktiviert wurde afterSheetShow: function() { var me = this, grid = this.grid; //getEditGrid(); if (this.loadingData) return; if (!this.dataLoaded) { this.loadStore(); return; } if (!me.visible) { me.visible = true; this.initSelection(); } // Focus auf das Grid grid.getView().focus( false, 10 ); // delay ist notwendig, da andernfalls der Focus direkt wieder entzogen wird }, // wird beim Resume aufgerufen, nachdem der Store wieder geladen wurde //finishResume: function() applyCachedState: function() { var me = this, svs = me.cachedState, modifData = svs ? svs.modifData : {}, md, grid = this.getEditGrid(), store = grid.store, cmpIds = me.filterCmpIds, cmp, cbRel, filterbar = me.filterbar, fCrits, fCrit, row, rec, text, prop, selOk = false, i; if (!svs) { me.filterLoaded = true; // applyFilter() kann nun aggieren return; } // zuerst die modifizierten, aber noch nicht abgespeicherten Werte zurückschreiben if (!this.ignoreCachedModifData) { for (i = 0; i < modifData.length; i++) { md = modifData[i]; rec = store.findRecord( 'id', md.id, 0, false, false, true ); if (!rec) continue; for (prop in md) { if (prop !== 'id') rec.set( prop, md[prop] ); } } } // ggf. Filterkriterien setzen and anwenden if (svs.filtered) { fCrits = svs.filterCriterias; if (fCrits.length > 0) // muss nicht sein for (i = 0; i < fCrits.length; i++) { fCrit = fCrits[i]; cmp = filterbar.down('#' + fCrit.cmpId); if (!cmp) continue; switch (fCrit.cmpXtype) { case 'swcombo' : cmp.setValue( fCrit.rawValue ); break; case 'checkbox' : cmp.setValue( fCrit.rawValue ); break; case 'textfield' : cmp.setValue( fCrit.rawValue ); if (cmp.relCmp) { cbRel = me.filterbar.down( '#' + cmp.relCmp ); cbRel.setValue( fCrit.comparison ); } break; } } // vor dem Filtern den abgeleiteten Klassen die Möglichkeit für weitere Vorbereitungen geben this.onApplySaveState( svs ); me.filterLoaded = true; // applyFilter() kann nun aggieren me.applyFilter( true ); } else { // vor dem Filtern den abgeleiteten Klassen die Möglichkeit für weitere Vorbereitungen geben this.onApplySaveState( svs ); me.filterLoaded = true; // applyFilter() kann nun aggieren //this.fillFilterCombos(); this.doAfterApplyFilter(); // noch ein paar Initialisierungen } }, doAfterApplyFilter: function( needFilterComboRefresh ) { this.afterApplyFilter(); this.setTitelNotenspalte(); }, clearSelection: function() { var me = this, grid = this.getEditGrid(), selModel = grid.getSelectionModel(), sel = selModel.getSelection(); if (sel) selModel.deselect( selModel.getSelection(), true ); }, // wird aufgerufen // a) nachdem das Tabsheet das erste mal angezeigt wird, oder // b) nachdem der Filter geaendert wurde // // zu a: wenn nötig/möglich, wird die in der letzten Sitzung aktive Zelle selektiert // und der zuvor aktive Editor reaktiviert // zu b : es wird der erste Datensatz selektiert initSelection: function( filterChanged ) { var me = this, svs = me.cachedState, store = me.store, grid = this.grid, // this.getEditGrid(), row, col, colIx = -1, rec, text, selOk = false, selModel = grid.getSelectionModel(), editor; function setSelPosition( row, col ) { if (grid.selType === 'rbkcellmodel') { if (col == undefined || col == null) col = 0; if (Ext.isNumber( col )) selModel.setCurrentPosition({row: row, column: col}); else selModel.setCurrentPosition({row: row, columnHeader: col}); } else selModel.select( row ); } if (filterChanged || !svs) { //selModel.deselect( selModel.getSelection(), true ); if (this.store.data.length > 0) setSelPosition( 0, 0 ); return; } // den zuletzt aktiven Datensatz selektieren if (svs.activeRecord && svs.activeColumn) { selOk = true; col = Rbk.grid.Tools.columnByFieldName( grid, svs.activeColumn.field); selOk = !Ext.isEmpty( col ); if (selOk) { row = store.findExact( 'id', svs.activeRecord.id ); if (row > -1) setSelPosition( row, col ); else selOk = false; } else selOk = false; if (!selOk) setSelPosition( 0, col ); } // ggf. CellEditor oder InputWindow starten if (selOk && svs.activeRecord.editing) { text = svs.activeRecord.editorText; rec = me.getActiveRecord(); if (svs.activeRecord.editor == 'celleditor') { if (me.dataHandler.cellEditing) { editor = col.getEditor(); if (editor) { editor.setValue( text ); if (editor.focus) editor.focus( true, 100 ); me.dataHandler.startEdit( rec, col ); } } } else { // inputWindow me.openInputWindow( rec, row, col, text, svs.activeRecord.editorNacharbeiten ); //me.openInputWindow( rec, row, svs.activeColumn.index, text, svs.activeRecord.editorNacharbeiten ); } } }, /* OBSOLET createGrid: function() { var me = this; me.grid = Ext.create('Ext.grid.Panel', { store: me.store, stateful: true, stateId: 'stateGrid', selectOnFocus: true, scroll: 'both', selModel: { selType: 'cellmodel' }, viewConfig: { stripeRows: true, loadMask:false }, plugins: [me.cellEditing], features: { ftype: 'filters', //encode: encode, local: true, //local, filters : me.getFilterDef() }, columns: me.getColumnsDef() }); //----------------- // EVENTS me.grid.on('focus', me.onFocus, me ); me.grid.on('beforeedit', me.onGridBeforeEdit, me ); me.grid.on('edit', me.onGridAfterEdit, me ); me.grid.on('beforeselect', me.onGridBeforeSelect, me ); me.grid.on('selectionchange', me.onGridSelectionChange, me ); }, */ pruefeNote: function( value, benoetigtPunkte, tendenznotenErlaubt ) { var errMsg = "", notenStattPunkte = benoetigtPunkte && this.getNotenStattPunkte(), moeglicheNote = "", val; if (typeof( value ) == 'string' ) value = value.trim(); else if (value == '0' || value === null) value = ""; if (value !== "") // zulassen, wenn alter Wert geloescht wird { if (this.isNotenKuerzel( value )) { // 'E1' .... } else if (!benoetigtPunkte || notenStattPunkte) { moeglicheNote = notenStattPunkte || tendenznotenErlaubt ? "1- 1 1+ 2- 2 2+ 3- 3 3+ 4- 4 4+ 5- 5 5+ 6" : "1 2 3 4 5 6"; //if (moeglicheNote.search(value) == -1) // string.search arbeitet mit regul�ren Ausdr�cken; kann also so nicht verwendet werden if (moeglicheNote.indexOf(value) == -1) { errMsg = 'Der von Ihnen eingegebene Wert ist keine gültige Note.
' + ' Erlaubt: ' + moeglicheNote + '
' + ' oder (E1, E2, E3, NT, AT)'; } } else { val = parseInt(value, 10); if (isNaN(value) || (val > 15) || (val < 0)) { errMsg = 'Der von Ihnen eingegebene Wert ist keine gütige Punkteeingabe.
' + ' Erlaubt: (0 - 15) oder (E1, E2, E3, NT, AT)' ; } } } return errMsg; }, /** * Prüft, ob es sich bei {fieldName} um ein Noten-Feld handelt * @virtual * @param {string} fieldName * @returns {Boolean} */ fieldIsNote: function ( fieldName ) { return (fieldName === this.editFieldNote1) || (fieldName === this.editFieldNote12); }, // Validierung des aktuellen ZellEditor-Wertes pruefeEingabe: function(showError) { var me = this, activeEdit = this.dataHandler.activeEdit, editor = activeEdit ? activeEdit.editor : null, context = activeEdit ? activeEdit.context : null; if (!context) return false; var record = context.record, field = context.field, value = editor.getValue(), val, fldNote1 = me.editFieldNote1, fldNote2 = me.editFieldNote2, fldFsu = me.editFieldFsu, fldFsg = me.editFieldFsg, fsg, fsu, moeglicheNote, benoetigtPunkte = record.data.benoetigtPunkte, notenStattPunkte = benoetigtPunkte && this.getNotenStattPunkte(), errMsg = ""; if (me.activeMessageBox !== null) { // aus irgend einem Grund wird Editor.beforecomplete (ruft pruefeEingabe() auf) // doppelt aufgerufen; Nach dem ersten Aufruf wird bei einer ung�ltigen Eingabe d // ie ErrorMsgBox angezeigt (Referenz in me.activeMessageBox).; // Wenn die MsgBox also bereits angezeigt wird, dann ist eine zweite Validierung �berfl�ssig; // (w�rde zudem zu einer doppelten Anzeige der MsgBox f�hren) return activeEdit.valid === true; } if (this.fieldIsNote( field )) // if ((field === fldNote1) || (field === fldNote2)) { errMsg = this.pruefeNote( value, benoetigtPunkte, record.data.tendenznote ); // if (typeof( value ) == 'string' ) // value = value.trim(); // else if (value == '0' || value === null) // value = ""; // // if (value !== "") // zulassen, wenn alter Wert geloescht wird // { // if (this.isNotenKuerzel( value )) { // // 'E1' .... // } // // else if (!benoetigtPunkte || notenStattPunkte) // { // moeglicheNote = notenStattPunkte || (record.data.tendenznote) // ? "1- 1 1+ 2- 2 2+ 3- 3 3+ 4- 4 4+ 5- 5 5+ 6" // : "1 2 3 4 5 6"; // // //if (moeglicheNote.search(value) == -1) // // string.search arbeitet mit regul�ren Ausdr�cken; kann also so nicht verwendet werden // if (moeglicheNote.indexOf(value) == -1) // { // errMsg = 'Der von Ihnen eingegebene Wert ist keine gültige Note.
' + // ' Erlaubt: ' + moeglicheNote + '
' + // ' oder (E1, E2, E3, NT, AT)'; // } // } // else // { // val = parseInt(value, 10); // if (isNaN(value) || (val > 15) || (val < 0)) // { // errMsg = 'Der von Ihnen eingegebene Wert ist keine gütige Punkteeingabe.
' + // ' Erlaubt: (0 - 15) oder (E1, E2, E3, NT, AT)' ; // } // } // } } else if ((field === fldFsu) || (field === fldFsg)) { // value is Number if (Ext.isEmpty( value )) value = 0; if (field === fldFsu) { fsu = value; fsg = record.data[fldFsg]; } else { fsu = record.data[fldFsu]; fsg = value; } if (fsu > fsg) { errMsg = "Die unentschuldigten Fehlstunden können nicht
höher als die gesamten Fehlstunden sein."; } } activeEdit.valid = errMsg === ""; if (errMsg !== "" && showError) { me.activeMessageBox = Rbk.SysUtils.errorBox( errMsg, this.callbackEingabeFehler, me, editor.field, {} ); } return activeEdit.valid === true; }, // wird von " Rbk.Utils.errorBox" aufgerufen callbackEingabeFehler: function( btn, txt, cfg) { var me = this, grid = this.getEditGrid(), opts = cfg.opts, activeEdit = this.dataHandler.activeEdit, context = activeEdit.context, editor = activeEdit.editor, cellEdit = this.dataHandler.cellEditing; this.dataHandler.suppressEvents++; this.dataHandler.suppresseEditValidation++; try { grid.getSelectionModel().setCurrentPosition({record: context.record, row: context.row, columnHeader: context.columnHeader, column: context.column }); grid.getView().focus(); //( false, 10 ); this.dataHandler.activeEdit.editor.focus( true, 10 ); } finally { this.dataHandler.suppressEvents--; this.dataHandler.suppresseEditValidation--; } me.activeMessageBox = null; }, // liefert ALLE geaenderten Records, // auch die ausserhalb des Filters getModifiedRecords: function() { var me = this, store = this.getEditStore(), data = store.snapshot || store.data; return data.filterBy( store.filterUpdated ).items; }, getModifiedRecordCount: function(forSave) { return this.getModifiedRecords(forSave).length; }, commitChanges: function( modifStoreRecords, savedRecords ) { var me = this, recs = modifStoreRecords || this.getModifiedRecords(), // ALLE, auch die ausserhalb des Filters rec, savedFields, len, i; for (i = 0, len = recs.length; i < len; i++) { rec = recs[i]; savedFields = savedRecords[rec.data.id]; if (savedFields) rec.commit( false, savedFields ); } }, getRejectRecords: function() { return this.getModifiedRecords(); }, rejectChanges: function() { var me = this, recs = me.getRejectRecords(), len = recs.length, i = 0, rec; for (; i < len; i++) { rec = recs[i]; rec.reject(); if (rec.phantom) { me.store.remove(rec); } } }, /** * liefert die Daten aller modifizierten Datensaetze zum Speichern in der DB.
* * Diese müssen nicht unbedingt mit dem {data}-Property der modifizierten Store-Records üvbereinstimmen * (z.B. bei den Teilleistungen; dort enthält ein Store-Record die Dten mehrerer Teilleistungs-Datensätze). * * @param {Array} modifStoreRecords Ein Array, in dem die modifizeirten Store-Records zurückgegeben werden * @returns {Array} Die geanderten Daten */ getDataToSave: function( modifStoreRecords ) { var me = this, modifiedRecords = this.getModifiedRecords(), dataToSave = [], storeRecord; for(var i = 0, len = modifiedRecords.length; i < len; i++) { storeRecord = modifiedRecords[i]; if (this.getRecordDataToSave( storeRecord, dataToSave ) && modifStoreRecords) modifStoreRecords.push( storeRecord ); } return dataToSave; }, /** * liefert die Daten des aktuellen DAtensatz zum Speichern in der DB, wenn dieser geändert wurde.
* * Diese müssen nicht unbedingt mit dem {data}-Property der modifizierten Store-Records üvbereinstimmen * (z.B. bei den Teilleistungen; dort enthält ein Store-Record die Dten mehrerer Teilleistungs-Datensätze). * * @param {Array} modifStoreRecords * Ein Array, in dem die modifizeirten Store-Records zurückgegeben werden * @returns {Array} Die geanderten Daten */ getCurrentRecordModifData: function( modifStoreRecords ) { var storeRecord = this.getActiveRecord(), dataToSave = []; if (!storeRecord || !storeRecord.dirty) return null; if (this.getRecordDataToSave( storeRecord, dataToSave ) && modifStoreRecords) modifStoreRecords.push( storeRecord ); return dataToSave; }, /** * @virtual * Prüft, ob die in Änderungen in einem Recorde gespeichert werden können.
* * Dies ist z. B. nicht der Fall, wenn die Änderungen nach dem Login aus dem Zwischenspeicher stammen * (Autologout oder Sperren), die Eingabefrist für diese Daten aber zwischenzeitig abgelaufen ist. */ canSaveModifRecord: function( modifStoreRecord ) { return true; }, /** * @virtual * liefert die Daten des aktuellen DAtensatz zum Speichern in der DB, wenn dieser geändert wurde.
* * Diese müssen nicht unbedingt mit dem {data}-Property der modifizierten Store-Records üvbereinstimmen * (z.B. bei den Teilleistungen; dort enthält ein Store-Record die Dten mehrerer Teilleistungs-Datensätze). * * @param {type} modifStoreRecord * @param {type} modifData * @returns {undefined} */ getRecordDataToSave: function( modifStoreRecord, dataToSave ) { if (this.canSaveModifRecord( modifStoreRecord )) { dataToSave.push( modifStoreRecord.data ); return true; } else return false; }, // // False, wenn noch nicht gespeicherte Daten vorliegen // canClose: function() // { // return this.getModifiedRecordCount() == 0; // }, // onUserConfigChanged: function( newCfg ) { if (!Ext.isEmpty( newCfg.schalterMitBeschriftung)) this.actionHandler.setButtonTextVisibilty( newCfg.schalterMitBeschriftung ); if (!Ext.isEmpty( newCfg.spalteFehlstundenAutomatischAusblenden)) this.showFehlstundenSpalte(); }, /** * Listener für den User-Event "HasModifData" * @returns {boolean} Liefert FALSE, wenn geänderte Daten vorliegen */ onUserEventHasModifData: function() { // ACHTUNG: der Rückgabewert ist 'invers' zur eigentlichen Bedeutung return !this.hasModifData(); }, /** * Listener für den User-Event "GetModifData".
* * Der Event wird beim Shutdown ausgelöst. * * @param {type} user * @param {object} data * @returns {Boolean} */ onUserEventGetModifData: function( user, data) { var propName = this.prefix + 'Data'; data[propName] = this.getDataToSave(); return true; }, /** * Listener für den User-Event "GetCacheData" * @param {type} user * @param {boolean} onlyModifData * @param {object} cacheData * @returns {Boolean} */ onUserEventGetCacheData: function( user, onlyModifData, cacheData) { // die geänderten Daten und einige andere Parameter (Filter, aktiver Editor etc) werden 'gecached' if (!this.dataHandler) // Sheet ist nicht initialisiert return; var me = this, activeEdit = this.dataHandler.activeEdit, rec = me.getActiveRecord(), grid = this.getEditGrid(), cell = grid.getSelectionModel().getCurrentPosition(), modifiedRecords = me.getModifiedRecords(), modifData = [], data, propName = this.prefix + 'Data', md, prop, i, j, svs = { filtered : false }; // ggf. Filter-Kriterien speichern if (!onlyModifData && me.store.isFiltered()) { svs.filtered = true; svs.filterCriterias = me.filterCriterias; } else svs.filtered = false; // Aktive Zelle if (!onlyModifData && cell && cell.columnHeader && !Ext.isEmpty(cell.columnHeader.dataIndex)) { svs.activeColumn = {}; svs.activeColumn.index = cell.column; svs.activeColumn.field = cell.columnHeader.dataIndex; } // Aktiver Datensatz if (!onlyModifData && svs.activeColumn && rec) { data = rec.data; svs.activeRecord = {id: data['id']}; svs.activeRecord.editing = false; // Cell-Editor aktiv? //if (me.cellEditing.editing) { if (activeEdit.editor) { svs.activeRecord.editing = true; svs.activeRecord.editor = 'celleditor'; svs.activeRecord.editorText = activeEdit.editor.getValue(); } // InputWindow aktiv ? else if (me.activeInputWindow) { var val = me.activeInputWindow.getValue(); svs.activeRecord.editing = true; svs.activeRecord.editor = 'inputwindow'; svs.activeRecord.editorText = val[0]; svs.activeRecord.editorNacharbeiten = val[1]; } } // alle nicht gespeicherten Aenderungen sichern for(i = 0; i < modifiedRecords.length; i++) { rec = modifiedRecords[i]; data = rec.data; // enthält u.a. die modifizierten Werte md = Ext.merge( {}, rec.modified); // "rec.modified" enthält die geaenderten Felder, allerdings mit dem alten Wert for (prop in md) { md[prop] = data[prop]; } md.id = data.id; modifData.push( md ); } if (!onlyModifData || modifData.length > 0) { svs.modifData = modifData; cacheData[propName] = svs; } return true; }, /** * Listener für den User-Event "StandardConfigChange" * @param {type} oldCfg * @param {type} newCfg * @returns {undefined} */ onUserEventStandardConfigChange : function( oldCfg, newCfg ) { var prop = this.prefix.toLowerCase() + 'Data'; if (!this.notenPunkteColumns || newCfg[prop].notenStattPunkte === oldCfg[prop].notenStattPunkte) return ; this.setTitelNotenspalte(); this.swapNotenPunkte(); this.grid.getView().refresh(); if (this.grid !== this.getEditGrid()) this.getEditGrid().getView().refresh(); }, /** * Listener für den User-Event "GetCurrentConfig" * * @param {Swnm.User} user * @param {Object} currentConfig * @returns {Boolean} */ onUserEventGetCurrentConfig: function( user, currentCfg ) { var propName = this.prefix.toLowerCase() + 'Data'; if (!currentCfg[propName]) currentCfg[propName] = {}; if (!currentCfg[propName].grid) currentCfg[propName].grid = {}; if (this.detailsContainer) { currentCfg[propName].grid.width = this.grid && this.grid.el && this.grid.getWidth ? this.grid.getWidth() : this.initialGridWidth; if (!currentCfg[propName].detailsContainer) currentCfg[propName].detailsContainer = {}; //currentCfg[propName].detailsContainer.width = this.detailsContainer.getWidth(); if (this.detailsGrid) { if (!currentCfg[propName].detailsContainer.grid) currentCfg[propName].detailsContainer.grid = {}; currentCfg[propName].detailsContainer.grid.columns = Rbk.grid.Tools.saveUserGridColumnCfg( this.detailsGrid ); } } currentCfg[propName].grid.columns = Rbk.grid.Tools.saveUserGridColumnCfg( this.grid ); }, isNotenKuerzel: function( n ) { var nk = this.notenKuerzel; // 'E1 E2 E3 AT AM NB NT NE LM'; return (!Ext.isEmpty(n)) && (n.length === 2) && (nk.indexOf( n ) > -1) ? true : false; }, /** * Behandelt die 'ENTER-Eingabe' in einem Spalteneditor. * Wenn die option 'Spalte beibehalten' markiert ist, dann wird in die nächste Zeie gewechselt * * @param {type} editor ist 'undefined', wenn die Methode von einer CheckColumn aufgerufen wird * @param {type} field * @param {type} event * @param {type} opts * @returns {Boolean} */ onEditorSpecialKey: function( editor, event, opts ) { var me = this, ce = this.dataHandler.cellEditing, keyCode = event.keyCode, editContext; if (keyCode !== 10 && keyCode !== 13) return true; // die eingabe wird bei einer Combobox ignoriert, wenn diese aufgeklappt ist if (editor && editor.xtype === 'combobox' && editor.isExpanded) return true; // wenn z. Z. ein Editor aktiv ist, dann wird die Eingabe gestoppt if (editor && ce.editing) { ce.completeEdit(); if (this.dataHandler.activeEdit.valid === false) { // ungültige Eingabe => Event abbrechen event.stopEvent(); return false; } } this.moveInputCell( editor, event.shiftKey ); // // //Rbk.Utils.log( 'GridEditor-ENTER'); // // var activeEdit = me.activeEdit, // rec = editor ? activeEdit.context.record : this.getActiveRecord(), // col = this.getActiveColumn(), // fieldName = col.dataIndex, // selModel = me.grid.getSelectionModel(), // newPos; // // // zur nächsten Spalte wechseln // // newPos = me.getNextInputCell( rec, fieldName, !event.shiftKey ); // // if (newPos !== false) { // selModel.setCurrentPosition({row: newPos.rowIx, column: newPos.colIx}); // // // wenn die neue Zelle über einen Editor vefügt (also keine Checkbox), // //dann wird der EditModus aktiviert // if (newPos.column.dataIndex !== 'mahnen') { // if (me.activeEdit.editor && me.activeEdit.editor.setFocus) // me.activeEdit.editor.setFocus( true, 10 ); // ce.startEdit( newPos.rec, newPos.column ); // } // //Rbk.Utils.log('START EDIT'); // } event.stopEvent(); return false; }, moveInputCell: function( editor, shiftPresses ) { var me = this, activeEdit = this.dataHandler.activeEdit, grid = this.getEditGrid(), selModel = grid.getSelectionModel(), // rec = editor ? activeEdit.context.record : this.getActiveRecord(), // col = this.getActiveColumn(), pos = selModel.getCurrentPosition(), rec = pos.record, col = pos.columnHeader, fieldName = col ? col.dataIndex : '', ce = this.dataHandler.cellEditing, newPos; if (!rec || !col) return; // zur nächsten Spalte wechseln newPos = me.getNextInputCell( rec, fieldName, !shiftPresses ); if (newPos !== false) { selModel.setCurrentPosition({row: newPos.rowIx, column: newPos.colIx}); // wenn die neue Zelle über einen Editor vefügt (also keine Checkbox), //dann wird der EditModus aktiviert if (newPos.column.dataIndex !== 'mahnen') { if (activeEdit.editor && activeEdit.editor.focus) { me.editorFocusCell = { cellEdit: ce, rec: newPos.rec, column: newPos.column }; activeEdit.editor.focus( true, 100 ); ce.startEdit( newPos.rec, newPos.column ); } else { if (!this.startEditDelayedTask) ce.startEdit( newPos.rec, newPos.column ); else // WENN IE this.startEditDelayedTask.delay( 100, this.startDelayedEdit, this, [ce, newPos.rec, newPos.column] ); } } } }, startDelayedEdit: function( cellEdit, rec, column ) { cellEdit.startEdit( rec, column ); }, // NUR ZUM DEBUGGEn onGridAfterRender: function() { RSU.log("onGridAfterRender"); }, doAfterEditorFocus: function() { var params = this.editorFocusCell; params.cellEdit.startEdit( params.rec, params.column ); }, /** * * @param {type} rec * @param {String} fieldName * @param {Boolean} foreward * @returns {Object|Boolean} */ getNextInputCell: function(rec, fieldName, foreward) { var me = this, store = this.getEditStore(), grid = this.getEditGrid(), gridCols = grid.columns, cols = {}, nCols = 0, col, fixInputCol = this.appSurface.fixInputCol, recIx = store.indexOf( rec ), recCount = store.getCount(), colIx, startIx, i, len; // Feste Spalte if (fixInputCol) { col = Rbk.grid.Tools.columnByFieldName( grid, fieldName ); if (foreward) recIx++; else recIx--; while (foreward ? recIx < recCount : recIx >= 0) { rec = store.getAt( recIx ); if (me.canEditCell( rec, fieldName )) { return { rowIx: recIx, colIx: col.getIndex(), rec : rec, column : col }; } if (foreward) { recIx++; } else { recIx--; } } return false; } // Mit Spaltenwechsel var newCol; function getColAbsoluteIndex( col ) { for (var i = 0, len = gridCols.length; i < len; i++) { if (gridCols[i] === col) return i; } } function findForeward( fromIx ) { var col; for (var i = fromIx; i < nCols; i++) { col = cols[i]; if (me.canEditCell( rec, col.dataIndex)) { newCol = col; return col.getIndex(); } } return -1; } function findBackward( fromIx ) { var col; for (var i = fromIx; i >= 0; i--) { col = cols[i]; if (me.canEditCell( rec, col.dataIndex)) { newCol = col; return col.getIndex(); } } return -1; } // die sichtbaren Spalten in der aktuelle Reihenfolge ermitteln this.calcFixedCols(); cols = this.fixedCols; nCols = cols.length; // den Index der aktuellen Spalte im FixedCols-Array ermitteln for (i = 0, len = nCols; i < len; i++) { if (cols[i].dataIndex === fieldName) { startIx = i; break; } } startIx = foreward ? startIx + 1 : startIx -1; do { rec = store.getAt( recIx ); colIx = foreward ? findForeward( startIx ) : findBackward( startIx ); if (colIx > -1) return { rowIx: recIx, colIx: colIx, // aktueller Index (nicht der absolute Index) rec : rec, column : newCol }; if (foreward) { startIx = 0; recIx++; } else { startIx = nCols-1; recIx--; } } while (foreward ? recIx < recCount : recIx >= 0); return false; }, calcFixedCols: function() { var gridCols = this.grid.columns, col, i = 0, len = gridCols.length, cols = {}; cols = this.grid.headerCt.query('gridcolumn:not([hidden])'); this.fixedCols = []; for (i = 0, len = cols.length; i < len; i++) { col = cols[i]; if (col.isFixCol) { this.fixedCols.push( col ); } } return; // zuerst die sichtbaren Cols mit ihrem aktuellen Index als Key // (== aktuelle Position) in einem Objekt sammeln for (; i < len; i++) { col = gridCols[i]; if (col.isVisible() && col.isFixCol) { cols[col.getIndex()] = col; } } this.fixedCols = []; for (i = 0; i < len; i++) { if (cols[i]) this.fixedCols.push( cols[i] ); } this.fixedColCount = this.fixedCols.length; }, afterInputWindowClosed: function( rowIx, colIx, openByReturnKey ) { // this.childWindowCloseTask.stop(); // Ext.TaskManager.stop( this.childWindowCloseTask ); // this.childWindowCloseTask.destroy(); //this.childWindowCloseTask.destroy(); // = null; var grid = this.getEditGrid(); grid.getSelectionModel().setCurrentPosition({row: rowIx, column: colIx}); grid.getView().focus(); //( false, 10 ); if (openByReturnKey) this.moveInputCell( false, false ); }, // Sortier-Function für die Schüler-Spalte der Gitter doSortSchuelerName: function( state ) { var me = this.sheet, store = me.store; if (!me.schuelerNameSorter) { me.schuelerNameSorter = Ext.create( "Ext.util.Sorter", { direction: 'ASC', sorterFn: function( v1, v2 ) { var ret = v1.data.nname.localeCompare( v2.data.nname ); if (ret === 0) ret = v1.data.vname.localeCompare( v2.data.vname ); return ret; } } ); } me.schuelerNameSorter.toggle(); store.sort(me.schuelerNameSorter); }, doSortFaecher: function( state ) { var me = this.sheet, store = me.store; if (!me.schuelerFaecherSorter) { me.schuelerFaecherSorter = Ext.create( "Ext.util.Sorter", { direction: 'ASC', sortHashKlassen : me.sortierungen.klassen, sortHashFaecher : me.sortierungen.faecher, sortHashKurse : me.sortierungen.kurse, sorterFn: function( v1, v2 ) { var data1 = v1.data, data2 = v2.data, klasse1 = data1.klasse, klasse2 = data2.klasse, sortHashKlassen = this.sortHashKlassen, srt1 = data1.ldSortierung, srt2 = data2.ldSortierung, ret; // nach Leitungsdaten-Sortierung (fächern) sortieren ret = srt1 < srt2 ? -1 : (srt1 > srt2 ? 1 : 0); if (ret !== 0) return ret; if (data1.fachId !== data2.fachId) { // zwei unterschiedliche Fächer können die gleiche SeqNo besitzen; z.B. Kath-Religion und Ev-Religion // => Fach-Bez. vergleichen ret = data1.fach.localeCompare( data2.fach ); if (ret !== 0) return ret; } // Sortierung nach Klassen srt1 = sortHashKlassen[klasse1]; srt2 = sortHashKlassen[klasse2], ret = srt1 < srt2 ? -1 : (srt1 > srt2 ? 1 : 0); if (ret === 0 && srt1 === 32000) { // wenn Sortierung nach SeqNo identisch und SeqNo == 32000 (üerhaupt keine Sortierung) // dann Sortierung nach Klasse ret = klasse1 = klasse2 ? 0 :(klasse1 < klasse2 ? -1 : 1); } // wenn gleich, dann nach namen sortieren if (ret === 0) { var ret = data1.nname.localeCompare( data2.nname ); if (ret === 0) ret = data1.vname.localeCompare( data2.vname ); } // sortierung nach Klassen und Name und immer aufsteigend if (this.direction === 'DESC') ret *= -1; return ret; } } ); } me.schuelerFaecherSorter.toggle(); store.sort(me.schuelerFaecherSorter); }, doSortKlassen: function(state) { var me = this.sheet, store = me.store; if (!me.schuelerKlassenSorter) { me.schuelerKlassenSorter = Ext.create( "Ext.util.Sorter", { direction: 'ASC', sortHashKlassen : me.sortierungen.klassen, sortHashFaecher : me.sortierungen.faecher, sortHashKurse : me.sortierungen.kurse, sorterFn: function( v1, v2 ) { var data1 = v1.data, data2 = v2.data, sortHashKlassen = this.sortHashKlassen, klasse1 = data1.klasse, klasse2 = data2.klasse, srt1 = sortHashKlassen[klasse1], srt2 = sortHashKlassen[klasse2], ret; // Sortierung nach SeqNo ret = srt1 < srt2 ? -1 : (srt1 > srt2 ? 1 : 0); if (ret !== 0) return ret; // wenn Sortierung nach SeqNo identisch und SeqNo == 32000 (üerhaupt keine Sortierung) // dann Sortierung nach Klasse if (srt1 === 32000) { ret = klasse1 = klasse2 ? 0 :(klasse1 < klasse2 ? -1 : 1); if (ret !== 0) return ret; } // wenn gleich, dann nach namen sortieren if (ret === 0) { var ret = data1.nname.localeCompare( data2.nname ); if (ret === 0) ret = data1.vname.localeCompare( data2.vname ); } // wenn gleich, dann nach Leitungsdaten-Sortierung (fächern) sortieren if (ret === 0) { srt1 = data1.ldSortierung; srt2 = data2.ldSortierung; ret = srt1 < srt2 ? -1 : (srt1 > srt2 ? 1 : 0); } // sortierung nach Name und Fächern immer aufsteigend if (this.direction === 'DESC') ret *= -1; return ret; } } ); } me.schuelerKlassenSorter.toggle(); store.sort(me.schuelerKlassenSorter); }, doSortKurse: function( state ) { var me = this.sheet, store = me.store; if (!me.schuelerKurseSorter) { me.schuelerKurseSorter = Ext.create( "Ext.util.Sorter", { direction: 'ASC', sortHashKlassen : me.sortierungen.klassen, sortHashFaecher : me.sortierungen.faecher, sortHashKurse : me.sortierungen.kurse, sorterFn: function( v1, v2 ) { var data1 = v1.data, data2 = v2.data, kursId1 = data1.kursId, kursId2 = data2.kursId, isEmpty = Ext.isEmpty, k1Empty = isEmpty( kursId1 ) || kursId1 == 0, k2Empty = isEmpty( kursId2 ) || kursId2 == 0, fachId1 = data1.fachId, fachId2 = data2.fachId, klasse1 = data1.klasse, klasse2 = data2.klasse, sortHashKurse = this.sortHashKurse, sortHashKlassen = this.sortHashKlassen, srt1 = !k1Empty ? sortHashKurse[kursId1] : 32000, srt2 = !k2Empty ? sortHashKurse[kursId2] : 32000, direction = this.direction, ret; // nach Kursen sortieren if (kursId1 === null || kursId1 === undefined || kursId1 == 0) { ret = 0; } if (!k1Empty && k2Empty) return this.direction == 'ASC' ? -1 : 1; // "MIT Kurs" immer vor "OHNE Kurs" else if (k1Empty && !k2Empty) return this.direction == 'ASC' ? 1 : -1; // "MIT Kurs" immer vor "OHNE Kurs" else if (!k1Empty && !k2Empty) { ret = srt1 < srt2 ? -1 : (srt1 > srt2 ? 1 : 0); if (ret !== 0) return ret; } // wenn gleich, dann Sortierung nach Fächern (Leistungsdaten-Sortierung) srt1 = data1.ldSortierung; srt2 = data2.ldSortierung; ret = srt1 < srt2 ? -1 : (srt1 > srt2 ? 1 : 0); if (ret !== 0) return ret; // wenn gleich, dann Sortierung nach Klassen srt1 = sortHashKlassen[klasse1]; srt2 = sortHashKlassen[klasse2], ret = srt1 < srt2 ? -1 : (srt1 > srt2 ? 1 : 0); if (ret === 0 && srt1 === 32000) { // wenn Sortierung nach SeqNo identisch und SeqNo == 32000 (üerhaupt keine Sortierung) // dann Sortierung nach Klasse ret = klasse1 = klasse2 ? 0 :(klasse1 < klasse2 ? -1 : 1); } // wenn gleich, dann nach namen sortieren if (ret === 0) { var ret = data1.nname.localeCompare( data2.nname ); if (ret === 0) ret = data1.vname.localeCompare( data2.vname ); } // sortierung nach Klassen und Name und immer aufsteigend if (this.direction === 'DESC') ret *= -1; return ret; } } ); } me.schuelerKurseSorter.toggle(); store.sort(me.schuelerKurseSorter); }, doSortNoten: function( state ) { var me = this.sheet, store = me.store; if (!me.schuelerNotenSorter) { me.schuelerNotenSorter = Ext.create( "Ext.util.Sorter", { direction: 'ASC', sorterFn: function( v1, v2 ) { var data1 = v1.data, data2 = v2.data, sn1 = data1.note, sn2 = data2.note, isEmpty = Ext.isEmpty, n1Empty = isEmpty( sn1 ), n2Empty = isEmpty( sn2 ), flag1 = !n1Empty && sn1.length === 2 ? sn1.charAt( 1 ) : '', flag2 = !n2Empty && sn2.length === 2 ? sn2.charAt( 1 ) : '', n1 = flag1 === '+' || flag1 === '-' ? parseInt( sn1.charAt(0) ) : parseInt( sn1, 10), n2 = flag2 === '+' || flag2 === '-' ? parseInt( sn2.charAt(0) ) : parseInt( sn2, 10), isNote1 = true, isNote2 = true, ret = undefined; if (n1Empty && n2Empty) ret = 0; else if (n1Empty) ret = -1; else if (n2Empty) ret = 1; if (ret === 1 || ret === -1) { return this.direction === 'ASC' ? -ret : ret; } if (ret === undefined) { if (isNaN(n1)) isNote1 = false; else { n1 = n1 * 10; if (flag1 === '+') n1--; else if (flag1 === '-') n1++; } if (isNaN(n2)) isNote2 = false; else { n2 = n2 * 10; if (flag2 === '+') n2--; else if (flag2 === '-') n2++; } if (!isNote1 && !isNote2) return sn1.localeCompare( sn2 ); if (!isNote1) ret = -1; if (!isNote2) ret = 1; if (ret === 1 || ret === -1) { return this.direction === 'ASC' ? -ret : ret; } if (ret === undefined) { if (data1.benoetigtPunkte && data2.benoetigtPunkte && !data1.noteStattPunkteEingegeben) {// Punkte n1 *= -1; n2 *= -1; } if (n1 === n2) ret = 0; else if (n1 < n2) return 1; else return -1; } } // ret === 0 // nach namen Sortieren var ret = data1.nname.localeCompare( data2.nname ); if (ret === 0) ret = data1.vname.localeCompare( data2.vname ); // Namen immer aufsteigend if (this.direction === 'DESC') ret *= -1; return ret; } } ); } me.schuelerNotenSorter.toggle(); store.sort(me.schuelerNotenSorter); }, onLehrerStatusChange: function() { if (!this.cbLehrerStatus) return; var newStatus = this.cbLehrerStatus.getValue(); if (newStatus === this.lehrerStatus) return; this.lehrerStatus = newStatus; this.applyFilter( true ); }, /** * @virtual */ getNeededActionIds: function() { return [{ menuItemId : 'mnuSave', disabled: true, iconCls : 'file-save', itemIds : [ 'Save', 'SaveRecord' ], title: 'Speichern' },{ menuItemId : 'mnuUndo', disabled: true, iconCls : 'undo', itemIds : [ 'Reset', 'ResetRecord' ], title: 'Rückgängig' }]; }, /** * @abstract * @returns {undefined} */ getNeededFilterItems: function() { return { name: false, lehrerstatus: false, klasse: false, fachid: false, kursart: false, kursid: false, mahnen: false, note: false, nacharbeiten: false, fsg: false, fsu: false, lbngw: false, lbnnw: false }; }, /** * @virtual * @returns {undefined} */ createActions: function() { var me = this; me.actionHandler.newAction([ { text: 'Alle Änderungen der ' + this.menuCaption + ' speichern (alle Datensätze)', itemId: 'Save', iconCls: 'file-save', hint: '' + 'Alle geänderten '+ this.menuCaption +' speichern.
' + '
' + 'Speichert alle Änderungen in der SchILD-Datenbank.
' + 'Es werden auch die Datensätze gespeichert, die
' + 'aktuell nicht sichtbar sind.', //hint: 'Alle geänderten Daten entgültig speichern.', hotkey: 'S', hkExtKey: 'alt', handler: this.saveStore, scope: me },{ text: 'Nur Änderungen am aktuellen Datensatz speichern', itemId: 'SaveRecord', iconCls: 'file-save', hint: '' + 'Aktuellen Datensatz speichern.
' + '
' + 'Speichert nur die Änderungen am aktuellen Datensatz in der SchILD-Datenbank.
', hotkey: 'P', hkExtKey: 'alt', handler: me.saveRecord, scope: me },{ text: 'Rückgängig (alle Datensätze)', itemId: 'Reset', iconCls: 'undo', hint: '' + 'Alle Änderungen der ' + this.menuCaption + ' zurücknehmen.
' + '
' + 'Alle geänderten Daten auf den zuletzt gespeicherten Stand zurücksetzen.
' + 'Alle eingegebenen Änderungen gehen dabei verloren.', hotkey: 'R', hkExtKey: 'alt', handler: me.resetStore, scope: me },{ text: 'Rückgängig (aktueller Datensatz)', itemId: 'ResetRecord', iconCls: 'undo', hint: '' + 'Die Änderungen am aktuellen Datensatz zurücknehmen.
' + '
' + 'Den aktuellen Datensatz auf den zuletzt gespeicherten Stand zurücksetzen.', hotkey: 'K', hkExtKey: 'alt', handler: me.resetRecord, scope: me },{ text: 'Notentabelle', itemId: 'ShowNotentabelle', iconCls: 'information', hint: 'Liste der Noten/Notenkürzel und ihre Bedeutung anzeigen', hotkey: 'L', // hidden: isNB, hkExtKey: 'alt', handler: this.showNotentabelle, scope: me },{ text: 'Einzelfehlstunden', itemId: 'EinzelFehlstunden', iconCls: 'user-minus', hint: 'Einzelfehlstunden eingeben oder bearbeiten', hotkey: '', hkExtKey: 'alt', handler: this.einzelFehlstundenBearbeiten, scope: me },{ text: 'Tabelle Drucken', itemId: 'Print', iconCls: 'print', hint: 'Aktuelle Tabelle ausdrucken.', hotkey: 'D', hkExtKey: 'alt', handler: this.print, scope: me },{ text: 'Filter zurücksetzen', itemId: 'btnClearFilter', iconCls: 'filter-reset', tooltip: 'Schaltet alle aktiven Filter aus.', hotkey: 'Z', hkExtKey: 'alt', handler: function() { me.clearFilter( true ); }, scope: me } ]); }, createFilterBar: function() { var me = this, items = [], user = this.user, fhk = Rbk.SysUtils.fmtHotkeyText, neededFilterItems = this.getNeededFilterItems(); me.filterCmpIds = []; me.filterCmps = []; /** * fuegt den items Spacer + Label + Combobox hinzu * @param {type} name * @param {string} field * @param {type} width * @param {type} matchFieldWidth * @param {type} visible * @param {type} listener * @param {type} storeData * @returns {undefined} */ function addCb( name, field, width, matchFieldWidth, visible, listener , storeData ) { if (!neededFilterItems[field.toLowerCase()]) return; if (visible === undefined) visible = true; listener = me.onFilterComboChange; items.push( { xtype: 'tbspacer', itemId: 'tbs' + name, width: 5, hidden: !visible },{ xtype: 'label', itemId: 'lbl' + name, text: name , hidden: !visible },{ xtype: 'swcombo', itemId: 'cb'+ name, hidden: !visible, kuerzelField: field === 'fachId' || field === 'kursId' ? 'kuerzel' : undefined, field: field, width: width, matchFieldWidth: matchFieldWidth, data: storeData, createDataMap : field === 'klasse' || field === 'kursart', listeners : { change: { scope: me, fn: listener } } // xtype: 'swcombo', // itemId: 'cb'+ name, // hidden: !visible, // kuerzelField: field === 'fachId' ? 'kuerzel' : undefined, // field: field, // width: width, // matchFieldWidth: matchFieldWidth, // data: storeData, // createDataMap : field === 'klasse' || field === 'kursart', // listeners : { // change: { // scope: me, // fn: listener // } // } } ); me.filterCmpIds.push( 'cb'+ name ); } // fuegt den items Spacer + RelationCombobox + Eingabefeld hinzu function addRel( displayName, name, field, tendenznotenMoeglich ){ if (!neededFilterItems[name.toLowerCase()]) return; items.push( { xtype: 'tbspacer', width: 5 },{ // Label xtype: 'label', text: displayName },{ // RelationCombobox xtype: 'swcombo', itemId: 'cbRel' + name, data : ['=', '<', '>'], width: 35, valueCmp: 'ed' + name, // itemID des nachfolgenden Eingabefldes listeners : { change: { scope: me, fn: me.onCbRelChange } } },{ // Eingabefeld xtype : 'textfield', itemId : 'ed' + name, field : field, width : 25, relCmp: 'cbRel' + name, // ItemId der zugeh�rigen RelationCombobox tendenznotenMoeglich: tendenznotenMoeglich !== undefined ? tendenznotenMoeglich : false, listeners : { change: { scope: me, fn: me.onApplyFilter } } } ); me.filterCmpIds.push( 'ed'+ name ); } if (neededFilterItems['name']) { items = [ //{ xtype: 'tbspacer', width: 5 }, { xtype: 'label', text: 'Filter', style: { "font-weight" : 'bold', "font-size": "12px", color: '#088' }, cls: 'x-panel-header-text-default' }, // NAME { xtype: 'tbspacer', width: 20 }, { xtype : 'textfield', itemId : 'edName', field: 'nname', emptyText: 'Name', width: 40, listeners : { change: { scope: me, fn : this.onApplyFilter } } } ]; me.filterCmpIds.push( 'edName' ); } addCb( 'Lehrerstatus', 'lehrerStatus', 100, false, false, me.onLehrerStatusChange, [ ['-', '-'], ['K', 'Klassenlehrer'], ['F', 'Fachlehrer'] ] ); addCb( 'Klasse', 'klasse', 70, false, true ); addCb( 'Fach', 'fachId', 70, false, true ); addCb( 'Kursart', 'kursart', 70, false, true ); addCb( 'Kurs', 'kursId', 70, false ); addRel( 'FSG', 'Fsg', me.editFieldFsg ); addRel( 'FSU', 'Fsu', me.editFieldFsu ); addRel( 'LBN GW', 'LbnGW', 'gn_gs' ); addRel( 'LBN NW', 'LbnNw', 'gn_nw' ); // Note addRel( 'Note', 'Note', 'note', true /*tendenznotenMoeglich*/ ); // Mahnen if (neededFilterItems['mahnen']) { items.push( ); items.push( { xtype: 'tbspacer', width: 5 }, { xtype: 'checkbox', itemId: 'ckMahnen', field: 'mahnen', hideLabel : true, boxLabel: 'Mahnen', listeners : { change: { scope: me, fn: me.onApplyFilter } } } // { // xtype: 'label', // text: 'Mahnen' // },{ // xtype: 'checkbox', // itemId: 'ckMahnen', // field: 'mahnen', // listeners : { // change: { // scope: me, // fn: me.applyFilter // } // } // } ); me.filterCmpIds.push( 'ckMahnen' ); } // Noch nacharbeiten if (neededFilterItems['nacharbeiten']) { items.push( { xtype: 'tbspacer', width: 5 }, { xtype: 'checkbox', itemId: 'ckNacharbeiten', field: 'ef_*', hideLabel: true, boxLabel : 'Nacharbeiten', listeners : { change: { scope: me, fn: me.onApplyFilter } } } ); me.filterCmpIds.push( 'ckNacharbeiten' ); } // z.B. bei Teilleistungen weiter Componenten einbauen this.extendFilterBar( items ); // ClearFilter-Button items.push( { xtype: 'tbspacer', width: 5 }, //{ xtype: 'tbfill' }, // elemente rechts ausf�llen { text: fhk('Filter $zurücksetzen'), itemId: 'btnClearFilter', iconCls: 'filter-reset', tooltip: 'Schaltet alle aktiven Filter aus.', handler: function() { me.clearFilter( true ); }, scope: me } ); var filterbar = Ext.create( 'Ext.toolbar.Toolbar', { itemId: 'filterbar', dock: 'top', height: 30, padding: "0 0 0 8", ui: "rbktb", defaultButtonUI: 'rbktb-toolbar', defaults: { margin: '0 2', ui: 'rbktb' }, items: items }); for (var i = 0, len = me.filterCmpIds.length; i < len; i++) this[me.filterCmpIds[i]] = filterbar.down( '#'+me.filterCmpIds[i] ); this.cbFilterKlasse = filterbar.down( '#cbKlasse' ); this.cbFilterFach = filterbar.down( '#cbFach' ); this.cbFilterKurs = filterbar.down( '#cbKurs' ); this.cbFilterKursart = filterbar.down( '#cbKursart' ); return filterbar; }, /** * Wird von 'ApplyFilter' abgefragt.
* * Bei manchen 'Datenarten' (z.B. Teilleistungen) werden die Datensätze erst dann angezeigt, * wenn mindesten eine Klasse+Fach oder ein Kurs ausgewählt wurde.
* * @returns {Boolean} */ canShowRecords: function() { if (!this.needMinimumFilterCriterias) return true; return (this.cbFilterKlasse.getValue() !== '-' && this.cbFilterFach.getValue() !== 0) || (this.cbFilterKurs.getValue() !== 0); }, /** * @virtual; */ extendFilterBar: function( filterBarItems ) { }, /** * @virtual; */ extendToolBar: function( toolbarItems ) { }, getIsRecordInFilterFunc: function( sheet, rec ) { return undefined; }, /** * @virtual * Wird in "applySaveState" unmittelbar vor dem Filtern aufgerufen * @param {Object} cachedData */ onApplySaveState: function( cachedData ) { }, //--------------------------------------------------------------------- // NOTEN/PUNKTE-Eingabe //--------------------------------------------------------------------- getNotenStattPunkte: function() { return this.user.standardCfg[this.prefix.toLowerCase()+'Data'].notenStattPunkte; }, setTitelNotenspalte: function() { var me = this, notenVisible = false, punkteVisible = false, status = this.visDatenStatus, title, notenPunkteColumns = this.notenPunkteColumns; if (!notenPunkteColumns) return; if (this.getNotenStattPunkte()) { // alle Eingaben als Note notenVisible = true; } else { punkteVisible = status.mitPunkteSchuelern; notenVisible = status.mitNotenSchuelern; } if (notenVisible && punkteVisible) title = 'Nt./Pkt.'; else if (punkteVisible) title = 'Punkte'; else title = 'Note'; Ext.each( notenPunkteColumns, function(col) { col.setText( title ); }); }, swapNotenPunkte: function( startData ) { var me = this, isStoreData = startData === undefined, user = this.user, notenStattPunkte = this.getNotenStattPunkte(), nsp = notenStattPunkte, records = isStoreData ? (me.store.snapshot || me.store.data) : null, data = isStoreData ? records.items : startData, rec, recData, recRaw, recModified, i = 0, len = data.length, notenPunkteColumns = this.notenPunkteColumns, j, len2 = notenPunkteColumns.length, fieldName, changeRec, changeRawRec; for (i; i < len; i++) { rec = data[i]; recData = isStoreData ? rec.data : rec; if (recData.benoetigtPunkte) { changeRec = recData.noteStattPunkteEingegeben !== nsp; recRaw = rec.raw; changeRawRec = recRaw.noteStattPunkteEingegeben !== nsp; if (!changeRec && !changeRawRec) continue; recModified = rec.modified; for (j = 0; j < len2; j++) { fieldName = notenPunkteColumns[j].dataIndex; if (changeRec) recData[fieldName] = notenStattPunkte ? this.punkteNachNote( recData[fieldName] ) : this.noteNachPunkte( recData[fieldName] ); if (!changeRawRec) continue; // nächstes Feld recRaw[fieldName] = notenStattPunkte ? this.punkteNachNote( recRaw[fieldName] ) : this.noteNachPunkte( recRaw[fieldName] ); if (!recModified || !recModified[fieldName]) continue; recModified[fieldName] = notenStattPunkte ? this.punkteNachNote( recModified[fieldName] ) : this.noteNachPunkte( recModified[fieldName] ); } if (changeRec) { recData.noteStattPunkteEingegeben = nsp; recData.punkteEingegeben = !nsp; } if (changeRawRec) { recRaw.noteStattPunkteEingegeben = nsp; recRaw.punkteEingegeben = !nsp; } } } }, noteNachPunkte: function( note ) { if (Ext.isEmpty( note ) || this.isNotenKuerzel( note )) return note; if (note === '6') return "0"; var punkte = 17 - ( parseInt( note.substr(0, 1), 10 ) * 3); if (note.length > 1) // '+' oder '-' if (note.substr(1, 1) === '+') punkte += 1; else if (note.substr(1, 1) === '-') punkte -= 1; return punkte; } , punkteNachNote: function( punkte ) { if (Ext.isEmpty(punkte) || this.isNotenKuerzel( punkte)) return punkte; if (punkte === '0') return "6"; var p = parseInt( punkte, 10 ) - 1; var note = 5 - parseInt( p / 3 ); note += (p % 3) === 0 ? "-" : ((p % 3) === 2 ? "+" : ""); return note; }, //--------------------------------------------------------------------- // FOERDEREMPFEHLUNGEN //--------------------------------------------------------------------- addFoemaColumnDef: function( colDefs ) { colDefs.push({ header:'FM', menuText: 'FM', // für Spalten-Config-Menü dataIndex:'foema', xtype: 'actioncolumn', isFixCol: true, // SW-Property width: 50, sortable:false, align: 'center', renderer: this.foemaActionColumnRenderer, items: [{ tooltip: 'Fördermaßnahmen', scope: this, handler: this.onFoemaActionColumnClick }] }); }, onFoemaActionColumnClick: function(grid, rowIndex, colIndex, x, e ) { var me = this, grid = this.getEditGrid(), recData = grid.store.getAt(rowIndex).data; if (!me.commit()) return; grid.getSelectionModel().setCurrentPosition({row: rowIndex, column: colIndex}); Ext.create( "Swnm.view.FrmFoerdermassnahmen", { leistungId : this.prefix == 'LD' ? recData.id : 0, guid : recData.foemaGuid, schuelerId : recData.schuelerId, schuelerName : recData.aname, klasse : recData.klasse, kursId : recData.kursId, kursKrz : recData.kurs, fachId : recData.fachId, fachKrz : recData.fach, lehrerId : this.prefix == 'LD' ? recData.lehrerId : this.user.id, readOnly : recData.foemaGesperrt, nacharbeiten : recData.ef_foema === '-', foemaCache : me.foemaCache, info: { vname: recData.vname, nname: recData.nname, geschlecht: recData.geschlecht, fach: recData.fach }, sheet : this, rowIndex : rowIndex, colIndex : colIndex, openByReturnKey : e.keyCode === 13, success : this.onFoemaEditSuccess, onDelete : this.onFoemaDeleteSuccess }).show(); // schuelerId: 0, // schuelerName: "", // klasse: "", // kursId: 0, // kursKrz: "", // fachLehrerKrz : "", // fachLehrerName: "", }, onFoemaEditSuccess: function( guid, eingabeFertig ) { var me = this, rec = this.getActiveRecord(); //rec.set( 'foemaGuid', guid ); //rec.set( 'ef_foema', eingabeFertig ); rec.data.foemaGuid = guid; rec.data.ef_foema = eingabeFertig; this.getEditGrid().getView().refreshNode( this.getEditStore().indexOf( rec )); this.enableActions(); }, onFoemaDeleteSuccess: function( leistungId, guid ) { var me = this, rec = me.getActiveRecord(); // nach dem Löschen inde DB den Datensatz im Fördermassnahme-Cache des Leistungsdaten-Sheets löschen if (this.foemaCache[leistungId]) delete this.foemaCache[leistungId]; rec.data.foemaGuid = null; rec.data.ef_foema = '-'; this.getEditGrid().getView().refreshNode( this.getEditStore().indexOf( rec )); me.enableActions(); }, /** * @override * @returns {GridTabSheetAnonym$0} */ getLoadMaskCmp: function() { return this.getEditGrid(); }, getIsRecordInSpecFilterFunc: function() { return undefined; }, getToolbarSeparatorDef: function() { return { xtype: 'tbseparator', style: { top: "0px", height: "22px", "border-left-color": "rgb(21, 127, 204)" } }; }, /** * Wird nach dem Anwenden des aktuellen Filters aufgerufen, um das Status-Objekt für die sichtbaren Datenmenge * mit den Standard Status-Feldern zu initialisieren.
* @returns {Object} Das initialiserte Status-Objekt */ initVisDatenStatus: function() { var status = Ext.apply( {}, this.visDatenStatus ); for (var key in status) { status[key] = false; } return status; }, /** * Wird nach dem Anwenden des aktuellen Filters für jeden sichtbaren Record aufgerufen, um den Status * der sichtbaren Datenmenge zu ermitteln * @param {Object} status * @param {Object} recData Die aktuellen Record-Daten * @param {Boolean} checkIfReady * Wenn TRUE, dann wird nach der Auswertung des aktuellen Records geprüft, ob alle Status-Felder mit TRUE belegt sind. * Wenn Ja, dann gibt die Funktion TRUe andernfalls FALSE zurück * @returns {Boolean} */ calcVisDatenStatus: function( status, recData, checkIfReady ) { var alsKlassenLehrer = recData.alsKlassenLehrer, alsFachLehrer = recData.alsFachLehrer; if (alsKlassenLehrer) { status.mitKlassenSchuelern = true; if (recData.alsKlassenLehrerStv) status.mitKlassenSchuelernStv = true; else status.mitKlassenSchuelernPri= true; } if (alsFachLehrer) { status.mitFachSchuelern = true; if (recData.alsFachLehrerStv) status.mitFachSchuelernStv = true; else status.mitFachSchuelernPri = true; } if (recData.alsKoordinator) status.mitKoordinatorSchuelern = true; if (!alsKlassenLehrer || !alsFachLehrer) status.mitFremdSchuelern = true; if (recData.istSek1) status.mitSek1Schuelern = true; else status.mitSek2Schuelern = true; if (recData.gymSek2) status.mitGymSek2Schuelern = true; if (recData.benoetigtPunkte) status.mitPunkteSchuelern = true; else status.mitNotenSchuelern = true; if (!checkIfReady) return false; var ok = true; for (var key in status) { if (status[key] === false) { ok = false; break; } } return ok; }, /** * @virtual * @param {object} exConfig * @returns {undefined} */ createDetailsContainer: function( exCtConfig ) { if (!this.needDetails) return; var detailsCnt, cntCfg, currentCfg = this.getUserCurrentCfg(); cntCfg = { region: 'center', title: this.detailsContainerTitle }; Ext.apply( cntCfg, exCtConfig ); detailsCnt = Ext.create( 'Ext.panel.Panel', cntCfg ); this.detailsContainer = detailsCnt; this.detailsContainer.grid = this.detailsGrid; }, getUserCurrentCfg: function() { return this.user.currentCfg[this.prefix.toLowerCase() + 'Data']; }, getCellStatus: function( record, fieldName ) { return this.canEditCell( record, fieldName ) ? 'editable' : 'disabled'; }, getOtherSheet: function( prefix ) { return this.appSurface.getSheet( prefix ); }, getEditGrid: function () { return this.grid; }, getEditStore: function () { return this.store; } // osc: function() // { // Rbk.SysUtils.log( "OSC"); // }, // // ofc: function() // { // Rbk.SysUtils.log( "OFC"); // } });