Merge branch 'cis40_2026-05_ma_rc' into demo-cis40

This commit is contained in:
Harald Bamberger
2026-05-29 13:40:02 +02:00
14 changed files with 130 additions and 26 deletions
@@ -25,12 +25,6 @@ class ProjektabgabeUebersicht extends Auth_Controller
*/
public function index()
{
// TODO create permission
$viewData = array(
'uid' => getAuthUID(),
'showEdit' => true
);
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'ProjektabgabeUebersicht']);
$this->load->view('CisRouterView/CisRouterView.php', ['route' => 'ProjektabgabeUebersicht']);
}
}
@@ -27,11 +27,12 @@ class PaabgabeUebersicht extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
'viewData' => self::PERM_LOGGED,
'getPaAbgaben' => array('lehre/abgabetool:r'),
'getStudiengaenge' => array('lehre/abgabetool:r'),
'getTermine' => array('lehre/abgabetool:r'),
'getPaAbgabetypen' => array('lehre/abgabetool:r'),
'downloadZip' => array('lehre/abgabetool:r')
'downloadZip' => array('lehre/abgabetool:r'),
//'downloadProjektarbeit' => array('lehre/abgabetool:r')
]);
@@ -45,6 +46,17 @@ class PaabgabeUebersicht extends FHCAPI_Controller
]);
}
public function viewData()
{
$viewData = [
"uid" => getAuthUID(),
// TODO create permission
"showEdit" => true,
];
$this->terminateWithSuccess($viewData);
}
/**
* Get Projektabgaben for search criteria.
*/
+4 -1
View File
@@ -361,7 +361,10 @@ class StundenplanLib
if (isError($ort_content_object)) {
return error(getData($ort_content_object));
}
$ort_content_object = getData($ort_content_object)[0];
$ort_content_object_data = getData($ort_content_object);
$ort_content_object = (is_array($ort_content_object_data) && count($ort_content_object_data) > 0)
? $ort_content_object_data[0]
: null;
if($ort_content_object) {
$item->ort_content_id = $ort_content_object->content_id;
}
@@ -26,5 +26,11 @@ export default {
method: 'get',
url: '/api/frontend/v1/education/PaabgabeUebersicht/getPaAbgabetypen'
};
},
getViewData() {
return {
method: 'get',
url: '/api/frontend/v1/education/PaabgabeUebersicht/viewData'
};
}
};
+8 -2
View File
@@ -19,7 +19,8 @@ export default {
originalBackgrounds: "backgrounds",
dropAllowed: "dropAllowed",
timezone: "timezone",
reservierbar: "isReservierbar"
reservierbar: "isReservierbar",
reservierbarMap: "reservierbarMap",
},
provide() {
return {
@@ -328,6 +329,9 @@ export default {
return !dayEvents.some(ev => ev.start < end && ev.end > start);
}
},
created() {
this.$p.loadCategory(["LvPlan"]);
},
beforeUnmount() {
this.disableAutoScroll();
},
@@ -424,9 +428,11 @@ export default {
class="fhc-calendar-empty-slot"
style="position:absolute; inset:0; z-index:1"
v-cal-click:slot="{ date, part }"
:title="this.reservierbarMap?.[date.toISODate()] ? $p.t('LvPlan/add_reservation') : $p.t('LvPlan/reservation_not_allowed')"
>
<div class="fhc-calendar-empty-slot-plus">
<i class="fa-solid fa-plus"></i>
<i v-if="this.reservierbarMap?.[date.toISODate()]" class="fa-solid fa-plus"></i>
<i v-else class="fa-solid fa-ban" style="color: red;"></i>
</div>
</div>
+3
View File
@@ -230,6 +230,9 @@ export default {
:is="renderers[event.type]?.calendarEvent"
:event="event"
@delete-event="(event) => $emit('delete-event', event)"
:timeSlotDisplayBehavior="
$props.mode.toLowerCase() === 'list' ? 'always' : 'default'
"
></component>
</div>
</template>
+1
View File
@@ -97,6 +97,7 @@ export default {
<component
:is="renderers[event.type]?.calendarEvent"
:event="event"
:timeSlotDisplayBehavior="'always'"
></component>
</div>
</template>
@@ -340,7 +340,7 @@ export default {
<div class="row">
<div class="d-md-none col-12">
<!-- Bearbeiten Button -->
<div v-if="isEditable" class="row mb-4">
<div v-if="isEditable" class="row mb-3 ">
<div class="col">
<button @click="()=>showEditProfilModal()" type="button" class="text-start card w-100 btn btn-outline-secondary" >
<div class="row">
@@ -176,6 +176,7 @@ export const Profil = {
this.data = data.profil_data.data;
this.calendarSyncUrls = data.calendar_sync_urls ?? [];
this.authPermissions = data.permissions;
console.log(data.profil_data);
},
zustellAdressenCount() {
if (!this.data || !this.data.adressen) {
@@ -4,9 +4,6 @@ import Loader from "../../Loader.js";
export const ProjektabgabeUebersicht = {
name: "ProjektabgabeUebersicht",
props: {
viewData: Object // NOTE: this is inherited from router-view
},
components: {
CoreFilterCmpt,
Loader
@@ -60,7 +57,7 @@ export const ProjektabgabeUebersicht = {
});
container.append(downloadButton);
if (this.viewData.showEdit)
if (this.showEdit)
{
let editButton = document.createElement('button');
editButton.className = 'btn btn-outline-secondary';
@@ -116,7 +113,9 @@ export const ProjektabgabeUebersicht = {
this.tableBuiltResolve()
}
}
]};
],
showEdit: null,
};
},
methods: {
tableResolve(resolve) {
@@ -220,7 +219,12 @@ export const ProjektabgabeUebersicht = {
if (this.selectedTermin) url.searchParams.append('abgabedatum', this.selectedTermin);
if (this.personSearchString) url.searchParams.append('personSearchString', this.personSearchString);
window.open(url.toString(), '_blank');
}
},
async getViewData() {
const viewDataResponse = await this.$api.call(ApiPaabgabe.getViewData());
const viewData = viewDataResponse.data;
this.showEdit = viewData.showEdit;
},
},
computed: {
isDarkMode() {
@@ -236,7 +240,8 @@ export const ProjektabgabeUebersicht = {
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/api/frontend/v1/education/PaabgabeUebersicht/downloadZip';
}
},
created() {
async created() {
await this.getViewData();
this.phrasenPromise = this.$p.loadCategory(['abgabetool', 'global', 'person', 'ui']);
this.phrasenPromise.then(()=> {this.phrasenResolved = true});
},
@@ -3,6 +3,11 @@ export default {
event: {
type: Object,
required: true
},
timeSlotDisplayBehavior: {
type: String,
default: "default",
// options: default, always, never
}
},
computed:{
@@ -50,7 +55,17 @@ export default {
return luxon.Duration
.fromISOTime(this.event.ende)
.toISOTime({ suppressSeconds: true });
}
},
timeSlotDisplayClasses() {
switch (this.$props.timeSlotDisplayBehavior) {
case "always":
return "d-grid";
case "never":
return "d-none";
default:
return "d-none d-xl-grid";
}
},
},
template: /*html*/`
<div
@@ -58,8 +73,9 @@ export default {
@wheel.stop
>
<div
v-if="!event.allDayEvent && event?.beginn && event?.ende"
class="event-time d-none d-xl-grid h-100"
v-if="!event?.allDayEvent && event?.beginn && event?.ende"
:class="timeSlotDisplayClasses"
class="event-time h-100"
>
<span>{{ start }}</span>
<span>{{ end }}</span>
@@ -3,6 +3,11 @@ export default {
event: {
type: Object,
required: true
},
timeSlotDisplayBehavior: {
type: String,
default: "default",
// options: default, always, never
}
},
inject: {
@@ -63,14 +68,25 @@ export default {
methods: {
handleDelete() {
this.$emit('delete-event', this.event);
}
},
timeSlotDisplayClasses() {
switch (this.$props.timeSlotDisplayBehavior) {
case "always":
return "d-grid";
case "never":
return "d-none";
default:
return "d-none d-xl-grid";
}
},
},
template: /* html */`
<div
class="cis-renderer-reservierungen-calendar-event calendar-event-default h-100 w-100 p-1 position-relative">
<div
v-if="!event.allDayEvent && event?.beginn && event?.ende"
class="event-time d-grid h-100"
v-if="!event?.allDayEvent && event?.beginn && event?.ende"
:class="timeSlotDisplayClasses"
class="event-time h-100"
>
<span>{{ start }}</span>
<span>{{ end }}</span>
@@ -86,6 +102,7 @@ export default {
</button>
<span class="event-topic">{{ event.topic }}</span>
<span class="event-place">{{ event.ort_kurzbz }}</span>
<span
v-for="lektor in event.lektor.slice(0, 3)"
class="event-lectors"
@@ -98,7 +115,6 @@ export default {
>
... +{{ event.lektor.length - 3 }}
</span>
<span class="event-place">{{ event.ort_kurzbz }}</span>
</div>
</div>
`,
@@ -75,6 +75,7 @@ export default {
},
methods: {
switchFilter(evt) {
console.log(evt);
this.$emit('switchFilter', evt.currentTarget.value);
},
applyFilterConfig() {
+40
View File
@@ -29924,6 +29924,46 @@ array(
)
)
),
array(
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'add_reservation',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Reservierung hinzufügen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Add reservation',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'LvPlan',
'phrase' => 'reservation_not_allowed',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Reservierung nicht erlaubt',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Reservation not allowed',
'description' => '',
'insertvon' => 'system'
)
)
),
// LvPlan Phrasen ende
//ProfilUpdate Phrasen start
array(