mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-22 17:32:18 +00:00
Merge branch 'feature-77537/Studvw_Feedback' into studvw_2026_05_rc_tags
This commit is contained in:
@@ -385,7 +385,7 @@ $config['navigation_menu']['apps'] = [
|
||||
],
|
||||
'lav' => [
|
||||
'link' => site_url('lehre/lehrauftrag/Lehrauftrag/Dashboard'),
|
||||
'description' => 'Lehraufträge',
|
||||
'description' => 'Lehrauftragsverwaltung',
|
||||
#'icon' => 'person-chalkboard',
|
||||
'requiredPermissions' => array('lehre/lehrauftrag_bestellen:r', 'lehre/lehrauftrag_erteilen:r')
|
||||
]
|
||||
|
||||
@@ -15,7 +15,9 @@ class Tags extends Tag_Controller
|
||||
'addTag' => self::BERECHTIGUNG_KURZBZ,
|
||||
'updateTag' => self::BERECHTIGUNG_KURZBZ,
|
||||
'doneTag' => self::BERECHTIGUNG_KURZBZ,
|
||||
'deleteTag' => self::BERECHTIGUNG_KURZBZ
|
||||
'deleteTag' => self::BERECHTIGUNG_KURZBZ,
|
||||
'getAllTags' => self::BERECHTIGUNG_KURZBZ,
|
||||
'rebuildTagsForTypeId' => self::BERECHTIGUNG_KURZBZ,
|
||||
]);
|
||||
|
||||
$this->config->load('stv');
|
||||
|
||||
@@ -7,7 +7,7 @@ class Tag_Controller extends FHCAPI_Controller
|
||||
{
|
||||
private $_uid;
|
||||
|
||||
const BERECHTIGUNG_KURZBZ = 'admin:rw';
|
||||
const BERECHTIGUNG_KURZBZ = ['admin:rw'];
|
||||
|
||||
public function __construct($permissions)
|
||||
{
|
||||
|
||||
@@ -72,7 +72,7 @@ class StudentListLib
|
||||
$this->addSelect('pls.bestaetigtam AS status_bestaetigung');
|
||||
$this->addSelect("
|
||||
CASE
|
||||
WHEN pls.status_kurzbz = 'Interessent'
|
||||
WHEN pls.status_kurzbz IN ('Interessent','Aufgenommener','Bewerber','Wartender')
|
||||
THEN pls.ausbildungssemester
|
||||
ELSE s.semester
|
||||
END AS semester_berechnet
|
||||
|
||||
@@ -60,6 +60,7 @@ class Bisio_model extends DB_Model
|
||||
JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id)
|
||||
JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz)
|
||||
WHERE ss.studiensemester_kurzbz = ?
|
||||
AND nation_code <> 'A'
|
||||
AND (
|
||||
tbl_bisio.von <= ss.ende
|
||||
AND (
|
||||
@@ -83,7 +84,7 @@ class Bisio_model extends DB_Model
|
||||
JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id)
|
||||
JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz)
|
||||
WHERE ss.studiensemester_kurzbz = ?
|
||||
--AND pss.status_kurzbz = 'Student'
|
||||
AND nation_code <> 'A'
|
||||
AND (
|
||||
tbl_bisio.von <= ss.ende
|
||||
AND (
|
||||
|
||||
@@ -96,6 +96,13 @@ html.fs_huge {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
/* to enable scrolling for many student entries*/
|
||||
.stv-details-abschlusspruefung-student-names {
|
||||
max-height: 80px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.p-dropdown-item{
|
||||
z-index: 1201 !important;
|
||||
}
|
||||
|
||||
+20
-1
@@ -46,7 +46,6 @@
|
||||
background-color: #ffA500ff;
|
||||
}
|
||||
|
||||
|
||||
.tag_braun {
|
||||
background-color: #6d4c41;
|
||||
}
|
||||
@@ -72,6 +71,26 @@
|
||||
color: black;
|
||||
}
|
||||
|
||||
.tag_turquoise {
|
||||
background-color: #89cccf;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.tag_bordeaux {
|
||||
background-color: #7B1B38;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.tag_olive {
|
||||
background-color: #868d07;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.tag_beige {
|
||||
background-color: #E4D5B4;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.tag_done {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
@@ -59,10 +59,6 @@ export default {
|
||||
from: 'configStvTagsEnabled',
|
||||
default: false
|
||||
},
|
||||
currentSemester: {
|
||||
from: 'currentSemester',
|
||||
required: true
|
||||
},
|
||||
lists: {
|
||||
from: 'lists',
|
||||
required: true
|
||||
@@ -293,8 +289,10 @@ export default {
|
||||
this.semesterDates.ende
|
||||
);
|
||||
|
||||
this.$refs.tagWrapper.innerHTML = '';
|
||||
this.$refs.tagWrapper.appendChild(container);
|
||||
if(this.headerData.length == 1) {
|
||||
this.$refs.tagWrapper.innerHTML = '';
|
||||
this.$refs.tagWrapper.appendChild(container);
|
||||
}
|
||||
},
|
||||
getAllTags(prestudent_id){
|
||||
return this.$api
|
||||
@@ -437,6 +435,12 @@ export default {
|
||||
{{headerData[0].verband}}
|
||||
<strong v-if="headerData[0].gruppe !== null && headerData[0].gruppe != ' '" class="text-muted"> | {{$p.t('lehre', 'gruppe')}} </strong>
|
||||
{{headerData[0].gruppe}}
|
||||
<strong v-if="headerData[0].status=='Interessent'
|
||||
|| headerData[0].status=='Aufgenommener'
|
||||
|| headerData[0].status=='Bewerber'
|
||||
|| headerData[0].status=='Wartender'"
|
||||
class="text-muted"> | Einstiegssemester {{headerData[0].semester_berechnet}}
|
||||
</strong>
|
||||
</template>
|
||||
<template v-else>
|
||||
<strong class="text-muted"> | {{$p.t('lehre', 'semester')}} </strong>
|
||||
@@ -456,6 +460,13 @@ export default {
|
||||
<span v-else>
|
||||
<pv-skeleton width="10rem"></pv-skeleton>
|
||||
</span>
|
||||
<strong class="text-muted"> | {{$p.t('ui', 'private')}} </strong>
|
||||
<span v-if="!isLoading">
|
||||
<a :href="'mailto:'+headerData[0]?.mail_privat">{{headerData[0].mail_privat}}</a>
|
||||
</span>
|
||||
<span v-else>
|
||||
<pv-skeleton width="10rem"></pv-skeleton>
|
||||
</span>
|
||||
<strong class="text-muted"> | Status </strong>
|
||||
<span v-if="noCurrentStatus">
|
||||
<strong class="text-danger">{{$p.t('lehre', 'textNoStatusInSem', { sem: currentSemester}) }}</strong>
|
||||
|
||||
+40
-16
@@ -78,7 +78,7 @@ export default {
|
||||
layout: 'fitDataStretchFrozen',
|
||||
layoutColumnsOnNewData: false,
|
||||
height: 'auto',
|
||||
minHeight: '200',
|
||||
minHeight: '200'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -302,7 +302,7 @@ export default {
|
||||
|
||||
//prepare local Storage
|
||||
let STORAGE_KEY = 'finalExamDefaultData';
|
||||
const id = '20260224_02';
|
||||
const id = '20260625_01';
|
||||
const stored = JSON.parse(localStorage.getItem(STORAGE_KEY)) || {};
|
||||
|
||||
if (stored[id]) {
|
||||
@@ -312,6 +312,7 @@ export default {
|
||||
this.formData.datum = data.datum;
|
||||
this.formData.sponsion = data.sponsion;
|
||||
this.formData.akadgrad_id = data.akadgrad_id;
|
||||
this.formData.pruefungsantritt_kurzbz = data.pruefungsantritt_kurzbz;
|
||||
|
||||
if (data.vorsitz_uid) {
|
||||
this.selectedVorsitz = {
|
||||
@@ -393,11 +394,12 @@ export default {
|
||||
saveOrUpdateLocalStorage(){
|
||||
let STORAGE_KEY = 'finalExamDefaultData';
|
||||
|
||||
const id = '20260224_02';
|
||||
const id = '20260625_01';
|
||||
const stored = JSON.parse(localStorage.getItem(STORAGE_KEY)) || {};
|
||||
|
||||
stored[id] = {
|
||||
pruefungstyp_kurzbz: this.formData.pruefungstyp_kurzbz,
|
||||
pruefungsantritt_kurzbz: this.formData.pruefungsantritt_kurzbz,
|
||||
vorsitz_uid: this.selectedVorsitz?.mitarbeiter_uid || null,
|
||||
vorsitz_person_id: this.selectedVorsitz?.person_id || null,
|
||||
vorsitz_label: this.selectedVorsitz?.label || null,
|
||||
@@ -435,20 +437,37 @@ export default {
|
||||
},
|
||||
async addNewAbschlusspruefungMulti(){
|
||||
try {
|
||||
for (const student of this.studentUids) {
|
||||
const arraySuccessfullySent = [];
|
||||
const arrayError = [];
|
||||
|
||||
await this.$refs.formFinalExam.call(
|
||||
ApiStvAbschlusspruefung.addNewAbschlusspruefung({
|
||||
uid: student,
|
||||
formData: this.formData
|
||||
})
|
||||
);
|
||||
for (const student of this.studentUids) {
|
||||
try {
|
||||
await this.$refs.formFinalExam.call(
|
||||
ApiStvAbschlusspruefung.addNewAbschlusspruefung({
|
||||
uid: student,
|
||||
formData: this.formData
|
||||
})
|
||||
);
|
||||
arraySuccessfullySent.push(student);
|
||||
} catch (error) {
|
||||
arrayError.push(student);
|
||||
}
|
||||
}
|
||||
if (arraySuccessfullySent.length) {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||
//TODO(Manu) check if really needed in case of success
|
||||
//this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave') + ': Uids: ' + arraySuccessfullySent.join(", "));
|
||||
}
|
||||
|
||||
if (arrayError.length) {
|
||||
this.$fhcAlert.alertError(this.$p.t('ui', 'errorSavingData') + ': Uids: ' + arrayError.join(", "));
|
||||
}
|
||||
|
||||
if (arraySuccessfullySent.length) {
|
||||
this.saveOrUpdateLocalStorage();
|
||||
this.hideModal("finalexamModal");
|
||||
this.resetForm();
|
||||
}
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||
//save formData fields in LocalStorage
|
||||
this.saveOrUpdateLocalStorage();
|
||||
this.hideModal('finalexamModal');
|
||||
this.resetForm();
|
||||
} catch (error) {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
}
|
||||
@@ -680,7 +699,12 @@ export default {
|
||||
<template #title>
|
||||
<p v-if="statusNew" class="fw-bold mt-3">{{$p.t('abschlusspruefung', 'abschluessPruefungAnlegen')}}</p>
|
||||
<p v-else class="fw-bold mt-3">{{$p.t('abschlusspruefung', 'abschluessPruefungBearbeiten')}}</p>
|
||||
<small v-if="this.student.length" class="text-muted">{{studentNames}}</small>
|
||||
<div
|
||||
v-if="this.student.length"
|
||||
class="stv-details-abschlusspruefung-student-names"
|
||||
>
|
||||
<small class="text-muted">{{studentNames}}</small>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<form-form ref="formFinalExam" @submit.prevent>
|
||||
|
||||
@@ -93,7 +93,7 @@ export default {
|
||||
}
|
||||
},
|
||||
{title:"Geschlecht", field:"geschlecht", headerFilter: "list", headerFilterParams: {values:{'m':'männlich','w':'weiblich','x':'divers','u':'unbekannt'}, listOnEmpty:true, autocomplete:true}},
|
||||
{title:"Sem.", field:"semester_berechnet", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{title: "Sem.", field:"semester_berechnet", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{title:"Verb.", field:"verband", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{title:"Grp.", field:"gruppe", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{title:"Studiengang", field:"studiengang", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
@@ -283,7 +283,6 @@ export default {
|
||||
};
|
||||
});
|
||||
},
|
||||
//TODO(Manu) check: replace download or additional entry?
|
||||
downloadConfig() {
|
||||
return {
|
||||
csv: {
|
||||
@@ -292,8 +291,9 @@ export default {
|
||||
options: {
|
||||
delimiter: ';',
|
||||
bom: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
rowRange: this.selectedcount > 0 ? "selected" : "all",
|
||||
},
|
||||
};
|
||||
},
|
||||
fileString() {
|
||||
@@ -420,8 +420,12 @@ export default {
|
||||
rowSelectionChanged(data, rows, selected, deselected) {
|
||||
this.selectedcount = data.length;
|
||||
|
||||
if(selected.length > 0 || deselected.length > 0){
|
||||
//in case of empty selection (eg. in future or past semester of selected student without sem)
|
||||
if(selected.length == 0 ) {
|
||||
this.lastSelected = this.selected;
|
||||
}
|
||||
|
||||
if(selected.length > 0 || deselected.length > 0){
|
||||
|
||||
//for tags
|
||||
this.selectedRows = this.$refs.table.tabulator.getSelectedRows();
|
||||
@@ -510,6 +514,14 @@ export default {
|
||||
this.$reloadList();
|
||||
},
|
||||
onKeydown(e) { // TODO(chris): this should be in the filter component
|
||||
|
||||
if ((e.ctrlKey || e.metaKey) && e.code === "KeyA") {
|
||||
e.preventDefault();
|
||||
|
||||
this.$refs.table.tabulator.deselectRow();
|
||||
this.$refs.table.tabulator.selectRow();
|
||||
}
|
||||
|
||||
if (!this.focusObj)
|
||||
return;
|
||||
|
||||
@@ -638,7 +650,7 @@ export default {
|
||||
// TODO(chris): focusin, focusout, keydown and tabindex should be in the filter component
|
||||
// TODO(chris): filter component column chooser has no accessibilty features
|
||||
template: `
|
||||
<div class="stv-list h-100 pt-3">
|
||||
<div class="stv-list h-100 pt-3">
|
||||
<div
|
||||
class="tabulator-container d-flex flex-column h-100"
|
||||
:class="{'has-filter': filter.length}"
|
||||
|
||||
@@ -202,7 +202,7 @@ export default {
|
||||
return true;
|
||||
},
|
||||
download(config) {
|
||||
this.tabulator.download(config.formatter, config.file, config.options)
|
||||
this.tabulator.download(config.formatter, config.file, config.options, config.rowRange)
|
||||
}
|
||||
},
|
||||
template: `
|
||||
|
||||
@@ -16,28 +16,28 @@ if(!@$db->db_query("SELECT taglib FROM public.tbl_notiz_typ LIMIT 1"))
|
||||
$tags = [
|
||||
[
|
||||
'typ_kurzbz' => 'wh_auto',
|
||||
'bezeichnung' => '{Wiederholer, repeater}',
|
||||
'bezeichnung' => '{WH, R}',
|
||||
'style' => 'tag_dark_grey',
|
||||
'prioritaet' => 11,
|
||||
'taglib' => 'tags/CoreWiederholerTagLib'
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'dd_auto',
|
||||
'bezeichnung' => '{DoubleDegree, DoubleDegree}',
|
||||
'bezeichnung' => '{DD, DD}',
|
||||
'style' => 'tag_braun',
|
||||
'prioritaet' => 10,
|
||||
'taglib' => 'tags/CoreDoubleDegreeTagLib'
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'out_auto',
|
||||
'bezeichnung' => '{Outgoing, Outgoing}',
|
||||
'bezeichnung' => '{Out, Out}',
|
||||
'style' => 'tag_limette',
|
||||
'prioritaet' => 12,
|
||||
'taglib' => 'tags/CoreOutgoingTagLib'
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'prewh_auto',
|
||||
'bezeichnung' => '{Pre-Wiederholer, pre-repeater}',
|
||||
'bezeichnung' => '{Pre-WH, pre-R}',
|
||||
'style' => 'tag_light_grey',
|
||||
'prioritaet' => 13,
|
||||
'taglib' => 'tags/CorePrewiederholerTagLib'
|
||||
@@ -45,28 +45,28 @@ $tags = [
|
||||
[
|
||||
'typ_kurzbz' => 'zgv_auto',
|
||||
'bezeichnung' => '{ZGV offen, ZGV missing}',
|
||||
'style' => 'tag_lavendel',
|
||||
'style' => 'tag_beige',
|
||||
'prioritaet' => 14,
|
||||
'taglib' => 'tags/CoreMissingZgvTagLib'
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'unterbrecher_auto',
|
||||
'bezeichnung' => '{Unterbrecher, Interrupter}',
|
||||
'style' => 'tag_blau',
|
||||
'bezeichnung' => '{UB, I}',
|
||||
'style' => 'tag_turquoise',
|
||||
'prioritaet' => 15,
|
||||
'taglib' => 'tags/CoreUnterbrecherTagLib'
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'stbtr_erh_auto',
|
||||
'bezeichnung' => '{erh.Studienbeitrag, Incr. Tuition Fees}',
|
||||
'style' => 'tag_pfirsich',
|
||||
'style' => 'tag_bordeaux',
|
||||
'prioritaet' => 16,
|
||||
'taglib' => 'tags/CoreStbErhoehtTagLib'
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'jgv_auto',
|
||||
'bezeichnung' => '{JGV, Year Group Representative}',
|
||||
'style' => 'tag_gelb',
|
||||
'bezeichnung' => '{JGV, YGR}',
|
||||
'style' => 'tag_olive',
|
||||
'prioritaet' => 17,
|
||||
'taglib' => 'tags/CoreJgvTagLib'
|
||||
],
|
||||
|
||||
@@ -60938,6 +60938,46 @@ I have been informed that I am under no obligation to consent to the transmissio
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'errorSavingData',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Speichern der Daten nicht erfolgreich',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' =>'Data saving failed',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'private',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Privat',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'private',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user