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");
// }
});