mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-23 01:42:17 +00:00
reworked assistenz timeline feature; now shows all projektarbeiten of associated student in a more compact form;
This commit is contained in:
@@ -50,7 +50,8 @@ class Abgabe extends FHCAPI_Controller
|
||||
'getStudentProjektarbeitAbgabeFile' => array('basis/abgabe_student:rw', 'basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw'),
|
||||
'postStudentProjektarbeitZusatzdaten' => array('basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw'),
|
||||
'getSignaturStatusForProjektarbeitAbgaben' => array('basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw'),
|
||||
'sendZweitbetreuerTokenMail' => array('basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw')
|
||||
'sendZweitbetreuerTokenMail' => array('basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw'),
|
||||
'fetchProjektarbeitenHistory' => array('basis/abgabe_assistenz:rw')
|
||||
]);
|
||||
|
||||
$this->load->library('PhrasesLib');
|
||||
@@ -1549,6 +1550,37 @@ class Abgabe extends FHCAPI_Controller
|
||||
$this->sendUploadEmailZweitbegutachterToken($bperson_id, $projektarbeit_id, $student_uid);
|
||||
}
|
||||
|
||||
// basically what getStudentProjektarbeiten intends to do for the student page but
|
||||
// designed for the assistenz timeline component -> more extensive loading upfront
|
||||
// with every abgabetermin fetched here aswell
|
||||
public function fetchProjektarbeitenHistory() {
|
||||
$student_uid = $this->input->post('student_uid');
|
||||
$this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel');
|
||||
|
||||
$projektarbeiten = $this->ProjektarbeitModel->getProjektarbeitenForStudent($student_uid);
|
||||
|
||||
$mapFunc = function($projektarbeit) {
|
||||
return $projektarbeit->projektarbeit_id;
|
||||
};
|
||||
$projektarbeiten_ids = array_map($mapFunc, $projektarbeiten->retval);
|
||||
|
||||
if(count($projektarbeiten_ids) > 0) {
|
||||
$ret = $this->ProjektarbeitModel->getProjektarbeitenAbgabetermine($projektarbeiten_ids);
|
||||
$projektabgaben = $this->getDataOrTerminateWithError($ret, 'general');
|
||||
}
|
||||
|
||||
forEach($projektarbeiten->retval as $pa) {
|
||||
|
||||
$filterFunc = function($projektabgabe) use ($pa) {
|
||||
return $projektabgabe->projektarbeit_id == $pa->projektarbeit_id;
|
||||
};
|
||||
|
||||
$pa->abgabetermine = array_values(array_filter($projektabgaben, $filterFunc));
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess($projektarbeiten->retval);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper function to check the signature status of uploaded files for zwischenabgabe & endupload
|
||||
*/
|
||||
|
||||
@@ -187,7 +187,10 @@ class Projektarbeit_model extends DB_Model
|
||||
campus.tbl_paabgabetyp.bezeichnung,
|
||||
campus.tbl_paabgabetyp.benotbar,
|
||||
campus.tbl_paabgabe.abgabedatum,
|
||||
campus.tbl_paabgabe.insertvon
|
||||
campus.tbl_paabgabe.insertvon,
|
||||
campus.tbl_paabgabe.insertamum,
|
||||
campus.tbl_paabgabe.updatevon,
|
||||
campus.tbl_paabgabe.updateamum
|
||||
FROM campus.tbl_paabgabe JOIN campus.tbl_paabgabetyp USING(paabgabetyp_kurzbz)
|
||||
WHERE campus.tbl_paabgabe.projektarbeit_id = ?
|
||||
ORDER BY campus.tbl_paabgabe.datum";
|
||||
@@ -581,6 +584,129 @@ class Projektarbeit_model extends DB_Model
|
||||
|
||||
return $this->execReadOnlyQuery($new_qry, array($studiengang_kz));
|
||||
}
|
||||
|
||||
public function getProjektarbeitenForStudent($student_uid) {
|
||||
$new_qry = "WITH secondary_betreuer AS (
|
||||
SELECT DISTINCT ON (pb.projektarbeit_id)
|
||||
pb.projektarbeit_id,
|
||||
pb.person_id AS zweitbetreuer_person_id,
|
||||
pb.betreuerart_kurzbz AS zweitbetreuer_betreuerart_kurzbz,
|
||||
ba.beschreibung AS zweitbetreuer_betreuerart_beschreibung,
|
||||
p.titelpre AS zweitbetreuer_titelpre,
|
||||
p.vorname AS zweitbetreuer_vorname,
|
||||
p.nachname AS zweitbetreuer_nachname,
|
||||
p.titelpost AS zweitbetreuer_titelpost,
|
||||
trim(
|
||||
COALESCE(p.titelpre, '') || ' ' ||
|
||||
COALESCE(p.vorname, '') || ' ' ||
|
||||
COALESCE(p.nachname, '') || ' ' ||
|
||||
COALESCE(p.titelpost, '')
|
||||
) AS zweitbetreuer_full_name
|
||||
FROM lehre.tbl_projektbetreuer pb
|
||||
JOIN public.tbl_person p ON p.person_id = pb.person_id
|
||||
LEFT JOIN public.tbl_benutzer b ON b.person_id = p.person_id
|
||||
LEFT JOIN lehre.tbl_betreuerart ba ON ba.betreuerart_kurzbz = pb.betreuerart_kurzbz
|
||||
WHERE pb.betreuerart_kurzbz = ANY('{Zweitbetreuer,Zweitbegutachter,Senatsmitglied}')
|
||||
ORDER BY pb.projektarbeit_id -- DISTINCT ON needs this to be deterministic
|
||||
)
|
||||
|
||||
SELECT DISTINCT ON (tmp.projektarbeit_id)
|
||||
*,
|
||||
campus.get_betreuer_details(tmp.zweitbetreuer_person_id) AS zweitbetreuer_full_name,
|
||||
campus.get_betreuer_details(tmp.betreuer_person_id) AS erstbetreuer_full_name
|
||||
FROM (
|
||||
SELECT DISTINCT ON (tbl_projektarbeit.projektarbeit_id)
|
||||
tbl_projektarbeit.projekttyp_kurzbz,
|
||||
tbl_projektarbeit.titel,
|
||||
tbl_projektarbeit.projektarbeit_id,
|
||||
tbl_studiengang.typ,
|
||||
tbl_studiengang.kurzbz,
|
||||
student_benutzer.uid AS student_uid,
|
||||
student_person.vorname AS student_vorname,
|
||||
student_person.nachname AS student_nachname,
|
||||
public.tbl_student.matrikelnr,
|
||||
tbl_lehreinheit.studiensemester_kurzbz,
|
||||
betreuer_benutzer.uid AS betreuer_benutzer_uid,
|
||||
betreuer_person.titelpre AS betreuer_titelpre,
|
||||
betreuer_person.vorname AS betreuer_vorname,
|
||||
betreuer_person.nachname AS betreuer_nachname,
|
||||
betreuer_person.titelpost AS betreuer_titelpost,
|
||||
lehre.tbl_projektbetreuer.betreuerart_kurzbz AS betreuerart,
|
||||
lehre.tbl_projektbetreuer.person_id AS betreuer_person_id,
|
||||
lehre.tbl_projektarbeit.sprache,
|
||||
lehre.tbl_projektarbeit.seitenanzahl,
|
||||
lehre.tbl_projektarbeit.kontrollschlagwoerter,
|
||||
lehre.tbl_projektarbeit.schlagwoerter,
|
||||
lehre.tbl_projektarbeit.schlagwoerter_en,
|
||||
lehre.tbl_projektarbeit.abstract,
|
||||
lehre.tbl_projektarbeit.abstract_en,
|
||||
lehre.tbl_projektarbeit.insertamum,
|
||||
lehre.tbl_projektarbeit.note,
|
||||
|
||||
sb.zweitbetreuer_person_id,
|
||||
sb.zweitbetreuer_betreuerart_kurzbz,
|
||||
sb.zweitbetreuer_betreuerart_beschreibung,
|
||||
sb.zweitbetreuer_full_name,
|
||||
sb.zweitbetreuer_titelpre,
|
||||
sb.zweitbetreuer_vorname,
|
||||
sb.zweitbetreuer_nachname,
|
||||
sb.zweitbetreuer_titelpost,
|
||||
|
||||
(
|
||||
SELECT orgform_kurzbz
|
||||
FROM public.tbl_prestudentstatus
|
||||
WHERE prestudent_id = (
|
||||
SELECT prestudent_id FROM public.tbl_student
|
||||
WHERE student_uid = student_benutzer.uid LIMIT 1
|
||||
)
|
||||
ORDER BY datum DESC, insertamum DESC, ext_id DESC
|
||||
LIMIT 1
|
||||
) AS organisationsform,
|
||||
(
|
||||
SELECT COALESCE(tbl_studienplan.orgform_kurzbz,
|
||||
tbl_prestudentstatus.orgform_kurzbz,
|
||||
tbl_studiengang.orgform_kurzbz)
|
||||
FROM public.tbl_prestudent
|
||||
JOIN public.tbl_prestudentstatus USING (prestudent_id)
|
||||
JOIN public.tbl_studiensemester USING (studiensemester_kurzbz)
|
||||
JOIN public.tbl_studiengang USING (studiengang_kz)
|
||||
LEFT JOIN lehre.tbl_studienplan USING (studienplan_id)
|
||||
WHERE prestudent_id = public.tbl_student.prestudent_id
|
||||
ORDER BY tbl_prestudentstatus.datum DESC
|
||||
LIMIT 1
|
||||
) AS orgform,
|
||||
(
|
||||
SELECT status_kurzbz
|
||||
FROM public.tbl_prestudentstatus
|
||||
WHERE prestudent_id = public.tbl_student.prestudent_id
|
||||
ORDER BY datum DESC, insertamum DESC, ext_id DESC
|
||||
LIMIT 1
|
||||
) AS studienstatus
|
||||
|
||||
FROM lehre.tbl_projektarbeit
|
||||
LEFT JOIN public.tbl_benutzer student_benutzer ON student_benutzer.uid = lehre.tbl_projektarbeit.student_uid
|
||||
LEFT JOIN public.tbl_person student_person ON student_benutzer.person_id = student_person.person_id
|
||||
LEFT JOIN public.tbl_student ON student_benutzer.uid = public.tbl_student.student_uid
|
||||
LEFT JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_studiengang ON public.tbl_student.studiengang_kz = public.tbl_studiengang.studiengang_kz
|
||||
LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz)
|
||||
LEFT JOIN lehre.tbl_projektbetreuer USING (projektarbeit_id)
|
||||
LEFT JOIN public.tbl_person betreuer_person ON betreuer_person.person_id = lehre.tbl_projektbetreuer.person_id
|
||||
LEFT JOIN public.tbl_benutzer betreuer_benutzer ON betreuer_person.person_id = betreuer_benutzer.person_id
|
||||
LEFT JOIN secondary_betreuer sb ON sb.projektarbeit_id = tbl_projektarbeit.projektarbeit_id
|
||||
|
||||
WHERE (projekttyp_kurzbz = 'Bachelor' OR projekttyp_kurzbz = 'Diplom')
|
||||
AND student_benutzer.aktiv
|
||||
AND lehre.tbl_projektbetreuer.betreuerart_kurzbz IN (
|
||||
'Erstbegutachter', 'Begutachter', 'Betreuer', 'Erstbetreuer', 'Senatsvorsitz'
|
||||
)
|
||||
AND public.tbl_student.student_uid = ?
|
||||
ORDER BY tbl_projektarbeit.projektarbeit_id DESC, student_person.nachname ASC
|
||||
) as tmp";
|
||||
|
||||
return $this->execReadOnlyQuery($new_qry, array($student_uid));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -396,3 +396,13 @@
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.p-timeline-event-opposite {
|
||||
flex: 0 0 90px;
|
||||
max-width: 90px;
|
||||
}
|
||||
|
||||
.p-timeline-event-content {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@@ -169,6 +169,14 @@ export default {
|
||||
url: '/api/frontend/v1/Abgabe/sendZweitbetreuerTokenMail',
|
||||
params: {projektarbeit_id, bperson_id: betreuer_person_id, student_uid},
|
||||
|
||||
};
|
||||
},
|
||||
fetchProjektarbeitenHistory(student_uid) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Abgabe/fetchProjektarbeitenHistory',
|
||||
params: {student_uid},
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,251 @@
|
||||
import AbgabeterminStatusLegende from "./StatusLegende.js";
|
||||
import {formatDateTime} from "./dateUtils.js";
|
||||
|
||||
export const AbgabeStudentTimeline = {
|
||||
name: "AbgabeStudentTimeline",
|
||||
components: {
|
||||
AbgabeterminStatusLegende,
|
||||
Timeline: primevue.timeline,
|
||||
},
|
||||
props: {
|
||||
projekte: { type: Array, default: () => [] },
|
||||
notenOptions: { type: Array, default: () => [] },
|
||||
formatDateFn: { type: Function, required: true }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
legendExpanded: false,
|
||||
expandedProjects: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
student() {
|
||||
return this.projekte?.[0] ?? null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
projekte: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
// open all projects by default whenever the student changes
|
||||
const state = {}
|
||||
val?.forEach(p => { state[p.projektarbeit_id] = true })
|
||||
this.expandedProjects = state
|
||||
this.legendExpanded = false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getNoteBezeichnung(projektarbeit) {
|
||||
if(projektarbeit.note && this.notenOptions) {
|
||||
const noteOpt = this.notenOptions.find(opt => opt.note == projektarbeit.note)
|
||||
return noteOpt?.bezeichnung
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
getSavedTerminInfoString(termin) {
|
||||
const isUpdate = termin.updateamum != null;
|
||||
|
||||
const fullname = isUpdate
|
||||
? termin.updatevon_fullname
|
||||
: termin.insertvon_fullname;
|
||||
|
||||
const datetime = isUpdate
|
||||
? termin.updateamum
|
||||
: termin.insertamum;
|
||||
|
||||
return this.$p.t('ui/savedAtByV3', [formatDateTime(datetime), fullname])
|
||||
},
|
||||
getItemBezeichnung(item) {
|
||||
if (!item?.bezeichnung) return ''
|
||||
return item.bezeichnung?.bezeichnung ?? item.bezeichnung
|
||||
},
|
||||
getItemNote(item) {
|
||||
if (!item?.note) return ''
|
||||
if (item.note?.bezeichnung) return item.note.bezeichnung
|
||||
return this.notenOptions?.find(n => n.note == item.note)?.bezeichnung ?? String(item.note)
|
||||
},
|
||||
getIconClass(dateStyle) {
|
||||
return ({
|
||||
verspaetet: 'fa-solid fa-triangle-exclamation',
|
||||
verpasst: 'fa-solid fa-calendar-xmark',
|
||||
abzugeben: 'fa-solid fa-hourglass-half',
|
||||
standard: 'fa-solid fa-clock',
|
||||
abgegeben: 'fa-solid fa-paperclip',
|
||||
beurteilungerforderlich: 'fa-solid fa-list-check',
|
||||
bestanden: 'fa-solid fa-check',
|
||||
nichtbestanden: 'fa-solid fa-circle-exclamation',
|
||||
})[dateStyle] ?? ''
|
||||
},
|
||||
getBetreuerLabel(projekt) {
|
||||
return projekt.erstbetreuer_full_name
|
||||
|| (projekt.betreuer_vorname ? `${projekt.betreuer_vorname} ${projekt.betreuer_nachname}`.trim() : null)
|
||||
},
|
||||
toggleProject(id) {
|
||||
this.expandedProjects[id] = !this.expandedProjects[id]
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div v-if="student">
|
||||
|
||||
<div class="d-flex align-items-baseline gap-2 mb-3 pb-2 border-bottom">
|
||||
<span class="fw-bold fs-6">{{ student.student_vorname }} {{ student.student_nachname }}</span>
|
||||
<span class="text-muted small">{{ student.student_uid }}</span>
|
||||
<span v-if="student.matrikelnr" class="text-muted small ms-auto">{{ student.matrikelnr }}</span>
|
||||
</div>
|
||||
|
||||
<div v-for="projekt in projekte" :key="projekt.projektarbeit_id" class="mb-2">
|
||||
|
||||
<button
|
||||
class="btn btn-sm w-100 text-start d-flex align-items-center gap-2 rounded bg-light border-0 py-2 px-3"
|
||||
@click="toggleProject(projekt.projektarbeit_id)"
|
||||
>
|
||||
<i
|
||||
:class="expandedProjects[projekt.projektarbeit_id] ? 'fa-solid fa-chevron-down' : 'fa-solid fa-chevron-right'"
|
||||
style="width: 12px; flex-shrink: 0;"
|
||||
></i>
|
||||
<span class="fw-semibold text-truncate flex-grow-1" :title="projekt.titel">
|
||||
{{ projekt.titel || projekt.projekttyp_kurzbz || projekt.projektarbeit_id }}
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="projekt.note"
|
||||
class="small fw-semibold mx-2 flex-shrink-0"
|
||||
>
|
||||
{{ getNoteBezeichnung(projekt) }}
|
||||
</span>
|
||||
|
||||
<span class="text-muted small me-1 flex-shrink-0">{{ projekt.studiensemester_kurzbz }}</span>
|
||||
<span class="badge bg-secondary flex-shrink-0">{{ projekt.abgabetermine?.length ?? 0 }}</span>
|
||||
</button>
|
||||
|
||||
<div v-show="expandedProjects[projekt.projektarbeit_id]" class="px-2 pt-1">
|
||||
|
||||
<div v-if="getBetreuerLabel(projekt)" class="text-muted small px-1 mb-2">
|
||||
{{ projekt.betreuerart || $capitalize($p.t('abgabetool/c4erstbetreuerv2')) }}:
|
||||
{{ getBetreuerLabel(projekt) }}
|
||||
</div>
|
||||
|
||||
<Timeline :value="projekt.abgabetermine" align="right">
|
||||
|
||||
<template #marker="slotProps">
|
||||
<!-- padding:0 overrides the 34px accordion left-padding from the -header CSS class -->
|
||||
<div
|
||||
:class="slotProps.item.dateStyle + '-header'"
|
||||
style="height: 26px; width: 26px; padding: 0; border-radius: 4px; display: flex; align-items: center; justify-content: center; flex-shrink: 0;"
|
||||
>
|
||||
<i :class="getIconClass(slotProps.item.dateStyle)" style="font-size: 0.75rem;"></i>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #opposite="slotProps">
|
||||
<div class="text-end small text-nowrap text-muted">
|
||||
{{ formatDateFn(slotProps.item.datum) }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #content="slotProps">
|
||||
<div class="small pb-1">
|
||||
|
||||
<div class="d-flex align-items-center gap-1 fw-semibold">
|
||||
|
||||
<div
|
||||
:class="slotProps.item.dateStyle + '-header'"
|
||||
style="height:20px;width:20px;padding:0;border-radius:3px;display:flex;align-items:center;justify-content:center;flex-shrink:0;"
|
||||
>
|
||||
<i :class="getIconClass(slotProps.item.dateStyle)" style="font-size:.65rem;"></i>
|
||||
</div>
|
||||
|
||||
<span>
|
||||
{{ getItemBezeichnung(slotProps.item) }}
|
||||
</span>
|
||||
|
||||
<i
|
||||
v-if="slotProps.item.fixtermin"
|
||||
class="fa-solid fa-lock text-muted"
|
||||
title="Fixtermin"
|
||||
></i>
|
||||
|
||||
<i
|
||||
v-if="slotProps.item.abgabedatum"
|
||||
class="fa-solid fa-file text-muted"
|
||||
:title="$capitalize($p.t('abgabetool/c4abgabedatum'))"
|
||||
></i>
|
||||
|
||||
<div class="flex-grow-1 text-end">
|
||||
<span
|
||||
v-if="slotProps.item.noteBackend?.bezeichnung"
|
||||
class="fw-bold"
|
||||
>
|
||||
{{ slotProps.item.noteBackend?.positiv
|
||||
? $capitalize($p.t('abgabetool/c4positivBenotet'))
|
||||
: $capitalize($p.t('abgabetool/c4negativBenotet'))
|
||||
}}
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-else-if="slotProps.item.bezeichnung?.benotbar"
|
||||
class="fw-bold text-muted"
|
||||
>
|
||||
{{ $capitalize($p.t('abgabetool/c4notYetGraded')) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="slotProps.item.kurzbz"
|
||||
class="text-muted fst-italic ms-4"
|
||||
>
|
||||
{{ slotProps.item.kurzbz }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="slotProps.item.abgabedatum"
|
||||
class="small text-muted ms-4"
|
||||
>
|
||||
{{ $capitalize($p.t('abgabetool/c4abgabedatum')) }}:
|
||||
{{ formatDateFn(slotProps.item.abgabedatum) }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="slotProps.item.beurteilungsnotiz"
|
||||
class="small ms-4 mt-1 text-muted"
|
||||
>
|
||||
{{ slotProps.item.beurteilungsnotiz }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="slotProps.item.insertamum"
|
||||
class="small text-muted ms-4 mt-1"
|
||||
style="font-size: .72rem;"
|
||||
>
|
||||
<i class="fa-solid fa-clock-rotate-left me-1"></i>
|
||||
{{ getSavedTerminInfoString(slotProps.item) }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</Timeline>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 border-top pt-2">
|
||||
<button
|
||||
class="btn btn-link btn-sm p-0 text-muted text-decoration-none d-flex align-items-center gap-1"
|
||||
@click="legendExpanded = !legendExpanded"
|
||||
>
|
||||
<i :class="legendExpanded ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'" style="font-size: 0.7rem;"></i>
|
||||
Legende
|
||||
</button>
|
||||
<div v-show="legendExpanded" class="mt-2">
|
||||
<AbgabeterminStatusLegende />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
export default AbgabeStudentTimeline;
|
||||
@@ -7,6 +7,7 @@ import ApiAbgabe from '../../../api/factory/abgabe.js'
|
||||
import ApiStudiensemester from '../../../api/factory/studiensemester.js';
|
||||
import AbgabeterminStatusLegende from "./StatusLegende.js";
|
||||
import FhcOverlay from "../../Overlay/FhcOverlay.js";
|
||||
import AbgabeStudentTimeline from "./AbgabeStudentTimeline.js";
|
||||
import { splitMailsHelper } from "../../../helpers/EmailHelpers.js"
|
||||
import { getDateStyleClass} from "./getDateStyleClass.js";
|
||||
import { dateFilter } from '../../../tabulator/filters/DatesManual.js';
|
||||
@@ -16,6 +17,7 @@ export const AbgabetoolAssistenz = {
|
||||
name: "AbgabetoolAssistenz",
|
||||
components: {
|
||||
AbgabeterminStatusLegende,
|
||||
AbgabeStudentTimeline,
|
||||
BsModal,
|
||||
BsOffcanvas,
|
||||
CoreFilterCmpt,
|
||||
@@ -76,7 +78,7 @@ export const AbgabetoolAssistenz = {
|
||||
colLayoutRestoredFlat: false,
|
||||
sortRestoredFlat: false,
|
||||
stateRestoredFlat: false,
|
||||
timelineProjekt: null,
|
||||
timelineProjekte: [],
|
||||
selectedStudiengangOption: null,
|
||||
studiengaengeOptions: null,
|
||||
detailIsFullscreen: false,
|
||||
@@ -1878,21 +1880,54 @@ export const AbgabetoolAssistenz = {
|
||||
this.$refs.modalContainerAbgabeDetail.show()
|
||||
},
|
||||
openTimeline(val) {
|
||||
const projekt = this.projektarbeiten.find(p => p.projektarbeit_id == val.projektarbeit_id)
|
||||
if(!projekt) {
|
||||
|
||||
this.$api.call(ApiAbgabe.fetchProjektarbeitenHistory(val.student_uid)).then(res => {
|
||||
console.log(res)
|
||||
|
||||
this.$fhcAlert.alertInfo('Keine projektarbeit gefunden')
|
||||
|
||||
return
|
||||
}
|
||||
projekt.abgabetermine.forEach(termin => {
|
||||
// show note only on termine with abgabetypen which are benotbar
|
||||
const terminTypOpt = this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz == termin.paabgabetyp_kurzbz)
|
||||
termin.benotbar = terminTypOpt.benotbar
|
||||
res.data.forEach(projekt => {
|
||||
projekt.abgabetermine?.forEach(termin => {
|
||||
// only set this if it has not been set yet and abgabetermin has a note (qgate)
|
||||
if(!termin.noteBackend && termin.note) {
|
||||
termin.noteBackend = this.notenOptions.find(opt => termin.note == opt.note)
|
||||
}
|
||||
|
||||
termin.dateStyle = getDateStyleClass(termin, this.notenOptions)
|
||||
|
||||
const terminTypOpt = this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz == termin.paabgabetyp_kurzbz)
|
||||
if (terminTypOpt) termin.benotbar = terminTypOpt.benotbar
|
||||
})
|
||||
})
|
||||
|
||||
// keep the history API stub for future use
|
||||
|
||||
|
||||
this.timelineProjekte = res.data
|
||||
this.$refs.drawer.show()
|
||||
})
|
||||
this.timelineProjekt = projekt
|
||||
this.$refs.drawer.show()
|
||||
},
|
||||
// openTimeline(val) {
|
||||
//
|
||||
// this.$api.call(ApiAbgabe.fetchProjektarbeitenHistory(val.student_uid)).then(res => {
|
||||
// console.log(res)
|
||||
// })
|
||||
//
|
||||
// const projekt = this.projektarbeiten.find(p => p.projektarbeit_id == val.projektarbeit_id)
|
||||
// if(!projekt) {
|
||||
//
|
||||
// this.$fhcAlert.alertInfo('Keine projektarbeit gefunden')
|
||||
//
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// projekt.abgabetermine.forEach(termin => {
|
||||
// // show note only on termine with abgabetypen which are benotbar
|
||||
// const terminTypOpt = this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz == termin.paabgabetyp_kurzbz)
|
||||
// termin.benotbar = terminTypOpt.benotbar
|
||||
// })
|
||||
//
|
||||
// this.timelineProjekt = projekt
|
||||
// this.$refs.drawer.show()
|
||||
// },
|
||||
paabgabetypFormatter(cell) {
|
||||
const key = cell.getValue()
|
||||
return this.$p.t('abgabetool/c4paatyp' + key)
|
||||
@@ -2562,102 +2597,11 @@ export const AbgabetoolAssistenz = {
|
||||
{{ $p.t('abgabetool/c4projektarbeitTimelineTitle') }}
|
||||
</template>
|
||||
|
||||
<div class="row" style="margin-bottom: 12px;">
|
||||
<Inplace
|
||||
closable
|
||||
:closeButtonProps="{
|
||||
style: {
|
||||
position: 'absolute',
|
||||
top: '80px',
|
||||
right: '80px',
|
||||
zIndex: 1
|
||||
}
|
||||
}"
|
||||
>
|
||||
<template #display> {{ $capitalize($p.t('abgabetool/showStudentDetails'))}} </template>
|
||||
<template #content>
|
||||
<div class="col-auto">
|
||||
<div class="row">
|
||||
<div class="col-3">Student: </div>
|
||||
<div class="col-7">{{timelineProjekt?.student_vorname}} {{timelineProjekt?.student_nachname}}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-3">Uid: </div>
|
||||
<div class="col-7">{{timelineProjekt?.student_uid}}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-3">{{timelineProjekt?.betreuerart}}: </div>
|
||||
<div class="col-7">{{timelineProjekt?.erstbetreuer_full_name}}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-3">Titel: </div>
|
||||
<div class="col-7">{{timelineProjekt?.titel}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Inplace>
|
||||
</div>
|
||||
|
||||
<Timeline
|
||||
:value="timelineProjekt?.abgabetermine"
|
||||
align="right"
|
||||
>
|
||||
<template #marker="slotProps">
|
||||
<div :class="slotProps.item.dateStyle + '-header'" style="height: 48px; width:48px; padding: 0px; display: flex; align-items: center; justify-content: center;">
|
||||
<i v-if="slotProps.item.dateStyle == 'verspaetet'" class="fa-solid fa-triangle-exclamation"></i>
|
||||
<i v-else-if="slotProps.item.dateStyle == 'verpasst'" class="fa-solid fa-calendar-xmark"></i>
|
||||
<i v-else-if="slotProps.item.dateStyle == 'abzugeben'" class="fa-solid fa-hourglass-half"></i>
|
||||
<i v-else-if="slotProps.item.dateStyle == 'standard'" class="fa-solid fa-clock"></i>
|
||||
<i v-else-if="slotProps.item.dateStyle == 'abgegeben'" class="fa-solid fa-paperclip"></i>
|
||||
<i v-else-if="slotProps.item.dateStyle == 'beurteilungerforderlich'" class="fa-solid fa-list-check"></i>
|
||||
<i v-else-if="slotProps.item.dateStyle == 'bestanden'" class="fa-solid fa-check"></i>
|
||||
<i v-else-if="slotProps.item.dateStyle == 'nichtbestanden'" class="fa-solid fa-circle-exclamation"></i>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #opposite="slotProps">
|
||||
<div class="row g-1">
|
||||
<div class="col-5 fw-semibold text-end">
|
||||
{{ $capitalize($p.t('abgabetool/c4zieldatumv2')) }}:
|
||||
</div>
|
||||
<div class="col-7">
|
||||
{{ formatDate(slotProps.item.datum) }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #content="slotProps">
|
||||
<div class="row g-1">
|
||||
<div class="col-5 fw-semibold text-end">
|
||||
{{ $capitalize($p.t('abgabetool/c4abgabetyp')) }}:
|
||||
</div>
|
||||
<div class="col-7">
|
||||
{{ getItemBezeichnung(slotProps.item) }}
|
||||
</div>
|
||||
|
||||
<div class="col-5 fw-semibold text-end">
|
||||
{{ $capitalize($p.t('abgabetool/c4abgabedatum')) }}:
|
||||
</div>
|
||||
<div class="col-7">
|
||||
{{ formatDate(slotProps.item.abgabedatum) }}
|
||||
</div>
|
||||
|
||||
<div v-if="slotProps.item.benotbar" class="col-5 fw-semibold text-end">
|
||||
{{ $capitalize($p.t('abgabetool/c4note')) }}:
|
||||
</div>
|
||||
<div v-if="slotProps.item.benotbar" class="col-7">
|
||||
{{ getItemNote(slotProps.item) }}
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
</template>
|
||||
|
||||
</Timeline>
|
||||
|
||||
<template #footer>
|
||||
<AbgabeterminStatusLegende></AbgabeterminStatusLegende>
|
||||
</template>
|
||||
<AbgabeStudentTimeline
|
||||
:projekte="timelineProjekte"
|
||||
:notenOptions="notenOptions"
|
||||
:formatDateFn="formatDate"
|
||||
/>
|
||||
</BsOffcanvas>
|
||||
|
||||
<div id="abgabetable" style="max-height:40vw;">
|
||||
|
||||
@@ -14,7 +14,7 @@ export function formatISODate(dateParam) {
|
||||
export function formatDateTime(dateParam) {
|
||||
if (!dateParam) return '';
|
||||
|
||||
const date = luxon.DateTime.fromFormat(dateParam, "yyyy-MM-dd HH:mm:ss");
|
||||
const date = luxon.DateTime.fromSQL(dateParam);
|
||||
return date.isValid ? date.toFormat("dd.MM.yyyy HH:mm") : '';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user