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

532 lines
18 KiB
JavaScript

import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
import EditProfil from "./ProfilModal/EditProfil.js";
import Adresse from "./ProfilComponents/Adresse.js";
import Kontakt from "./ProfilComponents/Kontakt.js";
import FetchProfilUpdates from "./ProfilComponents/FetchProfilUpdates.js";
import Mailverteiler from "./ProfilComponents/Mailverteiler.js";
import AusweisStatus from "./ProfilComponents/FhAusweisStatus.js";
import QuickLinks from "./ProfilComponents/QuickLinks.js";
import ProfilEmails from "./ProfilComponents/ProfilEmails.js";
import RoleInformation from "./ProfilComponents/RoleInformation.js";
import ProfilInformation from "./ProfilComponents/ProfilInformation.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,
EditProfil,
Adresse,
Kontakt,
FetchProfilUpdates,
AusweisStatus,
Mailverteiler,
QuickLinks,
ProfilEmails,
RoleInformation,
ProfilInformation,
CalendarSync,
},
inject: ["sortProfilUpdates", "collapseFunction", "language","isEditable"],
data() {
return {
showModal: false,
editDataFilter: null,
arePhrasesPreloaded: false,
// tabulator options
funktionen_table_options: {
persistenceID: "filterTableMaProfilFunktionen",
persistence: {
columns: false
},
minHeight: 300,
layout: "fitColumns",
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
responsiveLayoutCollapseStartOpen: false,
columns: [
{
title:
"<i id='collapseIconFunktionen' role='button' class='fa-solid fa-angle-down '></i>",
field: "collapse",
headerSort: false,
headerFilter: false,
formatter: "responsiveCollapse",
maxWidth: 40,
headerClick: this.collapseFunction,
visible: true,
responsive: 0,
},
{
title: Vue.computed(() => this.$p.t('ui/bezeichnung')),
field: "Bezeichnung",
headerFilter: true,
minWidth: 200,
visible: true,
responsive: 0,
},
{
title: Vue.computed(() => this.$p.t('lehre/organisationseinheit')),
field: "Organisationseinheit",
headerFilter: true,
minWidth: 200,
visible: true,
responsive: 1,
},
{
title: Vue.computed(() => this.$p.t('global/gueltigVon')),
field: "Gültig_von",
headerFilterFunc: 'dates',
headerFilter: dateFilter,
resizable: true,
minWidth: 200,
visible: true,
formatter:"datetime",
formatterParams: this.datetimeFormatterParams(),
responsive: 4,
},
{
title: Vue.computed(() => this.$p.t('global/gueltigBis')),
field: "Gültig_bis",
headerFilterFunc: 'dates',
headerFilter: dateFilter,
resizable: true,
minWidth: 200,
visible: true,
formatter:"datetime",
formatterParams: this.datetimeFormatterParams(),
responsive: 3,
},
{
title: Vue.computed(() => this.$p.t('profil/wochenstunden')),
field: "Wochenstunden",
headerFilter: true,
minWidth: 200,
visible: true,
responsive: 2,
},
],
},
betriebsmittel_table_options: {
persistenceID: "filterTableMaProfilBetriebsmittel",
persistence: {
columns: false
},
minHeight: 300,
layout: "fitColumns",
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
data: [{betriebsmittel: "", Nummer: "", Ausgegeben_am: ""}],
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,
visible: true,
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,
},
methods: {
betriebsmittelTableBuilt: function () {
this.$refs.betriebsmittelTable.tabulator.setData(this.data.mittel);
},
funktionenTableBuilt: function () {
this.$refs.funktionenTable.tabulator.setData(this.data.funktionen);
},
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;
Vue.nextTick(() => {
this.$refs.editModal.show();
});
// after a state change, wait for the DOM updates to complete
},
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;
}
});
},
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);
},
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;
},
getTelefonValue() {
if(this.data.standort_telefon?.kontakt) {
return this.data.standort_telefon.kontakt + " " + this.data.telefonklappe
} else if(this.data.standort_telefon) {
return this.data.standort_telefon + " " + this.data.telefonklappe
} else {
return this.data.telefonklappe
}
},
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('profil','Kurzzeichen')}`,
value: this.data.kurzbz
},
telefon: {
label: `${this.$p.t('profil','Telefon')}`,
value: this.getTelefonValue
},
office: {
label: `${this.$p.t('profil','Büro')}`,
value: this.data.ort_kurzbz
}
};
},
quickLinks() {
let quickLinks = [];
//
return quickLinks;
},
},
created() {
// preload phrasen
this.$p.loadCategory(["ui","lehre","global","profil"]).then(() => {
this.arePhrasesPreloaded = true;
});
//? sorts the profil Updates: pending -> accepted -> rejected
this.data.profilUpdates?.sort(this.sortProfilUpdates);
},
watch: {
'data.funktionen'(newVal) {
if(this.$refs.funktionenTable) this.$refs.funktionenTable.tabulator.setData(newVal);
},
'data.mittel'(newVal) {
if(this.$refs.betriebsmittelTable) this.$refs.betriebsmittelTable.tabulator.setData(newVal);
},
'language.value'(newVal) {
this.setTableColumnTitles()
}
},
template: /*html*/ `
<div class="container-fluid text-break fhc-form" >
<edit-profil v-if="showModal" ref="editModal" :isMitarbeiter="true" @hideBsModal="hideEditProfilModal" :value="JSON.parse(JSON.stringify(filteredEditData))" :titel="$p.t('profil','profilBearbeiten')"></edit-profil>
<div class="row">
<div class="d-md-none col-12">
<!-- Bearbeiten Button -->
<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">
<div class="col-auto">
<i class="fa fa-edit"></i>
</div>
<div class="col-auto">{{$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>
<!-- END OF HIDDEN ROW (HIDDEN IN VIEWPORTS GREATER THEN-EQUAL MD) -->
<!-- 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','mitarbeiterIn')" :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>
<!-- MITARBEITER INFO -->
<div class="row mb-4">
<div class=" col-lg-12">
<role-information :title="$p.t('profil','mitarbeiterInformation')" :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 >
<div class="row">
<!-- FUNKTIONEN TABELLE -->
<div class="col-12 mb-4" >
<core-filter-cmpt
v-if="arePhrasesPreloaded"
@tableBuilt="funktionenTableBuilt"
:title="$p.t('person','funktionen')"
ref="funktionenTable"
:tabulator-options="funktionen_table_options"
tableOnly
:sideMenu="false"
/>
</div>
<!-- BETRIEBSMITTEL TABELLE -->
<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>
</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="text-start card w-100 btn btn-outline-secondary" >
<div class="row">
<div class="col-auto">
<i class="fa fa-edit"></i>
</div>
<div class="col-auto">{{$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>
<!-- AUSWEIS STATUS -->
<div class="row mb-3" >
<div class="col-12">
<ausweis-status :data="data.zutrittsdatum"></ausweis-status>
</div>
</div>
<!-- MAILVERTEILER -->
<div class="row mb-3">
<div class="col">
<mailverteiler :data="data?.mailverteiler" :title="$p.t('profil','mailverteiler')"></mailverteiler>
</div>
</div>
</div>
</div>
</div>
`,
};