Compare commits

...
Author SHA1 Message Date
Paolo b2af21124e - Checksystem adds new column account_creation to the table public.tbl_studiengang
- Changed include/studiengang.class.php to make use of the new column account_creation
- Changed vilesci/stammdaten/studiengang* to make use of the new column account_creation
2026-10-06 11:01:49 +02:00
Harald Bamberger 4ba2869632 Merge branch 'master' into bugfix-83059_incorrect-ical-semester-parameters 2026-10-05 11:22:59 +02:00
Andreas Österreicher 293bb77179 Merge branch 'bug-44023/EingabemaskeEntwicklungsteamNamenOhneUid2' 2026-10-02 13:23:02 +02:00
Andreas Österreicher 3fe10d715d Fixed Saving of Entwicklungsteam 2026-10-02 13:14:41 +02:00
Andreas Österreicher 36064afbba Fixed Testing Projektarbeit Seeds 2026-10-01 15:33:05 +02:00
Harald Bamberger f3d031ab16 cismenu: add cis-main-menu class to main nav, add li elements to ul, style cis-main-menu ul and li to prevent interferec with cms content styles, add draggable false to cis menu entries to improve menu scrolling especially on mobile devices 2026-10-01 11:48:51 +02:00
Harald Bamberger 3d8c4fa4d0 Merge branch 'feature-77757/WidgetsBerechtigung' 2026-09-30 15:48:00 +02:00
Harald Bamberger 272014bd78 remove odd phrases 2026-09-30 15:38:43 +02:00
Harald Bamberger 76a8e00edf Merge branch 'master' into feature-77757/WidgetsBerechtigung 2026-09-30 15:23:08 +02:00
Harald Bamberger c8c7d1566c Merge branch 'master' into bugfix-83059_incorrect-ical-semester-parameters 2026-09-11 11:43:23 +02:00
adisposkofh 9d4218bf38 implemented displayed semester/ical dates changes from my lv plan to other lv plan 2026-09-09 11:36:19 +02:00
adisposkofh 67f30c7765 fixed issue with wrong semester displayed and wrong ical dates used in my lv plan 2026-09-09 11:30:43 +02:00
Johann Hoffmann d40040efd8 added new fkey to tbl_widget for system.tbl_berechtigung; check for permission status during load & in widget picker; if widget was already picked/configured but not permitted anymore -> show a generalized "missing permission" screen via fallback component during widget init; 2026-07-21 18:14:26 +02:00
22 changed files with 435 additions and 96 deletions
@@ -101,6 +101,9 @@ class Widget extends FHCAPI_Controller
$tmpsetup = json_decode($widget->setup);
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
$widget->setup = $tmpsetup;
$widget->permitted = empty($widget->berechtigung_kurzbz)
|| $this->permissionlib->isBerechtigt($widget->berechtigung_kurzbz);
return $widget;
}, $widgets);
@@ -28,7 +28,8 @@ class Studiensemester extends FHCAPI_Controller
'getStudienjahrByStudiensemester' => self::PERM_LOGGED,
'getAllStudiensemesterAndAktOrNext' => self::PERM_LOGGED,
'current' => self::PERM_LOGGED,
'set' => self::PERM_LOGGED
'set' => self::PERM_LOGGED,
'getContainingOrNearestByDateRange' => self::PERM_LOGGED,
)
);
// Load model StudiensemesterModel
@@ -203,4 +204,15 @@ class Studiensemester extends FHCAPI_Controller
$this->terminateWithSuccess(true);
}
public function getContainingOrNearestByDateRange()
{
$from = $this->input->get("from");
$to = $this->input->get("to");
$result = $this->StudiensemesterModel->getContainingOrNearestByDateRange($from, $to);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
}
@@ -292,13 +292,29 @@ class Studiensemester_model extends DB_Model
COALESCE(
(SELECT studiensemester_kurzbz FROM semester_interval_startdate),
(SELECT studiensemester_kurzbz FROM nearest_semester_interval_startdate)
) AS studiensemester_kurzbz
) AS studiensemester_kurzbz,
COALESCE(
(SELECT start FROM semester_interval_startdate),
(SELECT start FROM nearest_semester_interval_startdate)
) as start,
COALESCE(
(SELECT ende FROM semester_interval_startdate),
(SELECT ende FROM nearest_semester_interval_startdate)
) as ende
UNION
SELECT
COALESCE(
(SELECT studiensemester_kurzbz FROM semester_interval_enddate),
(SELECT studiensemester_kurzbz FROM nearest_semester_interval_enddate)
) AS studiensemester_kurzbz
) AS studiensemester_kurzbz,
COALESCE(
(SELECT start FROM semester_interval_enddate),
(SELECT start FROM nearest_semester_interval_enddate)
) as start,
COALESCE(
(SELECT ende FROM semester_interval_enddate),
(SELECT ende FROM nearest_semester_interval_enddate)
) as ende
EOSQL;
+63 -25
View File
@@ -21,6 +21,7 @@
* Manuela Thamer <[email protected]>
*/
require_once(dirname(__FILE__).'/basis_db.class.php');
require_once(dirname(__FILE__).'/mitarbeiter.class.php');
class entwicklungsteam extends basis_db
{
@@ -43,7 +44,6 @@ class entwicklungsteam extends basis_db
public $ext_id;
public $besqual;
public $studiengang_kz_old;
/**
* Konstruktor
@@ -74,7 +74,7 @@ class entwicklungsteam extends basis_db
$qry = "SELECT * FROM bis.tbl_entwicklungsteam JOIN bis.tbl_besqual USING(besqualcode)
WHERE entwicklungsteam_id=".$this->db_add_param($entwicklungsteam_id);
$qry.=";";
$qry.=";";
if($this->db_query($qry))
{
@@ -147,6 +147,11 @@ class entwicklungsteam extends basis_db
$this->errormsg = 'Es muss ein Mitarbeiter angegeben werden';
return false;
}
if(!$this->checkIfExistingUid($this->mitarbeiter_uid))
{
$this->errormsg = 'Bitte einen Eintrag aus dem Dropdown Personensuche auswählen!';
return false;
}
if($this->studiengang_kz=='')
{
$this->errormsg = 'Es muss ein Studiengang angegeben werden';
@@ -162,6 +167,26 @@ class entwicklungsteam extends basis_db
$this->errormsg = 'Endedatum darf nicht vor Anfangsdatum liegen';
return false;
}
if($this->beginn != '')
{
$beginnParts = explode('-', $this->beginn);
if (!checkdate((int)$beginnParts[1], (int)$beginnParts[2], (int)$beginnParts[0])) {
$this->errormsg = 'Anfangsdatum ist ungültig';
return false;
}
}
if($this->ende != '')
{
$endeParts = explode('-', $this->ende);
if (!checkdate((int)$endeParts[1], (int)$endeParts[2], (int)$endeParts[0]))
{
$this->errormsg = 'Endedatum ist ungültig';
return false;
}
}
return true;
}
@@ -183,30 +208,28 @@ class entwicklungsteam extends basis_db
//Neuen Datensatz anlegen
$qry = "INSERT INTO bis.tbl_entwicklungsteam (mitarbeiter_uid, studiengang_kz, besqualcode, beginn, ende,
updateamum, updatevon, insertamum, insertvon) VALUES (".
$this->db_add_param($this->mitarbeiter_uid).', '.
$this->db_add_param($this->studiengang_kz, FHC_INTEGER).', '.
$this->db_add_param($this->besqualcode, FHC_INTEGER).', '.
$this->db_add_param($this->beginn).', '.
$this->db_add_param($this->ende).', '.
$this->db_add_param($this->updateamum).', '.
$this->db_add_param($this->updatevon).', '.
$this->db_add_param($this->insertamum).', '.
$this->db_add_param($this->insertvon).');';
$this->db_add_param($this->mitarbeiter_uid).', '.
$this->db_add_param($this->studiengang_kz, FHC_INTEGER).', '.
$this->db_add_param($this->besqualcode, FHC_INTEGER).', '.
$this->db_add_param($this->beginn).', '.
$this->db_add_param($this->ende).', '.
$this->db_add_param($this->updateamum).', '.
$this->db_add_param($this->updatevon).', '.
$this->db_add_param($this->insertamum).', '.
$this->db_add_param($this->insertvon).');';
}
else
{
if($this->studiengang_kz_old=='')
$this->studiengang_kz_old = $this->studiengang_kz;
//Bestehenden Datensatz aktualisieren
$qry= "UPDATE bis.tbl_entwicklungsteam SET".
" besqualcode=".$this->db_add_param($this->besqualcode, FHC_INTEGER).",".
" beginn=".$this->db_add_param($this->beginn).",".
" studiengang_kz=".$this->db_add_param($this->studiengang_kz, FHC_INTEGER).",".
" ende=".$this->db_add_param($this->ende).",".
" updateamum=".$this->db_add_param($this->updateamum).",".
" updatevon=".$this->db_add_param($this->updatevon).
" WHERE entwicklungsteam_id=".$this->db_add_param($this->entwicklungsteam_id).";";
" besqualcode=".$this->db_add_param($this->besqualcode, FHC_INTEGER).",".
" beginn=".$this->db_add_param($this->beginn).",".
" studiengang_kz=".$this->db_add_param($this->studiengang_kz, FHC_INTEGER).",".
" ende=".$this->db_add_param($this->ende).",".
" mitarbeiter_uid=".$this->db_add_param($this->mitarbeiter_uid).",".
" updateamum=".$this->db_add_param($this->updateamum).",".
" updatevon=".$this->db_add_param($this->updatevon).
" WHERE entwicklungsteam_id=".$this->db_add_param($this->entwicklungsteam_id).";";
}
if($this->db_query($qry))
@@ -234,7 +257,7 @@ class entwicklungsteam extends basis_db
if($studiengang_kz!=null)
$qry.=" AND studiengang_kz=".$this->db_add_param($studiengang_kz);
$qry.=";";
$qry.=";";
if($this->db_query($qry))
{
@@ -316,7 +339,7 @@ class entwicklungsteam extends basis_db
if ($sort != null)
{
$qry .= " ORDER BY ".$sort;
$qry .= " ORDER BY ".$sort;
}
$qry .= ";";
@@ -364,7 +387,7 @@ class entwicklungsteam extends basis_db
$bismeldung_jahr = $datetime->format('Y');
//laden des Datensatzes
$qry = "SELECT tbl_entwicklungsteam.*, tbl_besqual.*, tbl_studiengang.studiengang_kz, tbl_studiengang.melderelevant
$qry = "SELECT tbl_entwicklungsteam.*, tbl_besqual.*, tbl_studiengang.studiengang_kz, tbl_studiengang.melderelevant
FROM bis.tbl_entwicklungsteam
JOIN bis.tbl_besqual USING(besqualcode)
JOIN public.tbl_studiengang USING(studiengang_kz)
@@ -375,7 +398,7 @@ class entwicklungsteam extends basis_db
if($studiengang_kz!=null)
$qry.=" AND studiengang_kz=".$this->db_add_param($studiengang_kz);
$qry.=";";
$qry.=";";
if($this->db_query($qry))
{
@@ -407,5 +430,20 @@ class entwicklungsteam extends basis_db
return false;
}
}
/*
* Überprüft, ob die übergebene Uid in der Tabelle tbl_mitarbeiter vorhanden ist
* @param String $uid UID des Mitarbeiters
* @return true wenn vorhanden, false wenn nicht
*/
private function checkIfExistingUid($uid)
{
$mitarbeiter = new mitarbeiter();
if(!$mitarbeiter->checkIfExistingUid($uid))
return false;
return true;
}
}
?>
+18
View File
@@ -1995,5 +1995,23 @@ class mitarbeiter extends benutzer
return true;
}
}
/**
* Prueft ob eine existierende ma_uid übergeben wurde
* @param String $mitarbeiter_uid mitarbeiter_uid
* @return bool True wenn mitarbeiter_uid vorhanden sonst false.
*/
public function checkIfExistingUid($mitarbeiter_uid)
{
$qry = "Select 1 from public.tbl_mitarbeiter where mitarbeiter_uid =".$this->db_add_param($mitarbeiter_uid);
if ($result = $this->db_query($qry))
{
if ($this->db_num_rows($result) > 0)
return true;
else
return false;
}
}
}
?>
+36 -3
View File
@@ -57,6 +57,7 @@ class studiengang extends basis_db
public $foerderrelevant; // boolean
public $standort_code; // integer
public $melde_studiengang_kz; // varchar(32)
public $account_creation; // boolean
public $kuerzel; // = typ + kurzbz (Bsp: BBE)
public $kuerzel_arr = array(); // Array mit allen Kurzeln Index=studiengangs_kz
@@ -76,6 +77,8 @@ class studiengang extends basis_db
{
parent::__construct();
$this->account_creation = true; // default value
if(!is_null($studiengang_kz))
$this->load($studiengang_kz);
}
@@ -136,6 +139,7 @@ class studiengang extends basis_db
$this->foerderrelevant = $this->db_parse_bool($row->foerderrelevant);
$this->standort_code = $row->standort_code;
$this->melde_studiengang_kz = $row->melde_studiengang_kz;
$this->account_creation = $this->db_parse_bool($row->account_creation);
$this->bezeichnung_arr['German'] = $this->bezeichnung;
$this->bezeichnung_arr['English'] = $this->english;
@@ -213,6 +217,7 @@ class studiengang extends basis_db
$stg_obj->foerderrelevant = $this->db_parse_bool($row->foerderrelevant);
$stg_obj->standort_code = $row->standort_code;
$stg_obj->melde_studiengang_kz = $row->melde_studiengang_kz;
$stg_obj->account_creation = $this->db_parse_bool($row->account_creation);
$stg_obj->bezeichnung_arr['German'] = $row->bezeichnung;
$stg_obj->bezeichnung_arr['English'] = $row->english;
@@ -435,6 +440,7 @@ class studiengang extends basis_db
$stg_obj->foerderrelevant = $this->db_parse_bool($row->foerderrelevant);
$stg_obj->standort_code = $row->standort_code;
$stg_obj->melde_studiengang_kz = $row->melde_studiengang_kz;
$stg_obj->account_creation = $this->db_parse_bool($row->account_creation);
$stg_obj->bezeichnung_arr['German'] = $row->bezeichnung;
$stg_obj->bezeichnung_arr['English'] = $row->english;
@@ -510,7 +516,7 @@ class studiengang extends basis_db
typ, farbe, email, telefon, max_verband, max_semester, max_gruppe, erhalter_kz, bescheid, bescheidbgbl1,
bescheidbgbl2, bescheidgz, bescheidvom, titelbescheidvom, aktiv, onlinebewerbung, orgform_kurzbz, zusatzinfo_html,
oe_kurzbz, moodle, sprache, testtool_sprachwahl, studienplaetze, lgartcode, mischform,projektarbeit_note_anzeige,
melderelevant, foerderrelevant, standort_code, melde_studiengang_kz) VALUES ('.
melderelevant, foerderrelevant, standort_code, melde_studiengang_kz, account_creation) VALUES ('.
$this->db_add_param($this->studiengang_kz, FHC_INTEGER).', '.
$this->db_add_param($this->kurzbz).', '.
$this->db_add_param($this->kurzbzlang).', '.
@@ -545,7 +551,8 @@ class studiengang extends basis_db
$this->db_add_param($this->melderelevant, FHC_BOOLEAN).','.
$this->db_add_param($this->foerderrelevant, FHC_BOOLEAN).','.
$this->db_add_param($this->standort_code).','.
$this->db_add_param($this->melde_studiengang_kz).');';
$this->db_add_param($this->melde_studiengang_kz).','.
$this->db_add_param($this->account_creation, FHC_BOOLEAN).');';
}
else
{
@@ -586,7 +593,8 @@ class studiengang extends basis_db
'melderelevant='.$this->db_add_param($this->melderelevant, FHC_BOOLEAN).', '.
'foerderrelevant='.$this->db_add_param($this->foerderrelevant, FHC_BOOLEAN).', '.
'standort_code='.$this->db_add_param($this->standort_code).', '.
'melde_studiengang_kz='.$this->db_add_param($this->melde_studiengang_kz).' '.
'melde_studiengang_kz='.$this->db_add_param($this->melde_studiengang_kz).', '.
'account_creation='.$this->db_add_param($this->account_creation, FHC_BOOLEAN).' '.
'WHERE studiengang_kz='.$this->db_add_param($this->studiengang_kz, FHC_INTEGER, false).';';
}
@@ -627,6 +635,27 @@ class studiengang extends basis_db
}
/**
* Toggle the IDAM flag account_creation
*/
public function toggleAccountCreation($studiengang_kz)
{
if( !is_numeric($studiengang_kz))
{
$this->errormsg = 'Studiengang_kz muss eine gueltige Zahl sein';
return false;
}
$qry = 'UPDATE public.tbl_studiengang SET account_creation = NOT account_creation WHERE studiengang_kz = '.$this->db_add_param($studiengang_kz, FHC_INTEGER);
if (!$this->db_query($qry))
{
$this->errormsg = 'Fehler beim Speichern des Datensatzes';
return false;
}
return true;
}
/**
* Liefert die UIDs der Studiengangsleiter
*
@@ -713,6 +742,7 @@ class studiengang extends basis_db
$this->foerderrelevant = $this->db_parse_bool($row->foerderrelevant);
$this->standort_code = $row->standort_code;
$this->melde_studiengang_kz = $row->melde_studiengang_kz;
$this->account_creation = $this->db_parse_bool($row->account_creation);
$this->projektarbeit_note_anzeige = $this->db_parse_bool($row->projektarbeit_note_anzeige);
$this->bezeichnung_arr['German'] = $this->bezeichnung;
@@ -857,6 +887,7 @@ class studiengang extends basis_db
$obj->foerderrelevant = $this->db_parse_bool($row->foerderrelevant);
$obj->standort_code = $row->standort_code;
$obj->melde_studiengang_kz = $row->melde_studiengang_kz;
$obj->account_creation = $this->db_parse_bool($row->account_creation);
$obj->aktiv = $this->db_parse_bool($row->aktiv);
$this->result[] = $obj;
@@ -1038,6 +1069,7 @@ class studiengang extends basis_db
$obj->foerderrelevant = $this->db_parse_bool($row->foerderrelevant);
$obj->standort_code = $row->standort_code;
$obj->melde_studiengang_kz = $row->melde_studiengang_kz;
$obj->account_creation = $this->db_parse_bool($row->account_creation);
$obj->bezeichnung_arr['German'] = $obj->bezeichnung;
$obj->bezeichnung_arr['English'] = $obj->english;
@@ -1176,6 +1208,7 @@ class studiengang extends basis_db
$obj->foerderrelevant = $this->db_parse_bool($row->foerderrelevant);
$obj->standort_code = $row->standort_code;
$obj->melde_studiengang_kz = $row->melde_studiengang_kz;
$obj->account_creation = $this->db_parse_bool($row->account_creation);
$obj->bezeichnung_arr['German'] = $obj->bezeichnung;
$obj->bezeichnung_arr['English'] = $obj->english;
+17 -1
View File
@@ -853,4 +853,20 @@ html {
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.5rem;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
}
}
.cis-main-menu {
max-width: 100vw;
}
.cis-main-menu ul {
list-style: none;
margin: 0;
padding: 0;
}
.cis-main-menu ul li {
margin: 0;
padding: 0;
width: 100%;
}
+11 -1
View File
@@ -44,5 +44,15 @@ export default {
studiensemester_kurzbz
}
};
}
},
getContainingOrNearestByDateRange(from, to) {
return {
method: 'get',
url: 'api/frontend/v1/organisation/studiensemester/getContainingOrNearestByDateRange',
params: {
from,
to,
}
};
},
};
+30 -19
View File
@@ -1,6 +1,7 @@
import FhcCalendar from "../../Calendar/LvPlan.js";
import ApiLvPlan from '../../../api/factory/lvPlan.js';
import ApiStudienSemester from '../../../api/factory/studiensemester.js';
import ApiAuthinfo from '../../../api/factory/authinfo.js';
export const DEFAULT_MODE_LVPLAN_DESKTOP = "Week";
@@ -16,13 +17,12 @@ export default {
},
data() {
return {
studiensemester_kurzbz: null,
studiensemester_start: null,
studiensemester_ende: null,
uid: null,
isMitarbeiter: false,
isStudent: false,
timezone: FHC_JS_DATA_STORAGE_OBJECT.timezone,
startSemester: null,
endSemester: null,
};
},
inject: ["isMobile"],
@@ -48,9 +48,12 @@ export default {
return this.propsViewData?.mode;
},
downloadLinks() {
if (!this.studiensemester_start || !this.studiensemester_ende || !this.uid)
return false;
const startDate = this.startSemester?.start;
const endDate = this.endSemester ? this.endSemester.ende : this.startSemester?.ende;
if (!startDate || !endDate || !this.uid)
return false;
let type = false;
type = this.isStudent ? 'student' : type;
type = this.isMitarbeiter ? 'lektor' : type;
@@ -61,10 +64,10 @@ export default {
const opts = { zone: this.timezone };
const start = luxon.DateTime
.fromISO(this.studiensemester_start, opts)
.fromISO(startDate, opts)
.toUnixInteger();
const ende = luxon.DateTime
.fromISO(this.studiensemester_ende, opts)
.fromISO(endDate, opts)
.toUnixInteger();
const download_link = FHC_JS_DATA_STORAGE_OBJECT.app_root
@@ -109,16 +112,21 @@ export default {
}
});
},
updateRange(rangeInterval) {
this.$api
.call(ApiLvPlan.studiensemesterDateInterval(
rangeInterval.end.startOf('week').toISODate()
))
.then(res => {
this.studiensemester_kurzbz = res.data.studiensemester_kurzbz;
this.studiensemester_start = res.data.start;
this.studiensemester_ende = res.data.ende;
});
async updateRange(rangeInterval) {
const semesterResponse = await this.$api.call(
ApiStudienSemester.getContainingOrNearestByDateRange(
rangeInterval.s.toISO().slice(0, 10),
rangeInterval.e.toISO().slice(0, 10),
),
);
this.startSemester =
semesterResponse.data.length
? semesterResponse.data[0]
: null;
this.endSemester =
semesterResponse.data.length > 1
? semesterResponse.data[1]
: null;
},
getPromiseFunc(start, end) {
return [
@@ -142,8 +150,11 @@ export default {
<div class="cis-lvplan-personal d-flex flex-column h-100">
<h2>
{{ $p.t('lehre/stundenplan') }}
<span v-if="studiensemester_kurzbz" class="ps-3">
{{ studiensemester_kurzbz }}
<span v-if="startSemester?.studiensemester_kurzbz">
{{ startSemester.studiensemester_kurzbz }}
<span v-if="endSemester?.studiensemester_kurzbz">
{{ "- " + endSemester.studiensemester_kurzbz }}
</span>
</span>
</h2>
<hr>
+32 -25
View File
@@ -5,6 +5,7 @@ import FhcCalendar from "../../Calendar/LvPlan.js";
import ApiLvPlan from "../.././../api/factory/lvPlan.js";
import ApiOtherLvPlan from "../.././../api/factory/otherLvPlan.js";
import ApiAuthinfo from "../../../api/factory/authinfo.js";
import ApiStudienSemester from '../../../api/factory/studiensemester.js';
export const DEFAULT_MODE_LVPLAN_DESKTOP = "Week";
export const DEFAULT_MODE_LVPLAN_MOBILE = "List";
@@ -22,9 +23,6 @@ export default {
data() {
return {
localProps: {},
studiensemester_kurzbz: null,
studiensemester_start: null,
studiensemester_ende: null,
isOtherPersonMitarbeiter: false,
isOtherPersonStudent: false,
currentStgBezeichnung: null,
@@ -36,6 +34,8 @@ export default {
photo: "",
},
timezone: FHC_JS_DATA_STORAGE_OBJECT.timezone,
startSemester: null,
endSemester: null,
};
},
inject: ["isMobile"],
@@ -67,11 +67,10 @@ export default {
// do not show download links in otherLvPlan Mode
return false;
if (
!this.studiensemester_start ||
!this.studiensemester_ende ||
!this.propsViewData.otherUid
)
const startDate = this.startSemester?.start;
const endDate = this.endSemester ? this.endSemester.ende : this.startSemester?.ende;
if (!startDate || !endDate || !this.uid)
return false;
const type = this.isOtherPersonStudent
@@ -84,11 +83,11 @@ export default {
const opts = { zone: this.timezone };
const start = luxon.DateTime.fromISO(
this.studiensemester_start,
startDate,
opts,
).toUnixInteger();
const ende = luxon.DateTime.fromISO(
this.studiensemester_ende,
endDate,
opts,
).toUnixInteger();
@@ -166,19 +165,21 @@ export default {
},
});
},
updateRange(rangeInterval) {
this.$api
.call(
ApiLvPlan.studiensemesterDateInterval(
rangeInterval.end.startOf("week").toISODate(),
),
)
.then((res) => {
this.studiensemester_kurzbz =
res.data.studiensemester_kurzbz;
this.studiensemester_start = res.data.start;
this.studiensemester_ende = res.data.ende;
});
async updateRange(rangeInterval) {
const semesterResponse = await this.$api.call(
ApiStudienSemester.getContainingOrNearestByDateRange(
rangeInterval.s.toISO().slice(0, 10),
rangeInterval.e.toISO().slice(0, 10),
),
);
this.startSemester =
semesterResponse.data.length
? semesterResponse.data[0]
: null;
this.endSemester =
semesterResponse.data.length > 1
? semesterResponse.data[1]
: null;
},
getPromiseFunc(start, end) {
return [
@@ -250,8 +251,14 @@ export default {
<div class="d-flex flex-column h-100">
<h2>
<div class="d-flex flex-row justify-content-between align-items-center">
<span>
{{ $p.t('lehre/stundenplan') + (studiensemester_kurzbz ? " " + studiensemester_kurzbz : "") }}
<span>
{{ $p.t('lehre/stundenplan') }}
<span v-if="startSemester?.studiensemester_kurzbz">
{{ startSemester.studiensemester_kurzbz }}
<span v-if="endSemester?.studiensemester_kurzbz">
{{ "- " + endSemester.studiensemester_kurzbz }}
</span>
</span>
</span>
<div @click="this.$router.push({name: 'ProfilView', params: {uid: propsViewData.otherUid}})" type="button" class="d-flex flex-row align-items-center gap-3">
<span v-if="otherPersonData.fullNameWithTitle?.length">
+1 -1
View File
@@ -186,7 +186,7 @@ export default {
</div>
</div>
<nav id="nav-main" class="offcanvas offcanvas-start" tabindex="-1" aria-labelledby="nav-main-btn" data-bs-backdrop="false">
<nav id="nav-main" class="cis-main-menu offcanvas offcanvas-start" tabindex="-1" aria-labelledby="nav-main-btn" data-bs-backdrop="false">
<div id="nav-main-sticky">
<div class="d-flex flex-row h-100">
<div class="offcanvas-body p-0">
+5 -1
View File
@@ -162,6 +162,7 @@ export default {
<div class="btn-group w-100">
<a :target="target"
:href="(entry.menu_open && hasFullLink) ? entry.url : null"
draggable="false"
@click="toggleCollapse"
:class="{
'btn btn-default rounded-0 text-start': true,
@@ -180,12 +181,15 @@ export default {
</div>
<ul ref="children"
class="nav w-100 collapse">
<cis-menu-entry :highestMatchingUrlCount="highestMatchingUrlCount" :activeContent="activeContent" v-for="child in entry.childs" :key="child" :entry="child" :level="level + 1"/>
<li>
<cis-menu-entry :highestMatchingUrlCount="highestMatchingUrlCount" :activeContent="activeContent" v-for="child in entry.childs" :key="child" :entry="child" :level="level + 1"/>
</li>
</ul>
</template>
<a v-else
:href="entry.url"
:target="target"
draggable="false"
:class="{
'btn btn-default rounded-0 w-100 text-start': true,
['btn-level-' + level]: true,
+13 -2
View File
@@ -1,5 +1,6 @@
import BsModal from "../Bootstrap/Modal.js";
import HeightTransition from "../Tranistion/HeightTransition.js";
import MissingPermissionWidget from "../DashboardWidget/MissingPermission.js";
import { enableDragDropTouch } from "../../../../vendor/drag-drop-touch-js/dragdroptouch/dist/drag-drop-touch.esm.min.js";
@@ -112,6 +113,12 @@ export default {
isPinned() {
return this.place?.pinned ? true : false;
},
permitted() {
// widgets without a linked permission (or before the template loaded)
// are considered permitted; the backend sets permitted === false only
// when the user is missing the widget's required permission
return this.widgetTemplate?.permitted !== false;
},
ready() {
return this.component && this.arguments !== null;
}
@@ -169,7 +176,11 @@ export default {
&& this.widgetTemplate.widget_id
&& this.widgetTemplate.arguments
) {
let component = (await import(this.widgetTemplate.setup.file)).default;
// render the "missing permission" screen instead of the actual
// widget when the user does not hold the widget's linked permission
let component = this.permitted
? (await import(this.widgetTemplate.setup.file)).default
: MissingPermissionWidget;
this.$options.components["widget" + this.widgetTemplate.widget_id] = component;
this.component = "widget" + this.widgetTemplate.widget_id;
this.arguments = { ...this.widgetTemplate.arguments, ...this.config };
@@ -269,7 +280,7 @@ export default {
</template>
<!-- widget link -->
<a
v-if="widgetTemplate.setup.cis4link"
v-if="widgetTemplate.setup.cis4link && permitted"
:href="getWidgetC4Link(widgetTemplate)"
class="col-auto ms-auto"
:aria-label="$p.t('dashboard/widget_link')"
@@ -14,10 +14,14 @@ export default {
callbacks: {}
}),
computed: {
// filter widgets away the user has no permissions for
availableWidgets() {
return (this.widgets || []).filter(widget => widget.permitted !== false);
},
hasAnyWidgets() {
if (!this.widgets)
return false;
if (!this.widgets.length && !this.hiddenWidgets?.length)
if (!this.availableWidgets.length && !this.hiddenWidgets?.length)
return false;
return true;
}
@@ -54,7 +58,7 @@ export default {
<template v-slot:default>
<template v-if="widgets && hiddenWidgets">
<div
v-if="!widgets.length && !hiddenWidgets.length"
v-if="!availableWidgets.length && !hiddenWidgets.length"
class="row g-2"
>
<div>{{ $p.t('dashboard/noWidgetsAvailable') }}</div>
@@ -74,16 +78,17 @@ export default {
</div>
</div>
<div
v-if="widgets.length"
v-if="availableWidgets.length"
class="row g-2"
>
<div
v-for="widget in widgets"
<template
v-for="widget in availableWidgets"
:key="widget.widget_id"
class="widget-icon-container col-sm-6 col-md-4 col-lg-3 col-xl-2"
>
<widget-icon @select="pick" :widget="widget"></widget-icon>
</div>
<div v-if="widget.permitted" class="widget-icon-container col-sm-6 col-md-4 col-lg-3 col-xl-2">
<widget-icon @select="pick" :widget="widget"></widget-icon>
</div>
</template>
</div>
</template>
</template>
@@ -0,0 +1,21 @@
import AbstractWidget from './Abstract.js';
/**
* Fallback screen rendered in place of a widget when the current user is missing
* the permission (berechtigung_kurzbz) linked to that widget. Used for widgets
* that are already on a user's dashboard but whose required permission the user
* no longer holds.
*/
export default {
mixins: [
AbstractWidget
],
created() {
this.$emit('setConfig', false);
},
template: /*html*/`
<div class="dashboard-widget-missing-permission d-flex flex-column justify-content-center align-items-center text-center h-100 p-3 text-body-secondary">
<i class="fa-solid fa-lock fa-2x mb-2" aria-hidden="true"></i>
<p class="mb-0">{{ $p.t('dashboard/widget_missing_permission') }}</p>
</div>`
}
+3 -2
View File
@@ -103,7 +103,8 @@ require_once('dbupdate_3.4/76160_lvv_favorites.php');
require_once('dbupdate_3.4/77080_tabulator_presets_table.php');
require_once('dbupdate_3.4/78292_gehaltsanpassungtyp.php');
require_once('dbupdate_3.4/54225_reihungstest_ablauf_fuer_quereinsteiger.php');
require_once('dbupdate_3.4/77757_widgets_berechtigungen.php');
require_once('dbupdate_3.4/83575_IDAM_Exclude_Degree_Program_from_Student_Sync.php');
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
@@ -397,7 +398,7 @@ $tabellen=array(
"public.tbl_statistik" => array("statistik_kurzbz","bezeichnung","url","gruppe","sql","content_id","insertamum","insertvon","updateamum","updatevon","berechtigung_kurzbz","publish","preferences"),
"public.tbl_student" => array("student_uid","matrikelnr","prestudent_id","studiengang_kz","semester","verband","gruppe","updateamum","updatevon","insertamum","insertvon","ext_id"),
"public.tbl_studentlehrverband" => array("student_uid","studiensemester_kurzbz","studiengang_kz","semester","verband","gruppe","updateamum","updatevon","insertamum","insertvon","ext_id"),
"public.tbl_studiengang" => array("studiengang_kz","kurzbz","kurzbzlang","typ","bezeichnung","english","farbe","email","telefon","max_semester","max_verband","max_gruppe","erhalter_kz","bescheid","bescheidbgbl1","bescheidbgbl2","bescheidgz","bescheidvom","orgform_kurzbz","titelbescheidvom","aktiv","ext_id","zusatzinfo_html","moodle","sprache","testtool_sprachwahl","studienplaetze","oe_kurzbz","lgartcode","mischform","projektarbeit_note_anzeige", "onlinebewerbung","melderelevant","foerderrelevant","standort_code","melde_studiengang_kz"),
"public.tbl_studiengang" => array("studiengang_kz","kurzbz","kurzbzlang","typ","bezeichnung","english","farbe","email","telefon","max_semester","max_verband","max_gruppe","erhalter_kz","bescheid","bescheidbgbl1","bescheidbgbl2","bescheidgz","bescheidvom","orgform_kurzbz","titelbescheidvom","aktiv","ext_id","zusatzinfo_html","moodle","sprache","testtool_sprachwahl","studienplaetze","oe_kurzbz","lgartcode","mischform","projektarbeit_note_anzeige", "onlinebewerbung","melderelevant","foerderrelevant","standort_code","melde_studiengang_kz", "account_creation"),
"public.tbl_studiengangstyp" => array("typ","bezeichnung","beschreibung","bezeichnung_mehrsprachig"),
"public.tbl_studienjahr" => array("studienjahr_kurzbz","bezeichnung"),
"public.tbl_studiensemester" => array("studiensemester_kurzbz","bezeichnung","start","ende","studienjahr_kurzbz","ext_id","beschreibung","onlinebewerbung"),
@@ -0,0 +1,57 @@
<?php
/* 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 the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* Beschreibung:
* Dashboard Widgets: Verknüpfung einer (einzelnen) Berechtigung pro Widget.
* Neue Spalte dashboard.tbl_widget.berechtigung_kurzbz mit FK auf
* system.tbl_berechtigung. Ist die Spalte NULL, erfordert das Widget keine
* gesonderte Berechtigung. Benutzer denen die verknüpfte Berechtigung fehlt,
* bekommen das Widget nicht mehr zur Auswahl angezeigt bzw. sehen (falls bereits
* am Dashboard) einen "Fehlende Berechtigung"-Screen.
*/
if (! defined('DB_NAME')) exit('No direct script access allowed');
// Add column dashboard.tbl_widget.berechtigung_kurzbz (FK => system.tbl_berechtigung)
if ($result = @$db->db_query("
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'dashboard'
AND table_name = 'tbl_widget'
AND column_name = 'berechtigung_kurzbz';"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "
ALTER TABLE dashboard.tbl_widget
ADD COLUMN berechtigung_kurzbz VARCHAR(32) NULL;
ALTER TABLE dashboard.tbl_widget
ADD CONSTRAINT tbl_widget_berechtigung_fk
FOREIGN KEY (berechtigung_kurzbz)
REFERENCES system.tbl_berechtigung (berechtigung_kurzbz)
ON UPDATE CASCADE ON DELETE SET NULL;";
if (!$db->db_query($qry))
{
echo '<strong>dashboard.tbl_widget: '.$db->db_last_error().'</strong><br>';
}
else
{
echo 'dashboard.tbl_widget: Spalte berechtigung_kurzbz (FK system.tbl_berechtigung) hinzugefuegt<br>';
}
}
}
@@ -0,0 +1,17 @@
<?php
if (! defined('DB_NAME')) exit('No direct script access allowed');
// Add column account_creation to public.tbl_studiengang
if( !@$db->db_query('SELECT account_creation FROM public.tbl_studiengang LIMIT 1'))
{
$qry = 'ALTER TABLE public.tbl_studiengang ADD COLUMN IF NOT EXISTS account_creation BOOLEAN NOT NULL DEFAULT TRUE;';
$qry .= "COMMENT ON COLUMN public.tbl_studiengang.account_creation IS 'Flag for the student accounts creation on IDAM';";
if (!$db->db_query($qry))
echo '<strong>public.tbl_studiengang.account_creation: '.$db->db_last_error().'</strong><br>';
else
echo '<br>public.tbl_studiengang.account_creation: Neue Spalte hinzugefügt';
}
+20
View File
@@ -49620,6 +49620,26 @@ array(
)
)
),
array(
'app' => 'core',
'category' => 'dashboard',
'phrase' => 'widget_missing_permission',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Ihnen fehlt die erforderliche Berechtigung, um dieses Widget anzuzeigen.',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'You do not have the permission required to display this widget.',
'description' => '',
'insertvon' => 'system'
)
)
),
// CIS4 phrases from legacy code end
// FHC4 Phrases Abschlusspruefung
array(
@@ -1,9 +1,9 @@
INSERT INTO lehre.tbl_projektarbeit
(projektarbeit_id, projekttyp_kurzbz, titel, lehreinheit_id, student_uid, firma_id, note, punkte, beginn, ende, faktor, freigegeben, gesperrtbis, stundensatz, themenbereich, anmerkung, updateamum, updatevon, insertamum, insertvon, ext_id, gesamtstunden, titel_english, sprache, seitenanzahl, abgabedatum, kontrollschlagwoerter, schlagwoerter, schlagwoerter_en, abstract, abstract_en, "final") VALUES
(1, 'Bachelor', 'Auswirkung der Sonneneinstrahlung auf die Gesundheit', 46111, 's46b413', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true),
(2, 'Bachelor', 'Neue Unterrichtsmethoden mit KI', 46111, 's46b414', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true),
(3, 'Bachelor', 'Betrugsbekämpfung bei Anwesenheitskontrolle', 46111, 's46b415', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true),
(4, 'Bachelor', 'Neuronale Netze', 46111, 's46b416', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true)
(projektarbeit_id, projekttyp_kurzbz, titel, lehreinheit_id, student_uid, firma_id, note, punkte, beginn, ende, faktor, freigegeben, gesperrtbis, stundensatz, themenbereich, anmerkung, updateamum, updatevon, insertamum, insertvon, ext_id, gesamtstunden, titel_english, sprache, seitenanzahl, abgabedatum, kontrollschlagwoerter, schlagwoerter, schlagwoerter_en, abstract, abstract_en, "final", lehrveranstaltung_id, studiensemester_kurzbz) VALUES
(1, 'Bachelor', 'Auswirkung der Sonneneinstrahlung auf die Gesundheit', 46111, 's46b413', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true, 4611, NearestWintersemester(1)),
(2, 'Bachelor', 'Neue Unterrichtsmethoden mit KI', 46111, 's46b414', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true, 4611, NearestWintersemester(1)),
(3, 'Bachelor', 'Betrugsbekämpfung bei Anwesenheitskontrolle', 46111, 's46b415', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true, 4611, NearestWintersemester(1)),
(4, 'Bachelor', 'Neuronale Netze', 46111, 's46b416', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true, 4611, NearestWintersemester(1))
;
INSERT INTO lehre.tbl_projektbetreuer
@@ -93,6 +93,7 @@ $melderelevant = false;
$foerderrelevant = false;
$standort_code='';
$melde_studiengang_kz = '';
$account_creation = true;
$schick = filter_input(INPUT_POST, 'schick');
$onlinebewerbung = false;
@@ -157,6 +158,7 @@ if($schick)
$foerderrelevant = filter_input(INPUT_POST, 'foerderrelevant', FILTER_VALIDATE_BOOLEAN);
$standort_code = filter_input(INPUT_POST, 'standort_code');
$melde_studiengang_kz = filter_input(INPUT_POST, 'melde_studiengang_kz');
$account_creation = filter_input(INPUT_POST, 'account_creation', FILTER_VALIDATE_BOOLEAN);
$ext_id = filter_input(INPUT_POST, 'ext_id');
@@ -226,6 +228,7 @@ if($schick)
$sg_update->foerderrelevant = $foerderrelevant;
$sg_update->standort_code = $standort_code;
$sg_update->melde_studiengang_kz = $melde_studiengang_kz;
$sg_update->account_creation = $account_creation;
$sg_update->bescheidvom=$date->formatDatum($sg_update->bescheidvom,'Y-m-d');
$sg_update->titelbescheidvom=$date->formatDatum($sg_update->titelbescheidvom,'Y-m-d');
@@ -296,6 +299,7 @@ if ((isset($_REQUEST['studiengang_kz'])) && ((!isset($_REQUEST['neu'])) || ($_RE
$foerderrelevant = $sg->foerderrelevant;
$standort_code = $sg->standort_code;
$melde_studiengang_kz = $sg->melde_studiengang_kz;
$account_creation = $sg->account_creation;
}
$erh = new erhalter();
@@ -446,6 +450,13 @@ if (!$erh->getAll('kurzbz'))
<input type="checkbox" name="mischform" <?php echo $mischform ? 'checked' : '' ?> onchange="submitable()">
</td>
</tr>
<tr>
<td valign="top">IDAM student accounts creation</td>
<td>
<input type="hidden" name="account_creation" value="0">
<input type="checkbox" name="account_creation" <?php echo $account_creation ? 'checked' : '' ?> onchange="submitable()">
</td>
</tr>
</table>
</td>
<td valign="top">
@@ -49,6 +49,23 @@ require_once('../../include/benutzerberechtigung.class.php');
else
die('Sie haben keine Rechte fuer diese Aktion');
}
if (isset($_GET["toggleAC"]) && ($_GET["kz"] != ""))
{
$kennzahl = intval($_GET["kz"]);
$stg_hlp = new studiengang();
if(!$stg_hlp->load($kennzahl))
die('Studiengang nicht gefunden');
if ($rechte->isBerechtigt('basis/studiengang', $stg_hlp->oe_kurzbz, 'suid'))
{
$sg_update = new studiengang();
if (!$sg_update->toggleAccountCreation($kennzahl))
die($sg_update->errormsg);
}
else
die('Sie haben keine Rechte fuer diese Aktion');
}
$sg = new studiengang();
if (!$sg->loadArray($rechte->getStgKz('basis/studiengang'),'kurzbzlang',false))
@@ -67,6 +84,7 @@ require_once('../../include/benutzerberechtigung.class.php');
<th>Englisch</th>
<th>Lehrgangsart</th>
<th data-placeholder="t or f">Aktiv</th>
<th data-placeholder="t or f">IDAM</th>
<th>Email</th>
</tr></thead><tbody>
';
@@ -93,6 +111,16 @@ require_once('../../include/benutzerberechtigung.class.php');
$aktivlink = "?toggle=true&kz=".$stg->studiengang_kz;
$htmlstr .= " <td align='center'><a href='".$aktivlink."'><img src='../../skin/images/".$aktivbild."' height='20px' alt='".$aktivbild."'></a></td>\n";
// IDAM account activation
if($stg->account_creation)
$acbild = "true.png";
else
$acbild = "false.png";
$aclink = "?toggleAC=true&kz=".$stg->studiengang_kz;
$htmlstr .= " <td align='center'><a href='".$aclink."'><img src='../../skin/images/".$acbild."' height='20px' alt='".$acbild."'></a></td>\n";
$htmlstr .= " <td><a href='mailto:".$stg->email."'>".$stg->email."</a></td>\n";
$htmlstr .= " </tr>\n";
$i++;