mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 20:29:29 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 868599a7fe | |||
| 331381c94d | |||
| 478b23825c | |||
| 92a2053b42 | |||
| 70602be54e | |||
| dac71f597a | |||
| 98a10a2f55 | |||
| e48b94b858 | |||
| 38e8f91fdf | |||
| d542cf7720 |
@@ -128,7 +128,7 @@ class AntragLib
|
||||
return $this->_ci->StudierendenantragstatusModel->resumeAntraegeForAbmeldungStgl($antrag_id);
|
||||
}
|
||||
// NOTE(chris): get last status that is not pause
|
||||
$this->_ci->StudierendenantragstatusModel->addOrder('insertamum');
|
||||
$this->_ci->StudierendenantragstatusModel->addOrder('insertamum', 'DESC');
|
||||
$this->_ci->StudierendenantragstatusModel->addLimit(1);
|
||||
$result = $this->_ci->StudierendenantragstatusModel->loadWhere([
|
||||
'studierendenantrag_id' => $antrag_id,
|
||||
|
||||
@@ -594,7 +594,10 @@ class Studiengang_model extends DB_Model
|
||||
$this->addSelect('p.prestudent_id');
|
||||
$this->addSelect('pers.vorname');
|
||||
$this->addSelect('pers.nachname');
|
||||
$this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', " . $this->dbTable . ".bezeichnung, ')') AS name");
|
||||
$this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', "
|
||||
. $this->dbTable . ".bezeichnung, ', ', "
|
||||
. "UPPER(" . $this->dbTable . ".typ), "
|
||||
. "UPPER(" . $this->dbTable . ".kurzbz),')') AS name");
|
||||
|
||||
$this->addJoin('public.tbl_prestudent p', 'studiengang_kz');
|
||||
$this->addJoin(
|
||||
|
||||
@@ -46,12 +46,13 @@ echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<link rel="stylesheet" href="../../../skin/tablesort.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="../../../skin/style.css.php" type="text/css">
|
||||
<link rel="stylesheet" type="text/css" href="../../../skin/jquery-ui-1.9.2.custom.min.css">
|
||||
<script type="text/javascript" src="../../../vendor/jquery/jquery1/jquery-1.12.4.min.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/christianbach/tablesorter/jquery.tablesorter.min.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/components/jqueryui/jquery-ui.min.js"></script>
|
||||
<script type="text/javascript" src="../../../include/js/jquery.ui.datepicker.translation.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/jquery/sizzle/sizzle.js"></script>';
|
||||
|
||||
include('../../../include/meta/jquery.php');
|
||||
include('../../../include/meta/jquery-tablesorter.php');
|
||||
|
||||
const MOODLE_ADDON_KURZBZ = 'moodle';
|
||||
|
||||
// Load Addons to get Moodle_Path
|
||||
@@ -71,7 +72,7 @@ echo '
|
||||
$("#myTable").tablesorter(
|
||||
{
|
||||
sortList: [[0,0],[1,0]],
|
||||
widgets: [\'zebra\']
|
||||
widgets: [\'zebra\',\'filter\']
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -151,8 +152,9 @@ foreach($service->result as $row)
|
||||
$person = new person();
|
||||
$person->getPersonFromBenutzer($row->operativ_uid);
|
||||
$operativ = $person->nachname.' '.$person->vorname;
|
||||
$oeBez = new organisationseinheit($row->oe_kurzbz);
|
||||
echo '<tr>';
|
||||
echo '<td>',$row->oe_kurzbz,'</td>';
|
||||
echo '<td>',$oeBez->bezeichnung,'</td>';
|
||||
echo '<td><b>'.$row->bezeichnung.'</b></td>';
|
||||
echo '<td>',$row->beschreibung,'</td>';
|
||||
echo '<td><nobr><a href="../profile/index.php?uid='.$row->design_uid.'">',$design,'</a></nobr></td>';
|
||||
|
||||
@@ -136,18 +136,6 @@ const app = Vue.createApp({
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isMobile() {
|
||||
const smallScreen = window.matchMedia("(max-width: 767px)").matches;
|
||||
const touchCapable = ("ontouchstart" in window) || navigator.maxTouchPoints > 0;
|
||||
return smallScreen;// && touchCapable;
|
||||
},
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
isMobile: this.isMobile
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
searchfunction: function(searchsettings) {
|
||||
return this.$api.call(ApiSearchbar.searchCis(searchsettings));
|
||||
|
||||
@@ -233,10 +233,18 @@ const app = Vue.createApp({
|
||||
renderers: null,
|
||||
}),
|
||||
components: {},
|
||||
computed: {
|
||||
isMobile() {
|
||||
const smallScreen = window.matchMedia("(max-width: 767px)").matches;
|
||||
const touchCapable = ("ontouchstart" in window) || navigator.maxTouchPoints > 0;
|
||||
return smallScreen;// && touchCapable;
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return { // provide injectable & watchable language property
|
||||
language: Vue.computed(() => this.$p.user_language),
|
||||
renderers: Vue.computed(() => this.renderers),
|
||||
isMobile: this.isMobile
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -30,7 +30,6 @@ export default {
|
||||
menuOpen:true,
|
||||
};
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
provide(){
|
||||
return{
|
||||
setActiveEntry: this.setActiveEntry,
|
||||
@@ -59,7 +58,7 @@ export default {
|
||||
},
|
||||
site_url(){
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchMenu() {
|
||||
@@ -113,26 +112,10 @@ export default {
|
||||
});
|
||||
},
|
||||
template: /*html*/`
|
||||
<div
|
||||
id="header-options-collapsible"
|
||||
class="collapse multi-collapse collapse-horizontal show"
|
||||
>
|
||||
<div class="d-flex flex-row align-items-center gap-2 h-100" style="width: 79px">
|
||||
<button id="nav-main-btn" class="navbar-toggler rounded-0 px-2 border-0" type="button" data-bs-toggle="offcanvas" data-bs-target="#nav-main" aria-controls="nav-main" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<span v-if="isMobile" class="d-flex flex-row align-items-center">
|
||||
<theme-switch></theme-switch>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<fhc-searchbar
|
||||
:searchoptions="searchbaroptions"
|
||||
:searchfunction="searchfunction"
|
||||
ref="searchbar"
|
||||
id="nav-search"
|
||||
class="fhc-searchbar w-100 py-1 py-lg-2"
|
||||
></fhc-searchbar>
|
||||
<button id="nav-main-btn" class="navbar-toggler rounded-0" type="button" data-bs-toggle="offcanvas" data-bs-target="#nav-main" aria-controls="nav-main" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<fhc-searchbar ref="searchbar" id="nav-search" class="fhc-searchbar w-100 py-1 py-lg-2" :searchoptions="searchbaroptions" :searchfunction="searchfunction"></fhc-searchbar>
|
||||
<div id="nav-logo" class="d-none d-lg-block">
|
||||
<div class="d-flex h-100 justify-content-between">
|
||||
<a :href="rootUrl">
|
||||
@@ -141,32 +124,22 @@ export default {
|
||||
<theme-switch></theme-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="header-usermenu-collapsible"
|
||||
class="collapse multi-collapse collapse-horizontal show"
|
||||
>
|
||||
<div
|
||||
:style="!isMobile ? '' : 'width: 51px'"
|
||||
id="nav-user"
|
||||
>
|
||||
<button id="nav-user-btn" class="btn btn-link rounded-0" type="button" data-bs-toggle="collapse" data-bs-target="#nav-user-menu" aria-expanded="false" aria-controls="nav-user-menu">
|
||||
<img :src="avatarUrl" :alt="$p.t('profilUpdate/profilBild')" class="bg-dark avatar rounded-circle border border-dark"/>
|
||||
</button>
|
||||
<ul ref="navUserDropdown"
|
||||
@[\`shown.bs.collapse\`]="handleShowNavUser"
|
||||
@[\`hide.bs.collapse\`]="handleHideNavUser"
|
||||
id="nav-user-menu" class="top-100 end-0 collapse list-unstyled" aria-labelledby="nav-user-btn">
|
||||
<li><a class="fhc-dark-bg btn rounded-0 d-block" :href="site_url + '/Cis/Profil'" id="menu-profil">Profil</a></li>
|
||||
<li >
|
||||
<cis-sprachen @languageChanged="fetchMenu"></cis-sprachen>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider m-0 "></li>
|
||||
<li ><a class="fhc-dark-bg btn rounded-0 d-block" :href="logoutUrl">Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="nav-user">
|
||||
<button id="nav-user-btn" class="btn btn-link rounded-0" type="button" data-bs-toggle="collapse" data-bs-target="#nav-user-menu" aria-expanded="false" aria-controls="nav-user-menu">
|
||||
<img :src="avatarUrl" :alt="$p.t('profilUpdate/profilBild')" class="bg-dark avatar rounded-circle border border-dark"/>
|
||||
</button>
|
||||
<ul ref="navUserDropdown"
|
||||
@[\`shown.bs.collapse\`]="handleShowNavUser"
|
||||
@[\`hide.bs.collapse\`]="handleHideNavUser"
|
||||
id="nav-user-menu" class="top-100 end-0 collapse list-unstyled" aria-labelledby="nav-user-btn">
|
||||
<li><a class="fhc-dark-bg btn rounded-0 d-block" :href="site_url + '/Cis/Profil'" id="menu-profil">Profil</a></li>
|
||||
<li >
|
||||
<cis-sprachen @languageChanged="fetchMenu"></cis-sprachen>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider m-0 "></li>
|
||||
<li ><a class="fhc-dark-bg btn rounded-0 d-block" :href="logoutUrl">Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<nav id="nav-main" class="offcanvas offcanvas-start" tabindex="-1" aria-labelledby="nav-main-btn" data-bs-backdrop="false">
|
||||
<div id="nav-main-sticky">
|
||||
<div id="nav-main-toggle" class="position-static d-none d-lg-block ">
|
||||
|
||||
@@ -34,7 +34,7 @@ export default {
|
||||
return {
|
||||
showModal: false,
|
||||
editDataFilter: null,
|
||||
preloadedPhrasen:{},
|
||||
arePhrasesPreloaded: false,
|
||||
// tabulator options
|
||||
funktionen_table_options: {
|
||||
persistenceID: "filterTableMaProfilFunktionen",
|
||||
@@ -46,6 +46,7 @@ export default {
|
||||
responsiveLayout: "collapse",
|
||||
responsiveLayoutCollapseUseFormatters: false,
|
||||
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
|
||||
responsiveLayoutCollapseStartOpen: false,
|
||||
columns: [
|
||||
{
|
||||
title:
|
||||
@@ -56,24 +57,27 @@ export default {
|
||||
formatter: "responsiveCollapse",
|
||||
maxWidth: 40,
|
||||
headerClick: this.collapseFunction,
|
||||
visible: true
|
||||
visible: true,
|
||||
responsive: 0,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(() => this.preloadedPhrasen.bezeichnungPhrase),
|
||||
title: Vue.computed(() => this.$p.t('ui/bezeichnung')),
|
||||
field: "Bezeichnung",
|
||||
headerFilter: true,
|
||||
minWidth: 200,
|
||||
visible: true
|
||||
visible: true,
|
||||
responsive: 0,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(() => this.preloadedPhrasen.organisationseinheitPhrase),
|
||||
title: Vue.computed(() => this.$p.t('lehre/organisationseinheit')),
|
||||
field: "Organisationseinheit",
|
||||
headerFilter: true,
|
||||
minWidth: 200,
|
||||
visible: true
|
||||
visible: true,
|
||||
responsive: 1,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(() => this.preloadedPhrasen.gueltigVonPhrase),
|
||||
title: Vue.computed(() => this.$p.t('global/gueltigVon')),
|
||||
field: "Gültig_von",
|
||||
headerFilterFunc: 'dates',
|
||||
headerFilter: dateFilter,
|
||||
@@ -81,10 +85,11 @@ export default {
|
||||
minWidth: 200,
|
||||
visible: true,
|
||||
formatter:"datetime",
|
||||
formatterParams: this.datetimeFormatterParams()
|
||||
formatterParams: this.datetimeFormatterParams(),
|
||||
responsive: 4,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(() => this.preloadedPhrasen.gueltigBisPhrase),
|
||||
title: Vue.computed(() => this.$p.t('global/gueltigBis')),
|
||||
field: "Gültig_bis",
|
||||
headerFilterFunc: 'dates',
|
||||
headerFilter: dateFilter,
|
||||
@@ -92,14 +97,16 @@ export default {
|
||||
minWidth: 200,
|
||||
visible: true,
|
||||
formatter:"datetime",
|
||||
formatterParams: this.datetimeFormatterParams()
|
||||
formatterParams: this.datetimeFormatterParams(),
|
||||
responsive: 3,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(() => this.preloadedPhrasen.wochenstundenPhrase),
|
||||
title: Vue.computed(() => this.$p.t('profil/wochenstunden')),
|
||||
field: "Wochenstunden",
|
||||
headerFilter: true,
|
||||
minWidth: 200,
|
||||
visible: true
|
||||
visible: true,
|
||||
responsive: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -115,6 +122,7 @@ export default {
|
||||
responsiveLayoutCollapseUseFormatters: false,
|
||||
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
|
||||
data: [{betriebsmittel: "", Nummer: "", Ausgegeben_am: ""}],
|
||||
responsiveLayoutCollapseStartOpen: false,
|
||||
columns: [
|
||||
{
|
||||
title:
|
||||
@@ -125,32 +133,36 @@ export default {
|
||||
formatter: "responsiveCollapse",
|
||||
maxWidth: 40,
|
||||
headerClick: this.collapseFunction,
|
||||
visible: true
|
||||
visible: true,
|
||||
responsive: 0,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(() => this.preloadedPhrasen.entlehnteBetriebsmittelPhrase),
|
||||
title: Vue.computed(() => this.$p.t('profil/entlehnteBetriebsmittel')),
|
||||
field: "betriebsmittel",
|
||||
headerFilter: true,
|
||||
minWidth: 200,
|
||||
visible: true
|
||||
visible: true,
|
||||
responsive: 0,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(() => this.preloadedPhrasen.inventarnummerPhrase),
|
||||
title: Vue.computed(() => this.$p.t('profil/inventarnummer')),
|
||||
field: "Nummer",
|
||||
headerFilter: true,
|
||||
resizable: true,
|
||||
minWidth: 200,
|
||||
visible: true
|
||||
visible: true,
|
||||
responsive: 2,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(() => this.preloadedPhrasen.ausgabedatumPhrase),
|
||||
title: Vue.computed(() => this.$p.t('profil/ausgabedatum')),
|
||||
field: "Ausgegeben_am",
|
||||
headerFilterFunc: 'dates',
|
||||
headerFilter: dateFilter,
|
||||
minWidth: 200,
|
||||
visible: true,
|
||||
formatter:"datetime",
|
||||
formatterParams: this.datetimeFormatterParams()
|
||||
formatterParams: this.datetimeFormatterParams(),
|
||||
responsive: 1,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -164,11 +176,9 @@ export default {
|
||||
|
||||
methods: {
|
||||
betriebsmittelTableBuilt: function () {
|
||||
this.$refs.betriebsmittelTable.tabulator.setColumns(this.betriebsmittel_table_options.columns)
|
||||
this.$refs.betriebsmittelTable.tabulator.setData(this.data.mittel);
|
||||
},
|
||||
funktionenTableBuilt: function () {
|
||||
this.$refs.funktionenTable.tabulator.setColumns(this.funktionen_table_options.columns)
|
||||
this.$refs.funktionenTable.tabulator.setData(this.data.funktionen);
|
||||
},
|
||||
hideEditProfilModal: function () {
|
||||
@@ -219,8 +229,8 @@ export default {
|
||||
});
|
||||
},
|
||||
setTableColumnTitles() { // reevaluates computed phrasen
|
||||
if(this.$refs.betriebsmittelTable) this.$refs.betriebsmittelTable.tabulator.setColumns(this.betriebsmittel_table_options.columns)
|
||||
if(this.$refs.funktionenTable) this.$refs.funktionenTable.tabulator.setColumns(this.funktionen_table_options.columns)
|
||||
if(this.$refs.betriebsmittelTable) this.$refs.betriebsmittelTable.tabulator.setColumns(this.betriebsmittel_table_options.columns);
|
||||
if(this.$refs.funktionenTable) this.$refs.funktionenTable.tabulator.setColumns(this.funktionen_table_options.columns);
|
||||
},
|
||||
datetimeFormatterParams: function() {
|
||||
const params = {
|
||||
@@ -301,15 +311,7 @@ export default {
|
||||
created() {
|
||||
// preload phrasen
|
||||
this.$p.loadCategory(["ui","lehre","global","profil"]).then(() => {
|
||||
this.preloadedPhrasen.bezeichnungPhrase = this.$p.t('ui/bezeichnung');
|
||||
this.preloadedPhrasen.organisationseinheitPhrase = this.$p.t('lehre/organisationseinheit');
|
||||
this.preloadedPhrasen.gueltigVonPhrase = this.$p.t('global/gueltigVon');
|
||||
this.preloadedPhrasen.gueltigBisPhrase = this.$p.t('global/gueltigBis');
|
||||
this.preloadedPhrasen.wochenstundenPhrase = this.$p.t('profil/wochenstunden');
|
||||
this.preloadedPhrasen.entlehnteBetriebsmittelPhrase = this.$p.t('profil/entlehnteBetriebsmittel');
|
||||
this.preloadedPhrasen.inventarnummerPhrase = this.$p.t('profil/inventarnummer');
|
||||
this.preloadedPhrasen.ausgabedatumPhrase = this.$p.t('profil/ausgabedatum');
|
||||
this.preloadedPhrasen.loaded=true;
|
||||
this.arePhrasesPreloaded = true;
|
||||
});
|
||||
//? sorts the profil Updates: pending -> accepted -> rejected
|
||||
this.data.profilUpdates?.sort(this.sortProfilUpdates);
|
||||
@@ -440,7 +442,7 @@ export default {
|
||||
<div class="col-12 mb-4" >
|
||||
<!-- FUNKTIONEN TABELLE -->
|
||||
<core-filter-cmpt
|
||||
v-if="preloadedPhrasen.loaded"
|
||||
v-if="arePhrasesPreloaded"
|
||||
@tableBuilt="funktionenTableBuilt"
|
||||
:title="$p.t('person','funktionen')"
|
||||
ref="funktionenTable"
|
||||
@@ -452,7 +454,7 @@ export default {
|
||||
<div class="col-12 mb-4" >
|
||||
<!-- BETRIEBSMITTEL TABELLE -->
|
||||
<core-filter-cmpt
|
||||
v-if="preloadedPhrasen.loaded"
|
||||
v-if="arePhrasesPreloaded"
|
||||
@tableBuilt="betriebsmittelTableBuilt"
|
||||
:title="$p.t('profil','entlehnteBetriebsmittel')"
|
||||
ref="betriebsmittelTable"
|
||||
|
||||
@@ -20,7 +20,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
collapseIconFunktionen: true,
|
||||
preloadedPhrasen:{},
|
||||
arePhrasesPreloaded: false,
|
||||
funktionen_table_options: {
|
||||
persistenceID: "filterTableMaViewProfilFunktionen",
|
||||
persistence: {
|
||||
@@ -182,12 +182,7 @@ export default {
|
||||
},
|
||||
created(){
|
||||
this.$p.loadCategory(["ui", "lehre", "global", "profil"]).then(() => {
|
||||
this.preloadedPhrasen.bezeichnungPhrase = this.$p.t('ui/bezeichnung');
|
||||
this.preloadedPhrasen.organisationseinheitPhrase = this.$p.t('lehre/organisationseinheit');
|
||||
this.preloadedPhrasen.gueltigVonPhrase = this.$p.t('global/gueltigVon');
|
||||
this.preloadedPhrasen.gueltigBisPhrase = this.$p.t('global/gueltigBis');
|
||||
this.preloadedPhrasen.wochenstundenPhrase = this.$p.t('profil/wochenstunden');
|
||||
this.preloadedPhrasen.loaded = true;
|
||||
this.arePhrasesPreloaded = true;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -247,7 +242,7 @@ export default {
|
||||
<div class="row">
|
||||
<!-- FIRST TABLE -->
|
||||
<div class="col-12 mb-4" >
|
||||
<core-filter-cmpt v-if="preloadedPhrasen.loaded" @tableBuilt="funktionenTableBuilt" :title="$p.t('person','funktionen')" ref="funktionenTable" :tabulator-options="funktionen_table_options" tableOnly :sideMenu="false" />
|
||||
<core-filter-cmpt v-if="arePhrasesPreloaded" @tableBuilt="funktionenTableBuilt" :title="$p.t('person','funktionen')" ref="funktionenTable" :tabulator-options="funktionen_table_options" tableOnly :sideMenu="false" />
|
||||
</div>
|
||||
<!-- END OF THE ROW WITH THE TABLES UNDER THE PROFIL INFORMATION -->
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,7 @@ export default {
|
||||
showModal: false,
|
||||
collapseIconBetriebsmittel: true,
|
||||
editDataFilter: null,
|
||||
preloadedPhrasen:{},
|
||||
arePhrasesPreloaded: false,
|
||||
// tabulator options
|
||||
zutrittsgruppen_table_options: {
|
||||
persistenceID: "filterTableStudentProfilZutrittsgruppen",
|
||||
@@ -42,10 +42,12 @@ export default {
|
||||
},
|
||||
minHeight: 200,
|
||||
layout: "fitColumns",
|
||||
columns: [{
|
||||
title: Vue.computed(() => this.preloadedPhrasen.zutrittsGruppenPhrase),
|
||||
columns: [
|
||||
{
|
||||
title: Vue.computed(() => this.$p.t('profil/zutrittsGruppen')),
|
||||
field: "bezeichnung"
|
||||
}],
|
||||
}
|
||||
],
|
||||
},
|
||||
betriebsmittel_table_options: {
|
||||
persistenceID: "filterTableStudentProfilBetriebsmittel",
|
||||
@@ -57,6 +59,7 @@ export default {
|
||||
responsiveLayout: "collapse",
|
||||
responsiveLayoutCollapseUseFormatters: false,
|
||||
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
|
||||
responsiveLayoutCollapseStartOpen: false,
|
||||
columns: [
|
||||
{
|
||||
title:
|
||||
@@ -67,31 +70,35 @@ export default {
|
||||
formatter: "responsiveCollapse",
|
||||
maxWidth: 40,
|
||||
headerClick: this.collapseFunction,
|
||||
responsive: 0,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(()=>this.preloadedPhrasen.entlehnteBetriebsmittelPhrase),
|
||||
title: Vue.computed(()=>this.$p.t('profil/entlehnteBetriebsmittel')),
|
||||
field: "betriebsmittel",
|
||||
headerFilter: true,
|
||||
minWidth: 200,
|
||||
visible: true
|
||||
visible: true,
|
||||
responsive: 0,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(() =>this.preloadedPhrasen.inventarnummerPhrase) ,
|
||||
title: Vue.computed(() => this.$p.t('profil/inventarnummer')) ,
|
||||
field: "Nummer",
|
||||
headerFilter: true,
|
||||
resizable: true,
|
||||
minWidth: 200,
|
||||
visible: true
|
||||
visible: true,
|
||||
responsive: 2,
|
||||
},
|
||||
{
|
||||
title: Vue.computed(() =>this.preloadedPhrasen.ausgabedatum) ,
|
||||
title: Vue.computed(() => this.$p.t('profil/ausgabedatum')) ,
|
||||
field: "Ausgegeben_am",
|
||||
headerFilterFunc: 'dates',
|
||||
headerFilter: dateFilter,
|
||||
minWidth: 200,
|
||||
visible: true,
|
||||
formatter:"datetime",
|
||||
formatterParams: this.datetimeFormatterParams()
|
||||
formatterParams: this.datetimeFormatterParams(),
|
||||
responsive: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -110,11 +117,9 @@ export default {
|
||||
methods: {
|
||||
|
||||
betriebsmittelTableBuilt: function () {
|
||||
this.$refs.betriebsmittelTable.tabulator.setColumns(this.betriebsmittel_table_options.columns)
|
||||
this.$refs.betriebsmittelTable.tabulator.setData(this.data.mittel);
|
||||
},
|
||||
zutrittsgruppenTableBuilt: function () {
|
||||
this.$refs.zutrittsgruppenTable.tabulator.setColumns(this.zutrittsgruppen_table_options.columns)
|
||||
this.$refs.zutrittsgruppenTable.tabulator.setData(
|
||||
this.data.zuttritsgruppen
|
||||
);
|
||||
@@ -244,11 +249,7 @@ export default {
|
||||
created() {
|
||||
// preload phrasen
|
||||
this.$p.loadCategory('profil').then(() => {
|
||||
this.preloadedPhrasen.zutrittsGruppenPhrase = this.$p.t('profil/zutrittsGruppen');
|
||||
this.preloadedPhrasen.entlehnteBetriebsmittelPhrase = this.$p.t('profil/entlehnteBetriebsmittel');
|
||||
this.preloadedPhrasen.inventarnummerPhrase = this.$p.t('profil/inventarnummer');
|
||||
this.preloadedPhrasen.ausgabedatum = this.$p.t('profil/ausgabedatum');
|
||||
this.preloadedPhrasen.loaded = true;
|
||||
this.arePhrasesPreloaded = true;
|
||||
});
|
||||
//? sorts the profil Updates: pending -> accepted -> rejected
|
||||
this.data.profilUpdates?.sort(this.sortProfilUpdates);
|
||||
@@ -379,7 +380,7 @@ export default {
|
||||
<div class="row">
|
||||
<div class="col-12 mb-4" >
|
||||
<core-filter-cmpt
|
||||
v-if="preloadedPhrasen.loaded"
|
||||
v-if="arePhrasesPreloaded"
|
||||
@tableBuilt="betriebsmittelTableBuilt"
|
||||
:title="$p.t('profil','entlehnteBetriebsmittel')"
|
||||
ref="betriebsmittelTable"
|
||||
@@ -389,7 +390,7 @@ export default {
|
||||
</div>
|
||||
<div class="col-12 mb-4" >
|
||||
<core-filter-cmpt
|
||||
v-if="preloadedPhrasen.loaded"
|
||||
v-if="arePhrasesPreloaded"
|
||||
@tableBuilt="zutrittsgruppenTableBuilt"
|
||||
:title="$p.t('profil','zutrittsGruppen')"
|
||||
ref="zutrittsgruppenTable"
|
||||
|
||||
@@ -21,71 +21,69 @@ export default {
|
||||
dms,
|
||||
cms,
|
||||
mergedStudent,
|
||||
mergedPerson,
|
||||
mergedPerson
|
||||
},
|
||||
props: {
|
||||
searchoptions: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
searchfunction: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
showBtnSubmit: Boolean,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
query: Vue.computed(() => this.lastQuery),
|
||||
};
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
data: function () {
|
||||
return {
|
||||
searchtimer: null,
|
||||
hidetimer: null,
|
||||
searchsettings: {
|
||||
searchstr: this.getSearchStr(),
|
||||
types: this.getInitiallySelectedTypes(),
|
||||
},
|
||||
searchresult: [],
|
||||
searchmode: "",
|
||||
showresult: false,
|
||||
searching: false,
|
||||
error: null,
|
||||
abortController: null,
|
||||
props: {
|
||||
searchoptions: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
searchfunction: {
|
||||
type: Function,
|
||||
required: true
|
||||
},
|
||||
showBtnSubmit: Boolean
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
query: Vue.computed(() => this.lastQuery)
|
||||
};
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
searchtimer: null,
|
||||
hidetimer: null,
|
||||
searchsettings: {
|
||||
searchstr: this.getSearchStr(),
|
||||
types: this.getInitiallySelectedTypes(),
|
||||
},
|
||||
searchresult: [],
|
||||
searchmode: '',
|
||||
showresult: false,
|
||||
searching: false,
|
||||
error: null,
|
||||
abortController: null,
|
||||
settingsDropdown: null,
|
||||
lastQuery: "",
|
||||
isSearchShownInMobileView: false,
|
||||
};
|
||||
},
|
||||
lastQuery: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
searchTypesPlaceholder() {
|
||||
if (!this.searchsettings.types.length) {
|
||||
return Object.values(this.typeLabels).join(" / ");
|
||||
return Object.values(this.typeLabels).join(' / ');
|
||||
}
|
||||
return this.searchsettings.types
|
||||
.map((type) => this.typeLabels[type])
|
||||
.join(" / ");
|
||||
return this.searchsettings.types.map(type => this.typeLabels[type]).join(' / ');
|
||||
},
|
||||
types() {
|
||||
if (!this.searchoptions.types) return [];
|
||||
if (!this.searchoptions.types)
|
||||
return [];
|
||||
if (Array.isArray(this.searchoptions.types))
|
||||
return this.searchoptions.types;
|
||||
return Object.keys(this.searchoptions.types);
|
||||
},
|
||||
typeLabels() {
|
||||
if (!this.searchoptions.types) return {};
|
||||
if (!this.searchoptions.types)
|
||||
return {};
|
||||
if (Array.isArray(this.searchoptions.types)) {
|
||||
return this.searchoptions.types.reduce((res, type) => {
|
||||
res[type] = type;
|
||||
return res;
|
||||
return res
|
||||
}, {});
|
||||
}
|
||||
return this.searchoptions.types;
|
||||
},
|
||||
}
|
||||
},
|
||||
template: /*html*/ `
|
||||
template: /*html*/`
|
||||
<form
|
||||
ref="searchform"
|
||||
class="d-flex me-3"
|
||||
@@ -94,89 +92,80 @@ export default {
|
||||
@focusin="searchfocusin"
|
||||
@focusout="searchfocusout"
|
||||
>
|
||||
<span
|
||||
v-if="isMobile"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target=".multi-collapse"
|
||||
aria-controls="header-searchbar-collapsible header-options-collapsible header-usermenu-collapsible"
|
||||
aria-expanded="false"
|
||||
class="d-flex flex-row align-items-center ps-3 pe-1"
|
||||
>
|
||||
<i v-if="isSearchShownInMobileView" class="fa-solid fa-chevron-left"></i>
|
||||
<i v-else class="fa-solid fa-magnifying-glass"></i>
|
||||
</span>
|
||||
|
||||
<div
|
||||
:class="{'flex-grow-1': !isMobile, 'collapse multi-collapse collapse-horizontal': isMobile}"
|
||||
id="header-searchbar-collapsible"
|
||||
ref="searchbox"
|
||||
class="h-100 input-group me-2 searchbar_searchbox"
|
||||
:class="showresult ? 'open' : 'closed'"
|
||||
>
|
||||
<div
|
||||
:class="{open: showresult, closed: showresult, 'px-3': isMobile}"
|
||||
ref="searchbox"
|
||||
class="h-100 input-group me-2 searchbar_searchbox"
|
||||
:style="isMobile ? 'width: ' + getMaxWidthOfSearchbarInMobileView() : ''"
|
||||
<span class="input-group-text">
|
||||
<i class="fa-solid fa-magnifying-glass"></i>
|
||||
</span>
|
||||
<input
|
||||
ref="input"
|
||||
@keyup="search"
|
||||
@focus="showsearchresult"
|
||||
v-model="searchsettings.searchstr"
|
||||
class="form-control searchbar_input"
|
||||
type="search"
|
||||
:placeholder="$p.t('search/input_search_label', { types: searchTypesPlaceholder })"
|
||||
:aria-label="$p.t('search/input_search_label', { types: searchTypesPlaceholder })"
|
||||
>
|
||||
<button
|
||||
v-if="searchsettings.searchstr"
|
||||
type="button"
|
||||
class="searchbar_input_clear btn btn-outline-secondary"
|
||||
@click="clearInput"
|
||||
@focusin.stop
|
||||
>
|
||||
<span class="input-group-text">
|
||||
<i class="fa-solid fa-magnifying-glass color-white"></i>
|
||||
</span>
|
||||
<input
|
||||
ref="input"
|
||||
@keyup="search"
|
||||
@focus="showsearchresult"
|
||||
v-model="searchsettings.searchstr"
|
||||
class="form-control searchbar_input"
|
||||
type="search"
|
||||
:placeholder="$p.t('search/input_search_label', { types: searchTypesPlaceholder })"
|
||||
:aria-label="$p.t('search/input_search_label', { types: searchTypesPlaceholder })"
|
||||
>
|
||||
<button
|
||||
v-if="showBtnSubmit"
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
:title="$p.t('search/submit')"
|
||||
:aria-label="$p.t('search/submit')"
|
||||
>
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
<button
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#searchSettings"
|
||||
aria-expanded="false"
|
||||
aria-controls="searchSettings"
|
||||
ref="settingsbutton"
|
||||
class="searchbar_setting_btn btn btn-secondary"
|
||||
type="button"
|
||||
:title="$p.t('search/button_filter_label')"
|
||||
:aria-label="$p.t('search/button_filter_label')"
|
||||
>
|
||||
<i class="fas fa-filter"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div v-show="showresult"
|
||||
class="searchbar_results" tabindex="-1">
|
||||
<div class="searchbar_results_scroller" ref="result">
|
||||
<div class="searchbar_results_wrapper" ref="results">
|
||||
<div v-if="searching">
|
||||
<i class="fas fa-spinner fa-spin fa-2x"></i>
|
||||
</div>
|
||||
<div v-else-if="this.error !== null">{{ error }}</div>
|
||||
<div v-else-if="searchresult.length < 1">{{ $p.t('search/error_no_results') }}</div>
|
||||
<template v-else v-for="res in searchresult">
|
||||
<component
|
||||
v-if="isValidRenderer(res.renderer)"
|
||||
:is="res.renderer"
|
||||
:mode="searchmode"
|
||||
:res="res"
|
||||
:actions="getActions(res)"
|
||||
@actionexecuted="hideresult"
|
||||
></component>
|
||||
<div v-else class="searchbar-result text-danger fw-bold">{{ $p.t('search/error_unknown_type', res) }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<i class="fas fa-close"></i>
|
||||
</button>
|
||||
<button
|
||||
v-if="showBtnSubmit"
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
:title="$p.t('search/submit')"
|
||||
:aria-label="$p.t('search/submit')"
|
||||
>
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
<button
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#searchSettings"
|
||||
aria-expanded="false"
|
||||
aria-controls="searchSettings"
|
||||
ref="settingsbutton"
|
||||
class="searchbar_setting_btn btn btn-secondary"
|
||||
type="button"
|
||||
:title="$p.t('search/button_filter_label')"
|
||||
:aria-label="$p.t('search/button_filter_label')"
|
||||
>
|
||||
<i class="fas fa-cog"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-show="showresult"
|
||||
class="searchbar_results" tabindex="-1">
|
||||
<div class="searchbar_results_scroller" ref="result">
|
||||
<div class="searchbar_results_wrapper" ref="results">
|
||||
<div v-if="searching">
|
||||
<i class="fas fa-spinner fa-spin fa-2x"></i>
|
||||
</div>
|
||||
<div v-else-if="this.error !== null">{{ error }}</div>
|
||||
<div v-else-if="searchresult.length < 1">{{ $p.t('search/error_no_results') }}</div>
|
||||
<template v-else v-for="res in searchresult">
|
||||
<component
|
||||
v-if="isValidRenderer(res.renderer)"
|
||||
:is="res.renderer"
|
||||
:mode="searchmode"
|
||||
:res="res"
|
||||
:actions="getActions(res)"
|
||||
@actionexecuted="hideresult"
|
||||
></component>
|
||||
<div v-else class="searchbar-result text-danger fw-bold">{{ $p.t('search/error_unknown_type', res) }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="searchSettings"
|
||||
@@ -218,53 +207,34 @@ export default {
|
||||
</div>
|
||||
</form>
|
||||
`,
|
||||
watch: {
|
||||
"searchsettings.searchstr": function (newSearchValue) {
|
||||
if (this.searchoptions.origin) {
|
||||
sessionStorage.setItem(
|
||||
`${this.searchoptions.origin}_searchstr`,
|
||||
newSearchValue,
|
||||
);
|
||||
watch:{
|
||||
'searchsettings.searchstr': function (newSearchValue) {
|
||||
if(this.searchoptions.origin){
|
||||
sessionStorage.setItem(`${this.searchoptions.origin}_searchstr`,newSearchValue);
|
||||
}
|
||||
},
|
||||
"searchsettings.types"(newValue) {
|
||||
'searchsettings.types'(newValue) {
|
||||
if (Array.isArray(newValue) && newValue.length === 0) {
|
||||
this.searchsettings.types = [...this.types];
|
||||
}
|
||||
// stores the search types in the localstorage, only if the newValue is also an array
|
||||
if (Array.isArray(newValue) && this.searchoptions.origin) {
|
||||
localStorage.setItem(
|
||||
`${this.searchoptions.origin}_searchtypes`,
|
||||
JSON.stringify(newValue),
|
||||
);
|
||||
localStorage.setItem(`${this.searchoptions.origin}_searchtypes`, JSON.stringify(newValue));
|
||||
}
|
||||
this.search();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
this.settingsDropdown = new bootstrap.Collapse(this.$refs.settings, {
|
||||
toggle: false,
|
||||
toggle: false
|
||||
});
|
||||
|
||||
if (!this.searchoptions.origin) {
|
||||
console.warn(
|
||||
"No origin defined in the searchoptions for the searchbar, please define the origin property in the searchbaroptions to allow reliable storage of searchstr and searchtypes accross applications.",
|
||||
);
|
||||
if (!this.searchoptions.origin){
|
||||
console.warn("No origin defined in the searchoptions for the searchbar, please define the origin property in the searchbaroptions to allow reliable storage of searchstr and searchtypes accross applications.");
|
||||
}
|
||||
|
||||
document
|
||||
.getElementById("header-searchbar-collapsible")
|
||||
.addEventListener("show.bs.collapse", (e) => {
|
||||
this.isSearchShownInMobileView = true;
|
||||
});
|
||||
document
|
||||
.getElementById("header-searchbar-collapsible")
|
||||
.addEventListener("hidden.bs.collapse", (e) => {
|
||||
this.isSearchShownInMobileView = false;
|
||||
});
|
||||
},
|
||||
updated() {
|
||||
if (this.showresult) {
|
||||
if(this.showresult) {
|
||||
Vue.nextTick(() => {
|
||||
this.calcSearchResultHeight();
|
||||
});
|
||||
@@ -279,34 +249,32 @@ export default {
|
||||
getInitiallySelectedTypes() {
|
||||
let result = false;
|
||||
if (this.searchoptions.origin) {
|
||||
let localStorageValue = localStorage.getItem(
|
||||
`${this.searchoptions.origin}_searchtypes`,
|
||||
);
|
||||
let localStorageValue = localStorage.getItem(`${this.searchoptions.origin}_searchtypes`);
|
||||
if (localStorageValue) {
|
||||
result = JSON.parse(localStorageValue);
|
||||
}
|
||||
}
|
||||
if (result) return result;
|
||||
if (!this.searchoptions.types) return [];
|
||||
if (result)
|
||||
return result;
|
||||
if (!this.searchoptions.types)
|
||||
return [];
|
||||
if (Array.isArray(this.searchoptions.types))
|
||||
return [...this.searchoptions.types];
|
||||
return Object.keys(this.searchoptions.types);
|
||||
},
|
||||
getSearchStr: function () {
|
||||
if (!this.searchoptions.origin) return "";
|
||||
return (
|
||||
sessionStorage.getItem(
|
||||
`${this.searchoptions.origin}_searchstr`,
|
||||
) ?? ""
|
||||
);
|
||||
getSearchStr: function(){
|
||||
if (!this.searchoptions.origin)
|
||||
return '';
|
||||
return sessionStorage.getItem(`${this.searchoptions.origin}_searchstr`) ?? '';
|
||||
},
|
||||
checkSettingsVisibility: function (event) {
|
||||
checkSettingsVisibility: function(event) {
|
||||
// hides the settings collapsible if the user clicks somewhere else
|
||||
if (!this.$refs.settings.contains(event.target)) {
|
||||
if (!this.$refs.settings.contains(event.target))
|
||||
{
|
||||
this.settingsDropdown.hide();
|
||||
}
|
||||
},
|
||||
handleShowSettings: function () {
|
||||
handleShowSettings: function() {
|
||||
// adds the event listener checkSettingsVisibility only when the collapsible is shown
|
||||
document.addEventListener("click", this.checkSettingsVisibility);
|
||||
},
|
||||
@@ -314,208 +282,183 @@ export default {
|
||||
// removes the event listener checkSettingsVisibility when the collapsible is hidden
|
||||
document.removeEventListener("click", this.checkSettingsVisibility);
|
||||
},
|
||||
calcSearchResultHeight: function () {
|
||||
calcSearchResultHeight: function() {
|
||||
const rect = this.$refs.results.getBoundingClientRect();
|
||||
if (rect.height > 0 && rect.height < window.innerHeight * 0.8) {
|
||||
this.$refs.result.style.height =
|
||||
Math.ceil(rect.height + 16) + "px";
|
||||
if( rect.height > 0 && rect.height < (window.innerHeight * 0.8) ) {
|
||||
this.$refs.result.style.height = Math.ceil(rect.height + 16) + 'px';
|
||||
} else {
|
||||
this.$refs.result.style.height =
|
||||
Math.floor(window.innerHeight * 0.8) + "px";
|
||||
this.$refs.result.style.height = Math.floor(window.innerHeight * 0.8) + 'px';
|
||||
}
|
||||
},
|
||||
calcSearchResultExtent: function () {
|
||||
if (!this.showresult) {
|
||||
calcSearchResultExtent: function() {
|
||||
if(!this.showresult) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
this.searchoptions?.calcheightonly === undefined ||
|
||||
this.searchoptions.calcheightonly === false
|
||||
) {
|
||||
if(this.searchoptions?.calcheightonly === undefined
|
||||
|| this.searchoptions.calcheightonly === false) {
|
||||
var rect = this.$refs.searchbox.getBoundingClientRect();
|
||||
this.$refs.result.style.top =
|
||||
Math.floor(rect.bottom + 3) + "px";
|
||||
this.$refs.result.style.right = Math.floor(rect.right) + "px";
|
||||
this.$refs.result.style.width = Math.floor(rect.width) + "px";
|
||||
this.$refs.result.style.top = Math.floor(rect.bottom + 3) + 'px';
|
||||
this.$refs.result.style.right = Math.floor(rect.right) + 'px';
|
||||
this.$refs.result.style.width = Math.floor(rect.width) + 'px';
|
||||
}
|
||||
this.calcSearchResultHeight();
|
||||
},
|
||||
search: function () {
|
||||
if (this.searchoptions?.nolivesearch === true) return;
|
||||
this.calcSearchResultHeight();
|
||||
},
|
||||
search: function() {
|
||||
if(this.searchoptions?.nolivesearch === true) return;
|
||||
|
||||
this.abort();
|
||||
if (this.searchsettings.searchstr.length >= 2) {
|
||||
this.abort();
|
||||
if( this.searchsettings.searchstr.length >= 2 ) {
|
||||
this.calcSearchResultExtent();
|
||||
this.searchtimer = setTimeout(
|
||||
this.callsearchapi,
|
||||
500
|
||||
);
|
||||
} else {
|
||||
this.showresult = false;
|
||||
}
|
||||
},
|
||||
abort() {
|
||||
if (this.searchtimer !== null) {
|
||||
clearTimeout(this.searchtimer);
|
||||
}
|
||||
if (this.abortController) {
|
||||
this.abortController.abort();
|
||||
this.abortController = null;
|
||||
}
|
||||
this.searchresult = [];
|
||||
},
|
||||
callsearchapi: function() {
|
||||
this.error = null;
|
||||
this.searchresult.splice(0, this.searchresult.length);
|
||||
this.searching = true;
|
||||
this.showsearchresult();
|
||||
if(this.searchsettings.types.length === 0) {
|
||||
this.error = this.$p.t('search/error_missing_type');
|
||||
this.searching = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.abortController)
|
||||
this.abortController.abort();
|
||||
this.abortController = new AbortController();
|
||||
|
||||
this.searchfunction(this.searchsettings, { timeout: 50000, signal: this.abortController.signal })
|
||||
.then(response=>{
|
||||
if (!response.data) {
|
||||
this.error = this.$p.t('search/error_general');
|
||||
} else {
|
||||
let res = response.data.map(el => el.data ? {...el, ...JSON.parse(el.data)} : el);
|
||||
this.lastQuery = response.meta.searchstring;
|
||||
if (this.searchoptions.mergeResults) {
|
||||
let counter = 0;
|
||||
let mergeTypes = [];
|
||||
let mergedType = 'merged-';
|
||||
let mergeKey = '';
|
||||
|
||||
switch (this.searchoptions.mergeResults) {
|
||||
case 'student':
|
||||
mergeTypes = ['student', 'prestudent'];
|
||||
mergedType += this.searchoptions.mergeResults;
|
||||
mergeKey = 'uid';
|
||||
break;
|
||||
case 'person':
|
||||
mergeTypes = ['person', 'employee', 'student', 'prestudent'];
|
||||
mergedType += this.searchoptions.mergeResults;
|
||||
mergeKey = 'person_id';
|
||||
break;
|
||||
}
|
||||
|
||||
if (mergeTypes.length) {
|
||||
res = Object.values(res.reduce((a, c) => {
|
||||
if (!mergeTypes.includes(c.renderer)) {
|
||||
a['nomerge' + counter++] = c;
|
||||
} else if (c[mergeKey] === null) {
|
||||
a['nomerge' + counter++] = c;
|
||||
} else if (a[c[mergeKey]] === undefined) {
|
||||
a[c[mergeKey]] = {
|
||||
rank: c.rank,
|
||||
renderer: mergedType,
|
||||
type: mergedType,
|
||||
list: [c]
|
||||
};
|
||||
} else {
|
||||
a[c[mergeKey]].list.push(c);
|
||||
if (c.rank > a[c[mergeKey]].rank)
|
||||
a[c[mergeKey]].rank = c.rank;
|
||||
}
|
||||
return a;
|
||||
}, {})).sort((a, b) => b.rank - a.rank);
|
||||
}
|
||||
}
|
||||
this.searchresult = res;
|
||||
this.searchmode = response.meta.mode;
|
||||
}
|
||||
this.searching = false;
|
||||
this.retry = 0;
|
||||
})
|
||||
.catch(error=> {
|
||||
if (error.code == "ERR_CANCELED") {
|
||||
return this.retry = 0;
|
||||
}
|
||||
if (error.code == "ECONNABORTED" && this.retry) {
|
||||
this.retry--;
|
||||
return this.callsearchapi();
|
||||
}
|
||||
|
||||
this.error = this.$p.t('search/error_general', error);
|
||||
this.searching = false;
|
||||
this.retry = 0;
|
||||
});
|
||||
},
|
||||
refreshsearch: function() {
|
||||
this.search();
|
||||
this.togglesettings();
|
||||
},
|
||||
hideresult: function() {
|
||||
this.showresult = false;
|
||||
window.removeEventListener('resize', this.calcSearchResultExtent);
|
||||
},
|
||||
showsearchresult: function() {
|
||||
if(this.searchoptions?.nolivesearch === true) return;
|
||||
|
||||
if( this.searchsettings.searchstr.length >= 2 ) {
|
||||
this.showresult = true;
|
||||
window.addEventListener('resize', this.calcSearchResultExtent);
|
||||
this.calcSearchResultExtent();
|
||||
this.searchtimer = setTimeout(this.callsearchapi, 500);
|
||||
} else {
|
||||
this.showresult = false;
|
||||
}
|
||||
},
|
||||
abort() {
|
||||
if (this.searchtimer !== null) {
|
||||
clearTimeout(this.searchtimer);
|
||||
}
|
||||
if (this.abortController) {
|
||||
this.abortController.abort();
|
||||
this.abortController = null;
|
||||
}
|
||||
this.searchresult = [];
|
||||
},
|
||||
callsearchapi: function () {
|
||||
this.error = null;
|
||||
this.searchresult.splice(0, this.searchresult.length);
|
||||
this.searching = true;
|
||||
this.showsearchresult();
|
||||
if (this.searchsettings.types.length === 0) {
|
||||
this.error = this.$p.t("search/error_missing_type");
|
||||
this.searching = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.abortController) this.abortController.abort();
|
||||
this.abortController = new AbortController();
|
||||
|
||||
this.searchfunction(this.searchsettings, {
|
||||
timeout: 50000,
|
||||
signal: this.abortController.signal,
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.data) {
|
||||
this.error = this.$p.t("search/error_general");
|
||||
} else {
|
||||
let res = response.data.map((el) =>
|
||||
el.data ? { ...el, ...JSON.parse(el.data) } : el,
|
||||
);
|
||||
this.lastQuery = response.meta.searchstring;
|
||||
if (this.searchoptions.mergeResults) {
|
||||
let counter = 0;
|
||||
let mergeTypes = [];
|
||||
let mergedType = "merged-";
|
||||
let mergeKey = "";
|
||||
|
||||
switch (this.searchoptions.mergeResults) {
|
||||
case "student":
|
||||
mergeTypes = ["student", "prestudent"];
|
||||
mergedType +=
|
||||
this.searchoptions.mergeResults;
|
||||
mergeKey = "uid";
|
||||
break;
|
||||
case "person":
|
||||
mergeTypes = [
|
||||
"person",
|
||||
"employee",
|
||||
"student",
|
||||
"prestudent",
|
||||
];
|
||||
mergedType +=
|
||||
this.searchoptions.mergeResults;
|
||||
mergeKey = "person_id";
|
||||
break;
|
||||
}
|
||||
|
||||
if (mergeTypes.length) {
|
||||
res = Object.values(
|
||||
res.reduce((a, c) => {
|
||||
if (!mergeTypes.includes(c.renderer)) {
|
||||
a["nomerge" + counter++] = c;
|
||||
} else if (c[mergeKey] === null) {
|
||||
a["nomerge" + counter++] = c;
|
||||
} else if (
|
||||
a[c[mergeKey]] === undefined
|
||||
) {
|
||||
a[c[mergeKey]] = {
|
||||
rank: c.rank,
|
||||
renderer: mergedType,
|
||||
type: mergedType,
|
||||
list: [c],
|
||||
};
|
||||
} else {
|
||||
a[c[mergeKey]].list.push(c);
|
||||
if (c.rank > a[c[mergeKey]].rank)
|
||||
a[c[mergeKey]].rank = c.rank;
|
||||
}
|
||||
return a;
|
||||
}, {}),
|
||||
).sort((a, b) => b.rank - a.rank);
|
||||
}
|
||||
}
|
||||
this.searchresult = res;
|
||||
this.searchmode = response.meta.mode;
|
||||
}
|
||||
this.searching = false;
|
||||
this.retry = 0;
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.code == "ERR_CANCELED") {
|
||||
return (this.retry = 0);
|
||||
}
|
||||
if (error.code == "ECONNABORTED" && this.retry) {
|
||||
this.retry--;
|
||||
return this.callsearchapi();
|
||||
}
|
||||
|
||||
this.error = this.$p.t("search/error_general", error);
|
||||
this.searching = false;
|
||||
this.retry = 0;
|
||||
});
|
||||
},
|
||||
refreshsearch: function () {
|
||||
this.search();
|
||||
this.togglesettings();
|
||||
},
|
||||
hideresult: function () {
|
||||
this.showresult = false;
|
||||
window.removeEventListener("resize", this.calcSearchResultExtent);
|
||||
},
|
||||
showsearchresult: function () {
|
||||
if (this.searchoptions?.nolivesearch === true) return;
|
||||
|
||||
if (this.searchsettings.searchstr.length >= 2) {
|
||||
this.showresult = true;
|
||||
window.addEventListener("resize", this.calcSearchResultExtent);
|
||||
this.calcSearchResultExtent();
|
||||
}
|
||||
},
|
||||
searchfocusin: function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (this.hidetimer !== null) {
|
||||
clearTimeout(this.hidetimer);
|
||||
}
|
||||
if (
|
||||
this.searchsettings.searchstr.length >= 2 &&
|
||||
this.searchresult.length === 0
|
||||
) {
|
||||
}
|
||||
},
|
||||
searchfocusin: function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if( this.hidetimer !== null ) {
|
||||
clearTimeout(this.hidetimer);
|
||||
}
|
||||
if (this.searchsettings.searchstr.length >= 2
|
||||
&& this.searchresult.length === 0) {
|
||||
this.search();
|
||||
}
|
||||
},
|
||||
searchfocusout: function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.hidetimer = setTimeout(this.hideresult, 100);
|
||||
},
|
||||
dash2camelCase(string) {
|
||||
return string.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
||||
},
|
||||
isValidRenderer(renderer) {
|
||||
const camelCaseRenderer = this.dash2camelCase(renderer);
|
||||
return Object.keys(this.$.components).includes(camelCaseRenderer);
|
||||
},
|
||||
},
|
||||
searchfocusout: function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.hidetimer = setTimeout(
|
||||
this.hideresult,
|
||||
100
|
||||
);
|
||||
},
|
||||
dash2camelCase(string) {
|
||||
return string.replace(/-([a-z])/g, g => g[1].toUpperCase());
|
||||
},
|
||||
isValidRenderer(renderer) {
|
||||
const camelCaseRenderer = this.dash2camelCase(renderer);
|
||||
return Object.keys(this.$.components).includes(camelCaseRenderer);
|
||||
},
|
||||
getActions(res) {
|
||||
let actions =
|
||||
this.searchoptions.actions[this.dash2camelCase(res.renderer)];
|
||||
let actions = this.searchoptions.actions[this.dash2camelCase(res.renderer)];
|
||||
if (actions) {
|
||||
return actions;
|
||||
}
|
||||
return this.searchoptions.actions[res.type];
|
||||
},
|
||||
getMaxWidthOfSearchbarInMobileView() {
|
||||
// body width - hardcoded chevron width; necessary for accurate collapse transition transition
|
||||
return (
|
||||
document.querySelector("body").getBoundingClientRect().width -
|
||||
27 +
|
||||
"px"
|
||||
);
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -227,7 +227,8 @@ if (isset($_GET['sendform']))
|
||||
<table class="tablesorter" id="t1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><span class="tooltip"><img src="../../skin/images/information.png" height="20px" name="infoicon"/>
|
||||
<th><button type="button" class="resetsaved" title="Reset Filter">Reset Filter</button>
|
||||
<span class="tooltip"><img src="../../skin/images/information.png" height="20px" name="infoicon"/>
|
||||
'.$tooltiptext.'
|
||||
</span>
|
||||
</th>
|
||||
@@ -364,9 +365,10 @@ if (isset($_GET['sendform']))
|
||||
$("#t1").tablesorter(
|
||||
{
|
||||
sortList: [[3,0]],
|
||||
widgets: ["zebra", "filter", "stickyHeaders"],
|
||||
widgets: ["saveSort", "zebra", "filter", "stickyHeaders"],
|
||||
headers: { 0: { filter: false, sorter: false }},
|
||||
widgetOptions : { filter_functions : {
|
||||
widgetOptions : { filter_saveFilters : true,
|
||||
filter_functions : {
|
||||
// Add select menu to this column
|
||||
8 : {
|
||||
"True" : function(e, n, f, i, $r, c, data) { return /t/.test(e); },
|
||||
@@ -381,6 +383,13 @@ if (isset($_GET['sendform']))
|
||||
"False" : function(e, n, f, i, $r, c, data) { return /f/.test(e); }
|
||||
}
|
||||
}}
|
||||
});
|
||||
|
||||
$('.resetsaved').click(function()
|
||||
{
|
||||
$("#t1").trigger("filterReset");
|
||||
location.reload(forceGet);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -588,7 +588,9 @@ if(isset($_POST['testergebnisanzeigen']) && isset($_POST['prestudent_id']))
|
||||
{
|
||||
if(is_numeric($_POST['prestudent_id']) && $_POST['prestudent_id']!='')
|
||||
{
|
||||
$qry="SELECT nachname,vorname,person_id,prestudent_id,tbl_pruefling.pruefling_id,tbl_pruefling_frage.begintime,bezeichnung,kurzbz,tbl_frage.nummer,level, tbl_vorschlag.nummer as antwortnummer, tbl_vorschlag.punkte
|
||||
$qry="SELECT nachname,vorname,person_id,prestudent_id,tbl_pruefling.pruefling_id,
|
||||
tbl_pruefling_frage.begintime,bezeichnung,kurzbz,tbl_frage.nummer,level,
|
||||
tbl_vorschlag.nummer as antwortnummer, tbl_vorschlag.punkte, tbl_frage.frage_id
|
||||
FROM testtool.tbl_antwort
|
||||
JOIN testtool.tbl_vorschlag USING(vorschlag_id)
|
||||
JOIN testtool.tbl_frage USING (frage_id)
|
||||
@@ -615,6 +617,7 @@ if(isset($_POST['testergebnisanzeigen']) && isset($_POST['prestudent_id']))
|
||||
<th>Level</th>
|
||||
<th>Antwort #</th>
|
||||
<th>Punkte</th>
|
||||
<th>FrageID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
@@ -632,6 +635,7 @@ if(isset($_POST['testergebnisanzeigen']) && isset($_POST['prestudent_id']))
|
||||
echo "<td>$row->level</td>";
|
||||
echo "<td>$row->antwortnummer</td>";
|
||||
echo "<td>$row->punkte</td>";
|
||||
echo "<td>$row->frage_id</td>";
|
||||
echo '</tr>';
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
|
||||
@@ -837,6 +837,25 @@ if(isset($_GET['excel']))
|
||||
<script src="../../vendor/fgelinas/timepicker/jquery.ui.timepicker.js" type="text/javascript" ></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$.tablesorter.addParser({
|
||||
id: "customDate",
|
||||
is: function(s) {
|
||||
//return false;
|
||||
//use the above line if you don\'t want table sorter to auto detected this parser
|
||||
// match dd.mm.yyyy e.g. 01.01.2001 as regex
|
||||
//return /\d{1,4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2} .*/.test(s);
|
||||
return /\d{1,2}.\d{1,2}.\d{1,4}.*/.test(s);
|
||||
},
|
||||
// replace regex-wildcards and return new date
|
||||
format: function(s) {
|
||||
s = s.replace(/\-/g," ");
|
||||
s = s.replace(/:/g," ");
|
||||
s = s.replace(/\./g," ");
|
||||
s = s.split(" ");
|
||||
return $.tablesorter.formatFloat(new Date(s[2], s[1]-1, s[0]).getTime());
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
$(document).ready(function()
|
||||
{
|
||||
// Check, ob Räume zugeteilt sind oder max_teilnehmer gesetzt ist, wenn "öffentlich" gesetzt wird
|
||||
@@ -1007,7 +1026,7 @@ if(isset($_GET['excel']))
|
||||
{
|
||||
widgets: ["zebra", "filter", "stickyHeaders"],
|
||||
sortList: [[2,0],[3,0]],
|
||||
headers: {0: { sorter: false}},
|
||||
headers: {0: { sorter: false},10: { sorter: "customDate"},11: { sorter: "customDate"}},
|
||||
widgetOptions: {filter_cssFilter: [
|
||||
"filter_clm_null",
|
||||
"filter_clm_prestudent_id",
|
||||
@@ -1020,6 +1039,7 @@ if(isset($_GET['excel']))
|
||||
"filter_clm_studienplan",
|
||||
"filter_clm_einstiegssemester",
|
||||
"filter_clm_geburtsdatum",
|
||||
"filter_clm_anmeldedatum",
|
||||
"filter_clm_email",
|
||||
"filter_clm_absolviert"]}
|
||||
});
|
||||
@@ -1072,6 +1092,7 @@ if(isset($_GET['excel']))
|
||||
'clm_studienplan',
|
||||
'clm_einstiegssemester',
|
||||
'clm_geburtsdatum',
|
||||
"filter_clm_anmeldedatum",
|
||||
'clm_email',
|
||||
'clm_absolviert'];
|
||||
for (var i in arr)
|
||||
@@ -2697,7 +2718,8 @@ if($reihungstest_id!='')
|
||||
WHERE prestudent_id = tbl_prestudent.prestudent_id
|
||||
AND status_kurzbz = 'Interessent'
|
||||
) LIMIT 1
|
||||
) AS orgform_kurzbz
|
||||
) AS orgform_kurzbz,
|
||||
tbl_rt_person.anmeldedatum
|
||||
FROM PUBLIC.tbl_rt_person
|
||||
JOIN PUBLIC.tbl_person USING (person_id)
|
||||
JOIN PUBLIC.tbl_reihungstest rt ON (rt_id = rt.reihungstest_id)
|
||||
@@ -2786,6 +2808,7 @@ if($reihungstest_id!='')
|
||||
echo '<div id="clm_studienplan" class="active" onclick="hideColumn(\'clm_studienplan\')">Studienplan</div>';
|
||||
echo '<div id="clm_einstiegssemester" class="active" onclick="hideColumn(\'clm_einstiegssemester\')">Einstiegssemester</div>';
|
||||
echo '<div id="clm_geburtsdatum" class="active" onclick="hideColumn(\'clm_geburtsdatum\')">Geburtsdatum</div>';
|
||||
echo '<div id="clm_anmeldedatum" class="active" onclick="hideColumn(\'clm_anmeldedatum\')">Geburtsdatum</div>';
|
||||
echo '<div id="clm_email" class="active" onclick="hideColumn(\'clm_email\')">EMail</div>';
|
||||
echo '<div id="clm_absolviert" class="active" onclick="hideColumn(\'clm_absolviert\')">Absolvierte Tests <span class="wait"></span></div>';
|
||||
//echo '<div id="clm_ergebnis" class="active" onclick="hideColumn(\'clm_ergebnis\')">Ergebnis <span class="wait"></span></div>';
|
||||
@@ -2827,6 +2850,7 @@ if($reihungstest_id!='')
|
||||
<th style="display: table-cell" class="clm_studienplan">Studienplan</th>
|
||||
<th style="display: table-cell" class="clm_einstiegssemester">Einstiegssemester</th>
|
||||
<th style="display: table-cell" class="clm_geburtsdatum">Geburtsdatum</th>
|
||||
<th style="display: table-cell" class="clm_anmeldedatum">Anmeldedatum</th>
|
||||
<th style="display: table-cell" class="clm_email">EMail</th>
|
||||
<th style="display: table-cell" class="clm_absolviert">bereits absolvierte Verfahren</th>
|
||||
<!--<th style="display: table-cell" class="clm_ergebnis">Ergebnis</th>
|
||||
@@ -2946,6 +2970,7 @@ if($reihungstest_id!='')
|
||||
<td style="display: table-cell" class="clm_studienplan">'.$db->convert_html_chars($studienplan_bezeichnung).' ('.$row->studienplan_id.')</td>
|
||||
<td style="display: table-cell" class="clm_einstiegssemester">'.$db->convert_html_chars($row->ausbildungssemester).'</td>
|
||||
<td style="display: table-cell" class="clm_geburtsdatum">'.$db->convert_html_chars($row->gebdatum!=''?$datum_obj->convertISODate($row->gebdatum):' ').'</td>
|
||||
<td style="display: table-cell" class="clm_anmeldedatum">'.$db->convert_html_chars($row->anmeldedatum!=''?$datum_obj->convertISODate($row->anmeldedatum):' ').'</td>
|
||||
<td style="display: table-cell; text-align: center" class="clm_email"><a href="mailto:'.$db->convert_html_chars($row->email).'"><img src="../../skin/images/button_mail.gif" name="mail"></a></td>
|
||||
<td style="display: table-cell;" class="clm_absolviert">'.$rt_in_anderen_stg.'</td>
|
||||
</tr>';
|
||||
@@ -3009,6 +3034,7 @@ if($reihungstest_id!='')
|
||||
<th style="display: table-cell" class="clm_studienplan">Studienplan</th>
|
||||
<th style="display: table-cell" class="clm_einstiegssemester">Einstiegssemester</th>
|
||||
<th style="display: table-cell" class="clm_geburtsdatum">Geburtsdatum</th>
|
||||
<th style="display: table-cell" class="clm_anmeldedatum">Anmeldedatum</th>
|
||||
<th style="display: table-cell" class="clm_email">EMail</th>
|
||||
<th style="display: table-cell" class="clm_absolviert">bereits absolvierte Verfahren</th>
|
||||
<!--<th style="display: table-cell" class="clm_ergebnis">Ergebnis</th>
|
||||
@@ -3128,6 +3154,7 @@ if($reihungstest_id!='')
|
||||
<td style="display: table-cell" class="clm_studienplan">'.$db->convert_html_chars($studienplan_bezeichnung).' ('.$row->studienplan_id.')</td>
|
||||
<td style="display: table-cell" class="clm_einstiegssemester">'.$db->convert_html_chars($row->ausbildungssemester).'</td>
|
||||
<td style="display: table-cell" class="clm_geburtsdatum">'.$db->convert_html_chars($row->gebdatum!=''?$datum_obj->convertISODate($row->gebdatum):' ').'</td>
|
||||
<td style="display: table-cell" class="clm_anmeldedatum">'.$db->convert_html_chars($row->anmeldedatum!=''?$datum_obj->convertISODate($row->anmeldedatum):' ').'</td>
|
||||
<td style="display: table-cell; text-align: center" class="clm_email"><a href="mailto:'.$db->convert_html_chars($row->email).'"><img src="../../skin/images/button_mail.gif" name="mail"></a></td>
|
||||
<td style="display: table-cell;" class="clm_absolviert">'.$rt_in_anderen_stg.'</td>';
|
||||
/*echo '<td style="display: table-cell; align: right" class="clm_ergebnis">'.($rtergebnis==0?'-':number_format($rtergebnis,2,'.','')).' %</td>
|
||||
|
||||
Reference in New Issue
Block a user