mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 12:19:28 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f3e1208f27 | |||
| 13684e638f | |||
| 55be235fbe | |||
| ec782d168c | |||
| ddfcb68d62 | |||
| 3cf7543586 | |||
| c6d438c032 | |||
| 6560b27de9 | |||
| fe5931e6c7 | |||
| a7c4571d25 | |||
| 8d5588de02 | |||
| 6a813499d1 | |||
| 2c75fb7827 | |||
| 9f8e292f49 | |||
| 11f93f0c91 | |||
| 7307c1fa44 | |||
| 869a7e3335 | |||
| 010b370914 | |||
| a29e0aeb62 | |||
| fe68d46831 | |||
| d8f5c412c5 | |||
| 59d531ed0f |
@@ -45,6 +45,14 @@ $config['navigation_header'] = array(
|
||||
'expand' => true,
|
||||
'sort' => 30,
|
||||
'requiredPermissions' => 'admin:w'
|
||||
),
|
||||
'classScheduleOverview' => array(
|
||||
'link' => site_url('lehre/ClassSchedule'),
|
||||
'icon' => '',
|
||||
'description' => 'Unterrichtszeiten der Studiengänge',
|
||||
'expand' => true,
|
||||
'sort' => 50,
|
||||
'requiredPermissions' => 'lehre/unterrichtszeiten_gk:r'
|
||||
)
|
||||
)
|
||||
),
|
||||
@@ -383,3 +391,12 @@ $config['navigation_menu']['apps'] = [
|
||||
'requiredPermissions' => array('lehre/lehrauftrag_bestellen:r', 'lehre/lehrauftrag_erteilen:r')
|
||||
]
|
||||
];
|
||||
|
||||
$config['navigation_menu']['lehre/ClassSchedule/index'] = array(
|
||||
'classScheduleOverview' => array(
|
||||
'link' => site_url('lehre/ClassSchedule'),
|
||||
'description' => 'Unterrichtszeiten der Studiengänge',
|
||||
'icon' => '',
|
||||
'sort' => 1
|
||||
)
|
||||
);
|
||||
@@ -119,6 +119,9 @@ $route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/prestudent/(:num)'] = 'a
|
||||
// // (studiensemester_kurzbz)/person/(person_id)
|
||||
$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/person/(:num)'] = 'api/frontend/v1/stv/Students/getPerson/$1/$2';
|
||||
|
||||
|
||||
$route['lehre/ClassSchedule/.*'] = 'lehre/ClassSchedule/index';
|
||||
|
||||
// load routes from extensions, also look for environment-specific configs
|
||||
$subdirs = ['application/config/extensions', 'application/config/' . ENVIRONMENT . '/extensions'];
|
||||
|
||||
|
||||
@@ -0,0 +1,666 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
class ClassScheduleApi extends FHCAPI_Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getAllClassTimeValidityPeriods'=> array('lehre/unterrichtszeiten_gk:r'),
|
||||
'getAllClassTimeValidityPeriodsPerOrganizationalUnit' => array('lehre/unterrichtszeiten_gk:r'),
|
||||
'getClassTimeValidityPeriod' => array('lehre/unterrichtszeiten_gk:r'),
|
||||
'createClassTimeSlotValidityPeriod' => array('lehre/unterrichtszeiten_gk:rw'),
|
||||
'updateClassTimeSlotValidityPeriod' => array('lehre/unterrichtszeiten_gk:rw'),
|
||||
'deleteClassTimeSlotValidityPeriod' => array('lehre/unterrichtszeiten_gk:rw'),
|
||||
'getClassTimeSlotsForValidityPeriod' => array('lehre/unterrichtszeiten_gk:r'),
|
||||
'createClassTimeSlotsForValidityPeriod' => array('lehre/unterrichtszeiten_gk:r'),
|
||||
'updateClassTimeSlotsForValidityPeriod' => array('lehre/unterrichtszeiten_gk:r'),
|
||||
'deleteClassTimeSlotsForValidityPeriod' => array('lehre/unterrichtszeiten_gk:r'),
|
||||
'getAllClassScheduleTypes' => array('lehre/unterrichtszeiten_typ:r'),
|
||||
'createClassTimeSlotType' => array('lehre/unterrichtszeiten_typ:rw'),
|
||||
'updateClassTimeSlotType' => array('lehre/unterrichtszeiten_typ:rw'),
|
||||
'deleteClassTimeSlotType' => array('lehre/unterrichtszeiten_typ:rw'),
|
||||
]);
|
||||
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->load->model('education/ClassTimeSlotValidityPeriod_model', "ClassTimeSlotValidityPeriodModel");
|
||||
$this->load->model('education/ClassTimeSlot_model', "ClassTimeSlotModel");
|
||||
$this->load->model('education/ClassTimeSlotType_model', "ClassTimeSlotTypeModel");
|
||||
|
||||
// Loads phrases system
|
||||
$this->loadPhrases([
|
||||
'global',
|
||||
'ui',
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
public function getAllClassTimeValidityPeriods()
|
||||
{
|
||||
$entitledOrganizationalUnitsShortCodes = $this->permissionlib->getOE_isEntitledFor('lehre/unterrichtszeiten_gk');
|
||||
|
||||
$organizationalUnitShortCode = $this->input->get('organizationalUnitShortCode');
|
||||
$validityPeriodFrom = $this->input->get('validityPeriodFrom');
|
||||
$validityPeriodTo = $this->input->get('validityPeriodTo');
|
||||
|
||||
$this->ClassTimeSlotValidityPeriodModel->db->where_in('lehre.tbl_unterrichtszeiten_gueltigkeit.oe_kurzbz', $entitledOrganizationalUnitsShortCodes);
|
||||
$this->ClassTimeSlotValidityPeriodModel->addSelect(
|
||||
'lehre.tbl_unterrichtszeiten_gueltigkeit.*,' .
|
||||
'public.tbl_organisationseinheit.bezeichnung as organisationseinheit_bezeichnung,' .
|
||||
'public.tbl_organisationseinheit.organisationseinheittyp_kurzbz as organisationseinheit_organisationseinheittyp_kurzbz,' .
|
||||
'lehre.tbl_studienplan.bezeichnung as studienplan_bezeichnung,' .
|
||||
'lehre.tbl_unterrichtszeiten_typ.bezeichnung_mehrsprachig as unterrichtszeiten_typ_bezeichnung_mehrsprachig, '
|
||||
);
|
||||
$this->ClassTimeSlotValidityPeriodModel->addJoin('lehre.tbl_studienplan', 'lehre.tbl_studienplan.studienplan_id=lehre.tbl_unterrichtszeiten_gueltigkeit.studienplan_id', 'LEFT');
|
||||
$this->ClassTimeSlotValidityPeriodModel->addJoin('public.tbl_organisationseinheit', 'public.tbl_organisationseinheit.oe_kurzbz=lehre.tbl_unterrichtszeiten_gueltigkeit.oe_kurzbz', 'LEFT');
|
||||
$this->ClassTimeSlotValidityPeriodModel->addJoin('lehre.tbl_unterrichtszeiten_typ', 'lehre.tbl_unterrichtszeiten_typ.unterrichtszeitentyp_kurzbz=lehre.tbl_unterrichtszeiten_gueltigkeit.unterrichtszeitentyp_kurzbz', 'LEFT');
|
||||
$this->ClassTimeSlotValidityPeriodModel->addOrder('gueltig_von', 'DESC');
|
||||
|
||||
if ($organizationalUnitShortCode) {
|
||||
$this->ClassTimeSlotValidityPeriodModel->db->where('lehre.tbl_unterrichtszeiten_gueltigkeit.oe_kurzbz', $organizationalUnitShortCode);
|
||||
}
|
||||
|
||||
if ($validityPeriodFrom) {
|
||||
$this->ClassTimeSlotValidityPeriodModel->db
|
||||
->where('lehre.tbl_unterrichtszeiten_gueltigkeit.gueltig_von >=', date('Y-m-d', strtotime($validityPeriodFrom)));
|
||||
}
|
||||
if ($validityPeriodTo) {
|
||||
$this->ClassTimeSlotValidityPeriodModel->db
|
||||
->where('lehre.tbl_unterrichtszeiten_gueltigkeit.gueltig_bis <=', date('Y-m-d', strtotime($validityPeriodTo)));
|
||||
}
|
||||
|
||||
$class_time_slot_validity_period_res = $this->ClassTimeSlotValidityPeriodModel->load();
|
||||
$class_time_slot_validity_period_res = $this->getDataOrTerminateWithError($class_time_slot_validity_period_res);
|
||||
$this->terminateWithSuccess($class_time_slot_validity_period_res);
|
||||
}
|
||||
|
||||
public function getAllClassTimeValidityPeriodsPerOrganizationalUnit($organizationUnitId)
|
||||
{
|
||||
if (!$this->isUserEntitledForOrganizationalUnit($organizationUnitId, 'lehre/unterrichtszeiten_gk')) {
|
||||
$this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
}
|
||||
|
||||
$this->ClassTimeSlotValidityPeriodModel->addSelect(
|
||||
'lehre.tbl_unterrichtszeiten_gueltigkeit.*,' .
|
||||
'public.tbl_organisationseinheit.bezeichnung as organisationseinheit_bezeichnung,' .
|
||||
'public.tbl_organisationseinheit.organisationseinheittyp_kurzbz as organisationseinheit_organisationseinheittyp_kurzbz,' .
|
||||
'lehre.tbl_studienplan.bezeichnung as studienplan_bezeichnung,' .
|
||||
'lehre.tbl_unterrichtszeiten_typ.bezeichnung_mehrsprachig as unterrichtszeiten_typ_bezeichnung_mehrsprachig, '
|
||||
);
|
||||
$this->ClassTimeSlotValidityPeriodModel->addJoin('lehre.tbl_studienplan', 'lehre.tbl_studienplan.studienplan_id=lehre.tbl_unterrichtszeiten_gueltigkeit.studienplan_id', 'LEFT');
|
||||
$this->ClassTimeSlotValidityPeriodModel->addJoin('public.tbl_organisationseinheit', 'public.tbl_organisationseinheit.oe_kurzbz=lehre.tbl_unterrichtszeiten_gueltigkeit.oe_kurzbz', 'LEFT');
|
||||
$this->ClassTimeSlotValidityPeriodModel->addJoin('lehre.tbl_unterrichtszeiten_typ', 'lehre.tbl_unterrichtszeiten_typ.unterrichtszeitentyp_kurzbz=lehre.tbl_unterrichtszeiten_gueltigkeit.unterrichtszeitentyp_kurzbz', 'LEFT');
|
||||
$this->ClassTimeSlotValidityPeriodModel->addOrder('gueltig_von', 'DESC');
|
||||
$class_time_slot_validity_period_res = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['lehre.tbl_unterrichtszeiten_gueltigkeit.oe_kurzbz' => $organizationUnitId]);
|
||||
$class_time_slot_validity_period_res = $this->getDataOrTerminateWithError($class_time_slot_validity_period_res);
|
||||
$this->terminateWithSuccess($class_time_slot_validity_period_res);
|
||||
}
|
||||
|
||||
public function getClassTimeValidityPeriod($classTimeSlotValidityPeriodId)
|
||||
{
|
||||
$this->ClassTimeSlotValidityPeriodModel->addSelect('
|
||||
lehre.tbl_unterrichtszeiten_gueltigkeit.*,
|
||||
public.tbl_organisationseinheit.oe_kurzbz as oe_kurzbz,
|
||||
public.tbl_organisationseinheit.bezeichnung as oe_bezeichnung,
|
||||
public.tbl_organisationseinheit.organisationseinheittyp_kurzbz as oe_organisationseinheittyp_kurzbz,
|
||||
lehre.tbl_studienplan.studienplan_id,
|
||||
lehre.tbl_studienplan.bezeichnung as studienplan_bezeichnung,
|
||||
');
|
||||
$this->ClassTimeSlotValidityPeriodModel->addJoin('public.tbl_organisationseinheit', 'public.tbl_organisationseinheit.oe_kurzbz=lehre.tbl_unterrichtszeiten_gueltigkeit.oe_kurzbz', 'LEFT');
|
||||
$this->ClassTimeSlotValidityPeriodModel->addJoin('lehre.tbl_studienplan', 'lehre.tbl_studienplan.studienplan_id=lehre.tbl_unterrichtszeiten_gueltigkeit.studienplan_id', 'LEFT');
|
||||
$class_time_slot_validity_period_res = $this->ClassTimeSlotValidityPeriodModel->load($classTimeSlotValidityPeriodId);
|
||||
|
||||
$class_time_slot_validity_period_res = $this->getDataOrTerminateWithError($class_time_slot_validity_period_res);
|
||||
if (!$class_time_slot_validity_period_res || count($class_time_slot_validity_period_res) === 0) {
|
||||
$this->terminateWithError($this->p->t('ui', 'classTimeSlotValidityPeriodNotFound'));
|
||||
}
|
||||
|
||||
if (!$this->isUserEntitledForOrganizationalUnit($class_time_slot_validity_period_res[0]->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) {
|
||||
$this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess($class_time_slot_validity_period_res);
|
||||
}
|
||||
|
||||
public function createClassTimeSlotValidityPeriod()
|
||||
{
|
||||
$this->form_validation->set_rules('validityPeriodFrom', 'Validity Period From', 'required|is_valid_date[Y-m-d]', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'field_validityPeriodFrom')]),
|
||||
'is_valid_date' => $this->p->t('ui', 'error_fieldInvalidDate', ['field' => $this->p->t('ui', 'field_validityPeriodFrom')])
|
||||
]);
|
||||
$this->form_validation->set_rules('validityPeriodTo', 'Validity Period To', 'required|is_valid_date[Y-m-d]|callback_date_greater_equal[validityPeriodFrom]');
|
||||
$this->form_validation->set_rules('organizationalUnitShortCode', 'Organizational Unit Shortcode', 'required|max_length[32]', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'field_organizationalUnit')]),
|
||||
'max_length' => $this->p->t('ui', 'error_fieldMaxLength', ['field' => $this->p->t('ui', 'field_organizationalUnit'), 'max' => 32])
|
||||
]);
|
||||
$this->form_validation->set_rules('semester', 'Semester', 'is_natural_no_zero|less_than_equal_to[8]', [
|
||||
'is_natural_no_zero' => $this->p->t('ui', 'error_fieldInvalid', ['field' => $this->p->t('ui', 'field_semester')]),
|
||||
'less_than_equal_to' => $this->p->t('ui', 'error_fieldMaxValue', ['field' => $this->p->t('ui', 'field_semester'), 'max' => 8])
|
||||
]);
|
||||
$this->form_validation->set_rules('classTimeSlotTypeShortcode', 'Class Time Slot Type Shortcode', 'max_length[32]');
|
||||
$this->form_validation->set_rules('studyPlanId', 'Study Plan ID', 'is_natural_no_zero');
|
||||
|
||||
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
if (!$this->isUserEntitledForOrganizationalUnit($this->input->post('organizationalUnitShortCode'), 'lehre/unterrichtszeiten_gk')) {
|
||||
$this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
}
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
$result = $this->ClassTimeSlotValidityPeriodModel->insert([
|
||||
'gueltig_von' => $this->input->post('validityPeriodFrom'),
|
||||
'gueltig_bis' => $this->input->post('validityPeriodTo'),
|
||||
'oe_kurzbz' => $this->input->post('organizationalUnitShortCode'),
|
||||
'ausbildungssemester' => $this->input->post('semester'),
|
||||
'anmerkung' => $this->input->post('description'),
|
||||
'unterrichtszeitentyp_kurzbz' => $this->input->post('classTimeSlotTypeShortcode') ?? null,
|
||||
'studienplan_id' => $this->input->post('studyPlanId'),
|
||||
'insertamum' => date('c'),
|
||||
'insertvon' => getAuthUid(),
|
||||
'updateamum' => date('c'),
|
||||
'updatevon' => getAuthUid(),
|
||||
]);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->db->trans_complete();
|
||||
|
||||
$this->terminateWithSuccess(true);
|
||||
}
|
||||
|
||||
public function updateClassTimeSlotValidityPeriod($classTimeSlotValidityPeriodId)
|
||||
{
|
||||
$this->form_validation->set_rules('validityPeriodFrom', 'Validity Period From', 'required|is_valid_date[Y-m-d]', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'field_validityPeriodFrom')]),
|
||||
'is_valid_date' => $this->p->t('ui', 'error_fieldInvalidDate', ['field' => $this->p->t('ui', 'field_validityPeriodFrom')])
|
||||
]);
|
||||
$this->form_validation->set_rules('validityPeriodTo', 'Validity Period To', 'required|is_valid_date[Y-m-d]|callback_date_greater_equal[validityPeriodFrom]');
|
||||
$this->form_validation->set_rules('organizationalUnitShortCode', 'Organizational Unit Shortcode', 'required|max_length[32]', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'field_organizationalUnit')]),
|
||||
'max_length' => $this->p->t('ui', 'error_fieldMaxLength', ['field' => $this->p->t('ui', 'field_organizationalUnit'), 'max' => 32])
|
||||
]);
|
||||
$this->form_validation->set_rules('semester', 'Semester', 'is_natural_no_zero|less_than_equal_to[8]', [
|
||||
'is_natural_no_zero' => $this->p->t('ui', 'error_fieldInvalid', ['field' => $this->p->t('ui', 'field_semester')]),
|
||||
'less_than_equal_to' => $this->p->t('ui', 'error_fieldMaxValue', ['field' => $this->p->t('ui', 'field_semester'), 'max' => 8])
|
||||
]);
|
||||
$this->form_validation->set_rules('classTimeSlotTypeShortcode', 'Class Time Slot Type Shortcode', 'max_length[32]');
|
||||
$this->form_validation->set_rules('studyPlanId', 'Study Plan ID', 'is_natural_no_zero');
|
||||
|
||||
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
if (!$this->isUserEntitledForOrganizationalUnit($this->input->post('organizationalUnitShortCode'), 'lehre/unterrichtszeiten_gk')) {
|
||||
$this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
}
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
$result = $this->ClassTimeSlotValidityPeriodModel->update($classTimeSlotValidityPeriodId, [
|
||||
'gueltig_von' => $this->input->post('validityPeriodFrom'),
|
||||
'gueltig_bis' => $this->input->post('validityPeriodTo'),
|
||||
'oe_kurzbz' => $this->input->post('organizationalUnitShortCode'),
|
||||
'ausbildungssemester' => $this->input->post('semester'),
|
||||
'anmerkung' => $this->input->post('description'),
|
||||
'unterrichtszeitentyp_kurzbz' => $this->input->post('classTimeSlotTypeShortcode') ?? null,
|
||||
'studienplan_id' => $this->input->post('studyPlanId'),
|
||||
'updateamum' => date('c'),
|
||||
'updatevon' => getAuthUid(),
|
||||
]);
|
||||
|
||||
$this->db->trans_complete();
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess(true);
|
||||
}
|
||||
|
||||
public function deleteClassTimeSlotValidityPeriod($classTimeSlotValidityPeriodId)
|
||||
{
|
||||
$validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]);
|
||||
$validityPeriod = $this->getDataOrTerminateWithError($validityPeriodResult)[0];
|
||||
if (!$this->isUserEntitledForOrganizationalUnit($validityPeriod->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) {
|
||||
$this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
}
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
$result = $this->ClassTimeSlotModel->delete(['unterrichtszeitengueltigkeit_id'=> $classTimeSlotValidityPeriodId]);
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$result = $this->ClassTimeSlotValidityPeriodModel->delete($classTimeSlotValidityPeriodId);
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$this->db->trans_complete();
|
||||
|
||||
$this->terminateWithSuccess(true);
|
||||
}
|
||||
|
||||
public function getClassTimeSlotsForValidityPeriod($classTimeSlotValidityPeriodId)
|
||||
{
|
||||
$validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]);
|
||||
$validityPeriodData = $this->getDataOrTerminateWithError($validityPeriodResult);
|
||||
if (!$validityPeriodData || count($validityPeriodData) === 0) {
|
||||
$this->terminateWithError($this->p->t('ui', 'classTimeSlotValidityPeriodNotFound'));
|
||||
}
|
||||
|
||||
$validityPeriod = $validityPeriodData[0];
|
||||
|
||||
if (!$this->isUserEntitledForOrganizationalUnit($validityPeriod->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) {
|
||||
$this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
}
|
||||
|
||||
$this->ClassTimeSlotModel->addOrder('insertamum', 'DESC');
|
||||
$class_time_slots_res = $this->ClassTimeSlotModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]);
|
||||
$class_time_slots_res = $this->getDataOrTerminateWithError($class_time_slots_res);
|
||||
$this->terminateWithSuccess($class_time_slots_res);
|
||||
}
|
||||
|
||||
public function createClassTimeSlotsForValidityPeriod($classTimeSlotValidityPeriodId)
|
||||
{
|
||||
$this->form_validation->set_rules('unterrichtszeiten', 'Class Time Slots', 'callback_validate_items_in_class_time_slots');
|
||||
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]);
|
||||
$validityPeriod = $this->getDataOrTerminateWithError($validityPeriodResult)[0];
|
||||
if (!$this->isUserEntitledForOrganizationalUnit($validityPeriod->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) {
|
||||
$this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
}
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
foreach ($this->input->post('unterrichtszeiten') as $timeSlot) {
|
||||
$result = $this->ClassTimeSlotModel->insert([
|
||||
'wochentag' => $timeSlot['wochentag'],
|
||||
'uhrzeit_von' => $timeSlot['startTime'],
|
||||
'uhrzeit_bis' => $timeSlot['endTime'],
|
||||
'unterrichtszeitentyp_kurzbz' => $timeSlot['classTimeSlotTypeShortcode'],
|
||||
'unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId,
|
||||
'insertamum' => date('c'),
|
||||
'insertvon' => getAuthUid(),
|
||||
'updateamum' => date('c'),
|
||||
'updatevon' => getAuthUid(),
|
||||
]);
|
||||
|
||||
$this->getDataOrTerminateWithError($result);
|
||||
}
|
||||
$this->db->trans_complete();
|
||||
|
||||
$this->terminateWithSuccess(true);
|
||||
}
|
||||
|
||||
public function updateClassTimeSlotsForValidityPeriod($classTimeSlotValidityPeriodId)
|
||||
{
|
||||
$this->form_validation->set_rules('unterrichtszeiten', 'Class Time Slots', 'callback_validate_items_in_class_time_slots');
|
||||
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]);
|
||||
$validityPeriod = $this->getDataOrTerminateWithError($validityPeriodResult)[0];
|
||||
if (!$this->isUserEntitledForOrganizationalUnit($validityPeriod->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) {
|
||||
$this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
}
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
$currentTimeSlotsResult = $this->ClassTimeSlotModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]);
|
||||
$currentTimeSlots = $this->getDataOrTerminateWithError($currentTimeSlotsResult);
|
||||
$currentTimeSlotIds = array_column($currentTimeSlots, 'unterrichtszeit_id');
|
||||
|
||||
$removedTimeSlotIds = array_values(array_diff($currentTimeSlotIds, array_column($this->input->post('unterrichtszeiten'), 'id')));
|
||||
|
||||
if (count($removedTimeSlotIds) > 0) {
|
||||
$query = 'DELETE FROM lehre.tbl_unterrichtszeiten WHERE unterrichtszeit_id IN ?';
|
||||
$result = $this->db->query($query, [ $removedTimeSlotIds ]);
|
||||
}
|
||||
|
||||
foreach ($this->input->post('unterrichtszeiten') as $timeSlot) {
|
||||
$data = [
|
||||
'wochentag' => $timeSlot['wochentag'],
|
||||
'uhrzeit_von' => $timeSlot['startTime'],
|
||||
'uhrzeit_bis' => $timeSlot['endTime'],
|
||||
'unterrichtszeitentyp_kurzbz' => $timeSlot['classTimeSlotTypeShortcode'],
|
||||
'unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId,
|
||||
'updateamum' => date('c'),
|
||||
'updatevon' => getAuthUid(),
|
||||
];
|
||||
if (isset($timeSlot['id'])) {
|
||||
$result = $this->ClassTimeSlotModel->update($timeSlot['id'], $data);
|
||||
} else {
|
||||
$result = $this->ClassTimeSlotModel->insert(array_merge($data, [
|
||||
'insertvon' => getAuthUid(),
|
||||
'updateamum' => date('c'),
|
||||
]));
|
||||
}
|
||||
|
||||
$this->getDataOrTerminateWithError($result);
|
||||
}
|
||||
$this->db->trans_complete();
|
||||
|
||||
$this->terminateWithSuccess(true);
|
||||
|
||||
}
|
||||
public function deleteClassTimeSlotsForValidityPeriod($classTimeSlotValidityPeriodId)
|
||||
{
|
||||
$validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]);
|
||||
$validityPeriod = $this->getDataOrTerminateWithError($validityPeriodResult)[0];
|
||||
if (!$this->isUserEntitledForOrganizationalUnit($validityPeriod->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) {
|
||||
$this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
}
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
$result = $this->ClassTimeSlotModel->delete(['unterrichtszeitengueltigkeit_id'=> $classTimeSlotValidityPeriodId]);
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$this->db->trans_complete();
|
||||
|
||||
$this->terminateWithSuccess(true);
|
||||
}
|
||||
|
||||
public function getAllClassScheduleTypes()
|
||||
{
|
||||
$filter = $this->input->get('filter');
|
||||
|
||||
if ($filter) {
|
||||
if (isset($filter['aktiv'])) {
|
||||
$this->ClassTimeSlotTypeModel->db->where('aktiv', $filter['aktiv']);
|
||||
}
|
||||
}
|
||||
|
||||
$class_schedule_types_res = $this->ClassTimeSlotTypeModel->load();
|
||||
$class_schedule_types_res = $this->getDataOrTerminateWithError($class_schedule_types_res);
|
||||
|
||||
$this->terminateWithSuccess($class_schedule_types_res);
|
||||
}
|
||||
|
||||
public function createClassTimeSlotType()
|
||||
{
|
||||
$this->form_validation->set_rules('shortCode', 'Short Code', 'required|max_length[32]', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'field_classTimeSlotTypeShortCode')]),
|
||||
'max_length' => $this->p->t('ui', 'error_fieldMaxLength', ['field' => $this->p->t('ui', 'field_classTimeSlotTypeShortCode'), 'max' => 32])
|
||||
]);
|
||||
$this->form_validation->set_rules('descriptions', 'Descriptions', 'callback_validate_descriptions_array');
|
||||
$this->form_validation->set_rules('backgroundColor', 'Background Color', 'required|regex_match[/^#([0-9a-fA-F]{3}){1,2}$/]', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'field_backgroundColor')]),
|
||||
'regex_match' => $this->p->t('ui', 'error_fieldInvalid', ['field' => $this->p->t('ui', 'field_backgroundColor')]),
|
||||
]);
|
||||
|
||||
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
$descriptions = $this->input->post('descriptions');
|
||||
$pgArray = $this->arrayToPgArray($descriptions);
|
||||
|
||||
$query = 'INSERT INTO lehre.tbl_unterrichtszeiten_typ (
|
||||
unterrichtszeitentyp_kurzbz,
|
||||
bezeichnung_mehrsprachig,
|
||||
hintergrundfarbe,
|
||||
aktiv,
|
||||
insertamum,
|
||||
insertvon,
|
||||
updateamum,
|
||||
updatevon) VALUES (?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
$result = $this->db->query($query, [
|
||||
$this->input->post('shortCode'),
|
||||
$pgArray,
|
||||
$this->input->post('backgroundColor'),
|
||||
$this->input->post('isActive'),
|
||||
date('c'),
|
||||
getAuthUid(),
|
||||
date('c'),
|
||||
getAuthUid(),
|
||||
]);
|
||||
$this->db->trans_complete();
|
||||
|
||||
$this->terminateWithSuccess(true);
|
||||
}
|
||||
|
||||
public function updateClassTimeSlotType($classTimeSlotTypeId)
|
||||
{
|
||||
$this->form_validation->set_rules('descriptions', 'Descriptions', 'callback_validate_descriptions_array');
|
||||
|
||||
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
|
||||
$parsedClassTimeSlotTypeId = urldecode($classTimeSlotTypeId);
|
||||
|
||||
$descriptions = $this->input->post('descriptions');
|
||||
$pgArray = $this->arrayToPgArray($descriptions);
|
||||
|
||||
$query = 'UPDATE lehre.tbl_unterrichtszeiten_typ SET bezeichnung_mehrsprachig = ?, hintergrundfarbe = ?, aktiv = ?, updateamum = ?, updatevon = ? WHERE unterrichtszeitentyp_kurzbz = ?';
|
||||
$result = $this->db->query($query, [
|
||||
$pgArray,
|
||||
$this->input->post('backgroundColor'),
|
||||
$this->input->post('isActive'),
|
||||
date('c'),
|
||||
getAuthUid(),
|
||||
$parsedClassTimeSlotTypeId,
|
||||
]);
|
||||
$this->db->trans_complete();
|
||||
|
||||
$this->terminateWithSuccess(true);
|
||||
}
|
||||
|
||||
public function deleteClassTimeSlotType($classTimeSlotTypeId)
|
||||
{
|
||||
$isClassTimeSlotDeletable = true;
|
||||
$parsedClassTimeSlotTypeId = urldecode($classTimeSlotTypeId);
|
||||
|
||||
$validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitentyp_kurzbz' => $parsedClassTimeSlotTypeId]);
|
||||
$validityPeriod = $this->getDataOrTerminateWithError($validityPeriodResult);
|
||||
if ($validityPeriod && count($validityPeriod) > 0) {
|
||||
$isClassTimeSlotDeletable = false;
|
||||
}
|
||||
|
||||
$classTimeSlotResult = $this->ClassTimeSlotModel->loadWhere(['unterrichtszeitentyp_kurzbz' => $parsedClassTimeSlotTypeId]);
|
||||
$classTimeSlot = $this->getDataOrTerminateWithError($classTimeSlotResult);
|
||||
if ($classTimeSlot && count($classTimeSlot) > 0) {
|
||||
$isClassTimeSlotDeletable = false;
|
||||
}
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
if (!$isClassTimeSlotDeletable) {
|
||||
$result = $this->ClassTimeSlotTypeModel->update($parsedClassTimeSlotTypeId, ['aktiv' => false, 'updateamum' => date('c'), 'updatevon' => getAuthUid()]);
|
||||
} else {
|
||||
$result = $this->ClassTimeSlotTypeModel->delete(['unterrichtszeitentyp_kurzbz' => $parsedClassTimeSlotTypeId]);
|
||||
}
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$this->db->trans_complete();
|
||||
|
||||
$this->terminateWithSuccess(true);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Private methods
|
||||
private function arrayToPgArray(array $assoc) {
|
||||
$flat = [null, null];
|
||||
|
||||
foreach ($assoc as $assocItem) {
|
||||
if ($assocItem['lang'] === 'de') {
|
||||
$flat[0] = $assocItem['value'];
|
||||
} else if ($assocItem['lang'] === 'en') {
|
||||
$flat[1] = $assocItem['value'];
|
||||
} else {
|
||||
$flat[] = $assocItem['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$escaped = array_map(function ($v) {
|
||||
return '"' . addslashes($v) . '"';
|
||||
}, $flat);
|
||||
return '{' . implode(',', $escaped) . '}';
|
||||
}
|
||||
|
||||
public function date_greater_equal($toDate, $fromField)
|
||||
{
|
||||
$fromDate = $this->input->post($fromField);
|
||||
|
||||
if (!$fromDate) {
|
||||
$this->form_validation->set_message(
|
||||
'date_greater_equal',
|
||||
$this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'field_validityPeriodTo')])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!strtotime($toDate) || !strtotime($fromDate)) {
|
||||
$this->form_validation->set_message(
|
||||
'date_greater_equal',
|
||||
$this->p->t('ui', 'error_fieldInvalidDate', ['field' => $this->p->t('ui', 'field_validityPeriodTo')])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strtotime($toDate) < strtotime($fromDate)) {
|
||||
$this->form_validation->set_message(
|
||||
'date_greater_equal',
|
||||
$this->p->t('ui', 'error_fieldDateGreaterEqual', ['field' => $this->p->t('ui', 'field_validityPeriodTo'), 'otherField' => $this->p->t('ui', 'field_validityPeriodFrom')])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate_items_in_class_time_slots($unterrichtszeiten)
|
||||
{
|
||||
if (!is_array($this->input->post('unterrichtszeiten')) || count($this->input->post('unterrichtszeiten')) === 0) {
|
||||
$this->form_validation->set_message(
|
||||
'validate_items_in_class_time_slots',
|
||||
$this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'field_classTimeSlot')])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($this->input->post('unterrichtszeiten') as $index => $timeSlot) {
|
||||
if (!isset($timeSlot['wochentag'], $timeSlot['startTime'], $timeSlot['endTime'], $timeSlot['classTimeSlotTypeShortcode'])) {
|
||||
$this->form_validation->set_message(
|
||||
'validate_items_in_class_time_slots',
|
||||
$this->p->t('ui', 'error_fieldClassTimeSlotContentInvalid', ['field' => $this->p->t('ui', 'field_classTimeSlot')])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!in_array($timeSlot['wochentag'], [1, 2, 3, 4, 5, 6, 0])) {
|
||||
$this->form_validation->set_message(
|
||||
'validate_items_in_class_time_slots',
|
||||
$this->p->t('ui', 'error_fieldWeekdayInvalid', ['field' => $this->p->t('ui', 'field_classTimeSlot')])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!strtotime($timeSlot['startTime']) || !strtotime($timeSlot['endTime'])) {
|
||||
$this->form_validation->set_message(
|
||||
'validate_items_in_class_time_slots',
|
||||
$this->p->t('ui', 'error_fieldClassTimeSlotTimeInvalid', ['field' => $this->p->t('ui', 'field_classTimeSlot')])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strtotime($timeSlot['endTime']) <= strtotime($timeSlot['startTime'])) {
|
||||
$this->form_validation->set_message(
|
||||
'validate_items_in_class_time_slots',
|
||||
$this->p->t('ui', 'error_fieldDateGreaterEqual', ['field' => $this->p->t('ui', 'field_classTimeSlotEndTime'), 'otherField' => $this->p->t('ui', 'field_classTimeSlotStartTime')])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$slotsByDay = [];
|
||||
foreach ($this->input->post('unterrichtszeiten') as $timeSlot) {
|
||||
$slotsByDay[$timeSlot['wochentag']][] = $timeSlot;
|
||||
}
|
||||
|
||||
foreach ($slotsByDay as $day => $slots) {
|
||||
usort($slots, function ($a, $b) {
|
||||
return strtotime($a['startTime']) - strtotime($b['startTime']);
|
||||
});
|
||||
|
||||
for ($i = 1; $i < count($slots); $i++) {
|
||||
if (strtotime($slots[$i]['startTime']) < strtotime($slots[$i - 1]['endTime'])) {
|
||||
$this->form_validation->set_message(
|
||||
'validate_items_in_class_time_slots',
|
||||
$this->p->t('ui', 'error_fieldClassTimeSlotOverlap', ['field' => $this->p->t('ui', 'field_classTimeSlot')])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate_descriptions_array($descriptions)
|
||||
{
|
||||
$descriptions = $this->input->post('descriptions');
|
||||
if (!is_array($descriptions) || count($descriptions) === 0) {
|
||||
$this->form_validation->set_message(
|
||||
'validate_descriptions_array',
|
||||
$this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'field_descriptions')])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($descriptions as $index => $description) {
|
||||
if (!isset($description['lang'], $description['value'])) {
|
||||
$this->form_validation->set_message(
|
||||
'validate_descriptions_array',
|
||||
$this->p->t('ui', 'error_fieldDescriptionContentInvalid')
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($description['lang']) || empty($description['value'])) {
|
||||
$this->form_validation->set_message(
|
||||
'validate_descriptions_array',
|
||||
$this->p->t('ui', 'error_fieldDescriptionContentInvalid')
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function isUserEntitledForOrganizationalUnit($organizationalUnitShortCode, $requiredPermission)
|
||||
{
|
||||
$entitledOrganizationalUnitsShortCodes = $this->permissionlib->getOE_isEntitledFor($requiredPermission);
|
||||
return in_array($organizationalUnitShortCode, $entitledOrganizationalUnitsShortCodes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
class ClassroomHourApi extends FHCAPI_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getAllClassroomHours' => self::PERM_LOGGED,
|
||||
]);
|
||||
|
||||
$this->load->model('ressource/Stunde_model', "ClassroomHourModel");
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
public function getAllClassroomHours()
|
||||
{
|
||||
$this->ClassroomHourModel->addOrder('stunde', 'ASC');
|
||||
$result = $this->ClassroomHourModel->load();
|
||||
|
||||
$this->terminateWithSuccess($this->getDataOrTerminateWithError($result));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ class Studgang extends FHCAPI_Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getStudiengangInfo'=> self::PERM_LOGGED,
|
||||
'getAllStudiengange'=> self::PERM_LOGGED,
|
||||
'getAllDegreePrograms'=> self::PERM_LOGGED,
|
||||
|
||||
]);
|
||||
|
||||
@@ -43,6 +44,14 @@ class Studgang extends FHCAPI_Controller
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
public function getAllDegreePrograms()
|
||||
{
|
||||
$this->load->model('organisation/Studiengang_model', "StudiengangModel");
|
||||
$class_schedule_res = $this->StudiengangModel->load();
|
||||
$class_schedule_res = $this->getDataOrTerminateWithError($class_schedule_res);
|
||||
$this->terminateWithSuccess($class_schedule_res);
|
||||
}
|
||||
|
||||
public function getStudiengangInfo(){
|
||||
$isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID());
|
||||
$isMitarbeiter = $this->getDataOrTerminateWithError($isMitarbeiter);
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
class OrganizationalUnitApi extends FHCAPI_Controller
|
||||
{
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getAllOrganizationalUnits'=> array('basis/organisationseinheit:r'),
|
||||
]);
|
||||
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
|
||||
|
||||
// Loads phrases system
|
||||
$this->loadPhrases([
|
||||
'global'
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
public function getAllOrganizationalUnits()
|
||||
{
|
||||
$entitledOrganizationalUnitsShortCodes = $this->permissionlib->getOE_isEntitledFor('basis/organisationseinheit');
|
||||
|
||||
$this->OrganisationseinheitModel->db->where_in('oe_kurzbz', $entitledOrganizationalUnitsShortCodes);
|
||||
$result = $this->OrganisationseinheitModel->load();
|
||||
|
||||
$organization_units_result = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($organization_units_result);
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,41 @@ class Studienplan extends FHCAPI_Controller
|
||||
{
|
||||
// TODO(chris): access!
|
||||
parent::__construct([
|
||||
'getBySemester' => self::PERM_LOGGED
|
||||
'getAllStudyPlans' => self::PERM_LOGGED,
|
||||
'getStudyPlansByOrganizationalUnitAndSemesterDates' => self::PERM_LOGGED,
|
||||
'getBySemester' => self::PERM_LOGGED,
|
||||
'getStudyPlan' => self::PERM_LOGGED,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getAllStudyPlans()
|
||||
{
|
||||
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
|
||||
$result = $this->StudienplanModel->load();
|
||||
$studien_plan_result = $this->getDataOrTerminateWithError($result);
|
||||
$this->terminateWithSuccess($studien_plan_result);
|
||||
}
|
||||
|
||||
public function getStudyPlansByOrganizationalUnitAndSemesterDates($organizationalUnitShortCode)
|
||||
{
|
||||
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
|
||||
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
|
||||
$this->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
|
||||
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
|
||||
|
||||
$startDate = date('Y-m-d', strtotime($this->input->get('filter[startDate]')));
|
||||
$endDate = date('Y-m-d', strtotime($this->input->get('filter[endDate]')));
|
||||
if (!$startDate || !$endDate) {
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Start- oder Enddatum']), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$studyPlansResponse = $this->StudienplanModel->getStudyPlansForOrganizationalUnitAndDatesQueryResponse($organizationalUnitShortCode, $startDate, $endDate);
|
||||
if (isError($studyPlansResponse)) $this->terminateWithError(getError($studyPlansResponse), self::ERROR_TYPE_DB);
|
||||
if (!hasData($studyPlansResponse)) return $this->terminateWithSuccess(null);
|
||||
|
||||
return $this->terminateWithSuccess($this->getDataOrTerminateWithError($studyPlansResponse));
|
||||
}
|
||||
|
||||
public function getBySemester()
|
||||
{
|
||||
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
|
||||
@@ -66,4 +97,15 @@ class Studienplan extends FHCAPI_Controller
|
||||
|
||||
$this->terminateWithSuccess(hasData($result) ? getData($result) : []);
|
||||
}
|
||||
|
||||
public function getStudyPlan($id)
|
||||
{
|
||||
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
|
||||
|
||||
$result = $this->StudienplanModel->loadWhere(['studienplan_id' => $id]);
|
||||
if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
|
||||
if (!hasData($result)) return $this->terminateWithSuccess(null);
|
||||
|
||||
$this->terminateWithSuccess(getData($result)[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,16 @@ class Studiensemester extends FHCAPI_Controller
|
||||
'getAll' => self::PERM_LOGGED,
|
||||
'getAktNext' => self::PERM_LOGGED,
|
||||
'getStudienjahrByStudiensemester' => self::PERM_LOGGED,
|
||||
'getAllStudiensemesterAndAktOrNext' => self::PERM_LOGGED
|
||||
'getAllStudiensemesterAndAktOrNext' => self::PERM_LOGGED,
|
||||
'getStudySemestersByOrganizationalUnitAndDates' => self::PERM_LOGGED,
|
||||
'getStudySemestersByStudyPlanAndDates' => self::PERM_LOGGED,
|
||||
)
|
||||
);
|
||||
// Load model StudiensemesterModel
|
||||
|
||||
$this->load->model('organisation/studiensemester_model', 'StudiensemesterModel');
|
||||
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
|
||||
$this->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
|
||||
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,4 +171,47 @@ class Studiensemester extends FHCAPI_Controller
|
||||
|
||||
$this->terminateWithSuccess(array($studiensemester, $aktuell));
|
||||
}
|
||||
|
||||
public function getStudySemestersByOrganizationalUnitAndDates($organizationalUnitShortCode)
|
||||
{
|
||||
$startDate = date('Y-m-d', strtotime($this->input->get('filter[startDate]')));
|
||||
$endDate = date('Y-m-d', strtotime($this->input->get('filter[endDate]')));
|
||||
if (!$startDate || !$endDate) {
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Start- oder Enddatum']), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$studyPlansResponse = $this->StudienplanModel->getStudyPlansForOrganizationalUnitQueryResponse($organizationalUnitShortCode);
|
||||
if (isError($studyPlansResponse)) $this->terminateWithError(getError($studyPlansResponse), self::ERROR_TYPE_DB);
|
||||
if (!hasData($studyPlansResponse)) return $this->terminateWithSuccess(null);
|
||||
|
||||
$studyPlans = $this->getDataOrTerminateWithError($studyPlansResponse);
|
||||
$studyPlansIds = array_map(function ($studyPlan) { return $studyPlan->studienplan_id; }, $studyPlans);
|
||||
|
||||
$studySemestersResponse = $this->StudiensemesterModel->getStudySemestersByStudyPlansAndDatesQueryResponse($studyPlansIds, $startDate, $endDate);
|
||||
if (isError($studySemestersResponse)) $this->terminateWithError(getError($studySemestersResponse), self::ERROR_TYPE_DB);
|
||||
if (!hasData($studySemestersResponse)) return $this->terminateWithSuccess([]);
|
||||
|
||||
$studySemesters = $this->getDataOrTerminateWithError($studySemestersResponse);
|
||||
|
||||
return $this->terminateWithSuccess($studySemesters);
|
||||
}
|
||||
|
||||
public function getStudySemestersByStudyPlanAndDates()
|
||||
{
|
||||
$studyPlansId = $this->input->get('filter[studyPlanId]');
|
||||
|
||||
$startDate = date('Y-m-d', strtotime($this->input->get('filter[startDate]')));
|
||||
$endDate = date('Y-m-d', strtotime($this->input->get('filter[endDate]')));
|
||||
if (!$startDate || !$endDate) {
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Start- oder Enddatum']), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$studySemestersResponse = $this->StudiensemesterModel->getStudySemestersByStudyPlansAndDatesQueryResponse([$studyPlansId], $startDate, $endDate);
|
||||
if (isError($studySemestersResponse)) $this->terminateWithError(getError($studySemestersResponse), self::ERROR_TYPE_DB);
|
||||
if (!hasData($studySemestersResponse)) return $this->terminateWithSuccess([]);
|
||||
|
||||
$studySemesters = $this->getDataOrTerminateWithError($studySemestersResponse);
|
||||
|
||||
return $this->terminateWithSuccess($studySemesters);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
*/
|
||||
class ClassSchedule extends Auth_Controller
|
||||
{
|
||||
private $_uid; // uid of the logged user
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
array(
|
||||
'index' => array('lehre/unterrichtszeiten_gk:r'),
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->library('PermissionLib');
|
||||
$this->load->library('AuthLib');
|
||||
|
||||
$this->loadPhrases(
|
||||
array(
|
||||
'ui',
|
||||
'global',
|
||||
'person',
|
||||
'abschlusspruefung',
|
||||
'password',
|
||||
'lehre'
|
||||
)
|
||||
);
|
||||
|
||||
$this->_setAuthUID();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
public function index()
|
||||
{
|
||||
return $this->load->view('lehre/class_schedule/index.php', [
|
||||
'permissions' => [
|
||||
'lehre/unterrichtszeiten_typ_w' => $this->permissionlib->isBerechtigt('lehre/unterrichtszeiten_typ', 'suid'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Private methods
|
||||
|
||||
/**
|
||||
* Retrieve the UID of the logged user and checks if it is valid
|
||||
*/
|
||||
private function _setAuthUID()
|
||||
{
|
||||
$this->_uid = getAuthUID();
|
||||
|
||||
if (!$this->_uid) show_error('User authentification failed');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
class ClassTimeSlotType_model extends DB_Model
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'lehre.tbl_unterrichtszeiten_typ';
|
||||
$this->pk = 'unterrichtszeitentyp_kurzbz';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
class ClassTimeSlotValidityPeriod_model extends DB_Model
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'lehre.tbl_unterrichtszeiten_gueltigkeit';
|
||||
$this->pk = 'unterrichtszeitengueltigkeit_id';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
class ClassTimeSlot_model extends DB_Model
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'lehre.tbl_unterrichtszeiten';
|
||||
$this->pk = 'unterrichtszeit_id';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -168,5 +168,35 @@ class Studienplan_model extends DB_Model
|
||||
return $this->loadWhere([
|
||||
'person_id' => $person_id
|
||||
]);
|
||||
}
|
||||
|
||||
public function getStudyPlansForOrganizationalUnitQueryResponse($organizationalUnitShortCode)
|
||||
{
|
||||
$query = "SELECT sp.* FROM lehre.tbl_studienplan sp
|
||||
JOIN lehre.tbl_studienordnung so ON sp.studienordnung_id = so.studienordnung_id
|
||||
JOIN public.tbl_studiengang sg ON so.studiengang_kz = sg.studiengang_kz
|
||||
WHERE sg.oe_kurzbz = ?";
|
||||
|
||||
return $this->execReadOnlyQuery($query, array($organizationalUnitShortCode));
|
||||
}
|
||||
|
||||
public function getStudyPlansForOrganizationalUnitAndDatesQueryResponse($organizationalUnitShortCode, $startDate, $endDate)
|
||||
{
|
||||
$query = "SELECT DISTINCT sp.* FROM lehre.tbl_studienplan sp
|
||||
JOIN lehre.tbl_studienordnung so ON sp.studienordnung_id = so.studienordnung_id
|
||||
JOIN public.tbl_studiengang sg ON so.studiengang_kz = sg.studiengang_kz
|
||||
AND sg.oe_kurzbz = ? AND sp.studienplan_id IN (
|
||||
SELECT sps.studienplan_id
|
||||
FROM lehre.tbl_studienplan_semester sps
|
||||
JOIN public.tbl_studiensemester ss ON ss.studiensemester_kurzbz = sps.studiensemester_kurzbz
|
||||
WHERE (
|
||||
(ss.start >= ? AND ss.ende <= ?) OR
|
||||
(ss.start <= ? AND ss.ende >= ?) OR
|
||||
(ss.start <= ? AND ss.ende >= ? AND ss.ende <= ?) OR
|
||||
(ss.start >= ? AND ss.start <= ? AND ss.ende >= ?)
|
||||
)
|
||||
)";
|
||||
|
||||
return $this->execReadOnlyQuery($query, array($organizationalUnitShortCode, $startDate, $endDate, $startDate, $endDate, $startDate, $startDate, $endDate, $startDate, $endDate, $endDate));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,4 +347,26 @@ class Studiensemester_model extends DB_Model
|
||||
$result = $this->load($studiensemester_kurzbz);
|
||||
return hasData($result);
|
||||
}
|
||||
|
||||
public function getStudySemestersByStudyPlansAndDatesQueryResponse($studyPlanIds, $fromDate, $toDate)
|
||||
{
|
||||
$subQuery = "(
|
||||
SELECT ARRAY_AGG(DISTINCT sp.semester)
|
||||
FROM lehre.tbl_studienplan_semester sp
|
||||
WHERE sp.studienplan_id IN ?
|
||||
AND sp.studiensemester_kurzbz = s.studiensemester_kurzbz
|
||||
) AS semester_numbers";
|
||||
|
||||
$query = "SELECT DISTINCT s.*," . $subQuery . "
|
||||
FROM public.tbl_studiensemester s
|
||||
JOIN lehre.tbl_studienplan_semester sp ON sp.studiensemester_kurzbz = s.studiensemester_kurzbz
|
||||
WHERE sp.studienplan_id IN ? AND (
|
||||
(s.start >= ? AND s.ende <= ?) OR
|
||||
(s.start <= ? AND s.ende >= ?) OR
|
||||
(s.start <= ? AND s.ende >= ? AND s.ende <= ?) OR
|
||||
(s.start >= ? AND s.start <= ? AND s.ende >= ?)
|
||||
)";
|
||||
|
||||
return $this->execQuery($query, array($studyPlanIds, $studyPlanIds, $fromDate, $toDate, $fromDate, $toDate, $fromDate, $fromDate, $toDate, $fromDate, $toDate, $toDate));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
$includesArray = array(
|
||||
'title' => ucfirst($this->p->t('ui', 'classSchedulePageTitle')),
|
||||
'vue3' => true,
|
||||
'axios027' => true,
|
||||
'bootstrap5' => true,
|
||||
'tabulator5' => true,
|
||||
'fontawesome6' => true,
|
||||
'primevue3' => true,
|
||||
'navigationcomponent' => true,
|
||||
'filtercomponent' => true,
|
||||
'vuedatepicker11' => true,
|
||||
'momentjs2' => true,
|
||||
'customJSs' => array(
|
||||
'vendor/moment/luxonjs/luxon.min.js'
|
||||
),
|
||||
'customJSModules' => array(
|
||||
'public/js/apps/lehre/ClassScheduleApp.js'
|
||||
),
|
||||
'customCSSs' => array(
|
||||
'public/css/components/primevue.css',
|
||||
'public/css/components/verticalsplit.css',
|
||||
'public/extensions/FHC-Core-Developer/css/FhcMain.css',
|
||||
'public/css/components/calendar.css',
|
||||
'public/css/components/classSchedule.css',
|
||||
'public/css/components/vue-datepicker.css',
|
||||
'public/css/classScheduleOverview.css',
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->view('templates/FHC-Header', $includesArray);
|
||||
?>
|
||||
|
||||
<div id="main">
|
||||
<core-navigation-cmpt></core-navigation-cmpt>
|
||||
<router-view
|
||||
cis-root="<?= CIS_ROOT; ?>"
|
||||
:permissions="<?= htmlspecialchars(json_encode($permissions)); ?>"
|
||||
>
|
||||
</router-view>
|
||||
</div>
|
||||
|
||||
<?php $this->load->view('templates/FHC-Footer', $includesArray); ?>
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
html {
|
||||
font-size: .75em;
|
||||
}
|
||||
|
||||
nav.navbar.navbar-header,
|
||||
nav.navbar.navbar-left-side {
|
||||
font-size: 18px
|
||||
}
|
||||
|
||||
nav.navbar.navbar-left-side {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
/* Relative sizing inside navbar */
|
||||
nav.navbar .nav-item {
|
||||
font-size: 18px
|
||||
}
|
||||
|
||||
nav.navbar .navbar-brand-icon {
|
||||
font-size: 16px
|
||||
}
|
||||
|
||||
nav.navbar .left-side-menu-link-entry {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
nav.navbar .nav-link {
|
||||
font-size: 18px;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
nav.navbar .dropdown-menu {
|
||||
padding: 8px 0px;
|
||||
}
|
||||
|
||||
nav.navbar .dropdown-item {
|
||||
font-size: 16px;
|
||||
padding: 4px 16px;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
.fhc-pointer-events-none {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.fhc-pointer-events-all {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.fhc-cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fhc-resize-vertical {
|
||||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
.fhc-drag-handle:hover {
|
||||
cursor: grab;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.fhc-w-fit {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.tabulator-group-level-0 {
|
||||
background-color: #c6c6c6 !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tabulator-group-level-1 {
|
||||
background-color: #f5f5f5 !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tabulator-cell {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
div[role="row"] {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.v-enter-active {
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.v-leave-active {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.v-enter-from,
|
||||
.v-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.scrollable {
|
||||
overflow: auto;
|
||||
|
||||
/* Firefox */
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #888 transparent;
|
||||
}
|
||||
|
||||
/* Chrome / Edge / Safari */
|
||||
.scrollable::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.scrollable::-webkit-scrollbar-thumb {
|
||||
background: #888;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.scrollable::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* Copyright (C) 2025 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
getAllClassTimeValidityPeriods(params) {
|
||||
return {
|
||||
method: "get",
|
||||
url: "/api/frontend/v1/ClassScheduleApi/getAllClassTimeValidityPeriods",
|
||||
params,
|
||||
};
|
||||
},
|
||||
getAllClassTimeValidityPeriodsPerOrganizationalUnit(organizationUnitId) {
|
||||
return {
|
||||
method: "get",
|
||||
url: `/api/frontend/v1/ClassScheduleApi/getAllClassTimeValidityPeriodsPerOrganizationalUnit/${organizationUnitId}`,
|
||||
};
|
||||
},
|
||||
getClassTimeValidityPeriod(classTimeSlotValidityPeriodId) {
|
||||
return {
|
||||
method: "get",
|
||||
url: `/api/frontend/v1/ClassScheduleApi/getClassTimeValidityPeriod/${classTimeSlotValidityPeriodId}`,
|
||||
};
|
||||
},
|
||||
createClassTimeSlotValidityPeriod(userId, params) {
|
||||
return {
|
||||
method: "post",
|
||||
url: "api/frontend/v1/ClassScheduleApi/createClassTimeSlotValidityPeriod/",
|
||||
params,
|
||||
};
|
||||
},
|
||||
deleteClassTimeSlotValidityPeriod(userId, classTimeSlotValidityPeriodId) {
|
||||
return {
|
||||
method: "post",
|
||||
url: `api/frontend/v1/ClassScheduleApi/deleteClassTimeSlotValidityPeriod/${classTimeSlotValidityPeriodId}`,
|
||||
};
|
||||
},
|
||||
getClassTimeSlotsForValidityPeriod(classTimeSlotValidityPeriodId) {
|
||||
return {
|
||||
method: "get",
|
||||
url: `api/frontend/v1/ClassScheduleApi/getClassTimeSlotsForValidityPeriod/${classTimeSlotValidityPeriodId}`,
|
||||
};
|
||||
},
|
||||
createClassTimeSlotsForValidityPeriod(
|
||||
userId,
|
||||
classTimeSlotValidityPeriodId,
|
||||
params,
|
||||
) {
|
||||
return {
|
||||
method: "post",
|
||||
url: `api/frontend/v1/ClassScheduleApi/createClassTimeSlotsForValidityPeriod/${classTimeSlotValidityPeriodId}`,
|
||||
params,
|
||||
};
|
||||
},
|
||||
updateClassTimeSlotsForValidityPeriod(
|
||||
userId,
|
||||
classTimeSlotValidityPeriodId,
|
||||
params,
|
||||
) {
|
||||
return {
|
||||
method: "post",
|
||||
url: `api/frontend/v1/ClassScheduleApi/updateClassTimeSlotsForValidityPeriod/${classTimeSlotValidityPeriodId}`,
|
||||
params,
|
||||
};
|
||||
},
|
||||
updateClassTimeSlotValidityPeriod(
|
||||
userId,
|
||||
classTimeSlotValidityPeriodId,
|
||||
params,
|
||||
) {
|
||||
return {
|
||||
method: "post",
|
||||
url: `api/frontend/v1/ClassScheduleApi/updateClassTimeSlotValidityPeriod/${classTimeSlotValidityPeriodId}`,
|
||||
params,
|
||||
};
|
||||
},
|
||||
deleteClassTimeSlotsForValidityPeriod(
|
||||
userId,
|
||||
classTimeSlotValidityPeriodId,
|
||||
) {
|
||||
return {
|
||||
method: "post",
|
||||
url: `api/frontend/v1/ClassScheduleApi/deleteClassTimeSlotsForValidityPeriod/${classTimeSlotValidityPeriodId}`,
|
||||
};
|
||||
},
|
||||
getAllClassScheduleTypes(queryParams) {
|
||||
return {
|
||||
method: "get",
|
||||
url:
|
||||
"/api/frontend/v1/ClassScheduleApi/getAllClassScheduleTypes?" +
|
||||
new URLSearchParams(queryParams).toString(),
|
||||
};
|
||||
},
|
||||
createClassTimeSlotType(params) {
|
||||
return {
|
||||
method: "post",
|
||||
url: "api/frontend/v1/ClassScheduleApi/createClassTimeSlotType/",
|
||||
params,
|
||||
};
|
||||
},
|
||||
updateClassTimeSlotType(classTimeSlotTypeId, params) {
|
||||
return {
|
||||
method: "post",
|
||||
url: `api/frontend/v1/ClassScheduleApi/updateClassTimeSlotType/${encodeURIComponent(classTimeSlotTypeId)}`,
|
||||
params,
|
||||
};
|
||||
},
|
||||
deleteClassTimeSlotType(userId, classTimeSlotTypeId) {
|
||||
return {
|
||||
method: "post",
|
||||
url: `api/frontend/v1/ClassScheduleApi/deleteClassTimeSlotType/${encodeURIComponent(classTimeSlotTypeId)}`,
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (C) 2025 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
getAllClassroomHours() {
|
||||
return {
|
||||
method: "get",
|
||||
url: "/api/frontend/v1/ClassroomHourApi/getAllClassroomHours",
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
getAllOrganizationalUnits() {
|
||||
return {
|
||||
method: "get",
|
||||
url: "api/frontend/v1/organisation/organizationalUnitApi/getAllOrganizationalUnits",
|
||||
};
|
||||
},
|
||||
}
|
||||
@@ -16,6 +16,12 @@
|
||||
*/
|
||||
|
||||
export default {
|
||||
getAllDegreePrograms() {
|
||||
return {
|
||||
method: "get",
|
||||
url: "/api/frontend/v1/Studgang/getAllDegreePrograms",
|
||||
};
|
||||
},
|
||||
studiengangInformation() {
|
||||
return {
|
||||
method: 'get',
|
||||
|
||||
@@ -1,11 +1,37 @@
|
||||
export default {
|
||||
|
||||
getStudienplaeneBySemester(studiengang_kz, studiensemester_kurzbz, ausbildungssemester, orgform_kurzbz)
|
||||
{
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/organisation/studienplan/getBySemester',
|
||||
params: { studiengang_kz, studiensemester_kurzbz, ausbildungssemester, orgform_kurzbz },
|
||||
};
|
||||
}
|
||||
}
|
||||
getAllStudyPlans() {
|
||||
return {
|
||||
method: "get",
|
||||
url: "api/frontend/v1/organisation/studienplan/getAllStudyPlans",
|
||||
};
|
||||
},
|
||||
getStudyPlansByOrganizationalUnitAndSemesterDates(organizationalUnitShortCode, startDate, endDate) {
|
||||
return {
|
||||
method: "get",
|
||||
url: `api/frontend/v1/organisation/studienplan/getStudyPlansByOrganizationalUnitAndSemesterDates/${organizationalUnitShortCode}?filter[startDate]=${startDate}&filter[endDate]=${endDate}`,
|
||||
};
|
||||
},
|
||||
getStudienplaeneBySemester(
|
||||
studiengang_kz,
|
||||
studiensemester_kurzbz,
|
||||
ausbildungssemester,
|
||||
orgform_kurzbz,
|
||||
) {
|
||||
return {
|
||||
method: "get",
|
||||
url: "api/frontend/v1/organisation/studienplan/getBySemester",
|
||||
params: {
|
||||
studiengang_kz,
|
||||
studiensemester_kurzbz,
|
||||
ausbildungssemester,
|
||||
orgform_kurzbz,
|
||||
},
|
||||
};
|
||||
},
|
||||
getStudyPlan(studienplan_id) {
|
||||
return {
|
||||
method: "get",
|
||||
url: `api/frontend/v1/organisation/studienplan/getStudyPlan/${studienplan_id}`,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -29,5 +29,17 @@ export default {
|
||||
url: 'api/frontend/v1/organisation/studiensemester/getAll',
|
||||
params: { order, start }
|
||||
};
|
||||
}
|
||||
},
|
||||
getStudySemestersByOrganizationalUnitAndDates(organizationalUnitShortCode, startDate, endDate) {
|
||||
return {
|
||||
method: "get",
|
||||
url: `api/frontend/v1/organisation/studiensemester/getStudySemestersByOrganizationalUnitAndDates/${organizationalUnitShortCode}?filter[startDate]=${startDate}&filter[endDate]=${endDate}`,
|
||||
};
|
||||
},
|
||||
getStudySemestersByStudyPlanAndDates(studyPlanId, startDate, endDate) {
|
||||
return {
|
||||
method: "get",
|
||||
url: `api/frontend/v1/organisation/studiensemester/getStudySemestersByStudyPlanAndDates?filter[studyPlanId]=${studyPlanId}&filter[startDate]=${startDate}&filter[endDate]=${endDate}`,
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (C) 2023 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import ClassScheduleOverview from "../../components/ClassSchedule/ClassScheduleOverview.js";
|
||||
import ClassScheduleValidityPeriodOverview from "../../components/ClassSchedule/ClassScheduleValidityPeriodOverview.js";
|
||||
import ClassScheduleOrgUnitGroupedValidityPeriodsOverview from "../../components/ClassSchedule/ClassScheduleOrgUnitGroupedValidityPeriodsOverview.js";
|
||||
|
||||
import FhcAlert from "../../plugins/FhcAlert.js";
|
||||
import Phrasen from "../../plugins/Phrasen.js";
|
||||
import FhcApi from "../../plugins/Api.js";
|
||||
|
||||
import {CoreNavigationCmpt} from '../../components/navigation/Navigation.js';
|
||||
import {capitalize} from "../../helpers/StringHelpers.js";
|
||||
|
||||
const ciPath =
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, "") +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router;
|
||||
|
||||
const router = VueRouter.createRouter({
|
||||
history: VueRouter.createWebHistory(),
|
||||
routes: [
|
||||
{
|
||||
name: "overview",
|
||||
path: `/${ciPath}/lehre/ClassSchedule`,
|
||||
component: ClassScheduleOverview,
|
||||
},
|
||||
{
|
||||
name: "validityPeriodsOverviewByOrganizationUnit",
|
||||
path: `/${ciPath}/lehre/ClassSchedule/validityPeriods/groupedOverviewByOrganizationUnit/:organizationalUnitShortCode`,
|
||||
component: ClassScheduleOrgUnitGroupedValidityPeriodsOverview,
|
||||
params: true,
|
||||
},
|
||||
{
|
||||
name: "validityPeriodsOverviewByOrganizationUnitAndStudyPlan",
|
||||
path: `/${ciPath}/lehre/ClassSchedule/validityPeriods/groupedOverviewByOrganizationUnit/:organizationalUnitShortCode/studyPlan/:studyPlanId`,
|
||||
component: ClassScheduleOrgUnitGroupedValidityPeriodsOverview,
|
||||
params: true,
|
||||
},
|
||||
{
|
||||
name: "validityPeriodOverview",
|
||||
path: `/${ciPath}/lehre/ClassSchedule/validityPeriods/:classTimeSlotValidityPeriodId`,
|
||||
component: ClassScheduleValidityPeriodOverview,
|
||||
params: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const app = Vue.createApp({
|
||||
components: {
|
||||
CoreNavigationCmpt,
|
||||
ClassScheduleOverview,
|
||||
ClassScheduleValidityPeriodOverview,
|
||||
ClassScheduleOrgUnitGroupedValidityPeriodsOverview,
|
||||
},
|
||||
});
|
||||
|
||||
app.config.globalProperties.$capitalize = capitalize;
|
||||
|
||||
app
|
||||
.use(router)
|
||||
.use(primevue.config.default, { zIndex: { overlay: 9999 } })
|
||||
.use(FhcAlert)
|
||||
.use(Phrasen)
|
||||
.use(FhcApi)
|
||||
.mount("#main");
|
||||
File diff suppressed because it is too large
Load Diff
+121
@@ -0,0 +1,121 @@
|
||||
import ApiClassSchedule from "../../../js/api/factory/classSchedule.js";
|
||||
import ClassScheduleValidityPeriodPreview from "./ClassScheduleValidityPeriodPreview.js";
|
||||
|
||||
export default {
|
||||
name: "ClassScheduleOrgUnitGroupedValidityPeriodsOverview",
|
||||
components: {
|
||||
ClassScheduleValidityPeriodPreview,
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
organizationalUnitShortCode: null,
|
||||
studyPlanId: null,
|
||||
classScheduleValidityPeriods: [],
|
||||
classScheduleTimeSlots: [],
|
||||
classTimeSlotTypes: [],
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
methods: {},
|
||||
async created() {
|
||||
this.organizationalUnitShortCode =
|
||||
this.$route.params.organizationalUnitShortCode;
|
||||
this.studyPlanId = parseInt(this.$route.params.studyPlanId);
|
||||
|
||||
let getAllClassTimeValidityPeriodsPerOrganizationalUnitResponse =
|
||||
await this.$api.call(
|
||||
ApiClassSchedule.getAllClassTimeValidityPeriodsPerOrganizationalUnit(
|
||||
this.organizationalUnitShortCode,
|
||||
),
|
||||
);
|
||||
if (
|
||||
getAllClassTimeValidityPeriodsPerOrganizationalUnitResponse.meta
|
||||
.status === "success"
|
||||
) {
|
||||
this.classScheduleValidityPeriods =
|
||||
getAllClassTimeValidityPeriodsPerOrganizationalUnitResponse.data.filter(
|
||||
(period) => {
|
||||
if (!this.studyPlanId) return true;
|
||||
|
||||
return period.studienplan_id === this.studyPlanId;
|
||||
},
|
||||
);
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingClassScheduleValidityPeriods"),
|
||||
);
|
||||
}
|
||||
|
||||
for (let validityPeriod of this.classScheduleValidityPeriods) {
|
||||
if (
|
||||
this.studyPlanId &&
|
||||
validityPeriod.studienplan_id !== this.studyPlanId
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let getClassTimeSlotsForValidityPeriodResponse = await this.$api.call(
|
||||
ApiClassSchedule.getClassTimeSlotsForValidityPeriod(
|
||||
validityPeriod.unterrichtszeitengueltigkeit_id,
|
||||
),
|
||||
);
|
||||
if (
|
||||
getClassTimeSlotsForValidityPeriodResponse.meta.status === "success"
|
||||
) {
|
||||
this.classScheduleTimeSlots = [
|
||||
...this.classScheduleTimeSlots,
|
||||
...getClassTimeSlotsForValidityPeriodResponse.data,
|
||||
];
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t(
|
||||
"ui",
|
||||
"errorFetchingClassScheduleTimeSlotForValidityPeriod",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let getAllClassTimeSlotTypesResponse = await this.$api.call(
|
||||
ApiClassSchedule.getAllClassScheduleTypes("filter[aktiv]=true"),
|
||||
);
|
||||
if (getAllClassTimeSlotTypesResponse.meta.status === "success") {
|
||||
this.classTimeSlotTypes = getAllClassTimeSlotTypesResponse.data.map(
|
||||
(type) => {
|
||||
let descriptions = [{
|
||||
lang: "de",
|
||||
value: type.bezeichnung_mehrsprachig[0] || "",
|
||||
}, {
|
||||
lang: "en",
|
||||
value: type.bezeichnung_mehrsprachig[1] || "",
|
||||
}];
|
||||
|
||||
return {
|
||||
...type,
|
||||
bezeichnung_mehrsprachig: descriptions,
|
||||
};
|
||||
},
|
||||
);
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingClassScheduleTimeSlotTypes"),
|
||||
);
|
||||
}
|
||||
},
|
||||
template: /* html */ `
|
||||
<div class="container mt-4">
|
||||
<div class="my-2">
|
||||
<h2 v-if="!this.studyPlanId">{{ $p.t("ui", "classScheduleOrgUnitGroupedValidityPeriodsOverviewTitle") }}</h2>
|
||||
<h2 v-else>{{ $p.t("ui", "classScheduleStudyPlanGroupedValidityPeriodsOverviewTitle") }}</h2>
|
||||
</div>
|
||||
<class-schedule-validity-period-preview
|
||||
v-for="validityPeriod in classScheduleValidityPeriods"
|
||||
:key="validityPeriod.unterrichtszeitengueltigkeit"
|
||||
:class-schedule-validity-period="validityPeriod"
|
||||
:class-time-slots="classScheduleTimeSlots.filter(slot => slot.unterrichtszeitengueltigkeit_id === validityPeriod.unterrichtszeitengueltigkeit_id)"
|
||||
:class-time-slot-types="classTimeSlotTypes"
|
||||
class="shadow"
|
||||
/>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
@@ -0,0 +1,556 @@
|
||||
import { CoreFilterCmpt } from "../filter/Filter.js";
|
||||
import ApiClassSchedule from "../../../js/api/factory/classSchedule.js";
|
||||
import ApiStudienSemester from "../../../js/api/factory/studiensemester.js";
|
||||
|
||||
import ClassScheduleTypeModal from "./ClassScheduleTypeModal.js";
|
||||
import ClassScheduleValidityPeriodModal from "./ClassScheduleValidityPeriodModal.js";
|
||||
import CoreForm from "../Form/Form.js";
|
||||
import FormInput from "../Form/Input.js";
|
||||
import ApiOrganizationalUnit from "../../../js/api/factory/organizationalUnit.js";
|
||||
|
||||
export default {
|
||||
name: "ClassScheduleOverview",
|
||||
components: {
|
||||
CoreFilterCmpt,
|
||||
ClassScheduleTypeModal,
|
||||
ClassScheduleValidityPeriodModal,
|
||||
CoreForm,
|
||||
FormInput,
|
||||
},
|
||||
props: {
|
||||
permissions: Object,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
cisRoot: this.cisRoot,
|
||||
hasLehreUnterrichtszeitenTypWPermission:
|
||||
this.permissions["lehre/unterrichtszeiten_typ_w"] || false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
filterData: {
|
||||
handler(newValue) {
|
||||
this.$refs.classTimeSlotValidityPeriodsTable.tabulator.replaceData();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
selectedSemester: {
|
||||
handler(newValue) {
|
||||
this.filterData.validityPeriodFrom = this.selectedSemester.start;
|
||||
this.filterData.validityPeriodTo = this.selectedSemester.ende;
|
||||
},
|
||||
},
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
phrasesLoaded: false,
|
||||
editorParams: null,
|
||||
classTimeSlotValidityPeriods: [],
|
||||
classTimeSlotValidityPeriodId: null,
|
||||
editedClassTimeSlotValidityPeriodId: null,
|
||||
mondayClassTimeSlots: [],
|
||||
isClassTimeSlotTypeModalVisible: false,
|
||||
isClassTimeSlotValidityPeriodModalVisible: false,
|
||||
organizationalUnits: [],
|
||||
filteredOrganizationalUnits: [],
|
||||
allSemesters: [],
|
||||
filteredSemesters: [],
|
||||
filterData: {
|
||||
selectedOrganizationalUnit: null,
|
||||
validityPeriodFrom: null,
|
||||
validityPeriodTo: null,
|
||||
},
|
||||
selectedSemester: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tabulatorOptions() {
|
||||
const options = {
|
||||
ajaxURL: "dummy",
|
||||
ajaxRequestFunc: async () => {
|
||||
return await this.getParsedClassTimeSlotValidityPeriodData();
|
||||
},
|
||||
ajaxResponse: (url, params, response) => response,
|
||||
persistenceID: "class_schedule_validity_periods_table",
|
||||
selectableRows: true,
|
||||
columns: [
|
||||
{
|
||||
title: this.$p.t("ui", "zeitraum"),
|
||||
formatter: (cell, formatterParams, onRendered) => {
|
||||
const data = cell.getData();
|
||||
const validFrom = new Date(data.gueltig_von).toLocaleDateString(
|
||||
"de-AT",
|
||||
{
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
},
|
||||
);
|
||||
data.gueltig_von;
|
||||
const validTo = new Date(data.gueltig_bis).toLocaleDateString(
|
||||
"de-AT",
|
||||
{
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
},
|
||||
);
|
||||
return `${validFrom ? validFrom : "?"} - ${validTo ? validTo : "?"}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: this.$p.t("global", "typ"),
|
||||
field: "unterrichtszeiten_typ_bezeichnung_mehrsprachig",
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: this.$p.t("lehre", "sem"),
|
||||
field: "ausbildungssemester",
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: this.$p.t("global", "actions"),
|
||||
field: "actions",
|
||||
minWidth: 150,
|
||||
maxWidth: 150,
|
||||
formatter: (cell, formatterParams, onRendered) => {
|
||||
let container = document.createElement("div");
|
||||
container.className = "d-flex gap-2";
|
||||
|
||||
let button = document.createElement("button");
|
||||
|
||||
button = document.createElement("button");
|
||||
button.className = "btn btn-outline-secondary btn-action";
|
||||
button.innerHTML = '<i class="fa fa-eye"></i>';
|
||||
button.title = this.$p.t(
|
||||
"classSchedule",
|
||||
"btn_showClassTimeSlotValidityPeriod",
|
||||
);
|
||||
button.addEventListener("click", (event) =>
|
||||
this.$router.push({
|
||||
name: "validityPeriodOverview",
|
||||
params: {
|
||||
classTimeSlotValidityPeriodId:
|
||||
cell.getData().unterrichtszeitengueltigkeit_id,
|
||||
},
|
||||
}),
|
||||
);
|
||||
container.append(button);
|
||||
|
||||
button = document.createElement("button");
|
||||
button.className = "btn btn-outline-secondary btn-action";
|
||||
button.innerHTML = '<i class="fa fa-edit"></i>';
|
||||
button.title = this.$p.t(
|
||||
"classSchedule",
|
||||
"btn_editClassTimeSlotValidityPeriod",
|
||||
);
|
||||
button.addEventListener("click", (event) =>
|
||||
this.editClassTimeSlotValidityPeriod(
|
||||
cell.getData().unterrichtszeitengueltigkeit_id,
|
||||
),
|
||||
);
|
||||
container.append(button);
|
||||
|
||||
button = document.createElement("button");
|
||||
button.className =
|
||||
"btn btn-outline-secondary btn-action bg-danger";
|
||||
button.innerHTML = '<i class="fa fa-xmark text-white"></i>';
|
||||
button.title = this.$p.t(
|
||||
"classSchedule",
|
||||
"btn_deleteClassTimeSlotValidityPeriod",
|
||||
);
|
||||
button.addEventListener("click", () => {
|
||||
let isDeletionConfirmed = confirm(
|
||||
this.$p.t(
|
||||
"ui",
|
||||
"deleteClassTimeSlotValidityPeriodConfirmation",
|
||||
),
|
||||
);
|
||||
if (!isDeletionConfirmed) return;
|
||||
|
||||
this.deleteClassTimeSlotValidityPeriod(
|
||||
cell.getData().unterrichtszeitengueltigkeit_id,
|
||||
);
|
||||
});
|
||||
container.append(button);
|
||||
|
||||
return container;
|
||||
},
|
||||
frozen: true,
|
||||
},
|
||||
],
|
||||
groupBy: [
|
||||
"organisationseinheit_bezeichnung_extended",
|
||||
"studienplan_bezeichnung",
|
||||
],
|
||||
groupHeader: [
|
||||
function (value, count, data) {
|
||||
let container = document.createElement("span");
|
||||
|
||||
container.className =
|
||||
"d-flex align-items-center justify-content-between";
|
||||
container.style.display = "inline-block";
|
||||
container.style.width = "100%";
|
||||
|
||||
let label = document.createElement("span");
|
||||
label.textContent = value;
|
||||
container.append(label);
|
||||
|
||||
let button = document.createElement("button");
|
||||
button.className =
|
||||
"btn btn-sm btn-outline-secondary fhc-btn-for-org-unit-grouping";
|
||||
button.style.marginLeft = "10px";
|
||||
button.innerHTML = '<i class="fa fa-eye"></i>';
|
||||
|
||||
button.dataset.organizationalUnitShortCode = data[0].oe_kurzbz;
|
||||
|
||||
container.append(button);
|
||||
return container;
|
||||
},
|
||||
function (value, count, data) {
|
||||
let container = document.createElement("span");
|
||||
|
||||
container.className =
|
||||
"d-flex align-items-center justify-content-between";
|
||||
container.style.display = "inline-block";
|
||||
container.style.width = "100%";
|
||||
|
||||
let label = document.createElement("span");
|
||||
label.textContent = value;
|
||||
container.append(label);
|
||||
|
||||
let button = document.createElement("button");
|
||||
button.className =
|
||||
"btn btn-sm btn-outline-secondary fhc-btn-for-org-unit-and-study-plan-grouping";
|
||||
button.style.marginLeft = "10px";
|
||||
button.innerHTML = '<i class="fa fa-eye"></i>';
|
||||
button.title = 22;
|
||||
|
||||
button.dataset.organizationalUnitShortCode = data[0].oe_kurzbz;
|
||||
button.dataset.studyPlanId = data[0].studienplan_id;
|
||||
|
||||
container.append(button);
|
||||
return container;
|
||||
},
|
||||
],
|
||||
};
|
||||
return options;
|
||||
},
|
||||
tabulatorEvents() {
|
||||
const events = [
|
||||
{
|
||||
event: "renderComplete",
|
||||
handler: async () => {
|
||||
document
|
||||
.querySelectorAll(".fhc-btn-for-org-unit-grouping")
|
||||
.forEach((button) => {
|
||||
button.addEventListener("click", (e) => {
|
||||
let organizationalUnitShortCode =
|
||||
button.dataset.organizationalUnitShortCode;
|
||||
|
||||
this.$router.push({
|
||||
name: "validityPeriodsOverviewByOrganizationUnit",
|
||||
params: {
|
||||
organizationalUnitShortCode,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
document
|
||||
.querySelectorAll(".fhc-btn-for-org-unit-and-study-plan-grouping")
|
||||
.forEach((button) => {
|
||||
button.addEventListener("click", (e) => {
|
||||
let organizationalUnitShortCode =
|
||||
button.dataset.organizationalUnitShortCode;
|
||||
let studyPlanId = button.dataset.studyPlanId;
|
||||
this.$router.push({
|
||||
name: "validityPeriodsOverviewByOrganizationUnitAndStudyPlan",
|
||||
params: {
|
||||
organizationalUnitShortCode,
|
||||
studyPlanId,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
return events;
|
||||
},
|
||||
dropdownParsedOrganizationalUnits() {
|
||||
return this.organizationalUnits
|
||||
.filter((unit) => unit.aktiv)
|
||||
.map((unit) => {
|
||||
return {
|
||||
label: `[${unit.organisationseinheittyp_kurzbz}] ${unit.bezeichnung}`,
|
||||
value: unit.oe_kurzbz,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
},
|
||||
dropdownParsedSemesters() {
|
||||
return this.allSemesters.map((semester) => {
|
||||
return {
|
||||
label: semester.studiensemester_kurzbz,
|
||||
value: semester.studiensemester_kurzbz,
|
||||
start: semester.start,
|
||||
ende: semester.ende,
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async getParsedClassTimeSlotValidityPeriodData() {
|
||||
let getAllClassTimeValidityPeriodsResponse = await this.$api.call(
|
||||
ApiClassSchedule.getAllClassTimeValidityPeriods({
|
||||
organizationalUnitShortCode:
|
||||
this.filterData.selectedOrganizationalUnit?.value,
|
||||
validityPeriodFrom: this.filterData.validityPeriodFrom
|
||||
? moment(this.filterData.validityPeriodFrom).format("YYYY-MM-DD")
|
||||
: null,
|
||||
validityPeriodTo: this.filterData.validityPeriodTo
|
||||
? moment(this.filterData.validityPeriodTo).format("YYYY-MM-DD")
|
||||
: null,
|
||||
}),
|
||||
);
|
||||
|
||||
if (getAllClassTimeValidityPeriodsResponse.meta.status === "success") {
|
||||
let generalWord = this.$p.t("ui", "general");
|
||||
return getAllClassTimeValidityPeriodsResponse.data.map(
|
||||
function (period) {
|
||||
period.organisationseinheit_bezeichnung_extended =
|
||||
"[" + period.organisationseinheit_organisationseinheittyp_kurzbz + "] " + period.organisationseinheit_bezeichnung;
|
||||
if (!period.studienplan_bezeichnung) {
|
||||
period.studienplan_bezeichnung = generalWord;
|
||||
}
|
||||
period.unterrichtszeiten_typ_bezeichnung_mehrsprachig =
|
||||
period.unterrichtszeiten_typ_bezeichnung_mehrsprachig[0]?.split(
|
||||
":",
|
||||
)[1];
|
||||
return {
|
||||
...period,
|
||||
};
|
||||
},
|
||||
);
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingClassScheduleValidityPeriods"),
|
||||
);
|
||||
}
|
||||
},
|
||||
showClassTimeSlotValidityPeriodModal() {
|
||||
this.isClassTimeSlotValidityPeriodModalVisible = true;
|
||||
},
|
||||
editClassTimeSlotValidityPeriod(classTimeSlotValidityPeriodId) {
|
||||
this.editedClassTimeSlotValidityPeriodId = classTimeSlotValidityPeriodId;
|
||||
},
|
||||
deleteClassTimeSlotValidityPeriod(classTimeSlotValidityPeriodId) {
|
||||
return this.$api
|
||||
.call(
|
||||
ApiClassSchedule.deleteClassTimeSlotValidityPeriod(
|
||||
this.id,
|
||||
classTimeSlotValidityPeriodId,
|
||||
),
|
||||
)
|
||||
.then((response) => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successDelete"));
|
||||
window.scrollTo(0, 0);
|
||||
this.$refs.classTimeSlotValidityPeriodsTable.tabulator.replaceData();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
showClassTimeSlotTypeModal() {
|
||||
this.isClassTimeSlotTypeModalVisible = true;
|
||||
},
|
||||
resetClassTimeSlotTypeModal() {
|
||||
this.isClassTimeSlotTypeModalVisible = false;
|
||||
},
|
||||
resetClassTimeSlotValidityPeriodModal() {
|
||||
this.isClassTimeSlotValidityPeriodModalVisible = false;
|
||||
},
|
||||
filterOrganizationalUnits(event) {
|
||||
let defaultItem = {
|
||||
label: this.$p.t("ui", "dropdownEmptyOption"),
|
||||
value: null,
|
||||
};
|
||||
|
||||
const query = event.query.toLowerCase();
|
||||
if (!query) {
|
||||
return (this.filteredOrganizationalUnits = [
|
||||
defaultItem,
|
||||
...this.dropdownParsedOrganizationalUnits,
|
||||
]);
|
||||
}
|
||||
|
||||
return (this.filteredOrganizationalUnits = [defaultItem]
|
||||
.concat(this.dropdownParsedOrganizationalUnits)
|
||||
.filter((unit) => {
|
||||
return unit.label.toLowerCase().includes(query);
|
||||
}));
|
||||
},
|
||||
filterSemesters(event) {
|
||||
let defaultItem = {
|
||||
label: this.$p.t("ui", "dropdownEmptyOption"),
|
||||
value: null,
|
||||
};
|
||||
|
||||
const query = event.query.toLowerCase();
|
||||
if (!query) {
|
||||
return (this.filteredSemesters = [
|
||||
defaultItem,
|
||||
...this.dropdownParsedSemesters,
|
||||
]);
|
||||
}
|
||||
|
||||
return (this.filteredSemesters = [defaultItem]
|
||||
.concat(this.dropdownParsedSemesters)
|
||||
.filter((semester) => {
|
||||
return semester.label.toLowerCase().includes(query);
|
||||
}));
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
let getAllClassTimeValidityPeriodsResponse = await this.$api.call(
|
||||
ApiClassSchedule.getAllClassTimeValidityPeriods(),
|
||||
);
|
||||
if (getAllClassTimeValidityPeriodsResponse.meta.status === "success") {
|
||||
this.classTimeSlotValidityPeriods =
|
||||
getAllClassTimeValidityPeriodsResponse.data;
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingClassScheduleValidityPeriods"),
|
||||
);
|
||||
}
|
||||
|
||||
let getAllOrganizationalUnitsResponse = await this.$api.call(
|
||||
ApiOrganizationalUnit.getAllOrganizationalUnits(),
|
||||
);
|
||||
if (getAllOrganizationalUnitsResponse.meta.status === "success") {
|
||||
this.organizationalUnits = getAllOrganizationalUnitsResponse.data.sort(
|
||||
(a, b) => a.bezeichnung.localeCompare(b.bezeichnung),
|
||||
);
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingOrganizationalUnits"),
|
||||
);
|
||||
}
|
||||
|
||||
let getAllSemestersResponse = await this.$api.call(
|
||||
ApiStudienSemester.getAll("DESC"),
|
||||
);
|
||||
if (getAllSemestersResponse.meta.status === "success") {
|
||||
this.allSemesters = getAllSemestersResponse.data;
|
||||
} else {
|
||||
this.$fhcAlert.alertError(this.$p.t("ui", "errorFetchingSemesters"));
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$p
|
||||
.loadCategory(["global", "lehre", "ui", "gruppenmanagement", "core"])
|
||||
.then(() => {
|
||||
this.phrasesLoaded = true;
|
||||
});
|
||||
},
|
||||
template: /* html */ `
|
||||
<div class="container mt-4">
|
||||
<h1 class='mb-5'>{{ $p.t("ui", "classScheduleOverviewHeading") }}</h1>
|
||||
<div class="row mb-3">
|
||||
<div class="col d-flex justify-content-between">
|
||||
<a class="btn btn-primary mb-3" @click="showClassTimeSlotValidityPeriodModal">{{$p.t('ui', 'addClassTimeSlotValidityPeriodButton')}}</a>
|
||||
<a class="btn btn-secondary mb-3" @click="showClassTimeSlotTypeModal">{{$p.t('ui', 'addClassTimeSlotTypeButton')}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<class-schedule-type-modal
|
||||
:isVisible="isClassTimeSlotTypeModalVisible"
|
||||
@hideBsModal="resetClassTimeSlotTypeModal"
|
||||
/>
|
||||
<class-schedule-validity-period-modal
|
||||
:isVisible="isClassTimeSlotValidityPeriodModalVisible"
|
||||
:editedClassTimeSlotValidityPeriodId="editedClassTimeSlotValidityPeriodId"
|
||||
@hideBsModal="() => { resetClassTimeSlotValidityPeriodModal(); editedClassTimeSlotValidityPeriodId = null; }"
|
||||
@classTimeSlotValidityPeriodCreated="() => {
|
||||
$refs.classTimeSlotValidityPeriodsTable.tabulator.replaceData();
|
||||
resetClassTimeSlotValidityPeriodModal();
|
||||
this.editedClassTimeSlotValidityPeriodId = null;
|
||||
}"
|
||||
@classTimeSlotValidityPeriodUpdated="() => {
|
||||
$refs.classTimeSlotValidityPeriodsTable.tabulator.replaceData();
|
||||
resetClassTimeSlotValidityPeriodModal();
|
||||
this.editedClassTimeSlotValidityPeriodId = null;
|
||||
}"
|
||||
/>
|
||||
<core-filter-cmpt
|
||||
v-if="phrasesLoaded"
|
||||
ref="classTimeSlotValidityPeriodsTable"
|
||||
table-only
|
||||
:side-menu="false"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
:tabulator-events="tabulatorEvents"
|
||||
>
|
||||
<template #search>
|
||||
<slot name="filterzuruecksetzen">
|
||||
<core-form class="d-flex flex-column flex-md-row align-items-md-end gap-3">
|
||||
<div>
|
||||
<form-input
|
||||
:label="$capitalize($p.t('lehre/organisationseinheit'))"
|
||||
:suggestions="filteredOrganizationalUnits"
|
||||
:optionValue="(option) => option.value"
|
||||
:optionLabel="(option) => option.label"
|
||||
@complete="filterOrganizationalUnits($event)"
|
||||
@itemSelect="(option) => { filterData.selectedOrganizationalUnit = option.value; }"
|
||||
type="autocomplete"
|
||||
name="organizationalUnitShortCode"
|
||||
dropdown
|
||||
forceSelection
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div>
|
||||
<form-input
|
||||
v-model="selectedSemester"
|
||||
:label="$capitalize($p.t('lehre/studiensemester'))"
|
||||
:suggestions="filteredSemesters"
|
||||
:optionValue="(option) => option.value"
|
||||
:optionLabel="(option) => option.label"
|
||||
@complete="filterSemesters($event)"
|
||||
type="autocomplete"
|
||||
name="selectedSemester"
|
||||
dropdown
|
||||
forceSelection
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<form-input
|
||||
v-model="filterData.validityPeriodFrom"
|
||||
:label="$p.t('ui', 'validityPeriod') + ' ' + $p.t('ui', 'von')"
|
||||
:teleport="true"
|
||||
:enable-time-picker="false"
|
||||
type="datePicker"
|
||||
name="validityPeriodFrom"
|
||||
format="dd.MM.yyyy"
|
||||
auto-apply
|
||||
/>
|
||||
<form-input
|
||||
v-model="filterData.validityPeriodTo"
|
||||
:label="$p.t('ui', 'validityPeriod') + ' ' + $p.t('global', 'bis')"
|
||||
:teleport="true"
|
||||
:enable-time-picker="false"
|
||||
type="datePicker"
|
||||
name="validityPeriodTo"
|
||||
format="dd.MM.yyyy"
|
||||
auto-apply
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</core-form>
|
||||
</slot>
|
||||
</template>
|
||||
</core-filter-cmpt>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
@@ -0,0 +1,273 @@
|
||||
import ApiClassSchedule from "../../../js/api/factory/classSchedule.js";
|
||||
|
||||
import BsModal from "../Bootstrap/Modal.js";
|
||||
import CoreForm from "../Form/Form.js";
|
||||
import FormInput from "../Form/Input.js";
|
||||
|
||||
export default {
|
||||
name: "ClassScheduleTypeModal",
|
||||
components: {
|
||||
BsModal,
|
||||
CoreForm,
|
||||
FormInput,
|
||||
},
|
||||
inject: {
|
||||
hasLehreUnterrichtszeitenTypWPermission:
|
||||
"hasLehreUnterrichtszeitenTypWPermission",
|
||||
},
|
||||
props: {
|
||||
isVisible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
"hideBsModal",
|
||||
"classTimeSlotTypeCreated",
|
||||
"classTimeSlotTypeUpdated",
|
||||
],
|
||||
watch: {
|
||||
isVisible(newValue) {
|
||||
if (newValue) {
|
||||
this.$refs.classScheduleTypeModal.show();
|
||||
} else {
|
||||
this.$refs.classScheduleTypeModal.hide();
|
||||
}
|
||||
},
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
isFormVisible: false,
|
||||
isEditInProgress: false,
|
||||
editedClassScheduleType: null,
|
||||
classTimeSlotTypeFormData: {
|
||||
isActive: true,
|
||||
shortCode: "",
|
||||
descriptions: [
|
||||
{ lang: "de", value: "" },
|
||||
{ lang: "en", value: "" },
|
||||
],
|
||||
backgroundColor: "#ffffff",
|
||||
},
|
||||
classScheduleTypes: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async getAllClassScheduleTypes() {
|
||||
let getAllClassScheduleTypeResponse = await this.$api.call(
|
||||
ApiClassSchedule.getAllClassScheduleTypes(),
|
||||
);
|
||||
if (getAllClassScheduleTypeResponse.meta.status === "success") {
|
||||
this.classScheduleTypes = getAllClassScheduleTypeResponse.data.map(
|
||||
(type) => {
|
||||
let descriptions = [{
|
||||
lang: "de",
|
||||
value: type.bezeichnung_mehrsprachig[0] || "",
|
||||
}, {
|
||||
lang: "en",
|
||||
value: type.bezeichnung_mehrsprachig[1] || "",
|
||||
}];
|
||||
|
||||
return {
|
||||
...type,
|
||||
bezeichnung_mehrsprachig: descriptions,
|
||||
};
|
||||
},
|
||||
);
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingClassScheduleTimeSlotTypes"),
|
||||
);
|
||||
}
|
||||
},
|
||||
createClassTimeSlotType() {
|
||||
return this.$refs.classTimeSlotTypeForm
|
||||
.call(
|
||||
ApiClassSchedule.createClassTimeSlotType({
|
||||
isActive: this.classTimeSlotTypeFormData.isActive,
|
||||
shortCode: this.classTimeSlotTypeFormData.shortCode,
|
||||
descriptions: this.classTimeSlotTypeFormData.descriptions,
|
||||
backgroundColor: this.classTimeSlotTypeFormData.backgroundColor,
|
||||
}),
|
||||
)
|
||||
.then((response) => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
|
||||
this.$emit("classTimeSlotTypeCreated");
|
||||
this.getAllClassScheduleTypes();
|
||||
this.resetClassTimeSlotTypeForm();
|
||||
});
|
||||
},
|
||||
editClassTimeSlotType(classScheduleType) {
|
||||
this.isEditInProgress = true;
|
||||
this.isFormVisible = true;
|
||||
this.editedClassScheduleType = classScheduleType;
|
||||
this.classTimeSlotTypeFormData = {
|
||||
isActive: classScheduleType.aktiv,
|
||||
shortCode: classScheduleType.unterrichtszeitentyp_kurzbz,
|
||||
descriptions: classScheduleType.bezeichnung_mehrsprachig.map(
|
||||
(desc) => ({
|
||||
lang: desc.lang,
|
||||
value: desc.value,
|
||||
}),
|
||||
),
|
||||
backgroundColor: classScheduleType.hintergrundfarbe || "#ffffff",
|
||||
};
|
||||
},
|
||||
updateClassTimeSlotType() {
|
||||
return this.$refs.classTimeSlotTypeForm
|
||||
.call(
|
||||
ApiClassSchedule.updateClassTimeSlotType(
|
||||
this.classTimeSlotTypeFormData.shortCode,
|
||||
{
|
||||
isActive: this.classTimeSlotTypeFormData.isActive,
|
||||
descriptions: this.classTimeSlotTypeFormData.descriptions,
|
||||
backgroundColor: this.classTimeSlotTypeFormData.backgroundColor,
|
||||
},
|
||||
),
|
||||
)
|
||||
.then((response) => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
|
||||
this.$emit("classTimeSlotTypeUpdated");
|
||||
this.getAllClassScheduleTypes();
|
||||
this.resetClassTimeSlotTypeForm();
|
||||
});
|
||||
},
|
||||
deleteClassTimeSlotType(classScheduleTypeShortCode) {
|
||||
let isConfirmed = confirm(
|
||||
this.$p.t("ui", "confirmDeleteClassTimeSlotType"),
|
||||
);
|
||||
if (!isConfirmed) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return this.$api
|
||||
.call(
|
||||
ApiClassSchedule.deleteClassTimeSlotType(
|
||||
this.id,
|
||||
classScheduleTypeShortCode,
|
||||
),
|
||||
)
|
||||
.then((response) => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successDelete"));
|
||||
window.scrollTo(0, 0);
|
||||
this.getAllClassScheduleTypes();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
showClassTimeSlotTypeForm() {
|
||||
this.isFormVisible = true;
|
||||
},
|
||||
hideClassTimeSlotTypeForm() {
|
||||
this.resetClassTimeSlotTypeForm();
|
||||
},
|
||||
resetClassTimeSlotTypeForm() {
|
||||
this.isEditInProgress = false;
|
||||
this.isFormVisible = false;
|
||||
this.classTimeSlotTypeFormData = {
|
||||
isActive: true,
|
||||
shortCode: "",
|
||||
descriptions: [
|
||||
{ lang: "de", value: "" },
|
||||
{ lang: "en", value: "" },
|
||||
],
|
||||
backgroundColor: "#ffffff",
|
||||
};
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
await this.getAllClassScheduleTypes();
|
||||
},
|
||||
template: /* html */ `
|
||||
<bs-modal ref="classScheduleTypeModal" size="md" @hideBsModal="() => { $emit('hideBsModal'); resetClassTimeSlotTypeForm(); }">
|
||||
<template #title>
|
||||
<p v-if="hasLehreUnterrichtszeitenTypWPermission" class="fw-bold mt-3">{{$p.t('ui', 'editClassTimeSlotTypeModalTitle')}}</p>
|
||||
<p v-else class="fw-bold mt-3">{{$p.t('ui', 'existingClassScheduleTypesLabel')}}</p>
|
||||
</template>
|
||||
<div v-if="!isFormVisible && hasLehreUnterrichtszeitenTypWPermission" class="row mb-3">
|
||||
<div class="col d-flex justify-content-end">
|
||||
<button @click="showClassTimeSlotTypeForm" type="button" class="btn btn-primary">{{$p.t('global', 'create')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<core-form v-else-if="isFormVisible && hasLehreUnterrichtszeitenTypWPermission" ref="classTimeSlotTypeForm" class="row g-3 pb-3">
|
||||
<div v-if="!isEditInProgress" class="row mb-3">
|
||||
<form-input
|
||||
v-model="classTimeSlotTypeFormData.shortCode"
|
||||
:label="$p.t('ui/shortName')"
|
||||
type="text"
|
||||
name="shortCode"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div v-else class="row mb-3">
|
||||
<p class="mb-0"><span class="fw-bold">{{$p.t('ui/shortName')}}:</span> {{editedClassScheduleType.unterrichtszeitentyp_kurzbz}}</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form-input
|
||||
v-for="description in classTimeSlotTypeFormData.descriptions"
|
||||
:key="description.lang"
|
||||
v-model="description.value"
|
||||
:name="description.lang"
|
||||
:label="$p.t('ui/description') + ' (' + description.lang + ')'"
|
||||
type="textarea"
|
||||
class="mb-3"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
v-model="classTimeSlotTypeFormData.backgroundColor"
|
||||
:label="$p.t('ui/backgroundColor')"
|
||||
type="color"
|
||||
name="backgroundColor"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col d-flex align-items-center justify-content-end">
|
||||
<form-input
|
||||
v-model="classTimeSlotTypeFormData.isActive"
|
||||
:label="$p.t('ui/isActive')"
|
||||
type="checkbox"
|
||||
name="isActive"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col d-flex justify-content-end gap-2">
|
||||
<button type="button" class="btn btn-secondary" @click="hideClassTimeSlotTypeForm">{{$p.t('ui', 'abbrechen')}}</button>
|
||||
<button type="button" class="btn btn-primary" @click="isEditInProgress ? updateClassTimeSlotType() : createClassTimeSlotType()">{{$p.t('ui', 'speichern')}}</button>
|
||||
</div>
|
||||
</core-form>
|
||||
<div class="row mb-3">
|
||||
<p v-if="hasLehreUnterrichtszeitenTypWPermission" class="fw-bold mb-2">{{$p.t('ui', 'existingClassScheduleTypesLabel')}}</p>
|
||||
<div
|
||||
>
|
||||
<div
|
||||
v-for="classScheduleType in classScheduleTypes"
|
||||
:key="classScheduleType.unterrichtszeitentyp_kurzbz"
|
||||
:value="classScheduleType.unterrichtszeitentyp_kurzbz"
|
||||
:class='{"opacity-50": !classScheduleType.aktiv}'
|
||||
class=" shadow-sm p-2 mb-2 bg-body rounded"
|
||||
>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span
|
||||
:style="{ backgroundColor: classScheduleType.hintergrundfarbe }"
|
||||
class="badge me-2 text-black">
|
||||
{{classScheduleType.unterrichtszeitentyp_kurzbz}}
|
||||
</span>
|
||||
<div v-if="hasLehreUnterrichtszeitenTypWPermission" class="d-flex justify-content-between align-items-center gap-2">
|
||||
<a href="#" @click.prevent="editClassTimeSlotType(classScheduleType)"><i class="fa fa-edit"></i></a>
|
||||
<a href="#" @click.prevent="deleteClassTimeSlotType(classScheduleType.unterrichtszeitentyp_kurzbz)"><i class="fa fa-trash text-danger"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
{{classScheduleType.bezeichnung_mehrsprachig[0].value}} / {{classScheduleType.bezeichnung_mehrsprachig[1].value}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</bs-modal>
|
||||
`,
|
||||
};
|
||||
@@ -0,0 +1,170 @@
|
||||
import ApiClassSchedule from "../../../js/api/factory/classSchedule.js";
|
||||
import ApiClassroomHour from "../../../js/api/factory/classroomHour.js";
|
||||
|
||||
import ClassScheduleCalendarSelector from "./ClassScheduleCalendarSelector.js";
|
||||
|
||||
export default {
|
||||
name: "ClassScheduleValidityPeriodForm",
|
||||
components: {
|
||||
ClassScheduleCalendarSelector,
|
||||
},
|
||||
props: {
|
||||
classTimeSlotTypes: {
|
||||
type: [Array, null],
|
||||
required: true,
|
||||
},
|
||||
classTimeSlotValidityPeriod: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
editedClassTimeSlots: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
classroomHours: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
emits: ["hideForm", "classTimeSlotsCreated", "classTimeSlotsEdited"],
|
||||
watch: {
|
||||
editedClassTimeSlots: {
|
||||
handler(newVal) {
|
||||
this.editedOverlays = newVal.map((slot) => {
|
||||
return {
|
||||
databaseId: slot.id,
|
||||
id: slot.identifier,
|
||||
weekday: slot.wochentag + 1,
|
||||
type: slot.unterrichtszeitentyp_kurzbz,
|
||||
startTime: slot.startTime,
|
||||
endTime: slot.endTime,
|
||||
};
|
||||
});
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
editedOverlays: [],
|
||||
classTimeSlots: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
areClassTimeSlotsEdited() {
|
||||
return this.editedClassTimeSlots && this.editedClassTimeSlots.length > 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hideForm() {
|
||||
this.$emit("hideForm");
|
||||
this.classTimeSlots = [];
|
||||
},
|
||||
addClassTimeSlotPerDay(day) {
|
||||
this.classTimeSlots.push({
|
||||
identifier: Math.random().toString(36).substr(2, 9),
|
||||
wochentag: this.getWeekdayNumberFromDay(day),
|
||||
startTime: "08:00",
|
||||
endTime: "10:00",
|
||||
classTimeSlotTypeShortcode: null,
|
||||
});
|
||||
},
|
||||
removeClassTimeSlotPerDay(day, identifier) {
|
||||
this.classTimeSlots = this.classTimeSlots.filter(
|
||||
(slot) =>
|
||||
!(
|
||||
slot.wochentag === this.getWeekdayNumberFromDay(day) &&
|
||||
slot.identifier === identifier
|
||||
),
|
||||
);
|
||||
},
|
||||
async createClassTimeSlots() {
|
||||
let response = await this.$api.call(
|
||||
ApiClassSchedule.createClassTimeSlotsForValidityPeriod(
|
||||
this.id,
|
||||
this.$props.classTimeSlotValidityPeriod
|
||||
.unterrichtszeitengueltigkeit_id,
|
||||
{
|
||||
unterrichtszeiten: this.classTimeSlots.map((slot) => {
|
||||
slot.wochentag = parseInt(slot.wochentag)- 1;
|
||||
return slot;
|
||||
}),
|
||||
},
|
||||
),
|
||||
);
|
||||
if (response.meta.status === "success") {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
|
||||
this.classTimeSlots = [];
|
||||
this.$emit("classTimeSlotsCreated");
|
||||
} else {
|
||||
this.$fhcAlert.handleSystemError(response.meta.message);
|
||||
}
|
||||
},
|
||||
async updateClassTimeSlots() {
|
||||
let response = await this.$api.call(
|
||||
ApiClassSchedule.updateClassTimeSlotsForValidityPeriod(
|
||||
this.id,
|
||||
this.$props.classTimeSlotValidityPeriod
|
||||
.unterrichtszeitengueltigkeit_id,
|
||||
{
|
||||
unterrichtszeiten: this.classTimeSlots.map((slot) => {
|
||||
slot.wochentag = parseInt(slot.wochentag)- 1;
|
||||
return slot;
|
||||
}),
|
||||
},
|
||||
),
|
||||
);
|
||||
if (response.meta.status === "success") {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
|
||||
this.classTimeSlots = [];
|
||||
this.$emit("classTimeSlotsEdited");
|
||||
} else {
|
||||
this.$fhcAlert.handleSystemError(response.meta.message);
|
||||
}
|
||||
},
|
||||
getWeekdayNumberFromDay(day) {
|
||||
const days = {
|
||||
monday: 1,
|
||||
tuesday: 2,
|
||||
wednesday: 3,
|
||||
thursday: 4,
|
||||
friday: 5,
|
||||
saturday: 6,
|
||||
sunday: 7,
|
||||
};
|
||||
return days[day.toLowerCase()] || null;
|
||||
},
|
||||
handleOverlaysChanged(newOverlays) {
|
||||
this.classTimeSlots = newOverlays.map((overlay) => {
|
||||
return {
|
||||
id: overlay.databaseId || null,
|
||||
identifier: overlay.id,
|
||||
wochentag: overlay.weekday,
|
||||
startTime: overlay.startingTimeSlot.split("-")[0],
|
||||
endTime: overlay.endingTimeSlot.split("-")[1],
|
||||
classTimeSlotTypeShortcode: overlay.type,
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div class='row'>
|
||||
<div class='col-12'>
|
||||
<class-schedule-calendar-selector
|
||||
:classroom-hours="this.$props.classroomHours"
|
||||
:default-class-time-slot-type="this.$props.classTimeSlotTypes.find(type => type.is_default)"
|
||||
:class-time-slot-types="this.$props.classTimeSlotTypes"
|
||||
:edited-overlays="this.editedOverlays"
|
||||
@overlaysChanged="handleOverlaysChanged"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-12 d-flex justify-content-end gap-2">
|
||||
<button type="button" class="btn btn-secondary" @click="hideForm">{{$p.t('ui', 'abbrechen')}}</button>
|
||||
<button v-if="!areClassTimeSlotsEdited" type="button" class="btn btn-primary" @click="createClassTimeSlots">{{$p.t('ui', 'speichern')}}</button>
|
||||
<button v-else type="button" class="btn btn-primary" @click="updateClassTimeSlots">{{$p.t('ui', 'btnAktualisieren')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
@@ -0,0 +1,577 @@
|
||||
import ApiClassSchedule from "../../../js/api/factory/classSchedule.js";
|
||||
import ApiStudienPlan from "../../../js/api/factory/studienplan.js";
|
||||
import ApiStudienSemester from "../../../js/api/factory/studiensemester.js";
|
||||
import ApiOrganizationalUnit from "../../../js/api/factory/organizationalUnit.js";
|
||||
|
||||
import BsModal from "../Bootstrap/Modal.js";
|
||||
import CoreForm from "../Form/Form.js";
|
||||
import FormInput from "../Form/Input.js";
|
||||
import FormValidation from "../Form/Validation.js";
|
||||
|
||||
export default {
|
||||
name: "ClassScheduleValidityPeriodModal",
|
||||
components: {
|
||||
BsModal,
|
||||
CoreForm,
|
||||
FormInput,
|
||||
FormValidation,
|
||||
},
|
||||
props: {
|
||||
isVisible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
editedClassTimeSlotValidityPeriodId: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
"hideBsModal",
|
||||
"classTimeSlotValidityPeriodCreated",
|
||||
"classTimeSlotValidityPeriodUpdated",
|
||||
],
|
||||
watch: {
|
||||
isVisible(newValue) {
|
||||
if (newValue) {
|
||||
this.$refs.classTimeSlotValidityPeriodModal.show();
|
||||
} else {
|
||||
this.$refs.classTimeSlotValidityPeriodModal.hide();
|
||||
}
|
||||
},
|
||||
editedClassTimeSlotValidityPeriodId(newValue) {
|
||||
if (!newValue) return;
|
||||
|
||||
return this.$api
|
||||
.call(ApiClassSchedule.getClassTimeValidityPeriod(newValue))
|
||||
.then((response) => {
|
||||
let validityPeriodData = response.data[0];
|
||||
let parsedOrganizationalUnit = this.dropdownParsedOrganizationalUnits.find(
|
||||
(unit) => unit.value === validityPeriodData.oe_kurzbz,
|
||||
);
|
||||
if (!parsedOrganizationalUnit) {
|
||||
parsedOrganizationalUnit = {
|
||||
value: validityPeriodData.oe_kurzbz,
|
||||
label: validityPeriodData.oe_bezeichnung ,
|
||||
};
|
||||
}
|
||||
|
||||
this.editedClassTimeSlotValidityPeriod = validityPeriodData;
|
||||
|
||||
this.classTimeSlotValidityPeriodFormData = {
|
||||
id: validityPeriodData.unterrichtszeitengueltigkeit_id,
|
||||
organizationalUnit: parsedOrganizationalUnit,
|
||||
studyPlanId: validityPeriodData.studienplan_id,
|
||||
classTimeSlotTypeShortcode:
|
||||
validityPeriodData.unterrichtszeitentyp_kurzbz,
|
||||
validityPeriodFrom: validityPeriodData.gueltig_von,
|
||||
validityPeriodTo: validityPeriodData.gueltig_bis,
|
||||
semester: validityPeriodData.ausbildungssemester,
|
||||
description: validityPeriodData.anmerkung,
|
||||
};
|
||||
this.$refs.classTimeSlotValidityPeriodModal.show();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
"classTimeSlotValidityPeriodFormData.organizationalUnit"() {
|
||||
this.updateClassTimeSlotValidityPeriodFormDataWatcher();
|
||||
},
|
||||
"classTimeSlotValidityPeriodFormData.validityPeriodFrom"() {
|
||||
this.updateClassTimeSlotValidityPeriodFormDataWatcher();
|
||||
},
|
||||
"classTimeSlotValidityPeriodFormData.validityPeriodTo"() {
|
||||
this.updateClassTimeSlotValidityPeriodFormDataWatcher();
|
||||
},
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
editedValidityPeriod: null,
|
||||
isFormVisible: false,
|
||||
organizationalUnits: [],
|
||||
filteredOrganizationalUnits: [],
|
||||
studyPlans: [],
|
||||
studySemesters: [],
|
||||
studySemestersByNumber: [],
|
||||
classTimeSlotTypes: [],
|
||||
classTimeSlotValidityPeriodFormData: {
|
||||
id: null,
|
||||
organizationalUnit: null,
|
||||
studyPlanId: null,
|
||||
classTimeSlotTypeShortcode: null,
|
||||
validityPeriodFrom: null,
|
||||
validityPeriodTo: null,
|
||||
semester: null,
|
||||
description: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isEditMode() {
|
||||
return !!this.$props.editedClassTimeSlotValidityPeriodId;
|
||||
},
|
||||
isStudyPlanSelectDisabled() {
|
||||
return (
|
||||
!this.classTimeSlotValidityPeriodFormData.organizationalUnit
|
||||
?.value ||
|
||||
!this.classTimeSlotValidityPeriodFormData.validityPeriodFrom ||
|
||||
!this.classTimeSlotValidityPeriodFormData.validityPeriodTo
|
||||
);
|
||||
},
|
||||
formattedValidityPeriodFrom() {
|
||||
if (!this.classTimeSlotValidityPeriodFormData.validityPeriodFrom)
|
||||
return null;
|
||||
|
||||
return moment(this.classTimeSlotValidityPeriodFormData.validityPeriodFrom).format("YYYY-MM-DD");
|
||||
},
|
||||
formattedValidityPeriodTo() {
|
||||
if (!this.classTimeSlotValidityPeriodFormData.validityPeriodTo)
|
||||
return null;
|
||||
return moment(this.classTimeSlotValidityPeriodFormData.validityPeriodTo).format("YYYY-MM-DD");
|
||||
},
|
||||
userLanguage() {
|
||||
return Vue.ref(FHC_JS_DATA_STORAGE_OBJECT.user_language);
|
||||
},
|
||||
dropdownParsedOrganizationalUnits() {
|
||||
return this.organizationalUnits
|
||||
.filter((unit) => unit.aktiv)
|
||||
.map((unit) => {
|
||||
return {
|
||||
label: `[${unit.organisationseinheittyp_kurzbz}] ${unit.bezeichnung}`,
|
||||
value: unit.oe_kurzbz,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateClassTimeSlotValidityPeriodFormDataWatcher() {
|
||||
if (
|
||||
!this.classTimeSlotValidityPeriodFormData.organizationalUnit
|
||||
?.value ||
|
||||
!this.classTimeSlotValidityPeriodFormData.validityPeriodFrom ||
|
||||
!this.classTimeSlotValidityPeriodFormData.validityPeriodTo
|
||||
) {
|
||||
this.classTimeSlotValidityPeriodFormData.studyPlanId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.refetchFilterableOptions();
|
||||
},
|
||||
async refetchFilterableOptions() {
|
||||
this.studyPlans = await this.getTargetedStudyPlans(
|
||||
this.classTimeSlotValidityPeriodFormData.organizationalUnit?.value,
|
||||
this.formattedValidityPeriodFrom,
|
||||
this.formattedValidityPeriodTo,
|
||||
);
|
||||
|
||||
if (this.isEditMode) {
|
||||
let isStudyPlanStillValid = this.studyPlans.some(
|
||||
(plan) =>
|
||||
plan.studienplan_id ===
|
||||
this.editedClassTimeSlotValidityPeriod.studienplan_id,
|
||||
);
|
||||
|
||||
if (!isStudyPlanStillValid) {
|
||||
let editedStudyPlan = await this.getStudyPlan(
|
||||
this.editedClassTimeSlotValidityPeriod.studienplan_id,
|
||||
);
|
||||
if (editedStudyPlan) {
|
||||
this.studyPlans.push(editedStudyPlan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let studySemestersByDates =
|
||||
await this.getStudySemestersByOrganizationalUnitAndDates(
|
||||
this.classTimeSlotValidityPeriodFormData.organizationalUnit
|
||||
?.value,
|
||||
this.formattedValidityPeriodFrom,
|
||||
this.formattedValidityPeriodTo,
|
||||
);
|
||||
|
||||
let studySemesters = new Array(
|
||||
...new Set(
|
||||
studySemestersByDates
|
||||
.map((s) => s.semester_numbers)
|
||||
.flat()
|
||||
.sort((a, b) => a - b),
|
||||
),
|
||||
);
|
||||
|
||||
this.studySemestersByNumber = studySemesters;
|
||||
if (this.classTimeSlotValidityPeriodFormData.studyPlanId) {
|
||||
let studySemestersByStudyProgramId =
|
||||
await this.getStudySemestersByStudyPlanAndDates(
|
||||
this.classTimeSlotValidityPeriodFormData.studyPlanId,
|
||||
this.formattedValidityPeriodFrom,
|
||||
this.formattedValidityPeriodTo,
|
||||
);
|
||||
studySemestersByStudyProgramId = new Array(
|
||||
...new Set(
|
||||
studySemestersByStudyProgramId
|
||||
.map((s) => s.semester_numbers)
|
||||
.flat()
|
||||
.sort((a, b) => a - b),
|
||||
),
|
||||
);
|
||||
|
||||
studySemesters = studySemestersByStudyProgramId;
|
||||
}
|
||||
|
||||
this.studySemestersByNumber = studySemesters;
|
||||
},
|
||||
async getTargetedStudyPlans(
|
||||
organizationalUnitShortCode,
|
||||
validityPeriodFrom,
|
||||
validityPeriodTo,
|
||||
) {
|
||||
if (
|
||||
!organizationalUnitShortCode ||
|
||||
!validityPeriodFrom ||
|
||||
!validityPeriodTo
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let getAllStudyPlansResponse = await this.$api.call(
|
||||
ApiStudienPlan.getStudyPlansByOrganizationalUnitAndSemesterDates(
|
||||
organizationalUnitShortCode,
|
||||
validityPeriodFrom,
|
||||
validityPeriodTo,
|
||||
),
|
||||
);
|
||||
if (getAllStudyPlansResponse.meta.status !== "success") {
|
||||
this.$fhcAlert.alertError(this.$p.t("ui", "errorFetchingStudyPlans"));
|
||||
}
|
||||
|
||||
return getAllStudyPlansResponse.data?.length
|
||||
? getAllStudyPlansResponse.data
|
||||
: [];
|
||||
},
|
||||
async getStudyPlan(studienplan_id) {
|
||||
if (!studienplan_id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let getStudyPlanResponse = await this.$api.call(
|
||||
ApiStudienPlan.getStudyPlan(studienplan_id),
|
||||
);
|
||||
if (getStudyPlanResponse.meta.status !== "success") {
|
||||
this.$fhcAlert.alertError(this.$p.t("ui", "errorFetchingStudyPlan"));
|
||||
return null;
|
||||
}
|
||||
|
||||
return getStudyPlanResponse.data ? getStudyPlanResponse.data : null;
|
||||
},
|
||||
async getStudySemestersByOrganizationalUnitAndDates(
|
||||
organizationalUnitShortCode,
|
||||
validityPeriodFrom,
|
||||
validityPeriodTo,
|
||||
) {
|
||||
if (
|
||||
!organizationalUnitShortCode ||
|
||||
!validityPeriodFrom ||
|
||||
!validityPeriodTo
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let getStudySemestersResponse = await this.$api.call(
|
||||
ApiStudienSemester.getStudySemestersByOrganizationalUnitAndDates(
|
||||
organizationalUnitShortCode,
|
||||
validityPeriodFrom,
|
||||
validityPeriodTo,
|
||||
),
|
||||
);
|
||||
if (getStudySemestersResponse.meta.status !== "success") {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingSemesters"),
|
||||
);
|
||||
}
|
||||
|
||||
return getStudySemestersResponse.data?.length
|
||||
? getStudySemestersResponse.data
|
||||
: [];
|
||||
},
|
||||
async getStudySemestersByStudyPlanAndDates(
|
||||
studyProgramId,
|
||||
validityPeriodFrom,
|
||||
validityPeriodTo,
|
||||
) {
|
||||
if (!studyProgramId || !validityPeriodFrom || !validityPeriodTo) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let getStudySemestersResponse = await this.$api.call(
|
||||
ApiStudienSemester.getStudySemestersByStudyPlanAndDates(
|
||||
studyProgramId,
|
||||
validityPeriodFrom,
|
||||
validityPeriodTo,
|
||||
),
|
||||
);
|
||||
if (getStudySemestersResponse.meta.status !== "success") {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingSemesters"),
|
||||
);
|
||||
}
|
||||
|
||||
return getStudySemestersResponse.data?.length
|
||||
? getStudySemestersResponse.data
|
||||
: [];
|
||||
},
|
||||
createClassTimeSlotValidityPeriod() {
|
||||
return this.$refs.classTimeSlotValidityPeriodData
|
||||
.call(
|
||||
ApiClassSchedule.createClassTimeSlotValidityPeriod(this.id, {
|
||||
...this.classTimeSlotValidityPeriodFormData,
|
||||
organizationalUnitShortCode:
|
||||
this.classTimeSlotValidityPeriodFormData.organizationalUnit
|
||||
?.value,
|
||||
}),
|
||||
)
|
||||
.then((response) => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
|
||||
this.$refs.classTimeSlotValidityPeriodModal.hide();
|
||||
this.resetClassTimeSlotValidityPeriodModal();
|
||||
window.scrollTo(0, 0);
|
||||
this.$emit("classTimeSlotValidityPeriodCreated");
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
updateClassTimeSlotValidityPeriod() {
|
||||
return this.$refs.classTimeSlotValidityPeriodData
|
||||
.call(
|
||||
ApiClassSchedule.updateClassTimeSlotValidityPeriod(
|
||||
this.id,
|
||||
this.classTimeSlotValidityPeriodFormData.id,
|
||||
{
|
||||
...this.classTimeSlotValidityPeriodFormData,
|
||||
organizationalUnitShortCode:
|
||||
this.classTimeSlotValidityPeriodFormData.organizationalUnit
|
||||
?.value,
|
||||
},
|
||||
),
|
||||
)
|
||||
.then((response) => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
|
||||
this.$refs.classTimeSlotValidityPeriodModal.hide();
|
||||
this.resetClassTimeSlotValidityPeriodModal();
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
this.editedClassTimeSlotValidityPeriod = null;
|
||||
|
||||
this.$emit("classTimeSlotValidityPeriodUpdated");
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
resetClassTimeSlotValidityPeriodModal() {
|
||||
this.$refs.classTimeSlotValidityPeriodData?.clearValidation();
|
||||
this.classTimeSlotValidityPeriodFormData = {
|
||||
id: null,
|
||||
organizationalUnit: null,
|
||||
studyPlanId: null,
|
||||
classTimeSlotTypeShortcode: null,
|
||||
validityPeriodFrom: null,
|
||||
validityPeriodTo: null,
|
||||
semester: null,
|
||||
description: null,
|
||||
};
|
||||
},
|
||||
filterOrganizationalUnits(event) {
|
||||
const query = event.query.toLowerCase();
|
||||
if (!query) {
|
||||
return (this.filteredOrganizationalUnits = [
|
||||
...this.dropdownParsedOrganizationalUnits,
|
||||
]);
|
||||
}
|
||||
|
||||
return (this.filteredOrganizationalUnits =
|
||||
this.dropdownParsedOrganizationalUnits.filter((unit) => {
|
||||
return unit.label.toLowerCase().includes(query);
|
||||
}));
|
||||
},
|
||||
getClassTimeSlotTypeLabel(classTimeSlotType) {
|
||||
if (!classTimeSlotType) return "";
|
||||
return this.userLanguage?.value === "English"
|
||||
? classTimeSlotType.bezeichnung_mehrsprachig[1].value
|
||||
: classTimeSlotType.bezeichnung_mehrsprachig[0].value;
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
let getAllOrganizationalUnitsResponse = await this.$api.call(
|
||||
ApiOrganizationalUnit.getAllOrganizationalUnits(),
|
||||
);
|
||||
if (getAllOrganizationalUnitsResponse.meta.status === "success") {
|
||||
this.organizationalUnits = getAllOrganizationalUnitsResponse.data.sort(
|
||||
(a, b) => a.bezeichnung.localeCompare(b.bezeichnung),
|
||||
);
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingOrganizationalUnits"),
|
||||
);
|
||||
}
|
||||
|
||||
let getAllStudyPlansResponse = await this.$api.call(
|
||||
ApiStudienPlan.getAllStudyPlans(),
|
||||
);
|
||||
if (getAllStudyPlansResponse.meta.status === "success") {
|
||||
this.studyPlans = getAllStudyPlansResponse.data;
|
||||
} else {
|
||||
this.$fhcAlert.alertError(this.$p.t("ui", "errorFetchingStudyPlans"));
|
||||
}
|
||||
|
||||
let getAllClassTimeSlotTypesResponse = await this.$api.call(
|
||||
ApiClassSchedule.getAllClassScheduleTypes("filter[aktiv]=true"),
|
||||
);
|
||||
if (getAllClassTimeSlotTypesResponse.meta.status === "success") {
|
||||
this.classTimeSlotTypes = getAllClassTimeSlotTypesResponse.data.map(
|
||||
(type) => {
|
||||
let descriptions = [{
|
||||
lang: "de",
|
||||
value: type.bezeichnung_mehrsprachig[0] || "",
|
||||
}, {
|
||||
lang: "en",
|
||||
value: type.bezeichnung_mehrsprachig[1] || "",
|
||||
}];
|
||||
|
||||
return {
|
||||
...type,
|
||||
bezeichnung_mehrsprachig: descriptions,
|
||||
};
|
||||
},
|
||||
);
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingClassScheduleTimeSlotTypes"),
|
||||
);
|
||||
}
|
||||
},
|
||||
template: /*html*/ `
|
||||
<bs-modal ref="classTimeSlotValidityPeriodModal" @hideBsModal="() => { $emit('hideBsModal'); resetClassTimeSlotValidityPeriodModal(); }" size="md">
|
||||
<template #title>
|
||||
<p v-if="!classTimeSlotValidityPeriodFormData.id" class="fw-bold mt-3">{{$p.t('ui', 'addClassTimeSlotValidityPeriodModalTitle')}}</p>
|
||||
<p v-else class="fw-bold mt-3">{{$p.t('ui', 'editClassTimeSlotValidityPeriodModalTitle')}}</p>
|
||||
</template>
|
||||
<core-form class="row g-3" ref="classTimeSlotValidityPeriodData">
|
||||
<form-validation />
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
v-model="classTimeSlotValidityPeriodFormData.organizationalUnit"
|
||||
:label="$capitalize($p.t('lehre/organisationseinheit')) + ' *'"
|
||||
:suggestions="filteredOrganizationalUnits"
|
||||
:optionValue="(option) => option.value"
|
||||
:optionLabel="(option) => option.label"
|
||||
@complete="filterOrganizationalUnits"
|
||||
dropdown
|
||||
forceSelection
|
||||
type="autocomplete"
|
||||
name="organizationalUnitShortCode"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-12 mb-3">
|
||||
<label>{{$p.t('ui', 'validityPeriod')}}</label>
|
||||
</div>
|
||||
<div class="col">
|
||||
<form-input
|
||||
v-model="classTimeSlotValidityPeriodFormData.validityPeriodFrom"
|
||||
:label="$p.t('ui/von') + ' *'"
|
||||
:teleport="true"
|
||||
:enable-time-picker="false"
|
||||
type="datePicker"
|
||||
name="validityPeriodFrom"
|
||||
format="dd.MM.yyyy"
|
||||
auto-apply
|
||||
/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<form-input
|
||||
v-model="classTimeSlotValidityPeriodFormData.validityPeriodTo"
|
||||
:label="$p.t('global/bis') + ' *'"
|
||||
:teleport="true"
|
||||
:enable-time-picker="false"
|
||||
type="datePicker"
|
||||
name="validityPeriodTo"
|
||||
format="dd.MM.yyyy"
|
||||
auto-apply
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
v-model="classTimeSlotValidityPeriodFormData.studyPlanId"
|
||||
:label="$p.t('lehre/studienplan')"
|
||||
:disabled="isStudyPlanSelectDisabled"
|
||||
type="select"
|
||||
name="studyPlan"
|
||||
>
|
||||
<option :value="null"> - </option>
|
||||
<option
|
||||
v-for="studyPlan in studyPlans"
|
||||
:key="studyPlan.studienplan_id"
|
||||
:value="studyPlan.studienplan_id"
|
||||
>
|
||||
{{studyPlan.bezeichnung}}
|
||||
</option>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="select"
|
||||
id="ausbildungssemester"
|
||||
name="semester"
|
||||
:disabled="isStudyPlanSelectDisabled"
|
||||
:label="$p.t('lehre', 'ausbildungssemester')"
|
||||
v-model="classTimeSlotValidityPeriodFormData.semester"
|
||||
>
|
||||
<option
|
||||
v-for="studySemester in studySemestersByNumber"
|
||||
:key="studySemester"
|
||||
:value="studySemester"
|
||||
>
|
||||
{{studySemester}}
|
||||
</option>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="select"
|
||||
name="classTimeSlotType"
|
||||
:label="$p.t('ui/classTimeSlotType')"
|
||||
v-model="classTimeSlotValidityPeriodFormData.classTimeSlotTypeShortcode"
|
||||
>
|
||||
<option :value="null"> - </option>
|
||||
<option
|
||||
v-for="classTimeSlotType in classTimeSlotTypes"
|
||||
:key="classTimeSlotType.unterrichtszeitentyp_kurzbz"
|
||||
:value="classTimeSlotType.unterrichtszeitentyp_kurzbz"
|
||||
>
|
||||
{{ getClassTimeSlotTypeLabel(classTimeSlotType) }}
|
||||
</option>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="textarea"
|
||||
name="beschreibung"
|
||||
:label="$p.t('global/beschreibung')"
|
||||
v-model="classTimeSlotValidityPeriodFormData.description"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
</core-form>
|
||||
|
||||
<template #footer>
|
||||
<button v-if="!classTimeSlotValidityPeriodFormData.id" type="button" class="btn btn-primary" @click="createClassTimeSlotValidityPeriod">{{$p.t('ui', 'speichern')}}</button>
|
||||
<button v-else type="button" class="btn btn-primary" @click="updateClassTimeSlotValidityPeriod">{{$p.t('ui', 'btnAktualisieren')}}</button>
|
||||
</template>
|
||||
</bs-modal>
|
||||
`,
|
||||
};
|
||||
@@ -0,0 +1,317 @@
|
||||
import ApiClassSchedule from "../../../js/api/factory/classSchedule.js";
|
||||
import ApiClassroomHour from "../../../js/api/factory/classroomHour.js";
|
||||
|
||||
import BsModal from "../Bootstrap/Modal.js";
|
||||
import ClassScheduleValidityPeriodForm from "./ClassScheduleValidityPeriodForm.js";
|
||||
import ClassScheduleValidityPeriodModal from "./ClassScheduleValidityPeriodModal.js";
|
||||
import ClassScheduleCalendarSelector from "./ClassScheduleCalendarSelector.js";
|
||||
|
||||
export default {
|
||||
name: "ClassScheduleValidityPeriodOverview",
|
||||
components: {
|
||||
BsModal,
|
||||
ClassScheduleValidityPeriodForm,
|
||||
ClassScheduleValidityPeriodModal,
|
||||
ClassScheduleCalendarSelector,
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
classroomHours: [],
|
||||
isClassTimeSlotFormVisible: false,
|
||||
classTimeSlotValidityPeriodId: null,
|
||||
classTimeSlotValidityPeriod: null,
|
||||
areClassTimeSlotsLoaded: false,
|
||||
classTimeSlots: [],
|
||||
classTimeSlotTypes: [],
|
||||
editedClassTimeSlots: [],
|
||||
isClassTimeSlotValidityPeriodModalVisible: false,
|
||||
editedClassTimeSlotValidityPeriodId: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classScheduleValidityPeriodStartDate() {
|
||||
if (!this.classTimeSlotValidityPeriod) return null;
|
||||
|
||||
let dateParts = this.classTimeSlotValidityPeriod.gueltig_von
|
||||
.split("-")
|
||||
.reverse();
|
||||
return dateParts.join(".");
|
||||
},
|
||||
classScheduleValidityPeriodEndDate() {
|
||||
if (!this.classTimeSlotValidityPeriod) return null;
|
||||
let dateParts = this.classTimeSlotValidityPeriod.gueltig_bis
|
||||
.split("-")
|
||||
.reverse();
|
||||
return dateParts.join(".");
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async fetchClassTimeValidityPeriod() {
|
||||
let getClassTimeValidityPeriodResponse = await this.$api.call(
|
||||
ApiClassSchedule.getClassTimeValidityPeriod(
|
||||
this.classTimeSlotValidityPeriodId,
|
||||
),
|
||||
);
|
||||
|
||||
if (getClassTimeValidityPeriodResponse.meta.status === "success") {
|
||||
this.classTimeSlotValidityPeriod =
|
||||
getClassTimeValidityPeriodResponse.data[0];
|
||||
|
||||
if (!this.classTimeSlotValidityPeriod) {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "classTimeSlotValidityPeriodNotFound"),
|
||||
);
|
||||
this.$router.push({ name: "overview" });
|
||||
}
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingClassScheduleValidityPeriod"),
|
||||
);
|
||||
}
|
||||
},
|
||||
async fetchClassTimeSlots() {
|
||||
let getClassTimeSlotsForValidityPeriodResponse = await this.$api.call(
|
||||
ApiClassSchedule.getClassTimeSlotsForValidityPeriod(
|
||||
this.classTimeSlotValidityPeriodId,
|
||||
),
|
||||
);
|
||||
if (
|
||||
getClassTimeSlotsForValidityPeriodResponse.meta.status === "success"
|
||||
) {
|
||||
this.classTimeSlots = getClassTimeSlotsForValidityPeriodResponse.data;
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t(
|
||||
"ui",
|
||||
"errorFetchingClassScheduleTimeSlotForValidityPeriod",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
this.areClassTimeSlotsLoaded = true;
|
||||
},
|
||||
showClassTimeSlotForm() {
|
||||
this.isClassTimeSlotFormVisible = true;
|
||||
},
|
||||
async editClassTimeSlotsForValidityPeriod() {
|
||||
await this.fetchClassTimeSlots();
|
||||
|
||||
this.editedClassTimeSlots =
|
||||
this.classTimeSlots.map((slot) => {
|
||||
return {
|
||||
...slot,
|
||||
id: slot.unterrichtszeit_id,
|
||||
startTime: slot.uhrzeit_von,
|
||||
endTime: slot.uhrzeit_bis,
|
||||
classTimeSlotTypeShortcode: slot.unterrichtszeitentyp_kurzbz,
|
||||
};
|
||||
}) || [];
|
||||
|
||||
this.showClassTimeSlotForm();
|
||||
},
|
||||
deleteClassTimeSlotsForValidityPeriod() {
|
||||
let isDeletionConfirmed = confirm(
|
||||
this.$p.t("ui", "confirmDeleteClassTimeSlotsForGroup"),
|
||||
);
|
||||
if (!isDeletionConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.$api
|
||||
.call(
|
||||
ApiClassSchedule.deleteClassTimeSlotsForValidityPeriod(
|
||||
this.id,
|
||||
this.classTimeSlotValidityPeriodId,
|
||||
),
|
||||
)
|
||||
.then((response) => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successDelete"));
|
||||
this.classTimeSlots = [];
|
||||
this.fetchClassTimeSlots();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
getClassTimeSlotType(classTimeSlot) {
|
||||
let classTimeSlotType = this.classTimeSlotTypes.find(
|
||||
(type) =>
|
||||
type.unterrichtszeitentyp_kurzbz ===
|
||||
classTimeSlot.unterrichtszeitentyp_kurzbz,
|
||||
);
|
||||
|
||||
return classTimeSlotType;
|
||||
},
|
||||
getClassTimeSlotBackgroundColor(classTimeSlot) {
|
||||
let classTimeSlotType = this.classTimeSlotTypes.find(
|
||||
(type) =>
|
||||
type.unterrichtszeitentyp_kurzbz ===
|
||||
classTimeSlot.unterrichtszeitentyp_kurzbz,
|
||||
);
|
||||
|
||||
return classTimeSlotType ? classTimeSlotType.hintergrundfarbe : "#fff";
|
||||
},
|
||||
editClassTimeSlotValidityPeriod(classTimeSlotValidityPeriodId) {
|
||||
this.editedClassTimeSlotValidityPeriodId = classTimeSlotValidityPeriodId;
|
||||
},
|
||||
deleteClassTimeSlotValidityPeriod(classTimeSlotValidityPeriodId) {
|
||||
let isDeletionConfirmed = confirm(
|
||||
this.$p.t("ui", "deleteClassTimeSlotValidityPeriodConfirmation"),
|
||||
);
|
||||
if (!isDeletionConfirmed) return;
|
||||
|
||||
return this.$api
|
||||
.call(
|
||||
ApiClassSchedule.deleteClassTimeSlotValidityPeriod(
|
||||
this.id,
|
||||
classTimeSlotValidityPeriodId,
|
||||
),
|
||||
)
|
||||
.then((response) => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successDelete"));
|
||||
this.$router.push({ name: "overview" });
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
resetClassTimeSlotValidityPeriodModal() {
|
||||
this.isClassTimeSlotValidityPeriodModalVisible = false;
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
this.classTimeSlotValidityPeriodId =
|
||||
this.$route.params.classTimeSlotValidityPeriodId;
|
||||
|
||||
await this.fetchClassTimeValidityPeriod();
|
||||
|
||||
let getAllClassTimeSlotTypesResponse = await this.$api.call(
|
||||
ApiClassSchedule.getAllClassScheduleTypes("filter[aktiv]=true"),
|
||||
);
|
||||
if (getAllClassTimeSlotTypesResponse.meta.status === "success") {
|
||||
this.classTimeSlotTypes = getAllClassTimeSlotTypesResponse.data.map(
|
||||
(type) => {
|
||||
let descriptions = [{
|
||||
lang: "de",
|
||||
value: type.bezeichnung_mehrsprachig[0] || "",
|
||||
}, {
|
||||
lang: "en",
|
||||
value: type.bezeichnung_mehrsprachig[1] || "",
|
||||
}];
|
||||
return {
|
||||
...type,
|
||||
bezeichnung_mehrsprachig: descriptions,
|
||||
};
|
||||
},
|
||||
);
|
||||
} else {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("ui", "errorFetchingClassScheduleTimeSlotTypes"),
|
||||
);
|
||||
}
|
||||
|
||||
let getAllClassroomHoursResponse = await this.$api.call(
|
||||
ApiClassroomHour.getAllClassroomHours(),
|
||||
);
|
||||
if (getAllClassroomHoursResponse.meta.status === "success") {
|
||||
this.classroomHours = getAllClassroomHoursResponse.data.map((hour) => {
|
||||
return {
|
||||
...hour,
|
||||
beginn: hour.beginn.substring(0, 5),
|
||||
ende: hour.ende.substring(0, 5),
|
||||
};
|
||||
});
|
||||
} else {
|
||||
this.$fhcAlert.alertError(this.$p.t("ui", "errorFetchingClassroomHours"));
|
||||
}
|
||||
|
||||
this.fetchClassTimeSlots();
|
||||
},
|
||||
template: /* html */ `
|
||||
<div class="container mt-4">
|
||||
<div class='mb-5'>
|
||||
<div class="d-flex align-items-center justify-content-between mb-2">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<h1 class='m-0'>
|
||||
{{ $p.t("ui", "classScheduleValidityPeriodOverviewHeading") }}
|
||||
</h1>
|
||||
<span class="m-0 badge bg-secondary">{{ classTimeSlotValidityPeriod?.orgform_kurzbz }}</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<a
|
||||
@click="editClassTimeSlotValidityPeriod(classTimeSlotValidityPeriodId)"
|
||||
class="btn btn-link fs-3 p-0">
|
||||
<i class="fa fa-edit"></i></a>
|
||||
<a @click="deleteClassTimeSlotValidityPeriod(classTimeSlotValidityPeriodId)" class="btn btn-link text-danger fs-3 p-0"><i class="fa fa-trash"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<h2>{{ classScheduleValidityPeriodStartDate }} - {{ classScheduleValidityPeriodEndDate }}</h2>
|
||||
<h4 class="text-capitalize">{{ $p.t("lehre", "organisationseinheit") }}: {{ classTimeSlotValidityPeriod?.oe_bezeichnung }} ({{ classTimeSlotValidityPeriod?.oe_organisationseinheittyp_kurzbz }})</h4>
|
||||
<h4 class="text-capitalize">{{ $p.t("lehre", "studienplan") }}: {{ classTimeSlotValidityPeriod?.studienplan_bezeichnung }}</h4>
|
||||
<h5 class="text-capitalize">{{ $p.t("lehre", "ausbildungssemester") }}:
|
||||
<span class="fw-normal">{{ classTimeSlotValidityPeriod?.ausbildungssemester }}</span>
|
||||
</h5>
|
||||
<h5 class="text-capitalize">{{ $p.t("global", "anmerkung") }}:
|
||||
<span class="fw-normal">{{ classTimeSlotValidityPeriod?.anmerkung }}</span>
|
||||
</h5>
|
||||
</div>
|
||||
<div>
|
||||
<div v-if='!isClassTimeSlotFormVisible && !classTimeSlots.length && areClassTimeSlotsLoaded' class="col-12 d-flex justify-content-end">
|
||||
<button type="button" class="btn btn-primary" @click="showClassTimeSlotForm">{{$p.t('ui', 'addClassTimeSlotButton')}}</button>
|
||||
</div>
|
||||
<class-schedule-validity-period-form
|
||||
v-if="isClassTimeSlotFormVisible"
|
||||
:class-time-slot-types="this.classTimeSlotTypes"
|
||||
:classroom-hours="this.classroomHours.map(hour => hour.beginn + '-' + hour.ende)"
|
||||
:class-time-slot-validity-period="classTimeSlotValidityPeriod"
|
||||
:edited-class-time-slots="editedClassTimeSlots"
|
||||
@classTimeSlotsCreated="() => { isClassTimeSlotFormVisible = false; this.areClassTimeSlotsLoaded = false; this.classTimeSlots = []; fetchClassTimeSlots(); this.editedClassTimeSlots = []; }"
|
||||
@classTimeSlotsEdited="() => { isClassTimeSlotFormVisible = false; this.areClassTimeSlotsLoaded = false; this.classTimeSlots = []; fetchClassTimeSlots(); this.editedClassTimeSlots = []; }"
|
||||
@hideForm="() => { isClassTimeSlotFormVisible = false; this.areClassTimeSlotsLoaded = false; this.classTimeSlots = []; fetchClassTimeSlots(); this.editedClassTimeSlots = []; }"
|
||||
class="mb-4"
|
||||
/>
|
||||
<div v-if="!isClassTimeSlotFormVisible">
|
||||
<h4>{{ $p.t("ui", "classScheduleValidityPeriodTimeSlots") }}</h4>
|
||||
</div>
|
||||
<transition>
|
||||
<div v-if="classTimeSlots && Object.keys(classTimeSlots).length > 0 && !isClassTimeSlotFormVisible">
|
||||
<div class="col-12 d-flex align-items-center justify-content-end gap-2">
|
||||
<a class="ml-auto" @click="editClassTimeSlotsForValidityPeriod"><i class="fa fa-edit fs-5"></i></a>
|
||||
<a class="ml-auto" @click="deleteClassTimeSlotsForValidityPeriod"><i class="fa fa-trash text-danger fs-5"></i></a>
|
||||
</div>
|
||||
<div class="row border-top rounded p-2 mt-4 mb-2 pt-1 pb-5">
|
||||
<class-schedule-calendar-selector
|
||||
:classroom-hours="this.classroomHours.map(hour => hour.beginn + '-' + hour.ende)"
|
||||
:class-time-slot-types="this.classTimeSlotTypes"
|
||||
:edited-overlays="classTimeSlots.map((slot) => {
|
||||
return {
|
||||
databaseId: slot.id,
|
||||
id: slot.identifier,
|
||||
weekday: parseInt(slot.wochentag) + 1,
|
||||
type: slot.unterrichtszeitentyp_kurzbz,
|
||||
startTime: slot.uhrzeit_von,
|
||||
endTime: slot.uhrzeit_bis,
|
||||
};
|
||||
})"
|
||||
:isPreviewMode="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<div v-if="!classTimeSlots || Object.keys(classTimeSlots).length === 0" class="d-flex align-items-center justify-content-center border rounded p-4 mt-4">
|
||||
<p class="m-0">{{ $p.t("ui", "noClassScheduleValidityPeriodTimeSlotsFound") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<class-schedule-validity-period-modal
|
||||
:isVisible="isClassTimeSlotValidityPeriodModalVisible"
|
||||
:editedClassTimeSlotValidityPeriodId="editedClassTimeSlotValidityPeriodId"
|
||||
@hideBsModal="() => { resetClassTimeSlotValidityPeriodModal(); editedClassTimeSlotValidityPeriodId = null; }"
|
||||
@classTimeSlotValidityPeriodUpdated="() => {
|
||||
resetClassTimeSlotValidityPeriodModal();
|
||||
this.editedClassTimeSlotValidityPeriodId = null;
|
||||
fetchClassTimeValidityPeriod();
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
@@ -0,0 +1,112 @@
|
||||
import ClassScheduleCalendarSelector from "./ClassScheduleCalendarSelector.js";
|
||||
import ApiClassroomHour from "../../../js/api/factory/classroomHour.js";
|
||||
|
||||
export default {
|
||||
name: "ClassScheduleValidityPeriodPreview",
|
||||
components: {
|
||||
ClassScheduleCalendarSelector,
|
||||
},
|
||||
props: {
|
||||
classScheduleValidityPeriod: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
classTimeSlots: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
classTimeSlotTypes: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
classRoomHours: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classScheduleValidityPeriodStartDate() {
|
||||
if (!this.$props.classScheduleValidityPeriod) return null;
|
||||
|
||||
let dateParts = this.$props.classScheduleValidityPeriod.gueltig_von
|
||||
.split("-")
|
||||
.reverse();
|
||||
return dateParts.join(".");
|
||||
},
|
||||
classScheduleValidityPeriodEndDate() {
|
||||
if (!this.$props.classScheduleValidityPeriod) return null;
|
||||
let dateParts = this.$props.classScheduleValidityPeriod.gueltig_bis
|
||||
.split("-")
|
||||
.reverse();
|
||||
return dateParts.join(".");
|
||||
},
|
||||
classScheduleValidityPeriodStudyPlan() {
|
||||
return this.$props.classScheduleValidityPeriod.studienplan_bezeichnung;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
showClassScheduleValidityPeriod(classScheduleValidityPeriodId) {
|
||||
this.$router.push({
|
||||
name: "validityPeriodOverview",
|
||||
params: {
|
||||
classTimeSlotValidityPeriodId: classScheduleValidityPeriodId,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
let getAllClassroomHoursResponse = await this.$api.call(
|
||||
ApiClassroomHour.getAllClassroomHours(),
|
||||
);
|
||||
if (getAllClassroomHoursResponse.meta.status === "success") {
|
||||
this.classroomHours = getAllClassroomHoursResponse.data.map((hour) => {
|
||||
return {
|
||||
...hour,
|
||||
beginn: hour.beginn.substring(0, 5),
|
||||
ende: hour.ende.substring(0, 5),
|
||||
};
|
||||
});
|
||||
} else {
|
||||
this.$fhcAlert.alertError(this.$p.t("ui", "errorFetchingClassroomHours"));
|
||||
}
|
||||
},
|
||||
template: /* html */ `
|
||||
<div class="container mt-4">
|
||||
<div class='py-3 d-flex align-items-center justify-content-between'>
|
||||
<div>
|
||||
<h2>{{ classScheduleValidityPeriodStartDate }} - {{ classScheduleValidityPeriodEndDate }}</h2>
|
||||
<h4>{{ classScheduleValidityPeriodStudyPlan }}</h4>
|
||||
</div>
|
||||
<a
|
||||
@click="showClassScheduleValidityPeriod($props.classScheduleValidityPeriod.unterrichtszeitengueltigkeit_id)"
|
||||
class="ml-auto btn btn-link"
|
||||
><i class="fa fa-eye fs-5"></i></a>
|
||||
</div>
|
||||
<div class='py-3 mb-4'>
|
||||
<div v-if="$props.classTimeSlots && $props.classTimeSlots.length > 0">
|
||||
<div class="row border-top rounded pt-1 pb-5">
|
||||
<class-schedule-calendar-selector
|
||||
:classroom-hours="this.classroomHours.map(hour => hour.beginn + '-' + hour.ende)"
|
||||
:class-time-slot-types="this.classTimeSlotTypes"
|
||||
:edited-overlays="$props.classTimeSlots.map((slot) => {
|
||||
return {
|
||||
databaseId: slot.id,
|
||||
id: slot.identifier,
|
||||
weekday: parseInt(slot.wochentag) + 1,
|
||||
type: slot.unterrichtszeitentyp_kurzbz,
|
||||
startTime: slot.uhrzeit_von,
|
||||
endTime: slot.uhrzeit_bis,
|
||||
};
|
||||
})"
|
||||
:isPreviewMode="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="d-flex align-items-center justify-content-center border rounded p-2">
|
||||
<p class="m-0">{{ $p.t("ui", "noClassScheduleValidityPeriodTimeSlotsFound") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
@@ -30,7 +30,8 @@ export default {
|
||||
function onStart(evt) {
|
||||
const value = el.dataset.fhcDraggableValue;
|
||||
if (value) {
|
||||
setTransferData(evt, JSON.parse(value), true);
|
||||
let disableImage = binding.modifiers?.noImage === true;
|
||||
setTransferData(evt, JSON.parse(value), !disableImage);
|
||||
if (el.dataset.fhcEffectAllowed)
|
||||
evt.dataTransfer.effectAllowed = el.dataset.fhcEffectAllowed;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export function formatDate(d) {
|
||||
// parameter is of type Date
|
||||
if(d instanceof Date)
|
||||
{
|
||||
if (isNaN(date.valueOf())) {
|
||||
if (isNaN(d.valueOf())) {
|
||||
return 'N/A';
|
||||
}
|
||||
// if the date is an invalid string then creating a date from the string will fail and N/A is returned
|
||||
|
||||
@@ -30,6 +30,9 @@ const TYPE_DEFINITION = {
|
||||
prestudent: {
|
||||
id: "prestudent_id",
|
||||
dragIcon: "fa-solid fa-user-graduate text-muted"
|
||||
},
|
||||
calendar_selector_overlay: {
|
||||
id: "calendar_selector_overlay_id",
|
||||
}
|
||||
// TODO: IMPLEMENT OTHER TYPES
|
||||
};
|
||||
|
||||
@@ -93,6 +93,7 @@ require_once('dbupdate_3.4/62889_reihungstest_ueberwachung_mit_constructor.php')
|
||||
require_once('dbupdate_3.4/71399_dashboard_update_widget_paths.php');
|
||||
require_once('dbupdate_3.4/71645_studvw_messagetab_ladezeit.php');
|
||||
require_once('dbupdate_3.4/71566_studienordnungsdokument_neuer_organisationseinheitstyp_programm.php');
|
||||
require_once('dbupdate_3.4/76031_unterrichtszeiten_der_studiengänge.php');
|
||||
|
||||
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
|
||||
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
<?php
|
||||
|
||||
if($result = @$db->db_query("SELECT 1 FROM system.tbl_berechtigung WHERE berechtigung_kurzbz='lehre/unterrichtszeiten_gk' LIMIT 1"))
|
||||
{
|
||||
if($db->db_num_rows($result)==0)
|
||||
{
|
||||
$qry = "
|
||||
INSERT INTO system.tbl_berechtigung(berechtigung_kurzbz, beschreibung) VALUES
|
||||
('lehre/unterrichtszeiten_gk','Unterrichtszeiten Gültigkeit')
|
||||
";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>system.tbl_berechtigung '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo ' system.tbl_berechtigung: lehre/unterrichtszeiten_gk permissions inserted<br>';
|
||||
}
|
||||
}
|
||||
|
||||
if($result = @$db->db_query("SELECT 1 FROM system.tbl_berechtigung WHERE berechtigung_kurzbz='lehre/unterrichtszeiten_typ' LIMIT 1"))
|
||||
{
|
||||
if($db->db_num_rows($result)==0)
|
||||
{
|
||||
$qry = "
|
||||
INSERT INTO system.tbl_berechtigung(berechtigung_kurzbz, beschreibung) VALUES
|
||||
('lehre/unterrichtszeiten_typ','Unterrichtszeiten Typ')
|
||||
";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>system.tbl_berechtigung '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo ' system.tbl_berechtigung: lehre/unterrichtszeiten_typ permissions inserted<br>';
|
||||
}
|
||||
}
|
||||
|
||||
if(!$result = @$db->db_query("SELECT 1 FROM lehre.tbl_unterrichtszeiten LIMIT 1"))
|
||||
{
|
||||
$qry = '
|
||||
CREATE TABLE lehre.tbl_unterrichtszeiten (
|
||||
"unterrichtszeit_id" INTEGER NOT NULL,
|
||||
"wochentag" INTEGER NOT NULL,
|
||||
"uhrzeit_von" TIME NOT NULL,
|
||||
"uhrzeit_bis" TIME NOT NULL,
|
||||
"unterrichtszeitentyp_kurzbz" VARCHAR(32) NOT NULL,
|
||||
"unterrichtszeitengueltigkeit_id" INTEGER NOT NULL,
|
||||
"insertamum" TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
"insertvon" VARCHAR(32),
|
||||
"updateamum" TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
"updatevon" VARCHAR(32),
|
||||
CONSTRAINT pk_unterrichtszeit_id PRIMARY KEY("unterrichtszeit_id")
|
||||
);';
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>lehre.tbl_unterrichtszeiten table created';
|
||||
|
||||
$db->db_query('CREATE SEQUENCE IF NOT EXISTS lehre.seq_tbl_unterrichtszeiten_unterrichtszeit_id
|
||||
INCREMENT BY 1
|
||||
NO MAXVALUE
|
||||
NO MINVALUE
|
||||
CACHE 1;');
|
||||
|
||||
$db->db_query("ALTER TABLE lehre.tbl_unterrichtszeiten ALTER COLUMN unterrichtszeit_id SET DEFAULT nextval('lehre.seq_tbl_unterrichtszeiten_unterrichtszeit_id');");
|
||||
|
||||
|
||||
$qry = 'GRANT SELECT ON TABLE lehre.tbl_unterrichtszeiten TO web;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>web</strong> on lehre.tbl_unterrichtszeiten';
|
||||
|
||||
$qry = 'GRANT USAGE ON lehre.seq_tbl_unterrichtszeiten_unterrichtszeit_id TO web;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>web</strong> on lehre.tbl_unterrichtszeiten';
|
||||
|
||||
|
||||
$qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE lehre.tbl_unterrichtszeiten TO vilesci;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on lehre.tbl_unterrichtszeiten';
|
||||
|
||||
$qry = 'GRANT USAGE, INSERT ON lehre.seq_tbl_unterrichtszeiten_unterrichtszeit_id TO vilesci;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on lehre.tbl_unterrichtszeiten';
|
||||
|
||||
$qry = 'GRANT USAGE, UPDATE ON lehre.seq_tbl_unterrichtszeiten_unterrichtszeit_id TO vilesci;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on lehre.tbl_unterrichtszeiten';
|
||||
}
|
||||
|
||||
if(!$result = @$db->db_query("SELECT 1 FROM lehre.tbl_unterrichtszeiten_typ LIMIT 1"))
|
||||
{
|
||||
$qry = '
|
||||
CREATE TABLE lehre.tbl_unterrichtszeiten_typ (
|
||||
"unterrichtszeitentyp_kurzbz" VARCHAR(32) NOT NULL,
|
||||
"bezeichnung_mehrsprachig" TEXT[] NOT NULL,
|
||||
"aktiv" BOOLEAN DEFAULT true,
|
||||
"hintergrundfarbe" VARCHAR(7),
|
||||
"is_default" BOOLEAN DEFAULT false,
|
||||
"insertamum" TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
"insertvon" VARCHAR(32),
|
||||
"updateamum" TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
"updatevon" VARCHAR(32),
|
||||
CONSTRAINT pk_unterrichtszeitentyp_kurzbz PRIMARY KEY("unterrichtszeitentyp_kurzbz")
|
||||
);';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_typ: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>lehre.tbl_unterrichtszeiten_typ table created';
|
||||
|
||||
$db->db_query('CREATE SEQUENCE IF NOT EXISTS lehre.seq_tbl_unterrichtszeiten_typ_unterrichtszeitentyp_kurzbz
|
||||
INCREMENT BY 1
|
||||
NO MAXVALUE
|
||||
NO MINVALUE
|
||||
CACHE 1;');
|
||||
|
||||
$db->db_query("ALTER TABLE lehre.tbl_unterrichtszeiten_typ ALTER COLUMN unterrichtszeitentyp_kurzbz SET DEFAULT nextval('lehre.seq_tbl_unterrichtszeiten_typ_unterrichtszeitentyp_kurzbz');");
|
||||
|
||||
$qry = 'GRANT SELECT ON TABLE lehre.tbl_unterrichtszeiten_typ TO web;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_typ: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>web</strong> on lehre.tbl_unterrichtszeiten_typ';
|
||||
|
||||
$qry = 'GRANT USAGE ON lehre.seq_tbl_unterrichtszeiten_typ_unterrichtszeitentyp_kurzbz TO web;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_typ: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>web</strong> on lehre.tbl_unterrichtszeiten_typ';
|
||||
|
||||
|
||||
$qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE lehre.tbl_unterrichtszeiten_typ TO vilesci;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_typ: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on lehre.tbl_unterrichtszeiten_typ';
|
||||
|
||||
$qry = 'GRANT USAGE, INSERT ON lehre.seq_tbl_unterrichtszeiten_typ_unterrichtszeitentyp_kurzbz TO vilesci;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_typ: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on lehre.tbl_unterrichtszeiten_typ';
|
||||
|
||||
$qry = 'GRANT USAGE, UPDATE ON lehre.seq_tbl_unterrichtszeiten_typ_unterrichtszeitentyp_kurzbz TO vilesci;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_typ: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on lehre.tbl_unterrichtszeiten_typ';
|
||||
|
||||
|
||||
$qry = "
|
||||
INSERT INTO lehre.tbl_unterrichtszeiten_typ (unterrichtszeitentyp_kurzbz, bezeichnung_mehrsprachig, aktiv, hintergrundfarbe, is_default) VALUES
|
||||
('unterrichtszeiten', ARRAY['Unterrichtszeiten', 'Teaching Times'], 't', '#FFFFFF', 'f'),
|
||||
('vorlesungen', ARRAY['Vorlesung', 'Lecture'], 't', '#FF8A8A', 't'),
|
||||
('backuptage', ARRAY['Übung', 'Exercise'], 't', '#8AFF8A', 'f'),
|
||||
('ausgleichswochen', ARRAY['Ausgleichswochen', 'Compensation Weeks'], 't', '#8A8AFF', 'f'),
|
||||
('prüfungswochen', ARRAY['Prüfungswochen', 'Exam Weeks'], 't', '#FFFF8A', 'f');
|
||||
";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_typ seeders: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Seeded lehre.tbl_unterrichtszeiten_typ with main class time slot types';
|
||||
|
||||
}
|
||||
|
||||
if(!$result = @$db->db_query("SELECT 1 FROM lehre.tbl_unterrichtszeiten_gueltigkeit LIMIT 1"))
|
||||
{
|
||||
$qry = '
|
||||
CREATE TABLE lehre.tbl_unterrichtszeiten_gueltigkeit (
|
||||
"unterrichtszeitengueltigkeit_id" BIGINT NOT NULL,
|
||||
"gueltig_von" DATE NOT NULL,
|
||||
"gueltig_bis" DATE NOT NULL,
|
||||
"oe_kurzbz" VARCHAR(32) NOT NULL,
|
||||
"ausbildungssemester" SMALLINT,
|
||||
"anmerkung" TEXT,
|
||||
"unterrichtszeitentyp_kurzbz" VARCHAR(32),
|
||||
"studienplan_id" INTEGER,
|
||||
"insertamum" TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
"insertvon" VARCHAR(32),
|
||||
"updateamum" TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
||||
"updatevon" VARCHAR(32),
|
||||
CONSTRAINT pk_unterrichtszeitengueltigkeit_id PRIMARY KEY("unterrichtszeitengueltigkeit_id")
|
||||
);';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_gueltigkeit: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>lehre.tbl_unterrichtszeiten_gueltigkeit table created';
|
||||
|
||||
$db->db_query('CREATE SEQUENCE IF NOT EXISTS lehre.seq_tbl_unterrichtszeiten_gueltigkeit_unterrichtszeitengueltigkeit_id
|
||||
INCREMENT BY 1
|
||||
NO MAXVALUE
|
||||
NO MINVALUE
|
||||
CACHE 1;');
|
||||
|
||||
$db->db_query("ALTER TABLE lehre.tbl_unterrichtszeiten_gueltigkeit ALTER COLUMN unterrichtszeitengueltigkeit_id SET DEFAULT nextval('lehre.seq_tbl_unterrichtszeiten_gueltigkeit_unterrichtszeitengueltigkeit_id');");
|
||||
|
||||
$qry = 'GRANT SELECT ON TABLE lehre.tbl_unterrichtszeiten_gueltigkeit TO web;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_gueltigkeit: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>web</strong> on lehre.tbl_unterrichtszeiten_gueltigkeit';
|
||||
|
||||
$qry = 'GRANT USAGE ON lehre.seq_tbl_unterrichtszeiten_gueltigkeit_unterrichtszeitengueltigkeit_id TO web;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_gueltigkeit: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>web</strong> on lehre.tbl_unterrichtszeiten_gueltigkeit';
|
||||
|
||||
|
||||
$qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE lehre.tbl_unterrichtszeiten_gueltigkeit TO vilesci;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_gueltigkeit: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on lehre.tbl_unterrichtszeiten_gueltigkeit';
|
||||
|
||||
$qry = 'GRANT USAGE, INSERT ON lehre.seq_tbl_unterrichtszeiten_gueltigkeit_unterrichtszeitengueltigkeit_id TO vilesci;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_gueltigkeit: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on lehre.tbl_unterrichtszeiten_gueltigkeit';
|
||||
|
||||
$qry = 'GRANT USAGE, UPDATE ON lehre.seq_tbl_unterrichtszeiten_gueltigkeit_unterrichtszeitengueltigkeit_id TO vilesci;';
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_gueltigkeit: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on lehre.tbl_unterrichtszeiten_gueltigkeit';
|
||||
}
|
||||
|
||||
|
||||
|
||||
$result = $db->db_query("SELECT constraint_name FROM information_schema.table_constraints
|
||||
WHERE table_name='tbl_unterrichtszeiten' AND constraint_type='FOREIGN KEY' AND constraint_name='fk_unterrichtszeitentyp_kurzbz'");
|
||||
if($db->db_num_rows($result)==0)
|
||||
{
|
||||
$qry = "ALTER TABLE lehre.tbl_unterrichtszeiten ADD CONSTRAINT fk_unterrichtszeitentyp_kurzbz FOREIGN KEY(unterrichtszeitentyp_kurzbz) REFERENCES lehre.tbl_unterrichtszeiten_typ(unterrichtszeitentyp_kurzbz);";
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Added foreign key constraint fk_unterrichtszeitentyp_kurzbz to lehre.tbl_unterrichtszeiten';
|
||||
}
|
||||
|
||||
$result = $db->db_query("SELECT constraint_name FROM information_schema.table_constraints
|
||||
WHERE table_name='tbl_unterrichtszeiten' AND constraint_type='FOREIGN KEY' AND constraint_name='fk_unterrichtszeitengueltigkeit_id'");
|
||||
if($db->db_num_rows($result)==0)
|
||||
{
|
||||
$qry = "ALTER TABLE lehre.tbl_unterrichtszeiten ADD CONSTRAINT fk_unterrichtszeitengueltigkeit_id FOREIGN KEY(unterrichtszeitengueltigkeit_id) REFERENCES lehre.tbl_unterrichtszeiten_gueltigkeit(unterrichtszeitengueltigkeit_id);";
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Added foreign key constraint fk_unterrichtszeitengueltigkeit_id to lehre.tbl_unterrichtszeiten';
|
||||
}
|
||||
|
||||
$result = $db->db_query("SELECT constraint_name FROM information_schema.table_constraints
|
||||
WHERE table_name='tbl_unterrichtszeiten_gueltigkeit' AND constraint_type='FOREIGN KEY' AND constraint_name='fk_unterrichtszeitentyp_kurzbz'");
|
||||
if($db->db_num_rows($result)==0)
|
||||
{
|
||||
$qry = "ALTER TABLE lehre.tbl_unterrichtszeiten_gueltigkeit ADD CONSTRAINT fk_unterrichtszeitentyp_kurzbz FOREIGN KEY(unterrichtszeitentyp_kurzbz) REFERENCES lehre.tbl_unterrichtszeiten_typ(unterrichtszeitentyp_kurzbz);";
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_gueltigkeit: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Added foreign key constraint fk_unterrichtszeitentyp_kurzbz to lehre.tbl_unterrichtszeiten_gueltigkeit';
|
||||
}
|
||||
|
||||
$result = $db->db_query("SELECT constraint_name FROM information_schema.table_constraints
|
||||
WHERE table_name='tbl_unterrichtszeiten_gueltigkeit' AND constraint_type='FOREIGN KEY' AND constraint_name='fk_studienplan_id'");
|
||||
if($db->db_num_rows($result)==0)
|
||||
{
|
||||
$qry = "ALTER TABLE lehre.tbl_unterrichtszeiten_gueltigkeit ADD CONSTRAINT fk_studienplan_id FOREIGN KEY(studienplan_id) REFERENCES lehre.tbl_studienplan(studienplan_id);";
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_gueltigkeit: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Added foreign key constraint fk_studienplan_id to lehre.tbl_unterrichtszeiten_gueltigkeit';
|
||||
}
|
||||
|
||||
$result = $db->db_query("SELECT constraint_name FROM information_schema.table_constraints
|
||||
WHERE table_name='tbl_unterrichtszeiten_gueltigkeit' AND constraint_type='FOREIGN KEY' AND constraint_name='fk_oe_kurzbz'");
|
||||
if($db->db_num_rows($result)==0)
|
||||
{
|
||||
$qry = "ALTER TABLE lehre.tbl_unterrichtszeiten_gueltigkeit ADD CONSTRAINT fk_oe_kurzbz FOREIGN KEY(oe_kurzbz) REFERENCES public.tbl_organisationseinheit(oe_kurzbz);";
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_unterrichtszeiten_gueltigkeit: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Added foreign key constraint fk_oe_kurzbz to lehre.tbl_unterrichtszeiten_gueltigkeit';
|
||||
}
|
||||
?>
|
||||
+1401
-1
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user