Merge branch 'master' into tabulator-localization-minor-fixes

This commit is contained in:
adisposkofh
2026-08-10 15:57:12 +02:00
11 changed files with 184 additions and 59 deletions
+7 -1
View File
@@ -60,7 +60,13 @@ $config['tabs'] =
],
'notes' => [
//if true, the count of Messages will be shown in the header of the Tab Messages
'showCountNotes' => true
'showCountNotes' => true,
//if true: section with following fields will be displayed: 'verfasser', 'bearbeiter', 'von', 'bis' and 'erledigt'
'showErweitert' => false,
//notizlayout: choose of "classicFas", "twoColumnsFormLeft", twoColumnsFormRight, popupModal"
'notizLayout' => 'popupModal'
],
'combinePeople' => [
//multitab should only be shown with this length of selection
@@ -17,60 +17,59 @@
*/
if (!defined('BASEPATH'))
exit('No direct script access allowed');
exit('No direct script access allowed');
class OtherLvPlan extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'otherLvPlanViewData' => ['basis/other_lv_plan:r'],
]);
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'otherLvPlanViewData' => ['basis/other_lv_plan:r'],
]);
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$this->load->library('ProfilLib');
}
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
//------------------------------------------------------------------------------------------------------------------
// Public methods
/**
* retrieves viewData for other lv plan view
* @access public
* @param $uid the userID for which the other lv plan is being viewed
*/
public function otherLvPlanViewData($uid)
{
$isMitarbeiterResult = $this->MitarbeiterModel->isMitarbeiter($uid);
$isMitarbeiter = getData($isMitarbeiterResult);
$isStudent = !$isMitarbeiter;
/**
* retrieves viewData for other lv plan view
* @access public
* @param $uid the userID for which the other lv plan is being viewed
*/
public function otherLvPlanViewData($uid)
{
$isMitarbeiterResult = $this->MitarbeiterModel->isMitarbeiter($uid);
$isMitarbeiter = getData($isMitarbeiterResult);
$isStudent = !$isMitarbeiter;
$this->BenutzerModel->addSelect(["foto", "vorname", "nachname"]);
$this->BenutzerModel->addJoin("tbl_person", "person_id");
$personResult = $this->BenutzerModel->load([$uid]);
$person = hasData($personResult) ? getData($personResult) : null;
$resProfileData = $this->profillib->getView($uid);
$profileData = hasData($resProfileData) ? getData($resProfileData) : null;
$viewData = [
"user_data" => [
"username" => $uid,
"is_student" => $isStudent,
"is_mitarbeiter" => $isMitarbeiter,
"foto" => $person[0]->foto,
"vorname" => $person[0]->vorname,
"nachname" => $person[0]->nachname,
],
];
$viewData = [
"user_data" => [
"username" => $uid,
"is_student" => $isStudent,
"is_mitarbeiter" => $isMitarbeiter,
"foto" => $profileData->data->foto,
"vorname" => $profileData->data->vorname,
"nachname" => $profileData->data->nachname,
],
];
$this->terminateWithSuccess($viewData);
}
$this->terminateWithSuccess($viewData);
}
// -----------------------------------------------------------------------------------------------------------------
// Private methods
// -----------------------------------------------------------------------------------------------------------------
// Private methods
}
+4 -1
View File
@@ -80,10 +80,12 @@ class StundenplanLib
if (isError($semester_range))
return $semester_range;
$semester_range = getData($semester_range);
$this->_ci->addMeta('semester_range', $semester_range);
$this->sortStudienSemester($semester_range);
$function_error = $this->applyLoadUeberSemesterHaelfte($semester_range);
$this->_ci->addMeta('nach_apply_semester_range', $semester_range);
if ($function_error)
return $function_error;
@@ -784,7 +786,8 @@ class StundenplanLib
$this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
// gets all studiensemester from the student from start_date to end_date
$semester_range = $this->_ci->StudiensemesterModel->getByDateRange($start_date, $end_date);
//$semester_range = $this->_ci->StudiensemesterModel->getByDateRange($start_date, $end_date);
$semester_range = $this->_ci->StudiensemesterModel->getContainingOrNearestByDateRange($start_date, $end_date);
if (isError($semester_range))
return $semester_range;
@@ -229,6 +229,82 @@ class Studiensemester_model extends DB_Model
return $this->execQuery($query, array($date,$date,$date,$date));
}
/**
* Gets all Studiensemester where the range dates are contained
* or the nearest if date is not contained
* @param $from
* @param $to
* @return array|null
*/
public function getContainingOrNearestByDateRange($from, $to)
{
if (date_format(date_create($from), 'Y-m-d') > (date_format(date_create($to), 'Y-m-d')))
return success(array());
$query = <<<EOSQL
WITH semester_interval_startdate AS (
SELECT
s.*
FROM
public.tbl_studiensemester s
WHERE
{$this->db->escape($from)}::date BETWEEN s.start AND s.ende
ORDER BY
s.start DESC
LIMIT 1
),
semester_interval_enddate AS (
SELECT
s.*
FROM
public.tbl_studiensemester s
WHERE
{$this->db->escape($to)}::date BETWEEN s.start AND s.ende
ORDER BY
s.start DESC
LIMIT 1
),
nearest_semester_interval_startdate AS (
SELECT
LEAST(ABS(s.start - {$this->db->escape($from)}::date), ABS(s.ende - {$this->db->escape($from)}::date)) AS mindiff,
s.*
FROM
public.tbl_studiensemester s
WHERE
s.ende < {$this->db->escape($from)}::date
ORDER BY
1 ASC
LIMIT 1
),
nearest_semester_interval_enddate AS (
SELECT
LEAST(ABS(s.start - {$this->db->escape($to)}::date), ABS(s.ende - {$this->db->escape($to)}::date)) AS mindiff,
s.*
FROM
public.tbl_studiensemester s
WHERE
s.start > {$this->db->escape($to)}::date
ORDER BY
1 ASC
LIMIT 1
)
SELECT
COALESCE(
(SELECT studiensemester_kurzbz FROM semester_interval_startdate),
(SELECT studiensemester_kurzbz FROM nearest_semester_interval_startdate)
) AS studiensemester_kurzbz
UNION
SELECT
COALESCE(
(SELECT studiensemester_kurzbz FROM semester_interval_enddate),
(SELECT studiensemester_kurzbz FROM nearest_semester_interval_enddate)
) AS studiensemester_kurzbz
EOSQL;
return $this->execReadonlyQuery($query);
}
/**
* Gets all Studiensemester between two dates
* @param $from
@@ -70,6 +70,10 @@
margin-top: 20px;
}
.filter-table-dataset .tabulator-tableholder {
padding-bottom: 16px;
}
.tabulator {
font-size: 1rem;
}
@@ -56,6 +56,7 @@ export default {
previewText: null,
previewBody: "",
replyData: null,
isSending: false
}
},
methods: {
@@ -113,6 +114,9 @@ export default {
data.append('data', JSON.stringify(this.formData));
data.append('ids', JSON.stringify(this.id));
//for disabling sendButton and show Spinner
this.isSending = true;
return this.$refs.formMessage
.call(ApiMessages.sendMessage(this.typeId, data))
.then(response => {
@@ -121,6 +125,7 @@ export default {
this.resetForm();
}).catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.isSending = false;
//just emit if no multitasking
if(this.id.length == 1){
@@ -288,6 +293,9 @@ export default {
dialog-class=" modal-dialog-scrollable modal-xl modal-msg"
header-class="flex-wrap pb-0"
body-class="px-3 py-2"
:backdrop="isSending ? 'static' : true"
:keyboard="!isSending"
:noCloseBtn="isSending"
@hidden.bs.modal="resetForm"
>
@@ -476,7 +484,12 @@ export default {
<button class="btn btn-secondary" @click="resetForm">{{$p.t('ui', 'reset')}}</button>
<button v-if="statusNew" type="button" class="btn btn-primary" @click="sendMessage()">{{$p.t('ui', 'nachrichtSenden')}}</button>
<button v-if="statusNew" type="button" class="btn btn-primary" :disabled="isSending" @click="sendMessage()">
<span
v-if="isSending"
class="spinner-border spinner-border-sm me-2"
></span>
{{$p.t('ui', 'nachrichtSenden')}}</button>
<button v-else type="button" class="btn btn-primary" @click="replyMessage(formData.message_id)">{{$p.t('global', 'reply')}}</button>
</div>
</template>
@@ -55,6 +55,7 @@ export default {
previewBody: "",
replyData: null,
messageSent: false,
isSending: false
}
},
methods: {
@@ -104,16 +105,21 @@ export default {
data.append('data', JSON.stringify(this.formData));
data.append('ids', JSON.stringify(this.id));
//for disabling sendButton and show Spinner
this.isSending = true;
return this.$api
.call(ApiMessages.sendMessage(this.typeId, data))
.then(response => {
if(this.openMode == "inSamePage")
if(this.openMode == "inSamePage") {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSent'));
}
this.hideTemplate();
this.resetForm();
this.messageSent = true;
}).catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.isSending = false;
if(this.openMode == "inSamePage" && this.id.length == 1 ){
this.$emit('reloadTable');
}
@@ -413,7 +419,12 @@ export default {
<button class="btn btn-secondary" @click="resetForm">{{$p.t('ui', 'reset')}}</button>
<button v-if="statusNew" type="button" class="btn btn-primary" @click="sendMessage()">{{$p.t('ui', 'nachrichtSenden')}}</button>
<button v-if="statusNew" type="button" class="btn btn-primary" :disabled="isSending" @click="sendMessage()">
<span
v-if="isSending"
class="spinner-border spinner-border-sm me-2"
></span>
{{$p.t('ui', 'nachrichtSenden')}}</button>
<button v-else type="button" class="btn btn-primary" @click="replyMessage(formData.message_id)">{{$p.t('global', 'reply')}}</button>
</div>
@@ -15,7 +15,8 @@ export default {
data() {
return {
configStudent: {},
configStudents: {}
configStudents: {},
activeTab: null
};
},
props: {
@@ -74,6 +75,10 @@ export default {
})
.catch(this.$fhcAlert.handleSystemError);
},
handleTabChanged(key) {
this.activeTab = key
this.reload()
},
reload() {
if (this.$refs.tabs?.$refs?.current?.reload)
this.$refs.tabs.$refs.current.reload();
@@ -111,12 +116,12 @@ export default {
:useprimevue="true"
:modelValue="students[0]"
:config="config"
:default="$route.params.tab"
:default="activeTab ?? $route.params.tab"
style="flex: 1 1 0%; height: 0%"
@changed="reload"
@changed="handleTabChanged"
>
</fhc-tabs>
<fhc-tabs v-else ref="tabs" :useprimevue="true" :modelValue="students" :config="config" :default="$route.params.tab" style="flex: 1 1 0%; height: 0%" @changed="reload"></fhc-tabs>
<fhc-tabs v-else ref="tabs" :useprimevue="true" :modelValue="students" :config="config" :default="activeTab ?? $route.params.tab" style="flex: 1 1 0%; height: 0%" @changed="handleTabChanged"></fhc-tabs>
</div>
<div v-else>
Loading...
@@ -434,7 +434,10 @@ export default {
}
if (!this.formData.akadgrad_id && this.arrAkadGrad.length > 0) {
this.formData.akadgrad_id = this.arrAkadGrad[0].akadgrad_id;
if(this.student.geschlecht == 'w')
this.formData.akadgrad_id = this.arrAkadGrad[1].akadgrad_id;
else
this.formData.akadgrad_id = this.arrAkadGrad[0].akadgrad_id;
}
},
printDocument(link) {
@@ -718,7 +721,7 @@ export default {
:key="grad.akadgrad_id"
:value="grad.akadgrad_id"
>
{{grad.titel}}
{{ grad.titel }} <span v-if="grad.geschlecht !== null"> ({{ grad.geschlecht }}) </span>
</option>
</form-input>
<form-input
@@ -8,7 +8,11 @@ export default {
CoreNotiz
},
props: {
modelValue: Object
modelValue: Object,
config: {
type: Object,
default: {}
}
},
data() {
return {
@@ -23,7 +27,7 @@ export default {
class="overflow-hidden"
:endpoint="endpoint"
ref="formc"
notiz-layout="popupModal"
:notiz-layout="config.notizLayout"
type-id="person_id"
:id="modelValue.person_id"
show-document
@@ -31,6 +35,7 @@ export default {
:visibleColumns="['titel','text','verfasser','bearbeiter','dokumente']"
@reload="$emit('update:suffix')"
tabulator-persistence-id="stv-notiz-20260217"
:show-erweitert="config.showErweitert"
>
</core-notiz>
@@ -49,16 +54,16 @@ ref="formc"
type-id: id to which table the notizdata should be connected... eg. person_id, prestudent_id, uid (for mitarbeiter_uid), projekt_kurzbz, projektphase_id, projekttask_id,
bestellung_id, lehreinheit_id, anrechnung_id
notizLayout: "classicFas", "twoColumnsFormLeft", twoColumnsFormRight, popupModal"
notizLayout: "classicFas", "twoColumnsFormLeft", twoColumnsFormRight, popupModal"; is now configurable in config/stv.php
showErweitert: if true: section with following fields will be displayed:
'verfasser', 'bearbeiter', 'von', 'bis'
'verfasser', 'bearbeiter', 'von', 'bis' and 'erledigt'; is now configurable in config/stv.php
showDocument: if true: section with documentHandling will be displayed
showTinyMCE: if true: section with WYSIWYG Editor for Text will be displayed
visibleColumns: list, which fields shoult be showed as default in filter component
visibleColumns: list, which fields should be showed as default in filter component
fullVersion: :visibleColumns="['titel','text','bearbeiter','verfasser','von','bis','dokumente','erledigt','notiz_id','notizzuordnung_id','id','lastupdate']"
+1 -1
View File
@@ -219,7 +219,7 @@ export default {
:scrollable="true"
:lazy="true"
:activeIndex="calcActiveIndex"
:pt="{navContainer:{style: 'flex: 0 0 auto;'}, panelContainer:{class: 'overflow-y-scroll p-2', style: 'flex: 1 1 auto;'}}"
:pt="{navContainer:{style: 'flex: 0 0 auto;'}, panelContainer:{class: 'overflow-y-scroll p-2 pe-3', style: 'flex: 1 1 auto;'}}"
@tab-click="handleTabClick"
>
<tabpanel