mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 20:29:29 +00:00
mobility legende; TopCalc Row (sum, negative, prueflinge); fix row selection issues;
This commit is contained in:
@@ -36,7 +36,8 @@ $includesArray = array(
|
||||
'vendor/npm-asset/primevue/multiselect/multiselect.js'
|
||||
),
|
||||
'customJSModules' => array(
|
||||
'public/js/apps/Dashboard/Fhc.js'
|
||||
'public/js/apps/Dashboard/Fhc.js',
|
||||
'vendor/olifolkerd/tabulator5/src/js/modules/ColumnCalcs/ColumnCalcs.js'
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
@@ -5,11 +5,14 @@ import ApiStudiensemester from "../../../api/factory/studiensemester.js";
|
||||
import BsModal from '../../Bootstrap/Modal.js';
|
||||
import VueDatePicker from '../../vueDatepicker.js.php';
|
||||
import LehreinheitenModule from '../../DropdownModes/LehreinheitenModule';
|
||||
import MobilityLegende from '../../Mobility/Legende.js';
|
||||
|
||||
export const Benotungstool = {
|
||||
name: "Benotungstool",
|
||||
components: {
|
||||
BsModal,
|
||||
CoreFilterCmpt,
|
||||
MobilityLegende,
|
||||
Dropdown: primevue.dropdown,
|
||||
Password: primevue.password,
|
||||
Textarea: primevue.textarea,
|
||||
@@ -73,7 +76,7 @@ export const Benotungstool = {
|
||||
{
|
||||
event: "cellClick",
|
||||
handler: async (e, cell) => {
|
||||
|
||||
console.log('cellClick Handler normal')
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -430,20 +433,42 @@ export const Benotungstool = {
|
||||
|
||||
return true; // student can be selected to add pruefung
|
||||
},
|
||||
rowFormatter: this.fixTabulatorSelectionFormatter,
|
||||
columns: [
|
||||
{
|
||||
formatter: "rowSelection",
|
||||
titleFormatter: "rowSelection", // Adds "select all" checkbox in header
|
||||
titleFormatter: function (cell, formatterParams, onRendered) {
|
||||
// Create the built-in checkbox
|
||||
let checkbox = document.createElement("input");
|
||||
checkbox.type = "checkbox";
|
||||
|
||||
// Handle "select all" manually
|
||||
checkbox.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
console.log("Custom select all handler");
|
||||
|
||||
// Or call your function
|
||||
if (formatterParams && formatterParams.handleClick) {
|
||||
formatterParams.handleClick(e, cell);
|
||||
}
|
||||
});
|
||||
|
||||
return checkbox;
|
||||
},
|
||||
hozAlign: "center",
|
||||
headerSort: false,
|
||||
titleFormatterParams: {
|
||||
handleClick: this.selectAllHandler
|
||||
},
|
||||
cellClick: function (e, cell) {
|
||||
|
||||
cell.getRow().toggleSelect();
|
||||
},
|
||||
width: 50,
|
||||
},
|
||||
{title: Vue.computed(() => this.$p.t('benotungstool/c4mail')), field: 'email', formatter: this.mailFormatter, tooltip: false, widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$p.t('benotungstool/c4antrittCount')), field: 'hoechsterAntritt', tooltip: false, widthGrow: 1},
|
||||
{title: 'UID', field: 'uid', tooltip: false, widthGrow: 1, topCalc:"sum"},
|
||||
{title: 'UID', field: 'uid', tooltip: false, widthGrow: 1, topCalc: this.sumCalcFunc},
|
||||
{title: Vue.computed(() => this.$p.t('benotungstool/c4vorname')), field: 'vorname', tooltip: false, widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$p.t('benotungstool/c4nachname')), field: 'nachname', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$p.t('benotungstool/c4teilnoten')), field: 'teilnote', widthGrow: 1, formatter: this.teilnotenFormatter},
|
||||
@@ -467,7 +492,7 @@ export const Benotungstool = {
|
||||
if(!noteOption) return true
|
||||
|
||||
// also if student has any pruefungsnote disable noten selection
|
||||
if(this.pruefungen.find(p => p.student_uid == rowData.uid)) return false
|
||||
if(this.pruefungen?.find(p => p.student_uid == rowData.uid)) return false
|
||||
|
||||
return noteOption.lkt_ueberschreibbar
|
||||
},
|
||||
@@ -476,7 +501,7 @@ export const Benotungstool = {
|
||||
const value = cell.getValue()
|
||||
const match = this.notenOptions?.find(opt => opt.note == value)
|
||||
const val = match ? match.bezeichnung : value
|
||||
const p = this.pruefungen.find(p => p.student_uid == rowData.uid)
|
||||
const p = this.pruefungen?.find(p => p.student_uid == rowData.uid)
|
||||
let style = ''
|
||||
|
||||
if(val === undefined) return ''
|
||||
@@ -497,17 +522,76 @@ export const Benotungstool = {
|
||||
{title: Vue.computed(() => this.$p.t('benotungstool/c4zeugnisnote')),
|
||||
field: 'note',
|
||||
formatter: this.notenFormatter,
|
||||
topCalc: this.negativeNotenCalc,
|
||||
topCalcFormatter: this.negativeNotenCalcFormatter,
|
||||
headerFilter: 'list',
|
||||
headerFilterParams: () => {
|
||||
return { values: ["\u00A0", this.$p.t('benotungstool/c4noteEmpty'),this.$p.t('benotungstool/c4positiv'), this.$p.t('benotungstool/c4negativ') ,...this.notenOptions.map(opt => opt.bezeichnung)] }
|
||||
},
|
||||
headerFilterFunc: this.notenFilterFunc,
|
||||
widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$p.t('benotungstool/c4kommPruef')), field: 'kommPruef', widthGrow: 1, formatter: this.pruefungFormatter, hozAlign:"center", minWidth: 150}
|
||||
{title: Vue.computed(() => this.$p.t('benotungstool/c4kommPruef')),
|
||||
field: 'kommPruef', widthGrow: 1,
|
||||
formatter: this.pruefungFormatter,
|
||||
topCalc: this.terminCalcFunc,
|
||||
topCalcFormatter: this.terminCalcFormatter,
|
||||
hozAlign:"center", minWidth: 150}
|
||||
],
|
||||
persistence: false,
|
||||
}
|
||||
},
|
||||
selectAllHandler(e, col) {
|
||||
const table = col.getTable();
|
||||
const rows = table.getRows();
|
||||
|
||||
// custom select all logic
|
||||
const allowed = rows.filter(r => r.getData().selectable);
|
||||
const selected = allowed.every(r => r.isSelected());
|
||||
|
||||
if(selected){
|
||||
allowed.forEach(r => r.deselect());
|
||||
} else {
|
||||
allowed.forEach(r => r.select());
|
||||
}
|
||||
|
||||
// stop Tabulator’s built-in handler
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
},
|
||||
fixTabulatorSelectionFormatter(row) {
|
||||
// if a row is not selectable, remove the checkbox from the dom
|
||||
|
||||
const data = row.getData()
|
||||
|
||||
const notSelectable = data.pruefungen?.find(p => p.pruefungstyp_kurzbz == 'kommPruef') || data.hoechsterAntritt >= 3
|
||||
if(notSelectable) row.getElement().children[0]?.children[0]?.remove()
|
||||
},
|
||||
terminCalcFunc(entries) {
|
||||
return entries.reduce((acc, cur) => {
|
||||
if(cur !== undefined) acc++
|
||||
return acc
|
||||
}, 0)
|
||||
},
|
||||
terminCalcFormatter(cell) {
|
||||
const cellval = cell.getValue()
|
||||
// TODO: phrase
|
||||
return 'Prüflinge: ' + cellval
|
||||
},
|
||||
negativeNotenCalcFormatter(cell) {
|
||||
const cellval = cell.getValue()
|
||||
// TODO: phrase
|
||||
return 'Negativ: ' + cellval
|
||||
},
|
||||
negativeNotenCalc(entries) {
|
||||
return entries.reduce((acc, cur) => {
|
||||
const opt = this.notenOptions.find(opt => opt.note == cur)
|
||||
if(opt && !opt.positiv) acc++
|
||||
return acc
|
||||
}, 0)
|
||||
},
|
||||
sumCalcFunc(entries) {
|
||||
return entries.length
|
||||
},
|
||||
notenFilterFunc(filterVal, rowVal) {
|
||||
// option of the searchterm
|
||||
const opt = this.notenOptions.find(opt => opt.bezeichnung === filterVal)
|
||||
@@ -885,6 +969,15 @@ export const Benotungstool = {
|
||||
else s.teilnote += ('<span style="color: red;">'+g.text +'</span>'+ '<br/>')
|
||||
})
|
||||
|
||||
Object.defineProperty(s, 'selectable', {
|
||||
get() {
|
||||
const kP = s.pruefungen?.find(p => p.pruefungstyp_kurzbz == 'kommPruef')
|
||||
return !(kP || s.hoechsterAntritt >= 3)
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
this.distinctPruefungsDates.sort((d1, d2) => {
|
||||
@@ -910,6 +1003,8 @@ export const Benotungstool = {
|
||||
field: date,
|
||||
formatter: this.pruefungFormatter,
|
||||
titleFormatter: this.pruefungTitleFormatter,
|
||||
topCalc: this.terminCalcFunc,
|
||||
topCalcFormatter: this.terminCalcFormatter,
|
||||
hozAlign:"center",
|
||||
widthGrow: 1,
|
||||
minWidth: 200,
|
||||
@@ -1338,7 +1433,7 @@ export const Benotungstool = {
|
||||
}
|
||||
},
|
||||
getStudentenOptions() {
|
||||
return this.studenten ? this.studenten : []
|
||||
return this.studenten ? this.studenten.filter(s => s.selectable) : []
|
||||
},
|
||||
getKommPruefCount(){
|
||||
let counter = 0
|
||||
@@ -1548,6 +1643,8 @@ export const Benotungstool = {
|
||||
</template>
|
||||
</core-filter-cmpt>
|
||||
</div>
|
||||
|
||||
<MobilityLegende/>
|
||||
`,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
export const MobilityLegende = {
|
||||
name: 'MobilityLegende',
|
||||
template:`
|
||||
<div class="col-auto" style="max-width: 60vw">
|
||||
<!-- TODO: phrasen definieren & verwenden-->
|
||||
<div class="row" style="font-weight: bold"><h6>Legende</h6></div>
|
||||
<div class="row"><h6>(i) ... Incoming</h6></div>
|
||||
<div class="row"><h6>(o) ... Outgoing</h6></div>
|
||||
<div class="row"><h6>(ar) ... angerechnet </h6></div>
|
||||
<div class="row"><h6>(iar) ... intern angerechnet</h6></div>
|
||||
<div class="row"><h6>(nz) ... nicht zugelassen</h6></div>
|
||||
<div class="row"><h6>(ma) ... MitarbeiterIn</h6></div>
|
||||
<div class="row"><h6>(a.o.) ... Außerordentliche/r HörerIn</h6></div>
|
||||
<div class="row"><h6>(d.d.) ... Double Degree Program</h6></div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
|
||||
export default MobilityLegende;
|
||||
Reference in New Issue
Block a user