Merge branch 'feature-25999/C4_cleanup' into feature-25999/C4_anwesenheiten_widget

This commit is contained in:
Johann Hoffmann
2024-11-28 10:22:57 +01:00
13 changed files with 140 additions and 56 deletions
@@ -29,7 +29,9 @@ class Phrasen extends FHCAPI_Controller
{
parent::__construct([
'loadModule' => self::PERM_ANONYMOUS,
'setLanguage' => self::PERM_ANONYMOUS
'setLanguage' => self::PERM_ANONYMOUS,
'getLanguage' => self::PERM_ANONYMOUS,
'getAllLanguages' => self::PERM_ANONYMOUS,
]);
$this->load->helper('hlp_language');
@@ -60,4 +62,23 @@ class Phrasen extends FHCAPI_Controller
$phrases = $this->p->setPhrases($categories, $language);
$this->terminateWithSuccess($phrases);
}
// gets the langauge of the currently logged in user session and otherwhise the system language
public function getLanguage()
{
$lang = getUserLanguage();
$this->terminateWithSuccess($lang);
}
// gets all languages that are set as active in the database
public function getAllLanguages()
{
$langs = getDBActiveLanguages();
$langs = $this->getDataOrTerminateWithError($langs);
$langs = array_map(function($lang){
return $lang->sprache;
}, $langs);
$this->terminateWithSuccess($langs);
}
}
@@ -135,7 +135,7 @@ class Stundenplan_model extends DB_Model
/**
* function that takes a query that fetches lehre.vw_stundenplan rows and groups them so that they can be displayed in a calendar
* groups rows of a subquery that fetches data from the lehre.vw_stundenplan table
* @param string $stundenplanViewQuery the subquery used to group the result
*
* @return stdClass
@@ -190,7 +190,7 @@ class Stundenplan_model extends DB_Model
* NO STANDALONE FUNCTION - Generates a SQL query string to fetch 'stundenplan' events for a specific student within the current semester.
* @param string $uid the user id that is used to fetch the stundenplan rows from the lehre.vw_stundenplan table
*
* @return string
* @return mixed
*/
public function getStundenplanQuery($start_date, $end_date,$semester,$gruppen,$studentlehrverbaende){
@@ -207,10 +207,10 @@ class Stundenplan_model extends DB_Model
return $result;
};
// if both the gruppen and the studentlehrverbaende are empty we return nothing
// if both the gruppen and the studentlehrverbaende are empty we early return
if($emptyCheck($gruppen) && $emptyCheck($studentlehrverbaende))
{
return "";
return false;
}
$query =
@@ -239,13 +239,11 @@ class Stundenplan_model extends DB_Model
// converts the array of gruppen strings into a sql IN (_,_,_) chain
$query .="(sp.gruppe_kurzbz IN (" .implode(',',$gruppen[$sem_date]).") AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende)." )";
// adds the OR sql chain only if the $studentlehrverbaende array is not empty
// or its not the last semester to add the groups from
$query .="OR";
}
}
// if there are no studentlehrverbaende, we can remove the last OR added after the groups
// if there are no studentlehrverbaende and the gruppen are not empty, we can remove the last OR added after the groups
if($emptyCheck($studentlehrverbaende) && !$emptyCheck($gruppen))
{
$query = substr($query, 0, -2);
@@ -267,7 +265,7 @@ class Stundenplan_model extends DB_Model
// Eintraege fuer das ganze Semester
$query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND (sp.verband is null OR sp.verband='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).") AND gruppe_kurzbz is null)";
$query .="OR";
$query .="OR";
}
}
+14 -1
View File
@@ -478,15 +478,28 @@ html {
}
.fhc-entry:hover{
background-color:#0088d6 !important;
background-color:#005585 !important;
color:white !important;
}
.fhc-entry.btn:focus {
box-shadow: none !important;
}
.fhc-entry.btn {
border-radius: 0 !important;
}
.fhc-entry {
transition-property: background,color;
transition-duration: 0.3s,0.2s;
transition-timing-function: ease-out,ease-out;
}
[selected].fhc-entry {
background-color: #00649C !important;
}
@media screen and ( max-width: 767px ) {
#nav-search {
position: static;
+6
View File
@@ -22,5 +22,11 @@ export default {
setLanguage(categories,language) {
const payload = {categories, language}
return this.$fhcApi.post('/api/frontend/v1/phrasen/setLanguage', payload);
},
getLanguage() {
return this.$fhcApi.get('/api/frontend/v1/phrasen/getLanguage', {});
},
getActiveDbLanguages() {
return this.$fhcApi.get('/api/frontend/v1/phrasen/getAllLanguages', {});
}
};
+1 -1
View File
@@ -130,7 +130,7 @@ const app = Vue.createApp({
</div>
</template>
<template #dayPage="{event,day,mobile}">
<div @click="mobile? showModal(event?.orig):null" type="button" class="fhc-entry border border-secondary border row h-100 justify-content-center align-items-center text-center">
<div @click="mobile? showModal(event?.orig):null" type="button" class="fhc-entry border border-secondary border row m-0 h-100 justify-content-center align-items-center text-center">
<div class="col ">
<p>Lehrveranstaltung:</p>
<p class="m-0">{{event?.orig.topic}}</p>
@@ -75,6 +75,14 @@ export default {
this.fetchLvMenu(event);
},
immediate:true,
},
isSliding:{
handler(value){
if(value)
{
this.setSelectedEvent(null);
}
}
}
},
computed: {
+1 -1
View File
@@ -53,7 +53,7 @@ export default {
},
template: /*html*/ `
<!-- div that contains the content -->
<component :is="computeContentType" v-if="content" :content="content" />
<component :is="computeContentType" v-if="content" :content="content" :content_id="content_id" />
<p v-else>No content is available to display</p>
`,
};
+4 -4
View File
@@ -12,7 +12,7 @@ export default {
RaumContent,
},
props:{
contentID:{
content_id:{
type: Number
},
ort_kurzbz:{
@@ -34,8 +34,8 @@ export default {
// this method is always called when the modal is shown
modalShown: function(){
if(this.contentID){
this.$fhcApi.factory.cms.content(this.contentID).then(res =>{
if(this.content_id){
this.$fhcApi.factory.cms.content(this.content_id).then(res =>{
this.content = res.data.content;
this.type = res.data.type;
@@ -55,7 +55,7 @@ export default {
<span v-else>Raum Informationen</span>
</template>
<template #default>
<RaumContent v-if="content" :content="content"></RaumContent>
<RaumContent v-if="content" :content="content" :content_id="content_id"></RaumContent>
<div v-else>Der Content für diesen Raum konnte nicht geladen werden</div>
</template>
<template #footer>
@@ -5,6 +5,9 @@ export default {
type:String,
required:true,
},
content_id:{
type:Number,
}
},
mounted(){
// replaces the tablesorter with the tabulator
@@ -21,6 +24,34 @@ export default {
}
})
}
// tries to wrap the Raum titel with a link tag that redirects to the Reservierungen of that Raum
let title = document.getElementsByTagName("h1");
title = title.length ? title[0] : null;
if (title)
{
let room_name = title.innerText;
let room_name_reg_exp = new RegExp("\\w*\\s([a-zA-Z][0-9\\.]+)$");
let room_name_reg_exp_result = room_name.match(room_name_reg_exp);
if(room_name_reg_exp_result)
{
room_name = room_name_reg_exp_result[0];
room_name = room_name.replace(" ","_");
let link_element = document.createElement("a");
link_element.href = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + "/CisVue/Cms/getRoomInformation/" + room_name;
link_element.appendChild(title.cloneNode(true));
title.replaceWith(link_element);
}
else
{
console.error(`the regular expression did not match the room name: ${room_name}`);
}
}
else
{
console.error(`was not able to get the title of the raum_contentmittitel by searching for the first h1 element`);
}
},
template: /*html*/ `
<!-- div that contains the content -->
+10 -39
View File
@@ -1,10 +1,12 @@
import CisMenuEntry from "./Menu/Entry.js";
import FhcSearchbar from "../searchbar/searchbar.js";
import CisSprachen from "./Sprachen.js"
export default {
components: {
CisMenuEntry,
FhcSearchbar
FhcSearchbar,
CisSprachen,
},
props: {
menu: Array,
@@ -49,24 +51,6 @@ export default {
}
},
methods: {
getLanguageButtonClass(lang) {
let classString = 'btn btn-level-2 rounded-0'
const langCookie = (function(lang) {
const cookieString = document.cookie;
const cookies = cookieString.split('; ');
for (let cookie of cookies) {
const [key, value] = cookie.split('=');
if (key === lang) {
return decodeURIComponent(value);
}
}
return null; // Return null if the cookie is not found
})('sprache');
if(langCookie === lang) classString += ' fhc-active';
return classString
},
toggleCollapsibles(target){
switch(target){
case 'settings':
@@ -93,20 +77,6 @@ export default {
setActiveEntry(content_id){
this.activeEntry = content_id;
},
handleChangeLanguage(lang) {
this.$p.setLanguage(lang, this.$fhcApi)
const gerButton = this.$refs.ger
const engButton = this.$refs.eng
if(lang === 'German') {
gerButton.classList.add('fhc-active')
engButton.classList.remove('fhc-active')
} else if(lang === 'English') {
engButton.classList.add('fhc-active')
gerButton.classList.remove('fhc-active')
}
}
},
mounted(){
this.entries = this.menu;
@@ -133,24 +103,25 @@ export default {
</button>
<ul ref="navUserDropdown" @[\`show.bs.collapse\`]="toggleCollapsibles('navUserDropdown')" id="nav-user-menu" class="top-100 end-0 collapse list-unstyled" aria-labelledby="nav-user-btn">
<li class="btn-level-2"><a class="btn btn-level-2 rounded-0 d-block" :href="site_url + '/Cis/Profil'" id="menu-profil">Profil</a></li>
<li class="fhc-languages btn-level-2" style="text-align: center;">
<div class="btn-group">
<a :class="getLanguageButtonClass('German')" ref="ger" href="#" @click="handleChangeLanguage('German')">Deutsch</a>
<a :class="getLanguageButtonClass('English')" ref="eng" href="#" @click="handleChangeLanguage('English')">English</a>
</div>
<li class="btn-level-2">
<cis-sprachen></cis-sprachen>
</li>
<li class="btn-level-2"><hr class="dropdown-divider p-0 "></li>
<li class="btn-level-2"><hr class="dropdown-divider m-0 "></li>
<li><a class="btn btn-level-2 rounded-0 d-block" :href="logoutUrl">Logout</a></li>
</ul>
</div>
<nav id="nav-main" class="offcanvas offcanvas-start bg-dark" tabindex="-1" aria-labelledby="nav-main-btn" data-bs-backdrop="false">
<div id="nav-main-sticky">
<div class="border-top border-bottom border-dark" >
<cis-sprachen></cis-sprachen>
</div>
<div id="nav-main-toggle" class="position-static d-none d-lg-block bg-dark">
<button type="button" class="btn bg-dark text-light rounded-0 p-1 d-flex align-items-center" data-bs-toggle="collapse" data-bs-target="#nav-main-menu" aria-expanded="true" aria-controls="nav-main-menu">
<i class="fa fa-arrow-circle-left"></i>
</button>
</div>
<div class="offcanvas-body p-0">
<div id="nav-main-menu" class="collapse collapse-horizontal show">
<div>
<cis-menu-entry :highestMatchingUrlCount="highestMatchingUrlCount" :activeContent="activeEntry" v-for="entry in entries" :key="entry.content_id" :entry="entry" />
+31
View File
@@ -0,0 +1,31 @@
export default {
data(){
return {
allActiveLanguages: null,
}
},
methods:{
changeLanguage: function(lang){
if(this.allActiveLanguages.some(l => l === lang))
{
this.$p.setLanguage(lang, this.$fhcApi);
}
},
},
mounted(){
this.$fhcApi.factory.phrasen.getActiveDbLanguages()
.then(res => res.data)
.then(
(langs) => {
this.allActiveLanguages = langs;
}
);
},
template:/*html*/`
<div class="container flex-shrink-0">
<div class="row justify-content-center align-items-center">
<button v-for="lang in allActiveLanguages" @click.prevent="changeLanguage(lang)" class="col text-white fhc-entry btn text-center w-100" :selected="$p.user_language.value==lang?'':null">{{lang}}</button>
</div>
</div>
`,
};
@@ -188,7 +188,7 @@ export default {
template: /*html*/`
<div class="dashboard-widget-stundenplan d-flex flex-column h-100">
<lv-modal v-if="selectedEvent" ref="lvmodal" :event="selectedEvent" />
<content-modal :contentID="roomInfoContentID" dialogClass="modal-lg" ref="contentModal"/>
<content-modal :content_id="roomInfoContentID" dialogClass="modal-lg" ref="contentModal"/>
<fhc-calendar @change:range="updateRange" :initial-date="currentDay" class="border-0" class-header="p-0" @select:day="selectDay" :widget="true" v-model:minimized="minimized" :events="events" no-week-view :show-weeks="false" >
<template #monthPage="{event,day,isSelected}">
<span class="fhc-entry" :class="{'selectedEvent':isSelected}" style="color:white" :style="{'background-color': event.color}">
+5
View File
@@ -1,6 +1,7 @@
import FhcApi from './FhcApi.js';
const categories = Vue.reactive({});
const user_language = Vue.ref(FHC_JS_DATA_STORAGE_OBJECT.user_language);
const loadingModules = {};
let reload = false;
@@ -30,6 +31,9 @@ const phrasen = {
categories[row.category][row.phrase] = row.text
})
// update the reactive data that holds the current active user_language
user_language.value = language;
return res
})
},
@@ -81,6 +85,7 @@ export default {
t: phrasen.t,
loadCategory: cat => phrasen.loadCategory.call(app, cat),
setLanguage: phrasen.setLanguage,
user_language: user_language,
t_ref: phrasen.t_ref
};
app.provide('$p', app.config.globalProperties.$p);