diff --git a/application/config/navigation.php b/application/config/navigation.php
index 3680930d0..d57cd697a 100644
--- a/application/config/navigation.php
+++ b/application/config/navigation.php
@@ -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'),
diff --git a/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php b/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php
new file mode 100644
index 000000000..636c8e3f3
--- /dev/null
+++ b/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php
@@ -0,0 +1,65 @@
+ 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) ?: []));
+ }
+}
diff --git a/application/controllers/api/frontend/v1/organisation/Studiensemester.php b/application/controllers/api/frontend/v1/organisation/Studiensemester.php
new file mode 100644
index 000000000..72a449aaa
--- /dev/null
+++ b/application/controllers/api/frontend/v1/organisation/Studiensemester.php
@@ -0,0 +1,118 @@
+ 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) ?: ''));
+ }
+}
diff --git a/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php b/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php
new file mode 100644
index 000000000..b1ab2fe26
--- /dev/null
+++ b/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php
@@ -0,0 +1,45 @@
+ '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');
+ }
+}
\ No newline at end of file
diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php
index cefd147b9..de8ebc5c9 100644
--- a/application/models/education/Lehrveranstaltung_model.php
+++ b/application/models/education/Lehrveranstaltung_model.php
@@ -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
diff --git a/application/models/organisation/Studienjahr_model.php b/application/models/organisation/Studienjahr_model.php
index 3bbe3a07f..a6e1bc575 100644
--- a/application/models/organisation/Studienjahr_model.php
+++ b/application/models/organisation/Studienjahr_model.php
@@ -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);
+ }
}
diff --git a/application/views/lehre/lvplanung/lvTemplateUebersicht.php b/application/views/lehre/lvplanung/lvTemplateUebersicht.php
new file mode 100644
index 000000000..5c873486c
--- /dev/null
+++ b/application/views/lehre/lvplanung/lvTemplateUebersicht.php
@@ -0,0 +1,29 @@
+ '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);
+?>
+
+
+
+
+
+
+
+
+load->view('templates/FHC-Footer', $includesArray); ?>
diff --git a/include/tw/vilesci_menu_main.inc.php b/include/tw/vilesci_menu_main.inc.php
index 2aa2e67d3..2a1ca74ae 100644
--- a/include/tw/vilesci_menu_main.inc.php
+++ b/include/tw/vilesci_menu_main.inc.php
@@ -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')),
diff --git a/public/css/lvTemplateUebersicht.css b/public/css/lvTemplateUebersicht.css
new file mode 100644
index 000000000..af279b8cb
--- /dev/null
+++ b/public/css/lvTemplateUebersicht.css
@@ -0,0 +1,3 @@
+html {
+ font-size: .75em;
+}
\ No newline at end of file
diff --git a/public/js/apps/lehre/lvplanung/LvTemplates.js b/public/js/apps/lehre/lvplanung/LvTemplates.js
new file mode 100644
index 000000000..b6ad3ae81
--- /dev/null
+++ b/public/js/apps/lehre/lvplanung/LvTemplates.js
@@ -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 .
+ */
+
+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')
\ No newline at end of file
diff --git a/public/js/lehre/lvplanung/LvTemplateUebersicht.js b/public/js/lehre/lvplanung/LvTemplateUebersicht.js
new file mode 100644
index 000000000..be0da75b8
--- /dev/null
+++ b/public/js/lehre/lvplanung/LvTemplateUebersicht.js
@@ -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: '',
+ crossElement: ''
+ }
+ },
+ {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 = ' ' + 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: `
+
+
+
{{ $p.t('lehre/lvTemplatesUebersicht') }}
+
+
+
+
+
+
+
+
+
+`
+};
diff --git a/system/filtersupdate.php b/system/filtersupdate.php
index e885b4e14..51dd86314 100644
--- a/system/filtersupdate.php
+++ b/system/filtersupdate.php
@@ -1298,6 +1298,7 @@ $filters = array(
{"name": "os"},
{"name": "lizenzserver_kurzbz"},
{"name": "lizenzserver_port"},
+ {"name": "anzahl_lizenzen"},
{"name": "softwarestatus_kurzbz"}
],
"filters": []
diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php
index 82e90d1da..16631efa8 100644
--- a/system/phrasesupdate.php
+++ b/system/phrasesupdate.php
@@ -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?
Hier bei IT-Services bestellen",
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => "Software not found?
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',