Files
FHC-Core/public/js/components/Cis/Profil/StudentProfil.js
T

474 lines
14 KiB
JavaScript

import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
import Mailverteiler from "./ProfilComponents/Mailverteiler.js";
import AusweisStatus from "./ProfilComponents/FhAusweisStatus.js";
import Adresse from "./ProfilComponents/Adresse.js";
import Kontakt from "./ProfilComponents/Kontakt.js";
import ProfilEmails from "./ProfilComponents/ProfilEmails.js";
import RoleInformation from "./ProfilComponents/RoleInformation.js";
import ProfilInformation from "./ProfilComponents/ProfilInformation.js";
import FetchProfilUpdates from "./ProfilComponents/FetchProfilUpdates.js";
import EditProfil from "./ProfilModal/EditProfil.js";
import QuickLinks from "./ProfilComponents/QuickLinks.js";
import CalendarSync from "./ProfilComponents/CalendarSync.js";
import ApiProfilUpdate from '../../../api/factory/profilUpdate.js';
import { dateFilter } from '../../../tabulator/filters/Dates.js';
export default {
components: {
CoreFilterCmpt,
Mailverteiler,
AusweisStatus,
Adresse,
Kontakt,
ProfilEmails,
RoleInformation,
ProfilInformation,
FetchProfilUpdates,
EditProfil,
QuickLinks,
CalendarSync,
},
inject: ["sortProfilUpdates", "collapseFunction", "language","isEditable"],
data() {
return {
showModal: false,
collapseIconBetriebsmittel: true,
editDataFilter: null,
arePhrasesPreloaded: false,
// tabulator options
zutrittsgruppen_table_options: {
persistenceID: "filterTableStudentProfilZutrittsgruppen",
persistence: {
columns: false
},
minHeight: 200,
layout: "fitColumns",
columns: [
{
title: Vue.computed(() => this.$p.t('profil/zutrittsGruppen')),
field: "bezeichnung"
}
],
},
betriebsmittel_table_options: {
persistenceID: "filterTableStudentProfilBetriebsmittel",
persistence: {
columns: false
},
minHeight: 300,
layout: "fitColumns",
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
responsiveLayoutCollapseStartOpen: false,
columns: [
{
title:
"<i id='collapseIconBetriebsmittel' role='button' class='fa-solid fa-angle-down '></i>",
field: "collapse",
headerSort: false,
headerFilter: false,
formatter: "responsiveCollapse",
maxWidth: 40,
headerClick: this.collapseFunction,
responsive: 0,
},
{
title: Vue.computed(()=>this.$p.t('profil/entlehnteBetriebsmittel')),
field: "betriebsmittel",
headerFilter: true,
minWidth: 200,
visible: true,
responsive: 0,
},
{
title: Vue.computed(() => this.$p.t('profil/inventarnummer')) ,
field: "Nummer",
headerFilter: true,
resizable: true,
minWidth: 200,
visible: true,
responsive: 2,
},
{
title: Vue.computed(() => this.$p.t('profil/ausgabedatum')) ,
field: "Ausgegeben_am",
headerFilterFunc: 'dates',
headerFilter: dateFilter,
minWidth: 200,
visible: true,
formatter:"datetime",
formatterParams: this.datetimeFormatterParams(),
responsive: 1,
},
],
},
};
},
props: {
data: Object,
editData: Object,
calendarSyncUrls: Array,
},
provide() {
return {
studiengang_kz: Vue.computed({ get: () => this.data.studiengang_kz }),
}
},
methods: {
betriebsmittelTableBuilt: function () {
this.$refs.betriebsmittelTable.tabulator.setData(this.data.mittel);
},
zutrittsgruppenTableBuilt: function () {
this.$refs.zutrittsgruppenTable.tabulator.setData(
this.data.zuttritsgruppen
);
},
fetchProfilUpdates: function () {
this.$api
.call(ApiProfilUpdate.selectProfilRequest())
.then((res) => {
if (!res.error && res) {
this.data.profilUpdates = res.data?.length
? res.data.sort(this.sortProfilUpdates)
: null;
}
});
},
hideEditProfilModal: function () {
//? checks the editModal component property result, if the user made a successful request or not
if (this.$refs.editModal.result) {
this.$api
.call(ApiProfilUpdate.selectProfilRequest())
.then((request) => {
if (!request.error && request.data) {
this.data.profilUpdates = request.data;
this.data.profilUpdates.sort(this.sortProfilUpdates);
} else {
console.error("Error when fetching profile updates: " + request);
}
})
.catch((err) => {
console.error(err);
});
} else {
// when modal was closed without submitting request
}
this.showModal = false;
this.editDataFilter = null;
},
showEditProfilModal(view) {
if (view) {
this.editDataFilter = view;
}
this.showModal = true;
// after a state change, wait for the DOM updates to complete
Vue.nextTick(() => {
this.$refs.editModal.show();
});
},
datetimeFormatterParams: function() {
const params = {
inputFormat:"yyyy-MM-dd",
outputFormat:"dd.MM.yyyy",
invalidPlaceholder:"(invalid date)",
timezone:FHC_JS_DATA_STORAGE_OBJECT.timezone
};
return params;
}
},
computed: {
fotoStatus() {
return this.data?.fotoStatus ?? null;
},
filteredEditData() {
return this.editDataFilter
? this.editData.data[this.editDataFilter]
: this.editData;
},
profilInformation() {
if (!this.data) {
return {};
}
return {
Vorname: this.data.vorname,
Nachname: this.data.nachname,
Username: this.data.username,
Anrede: this.data.anrede,
Titel: this.data.titel,
Postnomen: this.data.postnomen,
foto_sperre: this.data.foto_sperre,
foto: this.data.foto,
};
},
roleInformation() {
if (!this.data) {
return {};
}
return {
geburtsdatum: {
label: `${this.$p.t('profil','Geburtsdatum')}`,
value: this.data.gebdatum
},
geburtsort: {
label: `${this.$p.t('profil','Geburtsort')}`,
value: this.data.gebort
},
personenkennzeichen: {
label: `${this.$p.t('person','personenkennzeichen')}`,
value: this.data.personenkennzeichen
},
matrikelnummer: {
label: this.$p.t('person/matrikelnummer'),
value: this.data.matrikelnummer
},
studiengang: {
label: `${this.$p.t('lehre','studiengang')}`,
value: this.data.studiengang
},
semester: {
label: `${this.$p.t('lehre','semester')}`,
value: this.data.semester
},
verband: {
label: `${this.$p.t('lehre','lehrverband')}`,
value: this.data.verband
},
gruppe: {
label: `${this.$p.t('lehre','gruppe')}`,
value: this.data.gruppe.trim()
}
};
},
quickLinks() {
let quickLinks = [];
//
return quickLinks;
},
},
created() {
// preload phrasen
this.$p.loadCategory('profil').then(() => {
this.arePhrasesPreloaded = true;
});
//? sorts the profil Updates: pending -> accepted -> rejected
this.data.profilUpdates?.sort(this.sortProfilUpdates);
},
watch: {
'language.value'(newVal) {
if(this.$refs.betriebsmittelTable) this.$refs.betriebsmittelTable.tabulator.setColumns(this.betriebsmittel_table_options.columns)
if(this.$refs.zutrittsgruppenTable) this.$refs.zutrittsgruppenTable.tabulator.setColumns(this.zutrittsgruppen_table_options.columns)
}
},
template: /*html*/ `
<div class="container-fluid text-break fhc-form">
<edit-profil v-if="showModal" ref="editModal" @hideBsModal="hideEditProfilModal"
:value="JSON.parse(JSON.stringify(filteredEditData))" :titel="$p.t('profil','profilBearbeiten')"></edit-profil>
<!-- ROW -->
<div class="row">
<div class="d-md-none col-12 ">
<!-- Bearbeiten Button -->
<div v-if="isEditable" class="row ">
<div class="col mb-3">
<button @click="showEditProfilModal" type="button" class="card text-start w-100 btn btn-outline-secondary" >
<div class="row">
<div class="col-2">
<i class="fa fa-edit"></i>
</div>
<div class="col-10">{{$p.t('ui','bearbeiten')}}</div>
</div>
</button>
</div>
</div>
<!-- MOBILE PROFIL UPDATES -->
<div v-if="data.profilUpdates" class="row mb-3">
<div class="col">
<fetch-profil-updates v-if="data.profilUpdates && data.profilUpdates.length" @fetchUpdates="fetchProfilUpdates" :data="data.profilUpdates"></fetch-profil-updates>
</div>
</div>
</div>
<!-- MAIN PANNEL -->
<div class="col-sm-12 col-md-8 col-xxl-9 ">
<!-- ROW WITH PROFIL IMAGE AND INFORMATION -->
<!-- INFORMATION CONTENT START -->
<!-- ROW WITH THE PROFIL INFORMATION -->
<div class="row mb-4 ">
<div class="col-lg-12 col-xl-6 ">
<!-- PROFIL INFORMATION -->
<div class="row mb-4">
<div class="col">
<profil-information @showEditProfilModal="showEditProfilModal" :title="$p.t('profil','studentIn')" :data="profilInformation" :fotoStatus="fotoStatus"></profil-information>
</div>
</div>
<!-- QUICK LINKS, MOBILE VIEW (HIDDEN IF VIEWPORT >= MD BREAKPOINT) -->
<div v-if="quickLinks.length" class="row mb-4 d-md-none">
<div class="col">
<quick-links :title="$p.t('profil/quickLinks')" :links="quickLinks" />
</div>
</div>
<!-- CALENDAR SYNC OPTIONS, MOBILE VIEW (HIDDEN IF VIEWPORT >= MD BREAKPOINT) -->
<div class="row mb-4 d-md-none">
<div class="col">
<calendar-sync :uid="$props.data.username" :calendarSyncUrls="$props.calendarSyncUrls"></calendar-sync>
</div>
</div>
<!-- STUDENT INFO -->
<div class="row mb-4">
<div class=" col-lg-12">
<role-information :title="$p.t('profil','studentInformation')" :data="roleInformation"></role-information>
</div>
</div>
<!-- START OF SECOND PROFIL INFORMATION COLUMN -->
</div>
<div class="col-xl-6 col-lg-12 ">
<!-- EMAILS -->
<div class="row mb-4">
<div class="col">
<profil-emails :title="this.$p.t('person','email')" :data="data.emails" ></profil-emails>
</div>
</div>
<!-- PRIVATE KONTAKTE-->
<div class="row mb-4 ">
<div class="col">
<div class="card">
<div class="card-header">
<div class="row">
<div @click="showEditProfilModal('Private_Kontakte')" class="col-auto" type="button">
<i class="fa fa-edit"></i>
</div>
<div class="col">
<span>{{$p.t('profil','privateKontakte')}}</span>
</div>
</div>
</div>
<div class="card-body ">
<div class="gy-3 row">
<div v-for="element in data.kontakte" class="col-12">
<Kontakt :data="element"></Kontakt>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- PRIVATE ADRESSEN-->
<div class="row mb-4">
<div class="col">
<div class="card">
<div class="card-header">
<div class="row">
<div @click="showEditProfilModal('Private_Adressen')" class="col-auto" type="button">
<i class="fa fa-edit"></i>
</div>
<div class="col">
<span>{{$p.t('profil','privateAdressen')}}</span>
</div>
</div>
</div>
<div class="card-body">
<div class="gy-3 row ">
<div v-for="element in data.adressen" class="col-12">
<Adresse :data="element"></Adresse>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div >
<!-- SECOND ROW UNDER THE PROFIL IMAGE AND INFORMATION WITH THE TABLES -->
<div class="row">
<div class="col-12 mb-4" >
<core-filter-cmpt
v-if="arePhrasesPreloaded"
@tableBuilt="betriebsmittelTableBuilt"
:title="$p.t('profil','entlehnteBetriebsmittel')"
ref="betriebsmittelTable"
:tabulator-options="betriebsmittel_table_options"
tableOnly
:sideMenu="false" />
</div>
<div class="col-12 mb-4" >
<core-filter-cmpt
v-if="arePhrasesPreloaded"
@tableBuilt="zutrittsgruppenTableBuilt"
:title="$p.t('profil','zutrittsGruppen')"
ref="zutrittsgruppenTable"
:tabulator-options="zutrittsgruppen_table_options"
tableOnly
:sideMenu="false"
noColumnFilter />
</div>
</div>
<!-- END OF MAIN CONTENT COL -->
</div>
<!-- START OF SIDE PANEL -->
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
<!-- Bearbeiten Button -->
<div class="row d-none d-md-block">
<div class="col mb-3">
<button @click="()=>showEditProfilModal()" type="button" class="card text-start w-100 btn btn-outline-secondary" >
<div class="row">
<div class="col-2">
<i class="fa fa-edit"></i>
</div>
<div class="col-10">{{$p.t('ui','bearbeiten')}}</div>
</div>
</button>
</div>
</div>
<!-- QUICK LINKS, HIDDEN IF VIEWPORT < MD BREAKPOINT -->
<div v-if="quickLinks.length" class="row mb-3 d-none d-md-block">
<div class="col">
<quick-links :title="$p.t('profil/quickLinks')" :links="quickLinks" />
</div>
</div>
<!-- CALENDAR SYNC OPTIONS, HIDDEN IF VIEWPORT < MD BREAKPOINT -->
<div class="row mb-3 d-none d-md-block">
<div class="col">
<calendar-sync :uid="$props.data.username" :calendarSyncUrls="$props.calendarSyncUrls"></calendar-sync>
</div>
</div>
<!-- PROFIL UPDATES -->
<div v-if="data.profilUpdates" class="row d-none d-md-block mb-3">
<div class="col mb-3">
<fetch-profil-updates v-if="data.profilUpdates && data.profilUpdates.length" @fetchUpdates="fetchProfilUpdates" :data="data.profilUpdates"></fetch-profil-updates>
</div>
</div>
<div class="row mb-3" >
<div class="col-12">
<ausweis-status :data="data.zutrittsdatum"></ausweis-status>
</div>
</div>
<!-- START OF THE SECOND ROW IN THE SIDE PANEL -->
<!-- MAILVERTEILER -->
<div class="row mb-3">
<div class="col">
<mailverteiler :title="$p.t('profil','mailverteiler')" :data="data?.mailverteiler"></mailverteiler>
</div>
</div>
<!-- END OF THE SECOND ROW IN THE SIDE PANEL -->
<!-- END OF SIDE PANEL -->
</div>
<!-- END OF CONTAINER ROW-->
</div>
<!-- END OF CONTAINER -->
</div>
`,
};