diff --git a/application/config/lvverwaltung.php b/application/config/lvverwaltung.php
index 4fe09bff3..d315c9b38 100644
--- a/application/config/lvverwaltung.php
+++ b/application/config/lvverwaltung.php
@@ -8,4 +8,15 @@ $config['lvverwaltung_tags'] = [
];
*/
-$config['lvverwaltung_tags'] = [];
\ No newline at end of file
+$config['lvverwaltung_tags'] = [];
+
+# Additional columns:
+/*
+$config["list_columns"] = [
+ 'fieldname' => [
+ 'js' => 'path/to/snippet.js', // tabulator config snippet (eg: return { name: 'Name', field: 'fieldname' }; )
+ // NOTE: 'default' & 'joins' like in stv.php config are currently not available here
+ ]
+];
+*/
+
diff --git a/application/config/routes.php b/application/config/routes.php
index 8024f449a..a58fded36 100644
--- a/application/config/routes.php
+++ b/application/config/routes.php
@@ -75,52 +75,65 @@ $route['Abgabetool/Student'] = 'Cis/Abgabetool/Student';
$route['Abgabetool/Student/(:any)'] = 'Cis/Abgabetool/Student/$1';
$route['Abgabetool/Deadlines'] = 'Cis/Abgabetool/Deadlines';
+// Studierendenverwaltung App Routes
+$route['studvw'] = 'studentenverwaltung/index';
+$route['studvw/.*'] = 'studentenverwaltung/index';
+// Old routes
+$route['studentenverwaltung'] = 'redirect/301/studvw';
+$route['studentenverwaltung/(:any)'] = 'redirect/301/studvw/stdsem/$1';
+$route['studentenverwaltung/(:any)/(prestudent|student|person|search)/(:any)'] = 'redirect/301/studvw/stdsem/$1/$2/$3';
+$route['studentenverwaltung/(:any)/prestudent/(:any)/tab/:any'] = 'redirect/301/studvw/stdsem/$1/prestudent/$2';
+$route['studentenverwaltung/(:any)/search/(:any)/(:any)'] = 'redirect/301/studvw/stdsem/$1/search/$2/$3';
+$route['studentenverwaltung/(:any)/(:any)'] = 'redirect/301/studvw/stdsem/$1/stg/$2';
+
// Studierendenverwaltung List Routes
-$route['api/frontend/v1/stv/[sS]tudents/inout'] = 'api/frontend/v1/stv/Students/index';
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv/Students/index';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/inout/1/incoming/1'] = 'api/frontend/v1/stv/students/getIncoming/$1';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/inout/1/outgoing/1'] = 'api/frontend/v1/stv/students/getOutgoing/$1';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/inout/1/shared_studies/1'] = 'api/frontend/v1/stv/students/getGemeinsamestudien/$1';
-// (studiensemester_kurzbz)/inout[/(incoming|outgoing|gemeinsamestudien)]
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout'] = 'api/frontend/v1/stv/Students/index';
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/incoming'] = 'api/frontend/v1/stv/Students/getIncoming/$1';
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/outgoing'] = 'api/frontend/v1/stv/Students/getOutgoing/$1';
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/gemeinsamestudien'] = 'api/frontend/v1/stv/Students/getGemeinsamestudien/$1';
+$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/prestudent/1/stdsem/(:any)/:any/1/(:any)/1'] = 'api/frontend/v1/stv/students/getPrestudents/$1/$2/$3';
+$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/prestudent/1/stdsem/(:any)/(:any)/1'] = 'api/frontend/v1/stv/students/getPrestudents/$1/$2/$3';
+$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/prestudent/1/stdsem/(:any)'] = 'api/frontend/v1/stv/students/getPrestudents/$1/$2';
+$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/prestudent/1'] = 'api/frontend/v1/stv/students/getPrestudents/$1';
-// (studiengang_kz)/prestudent[/(studiensemester_kurzbz)[/(filter)[/(otherfilter)]]]
-$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent'] = 'api/frontend/v1/stv/Students/getPrestudents/$1';
-$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv/Students/getPrestudents/$1/$2';
-$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent/([WS]S[0-9]{4})/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudents/$1/$2/$3';
-$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent/([WS]S[0-9]{4})/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudents/$1/$2/$4';
+$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/orgform/(:any)/prestudent/1/stdsem/(:any)/:any/1/(:any)/1'] = 'api/frontend/v1/stv/students/getPrestudentsOrgform/$1/$2/$3/$4';
+$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/orgform/(:any)/prestudent/1/stdsem/(:any)/(:any)/1'] = 'api/frontend/v1/stv/students/getPrestudentsOrgform/$1/$2/$3/$4';
+$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/orgform/(:any)/prestudent/1/stdsem/(:any)'] = 'api/frontend/v1/stv/students/getPrestudentsOrgform/$1/$2/$3';
+$route['api/frontend/v1/treemenudata/stv/stdsem/:any/stg/(:any)/orgform/(:any)/prestudent/1'] = 'api/frontend/v1/stv/students/getPrestudentsOrgform/$1/$2';
-// (studiengang_kz)/(orgform)/prestudent[/(studiensemester_kurzbz)[/(filter)[/(otherfilter)]]]
-$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2';
-$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2/$3';
-$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent/([WS]S[0-9]{4})/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2/$3/$4';
-$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent/([WS]S[0-9]{4})/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2/$3/$5';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/semester/(:any)/verband/(:any)/group/(:any)'] = 'api/frontend/v1/stv/students/getStudents/$1/$2/$3/$4/$5';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/semester/(:any)/verband/(:any)'] = 'api/frontend/v1/stv/students/getStudents/$1/$2/$3/$4';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/semester/(:any)'] = 'api/frontend/v1/stv/students/getStudents/$1/$2/$3';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)'] = 'api/frontend/v1/stv/students/getStudents/$1/$2';
-// (studiensemester_kurzbz)/(studiengang_kz)/(semester)/grp/(gruppe)
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)/grp/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsSpezialgruppe/$1/$2/$3/$4';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/orgform/(:any)/semester/(:any)/verband/(:any)/group/(:any)'] = 'api/frontend/v1/stv/students/getStudentsOrgform/$1/$2/$3/$4/$5/$6';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/orgform/(:any)/semester/(:any)/verband/(:any)'] = 'api/frontend/v1/stv/students/getStudentsOrgform/$1/$2/$3/$4/$5';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/orgform/(:any)/semester/(:any)'] = 'api/frontend/v1/stv/students/getStudentsOrgform/$1/$2/$3/$4';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/orgform/(:any)'] = 'api/frontend/v1/stv/students/getStudentsOrgform/$1/$2/$3';
-// (studiensemester_kurzbz)/(studiengang_kz)[/(semester)[/(verband)[/(gruppe)]]]
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2';
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2/$3';
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)/(:any)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2/$3/$4';
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2/$3/$4/$5';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/semester/(:any)/group/(:any)'] = 'api/frontend/v1/stv/students/getStudentsSpezialgruppe/$1/$2/$3/$4';
-// (studiensemester_kurzbz)/(studiengang_kz)/(orgform)/(semester)/grp/(gruppe)
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)/grp/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsOrgformSpezialgruppe/$1/$2/$3/$4/$5';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/stg/(:any)/orgform/(:any)/semester/(:any)/group/(:any)'] = 'api/frontend/v1/stv/students/getStudentsOrgformSpezialgruppe/$1/$3/$2/$4/$5';
-// (studiensemester_kurzbz)/(studiengang_kz)/(orgform)[/(semester)[/(verband)[/(gruppe)]]]
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3';
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3/$4';
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3/$4/$5';
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3/$4/$5/$6';
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/prestudent/(:any)'] = 'api/frontend/v1/stv/students/getPrestudent/$1/$2';
+
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/student/(:any)'] = 'api/frontend/v1/stv/students/getStudent/$1/$2';
+
+$route['api/frontend/v1/treemenudata/stv/stdsem/(:any)/person/(:any)'] = 'api/frontend/v1/stv/students/getPerson/$1/$2';
+
+$route['api/frontend/v1/treemenudata/stv/.*'] = 'api/frontend/v1/stv/students/index';
+
+// Lvverwaltung List Routes
+$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/stg/(:any)'] = 'api/frontend/v1/Lehrveranstaltung/getByStg/$1/$2';
+$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/stg/(:any)/semester/(:any)'] = 'api/frontend/v1/Lehrveranstaltung/getByStg/$1/$2/$3';
+$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/stg/(:any)/semester/(:any)/.*'] = 'api/frontend/v1/Lehrveranstaltung/getByStg/$1/$2/$3';
+$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/stg/(:any)/orgform/(:any)'] = 'api/frontend/v1/Lehrveranstaltung/getByStg/$1/$2/$3';
+$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/stg/(:any)/orgform/(:any)/.*'] = 'api/frontend/v1/Lehrveranstaltung/getByStg/$1/$2/$3';
+
+$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/emp/(:any)'] = 'api/frontend/v1/Lehrveranstaltung/getByEmp/$1/$2';
+$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/emp/(:any)/stg/(:any)'] = 'api/frontend/v1/Lehrveranstaltung/getByEmp/$1/$2/$3';
+$route['api/frontend/v1/treemenudata/lvverwaltung/stdsem/(:any)/emp/(:any)/stg/(:any)/.*'] = 'api/frontend/v1/Lehrveranstaltung/getByEmp/$1/$2/$3';
-// // (studiensemester_kurzbz)/uid/(uid)
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/uid/(:any)'] = 'api/frontend/v1/stv/Students/getStudent/$1/$2';
-// // (studiensemester_kurzbz)/prestudent/(prestudent_id)
-$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/prestudent/(:num)'] = 'api/frontend/v1/stv/Students/getPrestudent/$1/$2';
-// // (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';
// load routes from extensions, also look for environment-specific configs
$subdirs = ['application/config/extensions', 'application/config/' . ENVIRONMENT . '/extensions'];
diff --git a/application/config/stv.php b/application/config/stv.php
index 3090e3f2e..3c318ad9d 100644
--- a/application/config/stv.php
+++ b/application/config/stv.php
@@ -1,6 +1,27 @@
[
+ 'js' => 'path/to/snippet.js', // tabulator config snippet (eg: return { name: 'Name', field: 'fieldname' }; )
+ 'default' => "SQL SELECT statement for value",
+ 'joins' => [
+ // additional joins needed for the SELECT statement above
+ [
+ 'tablename',
+ 'join condition', // single fieldname for USING or full condition for ON
+ 'LEFT|RIGHT', // optional - join type
+ 'after_xxx|before_xxx|end' // optional - position in query
+ ]
+ // ...
+ ]
+ ]
+];
+*/
+
$config['tabs'] =
[
'details' => [
diff --git a/public/js/api/factory/stv/verband.js b/application/config/treemenu.php
similarity index 60%
rename from public/js/api/factory/stv/verband.js
rename to application/config/treemenu.php
index 114931e4c..72a02947b 100644
--- a/public/js/api/factory/stv/verband.js
+++ b/application/config/treemenu.php
@@ -1,5 +1,7 @@
+.
*/
-export default {
- get(path) {
- let url = 'api/frontend/v1/stv/verband';
- if (path)
- url += '/' + path;
- return {
- method: 'get',
- url
- };
- },
- favorites: {
- get() {
- return {
- method: 'get',
- url: 'api/frontend/v1/stv/favorites'
- };
- },
- set(favorites) {
- return {
- method: 'post',
- url: 'api/frontend/v1/stv/favorites/set',
- params: { favorites }
- };
- }
- }
-};
\ No newline at end of file
+if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+$config['stv'] = [
+ "library" => "treemenu/StudVwLib",
+ "permissions" => ["admin:r", "assistenz:r"]
+];
+$config['lvv'] = [
+ "library" => "treemenu/LvVwLib",
+ "permissions" => ["admin:r", "assistenz:r"]
+];
diff --git a/application/config/treemenu/custom/lvvw.php b/application/config/treemenu/custom/lvvw.php
new file mode 100644
index 000000000..a1f270e05
--- /dev/null
+++ b/application/config/treemenu/custom/lvvw.php
@@ -0,0 +1,32 @@
+.
+ */
+
+if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+$config['root'] = [
+ 'stg' => [
+ 'semester' => [
+ /*'group',
+ 'verband' => [
+ 'group'
+ ]*/
+ ],
+ 'orgform'
+ ]
+];
diff --git a/application/config/treemenu/stg_base.php b/application/config/treemenu/stg_base.php
new file mode 100644
index 000000000..fcb9748b7
--- /dev/null
+++ b/application/config/treemenu/stg_base.php
@@ -0,0 +1,65 @@
+.
+ */
+
+if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+$config['root'] = [
+ 'stg' => [
+ 'prestudent' => [
+ 'stdsem' => [
+ 'interessenten' => [
+ 'bewerbungnichtabgeschickt',
+ 'bewerbungabgeschickt',
+ 'zgv',
+ 'statusbestaetigt' => [
+ 'statusbestaetigtrtnichtangemeldet',
+ 'statusbestaetigtrtangemeldet'
+ ],
+ 'reihungstestnichtangemeldet',
+ 'reihungstestangemeldet'
+ ],
+ 'bewerber' => [
+ 'bewerberrtnichtangemeldet',
+ 'bewerberrtangemeldet' => [
+ 'bewerberrtangemeldetteilgenommen',
+ 'bewerberrtangemeldetnichtteilgenommen'
+ ]
+ ],
+ 'aufgenommen',
+ 'warteliste',
+ 'absage',
+ 'incoming'
+ ]
+ ],
+ 'semester' => [
+ 'group',
+ 'verband' => [
+ 'group'
+ ]
+ ]
+ ],
+ 'inout' => [
+ 'incoming',
+ 'outgoing',
+ 'shared_studies'
+ ]
+];
+
+// copy stg tree into stg/orgforms
+$config['root']['stg']['orgform'] = $config['root']['stg'];
diff --git a/application/controllers/Redirect.php b/application/controllers/Redirect.php
new file mode 100644
index 000000000..f4a9f4cd7
--- /dev/null
+++ b/application/controllers/Redirect.php
@@ -0,0 +1,44 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller redirects urls to another location. This is mainly used
+ * with the $routes config
+ */
+class Redirect extends CI_Controller
+{
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Main function to handle all redirects.
+ *
+ * @param string $method - the redirect code (30x)
+ * @param array $params - the url to redirect to
+ *
+ * @return void
+ */
+ public function _remap($method, $params)
+ {
+ redirect($params, 'location', $method);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Favorites.php b/application/controllers/api/frontend/v1/Favorites.php
similarity index 78%
rename from application/controllers/api/frontend/v1/stv/Favorites.php
rename to application/controllers/api/frontend/v1/Favorites.php
index 951eb01a4..787163abb 100644
--- a/application/controllers/api/frontend/v1/stv/Favorites.php
+++ b/application/controllers/api/frontend/v1/Favorites.php
@@ -20,8 +20,8 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the back-end
- * Provides data to the ajax get calls about favorite verbände
- * Listens to ajax post calls to change the favorite verbände data
+ * Provides data to the ajax get calls about favorite treemenu entries
+ * Listens to ajax post calls to change the favorite treemenu entries
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class Favorites extends FHCAPI_Controller
@@ -29,7 +29,7 @@ class Favorites extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
- 'index' => self::PERM_LOGGED,
+ 'get' => self::PERM_LOGGED,
'set' => self::PERM_LOGGED
]);
@@ -37,19 +37,19 @@ class Favorites extends FHCAPI_Controller
$this->load->model('system/Variable_model', 'VariableModel');
}
- public function index()
+ public function get($app)
{
- $result = $this->VariableModel->getVariables(getAuthUID(), ['stv_favorites']);
+ $result = $this->VariableModel->getVariables(getAuthUID(), [$app . '_favorites']);
$data = $this->getDataOrTerminateWithError($result);
if (!$data)
$this->terminateWithSuccess(null);
else
- $this->terminateWithSuccess($data['stv_favorites'] ?? null);
+ $this->terminateWithSuccess($data[$app . '_favorites'] ?? null);
}
- public function set()
+ public function set($app)
{
$this->load->library('form_validation');
@@ -60,7 +60,7 @@ class Favorites extends FHCAPI_Controller
$favorites = $this->input->post('favorites');
- $result = $this->VariableModel->setVariable(getAuthUID(), 'stv_favorites', $favorites);
+ $result = $this->VariableModel->setVariable(getAuthUID(), $app . '_favorites', $favorites);
$this->getDataOrTerminateWithError($result);
diff --git a/application/controllers/api/frontend/v1/Lehrveranstaltung.php b/application/controllers/api/frontend/v1/Lehrveranstaltung.php
index 935602391..66bda9ebf 100644
--- a/application/controllers/api/frontend/v1/Lehrveranstaltung.php
+++ b/application/controllers/api/frontend/v1/Lehrveranstaltung.php
@@ -56,7 +56,9 @@ class Lehrveranstaltung extends FHCAPI_Controller
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
- $lehrveranstaltungen = $this->_ci->LehreinheitModel->getLvsByEmployee($mitarbeiter_uid, $studiensemester_kurzbz, $stg_kz);
+ $studiengang_kz = $this->getStudiengangKz($stg_kz);
+
+ $lehrveranstaltungen = $this->_ci->LehreinheitModel->getLvsByEmployee($mitarbeiter_uid, $studiensemester_kurzbz, $studiengang_kz);
$lehrveranstaltungen_data = $this->getDataOrTerminateWithError($lehrveranstaltungen);
$tree = [];
@@ -75,15 +77,17 @@ class Lehrveranstaltung extends FHCAPI_Controller
$this->terminateWithSuccess($tree);
}
- public function getByStg($studiensemester_kurzbz = null, $studiengang_kz = null, $semester = null)
+ public function getByStg($studiensemester_kurzbz = null, $stg_kz = null, $semester = null)
{
+ $studiengang_kz = $this->getStudiengangKz($stg_kz);
+
if (is_null($studiengang_kz) || !preg_match("/^-?[1-9][0-9]*$/", (string)$studiengang_kz))
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
$verband = null;
if (!is_null($semester) && !is_numeric($semester))
{
- $verband = $semester;
+ $verband = $this->getOrgformKurzbz($semester);
$semester = null;
}
@@ -260,18 +264,53 @@ class Lehrveranstaltung extends FHCAPI_Controller
}
}
+ protected function getStudiengangKz($studiengang_typ_kurzbz)
+ {
+ $this->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ $result = $this->StudiengangModel->loadWhere([
+ 'LOWER(CONCAT(typ, kurzbz)) =' => strtolower($studiengang_typ_kurzbz)
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if (!$data)
+ return null;
+
+ return current($data)->studiengang_kz;
+ }
+
private function getStudiensemesterKurzbz($studiensemester_kurzbz = null)
{
if (!is_null($studiensemester_kurzbz))
{
- $studiensemester_result = $this->_ci->StudiensemesterModel->load($studiensemester_kurzbz);
+ $studiensemester_result = $this->_ci->StudiensemesterModel->loadWhere([
+ 'LOWER(studiensemester_kurzbz)' => strtolower($studiensemester_kurzbz)
+ ]);
if (isError($studiensemester_result) || !hasData($studiensemester_result))
- $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
+ $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
return getData($studiensemester_result)[0]->studiensemester_kurzbz;
}
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
}
+
+ protected function getOrgformKurzbz($orgform_kurzbz)
+ {
+ if ($orgform_kurzbz === null)
+ return null;
+
+ $this->load->model('codex/Orgform_model', 'OrgformModel');
+ $result = $this->OrgformModel->loadWhere([
+ 'LOWER(orgform_kurzbz) =' => strtolower($orgform_kurzbz)
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if (!$data)
+ return $orgform_kurzbz;
+
+ return current($data)->orgform_kurzbz;
+ }
}
diff --git a/application/controllers/api/frontend/v1/Treemenu.php b/application/controllers/api/frontend/v1/Treemenu.php
new file mode 100644
index 000000000..e25610370
--- /dev/null
+++ b/application/controllers/api/frontend/v1/Treemenu.php
@@ -0,0 +1,148 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+use \ReflectionMethod as ReflectionMethod;
+use \ReflectionFunction as ReflectionFunction;
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about menues
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Treemenu extends FHCAPI_Controller
+{
+ public function __construct()
+ {
+ // Load Router
+ $router = load_class('Router');
+
+ // Load Config
+ $config = load_class('Config');
+ $config->load('treemenu');
+
+ // Get Treemenu name & config
+ $name = $router->method;
+ $conf = $config->item($name);
+
+ // Get Permissions from config
+ $permissions = $conf['permissions'] ?? self::PERM_ANONYMOUS;
+
+ // Call constructor
+ parent::__construct([
+ $name => $permissions
+ ]);
+
+ // Load Library
+ $libraryName = $conf['library'] ?? null;
+ $this->load->library($libraryName, null, 'treemenulib');
+ }
+
+ /**
+ * @param string $method
+ * @param array $params (optional)
+ *
+ * @return void
+ */
+ public function _remap($method, $params = [])
+ {
+ if (!$this->treemenulib)
+ show_404();
+
+ $this->addMeta('ci_method', $method);
+ $this->addMeta('ci_params', $params);
+
+ $params = $this->uri->uri_to_assoc(6); // 6 = start of $params
+ $config = $this->treemenulib->config;
+
+ foreach (array_keys($params) as $key) {
+ if (!isset($config[$key]) || !$config[$key])
+ show_404();
+
+ $config = $config[$key];
+ }
+
+ // Prepare aliases
+ $argumentaliases = [];
+ if (property_exists($this->treemenulib, 'path_to_argument'))
+ $argumentaliases = array_flip($this->treemenulib->path_to_argument);
+ $methodaliases = [];
+ if (property_exists($this->treemenulib, 'redirect_method'))
+ $methodaliases = $this->treemenulib->redirect_method;
+
+ $items = [];
+ foreach ($config as $uripart => $children) {
+ if (!is_array($children)) {
+ $uripart = $children;
+ $children = [];
+ }
+
+ $methodName = $uripart;
+ if (isset($methodaliases[$methodName])) {
+ $methodName = $methodaliases[$methodName];
+ } elseif (strpbrk($methodName, ' _-') !== false) {
+ $methodName = lcfirst(str_replace([' ', '_', '-'], '', ucwords($methodName, " \t\r\n\f\v_-")));
+ }
+
+ // Prepare arguments
+ if (is_callable($methodName, false, $name)) {
+ if (is_string($methodName) && is_callable([$this->treemenulib, $methodName]))
+ $callable = [$this->treemenulib, $methodName];
+ else
+ $callable = $methodName;
+ } else {
+ $callable = [$this->treemenulib, $methodName];
+ }
+
+ if (is_array($callable))
+ $reflection = new ReflectionMethod($callable[0], $callable[1]);
+ elseif (is_string($callable) && strstr($callable, '::'))
+ $reflection = new ReflectionMethod($callable);
+ elseif ($name != 'Closure::__invoke' && strstr($name, '::__invoke'))
+ $reflection = new ReflectionMethod($callable, '__invoke');
+ else
+ $reflection = new ReflectionFunction($callable);
+
+ $arguments = [];
+ foreach ($reflection->getParameters() as $arg) {
+ if ($arg->name == 'path_template') {
+ $path = $params;
+ $path[$uripart] = '%s';
+ $arguments[] = $this->uri->assoc_to_uri($path);
+ } elseif ($arg->name == 'has_children') {
+ $arguments[] = $children;
+ } elseif ($arg->name == 'original_method') {
+ $arguments[] = $uripart;
+ } elseif (isset($argumentaliases[$arg->name]) && isset($params[$argumentaliases[$arg->name]])) {
+ $arguments[] = $params[$argumentaliases[$arg->name]];
+ } elseif (isset($params[$arg->name])) {
+ $arguments[] = $params[$arg->name];
+ } else {
+ $arguments[] = null;
+ }
+ }
+
+ // Call function from lib
+ $items = array_merge($items, call_user_func_array($callable, $arguments));
+ }
+
+ $this->terminateWithSuccess($items);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/lv/Favorites.php b/application/controllers/api/frontend/v1/lv/Favorites.php
deleted file mode 100644
index 080a4ec6e..000000000
--- a/application/controllers/api/frontend/v1/lv/Favorites.php
+++ /dev/null
@@ -1,47 +0,0 @@
- self::PERM_LOGGED,
- 'set' => self::PERM_LOGGED
- ]);
-
- // Load models
- $this->load->model('system/Variable_model', 'VariableModel');
- }
-
- public function index()
- {
- $result = $this->VariableModel->getVariables(getAuthUID(), ['lv_favorites']);
-
- $data = $this->getDataOrTerminateWithError($result);
-
- if (!$data)
- $this->terminateWithSuccess(null);
- else
- $this->terminateWithSuccess(isset($data['lv_favorites']) ? $data['lv_favorites'] : null);
- }
-
- public function set()
- {
- $this->load->library('form_validation');
-
- $this->form_validation->set_rules('favorites', 'Favorites', 'required');
-
- if (!$this->form_validation->run())
- $this->terminateWithValidationErrors($this->form_validation->error_array());
-
- $favorites = $this->input->post('favorites');
-
- $result = $this->VariableModel->setVariable(getAuthUID(), 'lv_favorites', $favorites);
-
- $this->getDataOrTerminateWithError($result);
-
- $this->terminateWithSuccess(true);
- }
-}
diff --git a/application/controllers/api/frontend/v1/lv/StgTree.php b/application/controllers/api/frontend/v1/lv/StgTree.php
deleted file mode 100644
index 8272da978..000000000
--- a/application/controllers/api/frontend/v1/lv/StgTree.php
+++ /dev/null
@@ -1,117 +0,0 @@
-method] = ['admin:r', 'assistenz:r'];
- parent::__construct($permissions);
-
- $this->load->model('organisation/Studiengang_model', 'StudiengangModel');
- }
-
- public function _remap($method, $params = [])
- {
- if ($method == '' || $method == 'index')
- return $this->getBase();
-
- if (!$this->permissionlib->isBerechtigt('assistenz', 's', $method)
- && !$this->permissionlib->isBerechtigt('admin', 's', $method)
- ) {
- return $this->_outputAuthError([$method => ['admin:r', 'assistenz:r']]);
- }
-
- return $this->getStudiengang($method);
- show_404();
- }
-
- protected function getBase()
- {
- $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
-
- $this->StudiengangModel->addDistinct();
- $this->StudiengangModel->addSelect("v.studiengang_kz AS link");
- $this->StudiengangModel->addSelect(
- "CONCAT(kurzbzlang, ' (', UPPER(CONCAT(typ, kurzbz)), ') - ', tbl_studiengang.bezeichnung) AS name",
- false
- );
- $this->StudiengangModel->addSelect('erhalter_kz');
- $this->StudiengangModel->addSelect('typ');
- $this->StudiengangModel->addSelect('kurzbz');
- $this->StudiengangModel->addSelect('studiengang_kz');
- $this->StudiengangModel->addSelect('studiengang_kz AS stg_kz');
-
- $this->StudiengangModel->addOrder('erhalter_kz');
- $this->StudiengangModel->addOrder('typ');
- $this->StudiengangModel->addOrder('kurzbz');
-
- $stgs = $this->permissionlib->getSTG_isEntitledFor('admin') ?: [];
- $stgs = array_merge($stgs, $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
-
- if (!$stgs)
- $this->terminateWithSuccess([]);
-
- $this->StudiengangModel->db->where_in('studiengang_kz', $stgs);
-
- $result = $this->StudiengangModel->loadWhere(['v.aktiv' => true]);
-
- $list = $this->getDataOrTerminateWithError($result);
-
- $this->terminateWithSuccess($list);
- }
-
- protected function getStudiengang($studiengang_kz)
- {
- $link = $studiengang_kz . '/';
-
- $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
-
- $this->StudiengangModel->addDistinct();
- $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", semester) AS link", false);
- $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester ORDER BY verband, gruppe LIMIT 1)) AS name", false);
- $this->StudiengangModel->addSelect("TRUE AS leaf", false);
-
- $this->StudiengangModel->addSelect('semester');
- $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
-
- $this->StudiengangModel->addOrder('semester');
-
- $result = $this->StudiengangModel->loadWhere([
- 'v.studiengang_kz' => $studiengang_kz,
- 'v.aktiv' => true
- ]);
- $list = $this->getDataOrTerminateWithError($result);
-
- $result = $this->StudiengangModel->load($studiengang_kz);
- $result = $this->getDataOrTerminateWithError($result);
- if ($result)
- {
- if (current($result)->mischform)
- {
- $this->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
-
- $this->StudienordnungModel->addDistinct();
- $this->StudienordnungModel->addSelect("CONCAT(studiengang_kz, '/', p.orgform_kurzbz) AS link");
- $this->StudienordnungModel->addSelect("p.orgform_kurzbz AS name");
- $this->StudienordnungModel->addSelect("TRUE as leaf", false);
-
- $this->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id');
-
- $result = $this->StudienordnungModel->loadWhere([
- 'aktiv' => true,
- 'studiengang_kz' => $studiengang_kz,
- 'p.orgform_kurzbz !=' => 'DDP'
- ]);
- $result = $this->getDataOrTerminateWithError($result);
-
- $list = array_merge($list, $result);
- }
- }
-
- $this->terminateWithSuccess($list);
- }
-}
diff --git a/application/controllers/api/frontend/v1/organisation/Studiensemester.php b/application/controllers/api/frontend/v1/organisation/Studiensemester.php
index 3c6b72d2f..eaafc6ac5 100644
--- a/application/controllers/api/frontend/v1/organisation/Studiensemester.php
+++ b/application/controllers/api/frontend/v1/organisation/Studiensemester.php
@@ -26,7 +26,9 @@ 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,
+ 'current' => self::PERM_LOGGED,
+ 'set' => self::PERM_LOGGED
)
);
// Load model StudiensemesterModel
@@ -166,4 +168,39 @@ class Studiensemester extends FHCAPI_Controller
$this->terminateWithSuccess(array($studiensemester, $aktuell));
}
+
+ public function current()
+ {
+ $result = $this->StudiensemesterModel->getNearest();
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if (!$data)
+ $this->terminateWithError('Kein Studiensemester aktiv');
+ if (count($data) > 1)
+ $this->terminateWithError('Mehrere Studiensemester aktiv');
+
+ $this->terminateWithSuccess(current($data)->studiensemester_kurzbz);
+ }
+
+ public function set()
+ {
+ $this->load->library('AuthLib');
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $stdsem = $this->input->post('studiensemester_kurzbz');
+
+ $this->load->model('system/Variable_model', 'VariableModel');
+
+ $result = $this->VariableModel->setVariable(getAuthUID(), 'semester_aktuell', $stdsem);
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess(true);
+ }
}
diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php
index e77e20889..e97d81571 100644
--- a/application/controllers/api/frontend/v1/stv/Students.php
+++ b/application/controllers/api/frontend/v1/stv/Students.php
@@ -247,47 +247,54 @@ class Students extends FHCAPI_Controller
}
public function getPrestudents(
- $studiengang_kz,
+ $studiengang_typ_kurzbz,
$studiensemester_kurzbz = null,
$filter = null
) {
$this->addMeta('ci_method', __FUNCTION__);
$this->addMeta('ci_params', array(
- 'studiengang_kz' => $studiengang_kz,
+ 'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'filter' => $filter
));
- $this->fetchPrestudents($studiengang_kz, $studiensemester_kurzbz, $filter);
+ $this->fetchPrestudents($studiengang_typ_kurzbz, $studiensemester_kurzbz, $filter);
}
public function getPrestudentsOrgform(
- $studiengang_kz,
+ $studiengang_typ_kurzbz,
$orgform_kurzbz,
$studiensemester_kurzbz = null,
$filter = null
) {
$this->addMeta('ci_method', __FUNCTION__);
$this->addMeta('ci_params', array(
- 'studiengang_kz' => $studiengang_kz,
+ 'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'filter' => $filter,
'orgform_kurzbz' => $orgform_kurzbz
));
- $this->fetchPrestudents($studiengang_kz, $studiensemester_kurzbz, $filter, $orgform_kurzbz);
+ $this->fetchPrestudents($studiengang_typ_kurzbz, $studiensemester_kurzbz, $filter, $orgform_kurzbz);
}
/**
- * @param integer $studiengang_kz
+ * @param string $studiengang_typ_kurzbz
* @param string $studiensemester_kurzbz (optional)
* @param string $filter (optional)
* @param string $orgform_kurzbz (optional)
*
* @return void
*/
- protected function fetchPrestudents($studiengang_kz, $studiensemester_kurzbz = null, $filter = null, $orgform_kurzbz = null)
+ protected function fetchPrestudents($studiengang_typ_kurzbz, $studiensemester_kurzbz = null, $filter = null, $orgform_kurzbz = null)
{
+ $studiengang_kz = $this->getStudiengangKz($studiengang_typ_kurzbz);
+ $studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
+ $orgform_kurzbz = $this->getOrgformKurzbz($orgform_kurzbz);
+
+ if ($studiengang_kz === null)
+ show_404();
+
$stdsemEsc = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL';
$selectRT = "
@@ -453,7 +460,7 @@ class Students extends FHCAPI_Controller
public function getStudents(
$studiensemester_kurzbz,
- $studiengang_kz,
+ $studiengang_typ_kurzbz,
$semester = null,
$verband = null,
$gruppe = null
@@ -461,18 +468,18 @@ class Students extends FHCAPI_Controller
$this->addMeta('ci_method', __FUNCTION__);
$this->addMeta('ci_params', array(
'studiensemester_kurzbz' => $studiensemester_kurzbz,
- 'studiengang_kz' => $studiengang_kz,
+ 'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'semester' => $semester,
'verband' => $verband,
'gruppe' => $gruppe
));
- $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, $verband, $gruppe, null, null);
+ $this->fetchStudents($studiensemester_kurzbz, $studiengang_typ_kurzbz, $semester, $verband, $gruppe, null, null);
}
public function getStudentsOrgform(
$studiensemester_kurzbz,
- $studiengang_kz,
+ $studiengang_typ_kurzbz,
$orgform_kurzbz,
$semester = null,
$verband = null,
@@ -481,37 +488,37 @@ class Students extends FHCAPI_Controller
$this->addMeta('ci_method', __FUNCTION__);
$this->addMeta('ci_params', array(
'studiensemester_kurzbz' => $studiensemester_kurzbz,
- 'studiengang_kz' => $studiengang_kz,
+ 'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'orgform_kurzbz' => $orgform_kurzbz,
'semester' => $semester,
'verband' => $verband,
'gruppe' => $gruppe
));
- $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, $verband, $gruppe, null, $orgform_kurzbz);
+ $this->fetchStudents($studiensemester_kurzbz, $studiengang_typ_kurzbz, $semester, $verband, $gruppe, null, $orgform_kurzbz);
}
public function getStudentsSpezialgruppe(
$studiensemester_kurzbz,
- $studiengang_kz,
+ $studiengang_typ_kurzbz,
$semester,
$gruppe_kurzbz
) {
$this->addMeta('ci_method', __FUNCTION__);
$this->addMeta('ci_params', array(
'studiensemester_kurzbz' => $studiensemester_kurzbz,
- 'studiengang_kz' => $studiengang_kz,
+ 'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'semester' => $semester,
'gruppe_kurzbz' => $gruppe_kurzbz
));
- $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, null, null, $gruppe_kurzbz, null);
+ $this->fetchStudents($studiensemester_kurzbz, $studiengang_typ_kurzbz, $semester, null, null, $gruppe_kurzbz, null);
}
public function getStudentsOrgformSpezialgruppe(
$studiensemester_kurzbz,
$orgform_kurzbz,
- $studiengang_kz,
+ $studiengang_typ_kurzbz,
$semester,
$gruppe_kurzbz
) {
@@ -519,17 +526,17 @@ class Students extends FHCAPI_Controller
$this->addMeta('ci_params', array(
'studiensemester_kurzbz' => $studiensemester_kurzbz,
'orgform_kurzbz' => $orgform_kurzbz,
- 'studiengang_kz' => $studiengang_kz,
+ 'studiengang_typ_kurzbz' => $studiengang_typ_kurzbz,
'semester' => $semester,
'gruppe_kurzbz' => $gruppe_kurzbz
));
- $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, null, null, $gruppe_kurzbz, $orgform_kurzbz);
+ $this->fetchStudents($studiensemester_kurzbz, $studiengang_typ_kurzbz, $semester, null, null, $gruppe_kurzbz, $orgform_kurzbz);
}
/**
- * @param integer $studiengang_kz
* @param string $studiensemester_kurzbz
+ * @param string $studiengang_typ_kurzbz
* @param integer $semester (optional)
* @param string $verband (optional)
* @param integer $gruppe (optional)
@@ -540,13 +547,20 @@ class Students extends FHCAPI_Controller
*/
protected function fetchStudents(
$studiensemester_kurzbz,
- $studiengang_kz,
+ $studiengang_typ_kurzbz,
$semester = null,
$verband = null,
$gruppe = null,
$gruppe_kurzbz = null,
$orgform_kurzbz = null
) {
+ $studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
+ $studiengang_kz = $this->getStudiengangKz($studiengang_typ_kurzbz);
+ $orgform_kurzbz = $this->getOrgformKurzbz($orgform_kurzbz);
+
+ if ($studiengang_kz === null)
+ show_404();
+
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
@@ -626,6 +640,8 @@ class Students extends FHCAPI_Controller
'prestudent_id' => $prestudent_id,
));
+ $studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
+
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
@@ -670,6 +686,8 @@ class Students extends FHCAPI_Controller
'student_uid' => $student_uid,
));
+ $studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
+
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
@@ -704,6 +722,8 @@ class Students extends FHCAPI_Controller
'person_id' => $person_id,
));
+ $studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
+
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
@@ -818,4 +838,55 @@ class Students extends FHCAPI_Controller
}
}
}
+
+ protected function getStudiengangKz($studiengang_typ_kurzbz)
+ {
+ $this->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ $result = $this->StudiengangModel->loadWhere([
+ 'LOWER(CONCAT(typ, kurzbz)) =' => strtolower($studiengang_typ_kurzbz)
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if (!$data)
+ return null;
+
+ return current($data)->studiengang_kz;
+ }
+
+ protected function getStudiensemesterKurzbz($studiensemester_kurzbz)
+ {
+ if ($studiensemester_kurzbz === null)
+ return null;
+
+ $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+ $result = $this->StudiensemesterModel->loadWhere([
+ 'LOWER(studiensemester_kurzbz) =' => strtolower($studiensemester_kurzbz)
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if (!$data)
+ return $studiensemester_kurzbz;
+
+ return current($data)->studiensemester_kurzbz;
+ }
+
+ protected function getOrgformKurzbz($orgform_kurzbz)
+ {
+ if ($orgform_kurzbz === null)
+ return null;
+
+ $this->load->model('codex/Orgform_model', 'OrgformModel');
+ $result = $this->OrgformModel->loadWhere([
+ 'LOWER(orgform_kurzbz) =' => strtolower($orgform_kurzbz)
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if (!$data)
+ return $orgform_kurzbz;
+
+ return current($data)->orgform_kurzbz;
+ }
}
diff --git a/application/controllers/api/frontend/v1/stv/Verband.php b/application/controllers/api/frontend/v1/stv/Verband.php
deleted file mode 100644
index 32ef30a45..000000000
--- a/application/controllers/api/frontend/v1/stv/Verband.php
+++ /dev/null
@@ -1,513 +0,0 @@
-.
- */
-
-if (! defined('BASEPATH')) exit('No direct script access allowed');
-
-/**
- * This controller operates between (interface) the JS (GUI) and the back-end
- * Provides data to the ajax get calls about verbände
- * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
- */
-class Verband extends FHCAPI_Controller
-{
- public function __construct()
- {
- $permissions = [];
- $router = load_class('Router');
- $permissions[$router->method] = ['admin:r', 'assistenz:r'];
- parent::__construct($permissions);
-
- // Load Models
- $this->load->model('organisation/Studiengang_model', 'StudiengangModel');
- }
-
- /**
- * Remap calls:
- * /
- * /(studiengang_kz) => getStudiengang
- * /(studiengang_kz)/(semester) => getSemester
- * /(studiengang_kz)/(semester)/(verband) => getVerband
- * /(studiengang_kz)/(org_form) => getStudiengang
- * /(studiengang_kz)/(org_form)/(semester) => getSemester
- * /(studiengang_kz)/(org_form)/(semester)/(verband) => getVerband
- *
- * @param string $method
- * @param array $params (optional)
- *
- * @return void
- */
- public function _remap($method, $params = [])
- {
- if ($method == '' || $method == 'index')
- return $this->getBase();
-
- // NOTE(chris): Test if access is allowed ($method is the Studiengang)
- if (!$this->permissionlib->isBerechtigt('assistenz', 's', $method)
- && !$this->permissionlib->isBerechtigt('admin', 's', $method)
- ) {
- return $this->_outputAuthError([$method => ['admin:r', 'assistenz:r']]);
- }
-
- $count = count($params);
- if (!$count)
- return $this->getStudiengang($method);
-
- if ($count == 1) {
- if (is_numeric($params[0]))
- return $this->getSemester($method, $params[0]);
- elseif ($params[0] == 'prestudent')
- return $this->terminateWithSuccess($this->getStdSem($method . '/prestudent/', $method));
- else
- return $this->getStudiengang($method, $params[0]);
- }
- if ($count == 2) {
- if (is_numeric($params[0]))
- return $this->getVerband($method, $params[0], $params[1]);
- elseif ($params[1] == 'prestudent')
- return $this->terminateWithSuccess($this->getStdSem($method . '/' . $params[0] . '/prestudent/', $method));
- else
- return $this->getSemester($method, $params[1], $params[0]);
- }
- if ($count == 3 && !is_numeric($params[0]) && is_numeric($params[1]) && !is_numeric($params[2]))
- return $this->getVerband($method, $params[1], $params[2], $params[0]);
-
- show_404();
- }
-
- /**
- * @return void
- */
- protected function getBase()
- {
- $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
-
- $this->StudiengangModel->addDistinct();
- $this->StudiengangModel->addSelect("v.studiengang_kz AS link");
- $this->StudiengangModel->addSelect(
- "CONCAT(kurzbzlang, ' (', UPPER(CONCAT(typ, kurzbz)), ') - ', tbl_studiengang.bezeichnung) AS name",
- false
- );
- $this->StudiengangModel->addSelect('erhalter_kz');
- $this->StudiengangModel->addSelect('typ');
- $this->StudiengangModel->addSelect('kurzbz');
- $this->StudiengangModel->addSelect('studiengang_kz');
- $this->StudiengangModel->addSelect('studiengang_kz AS stg_kz');
-
- $this->StudiengangModel->addOrder('erhalter_kz');
- $this->StudiengangModel->addOrder('typ');
- $this->StudiengangModel->addOrder('kurzbz');
-
- $stgs = $this->permissionlib->getSTG_isEntitledFor('admin') ?: [];
- $stgs = array_merge($stgs, $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
-
- if (!$stgs)
- $this->terminateWithSuccess([]);
-
- $this->StudiengangModel->db->where_in('studiengang_kz', $stgs);
-
- $result = $this->StudiengangModel->loadWhere(['v.aktiv' => true]);
-
- $list = $this->getDataOrTerminateWithError($result);
-
- if ($this->permissionlib->isBerechtigt('inout/uebersicht'))
- $list[] = [
- 'name' => 'International',
- 'link' => 'inout',
- 'children' => [
- [
- 'name' => 'Incoming',
- 'link' => 'inout/incoming',
- 'leaf' => true
- ],
- [
- 'name' => 'Outgoing',
- 'link' => 'inout/outgoing',
- 'leaf' => true
- ],
- [
- 'name' => 'Gemeinsame Studien',
- 'link' => 'inout/gemeinsamestudien',
- 'leaf' => true
- ]
- ]
- ];
- $this->terminateWithSuccess($list);
- }
-
- /**
- * @param integer $studiengang_kz
- * @param string $orgform (optional)
- *
- * @return void
- */
- protected function getStudiengang($studiengang_kz, $org_form = null)
- {
- $link = $studiengang_kz . '/';
- if ($org_form !== null)
- $link .= $org_form . '/';
-
- $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
-
- $this->StudiengangModel->addDistinct();
- $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", semester) AS link", false);
- $this->StudiengangModel->addSelect("CONCAT(
- UPPER(CONCAT(typ, kurzbz)),
- '-',
- semester,
- (
- SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END
- FROM public.tbl_lehrverband
- WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester
- ORDER BY verband, gruppe LIMIT 1
- )
- ) AS name", false);
-
- $this->StudiengangModel->addSelect('semester');
- $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
-
- $this->StudiengangModel->addOrder('semester');
-
- if ($org_form !== null) {
- $this->StudiengangModel->addSelect("v.orgform_kurzbz");
- $this->StudiengangModel->db->group_start();
- $this->StudiengangModel->db->where('v.semester', 0);
- $this->StudiengangModel->db->or_where('v.orgform_kurzbz', $org_form);
- $this->StudiengangModel->db->group_end();
- }
-
- $result = $this->StudiengangModel->loadWhere([
- 'v.studiengang_kz' => $studiengang_kz,
- 'v.aktiv' => true
- ]);
- $list = $this->getDataOrTerminateWithError($result);
-
- array_unshift($list, [
- 'name' => 'PreStudent',
- 'link' => $link . 'prestudent',
- 'no_sem_reload' => true,
- 'stg_kz' => (int)$studiengang_kz,
- 'children' => $this->getStdSem($link . 'prestudent/', $studiengang_kz)
- ]);
-
- if ($org_form === null) {
- // NOTE(chris): if mischform show orgforms
- $result = $this->StudiengangModel->load($studiengang_kz);
- $result = $this->getDataOrTerminateWithError($result);
- if ($result) {
- if (current($result)->mischform) {
- $this->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
-
- $this->StudienordnungModel->addDistinct();
- $this->StudienordnungModel->addSelect("CONCAT(studiengang_kz, '/', p.orgform_kurzbz) AS link");
- $this->StudienordnungModel->addSelect("p.orgform_kurzbz AS name");
- $this->StudienordnungModel->addSelect("studiengang_kz AS stg_kz");
-
- $this->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id');
-
- $result = $this->StudienordnungModel->loadWhere([
- 'aktiv' => true,
- 'studiengang_kz' => $studiengang_kz,
- 'p.orgform_kurzbz !=' => 'DDP'
- ]);
- $result = $this->getDataOrTerminateWithError($result);
-
- $list = array_merge($list, $result);
- }
- }
- }
- $this->terminateWithSuccess($list);
- }
-
- /**
- * @param integer $studiengang_kz
- * @param integer $semester
- * @param string $orgform
- *
- * @return void
- */
- protected function getSemester($studiengang_kz, $semester, $org_form = null)
- {
- $link = $studiengang_kz . '/';
- if ($org_form !== null)
- $link .= $org_form . '/';
- $link .= $semester . '/';
-
-
- $this->load->model('organisation/Gruppe_model', 'GruppeModel');
-
- $this->GruppeModel->addDistinct();
- $this->GruppeModel->addSelect("CONCAT(" . $this->GruppeModel->escape($link . 'grp/') . ", gruppe_kurzbz) AS link", false);
- $this->GruppeModel->addSelect("CONCAT(gruppe_kurzbz, ' (', bezeichnung, ')') AS name", false);
- $this->GruppeModel->addSelect("TRUE AS leaf", false);
-
- $this->GruppeModel->addSelect('sort');
- $this->GruppeModel->addSelect('gruppe_kurzbz');
- $this->GruppeModel->addSelect($this->GruppeModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
-
- $this->GruppeModel->addOrder('sort');
- $this->GruppeModel->addOrder('gruppe_kurzbz');
-
- $where = [
- 'studiengang_kz' => $studiengang_kz,
- 'semester' => $semester,
- 'lehre' => true,
- 'sichtbar' => true,
- 'aktiv' => true,
- 'direktinskription' => false
- ];
-
- if ($org_form !== null)
- $where['orgform_kurzbz'] = $org_form;
-
- $result = $this->GruppeModel->loadWhere($where);
-
- $list = $this->getDataOrTerminateWithError($result);
-
- $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
-
- $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", verband) AS link", false);
- $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, verband, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester AND verband=v.verband ORDER BY gruppe LIMIT 1)) AS name", false);
- $this->StudiengangModel->addSelect("CASE WHEN MAX(gruppe)='' OR MAX(gruppe)=' ' THEN TRUE ELSE FALSE END AS leaf");
-
- $this->StudiengangModel->addSelect($this->StudiengangModel->escape($semester) . ' AS semester');
- $this->StudiengangModel->addSelect('verband');
- $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
-
- $this->StudiengangModel->addOrder('verband');
-
- $this->StudiengangModel->addGroupBy('link, name, verband');
-
- $where = [
- 'v.studiengang_kz' => $studiengang_kz,
- 'v.semester' => $semester,
- 'v.verband !=' => '',
- 'v.aktiv' => true
- ];
-
- if ($org_form !== null && $semester) // NOTE(chris): on semester 0 show all?
- $where['v.orgform_kurzbz'] = $org_form;
-
- $result = $this->StudiengangModel->loadWhere($where);
- $result = $this->getDataOrTerminateWithError($result);
-
- $list = array_merge($list, $result);
-
- $this->terminateWithSuccess($list);
- }
-
- /**
- * @param integer $studiengang_kz
- * @param integer $semester
- * @param integer $verband
- * @param string $orgform
- *
- * @return void
- */
- protected function getVerband($studiengang_kz, $semester, $verband, $org_form = null)
- {
- $link = $studiengang_kz . '/';
- if ($org_form !== null)
- $link .= $org_form . '/';
- $link .= $semester . '/'. $verband . '/';
-
-
- $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
-
- $this->StudiengangModel->addDistinct();
- $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", gruppe) AS link", false);
- $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, verband, gruppe, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester AND verband=v.verband AND gruppe=v.gruppe ORDER BY gruppe LIMIT 1)) AS name", false);
- $this->StudiengangModel->addSelect("TRUE AS leaf", false);
-
- $this->StudiengangModel->addSelect('v.semester');
- $this->StudiengangModel->addSelect('v.verband');
- $this->StudiengangModel->addSelect('gruppe');
- $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
-
- $this->StudiengangModel->addOrder('gruppe');
-
- $where = [
- 'v.studiengang_kz' => $studiengang_kz,
- 'v.semester' => $semester,
- 'v.verband' => $verband,
- 'v.gruppe !=' => '',
- 'v.aktiv' => true
- ];
-
- if ($org_form !== null && $semester) // NOTE(chris): on semester 0 show all?
- $where['v.orgform_kurzbz'] = $org_form;
-
- $result = $this->StudiengangModel->loadWhere($where);
-
- $list = $this->getDataOrTerminateWithError($result);
-
- $this->terminateWithSuccess($list);
- }
-
- /**
- * @param string $link
- * @param integer $studiengang_kz
- *
- * @return array
- */
- protected function getStdSem($link, $studiengang_kz)
- {
- $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
-
- $this->load->model('system/Variable_model', 'VariableModel');
- $result = $this->VariableModel->getVariables(getAuthUID(), ['number_displayed_past_studiensemester']);
- $data = $this->getDataOrTerminateWithError($result);
-
- $this->load->config('stv');
- $number_displayed_past_studiensemester_default = $this->config->item('number_displayed_past_studiensemester_default');
-
- $number_displayed_past_studiensemester = $data['number_displayed_past_studiensemester'] ?? $number_displayed_past_studiensemester_default;
-
- $this->StudiensemesterModel->addPlusMinus(null, $number_displayed_past_studiensemester);
- $this->StudiensemesterModel->addOrder('ende');
- $result = $this->StudiensemesterModel->load();
-
- $studiensemester = $this->getDataOrTerminateWithError($result);
- $result = [];
-
- $studiengang_kz = (int)$studiengang_kz;
-
- foreach ($studiensemester as $sem) {
- $semlink = $link . $sem->studiensemester_kurzbz;
- $intlink = $semlink . '/interessenten';
- $result[] = [
- 'name' => $sem->studiensemester_kurzbz,
- 'link' => $semlink,
- 'stg_kz' => $studiengang_kz,
- 'children' => [
- [
- 'name' => 'Interessenten',
- 'link' => $intlink,
- 'stg_kz' => $studiengang_kz,
- 'children' => [
- [
- 'name' => 'Bewerbung nicht abgeschickt',
- 'link' => $intlink . '/bewerbungnichtabgeschickt',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ],
- [
- 'name' => 'Bewerbung abgeschickt, Status unbestätigt',
- 'link' => $intlink . '/bewerbungabgeschickt',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ],
- [
- 'name' => 'ZGV erfüllt',
- 'link' => $intlink . '/zgv',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ],
- [
- 'name' => 'Status bestätigt',
- 'link' => $intlink . '/statusbestaetigt',
- 'stg_kz' => $studiengang_kz,
- 'children' => [
- [
- 'name' => 'Nicht zum Reihungstest angemeldet',
- 'link' => $intlink . '/statusbestaetigtrtnichtangemeldet',
- 'leaf' => true
- ],
- [
- 'name' => 'Reihungstest angemeldet',
- 'link' => $intlink . '/statusbestaetigtrtangemeldet',
- 'leaf' => true
- ]
- ]
- ],
- [
- 'name' => 'Nicht zum Reihungstest angemeldet',
- 'link' => $intlink . '/reihungstestnichtangemeldet',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ],
- [
- 'name' => 'Reihungstest angemeldet',
- 'link' => $intlink . '/reihungstestangemeldet',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ]
- ]
- ],
- [
- 'name' => 'Bewerber',
- 'link' => $semlink . '/bewerber',
- 'stg_kz' => $studiengang_kz,
- 'children' => [
- [
- 'name' => 'Nicht zum Reihungstest angemeldet',
- 'link' => $intlink . '/bewerberrtnichtangemeldet',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ],
- [
- 'name' => 'Reihungstest angemeldet',
- 'link' => $intlink . '/bewerberrtangemeldet',
- 'stg_kz' => $studiengang_kz,
- 'children' => [
- [
- 'name' => 'Teilgenommen',
- 'link' => $intlink . '/bewerberrtangemeldetteilgenommen',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ],
- [
- 'name' => 'Nicht teilgenommen',
- 'link' => $intlink . '/bewerberrtangemeldetnichtteilgenommen',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ]
- ]
- ]
- ]
- ],
- [
- 'name' => 'Aufgenommen',
- 'link' => $semlink . '/aufgenommen',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ],
- [
- 'name' => 'Warteliste',
- 'link' => $semlink . '/warteliste',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ],
- [
- 'name' => 'Absage',
- 'link' => $semlink . '/absage',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ],
- [
- 'name' => 'Incoming',
- 'link' => $semlink . '/incoming',
- 'stg_kz' => $studiengang_kz,
- 'leaf' => true
- ]
- ]
- ];
- }
-
- return $result;
- }
-}
diff --git a/application/controllers/components/stv/Studiensemester.php b/application/controllers/components/stv/Studiensemester.php
deleted file mode 100644
index c3db99686..000000000
--- a/application/controllers/components/stv/Studiensemester.php
+++ /dev/null
@@ -1,78 +0,0 @@
- self::PERM_LOGGED,
- 'now' => self::PERM_LOGGED,
- 'set' => self::PERM_LOGGED
- ]);
- }
-
- public function index()
- {
- $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
-
- $this->StudiensemesterModel->addOrder('start');
-
- $result = $this->StudiensemesterModel->load();
-
- if (isError($result)) {
- $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
- }
- $this->outputJson($result);
- }
-
- public function now()
- {
- $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
-
- $result = $this->StudiensemesterModel->getNearest();
-
- if (isError($result)) {
- $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
- $this->outputJson(getError($result));
- }
- $result = getData($result) ?: [];
-
- if (count($result) != 1) {
- $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
- $this->outputJsonError(count($result) ? 'Mehrere Studiensemester aktiv' : 'Kein Studiensemester aktiv');
- } else {
- $this->outputJsonSuccess(current($result)->studiensemester_kurzbz);
- }
- }
-
- public function set()
- {
- $this->load->library('AuthLib');
- $this->load->library('form_validation');
-
- $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
-
- $this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required');
-
- if ($this->form_validation->run() == false) {
- $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST);
- return $this->outputJsonError($this->form_validation->error_array());
- }
-
- $stdsem = $this->input->post('studiensemester');
-
- $this->load->model('system/Variable_model', 'VariableModel');
-
- $result = $this->VariableModel->setVariable(getAuthUID(), 'semester_aktuell', $stdsem);
-
- if (isError($result)) {
- $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
- return $this->outputJson($result);
- }
-
- $this->outputJsonSuccess(true);
- }
-}
diff --git a/application/controllers/js/Tabulatorcolumns.php b/application/controllers/js/Tabulatorcolumns.php
new file mode 100644
index 000000000..1a4621219
--- /dev/null
+++ b/application/controllers/js/Tabulatorcolumns.php
@@ -0,0 +1,60 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller generates javascript from snippets for tabulator columns
+ */
+class Tabulatorcolumns extends Auth_Controller
+{
+ public function __construct()
+ {
+ parent::__construct([
+ 'stv' => ['admin:r', 'assistenz:r'],
+ 'lvverwaltung' => ['admin:r', 'assistenz:r']
+ ]);
+ }
+
+ /**
+ * Render tabulator columns for config
+ *
+ * @param string $config
+ *
+ * @return void
+ */
+ public function _remap($config)
+ {
+ $this->load->config($config);
+ $list_columns = $this->config->item('list_columns') ?: [];
+
+ $snippets = [
+ 'jssnippets/tabulatorcolumns/' . $config . '.js'
+ ];
+
+ foreach ($list_columns as $col) {
+ $snippets[] = $col['js'];
+ }
+
+ $this->output->set_content_type('application/javascript');
+
+ $this->load->view('jssnippets/tabulatorcolumns.js', [
+ 'snippets' => $snippets
+ ]);
+ }
+}
diff --git a/application/libraries/stv/StudentListLib.php b/application/libraries/stv/StudentListLib.php
index 432b75bd4..a506af3d1 100644
--- a/application/libraries/stv/StudentListLib.php
+++ b/application/libraries/stv/StudentListLib.php
@@ -28,6 +28,7 @@ class StudentListLib
private $_allowedStgs = [];
private $_selects = [];
private $_joins = [];
+ private $_wheres = [];
/**
* Gets the CI instance, loads model and prepares default values
@@ -40,6 +41,8 @@ class StudentListLib
{
$this->_ci =& get_instance(); // get code igniter instance
+ $this->_ci->load->config('stv');
+
$this->_ci->load->model('crm/Prestudent_model', 'PrestudentModel');
if (isset($params['allowedStgs']))
@@ -116,7 +119,7 @@ class StudentListLib
) prest
WHERE laststatus NOT IN ('Abbrecher', 'Abgewiesener', 'Absolvent')
AND priorisierung <= tbl_prestudent.priorisierung
- ) || ' (' || COALESCE(tbl_prestudent.priorisierung::text, ' '::text) || ')' AS priorisierung_relativ", false); // TODO(chris): overwrite in fetchStudents
+ ) || ' (' || COALESCE(tbl_prestudent.priorisierung::text, ' '::text) || ')' AS priorisierung_relativ", false);
$this->addSelect('mentor');
$this->addSelect('b.aktiv AS bnaktiv');
$this->addSelect('unruly');
@@ -124,7 +127,7 @@ class StudentListLib
// Add default JOINs
$this->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
$this->addJoin('public.tbl_person p', 'person_id');
- $this->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT'); // TODO(chris): overwrite in fetchStudents
+ $this->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT');
$this->addJoin('public.tbl_prestudentstatus pls', '
pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL)
AND pls.prestudent_id=tbl_prestudent.prestudent_id
@@ -134,6 +137,15 @@ class StudentListLib
$this->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid', 'LEFT');
$this->addJoin("v", "", ""); // Will be replaced later
$this->addJoin("ps", "", ""); // Will be replaced later
+
+ // Add SELECTs and JOINs from config
+ $config = $this->_ci->config->item('list_columns') ?: [];
+ foreach ($config as $conf) {
+ $this->addSelect($conf['default']);
+ if (isset($conf['joins']))
+ foreach ($conf['joins'] as $join)
+ call_user_func_array([$this, 'addJoin'], $join);
+ }
}
//------------------------------------------------------------------------------------------------------------------
@@ -219,11 +231,7 @@ class StudentListLib
*/
public function addWhere($key, $value = null, $escape = true)
{
- if (!is_array($key) && is_array($value)) {
- $this->_ci->PrestudentModel->db->where_in($key, $value, $escape);
- } else {
- $this->_ci->PrestudentModel->db->where($key, $value, $escape);
- }
+ $this->_wheres[] = [$key, $value, $escape, false];
}
/**
@@ -237,11 +245,7 @@ class StudentListLib
*/
public function addOrWhere($key, $value = null, $escape = true)
{
- if (!is_array($key) && is_array($value)) {
- $this->_ci->PrestudentModel->db->or_where_in($key, $value, $escape);
- } else {
- $this->_ci->PrestudentModel->db->or_where($key, $value, $escape);
- }
+ $this->_wheres[] = [$key, $value, $escape, true];
}
/**
@@ -286,6 +290,20 @@ class StudentListLib
foreach ($this->_selects as $select)
$this->_ci->PrestudentModel->addSelect($select[0], $select[1]);
+ foreach ($this->_wheres as $where) {
+ if (!is_array($where[0]) && is_array($where[1])) {
+ if ($where[3])
+ $this->_ci->PrestudentModel->db->or_where_in($where[0], $where[1], $where[2]);
+ else
+ $this->_ci->PrestudentModel->db->where_in($where[0], $where[1], $where[2]);
+ } else {
+ if ($where[3])
+ $this->_ci->PrestudentModel->db->or_where($where[0], $where[1], $where[2]);
+ else
+ $this->_ci->PrestudentModel->db->where($where[0], $where[1], $where[2]);
+ }
+ }
+
$this->_ci->PrestudentModel->addOrder('nachname');
$this->_ci->PrestudentModel->addOrder('vorname');
diff --git a/application/libraries/treemenu/LvVwLib.php b/application/libraries/treemenu/LvVwLib.php
new file mode 100644
index 000000000..d3c91a196
--- /dev/null
+++ b/application/libraries/treemenu/LvVwLib.php
@@ -0,0 +1,192 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * LvVw Menu library
+ */
+class LvVwLib
+{
+ protected $_ci = null;
+
+ public $config = [];
+
+ public function __construct()
+ {
+ // Get code igniter instance
+ $this->_ci =& get_instance();
+
+ // Load Tree-config
+ $this->_ci->load->config('treemenu/custom/lvvw');
+ $this->config = $this->_ci->config->item('root');
+
+ // Load Libraries
+ $this->_ci->load->library('treemenu/base/StgLib');
+
+ // Load Model
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ }
+
+ public function stg($path_template)
+ {
+ $permittedStgs = $this->getPermittedStudiengangKzs();
+
+ if (!$permittedStgs)
+ return [];
+
+ $this->_ci->StudiengangModel->addSelect("ARRAY['link', FORMAT('{" .
+ '"type": "verband",' .
+ '"id": "lv/%1$s",' .
+ '"gruppe_kurzbz": null,' .
+ '"semester": null,' .
+ '"verband": null,' .
+ '"gruppe": null,' .
+ '"lehrverband": true,' .
+ '"stg_kz": "%1$s"' .
+ "}', studiengang_kz)] AS draggable", false);
+
+ return $this->_ci->stglib->studiengang($path_template, $permittedStgs);
+ }
+
+ public function semester($path_template, $has_children, $stg)
+ {
+ $stg = $this->getStgFromUrl($stg);
+
+ if ($stg === null)
+ return [];
+
+ if (!$has_children)
+ $this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
+ $this->_ci->StudiengangModel->addSelect("ARRAY['link', FORMAT('{" .
+ '"type": "verband",' .
+ '"id": "lv/%1$s/%2$s",' .
+ '"gruppe_kurzbz": null,' .
+ '"semester": "%2$s",' .
+ '"verband": null,' .
+ '"gruppe": null,' .
+ '"lehrverband": true,' .
+ '"stg_kz": "%1$s"' .
+ "}', v.studiengang_kz, v.semester)] AS draggable", false);
+
+ return $this->_ci->stglib->semester($path_template, $stg->studiengang_kz);
+ }
+
+ public function verband($path_template, $stg, $semester)
+ {
+ $stg = $this->getStgFromUrl($stg);
+
+ if ($stg === null)
+ return [];
+
+ $this->_ci->StudiengangModel->addSelect("CASE WHEN MAX(gruppe)='' OR MAX(gruppe)=' ' THEN TRUE ELSE FALSE END AS leaf");
+ $this->_ci->StudiengangModel->addSelect("ARRAY['link', FORMAT('{" .
+ '"type": "verband",' .
+ '"id": "lv/%1$s/%2$s/%3$s",' .
+ '"gruppe_kurzbz": null,' .
+ '"semester": "%2$s",' .
+ '"verband": "%3$s",' .
+ '"gruppe": null,' .
+ '"lehrverband": true,' .
+ '"stg_kz": "%1$s"' .
+ "}', v.studiengang_kz, v.semester, v.verband)] AS draggable", false);
+ $this->_ci->StudiengangModel->addGroupBy('v.studiengang_kz, v.semester');
+
+ return $this->_ci->stglib->verband($path_template, $stg->studiengang_kz, $semester);
+ }
+
+ public function group($path_template, $stg, $semester, $verband)
+ {
+ $stg = $this->getStgFromUrl($stg);
+
+ if ($stg === null)
+ return [];
+
+ $this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
+
+ if ($verband === null) {
+ $this->_ci->StudiengangModel->addSelect("ARRAY['link', FORMAT('{" .
+ '"type": "verband",' .
+ '"id": "grp/%1$s/%2$s/%3$s",' .
+ '"gruppe_kurzbz": "%3$s",' .
+ '"semester": "%2$s",' .
+ '"verband": null,' .
+ '"gruppe": null,' .
+ '"lehrverband": false,' .
+ '"stg_kz": "%1$s"' .
+ "}', studiengang_kz, semester, gruppe_kurzbz)] AS draggable", false);
+
+ return $this->_ci->stglib->group($path_template, $stg->studiengang_kz, $semester);
+ }
+
+ $this->_ci->StudiengangModel->addSelect("ARRAY['link', FORMAT('{" .
+ '"type": "verband",' .
+ '"id": "lv/%1$s/%2$s/%3$s/%4$s",' .
+ '"gruppe_kurzbz": null,' .
+ '"semester": "%2$s",' .
+ '"verband": "%3$s",' .
+ '"gruppe": "%4$s",' .
+ '"lehrverband": true,' .
+ '"stg_kz": "%1$s"' .
+ "}', v.studiengang_kz, v.semester, v.verband, v.gruppe)] AS draggable", false);
+
+ return $this->_ci->stglib->verbandsgroup($path_template, $stg->studiengang_kz, $semester, $verband);
+ }
+
+ public function orgform($path_template, $stg)
+ {
+ $stg = $this->getStgFromUrl($stg);
+
+ if ($stg === null)
+ return [];
+
+ if (!$stg->mischform)
+ return [];
+
+ $this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
+
+ return $this->_ci->stglib->orgform($path_template, $stg->studiengang_kz);
+ }
+
+ protected function getPermittedStudiengangKzs()
+ {
+ $permittedStgs = $this->_ci->permissionlib->getSTG_isEntitledFor('admin') ?: [];
+ $permittedStgs = array_merge($permittedStgs, $this->_ci->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
+
+ return $permittedStgs;
+ }
+
+ protected function getStgFromUrl($stg)
+ {
+ $permittedStgs = $this->getPermittedStudiengangKzs();
+
+ if (!$permittedStgs)
+ return null;
+
+ $this->_ci->StudiengangModel->db->where_in('studiengang_kz', $permittedStgs);
+ $stg = $this->_ci->StudiengangModel->loadWhere([
+ 'LOWER(CONCAT(typ, kurzbz)) =' => $stg
+ ]);
+
+ if (!hasData($stg))
+ return null;
+
+ return current(getData($stg));
+ }
+}
diff --git a/application/libraries/treemenu/StudVwLib.php b/application/libraries/treemenu/StudVwLib.php
new file mode 100644
index 000000000..ee3e2cbdc
--- /dev/null
+++ b/application/libraries/treemenu/StudVwLib.php
@@ -0,0 +1,257 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * StudVw Menu library
+ */
+class StudVwLib
+{
+ protected $_ci = null;
+
+ public $config = [];
+
+ public $redirect_method = [
+ 'interessenten' => 'filter',
+ 'bewerbungnichtabgeschickt' => 'filter',
+ 'bewerbungabgeschickt' => 'filter',
+ 'zgv' => 'filter',
+ 'statusbestaetigt' => 'filter',
+ 'statusbestaetigtrtnichtangemeldet' => 'filter',
+ 'statusbestaetigtrtangemeldet' => 'filter',
+ 'reihungstestnichtangemeldet' => 'filter',
+ 'reihungstestangemeldet' => 'filter',
+ 'bewerber' => 'filter',
+ 'bewerberrtnichtangemeldet' => 'filter',
+ 'bewerberrtangemeldet' => 'filter',
+ 'bewerberrtangemeldetteilgenommen' => 'filter',
+ 'bewerberrtangemeldetnichtteilgenommen' => 'filter',
+ 'aufgenommen' => 'filter',
+ 'warteliste' => 'filter',
+ 'absage' => 'filter',
+ 'outgoing' => 'inout',
+ 'shared_studies' => 'inout'
+ ];
+
+ public function __construct()
+ {
+ // Get code igniter instance
+ $this->_ci =& get_instance();
+
+ // Load Tree-config
+ $this->_ci->load->config('treemenu/stg_base');
+ $this->config = $this->_ci->config->item('root');
+
+ // Load Libraries
+ $this->_ci->load->library('treemenu/base/StgLib');
+
+ // Load Model
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ }
+
+ public function stg($path_template)
+ {
+ $permittedStgs = $this->getPermittedStudiengangKzs();
+
+ if (!$permittedStgs)
+ return [];
+
+ return $this->_ci->stglib->studiengang($path_template, $permittedStgs);
+ }
+
+ public function prestudent($path_template, $stg)
+ {
+ // Check permission
+ if ($this->getStgFromUrl($stg) === null)
+ return [];
+
+ return [
+ [
+ 'path' => sprintf($path_template, '1'),
+ 'name' => ['lehre', 'prestudent'],
+ 'no_sem_reload' => true
+ ]
+ ];
+ }
+
+ public function stdsem($path_template, $stg)
+ {
+ $stg = $this->getStgFromUrl($stg);
+
+ if ($stg === null)
+ return [];
+
+ return $this->_ci->stglib->studiensemester($path_template, $stg->studiengang_kz);
+ }
+
+ public function semester($path_template, $stg, $orgform)
+ {
+ $stg = $this->getStgFromUrl($stg);
+
+ if ($stg === null)
+ return [];
+
+ if ($orgform !== null) {
+ $orgform = $this->getOrgform($orgform);
+ if ($orgform === null)
+ return [];
+ $orgform = $orgform->orgform_kurzbz;
+ }
+
+ return $this->_ci->stglib->semester($path_template, $stg->studiengang_kz, $orgform);
+ }
+
+ public function verband($path_template, $stg, $semester, $orgform)
+ {
+ $stg = $this->getStgFromUrl($stg);
+
+ if ($stg === null)
+ return [];
+
+ if ($orgform !== null) {
+ $orgform = $this->getOrgform($orgform);
+ if ($orgform === null)
+ return [];
+ $orgform = $orgform->orgform_kurzbz;
+ }
+
+ $this->_ci->StudiengangModel->addSelect("CASE WHEN MAX(gruppe)='' OR MAX(gruppe)=' ' THEN TRUE ELSE FALSE END AS leaf");
+
+ return $this->_ci->stglib->verband($path_template, $stg->studiengang_kz, $semester, $orgform);
+ }
+
+ public function group($path_template, $stg, $semester, $verband, $orgform)
+ {
+ $stg = $this->getStgFromUrl($stg);
+
+ if ($stg === null)
+ return [];
+
+ if ($orgform !== null) {
+ $orgform = $this->getOrgform($orgform);
+ if ($orgform === null)
+ return [];
+ $orgform = $orgform->orgform_kurzbz;
+ }
+
+ $this->_ci->StudiengangModel->db->select('TRUE AS leaf', false);
+
+ if ($verband === null)
+ return $this->_ci->stglib->group($path_template, $stg->studiengang_kz, $semester, $orgform);
+
+ return $this->_ci->stglib->verbandsgroup($path_template, $stg->studiengang_kz, $semester, $verband, $orgform);
+ }
+
+ public function orgform($path_template, $stg)
+ {
+ $stg = $this->getStgFromUrl($stg);
+
+ if ($stg === null)
+ return [];
+
+ if (!$stg->mischform)
+ return [];
+
+ return $this->_ci->stglib->orgform($path_template, $stg->studiengang_kz);
+ }
+
+ public function incoming($has_children, $path_template, $stg)
+ {
+ if ($stg === null)
+ return $this->inout('incoming', $has_children, $path_template);
+
+ return $this->filter('incoming', $has_children, $path_template, $stg);
+ }
+
+ public function filter($original_method, $has_children, $path_template, $stg)
+ {
+ $stg = $this->getStgFromUrl($stg);
+
+ if ($stg === null)
+ return [];
+
+ // TODO(chris): phrasen
+ $item = [
+ 'path' => sprintf($path_template, '1'),
+ 'name' => ['treemenu', 'filter_' . $original_method]
+ ];
+
+ if (!$has_children)
+ $item['leaf'] = true;
+
+ return [ $item ];
+ }
+
+ public function inout($original_method, $has_children, $path_template)
+ {
+ if (!$this->_ci->permissionlib->isBerechtigt('inout/uebersicht'))
+ return [];
+
+ // TODO(chris): phrasen
+ $item = [
+ 'path' => sprintf($path_template, '1'),
+ 'name' => ['treemenu', 'inout_' . $original_method]
+ ];
+
+ if (!$has_children)
+ $item['leaf'] = true;
+
+ return [ $item ];
+ }
+
+ protected function getOrgform($orgform)
+ {
+ $this->_ci->load->model('codex/Orgform_model', 'OrgformModel');
+ $orgform = $this->_ci->OrgformModel->loadWhere([
+ 'LOWER(orgform_kurzbz) =' => $orgform
+ ]);
+
+ if (!hasData($orgform))
+ return null;
+
+ return current(getData($orgform));
+ }
+
+ protected function getPermittedStudiengangKzs()
+ {
+ $permittedStgs = $this->_ci->permissionlib->getSTG_isEntitledFor('admin') ?: [];
+ $permittedStgs = array_merge($permittedStgs, $this->_ci->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
+
+ return $permittedStgs;
+ }
+
+ protected function getStgFromUrl($stg)
+ {
+ $permittedStgs = $this->getPermittedStudiengangKzs();
+
+ if (!$permittedStgs)
+ return null;
+
+ $this->_ci->StudiengangModel->db->where_in('studiengang_kz', $permittedStgs);
+ $stg = $this->_ci->StudiengangModel->loadWhere([
+ 'LOWER(CONCAT(typ, kurzbz)) =' => $stg
+ ]);
+
+ if (!hasData($stg))
+ return null;
+
+ return current(getData($stg));
+ }
+}
diff --git a/application/libraries/treemenu/base/StgLib.php b/application/libraries/treemenu/base/StgLib.php
new file mode 100644
index 000000000..84665639d
--- /dev/null
+++ b/application/libraries/treemenu/base/StgLib.php
@@ -0,0 +1,313 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Stg Base library
+ */
+class StgLib
+{
+ protected $_ci = null;
+
+ public function __construct()
+ {
+ // Get code igniter instance
+ $this->_ci =& get_instance();
+ }
+
+ public function studiengang($path_template, $permittedStgs = [])
+ {
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+
+ $this->_ci->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
+
+ $this->_ci->StudiengangModel->addDistinct();
+ $this->_ci->StudiengangModel->addSelect("FORMAT(" . $this->_ci->StudiengangModel->escape($path_template) . ", LOWER(CONCAT(typ, kurzbz))) AS path");
+ $this->_ci->StudiengangModel->addSelect(
+ "CONCAT(kurzbzlang, ' (', UPPER(CONCAT(typ, kurzbz)), ') - ', tbl_studiengang.bezeichnung) AS name",
+ false
+ );
+ $this->_ci->StudiengangModel->addSelect("studiengang_kz AS title");
+ $this->_ci->StudiengangModel->addSelect("studiengang_kz AS search");
+ $this->_ci->StudiengangModel->addSelect('erhalter_kz');
+ $this->_ci->StudiengangModel->addSelect('typ');
+ $this->_ci->StudiengangModel->addSelect('kurzbz');
+ $this->_ci->StudiengangModel->addSelect('studiengang_kz');
+ $this->_ci->StudiengangModel->addSelect('studiengang_kz AS stg_kz');
+
+ $this->_ci->StudiengangModel->addOrder('erhalter_kz');
+ $this->_ci->StudiengangModel->addOrder('typ');
+ $this->_ci->StudiengangModel->addOrder('kurzbz');
+
+ if ($permittedStgs)
+ $this->_ci->StudiengangModel->db->where_in('studiengang_kz', $permittedStgs);
+
+ $result = $this->_ci->StudiengangModel->loadWhere(['v.aktiv' => true]);
+
+ return getData($result) ?: [];
+ }
+
+ public function semester($path_template, $studiengang_kz, $orgform_kurzbz = null)
+ {
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+
+ $this->_ci->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
+
+ $this->_ci->StudiengangModel->addDistinct();
+ $this->_ci->StudiengangModel->addSelect("FORMAT(" . $this->_ci->StudiengangModel->escape($path_template) . ", semester) AS path", false);
+ $this->_ci->StudiengangModel->addSelect("CONCAT(
+ UPPER(CONCAT(typ, kurzbz)),
+ '-',
+ semester,
+ (
+ SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END
+ FROM public.tbl_lehrverband
+ WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester
+ ORDER BY verband, gruppe LIMIT 1
+ )
+ ) AS name", false);
+
+ $this->_ci->StudiengangModel->addSelect('semester');
+ $this->_ci->StudiengangModel->addSelect('v.studiengang_kz AS stg_kz');
+ $this->_ci->StudiengangModel->addSelect("ARRAY['link-strict', 'student-collection'] AS droplink");
+
+ $this->_ci->StudiengangModel->addOrder('semester');
+
+ if ($orgform_kurzbz !== null) {
+ $this->_ci->StudiengangModel->addSelect($this->_ci->StudiengangModel->escape($orgform_kurzbz) . " AS orgform_kurzbz", false);
+ $this->_ci->StudiengangModel->addDistinct();
+ $this->_ci->StudiengangModel->db->group_start();
+ $this->_ci->StudiengangModel->db->where('v.semester', 0);
+ $this->_ci->StudiengangModel->db->or_where('v.orgform_kurzbz', $orgform_kurzbz);
+ $this->_ci->StudiengangModel->db->group_end();
+ }
+
+ $result = $this->_ci->StudiengangModel->loadWhere([
+ 'studiengang_kz' => $studiengang_kz,
+ 'v.aktiv' => true
+ ]);
+
+
+ return getData($result) ?: [];
+ }
+
+ public function group($path_template, $studiengang_kz, $semester, $orgform_kurzbz = null)
+ {
+ $this->_ci->load->model('organisation/Gruppe_model', 'GruppeModel');
+
+ $this->_ci->GruppeModel->addDistinct();
+ $this->_ci->GruppeModel->addSelect("FORMAT(" . $this->_ci->GruppeModel->escape($path_template) . ", gruppe_kurzbz) AS path", false);
+ $this->_ci->GruppeModel->addSelect("CONCAT(gruppe_kurzbz, ' (', bezeichnung, ')') AS name", false);
+
+ $this->_ci->GruppeModel->addSelect('sort');
+ $this->_ci->GruppeModel->addSelect('gruppe_kurzbz');
+ $this->_ci->GruppeModel->addSelect($this->_ci->GruppeModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
+ $this->_ci->GruppeModel->addSelect("ARRAY['link-strict', 'student-collection'] AS droplink");
+
+ $this->_ci->GruppeModel->addOrder('sort');
+ $this->_ci->GruppeModel->addOrder('gruppe_kurzbz');
+
+ $where = [
+ 'studiengang_kz' => $studiengang_kz,
+ 'semester' => $semester,
+ 'lehre' => true,
+ 'sichtbar' => true,
+ 'aktiv' => true,
+ 'direktinskription' => false
+ ];
+
+ if ($orgform_kurzbz !== null)
+ $where['orgform_kurzbz'] = $orgform_kurzbz;
+
+ $result = $this->_ci->GruppeModel->loadWhere($where);
+
+ return getData($result) ?: [];
+ }
+
+ public function verband($path_template, $studiengang_kz, $semester, $orgform_kurzbz = null)
+ {
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+
+ $this->_ci->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
+
+ $this->_ci->StudiengangModel->addSelect("FORMAT(" . $this->_ci->StudiengangModel->escape($path_template) . ", verband) AS path", false);
+ $this->_ci->StudiengangModel->addSelect("CONCAT(
+ UPPER(CONCAT(typ, kurzbz)),
+ '-',
+ semester,
+ verband,
+ (
+ SELECT
+ CASE
+ WHEN bezeichnung IS NULL OR bezeichnung=''
+ THEN ''::TEXT
+ ELSE CONCAT(' (', bezeichnung, ')')
+ END
+ FROM public.tbl_lehrverband
+ WHERE studiengang_kz=v.studiengang_kz
+ AND semester=v.semester
+ AND verband=v.verband
+ ORDER BY gruppe
+ LIMIT 1
+ )
+ ) AS name", false);
+
+ $this->_ci->StudiengangModel->addSelect($this->_ci->StudiengangModel->escape($semester) . ' AS semester');
+ $this->_ci->StudiengangModel->addSelect('verband');
+ $this->_ci->StudiengangModel->addSelect($this->_ci->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
+ $this->_ci->StudiengangModel->addSelect("ARRAY['link-strict', 'student-collection'] AS droplink");
+
+ $this->_ci->StudiengangModel->addOrder('verband');
+
+ $this->_ci->StudiengangModel->addGroupBy('path, name, verband');
+
+ $where = [
+ 'v.studiengang_kz' => $studiengang_kz,
+ 'v.semester' => $semester,
+ 'v.verband !=' => '',
+ 'v.aktiv' => true
+ ];
+
+ if ($orgform_kurzbz !== null && $semester) // NOTE(chris): on semester 0 show all?
+ $where['v.orgform_kurzbz'] = $orgform_kurzbz;
+
+ $result = $this->_ci->StudiengangModel->loadWhere($where);
+
+ return getData($result) ?: [];
+ }
+
+ public function verbandsgroup($path_template, $studiengang_kz, $semester, $verband, $orgform_kurzbz = null)
+ {
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+
+ $this->_ci->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
+
+ $this->_ci->StudiengangModel->addDistinct();
+ $this->_ci->StudiengangModel->addSelect("FORMAT(
+ " . $this->_ci->StudiengangModel->escape($path_template) . ",
+ gruppe
+ ) AS path", false);
+ $this->_ci->StudiengangModel->addSelect("CONCAT(
+ UPPER(CONCAT(typ, kurzbz)),
+ '-',
+ semester,
+ verband,
+ gruppe,
+ (
+ SELECT
+ CASE
+ WHEN bezeichnung IS NULL OR bezeichnung=''
+ THEN ''::TEXT
+ ELSE CONCAT(' (', bezeichnung, ')')
+ END
+ FROM public.tbl_lehrverband
+ WHERE studiengang_kz=v.studiengang_kz
+ AND semester=v.semester
+ AND verband=v.verband
+ AND gruppe=v.gruppe
+ ORDER BY gruppe
+ LIMIT 1
+ )
+ ) AS name", false);
+
+ $this->_ci->StudiengangModel->addSelect('v.semester');
+ $this->_ci->StudiengangModel->addSelect('v.verband');
+ $this->_ci->StudiengangModel->addSelect('gruppe');
+ $this->_ci->StudiengangModel->addSelect($this->_ci->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
+ $this->_ci->StudiengangModel->addSelect("ARRAY['link-strict', 'student-collection'] AS droplink");
+
+ $this->_ci->StudiengangModel->addOrder('gruppe');
+
+ $where = [
+ 'v.studiengang_kz' => $studiengang_kz,
+ 'v.semester' => $semester,
+ 'v.verband' => $verband,
+ 'v.gruppe !=' => '',
+ 'v.aktiv' => true
+ ];
+
+ if ($orgform_kurzbz !== null && $semester) // NOTE(chris): on semester 0 show all?
+ $where['v.orgform_kurzbz'] = $orgform_kurzbz;
+
+ $result = $this->_ci->StudiengangModel->loadWhere($where);
+
+ return getData($result) ?: [];
+ }
+
+ public function orgform($path_template, $studiengang_kz)
+ {
+ $this->_ci->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
+
+ $this->_ci->StudienordnungModel->addDistinct();
+ $this->_ci->StudienordnungModel->addSelect("FORMAT(
+ " . $this->_ci->StudienordnungModel->escape($path_template) . ",
+ LOWER(p.orgform_kurzbz)
+ ) AS path");
+ $this->_ci->StudienordnungModel->addSelect("p.orgform_kurzbz AS name");
+ $this->_ci->StudienordnungModel->addSelect("studiengang_kz AS stg_kz");
+
+ $this->_ci->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id');
+
+ $result = $this->_ci->StudienordnungModel->loadWhere([
+ 'aktiv' => true,
+ 'studiengang_kz' => $studiengang_kz,
+ 'p.orgform_kurzbz !=' => 'DDP'
+ ]);
+
+
+ return getData($result) ?: [];
+ }
+
+ public function studiensemester($path_template, $studiengang_kz)
+ {
+ $number_displayed_past_studiensemester = null;
+
+ $this->_ci->load->model('system/Variable_model', 'VariableModel');
+
+ $result = $this->_ci->VariableModel->getVariables(getAuthUID(), ['number_displayed_past_studiensemester']);
+ if (isError($result))
+ return [];
+
+ $data = getData($result);
+ if ($data && isset($data['number_displayed_past_studiensemester'])) {
+ $number_displayed_past_studiensemester = $data['number_displayed_past_studiensemester'];
+ } else {
+ $this->_ci->load->config('stv');
+ $number_displayed_past_studiensemester = $this->_ci->config->item('number_displayed_past_studiensemester_default');
+ }
+
+ $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+
+ $this->_ci->StudiensemesterModel->addPlusMinus(null, $number_displayed_past_studiensemester);
+
+ $this->_ci->StudiensemesterModel->addSelect("studiensemester_kurzbz AS name");
+ $this->_ci->StudiensemesterModel->addSelect("FORMAT(
+ " . $this->_ci->StudiensemesterModel->escape($path_template) . ",
+ LOWER(studiensemester_kurzbz)
+ ) AS path", false);
+ $this->_ci->StudiensemesterModel->addSelect($this->_ci->StudiensemesterModel->escape($studiengang_kz) . " AS stg_kz", false);
+
+ $this->_ci->StudiensemesterModel->addOrder('ende');
+
+ $result = $this->_ci->StudiensemesterModel->load();
+
+ return getData($result) ?: [];
+ }
+}
diff --git a/application/views/jssnippets/tabulatorcolumns.js b/application/views/jssnippets/tabulatorcolumns.js
new file mode 100644
index 000000000..44667e45b
--- /dev/null
+++ b/application/views/jssnippets/tabulatorcolumns.js
@@ -0,0 +1,19 @@
+let result = [];
+let current;
+
+
+
+current = (tabulatorcolumns => {
+load->view($path); ?>
+})(result);
+
+if (current) {
+ if (Array.isArray(current))
+ result = result.concat(current);
+ else
+ result.push(current);
+}
+
+
+
+export default result;
\ No newline at end of file
diff --git a/application/views/jssnippets/tabulatorcolumns/lvverwaltung.js b/application/views/jssnippets/tabulatorcolumns/lvverwaltung.js
new file mode 100644
index 000000000..60d156a8a
--- /dev/null
+++ b/application/views/jssnippets/tabulatorcolumns/lvverwaltung.js
@@ -0,0 +1,266 @@
+return [
+ {
+ title: 'kurzbz',
+ titlePhrase: 'lehre/kurzbz',
+ field: "lv_kurzbz",
+ headerFilterFuncParams: { field: 'lv_kurzbz' },
+ headerFilter: true,
+ formatter(cell,
+ formatterParams) {
+ const rowData = cell.getRow().getData();
+ const iconKey = (rowData.lehrtyp_kurzbz || '').toLowerCase();
+ const lvkurzbz = (cell.getValue()).toUpperCase();
+
+ const parentspan = document.createElement('span');
+ const span = document.createElement('span');
+
+ span.classList.add('lv_table_icon', `icon-${iconKey}`);
+ span.title = iconKey || 'LV-Teil';
+
+ parentspan.appendChild(span);
+ parentspan.appendChild(document.createTextNode(` ${lvkurzbz}`));
+
+ return parentspan;
+ },
+ cellClick(e,
+ cell) {
+ cell.getRow().treeToggle();
+ }
+ },
+ {
+ title: 'Tags',
+ field: 'tags',
+ tooltip: false,
+ headerFilter: "input",
+ headerFilterFunc: "tagHeaderFilter",
+ headerFilterFuncParams: { field: 'tags' },
+ formatter: "tagFormatter",
+ width: 150,
+ },
+ {
+ title: 'lehrveranstaltung_id',
+ titlePhrase: 'lehre/lehrveranstaltung_id',
+ field: "lehrveranstaltung_id",
+ headerFilterFuncParams: { field: 'lehrveranstaltung_id' },
+ headerFilter: true,
+ visible: false
+ },
+ {
+ title: 'bezeichnung',
+ titlePhrase: 'ui/bezeichnung',
+ field: "lv_bezeichnung",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'lv_bezeichnung' }
+ },
+ {
+ title: 'bezeichnungeng',
+ titlePhrase: 'lehre/bezeichnungeng',
+ field: "lv_bezeichnung_english",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'lv_bezeichnung_english' },
+ visible: false
+ },
+ {
+ title: 'studiengangskennzahlLehre',
+ titlePhrase: 'lehre/studiengangskennzahlLehre',
+ field: "lv_studiengang_kz",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'lv_studiengang_kz' },
+ visible: false
+ },
+ {
+ title: 'studiengang',
+ titlePhrase: 'lehre/studiengang',
+ field: "studiengang",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'studiengang' },
+ visible: false
+ },
+ {
+ title: 'semester',
+ titlePhrase: 'lehre/semester',
+ field: "semester",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'semester' }
+ },
+ {
+ title: 'sprache',
+ titlePhrase: 'global/sprache',
+ field: "sprache",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'sprache' },
+ visible: false
+ },
+ {
+ title: 'ects',
+ titlePhrase: 'lehre/ects',
+ field: "lv_ects",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'lv_ects' },
+ visible: false
+ },
+ {
+ title: 'semesterstunden',
+ titlePhrase: 'lehre/semesterstunden',
+ field: "semesterstunden",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'semesterstunden' },
+ visible: false
+ },
+ {
+ title: 'anmerkung',
+ titlePhrase: 'global/anmerkung',
+ field: "anmerkung",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'anmerkung' },
+ visible: false
+ },
+ {
+ title: 'lehre',
+ titlePhrase: 'lehre/lehre',
+ field: "lehre",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'lehre' },
+ formatter: 'ja_nein',
+ visible: false
+ },
+ {
+ title: 'aktiv',
+ titlePhrase: 'person/aktiv',
+ field: "aktiv",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'aktiv' },
+ formatter: 'ja_nein',
+ visible: false
+ },
+ {
+ title: 'organisationsform',
+ titlePhrase: 'lehre/organisationsform',
+ field: "orgform_kurzbz",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'orgform_kurzbz' }
+ },
+ {
+ title: 'studienplan_id',
+ titlePhrase: 'ui/studienplan_id',
+ field: "studienplan_id",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'studienplan_id' },
+ visible: false
+ },
+ {
+ title: 'studienplan',
+ titlePhrase: 'lehre/studienplan',
+ field: "studienplan_bezeichnung",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'studienplan_bezeichnung' },
+ visible: false
+ },
+ {
+ title: 'lehrtyp',
+ titlePhrase: 'lehre/lehrtyp',
+ field: "lehrtyp_kurzbz",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'lehrtyp_kurzbz' },
+ visible: false
+ },
+ {
+ title: 'lehrform',
+ titlePhrase: 'lehre/lehrform',
+ field: "lehrform_kurzbz",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'lehrform_kurzbz'} },
+ {
+ title: 'leplanstunden',
+ titlePhrase: 'lehre/leplanstunden',
+ field: "le_planstunden",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'le_planstunden' },
+ visible: false
+ },
+ {
+ title: 'lehreinheit_id',
+ titlePhrase: 'lehre/lehreinheit_id',
+ field: "lehreinheit_id",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'lehreinheit_id' },
+ visible: false
+ },
+ {
+ title: 'studiensemester',
+ titlePhrase: 'lehre/studiensemester',
+ field: "studiensemester_kurzbz",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'studiensemester_kurzbz' },
+ visible: false
+ },
+ {
+ title: 'unr',
+ titlePhrase: 'lehre/unr',
+ field: "unr",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'unr' },
+ visible: false
+ },
+ {
+ title: 'organisationseinheit',
+ titlePhrase: 'lehre/organisationseinheit',
+ field: "fachbereich",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'fachbereich' },
+ visible: false
+ },
+ {
+ title: 'stundenblockung',
+ titlePhrase: 'lehre/stundenblockung',
+ field: "stundenblockung",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'stundenblockung' },
+ visible: false
+ },
+ {
+ title: 'wochenrhythmus',
+ titlePhrase: 'lehre/wochenrhythmus',
+ field: "wochenrythmus",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'wochenrythmus' },
+ visible: false
+ },
+ {
+ title: 'startkw',
+ titlePhrase: 'lehre/startkw',
+ field: "start_kw",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'startkw' },
+ visible: false
+ },
+ {
+ title: 'raumtyp',
+ titlePhrase: 'lehre/raumtyp',
+ field: "raumtyp",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'raumtyp' },
+ visible: false
+ },
+ {
+ title: 'raumtypalternativ',
+ titlePhrase: 'lehre/raumtypalternativ',
+ field: "raumtypalternativ",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'raumtypalternativ' },
+ visible: false
+ },
+ {
+ title: 'gruppen',
+ titlePhrase: 'lehre/gruppen',
+ field: "gruppen",
+ headerFilter: true,
+ headerFilterFuncParams: { field: 'gruppen'} },
+ {
+ title: 'lehrende',
+ titlePhrase: 'lehre/lehrende',
+ field: "lektoren",
+ headerFilter: true,
+ headerFilterFuncParams: { field: ['lektoren', 'vorname', 'nachname'] }
+ },
+];
diff --git a/application/views/jssnippets/tabulatorcolumns/stv.js b/application/views/jssnippets/tabulatorcolumns/stv.js
new file mode 100644
index 000000000..54a370f5d
--- /dev/null
+++ b/application/views/jssnippets/tabulatorcolumns/stv.js
@@ -0,0 +1,343 @@
+return [
+ {
+ title: "UID",
+ titlePhrase: 'person/uid',
+ field: "uid",
+ headerFilter: true
+ },
+ {
+ title: "TitelPre",
+ titlePhrase: 'person/titelpre',
+ field: "titelpre",
+ headerFilter: "list",
+ headerFilterParams: {
+ valuesLookup: true,
+ listOnEmpty: true,
+ autocomplete: true,
+ sort: "asc"
+ }
+ },
+ {
+ title: "Nachname",
+ titlePhrase: 'person/nachname',
+ field: "nachname",
+ headerFilter: true
+ },
+ {
+ title: "Vorname",
+ titlePhrase: 'person/vorname',
+ field: "vorname",
+ headerFilter: true
+ },
+ {
+ title: "Wahlname",
+ titlePhrase: 'person/wahlname',
+ field: "wahlname",
+ visible: false,
+ headerFilter: true
+ },
+ {
+ title: "Vornamen",
+ titlePhrase: 'person/vornamen',
+ field: "vornamen",
+ visible: false,
+ headerFilter: true
+ },
+ {
+ title: "TitelPost",
+ titlePhrase: 'person/titelpost',
+ field: "titelpost",
+ headerFilter: "list",
+ headerFilterParams: {
+ valuesLookup: true,
+ listOnEmpty: true,
+ autocomplete: true,
+ sort: "asc"
+ }
+ },
+ {
+ title: "Ersatzkennzeichen",
+ titlePhrase: 'person/ersatzkennzeichen',
+ field: "ersatzkennzeichen",
+ headerFilter: true
+ },
+ {
+ title: "Geburtsdatum",
+ titlePhrase: 'person/geburtsdatum',
+ field: "gebdatum",
+ formatter: 'datetime',
+ formatterParams: {
+ inputFormat: "iso",
+ outputFormat: "dd.MM.yyyy",
+ invalidPlaceholder: " ",
+ timezone: FHC_JS_DATA_STORAGE_OBJECT.timezone
+ },
+ headerFilter: 'input',
+ headerFilterFunc: 'dateinput'
+ },
+ {
+ title: "Geschlecht",
+ titlePhrase: 'person/geschlecht',
+ field: "geschlecht",
+ headerFilter: "list",
+ headerFilterParams: {
+ values: {
+ 'm': 'männlich',
+ 'w': 'weiblich',
+ 'x': 'divers',
+ 'u': 'unbekannt'
+ },
+ listOnEmpty: true,
+ autocomplete: true
+ }
+ },
+ {
+ title: "Sem.",
+ titlePhrase: 'lehre/sem',
+ field: "semester_berechnet",
+ headerFilter: "list",
+ headerFilterParams: {
+ valuesLookup: true,
+ listOnEmpty: true,
+ autocomplete: true,
+ sort: "asc"
+ }
+ },
+ {
+ title: "Verb.",
+ titlePhrase: 'lehre/verb',
+ field: "verband",
+ headerFilter: "list",
+ headerFilterParams: {
+ valuesLookup: true,
+ listOnEmpty: true,
+ autocomplete: true,
+ sort: "asc"
+ }
+ },
+ {
+ title: "Grp.",
+ titlePhrase: 'lehre/grp',
+ field: "gruppe",
+ headerFilter: "list",
+ headerFilterParams: {
+ valuesLookup: true,
+ listOnEmpty: true,
+ autocomplete: true,
+ sort: "asc"
+ }
+ },
+ {
+ title: "Studiengang",
+ titlePhrase: 'lehre/studiengang',
+ field: "studiengang",
+ headerFilter: "list",
+ headerFilterParams: {
+ valuesLookup: true,
+ listOnEmpty: true,
+ autocomplete: true,
+ sort: "asc"
+ }
+ },
+ {
+ title: "Studiengang_kz",
+ titlePhrase: 'lehre/studiengang_kz',
+ field: "studiengang_kz",
+ visible: false,
+ headerFilter: true
+ },
+ {
+ title: "Personenkennzeichen",
+ titlePhrase: 'person/personenkennzeichen',
+ field: "matrikelnr",
+ headerFilter: true
+ },
+ {
+ title: "PersonID",
+ titlePhrase: 'person/person_id',
+ field: "person_id",
+ headerFilter: true
+ },
+ {
+ title: "Status",
+ titlePhrase: 'global/status',
+ field: "status",
+ headerFilter: "list",
+ headerFilterParams: {
+ valuesLookup: true,
+ listOnEmpty: true,
+ autocomplete: true,
+ sort: "asc"
+ }
+ },
+ {
+ title: "Status Datum",
+ titlePhrase: 'profilUpdate/statusDate',
+ field: "status_datum",
+ visible: false,
+ formatter: 'datetime',
+ formatterParams: {
+ inputFormat: "iso",
+ outputFormat: "dd.MM.yyyy",
+ invalidPlaceholder: " ",
+ timezone: FHC_JS_DATA_STORAGE_OBJECT.timezone
+ }
+ },
+ {
+ title: "Status Bestaetigung",
+ titlePhrase: 'global/status_bestaetigung',
+ field: "status_bestaetigung",
+ visible: false,
+ formatter: 'datetime',
+ formatterParams: {
+ inputFormat: "iso",
+ outputFormat: "dd.MM.yyyy",
+ invalidPlaceholder: " ",
+ timezone: FHC_JS_DATA_STORAGE_OBJECT.timezone
+ },
+ headerFilter: 'input',
+ headerFilterFunc: 'dateinput'
+ },
+ {
+ title: "EMail (Privat)",
+ titlePhrase: 'person/email_private',
+ field: "mail_privat",
+ visible: false,
+ headerFilter: true
+ },
+ {
+ title: "EMail (Intern)",
+ titlePhrase: 'person/email_intern',
+ field: "mail_intern",
+ visible: false,
+ headerFilter: true
+ },
+ {
+ title: "Anmerkungen",
+ titlePhrase: 'stv/notes_person',
+ field: "anmerkungen",
+ visible: false,
+ headerFilter: true
+ },
+ {
+ title: "AnmerkungPre",
+ titlePhrase: 'stv/notes_prestudent',
+ field: "anmerkung",
+ visible: false,
+ headerFilter: true
+ },
+ {
+ title: "OrgForm",
+ titlePhrase: 'lehre/orgform',
+ field: "orgform_kurzbz",
+ headerFilter: "list",
+ headerFilterParams: {
+ valuesLookup: true,
+ listOnEmpty: true,
+ autocomplete: true,
+ sort: "asc"
+ }
+ },
+ {
+ title: "Aufmerksamdurch",
+ titlePhrase: 'person/aufmerksamDurch',
+ field: "aufmerksamdurch_kurzbz",
+ visible: false
+ },
+ {
+ title: "Gesamtpunkte",
+ titlePhrase: 'admission/gesamtpunkte',
+ field: "punkte",
+ visible: false
+ },
+ {
+ title: "Aufnahmegruppe",
+ titlePhrase: 'stv/aufnahmegruppe_kurzbz',
+ field: "aufnahmegruppe_kurzbz",
+ visible: false
+ },
+ {
+ title: "Dual",
+ titlePhrase: 'lehre/dual_short',
+ field: "dual",
+ visible: false,
+ formatter: 'tickCross',
+ formatterParams: {
+ tickElement: '',
+ crossElement: ''
+ },
+ headerFilter: "tickCross",
+ headerFilterParams: {
+ "tristate": true,
+ elementAttributes: {
+ "value": "true"
+ }
+ },
+ headerFilterEmptyCheck(value) {
+ return value === null
+ }
+ },
+ {
+ title: "Matrikelnummer",
+ titlePhrase: 'person/matrikelnummer',
+ field: "matr_nr",
+ visible: false,
+ headerFilter: true
+ },
+ {
+ title: "Studienplan",
+ titlePhrase: 'lehre/studienplan',
+ field: "studienplan_bezeichnung",
+ headerFilter: "list",
+ headerFilterParams: {
+ valuesLookup: true,
+ listOnEmpty: true,
+ autocomplete: true,
+ sort: "asc"
+ }
+ },
+ {
+ title: "PreStudentInnenID",
+ titlePhrase: 'ui/prestudent_id',
+ field: "prestudent_id",
+ headerFilter: true
+ },
+ {
+ title: "Priorität",
+ titlePhrase: 'lehre/prioritaet',
+ field: "priorisierung_relativ"
+ },
+ {
+ title: "Mentor",
+ titlePhrase: 'stv/mentor',
+ field: "mentor",
+ visible: false
+ },
+ {
+ title: "Aktiv",
+ titlePhrase: 'person/aktiv',
+ field: "bnaktiv",
+ visible: false,
+ formatter: 'tickCross',
+ formatterParams: {
+ allowEmpty: true,
+ tickElement: '',
+ crossElement: ''
+ },
+ headerFilter: "tickCross",
+ headerFilterParams: {
+ "tristate": true,
+ elementAttributes: {
+ "value": "true"
+ }
+ },
+ headerFilterEmptyCheck(value) {
+ return value === null
+ }
+ },
+ {
+ title: "Unruly",
+ field: "unruly",
+ visible: false
+ }
+];
diff --git a/public/js/api/factory/studiensemester.js b/public/js/api/factory/studiensemester.js
index 7fe4a22d3..f57c10763 100644
--- a/public/js/api/factory/studiensemester.js
+++ b/public/js/api/factory/studiensemester.js
@@ -29,5 +29,20 @@ export default {
url: 'api/frontend/v1/organisation/studiensemester/getAll',
params: { order, start }
};
+ },
+ current() {
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/organisation/studiensemester/current'
+ };
+ },
+ set(studiensemester_kurzbz) {
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/organisation/studiensemester/set',
+ params: {
+ studiensemester_kurzbz
+ }
+ };
}
};
\ No newline at end of file
diff --git a/public/js/api/factory/stv.js b/public/js/api/factory/stv.js
index 95bc227f5..15ae15649 100644
--- a/public/js/api/factory/stv.js
+++ b/public/js/api/factory/stv.js
@@ -17,7 +17,6 @@
import app from './stv/app.js';
import lists from './stv/lists.js';
-import verband from './stv/verband.js';
import students from './stv/students.js';
import filter from './stv/filter.js';
import konto from './stv/konto.js';
@@ -34,7 +33,6 @@ import admissionDates from './stv/admissionDates.js';
export default {
app,
lists,
- verband,
students,
filter,
konto,
diff --git a/public/js/api/lehrveranstaltung/studiengangtree.js b/public/js/api/factory/treemenu.js
similarity index 68%
rename from public/js/api/lehrveranstaltung/studiengangtree.js
rename to public/js/api/factory/treemenu.js
index fb63db729..662297d22 100644
--- a/public/js/api/lehrveranstaltung/studiengangtree.js
+++ b/public/js/api/factory/treemenu.js
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2025 fhcomplete.org
+ * Copyright (C) 2026 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
@@ -16,26 +16,29 @@
*/
export default {
- get(path) {
- let url = 'api/frontend/v1/lv/StgTree';
- if (path)
- url += '/' + path;
+ get(config, path = '') {
return {
method: 'get',
- url
+ url: '/api/frontend/v1/treemenu/' + config + '/' + path
+ };
+ },
+ data(config, path = '') {
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/treemenudata/' + config + '/' + path
};
},
favorites: {
- get() {
+ get(config) {
return {
method: 'get',
- url: 'api/frontend/v1/lv/favorites'
+ url: 'api/frontend/v1/favorites/get/' + config
};
},
- set(favorites) {
+ set(config, favorites) {
return {
method: 'post',
- url: 'api/frontend/v1/lv/favorites/set',
+ url: 'api/frontend/v1/favorites/set/' + config,
params: { favorites }
};
}
diff --git a/public/js/api/stv.js b/public/js/api/stv.js
index 8a4e568ea..19125b1bf 100644
--- a/public/js/api/stv.js
+++ b/public/js/api/stv.js
@@ -1,4 +1,3 @@
-import verband from './stv/verband.js';
import students from './stv/students.js';
import filter from './stv/filter.js';
import konto from './stv/konto.js';
@@ -18,7 +17,6 @@ import jointstudies from "./stv/jointstudies.js";
import courselist from './stv/courselist.js';
export default {
- verband,
students,
filter,
konto,
diff --git a/public/js/api/stv/verband.js b/public/js/api/stv/verband.js
deleted file mode 100644
index f3479c81b..000000000
--- a/public/js/api/stv/verband.js
+++ /dev/null
@@ -1,15 +0,0 @@
-export default {
- get() {
- return this.$fhcApi.get('api/frontend/v1/stv/verband');
- },
- favorites: {
- get() {
- return this.$fhcApi.get('api/frontend/v1/stv/favorites');
- },
- set(favorites) {
- return this.$fhcApi.post('api/frontend/v1/stv/favorites/set', {
- favorites
- });
- }
- }
-}
\ No newline at end of file
diff --git a/public/js/apps/LVVerwaltung.js b/public/js/apps/LVVerwaltung.js
index 18f8a072f..22d3612ea 100644
--- a/public/js/apps/LVVerwaltung.js
+++ b/public/js/apps/LVVerwaltung.js
@@ -12,74 +12,13 @@ const router = VueRouter.createRouter({
component: LVVerwaltung
},
{
- name: `byEmp`,
- path: `/emp/:studiensemester_kurzbz/:emp/:stg?/:semester?`,
+ name: 'stdsem',
+ path: '/stdsem/:stdsem',
component: LVVerwaltung,
- props: route => {
- let {emp, stg, semester, studiensemester_kurzbz} = route.params;
-
- if (emp === '')
- emp = undefined;
-
- if (stg === '')
- stg = undefined;
-
- if (studiensemester_kurzbz === '')
- studiensemester_kurzbz = undefined;
-
- return {
- studiensemester_kurzbz: studiensemester_kurzbz,
- emp: emp,
- stg: stg,
- semester: semester
- };
- },
- beforeEnter: (to, from, next) => {
- const { studiensemester_kurzbz } = to.params;
- const isSemester = /^(SS|WS)\d{4}$/.test(studiensemester_kurzbz);
-
- if (!isSemester)
- return next({ path: '/' });
- else
- next();
- }
- },
- /*{
- name: `byFachbereich`,
- path: `/fachbereich/:fachbereich/:emp?`,
- component: LVVerwaltung
- },*/
- {
- name: `byStg`,
- path: '/stg/:studiensemester_kurzbz/:stg?/:semester?/',
- component: LVVerwaltung,
- props: route => {
- let { studiensemester_kurzbz, stg, semester } = route.params;
-
- if (semester === '')
- semester = undefined;
-
- if (studiensemester_kurzbz === '')
- studiensemester_kurzbz = undefined;
-
- if (stg === '')
- stg = undefined;
-
- return {
- studiensemester_kurzbz: studiensemester_kurzbz,
- stg: stg,
- semester: semester,
- };
- },
- beforeEnter: (to, from, next) => {
- const studiensemester_kurzbz = to.params?.studiensemester_kurzbz
- const isSemester = /^(SS|WS)\d{4}$/.test(studiensemester_kurzbz);
-
- if (!isSemester)
- return next({ path: '/' });
- else
- next();
- }
+ children: [
+ { name: 'emp', path: 'emp/:emp/:treemenu(.*)*', component: LVVerwaltung },
+ { name: 'treemenu', path: ':treemenu(.*)*', component: LVVerwaltung }
+ ]
},
{
path: '/:pathMatch(.*)*',
diff --git a/public/js/apps/Studentenverwaltung.js b/public/js/apps/Studentenverwaltung.js
index 47490bfdd..d22609fb9 100644
--- a/public/js/apps/Studentenverwaltung.js
+++ b/public/js/apps/Studentenverwaltung.js
@@ -24,167 +24,27 @@ import PluginsPhrasen from "../plugins/Phrasen.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(),
+ history: VueRouter.createWebHistory('/' + ciPath),
routes: [
{
name: 'index',
- path: `/${ciPath}/studentenverwaltung`,
- component: FhcStudentenverwaltung
- },
- {
- name: 'studiensemester',
- path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz`,
+ path: '/studvw',
component: FhcStudentenverwaltung,
- props: (route) => {
- return {
- url_studiensemester_kurzbz: route.params.studiensemester_kurzbz
- };
- },
- beforeEnter: (to, from, next) => {
- const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz);
- if (!isSemester) {
- return next({name: 'index'});
+ children: [
+ {
+ name: 'stdsem',
+ path: 'stdsem/:stdsem',
+ component: FhcStudentenverwaltung,
+ children: [
+ { name: 'search', path: 'search/:query', component: FhcStudentenverwaltung },
+ { name: 'searchtypes', path: 'search/:types/:query', component: FhcStudentenverwaltung },
+ { name: 'prestudent', path: 'prestudent/:prestudent_id', component: FhcStudentenverwaltung },
+ { name: 'student', path: 'student/:student_uid', component: FhcStudentenverwaltung },
+ { name: 'person', path: 'person/:person_id', component: FhcStudentenverwaltung },
+ { name: 'treemenu', path: ':treemenu(.*)*', component: FhcStudentenverwaltung },
+ ]
}
- next();
- }
- },
- {
- name: 'studiengang',
- path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/:studiengang`,
- component: FhcStudentenverwaltung,
- props: (route) => {
- return {
- url_studiensemester_kurzbz: route.params.studiensemester_kurzbz,
- url_studiengang: route.params.studiengang,
- };
- },
- beforeEnter: (to, from, next) => {
- const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz);
- if (!isSemester) {
- return next({name: 'index'});
- }
- const isStudiengang = /^[A-Z]{3}/.test(to.params.studiengang);
- if (!isStudiengang) {
- return next({
- name: 'studiensemester',
- params: {
- studiensemester_kurzbz: to.params.studiensemester_kurzbz
- }
- });
- }
- next();
- }
- },
- {
- path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/prestudent/:prestudent_id`,
- component: FhcStudentenverwaltung,
- props: (route) => {
- return {
- url_studiensemester_kurzbz: route.params.studiensemester_kurzbz,
- url_mode: 'prestudent',
- url_prestudent_id: route.params.prestudent_id
- };
- },
- beforeEnter: (to, from, next) => {
- const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz);
- if (!isSemester) {
- return next({name: 'index'});
- }
- next();
- }
- },
- {
- path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/prestudent/:prestudent_id/:tab`,
- component: FhcStudentenverwaltung,
- props: (route) => {
- return {
- url_studiensemester_kurzbz: route.params.studiensemester_kurzbz,
- url_mode: 'prestudent',
- url_prestudent_id: route.params.prestudent_id,
- url_tab: route.params.tab
- };
- },
- beforeEnter: (to, from, next) => {
- const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz);
- if (!isSemester) {
- return next({name: 'index'});
- }
- next();
- }
- },
- {
- path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/student/:id`,
- component: FhcStudentenverwaltung,
- props: (route) => {
- return {
- url_studiensemester_kurzbz: route.params.studiensemester_kurzbz,
- url_mode: 'student',
- url_student_id: route.params.id
- };
- },
- beforeEnter: (to, from, next) => {
- const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz);
- if (!isSemester) {
- return next({name: 'index'});
- }
- next();
- }
- },
- {
- path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/person/:person_id`,
- component: FhcStudentenverwaltung,
- props: (route) => {
- return {
- url_studiensemester_kurzbz: route.params.studiensemester_kurzbz,
- url_mode: 'person',
- url_prestudent_id: route.params.person_id
- };
- },
- beforeEnter: (to, from, next) => {
- const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz);
- if (!isSemester) {
- return next({name: 'index'});
- }
- next();
- }
- },
- {
- name: 'search',
- path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/search/:searchstr`,
- component: FhcStudentenverwaltung,
- props(route) {
- return {
- url_studiensemester_kurzbz: route.params.studiensemester_kurzbz,
- url_mode: 'search',
- url_prestudent_id: route.params.searchstr
- };
- },
- beforeEnter(to, from, next) {
- const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz);
- if (!isSemester) {
- return next({name: 'index'});
- }
- next();
- }
- },
- {
- name: 'search_w_types',
- path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/search/:types/:searchstr`,
- component: FhcStudentenverwaltung,
- props(route) {
- return {
- url_studiensemester_kurzbz: route.params.studiensemester_kurzbz,
- url_mode: 'search',
- url_prestudent_id: route.params.type + '/' + route.params.searchstr
- };
- },
- beforeEnter(to, from, next) {
- const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz);
- if (!isSemester) {
- return next({name: 'index'});
- }
- next();
- }
+ ]
},
{
path: '/:pathMatch(.*)*',
@@ -197,11 +57,16 @@ const router = VueRouter.createRouter({
router.afterEach((to, from, failure) => {
let title = 'Studierendenverwaltung FH-Complete';
- if (to.params.studiengang) {
- title = to.params.studiengang + ' ' + title;
+ if (to.params.treemenu) {
+ const index = to.params.treemenu.findIndex(
+ (e, i) => i%2 == 0 && e == 'stg'
+ );
+ if (index >= 0) {
+ title = to.params.treemenu[index + 1].toUpperCase() + ' ' + title;
+ }
}
- if (to.params.studiensemester_kurzbz) {
- title = to.params.studiensemester_kurzbz + ' ' + title;
+ if (to.params.stdsem) {
+ title = to.params.stdsem.toUpperCase() + ' ' + title;
}
document.title = title;
});
diff --git a/public/js/components/Base/Treemenu.js b/public/js/components/Base/Treemenu.js
new file mode 100644
index 000000000..5fe46606c
--- /dev/null
+++ b/public/js/components/Base/Treemenu.js
@@ -0,0 +1,363 @@
+import TreemenuEntry from './Treemenu/Entry.js';
+
+import dragClick from '../../directives/dragClick.js';
+
+import ApiTreemenu from '../../api/factory/treemenu.js';
+
+export default {
+ components: {
+ PvTreetable: primevue.treetable,
+ PvColumn: primevue.column,
+ TreemenuEntry
+ },
+ directives: {
+ dragClick
+ },
+ emits: [
+ 'selectEntry',
+ 'drop'
+ ],
+ props: {
+ config: {
+ type: String,
+ required: true,
+ },
+ preselectedKey: {
+ type: Array,
+ default: null
+ }
+ },
+ data() {
+ return {
+ loading: true,
+ nodes: [],
+ selectedKey: [],
+ expandedKeys: {},
+ filters: {}, // TODO(chris): filter only 1st level?
+ favorites: {on: false, list: []}
+ }
+ },
+ computed: {
+ filteredNodes() {
+ if (this.favorites.on)
+ return this.nodes.filter(node => this.favorites.list.includes(node.data.path));
+
+ return this.nodes;
+ }
+ },
+ watch: {
+ preselectedKey(newVal, oldVal) {
+ if (newVal !== oldVal) {
+ this.setPreselection();
+ }
+ }
+ },
+ methods: {
+ reloadNodesWithProp(prop, nodes = undefined) {
+ if (!nodes)
+ nodes = this.nodes;
+
+ nodes.forEach(node => {
+ if (node.data[prop]) {
+ // reload
+ delete node.children;
+ this.onExpandTreeNode(node);
+ } else if (node.children) {
+ this.reloadNodesWithProp(prop, node.children);
+ }
+ });
+ },
+ findNodeByKey(key, arr) {
+ if (!arr)
+ arr = this.nodes;
+ let res = arr.filter(n => n.key == key);
+ if (res.length)
+ return res.pop();
+ res = arr.map(n => n.children ? this.findNodeByKey(key, n.children) : null).filter(a => a);
+ if (res.length)
+ return res.pop();
+ return null;
+ },
+ async onExpandTreeNode(node) {
+ if (!node.children) {
+ if (node.data.path) {
+ /**
+ * NOTE(chris): activeEl is for keyboard navigation to
+ * prevent the focus jumping down to the next parent
+ * instead of the current submenu entry (which is not yet
+ * loaded)
+ */
+ let activeEl = null;
+ this.$nextTick(() => {
+ this.$nextTick(() => {
+ activeEl = document.activeElement;
+ });
+ });
+ this.loading = true;
+
+ return this.$api
+ .call(ApiTreemenu.get(this.config, node.data.path))
+ .then(result => {
+ const subNodes = result.data.map(this.mapResultToTreeData);
+ const realNode = this.findNodeByKey(node.key);
+ if (realNode)
+ realNode.children = subNodes;
+ else
+ node.children = subNodes; // NOTE(chris): fallback should never be the case
+
+ this.$nextTick(() => {
+ if (activeEl != document.activeElement)
+ return;
+
+ let treeitem = this.$refs.tree.$el.querySelector('[data-tree-item-key="' + node.key + '"]');
+ if (!treeitem)
+ return;
+
+ treeitem = treeitem.closest('[role="row"]');
+
+ if (!treeitem)
+ return;
+
+ treeitem.dispatchEvent(new KeyboardEvent('keydown', {
+ code: 'ArrowDown',
+ key: 'ArrowDown'
+ }));
+ });
+
+ this.loading = false;
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ }
+ }
+ },
+ onSelectTreeNode(node) {
+ this.$emit('selectEntry', node.data);
+ },
+ mapNodesToNoSemReloadNodes(result, node) {
+ if (node.data.no_sem_reload)
+ result.push(node);
+ if (node.children)
+ result = node.children.reduce(this.mapNodesToNoSemReloadNodes, result);
+ return result;
+ },
+ mapResultToTreeData(el) {
+ const cp = {
+ key: ("" + el.path).replace(/\//g, '-'),
+ data: el,
+ label: el.name // TODO(chris): phrase
+ };
+
+ if (el.children)
+ cp.children = el.children.map(this.mapResultToTreeData);
+ else
+ cp.leaf = el.leaf || false;
+
+ return cp;
+ },
+ async setPreselection()
+ {
+ if (!this.preselectedKey || !this.preselectedKey.length)
+ {
+ this.selectedKey = null;
+ return;
+ }
+
+ if (!this.preselectedKey || !Array.isArray(this.preselectedKey))
+ return;
+
+ // [1, 2, 3, 4, ...] => ['1-2', '3-4', ...]
+ const parts = this.preselectedKey.reduce((r, c, i, a) => (i%2 && r.push(a[i-1] + '-' + c), r), []);
+ let currentKey = parts[0];
+ let currentNode = this.findNodeByKey(currentKey);
+
+ if (!currentNode)
+ return;
+
+ if(this.selectedKey)
+ {
+ const currentSelectedKey = Object.keys(this.selectedKey).find(Boolean);
+ if (currentSelectedKey) {
+ if (currentSelectedKey == currentKey)
+ return;
+ /**
+ * Do not select a new entry if the current is a child of the new one.
+ * This happens if a child entry of a new stg is selected and the router
+ * tries to select the stg root entry (because subtrees do not have
+ * routes yet)
+ */
+ const isChild = this.findNodeByKey(
+ currentSelectedKey,
+ currentNode.children || []
+ );
+ if (isChild)
+ return;
+ }
+ }
+
+ for (let i = 1; i < parts.length; i++)
+ {
+ this.expandedKeys[currentNode.key] = true;
+
+ await this.onExpandTreeNode(currentNode);
+
+ currentKey += '-' + parts[i];
+ currentNode = this.findNodeByKey(currentKey);
+
+ if (!currentNode)
+ {
+ return;
+ }
+ }
+
+ this.selectedKey = {[currentNode.key]: true};
+ this.onSelectTreeNode(currentNode);
+ },
+ async toggleTreeNode(node) {
+ if (this.expandedKeys[node.key]) {
+ delete this.expandedKeys[node.key];
+ } else if (!node.leaf) {
+ await this.onExpandTreeNode(node);
+ this.expandedKeys[node.key] = true;
+ }
+ },
+ filterFav() {
+ this.favorites.on = !this.favorites.on;
+ this.$api
+ .call(ApiTreemenu.favorites.set(
+ this.config,
+ JSON.stringify(this.favorites)
+ ));
+ },
+ markFav(key) {
+ let index = this.favorites.list.indexOf(key.data.path + '');
+
+ if (index != -1) {
+ this.favorites.list.splice(index, 1);
+ } else {
+ this.favorites.list.push(key.data.path + '');
+ }
+
+ this.$api
+ .call(ApiTreemenu.favorites.set(
+ this.config,
+ JSON.stringify(this.favorites)
+ ));
+ },
+ unsetFavFocus(e) {
+ if (e.target.dataset?.linkFavAdd !== undefined) {
+ e.target.tabIndex = -1;
+ } else {
+ let items = e.target.querySelectorAll('[data-link-fav-add]:not([tabindex="-1"])');
+ items.forEach(el => el.tabIndex = document.activeElement == el ? 0 : -1);
+ }
+ },
+ setFavFocus(e) {
+ if (e.target.dataset?.linkFavAdd !== undefined) {
+ e.target.tabIndex = 0;
+ } else {
+ let items = e.target.querySelectorAll('[data-link-fav-add][tabindex="-1"]');
+ items.forEach(el => el.tabIndex = 0);
+ }
+ }
+ },
+ mounted() {
+ this.$api
+ .call(ApiTreemenu.get(this.config))
+ .then(result => {
+ this.nodes = result.data.map(el => {
+ el.root = true;
+ return this.mapResultToTreeData(el);
+ });
+ this.setPreselection();
+ this.loading = false;
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+
+ this.$api
+ .call(ApiTreemenu.favorites.get(this.config))
+ .then(result => {
+ if (result.data) {
+ this.favorites = JSON.parse(result.data);
+ }
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ template: /* html */`
+