WIP: Second feedback alterations

This commit is contained in:
Ivymaster
2026-05-27 15:17:30 +02:00
parent f3e1208f27
commit 69cdb43935
8 changed files with 155 additions and 112 deletions
@@ -36,7 +36,7 @@ class ClassScheduleApi extends FHCAPI_Controller
'createClassTimeSlotsForValidityPeriod' => array('lehre/unterrichtszeiten_gk:r'),
'updateClassTimeSlotsForValidityPeriod' => array('lehre/unterrichtszeiten_gk:r'),
'deleteClassTimeSlotsForValidityPeriod' => array('lehre/unterrichtszeiten_gk:r'),
'getAllClassScheduleTypes' => array('lehre/unterrichtszeiten_typ:r'),
'getAllClassScheduleTypes' => array('lehre/unterrichtszeiten_typ:r', 'lehre/unterrichtszeiten_gk:r'),
'createClassTimeSlotType' => array('lehre/unterrichtszeiten_typ:rw'),
'updateClassTimeSlotType' => array('lehre/unterrichtszeiten_typ:rw'),
'deleteClassTimeSlotType' => array('lehre/unterrichtszeiten_typ:rw'),
@@ -42,6 +42,7 @@ class ClassSchedule extends Auth_Controller
{
return $this->load->view('lehre/class_schedule/index.php', [
'permissions' => [
'lehre/unterrichtszeiten_typ_r' => $this->permissionlib->isBerechtigt('lehre/unterrichtszeiten_typ', 's'),
'lehre/unterrichtszeiten_typ_w' => $this->permissionlib->isBerechtigt('lehre/unterrichtszeiten_typ', 'suid'),
],
]);
@@ -1079,7 +1079,10 @@ export default {
let dropzoneElementDataNumber =
this.getElementDataNumber(closestPartBody);
if (dropzoneElementDataNumber === null || dropzoneElementDataNumber === undefined) {
if (
dropzoneElementDataNumber === null ||
dropzoneElementDataNumber === undefined
) {
return;
}
@@ -1350,6 +1353,8 @@ export default {
this.currentlyEditedOverlayId = null;
},
showOverlayClassTimeTypePopover(overlayId) {
if (this.$props.isPreviewMode) return;
let overlayElement = this.getOverlayElementByOverlayId(overlayId);
if (!overlayElement) return;
@@ -1827,18 +1832,6 @@ export default {
<div
class="d-flex flex-column justify-content-center align-items-center gap-1 p-0 overflow-auto scrollable h-100"
>
<a
v-if="!$props.isPreviewMode"
@mousedown.stop="showOverlayClassTimeTypePopover('overlay-item-' + index)"
:title="$p.t('ui', 'bearbeiten')"
:class="{
'bottom-0 end-0': isOverlayMinimallySized(this.overlays.find(overlay => overlay.id === 'overlay-item-' + index)),
'top-0 start-0': !isOverlayMinimallySized(this.overlays.find(overlay => overlay.id === 'overlay-item-' + index)),
}"
class="position-absolute p-1 d-flex gap-1 fhc-cursor-pointer"
>
<i class="fa fa-edit text-primary fs-6"></i>
</a>
<a
v-if="!$props.isPreviewMode"
@mousedown.stop="deleteOverlay('overlay-item-' + index)"
@@ -1854,7 +1847,10 @@ export default {
{{ getOverlayTimeSlotSpan("overlay-item-" + index) }}
</p>
<span
v-if="!isOverlayMinimallySized(this.overlays.find(overlay => overlay.id === 'overlay-item-' + index))"
v-if="!isOverlayMinimallySized(this.overlays.find(overlay => overlay.id === 'overlay-item-' + index))"
@mousedown.stop="showOverlayClassTimeTypePopover('overlay-item-' + index)"
:title="$props.isPreviewMode ? '' : $p.t('ui', 'bearbeiten')"
:class="$props.isPreviewMode ? '' : 'fhc-cursor-pointer'"
class="badge badge-pill bg-light text-dark"
>
{{ this.getOverlayClassScheduleTypeTitle('overlay-item-' + index) }}
@@ -64,6 +64,9 @@ export default {
};
},
computed: {
userLanguage() {
return Vue.ref(FHC_JS_DATA_STORAGE_OBJECT.user_language);
},
tabulatorOptions() {
const options = {
ajaxURL: "dummy",
@@ -71,11 +74,17 @@ export default {
return await this.getParsedClassTimeSlotValidityPeriodData();
},
ajaxResponse: (url, params, response) => response,
persistenceID: "class_schedule_validity_periods_table",
persistenceID: "class_schedule_validity_periods_table12333451",
selectableRows: true,
maxHeight:"100%",
columns: [
{
title: this.$p.t("ui", "zeitraum"),
title: this.$capitalize(this.$p.t("ui", "unterrichtszeitenGueltigkeitId")),
field: "unterrichtszeitengueltigkeit_id",
visible: false,
},
{
title: this.$capitalize(this.$p.t("ui", "zeitraum")),
formatter: (cell, formatterParams, onRendered) => {
const data = cell.getData();
const validFrom = new Date(data.gueltig_von).toLocaleDateString(
@@ -99,17 +108,32 @@ export default {
},
},
{
title: this.$p.t("global", "typ"),
title: this.$capitalize(this.$p.t("global", "typ")),
field: "unterrichtszeiten_typ_bezeichnung_mehrsprachig",
width: 150,
formatter: (cell, formatterParams, onRendered) => {
console.log(cell.getData())
if (!cell.getData().unterrichtszeiten_typ_bezeichnung_mehrsprachig) {
return "sdsd";
}
return this.userLanguage?.value === "English"
? cell.getData().unterrichtszeiten_typ_bezeichnung_mehrsprachig[1]
: cell.getData().unterrichtszeiten_typ_bezeichnung_mehrsprachig[0];
},
},
{
title: this.$p.t("lehre", "sem"),
title: this.$capitalize(this.$p.t("lehre", "sem")),
field: "ausbildungssemester",
width: 150,
},
{
title: this.$p.t("global", "actions"),
title: this.$capitalize(this.$p.t("global", "beschreibung")),
field: "anmerkung",
width: 150,
},
{
title: this.$capitalize(this.$p.t("global", "actions")),
field: "actions",
minWidth: 150,
maxWidth: 150,
@@ -299,6 +323,9 @@ export default {
};
});
},
hasLehreUnterrichtszeitenTypRPermission() {
return this.permissions["lehre/unterrichtszeiten_typ_r"] || false;
}
},
methods: {
async getParsedClassTimeSlotValidityPeriodData() {
@@ -324,10 +351,6 @@ export default {
if (!period.studienplan_bezeichnung) {
period.studienplan_bezeichnung = generalWord;
}
period.unterrichtszeiten_typ_bezeichnung_mehrsprachig =
period.unterrichtszeiten_typ_bezeichnung_mehrsprachig[0]?.split(
":",
)[1];
return {
...period,
};
@@ -460,97 +483,100 @@ export default {
<div class="row mb-3">
<div class="col d-flex justify-content-between">
<a class="btn btn-primary mb-3" @click="showClassTimeSlotValidityPeriodModal">{{$p.t('ui', 'addClassTimeSlotValidityPeriodButton')}}</a>
<a class="btn btn-secondary mb-3" @click="showClassTimeSlotTypeModal">{{$p.t('ui', 'addClassTimeSlotTypeButton')}}</a>
<a v-if="hasLehreUnterrichtszeitenTypRPermission" class="btn btn-secondary mb-3" @click="showClassTimeSlotTypeModal">{{$p.t('ui', 'addClassTimeSlotTypeButton')}}</a>
</div>
</div>
<class-schedule-type-modal
:isVisible="isClassTimeSlotTypeModalVisible"
@hideBsModal="resetClassTimeSlotTypeModal"
/>
<class-schedule-validity-period-modal
:isVisible="isClassTimeSlotValidityPeriodModalVisible"
:editedClassTimeSlotValidityPeriodId="editedClassTimeSlotValidityPeriodId"
@hideBsModal="() => { resetClassTimeSlotValidityPeriodModal(); editedClassTimeSlotValidityPeriodId = null; }"
@classTimeSlotValidityPeriodCreated="() => {
$refs.classTimeSlotValidityPeriodsTable.tabulator.replaceData();
resetClassTimeSlotValidityPeriodModal();
this.editedClassTimeSlotValidityPeriodId = null;
}"
@classTimeSlotValidityPeriodUpdated="() => {
$refs.classTimeSlotValidityPeriodsTable.tabulator.replaceData();
resetClassTimeSlotValidityPeriodModal();
this.editedClassTimeSlotValidityPeriodId = null;
}"
/>
<core-filter-cmpt
v-if="phrasesLoaded"
ref="classTimeSlotValidityPeriodsTable"
table-only
:side-menu="false"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
>
<template #search>
<slot name="filterzuruecksetzen">
<core-form class="d-flex flex-column flex-md-row align-items-md-end gap-3">
<div>
<form-input
:label="$capitalize($p.t('lehre/organisationseinheit'))"
:suggestions="filteredOrganizationalUnits"
:optionValue="(option) => option.value"
:optionLabel="(option) => option.label"
@complete="filterOrganizationalUnits($event)"
@itemSelect="(option) => { filterData.selectedOrganizationalUnit = option.value; }"
type="autocomplete"
name="organizationalUnitShortCode"
dropdown
forceSelection
>
</form-input>
</div>
<div>
<form-input
v-model="selectedSemester"
:label="$capitalize($p.t('lehre/studiensemester'))"
:suggestions="filteredSemesters"
:optionValue="(option) => option.value"
:optionLabel="(option) => option.label"
@complete="filterSemesters($event)"
type="autocomplete"
name="selectedSemester"
dropdown
forceSelection
>
</form-input>
</div>
<div>
<div class="d-flex align-items-center gap-2">
<div class="row mb-3" style="height: 65vh;">
<class-schedule-type-modal
v-if="hasLehreUnterrichtszeitenTypRPermission"
:isVisible="isClassTimeSlotTypeModalVisible"
@hideBsModal="resetClassTimeSlotTypeModal"
/>
<class-schedule-validity-period-modal
:isVisible="isClassTimeSlotValidityPeriodModalVisible"
:editedClassTimeSlotValidityPeriodId="editedClassTimeSlotValidityPeriodId"
@hideBsModal="() => { resetClassTimeSlotValidityPeriodModal(); editedClassTimeSlotValidityPeriodId = null; }"
@classTimeSlotValidityPeriodCreated="() => {
$refs.classTimeSlotValidityPeriodsTable.tabulator.replaceData();
resetClassTimeSlotValidityPeriodModal();
this.editedClassTimeSlotValidityPeriodId = null;
}"
@classTimeSlotValidityPeriodUpdated="() => {
$refs.classTimeSlotValidityPeriodsTable.tabulator.replaceData();
resetClassTimeSlotValidityPeriodModal();
this.editedClassTimeSlotValidityPeriodId = null;
}"
/>
<core-filter-cmpt
v-if="phrasesLoaded"
ref="classTimeSlotValidityPeriodsTable"
table-only
:side-menu="false"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
>
<template #search>
<slot name="filterzuruecksetzen">
<core-form class="d-flex flex-column flex-md-row align-items-md-end gap-3">
<div>
<form-input
v-model="filterData.validityPeriodFrom"
:label="$p.t('ui', 'validityPeriod') + ' ' + $p.t('ui', 'von')"
:teleport="true"
:enable-time-picker="false"
type="datePicker"
name="validityPeriodFrom"
format="dd.MM.yyyy"
auto-apply
/>
:label="$capitalize($p.t('lehre/organisationseinheit'))"
:suggestions="filteredOrganizationalUnits"
:optionValue="(option) => option.value"
:optionLabel="(option) => option.label"
@complete="filterOrganizationalUnits($event)"
@itemSelect="(option) => { filterData.selectedOrganizationalUnit = option.value; }"
type="autocomplete"
name="organizationalUnitShortCode"
dropdown
forceSelection
>
</form-input>
</div>
<div>
<form-input
v-model="selectedSemester"
:label="$capitalize($p.t('lehre/studiensemester'))"
:suggestions="filteredSemesters"
:optionValue="(option) => option.value"
:optionLabel="(option) => option.label"
@complete="filterSemesters($event)"
type="autocomplete"
name="selectedSemester"
dropdown
forceSelection
>
</form-input>
</div>
<div>
<div class="d-flex align-items-center gap-2">
<form-input
v-model="filterData.validityPeriodTo"
:label="$p.t('ui', 'validityPeriod') + ' ' + $p.t('global', 'bis')"
v-model="filterData.validityPeriodFrom"
:label="$p.t('ui', 'validityPeriod') + ' ' + $p.t('ui', 'von')"
:teleport="true"
:enable-time-picker="false"
type="datePicker"
name="validityPeriodTo"
name="validityPeriodFrom"
format="dd.MM.yyyy"
auto-apply
/>
<form-input
v-model="filterData.validityPeriodTo"
:label="$p.t('ui', 'validityPeriod') + ' ' + $p.t('global', 'bis')"
:teleport="true"
:enable-time-picker="false"
type="datePicker"
name="validityPeriodTo"
format="dd.MM.yyyy"
auto-apply
/>
</div>
</div>
</div>
</core-form>
</slot>
</template>
</core-filter-cmpt>
</core-form>
</slot>
</template>
</core-filter-cmpt>
</div>
</div>
`,
};
@@ -153,7 +153,7 @@ export default {
this.getAllClassScheduleTypes();
})
.catch((error) => {
this.$fhcAlert.handleSystemError(error);
this.$fhcAlert.alertError(this.$p.t("ui", "errorFetchingClassScheduleTimeSlotTypes"));
});
},
showClassTimeSlotTypeForm() {
@@ -482,7 +482,7 @@ export default {
<div class="col">
<form-input
v-model="classTimeSlotValidityPeriodFormData.validityPeriodFrom"
:label="$p.t('ui/von') + ' *'"
:label="$capitalize($p.t('ui/von') + ' *')"
:teleport="true"
:enable-time-picker="false"
type="datePicker"
@@ -494,7 +494,7 @@ export default {
<div class="col">
<form-input
v-model="classTimeSlotValidityPeriodFormData.validityPeriodTo"
:label="$p.t('global/bis') + ' *'"
:label="$capitalize($p.t('global/bis') + ' *')"
:teleport="true"
:enable-time-picker="false"
type="datePicker"
@@ -507,7 +507,7 @@ export default {
<div class="row mb-3">
<form-input
v-model="classTimeSlotValidityPeriodFormData.studyPlanId"
:label="$p.t('lehre/studienplan')"
:label="$capitalize($p.t('lehre/studienplan'))"
:disabled="isStudyPlanSelectDisabled"
type="select"
name="studyPlan"
@@ -528,7 +528,7 @@ export default {
id="ausbildungssemester"
name="semester"
:disabled="isStudyPlanSelectDisabled"
:label="$p.t('lehre', 'ausbildungssemester')"
:label="$capitalize($p.t('lehre', 'ausbildungssemester'))"
v-model="classTimeSlotValidityPeriodFormData.semester"
>
<option
@@ -544,7 +544,7 @@ export default {
<form-input
type="select"
name="classTimeSlotType"
:label="$p.t('ui/classTimeSlotType')"
:label="$capitalize($p.t('ui/classTimeSlotType'))"
v-model="classTimeSlotValidityPeriodFormData.classTimeSlotTypeShortcode"
>
<option :value="null"> - </option>
@@ -561,7 +561,7 @@ export default {
<form-input
type="textarea"
name="beschreibung"
:label="$p.t('global/beschreibung')"
:label="$capitalize($p.t('global/beschreibung'))"
v-model="classTimeSlotValidityPeriodFormData.description"
>
</form-input>
@@ -84,7 +84,7 @@ export default {
><i class="fa fa-eye fs-5"></i></a>
</div>
<div class='py-3 mb-4'>
<div v-if="$props.classTimeSlots && $props.classTimeSlots.length > 0">
<div v-if="$props.classTimeSlots.length > 0 && this.classroomHours?.length > 0">
<div class="row border-top rounded pt-1 pb-5">
<class-schedule-calendar-selector
:classroom-hours="this.classroomHours.map(hour => hour.beginn + '-' + hour.ende)"
+20
View File
@@ -58677,6 +58677,26 @@ I have been informed that I am under no obligation to consent to the transmissio
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'unterrichtszeitenGueltigkeitId',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Unterrichtszeit Gültigkeitszeitraum Id',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'validity period id',
'description' => '',
'insertvon' => 'system'
)
)
),
);