mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 12:19:28 +00:00
Merge branch 'feature-76657/AbgabetoolFinetuning' into cis40_2026-02_rc_abgabetool_finetuning
This commit is contained in:
@@ -38,8 +38,19 @@ $config['SIGNATUR_CHECK_PAABGABETYPEN'] = ['end'];
|
||||
|
||||
// to be used as "https://moodle.technikum-wien.at/course/view.php?idnumber=dl{$stg_kz}" for stg specific moodle routing
|
||||
$config['STG_MOODLE_LINK'] = 'https://moodle.technikum-wien.at/course/view.php?idnumber=dl';
|
||||
// TODO: check if these links change if the file changes and how to better retrieve the link?
|
||||
$config['SIGNATUR_INFO_LINK_GERMAN'] = 'https://cis.technikum-wien.at/cms/dms.php?id=214779';
|
||||
$config['SIGNATUR_INFO_LINK_ENGLISH'] = 'https://cis.technikum-wien.at/cms/dms.php?id=264256';
|
||||
|
||||
$config['ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT'] = true;
|
||||
$config['ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER'] = true;
|
||||
|
||||
$config['BETREUER_SAMMELMAIL_BUTTON_STUDENT'] = true;
|
||||
|
||||
$config['MULTIEDIT_TABLE'] = true;
|
||||
|
||||
$config['STUDENT_EDIT_PROJEKTARBEIT_TITLE'] = true;
|
||||
|
||||
$config['CONFETTI_ON_ENDUPLOAD'] = true;
|
||||
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ class Abgabe extends FHCAPI_Controller
|
||||
$ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT = $this->config->item('ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT');
|
||||
$ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER = $this->config->item('ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER');
|
||||
$BETREUER_SAMMELMAIL_BUTTON_STUDENT = $this->config->item('BETREUER_SAMMELMAIL_BUTTON_STUDENT');
|
||||
$MULTIEDIT_TABLE = $this->config->item('MULTIEDIT_TABLE');
|
||||
|
||||
$ret = array(
|
||||
'old_abgabe_beurteilung_link' => $old_abgabe_beurteilung_link,
|
||||
@@ -100,7 +101,7 @@ class Abgabe extends FHCAPI_Controller
|
||||
'abgabetypenBetreuer' => $abgabetypenBetreuer,
|
||||
'ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT' => $ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT,
|
||||
'ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER' => $ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER,
|
||||
'BETREUER_SAMMELMAIL_BUTTON_STUDENT' => $BETREUER_SAMMELMAIL_BUTTON_STUDENT,
|
||||
'MULTIEDIT_TABLE' => $MULTIEDIT_TABLE,
|
||||
);
|
||||
|
||||
$this->terminateWithSuccess($ret);
|
||||
@@ -110,10 +111,18 @@ class Abgabe extends FHCAPI_Controller
|
||||
* loads config related to abgabetool for students to avoid handing out links reserved for employees
|
||||
*/
|
||||
public function getConfigStudent() {
|
||||
$moodle_link =$this->config->item('STG_MOODLE_LINK');
|
||||
$moodle_link = $this->config->item('STG_MOODLE_LINK');
|
||||
$title_edit_allowed = $this->config->item('STUDENT_EDIT_PROJEKTARBEIT_TITLE');
|
||||
$confetti_on_endupload = $this->config->item('CONFETTI_ON_ENDUPLOAD');
|
||||
$siginfolink_german = $this->config->item('SIGNATUR_INFO_LINK_GERMAN');
|
||||
$siginfolink_english = $this->config->item('SIGNATUR_INFO_LINK_ENGLISH');
|
||||
|
||||
$ret = array(
|
||||
'moodle_link' => $moodle_link,
|
||||
'title_edit_allowed' => $title_edit_allowed,
|
||||
'confetti_on_endupload' => $confetti_on_endupload,
|
||||
'siginfolink_german' => $siginfolink_german,
|
||||
'siginfolink_english' => $siginfolink_english
|
||||
);
|
||||
|
||||
$this->terminateWithSuccess($ret);
|
||||
@@ -459,6 +468,10 @@ class Abgabe extends FHCAPI_Controller
|
||||
*/
|
||||
public function postStudentProjektarbeitTitel()
|
||||
{
|
||||
if(!$this->config->item('STUDENT_EDIT_PROJEKTARBEIT_TITLE')) {
|
||||
$this->terminateWithError($this->p->t('global', 'c4studentEditNotAllowed'), 'general');
|
||||
};
|
||||
|
||||
$projektarbeit_id = $this->input->post('projektarbeit_id');
|
||||
$titel = $this->input->post('titel');
|
||||
|
||||
@@ -467,6 +480,23 @@ class Abgabe extends FHCAPI_Controller
|
||||
$this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general');
|
||||
}
|
||||
|
||||
// strip all HTML tags to prevent XSS in mail bodies, table views and Projektarbeitsbenotung
|
||||
$titel = trim(strip_tags($titel));
|
||||
if ($titel === '') {
|
||||
$this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general');
|
||||
}
|
||||
|
||||
// Reject emojis and pictographs
|
||||
// allows foreign letters, math symbols, accents, and standard punctuation.
|
||||
$emojiPattern = '/[\x{1F300}-\x{1F5FF}\x{1F600}-\x{1F64F}\x{1F680}-\x{1F6FF}\x{1F900}-\x{1FAFF}\x{23E9}-\x{23EF}\x{2b50}\x{2700}-\x{27BF}]/u';
|
||||
|
||||
// i would like this much more but our server does not recognize this utf-8 character range this way, so hexcodes it is
|
||||
// if (preg_match('/\p{Extended_Pictographic}/u', $titel)) {
|
||||
if (preg_match($emojiPattern, $titel)) {
|
||||
|
||||
$this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general');
|
||||
}
|
||||
|
||||
$this->checkProjektarbeitForFinishedStatus($projektarbeit_id);
|
||||
|
||||
$this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel');
|
||||
@@ -484,6 +514,8 @@ class Abgabe extends FHCAPI_Controller
|
||||
$this->terminateWithError($this->p->t('abgabetool', 'c4noZuordnungBetreuerStudent'), 'general');
|
||||
}
|
||||
|
||||
|
||||
|
||||
$result = $this->ProjektarbeitModel->load($projektarbeit_id);
|
||||
$data = getData($result);
|
||||
|
||||
@@ -492,7 +524,7 @@ class Abgabe extends FHCAPI_Controller
|
||||
$result = $this->ProjektarbeitModel->update(
|
||||
$projektarbeit_id,
|
||||
array(
|
||||
'titel' => trim($titel),
|
||||
'titel' => $titel,
|
||||
'updatevon' => getAuthUID(),
|
||||
'updateamum' => date('Y-m-d H:i:s')
|
||||
)
|
||||
@@ -504,7 +536,7 @@ class Abgabe extends FHCAPI_Controller
|
||||
'titelUpdate',
|
||||
array(
|
||||
'projektarbeit_id' => $projektarbeit_id,
|
||||
'titel' => trim($titel),
|
||||
'titel' => $titel,
|
||||
'updatevon' => getAuthUID(),
|
||||
'updateamum' => date('Y-m-d H:i:s')
|
||||
),
|
||||
@@ -514,13 +546,14 @@ class Abgabe extends FHCAPI_Controller
|
||||
|
||||
$this->sendTitelChangedEmail(
|
||||
$projektarbeit_id,
|
||||
trim($titel),
|
||||
$titel,
|
||||
$oldTitle,
|
||||
$assignedStudentUid
|
||||
);
|
||||
|
||||
$result = $this->ProjektarbeitModel->load($projektarbeit_id);
|
||||
$this->terminateWithSuccess($result);
|
||||
$titel = hasData($result) ? getData($result)[0]->titel : $titel;
|
||||
$this->terminateWithSuccess($titel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1533,7 +1566,7 @@ class Abgabe extends FHCAPI_Controller
|
||||
};
|
||||
Events::trigger('projektarbeit_is_current', $projektarbeit_id, $returnFunc);
|
||||
if(!$projektarbeitIsCurrent) {
|
||||
$this->terminateWithError($this->p->t('abgabetool','c4fehlerAktualitaetProjektarbeit'), 'general');
|
||||
$this->terminateWithError($this->p->t('abgabetool','c4fehlerAktualitaetProjektarbeitv2'), 'general');
|
||||
}
|
||||
|
||||
// Link to Abgabetool
|
||||
@@ -1739,7 +1772,7 @@ class Abgabe extends FHCAPI_Controller
|
||||
$data = getData($res)[0];
|
||||
if($data->note !== NULL) {
|
||||
// hardcode this error msg cause phrasen arent reliable and people keep bugging why the cant edit old entries they definitely shouldnt update
|
||||
$message = $this->p->t('abgabetool','c4fehlerAktualitaetProjektarbeit');
|
||||
$message = $this->p->t('abgabetool','c4fehlerAktualitaetProjektarbeitv2');
|
||||
if(strpos($message, "<<") === 0) { // phrase could not be loaded
|
||||
$this->terminateWithError('Die Projektarbeit wurde bereits benotet, Sie dürfen deshalb keine weiteren Termine anlegen oder bearbeiten.', 'general');
|
||||
} else {
|
||||
|
||||
@@ -90,6 +90,15 @@ class Projektarbeit extends FHCAPI_Controller
|
||||
|
||||
if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) return $this->terminateWithError('Projektarbeit Id missing', self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$result = $this->fetchProjektarbeitByID($projektarbeit_id);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess(current($data));
|
||||
}
|
||||
|
||||
private function fetchProjektarbeitById($projektarbeit_id) {
|
||||
$this->ProjektarbeitModel->resetQuery();
|
||||
$this->ProjektarbeitModel->addSelect(
|
||||
'lehre.tbl_projektarbeit.projektarbeit_id, titel, titel_english, themenbereich, projekttyp_kurzbz, lehrveranstaltung_id, lehreinheit_id,
|
||||
firma_id, beginn, ende, gesperrtbis, note, final, freigegeben, tbl_projektarbeit.anmerkung, fa.name AS firma_name'
|
||||
@@ -97,13 +106,10 @@ class Projektarbeit extends FHCAPI_Controller
|
||||
$this->ProjektarbeitModel->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id');
|
||||
$this->ProjektarbeitModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id');
|
||||
$this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id', 'LEFT');
|
||||
$result = $this->ProjektarbeitModel->loadWhere(
|
||||
return $this->ProjektarbeitModel->loadWhere(
|
||||
array('projektarbeit_id' => $projektarbeit_id)
|
||||
);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess(current($data));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,6 +138,7 @@ class Projektarbeit extends FHCAPI_Controller
|
||||
);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
$data = $this->getDataOrTerminateWithError($this->fetchProjektarbeitById($data));
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
@@ -358,6 +358,7 @@ class AbgabetoolJob extends JOB_Controller
|
||||
foreach($assistenzMap as $assistenz_person_id => $tupelArr) {
|
||||
|
||||
$abgabenString = '<div style="font-family: Arial, sans-serif; color: #333;">';
|
||||
$hasContent = false;
|
||||
|
||||
foreach($tupelArr as $tupel) {
|
||||
$projektarbeit_id = $tupel[0];
|
||||
@@ -377,6 +378,7 @@ class AbgabetoolJob extends JOB_Controller
|
||||
if(count($relevantAbgaben) == 0) {
|
||||
continue;
|
||||
}
|
||||
$hasContent = true;
|
||||
|
||||
// Format the Student Name
|
||||
$s = $relevantAbgaben[0];
|
||||
@@ -448,6 +450,11 @@ class AbgabetoolJob extends JOB_Controller
|
||||
|
||||
$abgabenString .= '</div>';
|
||||
|
||||
// skip send entirely
|
||||
if (!$hasContent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// done with building the change list, now send it
|
||||
$assistenzRow = $tupelArr[0][1];
|
||||
$anrede = $assistenzRow->anrede;
|
||||
|
||||
@@ -38,7 +38,7 @@ $includesArray = array(
|
||||
|
||||
$this->load->view('templates/FHC-Header', $includesArray);
|
||||
?>
|
||||
<div id="abgabetoolroot" class="h-100" style="padding-left: 8px; padding-right: 8px;" route=<?php echo json_encode($route) ?>
|
||||
<div id="abgabetoolroot" class="h-100" style="max-width: 99%" route=<?php echo json_encode($route) ?>
|
||||
uid=<?php echo $uid ?>
|
||||
student_uid_prop="<?php echo $student_uid_prop ?? '' ?>"
|
||||
stg_kz_prop="<?php echo $stg_kz_prop ?? '' ?>"
|
||||
|
||||
@@ -277,3 +277,7 @@ html.fs_huge {
|
||||
}
|
||||
*/
|
||||
/* slim ende */
|
||||
|
||||
.fhc-xxl-modal {
|
||||
min-width: 80vw;
|
||||
}
|
||||
@@ -347,3 +347,52 @@
|
||||
|
||||
}
|
||||
|
||||
/*confetti celebration on endupload - impossible to miss*/
|
||||
#confetti-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.confetti-piece {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
will-change: top, transform, opacity;
|
||||
}
|
||||
|
||||
/* Background Rain */
|
||||
@keyframes fallAndSpin {
|
||||
0% {
|
||||
top: var(--start-y);
|
||||
transform: translate3d(0, 0, 0) rotateX(0deg) rotateY(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 105vh;
|
||||
transform: translate3d(var(--drift), 0, 0) rotateX(720deg) rotateY(360deg);
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
/* Corner Cannons*/
|
||||
@keyframes cannonBlast {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0) scale(0.3) rotate(0deg);
|
||||
opacity: 1;
|
||||
animation-timing-function: cubic-bezier(0.1, 0.8, 0.2, 1);
|
||||
}
|
||||
30% {
|
||||
transform: translate3d(var(--blast-x), var(--blast-y), 0) scale(1.2) rotate(270deg);
|
||||
opacity: 1;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(calc(var(--blast-x) * 1.4), 15vh, 0) scale(0.4) rotate(630deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,6 @@ const app = Vue.createApp({
|
||||
|
||||
},
|
||||
computed: {
|
||||
viewData() {
|
||||
return { uid: this.uid}
|
||||
},
|
||||
student_uid_computed() {
|
||||
return this.student_uid ?? this.uid
|
||||
},
|
||||
@@ -55,10 +52,10 @@ const app = Vue.createApp({
|
||||
},
|
||||
template: `
|
||||
<template v-if="comp && uid">
|
||||
<AbgabetoolStudent v-if="comp == 'AbgabetoolStudent'" :viewData="viewData" :student_uid_prop="student_uid_computed"></AbgabetoolStudent>
|
||||
<AbgabetoolMitarbeiter v-if="comp == 'AbgabetoolMitarbeiter'" :viewData="viewData"></AbgabetoolMitarbeiter>
|
||||
<AbgabetoolAssistenz v-if="comp == 'AbgabetoolAssistenz'" :viewData="viewData" :stg_kz_prop="stg_kz_computed"></AbgabetoolAssistenz>
|
||||
<DeadlineOverview v-if="comp == 'DeadlinesOverview'" :viewData="viewData"></DeadlineOverview>
|
||||
<AbgabetoolStudent v-if="comp == 'AbgabetoolStudent'" :student_uid_prop="student_uid_computed"></AbgabetoolStudent>
|
||||
<AbgabetoolMitarbeiter v-if="comp == 'AbgabetoolMitarbeiter'"></AbgabetoolMitarbeiter>
|
||||
<AbgabetoolAssistenz v-if="comp == 'AbgabetoolAssistenz'" :stg_kz_prop="stg_kz_computed"></AbgabetoolAssistenz>
|
||||
<DeadlineOverview v-if="comp == 'DeadlinesOverview'"></DeadlineOverview>
|
||||
</template>
|
||||
`
|
||||
});
|
||||
|
||||
@@ -625,6 +625,7 @@ export const AbgabeMitarbeiterDetail = {
|
||||
dialogClass="bordered-modal modal-lg"
|
||||
:backdrop="true"
|
||||
@hideBsModal="showAutomagicModalPhrase=false;"
|
||||
bodyClass="px-4 py-4"
|
||||
>
|
||||
<template v-slot:title>
|
||||
<div>
|
||||
@@ -892,9 +893,6 @@ export const AbgabeMitarbeiterDetail = {
|
||||
<Message v-else-if="termin?.signatur == false" severity="error" :closable="false" :pt="getMessagePtStyle"> {{ $capitalize($p.t('abgabetool/c4keineSignatur')) }} </Message>
|
||||
<Message v-else-if="termin?.signatur == 'error'" severity="warn" :closable="false" :pt="getMessagePtStyle"> {{ $capitalize($p.t('abgabetool/c4signaturServerError')) }} </Message>
|
||||
</div>
|
||||
<!-- <div v-else class="col-auto">-->
|
||||
<!-- <Message severity="info" :closable="false" :pt="getMessagePtStyle"> {{ $p.t('abgabetool/c4noFileFound') }} </Message>-->
|
||||
<!-- </div>-->
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@@ -947,7 +945,8 @@ export const AbgabeMitarbeiterDetail = {
|
||||
<bs-modal
|
||||
ref="modalContainerZusatzdaten"
|
||||
class="bootstrap-prompt"
|
||||
dialogClass="bordered-modal modal-lg">
|
||||
dialogClass="bordered-modal modal-lg"
|
||||
bodyClass="px-4 py-4">
|
||||
<template v-slot:title>
|
||||
<div>
|
||||
{{$capitalize( $p.t('abgabetool/c4enduploadZusatzdaten') )}}
|
||||
|
||||
@@ -4,6 +4,8 @@ import VueDatePicker from '../../vueDatepicker.js.php';
|
||||
import ApiAbgabe from '../../../api/factory/abgabe.js'
|
||||
import FhcOverlay from "../../Overlay/FhcOverlay.js";
|
||||
import { formatISODate, getViennaTodayISO } from "./dateUtils.js";
|
||||
import { validateThesisTitle } from './titleValidation.js'
|
||||
|
||||
|
||||
export const AbgabeStudentDetail = {
|
||||
name: "AbgabeStudentDetail",
|
||||
@@ -21,7 +23,16 @@ export const AbgabeStudentDetail = {
|
||||
VueDatePicker,
|
||||
FhcOverlay
|
||||
},
|
||||
inject: ['notenOptions', 'isMobile', 'isViewMode', 'moodle_link'],
|
||||
inject: [
|
||||
'notenOptions',
|
||||
'isMobile',
|
||||
'isViewMode',
|
||||
'moodle_link',
|
||||
'confetti_on_endupload',
|
||||
'title_edit_allowed',
|
||||
'siginfolink_german',
|
||||
'siginfolink_english'
|
||||
],
|
||||
props: {
|
||||
projektarbeit: {
|
||||
type: Object,
|
||||
@@ -52,15 +63,83 @@ export const AbgabeStudentDetail = {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
confettiCannons() {
|
||||
const container = document.getElementById('confetti-container');
|
||||
if (!container) return;
|
||||
|
||||
const colors = ['#FFC107', '#FF5722', '#E91E63', '#00BCD4', '#4CAF50', '#9C27B0'];
|
||||
const shapes = ['50%', '0%'];
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
// Corner Cannons - Slowed Down)
|
||||
const cannonCount = 150;
|
||||
|
||||
for (let i = 0; i < cannonCount; i++) {
|
||||
const leftConfetti = document.createElement('div');
|
||||
leftConfetti.classList.add('confetti-piece');
|
||||
leftConfetti.style.left = '0px';
|
||||
leftConfetti.style.top = '100%';
|
||||
|
||||
const rightConfetti = document.createElement('div');
|
||||
rightConfetti.classList.add('confetti-piece');
|
||||
rightConfetti.style.left = '100vw';
|
||||
rightConfetti.style.top = '100%';
|
||||
|
||||
const colorL = colors[Math.floor(Math.random() * colors.length)];
|
||||
const colorR = colors[Math.floor(Math.random() * colors.length)];
|
||||
const shapeL = shapes[Math.floor(Math.random() * shapes.length)];
|
||||
const shapeR = shapes[Math.floor(Math.random() * shapes.length)];
|
||||
|
||||
// Left Styles
|
||||
leftConfetti.style.background = colorL;
|
||||
leftConfetti.style.borderRadius = shapeL;
|
||||
leftConfetti.style.width = `${Math.random() * 10 + 6}px`;
|
||||
leftConfetti.style.height = `${Math.random() * 14 + 6}px`;
|
||||
leftConfetti.style.setProperty('--blast-x', `${Math.random() * 50 + 10}vw`);
|
||||
leftConfetti.style.setProperty('--blast-y', `-${Math.random() * 65 + 30}vh`);
|
||||
|
||||
// Right Styles
|
||||
rightConfetti.style.background = colorR;
|
||||
rightConfetti.style.borderRadius = shapeR;
|
||||
rightConfetti.style.width = `${Math.random() * 10 + 6}px`;
|
||||
rightConfetti.style.height = `${Math.random() * 14 + 6}px`;
|
||||
rightConfetti.style.setProperty('--blast-x', `-${Math.random() * 50 + 10}vw`);
|
||||
rightConfetti.style.setProperty('--blast-y', `-${Math.random() * 65 + 30}vh`);
|
||||
|
||||
// Increased durations to 3s - 5s for a floating gravity effect
|
||||
const durationL = Math.random() * 2 + 3;
|
||||
const durationR = Math.random() * 2 + 3;
|
||||
const delayL = Math.random() * 0.2;
|
||||
const delayR = Math.random() * 0.2;
|
||||
|
||||
leftConfetti.style.animation = `cannonBlast ${durationL}s linear ${delayL}s both`;
|
||||
rightConfetti.style.animation = `cannonBlast ${durationR}s linear ${delayR}s both`;
|
||||
|
||||
fragment.appendChild(leftConfetti);
|
||||
fragment.appendChild(rightConfetti);
|
||||
|
||||
setTimeout(() => leftConfetti.remove(), (delayL + durationL) * 1000);
|
||||
setTimeout(() => rightConfetti.remove(), (delayR + durationR) * 1000);
|
||||
}
|
||||
|
||||
container.appendChild(fragment);
|
||||
},
|
||||
openTitelEdit() {
|
||||
this.editingTitel = this.projektarbeit.titel ?? '';
|
||||
this.$refs.modalTitelEdit.show();
|
||||
},
|
||||
async saveTitel() {
|
||||
const trimmed = this.editingTitel.trim();
|
||||
if (!trimmed) {
|
||||
this.$fhcAlert.alertWarning(this.$capitalize(this.$p.t('global/warningEmptyField')));
|
||||
return;
|
||||
|
||||
const validation = validateThesisTitle(this.editingTitel);
|
||||
|
||||
if (!validation.isValid) {
|
||||
if (validation.error === 'empty') {
|
||||
this.$fhcAlert.alertWarning(this.$p.t('abgabetool/c4emptyThesisTitle'))
|
||||
} else if (validation.error === 'invalid_characters') {
|
||||
this.$fhcAlert.alertWarning(this.$p.t('abgabetool/c4invalidCharactersThesisTitle'))
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const confirmed = await this.$fhcAlert.confirm({
|
||||
@@ -77,14 +156,14 @@ export const AbgabeStudentDetail = {
|
||||
this.$api.call(
|
||||
ApiAbgabe.postStudentProjektarbeitTitel(
|
||||
this.projektarbeit.projektarbeit_id,
|
||||
trimmed
|
||||
validation.cleanedTitle
|
||||
)
|
||||
).then(res => {
|
||||
if (res.meta.status === 'success') {
|
||||
this.projektarbeit.titel = trimmed;
|
||||
this.projektarbeit.titel = res.data;
|
||||
this.$emit('titel-updated', {
|
||||
projektarbeit_id: this.projektarbeit.projektarbeit_id,
|
||||
titel: trimmed
|
||||
titel: res.data
|
||||
});
|
||||
this.$fhcAlert.alertSuccess(this.$capitalize(this.$p.t('abgabetool/c4titelSavedSuccess')));
|
||||
this.$refs.modalTitelEdit.hide();
|
||||
@@ -155,6 +234,9 @@ export const AbgabeStudentDetail = {
|
||||
this.$api.call(ApiAbgabe.postStudentProjektarbeitEndupload(formData))
|
||||
.then(res => {
|
||||
this.handleUploadRes(res, this.enduploadTermin)
|
||||
if(this.confetti_on_endupload && res.meta.status == "success") {
|
||||
this.confettiCannons()
|
||||
}
|
||||
}).finally(()=> {
|
||||
this.loading = false
|
||||
})
|
||||
@@ -237,6 +319,15 @@ export const AbgabeStudentDetail = {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getSignaturInfoLink() {
|
||||
if(this.$p.user_language.value == 'German' && this.siginfolink_german) return this.siginfolink_german
|
||||
else if (this.$p.user_language.value == 'English' && this.siginfolink_english) return this.siginfolink_english
|
||||
},
|
||||
getSignaturInfoAvailable() {
|
||||
if(this.$p.user_language.value == 'German' && this.siginfolink_german) return true
|
||||
else if (this.$p.user_language.value == 'English' && this.siginfolink_english) return true
|
||||
else return false
|
||||
},
|
||||
getMoodleLink() {
|
||||
return this.moodle_link + this.projektarbeit.studiengang_kz
|
||||
},
|
||||
@@ -274,8 +365,7 @@ export const AbgabeStudentDetail = {
|
||||
return qgatefound
|
||||
},
|
||||
isTitelEditAllowed() {
|
||||
// blocked once the projektarbeit has a note (finished) - mirrors backend guard
|
||||
return !this.isViewMode && !this.projektarbeit?.note;
|
||||
return this.title_edit_allowed && !this.isViewMode && !this.projektarbeit?.note;
|
||||
},
|
||||
getTooltipVerspaetet() {
|
||||
return { value: this.$capitalize(this.$p.t('abgabetool/c4tooltipVerspaetet')), class: "custom-tooltip" }
|
||||
@@ -343,9 +433,15 @@ export const AbgabeStudentDetail = {
|
||||
<p>{{$capitalize( $p.t('abgabetool/c4betreuerv2') ) }}: {{projektarbeit ? $p.t('abgabetool/c4betrart' + projektarbeit.betreuerart_kurzbz) + ' ' + projektarbeit.betreuer : ''}}</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<p>{{ $p.t('abgabetool/c4checkoutStgMoodleInfos') }}
|
||||
<a :href="getMoodleLink" target="_blank">Moodle</a>
|
||||
</p>
|
||||
<div class="row">
|
||||
<p>{{ $p.t('abgabetool/c4checkoutStgMoodleInfos') }}
|
||||
<a :href="getMoodleLink" target="_blank">Moodle</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="row" v-if="getSignaturInfoAvailable">
|
||||
<a :href="getSignaturInfoLink" target="_blank">{{$p.t('abgabetool/c4signaturinfo')}} <i class="fa-solid fa-circle-info"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -469,7 +565,7 @@ export const AbgabeStudentDetail = {
|
||||
<div class="col-12 col-md-9">
|
||||
<template v-if="termin?.abgabedatum">
|
||||
<div class="row">
|
||||
<div style="width:100px; align-content: center;">
|
||||
<div style="width:100px; align-content: end;">
|
||||
<h6>{{ termin.abgabedatum?.split("-").reverse().join(".") }}</h6>
|
||||
</div>
|
||||
|
||||
@@ -544,10 +640,13 @@ export const AbgabeStudentDetail = {
|
||||
|
||||
</div>
|
||||
|
||||
<div v-if="confetti_on_endupload" id="confetti-container"></div>
|
||||
|
||||
<bs-modal
|
||||
ref="modalTitelEdit"
|
||||
class="bootstrap-prompt"
|
||||
dialogClass="bordered-modal"
|
||||
bodyClass="px-4 py-4"
|
||||
>
|
||||
<template v-slot:title>
|
||||
{{$capitalize( $p.t('abgabetool/c4titelBearbeiten') )}}
|
||||
@@ -562,7 +661,7 @@ export const AbgabeStudentDetail = {
|
||||
rows="10"
|
||||
maxlength="1024"
|
||||
class="form-control w-100"
|
||||
@keyup.enter="saveTitel"
|
||||
@keydown.enter.prevent="saveTitel"
|
||||
/>
|
||||
<div class="form-text text-end">{{ editingTitel.length }} / 1024</div>
|
||||
</div>
|
||||
@@ -588,7 +687,8 @@ export const AbgabeStudentDetail = {
|
||||
<bs-modal
|
||||
ref="modalContainerEnduploadZusatzdaten"
|
||||
class="bootstrap-prompt"
|
||||
dialogClass="bordered-modal modal-lg">
|
||||
dialogClass="bordered-modal modal-lg"
|
||||
bodyClass="px-4 py-4">
|
||||
<template v-slot:title>
|
||||
<div>
|
||||
{{$capitalize( $p.t('abgabetool/c4enduploadZusatzdaten') )}}
|
||||
@@ -674,6 +774,7 @@ export const AbgabeStudentDetail = {
|
||||
<div v-show="!allowedToSaveZusatzdaten">{{ $p.t('abgabetool/c4zusatzdatenausfuellen') }}</div>
|
||||
<button class="btn btn-primary" :disabled="!getAllowedToSendEndupload" @click="triggerEndupload">{{$capitalize( $p.t('ui/hochladen') )}}</button>
|
||||
</template>
|
||||
|
||||
</bs-modal>
|
||||
`,
|
||||
};
|
||||
|
||||
@@ -87,6 +87,7 @@ export const AbgabetoolAssistenz = {
|
||||
old_abgabe_beurteilung_link: null,
|
||||
ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT: null,
|
||||
ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER: null,
|
||||
MULTIEDIT_TABLE: false,
|
||||
saving: false,
|
||||
loading: false,
|
||||
abgabeTypeOptions: null,
|
||||
@@ -1917,10 +1918,6 @@ export const AbgabetoolAssistenz = {
|
||||
'<p style="max-width: 100%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; margin: 0px;">'+longForm+'</p></div>'
|
||||
}
|
||||
},
|
||||
detailFormatter(cell) {
|
||||
return '<div style="display: flex; justify-content: start; align-items: center; height: 100%">' +
|
||||
'<a><i class="fa fa-folder-open" style="color:#00649C"></i></a></div>'
|
||||
},
|
||||
pkzTextFormatter(cell) {
|
||||
const val = cell.getValue()
|
||||
|
||||
@@ -2267,6 +2264,7 @@ export const AbgabetoolAssistenz = {
|
||||
this.old_abgabe_beurteilung_link = res.data?.old_abgabe_beurteilung_link;
|
||||
this.ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT = res.data?.ASSISTENZ_SAMMELMAIL_BUTTON_STUDENT;
|
||||
this.ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER = res.data?.ASSISTENZ_SAMMELMAIL_BUTTON_BETREUER;
|
||||
this.MULTIEDIT_TABLE = res.data?.MULTIEDIT_TABLE;
|
||||
}
|
||||
|
||||
// 2. Studiengänge
|
||||
@@ -2341,7 +2339,11 @@ export const AbgabetoolAssistenz = {
|
||||
<template v-if="phrasenResolved">
|
||||
<FhcOverlay :active="loading || saving"></FhcOverlay>
|
||||
|
||||
<bs-modal ref="modalContainerEditSeries" class="bootstrap-prompt" dialogClass="modal-lg">
|
||||
<bs-modal
|
||||
ref="modalContainerEditSeries"
|
||||
class="bootstrap-prompt"
|
||||
dialogClass="modal-lg"
|
||||
bodyClass="px-4 py-4">
|
||||
<template v-slot:title>
|
||||
<div>{{ $p.t('abgabetool/c4editTerminserie') }}</div>
|
||||
<div class="text-muted" style="font-size: 0.9rem;">
|
||||
@@ -2440,8 +2442,11 @@ export const AbgabetoolAssistenz = {
|
||||
</template>
|
||||
</bs-modal>
|
||||
|
||||
<bs-modal ref="modalContainerAddSeries" class="bootstrap-prompt"
|
||||
dialogClass="modal-lg">
|
||||
<bs-modal
|
||||
ref="modalContainerAddSeries"
|
||||
class="bootstrap-prompt"
|
||||
dialogClass="modal-lg"
|
||||
bodyClass="px-4 py-4">
|
||||
<template v-slot:title>
|
||||
<div>
|
||||
{{ $p.t('abgabetool/neueTerminserie') }}
|
||||
@@ -2520,7 +2525,8 @@ export const AbgabetoolAssistenz = {
|
||||
|
||||
<bs-modal ref="modalContainerAbgabeDetail" class="bootstrap-prompt"
|
||||
dialogClass="modal-xl" :allowFullscreenExpand="true"
|
||||
@toggle-fullscreen="handleToggleFullscreenDetail">
|
||||
@toggle-fullscreen="handleToggleFullscreenDetail"
|
||||
bodyClass="px-4 py-4">
|
||||
<template v-slot:title>
|
||||
<div>
|
||||
{{$p.t('abgabetool/c4abgabeMitarbeiterDetailTitle')}}
|
||||
@@ -2651,7 +2657,7 @@ export const AbgabetoolAssistenz = {
|
||||
<div class="col-auto me-auto">
|
||||
<h2 tabindex="1">{{$p.t('abgabetool/abgabetoolTitleAdmin')}}</h2>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="col-auto d-none d-xxl-flex">
|
||||
<label class="col-form-label">{{$capitalize($p.t('lehre/studiengang'))}}:</label>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
@@ -2668,10 +2674,10 @@ export const AbgabetoolAssistenz = {
|
||||
</template>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="col-auto d-none d-xxl-flex">
|
||||
<label class="col-form-label">{{$capitalize($p.t('lehre/note'))}}:</label>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="col-2">
|
||||
<Dropdown
|
||||
:placeholder="$p.t('lehre/note')"
|
||||
:style="{'width': '100%', 'scroll-behavior': 'auto !important'}"
|
||||
@@ -2730,7 +2736,7 @@ export const AbgabetoolAssistenz = {
|
||||
</button>
|
||||
<tiered-menu ref="menu" :model="emailItems" popup :autoZIndex="false" />
|
||||
|
||||
<button @click="switchMode" class="btn btn-secondary">
|
||||
<button v-if="MULTIEDIT_TABLE" @click="switchMode" class="btn btn-secondary">
|
||||
{{ $p.t('abgabetool/c4terminansicht') }}
|
||||
</button>
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ export const AbgabetoolMitarbeiter = {
|
||||
cssClass: 'sticky-col',
|
||||
visible: true
|
||||
},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4details'))), field: 'details', formatter: this.detailFormatter, headerFilter: false, headerSort: false, minWidth: 50, visible: true, tooltip: false, cssClass: 'sticky-col'},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4details'))), field: 'details', formatter: this.formAction, headerFilter: false, headerSort: false, minWidth: 85, visible: true, tooltip: false, cssClass: 'sticky-col'},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4personenkennzeichen'))), headerFilter: true, field: 'pkz', formatter: this.pkzTextFormatter, minWidth: 140, visible: false,tooltip: false},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4vorname'))), field: 'vorname', headerFilter: true, formatter: this.centeredTextFormatter, minWidth: 100,visible: false},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4nachname'))), field: 'nachname', headerFilter: true, formatter: this.centeredTextFormatter, minWidth: 100,visible: true},
|
||||
@@ -248,6 +248,77 @@ export const AbgabetoolMitarbeiter = {
|
||||
]};
|
||||
},
|
||||
methods: {
|
||||
async openBenotung(type, link) {
|
||||
if(type === 'new') {
|
||||
window.open(link, '_blank')
|
||||
} else if(type === 'old') {
|
||||
if(await this.$fhcAlert.confirm({
|
||||
message: this.$p.t('abgabetool/c4aeltereParbeitBenotenv2'),
|
||||
acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')),
|
||||
acceptClass: 'btn btn-danger',
|
||||
rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')),
|
||||
rejectClass: 'btn btn-outline-secondary'
|
||||
}) === false) {
|
||||
return false
|
||||
}
|
||||
|
||||
window.open(link, '_blank')
|
||||
} else {
|
||||
// show info text that no endupload with abgabe has been found
|
||||
if(await this.$fhcAlert.confirm({
|
||||
message: this.$p.t('abgabetool/c4keinEnduploadErfolgt'),
|
||||
acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')),
|
||||
acceptClass: 'btn btn-danger',
|
||||
rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')),
|
||||
rejectClass: 'btn btn-outline-secondary'
|
||||
}) === false) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
formAction(cell) {
|
||||
const actionButtons = document.createElement('div');
|
||||
actionButtons.className = "d-flex gap-3";
|
||||
actionButtons.style.display = "flex";
|
||||
actionButtons.style.alignItems = "stretch";
|
||||
actionButtons.style.justifyContent = "start";
|
||||
actionButtons.style.height = "100%";
|
||||
|
||||
const val = cell.getValue();
|
||||
const data = cell.getRow().getData()
|
||||
|
||||
const createButton = (iconClass, titleKey, clickHandler) => {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'btn btn-outline-secondary';
|
||||
btn.style.display = "flex";
|
||||
btn.style.alignItems = "center"; // center icon vertically
|
||||
btn.style.justifyContent = "center"; // center icon horizontally
|
||||
btn.style.height = "100%"; // fill parent container height
|
||||
btn.style.aspectRatio = "1 / 1"; // keep square shape (optional)
|
||||
btn.style.padding = "0"; // remove extra padding for compactness
|
||||
if(iconClass == 'fa fa-timeline') btn.style.transform = "rotate(90deg)";
|
||||
btn.innerHTML = `<i class="${iconClass}" style="color:#00649C; font-size:1.1rem;"></i>`;
|
||||
btn.title = this.$capitalize(this.$p.t(titleKey));
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
clickHandler();
|
||||
});
|
||||
return btn;
|
||||
};
|
||||
|
||||
actionButtons.append(
|
||||
createButton('fa fa-folder-open', 'abgabetool/c4details', () => this.setDetailComponent(val)),
|
||||
);
|
||||
|
||||
if(data.isCurrent && data.abgabetermine?.find(termin => termin.paabgabetyp_kurzbz == 'end' && termin.abgabedatum !== null) && data.beurteilungLinkNew) {
|
||||
actionButtons.append(createButton('fa fa-user-check', 'abgabetool/c4benoten', () => this.openBenotung('new', data.beurteilungLinkNew)))
|
||||
} else if(data.abgabetermine?.find(termin => termin.paabgabetyp_kurzbz == 'end' && termin.abgabedatum !== null) && data.beurteilungLinkOld) {
|
||||
actionButtons.append(createButton('fa fa-user-check', 'abgabetool/c4benoten', () => this.openBenotung('old', data.beurteilungLinkOld)))
|
||||
}
|
||||
|
||||
return actionButtons;
|
||||
},
|
||||
getDateStyleHtml(dateStyle) {
|
||||
const iconMap = {
|
||||
'verspaetet': '<i class="fa-solid fa-triangle-exclamation"></i>',
|
||||
@@ -1271,7 +1342,8 @@ export const AbgabetoolMitarbeiter = {
|
||||
<FhcOverlay :active="loading || saving"></FhcOverlay>
|
||||
|
||||
<bs-modal ref="modalContainerAddSeries" class="bootstrap-prompt"
|
||||
dialogClass="modal-lg">
|
||||
dialogClass="modal-lg"
|
||||
bodyClass="px-4 py-4">
|
||||
<template v-slot:title>
|
||||
<div>
|
||||
{{ $p.t('abgabetool/neueTerminserie') }}
|
||||
@@ -1339,7 +1411,8 @@ export const AbgabetoolMitarbeiter = {
|
||||
|
||||
<bs-modal ref="modalContainerAbgabeDetail" class="bootstrap-prompt"
|
||||
dialogClass="modal-xl" :allowFullscreenExpand="true"
|
||||
@toggle-fullscreen="handleToggleFullscreenDetail">
|
||||
@toggle-fullscreen="handleToggleFullscreenDetail"
|
||||
bodyClass="px-4 py-4">
|
||||
<template v-slot:title>
|
||||
<div>
|
||||
{{$p.t('abgabetool/c4abgabeMitarbeiterDetailTitle')}}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import AbgabeDetail from "./AbgabeStudentDetail.js";
|
||||
import ApiAbgabe from '../../../api/factory/abgabe.js'
|
||||
import ApiAuthinfo from '../../../api/factory/authinfo.js';
|
||||
import BsModal from "../../Bootstrap/Modal.js";
|
||||
import FhcOverlay from "../../Overlay/FhcOverlay.js";
|
||||
import { getDateStyleClass} from "./getDateStyleClass.js";
|
||||
import ApiAuthinfo from "../../../api/factory/authinfo.js";
|
||||
import { validateThesisTitle } from './titleValidation.js'
|
||||
|
||||
export const AbgabetoolStudent = {
|
||||
name: "AbgabetoolStudent",
|
||||
@@ -19,7 +21,11 @@ export const AbgabetoolStudent = {
|
||||
return {
|
||||
notenOptions: Vue.computed(() => this.notenOptions),
|
||||
isViewMode: Vue.computed(() => this.isViewMode),
|
||||
moodle_link: Vue.computed(() => this.moodle_link)
|
||||
moodle_link: Vue.computed(() => this.moodle_link),
|
||||
title_edit_allowed: Vue.computed(() => this.title_edit_allowed),
|
||||
confetti_on_endupload: Vue.computed(() => this.confetti_on_endupload),
|
||||
siginfolink_german: Vue.computed(() => this.siginfolink_german),
|
||||
siginfolink_english: Vue.computed(() => this.siginfolink_english)
|
||||
}
|
||||
},
|
||||
props: {
|
||||
@@ -40,8 +46,13 @@ export const AbgabetoolStudent = {
|
||||
selectedProjektarbeit: null,
|
||||
moodle_link: null,
|
||||
uid: null,
|
||||
title_edit_allowed: null,
|
||||
confetti_on_endupload: null,
|
||||
siginfolink_german: null,
|
||||
siginfolink_english: null,
|
||||
editingTitel: '',
|
||||
editingProjektarbeit: null,
|
||||
uid: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -61,10 +72,16 @@ export const AbgabetoolStudent = {
|
||||
this.$refs.modalTitelEdit.show();
|
||||
},
|
||||
async saveTitel() {
|
||||
const trimmed = this.editingTitel.trim();
|
||||
if (!trimmed) {
|
||||
this.$fhcAlert.alertWarning(this.$capitalize(this.$p.t('global/warningEmptyField')));
|
||||
return;
|
||||
const validation = validateThesisTitle(this.editingTitel);
|
||||
|
||||
if (!validation.isValid) {
|
||||
if (validation.error === 'empty') {
|
||||
this.$fhcAlert.alertWarning(this.$p.t('abgabetool/c4emptyThesisTitle'))
|
||||
} else if (validation.error === 'invalid_characters') {
|
||||
this.$fhcAlert.alertWarning(this.$p.t('abgabetool/c4invalidCharactersThesisTitle'))
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const confirmed = await this.$fhcAlert.confirm({
|
||||
@@ -81,15 +98,15 @@ export const AbgabetoolStudent = {
|
||||
this.$api.call(
|
||||
ApiAbgabe.postStudentProjektarbeitTitel(
|
||||
this.editingProjektarbeit.projektarbeit_id,
|
||||
trimmed
|
||||
validation.cleanedTitle
|
||||
)
|
||||
).then(res => {
|
||||
if (res.meta.status === 'success') {
|
||||
// update the local list entry in-place so the accordion header reflects it immediately
|
||||
this.editingProjektarbeit.titel = trimmed;
|
||||
this.editingProjektarbeit.titel = res.data;
|
||||
// keep the open detail modal in sync if it happens to be showing this projektarbeit
|
||||
if (this.selectedProjektarbeit?.projektarbeit_id === this.editingProjektarbeit.projektarbeit_id) {
|
||||
this.selectedProjektarbeit.titel = trimmed;
|
||||
this.selectedProjektarbeit.titel = res.data;
|
||||
}
|
||||
this.$fhcAlert.alertSuccess(this.$capitalize(this.$p.t('abgabetool/c4titelSavedSuccess')));
|
||||
this.$refs.modalTitelEdit.hide();
|
||||
@@ -309,6 +326,8 @@ export const AbgabetoolStudent = {
|
||||
// make sure zoom media query doesnt spill ever to other CIS4 sites
|
||||
document.documentElement.classList.add('abgabetool');
|
||||
|
||||
this.$api.call(ApiAuthinfo.getAuthUID()).then(res => this.uid = res.data.uid)
|
||||
|
||||
this.phrasenPromise = this.$p.loadCategory(['abgabetool', 'global'])
|
||||
this.phrasenPromise.then(()=> {this.phrasenResolved = true})
|
||||
|
||||
@@ -333,6 +352,10 @@ export const AbgabetoolStudent = {
|
||||
|
||||
this.$api.call(ApiAbgabe.getConfigStudent()).then(res => {
|
||||
this.moodle_link = res.data?.moodle_link
|
||||
this.title_edit_allowed = res.data?.title_edit_allowed
|
||||
this.confetti_on_endupload = res.data?.confetti_on_endupload
|
||||
this.siginfolink_german = res.data?.siginfolink_german
|
||||
this.siginfolink_english = res.data?.siginfolink_english
|
||||
}).catch(e => {
|
||||
this.loading = false
|
||||
})
|
||||
@@ -350,7 +373,7 @@ export const AbgabetoolStudent = {
|
||||
<FhcOverlay :active="loading"></FhcOverlay>
|
||||
|
||||
<bs-modal ref="modalContainerAbgabeDetail" class="bootstrap-prompt"
|
||||
dialogClass="modal-xl" :allowFullscreenExpand="true">
|
||||
dialogClass="modal-xl" :allowFullscreenExpand="true" bodyClass="px-4 py-4">
|
||||
<template v-slot:title>
|
||||
<div>
|
||||
{{$capitalize( $p.t('abgabetool/c4abgabeStudentDetailTitle') )}}
|
||||
@@ -367,6 +390,7 @@ export const AbgabetoolStudent = {
|
||||
ref="modalTitelEdit"
|
||||
class="bootstrap-prompt"
|
||||
dialogClass="bordered-modal"
|
||||
bodyClass="px-4 py-4"
|
||||
>
|
||||
<template v-slot:title>
|
||||
{{$capitalize( $p.t('abgabetool/c4titelBearbeiten') )}}
|
||||
@@ -381,7 +405,7 @@ export const AbgabetoolStudent = {
|
||||
rows="10"
|
||||
maxlength="1024"
|
||||
class="form-control w-100"
|
||||
@keyup.enter="saveTitel"
|
||||
@keydown.enter.prevent="saveTitel"
|
||||
/>
|
||||
<div class="form-text text-end">{{ editingTitel.length }} / 1024</div>
|
||||
</div>
|
||||
@@ -407,7 +431,7 @@ export const AbgabetoolStudent = {
|
||||
<h2>{{$capitalize( $p.t('abgabetool/abgabetoolTitle') )}}</h2>
|
||||
<hr>
|
||||
|
||||
<div v-if="projektarbeiten === null">
|
||||
<div v-if="projektarbeiten === null || projektarbeiten?.length == 0">
|
||||
{{$capitalize( $p.t('abgabetool/c4abgabeStudentNoProjectsFound') )}}
|
||||
</div>
|
||||
|
||||
@@ -497,7 +521,7 @@ export const AbgabetoolStudent = {
|
||||
style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"
|
||||
>{{ projektarbeit.titel }}</span>
|
||||
<button
|
||||
v-if="!isViewMode && projektarbeit.note == null"
|
||||
v-if="title_edit_allowed && !isViewMode && projektarbeit.note == null"
|
||||
class="btn btn-sm btn-outline-secondary border-0 p-1"
|
||||
v-tooltip.right="{ value: $capitalize($p.t('abgabetool/c4titelBearbeiten')), class: 'custom-tooltip' }"
|
||||
@click="openTitelEdit(projektarbeit, $event)"
|
||||
@@ -506,6 +530,15 @@ export const AbgabetoolStudent = {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-2">
|
||||
<div class="col-4 col-md-3 fw-bold">{{$capitalize( $p.t('abgabetool/c4note') )}}</div>
|
||||
|
||||
<div class="col-8 col-md-9">
|
||||
<span>{{getNoteBezeichnung(projektarbeit)}}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</AccordionTab>
|
||||
</template>
|
||||
</Accordion>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Validates the thesis title on the frontend
|
||||
* @param {string} title - The raw input from the title field
|
||||
* @returns {object} Validation result containing status and cleaned title
|
||||
*/
|
||||
export function validateThesisTitle(title) {
|
||||
if (!title) {
|
||||
return { isValid: false, error: 'empty' };
|
||||
}
|
||||
|
||||
// Replicate strip_tags / trim
|
||||
const cleanedTitle = title.replace(/<\/?[^>]+(>|$)/g, "").trim();
|
||||
|
||||
if (cleanedTitle === '') {
|
||||
return { isValid: false, error: 'empty' };
|
||||
}
|
||||
|
||||
// Replicate the emoji/pictograph rejection
|
||||
const emojiRegex = /\p{Extended_Pictographic}/u;
|
||||
if (emojiRegex.test(cleanedTitle)) {
|
||||
return { isValid: false, error: 'invalid_characters' };
|
||||
}
|
||||
|
||||
return { isValid: true, cleanedTitle: cleanedTitle };
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import PvAutoComplete from "../../../../../../../index.ci.php/public/js/componen
|
||||
import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js';
|
||||
|
||||
export default {
|
||||
name: 'ProjektarbeitDetails',
|
||||
components: {
|
||||
FormForm,
|
||||
FormInput,
|
||||
@@ -110,6 +111,10 @@ export default {
|
||||
this.formData.anmerkung = null;
|
||||
this.$refs.formDetails.clearValidation();
|
||||
},
|
||||
setFormData(projektarbeit) {
|
||||
this.formData = projektarbeit;
|
||||
if (this.formData.firma_id) this.formData.firma = {firma_id: this.formData.firma_id, name: this.formData.firma_name};
|
||||
},
|
||||
getFormData(newProjektarbeit, studiensemester_kurzbz, additional_lehrveranstaltung_id) {
|
||||
|
||||
this.additional_lehrveranstaltung_id = additional_lehrveranstaltung_id;
|
||||
@@ -148,8 +153,7 @@ export default {
|
||||
return this.$api
|
||||
.call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id))
|
||||
.then(result => {
|
||||
this.formData = result.data;
|
||||
if (this.formData.firma_id) this.formData.firma = {firma_id: this.formData.firma_id, name: this.formData.firma_name};
|
||||
this.setFormData(result.data)
|
||||
return result;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError)
|
||||
|
||||
+42
-59
@@ -9,6 +9,7 @@ import ProjektarbeitDetails from "./Details.js";
|
||||
import Projektbetreuer from "./Projektbetreuer.js";
|
||||
|
||||
export default {
|
||||
name: 'Projektarbeit',
|
||||
components: {
|
||||
CoreFilterCmpt,
|
||||
BsModal,
|
||||
@@ -213,17 +214,6 @@ export default {
|
||||
});
|
||||
container.append(button);
|
||||
|
||||
button = document.createElement('button');
|
||||
button.className = 'btn btn-outline-secondary btn-action';
|
||||
button.innerHTML = '<i class="fa fa-users"></i>';
|
||||
button.title = this.$p.t('projektarbeit', 'betreuerBearbeiten');
|
||||
button.addEventListener('click', (event) => {
|
||||
let data = cell.getData();
|
||||
this.editedProjektarbeit = data;
|
||||
this.actionEditBetreuer();
|
||||
});
|
||||
container.append(button);
|
||||
|
||||
button = document.createElement('button');
|
||||
button.className = 'btn btn-outline-secondary btn-action';
|
||||
button.innerHTML = '<i class="fa fa-xmark"></i>';
|
||||
@@ -264,6 +254,7 @@ export default {
|
||||
actionEditProjektarbeit() {
|
||||
this.statusNew = false;
|
||||
this.toggleMenu('details');
|
||||
this.$refs.projektbetreuer.getProjektbetreuer(this.editedProjektarbeit?.projektarbeit_id, this.editedProjektarbeit?.studiensemester_kurzbz);
|
||||
this.$refs.projektarbeitModal.show();
|
||||
},
|
||||
actionEditBetreuer() {
|
||||
@@ -280,18 +271,26 @@ export default {
|
||||
.then(this.deleteProjektarbeit)
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
saveProjektarbeit() {
|
||||
if(this.statusNew) this.addNewProjektarbeit()
|
||||
else this.updateProjektarbeit()
|
||||
},
|
||||
addNewProjektarbeit() {
|
||||
this.$refs.projektarbeitDetails.addNewProjektarbeit()
|
||||
.then((result) => {
|
||||
if(result?.data?.length) {
|
||||
this.editedProjektarbeit = result.data[0]
|
||||
this.$refs.projektarbeitDetails.setFormData(this.editedProjektarbeit)
|
||||
this.toggleMenu('betreuer');
|
||||
}
|
||||
this.projektarbeitSaved();
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
updateProjektarbeit() {
|
||||
this.$refs.projektarbeitDetails.updateProjektarbeit()
|
||||
.then((result) => {
|
||||
this.projektarbeitSaved();
|
||||
})
|
||||
.then(() => this.$refs.projektbetreuer.saveIfOpen())
|
||||
.then(() => this.projektarbeitSaved())
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
deleteProjektarbeit(projektarbeit_id) {
|
||||
@@ -308,7 +307,8 @@ export default {
|
||||
projektarbeitSaved() {
|
||||
this.reload();
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||
this.hideModal('projektarbeitModal');
|
||||
if(!this.statusNew) this.hideModal('projektarbeitModal');
|
||||
else this.statusNew = false
|
||||
},
|
||||
setDefaultStunden(projekttyp_kurzbz) {
|
||||
this.$refs.projektbetreuer.setDefaultStunden(projekttyp_kurzbz);
|
||||
@@ -321,22 +321,22 @@ export default {
|
||||
},
|
||||
toggleMenu(tabId) {
|
||||
this.activeTab = tabId;
|
||||
if (this.statusNew == false) {
|
||||
switch(tabId) {
|
||||
case 'details':
|
||||
this.$refs.projektarbeitDetails.getFormData(
|
||||
this.statusNew, this.editedProjektarbeit?.studiensemester_kurzbz, this.editedProjektarbeit?.lehrveranstaltung_id
|
||||
);
|
||||
this.$refs.projektarbeitDetails.loadProjektarbeit(this.editedProjektarbeit?.projektarbeit_id);
|
||||
break;
|
||||
case 'betreuer':
|
||||
this.$refs.projektbetreuer.getFormData(
|
||||
this.editedProjektarbeit ? this.editedProjektarbeit.projekttyp_kurzbz : null
|
||||
);
|
||||
this.$refs.projektbetreuer.getProjektbetreuer(this.editedProjektarbeit?.projektarbeit_id, this.editedProjektarbeit?.studiensemester_kurzbz);
|
||||
break;
|
||||
}
|
||||
if (this.statusNew == false && tabId == 'details') {
|
||||
|
||||
this.$refs.projektarbeitDetails.getFormData(
|
||||
this.statusNew, this.editedProjektarbeit?.studiensemester_kurzbz, this.editedProjektarbeit?.lehrveranstaltung_id
|
||||
);
|
||||
this.$refs.projektarbeitDetails.loadProjektarbeit(this.editedProjektarbeit?.projektarbeit_id);
|
||||
} else if(tabId == 'betreuer') {
|
||||
this.$refs.projektbetreuer.getFormData(
|
||||
this.editedProjektarbeit ? this.editedProjektarbeit.projekttyp_kurzbz : null
|
||||
);
|
||||
this.$refs.projektbetreuer.getProjektbetreuer(this.editedProjektarbeit?.projektarbeit_id, this.editedProjektarbeit?.studiensemester_kurzbz);
|
||||
}
|
||||
},
|
||||
resetFormData() {
|
||||
this.$refs.projektarbeitDetails.resetForm()
|
||||
this.$refs.projektbetreuer.resetForm()
|
||||
}
|
||||
},
|
||||
template: `
|
||||
@@ -358,46 +358,29 @@ export default {
|
||||
</core-filter-cmpt>
|
||||
|
||||
<!--Modal: projektarbeitModal-->
|
||||
<bs-modal ref="projektarbeitModal" dialog-class="modal-xl modal-dialog-scrollable" header-class="flex-wrap pb-0">
|
||||
<bs-modal ref="projektarbeitModal" :dialog-class="(statusNew ? 'modal-xl ' : 'fhc-xxl-modal ' ) + 'modal-dialog-scrollable'"
|
||||
header-class="flex-wrap pb-0"
|
||||
@hideBsModal="resetFormData"
|
||||
>
|
||||
<template #title>
|
||||
<p v-if="statusNew" class="fw-bold mt-3">{{$p.t('projektarbeit', 'projektarbeitAnlegen')}}</p>
|
||||
<p v-else class="fw-bold mt-3">{{$p.t('projektarbeit', 'projektarbeitBearbeiten')}}</p>
|
||||
</template>
|
||||
|
||||
<template #modal-header-content v-if="!statusNew">
|
||||
<ul class="nav nav-tabs w-100 mt-3 msg_preview" id="pa_tabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" :class="activeTab == 'details' ? 'active' : ''" id="details-tab" data-bs-toggle="tab" data-bs-target="#details" type="button" role="tab" aria-controls="details" aria-selected="true" @click="toggleMenu('details')">Details</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" :class="activeTab == 'betreuer' ? 'active' : ''" id="betreuer-tab" data-bs-toggle="tab" data-bs-target="#betreuer" type="button" role="tab" aria-controls="betreuer" aria-selected="false" @click="toggleMenu('betreuer')">{{$p.t('projektarbeit', 'betreuerGross')}}</button>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<div class="tab-content" id="pa_content">
|
||||
<div class="tab-pane fade show" :class="activeTab == 'details' ? 'active' : ''" id="details" role="tabpanel" aria-labelledby="details-tab">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<projektarbeit-details ref="projektarbeitDetails" :student="student" @projekttyp-changed="setDefaultStunden">
|
||||
</projektarbeit-details>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" >
|
||||
<div :class="statusNew ? 'col-12' : 'col-6'">
|
||||
<projektarbeit-details ref="projektarbeitDetails" :student="student" @projekttyp-changed="setDefaultStunden">
|
||||
</projektarbeit-details>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade show" :class="activeTab == 'betreuer' ? 'active' : ''" id="betreuer" role="tabpanel" aria-labelledby="betreuer-tab">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<projektbetreuer ref="projektbetreuer" :config="config" @betreuer-saved="reload"></projektbetreuer>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="statusNew ? '' : 'col-6'" :style="statusNew ? 'display: none' : ''">
|
||||
<projektbetreuer ref="projektbetreuer" :config="config" @betreuer-saved="reload"></projektbetreuer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{$p.t('ui', 'abbrechen')}}</button>
|
||||
<button v-if="statusNew" class="btn btn-primary" @click="addNewProjektarbeit()"> {{$p.t('ui', 'speichern')}}</button>
|
||||
<button v-if="!statusNew && activeTab == 'details'" class="btn btn-primary" @click="updateProjektarbeit()"> {{$p.t('ui', 'speichern')}}</button>
|
||||
<button type="button" class="btn btn-secondary" @click="resetFormData" data-bs-dismiss="modal">{{$p.t('ui', 'abbrechen')}}</button>
|
||||
<button class="btn btn-primary" @click="saveProjektarbeit()"> {{$p.t('ui', 'speichern')}}</button>
|
||||
</template>
|
||||
|
||||
</bs-modal>
|
||||
|
||||
+16
-10
@@ -10,6 +10,7 @@ import Vertrag from "./Vertrag.js";
|
||||
import ApiStvProjektbetreuer from '../../../../../api/factory/stv/projektbetreuer.js';
|
||||
|
||||
export default {
|
||||
name: 'Projektbetreuer',
|
||||
components: {
|
||||
CoreFilterCmpt,
|
||||
BsModal,
|
||||
@@ -296,17 +297,25 @@ export default {
|
||||
this.emptyBetreuerList();
|
||||
}
|
||||
},
|
||||
saveProjektbetreuer() {
|
||||
this.$refs.formProjektbetreuer.call(
|
||||
_doSaveBetreuer() {
|
||||
return this.$refs.formProjektbetreuer.call(
|
||||
ApiStvProjektbetreuer.saveProjektbetreuer(this.projektarbeit_id, this.getFormDataWithBetreuer())
|
||||
)
|
||||
.then(result => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||
).then(result => {
|
||||
this.getProjektbetreuer(this.projektarbeit_id, this.studiensemester_kurzbz);
|
||||
this.resetModes();
|
||||
this.$emit('betreuerSaved');
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
return result;
|
||||
});
|
||||
},
|
||||
// called by combined save button
|
||||
saveIfOpen() {
|
||||
if (!this.betreuerFormOpened) return Promise.resolve(null);
|
||||
return this._doSaveBetreuer();
|
||||
},
|
||||
saveProjektbetreuer() {
|
||||
this._doSaveBetreuer()
|
||||
.then(() => this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')))
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
searchBetreuer(event) {
|
||||
if (this.abortController.betreuer) {
|
||||
@@ -538,9 +547,6 @@ export default {
|
||||
|
||||
</form-form>
|
||||
|
||||
<button class="btn btn-primary" v-show="betreuerFormOpened" @click="saveProjektbetreuer">
|
||||
{{ $p.t('projektarbeit', 'betreuerSpeichern') }}
|
||||
</button>
|
||||
<!-- <div class = "mt-5" v-if="beurteilungDownloadLink !== null">
|
||||
<div class="mb-1">
|
||||
<a :href="beurteilungDownloadLink" class="btn btn-primary d-block" :class="{ 'disabled' : beurteilungDownloadLink === ''}">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export async function splitMailsHelper(mails, event, subject, body, alertPluginRef, phrasenPluginRef) {
|
||||
await phrasenPluginRef.loadCategory('ui');
|
||||
|
||||
debugger
|
||||
let splititem = ",";
|
||||
let maillist = mails.join(splititem);
|
||||
let useBcc = event?.ctrlKey || event?.metaKey;
|
||||
@@ -16,13 +16,13 @@ export async function splitMailsHelper(mails, event, subject, body, alertPluginR
|
||||
|
||||
// initial overhead: "mailto:?bcc=" -> 12 chars, "mailto:" -> 7 chars
|
||||
const baseOverhead = useBcc ? 12 : 7;
|
||||
let queryString = urlParams.toString();
|
||||
let queryString = urlParams.toString().replace(/\+/g, '%20');;
|
||||
let overhead = baseOverhead + (queryString ? 1 + queryString.length : 0); // +1 accounts for '?' or '&'
|
||||
|
||||
// calculate overhead with body to exceed the limit
|
||||
if (overhead > 2024) {
|
||||
await alertPluginRef.alertWarning(phrasenPluginRef.t('ui', 'bodyZuLang'));
|
||||
urlParams.delete('body');
|
||||
urlParams.delete('body').replace(/\+/g, '%20');;
|
||||
queryString = urlParams.toString();
|
||||
overhead = baseOverhead + (queryString ? 1 + queryString.length : 0);
|
||||
}
|
||||
|
||||
+16
-276
@@ -34544,7 +34544,7 @@ array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Sie können eine Entschuldigung für einen Zeitraum von bis zu {0} Tagen in die Vergangenheit und bis zum Ende des aktuellen Semesters hochladen. Die erlaubten Dateitypen für das Dokument sind .pdf, .png und .jpg.
|
||||
|
||||
Sobald Sie eine Entschuldigung hochladen wird die zugehörige Studiengangsassistenz informiert und Ihr Anliegen überprüft. Solange Ihre Entschuldigung noch keinen akzeptierten oder abgelehnten Status erhalten hat, steht es Ihnen frei diese inklusive Datei zu löschen. Sobald sie entweder akzeptiert oder abgelehnt wurde können Sie den Eintrag nichtmehr löschen.
|
||||
Sobald Sie eine Entschuldigung hochladen wird die zugehörige Studiengangsassistenz informiert und Ihr Anliegen überprüft. Solange Ihre Entschuldigung noch keinen akzeptierten oder abgelehnten Status erhalten hat, steht es Ihnen frei diese inklusive Datei zu löschen. Sobald sie entweder akzeptiert oder abgelehnt wurde können Sie den Eintrag nicht mehr löschen.
|
||||
|
||||
Bei einer akzeptierten Entschuldigung werden sämtliche digitalen Anwesenheiten in diesem Zeitraum als positiv gewertet. Eine abgelehnte Entschuldigung hat keine Auswirkungen auf ihre Anwesenheitsquote.',
|
||||
'description' => '',
|
||||
@@ -42204,12 +42204,12 @@ array(
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4fehlerAktualitaetProjektarbeit',
|
||||
'phrase' => 'c4fehlerAktualitaetProjektarbeitv2',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Projektarbeit ist nichtmehr aktuell",
|
||||
'text' => "Projektarbeit ist nicht mehr aktuell",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
@@ -43987,46 +43987,6 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'abgabetoolTitleBetreuer',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Bachelor-/Masterarbeiten Betreuungen",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "Supervision of Bachelor's/Master's theses",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'abgabetoolTitleAdmin',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Bachelor-/Masterarbeiten Administration",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "Administration of Bachelor's/Master's theses",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
@@ -44207,26 +44167,6 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4abgaben_n',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "{0} Abgaben",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "{0} Dates",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
@@ -44270,18 +44210,18 @@ array(
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4orgformv2',
|
||||
'phrase' => 'c4orgform',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Organisationsform",
|
||||
'text' => "Organisationseinheit",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "organization form",
|
||||
'text' => "organization unit",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
@@ -44647,26 +44587,6 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4edit',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Bearbeiten",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "Edit",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
@@ -45087,46 +45007,6 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4notetermin',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Terminnote",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Date grade',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4noteprojektarbeit',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Projektarbeitnote",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Project work grade',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
@@ -45492,26 +45372,6 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4beurteilungsnotizBeiNegNote',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Wenn Sie eine negative Note erteilen, müssen Sie eine Beurteilungsnotiz ausfüllen!",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'If you give a failing grade, you must fill out an evaluation form!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
@@ -45723,26 +45583,6 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4confirm_delete_n_termine',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Möchten Sie wirklich {0} Termine Löschen?",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Do you really want to delete {0} dates?',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
@@ -47527,18 +47367,18 @@ array(
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4projektansicht',
|
||||
'phrase' => 'c4signaturinfo',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Projektarbeitansicht',
|
||||
'text' => 'Digitale Signatur Leitfaden',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Projectwork mode',
|
||||
'text' => 'Guidelines for digital signatures',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
@@ -47547,18 +47387,18 @@ array(
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4terminansicht',
|
||||
'phrase' => 'c4emptyThesisTitle',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Terminansicht',
|
||||
'text' => 'Projektarbeit Titel darf nicht leer sein.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Deadline mode',
|
||||
'text' => 'Projekt work title is not allowed to be empty.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
@@ -47567,118 +47407,18 @@ array(
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4editTerminserie',
|
||||
'phrase' => 'c4invalidCharactersThesisTitle',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Mehrfachbearbeitung Termine',
|
||||
'text' => 'Ungültige Zeichen im Titel der Projektarbeit gefunden.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Multiedit Deadlines',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4nSelected',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => '{0} Termine zur Bearbeitung ausgewählt.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => '{0} Deadlines selected for editing.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4confirm_edit_n_termine',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Möchten sie wirklich {0} Termine bearbeiten?',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Do you really want to edit {0} Deadlines?',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4titelBearbeiten',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Titel bearbeiten',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Edit title',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'abgabetool',
|
||||
'phrase' => 'c4confirmTitelSpeichern',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Möchten Sie den Titel wirklich bearbeiten?',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Do you really want to edit the title?',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'bodyZuLang',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Der Emailtext ist zu lange um kopiert zu werden.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'The Emailbody is too long to be copied',
|
||||
'text' => 'Invalid characters detected in thesis title.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
@@ -48673,7 +48413,7 @@ array(
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'category' => 'stv',
|
||||
'phrase' => 'weitereEMail',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
|
||||
Reference in New Issue
Block a user