Merge branch 'feature-40953/LV-Template_Uebersichtsseite'

This commit is contained in:
Harald Bamberger
2024-10-08 16:38:50 +02:00
13 changed files with 1384 additions and 0 deletions
+15
View File
@@ -55,6 +55,12 @@ $config['navigation_header'] = array(
'description' => 'CIS',
'sort' => 10
),
'lehrveranstaltungen' => array(
'link' => site_url('lehre/lvplanung/LvTemplateUebersicht'),
'icon' => '',
'description' => 'Lehrveranstaltungen',
'sort' => 15
),
'reihungstest' => array(
'link' => site_url('organisation/Reihungstest'),
'description' => 'Reihungstests',
@@ -287,6 +293,15 @@ $config['navigation_menu']['lehre/lehrauftrag/LehrauftragErteilen/*'] = array(
)
);
$config['navigation_menu']['lehre/lvplanung/LvTemplateUebersicht/index'] = array(
'lvTemplateUebersicht' => array(
'link' => site_url('lehre/lvplanung/LvTemplateUebersicht'),
'description' => 'LV Template Übersicht',
'icon' => '',
'sort' => 1
)
);
$config['navigation_menu']['system/issues/Issues/*'] = array(
'fehlerzustaendigkeiten' => array(
'link' => site_url('system/issues/IssuesZustaendigkeiten'),
@@ -0,0 +1,65 @@
<?php
/**
* FH-Complete
*
* @package FHC-API
* @author FHC-Team
* @copyright Copyright (c) 2016, fhcomplete.org
* @license GPLv3
* @link http://fhcomplete.org
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Lehrveranstaltung extends FHCAPI_Controller
{
/**
* Lehrveranstaltung API constructor.
*/
public function __construct()
{
parent::__construct(array(
'getTemplateLvTree' => array(
'lehre/lehrveranstaltung:rw'
)
));
// Load model LehrveranstaltungModel
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
}
/**
* Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes of given Berechtigung,
* that are assigned to a template. This data structure can be used for nested tabulators' data tree.
*
* @param null|string $studiensemester_kurzbz
* @param null|string $berechtigung
* @return array|stdClass|null
*/
public function getTemplateLvTree()
{
$studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz');
$berechtigung = $this->input->get('berechtigung');
if ($berechtigung)
{
$oe_permissions = $this->permissionlib->getOE_isEntitledFor($berechtigung);
if(!$oe_permissions) $oe_permissions = [];
$result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz, $oe_permissions);
}
else
{
$result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz);
}
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$this->terminateWithSuccess((getData($result) ?: []));
}
}
@@ -0,0 +1,118 @@
<?php
/**
* FH-Complete
*
* @package FHC-API
* @author FHC-Team
* @copyright Copyright (c) 2016, fhcomplete.org
* @license GPLv3
* @link http://fhcomplete.org
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Studiensemester extends FHCAPI_Controller
{
/**
* Studiensemester API constructor.
*/
public function __construct()
{
parent::__construct(
array(
'getAll' => self::PERM_LOGGED,
'getAktNext' => self::PERM_LOGGED
)
);
// Load model StudiensemesterModel
$this->load->model('organisation/studiensemester_model', 'StudiensemesterModel');
}
/**
* Get all Studiensemester.
*
* @param null|string $order Sorting order for the Studiensemester, 'asc' or 'desc'. Defaults to 'asc'.
* @param null|string $start Start date of the displayed Studiensemester in the format 'YYYY-MM-DD'.
* If provided, only Studiensemester starting from this date onwards will be returned.
* eg. '2020-09-01' will start with WS2020.
*/
public function getAll()
{
$order = $this->input->get('order');
$start = $this->input->get('start');
if (strcasecmp($order, 'DESC') == 0)
{
$this->StudiensemesterModel->addOrder('ende', 'DESC');
}
else
{
$this->StudiensemesterModel->addOrder('ende', 'ASC');
}
if ($start)
{
$result = $this->StudiensemesterModel->loadWhere([
'start >= ' => $start
]);
}
else
{
$result = $this->StudiensemesterModel->load();
}
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$this->terminateWithSuccess((getData($result) ?: []));
}
/**
* @return void
*/
public function getAktNext()
{
$semester = $this->input->get('semester');
$result = null;
if (!is_numeric($semester))
{
$result = $this->StudiensemesterModel->loadWhere(array('start <=' => 'NOW()', 'ende >=' => 'NOW()'));
}
if (!hasData($result))
{
$this->StudiensemesterModel->addOrder('ende');
$this->StudiensemesterModel->addLimit(1);
$whereArray = array('ende >=' => 'NOW()');
if (is_numeric($semester))
{
if ($semester % 2 == 0)
{
$ss = 'SS';
}
else
{
$ss = 'WS';
}
$whereArray['SUBSTRING(studiensemester_kurzbz FROM 1 FOR 2) ='] = $ss;
}
$result = $this->StudiensemesterModel->loadWhere($whereArray);
}
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
}
$this->terminateWithSuccess((getData($result) ?: ''));
}
}
@@ -0,0 +1,45 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class LvTemplateUebersicht extends Auth_Controller
{
public function __construct()
{
// Set required permissions
parent::__construct(
array(
'index' => 'lehre/lehrveranstaltung:rw',
)
);
// Load libraries
$this->load->library('AuthLib');
// Load language phrases
$this->loadPhrases(
array(
'global',
'lehre'
)
);
$this->_setAuthUID();
}
public function index()
{
$this->load->view('lehre/lvplanung/lvTemplateUebersicht.php');
}
/**
* 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');
}
}
@@ -15,6 +15,297 @@ class Lehrveranstaltung_model extends DB_Model
$this->load->model('organisation/studiensemester_model', 'StudiensemesterModel');
}
/**
* Get Lehrveranstaltungen by eventQuery string. Use with autocomplete event queries.
* @param $eventQuery String
* @param string $studiensemester_kurzbz Filter by Studiensemester
* @param array $oes Filter by Organisationseinheiten
* @return array
*/
public function getAutocompleteSuggestions($eventQuery, $studiensemester_kurzbz = null, $oes = null)
{
$subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes);
$params = [];
/* filter by input string */
if (is_string($eventQuery)) {
$subQry.= ' AND lv.bezeichnung ILIKE ?';
$params[] = '%' . $eventQuery . '%';
}
$qry = 'SELECT DISTINCT ON (lehrveranstaltung_id) * FROM ('. $subQry. ') AS tmp';
return $this->execQuery($qry, $params);
}
/**
* Get Lehrveranstaltungen with its Stg, OE and OE-type.
* Filter by Studiensemester and Organisationseinheiten if necessary.
* @param $eventQuery String
* @param string $studiensemester_kurzbz Filter by Studiensemester
* @param array $oes Filter by Organisationseinheiten
* @param array $lv_ids Filter by Lehrveranstaltung-Ids
* @return array
*/
public function getLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lv_ids = null)
{
$subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes);
$qry = 'SELECT * FROM ('. $subQry. ') AS tmp';
if (isset($lv_ids) && is_array($lv_ids))
{
/* filter by lv_ids */
$implodedLvIds = "'". implode("', '", $lv_ids). "'";
$qry.= ' WHERE lehrveranstaltung_id IN ('. $implodedLvIds. ')';
}
$qry.= ' ORDER BY stg_typ_kurzbz, orgform_kurzbz DESC';
return $this->execQuery($qry);
}
/**
* Get basic query to retrieve Lehrveranstaltungen according to the Orgforms and Ausbildungssemesters actual Studienplan.
*
* @return string
*/
private function _getQryLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lehrtyp_kurzbz = 'lv')
{
$qry = '
SELECT
lv.oe_kurzbz AS lv_oe_kurzbz,
CASE
WHEN oe.organisationseinheittyp_kurzbz = \'Kompetenzfeld\' THEN (\'KF \' || oe.bezeichnung)
WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung)
ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung)
END AS lv_oe_bezeichnung,
stplsem.studiensemester_kurzbz,
studienordnung_id,
sto.studiengang_kz,
stpl.studienplan_id,
stplsem.semester,
stpl.orgform_kurzbz,
upper(stg.typ || stg.kurzbz) AS stg_typ_kurzbz,
stg.bezeichnung AS stg_bezeichnung,
stgtyp.bezeichnung AS stg_typ_bezeichnung,
lv.lehrveranstaltung_id,
lv.semester,
lv.bezeichnung AS lv_bezeichnung,
(
-- comma seperated string of all lehreinheitgruppen
SELECT string_agg(bezeichnung, \', \') AS lehreinheitgruppe_bezeichnung
FROM(
-- distinct bezeichnung, as may come multiple times from different lehreinheiten
SELECT DISTINCT ON (studiengang_kz, bezeichnung) studiengang_kz, bezeichnung FROM
(
-- distinct lehreinheitgruppe, as may come multiple times from different lehrform
SELECT DISTINCT ON (legr.lehreinheitgruppe_id) legr.studiengang_kz,
-- get Spezialgruppe or Lehrverbandgruppe
COALESCE(
legr.gruppe_kurzbz,
CONCAT( UPPER(stg1.typ), UPPER(stg1.kurzbz), \'-\', legr.semester, legr.verband, legr.gruppe )
) as bezeichnung
FROM lehre.tbl_lehreinheitgruppe legr
JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
JOIN lehre.tbl_lehrveranstaltung lv1 USING (lehrveranstaltung_id)
JOIN public.tbl_studiengang stg1 ON stg1.studiengang_kz = legr.studiengang_kz
WHERE lv1.lehrveranstaltung_id = lv.lehrveranstaltung_id
AND le.studiensemester_kurzbz = stplsem.studiensemester_kurzbz
) AS lehreinheitgruppen
GROUP BY studiengang_kz, bezeichnung
ORDER BY studiengang_kz DESC
) AS uniqueLehreinheitgruppen_bezeichnung
) AS lehreinheitgruppen_bezeichnung
FROM
lehre.tbl_studienplan stpl
JOIN lehre.tbl_studienordnung sto USING (studienordnung_id)
JOIN lehre.tbl_studienplan_semester stplsem USING (studienplan_id)
JOIN lehre.tbl_studienplan_lehrveranstaltung stpllv ON (stpllv.studienplan_id = stpl.studienplan_id AND stpllv.semester = stplsem.semester)
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz)
JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz
JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ
/* filter by lehrtyp_kurzbz, default is lvs only */
WHERE
lehrtyp_kurzbz = '. $this->db->escape($lehrtyp_kurzbz);
if (isset($studiensemester_kurzbz) && is_string($studiensemester_kurzbz))
{
/* filter by studiensemester */
$qry.= ' AND stplsem.studiensemester_kurzbz = '. $this->db->escape($studiensemester_kurzbz);
}
if (isset($oes) && is_array($oes))
{
/* filter by organisationseinheit */
$implodedOes = "'". implode("', '", $oes). "'";
$qry.= ' AND lv.oe_kurzbz IN ('. $implodedOes. ')';
}
return $qry;
}
/**
* Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes, that are assigned to
* a template. This data structure can be used for nested tabulator data tree.
*
* @param null|string $studiensemester_kurzbz
* @param null|array $oes
* @return array|stdClass|null
*/
public function getTemplateLvTree($studiensemester_kurzbz = null, $oes = null){
$params = [];
$qry = '
WITH
-- All Lvs that are assigned to a template in given Studiensemester for given Oes
-- joining via actual Studienplan
standardisierteLvs AS (
SELECT
lv.*,
stpl.studienplan_id::text as studienplan_id,
stpl.bezeichnung AS studienplan_bezeichnung,
stplsem.studiensemester_kurzbz
FROM
lehre.tbl_studienplan stpl
JOIN lehre.tbl_studienordnung sto USING (studienordnung_id)
JOIN lehre.tbl_studienplan_semester stplsem USING (studienplan_id)
JOIN lehre.tbl_studienplan_lehrveranstaltung stpllv ON (stpllv.studienplan_id = stpl.studienplan_id AND stpllv.semester = stplsem.semester)
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz)
JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz
JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ
WHERE
-- filter type lv
lehrtyp_kurzbz = \'lv\'
-- filter lvs assigned to template (= standardisierte lv)
AND lehrveranstaltung_template_id IS NOT NULL';
if (is_string($studiensemester_kurzbz))
{
/* filter by studiensemester */
$params[]= $studiensemester_kurzbz;
$qry.= ' AND stplsem.studiensemester_kurzbz = ? ';
}
if (is_array($oes))
{
/* filter by organisationseinheit */
$params[]= $oes;
$qry.= ' AND lv.oe_kurzbz IN ? ';
}
$qry.= '
),
-- All templates
templateLvs AS (
SELECT
lv.*,
NULL AS studienplan_id,
(
SELECT string_agg(stpl_bezeichnung, \', \')
FROM
(
SELECT stlv.studienplan_bezeichnung AS stpl_bezeichnung
FROM standardisierteLvs stlv
WHERE stlv.lehrveranstaltung_template_id = lv.lehrveranstaltung_id
) AS studienplaene
) AS studienplan_bezeichnung,
NULL AS studiensemester_kurzbz
FROM
lehre.tbl_lehrveranstaltung lv
WHERE
-- filter type template
lehrtyp_kurzbz = \'tpl\'
-- filter semester that were retrieved by standardisierte lvs semester for selected studiensemester
AND EXISTS (
SELECT 1
FROM standardisierteLvs std
WHERE std.lehrveranstaltung_template_id = lv.lehrveranstaltung_id
)';
if (is_array($oes))
{
/* filter by organisationseinheit */
$params[]= $oes;
$qry.= ' AND lv.oe_kurzbz IN ? ';
}
$qry.= '
)
';
$qry.= '
SELECT
lv.lehrveranstaltung_id,
lv.kurzbz,
lv.lehrtyp_kurzbz,
lv.bezeichnung AS lv_bezeichnung,
lv.bezeichnung_english,
lv.studiengang_kz,
lv.semester,
lv.oe_kurzbz,
lv.ects,
lv.lehrform_kurzbz,
lv.orgform_kurzbz,
lv.sprache,
lv.aktiv,
lv.lehrveranstaltung_template_id,
lv.studienplan_id,
lv.studienplan_bezeichnung,
lv.studiensemester_kurzbz,
upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz",
stg.bezeichnung AS "stg_bezeichnung",
stgtyp.bezeichnung AS "stg_typ_bezeichnung",
CASE
WHEN oe.organisationseinheittyp_kurzbz = \'Kompetenzfeld\' THEN (\'KF \' || oe.bezeichnung)
WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung)
ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung)
END AS "lv_oe_bezeichnung",
(
-- comma seperated string of all lehreinheitgruppen
SELECT string_agg(bezeichnung, \', \') AS lehreinheitgruppe_bezeichnung
FROM(
-- distinct bezeichnung, as may come multiple times from different lehreinheiten
SELECT DISTINCT ON (studiengang_kz, bezeichnung) studiengang_kz, bezeichnung FROM
(
-- distinct lehreinheitgruppe, as may come multiple times from different lehrform
SELECT DISTINCT ON (legr.lehreinheitgruppe_id) legr.studiengang_kz,
-- get Spezialgruppe or Lehrverbandgruppe
COALESCE(
legr.gruppe_kurzbz,
CONCAT( UPPER(stg1.typ), UPPER(stg1.kurzbz), \'-\', legr.semester, legr.verband, legr.gruppe )
) as bezeichnung
FROM lehre.tbl_lehreinheitgruppe legr
JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
JOIN lehre.tbl_lehrveranstaltung lv1 USING (lehrveranstaltung_id)
JOIN public.tbl_studiengang stg1 ON stg1.studiengang_kz = legr.studiengang_kz
WHERE lv1.lehrveranstaltung_id = lv.lehrveranstaltung_id
AND le.studiensemester_kurzbz = lv.studiensemester_kurzbz
) AS lehreinheitgruppen
GROUP BY studiengang_kz, bezeichnung
ORDER BY studiengang_kz DESC
) AS uniqueLehreinheitgruppen_bezeichnung
) AS lehreinheitgruppen_bezeichnung
FROM (
SELECT
*
FROM
standardisierteLvs
UNION
SELECT
*
FROM templateLvs
) AS lv
JOIN public.tbl_studiengang stg ON stg.studiengang_kz = lv.studiengang_kz
JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ
JOIN public.tbl_organisationseinheit oe ON oe.oe_kurzbz = lv.oe_kurzbz
ORDER BY
oe.bezeichnung, lv.semester, lv.bezeichnung
';
return $this->execQuery($qry, $params);
}
/**
* Gets unique Groupstrings for Lehrveranstaltungen, e.g. WS2018_BIF_1_PRJM_VZ_LV12345
* @param string $studiensemester_kurzbz
@@ -29,4 +29,54 @@ class Studienjahr_model extends DB_Model
return $this->execQuery($query);
}
/**
* Get the current Studienjahr. During the summer term, continue using the previous Studienjahr.
*
* @param int $days
* @return array|stdClass|null
*/
public function getLastOrAktStudienjahr($days = 60)
{
if (!is_numeric($days))
{
$days = 60;
}
$query = '
SELECT *
FROM public.tbl_studienjahr
JOIN public.tbl_studiensemester USING (studienjahr_kurzbz)
WHERE start < NOW() - \'' . $days . ' DAYS\'::INTERVAL
ORDER by start DESC
LIMIT 1
';
return $this->execQuery($query);
}
/**
* Get the current Studienjahr. During the summer term, get the upcoming next Studienjahr.
*
* @param int $days
* @return array|stdClass|null
*/
public function getAktOrNextStudienjahr($days = 62)
{
if (!is_numeric($days))
{
$days = 62;
}
$query = '
SELECT *
FROM public.tbl_studienjahr
JOIN public.tbl_studiensemester using(studienjahr_kurzbz)
WHERE start < NOW() + \'' . $days . ' DAYS\'::INTERVAL
ORDER by start DESC
LIMIT 1
';
return $this->execQuery($query);
}
}
@@ -0,0 +1,29 @@
<?php
$includesArray = array(
'title' => 'LV Template Übersicht',
'vue3' => true,
'axios027' => true,
'bootstrap5' => true,
'tabulator5' => true,
'fontawesome6' => true,
'primevue3' => true,
'navigationcomponent' => true,
'filtercomponent' => true,
'customJSModules' => array('public/js/apps/lehre/lvplanung/LvTemplates.js'),
'customCSSs' => array(
'public/css/Fhc.css',
'public/css/lvTemplateUebersicht.css'
)
);
$this->load->view('templates/FHC-Header', $includesArray);
?>
<div id="main">
<!-- Navigation component -->
<core-navigation-cmpt></core-navigation-cmpt>
<lv-template-uebersicht></lv-template-uebersicht>
</div>
<?php $this->load->view('templates/FHC-Footer', $includesArray); ?>
+1
View File
@@ -70,6 +70,7 @@ $menu=array
'link'=>'left.php?categorie=Lehre', 'target'=>'nav',
'Gruppenverwaltung'=>array('name'=>'Gruppen', 'permissions'=>array('admin','lv-plan','support','lehre/gruppe'), 'link'=>'stammdaten/lvbgruppenverwaltung.php', 'target'=>'main'),
'Lehrveranstaltung'=>array('name'=>'Lehrveranstaltung', 'link'=>'lehre/lehrveranstaltung_frameset.html', 'target'=>'main'),
'lvTemplateUebersicht'=>array('name'=>'LV-Template Übersicht', 'link'=>'../index.ci.php/lehre/lvplanung/LvTemplateUebersicht', 'target'=>'_blank'),
'Studienordnung'=>array('name'=>'Studienordnung', 'link'=>'lehre/studienordnung.php', 'target'=>'_blank','permissions'=>array('lehre/studienordnung')),
'StudienplanGueltigkeit'=>array('name'=>'Studienplan Gültigkeit', 'link'=>'lehre/studienplan_gueltigkeit.php', 'target'=>'main','permissions'=>array('lehre/studienordnung')),
'StudienplanVorruecken'=>array('name'=>'Studienplan vorrücken', 'link'=>'lehre/studienplan_vorrueckung.php', 'target'=>'main','permissions'=>array('lehre/studienplan')),
+3
View File
@@ -0,0 +1,3 @@
html {
font-size: .75em;
}
@@ -0,0 +1,37 @@
/**
* 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 LvTemplateUebersicht from '../../../lehre/lvplanung/LvTemplateUebersicht.js';
import {CoreNavigationCmpt} from '../../../components/navigation/Navigation.js';
import FhcAlert from '../../../plugin/FhcAlert.js';
import FhcApi from "../../../plugin/FhcApi.js";
import Phrasen from "../../../plugin/Phrasen.js";
const lvTemplatesApp = Vue.createApp({
components: {
CoreNavigationCmpt,
LvTemplateUebersicht
}
});
lvTemplatesApp
.use(primevue.config.default,{zIndex: {overlay: 9999}})
.use(FhcAlert)
.use(FhcApi)
.use(Phrasen)
.mount('#main')
@@ -0,0 +1,289 @@
import {CoreFilterCmpt} from '../../components/filter/Filter.js';
import CoreFormInput from "../../components/Form/Input.js";
// Fields used to restructure table data for dataTree
const idField = 'lehrveranstaltung_id';
const parentIdField = 'lehrveranstaltung_template_id';
const STUDIENSEMESTER_DROPDOWN_STARTDATE = '2011-01-01';
export default {
components: {
CoreFilterCmpt,
CoreFormInput
},
data: function() {
return {
table: null,
studiensemester: [],
selectedStudiensemester: '',
cbDataTreeStartExpanded: false // checkbox expand dataTree or not
}
},
computed: {
tabulatorOptions() {
const fhcValuesLookup = function(cell) {
var values = {};
const field = cell.getField();
const data = cell.getTable().getData();
const collectvalues = function(rows, field) {
var values = {};
var childvalues = {};
for(const row of rows) {
const rowvalue = (row[field] !== null) ? row[field] : '';
values[rowvalue] = rowvalue;
if(row['_children'] && row['_children'].length > 0) {
childvalues = collectvalues(row['_children'], field);
values = {...values, ...childvalues}
}
}
return values;
}
values = collectvalues(data, field);
const vals = Object.keys(values).sort();
if(vals.indexOf('') === -1) {
vals.unshift('');
}
return vals;
};
const fhctreefilter = function(headerValue, rowValue, rowData, filterParams){
if (rowData['_children'] && rowData['_children'].length > 0) {
for (var i in rowData['_children']) {
return rowValue == headerValue ||
fhctreefilter(
headerValue,
rowData['_children'][i][filterParams.field],
rowData['_children'][i],
filterParams
);
}
}
return rowValue == headerValue;
};
const self = this;
return {
// NOTE: data is set on table built to await preselected actual Studiensemester
ajaxResponse(url, params, response) {
return self.prepDataTreeData(response.data) // Prepare data for dataTree view
},
layout: 'fitColumns',
autoResize: false, // prevent auto resizing of table
resizableColumnFit: true, //maintain the fit of columns when resizing
index: 'lehrveranstaltung_id',
selectable: true,
selectableRangeMode: 'click',
dataTree: true,
dataTreeStartExpanded: self.cbDataTreeStartExpanded,
dataTreeChildIndent: 15, //indent child rows by 15 px
persistence:{
filter: false, //persist filter sorting
},
columns: [
{title: 'LV-ID', field: 'lehrveranstaltung_id', headerFilter: true, visible: false},
{title: 'LV Kurzbz', field: 'kurzbz', headerFilter: true, visible:false, width: 70},
{title: 'STG Kurzbz', field: 'stg_typ_kurzbz', headerFilter: "list", headerFilterParams: {valuesLookup: fhcValuesLookup}, headerFilterFunc: fhctreefilter, headerFilterFuncParams: {field: 'stg_typ_kurzbz'}, visible:true, width: 80},
{title: 'OrgEinheit', field: 'lv_oe_bezeichnung', headerFilter: true, visible: false, width: 250},
{title: 'Lehrtyp Kurzbz', field: 'lehrtyp_kurzbz', headerFilter: true, visible:false, width: 70},
{title: 'Studiengangtyp', field: 'stg_typ_bezeichnung', headerFilter: "list", headerFilterParams: {valuesLookup: fhcValuesLookup}, headerFilterFunc: fhctreefilter, headerFilterFuncParams: {field: 'stg_typ_bezeichnung'}, width: 150},
{title: 'OrgForm', field: 'orgform_kurzbz', headerFilter: "list", headerFilterParams: {valuesLookup: fhcValuesLookup}, headerFilterFunc: fhctreefilter, headerFilterFuncParams: {field: 'orgform_kurzbz'}, width: 70},
{title: 'Semester', field: 'semester', headerFilter: true, width: 50},
{title: 'Lehrveranstaltung', field: 'lv_bezeichnung', headerFilter: true, minWidth: 250},
{title: 'Lehrveranstaltung ENG', field: 'bezeichnung_english', headerFilter: true, minWidth: 250},
{title: 'ECTS', field: 'ects', headerFilter: true, width: 50, hozAlign: 'right'},
{title: 'Lehrform', field: 'lehrform_kurzbz', headerFilter: true, width: 50},
{title: 'Sprache', field: 'sprache', headerFilter: true, width: 100},
{title: 'Aktiv', field: 'aktiv', width: 50,
formatter:"tickCross",
headerFilter:"tickCross",
headerFilterParams:{"tristate": true},
hozAlign:"center",
formatterParams: {
tickElement: '<i class="fa fa-check text-success"></i>',
crossElement: '<i class="fa fa-xmark text-danger"></i>'
}
},
{title: 'Studienplan', field: 'studienplan_bezeichnung', headerFilter: true, visible:true, width: 220},
{title: 'OE Kurzbz', field: 'lv_oe_kurzbz', headerFilter: true, visible:false, minWidth: 80},
{
title: this.$p.t('global/aktionen'),
field: 'actions',
width: 140,
formatter: (cell, formatterParams, onRendered) => {
let container = document.createElement('div');
container.className = "d-flex gap-2";
let button = document.createElement('button');
button.className = 'btn btn-outline-secondary';
button.innerHTML = '<i class="fa fa-external-link"></i> ' + this.$p.t('global/verwalten');
button.addEventListener('click', (event) => this.openAdminLvTemplate(event, cell.getRow()));
container.append(button);
return container;
},
frozen: true
}
]
}
},
urlToAdminAllTemplates() {
return FHC_JS_DATA_STORAGE_OBJECT.app_root +
'vilesci/lehre/lehrveranstaltung.php?stg_kz=99999&semester=-1&orgform=-1';
}
},
methods: {
async loadAndSetStudiensemester(){
const result = await this.$fhcApi
.get('api/frontend/v1/organisation/Studiensemester/getAll', {start: STUDIENSEMESTER_DROPDOWN_STARTDATE})
.then(result => this.studiensemester = result.data )
.then(() => this.$fhcApi.get('api/frontend/v1/organisation/Studiensemester/getAktNext') ) // Get actual Studiensemester
.then(result => this.selectedStudiensemester = result.data[0].studiensemester_kurzbz ) // Preselect Studiensemester
.catch(error => this.$fhcAlert.handleSystemError(error) );
},
async onTableBuilt(){
this.table = this.$refs.lvTemplateUebersichtTable.tabulator;
// Await Studiensemester
await this.loadAndSetStudiensemester();
// Set table data
this.table.setData(
this.$fhcApi.getUri() +
'/api/frontend/v1/education/Lehrveranstaltung/getTemplateLvTree' +
'?studiensemester_kurzbz=' + this.selectedStudiensemester
);
// Await phrases categories
await this.$p.loadCategory(['lehre']);
// Replace column titles with phrasen
this.table.updateColumnDefinition('lv_bezeichnung', {title: this.$p.t('lehre', 'lehrveranstaltung')});
},
onChangeStudiensemester(){
// Reset table data
this.table.setData(
this.$fhcApi.getUri() +
'/api/frontend/v1/education/Lehrveranstaltung/getTemplateLvTree' +
'?studiensemester_kurzbz=' + this.selectedStudiensemester
);
},
openAdminLvTemplate(event, row){
const url = FHC_JS_DATA_STORAGE_OBJECT.app_root +
'vilesci/lehre/lehrveranstaltung.php?stg_kz=&semester=-1&orgform=-1&lehrveranstaltung_id=' +
row.getData().lehrveranstaltung_id;
window.open(url, '_blank').focus();
},
prepDataTreeData(data){
let toDelete = [];
// loop through all data
for (let childIdx = 0; childIdx < data.length; childIdx++)
{
let child = data[childIdx];
// if it has parent id, it is a child
if (child[parentIdField])
{
// append the child on the right place. If parent found, mark original sw child on 0 level for deleting
if (this._appendChild(data, child)) toDelete.push(childIdx);
}
}
// delete the marked children from 0 level
for (let counter = 0; counter < toDelete.length; counter++)
{
// decrease index by counter as index of data array changes after every deletion
data.splice(toDelete[counter] - counter, 1);
}
return data;
},
_appendChild(data, child) {
// get parent id
let parentId = child[parentIdField];
// loop thorugh all data
for (let parentIdx = 0; parentIdx < data.length; parentIdx++)
{
let parent = data[parentIdx];
// if it's the parent
if (parent[idField] == parentId)
{
// create children array if not done yet
if (!parent._children) parent._children = [];
// if child is not included in children array, append the child
if (!parent._children.includes(child)) parent._children.push(child);
// parent found
return true;
}
// search children for parents
else if (parent._children) this._appendChild(parent._children, child);
}
// parent not found
return false;
},
reloadTabulator() {
if (this.table !== null && this.table !== undefined)
{
for (let option in this.tabulatorOptions)
{
if (this.table.options.hasOwnProperty(option))
this.table.options[option] = this.tabulatorOptions[option];
}
this.$refs.lvTemplateUebersichtTable.reloadTable();
}
},
},
template: `
<div class="lvTemplateUebersicht overflow-hidden">
<div class="row d-flex mb-3">
<div class="col-10 h2 mb-4">{{ $p.t('lehre/lvTemplatesUebersicht') }}</div>
<div class="col-2 ms-auto align-self-end">
<core-form-input
type="select"
v-model="selectedStudiensemester"
name="studiensemester"
@change="onChangeStudiensemester">
<option
v-for="(studSem, index) in studiensemester"
:key="index"
:value="studSem.studiensemester_kurzbz">
{{studSem.studiensemester_kurzbz}}
</option>
</core-form-input>
</div>
</div>
<div class="row mb-5">
<div class="col">
<core-filter-cmpt
ref="lvTemplateUebersichtTable"
uniqueId="lvTemplateUebersichtTable"
table-only
:side-menu="false"
:tabulator-options="tabulatorOptions"
:tabulator-events="[{event: 'tableBuilt', handler: onTableBuilt}]">
<template v-slot:actions>
<a type="button" class="btn btn-primary" :href="urlToAdminAllTemplates" target="_blank"><i class="fa fa-external-link me-2"></i>{{ $p.t('lehre/lvTemplatesVerwalten') }}</a>
<div class="form-check form-check-inline">
<input
class="form-check-input"
type="checkbox"
v-model="cbDataTreeStartExpanded"
:checked="cbDataTreeStartExpanded"
@change="reloadTabulator">
<label class="form-check-label">Templates {{ $p.t('global/aufgeklappt') }}</label>
</div>
</template>
</core-filter-cmpt>
</div>
</div>
</div>
`
};
+1
View File
@@ -1298,6 +1298,7 @@ $filters = array(
{"name": "os"},
{"name": "lizenzserver_kurzbz"},
{"name": "lizenzserver_port"},
{"name": "anzahl_lizenzen"},
{"name": "softwarestatus_kurzbz"}
],
"filters": []
+440
View File
@@ -29198,6 +29198,446 @@ array(
)
),
// Betriebsmittel end
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'softwareanforderung',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Softwareanforderung',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Software Request',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'softwareanforderungSubtitle',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Softwareanforderung und Lizenzmanagement für die Lehre',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Software Request and License management for Education',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swAnforderungenUndLizenen',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Softwareanforderungen & Lizenzen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Software Requirements & Licenses',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'anforderungNachSw',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Anforderung nach Software',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Request by Software',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'anforderungNachLv',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Anforderung nach LV',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Request by Course',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swNichtGefundenHierBestellen',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Software nicht gefunden?<br>Hier bei IT-Services bestellen",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Software not found?<br>Order here from IT Services",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'bereitsAngefordert',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Bereits angefordert",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Requested already",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'mindEineZuorndungExistiertBereits',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Mindestens eine Zuordnung existiert bereits.",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "At least one assignment already exists.",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swFuerLvAnfordern',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Software für LV anfordern",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Request software for courses",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swWurdeBereitsAngefordert',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Software wurde bereits angefordert",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Software has already been requested",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swAnforderungUeberAuswahlVonSw',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Softwareanforderung über die Auswahl von Software",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Software Requirements based on the Selection of Software",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'swAnforderungUeberAuswahlVonLvs',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Softwareanforderung über die Auswahl von Lehrveranstaltungen",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Software Requirements based on the Selection of Courses",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'lizenzAnzahlNeu',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Lizenz-Anzahl NEU",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "License Number NEW",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'lizenzanzahlAendern',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Lizenzanzahl ändern",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Change Number of Licenses",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'eingabeFehlt',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Eingabe fehlt",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Input missing",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'unveraendert',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Unverändert",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Unchanged",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'anforderungenVorruecken',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Anforderungen vorrücken",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Take over Requirements",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'vorrueckenInStudiensemester',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Vorrücken in Studiensemester",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Take over to semester",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'softwarebereitstellung',
'category' => 'global',
'phrase' => 'anteiligInProzent',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Anteilig in %",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Percentage share",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'verwalten',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Verwalten",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Administrate",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'lehre',
'phrase' => 'lvTemplatesVerwalten',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "LV Templates verwalten",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Administrate Course Templates",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'lehre',
'phrase' => 'lvTemplatesUebersicht',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "LV Templates Übersicht",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Course Templates Overview",
'description' => '',
'insertvon' => 'system'
)
)
),
//**************************** CORE/konto
array(
'app' => 'core',