added paabgabetyp columns "aktiv", "upload_allowed", "aktiv"; setting sensible default values for existing typen that are just the developers best guess really; accordion header with icons & tooltips; logLib in Abgabe API controller logging all successful delete/insert/update requests; show arbitrary '23:59' string after target date so it is clear until when the upload should be fulfilled, even though we still dont do anything technically different; new Termine can only be made with aktiv paabgabe typen; note & benotungsnotiz now tied to paabgabetyp benotbar flag instead of hardcoded for qgate1 & 2; added "noch nicht abgegeben" text in case the abgabedatum is null; modal now spawns in xl with fullscreen optionally enabled;

This commit is contained in:
Johann Hoffmann
2025-10-14 16:45:28 +02:00
parent 14aad56d5e
commit 0d2e41cf2f
8 changed files with 478 additions and 75 deletions
@@ -43,6 +43,20 @@ class Abgabe extends FHCAPI_Controller
$this->load->library('PhrasesLib');
// Loads LogLib with different debug trace levels to get data of the job that extends this class
// It also specify parameters to set database fields
$this->load->library('LogLib', array(
'classIndex' => 5,
'functionIndex' => 5,
'lineIndex' => 4,
'dbLogType' => 'API', // required
'dbExecuteUser' => 'RESTful API',
'requestId' => 'API',
'requestDataFormatter' => function ($data) {
return json_encode($data);
}
), 'logLib');
$this->loadPhrases(
array(
'global',
@@ -150,7 +164,6 @@ class Abgabe extends FHCAPI_Controller
}
}
$this->terminateWithSuccess(array($projektarbeiten, DOMAIN, $uid));
}
@@ -161,7 +174,6 @@ class Abgabe extends FHCAPI_Controller
*/
public function postStudentProjektarbeitZwischenabgabe()
{
$projektarbeit_id = $_POST['projektarbeit_id'];
$paabgabe_id = $_POST['paabgabe_id'];
$student_uid = $_POST['student_uid'];
@@ -189,6 +201,13 @@ class Abgabe extends FHCAPI_Controller
));
$this->sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid);
$this->logLib->logInfoDB(array('zwischenupload',$res, array(
'abgabedatum' => date('Y-m-d'),
'updatevon' => getAuthUID(),
'updateamum' => date('Y-m-d H:i:s')
), getAuthUID(), getAuthPersonId(), $student_uid));
$this->terminateWithSuccess($res);
} else {
$this->terminateWithError('Error moving File');
@@ -197,7 +216,6 @@ class Abgabe extends FHCAPI_Controller
} else {
$this->terminateWithError('File missing');
}
}
/**
@@ -275,6 +293,13 @@ class Abgabe extends FHCAPI_Controller
$this->sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid);
$this->logLib->logInfoDB(array('endupload',$res, array(
'abgabedatum' => date('Y-m-d'),
'updatevon' => getAuthUID(),
'updateamum' => date('Y-m-d H:i:s')
), getAuthUID(), getAuthPersonId(), array($projektarbeit_id,$sprache,$abstract,$abstract_en
,$schlagwoerter, $schlagwoerter_en, $seitenanzahl)));
$this->terminateWithSuccess($res);
} else {
$this->terminateWithError('Error moving File');
@@ -531,6 +556,8 @@ class Abgabe extends FHCAPI_Controller
'insertamum' => date('Y-m-d H:i:s')
)
);
$this->logLib->logInfoDB(array('paabgabe created',$result, getAuthUID(), getAuthPersonId()));
} else {
// load existing entry of paabgabe and check if note has changed to negativ, to avoid sending when
// only notiz has changed.
@@ -554,6 +581,17 @@ class Abgabe extends FHCAPI_Controller
'updateamum' => date('Y-m-d H:i:s')
)
);
$this->logLib->logInfoDB(array('paabgabe updated',$result, array(
'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz,
'datum' => $datum,
'kurzbz' => $kurzbz,
'note' => $note,
'beurteilungsnotiz' => $beurteilungsnotiz,
'upload_allowed' => $upload_allowed,
'updatevon' => getAuthUID(),
'updateamum' => date('Y-m-d H:i:s')
), getAuthUID(), getAuthPersonId()));
}
// check if $paaabgabe is a qual gate and its note is deemed negative
@@ -583,12 +621,10 @@ class Abgabe extends FHCAPI_Controller
} else { // benotung legitimately changed -> email
$this->sendQualGateNegativEmail($projektarbeit_id, $betreuer_person_id, $paabgabe);
}
} else { // nothing existing previously -> send that mail
$this->sendQualGateNegativEmail($projektarbeit_id, $betreuer_person_id, $paabgabe);
}
}
}
@@ -603,15 +639,17 @@ class Abgabe extends FHCAPI_Controller
$this->load->model('education/Paabgabe_model', 'PaabgabeModel');
$result = $this->PaabgabeModel->load($paabgabe_id);
$result = $this->getDataOrTerminateWithError($result);
$paabgabeResult = $this->PaabgabeModel->load($paabgabe_id);
$paabgabeArr = $this->getDataOrTerminateWithError($paabgabeResult);
if(count($result) == 0)
if(count($paabgabeArr) == 0)
$this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general');
if($result[0]->insertvon === getAuthUID()) {
if($paabgabeArr[0]->insertvon === getAuthUID()) {
$result = $this->PaabgabeModel->delete($paabgabe_id);
$result = $this->getDataOrTerminateWithError($result);
$this->logLib->logInfoDB(array($paabgabeArr[0], getAuthUID(), getAuthPersonId()));
$this->terminateWithSuccess($result);
}
@@ -705,6 +743,8 @@ class Abgabe extends FHCAPI_Controller
);
}
$this->logLib->logInfoDB(array('serientermin angelegt',$res, getAuthUID(), getAuthPersonId()));
$this->terminateWithSuccess($res);
}
@@ -725,7 +765,7 @@ class Abgabe extends FHCAPI_Controller
$this->load->model('education/Paabgabe_model', 'PaabgabeModel');
$result = $this->PaabgabeModel->getDeadlines($person_id);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
+9 -9
View File
@@ -3,7 +3,7 @@
background-color: var(--fhc-red-70);
font-weight: 600;
border-radius: 6px;
padding: 0px 0px 0px 32px;
padding: 0px 0px 0px 34px;
transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
box-shadow: 0 1px 2px rgba(0,0,0,0.08);
}
@@ -31,7 +31,7 @@
background-color: var(--fhc-yellow-70);
font-weight: 600;
border-radius: 6px;
padding: 0px 0px 0px 32px;
padding: 0px 0px 0px 34px;
transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
box-shadow: 0 1px 2px rgba(0,0,0,0.08);
}
@@ -56,29 +56,29 @@
/* Base Header */
.verspaetet-header {
background-color: var(--fhc-pink-70);
background-color: var(--fhc-pink-40);
font-weight: 600;
border-radius: 6px;
padding: 0px 0px 0px 32px;
padding: 0px 0px 0px 34px;
transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
box-shadow: 0 1px 2px rgba(0,0,0,0.08);
}
/* Hover State */
.verspaetet-header:hover {
background-color: var(--fhc-pink-60);
background-color: var(--fhc-pink-20);
box-shadow: 0 2px 6px rgba(0,0,0,0.12);
}
/* Active / Expanded State */
.p-accordion-tab-active > .verspaetet-header {
background-color: var(--fhc-pink-50);
background-color: var(--fhc-pink-30);
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
}
/* Hover State Active*/
.p-accordion-tab-active > .verspaetet-header:hover {
background-color: var(--fhc-pink-60);
background-color: var(--fhc-pink-20);
box-shadow: 0 2px 6px rgba(0,0,0,0.12);
}
@@ -87,7 +87,7 @@
background-color: var(--fhc-green-70);
font-weight: 600;
border-radius: 6px;
padding: 0px 0px 0px 32px;
padding: 0px 0px 0px 34px;
transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
box-shadow: 0 1px 2px rgba(0,0,0,0.08);
}
@@ -115,7 +115,7 @@
background-color: var(--fhc-white-70);
font-weight: 600;
border-radius: 6px;
padding: 0px 0px 0px 32px;
padding: 0px 0px 0px 34px;
transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
box-shadow: 0 1px 2px rgba(0,0,0,0.08);
}
@@ -16,7 +16,13 @@ export const AbgabeMitarbeiterDetail = {
AccordionTab: primevue.accordiontab,
VueDatePicker
},
inject: ['abgabeTypeOptions', 'allowedNotenOptions', 'turnitin_link', 'old_abgabe_beurteilung_link', 'isMobile'],
inject: [
'abgabeTypeOptions',
'allowedNotenOptions',
'turnitin_link',
'old_abgabe_beurteilung_link',
'isMobile'
],
props: {
projektarbeit: {
type: Object,
@@ -164,23 +170,23 @@ export const AbgabeMitarbeiterDetail = {
const oneDayMs = 1000 * 60 * 60 * 24
return Math.round((new Date(datum) - new Date(today)) / oneDayMs)
},
getDateStyle(termin, mode) {
getDateStyleClass(termin, mode) {
const datum = new Date(termin.datum)
const abgabedatum = new Date(termin.abgabedatum)
// https://wiki.fhcomplete.info/doku.php?id=cis:abgabetool_fuer_studierende
if (termin.abgabedatum === null) {
if(datum < today) {
return 'verpasst-header'
return 'verpasst'
} else if (datum > today && this.dateDiffInDays(datum, today) <= 12) {
return 'abzugeben-header'
return 'abzugeben'
} else {
return 'standard-header'
return 'standard'
}
} else if(abgabedatum > datum) {
return 'verspaetet-header'
return 'verspaetet'
} else {
return 'abgegeben-header'
return 'abgegeben'
}
},
openBeurteilungLink(link) {
@@ -209,7 +215,7 @@ export const AbgabeMitarbeiterDetail = {
const link = FHC_JS_DATA_STORAGE_OBJECT.app_root + 'index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/' + path
window.open(link, '_blank')
},
formatDate(dateParam) {
formatDate(dateParam, showTime = true) {
const date = new Date(dateParam)
// handle missing leading 0
const padZero = (num) => String(num).padStart(2, '0');
@@ -217,19 +223,21 @@ export const AbgabeMitarbeiterDetail = {
const month = padZero(date.getMonth() + 1); // Months are zero-based
const day = padZero(date.getDate());
const year = date.getFullYear();
return `${day}.${month}.${year}`;
// abgabedatum should SHOW abgabezeit which should always be last minute of the day
return `${day}.${month}.${year}` + (showTime ? ' 23:59' : '');
},
getAccTabHeaderForTermin(termin) {
let tabTitle = ''
const datumFormatted = this.formatDate(termin.datum)
const datumFormatted = this.formatDate(termin.datum, false)
tabTitle += termin.bezeichnung?.bezeichnung + ' ' + datumFormatted
return tabTitle
},
openCreateNewAbgabeModal() {
if(!this.newTermin) {
const typ = this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz === 'zwischen')
this.newTermin = {
'paabgabe_id': -1,
'projektarbeit_id': this.projektarbeit.projektarbeit_id,
@@ -238,9 +246,9 @@ export const AbgabeMitarbeiterDetail = {
'datum': new Date().toISOString().split('T')[0],
'note': this.allowedNotenOptions.find(opt => opt.note == 9),
'beurteilungsnotiz': '',
'upload_allowed': false,
'upload_allowed': typ.upload_allowed_default,
'paabgabetyp_kurzbz': '',
'bezeichnung': this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz === 'zwischen'),
'bezeichnung': typ,
'abgabedatum': null,
'insertvon': this.viewData?.uid ?? ''
}
@@ -290,6 +298,9 @@ export const AbgabeMitarbeiterDetail = {
},
computed: {
activeAbgabeTypeOptions() {
return this.abgabeTypeOptions?.filter(opt => opt.aktiv === true)
},
getEid() {
return this.$p.t('abgabetool/c4eidesstattlicheErklaerung')
},
@@ -317,6 +328,36 @@ export const AbgabeMitarbeiterDetail = {
},
getSpeedDialStyle() {
return 'position: static !important;'
},
getTooltipVerspaetet() {
return {
value: this.$p.t('abgabetool/c4tooltipVerspaetet'),
class: "custom-tooltip"
}
},
getTooltipVerpasst() {
return {
value: this.$p.t('abgabetool/c4tooltipVerpasst'),
class: "custom-tooltip"
}
},
getTooltipAbzugeben() {
return {
value: this.$p.t('abgabetool/c4tooltipAbzugeben'),
class: "custom-tooltip"
}
},
getTooltipStandard() {
return {
value: this.$p.t('abgabetool/c4tooltipStandard'),
class: "custom-tooltip"
}
},
getTooltipAbgegeben() {
return {
value: this.$p.t('abgabetool/c4tooltipAbgegeben'),
class: "custom-tooltip"
}
}
},
watch: {
@@ -326,6 +367,8 @@ export const AbgabeMitarbeiterDetail = {
if(newVal?.paabgabetyp_kurzbz === 'qualgate1' || newVal?.paabgabetyp_kurzbz === 'qualgate2') {
this.newTermin.kurzbz = newVal.bezeichnung
}
this.newTermin.upload_allowed = newVal.upload_allowed_default
}
},
created() {
@@ -339,7 +382,7 @@ export const AbgabeMitarbeiterDetail = {
id="innerModalNewAbgabe"
ref="modalContainerCreateNewAbgabe"
class="bootstrap-prompt"
dialogClass="bordered-modal modal-xl"
dialogClass="bordered-modal modal-lg"
:backdrop="true"
@hideBsModal="console.log('hideBsModal'); showAutomagicModalPhrase=false;"
>
@@ -383,13 +426,13 @@ export const AbgabeMitarbeiterDetail = {
<Dropdown
:style="{'width': '100%'}"
v-model="newTermin.bezeichnung"
:options="abgabeTypeOptions"
:options="activeAbgabeTypeOptions"
:optionLabel="getOptionLabelAbgabetyp"
scrollHeight="300px">
</Dropdown>
</div>
</div>
<div class="row mt-2" v-if="newTermin.bezeichnung?.paabgabetyp_kurzbz === 'qualgate1' || newTermin.bezeichnung?.paabgabetyp_kurzbz === 'qualgate2'">
<div class="row mt-2">
<div class="col-4 col-md-3 fw-bold">{{$p.t('abgabetool/c4upload_allowed')}}</div>
<div class="col-8 col-md-9">
<Checkbox
@@ -403,7 +446,7 @@ export const AbgabeMitarbeiterDetail = {
<div class="row mt-2">
<div class="col-4 col-md-3 fw-bold">{{$p.t('abgabetool/c4abgabekurzbz')}}</div>
<div class="col-8 col-md-9">
<Textarea style="margin-bottom: 4px;" v-model="newTermin.kurzbz" rows="1" :cols=" isMobile ? 30 : 90"></Textarea>
<Textarea style="margin-bottom: 4px;" v-model="newTermin.kurzbz" rows="1" :cols=" isMobile ? 30 : 60"></Textarea>
</div>
</div>
</div>
@@ -439,8 +482,21 @@ export const AbgabeMitarbeiterDetail = {
<Accordion :multiple="true" :activeIndex="[0]">
<template v-for="termin in this.projektarbeit?.abgabetermine">
<AccordionTab :header="getAccTabHeaderForTermin(termin)" :headerClass="getDateStyle(termin)">
<AccordionTab :headerClass="getDateStyleClass(termin) + '-header'">
<template #header>
<div class="d-flex row w-100">
<div class="col-auto" style="transform: translateX(-62px)">
<i v-if="getDateStyleClass(termin) == 'verspaetet'" v-tooltip.right="getTooltipVerspaetet" class="fa-solid fa-triangle-exclamation"></i>
<i v-else-if="getDateStyleClass(termin) == 'verpasst'" v-tooltip.right="getTooltipVerpasst" class="fa-solid fa-calendar-xmark"></i>
<i v-else-if="getDateStyleClass(termin) == 'abzugeben'" v-tooltip.right="getTooltipAbzugeben" class="fa-solid fa-hourglass-half"></i>
<i v-else-if="getDateStyleClass(termin) == 'standard'" v-tooltip.right="getTooltipStandard" class="fa-solid fa-clock"></i>
<i v-else-if="getDateStyleClass(termin) == 'abgegeben'" v-tooltip.right="getTooltipAbgegeben" class="fa-solid fa-check"></i>
</div>
<div class="col-6 text-start">
<span>{{getAccTabHeaderForTermin(termin)}}</span>
</div>
</div>
</template>
<div class="row">
<div class="col-4 col-md-3 fw-bold">{{$p.t('abgabetool/c4fixterminv2')}}</div>
<div class="col-8 col-md-9">
@@ -476,7 +532,7 @@ export const AbgabeMitarbeiterDetail = {
:disabled="!termin.allowedToSave"
v-model="termin.bezeichnung"
@change="handleChangeAbgabetyp(termin)"
:options="abgabeTypeOptions"
:options="activeAbgabeTypeOptions"
:optionLabel="getOptionLabelAbgabetyp">
</Dropdown>
</div>
@@ -492,7 +548,7 @@ export const AbgabeMitarbeiterDetail = {
</Checkbox>
</div>
</div>
<div class="row mt-2" v-if="termin.bezeichnung?.paabgabetyp_kurzbz === 'qualgate1' || termin.bezeichnung?.paabgabetyp_kurzbz === 'qualgate2'">
<div class="row mt-2" v-if="termin.bezeichnung?.benotbar">
<div class="col-4 col-md-3 fw-bold">{{$p.t('abgabetool/c4note')}}</div>
<div class="col-8 col-md-9">
<Dropdown
@@ -503,7 +559,7 @@ export const AbgabeMitarbeiterDetail = {
</Dropdown>
</div>
</div>
<div class="row mt-2" v-if="termin.bezeichnung?.paabgabetyp_kurzbz === 'qualgate1' || termin.bezeichnung?.paabgabetyp_kurzbz === 'qualgate2'">
<div class="row mt-2" v-if="termin.bezeichnung?.benotbar">
<div class="col-4 col-md-3 fw-bold">{{$p.t('abgabetool/c4notizQualGatev2')}}</div>
<div class="col-8 col-md-9">
<Textarea style="margin-bottom: 4px;" v-model="termin.beurteilungsnotiz" rows="1" :cols=" isMobile ? 30 : 90" :disabled="!termin.allowedToSave"></Textarea>
@@ -519,10 +575,15 @@ export const AbgabeMitarbeiterDetail = {
<div class="row mt-2">
<div class="col-4 col-md-3 fw-bold">{{$p.t('abgabetool/c4abgabedatum')}}</div>
<div class="col-8 col-md-9">
{{ termin.abgabedatum?.split("-").reverse().join(".") }}
<button v-if="termin?.abgabedatum" @click="downloadAbgabe(termin)" class="btn btn-primary">
<a> {{$p.t('abgabetool/c4downloadAbgabe')}} <i class="fa fa-file-pdf" style="margin-left:4px; cursor: pointer;"></i></a>
</button>
<template v-if="termin?.abgabedatum">
{{ termin.abgabedatum?.split("-").reverse().join(".") }}
<button v-if="termin?.abgabedatum" @click="downloadAbgabe(termin)" class="btn btn-primary">
<a> {{$p.t('abgabetool/c4downloadAbgabe')}} <i class="fa fa-file-pdf" style="margin-left:4px; cursor: pointer;"></i></a>
</button>
</template>
<template v-else>
{{ $p.t('abgabetool/c4nochNichtsAbgegeben') }}
</template>
</div>
</div>
<div class="row mt-2">
@@ -531,13 +592,13 @@ export const AbgabeMitarbeiterDetail = {
</div>
<div class="col-8 col-md-9">
<div class="row">
<div class="col-4">
<div class="col-auto">
<button v-if="termin.allowedToSave" style="max-height: 40px;" class="btn btn-primary border-0" @click="saveTermin(termin)">
{{ $p.t('abgabetool/c4save') }}
<i class="fa-solid fa-floppy-disk"></i>
</button>
</div>
<div class="col-4">
<div class="col-auto">
<button v-if="termin.allowedToDelete && termin.paabgabe_id > 0" style="max-height: 40px;" class="btn btn-danger border-0" @click="handleDeleteTermin(termin)">
{{ $p.t('abgabetool/c4delete') }}
<i class="fa-solid fa-trash"></i>
@@ -146,7 +146,7 @@ export const AbgabeStudentDetail = {
downloadAbgabe(termin) {
this.$api.call(ApiAbgabe.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid))
},
formatDate(dateParam) {
formatDate(dateParam, showTime = true) {
const date = new Date(dateParam)
// handle missing leading 0
const padZero = (num) => String(num).padStart(2, '0');
@@ -155,7 +155,7 @@ export const AbgabeStudentDetail = {
const day = padZero(date.getDate());
const year = date.getFullYear();
return `${day}.${month}.${year}`;
return `${day}.${month}.${year}` + (showTime ? ' 23:59' : '');
},
async upload(termin) {
@@ -211,23 +211,23 @@ export const AbgabeStudentDetail = {
const oneDayMs = 1000 * 60 * 60 * 24
return Math.round((new Date(datum) - new Date(today)) / oneDayMs)
},
getDateStyle(termin, mode) {
getDateStyleClass(termin, mode) {
const datum = new Date(termin.datum)
const abgabedatum = new Date(termin.abgabedatum)
// https://wiki.fhcomplete.info/doku.php?id=cis:abgabetool_fuer_studierende
if (termin.abgabedatum === null) {
if(datum < today) {
return 'verpasst-header'
return 'verpasst'
} else if (datum > today && this.dateDiffInDays(datum, today) <= 12) {
return 'abzugeben-header'
return 'abzugeben'
} else {
return 'standard-header'
return 'standard'
}
} else if(abgabedatum > datum) {
return 'verspaetet-header'
return 'verspaetet'
} else {
return 'abgegeben-header'
return 'abgegeben'
}
},
openBeurteilungLink(link) {
@@ -243,7 +243,7 @@ export const AbgabeStudentDetail = {
getAccTabHeaderForTermin(termin) {
let tabTitle = ''
const datumFormatted = this.formatDate(termin.datum)
const datumFormatted = this.formatDate(termin.datum, false)
tabTitle += termin.bezeichnung + ' ' + datumFormatted
return tabTitle
@@ -277,6 +277,36 @@ export const AbgabeStudentDetail = {
}
})
return qgatefound
},
getTooltipVerspaetet() {
return {
value: this.$p.t('abgabetool/c4tooltipVerspaetet'),
class: "custom-tooltip"
}
},
getTooltipVerpasst() {
return {
value: this.$p.t('abgabetool/c4tooltipVerpasst'),
class: "custom-tooltip"
}
},
getTooltipAbzugeben() {
return {
value: this.$p.t('abgabetool/c4tooltipAbzugeben'),
class: "custom-tooltip"
}
},
getTooltipStandard() {
return {
value: this.$p.t('abgabetool/c4tooltipStandard'),
class: "custom-tooltip"
}
},
getTooltipAbgegeben() {
return {
value: this.$p.t('abgabetool/c4tooltipAbgegeben'),
class: "custom-tooltip"
}
}
},
created() {
@@ -301,7 +331,21 @@ export const AbgabeStudentDetail = {
<Accordion :multiple="true" :activeIndex="[0]">
<template v-for="termin in this.projektarbeit?.abgabetermine">
<AccordionTab :header="getAccTabHeaderForTermin(termin)" :headerClass="getDateStyle(termin)">
<AccordionTab :headerClass="getDateStyleClass(termin) + '-header'">
<template #header>
<div class="d-flex row w-100">
<div class="col-auto" style="transform: translateX(-62px)">
<i v-if="getDateStyleClass(termin) == 'verspaetet'" v-tooltip.right="getTooltipVerspaetet" class="fa-solid fa-triangle-exclamation"></i>
<i v-else-if="getDateStyleClass(termin) == 'verpasst'" v-tooltip.right="getTooltipVerpasst" class="fa-solid fa-calendar-xmark"></i>
<i v-else-if="getDateStyleClass(termin) == 'abzugeben'" v-tooltip.right="getTooltipAbzugeben" class="fa-solid fa-hourglass-half"></i>
<i v-else-if="getDateStyleClass(termin) == 'standard'" v-tooltip.right="getTooltipStandard" class="fa-solid fa-clock"></i>
<i v-else-if="getDateStyleClass(termin) == 'abgegeben'" v-tooltip.right="getTooltipAbgegeben" class="fa-solid fa-check"></i>
</div>
<div class="col-6 text-start">
<span>{{getAccTabHeaderForTermin(termin)}}</span>
</div>
</div>
</template>
<div class="row">
<div class="col-4 col-md-3 fw-bold">{{$p.t('abgabetool/c4fixterminv2')}}</div>
<div class="col-8 col-md-9">
@@ -312,8 +356,6 @@ export const AbgabeStudentDetail = {
:pt="{ root: { class: 'ml-auto' }}"
>
</Checkbox>
<!-- <i v-if="termin.fixtermin" class="fa-solid fa-2x fa-circle-check fhc-bullet-red"></i>-->
<!-- <i v-else="" class="fa-solid fa-2x fa-circle-xmark fhc-bullet-green"></i>-->
</div>
</div>
@@ -329,7 +371,6 @@ export const AbgabeStudentDetail = {
:text-input="true"
auto-apply>
</VueDatePicker>
<!-- <i class="position-absolute abgabe-zieldatum-overlay fa-solid fa-2x" :class="getDateStyle(termin, 'icon')"></i>-->
</div>
</div>
@@ -366,10 +407,15 @@ export const AbgabeStudentDetail = {
<div class="row mt-2">
<div class="col-4 col-md-3 fw-bold">{{$p.t('abgabetool/c4abgabedatum')}}</div>
<div class="col-8 col-md-9">
{{ termin.abgabedatum?.split("-").reverse().join(".") }}
<button v-if="termin?.abgabedatum" @click="downloadAbgabe(termin)" class="btn btn-primary">
<a> {{$p.t('abgabetool/c4downloadAbgabe')}} <i class="fa fa-file-pdf" style="margin-left:4px; cursor: pointer;"></i></a>
</button>
<template v-if="termin?.abgabedatum">
{{ termin.abgabedatum?.split("-").reverse().join(".") }}
<button v-if="termin?.abgabedatum" @click="downloadAbgabe(termin)" class="btn btn-primary">
<a> {{$p.t('abgabetool/c4downloadAbgabe')}} <i class="fa fa-file-pdf" style="margin-left:4px; cursor: pointer;"></i></a>
</button>
</template>
<template v-else>
{{ $p.t('abgabetool/c4nochNichtsAbgegeben') }}
</template>
</div>
</div>
@@ -229,10 +229,8 @@ export const AbgabetoolMitarbeiter = {
termin.allowedToSave = termin.insertvon == this.viewData?.uid && pa.betreuerart_kurzbz != 'Zweitbegutachter'
termin.allowedToDelete = termin.allowedToSave && !termin.abgabedatum
termin.bezeichnung = {
bezeichnung: termin.bezeichnung,
paabgabetyp_kurzbz: termin.paabgabetyp_kurzbz
}
termin.bezeichnung = this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz === termin.paabgabetyp_kurzbz)
})
pa.student_uid = details.student_uid
pa.student = `${pa.vorname} ${pa.nachname}`
@@ -355,7 +353,7 @@ export const AbgabetoolMitarbeiter = {
},
computed: {
},
created() {
// fetch config to avoid hard coded links
@@ -448,7 +446,7 @@ export const AbgabetoolMitarbeiter = {
</bs-modal>
<bs-modal ref="modalContainerAbgabeDetail" class="bootstrap-prompt"
dialogClass="modal-fullscreen">
dialogClass="modal-xl" :allowFullscreenExpand="true">
<template v-slot:title>
<div>
{{$p.t('abgabetool/c4abgabeMitarbeiterDetailTitle')}}
@@ -233,7 +233,7 @@ export const AbgabetoolStudent = {
template: `
<bs-modal ref="modalContainerAbgabeDetail" class="bootstrap-prompt"
dialogClass="modal-fullscreen">
dialogClass="modal-xl" :allowFullscreenExpand="true">
<template v-slot:title>
<div>
{{$p.t('abgabetool/c4abgabeStudentDetailTitle')}}
@@ -1,12 +1,59 @@
<?php
if (! defined('DB_NAME')) exit('No direct script access allowed');
// add campus.tbl_paabgabetyp options for Quality Gates
if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table_schema = 'campus' AND table_name = 'tbl_paabgabetyp' AND column_name = 'aktiv'"))
{
if($db->db_num_rows($result) === 0)
{
$qry = "ALTER TABLE campus.tbl_paabgabetyp
ADD COLUMN IF NOT EXISTS aktiv BOOLEAN DEFAULT true;";
if(!$db->db_query($qry))
echo '<strong>campus.tbl_paabgabetyp: '.$db->db_last_error().'</strong><br>';
else
echo '<br>paabgabetyp column aktiv default true hinzugefuegt';
}
}
if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table_schema = 'campus' AND table_name = 'tbl_paabgabetyp' AND column_name = 'upload_allowed_default'"))
{
if($db->db_num_rows($result) === 0)
{
$qry = "ALTER TABLE campus.tbl_paabgabetyp
ADD COLUMN IF NOT EXISTS upload_allowed_default BOOLEAN DEFAULT true;";
if(!$db->db_query($qry))
echo '<strong>campus.tbl_paabgabetyp: '.$db->db_last_error().'</strong><br>';
else
echo '<br>paabgabetyp column upload_allowed_default default true hinzugefuegt';
}
}
if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table_schema = 'campus' AND table_name = 'tbl_paabgabetyp' AND column_name = 'benotbar'"))
{
if($db->db_num_rows($result) === 0)
{
$qry = "ALTER TABLE campus.tbl_paabgabetyp
ADD COLUMN IF NOT EXISTS benotbar BOOLEAN DEFAULT true;";
if(!$db->db_query($qry))
echo '<strong>campus.tbl_paabgabetyp: '.$db->db_last_error().'</strong><br>';
else
echo '<br>paabgabetyp column benotbar default true hinzugefuegt';
}
}
// TODO DEFINE ACTUAL VALUES BENOTBAR / UPLOAD_ALLOWED_DEFAULT / AKTIV FOR EACH PAABGABETYPE - DEVLOPER DEFAULTS BELOW
if($result = $db->db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabetyp_kurzbz='qualgate1'"))
{
if($db->db_num_rows($result) === 0)
{
$qry = "INSERT INTO campus.tbl_paabgabetyp (paabgabetyp_kurzbz, bezeichnung) VALUES('qualgate1', 'Quality Gate 1');";
$qry = "INSERT INTO campus.tbl_paabgabetyp (paabgabetyp_kurzbz, bezeichnung, benotbar, upload_allowed_default, aktiv)
VALUES('qualgate1', 'Quality Gate 1', true, true, true);";
if(!$db->db_query($qry))
echo '<strong>campus.tbl_paabgabetyp: '.$db->db_last_error().'</strong><br>';
@@ -15,11 +62,102 @@ if($result = $db->db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabet
}
}
// set new cols for zwischenabgabe
if($result = $db->db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabetyp_kurzbz='zwischen'"))
{
if($db->db_num_rows($result) === 1)
{
$qry = "UPDATE campus.tbl_paabgabetyp
SET benotbar = false,
upload_allowed_default = true,
aktiv = true
WHERE paabgabetyp_kurzbz='zwischen';";
if(!$db->db_query($qry))
echo '<strong>campus.tbl_paabgabetyp: '.$db->db_last_error().'</strong><br>';
else
echo '<br>paabgabetyp zwischen updated benotbar = false, upload_allowed_default = true, aktiv = true';
}
}
// set new cols for note
if($result = $db->db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabetyp_kurzbz='note'"))
{
if($db->db_num_rows($result) === 1)
{
$qry = "UPDATE campus.tbl_paabgabetyp
SET benotbar = false,
upload_allowed_default = false,
aktiv = false
WHERE paabgabetyp_kurzbz='note';";
if(!$db->db_query($qry))
echo '<strong>campus.tbl_paabgabetyp: '.$db->db_last_error().'</strong><br>';
else
echo '<br>paabgabetyp note updated benotbar = false, upload_allowed_default = false, aktiv = false';
}
}
// set new cols for abstract / entwurf
if($result = $db->db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabetyp_kurzbz='abstract'"))
{
if($db->db_num_rows($result) === 1)
{
$qry = "UPDATE campus.tbl_paabgabetyp
SET benotbar = false,
upload_allowed_default = true,
aktiv = true
WHERE paabgabetyp_kurzbz='abstract';";
if(!$db->db_query($qry))
echo '<strong>campus.tbl_paabgabetyp: '.$db->db_last_error().'</strong><br>';
else
echo '<br>paabgabetyp abstract updated benotbar = false, upload_allowed_default = true, aktiv = true';
}
}
// set new cols for endabgabe / end
if($result = $db->db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabetyp_kurzbz='end'"))
{
if($db->db_num_rows($result) === 1)
{
$qry = "UPDATE campus.tbl_paabgabetyp
SET benotbar = false,
upload_allowed_default = true,
aktiv = true
WHERE paabgabetyp_kurzbz='end';";
if(!$db->db_query($qry))
echo '<strong>campus.tbl_paabgabetyp: '.$db->db_last_error().'</strong><br>';
else
echo '<br>paabgabetyp end updated benotbar = false, upload_allowed_default = true, aktiv = true';
}
}
// set new cols for endabgabe im sekretariat / enda
if($result = $db->db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabetyp_kurzbz='enda'"))
{
if($db->db_num_rows($result) === 1)
{
$qry = "UPDATE campus.tbl_paabgabetyp
SET benotbar = false,
upload_allowed_default = false,
aktiv = false
WHERE paabgabetyp_kurzbz='enda';";
if(!$db->db_query($qry))
echo '<strong>campus.tbl_paabgabetyp: '.$db->db_last_error().'</strong><br>';
else
echo '<br>paabgabetyp enda updated benotbar = false, upload_allowed_default = false, aktiv = false';
}
}
if($result = $db->db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabetyp_kurzbz='qualgate2'"))
{
if($db->db_num_rows($result) === 0)
{
$qry = "INSERT INTO campus.tbl_paabgabetyp (paabgabetyp_kurzbz, bezeichnung) VALUES('qualgate2', 'Quality Gate 2');";
$qry = "INSERT INTO campus.tbl_paabgabetyp (paabgabetyp_kurzbz, bezeichnung, benotbar, upload_allowed_default, aktiv)
VALUES('qualgate2', 'Quality Gate 2', true, true, true);";
if(!$db->db_query($qry))
echo '<strong>campus.tbl_paabgabetyp: '.$db->db_last_error().'</strong><br>';
@@ -34,7 +172,7 @@ if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table
{
$qry = "ALTER TABLE campus.tbl_paabgabe
ADD COLUMN note SMALLINT DEFAULT NULL,
ADD COLUMN IF NOT EXISTS note SMALLINT DEFAULT NULL,
ADD CONSTRAINT tbl_paabgabe_note_fkey
FOREIGN KEY (note)
REFERENCES lehre.tbl_note(note)
+120
View File
@@ -42816,6 +42816,106 @@ array(
)
)
),
array(
'app' => 'core',
'category' => 'abgabetool',
'phrase' => 'c4tooltipVerspaetet',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Verspätet abgegeben",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Submitted late',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abgabetool',
'phrase' => 'c4tooltipVerpasst',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Termin überschritten",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Deadline exceeded',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abgabetool',
'phrase' => 'c4tooltipAbzugeben',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Termin innerhalb von 12 Tagen",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Deadline within 12 days',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abgabetool',
'phrase' => 'c4tooltipStandard',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Termin mehr als 12 Tag entfernt",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Deadline more than 12 days away',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abgabetool',
'phrase' => 'c4tooltipAbgegeben',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Rechtzeitig abgegeben",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Delivered on time',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abgabetool',
@@ -42856,6 +42956,26 @@ array(
)
)
),
array(
'app' => 'core',
'category' => 'abgabetool',
'phrase' => 'c4nochNichtsAbgegeben',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Keine Abgabe vorhanden",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'No submission yet',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abgabetool',